fastapi-voyager 0.15.2__py3-none-any.whl → 0.15.3__py3-none-any.whl
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.
- fastapi_voyager/version.py +1 -1
- fastapi_voyager/web/store.js +420 -8
- fastapi_voyager/web/vue-main.js +33 -327
- {fastapi_voyager-0.15.2.dist-info → fastapi_voyager-0.15.3.dist-info}/METADATA +1 -1
- {fastapi_voyager-0.15.2.dist-info → fastapi_voyager-0.15.3.dist-info}/RECORD +8 -8
- {fastapi_voyager-0.15.2.dist-info → fastapi_voyager-0.15.3.dist-info}/WHEEL +0 -0
- {fastapi_voyager-0.15.2.dist-info → fastapi_voyager-0.15.3.dist-info}/entry_points.txt +0 -0
- {fastapi_voyager-0.15.2.dist-info → fastapi_voyager-0.15.3.dist-info}/licenses/LICENSE +0 -0
fastapi_voyager/version.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
__all__ = ["__version__"]
|
|
2
|
-
__version__ = "0.15.
|
|
2
|
+
__version__ = "0.15.3"
|
fastapi_voyager/web/store.js
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
const { reactive } = window.Vue
|
|
2
2
|
|
|
3
3
|
const state = reactive({
|
|
4
|
-
item: {
|
|
5
|
-
count: 0,
|
|
6
|
-
},
|
|
7
|
-
|
|
8
4
|
version: "",
|
|
9
5
|
config: {
|
|
10
6
|
initial_page_policy: "first",
|
|
@@ -15,7 +11,8 @@ const state = reactive({
|
|
|
15
11
|
mode: "voyager", // voyager / er-diagram
|
|
16
12
|
|
|
17
13
|
previousTagRoute: {
|
|
18
|
-
//
|
|
14
|
+
// Store the last non-search tag/route selection for restoration when clearing search
|
|
15
|
+
// Used by resetSearch to return to the state before entering search mode
|
|
19
16
|
hasValue: false,
|
|
20
17
|
tag: null,
|
|
21
18
|
routeId: null,
|
|
@@ -65,6 +62,9 @@ const state = reactive({
|
|
|
65
62
|
fieldOptions: [],
|
|
66
63
|
},
|
|
67
64
|
|
|
65
|
+
// cache all schema options for filtering
|
|
66
|
+
allSchemaOptions: [],
|
|
67
|
+
|
|
68
68
|
// route information
|
|
69
69
|
routeDetail: {
|
|
70
70
|
show: false,
|
|
@@ -105,13 +105,425 @@ const state = reactive({
|
|
|
105
105
|
},
|
|
106
106
|
})
|
|
107
107
|
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
108
|
+
const getters = {
|
|
109
|
+
/**
|
|
110
|
+
* Find tag name by route ID
|
|
111
|
+
* Used to determine which tag a route belongs to
|
|
112
|
+
*/
|
|
113
|
+
findTagByRoute(routeId) {
|
|
114
|
+
return (
|
|
115
|
+
state.leftPanel.tags.find((tag) => (tag.routes || []).some((route) => route.id === routeId))
|
|
116
|
+
?.name || null
|
|
117
|
+
)
|
|
118
|
+
},
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const actions = {
|
|
122
|
+
/**
|
|
123
|
+
* Read tag and route from URL query parameters
|
|
124
|
+
* @returns {{ tag: string|null, route: string|null }}
|
|
125
|
+
*/
|
|
126
|
+
readQuerySelection() {
|
|
127
|
+
if (typeof window === "undefined") {
|
|
128
|
+
return { tag: null, route: null }
|
|
129
|
+
}
|
|
130
|
+
const params = new URLSearchParams(window.location.search)
|
|
131
|
+
return {
|
|
132
|
+
tag: params.get("tag") || null,
|
|
133
|
+
route: params.get("route") || null,
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Sync current tag and route selection to URL
|
|
139
|
+
* Updates browser URL without reloading the page
|
|
140
|
+
*/
|
|
141
|
+
syncSelectionToUrl() {
|
|
142
|
+
if (typeof window === "undefined") {
|
|
143
|
+
return
|
|
144
|
+
}
|
|
145
|
+
const params = new URLSearchParams(window.location.search)
|
|
146
|
+
if (state.leftPanel.tag) {
|
|
147
|
+
params.set("tag", state.leftPanel.tag)
|
|
148
|
+
} else {
|
|
149
|
+
params.delete("tag")
|
|
150
|
+
}
|
|
151
|
+
if (state.leftPanel.routeId) {
|
|
152
|
+
params.set("route", state.leftPanel.routeId)
|
|
153
|
+
} else {
|
|
154
|
+
params.delete("route")
|
|
155
|
+
}
|
|
156
|
+
const hash = window.location.hash || ""
|
|
157
|
+
const search = params.toString()
|
|
158
|
+
const base = window.location.pathname
|
|
159
|
+
const newUrl = search ? `${base}?${search}${hash}` : `${base}${hash}`
|
|
160
|
+
window.history.replaceState({}, "", newUrl)
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Apply selection from URL query parameters to state
|
|
165
|
+
* @param {{ tag: string|null, route: string|null }} selection
|
|
166
|
+
* @returns {boolean} - true if any selection was applied
|
|
167
|
+
*/
|
|
168
|
+
applySelectionFromQuery(selection) {
|
|
169
|
+
let applied = false
|
|
170
|
+
if (selection.tag && state.leftPanel.tags.some((tag) => tag.name === selection.tag)) {
|
|
171
|
+
state.leftPanel.tag = selection.tag
|
|
172
|
+
state.leftPanel._tag = selection.tag
|
|
173
|
+
applied = true
|
|
174
|
+
}
|
|
175
|
+
if (selection.route && state.graph.routeItems?.[selection.route]) {
|
|
176
|
+
state.leftPanel.routeId = selection.route
|
|
177
|
+
applied = true
|
|
178
|
+
const inferredTag = getters.findTagByRoute(selection.route)
|
|
179
|
+
if (inferredTag) {
|
|
180
|
+
state.leftPanel.tag = inferredTag
|
|
181
|
+
state.leftPanel._tag = inferredTag
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return applied
|
|
185
|
+
},
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Restore full tags from cache
|
|
189
|
+
* Used when resetting search mode
|
|
190
|
+
*/
|
|
191
|
+
loadFullTags() {
|
|
192
|
+
state.leftPanel.tags = state.leftPanel.fullTagsCache
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Populate field options based on selected schema
|
|
197
|
+
* @param {string} schemaId - Schema ID
|
|
198
|
+
*/
|
|
199
|
+
populateFieldOptions(schemaId) {
|
|
200
|
+
if (!schemaId) {
|
|
201
|
+
state.search.fieldOptions = []
|
|
202
|
+
state.search.fieldName = null
|
|
203
|
+
return
|
|
204
|
+
}
|
|
205
|
+
const schema = state.graph.schemaMap?.[schemaId]
|
|
206
|
+
if (!schema) {
|
|
207
|
+
state.search.fieldOptions = []
|
|
208
|
+
state.search.fieldName = null
|
|
209
|
+
return
|
|
210
|
+
}
|
|
211
|
+
const fields = Array.isArray(schema.fields) ? schema.fields.map((f) => f.name) : []
|
|
212
|
+
state.search.fieldOptions = fields
|
|
213
|
+
if (!fields.includes(state.search.fieldName)) {
|
|
214
|
+
state.search.fieldName = null
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Rebuild schema options from schema map
|
|
220
|
+
* Should be called when schema map changes
|
|
221
|
+
*/
|
|
222
|
+
rebuildSchemaOptions() {
|
|
223
|
+
const dict = state.graph.schemaMap || {}
|
|
224
|
+
const opts = Object.values(dict).map((s) => ({
|
|
225
|
+
label: s.name,
|
|
226
|
+
desc: s.id,
|
|
227
|
+
value: s.id,
|
|
228
|
+
}))
|
|
229
|
+
state.allSchemaOptions = opts
|
|
230
|
+
state.search.schemaOptions = opts.slice()
|
|
231
|
+
this.populateFieldOptions(state.search.schemaName)
|
|
232
|
+
},
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Load tags based on search criteria
|
|
236
|
+
* @returns {Promise<void>}
|
|
237
|
+
*/
|
|
238
|
+
async loadSearchedTags() {
|
|
239
|
+
try {
|
|
240
|
+
const payload = {
|
|
241
|
+
schema_name: state.search.schemaName,
|
|
242
|
+
schema_field: state.search.fieldName || null,
|
|
243
|
+
show_fields: state.filter.showFields,
|
|
244
|
+
brief: state.filter.brief,
|
|
245
|
+
hide_primitive_route: state.filter.hidePrimitiveRoute,
|
|
246
|
+
show_module: state.filter.showModule,
|
|
247
|
+
}
|
|
248
|
+
const res = await fetch("dot-search", {
|
|
249
|
+
method: "POST",
|
|
250
|
+
headers: { "Content-Type": "application/json" },
|
|
251
|
+
body: JSON.stringify(payload),
|
|
252
|
+
})
|
|
253
|
+
if (res.ok) {
|
|
254
|
+
const data = await res.json()
|
|
255
|
+
const tags = Array.isArray(data.tags) ? data.tags : []
|
|
256
|
+
state.leftPanel.tags = tags
|
|
257
|
+
}
|
|
258
|
+
} catch (err) {
|
|
259
|
+
console.error("dot-search failed", err)
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Load initial data from API
|
|
265
|
+
* @param {Function} onGenerate - Callback to generate graph after load
|
|
266
|
+
* @param {Function} renderBasedOnInitialPolicy - Callback to render based on policy
|
|
267
|
+
* @returns {Promise<void>}
|
|
268
|
+
*/
|
|
269
|
+
async loadInitial(onGenerate, renderBasedOnInitialPolicy) {
|
|
270
|
+
state.initializing = true
|
|
271
|
+
try {
|
|
272
|
+
const res = await fetch("dot")
|
|
273
|
+
const data = await res.json()
|
|
274
|
+
const tags = Array.isArray(data.tags) ? data.tags : []
|
|
275
|
+
state.leftPanel.tags = tags
|
|
276
|
+
// Cache the full tags for later use (e.g., resetSearch)
|
|
277
|
+
state.leftPanel.fullTagsCache = tags
|
|
278
|
+
|
|
279
|
+
const schemasArr = Array.isArray(data.schemas) ? data.schemas : []
|
|
280
|
+
// Build dict keyed by id for faster lookups and simpler prop passing
|
|
281
|
+
const schemaMap = Object.fromEntries(schemasArr.map((s) => [s.id, s]))
|
|
282
|
+
state.graph.schemaMap = schemaMap
|
|
283
|
+
state.graph.schemaKeys = new Set(Object.keys(schemaMap))
|
|
284
|
+
state.graph.routeItems = data.tags
|
|
285
|
+
.map((t) => t.routes)
|
|
286
|
+
.flat()
|
|
287
|
+
.reduce((acc, r) => {
|
|
288
|
+
acc[r.id] = r
|
|
289
|
+
return acc
|
|
290
|
+
}, {})
|
|
291
|
+
state.modeControl.briefModeEnabled = data.enable_brief_mode || false
|
|
292
|
+
state.version = data.version || ""
|
|
293
|
+
state.swagger.url = data.swagger_url || null
|
|
294
|
+
state.config.has_er_diagram = data.has_er_diagram || false
|
|
295
|
+
state.config.enable_pydantic_resolve_meta = data.enable_pydantic_resolve_meta || false
|
|
296
|
+
|
|
297
|
+
this.rebuildSchemaOptions()
|
|
298
|
+
|
|
299
|
+
const querySelection = this.readQuerySelection()
|
|
300
|
+
const restoredFromQuery = this.applySelectionFromQuery(querySelection)
|
|
301
|
+
if (restoredFromQuery) {
|
|
302
|
+
this.syncSelectionToUrl()
|
|
303
|
+
onGenerate()
|
|
304
|
+
return
|
|
305
|
+
} else {
|
|
306
|
+
state.config.initial_page_policy = data.initial_page_policy
|
|
307
|
+
renderBasedOnInitialPolicy()
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// default route options placeholder
|
|
311
|
+
} catch (e) {
|
|
312
|
+
console.error("Initial load failed", e)
|
|
313
|
+
} finally {
|
|
314
|
+
state.initializing = false
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Filter schema options based on search text
|
|
320
|
+
* Used by Quasar select component's filter function
|
|
321
|
+
* @param {string} val - Search text
|
|
322
|
+
* @param {Function} update - Quasar update callback
|
|
323
|
+
*/
|
|
324
|
+
filterSearchSchemas(val, update) {
|
|
325
|
+
const needle = (val || "").toLowerCase()
|
|
326
|
+
update(() => {
|
|
327
|
+
if (!needle) {
|
|
328
|
+
state.search.schemaOptions = state.allSchemaOptions.slice()
|
|
329
|
+
return
|
|
330
|
+
}
|
|
331
|
+
state.search.schemaOptions = state.allSchemaOptions.filter((option) =>
|
|
332
|
+
option.label.toLowerCase().includes(needle)
|
|
333
|
+
)
|
|
334
|
+
})
|
|
335
|
+
},
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Handle schema selection change
|
|
339
|
+
* Updates state and triggers search if a schema is selected
|
|
340
|
+
* @param {string} val - Selected schema ID
|
|
341
|
+
* @param {Function} onSearch - Callback to trigger search
|
|
342
|
+
*/
|
|
343
|
+
onSearchSchemaChange(val, onSearch) {
|
|
344
|
+
state.search.schemaName = val
|
|
345
|
+
state.search.mode = false
|
|
346
|
+
if (!val) {
|
|
347
|
+
// Clearing the select should only run resetSearch via @clear
|
|
348
|
+
return
|
|
349
|
+
}
|
|
350
|
+
onSearch()
|
|
351
|
+
},
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Reset detail panels (right drawer and route detail)
|
|
355
|
+
*/
|
|
356
|
+
resetDetailPanels() {
|
|
357
|
+
state.rightDrawer.drawer = false
|
|
358
|
+
state.routeDetail.show = false
|
|
359
|
+
state.schemaDetail.schemaCodeName = ""
|
|
360
|
+
},
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Reset left panel selection and regenerate
|
|
364
|
+
* @param {Function} onGenerate - Callback to regenerate graph
|
|
365
|
+
*/
|
|
366
|
+
onReset(onGenerate) {
|
|
367
|
+
state.leftPanel.tag = null
|
|
368
|
+
state.leftPanel._tag = null
|
|
369
|
+
state.leftPanel.routeId = null
|
|
370
|
+
this.syncSelectionToUrl()
|
|
371
|
+
onGenerate()
|
|
372
|
+
},
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Toggle pydantic resolve meta visibility
|
|
376
|
+
* @param {boolean} val - New value
|
|
377
|
+
* @param {Function} onGenerate - Callback to regenerate graph
|
|
378
|
+
*/
|
|
379
|
+
togglePydanticResolveMeta(val, onGenerate) {
|
|
380
|
+
state.modeControl.pydanticResolveMetaEnabled = val
|
|
381
|
+
try {
|
|
382
|
+
localStorage.setItem("pydantic_resolve_meta", JSON.stringify(val))
|
|
383
|
+
} catch (e) {
|
|
384
|
+
console.warn("Failed to save pydantic_resolve_meta to localStorage", e)
|
|
385
|
+
}
|
|
386
|
+
onGenerate()
|
|
387
|
+
},
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Toggle show module clustering
|
|
391
|
+
* @param {boolean} val - New value
|
|
392
|
+
* @param {Function} onGenerate - Callback to regenerate graph
|
|
393
|
+
*/
|
|
394
|
+
toggleShowModule(val, onGenerate) {
|
|
395
|
+
state.filter.showModule = val
|
|
396
|
+
try {
|
|
397
|
+
localStorage.setItem("show_module_cluster", JSON.stringify(val))
|
|
398
|
+
} catch (e) {
|
|
399
|
+
console.warn("Failed to save show_module_cluster to localStorage", e)
|
|
400
|
+
}
|
|
401
|
+
onGenerate()
|
|
402
|
+
},
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Toggle show fields option
|
|
406
|
+
* @param {string} field - Field display option ("single", "object", "all")
|
|
407
|
+
* @param {Function} onGenerate - Callback to regenerate graph
|
|
408
|
+
*/
|
|
409
|
+
toggleShowField(field, onGenerate) {
|
|
410
|
+
state.filter.showFields = field
|
|
411
|
+
onGenerate(false)
|
|
412
|
+
},
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Toggle brief mode
|
|
416
|
+
* @param {boolean} val - New value
|
|
417
|
+
* @param {Function} onGenerate - Callback to regenerate graph
|
|
418
|
+
*/
|
|
419
|
+
toggleBrief(val, onGenerate) {
|
|
420
|
+
state.filter.brief = val
|
|
421
|
+
try {
|
|
422
|
+
localStorage.setItem("brief_mode", JSON.stringify(val))
|
|
423
|
+
} catch (e) {
|
|
424
|
+
console.warn("Failed to save brief_mode to localStorage", e)
|
|
425
|
+
}
|
|
426
|
+
onGenerate()
|
|
427
|
+
},
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Toggle hide primitive route
|
|
431
|
+
* @param {boolean} val - New value
|
|
432
|
+
* @param {Function} onGenerate - Callback to regenerate graph
|
|
433
|
+
*/
|
|
434
|
+
toggleHidePrimitiveRoute(val, onGenerate) {
|
|
435
|
+
state.filter.hidePrimitiveRoute = val
|
|
436
|
+
try {
|
|
437
|
+
localStorage.setItem("hide_primitive", JSON.stringify(val))
|
|
438
|
+
} catch (e) {
|
|
439
|
+
console.warn("Failed to save hide_primitive to localStorage", e)
|
|
440
|
+
}
|
|
441
|
+
onGenerate(false)
|
|
442
|
+
},
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Render based on initial page policy
|
|
446
|
+
* @param {Function} onGenerate - Callback to regenerate graph
|
|
447
|
+
*/
|
|
448
|
+
renderBasedOnInitialPolicy(onGenerate) {
|
|
449
|
+
switch (state.config.initial_page_policy) {
|
|
450
|
+
case "full":
|
|
451
|
+
onGenerate()
|
|
452
|
+
return
|
|
453
|
+
case "empty":
|
|
454
|
+
return
|
|
455
|
+
case "first":
|
|
456
|
+
state.leftPanel.tag = state.leftPanel.tags.length > 0 ? state.leftPanel.tags[0].name : null
|
|
457
|
+
state.leftPanel._tag = state.leftPanel.tag
|
|
458
|
+
this.syncSelectionToUrl()
|
|
459
|
+
onGenerate()
|
|
460
|
+
return
|
|
461
|
+
}
|
|
462
|
+
},
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* Build payload for Voyager rendering
|
|
466
|
+
* @returns {Object} Payload for dot API
|
|
467
|
+
*/
|
|
468
|
+
buildVoyagerPayload() {
|
|
469
|
+
const activeSchema = state.search.mode ? state.search.schemaName : null
|
|
470
|
+
const activeField = state.search.mode ? state.search.fieldName : null
|
|
471
|
+
return {
|
|
472
|
+
tags: state.leftPanel.tag ? [state.leftPanel.tag] : null,
|
|
473
|
+
schema_name: activeSchema || null,
|
|
474
|
+
schema_field: activeField || null,
|
|
475
|
+
route_name: state.leftPanel.routeId || null,
|
|
476
|
+
show_fields: state.filter.showFields,
|
|
477
|
+
brief: state.filter.brief,
|
|
478
|
+
hide_primitive_route: state.filter.hidePrimitiveRoute,
|
|
479
|
+
show_module: state.filter.showModule,
|
|
480
|
+
show_pydantic_resolve_meta: state.modeControl.pydanticResolveMetaEnabled,
|
|
481
|
+
}
|
|
482
|
+
},
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Build payload for ER Diagram rendering
|
|
486
|
+
* @returns {Object} Payload for er-diagram API
|
|
487
|
+
*/
|
|
488
|
+
buildErDiagramPayload() {
|
|
489
|
+
return {
|
|
490
|
+
show_fields: state.filter.showFields,
|
|
491
|
+
show_module: state.filter.showModule,
|
|
492
|
+
}
|
|
493
|
+
},
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* Restore search state and return whether to regenerate
|
|
497
|
+
* @returns {boolean} - true if should regenerate with previous selection
|
|
498
|
+
*/
|
|
499
|
+
resetSearchState() {
|
|
500
|
+
state.search.mode = false
|
|
501
|
+
const hadPreviousValue = state.previousTagRoute.hasValue
|
|
502
|
+
|
|
503
|
+
if (hadPreviousValue) {
|
|
504
|
+
state.leftPanel.tag = state.previousTagRoute.tag
|
|
505
|
+
state.leftPanel._tag = state.previousTagRoute.tag
|
|
506
|
+
state.leftPanel.routeId = state.previousTagRoute.routeId
|
|
507
|
+
// Clear the saved state
|
|
508
|
+
state.previousTagRoute.hasValue = false
|
|
509
|
+
} else {
|
|
510
|
+
state.leftPanel.tag = null
|
|
511
|
+
state.leftPanel._tag = null
|
|
512
|
+
state.leftPanel.routeId = null
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
this.syncSelectionToUrl()
|
|
516
|
+
this.loadFullTags()
|
|
517
|
+
|
|
518
|
+
return hadPreviousValue
|
|
111
519
|
},
|
|
112
520
|
}
|
|
113
521
|
|
|
522
|
+
const mutations = {}
|
|
523
|
+
|
|
114
524
|
export const store = {
|
|
115
525
|
state,
|
|
526
|
+
getters,
|
|
527
|
+
actions,
|
|
116
528
|
mutations,
|
|
117
529
|
}
|
fastapi_voyager/web/vue-main.js
CHANGED
|
@@ -22,7 +22,6 @@ function loadToggleState(key, defaultValue = false) {
|
|
|
22
22
|
const app = createApp({
|
|
23
23
|
setup() {
|
|
24
24
|
let graphUI = null
|
|
25
|
-
const allSchemaOptions = ref([])
|
|
26
25
|
const erDiagramLoading = ref(false)
|
|
27
26
|
const erDiagramCache = ref("")
|
|
28
27
|
|
|
@@ -42,20 +41,13 @@ const app = createApp({
|
|
|
42
41
|
graphUI = new GraphUI("#graph", {
|
|
43
42
|
onSchemaShiftClick: (id) => {
|
|
44
43
|
if (store.state.graph.schemaKeys.has(id)) {
|
|
45
|
-
// Only save current tag/route if we're not already in search mode
|
|
46
|
-
// This prevents overwriting the saved state with null values
|
|
47
|
-
if (!store.state.previousTagRoute.hasValue && !store.state.search.mode) {
|
|
48
|
-
store.state.previousTagRoute.tag = store.state.leftPanel.tag
|
|
49
|
-
store.state.previousTagRoute.routeId = store.state.leftPanel.routeId
|
|
50
|
-
store.state.previousTagRoute.hasValue = true
|
|
51
|
-
}
|
|
52
44
|
store.state.search.mode = true
|
|
53
45
|
store.state.search.schemaName = id
|
|
54
46
|
onSearch()
|
|
55
47
|
}
|
|
56
48
|
},
|
|
57
49
|
onSchemaClick: (id) => {
|
|
58
|
-
resetDetailPanels()
|
|
50
|
+
store.actions.resetDetailPanels()
|
|
59
51
|
if (store.state.graph.schemaKeys.has(id)) {
|
|
60
52
|
store.state.schemaDetail.schemaCodeName = id
|
|
61
53
|
store.state.rightDrawer.drawer = true
|
|
@@ -66,257 +58,44 @@ const app = createApp({
|
|
|
66
58
|
}
|
|
67
59
|
},
|
|
68
60
|
resetCb: () => {
|
|
69
|
-
resetDetailPanels()
|
|
61
|
+
store.actions.resetDetailPanels()
|
|
70
62
|
},
|
|
71
63
|
})
|
|
72
64
|
}
|
|
73
65
|
|
|
74
|
-
function rebuildSchemaOptions() {
|
|
75
|
-
const dict = store.state.graph.schemaMap || {}
|
|
76
|
-
const opts = Object.values(dict).map((s) => ({
|
|
77
|
-
label: s.name,
|
|
78
|
-
desc: s.id,
|
|
79
|
-
value: s.id,
|
|
80
|
-
}))
|
|
81
|
-
allSchemaOptions.value = opts
|
|
82
|
-
store.state.search.schemaOptions = opts.slice()
|
|
83
|
-
populateFieldOptions(store.state.search.schemaName)
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function populateFieldOptions(schemaId) {
|
|
87
|
-
if (!schemaId) {
|
|
88
|
-
store.state.search.fieldOptions = []
|
|
89
|
-
store.state.search.fieldName = null
|
|
90
|
-
return
|
|
91
|
-
}
|
|
92
|
-
const schema = store.state.graph.schemaMap?.[schemaId]
|
|
93
|
-
if (!schema) {
|
|
94
|
-
store.state.search.fieldOptions = []
|
|
95
|
-
store.state.search.fieldName = null
|
|
96
|
-
return
|
|
97
|
-
}
|
|
98
|
-
const fields = Array.isArray(schema.fields) ? schema.fields.map((f) => f.name) : []
|
|
99
|
-
store.state.search.fieldOptions = fields
|
|
100
|
-
if (!fields.includes(store.state.search.fieldName)) {
|
|
101
|
-
store.state.search.fieldName = null
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function filterSearchSchemas(val, update) {
|
|
106
|
-
const needle = (val || "").toLowerCase()
|
|
107
|
-
update(() => {
|
|
108
|
-
if (!needle) {
|
|
109
|
-
store.state.search.schemaOptions = allSchemaOptions.value.slice()
|
|
110
|
-
return
|
|
111
|
-
}
|
|
112
|
-
store.state.search.schemaOptions = allSchemaOptions.value.filter((option) =>
|
|
113
|
-
option.label.toLowerCase().includes(needle)
|
|
114
|
-
)
|
|
115
|
-
})
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function onSearchSchemaChange(val) {
|
|
119
|
-
store.state.search.schemaName = val
|
|
120
|
-
store.state.search.mode = false
|
|
121
|
-
if (!val) {
|
|
122
|
-
// Clearing the select should only run resetSearch via @clear
|
|
123
|
-
return
|
|
124
|
-
}
|
|
125
|
-
onSearch()
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function readQuerySelection() {
|
|
129
|
-
if (typeof window === "undefined") {
|
|
130
|
-
return { tag: null, route: null }
|
|
131
|
-
}
|
|
132
|
-
const params = new URLSearchParams(window.location.search)
|
|
133
|
-
return {
|
|
134
|
-
tag: params.get("tag") || null,
|
|
135
|
-
route: params.get("route") || null,
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function findTagByRoute(routeId) {
|
|
140
|
-
return (
|
|
141
|
-
store.state.leftPanel.tags.find((tag) =>
|
|
142
|
-
(tag.routes || []).some((route) => route.id === routeId)
|
|
143
|
-
)?.name || null
|
|
144
|
-
)
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
function syncSelectionToUrl() {
|
|
148
|
-
if (typeof window === "undefined") {
|
|
149
|
-
return
|
|
150
|
-
}
|
|
151
|
-
const params = new URLSearchParams(window.location.search)
|
|
152
|
-
if (store.state.leftPanel.tag) {
|
|
153
|
-
params.set("tag", store.state.leftPanel.tag)
|
|
154
|
-
} else {
|
|
155
|
-
params.delete("tag")
|
|
156
|
-
}
|
|
157
|
-
if (store.state.leftPanel.routeId) {
|
|
158
|
-
params.set("route", store.state.leftPanel.routeId)
|
|
159
|
-
} else {
|
|
160
|
-
params.delete("route")
|
|
161
|
-
}
|
|
162
|
-
const hash = window.location.hash || ""
|
|
163
|
-
const search = params.toString()
|
|
164
|
-
const base = window.location.pathname
|
|
165
|
-
const newUrl = search ? `${base}?${search}${hash}` : `${base}${hash}`
|
|
166
|
-
window.history.replaceState({}, "", newUrl)
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
function applySelectionFromQuery(selection) {
|
|
170
|
-
let applied = false
|
|
171
|
-
if (selection.tag && store.state.leftPanel.tags.some((tag) => tag.name === selection.tag)) {
|
|
172
|
-
store.state.leftPanel.tag = selection.tag
|
|
173
|
-
store.state.leftPanel._tag = selection.tag
|
|
174
|
-
applied = true
|
|
175
|
-
}
|
|
176
|
-
if (selection.route && store.state.graph.routeItems?.[selection.route]) {
|
|
177
|
-
store.state.leftPanel.routeId = selection.route
|
|
178
|
-
applied = true
|
|
179
|
-
const inferredTag = findTagByRoute(selection.route)
|
|
180
|
-
if (inferredTag) {
|
|
181
|
-
store.state.leftPanel.tag = inferredTag
|
|
182
|
-
store.state.leftPanel._tag = inferredTag
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
return applied
|
|
186
|
-
}
|
|
187
|
-
|
|
188
66
|
async function resetSearch() {
|
|
189
|
-
store.
|
|
190
|
-
const hadPreviousValue = store.state.previousTagRoute.hasValue
|
|
191
|
-
|
|
192
|
-
if (hadPreviousValue) {
|
|
193
|
-
store.state.leftPanel.tag = store.state.previousTagRoute.tag
|
|
194
|
-
store.state.leftPanel._tag = store.state.previousTagRoute.tag
|
|
195
|
-
store.state.leftPanel.routeId = store.state.previousTagRoute.routeId
|
|
196
|
-
store.state.previousTagRoute.hasValue = false
|
|
197
|
-
} else {
|
|
198
|
-
store.state.leftPanel.tag = null
|
|
199
|
-
store.state.leftPanel._tag = null
|
|
200
|
-
store.state.leftPanel.routeId = null
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
syncSelectionToUrl()
|
|
204
|
-
|
|
205
|
-
// Load the full tags from cache (not search results) since we're resetting search
|
|
206
|
-
loadFullTags()
|
|
67
|
+
const hadPreviousValue = store.actions.resetSearchState()
|
|
207
68
|
|
|
208
69
|
// If we restored a previous tag/route, generate with it
|
|
209
70
|
// Otherwise, fall back to initial policy
|
|
210
71
|
if (hadPreviousValue) {
|
|
211
72
|
onGenerate()
|
|
212
73
|
} else {
|
|
213
|
-
renderBasedOnInitialPolicy()
|
|
74
|
+
store.actions.renderBasedOnInitialPolicy(onGenerate)
|
|
214
75
|
}
|
|
215
76
|
}
|
|
216
77
|
|
|
217
|
-
function loadFullTags() {
|
|
218
|
-
// Restore from cache (set by loadInitial)
|
|
219
|
-
store.state.leftPanel.tags = store.state.leftPanel.fullTagsCache
|
|
220
|
-
}
|
|
221
|
-
|
|
222
78
|
async function onSearch() {
|
|
79
|
+
// Save current state before entering search mode (only if not already saved)
|
|
80
|
+
if (!store.state.previousTagRoute.hasValue) {
|
|
81
|
+
store.state.previousTagRoute.tag = store.state.leftPanel.tag
|
|
82
|
+
store.state.previousTagRoute.routeId = store.state.leftPanel.routeId
|
|
83
|
+
store.state.previousTagRoute.hasValue = true
|
|
84
|
+
}
|
|
85
|
+
|
|
223
86
|
store.state.search.mode = true
|
|
224
87
|
store.state.leftPanel.tag = null
|
|
225
88
|
store.state.leftPanel._tag = null
|
|
226
89
|
store.state.leftPanel.routeId = null
|
|
227
|
-
syncSelectionToUrl()
|
|
228
|
-
await loadSearchedTags()
|
|
90
|
+
store.actions.syncSelectionToUrl()
|
|
91
|
+
await store.actions.loadSearchedTags()
|
|
229
92
|
await onGenerate()
|
|
230
93
|
}
|
|
231
|
-
async function loadSearchedTags() {
|
|
232
|
-
try {
|
|
233
|
-
const payload = {
|
|
234
|
-
schema_name: store.state.search.schemaName,
|
|
235
|
-
schema_field: store.state.search.fieldName || null,
|
|
236
|
-
show_fields: store.state.filter.showFields,
|
|
237
|
-
brief: store.state.filter.brief,
|
|
238
|
-
hide_primitive_route: store.state.filter.hidePrimitiveRoute,
|
|
239
|
-
show_module: store.state.filter.showModule,
|
|
240
|
-
}
|
|
241
|
-
const res = await fetch("dot-search", {
|
|
242
|
-
method: "POST",
|
|
243
|
-
headers: { "Content-Type": "application/json" },
|
|
244
|
-
body: JSON.stringify(payload),
|
|
245
|
-
})
|
|
246
|
-
if (res.ok) {
|
|
247
|
-
const data = await res.json()
|
|
248
|
-
const tags = Array.isArray(data.tags) ? data.tags : []
|
|
249
|
-
store.state.leftPanel.tags = tags
|
|
250
|
-
}
|
|
251
|
-
} catch (err) {
|
|
252
|
-
console.error("dot-search failed", err)
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
94
|
|
|
256
95
|
async function loadInitial() {
|
|
257
|
-
store.
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
const data = await res.json()
|
|
261
|
-
const tags = Array.isArray(data.tags) ? data.tags : []
|
|
262
|
-
store.state.leftPanel.tags = tags
|
|
263
|
-
// Cache the full tags for later use (e.g., resetSearch)
|
|
264
|
-
store.state.leftPanel.fullTagsCache = tags
|
|
265
|
-
|
|
266
|
-
const schemasArr = Array.isArray(data.schemas) ? data.schemas : []
|
|
267
|
-
// Build dict keyed by id for faster lookups and simpler prop passing
|
|
268
|
-
const schemaMap = Object.fromEntries(schemasArr.map((s) => [s.id, s]))
|
|
269
|
-
store.state.graph.schemaMap = schemaMap
|
|
270
|
-
store.state.graph.schemaKeys = new Set(Object.keys(schemaMap))
|
|
271
|
-
store.state.graph.routeItems = data.tags
|
|
272
|
-
.map((t) => t.routes)
|
|
273
|
-
.flat()
|
|
274
|
-
.reduce((acc, r) => {
|
|
275
|
-
acc[r.id] = r
|
|
276
|
-
return acc
|
|
277
|
-
}, {})
|
|
278
|
-
store.state.modeControl.briefModeEnabled = data.enable_brief_mode || false
|
|
279
|
-
store.state.version = data.version || ""
|
|
280
|
-
store.state.swagger.url = data.swagger_url || null
|
|
281
|
-
store.state.config.has_er_diagram = data.has_er_diagram || false
|
|
282
|
-
store.state.config.enable_pydantic_resolve_meta = data.enable_pydantic_resolve_meta || false
|
|
283
|
-
|
|
284
|
-
rebuildSchemaOptions()
|
|
285
|
-
|
|
286
|
-
const querySelection = readQuerySelection()
|
|
287
|
-
const restoredFromQuery = applySelectionFromQuery(querySelection)
|
|
288
|
-
if (restoredFromQuery) {
|
|
289
|
-
syncSelectionToUrl()
|
|
290
|
-
onGenerate()
|
|
291
|
-
return
|
|
292
|
-
} else {
|
|
293
|
-
store.state.config.initial_page_policy = data.initial_page_policy
|
|
294
|
-
renderBasedOnInitialPolicy()
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// default route options placeholder
|
|
298
|
-
} catch (e) {
|
|
299
|
-
console.error("Initial load failed", e)
|
|
300
|
-
} finally {
|
|
301
|
-
store.state.initializing = false
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
async function renderBasedOnInitialPolicy() {
|
|
306
|
-
switch (store.state.config.initial_page_policy) {
|
|
307
|
-
case "full":
|
|
308
|
-
onGenerate()
|
|
309
|
-
return
|
|
310
|
-
case "empty":
|
|
311
|
-
return
|
|
312
|
-
case "first":
|
|
313
|
-
store.state.leftPanel.tag =
|
|
314
|
-
store.state.leftPanel.tags.length > 0 ? store.state.leftPanel.tags[0].name : null
|
|
315
|
-
store.state.leftPanel._tag = store.state.leftPanel.tag
|
|
316
|
-
syncSelectionToUrl()
|
|
317
|
-
onGenerate()
|
|
318
|
-
return
|
|
319
|
-
}
|
|
96
|
+
await store.actions.loadInitial(onGenerate, (cb) =>
|
|
97
|
+
store.actions.renderBasedOnInitialPolicy(cb)
|
|
98
|
+
)
|
|
320
99
|
}
|
|
321
100
|
|
|
322
101
|
async function onGenerate(resetZoom = true) {
|
|
@@ -331,21 +110,9 @@ const app = createApp({
|
|
|
331
110
|
}
|
|
332
111
|
|
|
333
112
|
async function renderVoyager(resetZoom = true) {
|
|
334
|
-
const activeSchema = store.state.search.mode ? store.state.search.schemaName : null
|
|
335
|
-
const activeField = store.state.search.mode ? store.state.search.fieldName : null
|
|
336
113
|
store.state.generating = true
|
|
337
114
|
try {
|
|
338
|
-
const payload =
|
|
339
|
-
tags: store.state.leftPanel.tag ? [store.state.leftPanel.tag] : null,
|
|
340
|
-
schema_name: activeSchema || null,
|
|
341
|
-
schema_field: activeField || null,
|
|
342
|
-
route_name: store.state.leftPanel.routeId || null,
|
|
343
|
-
show_fields: store.state.filter.showFields,
|
|
344
|
-
brief: store.state.filter.brief,
|
|
345
|
-
hide_primitive_route: store.state.filter.hidePrimitiveRoute,
|
|
346
|
-
show_module: store.state.filter.showModule,
|
|
347
|
-
show_pydantic_resolve_meta: store.state.modeControl.pydanticResolveMetaEnabled,
|
|
348
|
-
}
|
|
115
|
+
const payload = store.actions.buildVoyagerPayload()
|
|
349
116
|
initGraphUI()
|
|
350
117
|
const res = await fetch("dot", {
|
|
351
118
|
method: "POST",
|
|
@@ -362,37 +129,10 @@ const app = createApp({
|
|
|
362
129
|
}
|
|
363
130
|
}
|
|
364
131
|
|
|
365
|
-
function resetDetailPanels() {
|
|
366
|
-
store.state.rightDrawer.drawer = false
|
|
367
|
-
store.state.routeDetail.show = false
|
|
368
|
-
store.state.schemaDetail.schemaCodeName = ""
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
async function onReset() {
|
|
372
|
-
store.state.leftPanel.tag = null
|
|
373
|
-
store.state.leftPanel._tag = null
|
|
374
|
-
store.state.leftPanel.routeId = null
|
|
375
|
-
syncSelectionToUrl()
|
|
376
|
-
onGenerate()
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
async function togglePydanticResolveMeta(val) {
|
|
380
|
-
store.state.modeControl.pydanticResolveMetaEnabled = val
|
|
381
|
-
try {
|
|
382
|
-
localStorage.setItem("pydantic_resolve_meta", JSON.stringify(val))
|
|
383
|
-
} catch (e) {
|
|
384
|
-
console.warn("Failed to save pydantic_resolve_meta to localStorage", e)
|
|
385
|
-
}
|
|
386
|
-
onGenerate()
|
|
387
|
-
}
|
|
388
|
-
|
|
389
132
|
async function renderErDiagram(resetZoom = true) {
|
|
390
133
|
initGraphUI()
|
|
391
134
|
erDiagramLoading.value = true
|
|
392
|
-
const payload =
|
|
393
|
-
show_fields: store.state.filter.showFields,
|
|
394
|
-
show_module: store.state.filter.showModule,
|
|
395
|
-
}
|
|
135
|
+
const payload = store.actions.buildErDiagramPayload()
|
|
396
136
|
try {
|
|
397
137
|
const res = await fetch("er-diagram", {
|
|
398
138
|
method: "POST",
|
|
@@ -447,7 +187,7 @@ const app = createApp({
|
|
|
447
187
|
|
|
448
188
|
store.state.rightDrawer.drawer = false
|
|
449
189
|
store.state.routeDetail.show = false
|
|
450
|
-
syncSelectionToUrl()
|
|
190
|
+
store.actions.syncSelectionToUrl()
|
|
451
191
|
}
|
|
452
192
|
|
|
453
193
|
function toggleTagNavigatorCollapse() {
|
|
@@ -468,7 +208,7 @@ const app = createApp({
|
|
|
468
208
|
|
|
469
209
|
function selectRoute(routeId) {
|
|
470
210
|
// find belonging tag
|
|
471
|
-
const belongingTag = findTagByRoute(routeId)
|
|
211
|
+
const belongingTag = store.getters.findTagByRoute(routeId)
|
|
472
212
|
if (belongingTag) {
|
|
473
213
|
store.state.leftPanel.tag = belongingTag
|
|
474
214
|
store.state.leftPanel._tag = belongingTag
|
|
@@ -483,45 +223,10 @@ const app = createApp({
|
|
|
483
223
|
store.state.rightDrawer.drawer = false
|
|
484
224
|
store.state.routeDetail.show = false
|
|
485
225
|
store.state.schemaDetail.schemaCodeName = ""
|
|
486
|
-
syncSelectionToUrl()
|
|
487
|
-
onGenerate()
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
function toggleShowModule(val) {
|
|
491
|
-
store.state.filter.showModule = val
|
|
492
|
-
try {
|
|
493
|
-
localStorage.setItem("show_module_cluster", JSON.stringify(val))
|
|
494
|
-
} catch (e) {
|
|
495
|
-
console.warn("Failed to save show_module_cluster to localStorage", e)
|
|
496
|
-
}
|
|
226
|
+
store.actions.syncSelectionToUrl()
|
|
497
227
|
onGenerate()
|
|
498
228
|
}
|
|
499
229
|
|
|
500
|
-
function toggleShowField(field) {
|
|
501
|
-
store.state.filter.showFields = field
|
|
502
|
-
onGenerate(false)
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
function toggleBrief(val) {
|
|
506
|
-
store.state.filter.brief = val
|
|
507
|
-
try {
|
|
508
|
-
localStorage.setItem("brief_mode", JSON.stringify(val))
|
|
509
|
-
} catch (e) {
|
|
510
|
-
console.warn("Failed to save brief_mode to localStorage", e)
|
|
511
|
-
}
|
|
512
|
-
onGenerate()
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
function toggleHidePrimitiveRoute(val) {
|
|
516
|
-
store.state.filter.hidePrimitiveRoute = val
|
|
517
|
-
try {
|
|
518
|
-
localStorage.setItem("hide_primitive", JSON.stringify(val))
|
|
519
|
-
} catch (e) {
|
|
520
|
-
console.warn("Failed to save hide_primitive to localStorage", e)
|
|
521
|
-
}
|
|
522
|
-
onGenerate(false)
|
|
523
|
-
}
|
|
524
|
-
|
|
525
230
|
function startDragDrawer(e) {
|
|
526
231
|
const startX = e.clientX
|
|
527
232
|
const startWidth = store.state.rightDrawer.width
|
|
@@ -549,7 +254,7 @@ const app = createApp({
|
|
|
549
254
|
watch(
|
|
550
255
|
() => store.state.graph.schemaMap,
|
|
551
256
|
() => {
|
|
552
|
-
rebuildSchemaOptions()
|
|
257
|
+
store.actions.rebuildSchemaOptions()
|
|
553
258
|
},
|
|
554
259
|
{ deep: false }
|
|
555
260
|
)
|
|
@@ -573,8 +278,8 @@ const app = createApp({
|
|
|
573
278
|
watch(
|
|
574
279
|
() => store.state.search.schemaName,
|
|
575
280
|
(schemaId) => {
|
|
576
|
-
store.state.search.schemaOptions = allSchemaOptions.
|
|
577
|
-
populateFieldOptions(schemaId)
|
|
281
|
+
store.state.search.schemaOptions = store.state.allSchemaOptions.slice()
|
|
282
|
+
store.actions.populateFieldOptions(schemaId)
|
|
578
283
|
if (!schemaId) {
|
|
579
284
|
store.state.search.mode = false
|
|
580
285
|
}
|
|
@@ -591,21 +296,22 @@ const app = createApp({
|
|
|
591
296
|
store,
|
|
592
297
|
onSearch,
|
|
593
298
|
resetSearch,
|
|
594
|
-
filterSearchSchemas,
|
|
595
|
-
onSearchSchemaChange,
|
|
299
|
+
filterSearchSchemas: (val, update) => store.actions.filterSearchSchemas(val, update),
|
|
300
|
+
onSearchSchemaChange: (val) => store.actions.onSearchSchemaChange(val, onSearch),
|
|
596
301
|
toggleTag,
|
|
597
302
|
toggleTagNavigatorCollapse,
|
|
598
|
-
toggleBrief,
|
|
599
|
-
toggleHidePrimitiveRoute,
|
|
303
|
+
toggleBrief: (val) => store.actions.toggleBrief(val, onGenerate),
|
|
304
|
+
toggleHidePrimitiveRoute: (val) => store.actions.toggleHidePrimitiveRoute(val, onGenerate),
|
|
600
305
|
selectRoute,
|
|
601
306
|
onGenerate,
|
|
602
|
-
onReset,
|
|
603
|
-
toggleShowField,
|
|
307
|
+
onReset: () => store.actions.onReset(onGenerate),
|
|
308
|
+
toggleShowField: (field) => store.actions.toggleShowField(field, onGenerate),
|
|
604
309
|
startDragDrawer,
|
|
605
|
-
toggleShowModule,
|
|
310
|
+
toggleShowModule: (val) => store.actions.toggleShowModule(val, onGenerate),
|
|
606
311
|
onModeChange,
|
|
607
312
|
renderErDiagram,
|
|
608
|
-
togglePydanticResolveMeta,
|
|
313
|
+
togglePydanticResolveMeta: (val) => store.actions.togglePydanticResolveMeta(val, onGenerate),
|
|
314
|
+
resetDetailPanels: () => store.actions.resetDetailPanels(),
|
|
609
315
|
}
|
|
610
316
|
},
|
|
611
317
|
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastapi-voyager
|
|
3
|
-
Version: 0.15.
|
|
3
|
+
Version: 0.15.3
|
|
4
4
|
Summary: Visualize FastAPI application's routing tree and dependencies
|
|
5
5
|
Project-URL: Homepage, https://github.com/allmonday/fastapi-voyager
|
|
6
6
|
Project-URL: Source, https://github.com/allmonday/fastapi-voyager
|
|
@@ -9,7 +9,7 @@ fastapi_voyager/render_style.py,sha256=mPOuChEl71-3agCbPwkMt2sFmax2AEKDI6dK90eFP
|
|
|
9
9
|
fastapi_voyager/server.py,sha256=MUc_ia3_QIbYQ8VenOxv3CEYVTiPDs7e_H40YoalxZs,8970
|
|
10
10
|
fastapi_voyager/type.py,sha256=zluWvh5vpnjXJ9aAmyNJTSmXZPjAHCvgRT5oQRAjHrg,2104
|
|
11
11
|
fastapi_voyager/type_helper.py,sha256=FmfrZAI3Z4uDdh3sH_kH7UGoY6yNVPapneSN86qY_wo,10209
|
|
12
|
-
fastapi_voyager/version.py,sha256=
|
|
12
|
+
fastapi_voyager/version.py,sha256=mV_h7Kelwuchi4ZvsHaY1gjoGeeu7EK0TqrMYIGLwgI,49
|
|
13
13
|
fastapi_voyager/voyager.py,sha256=4vonmL-xt54C5San-DRBq4mjoV8Q96eoWRy68MJ1IJw,14169
|
|
14
14
|
fastapi_voyager/templates/dot/cluster.j2,sha256=I2z9KkfCzmAtqXe0gXBnxnOfBXUSpdlATs3uf-O8_B8,307
|
|
15
15
|
fastapi_voyager/templates/dot/cluster_container.j2,sha256=2tH1mOJvPoVKE_aHVMR3t06TfH_dYa9OeH6DBqSHt_A,204
|
|
@@ -30,8 +30,8 @@ fastapi_voyager/web/graphviz.svg.js,sha256=deI815RgxpZ3_MpELeV-TBYy2MVuUvZtQOHfS
|
|
|
30
30
|
fastapi_voyager/web/index.html,sha256=lA59Op4u1bb-B105Iadn2KN_n11-AtXFdJglUezZIDg,23225
|
|
31
31
|
fastapi_voyager/web/quasar.min.css,sha256=F5jQe7X2XT54VlvAaa2V3GsBFdVD-vxDZeaPLf6U9CU,203145
|
|
32
32
|
fastapi_voyager/web/quasar.min.js,sha256=h0ftyPMW_CRiyzeVfQqiup0vrVt4_QWojpqmpnpn07E,502974
|
|
33
|
-
fastapi_voyager/web/store.js,sha256=
|
|
34
|
-
fastapi_voyager/web/vue-main.js,sha256=
|
|
33
|
+
fastapi_voyager/web/store.js,sha256=zjmtx1HGN_umfyOQVwQgET-2V5hvXbS50YgXCr294Ok,14370
|
|
34
|
+
fastapi_voyager/web/vue-main.js,sha256=1s11NOjILgjncJ4WbN1DGzTeLUb0a2-LYIA3lUIX8Bc,10564
|
|
35
35
|
fastapi_voyager/web/component/demo.js,sha256=sAklFGhKGmMy9-ofgOw2oPIidAoIOgHu6yvV51L_MAA,350
|
|
36
36
|
fastapi_voyager/web/component/render-graph.js,sha256=9wnO70n3eyPKTpa744idgs5PSwgvzbfv4InZ68eEOKs,2454
|
|
37
37
|
fastapi_voyager/web/component/route-code-display.js,sha256=a823nBz3EEjutW2pfi73rcF3hodCBmgYNmuZi94sXE4,3615
|
|
@@ -43,8 +43,8 @@ fastapi_voyager/web/icon/favicon-16x16.png,sha256=JC07jEzfIYxBIoQn_FHXvyHuxESdhW
|
|
|
43
43
|
fastapi_voyager/web/icon/favicon-32x32.png,sha256=C7v1h58cfWOsiLp9yOIZtlx-dLasBcq3NqpHVGRmpt4,1859
|
|
44
44
|
fastapi_voyager/web/icon/favicon.ico,sha256=tZolYIXkkBcFiYl1A8ksaXN2VjGamzcSdes838dLvNc,15406
|
|
45
45
|
fastapi_voyager/web/icon/site.webmanifest,sha256=GRozZ5suTykYcPMap1QhjrAB8PLW0mbT_phhzw_utvQ,316
|
|
46
|
-
fastapi_voyager-0.15.
|
|
47
|
-
fastapi_voyager-0.15.
|
|
48
|
-
fastapi_voyager-0.15.
|
|
49
|
-
fastapi_voyager-0.15.
|
|
50
|
-
fastapi_voyager-0.15.
|
|
46
|
+
fastapi_voyager-0.15.3.dist-info/METADATA,sha256=_NFcPd07mWHADnTH01kf6c2y0Lw9AQgqQNnHMK0Y5xE,8513
|
|
47
|
+
fastapi_voyager-0.15.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
48
|
+
fastapi_voyager-0.15.3.dist-info/entry_points.txt,sha256=pEIKoUnIDXEtdMBq8EmXm70m16vELIu1VPz9-TBUFWM,53
|
|
49
|
+
fastapi_voyager-0.15.3.dist-info/licenses/LICENSE,sha256=lNVRR3y_bFVoFKuK2JM8N4sFaj3m-7j29kvL3olFi5Y,1067
|
|
50
|
+
fastapi_voyager-0.15.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|