Skip to content

Commit 3551f69

Browse files
HCK-10159: enable dbt feature (#130)
* HCK-10159: add dbt provider * HCK-10159: enable dbt feature
1 parent eabafe0 commit 3551f69

File tree

5 files changed

+192
-1
lines changed

5 files changed

+192
-1
lines changed

esbuild.package.js

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ esbuild
1414
path.resolve(__dirname, 'api', 're.js'),
1515
path.resolve(__dirname, 'forward_engineering', 'api.js'),
1616
path.resolve(__dirname, 'forward_engineering', 'ddlProvider.js'),
17+
path.resolve(__dirname, 'forward_engineering', 'dbtProvider.js'),
1718
path.resolve(__dirname, 'reverse_engineering', 'api.js'),
1819
],
1920
bundle: true,

forward_engineering/dbtProvider.js

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/**
2+
* @typedef {import('./types').AppInstance} AppInstance
3+
* @typedef {import('./types').ColumnDefinition} ColumnDefinition
4+
* @typedef {import('./types').JsonSchema} JsonSchema
5+
* @typedef {import('./types').ConstraintDto} ConstraintDto
6+
*/
7+
const { toLower, toUpper } = require('lodash');
8+
9+
const types = require('./configs/types');
10+
const defaultTypes = require('./configs/defaultTypes');
11+
const getKeyHelper = require('./helpers/keyHelper');
12+
const getColumnDefinitionHelper = require('./helpers/columnDefinitionHelper');
13+
14+
class DbtProvider {
15+
/**
16+
* @type {AppInstance}
17+
*/
18+
#appInstance;
19+
20+
/**
21+
* @param {{ appInstance: AppInstance }}
22+
*/
23+
constructor({ appInstance }) {
24+
this.#appInstance = appInstance;
25+
}
26+
27+
/**
28+
* @param {{ appInstance }}
29+
* @returns {DbtProvider}
30+
*/
31+
static createDbtProvider({ appInstance }) {
32+
return new DbtProvider({ appInstance });
33+
}
34+
35+
/**
36+
* @param {string} type
37+
* @returns {string | undefined}
38+
*/
39+
getDefaultType(type) {
40+
return defaultTypes[type];
41+
}
42+
43+
/**
44+
* @returns {Record<string, object>}
45+
*/
46+
getTypesDescriptors() {
47+
return types;
48+
}
49+
50+
/**
51+
* @param {string} type
52+
* @returns {boolean}
53+
*/
54+
hasType(type) {
55+
return Object.keys(types).map(toLower).includes(toLower(type));
56+
}
57+
58+
/**
59+
* @param {{ type: string; columnDefinition: ColumnDefinition }}
60+
* @returns {string}
61+
*/
62+
decorateType({ type, columnDefinition }) {
63+
const columnDefinitionHelper = getColumnDefinitionHelper(this.#appInstance);
64+
65+
return columnDefinitionHelper.decorateType(toUpper(type), columnDefinition);
66+
}
67+
68+
/**
69+
* @param {{ jsonSchema: JsonSchema }}
70+
* @returns {ConstraintDto[]}
71+
*/
72+
getCompositeKeyConstraints({ jsonSchema }) {
73+
const keyHelper = getKeyHelper(this.#appInstance);
74+
75+
return keyHelper.getCompositeKeyConstraints({ jsonSchema });
76+
}
77+
78+
/**
79+
* @param {{ columnDefinition: ColumnDefinition; jsonSchema: JsonSchema }}
80+
* @returns {ConstraintDto[]}
81+
*/
82+
getColumnConstraints({ columnDefinition, jsonSchema }) {
83+
const keyHelper = getKeyHelper(this.#appInstance);
84+
85+
return keyHelper.getColumnConstraints({ columnDefinition });
86+
}
87+
}
88+
89+
module.exports = DbtProvider;

forward_engineering/helpers/keyHelper.js

+62
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
/**
2+
* @typedef {import('../types').ColumnDefinition} ColumnDefinition
3+
* @typedef {import('../types').JsonSchema} JsonSchema
4+
* @typedef {import('../types').ConstraintDto} ConstraintDto
5+
*/
6+
17
module.exports = app => {
28
const _ = app.require('lodash');
39
const { clean } = app.require('@hackolade/ddl-fe-utils').general;
@@ -184,12 +190,68 @@ module.exports = app => {
184190
];
185191
};
186192

193+
/**
194+
* @param {{ jsonSchema: JsonSchema }}
195+
* @returns {ConstraintDto[]}
196+
*/
197+
const getCompositeKeyConstraints = ({ jsonSchema }) => {
198+
const compositePrimaryKeys = getCompositePrimaryKeys(jsonSchema);
199+
const compositeUniqueKeys = getCompositeUniqueKeys(jsonSchema);
200+
201+
return [...compositePrimaryKeys, ...compositeUniqueKeys];
202+
};
203+
204+
/**
205+
* @param {{ columnDefinition: ColumnDefinition }}
206+
* @returns {ConstraintDto | undefined}
207+
*/
208+
const getPrimaryKeyConstraint = ({ columnDefinition }) => {
209+
if (!isPrimaryKey(columnDefinition)) {
210+
return;
211+
}
212+
213+
return hydratePrimaryKeyOptions(columnDefinition.primaryKeyOptions ?? {}, '', columnDefinition.isActivated);
214+
};
215+
216+
/**
217+
* @param {{ columnDefinition: ColumnDefinition }}
218+
* @returns {ConstraintDto[]}
219+
*/
220+
const getUniqueKeyConstraints = ({ columnDefinition }) => {
221+
if (!isUnique(columnDefinition)) {
222+
return [];
223+
}
224+
225+
if (isInlineUnique(columnDefinition)) {
226+
const constraint = hydrateUniqueOptions({}, '', columnDefinition.isActivated);
227+
228+
return [constraint];
229+
}
230+
231+
return columnDefinition.uniqueKeyOptions.map(uniqueKeyOption => {
232+
return hydrateUniqueOptions(uniqueKeyOption, '', columnDefinition.isActivated);
233+
});
234+
};
235+
236+
/**
237+
* @param {{ columnDefinition: ColumnDefinition }}
238+
* @returns {ConstraintDto[]}
239+
*/
240+
const getColumnConstraints = ({ columnDefinition }) => {
241+
const primaryKeyConstraint = getPrimaryKeyConstraint({ columnDefinition });
242+
const uniqueKeyConstraints = getUniqueKeyConstraints({ columnDefinition });
243+
244+
return [primaryKeyConstraint, ...uniqueKeyConstraints].filter(Boolean);
245+
};
246+
187247
return {
188248
getTableKeyConstraints,
189249
isInlineUnique,
190250
isInlinePrimaryKey,
191251
hydratePrimaryKeyOptions,
192252
hydrateUniqueOptions,
193253
getCompositePrimaryKeys,
254+
getCompositeKeyConstraints,
255+
getColumnConstraints,
194256
};
195257
};

forward_engineering/types.d.ts

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
export type ColumnDefinition = {
2+
name: string;
3+
type: string;
4+
isActivated: boolean;
5+
length?: number;
6+
precision?: number;
7+
primaryKey?: boolean;
8+
scale?: number;
9+
timePrecision?: number;
10+
unique?: boolean;
11+
primaryKeyOptions?: { GUID: string; constraintName: string };
12+
uniqueKeyOptions?: Array<{ GUID: string; constraintName: string }>;
13+
};
14+
15+
export type AppInstance = {
16+
require: (packageName: string) => unknown;
17+
general: object;
18+
}
19+
20+
export type ConstraintDtoColumn = {
21+
name: string;
22+
isActivated: boolean;
23+
};
24+
25+
export type KeyType = 'PRIMARY KEY' | 'UNIQUE';
26+
27+
export type ConstraintDto = {
28+
keyType: KeyType;
29+
name: string;
30+
columns?: ConstraintDtoColumn[];
31+
};
32+
33+
export type JsonSchema = Record<string, unknown>;

package.json

+7-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,13 @@
2424
"nestedCollections": false,
2525
"disablePatternField": true,
2626
"disableMultipleTypes": true,
27-
"enableForwardEngineering": true,
27+
"enableForwardEngineering": {
28+
"jsonDocument": true,
29+
"jsonSchema": true,
30+
"excel": true,
31+
"plugin": true,
32+
"dbt": true
33+
},
2834
"disableReverseEngineering": false,
2935
"disableChoices": true,
3036
"enableJsonType": true,

0 commit comments

Comments
 (0)