Skip to content

Commit 4b1e209

Browse files
authored
Merge pull request #242 from Geode-solutions/feat/app_store
feat(app_store): adding app-store.js to save all stores and loop all keys and return t…
2 parents 7a58d92 + b593b8c commit 4b1e209

File tree

6 files changed

+324
-16
lines changed

6 files changed

+324
-16
lines changed

package-lock.json

Lines changed: 17 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

plugins/autoStoreRegister.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
const autoStoreRegister = ({ store }) => {
2+
if (store.$id === "app") {
3+
return
4+
}
5+
6+
const appStore = useAppStore()
7+
appStore.registerStore(store)
8+
console.log(`[AutoRegister] Store "${store.$id}" processed`)
9+
}
10+
11+
export default defineNuxtPlugin((nuxtApp) => {
12+
nuxtApp.$pinia.use(autoStoreRegister)
13+
console.log(
14+
"[AUTOREGISTER PLUGIN] Loaded automatically from OpenGeodeWeb-Front",
15+
)
16+
})

stores/app_store.js

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
export const useAppStore = defineStore("app", () => {
2+
const stores = []
3+
4+
function registerStore(store) {
5+
const isAlreadyRegistered = stores.some(
6+
(registeredStore) => registeredStore.$id === store.$id,
7+
)
8+
9+
if (isAlreadyRegistered) {
10+
console.log(
11+
`[AppStore] Store "${store.$id}" already registered, skipping`,
12+
)
13+
return
14+
}
15+
16+
console.log("[AppStore] Registering store", store.$id)
17+
stores.push(store)
18+
}
19+
20+
function save() {
21+
const snapshot = {}
22+
let savedCount = 0
23+
24+
for (const store of stores) {
25+
if (!store.save) {
26+
continue
27+
}
28+
const storeId = store.$id
29+
try {
30+
snapshot[storeId] = store.save()
31+
savedCount++
32+
} catch (error) {
33+
console.error(`[AppStore] Error saving store "${storeId}":`, error)
34+
}
35+
}
36+
37+
console.log(`[AppStore] Saved ${savedCount} stores`)
38+
return snapshot
39+
}
40+
41+
function load(snapshot) {
42+
if (!snapshot) {
43+
console.warn("[AppStore] load called with invalid snapshot")
44+
return
45+
}
46+
47+
let loadedCount = 0
48+
const notFoundStores = []
49+
50+
for (const store of stores) {
51+
if (!store.load) {
52+
continue
53+
}
54+
55+
const storeId = store.$id
56+
57+
if (!snapshot[storeId]) {
58+
notFoundStores.push(storeId)
59+
continue
60+
}
61+
62+
try {
63+
store.load(snapshot[storeId])
64+
loadedCount++
65+
} catch (error) {
66+
console.error(`[AppStore] Error loading store "${storeId}":`, error)
67+
}
68+
}
69+
70+
if (notFoundStores.length > 0) {
71+
console.warn(
72+
`[AppStore] Stores not found in snapshot: ${notFoundStores.join(", ")}`,
73+
)
74+
}
75+
76+
console.log(`[AppStore] Loaded ${loadedCount} stores`)
77+
}
78+
79+
return {
80+
stores,
81+
registerStore,
82+
save,
83+
load,
84+
}
85+
})

tests/integration/microservices/back/requirements.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,3 @@
55
# pip-compile --output-file=tests/integration/microservices/back/requirements.txt tests/integration/microservices/back/requirements.in
66
#
77

8-
opengeodeweb-back==5.*,>=5.10.5

tests/integration/microservices/viewer/requirements.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,3 @@
55
# pip-compile --output-file=tests/integration/microservices/viewer/requirements.txt tests/integration/microservices/viewer/requirements.in
66
#
77

8-
opengeodeweb-viewer==1.*,>=1.11.4
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
import { beforeEach, describe, expect, expectTypeOf, test, vi } from "vitest"
2+
import { createTestingPinia } from "@pinia/testing"
3+
import { useAppStore } from "@/stores/app_store.js"
4+
import { setActivePinia } from "pinia"
5+
6+
beforeEach(async () => {
7+
const pinia = createTestingPinia({
8+
stubActions: false,
9+
createSpy: vi.fn,
10+
})
11+
setActivePinia(pinia)
12+
})
13+
14+
describe("App Store", () => {
15+
describe("state", () => {
16+
test("initial state", () => {
17+
const app_store = useAppStore()
18+
expectTypeOf(app_store.stores).toBeArray()
19+
expectTypeOf(app_store.save).toBeFunction()
20+
expectTypeOf(app_store.load).toBeFunction()
21+
expectTypeOf(app_store.registerStore).toBeFunction()
22+
})
23+
})
24+
25+
describe("actions", () => {
26+
describe("registerStore", () => {
27+
test("register single store", () => {
28+
const app_store = useAppStore()
29+
const mock_store = {
30+
$id: "testStore",
31+
save: vi.fn().mockImplementation(() => ({ data: "test" })),
32+
load: vi.fn().mockImplementation(() => {}),
33+
}
34+
35+
app_store.registerStore(mock_store)
36+
37+
expect(app_store.stores.length).toBe(1)
38+
expect(app_store.stores[0]).toStrictEqual(mock_store)
39+
})
40+
41+
test("register multiple stores", () => {
42+
const app_store = useAppStore()
43+
const mock_store_1 = {
44+
$id: "userStore",
45+
save: vi.fn().mockImplementation(() => {}),
46+
load: vi.fn().mockImplementation(() => {}),
47+
}
48+
const mock_store_2 = {
49+
$id: "cartStore",
50+
save: vi.fn().mockImplementation(() => {}),
51+
load: vi.fn().mockImplementation(() => {}),
52+
}
53+
54+
app_store.registerStore(mock_store_1)
55+
app_store.registerStore(mock_store_2)
56+
57+
expect(app_store.stores.length).toBe(2)
58+
expect(app_store.stores[0].$id).toBe("userStore")
59+
expect(app_store.stores[1].$id).toBe("cartStore")
60+
})
61+
})
62+
63+
describe("save", () => {
64+
test("save stores with save method", () => {
65+
const app_store = useAppStore()
66+
const mock_store_1 = {
67+
$id: "userStore",
68+
save: vi.fn().mockImplementation(() => ({
69+
name: "toto",
70+
71+
})),
72+
load: vi.fn().mockImplementation(() => {}),
73+
}
74+
const mock_store_2 = {
75+
$id: "cartStore",
76+
save: vi.fn().mockImplementation(() => ({ items: [], total: 0 })),
77+
load: vi.fn().mockImplementation(() => {}),
78+
}
79+
80+
app_store.registerStore(mock_store_1)
81+
app_store.registerStore(mock_store_2)
82+
83+
const snapshot = app_store.save()
84+
85+
expect(mock_store_1.save).toHaveBeenCalledTimes(1)
86+
expect(mock_store_2.save).toHaveBeenCalledTimes(1)
87+
expect(snapshot).toEqual({
88+
userStore: { name: "toto", email: "[email protected]" },
89+
cartStore: { items: [], total: 0 },
90+
})
91+
})
92+
93+
test("skip stores without save method", () => {
94+
const app_store = useAppStore()
95+
const mock_store_1 = {
96+
$id: "withSave",
97+
save: vi.fn().mockImplementation(() => ({ data: "test" })),
98+
load: vi.fn().mockImplementation(() => {}),
99+
}
100+
const mock_store_2 = {
101+
$id: "withoutSave",
102+
load: vi.fn().mockImplementation(() => {}),
103+
}
104+
105+
app_store.registerStore(mock_store_1)
106+
app_store.registerStore(mock_store_2)
107+
108+
const snapshot = app_store.save()
109+
110+
expect(mock_store_1.save).toHaveBeenCalledTimes(1)
111+
expect(snapshot).toEqual({
112+
withSave: { data: "test" },
113+
})
114+
expect(snapshot.withoutSave).toBeUndefined()
115+
})
116+
117+
test("return empty snapshot when no stores registered", () => {
118+
const app_store = useAppStore()
119+
const snapshot = app_store.save()
120+
expect(snapshot).toEqual({})
121+
})
122+
})
123+
124+
describe("load", () => {
125+
test("load stores with load method", () => {
126+
const app_store = useAppStore()
127+
const mock_store_1 = {
128+
$id: "userStore",
129+
save: vi.fn().mockImplementation(() => {}),
130+
load: vi.fn().mockImplementation(() => {}),
131+
}
132+
const mock_store_2 = {
133+
$id: "cartStore",
134+
save: vi.fn().mockImplementation(() => {}),
135+
load: vi.fn().mockImplementation(() => {}),
136+
}
137+
138+
app_store.registerStore(mock_store_1)
139+
app_store.registerStore(mock_store_2)
140+
141+
const snapshot = {
142+
userStore: { name: "tata", email: "[email protected]" },
143+
cartStore: { items: [{ id: 1 }], total: 50 },
144+
}
145+
146+
app_store.load(snapshot)
147+
148+
expect(mock_store_1.load).toHaveBeenCalledTimes(1)
149+
expect(mock_store_1.load).toHaveBeenCalledWith({
150+
name: "tata",
151+
152+
})
153+
expect(mock_store_2.load).toHaveBeenCalledTimes(1)
154+
expect(mock_store_2.load).toHaveBeenCalledWith({
155+
items: [{ id: 1 }],
156+
total: 50,
157+
})
158+
})
159+
160+
test("skip stores without load method", () => {
161+
const app_store = useAppStore()
162+
const mock_store_1 = {
163+
$id: "withLoad",
164+
save: vi.fn().mockImplementation(() => {}),
165+
load: vi.fn().mockImplementation(() => {}),
166+
}
167+
const mock_store_2 = {
168+
$id: "withoutLoad",
169+
save: vi.fn().mockImplementation(() => {}),
170+
}
171+
172+
app_store.registerStore(mock_store_1)
173+
app_store.registerStore(mock_store_2)
174+
175+
const snapshot = {
176+
withLoad: { data: "test" },
177+
withoutLoad: { data: "ignored" },
178+
}
179+
180+
app_store.load(snapshot)
181+
182+
expect(mock_store_1.load).toHaveBeenCalledTimes(1)
183+
expect(mock_store_2.load).toBeUndefined()
184+
})
185+
186+
test("warn when store not found in snapshot", () => {
187+
const app_store = useAppStore()
188+
const console_warn_spy = vi
189+
.spyOn(console, "warn")
190+
.mockImplementation(() => {})
191+
const mock_store = {
192+
$id: "testStore",
193+
load: vi.fn().mockImplementation(() => {}),
194+
}
195+
196+
app_store.registerStore(mock_store)
197+
app_store.load({})
198+
199+
expect(console_warn_spy).toHaveBeenCalledWith(
200+
expect.stringContaining("Stores not found in snapshot: testStore"),
201+
)
202+
console_warn_spy.mockRestore()
203+
})
204+
})
205+
})
206+
})

0 commit comments

Comments
 (0)