@data-fair/lib-vue 1.21.1 → 1.22.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/async-action.js +43 -40
- package/computed-deep-diff.js +9 -0
- package/concept-filters.js +22 -20
- package/deep-diff.d.ts +3 -0
- package/deep-diff.js +14 -0
- package/fetch.js +57 -50
- package/locale-dayjs-global.js +4 -4
- package/locale-dayjs.js +33 -32
- package/package.json +2 -1
- package/reactive-search-params-global.js +3 -3
- package/reactive-search-params.js +140 -124
- package/session.js +369 -325
- package/ui-notif.js +80 -63
- package/vite.d.ts +1 -0
- package/vite.js +15 -14
- package/ws.js +62 -58
package/ui-notif.js
CHANGED
|
@@ -1,76 +1,93 @@
|
|
|
1
1
|
// simple composable to display store a UI notification
|
|
2
2
|
// this will be transmitted to frame parent if available (compatible with v-iframe uiNotification message type)
|
|
3
3
|
// or can be displayed locally by @data-fair/lib-vuetify/ui-notif.vue
|
|
4
|
-
import { shallowRef, inject } from 'vue'
|
|
5
|
-
import inIframe from '@data-fair/lib-utils/in-iframe.js'
|
|
6
|
-
export function getErrorCode
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
4
|
+
import { shallowRef, inject } from 'vue';
|
|
5
|
+
import inIframe from '@data-fair/lib-utils/in-iframe.js';
|
|
6
|
+
export function getErrorCode(error) {
|
|
7
|
+
if (typeof error === 'string')
|
|
8
|
+
return 500;
|
|
9
|
+
if (typeof error.statusCode === 'number')
|
|
10
|
+
return error.statusCode;
|
|
11
|
+
if (typeof error.response?.statusCode === 'number')
|
|
12
|
+
return error.response?.statusCode;
|
|
13
|
+
if (typeof error.code === 'number')
|
|
14
|
+
return error.code;
|
|
15
|
+
if (typeof error.response?.code === 'number')
|
|
16
|
+
return error.response?.code;
|
|
17
|
+
return 500;
|
|
13
18
|
}
|
|
14
|
-
export function getErrorMsg
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
export function getErrorMsg(error) {
|
|
20
|
+
if (typeof error === 'string')
|
|
21
|
+
return error;
|
|
22
|
+
if (error.data && typeof error.data === 'string')
|
|
23
|
+
return error.data;
|
|
24
|
+
if (error.response?.data && typeof error.response.data === 'string')
|
|
25
|
+
return error.response.data;
|
|
26
|
+
if (error.statusText && typeof error.statusText === 'string')
|
|
27
|
+
return error.statusText;
|
|
28
|
+
if (error.response?.statusText && typeof error.response?.statusText === 'string')
|
|
29
|
+
return error.response?.statusText;
|
|
30
|
+
if (error.message)
|
|
31
|
+
return error.message;
|
|
32
|
+
return 'erreur inconnue';
|
|
22
33
|
}
|
|
23
|
-
export function getFullNotif
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
export function getFullNotif(notif, defaultType = 'default') {
|
|
35
|
+
if (typeof notif === 'string')
|
|
36
|
+
return { msg: notif, type: defaultType };
|
|
37
|
+
if (notif.error) {
|
|
38
|
+
const code = getErrorCode(notif.error);
|
|
39
|
+
return {
|
|
40
|
+
...notif,
|
|
41
|
+
type: 'error',
|
|
42
|
+
errorMsg: getErrorMsg(notif.error),
|
|
43
|
+
clientError: code < 500
|
|
44
|
+
};
|
|
32
45
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
46
|
+
return {
|
|
47
|
+
...notif,
|
|
48
|
+
type: notif.type ?? defaultType
|
|
49
|
+
};
|
|
38
50
|
}
|
|
39
51
|
export const getUiNotif = () => {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
52
|
+
const notification = shallowRef(null);
|
|
53
|
+
function sendUiNotif(partialNotif) {
|
|
54
|
+
const notif = notification.value = getFullNotif(partialNotif);
|
|
55
|
+
if (inIframe) {
|
|
56
|
+
if (notif.type === 'error')
|
|
57
|
+
delete notif.error;
|
|
58
|
+
window.top?.postMessage({ vIframe: true, uiNotification: notif }, '*');
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
console.log('iframe notification', notif);
|
|
62
|
+
}
|
|
48
63
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
64
|
+
return { notification, sendUiNotif };
|
|
65
|
+
};
|
|
52
66
|
// uses pattern for SSR friendly plugin/composable, cf https://antfu.me/posts/composable-vue-vueday-2021#shared-state-ssr-friendly
|
|
53
|
-
export const uiNotifKey = Symbol('uiNotif')
|
|
54
|
-
export function createUiNotif
|
|
55
|
-
|
|
56
|
-
|
|
67
|
+
export const uiNotifKey = Symbol('uiNotif');
|
|
68
|
+
export function createUiNotif() {
|
|
69
|
+
const uiNotif = getUiNotif();
|
|
70
|
+
return { install(app) { app.provide(uiNotifKey, uiNotif); } };
|
|
57
71
|
}
|
|
58
|
-
export function useUiNotif
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
72
|
+
export function useUiNotif() {
|
|
73
|
+
const uiNotif = inject(uiNotifKey);
|
|
74
|
+
if (!uiNotif)
|
|
75
|
+
throw new Error('useUiNotif requires using the plugin createUiNotif');
|
|
76
|
+
return uiNotif;
|
|
62
77
|
}
|
|
63
|
-
export default useUiNotif
|
|
64
|
-
export function withUiNotif
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
78
|
+
export default useUiNotif;
|
|
79
|
+
export function withUiNotif(fn, errorMsg, successNotif) {
|
|
80
|
+
const { sendUiNotif } = useUiNotif();
|
|
81
|
+
console.warn('withUiNotif is deprecated, use useAsyncAction instead');
|
|
82
|
+
return async function (...args) {
|
|
83
|
+
try {
|
|
84
|
+
const result = await fn(...args);
|
|
85
|
+
if (successNotif)
|
|
86
|
+
sendUiNotif(getFullNotif(successNotif, 'success'));
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
sendUiNotif({ msg: errorMsg ?? '', error });
|
|
91
|
+
}
|
|
92
|
+
};
|
|
76
93
|
}
|
package/vite.d.ts
CHANGED
package/vite.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
// made for https://github.com/unplugin/unplugin-auto-import
|
|
2
2
|
export const autoImports = [
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
3
|
+
'vue',
|
|
4
|
+
'vue-i18n',
|
|
5
|
+
'vue-router',
|
|
6
|
+
{
|
|
7
|
+
'@data-fair/lib-vue/session.js': ['useSession', 'useSessionAuthenticated'],
|
|
8
|
+
'@data-fair/lib-vue/reactive-search-params.js': ['useReactiveSearchParams', 'useStringSearchParam', 'useBooleanSearchParam', 'useNumberSearchParam', 'useStringsArraySearchParam'],
|
|
9
|
+
'@data-fair/lib-vue/locale-dayjs.js': ['useLocaleDayjs'],
|
|
10
|
+
'@data-fair/lib-vue/concept-filters.js': ['useConceptFilters'],
|
|
11
|
+
'@data-fair/lib-vue/ui-notif.js': ['useUiNotif', 'withUiNotif'],
|
|
12
|
+
'@data-fair/lib-vue/fetch.js': ['useFetch'],
|
|
13
|
+
'@data-fair/lib-vue/ws.js': ['useWS'],
|
|
14
|
+
'@data-fair/lib-vue/async-action.js': ['useAsyncAction'],
|
|
15
|
+
'@data-fair/lib-vue/deep-diff.js': ['computedDeepDiff', 'watchDeepDiff'],
|
|
16
|
+
}
|
|
17
|
+
];
|
package/ws.js
CHANGED
|
@@ -1,62 +1,66 @@
|
|
|
1
|
-
import reconnectingWebSocketModule from 'reconnecting-websocket'
|
|
2
|
-
import { ref, reactive, onScopeDispose } from 'vue'
|
|
3
|
-
const ReconnectingWebSocket = reconnectingWebSocketModule
|
|
1
|
+
import reconnectingWebSocketModule from 'reconnecting-websocket';
|
|
2
|
+
import { ref, reactive, onScopeDispose } from 'vue';
|
|
3
|
+
const ReconnectingWebSocket = reconnectingWebSocketModule;
|
|
4
4
|
const getWS = (path) => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
opened
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
opened.value = false
|
|
25
|
-
})
|
|
26
|
-
ws.onmessage = (event) => {
|
|
27
|
-
const body = JSON.parse(event.data)
|
|
28
|
-
if (body.type === 'message') {
|
|
29
|
-
if (subscriptions[body.channel]?.length) {
|
|
30
|
-
for (const listener of subscriptions[body.channel]) {
|
|
31
|
-
listener(body.data)
|
|
5
|
+
if (!window.WebSocket)
|
|
6
|
+
return;
|
|
7
|
+
// @ts-ignore
|
|
8
|
+
if (import.meta.env?.SSR)
|
|
9
|
+
return;
|
|
10
|
+
const url = (window.location.origin + path).replace('http:', 'ws:').replace('https:', 'wss:');
|
|
11
|
+
const ws = new ReconnectingWebSocket(url);
|
|
12
|
+
const subscriptions = reactive({});
|
|
13
|
+
const opened = ref(false);
|
|
14
|
+
ws.addEventListener('open', () => {
|
|
15
|
+
opened.value = true;
|
|
16
|
+
for (const channel of Object.keys(subscriptions)) {
|
|
17
|
+
if (subscriptions[channel].length) {
|
|
18
|
+
ws.send(JSON.stringify({ type: 'subscribe', channel }));
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
ws.send(JSON.stringify({ type: 'unsubscribe', channel }));
|
|
22
|
+
delete subscriptions[channel];
|
|
23
|
+
}
|
|
32
24
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
25
|
+
});
|
|
26
|
+
ws.addEventListener('close', () => {
|
|
27
|
+
opened.value = false;
|
|
28
|
+
});
|
|
29
|
+
ws.onmessage = (event) => {
|
|
30
|
+
const body = JSON.parse(event.data);
|
|
31
|
+
if (body.type === 'message') {
|
|
32
|
+
if (subscriptions[body.channel]?.length) {
|
|
33
|
+
for (const listener of subscriptions[body.channel]) {
|
|
34
|
+
listener(body.data);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
function subscribe(channel, listener) {
|
|
40
|
+
if (!subscriptions[channel]) {
|
|
41
|
+
subscriptions[channel] = [];
|
|
42
|
+
if (opened.value)
|
|
43
|
+
ws.send(JSON.stringify({ type: 'subscribe', channel }));
|
|
44
|
+
}
|
|
45
|
+
subscriptions[channel].push(listener);
|
|
46
|
+
onScopeDispose(() => {
|
|
47
|
+
unsubscribe(channel, listener);
|
|
48
|
+
});
|
|
53
49
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
50
|
+
const unsubscribe = (channel, listener) => {
|
|
51
|
+
if (subscriptions[channel]) {
|
|
52
|
+
subscriptions[channel] = subscriptions[channel].filter(l => l !== listener);
|
|
53
|
+
if (subscriptions[channel].length === 0 && opened.value) {
|
|
54
|
+
ws.send(JSON.stringify({ type: 'unsubscribe', channel }));
|
|
55
|
+
delete subscriptions[channel];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
return { opened, ws, subscribe, unsubscribe };
|
|
60
|
+
};
|
|
61
|
+
const sockets = {};
|
|
62
|
+
export function useWS(path) {
|
|
63
|
+
sockets[path] = sockets[path] ?? getWS(path);
|
|
64
|
+
return sockets[path];
|
|
61
65
|
}
|
|
62
|
-
export default useWS
|
|
66
|
+
export default useWS;
|