@lightdash/cli 2.209.2 → 2.211.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.
- package/dist/.tsbuildinfo +1 -1
- package/dist/dbt/models.d.ts +15 -2
- package/dist/dbt/models.d.ts.map +1 -1
- package/dist/dbt/models.js +23 -14
- package/dist/dbt/models.test.js +79 -0
- package/dist/handlers/generate.d.ts.map +1 -1
- package/dist/handlers/generate.js +2 -1
- package/package.json +3 -3
package/dist/dbt/models.d.ts
CHANGED
|
@@ -25,11 +25,24 @@ type TableRef = {
|
|
|
25
25
|
* inside a repeated node.
|
|
26
26
|
*/
|
|
27
27
|
export declare const isGeneratableColumn: (catalog: WarehouseCatalog, { database, schema, table }: TableRef, columnPath: string) => boolean;
|
|
28
|
-
export
|
|
28
|
+
export type WarehouseModelColumns = {
|
|
29
|
+
/** Columns `generate` writes to YAML: scalars, struct leaves and arrays of scalars. */
|
|
30
|
+
table: WarehouseTableSchema;
|
|
31
|
+
/** Every column path the warehouse reports, containers and nested leaves included. */
|
|
32
|
+
warehouseColumnPaths: string[];
|
|
33
|
+
};
|
|
34
|
+
export declare const getWarehouseTableForModel: ({ model, warehouseClient, preserveColumnCase, }: GetDatabaseTableForModelArgs) => Promise<WarehouseModelColumns>;
|
|
35
|
+
/**
|
|
36
|
+
* Existing YAML columns the warehouse no longer has. Nested leaves and
|
|
37
|
+
* containers are not generated, but they are real warehouse paths, so they
|
|
38
|
+
* are never reported as missing.
|
|
39
|
+
*/
|
|
40
|
+
export declare const getColumnsMissingFromWarehouse: (existingColumnNames: string[], warehouseColumnPaths: string[]) => string[];
|
|
29
41
|
export declare const isDocBlock: (text?: string | undefined) => boolean;
|
|
30
42
|
type FindAndUpdateModelYamlArgs = {
|
|
31
43
|
model: CompiledModel;
|
|
32
44
|
table: WarehouseTableSchema;
|
|
45
|
+
warehouseColumnPaths: string[];
|
|
33
46
|
docs: Record<string, DbtDoc>;
|
|
34
47
|
includeMeta: boolean;
|
|
35
48
|
projectDir: string;
|
|
@@ -37,7 +50,7 @@ type FindAndUpdateModelYamlArgs = {
|
|
|
37
50
|
assumeYes: boolean;
|
|
38
51
|
dbtVersion?: SupportedDbtVersions;
|
|
39
52
|
};
|
|
40
|
-
export declare const findAndUpdateModelYaml: ({ model, table, docs, includeMeta, projectDir, projectName, assumeYes, dbtVersion, }: FindAndUpdateModelYamlArgs) => Promise<{
|
|
53
|
+
export declare const findAndUpdateModelYaml: ({ model, table, warehouseColumnPaths, docs, includeMeta, projectDir, projectName, assumeYes, dbtVersion, }: FindAndUpdateModelYamlArgs) => Promise<{
|
|
41
54
|
updatedYml: DbtSchemaEditor;
|
|
42
55
|
outputFilePath: string;
|
|
43
56
|
}>;
|
package/dist/dbt/models.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/dbt/models.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,MAAM,EACN,YAAY,EACZ,eAAe,EAKf,oBAAoB,EACpB,KAAK,gBAAgB,EACxB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAQ9E,KAAK,aAAa,GAAG;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,KAAK,4BAA4B,GAAG;IAChC,KAAK,EAAE,aAAa,CAAC;IACrB,eAAe,EAAE,eAAe,CAAC;IACjC,kBAAkB,EAAE,OAAO,CAAC;CAC/B,CAAC;AACF,KAAK,QAAQ,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpE;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,YACnB,gBAAgB,+BACI,QAAQ,cACzB,MAAM,KACnB,OAqBF,CAAC;AAEF,eAAO,MAAM,yBAAyB,oDAInC,4BAA4B,KAAG,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/dbt/models.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,MAAM,EACN,YAAY,EACZ,eAAe,EAKf,oBAAoB,EACpB,KAAK,gBAAgB,EACxB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAQ9E,KAAK,aAAa,GAAG;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,KAAK,4BAA4B,GAAG;IAChC,KAAK,EAAE,aAAa,CAAC;IACrB,eAAe,EAAE,eAAe,CAAC;IACjC,kBAAkB,EAAE,OAAO,CAAC;CAC/B,CAAC;AACF,KAAK,QAAQ,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpE;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,YACnB,gBAAgB,+BACI,QAAQ,cACzB,MAAM,KACnB,OAqBF,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAChC,uFAAuF;IACvF,KAAK,EAAE,oBAAoB,CAAC;IAC5B,sFAAsF;IACtF,oBAAoB,EAAE,MAAM,EAAE,CAAC;CAClC,CAAC;AAEF,eAAO,MAAM,yBAAyB,oDAInC,4BAA4B,KAAG,OAAO,CAAC,qBAAqB,CAoC9D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,8BAA8B,wBAClB,MAAM,EAAE,wBACP,MAAM,EAAE,KAC/B,MAAM,EAKR,CAAC;AAyDF,eAAO,MAAM,UAAU,UAAU,MAAM,GAAG,SAAS,KAAQ,OACX,CAAC;AA8BjD,KAAK,0BAA0B,GAAG;IAC9B,KAAK,EAAE,aAAa,CAAC;IACrB,KAAK,EAAE,oBAAoB,CAAC;IAC5B,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,oBAAoB,CAAC;CACrC,CAAC;AACF,eAAO,MAAM,sBAAsB,+GAUhC,0BAA0B,KAAG,OAAO,CAAC;IACpC,UAAU,EAAE,eAAe,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;CAC1B,CA8JA,CAAC;AAEF,eAAO,MAAM,iBAAiB,WAClB,YAAY,EAAE,QAChB;IACF,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC7B,OAAO,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC9B,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,KACF,OAAO,CAAC,aAAa,EAAE,CAoEzB,CAAC"}
|
package/dist/dbt/models.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getCompiledModels = exports.findAndUpdateModelYaml = exports.isDocBlock = exports.getWarehouseTableForModel = exports.isGeneratableColumn = void 0;
|
|
3
|
+
exports.getCompiledModels = exports.findAndUpdateModelYaml = exports.isDocBlock = exports.getColumnsMissingFromWarehouse = exports.getWarehouseTableForModel = exports.isGeneratableColumn = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const common_1 = require("@lightdash/common");
|
|
6
6
|
const execa_1 = tslib_1.__importDefault(require("execa"));
|
|
@@ -46,16 +46,29 @@ const getWarehouseTableForModel = async ({ model, warehouseClient, preserveColum
|
|
|
46
46
|
(table === undefined && `table ${tableRef.table}`);
|
|
47
47
|
throw new common_1.ParseError(`Expected to find materialised model at ${tableRef.database}.${tableRef.schema}.${tableRef.table} but couldn't find (or cannot access) ${missing}`);
|
|
48
48
|
}
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
const columnName = (key) => preserveColumnCase ? key : key.toLowerCase();
|
|
50
|
+
return {
|
|
51
|
+
table: Object.entries(table).reduce((accumulator, [key, value]) => {
|
|
52
|
+
if (!(0, exports.isGeneratableColumn)(catalog, tableRef, key)) {
|
|
53
|
+
return accumulator;
|
|
54
|
+
}
|
|
55
|
+
accumulator[columnName(key)] = value;
|
|
51
56
|
return accumulator;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return accumulator;
|
|
56
|
-
}, {});
|
|
57
|
+
}, {}),
|
|
58
|
+
warehouseColumnPaths: Object.keys(table).map(columnName),
|
|
59
|
+
};
|
|
57
60
|
};
|
|
58
61
|
exports.getWarehouseTableForModel = getWarehouseTableForModel;
|
|
62
|
+
/**
|
|
63
|
+
* Existing YAML columns the warehouse no longer has. Nested leaves and
|
|
64
|
+
* containers are not generated, but they are real warehouse paths, so they
|
|
65
|
+
* are never reported as missing.
|
|
66
|
+
*/
|
|
67
|
+
const getColumnsMissingFromWarehouse = (existingColumnNames, warehouseColumnPaths) => {
|
|
68
|
+
const known = new Set(warehouseColumnPaths.map((columnPath) => columnPath.toLowerCase()));
|
|
69
|
+
return existingColumnNames.filter((name) => !known.has(name.toLowerCase()));
|
|
70
|
+
};
|
|
71
|
+
exports.getColumnsMissingFromWarehouse = getColumnsMissingFromWarehouse;
|
|
59
72
|
// Check if we should use dbt 1.10+ metadata structure
|
|
60
73
|
const wrapInConfig = (dbtVersion, meta) => {
|
|
61
74
|
const useDbt110Metadata = dbtVersion &&
|
|
@@ -112,7 +125,7 @@ const askOverwriteDescription = async (columnName, existingDescription, newDescr
|
|
|
112
125
|
return newDescription;
|
|
113
126
|
return existingDescription;
|
|
114
127
|
};
|
|
115
|
-
const findAndUpdateModelYaml = async ({ model, table, docs, includeMeta, projectDir, projectName, assumeYes, dbtVersion, }) => {
|
|
128
|
+
const findAndUpdateModelYaml = async ({ model, table, warehouseColumnPaths, docs, includeMeta, projectDir, projectName, assumeYes, dbtVersion, }) => {
|
|
116
129
|
const generatedModel = generateModelYml({
|
|
117
130
|
model,
|
|
118
131
|
table,
|
|
@@ -185,11 +198,7 @@ const findAndUpdateModelYaml = async ({ model, table, docs, includeMeta, project
|
|
|
185
198
|
newColumns.forEach((column) => {
|
|
186
199
|
schemaEditor.addColumn(model.name, column);
|
|
187
200
|
});
|
|
188
|
-
|
|
189
|
-
const generatedColumnNamesLower = generatedModel.columns.map((gc) => gc.name.toLowerCase());
|
|
190
|
-
const deletedColumnNames = existingColumns
|
|
191
|
-
.filter((c) => !generatedColumnNamesLower.includes(c.name.toLowerCase()))
|
|
192
|
-
.map((c) => c.name);
|
|
201
|
+
const deletedColumnNames = (0, exports.getColumnsMissingFromWarehouse)(existingColumns.map((c) => c.name), warehouseColumnPaths);
|
|
193
202
|
if (deletedColumnNames.length > 0 && !globalState_1.default.isNonInteractive()) {
|
|
194
203
|
let answers = { isConfirm: assumeYes };
|
|
195
204
|
if (!assumeYes) {
|
package/dist/dbt/models.test.js
CHANGED
|
@@ -43,6 +43,85 @@ describe('Models', () => {
|
|
|
43
43
|
expect((0, models_1.isGeneratableColumn)(catalog, ref, 'hits.page.pagePath')).toBe(false);
|
|
44
44
|
});
|
|
45
45
|
});
|
|
46
|
+
describe('getWarehouseTableForModel', () => {
|
|
47
|
+
const catalog = {
|
|
48
|
+
db: {
|
|
49
|
+
ds: {
|
|
50
|
+
orders: {
|
|
51
|
+
order_id: common_1.DimensionType.STRING,
|
|
52
|
+
product: common_1.DimensionType.STRING,
|
|
53
|
+
'product.sku': common_1.DimensionType.STRING,
|
|
54
|
+
'product.price': common_1.DimensionType.NUMBER,
|
|
55
|
+
'product.variants': common_1.DimensionType.STRING,
|
|
56
|
+
'product.variants.size': common_1.DimensionType.STRING,
|
|
57
|
+
customer: common_1.DimensionType.STRING,
|
|
58
|
+
'customer.location': common_1.DimensionType.STRING,
|
|
59
|
+
tags: common_1.DimensionType.STRING,
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
Object.entries({
|
|
65
|
+
product: { repeated: true, record: true },
|
|
66
|
+
'product.variants': { repeated: true, record: true },
|
|
67
|
+
customer: { repeated: false, record: true },
|
|
68
|
+
tags: { repeated: true, record: false },
|
|
69
|
+
}).forEach(([path, shape]) => (0, common_1.setCatalogNestedColumnShape)(catalog, 'db', 'ds', 'orders', path, shape));
|
|
70
|
+
const warehouseClient = {
|
|
71
|
+
getCatalog: vi.fn(async () => catalog),
|
|
72
|
+
};
|
|
73
|
+
const model = {
|
|
74
|
+
name: 'orders',
|
|
75
|
+
schema: 'ds',
|
|
76
|
+
database: 'db',
|
|
77
|
+
alias: 'orders',
|
|
78
|
+
originalFilePath: 'models/orders.sql',
|
|
79
|
+
patchPath: null,
|
|
80
|
+
packageName: 'p',
|
|
81
|
+
uniqueId: 'model.p.orders',
|
|
82
|
+
};
|
|
83
|
+
test('generates scalars, struct leaves and arrays of scalars but reports every warehouse path', async () => {
|
|
84
|
+
const result = await (0, models_1.getWarehouseTableForModel)({
|
|
85
|
+
model,
|
|
86
|
+
warehouseClient,
|
|
87
|
+
preserveColumnCase: false,
|
|
88
|
+
});
|
|
89
|
+
expect(Object.keys(result.table).sort()).toEqual([
|
|
90
|
+
'customer.location',
|
|
91
|
+
'order_id',
|
|
92
|
+
'tags',
|
|
93
|
+
]);
|
|
94
|
+
expect(result.warehouseColumnPaths.sort()).toEqual([
|
|
95
|
+
'customer',
|
|
96
|
+
'customer.location',
|
|
97
|
+
'order_id',
|
|
98
|
+
'product',
|
|
99
|
+
'product.price',
|
|
100
|
+
'product.sku',
|
|
101
|
+
'product.variants',
|
|
102
|
+
'product.variants.size',
|
|
103
|
+
'tags',
|
|
104
|
+
]);
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
describe('getColumnsMissingFromWarehouse', () => {
|
|
108
|
+
test('keeps documented nested leaves and containers, drops only paths the warehouse lacks', () => {
|
|
109
|
+
expect((0, models_1.getColumnsMissingFromWarehouse)([
|
|
110
|
+
'order_id',
|
|
111
|
+
'Product',
|
|
112
|
+
'product.sku',
|
|
113
|
+
'product.variants.size',
|
|
114
|
+
'legacy_status',
|
|
115
|
+
'product.colour',
|
|
116
|
+
], [
|
|
117
|
+
'order_id',
|
|
118
|
+
'product',
|
|
119
|
+
'product.sku',
|
|
120
|
+
'product.variants',
|
|
121
|
+
'product.variants.size',
|
|
122
|
+
])).toEqual(['legacy_status', 'product.colour']);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
46
125
|
describe('isDocBlock', () => {
|
|
47
126
|
test('should match all doc block variations', () => {
|
|
48
127
|
expect((0, models_1.isDocBlock)("{{doc('user_id')}}")).toBe(true); // single quote
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/handlers/generate.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAMlD,KAAK,sBAAsB,GAAG,qBAAqB,GAAG;IAClD,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC7B,OAAO,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC9B,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC7B,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,kBAAkB,EAAE,OAAO,CAAC;CAC/B,CAAC;AAEF,eAAO,MAAM,eAAe,YAAmB,sBAAsB,
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/handlers/generate.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAMlD,KAAK,sBAAsB,GAAG,qBAAqB,GAAG;IAClD,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC7B,OAAO,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC9B,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC7B,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,kBAAkB,EAAE,OAAO,CAAC;CAC/B,CAAC;AAEF,eAAO,MAAM,eAAe,YAAmB,sBAAsB,kBA+KpE,CAAC"}
|
|
@@ -82,7 +82,7 @@ const generateHandler = async (options) => {
|
|
|
82
82
|
for await (const compiledModel of compiledModels) {
|
|
83
83
|
const spinner = globalState_1.default.startSpinner(` Generating .yml for model ${styles.bold(compiledModel.name)}`);
|
|
84
84
|
try {
|
|
85
|
-
const table = await (0, models_1.getWarehouseTableForModel)({
|
|
85
|
+
const { table, warehouseColumnPaths } = await (0, models_1.getWarehouseTableForModel)({
|
|
86
86
|
model: compiledModel,
|
|
87
87
|
warehouseClient,
|
|
88
88
|
preserveColumnCase: options.preserveColumnCase,
|
|
@@ -95,6 +95,7 @@ const generateHandler = async (options) => {
|
|
|
95
95
|
const { updatedYml, outputFilePath } = await (0, models_1.findAndUpdateModelYaml)({
|
|
96
96
|
model: compiledModel,
|
|
97
97
|
table,
|
|
98
|
+
warehouseColumnPaths,
|
|
98
99
|
docs: manifest.docs,
|
|
99
100
|
includeMeta: !options.excludeMeta,
|
|
100
101
|
projectDir: absoluteProjectPath,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lightdash/cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.211.0",
|
|
4
4
|
"description": "Lightdash CLI tool",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"@actions/core": "1.11.1",
|
|
23
23
|
"@aws-sdk/credential-providers": "3.995.0",
|
|
24
24
|
"@casl/ability": "6.8.0",
|
|
25
|
-
"@lightdash/common": "2.
|
|
26
|
-
"@lightdash/warehouses": "2.
|
|
25
|
+
"@lightdash/common": "2.211.0",
|
|
26
|
+
"@lightdash/warehouses": "2.211.0",
|
|
27
27
|
"@sidvind/better-ajv-errors": "7.0.0",
|
|
28
28
|
"@types/columnify": "1.5.1",
|
|
29
29
|
"ajv": "8.18.0",
|