datalex-cli 0.1.1__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.
Files changed (64) hide show
  1. datalex_cli/__init__.py +1 -0
  2. datalex_cli/datalex_cli.py +658 -0
  3. datalex_cli/main.py +2925 -0
  4. datalex_cli-0.1.1.dist-info/METADATA +228 -0
  5. datalex_cli-0.1.1.dist-info/RECORD +64 -0
  6. datalex_cli-0.1.1.dist-info/WHEEL +5 -0
  7. datalex_cli-0.1.1.dist-info/entry_points.txt +2 -0
  8. datalex_cli-0.1.1.dist-info/licenses/LICENSE +21 -0
  9. datalex_cli-0.1.1.dist-info/top_level.txt +2 -0
  10. datalex_core/__init__.py +94 -0
  11. datalex_core/_schemas/datalex/common.schema.json +127 -0
  12. datalex_core/_schemas/datalex/domain.schema.json +24 -0
  13. datalex_core/_schemas/datalex/entity.schema.json +158 -0
  14. datalex_core/_schemas/datalex/model.schema.json +141 -0
  15. datalex_core/_schemas/datalex/policy.schema.json +70 -0
  16. datalex_core/_schemas/datalex/project.schema.json +82 -0
  17. datalex_core/_schemas/datalex/snippet.schema.json +24 -0
  18. datalex_core/_schemas/datalex/source.schema.json +104 -0
  19. datalex_core/_schemas/datalex/term.schema.json +30 -0
  20. datalex_core/canonical.py +166 -0
  21. datalex_core/completion.py +204 -0
  22. datalex_core/connectors/__init__.py +39 -0
  23. datalex_core/connectors/base.py +417 -0
  24. datalex_core/connectors/bigquery.py +229 -0
  25. datalex_core/connectors/databricks.py +262 -0
  26. datalex_core/connectors/mysql.py +266 -0
  27. datalex_core/connectors/postgres.py +309 -0
  28. datalex_core/connectors/redshift.py +298 -0
  29. datalex_core/connectors/snowflake.py +336 -0
  30. datalex_core/connectors/sqlserver.py +425 -0
  31. datalex_core/datalex/__init__.py +26 -0
  32. datalex_core/datalex/diff.py +188 -0
  33. datalex_core/datalex/errors.py +85 -0
  34. datalex_core/datalex/loader.py +512 -0
  35. datalex_core/datalex/migrate_layout.py +382 -0
  36. datalex_core/datalex/parse_cache.py +102 -0
  37. datalex_core/datalex/project.py +214 -0
  38. datalex_core/datalex/types.py +224 -0
  39. datalex_core/dbt/__init__.py +18 -0
  40. datalex_core/dbt/emit.py +344 -0
  41. datalex_core/dbt/manifest.py +329 -0
  42. datalex_core/dbt/profiles.py +185 -0
  43. datalex_core/dbt/sync.py +279 -0
  44. datalex_core/dbt/warehouse.py +215 -0
  45. datalex_core/dialects/__init__.py +15 -0
  46. datalex_core/dialects/_common.py +48 -0
  47. datalex_core/dialects/base.py +47 -0
  48. datalex_core/dialects/postgres.py +164 -0
  49. datalex_core/dialects/registry.py +36 -0
  50. datalex_core/dialects/snowflake.py +129 -0
  51. datalex_core/diffing.py +358 -0
  52. datalex_core/docs_generator.py +797 -0
  53. datalex_core/doctor.py +181 -0
  54. datalex_core/generators.py +478 -0
  55. datalex_core/importers.py +1176 -0
  56. datalex_core/issues.py +23 -0
  57. datalex_core/loader.py +21 -0
  58. datalex_core/migrate.py +316 -0
  59. datalex_core/modeling.py +679 -0
  60. datalex_core/packages.py +430 -0
  61. datalex_core/policy.py +1037 -0
  62. datalex_core/resolver.py +456 -0
  63. datalex_core/schema.py +54 -0
  64. datalex_core/semantic.py +1561 -0
@@ -0,0 +1,158 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://duckcode.dev/schemas/datalex/entity.schema.json",
4
+ "title": "DataLex entity",
5
+ "type": "object",
6
+ "required": ["kind", "name", "columns"],
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "kind": { "const": "entity" },
10
+ "name": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
11
+ "previous_name": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
12
+ "layer": {
13
+ "type": "string",
14
+ "enum": ["conceptual", "logical", "physical"],
15
+ "description": "Required. Conceptual: business view. Logical: attributes/types. Physical: DBMS-specific DDL target."
16
+ },
17
+ "logical": {
18
+ "type": "string",
19
+ "description": "At physical layer: back-reference to the logical entity name this physical implements.",
20
+ "pattern": "^[a-z][a-z0-9_]*$"
21
+ },
22
+ "dialect": {
23
+ "type": "string",
24
+ "pattern": "^[a-z][a-z0-9_]*$",
25
+ "description": "Required at physical layer. Names the dialect plugin that owns emission."
26
+ },
27
+ "database": { "type": "string" },
28
+ "schema": { "type": "string" },
29
+ "physical_name": { "type": "string" },
30
+ "description": { "type": "string" },
31
+ "owner": { "type": "string" },
32
+ "domain": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
33
+ "subject_area": { "type": "string" },
34
+ "tags": {
35
+ "type": "array",
36
+ "items": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" }
37
+ },
38
+ "terms": {
39
+ "type": "array",
40
+ "items": { "type": "string", "pattern": "^(term:)?[a-z][a-z0-9_]*$" }
41
+ },
42
+ "raw_ddl": { "type": "string" },
43
+ "columns": {
44
+ "type": "array",
45
+ "minItems": 1,
46
+ "items": { "$ref": "#/$defs/column" }
47
+ },
48
+ "indexes": {
49
+ "type": "array",
50
+ "items": {
51
+ "type": "object",
52
+ "required": ["name", "columns"],
53
+ "additionalProperties": false,
54
+ "properties": {
55
+ "name": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
56
+ "previous_name": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
57
+ "columns": {
58
+ "type": "array",
59
+ "minItems": 1,
60
+ "items": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" }
61
+ },
62
+ "unique": { "type": "boolean" },
63
+ "type": { "type": "string", "enum": ["btree", "hash", "gin", "gist", "brin"] }
64
+ }
65
+ }
66
+ },
67
+ "partition_by": {
68
+ "type": "array",
69
+ "items": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" }
70
+ },
71
+ "cluster_by": {
72
+ "type": "array",
73
+ "items": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" }
74
+ },
75
+ "meta": {
76
+ "type": "object",
77
+ "additionalProperties": true
78
+ }
79
+ },
80
+ "$defs": {
81
+ "column": {
82
+ "type": "object",
83
+ "required": ["name", "type"],
84
+ "additionalProperties": false,
85
+ "properties": {
86
+ "name": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
87
+ "previous_name": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
88
+ "type": { "type": "string", "minLength": 1 },
89
+ "physical": {
90
+ "type": "object",
91
+ "additionalProperties": {
92
+ "type": "object",
93
+ "additionalProperties": false,
94
+ "properties": {
95
+ "type": { "type": "string" },
96
+ "raw_ddl": { "type": "string" }
97
+ }
98
+ }
99
+ },
100
+ "logical": { "type": "string" },
101
+ "description": { "type": "string" },
102
+ "nullable": { "type": "boolean" },
103
+ "primary_key": { "type": "boolean" },
104
+ "unique": { "type": "boolean" },
105
+ "default": { "type": ["string", "number", "boolean", "null"] },
106
+ "references": {
107
+ "type": "object",
108
+ "required": ["entity", "column"],
109
+ "additionalProperties": false,
110
+ "properties": {
111
+ "entity": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
112
+ "column": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
113
+ "on_delete": { "type": "string", "enum": ["restrict", "cascade", "set_null", "no_action"] },
114
+ "on_update": { "type": "string", "enum": ["restrict", "cascade", "set_null", "no_action"] },
115
+ "relationship": { "type": "string", "enum": ["many_to_one", "one_to_one", "many_to_many"] }
116
+ }
117
+ },
118
+ "constraints": {
119
+ "type": "array",
120
+ "items": {
121
+ "type": "object",
122
+ "required": ["type"],
123
+ "additionalProperties": true,
124
+ "properties": {
125
+ "type": { "type": "string", "enum": ["check", "not_null", "unique", "primary_key", "foreign_key"] },
126
+ "expression": { "type": "string" }
127
+ }
128
+ }
129
+ },
130
+ "sensitivity": { "type": "string" },
131
+ "terms": {
132
+ "type": "array",
133
+ "items": { "type": "string", "pattern": "^(term:)?[a-z][a-z0-9_]*$" }
134
+ },
135
+ "tags": {
136
+ "type": "array",
137
+ "items": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" }
138
+ },
139
+ "use": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
140
+ "examples": {
141
+ "type": "array",
142
+ "items": { "type": ["string", "number", "boolean", "null"] }
143
+ },
144
+ "deprecated": { "type": "boolean" },
145
+ "meta": {
146
+ "type": "object",
147
+ "additionalProperties": true
148
+ }
149
+ }
150
+ }
151
+ },
152
+ "allOf": [
153
+ {
154
+ "if": { "properties": { "layer": { "const": "physical" } }, "required": ["layer"] },
155
+ "then": { "required": ["dialect"] }
156
+ }
157
+ ]
158
+ }
@@ -0,0 +1,141 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://duckcode.dev/schemas/datalex/model.schema.json",
4
+ "title": "DataLex model (dbt-style transformation / derived table)",
5
+ "type": "object",
6
+ "required": ["kind", "name"],
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "kind": { "const": "model" },
10
+ "name": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
11
+ "previous_name": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
12
+ "description": { "type": "string" },
13
+ "materialization": {
14
+ "type": "string",
15
+ "enum": ["view", "table", "incremental", "ephemeral", "materialized_view", "snapshot"]
16
+ },
17
+ "database": { "type": "string" },
18
+ "schema": { "type": "string" },
19
+ "tags": {
20
+ "type": "array",
21
+ "items": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" }
22
+ },
23
+ "owner": { "type": "string" },
24
+ "domain": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
25
+ "derived_sql": {
26
+ "type": "string",
27
+ "description": "Inline SQL for the transformation. Used for column-level lineage extraction."
28
+ },
29
+ "sql_path": {
30
+ "type": "string",
31
+ "description": "Path to a .sql file (relative to the YAML file) containing the transformation."
32
+ },
33
+ "depends_on": {
34
+ "type": "array",
35
+ "items": {
36
+ "type": "object",
37
+ "maxProperties": 1,
38
+ "minProperties": 1,
39
+ "additionalProperties": false,
40
+ "properties": {
41
+ "ref": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
42
+ "source": {
43
+ "type": "object",
44
+ "required": ["source", "name"],
45
+ "additionalProperties": false,
46
+ "properties": {
47
+ "source": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
48
+ "name": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" }
49
+ }
50
+ }
51
+ }
52
+ }
53
+ },
54
+ "contract": {
55
+ "type": "object",
56
+ "additionalProperties": false,
57
+ "properties": {
58
+ "enforced": { "type": "boolean" }
59
+ }
60
+ },
61
+ "columns": {
62
+ "type": "array",
63
+ "items": {
64
+ "type": "object",
65
+ "required": ["name"],
66
+ "additionalProperties": false,
67
+ "properties": {
68
+ "name": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
69
+ "previous_name": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
70
+ "type": { "type": "string" },
71
+ "description": { "type": "string" },
72
+ "tests": {
73
+ "type": "array",
74
+ "items": {
75
+ "oneOf": [
76
+ { "type": "string", "enum": ["unique", "not_null"] },
77
+ {
78
+ "type": "object",
79
+ "maxProperties": 1,
80
+ "minProperties": 1,
81
+ "additionalProperties": true
82
+ }
83
+ ]
84
+ }
85
+ },
86
+ "constraints": {
87
+ "type": "array",
88
+ "items": {
89
+ "type": "object",
90
+ "required": ["type"],
91
+ "additionalProperties": true,
92
+ "properties": {
93
+ "type": { "type": "string", "enum": ["primary_key", "not_null", "unique", "foreign_key", "check"] }
94
+ }
95
+ }
96
+ },
97
+ "contract": {
98
+ "type": "object",
99
+ "additionalProperties": false,
100
+ "properties": { "enforced": { "type": "boolean" } }
101
+ },
102
+ "sensitivity": { "type": "string" },
103
+ "terms": {
104
+ "type": "array",
105
+ "items": { "type": "string", "pattern": "^(term:)?[a-z][a-z0-9_]*$" }
106
+ },
107
+ "tags": {
108
+ "type": "array",
109
+ "items": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" }
110
+ },
111
+ "meta": { "type": "object", "additionalProperties": true }
112
+ }
113
+ }
114
+ },
115
+ "freshness": {
116
+ "type": "object",
117
+ "additionalProperties": false,
118
+ "properties": {
119
+ "warn_after": {
120
+ "type": "object",
121
+ "required": ["count", "period"],
122
+ "additionalProperties": false,
123
+ "properties": {
124
+ "count": { "type": "integer", "minimum": 1 },
125
+ "period": { "type": "string", "enum": ["minute", "hour", "day"] }
126
+ }
127
+ },
128
+ "error_after": {
129
+ "type": "object",
130
+ "required": ["count", "period"],
131
+ "additionalProperties": false,
132
+ "properties": {
133
+ "count": { "type": "integer", "minimum": 1 },
134
+ "period": { "type": "string", "enum": ["minute", "hour", "day"] }
135
+ }
136
+ }
137
+ }
138
+ },
139
+ "meta": { "type": "object", "additionalProperties": true }
140
+ }
141
+ }
@@ -0,0 +1,70 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://duckcode.dev/schemas/datalex/policy.schema.json",
4
+ "title": "DataLex policy (access / masking / governance rule)",
5
+ "type": "object",
6
+ "required": ["kind", "name", "rule"],
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "kind": { "const": "policy" },
10
+ "name": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
11
+ "description": { "type": "string" },
12
+ "rule": {
13
+ "type": "string",
14
+ "enum": [
15
+ "require_description",
16
+ "require_owner",
17
+ "require_primary_key",
18
+ "require_indexes",
19
+ "require_sla",
20
+ "naming_convention",
21
+ "deprecation_check",
22
+ "column_sensitivity_required",
23
+ "contract_required",
24
+ "custom_expression"
25
+ ]
26
+ },
27
+ "scope": {
28
+ "type": "string",
29
+ "enum": ["entity", "column", "source", "model", "project"],
30
+ "default": "entity"
31
+ },
32
+ "severity": {
33
+ "type": "string",
34
+ "enum": ["info", "warn", "error"],
35
+ "default": "warn"
36
+ },
37
+ "applies_to": {
38
+ "type": "object",
39
+ "description": "Filter which objects the policy applies to.",
40
+ "additionalProperties": true
41
+ },
42
+ "expression": { "type": "string" },
43
+ "grants": {
44
+ "type": "array",
45
+ "description": "For access policies: principals and the privileges they receive.",
46
+ "items": {
47
+ "type": "object",
48
+ "required": ["principal", "privileges"],
49
+ "additionalProperties": false,
50
+ "properties": {
51
+ "principal": { "type": "string" },
52
+ "privileges": {
53
+ "type": "array",
54
+ "minItems": 1,
55
+ "items": { "type": "string", "enum": ["SELECT", "INSERT", "UPDATE", "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER", "USAGE", "ALL"] }
56
+ },
57
+ "on_entities": {
58
+ "type": "array",
59
+ "items": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" }
60
+ }
61
+ }
62
+ }
63
+ },
64
+ "extends": {
65
+ "type": "string",
66
+ "description": "Policy-pack inheritance."
67
+ },
68
+ "meta": { "type": "object", "additionalProperties": true }
69
+ }
70
+ }
@@ -0,0 +1,82 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://duckcode.dev/schemas/datalex/project.schema.json",
4
+ "title": "DataLex project manifest",
5
+ "type": "object",
6
+ "required": ["kind", "name", "version"],
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "kind": { "const": "project" },
10
+ "name": { "type": "string", "minLength": 1 },
11
+ "version": { "type": ["string", "integer"] },
12
+ "description": { "type": "string" },
13
+ "owner": { "type": "string" },
14
+ "dialects": {
15
+ "type": "array",
16
+ "items": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
17
+ "description": "Enabled dialect plugins. Must correspond to modules under datalex_core/dialects/."
18
+ },
19
+ "default_dialect": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
20
+ "glossary": {
21
+ "type": "string",
22
+ "description": "Glob for glossary files, e.g. 'glossary/**/*.yaml'."
23
+ },
24
+ "models": {
25
+ "type": "string",
26
+ "description": "Glob for entity/source/model files, e.g. 'models/**/*.yaml'."
27
+ },
28
+ "sources": {
29
+ "type": "string",
30
+ "description": "Glob for kind:source files, e.g. 'sources/**/*.yaml'. Optional."
31
+ },
32
+ "snippets": {
33
+ "type": "string",
34
+ "description": "Glob for snippet files, default '.datalex/snippets/**/*.yaml'."
35
+ },
36
+ "policies": {
37
+ "type": "string",
38
+ "description": "Glob for policy files."
39
+ },
40
+ "imports": {
41
+ "type": "array",
42
+ "description": "Cross-repo package imports. Resolver fetches packages into ~/.datalex/packages/ and pins them in .datalex/lock.yaml.",
43
+ "items": {
44
+ "type": "object",
45
+ "additionalProperties": false,
46
+ "required": ["package"],
47
+ "properties": {
48
+ "package": {
49
+ "type": "string",
50
+ "description": "Package identifier. Forms: 'org/name', 'org/name@version', or any Git-URL-like string when paired with git:."
51
+ },
52
+ "alias": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
53
+ "path": {
54
+ "type": "string",
55
+ "description": "Local directory (relative to project root or absolute). Mutually exclusive with git:."
56
+ },
57
+ "git": {
58
+ "type": "string",
59
+ "description": "Git URL (https or ssh) to clone for resolution."
60
+ },
61
+ "ref": {
62
+ "type": "string",
63
+ "description": "Git ref — tag, branch, or commit SHA."
64
+ },
65
+ "version": {
66
+ "type": "string",
67
+ "description": "Version override (falls back to parsing 'org/name@version' from package:)."
68
+ },
69
+ "entities": {
70
+ "type": "array",
71
+ "items": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
72
+ "description": "Optional allowlist of entity names to import (default: all)."
73
+ }
74
+ }
75
+ }
76
+ },
77
+ "meta": {
78
+ "type": "object",
79
+ "additionalProperties": true
80
+ }
81
+ }
82
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://duckcode.dev/schemas/datalex/snippet.schema.json",
4
+ "title": "DataLex snippet (reusable YAML fragment)",
5
+ "type": "object",
6
+ "required": ["kind", "name", "apply"],
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "kind": { "const": "snippet" },
10
+ "name": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
11
+ "description": { "type": "string" },
12
+ "targets": {
13
+ "type": "array",
14
+ "description": "Which object kinds this snippet is valid on. Default: column.",
15
+ "items": { "type": "string", "enum": ["entity", "column", "source_column", "model_column"] }
16
+ },
17
+ "apply": {
18
+ "type": "object",
19
+ "description": "Keys merged into the target. Target keys win on conflict unless override=true is set on a key.",
20
+ "additionalProperties": true
21
+ },
22
+ "meta": { "type": "object", "additionalProperties": true }
23
+ }
24
+ }
@@ -0,0 +1,104 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://duckcode.dev/schemas/datalex/source.schema.json",
4
+ "title": "DataLex source (dbt-style external data source)",
5
+ "type": "object",
6
+ "required": ["kind", "name", "tables"],
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "kind": { "const": "source" },
10
+ "name": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
11
+ "previous_name": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
12
+ "description": { "type": "string" },
13
+ "database": { "type": "string" },
14
+ "schema": { "type": "string" },
15
+ "loader": { "type": "string" },
16
+ "loaded_at_field": { "type": "string" },
17
+ "freshness": {
18
+ "type": "object",
19
+ "additionalProperties": false,
20
+ "properties": {
21
+ "warn_after": { "$ref": "#/$defs/duration" },
22
+ "error_after": { "$ref": "#/$defs/duration" },
23
+ "filter": { "type": "string" }
24
+ }
25
+ },
26
+ "owner": { "type": "string" },
27
+ "tags": {
28
+ "type": "array",
29
+ "items": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" }
30
+ },
31
+ "tables": {
32
+ "type": "array",
33
+ "minItems": 1,
34
+ "items": {
35
+ "type": "object",
36
+ "required": ["name"],
37
+ "additionalProperties": false,
38
+ "properties": {
39
+ "name": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
40
+ "previous_name": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
41
+ "description": { "type": "string" },
42
+ "identifier": { "type": "string" },
43
+ "loaded_at_field": { "type": "string" },
44
+ "freshness": {
45
+ "type": "object",
46
+ "additionalProperties": false,
47
+ "properties": {
48
+ "warn_after": { "$ref": "#/$defs/duration" },
49
+ "error_after": { "$ref": "#/$defs/duration" },
50
+ "filter": { "type": "string" }
51
+ }
52
+ },
53
+ "columns": {
54
+ "type": "array",
55
+ "items": {
56
+ "type": "object",
57
+ "required": ["name"],
58
+ "additionalProperties": false,
59
+ "properties": {
60
+ "name": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
61
+ "type": { "type": "string" },
62
+ "description": { "type": "string" },
63
+ "tests": { "$ref": "#/$defs/tests" },
64
+ "tags": {
65
+ "type": "array",
66
+ "items": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" }
67
+ },
68
+ "sensitivity": { "type": "string" },
69
+ "meta": { "type": "object", "additionalProperties": true }
70
+ }
71
+ }
72
+ },
73
+ "meta": { "type": "object", "additionalProperties": true }
74
+ }
75
+ }
76
+ },
77
+ "meta": { "type": "object", "additionalProperties": true }
78
+ },
79
+ "$defs": {
80
+ "duration": {
81
+ "type": "object",
82
+ "required": ["count", "period"],
83
+ "additionalProperties": false,
84
+ "properties": {
85
+ "count": { "type": "integer", "minimum": 1 },
86
+ "period": { "type": "string", "enum": ["minute", "hour", "day"] }
87
+ }
88
+ },
89
+ "tests": {
90
+ "type": "array",
91
+ "items": {
92
+ "oneOf": [
93
+ { "type": "string", "enum": ["unique", "not_null"] },
94
+ {
95
+ "type": "object",
96
+ "maxProperties": 1,
97
+ "minProperties": 1,
98
+ "additionalProperties": true
99
+ }
100
+ ]
101
+ }
102
+ }
103
+ }
104
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://duckcode.dev/schemas/datalex/term.schema.json",
4
+ "title": "DataLex glossary term",
5
+ "type": "object",
6
+ "required": ["kind", "name", "definition"],
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "kind": { "const": "term" },
10
+ "name": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
11
+ "previous_name": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
12
+ "definition": { "type": "string", "minLength": 1 },
13
+ "abbreviation": { "type": "string" },
14
+ "synonyms": {
15
+ "type": "array",
16
+ "items": { "type": "string", "minLength": 1 }
17
+ },
18
+ "steward": { "type": "string" },
19
+ "owner": { "type": "string" },
20
+ "tags": {
21
+ "type": "array",
22
+ "items": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" }
23
+ },
24
+ "related_terms": {
25
+ "type": "array",
26
+ "items": { "type": "string", "pattern": "^(term:)?[a-z][a-z0-9_]*$" }
27
+ },
28
+ "meta": { "type": "object", "additionalProperties": true }
29
+ }
30
+ }