@lightdash/cli 2.174.0 → 2.175.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.
@@ -1 +1 @@
1
- {"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/handlers/compile.ts"],"names":[],"mappings":"AAAA,OAAO,EAOH,OAAO,EACP,YAAY,EAkBf,MAAM,mBAAmB,CAAC;AAqB3B,OAAO,EAAE,iBAAiB,EAA8B,MAAM,eAAe,CAAC;AAsB9E,MAAM,MAAM,qBAAqB,GAAG,iBAAiB,GAAG;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IAC/B,QAAQ,EAAE,CAAC,OAAO,GAAG,YAAY,CAAC,EAAE,CAAC;IACrC,iBAAiB,EAAE,OAAO,CAAC;CAC9B,CAAC;AAEF,eAAO,MAAM,uBAAuB,YACvB,OAAO,GAAG,YAAY,KAChC,OAIW,CAAC;AAEf,eAAO,MAAM,0BAA0B,YAC1B,OAAO,GAAG,YAAY,KAChC,OAAO,GAAG,YAiBZ,CAAC;AA6TF,eAAO,MAAM,cAAc,YACd,qBAAqB,KAC/B,OAAO,CAAC,oBAAoB,CA2a9B,CAAC;AAEF,eAAO,MAAM,OAAO,YACP,qBAAqB,KAC/B,OAAO,CAAC,CAAC,OAAO,GAAG,YAAY,CAAC,EAAE,CACO,CAAC;AAE7C,eAAO,MAAM,cAAc,oBACN,qBAAqB,kBAmCzC,CAAC"}
1
+ {"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/handlers/compile.ts"],"names":[],"mappings":"AAAA,OAAO,EAOH,OAAO,EACP,YAAY,EAkBf,MAAM,mBAAmB,CAAC;AAqB3B,OAAO,EAAE,iBAAiB,EAA8B,MAAM,eAAe,CAAC;AAsB9E,MAAM,MAAM,qBAAqB,GAAG,iBAAiB,GAAG;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IAC/B,QAAQ,EAAE,CAAC,OAAO,GAAG,YAAY,CAAC,EAAE,CAAC;IACrC,iBAAiB,EAAE,OAAO,CAAC;CAC9B,CAAC;AAEF,eAAO,MAAM,uBAAuB,YACvB,OAAO,GAAG,YAAY,KAChC,OAIW,CAAC;AAEf,eAAO,MAAM,0BAA0B,YAC1B,OAAO,GAAG,YAAY,KAChC,OAAO,GAAG,YAiBZ,CAAC;AAgTF,eAAO,MAAM,cAAc,YACd,qBAAqB,KAC/B,OAAO,CAAC,oBAAoB,CA2a9B,CAAC;AAEF,eAAO,MAAM,OAAO,YACP,qBAAqB,KAC/B,OAAO,CAAC,CAAC,OAAO,GAAG,YAAY,CAAC,EAAE,CACO,CAAC;AAE7C,eAAO,MAAM,cAAc,oBACN,qBAAqB,kBAmCzC,CAAC"}
@@ -133,14 +133,11 @@ const getExploresFromLightdashYmlProject = async ({ projectDir, lightdashProject
133
133
  }
134
134
  const adapterType = lightdashProjectConfig.warehouse.type;
135
135
  globalState_1.default.debug(`> Using adapter type from lightdash.config.yml: ${adapterType}`);
136
- // Convert Lightdash models to DbtModelNode format
137
- const validModels = (0, common_1.convertLightdashModelsToDbtModels)(lightdashModels);
138
- if (validModels.length === 0) {
139
- return null;
140
- }
141
- globalState_1.default.debug('> Skipping warehouse catalog (types in YAML)');
142
136
  const warehouseSqlBuilder = (0, warehouses_1.warehouseSqlBuilderFromType)(adapterType, startOfWeek);
143
- const validExplores = await (0, common_1.convertExplores)(validModels, false, warehouseSqlBuilder.getAdapterType(), warehouseSqlBuilder, lightdashProjectConfig, {
137
+ const validExplores = await (0, common_1.compileLightdashModels)({
138
+ models: lightdashModels,
139
+ warehouseSqlBuilder,
140
+ lightdashProjectConfig,
144
141
  disableTimestampConversion,
145
142
  allowPartialCompilation,
146
143
  postProcessors: [common_1.preAggregatePostProcessor],
@@ -116,7 +116,7 @@ dimensions:
116
116
  });
117
117
  test('should allow partial compilation by default and allow it to be disabled explicitly', async () => {
118
118
  vi.spyOn(lightdashLoader, 'loadLightdashModels').mockResolvedValue([
119
- modelWithBrokenMetric,
119
+ { ...modelWithBrokenMetric, sourcePath: 'models/test_model.yml' },
120
120
  ]);
121
121
  const errorOutput = [];
122
122
  vi.spyOn(console, 'error').mockImplementation((...args) => {
@@ -144,4 +144,8 @@ dimensions:
144
144
  expect.stringContaining('Compiled 1 explores, SUCCESS=0 ERRORS=1'),
145
145
  ]));
146
146
  });
147
+ test('rejects malformed native YAML instead of compiling only the valid models', async () => {
148
+ await promises_1.default.writeFile(path.join(tempDir, 'lightdash/models/broken.yml'), 'type: model\ndimensions: [');
149
+ await expect((0, compile_1.compile)(getCompileOptions(tempDir))).rejects.toThrow(/broken.yml/);
150
+ });
147
151
  });
@@ -10,6 +10,7 @@ const context_1 = require("../dbt/context");
10
10
  const manifest_1 = require("../dbt/manifest");
11
11
  const validation_1 = require("../dbt/validation");
12
12
  const loader_1 = require("../lightdash/loader");
13
+ const projectType_1 = require("../lightdash/projectType");
13
14
  const compile_1 = require("./compile");
14
15
  const apiClient_1 = require("./dbt/apiClient");
15
16
  const compile_2 = require("./dbt/compile");
@@ -138,6 +139,36 @@ describe('compileProject completeness', () => {
138
139
  vi.restoreAllMocks();
139
140
  await promises_1.default.rm(tempDir, { recursive: true, force: true });
140
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
+ });
141
172
  test('reports an unselected model and seed manifest as complete', async () => {
142
173
  const projectManifest = manifest({
143
174
  'model.test.orders': dbtNode('model.test.orders', 'model', true),
@@ -454,7 +454,7 @@ describe('compile warehouse column validation', () => {
454
454
  describe('lightdash yml projects', () => {
455
455
  beforeEach(async () => {
456
456
  vi.mocked(loader_1.loadLightdashModels).mockResolvedValue([
457
- lightdashYmlModel,
457
+ { ...lightdashYmlModel, sourcePath: 'models/test_model.yml' },
458
458
  ]);
459
459
  await promises_1.default.writeFile(path.join(tempDir, 'lightdash.config.yml'), 'warehouse:\n type: postgres\n');
460
460
  });
@@ -1,11 +1,5 @@
1
- /**
2
- * Loader for Lightdash YAML model files
3
- */
4
- import { type LightdashModel } from '@lightdash/common';
5
- /**
6
- * Load a single Lightdash YAML model file
7
- */
8
- export declare function loadLightdashModel(filePath: string): Promise<LightdashModel>;
1
+ import { type LightdashModelWithSource } from '@lightdash/common';
2
+ export { loadLightdashModel } from '@lightdash/common/lightdash/loader';
9
3
  /**
10
4
  * Find all Lightdash YAML model files in a directory
11
5
  * Looks for files in models/ or lightdash/models/ directory that contain `type: model`
@@ -14,8 +8,5 @@ export declare function loadLightdashModel(filePath: string): Promise<LightdashM
14
8
  * to avoid false positives from other YAML files (e.g., content-as-code spaces).
15
9
  */
16
10
  export declare function findLightdashModelFiles(projectDir: string): Promise<string[]>;
17
- /**
18
- * Load all Lightdash YAML models from a project directory
19
- */
20
- export declare function loadLightdashModels(projectDir: string): Promise<LightdashModel[]>;
11
+ export declare function loadLightdashModels(projectDir: string): Promise<LightdashModelWithSource[]>;
21
12
  //# sourceMappingURL=loader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/lightdash/loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAMpE;;GAEG;AACH,wBAAsB,kBAAkB,CACpC,QAAQ,EAAE,MAAM,GACjB,OAAO,CAAC,cAAc,CAAC,CA6BzB;AAuBD;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CACzC,UAAU,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,EAAE,CAAC,CAqDnB;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACrC,UAAU,EAAE,MAAM,GACnB,OAAO,CAAC,cAAc,EAAE,CAAC,CAwB3B"}
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/lightdash/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAOlE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAoBxE;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CACzC,UAAU,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,EAAE,CAAC,CAqDnB;AAED,wBAAsB,mBAAmB,CACrC,UAAU,EAAE,MAAM,GACnB,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAGrC"}
@@ -1,44 +1,17 @@
1
1
  "use strict";
2
- /**
3
- * Loader for Lightdash YAML model files
4
- */
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.loadLightdashModel = loadLightdashModel;
3
+ exports.loadLightdashModel = void 0;
7
4
  exports.findLightdashModelFiles = findLightdashModelFiles;
8
5
  exports.loadLightdashModels = loadLightdashModels;
9
6
  const tslib_1 = require("tslib");
10
- const common_1 = require("@lightdash/common");
7
+ const loader_1 = require("@lightdash/common/lightdash/loader");
11
8
  const fs = tslib_1.__importStar(require("fs"));
12
9
  const yaml = tslib_1.__importStar(require("js-yaml"));
13
10
  const path = tslib_1.__importStar(require("path"));
14
11
  const globalState_1 = tslib_1.__importDefault(require("../globalState"));
15
- /**
16
- * Load a single Lightdash YAML model file
17
- */
18
- async function loadLightdashModel(filePath) {
19
- try {
20
- const fileContents = await fs.promises.readFile(filePath, 'utf8');
21
- const parsed = yaml.load(fileContents);
22
- // Basic validation
23
- if (!parsed.type || !parsed.name || !parsed.dimensions) {
24
- throw new common_1.ParseError(`Invalid Lightdash model in ${filePath}: must have type, name, and dimensions`);
25
- }
26
- if (!parsed.sql_from) {
27
- throw new common_1.ParseError(`Invalid Lightdash model in ${filePath}: must have sql_from`);
28
- }
29
- return parsed;
30
- }
31
- catch (error) {
32
- if (error instanceof common_1.ParseError) {
33
- throw error;
34
- }
35
- throw new common_1.ParseError(`Failed to load Lightdash model from ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
36
- }
37
- }
38
- /**
39
- * Check if a YAML file contains a Lightdash model definition
40
- * A valid model file must have a `type` field with value 'model', 'model/v1beta', or 'model/v1'
41
- */
12
+ var loader_2 = require("@lightdash/common/lightdash/loader");
13
+ Object.defineProperty(exports, "loadLightdashModel", { enumerable: true, get: function () { return loader_2.loadLightdashModel; } });
14
+ // Format detection must tolerate files that dbt may ignore or handle itself.
42
15
  async function isLightdashModelFile(filePath) {
43
16
  try {
44
17
  const fileContents = await fs.promises.readFile(filePath, 'utf8');
@@ -101,22 +74,8 @@ async function findLightdashModelFiles(projectDir) {
101
74
  }
102
75
  return modelFiles;
103
76
  }
104
- /**
105
- * Load all Lightdash YAML models from a project directory
106
- */
107
77
  async function loadLightdashModels(projectDir) {
108
- const modelFiles = await findLightdashModelFiles(projectDir);
109
- globalState_1.default.debug(`Found ${modelFiles.length} Lightdash model files in ${projectDir}`);
110
- const models = [];
111
- for await (const filePath of modelFiles) {
112
- try {
113
- const model = await loadLightdashModel(filePath);
114
- models.push(model);
115
- globalState_1.default.debug(`Loaded Lightdash model: ${model.name}`);
116
- }
117
- catch (error) {
118
- console.error(`Warning: Failed to load ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
119
- }
120
- }
121
- return models;
78
+ if ((await findLightdashModelFiles(projectDir)).length === 0)
79
+ return [];
80
+ return (0, loader_1.loadLightdashModels)(projectDir);
122
81
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightdash/cli",
3
- "version": "2.174.0",
3
+ "version": "2.175.0",
4
4
  "description": "Lightdash CLI tool",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -45,8 +45,8 @@
45
45
  "unique-names-generator": "4.7.1",
46
46
  "uuid": "11.1.1",
47
47
  "yaml": "2.8.3",
48
- "@lightdash/common": "2.174.0",
49
- "@lightdash/warehouses": "2.174.0"
48
+ "@lightdash/common": "2.175.0",
49
+ "@lightdash/warehouses": "2.175.0"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@types/inquirer": "8.2.4",