sqlmesh 0.217.1.dev1__py3-none-any.whl → 0.227.2.dev4__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 (183) hide show
  1. sqlmesh/__init__.py +12 -2
  2. sqlmesh/_version.py +2 -2
  3. sqlmesh/cli/project_init.py +10 -2
  4. sqlmesh/core/_typing.py +1 -0
  5. sqlmesh/core/audit/definition.py +8 -2
  6. sqlmesh/core/config/__init__.py +1 -1
  7. sqlmesh/core/config/connection.py +17 -5
  8. sqlmesh/core/config/dbt.py +13 -0
  9. sqlmesh/core/config/janitor.py +12 -0
  10. sqlmesh/core/config/loader.py +7 -0
  11. sqlmesh/core/config/model.py +2 -0
  12. sqlmesh/core/config/root.py +3 -0
  13. sqlmesh/core/console.py +80 -2
  14. sqlmesh/core/constants.py +1 -1
  15. sqlmesh/core/context.py +61 -25
  16. sqlmesh/core/dialect.py +3 -0
  17. sqlmesh/core/engine_adapter/_typing.py +2 -0
  18. sqlmesh/core/engine_adapter/base.py +322 -22
  19. sqlmesh/core/engine_adapter/base_postgres.py +17 -1
  20. sqlmesh/core/engine_adapter/bigquery.py +146 -7
  21. sqlmesh/core/engine_adapter/clickhouse.py +17 -13
  22. sqlmesh/core/engine_adapter/databricks.py +33 -2
  23. sqlmesh/core/engine_adapter/fabric.py +1 -29
  24. sqlmesh/core/engine_adapter/mixins.py +142 -48
  25. sqlmesh/core/engine_adapter/mssql.py +15 -4
  26. sqlmesh/core/engine_adapter/mysql.py +2 -2
  27. sqlmesh/core/engine_adapter/postgres.py +9 -3
  28. sqlmesh/core/engine_adapter/redshift.py +4 -0
  29. sqlmesh/core/engine_adapter/risingwave.py +1 -0
  30. sqlmesh/core/engine_adapter/shared.py +6 -0
  31. sqlmesh/core/engine_adapter/snowflake.py +82 -11
  32. sqlmesh/core/engine_adapter/spark.py +14 -10
  33. sqlmesh/core/engine_adapter/trino.py +4 -2
  34. sqlmesh/core/janitor.py +181 -0
  35. sqlmesh/core/lineage.py +1 -0
  36. sqlmesh/core/macros.py +35 -13
  37. sqlmesh/core/model/common.py +2 -0
  38. sqlmesh/core/model/definition.py +65 -4
  39. sqlmesh/core/model/kind.py +66 -2
  40. sqlmesh/core/model/meta.py +107 -2
  41. sqlmesh/core/node.py +101 -2
  42. sqlmesh/core/plan/builder.py +15 -10
  43. sqlmesh/core/plan/common.py +196 -2
  44. sqlmesh/core/plan/definition.py +21 -6
  45. sqlmesh/core/plan/evaluator.py +72 -113
  46. sqlmesh/core/plan/explainer.py +90 -8
  47. sqlmesh/core/plan/stages.py +42 -21
  48. sqlmesh/core/renderer.py +26 -18
  49. sqlmesh/core/scheduler.py +60 -19
  50. sqlmesh/core/selector.py +137 -9
  51. sqlmesh/core/signal.py +64 -1
  52. sqlmesh/core/snapshot/__init__.py +1 -0
  53. sqlmesh/core/snapshot/definition.py +109 -25
  54. sqlmesh/core/snapshot/evaluator.py +610 -50
  55. sqlmesh/core/state_sync/__init__.py +0 -1
  56. sqlmesh/core/state_sync/base.py +31 -27
  57. sqlmesh/core/state_sync/cache.py +12 -4
  58. sqlmesh/core/state_sync/common.py +216 -111
  59. sqlmesh/core/state_sync/db/facade.py +30 -15
  60. sqlmesh/core/state_sync/db/interval.py +27 -7
  61. sqlmesh/core/state_sync/db/migrator.py +14 -8
  62. sqlmesh/core/state_sync/db/snapshot.py +119 -87
  63. sqlmesh/core/table_diff.py +2 -2
  64. sqlmesh/core/test/definition.py +14 -9
  65. sqlmesh/dbt/adapter.py +20 -11
  66. sqlmesh/dbt/basemodel.py +52 -41
  67. sqlmesh/dbt/builtin.py +27 -11
  68. sqlmesh/dbt/column.py +17 -5
  69. sqlmesh/dbt/common.py +4 -2
  70. sqlmesh/dbt/context.py +14 -1
  71. sqlmesh/dbt/loader.py +60 -8
  72. sqlmesh/dbt/manifest.py +136 -8
  73. sqlmesh/dbt/model.py +105 -25
  74. sqlmesh/dbt/package.py +16 -1
  75. sqlmesh/dbt/profile.py +3 -3
  76. sqlmesh/dbt/project.py +12 -7
  77. sqlmesh/dbt/seed.py +1 -1
  78. sqlmesh/dbt/source.py +6 -1
  79. sqlmesh/dbt/target.py +25 -6
  80. sqlmesh/dbt/test.py +31 -1
  81. sqlmesh/migrations/v0000_baseline.py +3 -6
  82. sqlmesh/migrations/v0061_mysql_fix_blob_text_type.py +2 -5
  83. sqlmesh/migrations/v0062_add_model_gateway.py +2 -2
  84. sqlmesh/migrations/v0063_change_signals.py +2 -4
  85. sqlmesh/migrations/v0064_join_when_matched_strings.py +2 -4
  86. sqlmesh/migrations/v0065_add_model_optimize.py +2 -2
  87. sqlmesh/migrations/v0066_add_auto_restatements.py +2 -6
  88. sqlmesh/migrations/v0067_add_tsql_date_full_precision.py +2 -2
  89. sqlmesh/migrations/v0068_include_unrendered_query_in_metadata_hash.py +2 -2
  90. sqlmesh/migrations/v0069_update_dev_table_suffix.py +2 -4
  91. sqlmesh/migrations/v0070_include_grains_in_metadata_hash.py +2 -2
  92. sqlmesh/migrations/v0071_add_dev_version_to_intervals.py +2 -6
  93. sqlmesh/migrations/v0072_add_environment_statements.py +2 -4
  94. sqlmesh/migrations/v0073_remove_symbolic_disable_restatement.py +2 -4
  95. sqlmesh/migrations/v0074_add_partition_by_time_column_property.py +2 -2
  96. sqlmesh/migrations/v0075_remove_validate_query.py +2 -4
  97. sqlmesh/migrations/v0076_add_cron_tz.py +2 -2
  98. sqlmesh/migrations/v0077_fix_column_type_hash_calculation.py +2 -2
  99. sqlmesh/migrations/v0078_warn_if_non_migratable_python_env.py +2 -4
  100. sqlmesh/migrations/v0079_add_gateway_managed_property.py +7 -9
  101. sqlmesh/migrations/v0080_add_batch_size_to_scd_type_2_models.py +2 -2
  102. sqlmesh/migrations/v0081_update_partitioned_by.py +2 -4
  103. sqlmesh/migrations/v0082_warn_if_incorrectly_duplicated_statements.py +2 -4
  104. sqlmesh/migrations/v0083_use_sql_for_scd_time_data_type_data_hash.py +2 -2
  105. sqlmesh/migrations/v0084_normalize_quote_when_matched_and_merge_filter.py +2 -2
  106. sqlmesh/migrations/v0085_deterministic_repr.py +2 -4
  107. sqlmesh/migrations/v0086_check_deterministic_bug.py +2 -4
  108. sqlmesh/migrations/v0087_normalize_blueprint_variables.py +2 -4
  109. sqlmesh/migrations/v0088_warn_about_variable_python_env_diffs.py +2 -4
  110. sqlmesh/migrations/v0089_add_virtual_environment_mode.py +2 -2
  111. sqlmesh/migrations/v0090_add_forward_only_column.py +2 -6
  112. sqlmesh/migrations/v0091_on_additive_change.py +2 -2
  113. sqlmesh/migrations/v0092_warn_about_dbt_data_type_diff.py +2 -4
  114. sqlmesh/migrations/v0093_use_raw_sql_in_fingerprint.py +2 -2
  115. sqlmesh/migrations/v0094_add_dev_version_and_fingerprint_columns.py +2 -6
  116. sqlmesh/migrations/v0095_warn_about_dbt_raw_sql_diff.py +2 -4
  117. sqlmesh/migrations/v0096_remove_plan_dags_table.py +2 -4
  118. sqlmesh/migrations/v0097_add_dbt_name_in_node.py +2 -2
  119. sqlmesh/migrations/v0098_add_dbt_node_info_in_node.py +103 -0
  120. sqlmesh/migrations/v0099_add_last_altered_to_intervals.py +25 -0
  121. sqlmesh/migrations/v0100_add_grants_and_grants_target_layer.py +9 -0
  122. sqlmesh/utils/__init__.py +8 -1
  123. sqlmesh/utils/cache.py +5 -1
  124. sqlmesh/utils/date.py +1 -1
  125. sqlmesh/utils/errors.py +4 -0
  126. sqlmesh/utils/jinja.py +25 -2
  127. sqlmesh/utils/pydantic.py +6 -6
  128. sqlmesh/utils/windows.py +13 -3
  129. {sqlmesh-0.217.1.dev1.dist-info → sqlmesh-0.227.2.dev4.dist-info}/METADATA +5 -5
  130. {sqlmesh-0.217.1.dev1.dist-info → sqlmesh-0.227.2.dev4.dist-info}/RECORD +181 -176
  131. sqlmesh_dbt/cli.py +70 -7
  132. sqlmesh_dbt/console.py +14 -6
  133. sqlmesh_dbt/operations.py +103 -24
  134. sqlmesh_dbt/selectors.py +39 -1
  135. web/client/dist/assets/{Audits-Ucsx1GzF.js → Audits-CBiYyyx-.js} +1 -1
  136. web/client/dist/assets/{Banner-BWDzvavM.js → Banner-DSRbUlO5.js} +1 -1
  137. web/client/dist/assets/{ChevronDownIcon-D2VL13Ah.js → ChevronDownIcon-MK_nrjD_.js} +1 -1
  138. web/client/dist/assets/{ChevronRightIcon-DWGYbf1l.js → ChevronRightIcon-CLWtT22Q.js} +1 -1
  139. web/client/dist/assets/{Content-DdHDZM3I.js → Content-BNuGZN5l.js} +1 -1
  140. web/client/dist/assets/{Content-Bikfy8fh.js → Content-CSHJyW0n.js} +1 -1
  141. web/client/dist/assets/{Data-CzAJH7rW.js → Data-C1oRDbLx.js} +1 -1
  142. web/client/dist/assets/{DataCatalog-BJF11g8f.js → DataCatalog-HXyX2-_j.js} +1 -1
  143. web/client/dist/assets/{Editor-s0SBpV2y.js → Editor-BDyfpUuw.js} +1 -1
  144. web/client/dist/assets/{Editor-DgLhgKnm.js → Editor-D0jNItwC.js} +1 -1
  145. web/client/dist/assets/{Errors-D0m0O1d3.js → Errors-BfuFLcPi.js} +1 -1
  146. web/client/dist/assets/{FileExplorer-CEv0vXkt.js → FileExplorer-BR9IE3he.js} +1 -1
  147. web/client/dist/assets/{Footer-BwzXn8Ew.js → Footer-CgBEtiAh.js} +1 -1
  148. web/client/dist/assets/{Header-6heDkEqG.js → Header-DSqR6nSO.js} +1 -1
  149. web/client/dist/assets/{Input-obuJsD6k.js → Input-B-oZ6fGO.js} +1 -1
  150. web/client/dist/assets/Lineage-DYQVwDbD.js +1 -0
  151. web/client/dist/assets/{ListboxShow-HM9_qyrt.js → ListboxShow-BE5-xevs.js} +1 -1
  152. web/client/dist/assets/{ModelLineage-zWdKo0U2.js → ModelLineage-DkIFAYo4.js} +1 -1
  153. web/client/dist/assets/{Models-Bcu66SRz.js → Models-D5dWr8RB.js} +1 -1
  154. web/client/dist/assets/{Page-BWEEQfIt.js → Page-C-XfU5BR.js} +1 -1
  155. web/client/dist/assets/{Plan-C4gXCqlf.js → Plan-ZEuTINBq.js} +1 -1
  156. web/client/dist/assets/{PlusCircleIcon-CVDO651q.js → PlusCircleIcon-DVXAHG8_.js} +1 -1
  157. web/client/dist/assets/{ReportErrors-BT6xFwAr.js → ReportErrors-B7FEPzMB.js} +1 -1
  158. web/client/dist/assets/{Root-ryJoBK4h.js → Root-8aZyhPxF.js} +1 -1
  159. web/client/dist/assets/{SearchList-DB04sPb9.js → SearchList-W_iT2G82.js} +1 -1
  160. web/client/dist/assets/{SelectEnvironment-CUYcXUu6.js → SelectEnvironment-C65jALmO.js} +1 -1
  161. web/client/dist/assets/{SourceList-Doo_9ZGp.js → SourceList-DSLO6nVJ.js} +1 -1
  162. web/client/dist/assets/{SourceListItem-D5Mj7Dly.js → SourceListItem-BHt8d9-I.js} +1 -1
  163. web/client/dist/assets/{SplitPane-qHmkD1qy.js → SplitPane-CViaZmw6.js} +1 -1
  164. web/client/dist/assets/{Tests-DH1Z74ML.js → Tests-DhaVt5t1.js} +1 -1
  165. web/client/dist/assets/{Welcome-DqUJUNMF.js → Welcome-DvpjH-_4.js} +1 -1
  166. web/client/dist/assets/context-BctCsyGb.js +71 -0
  167. web/client/dist/assets/{context-Dr54UHLi.js → context-DFNeGsFF.js} +1 -1
  168. web/client/dist/assets/{editor-DYIP1yQ4.js → editor-CcO28cqd.js} +1 -1
  169. web/client/dist/assets/{file-DarlIDVi.js → file-CvJN3aZO.js} +1 -1
  170. web/client/dist/assets/{floating-ui.react-dom-BH3TFvkM.js → floating-ui.react-dom-CjE-JNW1.js} +1 -1
  171. web/client/dist/assets/{help-Bl8wqaQc.js → help-DuPhjipa.js} +1 -1
  172. web/client/dist/assets/{index-D1sR7wpN.js → index-C-dJH7yZ.js} +1 -1
  173. web/client/dist/assets/{index-O3mjYpnE.js → index-Dj0i1-CA.js} +2 -2
  174. web/client/dist/assets/{plan-CehRrJUG.js → plan-BTRSbjKn.js} +1 -1
  175. web/client/dist/assets/{popover-CqgMRE0G.js → popover-_Sf0yvOI.js} +1 -1
  176. web/client/dist/assets/{project-6gxepOhm.js → project-BvSOI8MY.js} +1 -1
  177. web/client/dist/index.html +1 -1
  178. web/client/dist/assets/Lineage-D0Hgdz2v.js +0 -1
  179. web/client/dist/assets/context-DgX0fp2E.js +0 -68
  180. {sqlmesh-0.217.1.dev1.dist-info → sqlmesh-0.227.2.dev4.dist-info}/WHEEL +0 -0
  181. {sqlmesh-0.217.1.dev1.dist-info → sqlmesh-0.227.2.dev4.dist-info}/entry_points.txt +0 -0
  182. {sqlmesh-0.217.1.dev1.dist-info → sqlmesh-0.227.2.dev4.dist-info}/licenses/LICENSE +0 -0
  183. {sqlmesh-0.217.1.dev1.dist-info → sqlmesh-0.227.2.dev4.dist-info}/top_level.txt +0 -0
sqlmesh_dbt/cli.py CHANGED
@@ -8,11 +8,13 @@ from sqlmesh_dbt.options import YamlParamType
8
8
  import functools
9
9
 
10
10
 
11
- def _get_dbt_operations(ctx: click.Context, vars: t.Optional[t.Dict[str, t.Any]]) -> DbtOperations:
11
+ def _get_dbt_operations(
12
+ ctx: click.Context, vars: t.Optional[t.Dict[str, t.Any]], threads: t.Optional[int] = None
13
+ ) -> DbtOperations:
12
14
  if not isinstance(ctx.obj, functools.partial):
13
15
  raise ValueError(f"Unexpected click context object: {type(ctx.obj)}")
14
16
 
15
- dbt_operations = ctx.obj(vars=vars)
17
+ dbt_operations = ctx.obj(vars=vars, threads=threads)
16
18
 
17
19
  if not isinstance(dbt_operations, DbtOperations):
18
20
  raise ValueError(f"Unexpected dbt operations type: {type(dbt_operations)}")
@@ -33,15 +35,39 @@ vars_option = click.option(
33
35
 
34
36
  select_option = click.option(
35
37
  "-s",
36
- "-m",
37
38
  "--select",
39
+ multiple=True,
40
+ help="Specify the nodes to include.",
41
+ )
42
+ model_option = click.option(
43
+ "-m",
38
44
  "--models",
39
45
  "--model",
40
46
  multiple=True,
41
- help="Specify the nodes to include.",
47
+ help="Specify the model nodes to include; other nodes are excluded.",
42
48
  )
43
49
  exclude_option = click.option("--exclude", multiple=True, help="Specify the nodes to exclude.")
44
50
 
51
+ # TODO: expand this out into --resource-type/--resource-types and --exclude-resource-type/--exclude-resource-types
52
+ resource_types = [
53
+ "metric",
54
+ "semantic_model",
55
+ "saved_query",
56
+ "source",
57
+ "analysis",
58
+ "model",
59
+ "test",
60
+ "unit_test",
61
+ "exposure",
62
+ "snapshot",
63
+ "seed",
64
+ "default",
65
+ "all",
66
+ ]
67
+ resource_type_option = click.option(
68
+ "--resource-type", type=click.Choice(resource_types, case_sensitive=False)
69
+ )
70
+
45
71
 
46
72
  @click.group(cls=ErrorHandlingGroup, invoke_without_command=True)
47
73
  @click.option("--profile", help="Which existing profile to load. Overrides output.profile")
@@ -52,6 +78,22 @@ exclude_option = click.option("--exclude", multiple=True, help="Specify the node
52
78
  default=False,
53
79
  help="Display debug logging during dbt execution. Useful for debugging and making bug reports events to help when debugging.",
54
80
  )
81
+ @click.option(
82
+ "--log-level",
83
+ default="info",
84
+ type=click.Choice(["debug", "info", "warn", "error", "none"]),
85
+ help="Specify the minimum severity of events that are logged to the console and the log file.",
86
+ )
87
+ @click.option(
88
+ "--profiles-dir",
89
+ type=click.Path(exists=True, file_okay=False, path_type=Path),
90
+ help="Which directory to look in for the profiles.yml file. If not set, dbt will look in the current working directory first, then HOME/.dbt/",
91
+ )
92
+ @click.option(
93
+ "--project-dir",
94
+ type=click.Path(exists=True, file_okay=False, path_type=Path),
95
+ help="Which directory to look in for the dbt_project.yml file. Default is the current working directory and its parents.",
96
+ )
55
97
  @click.pass_context
56
98
  @cli_global_error_handler
57
99
  def dbt(
@@ -59,6 +101,9 @@ def dbt(
59
101
  profile: t.Optional[str] = None,
60
102
  target: t.Optional[str] = None,
61
103
  debug: bool = False,
104
+ log_level: t.Optional[str] = None,
105
+ profiles_dir: t.Optional[Path] = None,
106
+ project_dir: t.Optional[Path] = None,
62
107
  ) -> None:
63
108
  """
64
109
  An ELT tool for managing your SQL transformations and data models, powered by the SQLMesh engine.
@@ -71,7 +116,13 @@ def dbt(
71
116
  # we have a partially applied function here because subcommands might set extra options like --vars
72
117
  # that need to be known before we attempt to load the project
73
118
  ctx.obj = functools.partial(
74
- create, project_dir=Path.cwd(), profile=profile, target=target, debug=debug
119
+ create,
120
+ project_dir=project_dir,
121
+ profiles_dir=profiles_dir,
122
+ profile=profile,
123
+ target=target,
124
+ debug=debug,
125
+ log_level=log_level,
75
126
  )
76
127
 
77
128
  if not ctx.invoked_subcommand:
@@ -86,11 +137,15 @@ def dbt(
86
137
 
87
138
  @dbt.command()
88
139
  @select_option
140
+ @model_option
89
141
  @exclude_option
142
+ @resource_type_option
90
143
  @click.option(
91
144
  "-f",
92
145
  "--full-refresh",
93
- help="If specified, dbt will drop incremental models and fully-recalculate the incremental table from the model definition.",
146
+ is_flag=True,
147
+ default=False,
148
+ help="If specified, sqlmesh will drop incremental models and fully-recalculate the incremental table from the model definition.",
94
149
  )
95
150
  @click.option(
96
151
  "--env",
@@ -100,21 +155,29 @@ def dbt(
100
155
  @click.option(
101
156
  "--empty/--no-empty", default=False, help="If specified, limit input refs and sources"
102
157
  )
158
+ @click.option(
159
+ "--threads",
160
+ type=int,
161
+ help="Specify number of threads to use while executing models. Overrides settings in profiles.yml.",
162
+ )
103
163
  @vars_option
104
164
  @click.pass_context
105
165
  def run(
106
166
  ctx: click.Context,
107
167
  vars: t.Optional[t.Dict[str, t.Any]],
168
+ threads: t.Optional[int],
108
169
  env: t.Optional[str] = None,
109
170
  **kwargs: t.Any,
110
171
  ) -> None:
111
172
  """Compile SQL and execute against the current target database."""
112
- _get_dbt_operations(ctx, vars).run(environment=env, **kwargs)
173
+ _get_dbt_operations(ctx, vars, threads).run(environment=env, **kwargs)
113
174
 
114
175
 
115
176
  @dbt.command(name="list")
116
177
  @select_option
178
+ @model_option
117
179
  @exclude_option
180
+ @resource_type_option
118
181
  @vars_option
119
182
  @click.pass_context
120
183
  def list_(ctx: click.Context, vars: t.Optional[t.Dict[str, t.Any]], **kwargs: t.Any) -> None:
sqlmesh_dbt/console.py CHANGED
@@ -1,6 +1,7 @@
1
1
  import typing as t
2
2
  from sqlmesh.core.console import TerminalConsole
3
3
  from sqlmesh.core.model import Model
4
+ from sqlmesh.core.snapshot.definition import Node
4
5
  from rich.tree import Tree
5
6
 
6
7
 
@@ -9,19 +10,26 @@ class DbtCliConsole(TerminalConsole):
9
10
  return self._print(msg)
10
11
 
11
12
  def list_models(
12
- self, models: t.List[Model], list_parents: bool = True, list_audits: bool = True
13
+ self,
14
+ models: t.List[Model],
15
+ all_nodes: t.Dict[str, Node],
16
+ list_parents: bool = True,
17
+ list_audits: bool = True,
13
18
  ) -> None:
14
19
  model_list = Tree("[bold]Models in project:[/bold]")
15
20
 
16
21
  for model in models:
17
- model_tree = model_list.add(model.name)
22
+ model_tree = model_list.add(model.dbt_fqn or model.name)
18
23
 
19
24
  if list_parents:
20
- for parent in model.depends_on:
21
- model_tree.add(f"depends_on: {parent}")
25
+ for parent_name in model.depends_on:
26
+ if parent := all_nodes.get(parent_name):
27
+ parent_name = parent.dbt_fqn or parent_name
28
+
29
+ model_tree.add(f"depends_on: {parent_name}")
22
30
 
23
31
  if list_audits:
24
- for audit_name in model.audit_definitions:
25
- model_tree.add(f"audit: {audit_name}")
32
+ for audit_name, audit in model.audit_definitions.items():
33
+ model_tree.add(f"audit: {audit.dbt_fqn or audit_name}")
26
34
 
27
35
  self._print(model_list)
sqlmesh_dbt/operations.py CHANGED
@@ -11,7 +11,7 @@ if t.TYPE_CHECKING:
11
11
  from sqlmesh.dbt.project import Project
12
12
  from sqlmesh_dbt.console import DbtCliConsole
13
13
  from sqlmesh.core.model import Model
14
- from sqlmesh.core.plan import Plan
14
+ from sqlmesh.core.plan import Plan, PlanBuilder
15
15
 
16
16
  logger = logging.getLogger(__name__)
17
17
 
@@ -26,24 +26,67 @@ class DbtOperations:
26
26
  self,
27
27
  select: t.Optional[t.List[str]] = None,
28
28
  exclude: t.Optional[t.List[str]] = None,
29
+ models: t.Optional[t.List[str]] = None,
30
+ resource_type: t.Optional[str] = None,
29
31
  ) -> None:
30
32
  # dbt list prints:
31
33
  # - models
32
34
  # - "data tests" (audits) for those models
33
35
  # it also applies selectors which is useful for testing selectors
34
- selected_models = list(self._selected_models(select, exclude).values())
35
- self.console.list_models(selected_models)
36
+ selected_models = list(
37
+ self._selected_models(select, exclude, models, resource_type).values()
38
+ )
39
+ self.console.list_models(
40
+ selected_models, {k: v.node for k, v in self.context.snapshots.items()}
41
+ )
36
42
 
37
43
  def run(
38
44
  self,
39
45
  environment: t.Optional[str] = None,
40
46
  select: t.Optional[t.List[str]] = None,
41
47
  exclude: t.Optional[t.List[str]] = None,
48
+ models: t.Optional[t.List[str]] = None,
49
+ resource_type: t.Optional[str] = None,
42
50
  full_refresh: bool = False,
43
51
  empty: bool = False,
44
52
  ) -> Plan:
45
- return self.context.plan(
46
- **self._plan_options(
53
+ consolidated_select, consolidated_exclude = selectors.consolidate(
54
+ select or [], exclude or [], models or [], resource_type
55
+ )
56
+
57
+ plan_builder = self._plan_builder(
58
+ environment=environment,
59
+ select=consolidated_select,
60
+ exclude=consolidated_exclude,
61
+ full_refresh=full_refresh,
62
+ empty=empty,
63
+ )
64
+
65
+ plan = plan_builder.build()
66
+
67
+ self.console.plan(
68
+ plan_builder,
69
+ default_catalog=self.context.default_catalog,
70
+ # start doing work immediately (since no_diff is set, there isnt really anything for the user to say yes/no to)
71
+ auto_apply=True,
72
+ # dont output a diff of model changes
73
+ no_diff=True,
74
+ # don't throw up any prompts like "set the effective date" - use defaults
75
+ no_prompts=True,
76
+ )
77
+
78
+ return plan
79
+
80
+ def _plan_builder(
81
+ self,
82
+ environment: t.Optional[str] = None,
83
+ select: t.Optional[t.List[str]] = None,
84
+ exclude: t.Optional[t.List[str]] = None,
85
+ full_refresh: bool = False,
86
+ empty: bool = False,
87
+ ) -> PlanBuilder:
88
+ return self.context.plan_builder(
89
+ **self._plan_builder_options(
47
90
  environment=environment,
48
91
  select=select,
49
92
  exclude=exclude,
@@ -53,9 +96,15 @@ class DbtOperations:
53
96
  )
54
97
 
55
98
  def _selected_models(
56
- self, select: t.Optional[t.List[str]] = None, exclude: t.Optional[t.List[str]] = None
99
+ self,
100
+ select: t.Optional[t.List[str]] = None,
101
+ exclude: t.Optional[t.List[str]] = None,
102
+ models: t.Optional[t.List[str]] = None,
103
+ resource_type: t.Optional[str] = None,
57
104
  ) -> t.Dict[str, Model]:
58
- if sqlmesh_selector := selectors.to_sqlmesh(select or [], exclude or []):
105
+ if sqlmesh_selector := selectors.to_sqlmesh(
106
+ *selectors.consolidate(select or [], exclude or [], models or [], resource_type)
107
+ ):
59
108
  if self.debug:
60
109
  self.console.print(f"dbt --select: {select}")
61
110
  self.console.print(f"dbt --exclude: {exclude}")
@@ -71,13 +120,15 @@ class DbtOperations:
71
120
 
72
121
  return selected_models
73
122
 
74
- def _plan_options(
123
+ def _plan_builder_options(
75
124
  self,
76
- environment: t.Optional[str] = None,
125
+ # upstream dbt options
77
126
  select: t.Optional[t.List[str]] = None,
78
127
  exclude: t.Optional[t.List[str]] = None,
79
128
  empty: bool = False,
80
129
  full_refresh: bool = False,
130
+ # sqlmesh extra options
131
+ environment: t.Optional[str] = None,
81
132
  ) -> t.Dict[str, t.Any]:
82
133
  import sqlmesh.core.constants as c
83
134
 
@@ -130,24 +181,38 @@ class DbtOperations:
130
181
  # `dbt --empty` adds LIMIT 0 to the queries, resulting in empty tables. In addition, it happily clobbers existing tables regardless of if they are populated.
131
182
  # This *partially* lines up with --skip-backfill in SQLMesh, which indicates to not populate tables if they happened to be created/updated as part of this plan.
132
183
  # However, if a table already exists and has data in it, there is no change so SQLMesh will not recreate the table and thus it will not be cleared.
133
- # So in order to fully replicate dbt's --empty, we also need --full-refresh semantics in order to replace existing tables
184
+ # Currently, SQLMesh has no way to say "restate with empty data", because --restate-model coupled with --skip-backfill ends up being a no-op
134
185
  options["skip_backfill"] = True
135
- full_refresh = True
186
+
187
+ self.console.log_warning(
188
+ "dbt's `--empty` drops the tables for all selected models and replaces them with empty ones.\n"
189
+ "This can easily result in accidental data loss, so SQLMesh limits this to only new or modified models and leaves the tables for existing unmodified models alone.\n\n"
190
+ "If you were creating empty tables to preview model changes, please consider using `--environment` to preview these changes in an isolated Virtual Data Environment instead.\n\n"
191
+ "Otherwise, if you really do want dbt's `--empty` behaviour of clearing every selected table, please file an issue on GitHub so we can better understand the use-case.\n"
192
+ )
193
+
194
+ if full_refresh:
195
+ # --full-refresh is implemented in terms of "add every model as a restatement"
196
+ # however, `--empty` sets skip_backfill=True, which causes the BackfillStage of the plan to be skipped.
197
+ # the re-processing of data intervals happens in the BackfillStage, so if it gets skipped, restatements become a no-op
198
+ raise ValueError("`--full-refresh` alongside `--empty` is not currently supported.")
136
199
 
137
200
  if full_refresh:
138
- # TODO: handling this requires some updates in the engine to enable restatements+changes in the same plan without affecting prod
139
- # if the plan targets dev
140
- pass
201
+ options.update(
202
+ dict(
203
+ # Add every selected model as a restatement to force them to get repopulated from scratch
204
+ restate_models=[m.dbt_fqn for m in self.context.models.values() if m.dbt_fqn]
205
+ if not select_models
206
+ else select_models,
207
+ # by default in SQLMesh, restatements only operate on what has been committed to state.
208
+ # in order to emulate dbt, we need to use the local filesystem instead, so we override this default
209
+ always_include_local_changes=True,
210
+ )
211
+ )
141
212
 
142
213
  return dict(
143
214
  environment=environment,
144
215
  select_models=select_models,
145
- # dont output a diff of model changes
146
- no_diff=True,
147
- # don't throw up any prompts like "set the effective date" - use defaults
148
- no_prompts=True,
149
- # start doing work immediately (since no_diff is set, there isnt really anything for the user to say yes/no to)
150
- auto_apply=True,
151
216
  **options,
152
217
  )
153
218
 
@@ -167,10 +232,13 @@ class DbtOperations:
167
232
 
168
233
  def create(
169
234
  project_dir: t.Optional[Path] = None,
235
+ profiles_dir: t.Optional[Path] = None,
170
236
  profile: t.Optional[str] = None,
171
237
  target: t.Optional[str] = None,
172
238
  vars: t.Optional[t.Dict[str, t.Any]] = None,
239
+ threads: t.Optional[int] = None,
173
240
  debug: bool = False,
241
+ log_level: t.Optional[str] = None,
174
242
  ) -> DbtOperations:
175
243
  with Progress(transient=True) as progress:
176
244
  # Indeterminate progress bar before SQLMesh import to provide feedback to the user that something is indeed happening
@@ -182,6 +250,7 @@ def create(
182
250
  from sqlmesh.core.console import set_console
183
251
  from sqlmesh_dbt.console import DbtCliConsole
184
252
  from sqlmesh.utils.errors import SQLMeshError
253
+ from sqlmesh.core.selector import DbtSelector
185
254
 
186
255
  # clear any existing handlers set up by click/rich as defaults so that once SQLMesh logging config is applied,
187
256
  # we dont get duplicate messages logged from things like console.log_warning()
@@ -189,7 +258,7 @@ def create(
189
258
  while root_logger.hasHandlers():
190
259
  root_logger.removeHandler(root_logger.handlers[0])
191
260
 
192
- configure_logging(force_debug=debug)
261
+ configure_logging(force_debug=debug, log_level=log_level)
193
262
  set_console(DbtCliConsole())
194
263
 
195
264
  progress.update(load_task_id, description="Loading project", total=None)
@@ -199,8 +268,16 @@ def create(
199
268
 
200
269
  sqlmesh_context = Context(
201
270
  paths=[project_dir],
202
- config_loader_kwargs=dict(profile=profile, target=target, variables=vars),
271
+ config_loader_kwargs=dict(
272
+ profile=profile,
273
+ target=target,
274
+ variables=vars,
275
+ threads=threads,
276
+ profiles_dir=profiles_dir,
277
+ ),
203
278
  load=True,
279
+ # DbtSelector selects based on dbt model fqn's rather than SQLMesh model names
280
+ selector=DbtSelector,
204
281
  )
205
282
 
206
283
  dbt_loader = sqlmesh_context._loaders[0]
@@ -213,7 +290,7 @@ def create(
213
290
  return DbtOperations(sqlmesh_context, dbt_project, debug=debug)
214
291
 
215
292
 
216
- def init_project_if_required(project_dir: Path) -> None:
293
+ def init_project_if_required(project_dir: Path, start: t.Optional[str] = None) -> None:
217
294
  """
218
295
  SQLMesh needs a start date to as the starting point for calculating intervals on incremental models, amongst other things
219
296
 
@@ -229,4 +306,6 @@ def init_project_if_required(project_dir: Path) -> None:
229
306
 
230
307
  if not any(f.exists() for f in [project_dir / file for file in ALL_CONFIG_FILENAMES]):
231
308
  get_console().log_warning("No existing SQLMesh config detected; creating one")
232
- init_example_project(path=project_dir, engine_type=None, template=ProjectTemplate.DBT)
309
+ init_example_project(
310
+ path=project_dir, engine_type=None, template=ProjectTemplate.DBT, start=start
311
+ )
sqlmesh_dbt/selectors.py CHANGED
@@ -4,7 +4,45 @@ import logging
4
4
  logger = logging.getLogger(__name__)
5
5
 
6
6
 
7
- def to_sqlmesh(dbt_select: t.Collection[str], dbt_exclude: t.Collection[str]) -> t.Optional[str]:
7
+ def consolidate(
8
+ select: t.List[str],
9
+ exclude: t.List[str],
10
+ models: t.List[str],
11
+ resource_type: t.Optional[str],
12
+ ) -> t.Tuple[t.List[str], t.List[str]]:
13
+ """
14
+ Given a bunch of dbt CLI arguments that may or may not be defined:
15
+ --select, --exclude, --models, --resource-type
16
+
17
+ Combine them into a single set of --select/--exclude node selectors, throwing an error if mutually exclusive combinations are provided
18
+ Note that the returned value is still in dbt format, pass it to to_sqlmesh() to create a selector for the sqlmesh selector engine
19
+ """
20
+ if models and select:
21
+ raise ValueError('"models" and "select" are mutually exclusive arguments')
22
+
23
+ if models and resource_type:
24
+ raise ValueError('"models" and "resource_type" are mutually exclusive arguments')
25
+
26
+ if models:
27
+ # --models implies resource_type:model
28
+ resource_type = "model"
29
+
30
+ if resource_type:
31
+ resource_type_selector = f"resource_type:{resource_type}"
32
+ all_selectors = [*select, *models]
33
+ select = (
34
+ [
35
+ f"resource_type:{resource_type},{original_selector}"
36
+ for original_selector in all_selectors
37
+ ]
38
+ if all_selectors
39
+ else [resource_type_selector]
40
+ )
41
+
42
+ return select, exclude
43
+
44
+
45
+ def to_sqlmesh(dbt_select: t.List[str], dbt_exclude: t.List[str]) -> t.Optional[str]:
8
46
  """
9
47
  Given selectors defined in the format of the dbt cli --select and --exclude arguments, convert them into a selector expression that
10
48
  the SQLMesh selector engine can understand.
@@ -1 +1 @@
1
- import{x as n,j as s,O as f,e as t,H as c,B as p,m as x,l as d}from"./index-O3mjYpnE.js";import{P as j}from"./Page-BWEEQfIt.js";import{u as h}from"./project-6gxepOhm.js";import{S as v}from"./SourceList-Doo_9ZGp.js";import{S as A}from"./SourceListItem-D5Mj7Dly.js";import"./SplitPane-qHmkD1qy.js";import"./file-DarlIDVi.js";import"./Input-obuJsD6k.js";import"./floating-ui.react-dom-BH3TFvkM.js";import"./index-D1sR7wpN.js";function k(){const{pathname:a}=n(),i=h(e=>e.files),r=Array.from(i.values()).filter(e=>e.path.endsWith("audits"));return s.jsx(j,{sidebar:s.jsxs("div",{className:"flex flex-col w-full h-full",children:[s.jsx(v,{keyId:"basename",keyName:"basename",to:t.Audits,items:r,isActive:e=>`${t.Audits}/${e}`===a,className:"h-full",listItem:({to:e,name:o,description:m,text:l,disabled:u=!1})=>s.jsx(A,{to:e,name:o,text:l,description:m,disabled:u})}),s.jsx(c,{}),s.jsx("div",{className:"py-1 px-1 flex justify-end",children:s.jsx(p,{size:d.sm,variant:x.Neutral,children:"Run All"})})]}),content:s.jsx(f,{})})}export{k as default};
1
+ import{x as n,j as s,O as f,e as t,H as c,B as p,m as x,l as d}from"./index-Dj0i1-CA.js";import{P as j}from"./Page-C-XfU5BR.js";import{u as h}from"./project-BvSOI8MY.js";import{S as v}from"./SourceList-DSLO6nVJ.js";import{S as A}from"./SourceListItem-BHt8d9-I.js";import"./SplitPane-CViaZmw6.js";import"./file-CvJN3aZO.js";import"./Input-B-oZ6fGO.js";import"./floating-ui.react-dom-CjE-JNW1.js";import"./index-C-dJH7yZ.js";function k(){const{pathname:a}=n(),i=h(e=>e.files),r=Array.from(i.values()).filter(e=>e.path.endsWith("audits"));return s.jsx(j,{sidebar:s.jsxs("div",{className:"flex flex-col w-full h-full",children:[s.jsx(v,{keyId:"basename",keyName:"basename",to:t.Audits,items:r,isActive:e=>`${t.Audits}/${e}`===a,className:"h-full",listItem:({to:e,name:o,description:m,text:l,disabled:u=!1})=>s.jsx(A,{to:e,name:o,text:l,description:m,disabled:u})}),s.jsx(c,{}),s.jsx("div",{className:"py-1 px-1 flex justify-end",children:s.jsx(p,{size:d.sm,variant:x.Neutral,children:"Run All"})})]}),content:s.jsx(f,{})})}export{k as default};
@@ -1 +1 @@
1
- import{j as s,c as i,l as a,m as n,H as p}from"./index-O3mjYpnE.js";function l({variant:t=n.Neutral,size:e=a.md,isFull:r=!1,isCenter:u=!1,hasBackground:x=!0,hasBackgroundOnHover:f=!1,hasBorder:c=!1,children:m,className:b}){return s.jsx("div",{className:i("w-full text-sm px-4 overflow-hidden rounded-lg",e===a.sm&&"py-2",e===a.md&&"py-4",e===a.lg&&"py-6",r&&"h-full",u&&"justify-center items-center",c&&"border-2",w(t,x,f),b),children:m})}function g({className:t}){return s.jsx(p,{className:i("mx-4 w-full",t)})}function d({children:t,className:e}){return s.jsx("h4",{className:i("font-bold text-sm whitespace-nowrap text-left",e),children:t})}function o({children:t,className:e}){return s.jsx("p",{className:i("text-neutral-600",e),children:t})}l.Label=d;l.Description=o;l.Divider=g;function w(t,e=!0,r=!1){switch(t){case n.Primary:return[r?"hover:bg-primary-5":"",e?"bg-primary-5":"","text-primary-600 dark:text-primary-400"];case n.Success:return[r?"hover:bg-success-5":"",e?"bg-success-5":"","text-success-600 dark:text-success-400"];case n.Warning:return[r?"hover:bg-warning-5":"",e?"bg-warning-5":"","text-warning-600 dark:text-warning-400"];case n.Danger:return[r?"hover:bg-danger-5":"",e?"bg-danger-5":"","text-danger-600 dark:text-danger-400"];case n.Info:return[r?"hover:bg-info-5":"",e?"bg-info-5":"","text-info-600 dark:text-info-400"];case n.Neutral:return[r?"hover:bg-neutral-5":"",e?"bg-neutral-5":"","text-neutral-600 dark:text-neutral-400"];default:return["bg-transparent","text-neutral-600 dark:text-neutral-400"]}}export{l as B};
1
+ import{j as s,c as i,l as a,m as n,H as p}from"./index-Dj0i1-CA.js";function l({variant:t=n.Neutral,size:e=a.md,isFull:r=!1,isCenter:u=!1,hasBackground:x=!0,hasBackgroundOnHover:f=!1,hasBorder:c=!1,children:m,className:b}){return s.jsx("div",{className:i("w-full text-sm px-4 overflow-hidden rounded-lg",e===a.sm&&"py-2",e===a.md&&"py-4",e===a.lg&&"py-6",r&&"h-full",u&&"justify-center items-center",c&&"border-2",w(t,x,f),b),children:m})}function g({className:t}){return s.jsx(p,{className:i("mx-4 w-full",t)})}function d({children:t,className:e}){return s.jsx("h4",{className:i("font-bold text-sm whitespace-nowrap text-left",e),children:t})}function o({children:t,className:e}){return s.jsx("p",{className:i("text-neutral-600",e),children:t})}l.Label=d;l.Description=o;l.Divider=g;function w(t,e=!0,r=!1){switch(t){case n.Primary:return[r?"hover:bg-primary-5":"",e?"bg-primary-5":"","text-primary-600 dark:text-primary-400"];case n.Success:return[r?"hover:bg-success-5":"",e?"bg-success-5":"","text-success-600 dark:text-success-400"];case n.Warning:return[r?"hover:bg-warning-5":"",e?"bg-warning-5":"","text-warning-600 dark:text-warning-400"];case n.Danger:return[r?"hover:bg-danger-5":"",e?"bg-danger-5":"","text-danger-600 dark:text-danger-400"];case n.Info:return[r?"hover:bg-info-5":"",e?"bg-info-5":"","text-info-600 dark:text-info-400"];case n.Neutral:return[r?"hover:bg-neutral-5":"",e?"bg-neutral-5":"","text-neutral-600 dark:text-neutral-400"];default:return["bg-transparent","text-neutral-600 dark:text-neutral-400"]}}export{l as B};
@@ -1 +1 @@
1
- import{r as e}from"./index-O3mjYpnE.js";function t({title:r,titleId:a,...l},o){return e.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true","data-slot":"icon",ref:o,"aria-labelledby":a},l),r?e.createElement("title",{id:a},r):null,e.createElement("path",{fillRule:"evenodd",d:"M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z",clipRule:"evenodd"}))}const c=e.forwardRef(t);export{c as F};
1
+ import{r as e}from"./index-Dj0i1-CA.js";function t({title:r,titleId:a,...l},o){return e.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true","data-slot":"icon",ref:o,"aria-labelledby":a},l),r?e.createElement("title",{id:a},r):null,e.createElement("path",{fillRule:"evenodd",d:"M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z",clipRule:"evenodd"}))}const c=e.forwardRef(t);export{c as F};
@@ -1 +1 @@
1
- import{r as e}from"./index-O3mjYpnE.js";function o({title:r,titleId:a,...t},l){return e.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true","data-slot":"icon",ref:l,"aria-labelledby":a},t),r?e.createElement("title",{id:a},r):null,e.createElement("path",{fillRule:"evenodd",d:"M8.22 5.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 0 1-1.06-1.06L11.94 10 8.22 6.28a.75.75 0 0 1 0-1.06Z",clipRule:"evenodd"}))}const i=e.forwardRef(o);export{i as F};
1
+ import{r as e}from"./index-Dj0i1-CA.js";function o({title:r,titleId:a,...t},l){return e.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true","data-slot":"icon",ref:l,"aria-labelledby":a},t),r?e.createElement("title",{id:a},r):null,e.createElement("path",{fillRule:"evenodd",d:"M8.22 5.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 0 1-1.06-1.06L11.94 10 8.22 6.28a.75.75 0 0 1 0-1.06Z",clipRule:"evenodd"}))}const i=e.forwardRef(o);export{i as F};
@@ -1 +1 @@
1
- import{d as a,Q as l,v as e,j as r,U as n,e as d}from"./index-O3mjYpnE.js";import{D as u}from"./ReportErrors-BT6xFwAr.js";import"./PlusCircleIcon-CVDO651q.js";import"./popover-CqgMRE0G.js";import"./floating-ui.react-dom-BH3TFvkM.js";import"./_commonjs-dynamic-modules-TDtrdbi3.js";import"./SplitPane-qHmkD1qy.js";function v(){const{errors:i}=a(),{id:o}=l(),s=e(o)?void 0:Array.from(i).find(t=>t.id===o);return r.jsx("div",{className:"flex overflow-auto w-full h-full",children:e(s)?r.jsx(n,{link:d.Errors,description:e(o)?void 0:`Error ${o} Does Not Exist`,message:"Back To Errors"}):r.jsx("div",{className:"p-4 h-full w-full",children:r.jsx("div",{className:"w-full h-full p-4 rounded-lg bg-danger-5 text-danger-700",children:r.jsx(u,{error:s,scope:s.key,withSplitPane:!0})})})})}export{v as default};
1
+ import{d as a,Q as l,v as e,j as r,U as n,e as d}from"./index-Dj0i1-CA.js";import{D as u}from"./ReportErrors-B7FEPzMB.js";import"./PlusCircleIcon-DVXAHG8_.js";import"./popover-_Sf0yvOI.js";import"./floating-ui.react-dom-CjE-JNW1.js";import"./_commonjs-dynamic-modules-TDtrdbi3.js";import"./SplitPane-CViaZmw6.js";function v(){const{errors:i}=a(),{id:o}=l(),s=e(o)?void 0:Array.from(i).find(t=>t.id===o);return r.jsx("div",{className:"flex overflow-auto w-full h-full",children:e(s)?r.jsx(n,{link:d.Errors,description:e(o)?void 0:`Error ${o} Does Not Exist`,message:"Back To Errors"}):r.jsx("div",{className:"p-4 h-full w-full",children:r.jsx("div",{className:"w-full h-full p-4 rounded-lg bg-danger-5 text-danger-700",children:r.jsx(u,{error:s,scope:s.key,withSplitPane:!0})})})})}export{v as default};
@@ -1,4 +1,4 @@
1
- import{r as v,R as J,a as _,j as e,m as O,s as Qe,b as C,B as oe,v as E,l as T,c as w,M as De,f as V,I as Xe,J as de,i as I,K as Q,g as H,T as Me,H as ue,P as ye,C as es,A as $,q as ss,L as as,d as ns,k as ts,o as ls,p as is,Q as rs,U as os,e as cs}from"./index-O3mjYpnE.js";import{u as W,S as ds,A as us,a as Ne,b as R,E as A,P as z,c as ms}from"./SelectEnvironment-CUYcXUu6.js";import{u as j,a as Y,E as M}from"./plan-CehRrJUG.js";import{B as S}from"./Banner-BWDzvavM.js";import{V as L,F as ke,a as Pe,p as ps}from"./PlusCircleIcon-CVDO651q.js";import{K as fs,L as $e,V as hs,y as xs,p as js,o as ce,$ as vs,W as gs,X as ys,_ as ws,Y as bs,a as Re,Z as Ns,z as se}from"./popover-CqgMRE0G.js";import{I as K}from"./Input-obuJsD6k.js";import{H as ks,V as Ps,Q as Ts,w as Cs,u as Fs,a as As,l as Ss,T as Ds,N as Rs,U as Es,j as Bs,p as _s}from"./ListboxShow-HM9_qyrt.js";import{u as ze}from"./project-6gxepOhm.js";import{F as we}from"./context-DgX0fp2E.js";import"./ModelLineage-zWdKo0U2.js";import"./editor-DYIP1yQ4.js";import"./file-DarlIDVi.js";import"./SearchList-DB04sPb9.js";import"./help-B59vE3aE.js";import"./floating-ui.react-dom-BH3TFvkM.js";import"./ChevronDownIcon-D2VL13Ah.js";import"./_commonjs-dynamic-modules-TDtrdbi3.js";import"./SourceList-Doo_9ZGp.js";import"./index-D1sR7wpN.js";function Os({title:s,titleId:a,...t},r){return v.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true","data-slot":"icon",ref:r,"aria-labelledby":a},t),s?v.createElement("title",{id:a},s):null,v.createElement("path",{fillRule:"evenodd",d:"M16.704 4.153a.75.75 0 0 1 .143 1.052l-8 10.5a.75.75 0 0 1-1.127.075l-4.5-4.5a.75.75 0 0 1 1.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 0 1 1.05-.143Z",clipRule:"evenodd"}))}const X=v.forwardRef(Os);let Te=v.createContext(null);Te.displayName="GroupContext";let Is=v.Fragment;function Ms(s){var a;let[t,r]=v.useState(null),[l,i]=Ts(),[c,u]=Cs(),o=v.useMemo(()=>({switch:t,setSwitch:r}),[t,r]),d={},m=s,n=$e();return J.createElement(u,{name:"Switch.Description",value:c},J.createElement(i,{name:"Switch.Label",value:l,props:{htmlFor:(a=o.switch)==null?void 0:a.id,onClick(h){t&&(hs(h.currentTarget)&&h.preventDefault(),t.click(),t.focus({preventScroll:!0}))}}},J.createElement(Te.Provider,{value:o},n({ourProps:d,theirProps:m,slot:{},defaultTag:Is,name:"Switch.Group"}))))}let $s="button";function zs(s,a){var t;let r=v.useId(),l=Fs(),i=As(),{id:c=l||`headlessui-switch-${r}`,disabled:u=i||!1,checked:o,defaultChecked:d,onChange:m,name:n,value:h,form:p,autoFocus:f=!1,...x}=s,F=v.useContext(Te),[B,D]=v.useState(null),N=v.useRef(null),k=xs(N,a,F===null?null:F.setSwitch,D),g=Ss(d),[P,Z]=Ds(o,m,g??!1),je=js(),[le,b]=v.useState(!1),ie=ce(()=>{b(!0),Z==null||Z(!P),je.nextFrame(()=>{b(!1)})}),re=ce(U=>{if(Ns(U.currentTarget))return U.preventDefault();U.preventDefault(),ie()}),ve=ce(U=>{U.key===Re.Space?(U.preventDefault(),ie()):U.key===Re.Enter&&_s(U.currentTarget)}),Le=ce(U=>U.preventDefault()),Ve=Rs(),Ge=Es(),{isFocusVisible:Fe,focusProps:He}=vs({autoFocus:f}),{isHovered:Ae,hoverProps:Ke}=gs({isDisabled:u}),{pressed:Se,pressProps:Ze}=ys({disabled:u}),qe=v.useMemo(()=>({checked:P,disabled:u,hover:Ae,focus:Fe,active:Se,autofocus:f,changing:le}),[P,Ae,Fe,Se,u,le,f]),We=ws({id:c,ref:k,role:"switch",type:bs(s,B),tabIndex:s.tabIndex===-1?0:(t=s.tabIndex)!=null?t:0,"aria-checked":P,"aria-labelledby":Ve,"aria-describedby":Ge,disabled:u||void 0,autoFocus:f,onClick:re,onKeyUp:ve,onKeyPress:Le},He,Ke,Ze),Ye=v.useCallback(()=>{if(g!==void 0)return Z==null?void 0:Z(g)},[Z,g]),Je=$e();return J.createElement(J.Fragment,null,n!=null&&J.createElement(Bs,{disabled:u,data:{[n]:h||"on"},overrides:{type:"checkbox",checked:P},form:p,onReset:Ye}),Je({ourProps:We,theirProps:x,slot:qe,defaultTag:$s,name:"Switch"}))}let Us=fs(zs),Ls=Ms,Vs=Ps,Gs=ks,ge=Object.assign(Us,{Group:Ls,Label:Vs,Description:Gs});function Hs(){const s=_(a=>a.environment);return e.jsx("div",{className:"flex flex-col px-4 py-2 w-full",children:e.jsx(S,{variant:O.Warning,children:e.jsx(L,{defaultOpen:!1,children:({open:a})=>e.jsxs(e.Fragment,{children:[e.jsxs(L.Button,{className:"w-full flex items-center justify-between",children:[e.jsx(S.Label,{className:"w-full",children:s.isInitialProd?"Initializing Prod Environment":"Prod Environment"}),s.isInitialProd&&e.jsx(e.Fragment,{children:a?e.jsx(ke,{className:"w-5 text-warning-500"}):e.jsx(Pe,{className:"w-5 text-warning-500"})})]}),s.isInitialProd&&e.jsx(L.Panel,{className:"px-2 text-sm mt-2",children:e.jsx(S.Description,{children:"Prod will be completely backfilled in order to ensure there are no data gaps. After this is applied, it is recommended to validate further changes in a dev environment before deploying to production."})})]})})})})}function Ks(s=0){return v.useCallback(a=>{setTimeout(()=>{a==null||a.focus()},s)},[s])}function Zs({run:s,apply:a,cancel:t,reset:r}){const l=Qe(),{change_categorization:i}=W(),c=_(b=>b.modules),u=_(b=>b.environment),o=_(b=>b.environments),d=_(b=>b.addConfirmation),m=_(b=>b.setShowConfirmation),n=j(b=>b.planAction),h=j(b=>b.planOverview),p=j(b=>b.planApply),f=j(b=>b.planCancel),x=Ks();function F(b){b.stopPropagation(),r()}function B(b){b.stopPropagation(),t()}function D(b){b.stopPropagation(),l(-1)}function N(b){b.stopPropagation();const ie=u.isProd&&C(u.isInitial),re=Array.from(i.values()).some(ve=>E(ve.category));ie?d({headline:"Applying Plan Directly On Prod Environment!",tagline:"Safer choice will be to select or add new environment first.",description:"Are you sure you want to apply your changes directly on prod?",yesText:`Yes, Run ${u.name}`,noText:"No, Cancel",action:a,details:re?["ATTENTION!","[Breaking Change] category will be applied to all uncategorized changes"]:void 0,children:e.jsxs("div",{className:"mt-5 pt-4",children:[e.jsx("h4",{className:"mb-2",children:`${o.size>1?"Select or ":""}Add Environment`}),e.jsxs("div",{className:"flex items-center relative",children:[o.size>1&&e.jsx(ds,{className:"mr-2",showAddEnvironment:!1,onSelect:()=>{m(!1)},size:T.md}),e.jsx(us,{className:"w-full",size:T.md,onAdd:()=>{m(!1)}})]})]})}):re?d({headline:"Some changes are missing categorization!",description:"Are you sure you want to proceed?",details:["[Breaking Change] category will be applied to all uncategorized changes"],yesText:"Yes, Apply",noText:"No, Cancel",action:a}):a()}function k(b){b.stopPropagation(),s()}const g=h.isFailed||p.isFailed||f.isSuccessful,P=C(n.isCancelling)&&C(n.isDone)&&(n.isProcessing?C(f.isSuccessful):!0)&&C(g),Z=n.isApplying||f.isCancelling||p.isRunning&&h.isFinished,je=g||C(n.isProcessing)&&C(n.isRun)&&C(n.isDone),le=c.showHistoryNavigation;return e.jsx(e.Fragment,{children:e.jsxs("div",{className:"flex justify-between pt-2 pl-4 pr-2 pb-2",children:[e.jsx("div",{className:"flex w-full items-center",children:e.jsx(se,{appear:!0,show:P,enter:"transition ease duration-300 transform",enterFrom:"opacity-0 scale-95",enterTo:"opacity-100 scale-100",leave:"transition ease duration-300 transform",leaveFrom:"opacity-100 scale-100",leaveTo:"opacity-0 scale-95",className:"trasition-all duration-300 ease-in-out",as:"div",children:P&&e.jsx(oe,{disabled:n.isProcessing||f.isSuccessful||n.isDone,onClick:n.isRun?k:f.isSuccessful?void 0:N,ref:x,variant:f.isSuccessful?O.Danger:O.Primary,autoFocus:!0,className:"trasition-all duration-300 ease-in-out",children:e.jsx("span",{children:Y.getActionDisplayName(n,f.isSuccessful?[]:[M.RunningTask,M.Running,M.Run,M.Applying,M.ApplyBackfill,M.ApplyVirtual,M.ApplyChangesAndBackfill,M.ApplyMetadata],f.isSuccessful?"Canceled":"Done")})})})}),e.jsxs("div",{className:"flex items-center",children:[Z&&e.jsx(oe,{onClick:B,variant:O.Danger,disabled:n.isCancelling||n.isProcessing&&f.isSuccessful,children:Y.getActionDisplayName(n,n.isProcessing&&C(f.isSuccessful)?[M.Cancelling]:[],f.isSuccessful?"Finishing Cancellation...":"Cancel")}),je&&e.jsx(oe,{onClick:F,variant:O.Info,disabled:n.isCancelling||n.isProcessing&&f.isSuccessful,children:"Start Over"}),le&&e.jsx(oe,{onClick:D,variant:O.Info,children:"Go Back"})]})]})})}function qs({label:s,enabled:a,setEnabled:t,a11yTitle:r,size:l=T.md,disabled:i=!1,className:c}){return e.jsxs(ge.Group,{as:"div",className:"m-1",children:[e.jsxs(ge,{checked:i?!1:a,onChange:t,className:w("flex relative border-secondary-30 rounded-full m-0","shrink-0 focus:outline-none ring-secondary-300 ring-opacity-60 ring-offset ring-offset-secondary-100 focus:border-secondary-500 focus-visible:ring-opacity-75","transition duration-200 ease-in-out",a?"bg-secondary-500":"bg-secondary-20",c,i?"opacity-50 cursor-not-allowed":"cursor-pointer",l===T.sm&&"h-[14px] w-6 focus:ring-1 border",l===T.md&&"h-5 w-10 focus:ring-2 border-2",l===T.lg&&"h-7 w-14 focus:ring-4 border-2"),disabled:i,children:[e.jsx("span",{className:"sr-only",children:r}),e.jsx("span",{"aria-hidden":"true",className:w("pointer-events-none inline-block transform rounded-full shadow-md transition duration-200 ease-in-out","bg-light",l===T.sm&&"h-3 w-3",l===T.md&&"h-4 w-4",l===T.lg&&"h-6 w-6",a&&l===T.sm&&"translate-x-[10px]",a&&l===T.md&&"translate-x-5",a&&l===T.lg&&"translate-x-7")})]}),s!=null&&e.jsx(ge.Label,{className:w("text-xs font-light ml-1 text-neutral-600 dark:text-neutral-400"),children:s})]})}function q({label:s,info:a,enabled:t,disabled:r=!1,setEnabled:l,className:i}){return e.jsxs("div",{className:w("flex justify-between",i),children:[e.jsxs("label",{className:"block mb-1 px-3 text-sm font-bold",children:[s,e.jsx("small",{className:"block text-xs text-neutral-500",children:a})]}),e.jsx(qs,{disabled:r,enabled:t,setEnabled:l,size:T.lg})]})}function Ws({disabled:s=!1,className:a}){const t=Ne(),{start:r,end:l,isInitialPlanRun:i}=W();return e.jsxs("div",{className:w("flex w-full flex-wrap md:flex-nowrap",a),children:[e.jsx(K,{className:"w-full md:w-[50%]",label:"Start Date (UTC)",info:"The start datetime of the interval",disabled:s||i,children:({disabled:c,className:u})=>e.jsx(K.Textfield,{className:w(u,"w-full"),disabled:c,placeholder:"2023-12-13",value:r,onInput:o=>{o.stopPropagation(),t({type:R.DateStart,start:o.target.value})}})}),e.jsx(K,{className:"w-full md:w-[50%]",label:"End Date (UTC)",info:"The end datetime of the interval",disabled:s||i,children:({disabled:c,className:u})=>e.jsx(K.Textfield,{className:w(u,"w-full"),disabled:c,placeholder:"2022-12-13",value:l,onInput:o=>{o.stopPropagation(),t({type:R.DateEnd,end:o.target.value})}})})]})}function Ys(){const s=Ne(),{skip_tests:a,no_gaps:t,skip_backfill:r,forward_only:l,auto_apply:i,no_auto_categorization:c,restate_models:u,isInitialPlanRun:o,create_from:d,include_unmodified:m}=W(),n=v.useRef(null),h=j(N=>N.planAction),p=j(N=>N.planOverview),f=j(N=>N.planApply),x=_(N=>N.environment),F=_(N=>N.environments),B=De.getOnlyRemote(Array.from(F));v.useEffect(()=>{s({type:R.PlanOptions,...p.plan_options,skip_tests:!1})},[]);const D=h.isProcessing||h.isDone||f.isFinished||p.isLatest&&C(h.isRun)||p.isVirtualUpdate;return v.useEffect(()=>{var N;E(n.current)||h.isProcessing&&n.current.classList.contains("--is-open")&&((N=n.current)==null||N.click())},[n,h]),e.jsxs("form",{className:"w-full",children:[e.jsx("fieldset",{className:w(D&&"opacity-50 cursor-not-allowed"),children:e.jsx(Ws,{className:w(D&&"pointer-events-none")})}),e.jsx("fieldset",{className:"my-2",children:e.jsx(S,{children:e.jsx(L,{defaultOpen:h.isRun,children:({open:N})=>e.jsxs(e.Fragment,{children:[e.jsxs(L.Button,{ref:n,className:w("w-full flex items-center",N&&"--is-open"),children:[e.jsxs(S.Label,{className:"mr-2 text-sm w-full",children:[e.jsx("span",{children:"Additional Options"}),D&&e.jsx("span",{className:"ml-1",children:"(Read Only)"})]}),N?e.jsx(ke,{className:"h-5 w-5 text-neutral-400"}):e.jsx(Pe,{className:"h-5 w-5 text-neutral-400"})]}),e.jsxs(L.Panel,{unmount:!1,className:w("py-4 text-sm text-neutral-500",D&&"opacity-50 cursor-not-allowed"),children:[e.jsx("div",{className:w(D&&"pointer-events-none"),children:e.jsxs("div",{className:"flex flex-wrap md:flex-nowrap",children:[C(x.isProd)&&e.jsx(K,{className:"w-full",label:"Create From Environment",info:"The environment to base the plan on rather than local files",disabled:B.length<2,children:({className:k,disabled:g})=>e.jsx(K.Selector,{className:w(k,"w-full"),list:De.getOnlyRemote(Array.from(F)).filter(P=>P!==x).map(P=>({value:P.name,text:P.name})),onChange:P=>{s({type:R.PlanOptions,create_from:P})},value:d,disabled:g})}),e.jsx(K,{className:"w-full",label:"Restate Models",info:`Restate data for specified models and models
1
+ import{r as v,R as J,a as _,j as e,m as O,s as Qe,b as C,B as oe,v as E,l as T,c as w,M as De,f as V,I as Xe,J as de,i as I,K as Q,g as H,T as Me,H as ue,P as ye,C as es,A as $,q as ss,L as as,d as ns,k as ts,o as ls,p as is,Q as rs,U as os,e as cs}from"./index-Dj0i1-CA.js";import{u as W,S as ds,A as us,a as Ne,b as R,E as A,P as z,c as ms}from"./SelectEnvironment-C65jALmO.js";import{u as j,a as Y,E as M}from"./plan-BTRSbjKn.js";import{B as S}from"./Banner-DSRbUlO5.js";import{V as L,F as ke,a as Pe,p as ps}from"./PlusCircleIcon-DVXAHG8_.js";import{K as fs,L as $e,V as hs,y as xs,p as js,o as ce,$ as vs,W as gs,X as ys,_ as ws,Y as bs,a as Re,Z as Ns,z as se}from"./popover-_Sf0yvOI.js";import{I as K}from"./Input-B-oZ6fGO.js";import{H as ks,V as Ps,Q as Ts,w as Cs,u as Fs,a as As,l as Ss,T as Ds,N as Rs,U as Es,j as Bs,p as _s}from"./ListboxShow-BE5-xevs.js";import{u as ze}from"./project-BvSOI8MY.js";import{F as we}from"./context-BctCsyGb.js";import"./ModelLineage-DkIFAYo4.js";import"./editor-CcO28cqd.js";import"./file-CvJN3aZO.js";import"./SearchList-W_iT2G82.js";import"./help-B59vE3aE.js";import"./floating-ui.react-dom-CjE-JNW1.js";import"./ChevronDownIcon-MK_nrjD_.js";import"./_commonjs-dynamic-modules-TDtrdbi3.js";import"./SourceList-DSLO6nVJ.js";import"./index-C-dJH7yZ.js";function Os({title:s,titleId:a,...t},r){return v.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true","data-slot":"icon",ref:r,"aria-labelledby":a},t),s?v.createElement("title",{id:a},s):null,v.createElement("path",{fillRule:"evenodd",d:"M16.704 4.153a.75.75 0 0 1 .143 1.052l-8 10.5a.75.75 0 0 1-1.127.075l-4.5-4.5a.75.75 0 0 1 1.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 0 1 1.05-.143Z",clipRule:"evenodd"}))}const X=v.forwardRef(Os);let Te=v.createContext(null);Te.displayName="GroupContext";let Is=v.Fragment;function Ms(s){var a;let[t,r]=v.useState(null),[l,i]=Ts(),[c,u]=Cs(),o=v.useMemo(()=>({switch:t,setSwitch:r}),[t,r]),d={},m=s,n=$e();return J.createElement(u,{name:"Switch.Description",value:c},J.createElement(i,{name:"Switch.Label",value:l,props:{htmlFor:(a=o.switch)==null?void 0:a.id,onClick(h){t&&(hs(h.currentTarget)&&h.preventDefault(),t.click(),t.focus({preventScroll:!0}))}}},J.createElement(Te.Provider,{value:o},n({ourProps:d,theirProps:m,slot:{},defaultTag:Is,name:"Switch.Group"}))))}let $s="button";function zs(s,a){var t;let r=v.useId(),l=Fs(),i=As(),{id:c=l||`headlessui-switch-${r}`,disabled:u=i||!1,checked:o,defaultChecked:d,onChange:m,name:n,value:h,form:p,autoFocus:f=!1,...x}=s,F=v.useContext(Te),[B,D]=v.useState(null),N=v.useRef(null),k=xs(N,a,F===null?null:F.setSwitch,D),g=Ss(d),[P,Z]=Ds(o,m,g??!1),je=js(),[le,b]=v.useState(!1),ie=ce(()=>{b(!0),Z==null||Z(!P),je.nextFrame(()=>{b(!1)})}),re=ce(U=>{if(Ns(U.currentTarget))return U.preventDefault();U.preventDefault(),ie()}),ve=ce(U=>{U.key===Re.Space?(U.preventDefault(),ie()):U.key===Re.Enter&&_s(U.currentTarget)}),Le=ce(U=>U.preventDefault()),Ve=Rs(),Ge=Es(),{isFocusVisible:Fe,focusProps:He}=vs({autoFocus:f}),{isHovered:Ae,hoverProps:Ke}=gs({isDisabled:u}),{pressed:Se,pressProps:Ze}=ys({disabled:u}),qe=v.useMemo(()=>({checked:P,disabled:u,hover:Ae,focus:Fe,active:Se,autofocus:f,changing:le}),[P,Ae,Fe,Se,u,le,f]),We=ws({id:c,ref:k,role:"switch",type:bs(s,B),tabIndex:s.tabIndex===-1?0:(t=s.tabIndex)!=null?t:0,"aria-checked":P,"aria-labelledby":Ve,"aria-describedby":Ge,disabled:u||void 0,autoFocus:f,onClick:re,onKeyUp:ve,onKeyPress:Le},He,Ke,Ze),Ye=v.useCallback(()=>{if(g!==void 0)return Z==null?void 0:Z(g)},[Z,g]),Je=$e();return J.createElement(J.Fragment,null,n!=null&&J.createElement(Bs,{disabled:u,data:{[n]:h||"on"},overrides:{type:"checkbox",checked:P},form:p,onReset:Ye}),Je({ourProps:We,theirProps:x,slot:qe,defaultTag:$s,name:"Switch"}))}let Us=fs(zs),Ls=Ms,Vs=Ps,Gs=ks,ge=Object.assign(Us,{Group:Ls,Label:Vs,Description:Gs});function Hs(){const s=_(a=>a.environment);return e.jsx("div",{className:"flex flex-col px-4 py-2 w-full",children:e.jsx(S,{variant:O.Warning,children:e.jsx(L,{defaultOpen:!1,children:({open:a})=>e.jsxs(e.Fragment,{children:[e.jsxs(L.Button,{className:"w-full flex items-center justify-between",children:[e.jsx(S.Label,{className:"w-full",children:s.isInitialProd?"Initializing Prod Environment":"Prod Environment"}),s.isInitialProd&&e.jsx(e.Fragment,{children:a?e.jsx(ke,{className:"w-5 text-warning-500"}):e.jsx(Pe,{className:"w-5 text-warning-500"})})]}),s.isInitialProd&&e.jsx(L.Panel,{className:"px-2 text-sm mt-2",children:e.jsx(S.Description,{children:"Prod will be completely backfilled in order to ensure there are no data gaps. After this is applied, it is recommended to validate further changes in a dev environment before deploying to production."})})]})})})})}function Ks(s=0){return v.useCallback(a=>{setTimeout(()=>{a==null||a.focus()},s)},[s])}function Zs({run:s,apply:a,cancel:t,reset:r}){const l=Qe(),{change_categorization:i}=W(),c=_(b=>b.modules),u=_(b=>b.environment),o=_(b=>b.environments),d=_(b=>b.addConfirmation),m=_(b=>b.setShowConfirmation),n=j(b=>b.planAction),h=j(b=>b.planOverview),p=j(b=>b.planApply),f=j(b=>b.planCancel),x=Ks();function F(b){b.stopPropagation(),r()}function B(b){b.stopPropagation(),t()}function D(b){b.stopPropagation(),l(-1)}function N(b){b.stopPropagation();const ie=u.isProd&&C(u.isInitial),re=Array.from(i.values()).some(ve=>E(ve.category));ie?d({headline:"Applying Plan Directly On Prod Environment!",tagline:"Safer choice will be to select or add new environment first.",description:"Are you sure you want to apply your changes directly on prod?",yesText:`Yes, Run ${u.name}`,noText:"No, Cancel",action:a,details:re?["ATTENTION!","[Breaking Change] category will be applied to all uncategorized changes"]:void 0,children:e.jsxs("div",{className:"mt-5 pt-4",children:[e.jsx("h4",{className:"mb-2",children:`${o.size>1?"Select or ":""}Add Environment`}),e.jsxs("div",{className:"flex items-center relative",children:[o.size>1&&e.jsx(ds,{className:"mr-2",showAddEnvironment:!1,onSelect:()=>{m(!1)},size:T.md}),e.jsx(us,{className:"w-full",size:T.md,onAdd:()=>{m(!1)}})]})]})}):re?d({headline:"Some changes are missing categorization!",description:"Are you sure you want to proceed?",details:["[Breaking Change] category will be applied to all uncategorized changes"],yesText:"Yes, Apply",noText:"No, Cancel",action:a}):a()}function k(b){b.stopPropagation(),s()}const g=h.isFailed||p.isFailed||f.isSuccessful,P=C(n.isCancelling)&&C(n.isDone)&&(n.isProcessing?C(f.isSuccessful):!0)&&C(g),Z=n.isApplying||f.isCancelling||p.isRunning&&h.isFinished,je=g||C(n.isProcessing)&&C(n.isRun)&&C(n.isDone),le=c.showHistoryNavigation;return e.jsx(e.Fragment,{children:e.jsxs("div",{className:"flex justify-between pt-2 pl-4 pr-2 pb-2",children:[e.jsx("div",{className:"flex w-full items-center",children:e.jsx(se,{appear:!0,show:P,enter:"transition ease duration-300 transform",enterFrom:"opacity-0 scale-95",enterTo:"opacity-100 scale-100",leave:"transition ease duration-300 transform",leaveFrom:"opacity-100 scale-100",leaveTo:"opacity-0 scale-95",className:"trasition-all duration-300 ease-in-out",as:"div",children:P&&e.jsx(oe,{disabled:n.isProcessing||f.isSuccessful||n.isDone,onClick:n.isRun?k:f.isSuccessful?void 0:N,ref:x,variant:f.isSuccessful?O.Danger:O.Primary,autoFocus:!0,className:"trasition-all duration-300 ease-in-out",children:e.jsx("span",{children:Y.getActionDisplayName(n,f.isSuccessful?[]:[M.RunningTask,M.Running,M.Run,M.Applying,M.ApplyBackfill,M.ApplyVirtual,M.ApplyChangesAndBackfill,M.ApplyMetadata],f.isSuccessful?"Canceled":"Done")})})})}),e.jsxs("div",{className:"flex items-center",children:[Z&&e.jsx(oe,{onClick:B,variant:O.Danger,disabled:n.isCancelling||n.isProcessing&&f.isSuccessful,children:Y.getActionDisplayName(n,n.isProcessing&&C(f.isSuccessful)?[M.Cancelling]:[],f.isSuccessful?"Finishing Cancellation...":"Cancel")}),je&&e.jsx(oe,{onClick:F,variant:O.Info,disabled:n.isCancelling||n.isProcessing&&f.isSuccessful,children:"Start Over"}),le&&e.jsx(oe,{onClick:D,variant:O.Info,children:"Go Back"})]})]})})}function qs({label:s,enabled:a,setEnabled:t,a11yTitle:r,size:l=T.md,disabled:i=!1,className:c}){return e.jsxs(ge.Group,{as:"div",className:"m-1",children:[e.jsxs(ge,{checked:i?!1:a,onChange:t,className:w("flex relative border-secondary-30 rounded-full m-0","shrink-0 focus:outline-none ring-secondary-300 ring-opacity-60 ring-offset ring-offset-secondary-100 focus:border-secondary-500 focus-visible:ring-opacity-75","transition duration-200 ease-in-out",a?"bg-secondary-500":"bg-secondary-20",c,i?"opacity-50 cursor-not-allowed":"cursor-pointer",l===T.sm&&"h-[14px] w-6 focus:ring-1 border",l===T.md&&"h-5 w-10 focus:ring-2 border-2",l===T.lg&&"h-7 w-14 focus:ring-4 border-2"),disabled:i,children:[e.jsx("span",{className:"sr-only",children:r}),e.jsx("span",{"aria-hidden":"true",className:w("pointer-events-none inline-block transform rounded-full shadow-md transition duration-200 ease-in-out","bg-light",l===T.sm&&"h-3 w-3",l===T.md&&"h-4 w-4",l===T.lg&&"h-6 w-6",a&&l===T.sm&&"translate-x-[10px]",a&&l===T.md&&"translate-x-5",a&&l===T.lg&&"translate-x-7")})]}),s!=null&&e.jsx(ge.Label,{className:w("text-xs font-light ml-1 text-neutral-600 dark:text-neutral-400"),children:s})]})}function q({label:s,info:a,enabled:t,disabled:r=!1,setEnabled:l,className:i}){return e.jsxs("div",{className:w("flex justify-between",i),children:[e.jsxs("label",{className:"block mb-1 px-3 text-sm font-bold",children:[s,e.jsx("small",{className:"block text-xs text-neutral-500",children:a})]}),e.jsx(qs,{disabled:r,enabled:t,setEnabled:l,size:T.lg})]})}function Ws({disabled:s=!1,className:a}){const t=Ne(),{start:r,end:l,isInitialPlanRun:i}=W();return e.jsxs("div",{className:w("flex w-full flex-wrap md:flex-nowrap",a),children:[e.jsx(K,{className:"w-full md:w-[50%]",label:"Start Date (UTC)",info:"The start datetime of the interval",disabled:s||i,children:({disabled:c,className:u})=>e.jsx(K.Textfield,{className:w(u,"w-full"),disabled:c,placeholder:"2023-12-13",value:r,onInput:o=>{o.stopPropagation(),t({type:R.DateStart,start:o.target.value})}})}),e.jsx(K,{className:"w-full md:w-[50%]",label:"End Date (UTC)",info:"The end datetime of the interval",disabled:s||i,children:({disabled:c,className:u})=>e.jsx(K.Textfield,{className:w(u,"w-full"),disabled:c,placeholder:"2022-12-13",value:l,onInput:o=>{o.stopPropagation(),t({type:R.DateEnd,end:o.target.value})}})})]})}function Ys(){const s=Ne(),{skip_tests:a,no_gaps:t,skip_backfill:r,forward_only:l,auto_apply:i,no_auto_categorization:c,restate_models:u,isInitialPlanRun:o,create_from:d,include_unmodified:m}=W(),n=v.useRef(null),h=j(N=>N.planAction),p=j(N=>N.planOverview),f=j(N=>N.planApply),x=_(N=>N.environment),F=_(N=>N.environments),B=De.getOnlyRemote(Array.from(F));v.useEffect(()=>{s({type:R.PlanOptions,...p.plan_options,skip_tests:!1})},[]);const D=h.isProcessing||h.isDone||f.isFinished||p.isLatest&&C(h.isRun)||p.isVirtualUpdate;return v.useEffect(()=>{var N;E(n.current)||h.isProcessing&&n.current.classList.contains("--is-open")&&((N=n.current)==null||N.click())},[n,h]),e.jsxs("form",{className:"w-full",children:[e.jsx("fieldset",{className:w(D&&"opacity-50 cursor-not-allowed"),children:e.jsx(Ws,{className:w(D&&"pointer-events-none")})}),e.jsx("fieldset",{className:"my-2",children:e.jsx(S,{children:e.jsx(L,{defaultOpen:h.isRun,children:({open:N})=>e.jsxs(e.Fragment,{children:[e.jsxs(L.Button,{ref:n,className:w("w-full flex items-center",N&&"--is-open"),children:[e.jsxs(S.Label,{className:"mr-2 text-sm w-full",children:[e.jsx("span",{children:"Additional Options"}),D&&e.jsx("span",{className:"ml-1",children:"(Read Only)"})]}),N?e.jsx(ke,{className:"h-5 w-5 text-neutral-400"}):e.jsx(Pe,{className:"h-5 w-5 text-neutral-400"})]}),e.jsxs(L.Panel,{unmount:!1,className:w("py-4 text-sm text-neutral-500",D&&"opacity-50 cursor-not-allowed"),children:[e.jsx("div",{className:w(D&&"pointer-events-none"),children:e.jsxs("div",{className:"flex flex-wrap md:flex-nowrap",children:[C(x.isProd)&&e.jsx(K,{className:"w-full",label:"Create From Environment",info:"The environment to base the plan on rather than local files",disabled:B.length<2,children:({className:k,disabled:g})=>e.jsx(K.Selector,{className:w(k,"w-full"),list:De.getOnlyRemote(Array.from(F)).filter(P=>P!==x).map(P=>({value:P.name,text:P.name})),onChange:P=>{s({type:R.PlanOptions,create_from:P})},value:d,disabled:g})}),e.jsx(K,{className:"w-full",label:"Restate Models",info:`Restate data for specified models and models
2
2
  downstream from the one specified. For production
3
3
  environment, all related model versions will have
4
4
  their intervals wiped, but only the current
@@ -1 +1 @@
1
- import{Q as x,a as m,v as h,P as a,a4 as c,a5 as D,a6 as P,r as T,j as u}from"./index-O3mjYpnE.js";import{g as b,T as g}from"./help-Bl8wqaQc.js";import{u as r}from"./editor-DYIP1yQ4.js";import"./index-D1sR7wpN.js";import"./floating-ui.react-dom-BH3TFvkM.js";import"./Input-obuJsD6k.js";import"./file-DarlIDVi.js";const d=1440*60*1e3;function S(){const{modelName:o}=x(),p=m(e=>e.models),s=m(e=>e.lastSelectedModel),v=r(e=>e.previewTable),i=r(e=>e.setPreviewQuery),n=r(e=>e.setPreviewTable),t=h(o)||o===(s==null?void 0:s.name)?s:p.get(encodeURI(o)),l={model:t.displayName,start:a(c(Date.now()-d)),end:a(new Date),execution_time:a(c(Date.now()-d)),limit:1e3},{refetch:f}=D(l),{refetch:w}=P(l);return T.useEffect(()=>{i(void 0),n(void 0),f().then(({data:e})=>{i(e==null?void 0:e.sql)}),w().then(({data:e})=>{n(b(e))})},[t]),u.jsx("div",{className:"flex overflow-hidden w-full h-full px-2",children:u.jsx(g,{headline:t==null?void 0:t.displayName,data:v??[[],[]]})})}export{S as default};
1
+ import{Q as x,a as m,v as h,P as a,a4 as c,a5 as D,a6 as P,r as T,j as u}from"./index-Dj0i1-CA.js";import{g as b,T as g}from"./help-DuPhjipa.js";import{u as r}from"./editor-CcO28cqd.js";import"./index-C-dJH7yZ.js";import"./floating-ui.react-dom-CjE-JNW1.js";import"./Input-B-oZ6fGO.js";import"./file-CvJN3aZO.js";const d=1440*60*1e3;function S(){const{modelName:o}=x(),p=m(e=>e.models),s=m(e=>e.lastSelectedModel),v=r(e=>e.previewTable),i=r(e=>e.setPreviewQuery),n=r(e=>e.setPreviewTable),t=h(o)||o===(s==null?void 0:s.name)?s:p.get(encodeURI(o)),l={model:t.displayName,start:a(c(Date.now()-d)),end:a(new Date),execution_time:a(c(Date.now()-d)),limit:1e3},{refetch:f}=D(l),{refetch:w}=P(l);return T.useEffect(()=>{i(void 0),n(void 0),f().then(({data:e})=>{i(e==null?void 0:e.sql)}),w().then(({data:e})=>{n(b(e))})},[t]),u.jsx("div",{className:"flex overflow-hidden w-full h-full px-2",children:u.jsx(g,{headline:t==null?void 0:t.displayName,data:v??[[],[]]})})}export{S as default};