linkml-store 0.1.11__py3-none-any.whl → 0.1.12__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.

Potentially problematic release.


This version of linkml-store might be problematic. Click here for more details.

@@ -1,5 +1,13 @@
1
1
  {% extends "base.html.j2" %}
2
2
 
3
+
4
+ {% macro make_link(link) %}
5
+ {{ link.rel }} [
6
+ page: <a href="/pages{{ link.href }}">/pages{{ link.href }}</a> |
7
+ API: <a href="{{ link.href }}">{{ link.href }}</a> ]
8
+ <a href="{{ href }}">{{ rel }}</a>
9
+ {% endmacro %}
10
+
3
11
  {% block title %}{meta.path}{% endblock %}
4
12
 
5
13
  {% block content %}
@@ -9,38 +17,27 @@
9
17
  </pre>
10
18
 
11
19
  <h1>Links</h1>
12
- <ul>
13
- {% for link in response.links %}
14
- <li>
15
- <a href="/pages{{ link.href }}">{{ link.rel }} ({{ link.href }})</a>
16
- </li>
17
- {% endfor %}
20
+ <ul>
21
+ {% for link in response.links %}
22
+ <li> {{ make_link(link) }} </li>
23
+ {% endfor %}
18
24
  </ul>
19
- </ul>
20
25
 
26
+ {% if response.items != None and response["items"] != None %}
27
+ <h1>Items</h1>
28
+ <ul>
29
+ {% for item in response["items"] %}
30
+ <li>
31
+ {{ item.name }}
32
+ {% for link in item.links %}
33
+ {{ make_link(link) }}
34
+ {% endfor %}
35
+ HTML: {{ item.html | safe }}
36
+ </li>
37
+ {% endfor %}
38
+ {% endif %}
21
39
  <h1>Data</h1>
22
- {% if data_html %}
23
- <ul>
24
- {% for e in data_html %}
25
- <li>{{ e|safe }}</li>
26
- {% endfor %}
27
- </ul>
28
- {% else %}
29
-
30
- {% if "items" in response.data %}
31
- <ul>
32
- {% for item in response.data['items'] %}
33
- <li>
34
- {{ item.name }}
35
- {% for link in item.links %}
36
- <a href="/pages{{ link.href }}">{{ link.rel }}</a>
37
- {% endfor %}
38
- </li>
39
- {% endfor %}
40
- </ul>
41
- {% endif %}
42
40
  <pre>
43
41
  {{ response.data }}
44
42
  </pre>
45
- {% endif %}
46
43
  {% endblock %}
@@ -55,6 +55,19 @@ class Link(BaseModel):
55
55
  href: str
56
56
 
57
57
 
58
+ class Item(BaseModel):
59
+ name: str
60
+ type: Optional[str] = None
61
+ links: List[Link]
62
+ data: Optional[Any] = None
63
+ html: Optional[str] = None
64
+
65
+
66
+ class ItemType(BaseModel):
67
+ name: str
68
+ description: Optional[str] = None
69
+
70
+
58
71
  class Meta(BaseModel):
59
72
  path: Optional[str] = None
60
73
  path_template: Optional[str] = None
@@ -62,6 +75,10 @@ class Meta(BaseModel):
62
75
  timestamp: str = Field(default_factory=lambda: datetime.utcnow().isoformat())
63
76
  version: str = "1.0"
64
77
  request_id: str = Field(default_factory=lambda: str(uuid.uuid4()))
78
+ item_count: Optional[int] = None
79
+ paged: bool = False
80
+ page: int = 1
81
+ page_size: Optional[int] = None
65
82
 
66
83
 
67
84
  class Error(BaseModel):
@@ -71,8 +88,10 @@ class Error(BaseModel):
71
88
 
72
89
 
73
90
  class APIResponse(BaseModel):
74
- data: Optional[Any] = None
75
91
  meta: Meta = Field(default_factory=Meta)
92
+ items: Optional[List[Item]] = None
93
+ item_type: Optional[ItemType] = None
94
+ data: Optional[Any] = None
76
95
  links: Optional[List[Link]] = None
77
96
  errors: Optional[List[Error]] = None
78
97
 
@@ -126,6 +145,7 @@ async def top(request: Request, client: Client = Depends(get_client)):
126
145
  links = [
127
146
  Link(rel="self", href="/"),
128
147
  Link(rel="docs", href="/docs"),
148
+ Link(rel="pages", href="/pages"),
129
149
  Link(rel="databases", href="/databases"),
130
150
  Link(rel="config", href="/config"),
131
151
  ]
@@ -137,10 +157,8 @@ async def config(request: Request, client: Client = Depends(get_client)):
137
157
  client = get_client()
138
158
  data = client.metadata
139
159
  links = [
140
- Link(rel="self", href="/"),
141
- Link(rel="docs", href="/docs"),
142
- Link(rel="databases", href="/databases"),
143
- Link(rel="config", href="/config"),
160
+ Link(rel="self", href="/config"),
161
+ Link(rel="parent", href="/"),
144
162
  ]
145
163
  return APIResponse(data=data, links=links)
146
164
 
@@ -151,31 +169,24 @@ async def config(request: Request, client: Client = Depends(get_client)):
151
169
  async def list_databases(request: Request, client: Client = Depends(get_client)):
152
170
  databases = list(client.databases.keys())
153
171
 
154
- database_links = [Link(rel="database", href=f"/databases/{db_name}") for db_name in databases]
172
+ # database_links = [Link(rel="database", href=f"/databases/{db_name}") for db_name in databases]
173
+ database_links = []
155
174
 
156
175
  additional_links = [
157
176
  Link(rel="self", href="/databases"),
177
+ Link(rel="parent", href="/"),
158
178
  Link(rel="create_database", href="/database/create"),
159
179
  ]
160
180
 
161
- response_data = {
162
- "objects": [
163
- {
164
- "name": db_name,
165
- "type": "Database",
166
- "links": [
167
- {"rel": "self", "href": f"/databases/{db_name}"},
168
- {"rel": "collections", "href": f"/databases/{db_name}/collections"},
169
- {"rel": "schema", "href": f"/databases/{db_name}/schema"},
170
- ],
171
- }
172
- for db_name in databases
173
- ]
174
- }
181
+ items = [
182
+ Item(name=db_name, type="Database", links=[Link(rel="self", href=f"/databases/{db_name}")], data={})
183
+ for db_name in databases
184
+ ]
175
185
 
176
186
  api_response = APIResponse(
177
187
  meta=Meta(path=request.url.path, path_template="databases", params={}),
178
- data=response_data,
188
+ data={},
189
+ items=items,
179
190
  links=additional_links + database_links,
180
191
  )
181
192
  if request.headers.get("Accept") == "text/html":
@@ -186,6 +197,7 @@ async def list_databases(request: Request, client: Client = Depends(get_client))
186
197
 
187
198
  @app.post("/database/create", response_model=APIResponse)
188
199
  async def create_database(database: DatabaseCreate, client: Client = Depends(get_client)):
200
+ # TODO
189
201
  db = client.attach_database(database.handle, alias=database.name)
190
202
  return APIResponse(
191
203
  data={"name": db.metadata.alias, "handle": db.metadata.handle},
@@ -202,53 +214,48 @@ async def get_database_details(
202
214
  ):
203
215
  database = get_db(database_name)
204
216
  collections = database.list_collections()
217
+ db_metadata = database.metadata.model_dump(exclude_none=True, exclude_defaults=True)
218
+ if "collections" in db_metadata:
219
+ # do not replicate information
220
+ del db_metadata["collections"]
205
221
  return APIResponse(
206
222
  meta=Meta(path=request.url.path, path_template="database_details", params={"database_name": database_name}),
207
223
  data={
208
224
  "name": database.metadata.alias,
209
225
  "handle": database.metadata.handle,
226
+ "config": db_metadata,
210
227
  "num_collections": len(collections),
211
- "collections": [
212
- {
213
- "name": c.name,
214
- "links": [
215
- {"rel": "self", "href": f"/databases/{database_name}/collections/{c.name}"},
216
- {"rel": "objects", "href": f"/databases/{database_name}/collections/{c.name}/objects"},
217
- ],
218
- }
219
- for c in collections
220
- ],
221
228
  },
222
229
  links=[
223
230
  Link(rel="self", href=f"/databases/{database_name}"),
224
231
  Link(rel="collections", href=f"/databases/{database_name}/collections"),
225
232
  Link(rel="schema", href=f"/databases/{database_name}/schema"),
226
- Link(rel="all_databases", href="/databases"),
233
+ Link(rel="parent", href="/databases"),
227
234
  ],
228
235
  )
229
236
 
230
237
 
231
238
  @app.get("/databases/{database_name}/collections", response_model=APIResponse)
232
- async def list_collections(
239
+ async def list_database_collections(
233
240
  request: Request, database_name: str, get_db: Callable[[str], Database] = Depends(get_database)
234
241
  ):
235
242
  database = get_db(database_name)
236
243
  collections = database.list_collections()
244
+ items = [
245
+ Item(
246
+ name=c.alias,
247
+ type="Collection",
248
+ links=[
249
+ Link(rel="self", href=f"/databases/{database_name}/collections/{c.alias}"),
250
+ Link(rel="objects", href=f"/databases/{database_name}/collections/{c.alias}/objects"),
251
+ ],
252
+ )
253
+ for c in collections
254
+ ]
237
255
  return APIResponse(
238
256
  meta=Meta(path=request.url.path, path_template="collections", params={}),
239
- data={
240
- "items": [
241
- {
242
- "name": c.name,
243
- "type": "Collection",
244
- "links": [
245
- {"rel": "self", "href": f"/databases/{database_name}/collections/{c.name}"},
246
- {"rel": "objects", "href": f"/databases/{database_name}/collections/{c.name}/objects"},
247
- ],
248
- }
249
- for c in collections
250
- ]
251
- },
257
+ items=items,
258
+ data={},
252
259
  links=[
253
260
  Link(rel="self", href=f"/databases/{database_name}/collections"),
254
261
  Link(rel="database", href=f"/databases/{database_name}"),
@@ -275,11 +282,15 @@ async def get_collection_details(
275
282
  "collection_name": collection_name,
276
283
  },
277
284
  ),
278
- data={"name": collection.name, "alias": collection.alias, "num_objects": collection.find({}).num_rows},
285
+ data={
286
+ "target_class_name": collection.target_class_name,
287
+ "alias": collection.alias,
288
+ "num_objects": collection.find({}).num_rows,
289
+ },
279
290
  links=[
280
291
  Link(rel="self", href=f"/databases/{database_name}/collections/{collection_name}"),
281
292
  Link(rel="objects", href=f"/databases/{database_name}/collections/{collection_name}/objects"),
282
- Link(rel="facets", href=f"/databases/{database_name}/collections/{collection_name}/facets"),
293
+ Link(rel="attributes", href=f"/databases/{database_name}/collections/{collection_name}/attributes"),
283
294
  Link(rel="search", href=f"/databases/{database_name}/collections/{collection_name}/search/{{term}}"),
284
295
  Link(rel="database", href=f"/databases/{database_name}"),
285
296
  ],
@@ -294,21 +305,21 @@ async def create_collection(
294
305
  get_db: Callable[[str], Database] = Depends(get_database),
295
306
  ):
296
307
  database = get_db(database_name)
297
- new_collection = database.create_collection(collection.name, alias=collection.alias)
308
+ new_collection = database.create_collection(collection.alias, alias=collection.alias)
298
309
  return APIResponse(
299
310
  meta=Meta(path=request.url.path, path_template="create_collection", params={"database_name": database_name}),
300
- data={"name": new_collection.name, "alias": new_collection.alias},
311
+ data={"name": new_collection.alias, "alias": new_collection.alias},
301
312
  links=[
302
- Link(rel="self", href=f"/databases/{database_name}/collections/{new_collection.name}"),
313
+ Link(rel="self", href=f"/databases/{database_name}/collections/{new_collection.alias}"),
303
314
  Link(rel="database", href=f"/databases/{database_name}"),
304
- Link(rel="objects", href=f"/databases/{database_name}/collections/{new_collection.name}/objects"),
305
- Link(rel="objects", href=f"/databases/{database_name}/collections/{new_collection.name}/facets"),
315
+ Link(rel="objects", href=f"/databases/{database_name}/collections/{new_collection.alias}/objects"),
316
+ Link(rel="objects", href=f"/databases/{database_name}/collections/{new_collection.alias}/facets"),
306
317
  ],
307
318
  )
308
319
 
309
320
 
310
321
  @app.get("/databases/{database_name}/collections/{collection_name}/objects", response_model=APIResponse)
311
- async def collection_list_objects(
322
+ async def list_collection_objects(
312
323
  request: Request,
313
324
  database_name: str,
314
325
  collection_name: str,
@@ -320,14 +331,28 @@ async def collection_list_objects(
320
331
  database = get_db(database_name)
321
332
  collection = database.get_collection(collection_name)
322
333
  where_clause = load_objects(where) if where else None
323
- query = StoreQuery(from_table=collection.name, where_clause=where_clause, limit=limit, offset=offset)
334
+ query = StoreQuery(from_table=collection.alias, where_clause=where_clause, limit=limit, offset=offset)
324
335
  result = collection.query(query)
336
+ base_url = f"/databases/{database_name}/collections/{collection_name}/objects"
337
+
338
+ items = []
339
+ cd = collection.class_definition()
340
+ id_att_name = collection.identifier_attribute_name
341
+ for i, row in enumerate(result.rows):
342
+ if id_att_name:
343
+ name = row[id_att_name]
344
+ link = Link(rel="self", href=f"{base_url}/{name}")
345
+ else:
346
+ ix = offset + i
347
+ name = str(ix)
348
+ link = Link(rel="self", href=f"{base_url}_index/{ix}")
349
+ item = Item(name=name, data=row, links=[link])
350
+ items.append(item)
325
351
 
326
352
  total_count = collection.find({}).num_rows
327
353
  total_pages = (total_count + limit - 1) // limit
328
354
  current_page = offset // limit + 1
329
355
 
330
- base_url = f"/databases/{database_name}/collections/{collection_name}/objects"
331
356
  links = [Link(rel="self", href=f"{base_url}?limit={limit}&offset={offset}")]
332
357
  if current_page > 1:
333
358
  links.append(Link(rel="prev", href=f"{base_url}?limit={limit}&offset={offset - limit}"))
@@ -338,6 +363,50 @@ async def collection_list_objects(
338
363
  [
339
364
  Link(rel="first", href=f"{base_url}?limit={limit}&offset=0"),
340
365
  Link(rel="last", href=f"{base_url}?limit={limit}&offset={(total_pages - 1) * limit}"),
366
+ Link(rel="parent", href=f"/databases/{database_name}/collections/{collection_name}"),
367
+ ]
368
+ )
369
+
370
+ return APIResponse(
371
+ meta=Meta(
372
+ path=request.url.path,
373
+ path_template="objects",
374
+ params={
375
+ "database_name": database_name,
376
+ "collection_name": collection_name,
377
+ },
378
+ paged=True,
379
+ item_count=total_count,
380
+ page=current_page,
381
+ page_size=limit,
382
+ ),
383
+ item_type=ItemType(
384
+ name=cd.name,
385
+ description=cd.description,
386
+ ),
387
+ items=items,
388
+ data={},
389
+ links=links,
390
+ )
391
+
392
+
393
+ @app.get("/databases/{database_name}/collections/{collection_name}/objects/{id}", response_model=APIResponse)
394
+ async def get_object_details(
395
+ request: Request,
396
+ database_name: str,
397
+ collection_name: str,
398
+ id: str,
399
+ get_db: Callable[[str], Database] = Depends(get_database),
400
+ ):
401
+ database = get_db(database_name)
402
+ collection = database.get_collection(collection_name)
403
+ ids = id.split("+")
404
+ result = collection.get(ids)
405
+
406
+ base_url = f"/databases/{database_name}/collections/{collection_name}/objects/{id}"
407
+ links = [Link(rel="self", href=base_url)]
408
+ links.extend(
409
+ [
341
410
  Link(rel="collection", href=f"/databases/{database_name}/collections/{collection_name}"),
342
411
  Link(rel="database", href=f"/databases/{database_name}"),
343
412
  ]
@@ -354,10 +423,6 @@ async def collection_list_objects(
354
423
  ),
355
424
  data={
356
425
  "domain_objects": result.rows,
357
- "total_count": total_count,
358
- "page": current_page,
359
- "total_pages": total_pages,
360
- "page_size": limit,
361
426
  },
362
427
  links=links,
363
428
  )
@@ -419,7 +484,7 @@ async def search_objects(
419
484
 
420
485
 
421
486
  @app.get("/databases/{database_name}/collections/{collection_name}/facets", response_model=APIResponse)
422
- async def objects_facets(
487
+ async def list_collection_facets(
423
488
  request: Request,
424
489
  database_name: str,
425
490
  collection_name: str,
@@ -428,6 +493,7 @@ async def objects_facets(
428
493
  offset: int = Query(0, ge=0),
429
494
  get_db: Callable[[str], Database] = Depends(get_database),
430
495
  ):
496
+ # DEPRECATED?
431
497
  database = get_db(database_name)
432
498
  collection = database.get_collection(collection_name)
433
499
  where_clause = load_objects(where) if where else None
@@ -473,6 +539,173 @@ async def objects_facets(
473
539
  )
474
540
 
475
541
 
542
+ @app.get("/databases/{database_name}/collections/{collection_name}/attributes", response_model=APIResponse)
543
+ async def list_collection_attributes(
544
+ request: Request,
545
+ database_name: str,
546
+ collection_name: str,
547
+ where: Optional[str] = None,
548
+ get_db: Callable[[str], Database] = Depends(get_database),
549
+ ):
550
+ database = get_db(database_name)
551
+ collection = database.get_collection(collection_name)
552
+ where_clause = load_objects(where) if where else None
553
+ base_url = f"/databases/{database_name}/collections/{collection_name}/attributes"
554
+ results = collection.query_facets(where_clause)
555
+ items = [
556
+ Item(
557
+ name=facet_att,
558
+ type="Attribute",
559
+ links=[
560
+ Link(rel="self", href=f"{base_url}/{facet_att}"),
561
+ ],
562
+ data=[{"value": v, "count": c} for v, c in data],
563
+ )
564
+ for facet_att, data in results.items()
565
+ ]
566
+
567
+ links = [
568
+ Link(rel="self", href=base_url),
569
+ Link(rel="parent", href=f"/databases/{database_name}/collections/{collection_name}"),
570
+ Link(rel="grandparent", href=f"/databases/{database_name}"),
571
+ ]
572
+
573
+ return APIResponse(
574
+ meta=Meta(
575
+ path=request.url.path,
576
+ path_template="facets",
577
+ params={
578
+ "database_name": database_name,
579
+ "collection_name": collection_name,
580
+ },
581
+ ),
582
+ data={},
583
+ items=items,
584
+ links=links,
585
+ )
586
+
587
+
588
+ @app.get(
589
+ "/databases/{database_name}/collections/{collection_name}/attributes/{attribute_name}", response_model=APIResponse
590
+ )
591
+ async def get_attribute_details(
592
+ request: Request,
593
+ database_name: str,
594
+ collection_name: str,
595
+ attribute_name: str,
596
+ where: Optional[str] = None,
597
+ get_db: Callable[[str], Database] = Depends(get_database),
598
+ ):
599
+ database = get_db(database_name)
600
+ collection = database.get_collection(collection_name)
601
+ where_clause = load_objects(where) if where else None
602
+ base_url = f"/databases/{database_name}/collections/{collection_name}/attributes/{attribute_name}"
603
+ count_tuples = collection.query_facets(where_clause, facet_columns=[attribute_name])[attribute_name]
604
+ _count_objs = [{"value": v, "count": c} for v, c in count_tuples]
605
+ cd = collection.class_definition()
606
+ att = cd.attributes[attribute_name]
607
+ att_dict = json_dumper.to_dict(att)
608
+ items = [
609
+ Item(
610
+ name=str(v),
611
+ type="Value",
612
+ links=[
613
+ Link(rel="self", href=f"{base_url}/equals/{v}"),
614
+ ],
615
+ data={"count": c},
616
+ )
617
+ for v, c in count_tuples
618
+ ]
619
+
620
+ links = [
621
+ Link(rel="self", href=base_url),
622
+ Link(rel="collection", href=f"/databases/{database_name}/collections/{collection_name}"),
623
+ Link(rel="database", href=f"/databases/{database_name}"),
624
+ ]
625
+
626
+ return APIResponse(
627
+ meta=Meta(
628
+ path=request.url.path,
629
+ path_template="facets",
630
+ params={
631
+ "database_name": database_name,
632
+ "collection_name": collection_name,
633
+ },
634
+ ),
635
+ data={
636
+ "attribute": att_dict,
637
+ },
638
+ items=items,
639
+ links=links,
640
+ )
641
+
642
+
643
+ @app.get(
644
+ "/databases/{database_name}/collections/{collection_name}/attributes/{attribute_name}/equals/{value}",
645
+ response_model=APIResponse,
646
+ )
647
+ async def query_by_attribute(
648
+ request: Request,
649
+ database_name: str,
650
+ collection_name: str,
651
+ attribute_name: str,
652
+ value: str,
653
+ where: Optional[str] = None,
654
+ limit: int = Query(10, ge=1, le=100),
655
+ offset: int = Query(0, ge=0),
656
+ get_db: Callable[[str], Database] = Depends(get_database),
657
+ ):
658
+ database = get_db(database_name)
659
+ collection = database.get_collection(collection_name)
660
+ where_clause = {attribute_name: value}
661
+ query = StoreQuery(from_table=collection.alias, where_clause=where_clause, limit=limit, offset=offset)
662
+ result = collection.query(query)
663
+ items = []
664
+ for i, row in enumerate(result.rows):
665
+ item = Item(name=str(i), type="X", data=row, links=[])
666
+ items.append(item)
667
+
668
+ total_count = collection.find({}).num_rows
669
+ total_pages = (total_count + limit - 1) // limit
670
+ current_page = offset // limit + 1
671
+
672
+ base_url = f"/databases/{database_name}/collections/{collection_name}/attributes/{attribute_name}/equals/{value}"
673
+ links = [Link(rel="self", href=f"{base_url}?limit={limit}&offset={offset}")]
674
+ if current_page > 1:
675
+ links.append(Link(rel="prev", href=f"{base_url}?limit={limit}&offset={offset - limit}"))
676
+ if current_page < total_pages:
677
+ links.append(Link(rel="next", href=f"{base_url}?limit={limit}&offset={offset + limit}"))
678
+
679
+ links.extend(
680
+ [
681
+ Link(rel="first", href=f"{base_url}?limit={limit}&offset=0"),
682
+ Link(rel="last", href=f"{base_url}?limit={limit}&offset={(total_pages - 1) * limit}"),
683
+ Link(
684
+ rel="parent",
685
+ href=f"/databases/{database_name}/collections/{collection_name}/attributes/{attribute_name}",
686
+ ),
687
+ ]
688
+ )
689
+
690
+ return APIResponse(
691
+ meta=Meta(
692
+ path=request.url.path,
693
+ path_template="objects",
694
+ params={
695
+ "database_name": database_name,
696
+ "collection_name": collection_name,
697
+ },
698
+ paged=True,
699
+ item_count=total_count,
700
+ page=current_page,
701
+ page_size=limit,
702
+ ),
703
+ items=items,
704
+ data={},
705
+ links=links,
706
+ )
707
+
708
+
476
709
  @app.post("/databases/{database_name}/collections/{collection_name}/objects", response_model=APIResponse)
477
710
  async def insert_objects(
478
711
  database_name: str,
@@ -509,8 +742,8 @@ async def get_database_schema(
509
742
  )
510
743
 
511
744
 
512
- @app.get("/pages/{path:path}", response_class=HTMLResponse)
513
- async def generic_page(request: Request, path: str, get_db: Callable[[str], Database] = Depends(get_database)):
745
+ @app.get("/xxxpages/{path:path}", response_class=HTMLResponse)
746
+ async def xxxgeneric_page(request: Request, path: str, get_db: Callable[[str], Database] = Depends(get_database)):
514
747
  # Construct the API URL
515
748
  api_url = f"{request.base_url}{path}"
516
749
  query_params = dict(request.query_params)
@@ -524,6 +757,7 @@ async def generic_page(request: Request, path: str, get_db: Callable[[str], Data
524
757
 
525
758
  # Parse the JSON response
526
759
  api_data = response.json()
760
+ # api_response = APIResponse(**api_data)
527
761
 
528
762
  # Use the template specified in the API response
529
763
  meta = api_data["meta"]
@@ -557,6 +791,55 @@ async def generic_page(request: Request, path: str, get_db: Callable[[str], Data
557
791
  )
558
792
 
559
793
 
794
+ @app.get("/pages/{path:path}", response_class=HTMLResponse)
795
+ async def generic_page(request: Request, path: str, get_db: Callable[[str], Database] = Depends(get_database)):
796
+ # Construct the API URL
797
+ api_url = f"{request.base_url}{path}"
798
+ query_params = dict(request.query_params)
799
+
800
+ # Make a request to the API
801
+ async with httpx.AsyncClient() as client:
802
+ response = await client.get(api_url, params=query_params)
803
+
804
+ if response.status_code != 200:
805
+ raise HTTPException(status_code=response.status_code, detail=response.text)
806
+
807
+ # Parse the JSON response
808
+ api_data = response.json()
809
+ payload = APIResponse(**api_data)
810
+ template_name = "generic.html.j2"
811
+ params = payload.meta.params
812
+
813
+ # data = payload.data
814
+ data_html = None
815
+ if "database_name" in params:
816
+ db = get_db(params["database_name"])
817
+ sv = db.schema_view
818
+ else:
819
+ sv = None
820
+ if not payload.items:
821
+ payload.items = []
822
+ if payload.item_type and payload.items:
823
+ cn = payload.item_type.name
824
+ style_engine = StyleEngine(schemaview=sv)
825
+ html_renderer.style_engine = style_engine
826
+ for item in payload.items:
827
+ if item.data:
828
+ item.html = html_renderer.render(item.data, schemaview=sv, source_element_name=cn)
829
+
830
+ # Render the appropriate template
831
+ return templates.TemplateResponse(
832
+ template_name,
833
+ {
834
+ "request": request,
835
+ "response": payload,
836
+ "current_path": f"/pages/{path}",
837
+ "data_html": data_html,
838
+ "params": params,
839
+ },
840
+ )
841
+
842
+
560
843
  def run_server():
561
844
  import uvicorn
562
845
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: linkml-store
3
- Version: 0.1.11
3
+ Version: 0.1.12
4
4
  Summary: linkml-store
5
5
  License: MIT
6
6
  Author: Author 1