Compare commits

2 Commits

Author SHA1 Message Date
AlexandruPopovici 25a0a4d4a2 Fixed the glob thing security issue 2025-12-02 10:18:58 +02:00
Mike Tasset 47e86e2996 Minor cleanup 2024-11-14 07:11:59 +00:00
6 changed files with 174 additions and 124 deletions
+72 -58
View File
@@ -71,14 +71,14 @@
}
},
"node_modules/@babel/code-frame": {
"version": "7.26.2",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
"integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
"integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
"license": "MIT",
"dependencies": {
"@babel/helper-validator-identifier": "^7.25.9",
"@babel/helper-validator-identifier": "^7.27.1",
"js-tokens": "^4.0.0",
"picocolors": "^1.0.0"
"picocolors": "^1.1.1"
},
"engines": {
"node": ">=6.9.0"
@@ -318,18 +318,18 @@
}
},
"node_modules/@babel/helper-string-parser": {
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
"integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
"integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
"integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -345,25 +345,25 @@
}
},
"node_modules/@babel/helpers": {
"version": "7.26.0",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz",
"integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==",
"version": "7.28.4",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz",
"integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==",
"license": "MIT",
"dependencies": {
"@babel/template": "^7.25.9",
"@babel/types": "^7.26.0"
"@babel/template": "^7.27.2",
"@babel/types": "^7.28.4"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
"version": "7.26.2",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz",
"integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==",
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz",
"integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==",
"license": "MIT",
"dependencies": {
"@babel/types": "^7.26.0"
"@babel/types": "^7.28.5"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -488,14 +488,14 @@
}
},
"node_modules/@babel/template": {
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz",
"integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==",
"version": "7.27.2",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
"integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.25.9",
"@babel/parser": "^7.25.9",
"@babel/types": "^7.25.9"
"@babel/code-frame": "^7.27.1",
"@babel/parser": "^7.27.2",
"@babel/types": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -529,13 +529,13 @@
}
},
"node_modules/@babel/types": {
"version": "7.26.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz",
"integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==",
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz",
"integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==",
"license": "MIT",
"dependencies": {
"@babel/helper-string-parser": "^7.25.9",
"@babel/helper-validator-identifier": "^7.25.9"
"@babel/helper-string-parser": "^7.27.1",
"@babel/helper-validator-identifier": "^7.28.5"
},
"engines": {
"node": ">=6.9.0"
@@ -977,9 +977,9 @@
}
},
"node_modules/@eslint/config-array/node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1035,9 +1035,9 @@
}
},
"node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1079,18 +1079,32 @@
}
},
"node_modules/@eslint/plugin-kit": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.2.tgz",
"integrity": "sha512-CXtq5nR4Su+2I47WPOlWud98Y5Lv8Kyxp2ukhgFx/eW6Blm18VXJO5WuQylPugRo8nbluoi6GvvxBLqHcvqUUw==",
"version": "0.2.8",
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz",
"integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@eslint/core": "^0.13.0",
"levn": "^0.4.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@eslint/plugin-kit/node_modules/@eslint/core": {
"version": "0.13.0",
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz",
"integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@types/json-schema": "^7.0.15"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@humanfs/core": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
@@ -2570,9 +2584,9 @@
"license": "ISC"
},
"node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3263,9 +3277,9 @@
}
},
"node_modules/eslint/node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3701,9 +3715,9 @@
}
},
"node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"version": "10.5.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
"integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
"dev": true,
"license": "ISC",
"dependencies": {
@@ -4121,9 +4135,9 @@
"license": "MIT"
},
"node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4506,9 +4520,9 @@
}
},
"node_modules/nanoid": {
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
"version": "3.3.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
"funding": [
{
"type": "github",
@@ -6450,9 +6464,9 @@
"license": "MIT"
},
"node_modules/vite": {
"version": "5.4.10",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.10.tgz",
"integrity": "sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==",
"version": "5.4.21",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz",
"integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
"dev": true,
"license": "MIT",
"dependencies": {
+2 -2
View File
@@ -1,8 +1,8 @@
<template>
<main class="relative">
<SpeckleViewer />
<!-- <ControlPanel />
<SelectionPanel /> -->
<ControlPanel />
<SelectionPanel />
</main>
</template>
+16 -13
View File
@@ -8,11 +8,11 @@
</div>
<div class="py-3 px-4">
<div class="flex gap-x-2">
<!-- <BaseButton @click="getLevels">Get levels</BaseButton> -->
<!-- <BaseButton @click="categorizeLevels">Categorize levels</BaseButton> -->
<!-- <BaseButton @click="uncategorizeLevels">Uncategorize levels</BaseButton> -->
<BaseButton @click="getLevels">Get levels</BaseButton>
<BaseButton @click="categorizeLevels">Categorize levels</BaseButton>
<BaseButton @click="uncategorizeLevels">Uncategorize levels</BaseButton>
</div>
<!-- <div v-if="levels" class="flex flex-col gap-y-2 items-start text-sm mt-4 mb-2">
<div v-if="levels" class="flex flex-col gap-y-2 items-start text-sm mt-4 mb-2">
<button
v-for="(property, index) in levels?.valueGroups"
:key="`level-${index}`"
@@ -22,7 +22,7 @@
{{ property.value }}
</button>
<button class="font-medium hover:text-blue-600 mt-2" @click="resetFilters">Show all</button>
</div> -->
</div>
</div>
</div>
</div>
@@ -39,20 +39,23 @@ const { categorize, isolate, animate, resetFilters } = useViewer()
const levels = ref()
// Get all the properties with the key 'properties.Instance Parameters.Constraints.Level.value'
const getLevels = () => {
// if (!properties) return
// levels.value = properties.find((property: PropertyInfo) => property.key === 'properties.Instance Parameters.Constraints.Level.value')
if (!properties) return
levels.value = properties.find((property: PropertyInfo) => property.key === 'properties.Instance Parameters.Constraints.Level.value')
}
// Categorize the levels and isolate the objects
const categorizeLevels = async () => {
// getLevels()
// categorize(levels.value.valueGroups)
// isolate(levels.value.valueGroups.flatMap((group: StringPropertyInfo['valueGroups']) => group.ids))
// animate()
getLevels()
categorize(levels.value.valueGroups)
isolate(levels.value.valueGroups.flatMap((group: StringPropertyInfo['valueGroups']) => group.ids))
animate()
}
// Reset filters and reverse the animation
const uncategorizeLevels = async () => {
// resetFilters()
// animate({ reverse: true })
resetFilters()
animate({ reverse: true })
}
</script>
+2 -2
View File
@@ -7,7 +7,7 @@
<h2 class="text-sm font-medium text-gray-800">Selection info</h2>
</div>
<div class="py-3 px-4 text-sm flex flex-col gap-y-1">
<!-- <template v-if="selectionInfo">
<template v-if="selectionInfo">
<div>
<span class="font-medium">ID:</span> {{ selectionInfo.id }}
</div>
@@ -18,7 +18,7 @@
<span class="font-medium">Level:</span> {{ selectionInfo.level.name }}
</div>
</template>
<p v-else class="text-sm text-gray-500">No selection</p> -->
<p v-else class="text-sm text-gray-500">No selection</p>
</div>
</div>
</div>
+6 -4
View File
@@ -11,16 +11,18 @@ import useViewer from '@/composables/viewer'
const canvas = useTemplateRef('canvas')
const { init, addExtensions,loadModelFromUrl } = useViewer()
// For demo purposes we will load two models
// You can replace these with your own as well
const MODELS = {
ONE: 'https://app.speckle.systems/projects/7744b171ca/models/e32f5e5416',
TWO: 'https://app.speckle.systems/projects/7744b171ca/models/7fee46df4b'
}
onMounted(async () => {
// if (!canvas.value) return
if (!canvas.value) return
// await init(canvas.value)
// addExtensions()
// await loadModelFromUrl(MODELS.ONE)
await init(canvas.value)
addExtensions()
await loadModelFromUrl(MODELS.ONE)
})
</script>
+76 -45
View File
@@ -19,76 +19,107 @@ export let properties: PropertyInfo[] | undefined = undefined
const selectionInfo = ref(null)
export default function useViewer() {
/**
* Initialize the viewer
* @param element - DOM element to initialize the viewer on
*/
const init = async (element: HTMLDivElement) => {
// const params = {
// ...DefaultViewerParams,
// showStats: false,
// verbose: true
// }
const params = {
...DefaultViewerParams,
showStats: false,
verbose: true
}
// viewer = new Viewer(element, params)
// await viewer.init()
viewer = new Viewer(element, params)
await viewer.init()
// viewer.on(ViewerEvent.LoadComplete, async() => {
// properties = await viewer.getObjectProperties()
// })
// Get the object properties after the model has loaded
// This will cache them and allow faster access later
viewer.on(ViewerEvent.LoadComplete, async() => {
properties = await viewer.getObjectProperties()
})
// viewer.on(ViewerEvent.ObjectClicked, (event: SelectionEvent | null) => {
// if (event) {
// const nodes = viewer.getWorldTree().findId(event.hits[0].node.model.id)
// if (nodes && nodes.length > 0) {
// selectionInfo.value = nodes[0].model.raw
// }
// } else {
// selectionInfo.value = null
// }
// })
// Handle object clicks in the viewer
viewer.on(ViewerEvent.ObjectClicked, (event: SelectionEvent | null) => {
// If there are no nodes, the click was not on an object
if (event) {
const nodes = viewer.getWorldTree().findId(event.hits[0].node.model.id)
if (nodes && nodes.length > 0) {
selectionInfo.value = nodes[0].model.raw
}
} else {
selectionInfo.value = null
}
})
}
/**
* The viewer can be extended with additional functionality by adding extensions
* You can use extensions provided by the viewer, or create your own
*/
const addExtensions = () => {
// if (!viewer) return
// viewer.createExtension(CameraController)
// viewer.createExtension(SelectionExtension)
// viewer.createExtension(FilteringExtension)
// viewer.createExtension(Catalogue)
if (!viewer) return
viewer.createExtension(CameraController)
viewer.createExtension(SelectionExtension)
viewer.createExtension(FilteringExtension)
viewer.createExtension(Catalogue)
}
/**
* Load a model from a Speckle URL
* @param url - The URL of the Speckle model
* @param authToken - This is required if the model is private
*/
const loadModelFromUrl = async (url: string, authToken?: string) => {
// const urls = await UrlHelper.getResourceUrls(url, authToken)
// urls.forEach(async (url) => {
// if (!viewer) return
// const loader = new SpeckleLoader(viewer.getWorldTree(), url, '')
// await viewer.loadObject(loader, true)
// })
const urls = await UrlHelper.getResourceUrls(url, authToken)
urls.forEach(async (url) => {
if (!viewer) return
const loader = new SpeckleLoader(viewer.getWorldTree(), url, '')
await viewer.loadObject(loader, true)
})
}
/**
* Isolate objects in the viewer
* @param ids - List of IDs to isolate
*/
const isolate = async (ids: Array<string>) => {
// if (!viewer) return
// const filter = viewer.getExtension(FilteringExtension)
// filter.resetFilters()
// filter.isolateObjects(ids)
if (!viewer) return
const filter = viewer.getExtension(FilteringExtension)
filter.resetFilters()
filter.isolateObjects(ids)
}
/**
* Categorize a certain property in the viewer
* @param input - ids to categorize
* @param options - options for the catalogue
*/
const categorize = async (
input: Array<{ ids: Array<string>; value: string }>,
options?: CatalogueOptions
) => {
// if (!viewer) return
// const catalogue = viewer.getExtension(Catalogue)
// catalogue.categorize(input, options)
if (!viewer) return
const catalogue = viewer.getExtension(Catalogue)
catalogue.categorize(input, options)
}
/**
* Use the catalogue extension to animate the objects
* @param options - option to reverse the animation
*/
const animate = async (options?:{ reverse?: boolean }) => {
// const { reverse } = options || {}
// if (!viewer) return
// const catalogue = viewer.getExtension(Catalogue)
// catalogue.animate(reverse)
const { reverse } = options || {}
if (!viewer) return
const catalogue = viewer.getExtension(Catalogue)
catalogue.animate(reverse)
}
// Reset the filtering extension
const resetFilters = async () => {
// if (!viewer) return
// const filter = viewer.getExtension(FilteringExtension)
// filter.resetFilters()
if (!viewer) return
const filter = viewer.getExtension(FilteringExtension)
filter.resetFilters()
}
return {