bk-schema-checker 0.1.3 → 0.1.4

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.
Files changed (2) hide show
  1. package/package.json +2 -2
  2. package/py/load_backend.py +45 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bk-schema-checker",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "对照前端 services、Django REST 序列化器,以及可选的 bk-local-mock 响应,做接口协议检查。不启动 Django。",
5
5
  "type": "module",
6
6
  "author": "austinqli",
@@ -43,4 +43,4 @@
43
43
  "check": "node ./bin/bk-schema-checker.js",
44
44
  "test": "node --test test/"
45
45
  }
46
- }
46
+ }
@@ -1380,10 +1380,48 @@ class BackendLoader:
1380
1380
  schema = self.materialize(ref, mode, stack)
1381
1381
  if schema.get("type") == "array":
1382
1382
  return {"schema": schema, "many": True, "empty": False}
1383
+ if not many and mode == "response" and isinstance(self.swagger_example(ref), list):
1384
+ many = True
1383
1385
  if many:
1384
1386
  schema = {"type": "array", "items": schema}
1385
1387
  return {"schema": schema, "many": many, "empty": False}
1386
1388
 
1389
+ def swagger_example(self, ref):
1390
+ if not ref:
1391
+ return None
1392
+ meta = nested_class(ref.node, "Meta")
1393
+ if not meta:
1394
+ return None
1395
+ node = class_assign(meta, "swagger_schema_fields")
1396
+ if node is None:
1397
+ return None
1398
+ value = self.eval_const(node, ref.module, set())
1399
+ if not isinstance(value, dict):
1400
+ return None
1401
+ return value.get("example")
1402
+
1403
+ def schema_from_swagger_example(self, ref):
1404
+ example = self.swagger_example(ref)
1405
+ if not isinstance(example, list):
1406
+ return None
1407
+ return {"type": "array", "items": self.example_item_schema(example), "required": True}
1408
+
1409
+ def example_item_schema(self, example):
1410
+ if not example:
1411
+ return any_schema()
1412
+ first = example[0]
1413
+ if isinstance(first, dict):
1414
+ return {"type": "object", "fields": {}, "open": True, "required": True}
1415
+ if isinstance(first, bool):
1416
+ return {"type": "boolean", "required": True, "allowNull": False}
1417
+ if isinstance(first, int):
1418
+ return {"type": "integer", "required": True, "allowNull": False}
1419
+ if isinstance(first, float):
1420
+ return {"type": "number", "required": True, "allowNull": False}
1421
+ if isinstance(first, str):
1422
+ return {"type": "string", "required": True, "allowNull": False}
1423
+ return any_schema()
1424
+
1387
1425
  def materialize(self, ref, mode, stack):
1388
1426
  key = f"{ref.module.file}#{ref.name}"
1389
1427
  if key in stack:
@@ -1414,7 +1452,13 @@ class BackendLoader:
1414
1452
  if mode == "response" and built.get("writeOnly"):
1415
1453
  continue
1416
1454
  fields[field_name] = built
1417
- return {"type": "object", "fields": fields, "serializer": ref.name, "required": True}
1455
+ schema = {"type": "object", "fields": fields, "serializer": ref.name, "required": True}
1456
+ if mode == "response" and not fields:
1457
+ hinted = self.schema_from_swagger_example(ref)
1458
+ if hinted:
1459
+ hinted.setdefault("serializer", ref.name)
1460
+ return hinted
1461
+ return schema
1418
1462
  finally:
1419
1463
  stack.discard(key)
1420
1464