mirror of
https://github.com/sabjorn7/meetguru.git
synced 2025-10-02 04:26:57 +03:00
v183 - reset_again
This commit is contained in:
parent
fd158e79aa
commit
2de028e570
@ -1 +1 @@
|
|||||||
{"name":"weweb-front","version":"4.0.0","private":true,"type":"module","scripts":{"serve":"vite","build":"vite build","postbuild":"node ./postbuild.js"},"dependencies":{"@vueuse/head":"2.0.0","axios":"1.9.0","html-escaper":"3.0.3","lodash":"4.17.21","pinia":"3.0.2","short-unique-id":"5.3.2","tiny-emitter":"2.1.0","uuid":"11.1.0","vue":"3.5.13","vue-cookie-next":"1.3.0","vue-meta":"2.4.0","vue-router":"4.5.1","vuex":"4.1.0","dayjs":"1.11.0","@supabase/supabase-js":"2.50.3","qs":"^6.14.0","@vueform/multiselect":"2.6.2","vue-ellipse-progress":"^2.1.1","@vueuse/core":"^13.0.0","diff":"^5.1.0","animejs":"^3.2.2","marked":"^14.1.2","medium-zoom":"^1.0.6","prismjs":"^1.23.0","@tiptap/extension-color":"2.8.0","@tiptap/extension-image":"2.8.0","@tiptap/extension-link":"2.8.0","@tiptap/extension-mathematics":"2.26.1","@tiptap/extension-mention":"2.8.0","@tiptap/extension-placeholder":"2.8.0","@tiptap/extension-table":"2.8.0","@tiptap/extension-table-cell":"2.8.0","@tiptap/extension-table-header":"2.8.0","@tiptap/extension-table-row":"2.8.0","@tiptap/extension-task-item":"2.8.0","@tiptap/extension-task-list":"2.8.0","@tiptap/extension-text-align":"2.8.0","@tiptap/extension-text-style":"2.8.0","@tiptap/extension-underline":"2.8.0","@tiptap/pm":"2.8.0","@tiptap/starter-kit":"2.8.0","@tiptap/suggestion":"2.8.0","@tiptap/vue-3":"2.8.0","katex":"^0.16.22","prosemirror-commands":"1.5.0","prosemirror-dropcursor":"1.5.0","prosemirror-gapcursor":"1.3.1","prosemirror-history":"1.3.0","prosemirror-keymap":"1.2.0","prosemirror-schema-list":"1.2.2","tiptap-markdown":"^0.8.10","lodash-es":"^4.17.21","@vuepic/vue-datepicker":"3.6.8","date-fns":"4.1.0"},"devDependencies":{"@vitejs/plugin-vue":"5.2.4","autoprefixer":"10.4.21","handlebars":"4.7.8","sass-embedded":"1.89.0","vite":"6.3.5","vite-plugin-node-polyfills":"0.23.0"},"browserslist":["last 3 years"]}
|
{"name":"weweb-front","version":"4.0.0","private":true,"type":"module","scripts":{"serve":"vite","build":"vite build","postbuild":"node ./postbuild.js"},"dependencies":{"@vueuse/head":"2.0.0","axios":"1.9.0","html-escaper":"3.0.3","lodash":"4.17.21","pinia":"3.0.2","short-unique-id":"5.3.2","tiny-emitter":"2.1.0","uuid":"11.1.0","vue":"3.5.13","vue-cookie-next":"1.3.0","vue-meta":"2.4.0","vue-router":"4.5.1","vuex":"4.1.0","dayjs":"1.11.0","@supabase/supabase-js":"2.50.3","qs":"^6.14.0","@vueform/multiselect":"2.6.2","vue-ellipse-progress":"^2.1.1","@vueuse/core":"^13.0.0","diff":"^5.1.0","animejs":"^3.2.2","marked":"^14.1.2","medium-zoom":"^1.0.6","prismjs":"^1.23.0","lodash-es":"^4.17.21","@vuepic/vue-datepicker":"3.6.8","date-fns":"4.1.0","@tiptap/extension-color":"2.8.0","@tiptap/extension-image":"2.8.0","@tiptap/extension-link":"2.8.0","@tiptap/extension-mathematics":"2.26.1","@tiptap/extension-mention":"2.8.0","@tiptap/extension-placeholder":"2.8.0","@tiptap/extension-table":"2.8.0","@tiptap/extension-table-cell":"2.8.0","@tiptap/extension-table-header":"2.8.0","@tiptap/extension-table-row":"2.8.0","@tiptap/extension-task-item":"2.8.0","@tiptap/extension-task-list":"2.8.0","@tiptap/extension-text-align":"2.8.0","@tiptap/extension-text-style":"2.8.0","@tiptap/extension-underline":"2.8.0","@tiptap/pm":"2.8.0","@tiptap/starter-kit":"2.8.0","@tiptap/suggestion":"2.8.0","@tiptap/vue-3":"2.8.0","katex":"^0.16.22","prosemirror-commands":"1.5.0","prosemirror-dropcursor":"1.5.0","prosemirror-gapcursor":"1.3.1","prosemirror-history":"1.3.0","prosemirror-keymap":"1.2.0","prosemirror-schema-list":"1.2.2","tiptap-markdown":"^0.8.10"},"devDependencies":{"@vitejs/plugin-vue":"5.2.4","autoprefixer":"10.4.21","handlebars":"4.7.8","sass-embedded":"1.89.0","vite":"6.3.5","vite-plugin-node-polyfills":"0.23.0"},"browserslist":["last 3 years"]}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
public/data/63d172e4-bec1-4021-9b5e-0817819aad7b.json
Normal file
1
public/data/63d172e4-bec1-4021-9b5e-0817819aad7b.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
|||||||
{"cacheVersion":182,"page":{"id":"cf9f551f-e733-4934-a682-535575cb7c70","paths":{"en":"promo","default":"promo"},"cmsDataSetPath":null,"workflows":[]},"sections":{"4a2188f6-d98c-4150-9ba7-5918c72f3421":{"uid":"4a2188f6-d98c-4150-9ba7-5918c72f3421","linkId":"416695e7-e54e-4897-9f9a-befeb223f1b0","_state":{"style":{"default":{}}},"content":{"default":{"wwObjects":[],"_ww-layout_alignItems":"flex-start","_ww-layout_flexDirection":"column"}},"sectionBaseId":"99586bd3-2b15-4d6b-a025-6a50d07ca845","sectionTitle":"Section"}},"wwObjects":{},"collections":[],"variables":[],"workflows":[],"formulas":[],"libraryComponents":[]}
|
{"cacheVersion":183,"page":{"id":"cf9f551f-e733-4934-a682-535575cb7c70","paths":{"en":"promo","default":"promo"},"cmsDataSetPath":null,"workflows":[]},"sections":{"4a2188f6-d98c-4150-9ba7-5918c72f3421":{"uid":"4a2188f6-d98c-4150-9ba7-5918c72f3421","linkId":"416695e7-e54e-4897-9f9a-befeb223f1b0","_state":{"style":{"default":{}}},"content":{"default":{"wwObjects":[],"_ww-layout_alignItems":"flex-start","_ww-layout_flexDirection":"column"}},"sectionBaseId":"99586bd3-2b15-4d6b-a025-6a50d07ca845","sectionTitle":"Section"}},"wwObjects":{},"collections":[],"variables":[],"workflows":[],"formulas":[],"libraryComponents":[]}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
15
public/icons/lucide/trash.svg
Normal file
15
public/icons/lucide/trash.svg
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M3 6h18" />
|
||||||
|
<path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" />
|
||||||
|
<path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 334 B |
@ -1 +1 @@
|
|||||||
{"name":"Образовательная платформа Meetguru","short_name":"Образовательная платформа Meetguru","icons":[{"src":"images/48-favicon.png?_wwcv=182","type":"image/png","sizes":"48x48"},{"src":"images/72-favicon.png?_wwcv=182","type":"image/png","sizes":"72x72"},{"src":"images/96-favicon.png?_wwcv=182","type":"image/png","sizes":"96x96"},{"src":"images/128-favicon.png?_wwcv=182","type":"image/png","sizes":"128x128"},{"src":"images/144-favicon.png?_wwcv=182","type":"image/png","sizes":"144x144"},{"src":"images/152-favicon.png?_wwcv=182","type":"image/png","sizes":"152x152"},{"src":"images/192-favicon.png?_wwcv=182","type":"image/png","sizes":"192x192"},{"src":"images/256-favicon.png?_wwcv=182","type":"image/png","sizes":"256x256"},{"src":"images/384-favicon.png?_wwcv=182","type":"image/png","sizes":"384x384"},{"src":"images/512-favicon.png?_wwcv=182","type":"image/png","sizes":"512x512"}],"start_url":"/","display":"fullscreen","scope":"/","background_color":"#FFFFFF","theme_color":"#FFFFFF"}
|
{"name":"Образовательная платформа Meetguru","short_name":"Образовательная платформа Meetguru","icons":[{"src":"images/48-favicon.png?_wwcv=183","type":"image/png","sizes":"48x48"},{"src":"images/72-favicon.png?_wwcv=183","type":"image/png","sizes":"72x72"},{"src":"images/96-favicon.png?_wwcv=183","type":"image/png","sizes":"96x96"},{"src":"images/128-favicon.png?_wwcv=183","type":"image/png","sizes":"128x128"},{"src":"images/144-favicon.png?_wwcv=183","type":"image/png","sizes":"144x144"},{"src":"images/152-favicon.png?_wwcv=183","type":"image/png","sizes":"152x152"},{"src":"images/192-favicon.png?_wwcv=183","type":"image/png","sizes":"192x192"},{"src":"images/256-favicon.png?_wwcv=183","type":"image/png","sizes":"256x256"},{"src":"images/384-favicon.png?_wwcv=183","type":"image/png","sizes":"384x384"},{"src":"images/512-favicon.png?_wwcv=183","type":"image/png","sizes":"512x512"}],"start_url":"/","display":"fullscreen","scope":"/","background_color":"#FFFFFF","theme_color":"#FFFFFF"}
|
@ -1,4 +1,4 @@
|
|||||||
const version = 182;
|
const version = 183;
|
||||||
self.addEventListener('install', event => {
|
self.addEventListener('install', event => {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(`Service worker v${version} installed`);
|
console.log(`Service worker v${version} installed`);
|
||||||
|
File diff suppressed because one or more lines are too long
@ -38,3 +38,19 @@ export function getTargetMedia({ screenSize, elementState, isResponsive, allowSt
|
|||||||
|
|
||||||
return targetMedia;
|
return targetMedia;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function splitPath(fullPath) {
|
||||||
|
if (fullPath.startsWith('content.')) {
|
||||||
|
const parts = fullPath.replace('content.', '').split('.');
|
||||||
|
const media = parts[0];
|
||||||
|
const path = `content.${parts.slice(1).join('.')}`;
|
||||||
|
return { path, media };
|
||||||
|
} else if (fullPath.startsWith('_state.style.')) {
|
||||||
|
const parts = fullPath.replace('_state.style.', '').split('.');
|
||||||
|
const media = parts[0];
|
||||||
|
const path = `_state.style.${parts.slice(1).join('.')}`;
|
||||||
|
return { path, media };
|
||||||
|
} else {
|
||||||
|
return { path: fullPath, media: 'default' };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
File diff suppressed because one or more lines are too long
@ -18,6 +18,7 @@ import { textOptions } from './src/settings';
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
editor: {
|
editor: {
|
||||||
|
deprecated: 'Use a rich text from the Elements panel instead of this one.',
|
||||||
label: {
|
label: {
|
||||||
en: 'Rich text',
|
en: 'Rich text',
|
||||||
},
|
},
|
||||||
|
@ -33,14 +33,14 @@
|
|||||||
:style="actionButtonStyles"
|
:style="actionButtonStyles"
|
||||||
aria-label="Remove file"
|
aria-label="Remove file"
|
||||||
>
|
>
|
||||||
<div class="fas fa-times"></div>
|
<div class="icon" v-html="removeIcon"></div>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { computed, inject } from 'vue';
|
import { computed, inject, onMounted, ref } from 'vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@ -81,9 +81,12 @@ export default {
|
|||||||
const showFileInfo = computed(() => content.value?.showFileInfo);
|
const showFileInfo = computed(() => content.value?.showFileInfo);
|
||||||
|
|
||||||
const fileItemStyles = computed(() => ({
|
const fileItemStyles = computed(() => ({
|
||||||
padding: content.value?.fileItemPadding || '12px',
|
backgroundColor: content.value?.fileItemBackground || '#fff',
|
||||||
|
borderColor: content.value?.fileItemBorderColor || '#eee',
|
||||||
borderRadius: content.value?.fileItemBorderRadius || '6px',
|
borderRadius: content.value?.fileItemBorderRadius || '6px',
|
||||||
|
padding: content.value?.fileItemPadding || '12px',
|
||||||
margin: content.value?.fileItemMargin || '0 0 8px 0',
|
margin: content.value?.fileItemMargin || '0 0 8px 0',
|
||||||
|
boxShadow: content.value?.fileItemShadow || '0 2px 4px rgba(0, 0, 0, 0.05)',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
}));
|
}));
|
||||||
@ -105,6 +108,7 @@ export default {
|
|||||||
const actionButtonStyles = computed(() => ({
|
const actionButtonStyles = computed(() => ({
|
||||||
width: content.value?.actionButtonSize || '28px',
|
width: content.value?.actionButtonSize || '28px',
|
||||||
height: content.value?.actionButtonSize || '28px',
|
height: content.value?.actionButtonSize || '28px',
|
||||||
|
backgroundColor: content.value?.actionButtonBackground || '#fff',
|
||||||
color: content.value?.actionButtonColor || '#666',
|
color: content.value?.actionButtonColor || '#666',
|
||||||
borderRadius: content.value?.actionButtonBorderRadius || '4px',
|
borderRadius: content.value?.actionButtonBorderRadius || '4px',
|
||||||
margin: content.value?.actionButtonMargin || '0 0 0 4px',
|
margin: content.value?.actionButtonMargin || '0 0 0 4px',
|
||||||
@ -120,6 +124,17 @@ export default {
|
|||||||
return `${(fileSizeInBytes / Math.pow(1024, i)).toFixed(2)} ${sizes[i]}`;
|
return `${(fileSizeInBytes / Math.pow(1024, i)).toFixed(2)} ${sizes[i]}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { getIcon } = wwLib.useIcons();
|
||||||
|
const removeIcon = ref(null);
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
try {
|
||||||
|
removeIcon.value = await getIcon('lucide/trash');
|
||||||
|
} catch (e) {
|
||||||
|
removeIcon.value = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
formattedSize,
|
formattedSize,
|
||||||
filesCount,
|
filesCount,
|
||||||
@ -129,6 +144,7 @@ export default {
|
|||||||
actionButtonStyles,
|
actionButtonStyles,
|
||||||
content,
|
content,
|
||||||
showFileInfo,
|
showFileInfo,
|
||||||
|
removeIcon,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -143,7 +159,6 @@ export default {
|
|||||||
border-radius: v-bind('content?.fileItemBorderRadius || "6px"');
|
border-radius: v-bind('content?.fileItemBorderRadius || "6px"');
|
||||||
margin-bottom: v-bind('(content?.fileItemMargin || "0 0 8px 0").split(" ")[2] || "8px"');
|
margin-bottom: v-bind('(content?.fileItemMargin || "0 0 8px 0").split(" ")[2] || "8px"');
|
||||||
background-color: v-bind('content?.fileItemBackground || "#fff"');
|
background-color: v-bind('content?.fileItemBackground || "#fff"');
|
||||||
box-shadow: v-bind('content?.fileItemShadow || "0 2px 4px rgba(0, 0, 0, 0.05)"');
|
|
||||||
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
|
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
|
||||||
transform-origin: center;
|
transform-origin: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -152,14 +167,6 @@ export default {
|
|||||||
will-change: transform, opacity;
|
will-change: transform, opacity;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border-color: v-bind('content?.fileItemHoverBorderColor || content?.fileItemBorderColor || "#ddd"');
|
|
||||||
background-color: v-bind('content?.fileItemHoverBackground || content?.fileItemBackground || "#fff"');
|
|
||||||
box-shadow: v-bind(
|
|
||||||
'content?.fileItemHoverShadow || content?.fileItemShadow || "0 2px 4px rgba(0, 0, 0, 0.05)"'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
&__progress {
|
&__progress {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
@ -170,6 +177,14 @@ export default {
|
|||||||
opacity: 0.2;
|
opacity: 0.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: v-bind('content?.fileItemHoverBorderColor || content?.fileItemBorderColor || "#ddd"');
|
||||||
|
background-color: v-bind('content?.fileItemHoverBackground || content?.fileItemBackground || "#fff"');
|
||||||
|
box-shadow: v-bind(
|
||||||
|
'content?.fileItemHoverShadow || content?.fileItemShadow || "0 2px 4px rgba(0, 0, 0, 0.05)"'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
&--disabled {
|
&--disabled {
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
@ -207,6 +222,10 @@ export default {
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:hover &__actions {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
&__btn {
|
&__btn {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -224,8 +243,8 @@ export default {
|
|||||||
&:hover:not(:disabled) {
|
&:hover:not(:disabled) {
|
||||||
border-color: v-bind(
|
border-color: v-bind(
|
||||||
'content?.actionButtonHoverBorderColor || content?.fileItemHoverBorderColor || "#ddd"'
|
'content?.actionButtonHoverBorderColor || content?.fileItemHoverBorderColor || "#ddd"'
|
||||||
) !important;
|
);
|
||||||
background-color: v-bind('content?.actionButtonHoverBackground || "#f8f8f8"') !important;
|
background-color: v-bind('content?.actionButtonHoverBackground || "#f8f8f8"');
|
||||||
transform: scale(1.05);
|
transform: scale(1.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,10 +252,25 @@ export default {
|
|||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
&:hover &__actions {
|
&--remove:hover:not(:disabled) {
|
||||||
opacity: 1;
|
color: v-bind('content?.actionButtonRemoveHoverColor || content?.progressBarColor || "#999"');
|
||||||
|
border-color: v-bind('content?.actionButtonRemoveHoverColor || content?.progressBarColor || "#999"');
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
width: 50%;
|
||||||
|
height: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
:deep(svg) {
|
||||||
|
width: 100% !important;
|
||||||
|
height: 100% !important;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -142,6 +142,7 @@ export default {
|
|||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
displayAllowedValues: ['flex', 'inline-flex', 'block'],
|
displayAllowedValues: ['flex', 'inline-flex', 'block'],
|
||||||
|
icons: ['lucide/trash'],
|
||||||
},
|
},
|
||||||
triggerEvents: [
|
triggerEvents: [
|
||||||
{
|
{
|
||||||
|
@ -138,7 +138,7 @@
|
|||||||
v-if="dataType === 'multipart/form-data'"
|
v-if="dataType === 'multipart/form-data'"
|
||||||
tooltip-position="top-left"
|
tooltip-position="top-left"
|
||||||
forced-content="Not allowed with content-type multipart/form-data"
|
forced-content="Not allowed with content-type multipart/form-data"
|
||||||
class="ml-2 text-yellow-500"
|
class="ml-2 content-warning"
|
||||||
/>
|
/>
|
||||||
<wwEditorQuestionMark
|
<wwEditorQuestionMark
|
||||||
v-else
|
v-else
|
||||||
@ -151,10 +151,34 @@
|
|||||||
<wwEditorFormRow v-if="!isThroughServer">
|
<wwEditorFormRow v-if="!isThroughServer">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<wwEditorInputSwitch :model-value="isWithCredentials" @update:modelValue="setIsWithCredentials" />
|
<wwEditorInputSwitch :model-value="isWithCredentials" @update:modelValue="setIsWithCredentials" />
|
||||||
<div class="body-2 ml-2">Send credentials</div>
|
<div class="body-sm ml-2">Send credentials</div>
|
||||||
<wwEditorQuestionMark tooltip-position="top-left" tooltip-name="rest-api-credentials" class="ml-auto" />
|
<wwEditorQuestionMark tooltip-position="top-left" tooltip-name="rest-api-credentials" class="ml-auto" />
|
||||||
</div>
|
</div>
|
||||||
</wwEditorFormRow>
|
</wwEditorFormRow>
|
||||||
|
<wwEditorFormRow>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<wwEditorInputSwitch :model-value="useStreaming" @update:modelValue="setUseStreaming" />
|
||||||
|
<div class="body-sm ml-2">Stream response</div>
|
||||||
|
<wwEditorQuestionMark
|
||||||
|
tooltip-position="top-left"
|
||||||
|
forced-content="The response will be streamed in real-time. You can use the stream variable to receive the data. This requires the server to support streaming responses."
|
||||||
|
class="ml-auto"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</wwEditorFormRow>
|
||||||
|
<wwEditorInputRow
|
||||||
|
v-if="useStreaming"
|
||||||
|
label="Stream variable"
|
||||||
|
placeholder="Select an array variable"
|
||||||
|
type="select"
|
||||||
|
:actions="[{ icon: 'plus', label: 'Create variable', onAction: createWwVariable }]"
|
||||||
|
:options="wwVariableOptions"
|
||||||
|
:model-value="streamVariableId"
|
||||||
|
@update:modelValue="setStreamVariableId"
|
||||||
|
@action="action => action?.onAction()"
|
||||||
|
required
|
||||||
|
tooltip="The array variable that will receive the stream data"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -172,10 +196,17 @@ export default {
|
|||||||
dataType: null,
|
dataType: null,
|
||||||
isThroughServer: false,
|
isThroughServer: false,
|
||||||
isWithCredentials: false,
|
isWithCredentials: false,
|
||||||
|
useStreaming: false,
|
||||||
|
streamVariableId: null,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
emits: ['update:args'],
|
emits: ['update:args'],
|
||||||
|
setup() {
|
||||||
|
const { website: websiteVariables, components: componentVariables } = wwLib.wwVariable.useEditorVariables();
|
||||||
|
|
||||||
|
return { websiteVariables, componentVariables };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
dataChoices: [
|
dataChoices: [
|
||||||
@ -230,9 +261,36 @@ export default {
|
|||||||
useRawBody() {
|
useRawBody() {
|
||||||
return this.args.useRawBody || false;
|
return this.args.useRawBody || false;
|
||||||
},
|
},
|
||||||
|
useStreaming() {
|
||||||
|
return this.args.useStreaming || false;
|
||||||
|
},
|
||||||
|
streamVariableId() {
|
||||||
|
return this.args.streamVariableId;
|
||||||
|
},
|
||||||
isData() {
|
isData() {
|
||||||
return ['POST', 'PUT', 'PATCH', 'DELETE'].includes(this.method);
|
return ['POST', 'PUT', 'PATCH', 'DELETE'].includes(this.method);
|
||||||
},
|
},
|
||||||
|
wwVariables() {
|
||||||
|
return [
|
||||||
|
...(this.websiteVariables ? Object.values(this.websiteVariables) : []),
|
||||||
|
...(this.componentVariables ? Object.values(this.componentVariables) : []),
|
||||||
|
];
|
||||||
|
},
|
||||||
|
wwVariableOptions() {
|
||||||
|
return this.wwVariables
|
||||||
|
.filter(variable => variable.type === 'array')
|
||||||
|
.map(variable => {
|
||||||
|
const labelPrefix = variable.componentType
|
||||||
|
? wwLib.wwElement.getComponentLabel(variable.componentType, variable.componentUid)
|
||||||
|
: null;
|
||||||
|
const label = labelPrefix ? `${labelPrefix} - ${variable.name}` : variable.name;
|
||||||
|
return {
|
||||||
|
label,
|
||||||
|
value: variable.id,
|
||||||
|
icon: variable.type,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
if (!this.method) this.setMethod('POST');
|
if (!this.method) this.setMethod('POST');
|
||||||
@ -270,6 +328,21 @@ export default {
|
|||||||
setUseRawBody(useRawBody) {
|
setUseRawBody(useRawBody) {
|
||||||
this.$emit('update:args', { ...this.args, useRawBody, data: useRawBody ? null : [] });
|
this.$emit('update:args', { ...this.args, useRawBody, data: useRawBody ? null : [] });
|
||||||
},
|
},
|
||||||
|
setUseStreaming(useStreaming) {
|
||||||
|
this.$emit('update:args', {
|
||||||
|
...this.args,
|
||||||
|
useStreaming,
|
||||||
|
isThroughServer: useStreaming ? false : this.isThroughServer,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
setStreamVariableId(streamVariableId) {
|
||||||
|
this.$emit('update:args', { ...this.args, streamVariableId });
|
||||||
|
},
|
||||||
|
createWwVariable() {
|
||||||
|
wwLib.wwPopupSidebars.open({ name: 'NAVIGATOR' });
|
||||||
|
wwLib.$emit('wwTopBar:navigator:tab', 'data');
|
||||||
|
wwLib.$emit('wwTopBar:navigator:data:variables:set', null);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -0,0 +1,123 @@
|
|||||||
|
export async function consumeEventStream(response, streamVariableId, wwUtils) {
|
||||||
|
if (!response.body) {
|
||||||
|
throw new Error('ReadableStream not supported in this browser.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const reader = response.body.getReader();
|
||||||
|
const decoder = new TextDecoder();
|
||||||
|
let buffer = '';
|
||||||
|
|
||||||
|
let streamActive = true;
|
||||||
|
while (streamActive) {
|
||||||
|
const { done, value } = await reader.read();
|
||||||
|
|
||||||
|
if (done) {
|
||||||
|
streamActive = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const chunk = decoder.decode(value, { stream: true });
|
||||||
|
buffer += chunk;
|
||||||
|
|
||||||
|
let newlineIndex;
|
||||||
|
while ((newlineIndex = buffer.indexOf('\n')) >= 0) {
|
||||||
|
let line = buffer.slice(0, newlineIndex).trim();
|
||||||
|
buffer = buffer.slice(newlineIndex + 1);
|
||||||
|
|
||||||
|
if (!line) continue;
|
||||||
|
|
||||||
|
if (line.startsWith('data:')) {
|
||||||
|
const dataContent = line.substring(5).trim();
|
||||||
|
if (dataContent === '[DONE]') {
|
||||||
|
streamActive = false;
|
||||||
|
wwUtils?.log('info', '[REST API Stream] Received [DONE] in data: line.');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (dataContent) {
|
||||||
|
try {
|
||||||
|
const parsedData = JSON.parse(dataContent);
|
||||||
|
const currentData = wwLib.wwVariable.getValue(streamVariableId) || [];
|
||||||
|
wwLib.wwVariable.updateValue(streamVariableId, [...currentData, parsedData]);
|
||||||
|
} catch (parseError) {
|
||||||
|
wwUtils?.log('warn', `[REST API Stream] Non-JSON data in data: line: ${dataContent}`, {
|
||||||
|
parseError,
|
||||||
|
});
|
||||||
|
const currentData = wwLib.wwVariable.getValue(streamVariableId) || [];
|
||||||
|
wwLib.wwVariable.updateValue(streamVariableId, [...currentData, dataContent]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (line === '[DONE]') {
|
||||||
|
streamActive = false;
|
||||||
|
wwUtils?.log('info', '[REST API Stream] Received [DONE] on its own line.');
|
||||||
|
break;
|
||||||
|
} else if (
|
||||||
|
line.startsWith('id:') ||
|
||||||
|
line.startsWith('event:') ||
|
||||||
|
line.startsWith('retry:') ||
|
||||||
|
line.startsWith(':')
|
||||||
|
) {
|
||||||
|
wwUtils?.log('debug', `[REST API Stream] Ignoring SSE metadata line: ${line}`);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
const parsedData = JSON.parse(line);
|
||||||
|
const currentData = wwLib.wwVariable.getValue(streamVariableId) || [];
|
||||||
|
wwLib.wwVariable.updateValue(streamVariableId, [...currentData, parsedData]);
|
||||||
|
} catch (parseError) {
|
||||||
|
wwUtils?.log('debug', `[REST API Stream] Adding raw line as non-JSON: ${line}`, {
|
||||||
|
parseError,
|
||||||
|
});
|
||||||
|
const currentData = wwLib.wwVariable.getValue(streamVariableId) || [];
|
||||||
|
wwLib.wwVariable.updateValue(streamVariableId, [...currentData, line]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!streamActive) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const finalBufferTrimmed = buffer.trim();
|
||||||
|
if (finalBufferTrimmed) {
|
||||||
|
if (finalBufferTrimmed.startsWith('data:')) {
|
||||||
|
const dataContent = finalBufferTrimmed.substring(5).trim();
|
||||||
|
if (dataContent && dataContent !== '[DONE]') {
|
||||||
|
try {
|
||||||
|
const parsedData = JSON.parse(dataContent);
|
||||||
|
const currentData = wwLib.wwVariable.getValue(streamVariableId) || [];
|
||||||
|
wwLib.wwVariable.updateValue(streamVariableId, [...currentData, parsedData]);
|
||||||
|
} catch (e) {
|
||||||
|
wwUtils?.log(
|
||||||
|
'warn',
|
||||||
|
`[REST API Stream] Failed to parse JSON from final buffer data: line: ${dataContent}`,
|
||||||
|
{ e }
|
||||||
|
);
|
||||||
|
const currentData = wwLib.wwVariable.getValue(streamVariableId) || [];
|
||||||
|
wwLib.wwVariable.updateValue(streamVariableId, [...currentData, dataContent]);
|
||||||
|
}
|
||||||
|
} else if (dataContent === '[DONE]') {
|
||||||
|
wwUtils?.log('info', '[REST API Stream] Received [DONE] in final buffer data: line.');
|
||||||
|
}
|
||||||
|
} else if (finalBufferTrimmed === '[DONE]') {
|
||||||
|
wwUtils?.log('info', '[REST API Stream] Received [DONE] as final buffer content.');
|
||||||
|
} else if (
|
||||||
|
finalBufferTrimmed.startsWith('id:') ||
|
||||||
|
finalBufferTrimmed.startsWith('event:') ||
|
||||||
|
finalBufferTrimmed.startsWith('retry:') ||
|
||||||
|
finalBufferTrimmed.startsWith(':')
|
||||||
|
) {
|
||||||
|
wwUtils?.log('debug', `[REST API Stream] Ignoring SSE metadata in final buffer: ${finalBufferTrimmed}`);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
const parsedData = JSON.parse(finalBufferTrimmed);
|
||||||
|
const currentData = wwLib.wwVariable.getValue(streamVariableId) || [];
|
||||||
|
wwLib.wwVariable.updateValue(streamVariableId, [...currentData, parsedData]);
|
||||||
|
} catch (e) {
|
||||||
|
wwUtils?.log('debug', `[REST API Stream] Adding raw final buffer as non-JSON: ${finalBufferTrimmed}`, {
|
||||||
|
e,
|
||||||
|
});
|
||||||
|
const currentData = wwLib.wwVariable.getValue(streamVariableId) || [];
|
||||||
|
wwLib.wwVariable.updateValue(streamVariableId, [...currentData, finalBufferTrimmed]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return wwLib.wwVariable.getValue(streamVariableId);
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import qs from 'qs';
|
import qs from 'qs';
|
||||||
|
import { consumeEventStream } from './utils/streamHandler';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
/*=============================================m_ÔÔ_m=============================================\
|
/*=============================================m_ÔÔ_m=============================================\
|
||||||
@ -40,10 +41,29 @@ export default {
|
|||||||
isThroughServer,
|
isThroughServer,
|
||||||
useRawBody = false,
|
useRawBody = false,
|
||||||
isWithCredentials = false,
|
isWithCredentials = false,
|
||||||
|
useStreaming = false,
|
||||||
|
streamVariableId = null,
|
||||||
},
|
},
|
||||||
wwUtils
|
wwUtils
|
||||||
) {
|
) {
|
||||||
if (isThroughServer) {
|
|
||||||
|
if (useStreaming) {
|
||||||
|
if (isThroughServer) {
|
||||||
|
throw new Error('Streaming is not supported with server-side requests.');
|
||||||
|
}
|
||||||
|
return await this._streamApiRequest(
|
||||||
|
url,
|
||||||
|
method,
|
||||||
|
data,
|
||||||
|
headers,
|
||||||
|
params,
|
||||||
|
dataType,
|
||||||
|
useRawBody,
|
||||||
|
isWithCredentials,
|
||||||
|
streamVariableId,
|
||||||
|
wwUtils
|
||||||
|
);
|
||||||
|
} else if (isThroughServer) {
|
||||||
const websiteId = wwLib.wwWebsiteData.getInfo().id;
|
const websiteId = wwLib.wwWebsiteData.getInfo().id;
|
||||||
const pluginURL = wwLib.wwApiRequests._getPluginsUrl();
|
const pluginURL = wwLib.wwApiRequests._getPluginsUrl();
|
||||||
|
|
||||||
@ -74,46 +94,140 @@ export default {
|
|||||||
|
|
||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
|
async _streamApiRequest(
|
||||||
|
url,
|
||||||
|
method,
|
||||||
|
data,
|
||||||
|
headers,
|
||||||
|
params,
|
||||||
|
dataType,
|
||||||
|
useRawBody,
|
||||||
|
isWithCredentials,
|
||||||
|
streamVariableId,
|
||||||
|
wwUtils
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
wwLib.wwVariable.updateValue(streamVariableId, []);
|
||||||
|
|
||||||
|
const payload = computePayload(method, data, headers, params, dataType, useRawBody, wwUtils);
|
||||||
|
|
||||||
|
const streamHeaders = {
|
||||||
|
...payload.headers,
|
||||||
|
Accept: 'text/event-stream',
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method,
|
||||||
|
headers: streamHeaders,
|
||||||
|
body: ['GET', 'HEAD'].includes(method) ? undefined : payload.data,
|
||||||
|
credentials: isWithCredentials ? 'include' : 'same-origin',
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const errorText = await response.text();
|
||||||
|
throw new Error(`HTTP error ${response.status}: ${errorText}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return await consumeEventStream(response, streamVariableId, wwUtils);
|
||||||
|
} catch (error) {
|
||||||
|
wwUtils?.log('error', '[REST API Stream] Error', {
|
||||||
|
type: 'error',
|
||||||
|
preview: {
|
||||||
|
message: error.message,
|
||||||
|
stack: error.stack,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function computePayload(method, data, headers, params, dataType, useRawBody) {
|
function computePayload(method, data, headers, params, dataType, useRawBody, wwUtils) {
|
||||||
if (!useRawBody) {
|
try {
|
||||||
data = computeList(data);
|
let processedData = data;
|
||||||
|
if (!useRawBody) {
|
||||||
|
processedData = computeList(data, 'data', wwUtils);
|
||||||
|
|
||||||
switch (dataType) {
|
switch (dataType) {
|
||||||
case 'application/x-www-form-urlencoded': {
|
case 'application/x-www-form-urlencoded': {
|
||||||
data = qs.stringify(data);
|
processedData = qs.stringify(processedData);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'multipart/form-data': {
|
case 'multipart/form-data': {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
for (const key in data) formData.append(key, data[key]);
|
for (const key in processedData) formData.append(key, processedData[key]);
|
||||||
data = formData;
|
processedData = formData;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (method) {
|
||||||
|
case 'OPTIONS':
|
||||||
|
case 'GET':
|
||||||
|
case 'DELETE':
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
switch (method) {
|
const processedParams = computeList(params, 'params', wwUtils);
|
||||||
case 'OPTIONS':
|
const processedHeaders = {
|
||||||
case 'GET':
|
|
||||||
case 'DELETE':
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
data,
|
|
||||||
params: computeList(params),
|
|
||||||
headers: {
|
|
||||||
'content-type': dataType || 'application/json',
|
'content-type': dataType || 'application/json',
|
||||||
...computeList(headers),
|
...computeList(headers, 'headers', wwUtils),
|
||||||
},
|
};
|
||||||
};
|
|
||||||
|
return {
|
||||||
|
data: processedData,
|
||||||
|
params: processedParams,
|
||||||
|
headers: processedHeaders,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
wwUtils?.log('error', '[REST API] Error in computePayload', {
|
||||||
|
type: 'error',
|
||||||
|
preview: {
|
||||||
|
error: error.message,
|
||||||
|
stack: error.stack,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function computeList(list) {
|
function computeList(list, label, wwUtils) {
|
||||||
return (list || []).reduce((obj, item) => ({ ...obj, [item.key]: item.value }), {});
|
try {
|
||||||
|
if (!list) return {};
|
||||||
|
|
||||||
|
if (!Array.isArray(list)) {
|
||||||
|
wwUtils?.log('warn', `[REST API] computeList expected array but got ${typeof list}`, {
|
||||||
|
type: 'warn',
|
||||||
|
preview: list,
|
||||||
|
});
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = (list || []).reduce((obj, item) => {
|
||||||
|
if (!item || typeof item !== 'object' || !('key' in item)) {
|
||||||
|
wwUtils?.log('warn', `[REST API] computeList skipping invalid item`, {
|
||||||
|
type: 'warn',
|
||||||
|
preview: item,
|
||||||
|
});
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
return { ...obj, [item.key]: item.value };
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
wwUtils?.log('error', `[REST API] Error in computeList for ${label}`, {
|
||||||
|
type: 'error',
|
||||||
|
preview: {
|
||||||
|
error: error.message,
|
||||||
|
stack: error.stack,
|
||||||
|
list: typeof list === 'undefined' ? 'undefined' : list === null ? 'null' : list,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
throw new Error(`Failed to process ${label}: ${error.message}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,6 +94,30 @@
|
|||||||
:model-value="body"
|
:model-value="body"
|
||||||
@update:modelValue="setArgs({ body: $event })"
|
@update:modelValue="setArgs({ body: $event })"
|
||||||
/>
|
/>
|
||||||
|
<wwEditorFormRow>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<wwEditorInputSwitch :model-value="useStreaming" @update:modelValue="setUseStreaming" />
|
||||||
|
<div class="body-sm ml-2">Stream response</div>
|
||||||
|
<wwEditorQuestionMark
|
||||||
|
tooltip-position="top-left"
|
||||||
|
forced-content="The response will be streamed in real-time. You can use the stream variable to receive the data. This requires the edge function to support streaming responses."
|
||||||
|
class="ml-auto"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</wwEditorFormRow>
|
||||||
|
<wwEditorInputRow
|
||||||
|
v-if="useStreaming"
|
||||||
|
label="Stream variable"
|
||||||
|
placeholder="Select an array variable"
|
||||||
|
type="select"
|
||||||
|
:actions="[{ icon: 'plus', label: 'Create variable', onAction: createWwVariable }]"
|
||||||
|
:options="wwVariableOptions"
|
||||||
|
:model-value="streamVariableId"
|
||||||
|
@update:modelValue="setArgs({ streamVariableId: $event })"
|
||||||
|
@action="action => action?.onAction()"
|
||||||
|
required
|
||||||
|
tooltip="The array variable that will receive the stream data"
|
||||||
|
/>
|
||||||
<wwLoader :loading="isLoading" />
|
<wwLoader :loading="isLoading" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -104,9 +128,14 @@ export default {
|
|||||||
components: { Expandable },
|
components: { Expandable },
|
||||||
props: {
|
props: {
|
||||||
plugin: { type: Object, required: true },
|
plugin: { type: Object, required: true },
|
||||||
args: { type: Object, default: () => ({ fieldsMode: 'guided' }) },
|
args: { type: Object, default: () => ({ fieldsMode: 'guided', useStreaming: false }) },
|
||||||
},
|
},
|
||||||
emits: ['update:args'],
|
emits: ['update:args'],
|
||||||
|
setup() {
|
||||||
|
const { website: websiteVariables, components: componentVariables } = wwLib.wwVariable.useEditorVariables();
|
||||||
|
|
||||||
|
return { websiteVariables, componentVariables };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isAdvancedOpen: false,
|
isAdvancedOpen: false,
|
||||||
@ -130,6 +159,35 @@ export default {
|
|||||||
body() {
|
body() {
|
||||||
return this.args.body;
|
return this.args.body;
|
||||||
},
|
},
|
||||||
|
useStreaming() {
|
||||||
|
return this.args.useStreaming || false;
|
||||||
|
},
|
||||||
|
streamVariableId() {
|
||||||
|
return this.args.streamVariableId;
|
||||||
|
},
|
||||||
|
wwVariables() {
|
||||||
|
return [
|
||||||
|
...(this.websiteVariables ? Object.values(this.websiteVariables) : []),
|
||||||
|
...(this.componentVariables ? Object.values(this.componentVariables) : []),
|
||||||
|
];
|
||||||
|
},
|
||||||
|
wwVariableOptions() {
|
||||||
|
return this.wwVariables
|
||||||
|
.filter(variable => variable.type === 'array')
|
||||||
|
.map(variable => {
|
||||||
|
const labelPrefix = variable.componentType
|
||||||
|
? wwLib.wwElement.getComponentLabel(variable.componentType, variable.componentUid)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
const label = labelPrefix ? `${labelPrefix} - ${variable.name}` : variable.name;
|
||||||
|
|
||||||
|
return {
|
||||||
|
label,
|
||||||
|
value: variable.id,
|
||||||
|
icon: variable.type,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.fetchFunctions();
|
this.fetchFunctions();
|
||||||
@ -148,6 +206,14 @@ export default {
|
|||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
setUseStreaming(useStreaming) {
|
||||||
|
this.setArgs({ useStreaming });
|
||||||
|
},
|
||||||
|
createWwVariable() {
|
||||||
|
wwLib.wwPopupSidebars.open({ name: 'NAVIGATOR' });
|
||||||
|
wwLib.$emit('wwTopBar:navigator:tab', 'data');
|
||||||
|
wwLib.$emit('wwTopBar:navigator:data:variables:set', null);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -0,0 +1,372 @@
|
|||||||
|
import { FunctionsHttpError, FunctionsRelayError, FunctionsFetchError } from '@supabase/supabase-js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds a query string from an array or object of queries.
|
||||||
|
* @param {Array|Object} queries - Input queries.
|
||||||
|
* @returns {string} - Formatted query string (e.g., "?key=value") or empty string.
|
||||||
|
*/
|
||||||
|
export function buildQueryString(queries = []) {
|
||||||
|
const queryArray = Array.isArray(queries)
|
||||||
|
? queries
|
||||||
|
: typeof queries === 'object' && queries !== null
|
||||||
|
? Object.entries(queries).map(([key, value]) => ({ key, value }))
|
||||||
|
: [];
|
||||||
|
|
||||||
|
if (!queryArray.length) return '';
|
||||||
|
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
for (const item of queryArray) {
|
||||||
|
if (item && typeof item.key === 'string') {
|
||||||
|
// Ensure key is a string
|
||||||
|
params.append(item.key, item.value ?? '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const queryString = params.toString();
|
||||||
|
return queryString ? `?${queryString}` : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds a headers object from an array or object of headers.
|
||||||
|
* @param {Array|Object} headers - Input headers.
|
||||||
|
* @returns {Object<string, string>} - Headers object.
|
||||||
|
*/
|
||||||
|
export function buildHeaders(headers = []) {
|
||||||
|
const headerObject = {};
|
||||||
|
const headersArray = Array.isArray(headers)
|
||||||
|
? headers
|
||||||
|
: typeof headers === 'object' && headers !== null
|
||||||
|
? Object.entries(headers).map(([key, value]) => ({ key, value }))
|
||||||
|
: [];
|
||||||
|
|
||||||
|
for (const item of headersArray) {
|
||||||
|
if (item && typeof item.key === 'string') {
|
||||||
|
// Ensure key is a string
|
||||||
|
// Ensure value is a string or provide default for header values
|
||||||
|
headerObject[item.key] = typeof item.value === 'string' ? item.value : String(item.value ?? '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return headerObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a line from an SSE stream.
|
||||||
|
* Handles 'data: ' prefix and '[DONE]' signal.
|
||||||
|
* Attempts JSON parsing. Returns null for signals, empty lines, or non-JSON data.
|
||||||
|
* @param {string} line - The raw line content.
|
||||||
|
* @param {object} [logger=console] - Optional logger (like wwUtils or wwLib.wwLog).
|
||||||
|
* @returns {object|null} - Parsed JSON data, or null if line should be skipped.
|
||||||
|
*/
|
||||||
|
export function parseSseLine(line, logger = console) {
|
||||||
|
line = line?.trim();
|
||||||
|
if (!line) return null;
|
||||||
|
|
||||||
|
if (line.startsWith('data:')) {
|
||||||
|
line = line.substring(5).trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line === '[DONE]') {
|
||||||
|
logger?.debug?.('[Supabase Stream] Received [DONE] signal.');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!line) return null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
return JSON.parse(line);
|
||||||
|
} catch (parseError) {
|
||||||
|
logger?.warn?.(`[Supabase Stream] Skipping non-JSON data line: "${line}"`, { parseError });
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the successful response body of a non-streaming function.
|
||||||
|
* @param {*} data - The raw response data.
|
||||||
|
* @returns {*} - Parsed data (object, string, or original type).
|
||||||
|
*/
|
||||||
|
export function parseFunctionResponse(data) {
|
||||||
|
try {
|
||||||
|
if (typeof data === 'object' && data !== null) return data;
|
||||||
|
if (typeof data === 'string') return JSON.parse(data);
|
||||||
|
return data;
|
||||||
|
} catch (e) {
|
||||||
|
if (typeof data === 'string') {
|
||||||
|
console.warn('[Supabase] Non-JSON string response received:', data);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
throw new Error(`Failed to parse non-streaming function response of type ${typeof data}`, { cause: e });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Standardizes errors thrown by Supabase function invocation.
|
||||||
|
* @param {Error} error - The original error from Supabase invoke.
|
||||||
|
* @returns {Promise<Error>} - A new Error object with structured cause.
|
||||||
|
*/
|
||||||
|
export async function handleSupabaseInvokeError(error) {
|
||||||
|
const status = error?.context?.status;
|
||||||
|
let causeData = null;
|
||||||
|
let errorType = 'Unknown function invocation error';
|
||||||
|
|
||||||
|
try {
|
||||||
|
causeData = error?.context ? await error.context.text?.() : null;
|
||||||
|
if (causeData && typeof causeData === 'string') {
|
||||||
|
try {
|
||||||
|
const jsonData = JSON.parse(causeData);
|
||||||
|
causeData = jsonData;
|
||||||
|
} catch (jsonErr) {
|
||||||
|
// Keep raw text if not JSON
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to get Supabase error context text', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
const cause = {
|
||||||
|
name: error?.name,
|
||||||
|
message: error?.message,
|
||||||
|
status,
|
||||||
|
responseBody: causeData,
|
||||||
|
originalError: error,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (error instanceof FunctionsHttpError) {
|
||||||
|
errorType = `Function returned an error status: ${status || 'unknown'}`;
|
||||||
|
} else if (error instanceof FunctionsRelayError) {
|
||||||
|
errorType = `Function relay error: ${error.message}`;
|
||||||
|
} else if (error instanceof FunctionsFetchError) {
|
||||||
|
errorType = `Function fetch error: ${error.message}`;
|
||||||
|
} else if (error?.message) {
|
||||||
|
errorType = error.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
const standardizedError = new Error(errorType);
|
||||||
|
standardizedError.cause = cause;
|
||||||
|
return standardizedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes a regular (non-streaming) edge function invocation.
|
||||||
|
* @param {Object} params - Function parameters
|
||||||
|
* @param {Object} params.instance - Supabase client instance
|
||||||
|
* @param {string} params.functionName - Name of the edge function to invoke
|
||||||
|
* @param {string} params.queryString - Query string for the request
|
||||||
|
* @param {string} params.method - HTTP method (GET, POST, etc.)
|
||||||
|
* @param {any} params.body - Request body
|
||||||
|
* @param {Object} params.headerObject - Request headers
|
||||||
|
* @param {Object} [wwUtils] - Optional logging utility
|
||||||
|
* @returns {Promise<any>} - Function response
|
||||||
|
*/
|
||||||
|
export async function executeRegularInvocation(
|
||||||
|
{ instance, functionName, queryString, method, body, headerObject },
|
||||||
|
wwUtils
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const { data, error } = await instance.functions.invoke(functionName + queryString, {
|
||||||
|
method,
|
||||||
|
body,
|
||||||
|
headers: headerObject,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (error) throw error;
|
||||||
|
|
||||||
|
const parsedData = parseFunctionResponse(data);
|
||||||
|
wwUtils?.log('info', `[Supabase] Edge function executed successfully - ${functionName}`, {
|
||||||
|
type: 'response',
|
||||||
|
preview: parsedData,
|
||||||
|
});
|
||||||
|
|
||||||
|
return parsedData;
|
||||||
|
} catch (error) {
|
||||||
|
const standardizedError = await handleSupabaseInvokeError(error);
|
||||||
|
wwUtils?.log('error', `[Supabase] Edge function error - ${functionName}`, {
|
||||||
|
type: 'error',
|
||||||
|
preview: standardizedError,
|
||||||
|
});
|
||||||
|
throw standardizedError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes a streaming edge function invocation.
|
||||||
|
* @param {Object} params - Function parameters
|
||||||
|
* @param {Object} params.instance - Supabase client instance
|
||||||
|
* @param {string} params.functionName - Name of the edge function to invoke
|
||||||
|
* @param {string} params.queryString - Query string for the request
|
||||||
|
* @param {string} params.method - HTTP method (GET, POST, etc.)
|
||||||
|
* @param {any} params.body - Request body
|
||||||
|
* @param {Object} params.headerObject - Request headers
|
||||||
|
* @param {string} params.streamVariableId - ID of the variable to update with stream data
|
||||||
|
* @param {Object} params.wwLib - Window & Widgets library for variable updates
|
||||||
|
* @param {Object} [wwUtils] - Optional logging utility
|
||||||
|
* @returns {Promise<any>} - Final accumulated stream data
|
||||||
|
*/
|
||||||
|
export async function executeStreamingInvocation(
|
||||||
|
{ instance, functionName, queryString, method, body, headerObject, streamVariableId, wwLib },
|
||||||
|
wwUtils
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
wwLib.wwVariable.updateValue(streamVariableId, []);
|
||||||
|
|
||||||
|
const invokeOptions = {
|
||||||
|
method,
|
||||||
|
body: method === 'GET' ? undefined : body,
|
||||||
|
headers: {
|
||||||
|
...headerObject,
|
||||||
|
Accept: 'text/event-stream',
|
||||||
|
},
|
||||||
|
responseType: 'stream',
|
||||||
|
};
|
||||||
|
|
||||||
|
const { data: responseData, error: invokeError } = await instance.functions.invoke(
|
||||||
|
functionName + queryString,
|
||||||
|
invokeOptions
|
||||||
|
);
|
||||||
|
|
||||||
|
if (invokeError) throw invokeError;
|
||||||
|
|
||||||
|
if (!responseData || !responseData.body || typeof responseData.body.getReader !== 'function') {
|
||||||
|
console.error('[Supabase Stream Debug] Failed response data object:', responseData);
|
||||||
|
throw new Error('Response data does not contain a readable stream.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const reader = responseData.body.getReader();
|
||||||
|
const decoder = new TextDecoder();
|
||||||
|
let buffer = '';
|
||||||
|
|
||||||
|
let streamActive = true;
|
||||||
|
while (streamActive) {
|
||||||
|
const { done, value } = await reader.read();
|
||||||
|
|
||||||
|
if (done) {
|
||||||
|
streamActive = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const textChunk = decoder.decode(value, { stream: true });
|
||||||
|
buffer += textChunk;
|
||||||
|
|
||||||
|
let newlineIndex;
|
||||||
|
while ((newlineIndex = buffer.indexOf('\n')) >= 0) {
|
||||||
|
let line = buffer.slice(0, newlineIndex).trim();
|
||||||
|
buffer = buffer.slice(newlineIndex + 1);
|
||||||
|
|
||||||
|
if (!line) continue; // Skip empty lines
|
||||||
|
|
||||||
|
if (line.startsWith('data:')) {
|
||||||
|
const dataContent = line.substring(5).trim();
|
||||||
|
if (dataContent === '[DONE]') {
|
||||||
|
streamActive = false;
|
||||||
|
wwUtils?.log('info', '[Supabase Stream] Received [DONE] in data: line.');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (dataContent) {
|
||||||
|
try {
|
||||||
|
const parsedData = JSON.parse(dataContent);
|
||||||
|
const currentData = wwLib.wwVariable.getValue(streamVariableId) || [];
|
||||||
|
wwLib.wwVariable.updateValue(streamVariableId, [...currentData, parsedData]);
|
||||||
|
} catch (parseError) {
|
||||||
|
wwUtils?.log('warn', `[Supabase Stream] Non-JSON data in data: line: ${dataContent}`, {
|
||||||
|
parseError,
|
||||||
|
});
|
||||||
|
// Keep non-JSON data as raw string (like REST API implementation)
|
||||||
|
const currentData = wwLib.wwVariable.getValue(streamVariableId) || [];
|
||||||
|
wwLib.wwVariable.updateValue(streamVariableId, [...currentData, dataContent]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (line === '[DONE]') {
|
||||||
|
streamActive = false;
|
||||||
|
wwUtils?.log('info', '[Supabase Stream] Received [DONE] on its own line.');
|
||||||
|
break;
|
||||||
|
} else if (
|
||||||
|
line.startsWith('id:') ||
|
||||||
|
line.startsWith('event:') ||
|
||||||
|
line.startsWith('retry:') ||
|
||||||
|
line.startsWith(':')
|
||||||
|
) {
|
||||||
|
// SSE metadata line (but not 'data:'). Ignore it.
|
||||||
|
wwUtils?.log('debug', `[Supabase Stream] Ignoring SSE metadata line: ${line}`);
|
||||||
|
} else {
|
||||||
|
// Not 'data:', not '[DONE]', and not other known SSE metadata.
|
||||||
|
// Treat the whole line as a potential payload (e.g., newline-delimited JSON/text).
|
||||||
|
try {
|
||||||
|
const parsedData = JSON.parse(line);
|
||||||
|
const currentData = wwLib.wwVariable.getValue(streamVariableId) || [];
|
||||||
|
wwLib.wwVariable.updateValue(streamVariableId, [...currentData, parsedData]);
|
||||||
|
} catch (parseError) {
|
||||||
|
wwUtils?.log('debug', `[Supabase Stream] Adding raw line as non-JSON: ${line}`, {
|
||||||
|
parseError,
|
||||||
|
});
|
||||||
|
// Keep non-JSON data as raw string (like REST API implementation)
|
||||||
|
const currentData = wwLib.wwVariable.getValue(streamVariableId) || [];
|
||||||
|
wwLib.wwVariable.updateValue(streamVariableId, [...currentData, line]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!streamActive) break; // Exit outer while loop if [DONE] was encountered
|
||||||
|
}
|
||||||
|
if (!streamActive) break; // Exit outer while loop if [DONE] was encountered
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process any remaining content in the buffer
|
||||||
|
const finalBufferTrimmed = buffer.trim();
|
||||||
|
if (finalBufferTrimmed) {
|
||||||
|
if (finalBufferTrimmed.startsWith('data:')) {
|
||||||
|
const dataContent = finalBufferTrimmed.substring(5).trim();
|
||||||
|
if (dataContent && dataContent !== '[DONE]') {
|
||||||
|
try {
|
||||||
|
const parsedData = JSON.parse(dataContent);
|
||||||
|
const currentData = wwLib.wwVariable.getValue(streamVariableId) || [];
|
||||||
|
wwLib.wwVariable.updateValue(streamVariableId, [...currentData, parsedData]);
|
||||||
|
} catch (e) {
|
||||||
|
wwUtils?.log(
|
||||||
|
'warn',
|
||||||
|
`[Supabase Stream] Failed to parse JSON from final buffer data: line: ${dataContent}`,
|
||||||
|
{ e }
|
||||||
|
);
|
||||||
|
const currentData = wwLib.wwVariable.getValue(streamVariableId) || [];
|
||||||
|
wwLib.wwVariable.updateValue(streamVariableId, [...currentData, dataContent]);
|
||||||
|
}
|
||||||
|
} else if (dataContent === '[DONE]') {
|
||||||
|
wwUtils?.log('info', '[Supabase Stream] Received [DONE] in final buffer data: line.');
|
||||||
|
}
|
||||||
|
} else if (finalBufferTrimmed === '[DONE]') {
|
||||||
|
wwUtils?.log('info', '[Supabase Stream] Received [DONE] as final buffer content.');
|
||||||
|
} else if (
|
||||||
|
finalBufferTrimmed.startsWith('id:') ||
|
||||||
|
finalBufferTrimmed.startsWith('event:') ||
|
||||||
|
finalBufferTrimmed.startsWith('retry:') ||
|
||||||
|
finalBufferTrimmed.startsWith(':')
|
||||||
|
) {
|
||||||
|
wwUtils?.log('debug', `[Supabase Stream] Ignoring SSE metadata in final buffer: ${finalBufferTrimmed}`);
|
||||||
|
} else {
|
||||||
|
// Treat the whole final buffer content as a potential payload.
|
||||||
|
try {
|
||||||
|
const parsedData = JSON.parse(finalBufferTrimmed);
|
||||||
|
const currentData = wwLib.wwVariable.getValue(streamVariableId) || [];
|
||||||
|
wwLib.wwVariable.updateValue(streamVariableId, [...currentData, parsedData]);
|
||||||
|
} catch (e) {
|
||||||
|
wwUtils?.log(
|
||||||
|
'debug',
|
||||||
|
`[Supabase Stream] Adding raw final buffer as non-JSON: ${finalBufferTrimmed}`,
|
||||||
|
{ e }
|
||||||
|
);
|
||||||
|
const currentData = wwLib.wwVariable.getValue(streamVariableId) || [];
|
||||||
|
wwLib.wwVariable.updateValue(streamVariableId, [...currentData, finalBufferTrimmed]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wwUtils?.log('info', `[Supabase] Streaming completed for Edge function - ${functionName}`, {
|
||||||
|
type: 'response',
|
||||||
|
});
|
||||||
|
|
||||||
|
return wwLib.wwVariable.getValue(streamVariableId);
|
||||||
|
} catch (error) {
|
||||||
|
const standardizedError = await handleSupabaseInvokeError(error);
|
||||||
|
wwUtils?.log('error', `[Supabase] Streaming error for Edge function - ${functionName}`, {
|
||||||
|
type: 'error',
|
||||||
|
preview: standardizedError,
|
||||||
|
});
|
||||||
|
throw standardizedError;
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,14 @@
|
|||||||
import { createClient, FunctionsHttpError, FunctionsRelayError, FunctionsFetchError } from '@supabase/supabase-js';
|
import { createClient } from '@supabase/supabase-js';
|
||||||
|
|
||||||
import { generateFilter } from './helpers/filters';
|
import { generateFilter } from './helpers/filters';
|
||||||
|
|
||||||
|
import {
|
||||||
|
buildQueryString,
|
||||||
|
buildHeaders,
|
||||||
|
executeRegularInvocation,
|
||||||
|
executeStreamingInvocation,
|
||||||
|
} from './helpers/edgeFunction.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
instance: null,
|
instance: null,
|
||||||
channels: {},
|
channels: {},
|
||||||
@ -235,49 +242,51 @@ export default {
|
|||||||
if (error) throw new Error(error.message, { cause: error });
|
if (error) throw new Error(error.message, { cause: error });
|
||||||
return this.formatReturn(data, count);
|
return this.formatReturn(data, count);
|
||||||
},
|
},
|
||||||
async invokeEdgeFunction({ functionName, body, headers = [], queries = [], method = 'POST' }, wwUtils) {
|
async invokeEdgeFunction(args, wwUtils) {
|
||||||
wwUtils?.log('info', `[Supabase] Invoke an Edge function - ${functionName}`, {
|
const {
|
||||||
|
functionName,
|
||||||
|
body,
|
||||||
|
headers = [],
|
||||||
|
queries = [],
|
||||||
|
method = 'POST',
|
||||||
|
useStreaming = false,
|
||||||
|
streamVariableId = null,
|
||||||
|
} = args;
|
||||||
|
|
||||||
|
|
||||||
|
wwUtils?.log('info', `[Supabase] ${useStreaming ? 'Streaming' : 'Invoking'} Edge function - ${functionName}`, {
|
||||||
type: 'request',
|
type: 'request',
|
||||||
preview: { body, headers, method },
|
preview: { body, headers, method },
|
||||||
});
|
});
|
||||||
const query = Array.isArray(queries)
|
const queryString = buildQueryString(queries);
|
||||||
? queries
|
const headerObject = buildHeaders(headers);
|
||||||
: queries && typeof queries === 'object'
|
|
||||||
? Object.keys(queries).map(k => ({ key: k, value: queries[k] }))
|
|
||||||
: [];
|
|
||||||
const queryString = query.length
|
|
||||||
? query.reduce((result, item) => `${result}${item.key}=${item.value}&`, '?')
|
|
||||||
: '';
|
|
||||||
const { data, error } = await this.instance.functions.invoke(functionName + queryString, {
|
|
||||||
body: method === 'GET' ? undefined : body,
|
|
||||||
headers: Array.isArray(headers)
|
|
||||||
? headers.reduce((result, item) => ({ ...result, [item.key]: item.value }), {})
|
|
||||||
: headers,
|
|
||||||
method,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (error instanceof FunctionsHttpError) {
|
if (useStreaming) {
|
||||||
throw new Error('Function returned an error with status code ' + error.context.status, {
|
return await executeStreamingInvocation(
|
||||||
cause: { ...error, status: error?.context?.status, data: await error?.context?.json?.() },
|
{
|
||||||
});
|
instance: this.instance,
|
||||||
} else if (error instanceof FunctionsRelayError) {
|
functionName,
|
||||||
throw new Error('Relay error: ' + error.message, {
|
queryString,
|
||||||
cause: { ...error, status: error?.context?.status, data: await error?.context?.json?.() },
|
method,
|
||||||
});
|
body,
|
||||||
} else if (error instanceof FunctionsFetchError) {
|
headerObject,
|
||||||
throw new Error('Fetch error: ' + error.message, {
|
streamVariableId,
|
||||||
cause: { ...error, status: error?.context?.status, data: await error?.context?.json?.() },
|
wwLib,
|
||||||
});
|
},
|
||||||
} else if (error) {
|
wwUtils
|
||||||
throw new Error(error.message, {
|
);
|
||||||
cause: { ...error, status: error?.context?.status, data: await error?.context?.json?.() },
|
} else {
|
||||||
});
|
return await executeRegularInvocation(
|
||||||
}
|
{
|
||||||
|
instance: this.instance,
|
||||||
try {
|
functionName,
|
||||||
return JSON.parse(data);
|
queryString,
|
||||||
} catch (error) {
|
method,
|
||||||
return data;
|
body,
|
||||||
|
headerObject,
|
||||||
|
},
|
||||||
|
wwUtils
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async listFiles({ bucket, path, options = {} }, wwUtils) {
|
async listFiles({ bucket, path, options = {} }, wwUtils) {
|
||||||
@ -311,14 +320,14 @@ export default {
|
|||||||
path,
|
path,
|
||||||
options.transform
|
options.transform
|
||||||
? {
|
? {
|
||||||
transform: {
|
transform: {
|
||||||
...(options.transform.format ? { format: options.transform.format } : {}),
|
...(options.transform.format ? { format: options.transform.format } : {}),
|
||||||
...(options.transform.quality ? { quality: options.transform.quality } : {}),
|
...(options.transform.quality ? { quality: options.transform.quality } : {}),
|
||||||
...(options.transform.resize ? { resize: options.transform.resize } : {}),
|
...(options.transform.resize ? { resize: options.transform.resize } : {}),
|
||||||
...(options.transform.width ? { width: options.transform.width } : {}),
|
...(options.transform.width ? { width: options.transform.width } : {}),
|
||||||
...(options.transform.height ? { height: options.transform.height } : {}),
|
...(options.transform.height ? { height: options.transform.height } : {}),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
: {}
|
: {}
|
||||||
);
|
);
|
||||||
if (error) throw new Error(error.message, { cause: error });
|
if (error) throw new Error(error.message, { cause: error });
|
||||||
@ -370,12 +379,12 @@ export default {
|
|||||||
download: options.download ? options.download.filename || true : false,
|
download: options.download ? options.download.filename || true : false,
|
||||||
transform: options.transform
|
transform: options.transform
|
||||||
? {
|
? {
|
||||||
...(options.transform.format ? { format: options.transform.format } : {}),
|
...(options.transform.format ? { format: options.transform.format } : {}),
|
||||||
...(options.transform.quality ? { quality: options.transform.quality } : {}),
|
...(options.transform.quality ? { quality: options.transform.quality } : {}),
|
||||||
...(options.transform.resize ? { resize: options.transform.resize } : {}),
|
...(options.transform.resize ? { resize: options.transform.resize } : {}),
|
||||||
...(options.transform.width ? { width: options.transform.width } : {}),
|
...(options.transform.width ? { width: options.transform.width } : {}),
|
||||||
...(options.transform.height ? { height: options.transform.height } : {}),
|
...(options.transform.height ? { height: options.transform.height } : {}),
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -396,14 +405,14 @@ export default {
|
|||||||
download: options.download ? options.download.filename || true : false,
|
download: options.download ? options.download.filename || true : false,
|
||||||
...(options.transform
|
...(options.transform
|
||||||
? {
|
? {
|
||||||
transform: {
|
transform: {
|
||||||
...(options.transform.format ? { format: options.transform.format } : {}),
|
...(options.transform.format ? { format: options.transform.format } : {}),
|
||||||
...(options.transform.quality ? { quality: options.transform.quality } : {}),
|
...(options.transform.quality ? { quality: options.transform.quality } : {}),
|
||||||
...(options.transform.resize ? { resize: options.transform.resize } : {}),
|
...(options.transform.resize ? { resize: options.transform.resize } : {}),
|
||||||
...(options.transform.width ? { width: options.transform.width } : {}),
|
...(options.transform.width ? { width: options.transform.width } : {}),
|
||||||
...(options.transform.height ? { height: options.transform.height } : {}),
|
...(options.transform.height ? { height: options.transform.height } : {}),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
});
|
});
|
||||||
if (error) throw new Error(error.message, { cause: error });
|
if (error) throw new Error(error.message, { cause: error });
|
||||||
@ -572,10 +581,10 @@ const applyModifiers = (query, { select, order, limit, range, single, maybeSingl
|
|||||||
select.mode === 'minimal'
|
select.mode === 'minimal'
|
||||||
? ''
|
? ''
|
||||||
: select.mode === 'guided'
|
: select.mode === 'guided'
|
||||||
? select?.fields.length
|
? select?.fields.length
|
||||||
? select.fields.join(', ')
|
? select.fields.join(', ')
|
||||||
: '*'
|
: '*'
|
||||||
: select?.fieldsAdvanced
|
: select?.fieldsAdvanced
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
7
src/global.d.ts
vendored
Normal file
7
src/global.d.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
// Global type declarations for WeWeb
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
var wwLib: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export {};
|
@ -1,15 +1,24 @@
|
|||||||
export class AsyncCache {
|
interface CacheItem<T> {
|
||||||
constructor(ttlMs = 60000) {
|
data: T;
|
||||||
|
timestamp: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AsyncCache<T = any> {
|
||||||
|
private cache: Map<string, CacheItem<T>>;
|
||||||
|
private TTL: number;
|
||||||
|
private pendingPromises: Map<string, Promise<T>>;
|
||||||
|
|
||||||
|
constructor(ttlMs: number = 60000) {
|
||||||
// Default 1 minute TTL
|
// Default 1 minute TTL
|
||||||
this.cache = new Map();
|
this.cache = new Map();
|
||||||
this.TTL = ttlMs;
|
this.TTL = ttlMs;
|
||||||
this.pendingPromises = new Map();
|
this.pendingPromises = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(key, fetchFn) {
|
async get(key: string, fetchFn: () => Promise<T>): Promise<T> {
|
||||||
// Check if there's already a pending promise for this key
|
// Check if there's already a pending promise for this key
|
||||||
if (this.pendingPromises.has(key)) {
|
if (this.pendingPromises.has(key)) {
|
||||||
return this.pendingPromises.get(key);
|
return this.pendingPromises.get(key)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cachedItem = this.cache.get(key);
|
const cachedItem = this.cache.get(key);
|
||||||
@ -39,15 +48,15 @@ export class AsyncCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_isExpired(timestamp) {
|
private _isExpired(timestamp: number): boolean {
|
||||||
return Date.now() - timestamp > this.TTL;
|
return Date.now() - timestamp > this.TTL;
|
||||||
}
|
}
|
||||||
|
|
||||||
invalidate(key) {
|
invalidate(key: string): void {
|
||||||
this.cache.delete(key);
|
this.cache.delete(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear(): void {
|
||||||
this.cache.clear();
|
this.cache.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
36
src/pages/63d172e4-bec1-4021-9b5e-0817819aad7b.js
Normal file
36
src/pages/63d172e4-bec1-4021-9b5e-0817819aad7b.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
import app from '@/_front/main.js';
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
import element_1b1e2173_9b78_42cc_a8ee_a6167caea340 from '@/components/elements/element-1b1e2173-9b78-42cc-a8ee-a6167caea340/src/wwElement.vue';
|
||||||
|
import element_3a7d6379_12d3_4387_98ff_b332bb492a63 from '@/components/elements/element-3a7d6379-12d3-4387-98ff-b332bb492a63/src/wwElement.vue';
|
||||||
|
import element_59dca300_db78_42e4_a7a6_0cbf22d3cc82 from '@/components/elements/element-59dca300-db78-42e4-a7a6-0cbf22d3cc82/src/wwElement.vue';
|
||||||
|
import element_69d0b3ef_b265_494c_8cd1_874da4aa1834 from '@/components/elements/element-69d0b3ef-b265-494c-8cd1-874da4aa1834/src/wwElement.vue';
|
||||||
|
import element_6f8796b1_8273_498d_95fc_7013b7c63214 from '@/components/elements/element-6f8796b1-8273-498d-95fc-7013b7c63214/src/wwElement.vue';
|
||||||
|
import element_83d890fb_84f9_4386_b459_fb4be89a8e15 from '@/components/elements/element-83d890fb-84f9-4386-b459-fb4be89a8e15/src/wwElement.vue';
|
||||||
|
import element_9256b033_f4e8_4ab4_adce_dac3a940d7f5 from '@/components/elements/element-9256b033-f4e8-4ab4-adce-dac3a940d7f5/src/wwElement.vue';
|
||||||
|
import element_aeb78b9a_6fb6_4c49_931d_faedcfad67ba from '@/components/elements/element-aeb78b9a-6fb6-4c49-931d-faedcfad67ba/src/wwElement.vue';
|
||||||
|
import element_b783dc65_d528_4f74_8c14_e27c934c39b1 from '@/components/elements/element-b783dc65-d528-4f74-8c14-e27c934c39b1/src/wwElement.vue';
|
||||||
|
import element_c6c0c00e_49fd_4cb9_bd78_5bc09945721e from '@/components/elements/element-c6c0c00e-49fd-4cb9-bd78-5bc09945721e/src/wwElement.vue';
|
||||||
|
import element_d7904e9d_fc9a_4d80_9e32_728e097879ad from '@/components/elements/element-d7904e9d-fc9a-4d80-9e32-728e097879ad/src/wwElement.vue';
|
||||||
|
import element_deb10a01_5eef_4aa1_9017_1b51c2ad6fd0 from '@/components/elements/element-deb10a01-5eef-4aa1-9017-1b51c2ad6fd0/src/wwElement.vue';
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
app.component('wwobject-1b1e2173-9b78-42cc-a8ee-a6167caea340', element_1b1e2173_9b78_42cc_a8ee_a6167caea340);
|
||||||
|
app.component('wwobject-3a7d6379-12d3-4387-98ff-b332bb492a63', element_3a7d6379_12d3_4387_98ff_b332bb492a63);
|
||||||
|
app.component('wwobject-59dca300-db78-42e4-a7a6-0cbf22d3cc82', element_59dca300_db78_42e4_a7a6_0cbf22d3cc82);
|
||||||
|
app.component('wwobject-69d0b3ef-b265-494c-8cd1-874da4aa1834', element_69d0b3ef_b265_494c_8cd1_874da4aa1834);
|
||||||
|
app.component('wwobject-6f8796b1-8273-498d-95fc-7013b7c63214', element_6f8796b1_8273_498d_95fc_7013b7c63214);
|
||||||
|
app.component('wwobject-83d890fb-84f9-4386-b459-fb4be89a8e15', element_83d890fb_84f9_4386_b459_fb4be89a8e15);
|
||||||
|
app.component('wwobject-9256b033-f4e8-4ab4-adce-dac3a940d7f5', element_9256b033_f4e8_4ab4_adce_dac3a940d7f5);
|
||||||
|
app.component('wwobject-aeb78b9a-6fb6-4c49-931d-faedcfad67ba', element_aeb78b9a_6fb6_4c49_931d_faedcfad67ba);
|
||||||
|
app.component('wwobject-b783dc65-d528-4f74-8c14-e27c934c39b1', element_b783dc65_d528_4f74_8c14_e27c934c39b1);
|
||||||
|
app.component('wwobject-c6c0c00e-49fd-4cb9-bd78-5bc09945721e', element_c6c0c00e_49fd_4cb9_bd78_5bc09945721e);
|
||||||
|
app.component('wwobject-d7904e9d-fc9a-4d80-9e32-728e097879ad', element_d7904e9d_fc9a_4d80_9e32_728e097879ad);
|
||||||
|
app.component('wwobject-deb10a01-5eef-4aa1-9017-1b51c2ad6fd0', element_deb10a01_5eef_4aa1_9017_1b51c2ad6fd0);
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
import section_99586bd3_2b15_4d6b_a025_6a50d07ca845 from '@/components/sections/section-99586bd3-2b15-4d6b-a025-6a50d07ca845/src/wwSection.vue';
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
app.component('section-99586bd3-2b15-4d6b-a025-6a50d07ca845', section_99586bd3_2b15_4d6b_a025_6a50d07ca845);
|
@ -30,11 +30,11 @@ import wwobject6dcad2080a6743a2bd1d3b13ff5819cf from '@/components/elements/elem
|
|||||||
import wwobject57831abf83ad49adba973bd30b035710 from '@/components/elements/element-57831abf-83ad-49ad-ba97-3bd30b035710/ww-config.js';
|
import wwobject57831abf83ad49adba973bd30b035710 from '@/components/elements/element-57831abf-83ad-49ad-ba97-3bd30b035710/ww-config.js';
|
||||||
import wwobject59dca300db7842e4a7a60cbf22d3cc82 from '@/components/elements/element-59dca300-db78-42e4-a7a6-0cbf22d3cc82/ww-config.js';
|
import wwobject59dca300db7842e4a7a60cbf22d3cc82 from '@/components/elements/element-59dca300-db78-42e4-a7a6-0cbf22d3cc82/ww-config.js';
|
||||||
import wwobject1be951afde7143e6ad1ee9b36de15529 from '@/components/elements/element-1be951af-de71-43e6-ad1e-e9b36de15529/ww-config.js';
|
import wwobject1be951afde7143e6ad1ee9b36de15529 from '@/components/elements/element-1be951af-de71-43e6-ad1e-e9b36de15529/ww-config.js';
|
||||||
import wwobjecta823467cbdc74ceca38c71875c4c214a from '@/components/elements/element-a823467c-bdc7-4cec-a38c-71875c4c214a/ww-config.js';
|
|
||||||
import wwobject9ae1fce82e314bfda4d20450235bdfd5 from '@/components/elements/element-9ae1fce8-2e31-4bfd-a4d2-0450235bdfd5/ww-config.js';
|
|
||||||
import wwobject9ecb2cfccef74be8b7363e17a3b7e9ff from '@/components/elements/element-9ecb2cfc-cef7-4be8-b736-3e17a3b7e9ff/ww-config.js';
|
import wwobject9ecb2cfccef74be8b7363e17a3b7e9ff from '@/components/elements/element-9ecb2cfc-cef7-4be8-b736-3e17a3b7e9ff/ww-config.js';
|
||||||
import wwobjectdeb10a015eef4aa190171b51c2ad6fd0 from '@/components/elements/element-deb10a01-5eef-4aa1-9017-1b51c2ad6fd0/ww-config.js';
|
import wwobjectdeb10a015eef4aa190171b51c2ad6fd0 from '@/components/elements/element-deb10a01-5eef-4aa1-9017-1b51c2ad6fd0/ww-config.js';
|
||||||
import wwobject985570fcb3c04566800482ab3b30a11d from '@/components/elements/element-985570fc-b3c0-4566-8004-82ab3b30a11d/ww-config.js';
|
import wwobject985570fcb3c04566800482ab3b30a11d from '@/components/elements/element-985570fc-b3c0-4566-8004-82ab3b30a11d/ww-config.js';
|
||||||
|
import wwobjecta823467cbdc74ceca38c71875c4c214a from '@/components/elements/element-a823467c-bdc7-4cec-a38c-71875c4c214a/ww-config.js';
|
||||||
|
import wwobject9ae1fce82e314bfda4d20450235bdfd5 from '@/components/elements/element-9ae1fce8-2e31-4bfd-a4d2-0450235bdfd5/ww-config.js';
|
||||||
import wwobjectc6c0c00e49fd4cb9bd785bc09945721e from '@/components/elements/element-c6c0c00e-49fd-4cb9-bd78-5bc09945721e/ww-config.js';
|
import wwobjectc6c0c00e49fd4cb9bd785bc09945721e from '@/components/elements/element-c6c0c00e-49fd-4cb9-bd78-5bc09945721e/ww-config.js';
|
||||||
/* wwFront:end */
|
/* wwFront:end */
|
||||||
|
|
||||||
@ -70,11 +70,11 @@ export const useComponentBasesStore = defineStore('componentBases', () => {
|
|||||||
'wwobject-57831abf-83ad-49ad-ba97-3bd30b035710': getInheritedConfiguration({ ...wwobject57831abf83ad49adba973bd30b035710, name: 'wwobject-57831abf-83ad-49ad-ba97-3bd30b035710' }),
|
'wwobject-57831abf-83ad-49ad-ba97-3bd30b035710': getInheritedConfiguration({ ...wwobject57831abf83ad49adba973bd30b035710, name: 'wwobject-57831abf-83ad-49ad-ba97-3bd30b035710' }),
|
||||||
'wwobject-59dca300-db78-42e4-a7a6-0cbf22d3cc82': getInheritedConfiguration({ ...wwobject59dca300db7842e4a7a60cbf22d3cc82, name: 'wwobject-59dca300-db78-42e4-a7a6-0cbf22d3cc82' }),
|
'wwobject-59dca300-db78-42e4-a7a6-0cbf22d3cc82': getInheritedConfiguration({ ...wwobject59dca300db7842e4a7a60cbf22d3cc82, name: 'wwobject-59dca300-db78-42e4-a7a6-0cbf22d3cc82' }),
|
||||||
'wwobject-1be951af-de71-43e6-ad1e-e9b36de15529': getInheritedConfiguration({ ...wwobject1be951afde7143e6ad1ee9b36de15529, name: 'wwobject-1be951af-de71-43e6-ad1e-e9b36de15529' }),
|
'wwobject-1be951af-de71-43e6-ad1e-e9b36de15529': getInheritedConfiguration({ ...wwobject1be951afde7143e6ad1ee9b36de15529, name: 'wwobject-1be951af-de71-43e6-ad1e-e9b36de15529' }),
|
||||||
'wwobject-a823467c-bdc7-4cec-a38c-71875c4c214a': getInheritedConfiguration({ ...wwobjecta823467cbdc74ceca38c71875c4c214a, name: 'wwobject-a823467c-bdc7-4cec-a38c-71875c4c214a' }),
|
|
||||||
'wwobject-9ae1fce8-2e31-4bfd-a4d2-0450235bdfd5': getInheritedConfiguration({ ...wwobject9ae1fce82e314bfda4d20450235bdfd5, name: 'wwobject-9ae1fce8-2e31-4bfd-a4d2-0450235bdfd5' }),
|
|
||||||
'wwobject-9ecb2cfc-cef7-4be8-b736-3e17a3b7e9ff': getInheritedConfiguration({ ...wwobject9ecb2cfccef74be8b7363e17a3b7e9ff, name: 'wwobject-9ecb2cfc-cef7-4be8-b736-3e17a3b7e9ff' }),
|
'wwobject-9ecb2cfc-cef7-4be8-b736-3e17a3b7e9ff': getInheritedConfiguration({ ...wwobject9ecb2cfccef74be8b7363e17a3b7e9ff, name: 'wwobject-9ecb2cfc-cef7-4be8-b736-3e17a3b7e9ff' }),
|
||||||
'wwobject-deb10a01-5eef-4aa1-9017-1b51c2ad6fd0': getInheritedConfiguration({ ...wwobjectdeb10a015eef4aa190171b51c2ad6fd0, name: 'wwobject-deb10a01-5eef-4aa1-9017-1b51c2ad6fd0' }),
|
'wwobject-deb10a01-5eef-4aa1-9017-1b51c2ad6fd0': getInheritedConfiguration({ ...wwobjectdeb10a015eef4aa190171b51c2ad6fd0, name: 'wwobject-deb10a01-5eef-4aa1-9017-1b51c2ad6fd0' }),
|
||||||
'wwobject-985570fc-b3c0-4566-8004-82ab3b30a11d': getInheritedConfiguration({ ...wwobject985570fcb3c04566800482ab3b30a11d, name: 'wwobject-985570fc-b3c0-4566-8004-82ab3b30a11d' }),
|
'wwobject-985570fc-b3c0-4566-8004-82ab3b30a11d': getInheritedConfiguration({ ...wwobject985570fcb3c04566800482ab3b30a11d, name: 'wwobject-985570fc-b3c0-4566-8004-82ab3b30a11d' }),
|
||||||
|
'wwobject-a823467c-bdc7-4cec-a38c-71875c4c214a': getInheritedConfiguration({ ...wwobjecta823467cbdc74ceca38c71875c4c214a, name: 'wwobject-a823467c-bdc7-4cec-a38c-71875c4c214a' }),
|
||||||
|
'wwobject-9ae1fce8-2e31-4bfd-a4d2-0450235bdfd5': getInheritedConfiguration({ ...wwobject9ae1fce82e314bfda4d20450235bdfd5, name: 'wwobject-9ae1fce8-2e31-4bfd-a4d2-0450235bdfd5' }),
|
||||||
'wwobject-c6c0c00e-49fd-4cb9-bd78-5bc09945721e': getInheritedConfiguration({ ...wwobjectc6c0c00e49fd4cb9bd785bc09945721e, name: 'wwobject-c6c0c00e-49fd-4cb9-bd78-5bc09945721e' })};
|
'wwobject-c6c0c00e-49fd-4cb9-bd78-5bc09945721e': getInheritedConfiguration({ ...wwobjectc6c0c00e49fd4cb9bd785bc09945721e, name: 'wwobject-c6c0c00e-49fd-4cb9-bd78-5bc09945721e' })};
|
||||||
/* wwFront:end */
|
/* wwFront:end */
|
||||||
|
|
||||||
|
25
src/vite-env.d.ts
vendored
Normal file
25
src/vite-env.d.ts
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
|
interface ImportMetaEnv {
|
||||||
|
readonly VITE_APP_API_URL: string
|
||||||
|
readonly VITE_APP_API_WEBSOCKETS: string
|
||||||
|
readonly VITE_APP_APOLLO_URL: string
|
||||||
|
readonly VITE_APP_BUCKET_URL: string
|
||||||
|
readonly VITE_APP_CDN_URL: string
|
||||||
|
readonly VITE_APP_CDN_URL_SHORT: string
|
||||||
|
readonly VITE_APP_DASHBOARD_URL: string
|
||||||
|
readonly VITE_APP_EDITOR_DEV_URL: string
|
||||||
|
readonly VITE_APP_EDITOR_URL: string
|
||||||
|
readonly VITE_APP_ENV_MODE: string
|
||||||
|
readonly VITE_APP_HOSTNAME: string
|
||||||
|
readonly VITE_APP_IS_EDITOR_DEV: string
|
||||||
|
readonly VITE_APP_PLUGINS_URL: string
|
||||||
|
readonly VITE_APP_PREVIEW_URL: string
|
||||||
|
readonly VITE_APP_SEGMENT_KEY: string
|
||||||
|
readonly VITE_APP_STRIPE_PUBLIC_KEY: string
|
||||||
|
readonly VITE_APP_USERFLOW_KEY: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ImportMeta {
|
||||||
|
readonly env: ImportMetaEnv
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
import { ref, inject, computed, unref, watch } from 'vue';
|
import { ref, inject, computed, unref, watch } from 'vue';
|
||||||
import { getLayoutStyleFromContent } from '@/_front/helpers/wwLayoutStyle';
|
import { getLayoutStyleFromContent } from '@/_front/helpers/wwLayoutStyle';
|
||||||
import { useRegisterElementLocalContext } from '@/_front/use/useElementLocalContext';
|
import { useRegisterElementLocalContext } from '@/_front/use/useElementLocalContext';
|
||||||
|
import { getComponentLabel } from '@/_common/helpers/component/component.js';
|
||||||
/* wwFront:start */
|
/* wwFront:start */
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
/* wwFront:end */
|
/* wwFront:end */
|
||||||
@ -399,4 +400,9 @@ export default {
|
|||||||
* @PUBLIC_API
|
* @PUBLIC_API
|
||||||
*/
|
*/
|
||||||
useRegisterElementLocalContext,
|
useRegisterElementLocalContext,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @PUBLIC_API
|
||||||
|
*/
|
||||||
|
getComponentLabel,
|
||||||
};
|
};
|
||||||
|
@ -7,7 +7,7 @@ export default {
|
|||||||
* @DEPRECATED wwLib.wwUtils.getUid
|
* @DEPRECATED wwLib.wwUtils.getUid
|
||||||
*/
|
*/
|
||||||
getUniqueId() {
|
getUniqueId() {
|
||||||
wwLib.wwLog.warn('wwLib.wwUtils.getUniqueId is deprecated, use wwLib.wwLib.getUid instead');
|
wwLib.wwLog.warn('wwLib.wwUtils.getUniqueId is deprecated, use wwLib.wwUtils.getUid instead');
|
||||||
var d = new Date();
|
var d = new Date();
|
||||||
return Math.floor((d.getTime() * Math.random() + Math.random() * 10000 + Math.random() * 100) / 100);
|
return Math.floor((d.getTime() * Math.random() + Math.random() * 10000 + Math.random() * 100) / 100);
|
||||||
},
|
},
|
||||||
|
@ -12,20 +12,20 @@
|
|||||||
|
|
||||||
<link rel="icon" type="image/x-icon" href="favicon.ico?_wwcv={{cacheVersion}}" />
|
<link rel="icon" type="image/x-icon" href="favicon.ico?_wwcv={{cacheVersion}}" />
|
||||||
|
|
||||||
<link rel="manifest" href="manifest.json?_wwcv=182" />
|
<link rel="manifest" href="manifest.json?_wwcv=183" />
|
||||||
<meta name="theme-color" content="" />
|
<meta name="theme-color" content="" />
|
||||||
<link rel="apple-touch-icon" sizes="48x48" href="images/48-favicon.png?_wwcv=182">
|
<link rel="apple-touch-icon" sizes="48x48" href="images/48-favicon.png?_wwcv=183">
|
||||||
<link rel="apple-touch-icon" sizes="72x72" href="images/72-favicon.png?_wwcv=182">
|
<link rel="apple-touch-icon" sizes="72x72" href="images/72-favicon.png?_wwcv=183">
|
||||||
<link rel="apple-touch-icon" sizes="96x96" href="images/96-favicon.png?_wwcv=182">
|
<link rel="apple-touch-icon" sizes="96x96" href="images/96-favicon.png?_wwcv=183">
|
||||||
<link rel="apple-touch-icon" sizes="128x128" href="images/128-favicon.png?_wwcv=182">
|
<link rel="apple-touch-icon" sizes="128x128" href="images/128-favicon.png?_wwcv=183">
|
||||||
<link rel="apple-touch-icon" sizes="144x144" href="images/144-favicon.png?_wwcv=182">
|
<link rel="apple-touch-icon" sizes="144x144" href="images/144-favicon.png?_wwcv=183">
|
||||||
<link rel="apple-touch-icon" sizes="152x152" href="images/152-favicon.png?_wwcv=182">
|
<link rel="apple-touch-icon" sizes="152x152" href="images/152-favicon.png?_wwcv=183">
|
||||||
<link rel="apple-touch-icon" sizes="192x192" href="images/192-favicon.png?_wwcv=182">
|
<link rel="apple-touch-icon" sizes="192x192" href="images/192-favicon.png?_wwcv=183">
|
||||||
<link rel="apple-touch-icon" sizes="256x256" href="images/256-favicon.png?_wwcv=182">
|
<link rel="apple-touch-icon" sizes="256x256" href="images/256-favicon.png?_wwcv=183">
|
||||||
<link rel="apple-touch-icon" sizes="384x384" href="images/384-favicon.png?_wwcv=182">
|
<link rel="apple-touch-icon" sizes="384x384" href="images/384-favicon.png?_wwcv=183">
|
||||||
<link rel="apple-touch-icon" sizes="512x512" href="images/512-favicon.png?_wwcv=182">
|
<link rel="apple-touch-icon" sizes="512x512" href="images/512-favicon.png?_wwcv=183">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap" rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap" rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'">
|
||||||
<link href="/fonts/Phosphor/font.css?_wwcv=182" rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'">
|
<link href="/fonts/Phosphor/font.css?_wwcv=183" rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Raleway:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'">
|
<link href="https://fonts.googleapis.com/css2?family=Raleway:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'">
|
||||||
<style>:root{ --ww-default-font-family: 'Raleway', sans-serif }</style>
|
<style>:root{ --ww-default-font-family: 'Raleway', sans-serif }</style>
|
||||||
<style>
|
<style>
|
||||||
|
25
tsconfig.app.json
Normal file
25
tsconfig.app.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/tsconfig",
|
||||||
|
"extends": "@vue/tsconfig/tsconfig.dom.json",
|
||||||
|
// Based on https://github.com/vitejs/vite/blob/main/packages/create-vite/template-vue-ts/tsconfig.json
|
||||||
|
"compilerOptions": {
|
||||||
|
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": [
|
||||||
|
"src/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"allowJs": true,
|
||||||
|
"checkJs": false,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"noEmit": true,
|
||||||
|
|
||||||
|
/* Linting */
|
||||||
|
"strict": false,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"noFallthroughCasesInSwitch": true
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "src/**/*.js", "src/**/*.jsx"]
|
||||||
|
}
|
27
tsconfig.node.json
Normal file
27
tsconfig.node.json
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/tsconfig",
|
||||||
|
// Based on https://github.com/vitejs/vite/blob/main/packages/create-vite/template-vue-ts/tsconfig.node.json
|
||||||
|
"compilerOptions": {
|
||||||
|
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||||
|
"target": "ES2023",
|
||||||
|
"lib": ["ES2023"],
|
||||||
|
"module": "ESNext",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"allowJs": true,
|
||||||
|
"checkJs": false,
|
||||||
|
|
||||||
|
/* Bundler mode */
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"noEmit": true,
|
||||||
|
|
||||||
|
/* Linting */
|
||||||
|
"strict": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"noFallthroughCasesInSwitch": true
|
||||||
|
},
|
||||||
|
"include": ["vite.config.js"]
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user