datacontract-cli 0.10.1__py3-none-any.whl → 0.10.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.

Potentially problematic release.


This version of datacontract-cli might be problematic. Click here for more details.

Files changed (36) hide show
  1. datacontract/breaking/breaking_rules.py +4 -0
  2. datacontract/catalog/catalog.py +76 -0
  3. datacontract/cli.py +39 -3
  4. datacontract/data_contract.py +12 -1
  5. datacontract/engines/fastjsonschema/check_jsonschema.py +1 -2
  6. datacontract/engines/soda/check_soda_execute.py +9 -15
  7. datacontract/engines/soda/connections/duckdb.py +83 -14
  8. datacontract/engines/soda/connections/kafka.py +108 -105
  9. datacontract/export/avro_idl_converter.py +1 -2
  10. datacontract/export/dbt_converter.py +1 -2
  11. datacontract/export/great_expectations_converter.py +1 -2
  12. datacontract/export/html_export.py +3 -2
  13. datacontract/export/jsonschema_converter.py +1 -2
  14. datacontract/export/odcs_converter.py +1 -2
  15. datacontract/export/rdf_converter.py +1 -1
  16. datacontract/export/sodacl_converter.py +1 -2
  17. datacontract/export/terraform_converter.py +1 -2
  18. datacontract/imports/avro_importer.py +1 -2
  19. datacontract/imports/glue_importer.py +183 -0
  20. datacontract/imports/sql_importer.py +20 -9
  21. datacontract/integration/publish_opentelemetry.py +3 -6
  22. datacontract/lint/linters/example_model_linter.py +1 -2
  23. datacontract/lint/linters/field_pattern_linter.py +1 -2
  24. datacontract/lint/linters/notice_period_linter.py +1 -2
  25. datacontract/lint/linters/quality_schema_linter.py +1 -2
  26. datacontract/lint/resolve.py +9 -6
  27. datacontract/model/data_contract_specification.py +2 -0
  28. datacontract/templates/datacontract.html +76 -21
  29. datacontract/templates/index.html +168 -0
  30. datacontract/templates/style/output.css +113 -4
  31. {datacontract_cli-0.10.1.dist-info → datacontract_cli-0.10.3.dist-info}/METADATA +180 -102
  32. {datacontract_cli-0.10.1.dist-info → datacontract_cli-0.10.3.dist-info}/RECORD +36 -33
  33. {datacontract_cli-0.10.1.dist-info → datacontract_cli-0.10.3.dist-info}/LICENSE +0 -0
  34. {datacontract_cli-0.10.1.dist-info → datacontract_cli-0.10.3.dist-info}/WHEEL +0 -0
  35. {datacontract_cli-0.10.1.dist-info → datacontract_cli-0.10.3.dist-info}/entry_points.txt +0 -0
  36. {datacontract_cli-0.10.1.dist-info → datacontract_cli-0.10.3.dist-info}/top_level.txt +0 -0
@@ -19,11 +19,14 @@ def resolve_data_contract(
19
19
  data_contract: DataContractSpecification = None,
20
20
  schema_location: str = None,
21
21
  inline_definitions: bool = False,
22
+ inline_quality: bool = False,
22
23
  ) -> DataContractSpecification:
23
24
  if data_contract_location is not None:
24
- return resolve_data_contract_from_location(data_contract_location, schema_location, inline_definitions)
25
+ return resolve_data_contract_from_location(
26
+ data_contract_location, schema_location, inline_definitions, inline_quality
27
+ )
25
28
  elif data_contract_str is not None:
26
- return resolve_data_contract_from_str(data_contract_str, schema_location, inline_definitions)
29
+ return resolve_data_contract_from_str(data_contract_str, schema_location, inline_definitions, inline_quality)
27
30
  elif data_contract is not None:
28
31
  return data_contract
29
32
  else:
@@ -37,13 +40,13 @@ def resolve_data_contract(
37
40
 
38
41
 
39
42
  def resolve_data_contract_from_location(
40
- location, schema_location: str = None, inline_definitions: bool = False, include_quality: bool = True
43
+ location, schema_location: str = None, inline_definitions: bool = False, inline_quality: bool = False
41
44
  ) -> DataContractSpecification:
42
45
  if location.startswith("http://") or location.startswith("https://"):
43
46
  data_contract_str = fetch_resource(location)
44
47
  else:
45
48
  data_contract_str = read_file(location)
46
- return resolve_data_contract_from_str(data_contract_str, schema_location, inline_definitions, include_quality)
49
+ return resolve_data_contract_from_str(data_contract_str, schema_location, inline_definitions, inline_quality)
47
50
 
48
51
 
49
52
  def inline_definitions_into_data_contract(spec: DataContractSpecification):
@@ -117,7 +120,7 @@ def get_quality_ref_file(quality_spec: str | object) -> str | object:
117
120
 
118
121
 
119
122
  def resolve_data_contract_from_str(
120
- data_contract_str, schema_location: str = None, inline_definitions: bool = False, include_quality: bool = False
123
+ data_contract_str, schema_location: str = None, inline_definitions: bool = False, inline_quality: bool = False
121
124
  ) -> DataContractSpecification:
122
125
  data_contract_yaml_dict = to_yaml(data_contract_str)
123
126
  validate(data_contract_yaml_dict, schema_location)
@@ -126,7 +129,7 @@ def resolve_data_contract_from_str(
126
129
 
127
130
  if inline_definitions:
128
131
  inline_definitions_into_data_contract(spec)
129
- if spec.quality and include_quality:
132
+ if spec.quality and inline_quality:
130
133
  resolve_quality_ref(spec.quality)
131
134
 
132
135
  return spec
@@ -63,6 +63,7 @@ class Definition(pyd.BaseModel):
63
63
  class Field(pyd.BaseModel):
64
64
  ref: str = pyd.Field(default=None, alias="$ref")
65
65
  ref_obj: Definition = pyd.Field(default=None, exclude=True)
66
+ title: str = None
66
67
  type: str = None
67
68
  format: str = None
68
69
  required: bool = None
@@ -95,6 +96,7 @@ class Model(pyd.BaseModel):
95
96
  class Info(pyd.BaseModel):
96
97
  title: str = None
97
98
  version: str = None
99
+ status: str = None
98
100
  description: str = None
99
101
  owner: str = None
100
102
  contact: Contact = None
@@ -19,7 +19,7 @@
19
19
  <div class="flex">
20
20
  <div class="flex flex-shrink-0 items-center mr-6">
21
21
  <a class="text-xl text-gray-900 font-semibold" href="/">
22
- Data Contract
22
+ Data Contracts
23
23
  </a>
24
24
  </div>
25
25
  </div>
@@ -34,7 +34,7 @@
34
34
 
35
35
  <div class="pt-5 mx-auto max-w-7xl sm:px-6 lg:px-8">
36
36
  <div>
37
- <div class="lg:flex lg:items-center lg:justify-between px-4 sm:px-0">
37
+ <div class="md:flex md:items-center md:justify-between px-4 sm:px-0">
38
38
  <div class="min-w-0 flex-1">
39
39
  <h2 class="text-2xl font-bold leading-7 text-gray-900 sm:truncate sm:text-3xl sm:tracking-tight">
40
40
  Data Contract</h2>
@@ -47,22 +47,17 @@
47
47
  type="button"
48
48
  onclick="document.getElementById('dialog-datacontract-yaml').showModal()"
49
49
  class="inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
50
- <svg class="-ml-0.5 mr-1.5 h-5 w-5 text-gray-600" viewBox="-0.5 -0.5 24 24" xmlns="http://www.w3.org/2000/svg">
50
+ <svg class="-ml-0.5 mr-1.5 h-5 w-5 text-gray-600" viewBox="-0.5 -0.5 24 24">
51
51
  <path d="m4.3125 8.145833333333334 9.104166666666668 0" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path><path d="m4.3125 11.020833333333334 9.104166666666668 0" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path><path d="m4.3125 5.270833333333334 6.708333333333334 0" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path><path d="m4.3125 13.895833333333334 7.1875 0" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path><path d="m4.3125 16.770833333333336 3.8333333333333335 0" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path><path d="M8.145833333333334 22.520833333333336h-6.708333333333334a0.9583333333333334 0.9583333333333334 0 0 1 -0.9583333333333334 -0.9583333333333334v-20.125a0.9583333333333334 0.9583333333333334 0 0 1 0.9583333333333334 -0.9583333333333334h12.739125a0.9583333333333334 0.9583333333333334 0 0 1 0.6775416666666667 0.28079166666666666L18.406708333333334 4.3125a0.9583333333333334 0.9583333333333334 0 0 1 0.28079166666666666 0.6775416666666667V8.145833333333334" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path><path d="m15.045833333333333 21.370833333333334 -4.025 1.15 1.15 -4.025 6.879875 -6.879875a2.032625 2.032625 0 0 1 2.875 2.875Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path><path d="m18.188208333333332 12.478458333333334 2.875 2.875" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path><path d="m12.170833333333333 18.495833333333334 2.875 2.875" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path>
52
52
  </svg>
53
53
  Show YAML
54
54
  </button>
55
55
  </div>
56
56
  </div>
57
-
58
-
59
57
  </div>
60
58
 
61
59
  <div>
62
-
63
60
  <div class="space-y-6 mt-6">
64
-
65
-
66
61
  <section>
67
62
  <div class=" px-4 sm:px-0">
68
63
  <h1 class="text-base font-semibold leading-6 text-gray-900" id="info">Info</h1>
@@ -83,6 +78,13 @@
83
78
  <dd class="mt-1 text-sm text-gray-900">{{ datacontract.info.version }}</dd>
84
79
  </div>
85
80
 
81
+ {% if datacontract.info.status %}
82
+ <div class="sm:col-span-1">
83
+ <dt class="text-sm font-medium text-gray-500">Status</dt>
84
+ <dd class="mt-1 text-sm text-gray-900">{{ datacontract.info.status }}</dd>
85
+ </div>
86
+ {% endif %}
87
+
86
88
  {% if datacontract.info.description %}
87
89
  <div class="sm:col-span-2">
88
90
  <dt class="text-sm font-medium text-gray-500">Description</dt>
@@ -358,7 +360,7 @@
358
360
  <table class="min-w-full divide-y divide-gray-300">
359
361
  <thead class="bg-gray-50">
360
362
  <tr>
361
- <th scope="colgroup" colspan="4" class="py-2 pl-4 pr-3 text-left font-semibold text-gray-900 sm:pl-6">
363
+ <th scope="colgroup" colspan="3" class="py-2 pl-4 pr-3 text-left font-semibold text-gray-900 sm:pl-6">
362
364
  <span>{{ model_name }}</span>
363
365
  <span class="inline-flex items-center rounded-md bg-gray-50 px-2 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10">{{ model.type }}</span>
364
366
  <div class="text-sm font-medium text-gray-500">{{ model.description }}</div>
@@ -371,28 +373,81 @@
371
373
  {% for field_name, field in model.fields.items() %}
372
374
 
373
375
  <tr>
374
- <td class="whitespace-nowrap py-2 pl-4 pr-2 text-sm font-medium text-gray-900 sm:pl-6 w-3/12">
376
+ <td class="whitespace-nowrap py-2 pl-4 pr-2 text-sm font-medium text-gray-900 sm:pl-6 w-2/12">
375
377
  <div class="py-2 text-sm">
376
- {{ field_name }}
378
+ {% if field.title %}
379
+ <div>{{ field.title }}</div>
380
+ {% endif %}
381
+ <div class="font-mono">{{ field_name }}</div>
377
382
  {# TODO nested fields #}
378
383
  </div>
379
384
  </td>
380
- <td class="whitespace-nowrap px-1 py-2 text-sm text-gray-500 w-16">
381
- {% if field.required %}
382
- <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10" title="required">R</span>
383
- {% endif %}
384
- {% if field.unique %}
385
- <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10" title="unique">U</span>
386
- {% endif %}
387
- </td>
388
385
  <td class="whitespace-nowrap px-1 py-2 text-sm text-gray-500 w-1/12">
389
386
  {% if field.type %}
390
387
  {{ field.type }}
391
388
  {% endif %}
392
389
  </td>
393
390
  <td class="px-3 py-2 text-sm text-gray-500 w-7/12">
394
- <div class="text-gray-400">{{ field.description or "No description" }}</div>
395
- {# TODO add format information #}
391
+ {% if field.description %}
392
+ <div class="text-gray-500">{{ field.description }}</div>
393
+ {% else %}
394
+ <div class="text-gray-400">No description</div>
395
+ {% endif %}
396
+
397
+ {% if field.example %}
398
+ <div class="mt-1 italic">
399
+ Example: {{ field.example }}
400
+ </div>
401
+ {% endif %}
402
+
403
+ <div>
404
+ {% if field.primary %}
405
+ <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">primary</span>
406
+ {% endif %}
407
+ {% if field.required %}
408
+ <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">required</span>
409
+ {% endif %}
410
+ {% if field.unique %}
411
+ <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">unique</span>
412
+ {% endif %}
413
+ {% if field.format %}
414
+ <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">format:{{ field.format }}</span>
415
+ {% endif %}
416
+ {% if field.minLength %}
417
+ <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">minLength:{{ field.minLength }}</span>
418
+ {% endif %}
419
+ {% if field.maxLength %}
420
+ <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">maxLength:{{ field.maxLength }}</span>
421
+ {% endif %}
422
+ {% if field.pattern %}
423
+ <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">pattern:{{ field.pattern }}</span>
424
+ {% endif %}
425
+ {% if field.precision %}
426
+ <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">precision:{{ field.precision }}</span>
427
+ {% endif %}
428
+ {% if field.scale %}
429
+ <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">scale:{{ field.scale }}</span>
430
+ {% endif %}
431
+ {% if field.minimum %}
432
+ <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">minimum:{{ field.minimum }}</span>
433
+ {% endif %}
434
+ {% if field.exclusiveMinimum %}
435
+ <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">exclusiveMinimum:{{ field.exclusiveMinimum }}</span>
436
+ {% endif %}
437
+ {% if field.maximum %}
438
+ <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">maximum:{{ field.maximum }}</span>
439
+ {% endif %}
440
+ {% if field.exclusiveMaximum %}
441
+ <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">exclusiveMaximum:{{ field.exclusiveMaximum }}</span>
442
+ {% endif %}
443
+ {% if field.classification %}
444
+ <span class="inline-flex items-center rounded-md bg-blue-50 px-1 py-1 text-xs font-medium text-blue-600 ring-1 ring-inset ring-blue-500/10 mr-1 mt-1">{{ field.classification }}</span>
445
+ {% endif %}
446
+ {% if field.pii %}
447
+ <span class="inline-flex items-center rounded-md bg-yellow-50 px-1 py-1 text-xs font-medium text-yellow-600 ring-1 ring-inset ring-yellow-500/10 mr-1 mt-1">PII</span>
448
+ {% endif %}
449
+ </div>
450
+
396
451
  </td>
397
452
 
398
453
  </tr>
@@ -0,0 +1,168 @@
1
+ <!doctype html>
2
+ <html class="h-full bg-gray-100" lang="en">
3
+ <head>
4
+ <title>Data Contract</title>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ {# <script src="https://cdn.tailwindcss.com"></script> #}
8
+ <style>
9
+ {{style | safe }}
10
+ </style>
11
+ </head>
12
+ <body class="h-full">
13
+
14
+ <div class="min-h-full flex flex-col">
15
+
16
+ <nav class="bg-white shadow-sm">
17
+ <div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
18
+ <div class="flex h-16 justify-between">
19
+ <div class="flex">
20
+ <div class="flex flex-shrink-0 items-center mr-6">
21
+ <a class="text-xl text-gray-900 font-semibold" href="/">
22
+ Data Contracts
23
+ </a>
24
+ </div>
25
+ </div>
26
+ <div class="hidden sm:ml-6 sm:flex sm:items-center">
27
+ <a href="https://datacontract.com" class="text-sky-500 hover:text-gray-700 text-sm font-semibold" target="_blank">datacontract.com</a>
28
+ </div>
29
+ </div>
30
+ </div>
31
+ </nav>
32
+
33
+ <main class="pb-7">
34
+
35
+ <div class="pt-5 mx-auto max-w-7xl sm:px-6 lg:px-8">
36
+ <div>
37
+ <div class="lg:flex lg:items-center lg:justify-between px-4 sm:px-0">
38
+ <div class="min-w-0 flex-1">
39
+ <h2 class="text-2xl font-bold leading-7 text-gray-900 sm:truncate sm:text-3xl sm:tracking-tight">
40
+ Data Contract Catalog</h2>
41
+ </div>
42
+ </div>
43
+
44
+
45
+ </div>
46
+
47
+ <div>
48
+
49
+ <div class="space-y-6 mt-6">
50
+
51
+ <section id="catalog">
52
+
53
+ {# TODO search and filter form #}
54
+
55
+ <ul role="list" class="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 ">
56
+
57
+ {% for contract in contracts %}
58
+
59
+ <li class="col-span-1 rounded-lg bg-white shadow hover:bg-gray-50">
60
+ <a href="{{contract.html_link}}" >
61
+ <div class="flex w-full justify-between space-x-1 p-6 pb-4">
62
+ <div class="flex-1 truncate">
63
+ <div class="flex items-center space-x-3">
64
+ <h3 class="truncate text-sm font-medium text-gray-900">{{contract.spec.info.title}}</h3>
65
+ </div>
66
+ <div class="flex flex-wrap mt-1 text-sm text-gray-500 gap-1">
67
+ {% if contract.spec.info.owner %}
68
+ <div class="flex items-center text-sm text-gray-500">
69
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.25" stroke="currentColor" class="w-4 h-4 mr-1.5">
70
+ <path stroke-linecap="round" stroke-linejoin="round" d="M18 18.72a9.094 9.094 0 003.741-.479 3 3 0 00-4.682-2.72m.94 3.198l.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0112 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 016 18.719m12 0a5.971 5.971 0 00-.941-3.197m0 0A5.995 5.995 0 0012 12.75a5.995 5.995 0 00-5.058 2.772m0 0a3 3 0 00-4.681 2.72 8.986 8.986 0 003.74.477m.94-3.197a5.971 5.971 0 00-.94 3.197M15 6.75a3 3 0 11-6 0 3 3 0 016 0zm6 3a2.25 2.25 0 11-4.5 0 2.25 2.25 0 014.5 0zm-13.5 0a2.25 2.25 0 11-4.5 0 2.25 2.25 0 014.5 0z" />
71
+ </svg>
72
+ <span>{{contract.spec.info.owner}}</span>
73
+ </div>
74
+ {% endif %}
75
+ </div>
76
+
77
+ </div>
78
+ <div class="h-10 w-10 flex-shrink-0 rounded-full">
79
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g><path d="M21.14 6.94a.77.77 0 0 0-.48.2c-1-.8-2.14-.25-3 .72A16.12 16.12 0 0 0 16.15 10a.28.28 0 0 0 .4.32c.08 0 1.39-1.21 1.47-1.28.73-.68 1.35-1.42 1.81-1.48s.32 0 .41.09a19 19 0 0 0-2.07 2.81c0 .12-.31 0 1.53 1.71l.27.24C19 13.57 16 16.73 15.74 17a2.66 2.66 0 0 1-1 .43 3.72 3.72 0 0 1-.22-1.52L17.7 12a.3.3 0 0 0-.47-.37c-.72.88-3.45 3.39-3.69 3.91a4 4 0 0 0 .28 2.62 1 1 0 0 0 .93.32 4.26 4.26 0 0 0 1.76-.65c.6-.62 3.86-4.79 4.65-5.31a20 20 0 0 0 1.77-1.64 4.67 4.67 0 0 0 1-1.37c.5-1.57-1.82-2.66-2.79-2.57Zm1.66 2.33a12.9 12.9 0 0 1-1.58 1.88c-.91 1-.65.74-1 .46-1.52-1.26-1.33-1-1.27-1.21l2-2.16c.34-.38-.06-.45.7-.15.44.16 1.43.63 1.15 1.18Z" fill="#020202" fill-rule="evenodd"></path><path d="M7.2 22.53c-1.48-.25-1.48-2.11-1.61-3.53a40 40 0 0 1 .15-6.57c.18-2.46.6-2.25.59-5.51 0-1.73-.33-4.06-1.79-5a40.29 40.29 0 0 1 6.24.08c2.64.18 5.71-.14 6.91.63C19.23 3.63 18.12 6 19 6a.32.32 0 0 0 .31-.36c-.06-1.31.24-2.44-.81-3.44A5.82 5.82 0 0 0 14.76 1a75.46 75.46 0 0 0-8.57 0C5.77 1 1.6 1.5 1 2.08A3.17 3.17 0 0 0 0 4.5 4.61 4.61 0 0 0 .72 7a1.92 1.92 0 0 0 .93.62c1 .31 3.24.25 2.86-.55C4.4 6.8 3.19 7 3.11 7a2.35 2.35 0 0 1-1.77-.56 3.77 3.77 0 0 1-.48-2 2.31 2.31 0 0 1 .76-1.73 3.54 3.54 0 0 1 1.27-.31c1.11 0 1.64.66 2 1.73a14.13 14.13 0 0 1 .3 4.46 33 33 0 0 0-.55 7c0 1.43.19 5 .84 6.22a2.1 2.1 0 0 0 1.67 1.24.3.3 0 0 0 .05-.52Z" fill="#020202" fill-rule="evenodd"></path><path d="M21.85 19.54a8 8 0 0 1-1.71-3.19.29.29 0 1 0-.57.15c.75 3.33 2.18 4 2.79 4.79-.34.08-13.26 1.1-14 1a.33.33 0 1 0-.09.66c1.61.26 10.59-.22 13.1-.49a3 3 0 0 0 2-.65c.63-.67-.71-1.47-1.52-2.27Z" fill="#020202" fill-rule="evenodd"></path><path d="M9.67 16.86c.39 0 .46.84.5 1.26 0 .13-.07.78.35.95a.51.51 0 0 0 .45 0c1.63-.85.93-.18 1.46-.18.68 0 .56-1.39-1.25-1 0-1.24-.34-2.29-1.59-2.2a2.75 2.75 0 0 0-2.18 1.81 3.92 3.92 0 0 0-.34 1.05c.11 1.84.86-1.68 2.6-1.69Z" fill="#0c6fff" fill-rule="evenodd"></path><path d="M8.57 8.41c5.28.19 2.32 0 6.08 0a.34.34 0 0 0 .35-.35.47.47 0 0 0-.39-.37c-.28-.06-2.1-.3-2.94-.33a17.84 17.84 0 0 0-3.84.48.31.31 0 0 0 .2.53c.09.02.48.04.54.04Z" fill="#0c6fff" fill-rule="evenodd"></path><path d="M13.22 11.64c-5.2-.15-5.49.12-5.57.34a.3.3 0 0 0 .17.38 1.23 1.23 0 0 0 .44.1c.84.06 7.28.38 7.24-.42-.03-.58-1.37-.33-2.28-.4Z" fill="#0c6fff" fill-rule="evenodd"></path></g></svg>
80
+ </div>
81
+ </div>
82
+ <div class="flex w-full items-center justify-between px-6 pb-6">
83
+ <p class="text-sm text-gray-500 line-clamp-3">
84
+ {{contract.spec.info.description}}
85
+ </p>
86
+ </div>
87
+
88
+ </a>
89
+ </li>
90
+ {% endfor %}
91
+ </ul>
92
+
93
+ {% if contracts_size == 0 %}
94
+ <p>The data contract catalog is empty.</p>
95
+ <p>
96
+ Learn more on data contracts on <a href="http://datacontract.com" class="text-sky-500 hover:text-gray-700 text-sm font-semibold">http://datacontract.com</a>.
97
+ </p>
98
+ {% endif %}
99
+
100
+
101
+ </section>
102
+
103
+ </div>
104
+
105
+ </div>
106
+
107
+ <div class="mt-6 text-sm text-gray-400">
108
+ Created at {{formatted_date}} with <a href="https://cli.datacontract.com" class="text-gray-400 hover:text-gray-500">Data Contract CLI</a> v{{datacontract_cli_version}}
109
+ </div>
110
+
111
+ </div>
112
+ </main>
113
+
114
+ <dialog id="dialog-datacontract-yaml" class="relative z-10" aria-labelledby="modal-title" aria-modal="true">
115
+ <div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity"></div>
116
+
117
+ <div class="fixed inset-0 z-10 w-screen overflow-y-auto">
118
+ <div class="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
119
+ <div class="relative transform rounded-lg bg-white px-4 pb-4 pt-5 text-left shadow-xl transition-all sm:my-8 sm:w-4/5 sm:p-6">
120
+ <div class="absolute right-0 top-0 pr-4 pt-4">
121
+ <button type="button" onclick="document.getElementById('dialog-datacontract-yaml').close()" class="rounded-md bg-white text-gray-400 hover:text-gray-500">
122
+ <span class="sr-only">Close</span>
123
+ <svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
124
+ <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
125
+ </svg>
126
+ </button>
127
+ </div>
128
+ <div>
129
+ <div class="mt-3 mb-3 text-center sm:mt-5">
130
+
131
+ <h3 class="text-base font-semibold leading-6 text-gray-900" id="modal-title">Data Contract YAML</h3>
132
+ </div>
133
+ <pre class="overflow-x-auto text-sm bg-gray-50 p-4"><code>{{datacontract_yaml}}</code></pre>
134
+ </div>
135
+ <div class="mt-5 sm:mt-6">
136
+ <button type="button" onclick="document.getElementById('dialog-datacontract-yaml').close()"
137
+ class="inline-flex w-full justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">Close</button>
138
+ </div>
139
+ </div>
140
+ </div>
141
+ </div>
142
+ </dialog>
143
+
144
+
145
+ <footer class="bg-white mt-auto text-sm text-gray-400">
146
+ <div class="mx-auto max-w-7xl py-5 px-6 md:flex md:items-center md:justify-between lg:px-8">
147
+ <div class="flex justify-center space-x-6 md:order-2">
148
+ <div>
149
+ <a href="https://cli.datacontract.com" class="text-gray-400 hover:text-gray-500 px-2">Data Contract CLI</a>
150
+
151
+ <a href="https://datacontract.com" class="text-gray-400 hover:text-gray-500 px-2">Data Contract Specification</a>
152
+ </div>
153
+
154
+
155
+ </div>
156
+ <div class="mt-8 md:order-1 md:mt-0">
157
+ <p class="text-center leading-5 text-gray-400">
158
+ Supported with ❤️ by <a href="https://datamesh-manager.com" class="text-gray-400 hover:text-gray-500">Data Mesh Manager</a>
159
+ </p>
160
+ </div>
161
+ </div>
162
+
163
+ </footer>
164
+
165
+ </div>
166
+
167
+ </body>
168
+ </html>
@@ -594,6 +594,10 @@ video {
594
594
  z-index: 10;
595
595
  }
596
596
 
597
+ .col-span-1 {
598
+ grid-column: span 1 / span 1;
599
+ }
600
+
597
601
  .-mx-4 {
598
602
  margin-left: -1rem;
599
603
  margin-right: -1rem;
@@ -661,6 +665,13 @@ video {
661
665
  margin-top: auto;
662
666
  }
663
667
 
668
+ .line-clamp-3 {
669
+ overflow: hidden;
670
+ display: -webkit-box;
671
+ -webkit-box-orient: vertical;
672
+ -webkit-line-clamp: 3;
673
+ }
674
+
664
675
  .inline-block {
665
676
  display: inline-block;
666
677
  }
@@ -689,10 +700,18 @@ video {
689
700
  display: none;
690
701
  }
691
702
 
703
+ .h-10 {
704
+ height: 2.5rem;
705
+ }
706
+
692
707
  .h-16 {
693
708
  height: 4rem;
694
709
  }
695
710
 
711
+ .h-4 {
712
+ height: 1rem;
713
+ }
714
+
696
715
  .h-5 {
697
716
  height: 1.25rem;
698
717
  }
@@ -713,12 +732,16 @@ video {
713
732
  width: 8.333333%;
714
733
  }
715
734
 
716
- .w-16 {
717
- width: 4rem;
735
+ .w-10 {
736
+ width: 2.5rem;
737
+ }
738
+
739
+ .w-2\/12 {
740
+ width: 16.666667%;
718
741
  }
719
742
 
720
- .w-3\/12 {
721
- width: 25%;
743
+ .w-4 {
744
+ width: 1rem;
722
745
  }
723
746
 
724
747
  .w-5 {
@@ -773,6 +796,10 @@ video {
773
796
  flex-direction: column;
774
797
  }
775
798
 
799
+ .flex-wrap {
800
+ flex-wrap: wrap;
801
+ }
802
+
776
803
  .items-end {
777
804
  align-items: flex-end;
778
805
  }
@@ -789,10 +816,18 @@ video {
789
816
  justify-content: space-between;
790
817
  }
791
818
 
819
+ .gap-1 {
820
+ gap: 0.25rem;
821
+ }
822
+
792
823
  .gap-3 {
793
824
  gap: 0.75rem;
794
825
  }
795
826
 
827
+ .gap-6 {
828
+ gap: 1.5rem;
829
+ }
830
+
796
831
  .gap-x-4 {
797
832
  -moz-column-gap: 1rem;
798
833
  column-gap: 1rem;
@@ -807,6 +842,18 @@ video {
807
842
  row-gap: 1.5rem;
808
843
  }
809
844
 
845
+ .space-x-1 > :not([hidden]) ~ :not([hidden]) {
846
+ --tw-space-x-reverse: 0;
847
+ margin-right: calc(0.25rem * var(--tw-space-x-reverse));
848
+ margin-left: calc(0.25rem * calc(1 - var(--tw-space-x-reverse)));
849
+ }
850
+
851
+ .space-x-3 > :not([hidden]) ~ :not([hidden]) {
852
+ --tw-space-x-reverse: 0;
853
+ margin-right: calc(0.75rem * var(--tw-space-x-reverse));
854
+ margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse)));
855
+ }
856
+
810
857
  .space-x-6 > :not([hidden]) ~ :not([hidden]) {
811
858
  --tw-space-x-reverse: 0;
812
859
  margin-right: calc(1.5rem * var(--tw-space-x-reverse));
@@ -852,6 +899,12 @@ video {
852
899
  overflow-y: auto;
853
900
  }
854
901
 
902
+ .truncate {
903
+ overflow: hidden;
904
+ text-overflow: ellipsis;
905
+ white-space: nowrap;
906
+ }
907
+
855
908
  .whitespace-nowrap {
856
909
  white-space: nowrap;
857
910
  }
@@ -860,6 +913,10 @@ video {
860
913
  white-space: pre-wrap;
861
914
  }
862
915
 
916
+ .rounded-full {
917
+ border-radius: 9999px;
918
+ }
919
+
863
920
  .rounded-lg {
864
921
  border-radius: 0.5rem;
865
922
  }
@@ -868,6 +925,11 @@ video {
868
925
  border-radius: 0.375rem;
869
926
  }
870
927
 
928
+ .bg-blue-50 {
929
+ --tw-bg-opacity: 1;
930
+ background-color: rgb(239 246 255 / var(--tw-bg-opacity));
931
+ }
932
+
871
933
  .bg-gray-100 {
872
934
  --tw-bg-opacity: 1;
873
935
  background-color: rgb(243 244 246 / var(--tw-bg-opacity));
@@ -893,6 +955,11 @@ video {
893
955
  background-color: rgb(255 255 255 / var(--tw-bg-opacity));
894
956
  }
895
957
 
958
+ .bg-yellow-50 {
959
+ --tw-bg-opacity: 1;
960
+ background-color: rgb(254 252 232 / var(--tw-bg-opacity));
961
+ }
962
+
896
963
  .bg-opacity-75 {
897
964
  --tw-bg-opacity: 0.75;
898
965
  }
@@ -901,6 +968,10 @@ video {
901
968
  padding: 1rem;
902
969
  }
903
970
 
971
+ .p-6 {
972
+ padding: 1.5rem;
973
+ }
974
+
904
975
  .px-1 {
905
976
  padding-left: 0.25rem;
906
977
  padding-right: 0.25rem;
@@ -945,6 +1016,10 @@ video {
945
1016
  padding-bottom: 1rem;
946
1017
  }
947
1018
 
1019
+ .pb-6 {
1020
+ padding-bottom: 1.5rem;
1021
+ }
1022
+
948
1023
  .pb-7 {
949
1024
  padding-bottom: 1.75rem;
950
1025
  }
@@ -985,6 +1060,10 @@ video {
985
1060
  vertical-align: middle;
986
1061
  }
987
1062
 
1063
+ .font-mono {
1064
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
1065
+ }
1066
+
988
1067
  .text-2xl {
989
1068
  font-size: 1.5rem;
990
1069
  line-height: 2rem;
@@ -1022,6 +1101,10 @@ video {
1022
1101
  font-weight: 600;
1023
1102
  }
1024
1103
 
1104
+ .italic {
1105
+ font-style: italic;
1106
+ }
1107
+
1025
1108
  .leading-5 {
1026
1109
  line-height: 1.25rem;
1027
1110
  }
@@ -1034,6 +1117,11 @@ video {
1034
1117
  line-height: 1.75rem;
1035
1118
  }
1036
1119
 
1120
+ .text-blue-600 {
1121
+ --tw-text-opacity: 1;
1122
+ color: rgb(37 99 235 / var(--tw-text-opacity));
1123
+ }
1124
+
1037
1125
  .text-gray-400 {
1038
1126
  --tw-text-opacity: 1;
1039
1127
  color: rgb(156 163 175 / var(--tw-text-opacity));
@@ -1064,6 +1152,11 @@ video {
1064
1152
  color: rgb(255 255 255 / var(--tw-text-opacity));
1065
1153
  }
1066
1154
 
1155
+ .text-yellow-600 {
1156
+ --tw-text-opacity: 1;
1157
+ color: rgb(202 138 4 / var(--tw-text-opacity));
1158
+ }
1159
+
1067
1160
  .shadow {
1068
1161
  --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
1069
1162
  --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
@@ -1097,6 +1190,10 @@ video {
1097
1190
  --tw-ring-color: rgb(0 0 0 / var(--tw-ring-opacity));
1098
1191
  }
1099
1192
 
1193
+ .ring-blue-500\/10 {
1194
+ --tw-ring-color: rgb(59 130 246 / 0.1);
1195
+ }
1196
+
1100
1197
  .ring-gray-300 {
1101
1198
  --tw-ring-opacity: 1;
1102
1199
  --tw-ring-color: rgb(209 213 219 / var(--tw-ring-opacity));
@@ -1110,10 +1207,18 @@ video {
1110
1207
  --tw-ring-color: rgb(17 24 39 / 0.05);
1111
1208
  }
1112
1209
 
1210
+ .ring-yellow-500\/10 {
1211
+ --tw-ring-color: rgb(234 179 8 / 0.1);
1212
+ }
1213
+
1113
1214
  .ring-opacity-5 {
1114
1215
  --tw-ring-opacity: 0.05;
1115
1216
  }
1116
1217
 
1218
+ .filter {
1219
+ filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
1220
+ }
1221
+
1117
1222
  .transition-all {
1118
1223
  transition-property: all;
1119
1224
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
@@ -1317,6 +1422,10 @@ video {
1317
1422
  display: flex;
1318
1423
  }
1319
1424
 
1425
+ .lg\:grid-cols-3 {
1426
+ grid-template-columns: repeat(3, minmax(0, 1fr));
1427
+ }
1428
+
1320
1429
  .lg\:items-center {
1321
1430
  align-items: center;
1322
1431
  }