@raclettejs/workbench 0.1.35 → 0.1.36-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -2
- package/config/compositions.js +18 -0
- package/config/interactionLinks.js +19 -0
- package/i18n/de-DE.json +15 -1
- package/i18n/en-EU.json +52 -1
- package/i18n/sk-SK.json +15 -1
- package/package.json +3 -4
- package/packages.json +3 -1
- package/plugins/pacifico__compositions/frontend/components/compositionConfiguration/CompositionConfiguration.vue +96 -14
- package/plugins/pacifico__compositions/frontend/components/compositionConfiguration/CompositionIntegration.vue +29 -1
- package/plugins/pacifico__compositions/frontend/components/compositionConfiguration/widgetsLayout/WidgetRenderer.vue +1 -6
- package/plugins/pacifico__compositions/frontend/composables/prefillInteractionLinkFromComposition.ts +54 -0
- package/plugins/pacifico__compositions/frontend/widgets/CompositionCreateWidget.vue +145 -9
- package/plugins/pacifico__compositions/frontend/widgets/CompositionEditWidget.vue +11 -2
- package/plugins/pacifico__compositions/frontend/widgets/CompositionListWidget.vue +25 -5
- package/plugins/pacifico__core/frontend/generated-config.ts +22 -0
- package/plugins/pacifico__interactionLinks/frontend/components/InteractionLinkConfiguration.vue +3 -65
- package/plugins/pacifico__plugins/frontend/widgets/PluginListWidget.vue +20 -3
- package/plugins/raclette__cache/backend/helpers/cacheEntryBuilder.ts +94 -0
- package/plugins/raclette__cache/backend/helpers/cacheEntrySanitizer.ts +86 -0
- package/plugins/raclette__cache/backend/helpers/valkeyExplorer.ts +89 -0
- package/plugins/raclette__cache/backend/index.ts +21 -0
- package/plugins/raclette__cache/backend/routes/route.cache.cacheEntries.get.ts +118 -0
- package/plugins/raclette__cache/backend/routes/route.cache.cacheEntry.get.ts +91 -0
- package/plugins/raclette__cache/backend/routes.ts +8 -0
- package/plugins/raclette__cache/frontend/components/TableColumnConfigDialog.vue +95 -0
- package/plugins/raclette__cache/frontend/composables/useTableColumnConfig.ts +66 -0
- package/plugins/raclette__cache/frontend/generated-config.ts +33 -0
- package/plugins/raclette__cache/frontend/utils/cacheValueTableRows.ts +340 -0
- package/plugins/raclette__cache/frontend/widgets/CacheListWidget.vue +742 -0
- package/plugins/raclette__cache/raclette.plugin.ts +8 -0
- package/services/frontend/src/app/components/dynamicForm/DynamicForm.vue +3 -1
- package/services/frontend/src/app/components/interactionLink/InteractionLinkBehaviorForm.vue +99 -0
- package/services/frontend/src/app/components/stepNavigator/StepNavigator.vue +175 -24
- package/services/frontend/src/app/components/stepNavigator/StepNavigatorTypes.ts +18 -0
- package/services/frontend/src/app/composables/useInteractionLinkBehaviorFields.ts +83 -0
- package/services/frontend/src/app/composables/useRacletteUserIsAdmin.ts +25 -0
- package/services/frontend/src/orchestrator/assets/styles/themes/light.ts +1 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
PluginFastifyInstance,
|
|
3
|
+
PluginOptions,
|
|
4
|
+
} from "@raclettejs/core/backend"
|
|
5
|
+
import { registerRoutes } from "./routes"
|
|
6
|
+
|
|
7
|
+
const cachePlugin = async (
|
|
8
|
+
fastify: PluginFastifyInstance,
|
|
9
|
+
_opts: PluginOptions,
|
|
10
|
+
) => {
|
|
11
|
+
try {
|
|
12
|
+
await fastify.register((instance) => registerRoutes(instance))
|
|
13
|
+
} catch (error) {
|
|
14
|
+
fastify.log.error("Failed to register cache plugin routes.", error)
|
|
15
|
+
throw error
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
fastify.registerForFrontendGeneration({})
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default cachePlugin
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { PluginFastifyInstance } from "@raclettejs/types"
|
|
2
|
+
import type { FastifyReply, FastifyRequest } from "fastify"
|
|
3
|
+
import { Type } from "@sinclair/typebox"
|
|
4
|
+
import {
|
|
5
|
+
buildCacheEntrySource,
|
|
6
|
+
toPayloadItems,
|
|
7
|
+
} from "../helpers/cacheEntryBuilder"
|
|
8
|
+
import {
|
|
9
|
+
normalizePattern,
|
|
10
|
+
parseExplorerDb,
|
|
11
|
+
scanKeys,
|
|
12
|
+
withExplorerClient,
|
|
13
|
+
} from "../helpers/valkeyExplorer"
|
|
14
|
+
|
|
15
|
+
const MAX_LIMIT = 500
|
|
16
|
+
const DEFAULT_LIMIT = 100
|
|
17
|
+
|
|
18
|
+
const QuerystringSchema = Type.Object({
|
|
19
|
+
pattern: Type.Optional(Type.String()),
|
|
20
|
+
offset: Type.Optional(Type.Number({ minimum: 0 })),
|
|
21
|
+
limit: Type.Optional(Type.Number({ minimum: 1, maximum: MAX_LIMIT })),
|
|
22
|
+
db: Type.Optional(Type.Number({ minimum: 0, maximum: 15 })),
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
type Querystring = {
|
|
26
|
+
pattern?: string
|
|
27
|
+
offset?: number
|
|
28
|
+
limit?: number
|
|
29
|
+
db?: number
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default (fastify: PluginFastifyInstance) => {
|
|
33
|
+
const handler = async (
|
|
34
|
+
req: FastifyRequest<{ Querystring: Querystring }>,
|
|
35
|
+
reply: FastifyReply,
|
|
36
|
+
) => {
|
|
37
|
+
try {
|
|
38
|
+
const { match, listAll } = normalizePattern(req.query.pattern)
|
|
39
|
+
const db = parseExplorerDb(
|
|
40
|
+
req.query.db !== undefined ? Number(req.query.db) : undefined,
|
|
41
|
+
)
|
|
42
|
+
const offset = Math.max(0, Number(req.query.offset ?? 0))
|
|
43
|
+
const limit = Math.min(
|
|
44
|
+
MAX_LIMIT,
|
|
45
|
+
Math.max(1, Number(req.query.limit ?? DEFAULT_LIMIT)),
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
const entries = []
|
|
49
|
+
let total = 0
|
|
50
|
+
|
|
51
|
+
await withExplorerClient(db, async (client) => {
|
|
52
|
+
const allKeys = (await scanKeys(client, match)).sort((a, b) =>
|
|
53
|
+
a.localeCompare(b),
|
|
54
|
+
)
|
|
55
|
+
total = allKeys.length
|
|
56
|
+
const pageKeys = allKeys.slice(offset, offset + limit)
|
|
57
|
+
|
|
58
|
+
if (pageKeys.length === 0) return
|
|
59
|
+
|
|
60
|
+
const values = await client.mget(...pageKeys)
|
|
61
|
+
|
|
62
|
+
const pageEntries = await Promise.all(
|
|
63
|
+
pageKeys.map(async (key, index) => {
|
|
64
|
+
const rawValue = values[index] ?? ""
|
|
65
|
+
const ttl = await client.ttl(key)
|
|
66
|
+
return buildCacheEntrySource(key, rawValue, ttl)
|
|
67
|
+
}),
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
entries.push(...pageEntries)
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
const requestData = req.requestParams ?? {}
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
appSessionId: requestData.appSessionId ?? "",
|
|
77
|
+
requestId: requestData.requestId ?? "",
|
|
78
|
+
appRequestCode: requestData.appRequestCode ?? "dataRead",
|
|
79
|
+
type: "dataRead",
|
|
80
|
+
body: {
|
|
81
|
+
items: toPayloadItems(entries),
|
|
82
|
+
hits: {
|
|
83
|
+
total,
|
|
84
|
+
offset,
|
|
85
|
+
limit,
|
|
86
|
+
hasMore: offset + limit < total,
|
|
87
|
+
instanceId: "default",
|
|
88
|
+
pattern: match,
|
|
89
|
+
listAll,
|
|
90
|
+
db,
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
}
|
|
94
|
+
} catch (err: unknown) {
|
|
95
|
+
const message = err instanceof Error ? err.message : String(err)
|
|
96
|
+
fastify.log.error(message)
|
|
97
|
+
return reply.internalServerError(message)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
handler,
|
|
103
|
+
onRequest: [
|
|
104
|
+
fastify.authenticate,
|
|
105
|
+
fastify.checkPermissions(["user.isAdmin"]),
|
|
106
|
+
],
|
|
107
|
+
config: {
|
|
108
|
+
type: "dataRead",
|
|
109
|
+
},
|
|
110
|
+
schema: {
|
|
111
|
+
querystring: QuerystringSchema,
|
|
112
|
+
summary: "List Valkey cache entries (admin)",
|
|
113
|
+
description:
|
|
114
|
+
"Read-only SCAN of keys (optional pattern, db defaults to 0 for explorer)",
|
|
115
|
+
tags: ["cache"],
|
|
116
|
+
},
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { PluginFastifyInstance } from "@raclettejs/types"
|
|
2
|
+
import type { FastifyReply, FastifyRequest } from "fastify"
|
|
3
|
+
import { Type } from "@sinclair/typebox"
|
|
4
|
+
import {
|
|
5
|
+
buildCacheEntrySource,
|
|
6
|
+
toPayloadItems,
|
|
7
|
+
type CacheEntrySource,
|
|
8
|
+
} from "../helpers/cacheEntryBuilder"
|
|
9
|
+
import { parseExplorerDb, withExplorerClient } from "../helpers/valkeyExplorer"
|
|
10
|
+
|
|
11
|
+
const QuerystringSchema = Type.Object({
|
|
12
|
+
key: Type.String({ minLength: 1 }),
|
|
13
|
+
db: Type.Optional(Type.Number({ minimum: 0, maximum: 15 })),
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
type Querystring = {
|
|
17
|
+
key: string
|
|
18
|
+
db?: number
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default (fastify: PluginFastifyInstance) => {
|
|
22
|
+
const handler = async (
|
|
23
|
+
req: FastifyRequest<{ Querystring: Querystring }>,
|
|
24
|
+
reply: FastifyReply,
|
|
25
|
+
) => {
|
|
26
|
+
try {
|
|
27
|
+
const key = req.query.key.trim()
|
|
28
|
+
if (!key.length) {
|
|
29
|
+
return reply.badRequest("key is required")
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const db = parseExplorerDb(
|
|
33
|
+
req.query.db !== undefined ? Number(req.query.db) : undefined,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
let entry: CacheEntrySource | null = null
|
|
37
|
+
|
|
38
|
+
await withExplorerClient(db, async (client) => {
|
|
39
|
+
const rawValue = await client.get(key)
|
|
40
|
+
if (rawValue === null) {
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const ttl = await client.ttl(key)
|
|
45
|
+
entry = buildCacheEntrySource(key, rawValue, ttl, {
|
|
46
|
+
attachFullParsed: true,
|
|
47
|
+
})
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
const requestData = req.requestParams ?? {}
|
|
51
|
+
const items = entry ? toPayloadItems([entry]) : []
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
appSessionId: requestData.appSessionId ?? "",
|
|
55
|
+
requestId: requestData.requestId ?? "",
|
|
56
|
+
appRequestCode: requestData.appRequestCode ?? "dataRead",
|
|
57
|
+
type: "dataRead",
|
|
58
|
+
body: {
|
|
59
|
+
items,
|
|
60
|
+
hits: {
|
|
61
|
+
total: items.length,
|
|
62
|
+
key,
|
|
63
|
+
db,
|
|
64
|
+
found: items.length > 0,
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
} catch (err: unknown) {
|
|
69
|
+
const message = err instanceof Error ? err.message : String(err)
|
|
70
|
+
fastify.log.error(message)
|
|
71
|
+
return reply.internalServerError(message)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
handler,
|
|
77
|
+
onRequest: [
|
|
78
|
+
fastify.authenticate,
|
|
79
|
+
fastify.checkPermissions(["user.isAdmin"]),
|
|
80
|
+
],
|
|
81
|
+
config: {
|
|
82
|
+
type: "dataRead",
|
|
83
|
+
},
|
|
84
|
+
schema: {
|
|
85
|
+
querystring: QuerystringSchema,
|
|
86
|
+
summary: "Read a single Valkey cache entry (admin)",
|
|
87
|
+
description: "GET + TTL for one key (no SCAN; safe for keys containing wildcards)",
|
|
88
|
+
tags: ["cache"],
|
|
89
|
+
},
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PluginFastifyInstance } from "@raclettejs/core/backend"
|
|
2
|
+
import getCacheEntriesRoute from "./routes/route.cache.cacheEntries.get"
|
|
3
|
+
import getCacheEntryRoute from "./routes/route.cache.cacheEntry.get"
|
|
4
|
+
|
|
5
|
+
export const registerRoutes = async (fastify: PluginFastifyInstance) => {
|
|
6
|
+
await fastify.get("/cacheEntries", getCacheEntriesRoute(fastify))
|
|
7
|
+
await fastify.get("/cacheEntry", getCacheEntryRoute(fastify))
|
|
8
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-dialog
|
|
3
|
+
v-model="isOpen"
|
|
4
|
+
:max-width="$vuetify.display.mobile ? undefined : '500px'"
|
|
5
|
+
scrollable
|
|
6
|
+
>
|
|
7
|
+
<v-card :title="$t('workbench.cacheList.configureColumns')">
|
|
8
|
+
<v-divider />
|
|
9
|
+
|
|
10
|
+
<v-card-text class="tw:p-0">
|
|
11
|
+
<div class="tw:p-4 tw:border-b tw:border-gray-200">
|
|
12
|
+
<div class="tw:flex tw:gap-2">
|
|
13
|
+
<v-btn
|
|
14
|
+
variant="outlined"
|
|
15
|
+
size="small"
|
|
16
|
+
prepend-icon="mdi-format-list-bulleted"
|
|
17
|
+
@click="emit('select-all')"
|
|
18
|
+
>
|
|
19
|
+
{{ $t("core.selectAll") }}
|
|
20
|
+
</v-btn>
|
|
21
|
+
<v-btn
|
|
22
|
+
variant="outlined"
|
|
23
|
+
size="small"
|
|
24
|
+
prepend-icon="mdi-format-list-checkbox"
|
|
25
|
+
@click="emit('deselect-all')"
|
|
26
|
+
>
|
|
27
|
+
{{ $t("workbench.cacheList.deselectAll") }}
|
|
28
|
+
</v-btn>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<v-list class="tw:py-0">
|
|
33
|
+
<v-list-item
|
|
34
|
+
v-for="header in headers"
|
|
35
|
+
:key="header.key"
|
|
36
|
+
class="tw:px-4"
|
|
37
|
+
@click="toggleHeader(header.key, !isHeaderEnabled(header.key))"
|
|
38
|
+
>
|
|
39
|
+
<template #prepend>
|
|
40
|
+
<v-switch
|
|
41
|
+
class="tw:mr-2"
|
|
42
|
+
:model-value="isHeaderEnabled(header.key)"
|
|
43
|
+
color="primary"
|
|
44
|
+
hide-details
|
|
45
|
+
inset
|
|
46
|
+
/>
|
|
47
|
+
</template>
|
|
48
|
+
<v-list-item-title>{{ header.title }}</v-list-item-title>
|
|
49
|
+
</v-list-item>
|
|
50
|
+
</v-list>
|
|
51
|
+
</v-card-text>
|
|
52
|
+
|
|
53
|
+
<v-card-actions v-if="$vuetify.display.mobile">
|
|
54
|
+
<v-spacer />
|
|
55
|
+
<v-btn variant="outlined" @click="isOpen = false">
|
|
56
|
+
{{ $t("workbench.cacheList.done") }}
|
|
57
|
+
</v-btn>
|
|
58
|
+
</v-card-actions>
|
|
59
|
+
</v-card>
|
|
60
|
+
</v-dialog>
|
|
61
|
+
</template>
|
|
62
|
+
|
|
63
|
+
<script setup lang="ts">
|
|
64
|
+
import { computed } from "vue"
|
|
65
|
+
import type { TableColumnHeader } from "../composables/useTableColumnConfig"
|
|
66
|
+
|
|
67
|
+
const props = defineProps<{
|
|
68
|
+
modelValue: boolean
|
|
69
|
+
headers: TableColumnHeader[]
|
|
70
|
+
disabledHeaders: string[]
|
|
71
|
+
}>()
|
|
72
|
+
|
|
73
|
+
const emit = defineEmits<{
|
|
74
|
+
"update:modelValue": [value: boolean]
|
|
75
|
+
"toggle-header": [headerKey: string, enabled: boolean]
|
|
76
|
+
"select-all": []
|
|
77
|
+
"deselect-all": []
|
|
78
|
+
}>()
|
|
79
|
+
|
|
80
|
+
const isOpen = computed({
|
|
81
|
+
get: () => props.modelValue,
|
|
82
|
+
set: (value: boolean) => emit("update:modelValue", value),
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
const disabledHeaderKeys = computed(() =>
|
|
86
|
+
Array.isArray(props.disabledHeaders) ? props.disabledHeaders : [],
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
const isHeaderEnabled = (headerKey: string) =>
|
|
90
|
+
!disabledHeaderKeys.value.includes(headerKey)
|
|
91
|
+
|
|
92
|
+
const toggleHeader = (headerKey: string, enabled: boolean) => {
|
|
93
|
+
emit("toggle-header", headerKey, enabled)
|
|
94
|
+
}
|
|
95
|
+
</script>
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { ref } from "vue"
|
|
2
|
+
import { useLocalStorage } from "@vueuse/core"
|
|
3
|
+
|
|
4
|
+
export type TableColumnHeader = {
|
|
5
|
+
title: string
|
|
6
|
+
key: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const normalizeDisabledHeaders = (value: unknown): string[] =>
|
|
10
|
+
Array.isArray(value) ? value.filter((key) => typeof key === "string") : []
|
|
11
|
+
|
|
12
|
+
export const useTableColumnConfig = (storageKey: string) => {
|
|
13
|
+
const configureDialogOpen = ref(false)
|
|
14
|
+
const disabledHeaders = useLocalStorage<string[]>(storageKey, [], {
|
|
15
|
+
mergeDefaults: (stored, defaults) =>
|
|
16
|
+
normalizeDisabledHeaders(stored ?? defaults),
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
if (!Array.isArray(disabledHeaders.value)) {
|
|
20
|
+
disabledHeaders.value = []
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const filterHeaders = <T extends TableColumnHeader>(headers: T[]): T[] => {
|
|
24
|
+
const visible = headers.filter(
|
|
25
|
+
(header) => !disabledHeaders.value.includes(header.key),
|
|
26
|
+
)
|
|
27
|
+
return visible.length > 0 ? visible : headers
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const toggleHeader = (headerKey: string, enabled: boolean) => {
|
|
31
|
+
if (enabled) {
|
|
32
|
+
disabledHeaders.value = disabledHeaders.value.filter(
|
|
33
|
+
(key) => key !== headerKey,
|
|
34
|
+
)
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
if (!disabledHeaders.value.includes(headerKey)) {
|
|
38
|
+
disabledHeaders.value = [...disabledHeaders.value, headerKey]
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const selectAll = (headers: TableColumnHeader[]) => {
|
|
43
|
+
for (const header of headers) {
|
|
44
|
+
if (disabledHeaders.value.includes(header.key)) {
|
|
45
|
+
toggleHeader(header.key, true)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const deselectAll = (headers: TableColumnHeader[]) => {
|
|
51
|
+
for (const header of headers) {
|
|
52
|
+
if (!disabledHeaders.value.includes(header.key)) {
|
|
53
|
+
toggleHeader(header.key, false)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
configureDialogOpen,
|
|
60
|
+
disabledHeaders,
|
|
61
|
+
filterHeaders,
|
|
62
|
+
toggleHeader,
|
|
63
|
+
selectAll,
|
|
64
|
+
deselectAll,
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Auto-generated frontend configuration for plugin: raclette__cache
|
|
2
|
+
// This file is generated from backend routes - do not edit manually
|
|
3
|
+
// Entity mapping: {}
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
pluginName: "cache",
|
|
7
|
+
author: "raclette",
|
|
8
|
+
pluginKey: "raclette__cache",
|
|
9
|
+
routePrefix: "/raclette__cache",
|
|
10
|
+
pluginPath: "/app/src/appPlugins/raclette__cache",
|
|
11
|
+
data: {
|
|
12
|
+
cacheEntries: {
|
|
13
|
+
type: "cacheEntries",
|
|
14
|
+
operations: {
|
|
15
|
+
get: {
|
|
16
|
+
target: "/raclette__cache/cacheEntries",
|
|
17
|
+
method: "get",
|
|
18
|
+
storeActionType: "dataRead"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
cacheEntry: {
|
|
23
|
+
type: "cacheEntry",
|
|
24
|
+
operations: {
|
|
25
|
+
get: {
|
|
26
|
+
target: "/raclette__cache/cacheEntry",
|
|
27
|
+
method: "get",
|
|
28
|
+
storeActionType: "dataRead"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|