@lightdash/cli 2.228.0 → 2.229.0

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 (177) hide show
  1. package/dist/.tsbuildinfo.build +1 -0
  2. package/package.json +4 -4
  3. package/dist/.tsbuildinfo +0 -1
  4. package/dist/config.test.d.ts +0 -2
  5. package/dist/config.test.d.ts.map +0 -1
  6. package/dist/config.test.js +0 -72
  7. package/dist/dbt/context.test.d.ts +0 -2
  8. package/dist/dbt/context.test.d.ts.map +0 -1
  9. package/dist/dbt/context.test.js +0 -152
  10. package/dist/dbt/manifest.test.d.ts +0 -2
  11. package/dist/dbt/manifest.test.d.ts.map +0 -1
  12. package/dist/dbt/manifest.test.js +0 -170
  13. package/dist/dbt/models.test.d.ts +0 -2
  14. package/dist/dbt/models.test.d.ts.map +0 -1
  15. package/dist/dbt/models.test.js +0 -139
  16. package/dist/dbt/profiles.test.d.ts +0 -2
  17. package/dist/dbt/profiles.test.d.ts.map +0 -1
  18. package/dist/dbt/profiles.test.js +0 -50
  19. package/dist/dbt/targets/athena.test.d.ts +0 -2
  20. package/dist/dbt/targets/athena.test.d.ts.map +0 -1
  21. package/dist/dbt/targets/athena.test.js +0 -78
  22. package/dist/dbt/targets/duckdb.test.d.ts +0 -2
  23. package/dist/dbt/targets/duckdb.test.d.ts.map +0 -1
  24. package/dist/dbt/targets/duckdb.test.js +0 -149
  25. package/dist/dbt/targets/redshift.test.d.ts +0 -2
  26. package/dist/dbt/targets/redshift.test.d.ts.map +0 -1
  27. package/dist/dbt/targets/redshift.test.js +0 -198
  28. package/dist/dbt/templating.test.d.ts +0 -2
  29. package/dist/dbt/templating.test.d.ts.map +0 -1
  30. package/dist/dbt/templating.test.js +0 -51
  31. package/dist/dbt/validation.test.d.ts +0 -2
  32. package/dist/dbt/validation.test.d.ts.map +0 -1
  33. package/dist/dbt/validation.test.js +0 -67
  34. package/dist/handlers/apps/appCodeFiles.test.d.ts +0 -2
  35. package/dist/handlers/apps/appCodeFiles.test.d.ts.map +0 -1
  36. package/dist/handlers/apps/appCodeFiles.test.js +0 -391
  37. package/dist/handlers/apps/appsDownload.test.d.ts +0 -2
  38. package/dist/handlers/apps/appsDownload.test.d.ts.map +0 -1
  39. package/dist/handlers/apps/appsDownload.test.js +0 -639
  40. package/dist/handlers/apps/build.test.d.ts +0 -2
  41. package/dist/handlers/apps/build.test.d.ts.map +0 -1
  42. package/dist/handlers/apps/build.test.js +0 -252
  43. package/dist/handlers/apps/createApp.test.d.ts +0 -2
  44. package/dist/handlers/apps/createApp.test.d.ts.map +0 -1
  45. package/dist/handlers/apps/createApp.test.js +0 -340
  46. package/dist/handlers/apps/pathContainment.test.d.ts +0 -2
  47. package/dist/handlers/apps/pathContainment.test.d.ts.map +0 -1
  48. package/dist/handlers/apps/pathContainment.test.js +0 -66
  49. package/dist/handlers/apps/preview.test.d.ts +0 -2
  50. package/dist/handlers/apps/preview.test.d.ts.map +0 -1
  51. package/dist/handlers/apps/preview.test.js +0 -353
  52. package/dist/handlers/apps/previewProxy.test.d.ts +0 -2
  53. package/dist/handlers/apps/previewProxy.test.d.ts.map +0 -1
  54. package/dist/handlers/apps/previewProxy.test.js +0 -178
  55. package/dist/handlers/apps/scaffolding.test.d.ts +0 -2
  56. package/dist/handlers/apps/scaffolding.test.d.ts.map +0 -1
  57. package/dist/handlers/apps/scaffolding.test.js +0 -151
  58. package/dist/handlers/apps/uploadRetry.test.d.ts +0 -2
  59. package/dist/handlers/apps/uploadRetry.test.d.ts.map +0 -1
  60. package/dist/handlers/apps/uploadRetry.test.js +0 -103
  61. package/dist/handlers/apps/validate.test.d.ts +0 -2
  62. package/dist/handlers/apps/validate.test.d.ts.map +0 -1
  63. package/dist/handlers/apps/validate.test.js +0 -526
  64. package/dist/handlers/compile.test.d.ts +0 -2
  65. package/dist/handlers/compile.test.d.ts.map +0 -1
  66. package/dist/handlers/compile.test.js +0 -151
  67. package/dist/handlers/compileProject.test.d.ts +0 -2
  68. package/dist/handlers/compileProject.test.d.ts.map +0 -1
  69. package/dist/handlers/compileProject.test.js +0 -637
  70. package/dist/handlers/compileWarehouseColumnValidation.test.d.ts +0 -2
  71. package/dist/handlers/compileWarehouseColumnValidation.test.d.ts.map +0 -1
  72. package/dist/handlers/compileWarehouseColumnValidation.test.js +0 -493
  73. package/dist/handlers/connectSnowflake.test.d.ts +0 -2
  74. package/dist/handlers/connectSnowflake.test.d.ts.map +0 -1
  75. package/dist/handlers/connectSnowflake.test.js +0 -320
  76. package/dist/handlers/contentAsCode/fileNames.test.d.ts +0 -2
  77. package/dist/handlers/contentAsCode/fileNames.test.d.ts.map +0 -1
  78. package/dist/handlers/contentAsCode/fileNames.test.js +0 -79
  79. package/dist/handlers/contentAsCode/registry.test.d.ts +0 -2
  80. package/dist/handlers/contentAsCode/registry.test.d.ts.map +0 -1
  81. package/dist/handlers/contentAsCode/registry.test.js +0 -18
  82. package/dist/handlers/contentAsCode/resource.test.d.ts +0 -2
  83. package/dist/handlers/contentAsCode/resource.test.d.ts.map +0 -1
  84. package/dist/handlers/contentAsCode/resource.test.js +0 -121
  85. package/dist/handlers/dbt/getDbtVersion.test.d.ts +0 -2
  86. package/dist/handlers/dbt/getDbtVersion.test.d.ts.map +0 -1
  87. package/dist/handlers/dbt/getDbtVersion.test.js +0 -106
  88. package/dist/handlers/deploy.test.d.ts +0 -2
  89. package/dist/handlers/deploy.test.d.ts.map +0 -1
  90. package/dist/handlers/deploy.test.js +0 -244
  91. package/dist/handlers/download.test.d.ts +0 -2
  92. package/dist/handlers/download.test.d.ts.map +0 -1
  93. package/dist/handlers/download.test.js +0 -1739
  94. package/dist/handlers/exportChartImage.test.d.ts +0 -2
  95. package/dist/handlers/exportChartImage.test.d.ts.map +0 -1
  96. package/dist/handlers/exportChartImage.test.js +0 -55
  97. package/dist/handlers/homepagesAsCode.test.d.ts +0 -2
  98. package/dist/handlers/homepagesAsCode.test.d.ts.map +0 -1
  99. package/dist/handlers/homepagesAsCode.test.js +0 -72
  100. package/dist/handlers/lint.test.d.ts +0 -2
  101. package/dist/handlers/lint.test.d.ts.map +0 -1
  102. package/dist/handlers/lint.test.js +0 -221
  103. package/dist/handlers/login.test.d.ts +0 -2
  104. package/dist/handlers/login.test.d.ts.map +0 -1
  105. package/dist/handlers/login.test.js +0 -24
  106. package/dist/handlers/metadataFile.test.d.ts +0 -2
  107. package/dist/handlers/metadataFile.test.d.ts.map +0 -1
  108. package/dist/handlers/metadataFile.test.js +0 -46
  109. package/dist/handlers/organizationContent/customRoles.test.d.ts +0 -2
  110. package/dist/handlers/organizationContent/customRoles.test.d.ts.map +0 -1
  111. package/dist/handlers/organizationContent/customRoles.test.js +0 -179
  112. package/dist/handlers/organizationContent/groups.test.d.ts +0 -2
  113. package/dist/handlers/organizationContent/groups.test.d.ts.map +0 -1
  114. package/dist/handlers/organizationContent/groups.test.js +0 -135
  115. package/dist/handlers/organizationContent/index.test.d.ts +0 -2
  116. package/dist/handlers/organizationContent/index.test.d.ts.map +0 -1
  117. package/dist/handlers/organizationContent/index.test.js +0 -212
  118. package/dist/handlers/organizationContent/themes.test.d.ts +0 -2
  119. package/dist/handlers/organizationContent/themes.test.d.ts.map +0 -1
  120. package/dist/handlers/organizationContent/themes.test.js +0 -180
  121. package/dist/handlers/organizationContent/users.test.d.ts +0 -2
  122. package/dist/handlers/organizationContent/users.test.d.ts.map +0 -1
  123. package/dist/handlers/organizationContent/users.test.js +0 -155
  124. package/dist/handlers/preAggregateAudit.test.d.ts +0 -2
  125. package/dist/handlers/preAggregateAudit.test.d.ts.map +0 -1
  126. package/dist/handlers/preAggregateAudit.test.js +0 -102
  127. package/dist/handlers/renameHandler.test.d.ts +0 -2
  128. package/dist/handlers/renameHandler.test.d.ts.map +0 -1
  129. package/dist/handlers/renameHandler.test.js +0 -189
  130. package/dist/handlers/resolveProjectFlag.test.d.ts +0 -2
  131. package/dist/handlers/resolveProjectFlag.test.d.ts.map +0 -1
  132. package/dist/handlers/resolveProjectFlag.test.js +0 -48
  133. package/dist/handlers/selectProject.test.d.ts +0 -2
  134. package/dist/handlers/selectProject.test.d.ts.map +0 -1
  135. package/dist/handlers/selectProject.test.js +0 -224
  136. package/dist/handlers/setProject.test.d.ts +0 -2
  137. package/dist/handlers/setProject.test.d.ts.map +0 -1
  138. package/dist/handlers/setProject.test.js +0 -63
  139. package/dist/handlers/slugUpdate.test.d.ts +0 -2
  140. package/dist/handlers/slugUpdate.test.d.ts.map +0 -1
  141. package/dist/handlers/slugUpdate.test.js +0 -265
  142. package/dist/handlers/timestampConversion.test.d.ts +0 -2
  143. package/dist/handlers/timestampConversion.test.d.ts.map +0 -1
  144. package/dist/handlers/timestampConversion.test.js +0 -87
  145. package/dist/handlers/upgradeCheck.test.d.ts +0 -2
  146. package/dist/handlers/upgradeCheck.test.d.ts.map +0 -1
  147. package/dist/handlers/upgradeCheck.test.js +0 -227
  148. package/dist/handlers/validate.test.d.ts +0 -2
  149. package/dist/handlers/validate.test.d.ts.map +0 -1
  150. package/dist/handlers/validate.test.js +0 -318
  151. package/dist/handlers/validateSpaceFilter.test.d.ts +0 -2
  152. package/dist/handlers/validateSpaceFilter.test.d.ts.map +0 -1
  153. package/dist/handlers/validateSpaceFilter.test.js +0 -79
  154. package/dist/handlers/warehouseConnection.test.d.ts +0 -2
  155. package/dist/handlers/warehouseConnection.test.d.ts.map +0 -1
  156. package/dist/handlers/warehouseConnection.test.js +0 -75
  157. package/dist/lightdash-config/lightdash-config.test.d.ts +0 -2
  158. package/dist/lightdash-config/lightdash-config.test.d.ts.map +0 -1
  159. package/dist/lightdash-config/lightdash-config.test.js +0 -69
  160. package/dist/prompts/fuzzySearchPrompt.test.d.ts +0 -2
  161. package/dist/prompts/fuzzySearchPrompt.test.d.ts.map +0 -1
  162. package/dist/prompts/fuzzySearchPrompt.test.js +0 -53
  163. package/dist/refsArgument.test.d.ts +0 -2
  164. package/dist/refsArgument.test.d.ts.map +0 -1
  165. package/dist/refsArgument.test.js +0 -42
  166. package/dist/releaseSafety/index.test.d.ts +0 -2
  167. package/dist/releaseSafety/index.test.d.ts.map +0 -1
  168. package/dist/releaseSafety/index.test.js +0 -154
  169. package/dist/releaseSafety/version.test.d.ts +0 -2
  170. package/dist/releaseSafety/version.test.d.ts.map +0 -1
  171. package/dist/releaseSafety/version.test.js +0 -22
  172. package/dist/skills.test.d.ts +0 -2
  173. package/dist/skills.test.d.ts.map +0 -1
  174. package/dist/skills.test.js +0 -112
  175. package/dist/terminal/contentAsCodeOutput.test.d.ts +0 -2
  176. package/dist/terminal/contentAsCodeOutput.test.d.ts.map +0 -1
  177. package/dist/terminal/contentAsCodeOutput.test.js +0 -231
@@ -1,637 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- const common_1 = require("@lightdash/common");
5
- const promises_1 = tslib_1.__importDefault(require("fs/promises"));
6
- const node_fetch_1 = require("node-fetch");
7
- const os_1 = tslib_1.__importDefault(require("os"));
8
- const path_1 = tslib_1.__importDefault(require("path"));
9
- const context_1 = require("../dbt/context");
10
- const manifest_1 = require("../dbt/manifest");
11
- const validation_1 = require("../dbt/validation");
12
- const loader_1 = require("../lightdash/loader");
13
- const projectType_1 = require("../lightdash/projectType");
14
- const compile_1 = require("./compile");
15
- const apiClient_1 = require("./dbt/apiClient");
16
- const compile_2 = require("./dbt/compile");
17
- const getDbtVersion_1 = require("./dbt/getDbtVersion");
18
- vi.mock('../analytics/analytics');
19
- vi.mock('../config', () => ({
20
- getConfig: vi.fn().mockResolvedValue({ user: null, context: null }),
21
- }));
22
- vi.mock('../dbt/context');
23
- vi.mock('../dbt/manifest', async (importOriginal) => ({
24
- ...(await importOriginal()),
25
- loadCombineManifest: vi.fn(),
26
- loadManifest: vi.fn(),
27
- }));
28
- vi.mock('../dbt/validation');
29
- vi.mock('../lightdash/loader');
30
- vi.mock('./dbt/compile');
31
- vi.mock('./dbt/getDbtVersion');
32
- vi.mock('./dbt/apiClient', async (importOriginal) => ({
33
- ...(await importOriginal()),
34
- lightdashRawApi: vi.fn(),
35
- }));
36
- const dbtNode = (uniqueId, resourceType, compiled, extra = {}) => ({
37
- unique_id: uniqueId,
38
- name: uniqueId.split('.').at(-1) ?? uniqueId,
39
- resource_type: resourceType,
40
- package_name: 'test',
41
- path: `${uniqueId}.sql`,
42
- original_file_path: `models/${uniqueId}.sql`,
43
- alias: uniqueId.split('.').at(-1) ?? uniqueId,
44
- checksum: { name: 'sha256', checksum: uniqueId },
45
- tags: [],
46
- refs: [],
47
- sources: [],
48
- depends_on: { macros: [], nodes: [] },
49
- database: 'db',
50
- schema: 'public',
51
- fqn: ['test', uniqueId],
52
- raw_code: 'SELECT 1',
53
- columns: {
54
- id: {
55
- name: 'id',
56
- data_type: common_1.DimensionType.NUMBER,
57
- meta: {},
58
- },
59
- },
60
- meta: {},
61
- description: '',
62
- created_at: 0,
63
- language: 'sql',
64
- relation_name: `"db"."public"."${uniqueId}"`,
65
- config: { materialized: 'table' },
66
- compiled,
67
- ...extra,
68
- });
69
- const manifest = (nodes) => ({
70
- metadata: {
71
- dbt_schema_version: 'https://schemas.getdbt.com/dbt/manifest/v12.json',
72
- generated_at: '2026-01-01T00:00:00Z',
73
- adapter_type: 'postgres',
74
- },
75
- nodes,
76
- sources: {},
77
- macros: {},
78
- docs: {},
79
- exposures: {},
80
- metrics: {},
81
- });
82
- const compileOptions = (projectDir) => ({
83
- projectDir,
84
- profilesDir: '',
85
- target: undefined,
86
- profile: undefined,
87
- vars: undefined,
88
- verbose: false,
89
- startOfWeek: 0,
90
- skipWarehouseCatalog: true,
91
- skipDbtCompile: true,
92
- useDbtList: false,
93
- select: undefined,
94
- models: undefined,
95
- threads: undefined,
96
- noVersionCheck: false,
97
- exclude: undefined,
98
- selector: undefined,
99
- state: undefined,
100
- fullRefresh: false,
101
- defer: false,
102
- targetPath: undefined,
103
- favorState: false,
104
- combineManifest: undefined,
105
- warehouseCredentials: false,
106
- disableTimestampConversion: false,
107
- });
108
- describe('compileProject completeness', () => {
109
- let tempDir;
110
- beforeEach(async () => {
111
- vi.clearAllMocks();
112
- tempDir = await promises_1.default.mkdtemp(path_1.default.join(os_1.default.tmpdir(), 'lightdash-compile-project-test-'));
113
- await promises_1.default.writeFile(path_1.default.join(tempDir, 'lightdash.config.yml'), 'warehouse:\n type: postgres\n');
114
- vi.mocked(getDbtVersion_1.tryGetDbtVersion).mockResolvedValue({
115
- success: true,
116
- version: {
117
- verboseVersion: '1.10.19',
118
- versionOption: common_1.SupportedDbtVersions.V1_10,
119
- isDbtCloudCLI: false,
120
- isDbtFusion: false,
121
- },
122
- });
123
- vi.mocked(context_1.getDbtContext).mockResolvedValue({
124
- projectName: 'test_project',
125
- profileName: 'test_profile',
126
- targetDir: path_1.default.join(tempDir, 'target'),
127
- modelsDir: 'models',
128
- });
129
- vi.mocked(loader_1.loadLightdashModels).mockResolvedValue([]);
130
- vi.mocked(validation_1.validateDbtModel).mockImplementation(async (_adapter, _version, models) => ({
131
- valid: models,
132
- invalid: [],
133
- skipped: [],
134
- }));
135
- vi.spyOn(console, 'error').mockImplementation(() => undefined);
136
- vi.spyOn(console, 'info').mockImplementation(() => undefined);
137
- });
138
- afterEach(async () => {
139
- vi.restoreAllMocks();
140
- await promises_1.default.rm(tempDir, { recursive: true, force: true });
141
- });
142
- test.each([false, true])('compiles dbt when ignored YAML is malformed, symlinked models: %s', async (symlinkedModels) => {
143
- const projectDir = path_1.default.join(tempDir, 'dbt-project');
144
- const modelsDir = symlinkedModels
145
- ? path_1.default.join(tempDir, 'shared-models')
146
- : path_1.default.join(projectDir, 'models');
147
- await promises_1.default.mkdir(projectDir);
148
- await promises_1.default.mkdir(modelsDir);
149
- if (symlinkedModels)
150
- await promises_1.default.symlink(modelsDir, path_1.default.join(projectDir, 'models'));
151
- await promises_1.default.writeFile(path_1.default.join(projectDir, 'dbt_project.yml'), 'name: test_project\nversion: "1.0"\nconfig-version: 2\n');
152
- await promises_1.default.writeFile(path_1.default.join(projectDir, '.dbtignore'), 'models/archived.yml\n');
153
- await promises_1.default.writeFile(path_1.default.join(modelsDir, 'schema.yml'), 'version: 2\nmodels:\n - name: orders\n');
154
- await promises_1.default.writeFile(path_1.default.join(modelsDir, 'archived.yml'), 'archived: [unfinished\n');
155
- const loader = await vi.importActual('../lightdash/loader');
156
- vi.mocked(loader_1.findLightdashModelFiles).mockImplementationOnce(loader.findLightdashModelFiles);
157
- vi.mocked(loader_1.loadLightdashModels).mockImplementationOnce(loader.loadLightdashModels);
158
- vi.mocked(manifest_1.loadManifest).mockResolvedValue(manifest({
159
- 'model.test.orders': dbtNode('model.test.orders', 'model', true),
160
- }));
161
- vi.mocked(compile_2.maybeCompileModelsAndJoins).mockResolvedValue({
162
- compiledModelIds: ['model.test.orders'],
163
- originallySelectedModelIds: undefined,
164
- });
165
- await expect((0, projectType_1.detectProjectType)({ projectDir })).resolves.toMatchObject({ type: projectType_1.CliProjectType.Dbt });
166
- const result = await (0, compile_1.compileProject)(compileOptions(projectDir));
167
- expect(result.explores.map((explore) => explore.name)).toEqual([
168
- 'orders',
169
- ]);
170
- expect(compile_2.maybeCompileModelsAndJoins).toHaveBeenCalled();
171
- });
172
- test('reports an unselected model and seed manifest as complete', async () => {
173
- const projectManifest = manifest({
174
- 'model.test.orders': dbtNode('model.test.orders', 'model', true),
175
- 'seed.test.countries': dbtNode('seed.test.countries', 'seed', false),
176
- });
177
- vi.mocked(manifest_1.loadManifest).mockResolvedValue(projectManifest);
178
- vi.mocked(compile_2.maybeCompileModelsAndJoins).mockResolvedValue({
179
- compiledModelIds: ['model.test.orders'],
180
- originallySelectedModelIds: undefined,
181
- });
182
- const result = await (0, compile_1.compileProject)(compileOptions(tempDir));
183
- expect(result.isProjectComplete).toBe(true);
184
- expect(result.dbtModelNames).toEqual([
185
- 'orders',
186
- 'test__orders',
187
- 'countries',
188
- 'test__countries',
189
- ]);
190
- });
191
- test('reports a selected subset as incomplete', async () => {
192
- const projectManifest = manifest({
193
- 'model.test.orders': dbtNode('model.test.orders', 'model', true),
194
- 'model.test.customers': dbtNode('model.test.customers', 'model', true),
195
- });
196
- vi.mocked(manifest_1.loadManifest).mockResolvedValue(projectManifest);
197
- vi.mocked(compile_2.maybeCompileModelsAndJoins).mockResolvedValue({
198
- compiledModelIds: ['model.test.orders'],
199
- originallySelectedModelIds: ['model.test.orders'],
200
- });
201
- const result = await (0, compile_1.compileProject)(compileOptions(tempDir));
202
- expect(result.isProjectComplete).toBe(false);
203
- expect(result.dbtModelNames).toEqual([
204
- 'orders',
205
- 'test__orders',
206
- 'customers',
207
- 'test__customers',
208
- ]);
209
- });
210
- test('omits cleanup inventory for YAML projects', async () => {
211
- vi.mocked(loader_1.loadLightdashModels).mockResolvedValue([
212
- {
213
- type: 'model',
214
- name: 'orders',
215
- sql_from: 'SELECT 1 AS id',
216
- dimensions: [
217
- { name: 'id', type: common_1.DimensionType.NUMBER, sql: 'id' },
218
- ],
219
- sourcePath: 'models/orders.yml',
220
- },
221
- ]);
222
- const result = await (0, compile_1.compileProject)(compileOptions(tempDir));
223
- expect(result.dbtModelNames).toBeUndefined();
224
- expect(manifest_1.loadManifest).not.toHaveBeenCalled();
225
- });
226
- test.each(['lightdash_source_name', 'lightdash_source_uuid'])('omits cleanup inventory for a manifest annotated with %s', async (sourceField) => {
227
- vi.mocked(manifest_1.loadManifest).mockResolvedValue(manifest({
228
- 'model.test.orders': dbtNode('model.test.orders', 'model', true, {
229
- [sourceField]: 'source-a',
230
- }),
231
- }));
232
- vi.mocked(compile_2.maybeCompileModelsAndJoins).mockResolvedValue({
233
- compiledModelIds: ['model.test.orders'],
234
- originallySelectedModelIds: undefined,
235
- });
236
- const result = await (0, compile_1.compileProject)(compileOptions(tempDir));
237
- expect(result.dbtModelNames).toBeUndefined();
238
- });
239
- test('derives completeness before combining an external manifest', async () => {
240
- const projectManifest = manifest({
241
- 'model.test.orders': dbtNode('model.test.orders', 'model', true),
242
- });
243
- const externalManifest = manifest({
244
- 'model.external.compiled': dbtNode('model.external.compiled', 'model', true),
245
- 'model.external.uncompiled': dbtNode('model.external.uncompiled', 'model', false),
246
- });
247
- vi.mocked(manifest_1.loadManifest).mockResolvedValue(projectManifest);
248
- vi.mocked(manifest_1.loadCombineManifest).mockResolvedValue(externalManifest);
249
- vi.mocked(compile_2.maybeCompileModelsAndJoins).mockResolvedValue({
250
- compiledModelIds: ['model.test.orders'],
251
- originallySelectedModelIds: undefined,
252
- });
253
- const result = await (0, compile_1.compileProject)({
254
- ...compileOptions(tempDir),
255
- combineManifest: 'external-manifest.json',
256
- combineManifestProjectUuid: 'project-uuid',
257
- });
258
- expect(result.isProjectComplete).toBe(true);
259
- expect(result.explores.map((explore) => explore.name)).toEqual([
260
- 'orders',
261
- 'compiled',
262
- ]);
263
- expect(result.dbtModelNames).toBeUndefined();
264
- expect(apiClient_1.lightdashRawApi).not.toHaveBeenCalled();
265
- expect(console.info).toHaveBeenCalledWith(expect.stringContaining('Combined external manifest from'));
266
- });
267
- test('projects, merges, and compiles served-only models while preserving local precedence and source identity', async () => {
268
- const projectManifest = manifest({
269
- 'model.test.orders': dbtNode('model.test.orders', 'model', true, {
270
- description: 'Local orders description',
271
- }),
272
- });
273
- const servedManifest = (0, common_1.projectMergedManifest)(manifest({
274
- 'model.test.orders': dbtNode('model.test.orders', 'model', true, {
275
- description: 'Served orders description',
276
- lightdash_source_name: 'local_source',
277
- }),
278
- 'model.served.customers': dbtNode('model.served.customers', 'model', true, {
279
- package_name: 'served',
280
- lightdash_source_name: 'served_source',
281
- }),
282
- 'model.served.customer_helper': dbtNode('model.served.customer_helper', 'model', false, {
283
- package_name: 'served',
284
- lightdash_source_name: 'served_source',
285
- }),
286
- }));
287
- vi.mocked(manifest_1.loadManifest).mockResolvedValue(projectManifest);
288
- vi.mocked(apiClient_1.lightdashRawApi).mockResolvedValue(new node_fetch_1.Response(JSON.stringify(servedManifest)));
289
- vi.mocked(compile_2.maybeCompileModelsAndJoins).mockResolvedValue({
290
- compiledModelIds: ['model.test.orders'],
291
- originallySelectedModelIds: undefined,
292
- });
293
- const result = await (0, compile_1.compileProject)({
294
- ...compileOptions(tempDir),
295
- combineManifestProjectUuid: 'project-uuid',
296
- });
297
- expect(result.explores.map((explore) => explore.name)).toEqual([
298
- 'orders',
299
- 'customers',
300
- ]);
301
- expect(result.isProjectComplete).toBe(true);
302
- expect(result.dbtModelNames).toBeUndefined();
303
- expect(apiClient_1.lightdashRawApi).toHaveBeenCalledWith({
304
- method: 'GET',
305
- url: '/api/v1/projects/project-uuid/dbt/manifest',
306
- body: undefined,
307
- });
308
- expect(console.info).toHaveBeenCalledWith(expect.stringMatching(/added [1-9]\d* model\(s\)/));
309
- const modelsForValidation = vi.mocked(validation_1.validateDbtModel).mock.calls[0][2];
310
- const localModel = modelsForValidation.find((model) => model.unique_id === 'model.test.orders');
311
- expect(localModel.description).toBe('Local orders description');
312
- expect(localModel.lightdash_source_name).toBe('local_source');
313
- expect(modelsForValidation.map((model) => model.unique_id)).not.toContain('model.served.customer_helper');
314
- expect(vi.mocked(validation_1.validateDbtModel).mock.calls[0][3]).toEqual(new Set(['model.served.customers']));
315
- });
316
- test('replaces the complete local source while retaining served models from other sources', async () => {
317
- const projectManifest = manifest({
318
- 'model.local.orders': dbtNode('model.local.orders', 'model', true, {
319
- description: 'Local orders description',
320
- }),
321
- });
322
- const servedManifest = (0, common_1.projectMergedManifest)(manifest({
323
- 'model.local.orders': dbtNode('model.local.orders', 'model', true, {
324
- description: 'Served orders description',
325
- lightdash_source_name: 'local_source',
326
- }),
327
- 'model.local.deleted': dbtNode('model.local.deleted', 'model', true, {
328
- lightdash_source_name: 'local_source',
329
- }),
330
- 'model.other.customers': dbtNode('model.other.customers', 'model', true, {
331
- lightdash_source_name: 'other_source',
332
- }),
333
- }));
334
- vi.mocked(manifest_1.loadManifest).mockResolvedValue(projectManifest);
335
- vi.mocked(apiClient_1.lightdashRawApi).mockResolvedValue(new node_fetch_1.Response(JSON.stringify(servedManifest)));
336
- vi.mocked(compile_2.maybeCompileModelsAndJoins).mockResolvedValue({
337
- compiledModelIds: ['model.local.orders'],
338
- originallySelectedModelIds: undefined,
339
- });
340
- const result = await (0, compile_1.compileProject)({
341
- ...compileOptions(tempDir),
342
- combineManifestProjectUuid: 'project-uuid',
343
- });
344
- expect(result.isProjectComplete).toBe(true);
345
- expect(result.explores.map((explore) => explore.name)).toEqual([
346
- 'orders',
347
- 'customers',
348
- ]);
349
- const modelsForValidation = vi.mocked(validation_1.validateDbtModel).mock.calls[0][2];
350
- expect(modelsForValidation).toEqual(expect.arrayContaining([
351
- expect.objectContaining({
352
- unique_id: 'model.local.orders',
353
- description: 'Local orders description',
354
- lightdash_source_name: 'local_source',
355
- }),
356
- expect.objectContaining({
357
- unique_id: 'model.other.customers',
358
- lightdash_source_name: 'other_source',
359
- }),
360
- ]));
361
- expect(modelsForValidation.map((model) => model.unique_id)).not.toContain('model.local.deleted');
362
- });
363
- test('additively combines selective local models with compiled served collision candidates', async () => {
364
- const projectManifest = manifest({
365
- 'model.source_a.orders': dbtNode('model.source_a.orders', 'model', true, {
366
- description: 'Local selected orders',
367
- }),
368
- 'model.source_a.customers': dbtNode('model.source_a.customers', 'model', true, {
369
- description: 'Local unselected customers',
370
- }),
371
- });
372
- const servedManifest = (0, common_1.projectMergedManifest)(manifest({
373
- 'model.source_a.orders': dbtNode('model.source_a.orders', 'model', true, {
374
- description: 'Served selected orders',
375
- lightdash_source_name: 'source_a',
376
- }),
377
- 'model.source_a.customers': dbtNode('model.source_a.customers', 'model', true, {
378
- description: 'Served unselected customers',
379
- lightdash_source_name: 'source_a',
380
- }),
381
- 'model.source_a.deleted': dbtNode('model.source_a.deleted', 'model', true, {
382
- lightdash_source_name: 'source_a',
383
- }),
384
- 'model.source_b.customers': dbtNode('model.source_b.customers', 'model', true, {
385
- lightdash_source_name: 'source_b',
386
- }),
387
- }));
388
- vi.mocked(manifest_1.loadManifest).mockResolvedValue(projectManifest);
389
- vi.mocked(apiClient_1.lightdashRawApi).mockResolvedValue(new node_fetch_1.Response(JSON.stringify(servedManifest)));
390
- vi.mocked(compile_2.maybeCompileModelsAndJoins).mockResolvedValue({
391
- compiledModelIds: ['model.source_a.orders'],
392
- originallySelectedModelIds: ['model.source_a.orders'],
393
- });
394
- const result = await (0, compile_1.compileProject)({
395
- ...compileOptions(tempDir),
396
- combineManifestProjectUuid: 'project-uuid',
397
- });
398
- expect(result.isProjectComplete).toBe(false);
399
- const modelsForValidation = vi.mocked(validation_1.validateDbtModel).mock.calls[0][2];
400
- expect(modelsForValidation).toEqual(expect.arrayContaining([
401
- expect.objectContaining({
402
- unique_id: 'model.source_a.orders',
403
- description: 'Local selected orders',
404
- lightdash_source_name: 'source_a',
405
- }),
406
- expect.objectContaining({
407
- unique_id: 'model.source_a.customers',
408
- description: 'Served unselected customers',
409
- compiled: true,
410
- lightdash_source_name: 'source_a',
411
- }),
412
- expect.objectContaining({
413
- unique_id: 'model.source_a.deleted',
414
- lightdash_source_name: 'source_a',
415
- }),
416
- expect.objectContaining({
417
- unique_id: 'model.source_b.customers',
418
- lightdash_source_name: 'source_b',
419
- }),
420
- ]));
421
- const unselectedCollisionCandidates = modelsForValidation.filter((model) => model.name === 'customers');
422
- expect(unselectedCollisionCandidates.map((model) => ({
423
- uniqueId: model.unique_id,
424
- sourceName: model.lightdash_source_name,
425
- }))).toEqual([
426
- {
427
- uniqueId: 'model.source_a.customers',
428
- sourceName: 'source_a',
429
- },
430
- {
431
- uniqueId: 'model.source_b.customers',
432
- sourceName: 'source_b',
433
- },
434
- ]);
435
- });
436
- test('rejects automatic combination when overlaps identify multiple local sources', async () => {
437
- const projectManifest = manifest({
438
- 'model.local.orders': dbtNode('model.local.orders', 'model', true),
439
- 'model.local.customers': dbtNode('model.local.customers', 'model', true),
440
- });
441
- const servedManifest = manifest({
442
- 'model.local.orders': dbtNode('model.local.orders', 'model', true, {
443
- lightdash_source_name: 'source_a',
444
- }),
445
- 'model.local.customers': dbtNode('model.local.customers', 'model', true, {
446
- lightdash_source_name: 'source_c',
447
- }),
448
- });
449
- vi.mocked(manifest_1.loadManifest).mockResolvedValue(projectManifest);
450
- vi.mocked(apiClient_1.lightdashRawApi).mockResolvedValue(new node_fetch_1.Response(JSON.stringify(servedManifest)));
451
- vi.mocked(compile_2.maybeCompileModelsAndJoins).mockResolvedValue({
452
- compiledModelIds: ['model.local.orders', 'model.local.customers'],
453
- originallySelectedModelIds: undefined,
454
- });
455
- await expect((0, compile_1.compileProject)({
456
- ...compileOptions(tempDir),
457
- combineManifestProjectUuid: 'project-uuid',
458
- })).rejects.toThrow('Cannot automatically combine manifest from the server: overlapping local models match multiple Lightdash sources (source_a, source_c)');
459
- expect(validation_1.validateDbtModel).not.toHaveBeenCalled();
460
- });
461
- test('skips automatic combination when the local dbt project is not a served source', async () => {
462
- const projectManifest = manifest({
463
- 'model.local.orders': dbtNode('model.local.orders', 'model', true),
464
- });
465
- const servedManifest = manifest({
466
- 'model.served.customers': dbtNode('model.served.customers', 'model', true),
467
- });
468
- vi.mocked(manifest_1.loadManifest).mockResolvedValue(projectManifest);
469
- vi.mocked(apiClient_1.lightdashRawApi).mockResolvedValue(new node_fetch_1.Response(JSON.stringify(servedManifest)));
470
- vi.mocked(compile_2.maybeCompileModelsAndJoins).mockResolvedValue({
471
- compiledModelIds: ['model.local.orders'],
472
- originallySelectedModelIds: undefined,
473
- });
474
- const result = await (0, compile_1.compileProject)({
475
- ...compileOptions(tempDir),
476
- combineManifestProjectUuid: 'project-uuid',
477
- });
478
- expect(result.explores.map((explore) => explore.name)).toEqual([
479
- 'orders',
480
- ]);
481
- expect(console.info).toHaveBeenCalledWith(expect.stringContaining('the local dbt project is not a source of this Lightdash project'));
482
- });
483
- test('explains when a matching served manifest has no compiled models', async () => {
484
- const projectManifest = manifest({
485
- 'model.test.orders': dbtNode('model.test.orders', 'model', true),
486
- });
487
- const servedManifest = manifest({
488
- 'model.test.orders': dbtNode('model.test.orders', 'model', false, {
489
- lightdash_source_name: 'local_source',
490
- }),
491
- 'model.served.helper': dbtNode('model.served.helper', 'model', false),
492
- });
493
- vi.mocked(manifest_1.loadManifest).mockResolvedValue(projectManifest);
494
- vi.mocked(apiClient_1.lightdashRawApi).mockResolvedValue(new node_fetch_1.Response(JSON.stringify(servedManifest)));
495
- vi.mocked(compile_2.maybeCompileModelsAndJoins).mockResolvedValue({
496
- compiledModelIds: ['model.test.orders'],
497
- originallySelectedModelIds: undefined,
498
- });
499
- await (0, compile_1.compileProject)({
500
- ...compileOptions(tempDir),
501
- combineManifestProjectUuid: 'project-uuid',
502
- });
503
- expect(console.info).toHaveBeenCalledWith(expect.stringContaining('contains no compiled models'));
504
- });
505
- test('explains when all compiled served models already overlap locally', async () => {
506
- const projectManifest = manifest({
507
- 'model.test.orders': dbtNode('model.test.orders', 'model', true),
508
- });
509
- const servedManifest = manifest({
510
- 'model.test.orders': dbtNode('model.test.orders', 'model', true, {
511
- lightdash_source_name: 'local_source',
512
- }),
513
- });
514
- vi.mocked(manifest_1.loadManifest).mockResolvedValue(projectManifest);
515
- vi.mocked(apiClient_1.lightdashRawApi).mockResolvedValue(new node_fetch_1.Response(JSON.stringify(servedManifest)));
516
- vi.mocked(compile_2.maybeCompileModelsAndJoins).mockResolvedValue({
517
- compiledModelIds: ['model.test.orders'],
518
- originallySelectedModelIds: undefined,
519
- });
520
- await (0, compile_1.compileProject)({
521
- ...compileOptions(tempDir),
522
- combineManifestProjectUuid: 'project-uuid',
523
- });
524
- expect(console.info).toHaveBeenCalledWith(expect.stringContaining('all compiled models already exist in the preview manifest'));
525
- });
526
- test('notices when no served manifest exists and keeps the local manifest', async () => {
527
- vi.mocked(manifest_1.loadManifest).mockResolvedValue(manifest({
528
- 'model.test.orders': dbtNode('model.test.orders', 'model', true),
529
- }));
530
- vi.mocked(apiClient_1.lightdashRawApi).mockRejectedValue(new common_1.LightdashError({
531
- message: 'Manifest not found',
532
- name: 'NotFoundError',
533
- statusCode: 404,
534
- data: {},
535
- }));
536
- vi.mocked(compile_2.maybeCompileModelsAndJoins).mockResolvedValue({
537
- compiledModelIds: ['model.test.orders'],
538
- originallySelectedModelIds: undefined,
539
- });
540
- const result = await (0, compile_1.compileProject)({
541
- ...compileOptions(tempDir),
542
- combineManifestProjectUuid: 'project-uuid',
543
- });
544
- expect(result.explores.map((explore) => explore.name)).toEqual([
545
- 'orders',
546
- ]);
547
- expect(console.error).not.toHaveBeenCalledWith(expect.stringContaining('Could not fetch the server manifest'));
548
- expect(console.info).toHaveBeenCalledWith(expect.stringContaining('No server manifest found; continuing with the preview manifest'));
549
- });
550
- test.each([
551
- ['a null response', null],
552
- ['an array of nodes', { metadata: {}, nodes: [] }],
553
- ['array metadata', { metadata: [], nodes: {} }],
554
- ['missing metadata', { nodes: {} }],
555
- ])('rejects %s from the server manifest endpoint and keeps the local manifest', async (_description, invalidManifest) => {
556
- vi.mocked(manifest_1.loadManifest).mockResolvedValue(manifest({
557
- 'model.test.orders': dbtNode('model.test.orders', 'model', true),
558
- }));
559
- vi.mocked(apiClient_1.lightdashRawApi).mockResolvedValue(new node_fetch_1.Response(JSON.stringify(invalidManifest)));
560
- vi.mocked(compile_2.maybeCompileModelsAndJoins).mockResolvedValue({
561
- compiledModelIds: ['model.test.orders'],
562
- originallySelectedModelIds: undefined,
563
- });
564
- const result = await (0, compile_1.compileProject)({
565
- ...compileOptions(tempDir),
566
- combineManifestProjectUuid: 'project-uuid',
567
- });
568
- expect(result.explores.map((explore) => explore.name)).toEqual([
569
- 'orders',
570
- ]);
571
- expect(console.error).toHaveBeenCalledWith(expect.stringContaining('/api/v1/projects/project-uuid/dbt/manifest returned an invalid manifest'));
572
- });
573
- test.each([
574
- [
575
- 'an authorization error',
576
- new common_1.LightdashError({
577
- message: 'Not authorized',
578
- name: 'AuthorizationError',
579
- statusCode: 401,
580
- data: {},
581
- }),
582
- ],
583
- [
584
- 'a server error',
585
- new common_1.LightdashError({
586
- message: 'Server unavailable',
587
- name: 'InternalServerError',
588
- statusCode: 500,
589
- data: {},
590
- }),
591
- ],
592
- [
593
- 'a permission error',
594
- new common_1.LightdashError({
595
- message: 'Forbidden',
596
- name: 'ForbiddenError',
597
- statusCode: 403,
598
- data: {},
599
- }),
600
- ],
601
- ['a network error', new Error('Connection refused')],
602
- ])('warns once and keeps the local manifest after %s', async (_description, error) => {
603
- vi.mocked(manifest_1.loadManifest).mockResolvedValue(manifest({
604
- 'model.test.orders': dbtNode('model.test.orders', 'model', true),
605
- }));
606
- vi.mocked(apiClient_1.lightdashRawApi).mockRejectedValue(error);
607
- vi.mocked(compile_2.maybeCompileModelsAndJoins).mockResolvedValue({
608
- compiledModelIds: ['model.test.orders'],
609
- originallySelectedModelIds: undefined,
610
- });
611
- const result = await (0, compile_1.compileProject)({
612
- ...compileOptions(tempDir),
613
- combineManifestProjectUuid: 'project-uuid',
614
- });
615
- expect(result.explores.map((explore) => explore.name)).toEqual([
616
- 'orders',
617
- ]);
618
- expect(vi
619
- .mocked(console.error)
620
- .mock.calls.filter(([message]) => String(message).includes('Could not fetch the server manifest'))).toHaveLength(1);
621
- });
622
- test('does not fetch a served manifest when manifest combining is disabled', async () => {
623
- vi.mocked(manifest_1.loadManifest).mockResolvedValue(manifest({
624
- 'model.test.orders': dbtNode('model.test.orders', 'model', true),
625
- }));
626
- vi.mocked(compile_2.maybeCompileModelsAndJoins).mockResolvedValue({
627
- compiledModelIds: ['model.test.orders'],
628
- originallySelectedModelIds: undefined,
629
- });
630
- await (0, compile_1.compileProject)({
631
- ...compileOptions(tempDir),
632
- combine: false,
633
- combineManifestProjectUuid: 'project-uuid',
634
- });
635
- expect(apiClient_1.lightdashRawApi).not.toHaveBeenCalled();
636
- });
637
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=compileWarehouseColumnValidation.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"compileWarehouseColumnValidation.test.d.ts","sourceRoot":"","sources":["../../src/handlers/compileWarehouseColumnValidation.test.ts"],"names":[],"mappings":""}