Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
5871a71
app js edited
SpliiT Nov 25, 2025
ab5e187
App.js changes
SpliiT Nov 26, 2025
9e4a435
changes app.js
SpliiT Nov 26, 2025
2f9743c
Merge branch 'next' of https://github.com/Geode-solutions/OpenGeodeWe…
SpliiT Nov 26, 2025
c337845
app.js changes
SpliiT Nov 26, 2025
28250e1
aoi
SpliiT Nov 26, 2025
9afa9d0
rm app.js from stores out of /app
SpliiT Nov 26, 2025
76e949b
change log
SpliiT Nov 27, 2025
68c5a44
rm comments
SpliiT Nov 27, 2025
374a4f6
transform code
SpliiT Nov 27, 2025
f7d45e9
move logic & refacto
SpliiT Nov 28, 2025
c66dc70
move feature
SpliiT Dec 1, 2025
7a8393e
transformer edit
SpliiT Dec 1, 2025
4302d90
add extensionID
SpliiT Dec 1, 2025
e2a93e1
rm useless extensionID
SpliiT Dec 2, 2025
007e1a6
Merge branch 'next' of https://github.com/Geode-solutions/OpenGeodeWe…
SpliiT Dec 2, 2025
63727d5
Apply prepare changes
SpliiT Dec 2, 2025
5f2c995
from next
SpliiT Dec 5, 2025
45afffd
Apply prepare changes
SpliiT Dec 5, 2025
9bf35d2
backendPath added
MaxNumerique Dec 8, 2025
24d5703
Merge branch 'feat/extensions' of https://github.com/Geode-solutions/…
MaxNumerique Dec 8, 2025
6428818
feat: dynamically adjust chat input textarea rows, character limit, a…
SpliiT Dec 8, 2025
7a70c67
Merge branch 'feat/extensions' of https://github.com/Geode-solutions/…
SpliiT Dec 8, 2025
b145f33
Apply prepare changes
SpliiT Dec 8, 2025
f8e3287
lauchExtensionMicroservice with backendPath
MaxNumerique Dec 8, 2025
a9468f9
test
MaxNumerique Dec 8, 2025
ed49890
demo mode and debug
MaxNumerique Dec 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 147 additions & 0 deletions app/stores/app.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
export const useAppStore = defineStore("app", () => {
const stores = []

function registerStore(store) {
const isAlreadyRegistered = stores.some(
(registeredStore) => registeredStore.$id === store.$id,
)
if (isAlreadyRegistered) {
console.log(
`[AppStore] Store "${store.$id}" already registered, skipping`,
)
return
}
console.log("[AppStore] Registering store", store.$id)
stores.push(store)
}

Check failure on line 16 in app/stores/app.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint(func-style)

Expected a function expression.

function exportStores() {
const snapshot = {}
let exportCount = 0

for (const store of stores) {
if (!store.exportStores) continue

Check failure on line 23 in app/stores/app.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint(curly)

Expected { after 'if' condition.
const storeId = store.$id
try {
snapshot[storeId] = store.exportStores()
Expand All @@ -36,17 +36,17 @@
return snapshot
}

Check failure on line 37 in app/stores/app.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint(func-style)

Expected a function expression.

async function importStores(snapshot) {
if (!snapshot) {
console.warn("[AppStore] import called with invalid snapshot")
return
}
console.log("[AppStore] Import snapshot keys:", Object.keys(snapshot || {}))

let importedCount = 0
const notFoundStores = []
for (const store of stores) {
if (!store.importStores) continue

Check failure on line 49 in app/stores/app.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint(curly)

Expected { after 'if' condition.
const storeId = store.$id
if (!snapshot[storeId]) {
notFoundStores.push(storeId)
Expand All @@ -67,10 +67,157 @@
console.log(`[AppStore] Imported ${importedCount} stores`)
}

Check failure on line 68 in app/stores/app.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint(func-style)

Expected a function expression.

const loadedExtensions = ref(new Map())
const extensionAPI = ref(null)
const codeTransformer = ref(null)

function setExtensionAPI(api) {
extensionAPI.value = api
}

Check failure on line 76 in app/stores/app.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint(func-style)

Expected a function expression.

function setCodeTransformer(transformer) {
codeTransformer.value = transformer
}

Check failure on line 80 in app/stores/app.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint(func-style)

Expected a function expression.

function getExtension(id) {
return loadedExtensions.value.get(id)
}

async function loadExtension(path, backendPath = null) {
try {
let finalURL = path

if (codeTransformer.value && path.startsWith("blob:")) {
const response = await fetch(path)
const code = await response.text()
const transformedCode = codeTransformer.value(code)

const newBlob = new Blob([transformedCode], {
type: "application/javascript",
})
finalURL = URL.createObjectURL(newBlob)
}

const extensionModule = await import(finalURL)

if (finalURL !== path && finalURL.startsWith("blob:")) {
URL.revokeObjectURL(finalURL)
}

if (!extensionModule.metadata?.id) {
throw new Error("Extension must have metadata.id")
}

const extensionId = extensionModule.metadata.id

if (loadedExtensions.value.has(extensionId)) {
console.warn(`[AppStore] Extension "${extensionId}" is already loaded`)
throw new Error(`Extension "${extensionId}" is already loaded.`)
}

if (!extensionAPI.value) {
throw new Error("Extension API not initialized")
}

if (typeof extensionModule.install === "function") {
await extensionModule.install(extensionAPI.value, backendPath)

const extensionData = {
module: extensionModule,
id: extensionId,
path,
backendPath,
loadedAt: new Date().toISOString(),
metadata: extensionModule.metadata,
enabled: true,
}
loadedExtensions.value.set(extensionId, extensionData)

console.log(`[AppStore] Extension loaded successfully: ${extensionId}`)

return extensionModule

Check warning on line 138 in app/stores/app.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint(no-else-return)

Unnecessary `else` after `return`.
} else {
throw new Error("Extension must export an install function")

Check warning on line 140 in app/stores/app.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint-plugin-unicorn(prefer-type-error)

Prefer throwing a `TypeError` over a generic `Error` after a type checking if-statement
}
} catch (error) {
console.error(`[AppStore] Failed to load extension from ${path}:`, error)
throw error
}
}

Check warning on line 146 in app/stores/app.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint(max-lines-per-function)

The async function `loadExtension` has too many lines (61). Maximum allowed is 50.

function getLoadedExtensions() {
return Array.from(loadedExtensions.value.values())
}

function unloadExtension(id) {
const extensionData = getExtension(id)
if (!extensionData) return false

Check failure on line 154 in app/stores/app.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint(curly)

Expected { after 'if' condition.

if (
extensionData.module &&
typeof extensionData.module.uninstall === "function"
) {
try {
extensionData.module.uninstall(extensionAPI.value)
console.log(`[AppStore] Extension uninstall called: ${id}`)
} catch (error) {
console.error(`[AppStore] Error calling uninstall for ${id}:`, error)
}
}

if (
extensionAPI.value &&
typeof extensionAPI.value.unregisterToolsByExtension === "function"
) {
extensionAPI.value.unregisterToolsByExtension(id)
}

loadedExtensions.value.delete(id)
console.log(`[AppStore] Extension unloaded: ${id}`)
return true
}

function toggleExtension(id) {
const extensionData = getExtension(id)
if (!extensionData) return false

Check failure on line 182 in app/stores/app.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint(curly)

Expected { after 'if' condition.

extensionData.enabled = !extensionData.enabled
console.log(
`[AppStore] Extension ${extensionData.enabled ? "enabled" : "disabled"}: ${id}`,
)
return extensionData.enabled
}

function setExtensionEnabled(id, enabled) {
const extensionData = getExtension(id)
if (!extensionData) return false

Check failure on line 193 in app/stores/app.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint(curly)

Expected { after 'if' condition.

extensionData.enabled = enabled
console.log(
`[AppStore] Extension ${enabled ? "enabled" : "disabled"}: ${id}`,
)
return true
}

function getExtensionEnabled(id) {
return getExtension(id)?.enabled ?? false
}

return {
stores,
registerStore,
exportStores,
importStores,
loadedExtensions,
extensionAPI,
setExtensionAPI,
setCodeTransformer,
loadExtension,
getLoadedExtensions,
getExtension,
unloadExtension,
toggleExtension,
setExtensionEnabled,
getExtensionEnabled,
}
})

Check warning on line 223 in app/stores/app.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint(max-lines-per-function)

The function has too many lines (223). Maximum allowed is 50.
10 changes: 9 additions & 1 deletion app/utils/file_import_workflow.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,15 @@ async function importItem(item) {
const dataStyleStore = useDataStyleStore()
const hybridViewerStore = useHybridViewerStore()
const treeviewStore = useTreeviewStore()
await dataBaseStore.registerObject(item.id)
console.log("importItem", { item })
try {
await dataBaseStore.registerObject(item.id)
} catch (error) {
console.warn(
`[Import] Failed to register object ${item.id} in backend viewer:`,
error,
)
}
await dataBaseStore.addItem(item.id, {
...item,
})
Expand Down
1 change: 0 additions & 1 deletion tests/integration/microservices/back/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@
# pip-compile --output-file=tests/integration/microservices/back/requirements.txt tests/integration/microservices/back/requirements.in
#

opengeodeweb-back==5.*,>=5.14.0
1 change: 0 additions & 1 deletion tests/integration/microservices/viewer/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@
# pip-compile --output-file=tests/integration/microservices/viewer/requirements.txt tests/integration/microservices/viewer/requirements.in
#

opengeodeweb-viewer==1.*,>=1.13.1rc1