@forestadmin/datasource-sequelize 1.0.0-beta.1

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.
@@ -0,0 +1,13 @@
1
+ import { ModelDefined } from 'sequelize';
2
+ import { AggregateResult, Aggregation, BaseCollection, DataSource, Filter, PaginatedFilter, Projection, RecordData } from '@forestadmin/datasource-toolkit';
3
+ export default class SequelizeCollection extends BaseCollection {
4
+ protected model: ModelDefined<any, any>;
5
+ private aggregationUtils;
6
+ constructor(name: string, datasource: DataSource, model: ModelDefined<any, any>);
7
+ create(data: RecordData[]): Promise<RecordData[]>;
8
+ list(filter: PaginatedFilter, projection: Projection): Promise<RecordData[]>;
9
+ update(filter: Filter, patch: RecordData): Promise<void>;
10
+ delete(filter: Filter): Promise<void>;
11
+ aggregate(filter: Filter, aggregation: Aggregation, limit?: number): Promise<AggregateResult[]>;
12
+ }
13
+ //# sourceMappingURL=collection.d.ts.map
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const sequelize_1 = require("sequelize");
7
+ const datasource_toolkit_1 = require("@forestadmin/datasource-toolkit");
8
+ const aggregation_1 = __importDefault(require("./utils/aggregation"));
9
+ const model_to_collection_schema_converter_1 = __importDefault(require("./utils/model-to-collection-schema-converter"));
10
+ const query_converter_1 = __importDefault(require("./utils/query-converter"));
11
+ class SequelizeCollection extends datasource_toolkit_1.BaseCollection {
12
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
+ constructor(name, datasource, model) {
14
+ super(name, datasource);
15
+ if (!model)
16
+ throw new Error('Invalid (null) model instance.');
17
+ this.model = model;
18
+ this.aggregationUtils = new aggregation_1.default(this.model);
19
+ const modelSchema = model_to_collection_schema_converter_1.default.convert(this.model);
20
+ this.addFields(modelSchema.fields);
21
+ this.addSegments(modelSchema.segments);
22
+ }
23
+ async create(data) {
24
+ const records = await this.model.bulkCreate(data);
25
+ return records.map(record => record.get({ plain: true }));
26
+ }
27
+ async list(filter, projection) {
28
+ let include = query_converter_1.default.getIncludeWithAttributesFromProjection(projection);
29
+ if (filter.conditionTree) {
30
+ include = include.concat(query_converter_1.default.getIncludeFromProjection(filter.conditionTree.projection));
31
+ }
32
+ const query = {
33
+ attributes: projection.columns,
34
+ where: query_converter_1.default.getWhereFromConditionTree(this.model, filter.conditionTree),
35
+ include,
36
+ limit: filter.page?.limit,
37
+ offset: filter.page?.skip,
38
+ order: query_converter_1.default.getOrderFromSort(filter.sort),
39
+ subQuery: false,
40
+ };
41
+ const records = await this.model.findAll(query);
42
+ return records.map(record => record.get({ plain: true }));
43
+ }
44
+ async update(filter, patch) {
45
+ await this.model.update(patch, {
46
+ where: query_converter_1.default.getWhereFromConditionTree(this.model, filter.conditionTree),
47
+ fields: Object.keys(patch),
48
+ });
49
+ }
50
+ async delete(filter) {
51
+ await this.model.destroy({
52
+ where: query_converter_1.default.getWhereFromConditionTree(this.model, filter.conditionTree),
53
+ });
54
+ }
55
+ async aggregate(filter, aggregation, limit) {
56
+ let aggregationField = aggregation.field;
57
+ if (aggregation.operation === 'Count' || !aggregationField) {
58
+ aggregationField = '*';
59
+ }
60
+ else {
61
+ aggregationField = this.aggregationUtils.unAmbigousField(aggregationField);
62
+ }
63
+ const aggregationFunction = (0, sequelize_1.fn)(aggregation.operation.toUpperCase(), (0, sequelize_1.col)(aggregationField));
64
+ const aggregationAttribute = [
65
+ aggregationFunction,
66
+ this.aggregationUtils.aggregateFieldName,
67
+ ];
68
+ const { groups, attributes: groupAttributes } = this.aggregationUtils.getGroupAndAttributesFromAggregation(aggregation.groups);
69
+ let include = query_converter_1.default.getIncludeFromProjection(aggregation.projection);
70
+ if (filter.conditionTree) {
71
+ include = include.concat(query_converter_1.default.getIncludeFromProjection(filter.conditionTree.projection));
72
+ }
73
+ const order = this.aggregationUtils.getOrder(aggregationFunction);
74
+ const query = {
75
+ attributes: [...groupAttributes, aggregationAttribute],
76
+ group: groups,
77
+ where: query_converter_1.default.getWhereFromConditionTree(this.model, filter.conditionTree),
78
+ include,
79
+ limit,
80
+ order: [order],
81
+ subQuery: false,
82
+ raw: true,
83
+ };
84
+ const rows = await this.model.findAll(query);
85
+ return this.aggregationUtils.computeResult(rows, aggregation.groups);
86
+ }
87
+ }
88
+ exports.default = SequelizeCollection;
89
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sbGVjdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9jb2xsZWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEseUNBQWdGO0FBRWhGLHdFQVN5QztBQUV6QyxzRUFBbUQ7QUFDbkQsd0hBQTBFO0FBQzFFLDhFQUFxRDtBQUVyRCxNQUFxQixtQkFBb0IsU0FBUSxtQ0FBYztJQUs3RCw4REFBOEQ7SUFDOUQsWUFBWSxJQUFZLEVBQUUsVUFBc0IsRUFBRSxLQUE2QjtRQUM3RSxLQUFLLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBRXhCLElBQUksQ0FBQyxLQUFLO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFDO1FBRTlELElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBQ25CLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLHFCQUFnQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUV6RCxNQUFNLFdBQVcsR0FBRyw4Q0FBYyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFdkQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDbkMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDekMsQ0FBQztJQUVELEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBa0I7UUFDN0IsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUVsRCxPQUFPLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM1RCxDQUFDO0lBRUQsS0FBSyxDQUFDLElBQUksQ0FBQyxN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
@@ -0,0 +1,9 @@
1
+ import { Sequelize } from 'sequelize';
2
+ import { BaseDataSource } from '@forestadmin/datasource-toolkit';
3
+ import SequelizeCollection from './collection';
4
+ export default class SequelizeDataSource extends BaseDataSource<SequelizeCollection> {
5
+ protected sequelize: Sequelize;
6
+ constructor(sequelize: Sequelize);
7
+ protected createCollections(models: Sequelize['models']): void;
8
+ }
9
+ //# sourceMappingURL=datasource.d.ts.map
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const datasource_toolkit_1 = require("@forestadmin/datasource-toolkit");
7
+ const collection_1 = __importDefault(require("./collection"));
8
+ class SequelizeDataSource extends datasource_toolkit_1.BaseDataSource {
9
+ constructor(sequelize) {
10
+ super();
11
+ this.sequelize = null;
12
+ if (!sequelize)
13
+ throw new Error('Invalid (null) Sequelize instance.');
14
+ this.sequelize = sequelize;
15
+ this.createCollections(this.sequelize.models);
16
+ }
17
+ createCollections(models) {
18
+ Object.values(models)
19
+ // avoid schema reordering
20
+ .sort((modelA, modelB) => (modelA.name > modelB.name ? 1 : -1))
21
+ .forEach(model => {
22
+ const collection = new collection_1.default(model.name, this, model);
23
+ this.addCollection(collection);
24
+ });
25
+ }
26
+ }
27
+ exports.default = SequelizeDataSource;
28
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YXNvdXJjZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9kYXRhc291cmNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBRUEsd0VBQWlFO0FBRWpFLDhEQUErQztBQUUvQyxNQUFxQixtQkFBb0IsU0FBUSxtQ0FBbUM7SUFHbEYsWUFBWSxTQUFvQjtRQUM5QixLQUFLLEVBQUUsQ0FBQztRQUhBLGNBQVMsR0FBYyxJQUFJLENBQUM7UUFLcEMsSUFBSSxDQUFDLFNBQVM7WUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLG9DQUFvQyxDQUFDLENBQUM7UUFFdEUsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7UUFFM0IsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDaEQsQ0FBQztJQUVTLGlCQUFpQixDQUFDLE1BQTJCO1FBQ3JELE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDO1lBQ25CLDBCQUEwQjthQUN6QixJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQzlELE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRTtZQUNmLE1BQU0sVUFBVSxHQUFHLElBQUksb0JBQW1CLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDcEUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNqQyxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7Q0FDRjtBQXRCRCxzQ0FzQkMifQ==
@@ -0,0 +1,4 @@
1
+ export { default as SequelizeCollection } from './collection';
2
+ export { default as SequelizeDataSource } from './datasource';
3
+ export { default as TypeConverter } from './utils/type-converter';
4
+ //# sourceMappingURL=index.d.ts.map
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.TypeConverter = exports.SequelizeDataSource = exports.SequelizeCollection = void 0;
7
+ var collection_1 = require("./collection");
8
+ Object.defineProperty(exports, "SequelizeCollection", { enumerable: true, get: function () { return __importDefault(collection_1).default; } });
9
+ var datasource_1 = require("./datasource");
10
+ Object.defineProperty(exports, "SequelizeDataSource", { enumerable: true, get: function () { return __importDefault(datasource_1).default; } });
11
+ var type_converter_1 = require("./utils/type-converter");
12
+ Object.defineProperty(exports, "TypeConverter", { enumerable: true, get: function () { return __importDefault(type_converter_1).default; } });
13
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsMkNBQThEO0FBQXJELGtJQUFBLE9BQU8sT0FBdUI7QUFDdkMsMkNBQThEO0FBQXJELGtJQUFBLE9BQU8sT0FBdUI7QUFDdkMseURBQWtFO0FBQXpELGdJQUFBLE9BQU8sT0FBaUIifQ==
@@ -0,0 +1,18 @@
1
+ import { GroupOption, Model, ModelDefined, ProjectionAlias } from 'sequelize';
2
+ import { Fn } from 'sequelize/types/utils';
3
+ import { AggregateResult, AggregationGroup } from '@forestadmin/datasource-toolkit';
4
+ export default class AggregationUtils {
5
+ private model;
6
+ private dialect;
7
+ readonly aggregateFieldName = "__aggregate__";
8
+ constructor(model: ModelDefined<any, any>);
9
+ getGroupFieldName(groupField: string): string;
10
+ unAmbigousField(field: string): string;
11
+ getGroupAndAttributesFromAggregation(aggregationQueryGroup: AggregationGroup[]): {
12
+ groups: GroupOption;
13
+ attributes: ProjectionAlias[];
14
+ };
15
+ getOrder(aggregationFunction: Fn): [string | Fn | import("sequelize/types/utils").Col | import("sequelize/types/utils").Literal, string];
16
+ computeResult(rows: Model<any, any>[], aggregationQueryGroup: AggregationGroup[]): AggregateResult[];
17
+ }
18
+ //# sourceMappingURL=aggregation.d.ts.map
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const sequelize_1 = require("sequelize");
7
+ const datasource_toolkit_1 = require("@forestadmin/datasource-toolkit");
8
+ const date_aggregation_converter_1 = __importDefault(require("./date-aggregation-converter"));
9
+ class AggregationUtils {
10
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
+ constructor(model) {
12
+ this.aggregateFieldName = '__aggregate__';
13
+ this.model = model;
14
+ this.dialect = this.model.sequelize.getDialect();
15
+ }
16
+ getGroupFieldName(groupField) {
17
+ return `${groupField}__grouped__`;
18
+ }
19
+ unAmbigousField(field) {
20
+ let tableName;
21
+ let fieldName;
22
+ if (field.includes(':')) {
23
+ const [associationName, nestedField] = field.split(':');
24
+ const association = this.model.associations[associationName];
25
+ if (!association) {
26
+ throw new datasource_toolkit_1.ValidationError(`${this.model.name} model does not have association "${associationName}".`);
27
+ }
28
+ const associationField = association.target.getAttributes()[nestedField];
29
+ if (!associationField) {
30
+ throw new datasource_toolkit_1.ValidationError(`${associationName} model does not have field "${nestedField}".`);
31
+ }
32
+ tableName = associationName;
33
+ fieldName = associationField.field;
34
+ }
35
+ else {
36
+ const modelField = this.model.getAttributes()[field];
37
+ if (!modelField) {
38
+ throw new datasource_toolkit_1.ValidationError(`${this.model.name} model does not have field "${field}".`);
39
+ }
40
+ tableName = this.model.name;
41
+ fieldName = modelField.field;
42
+ }
43
+ return this.model.sequelize.getQueryInterface().quoteIdentifiers(`${tableName}.${fieldName}`);
44
+ }
45
+ getGroupAndAttributesFromAggregation(aggregationQueryGroup) {
46
+ const attributes = [];
47
+ const groups = aggregationQueryGroup?.map(group => {
48
+ const { field } = group;
49
+ const groupFieldName = this.getGroupFieldName(field);
50
+ const groupField = this.unAmbigousField(field);
51
+ if (group.operation) {
52
+ const groupFunction = date_aggregation_converter_1.default.convertToDialect(this.dialect, groupField, group.operation);
53
+ attributes.push([groupFunction, groupFieldName]);
54
+ return this.dialect === 'mssql' ? groupFunction : groupFieldName;
55
+ }
56
+ attributes.push([(0, sequelize_1.col)(groupField), groupFieldName]);
57
+ return this.dialect === 'mssql' ? groupField : groupFieldName;
58
+ });
59
+ return { groups, attributes };
60
+ }
61
+ getOrder(aggregationFunction) {
62
+ let order;
63
+ // FIXME handle properly order
64
+ switch (this.dialect) {
65
+ case 'postgres':
66
+ order = [(0, sequelize_1.col)(this.aggregateFieldName), 'DESC NULLS LAST'];
67
+ break;
68
+ case 'mssql':
69
+ order = [aggregationFunction, 'DESC'];
70
+ break;
71
+ default:
72
+ order = [(0, sequelize_1.col)(this.aggregateFieldName), 'DESC'];
73
+ }
74
+ return order;
75
+ }
76
+ computeResult(
77
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
78
+ rows, aggregationQueryGroup) {
79
+ return rows.map(aggregate => {
80
+ const aggregateResult = {
81
+ value: aggregate[this.aggregateFieldName],
82
+ group: {},
83
+ };
84
+ aggregationQueryGroup?.forEach(({ field }) => {
85
+ aggregateResult.group[field] = aggregate[this.getGroupFieldName(field)];
86
+ });
87
+ return aggregateResult;
88
+ });
89
+ }
90
+ }
91
+ exports.default = AggregationUtils;
92
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWdncmVnYXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvYWdncmVnYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSx5Q0FRbUI7QUFHbkIsd0VBSXlDO0FBRXpDLDhGQUFvRTtBQUVwRSxNQUFxQixnQkFBZ0I7SUFPbkMsOERBQThEO0lBQzlELFlBQVksS0FBNkI7UUFIaEMsdUJBQWtCLEdBQUcsZUFBZSxDQUFDO1FBSTVDLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBQ25CLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsVUFBVSxFQUFhLENBQUM7SUFDOUQsQ0FBQztJQUVELGlCQUFpQixDQUFDLFVBQWtCO1FBQ2xDLE9BQU8sR0FBRyxVQUFVLGFBQWEsQ0FBQztJQUNwQyxDQUFDO0lBRUQsZUFBZSxDQUFDLEtBQWE7UUFDM0IsSUFBSSxTQUFpQixDQUFDO1FBQ3RCLElBQUksU0FBaUIsQ0FBQztRQUV0QixJQUFJLEtBQUssQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDdkIsTUFBTSxDQUFDLGVBQWUsRUFBRSxXQUFXLENBQUMsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3hELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBRTdELElBQUksQ0FBQyxXQUFXLEVBQUU7Z0JBQ2hCLE1BQU0sSUFBSSxvQ0FBZSxDQUN2QixHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxxQ0FBcUMsZUFBZSxJQUFJLENBQzNFLENBQUM7YUFDSDtZQUVELE1BQU0sZ0JBQWdCLEdBQUcsV0FBVyxDQUFDLE1BQU0sQ0FBQyxhQUFhLEVBQUUsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUV6RSxJQUFJLENBQUMsZ0JBQWdCLEVBQUU7Z0JBQ3JC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
@@ -0,0 +1,11 @@
1
+ import { Fn } from 'sequelize/types/utils';
2
+ import { Dialect } from 'sequelize';
3
+ import { DateOperation } from '@forestadmin/datasource-toolkit';
4
+ export default class DateAggregationConverter {
5
+ private static convertPostgres;
6
+ private static convertMssql;
7
+ private static convertMysql;
8
+ private static convertSqlite;
9
+ static convertToDialect(dialect: Dialect, field: string, operation: DateOperation): Fn;
10
+ }
11
+ //# sourceMappingURL=date-aggregation-converter.d.ts.map
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const sequelize_1 = require("sequelize");
4
+ class DateAggregationConverter {
5
+ static convertPostgres(field, operation) {
6
+ const aggregateFunction = (0, sequelize_1.fn)('DATE_TRUNC', operation.toLocaleLowerCase(), (0, sequelize_1.col)(field));
7
+ return (0, sequelize_1.fn)('TO_CHAR', aggregateFunction, 'YYYY-MM-DD');
8
+ }
9
+ static convertMssql(field, operation) {
10
+ let dateToConvert;
11
+ switch (operation) {
12
+ case 'Year':
13
+ dateToConvert = (0, sequelize_1.fn)('DATEFROMPARTS', (0, sequelize_1.fn)('DATEPART', (0, sequelize_1.literal)('YEAR'), (0, sequelize_1.col)(field)), '01', '01');
14
+ break;
15
+ case 'Month':
16
+ dateToConvert = (0, sequelize_1.fn)('DATEFROMPARTS', (0, sequelize_1.fn)('DATEPART', (0, sequelize_1.literal)('YEAR'), (0, sequelize_1.col)(field)), (0, sequelize_1.fn)('DATEPART', (0, sequelize_1.literal)('MONTH'), (0, sequelize_1.col)(field)), '01');
17
+ break;
18
+ case 'Week':
19
+ dateToConvert = (0, sequelize_1.fn)('DATEADD', (0, sequelize_1.literal)('DAY'), (0, sequelize_1.literal)(`-DATEPART(dw, ${field})+2`), (0, sequelize_1.col)(field));
20
+ break;
21
+ case 'Day':
22
+ dateToConvert = (0, sequelize_1.col)(field);
23
+ break;
24
+ default:
25
+ throw new Error(`Unknown Date operation: "${operation}"`);
26
+ }
27
+ // eslint-disable-next-line max-len
28
+ // https://docs.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?redirectedfrom=MSDN&view=sql-server-ver15
29
+ return (0, sequelize_1.fn)('CONVERT', (0, sequelize_1.literal)('varchar(10)'), dateToConvert, 23);
30
+ }
31
+ static convertMysql(field, operation) {
32
+ let format = '%Y-%m-%d';
33
+ let dateToConvert = (0, sequelize_1.col)(field);
34
+ switch (operation) {
35
+ case 'Year':
36
+ format = '%Y-01-01';
37
+ break;
38
+ case 'Month':
39
+ format = '%Y-%m-01';
40
+ break;
41
+ case 'Week':
42
+ dateToConvert = (0, sequelize_1.fn)('DATE_SUB', (0, sequelize_1.col)(field), (0, sequelize_1.literal)(`INTERVAL(WEEKDAY(${field})) DAY`));
43
+ break;
44
+ case 'Day':
45
+ break;
46
+ default:
47
+ throw new Error(`Unknown Date operation: "${operation}"`);
48
+ }
49
+ return (0, sequelize_1.fn)('DATE_FORMAT', dateToConvert, format);
50
+ }
51
+ static convertSqlite(field, operation) {
52
+ if (operation === 'Week') {
53
+ return (0, sequelize_1.fn)('DATE', (0, sequelize_1.col)(field), 'weekday 0');
54
+ }
55
+ let format;
56
+ switch (operation) {
57
+ case 'Year':
58
+ format = '%Y-01-01';
59
+ break;
60
+ case 'Month':
61
+ format = '%Y-%m-01';
62
+ break;
63
+ case 'Day':
64
+ format = '%Y-%m-%d';
65
+ break;
66
+ default:
67
+ throw new Error(`Unknown Date operation: "${operation}"`);
68
+ }
69
+ return (0, sequelize_1.fn)('STRFTIME', format, (0, sequelize_1.col)(field));
70
+ }
71
+ static convertToDialect(dialect, field, operation) {
72
+ switch (dialect) {
73
+ case 'postgres':
74
+ return this.convertPostgres(field, operation);
75
+ case 'mssql':
76
+ return this.convertMssql(field, operation);
77
+ case 'mariadb':
78
+ case 'mysql':
79
+ return this.convertMysql(field, operation);
80
+ case 'sqlite':
81
+ return this.convertSqlite(field, operation);
82
+ default:
83
+ throw new Error(`Unsupported dialect: "${dialect}"`);
84
+ }
85
+ }
86
+ }
87
+ exports.default = DateAggregationConverter;
88
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZS1hZ2dyZWdhdGlvbi1jb252ZXJ0ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvZGF0ZS1hZ2dyZWdhdGlvbi1jb252ZXJ0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFDQSx5Q0FBc0Q7QUFJdEQsTUFBcUIsd0JBQXdCO0lBQ25DLE1BQU0sQ0FBQyxlQUFlLENBQUMsS0FBYSxFQUFFLFNBQXdCO1FBQ3BFLE1BQU0saUJBQWlCLEdBQUcsSUFBQSxjQUFFLEVBQUMsWUFBWSxFQUFFLFNBQVMsQ0FBQyxpQkFBaUIsRUFBRSxFQUFFLElBQUEsZUFBRyxFQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFFdEYsT0FBTyxJQUFBLGNBQUUsRUFBQyxTQUFTLEVBQUUsaUJBQWlCLEVBQUUsWUFBWSxDQUFDLENBQUM7SUFDeEQsQ0FBQztJQUVPLE1BQU0sQ0FBQyxZQUFZLENBQUMsS0FBYSxFQUFFLFNBQXdCO1FBQ2pFLElBQUksYUFBdUIsQ0FBQztRQUU1QixRQUFRLFNBQVMsRUFBRTtZQUNqQixLQUFLLE1BQU07Z0JBQ1QsYUFBYSxHQUFHLElBQUEsY0FBRSxFQUNoQixlQUFlLEVBQ2YsSUFBQSxjQUFFLEVBQUMsVUFBVSxFQUFFLElBQUEsbUJBQU8sRUFBQyxNQUFNLENBQUMsRUFBRSxJQUFBLGVBQUcsRUFBQyxLQUFLLENBQUMsQ0FBQyxFQUMzQyxJQUFJLEVBQ0osSUFBSSxDQUNMLENBQUM7Z0JBQ0YsTUFBTTtZQUNSLEtBQUssT0FBTztnQkFDVixhQUFhLEdBQUcsSUFBQSxjQUFFLEVBQ2hCLGVBQWUsRUFDZixJQUFBLGNBQUUsRUFBQyxVQUFVLEVBQUUsSUFBQSxtQkFBTyxFQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUEsZUFBRyxFQUFDLEtBQUssQ0FBQyxDQUFDLEVBQzNDLElBQUEsY0FBRSxFQUFDLFVBQVUsRUFBRSxJQUFBLG1CQUFPLEVBQUMsT0FBTyxDQUFDLEVBQUUsSUFBQSxlQUFHLEVBQUMs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
@@ -0,0 +1,10 @@
1
+ import { ModelDefined } from 'sequelize';
2
+ import { CollectionSchema } from '@forestadmin/datasource-toolkit';
3
+ export default class ModelToCollectionSchemaConverter {
4
+ private static convertAssociation;
5
+ private static convertAssociations;
6
+ private static convertAttribute;
7
+ private static convertAttributes;
8
+ static convert(model: ModelDefined<any, any>): CollectionSchema;
9
+ }
10
+ //# sourceMappingURL=model-to-collection-schema-converter.d.ts.map
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const sequelize_1 = require("sequelize");
7
+ const type_converter_1 = __importDefault(require("./type-converter"));
8
+ class ModelToCollectionSchemaConverter {
9
+ static convertAssociation(
10
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
+ association) {
12
+ switch (association.associationType) {
13
+ case sequelize_1.BelongsTo.name:
14
+ return {
15
+ foreignCollection: association.target.name,
16
+ foreignKey: association.foreignKey,
17
+ foreignKeyTarget: association.targetKey,
18
+ type: 'ManyToOne',
19
+ };
20
+ case sequelize_1.BelongsToMany.name:
21
+ return {
22
+ foreignCollection: association.target.name,
23
+ throughCollection: association.through.model.name,
24
+ originKey: association.foreignKey,
25
+ originKeyTarget: association.targetKey,
26
+ foreignKey: association.otherKey,
27
+ foreignKeyTarget: association.sourceKey,
28
+ type: 'ManyToMany',
29
+ };
30
+ case sequelize_1.HasMany.name:
31
+ return {
32
+ foreignCollection: association.target.name,
33
+ originKey: association.foreignKey,
34
+ originKeyTarget: association.sourceKey,
35
+ type: 'OneToMany',
36
+ };
37
+ case sequelize_1.HasOne.name:
38
+ return {
39
+ foreignCollection: association.target.name,
40
+ originKey: association.foreignKey,
41
+ originKeyTarget: association.sourceKey,
42
+ type: 'OneToOne',
43
+ };
44
+ default:
45
+ throw new Error(`Unsupported association: "${association.associationType}".`);
46
+ }
47
+ }
48
+ static convertAssociations(associations) {
49
+ const schemaAssociations = {};
50
+ if (associations) {
51
+ Object.entries(associations).forEach(([key, association]) => {
52
+ schemaAssociations[key] = this.convertAssociation(association);
53
+ });
54
+ }
55
+ return schemaAssociations;
56
+ }
57
+ static convertAttribute(attribute) {
58
+ const sequelizeColumnType = attribute.type;
59
+ const columnType = type_converter_1.default.fromDataType(sequelizeColumnType);
60
+ const filterOperators = type_converter_1.default.operatorsForDataType(sequelizeColumnType);
61
+ const column = {
62
+ columnType,
63
+ filterOperators,
64
+ type: 'Column',
65
+ validation: [],
66
+ isReadOnly: attribute.autoIncrement,
67
+ };
68
+ if (attribute.allowNull === false &&
69
+ !column.isReadOnly &&
70
+ !attribute.defaultValue &&
71
+ // eslint-disable-next-line no-underscore-dangle
72
+ !attribute._autoGenerated) {
73
+ column.validation.push({ operator: 'Present' });
74
+ }
75
+ if (attribute.primaryKey)
76
+ column.isPrimaryKey = true;
77
+ if (attribute.defaultValue !== null &&
78
+ attribute.defaultValue !== undefined &&
79
+ (columnType === 'Json' || typeof attribute.defaultValue !== 'object')) {
80
+ column.defaultValue = attribute.defaultValue;
81
+ }
82
+ if (attribute.values) {
83
+ column.enumValues = [...attribute.values];
84
+ }
85
+ return column;
86
+ }
87
+ static convertAttributes(attributes) {
88
+ const fields = {};
89
+ Object.entries(attributes).forEach(([name, attribute]) => {
90
+ fields[name] = this.convertAttribute(attribute);
91
+ });
92
+ return fields;
93
+ }
94
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
95
+ static convert(model) {
96
+ if (!model)
97
+ throw new Error('Invalid (null) model.');
98
+ return {
99
+ actions: {},
100
+ fields: {
101
+ ...this.convertAttributes(model.getAttributes()),
102
+ ...this.convertAssociations(model.associations),
103
+ },
104
+ searchable: false,
105
+ segments: [],
106
+ };
107
+ }
108
+ }
109
+ exports.default = ModelToCollectionSchemaConverter;
110
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kZWwtdG8tY29sbGVjdGlvbi1zY2hlbWEtY29udmVydGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL21vZGVsLXRvLWNvbGxlY3Rpb24tc2NoZW1hLWNvbnZlcnRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLHlDQVdtQjtBQVNuQixzRUFBNkM7QUFFN0MsTUFBcUIsZ0NBQWdDO0lBQzNDLE1BQU0sQ0FBQyxrQkFBa0I7SUFDL0IsOERBQThEO0lBQzlELFdBQTBEO1FBRTFELFFBQVEsV0FBVyxDQUFDLGVBQWUsRUFBRTtZQUNuQyxLQUFLLHFCQUFTLENBQUMsSUFBSTtnQkFDakIsT0FBTztvQkFDTCxpQkFBaUIsRUFBRSxXQUFXLENBQUMsTUFBTSxDQUFDLElBQUk7b0JBQzFDLFVBQVUsRUFBRSxXQUFXLENBQUMsVUFBVTtvQkFDbEMsZ0JBQWdCLEVBQUcsV0FBZ0QsQ0FBQyxTQUFTO29CQUM3RSxJQUFJLEVBQUUsV0FBVztpQkFDbEIsQ0FBQztZQUNKLEtBQUsseUJBQWEsQ0FBQyxJQUFJO2dCQUNyQixPQUFPO29CQUNMLGlCQUFpQixFQUFFLFdBQVcsQ0FBQyxNQUFNLENBQUMsSUFBSTtvQkFDMUMsaUJBQWlCLEVBQUcsV0FBNkIsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUk7b0JBQ3BFLFNBQVMsRUFBRyxXQUE2QixDQUFDLFVBQVU7b0JBQ3BELGVBQWUsRUFBRyxXQUE2QixDQUFDLFNBQVM7b0JBQ3pELFVBQVUsRUFBRyxXQUE2QixDQUFDLFFBQVE7b0JBQ25ELGdCQUFnQixFQUFHLFdBQTZCLENBQUMsU0FBUztvQkFDMUQsSUFBSSxFQUFFLFlBQVk7aUJBQ25CLENBQUM7WUFDSixLQUFLLG1CQUFPLENBQUMsSUFBSTtnQkFDZixPQUFPO29CQUNMLGlCQUFpQixFQUFFLFdBQVcsQ0FBQyxNQUFNLENBQUMsSUFBSTtvQkFDMUMsU0FBUyxFQUFFLFdBQVcsQ0FBQyxVQUFVO29C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
@@ -0,0 +1,12 @@
1
+ import { ConditionTree, Projection, Sort } from '@forestadmin/datasource-toolkit';
2
+ import { IncludeOptions, ModelDefined, OrderItem, WhereOptions } from 'sequelize';
3
+ export default class QueryConverter {
4
+ private static asArray;
5
+ private static makeWhereClause;
6
+ static getWhereFromConditionTree(model: ModelDefined<any, any>, conditionTree?: ConditionTree): WhereOptions;
7
+ private static computeIncludeFromProjection;
8
+ static getIncludeFromProjection(projection: Projection): IncludeOptions[];
9
+ static getIncludeWithAttributesFromProjection(projection: Projection): IncludeOptions[];
10
+ static getOrderFromSort(sort: Sort): OrderItem[];
11
+ }
12
+ //# sourceMappingURL=query-converter.d.ts.map