@autofleet/sadot 0.12.0 → 0.13.0-beta.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 (124) hide show
  1. package/package.json +3 -1
  2. package/src/api/v1/index.ts +2 -0
  3. package/src/api/v1/validator/index.ts +127 -0
  4. package/src/api/v1/validator/validations.ts +39 -0
  5. package/src/events/index.ts +1 -1
  6. package/src/hooks/hooks.ts +304 -0
  7. package/src/hooks/index.ts +10 -5
  8. package/src/index.ts +6 -0
  9. package/src/models/CustomValidator.ts +76 -0
  10. package/src/models/index.ts +7 -2
  11. package/src/repository/validator.ts +91 -0
  12. package/src/tests/helpers/commonHooks.ts +9 -2
  13. package/src/tests/helpers/index.ts +7 -2
  14. package/src/types/index.ts +1 -0
  15. package/src/utils/validations/schema/README.md +93 -0
  16. package/src/utils/validations/schema/validator-schema.ts +103 -0
  17. package/dist/api/index.d.ts +0 -3
  18. package/dist/api/index.js +0 -12
  19. package/dist/api/v1/definition/index.d.ts +0 -3
  20. package/dist/api/v1/definition/index.js +0 -116
  21. package/dist/api/v1/definition/validations.d.ts +0 -2
  22. package/dist/api/v1/definition/validations.js +0 -77
  23. package/dist/api/v1/errors.d.ts +0 -4
  24. package/dist/api/v1/errors.js +0 -12
  25. package/dist/api/v1/index.d.ts +0 -3
  26. package/dist/api/v1/index.js +0 -11
  27. package/dist/errors/index.d.ts +0 -24
  28. package/dist/errors/index.js +0 -66
  29. package/dist/events/index.d.ts +0 -4
  30. package/dist/events/index.js +0 -50
  31. package/dist/hooks/create.d.ts +0 -10
  32. package/dist/hooks/create.js +0 -95
  33. package/dist/hooks/enrich.d.ts +0 -30
  34. package/dist/hooks/enrich.js +0 -159
  35. package/dist/hooks/find.d.ts +0 -1
  36. package/dist/hooks/find.js +0 -29
  37. package/dist/hooks/index.d.ts +0 -6
  38. package/dist/hooks/index.js +0 -18
  39. package/dist/hooks/update.d.ts +0 -10
  40. package/dist/hooks/update.js +0 -49
  41. package/dist/hooks/utils/updateInstanceValues.d.ts +0 -15
  42. package/dist/hooks/utils/updateInstanceValues.js +0 -50
  43. package/dist/hooks/workaround.d.ts +0 -10
  44. package/dist/hooks/workaround.js +0 -37
  45. package/dist/index.d.ts +0 -13
  46. package/dist/index.js +0 -67
  47. package/dist/models/CustomFieldDefinition.d.ts +0 -25
  48. package/dist/models/CustomFieldDefinition.js +0 -192
  49. package/dist/models/CustomFieldEntries.d.ts +0 -15
  50. package/dist/models/CustomFieldEntries.js +0 -123
  51. package/dist/models/CustomFieldValue.d.ts +0 -16
  52. package/dist/models/CustomFieldValue.js +0 -151
  53. package/dist/models/index.d.ts +0 -17
  54. package/dist/models/index.js +0 -113
  55. package/dist/models/tests/AssociatedTestModel.d.ts +0 -12
  56. package/dist/models/tests/AssociatedTestModel.js +0 -71
  57. package/dist/models/tests/TestModel.d.ts +0 -12
  58. package/dist/models/tests/TestModel.js +0 -69
  59. package/dist/models/tests/contextAwareModels/ContextAwareTestModel.d.ts +0 -10
  60. package/dist/models/tests/contextAwareModels/ContextAwareTestModel.js +0 -53
  61. package/dist/models/tests/contextAwareModels/ContextTestModel.d.ts +0 -13
  62. package/dist/models/tests/contextAwareModels/ContextTestModel.js +0 -47
  63. package/dist/repository/definition.d.ts +0 -36
  64. package/dist/repository/definition.js +0 -121
  65. package/dist/repository/entries.d.ts +0 -13
  66. package/dist/repository/entries.js +0 -92
  67. package/dist/repository/utils/formatValues.d.ts +0 -3
  68. package/dist/repository/utils/formatValues.js +0 -16
  69. package/dist/repository/value.d.ts +0 -28
  70. package/dist/repository/value.js +0 -124
  71. package/dist/scopes/filter.d.ts +0 -30
  72. package/dist/scopes/filter.js +0 -75
  73. package/dist/scopes/helpers/filter.helpers.d.ts +0 -42
  74. package/dist/scopes/helpers/filter.helpers.js +0 -204
  75. package/dist/scopes/index.d.ts +0 -2
  76. package/dist/scopes/index.js +0 -6
  77. package/dist/tests/api/test-api.d.ts +0 -2
  78. package/dist/tests/api/test-api.js +0 -38
  79. package/dist/tests/functional/searching/index.d.ts +0 -8
  80. package/dist/tests/functional/searching/index.js +0 -44
  81. package/dist/tests/helpers/commonHooks.d.ts +0 -5
  82. package/dist/tests/helpers/commonHooks.js +0 -55
  83. package/dist/tests/helpers/database-config.d.ts +0 -16
  84. package/dist/tests/helpers/database-config.js +0 -17
  85. package/dist/tests/helpers/index.d.ts +0 -7
  86. package/dist/tests/helpers/index.js +0 -29
  87. package/dist/tests/mocks/definition.mock.d.ts +0 -48
  88. package/dist/tests/mocks/definition.mock.js +0 -78
  89. package/dist/tests/mocks/events.mock.d.ts +0 -4
  90. package/dist/tests/mocks/events.mock.js +0 -21
  91. package/dist/tests/mocks/testModel.d.ts +0 -12
  92. package/dist/tests/mocks/testModel.js +0 -35
  93. package/dist/types/definition/index.d.ts +0 -25
  94. package/dist/types/definition/index.js +0 -2
  95. package/dist/types/entries/index.d.ts +0 -25
  96. package/dist/types/entries/index.js +0 -2
  97. package/dist/types/index.d.ts +0 -34
  98. package/dist/types/index.js +0 -2
  99. package/dist/types/value/index.d.ts +0 -15
  100. package/dist/types/value/index.js +0 -2
  101. package/dist/utils/constants/index.d.ts +0 -19
  102. package/dist/utils/constants/index.js +0 -22
  103. package/dist/utils/db/index.d.ts +0 -4
  104. package/dist/utils/db/index.js +0 -24
  105. package/dist/utils/helpers/index.d.ts +0 -26
  106. package/dist/utils/helpers/index.js +0 -40
  107. package/dist/utils/init.d.ts +0 -7
  108. package/dist/utils/init.js +0 -109
  109. package/dist/utils/logger/index.d.ts +0 -3
  110. package/dist/utils/logger/index.js +0 -42
  111. package/dist/utils/scopeAttributes.d.ts +0 -2
  112. package/dist/utils/scopeAttributes.js +0 -11
  113. package/dist/utils/validations/index.d.ts +0 -8
  114. package/dist/utils/validations/index.js +0 -41
  115. package/dist/utils/validations/schema/custom-fields.d.ts +0 -3
  116. package/dist/utils/validations/schema/custom-fields.js +0 -9
  117. package/dist/utils/validations/type.d.ts +0 -15
  118. package/dist/utils/validations/type.js +0 -2
  119. package/dist/utils/validations/validators/index.d.ts +0 -14
  120. package/dist/utils/validations/validators/index.js +0 -40
  121. package/dist/utils/validations/validators/select.validator.d.ts +0 -5
  122. package/dist/utils/validations/validators/select.validator.js +0 -12
  123. package/dist/utils/validations/validators/status.validator.d.ts +0 -12
  124. package/dist/utils/validations/validators/status.validator.js +0 -15
@@ -1,66 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MissingDefinitionError = exports.InvalidEntriesError = exports.InvalidValueError = exports.InvalidFieldTypeError = exports.UnsupportedCustomValidationError = exports.UnsupportedCustomFieldTypeError = exports.MissingRequiredCustomFieldError = void 0;
4
- /* eslint-disable max-classes-per-file */
5
- const errors_1 = require("@autofleet/errors");
6
- class MissingRequiredCustomFieldError extends errors_1.BadRequest {
7
- constructor(missingFields) {
8
- const err = new Error(`The following custom fields are required: ${missingFields.join(',')}`);
9
- super([err], null, missingFields);
10
- this.message = 'MISSING_REQUIRED_CUSTOM_FIELDS';
11
- }
12
- }
13
- exports.MissingRequiredCustomFieldError = MissingRequiredCustomFieldError;
14
- class UnsupportedCustomFieldTypeError extends errors_1.BadRequest {
15
- constructor(fieldType) {
16
- const err = new Error(`Type "${fieldType}" is not supported`);
17
- super([err], null, null);
18
- this.message = 'UNSUPPORTED_CUSTOM_FIELD_TYPE';
19
- }
20
- }
21
- exports.UnsupportedCustomFieldTypeError = UnsupportedCustomFieldTypeError;
22
- class UnsupportedCustomValidationError extends errors_1.BadRequest {
23
- constructor(fieldType) {
24
- const err = new Error(`Validation for "${fieldType}" is not supported`);
25
- super([err], null, null);
26
- this.message = 'UNSUPPORTED_CUSTOM_VALIDATION_TYPE';
27
- }
28
- }
29
- exports.UnsupportedCustomValidationError = UnsupportedCustomValidationError;
30
- class InvalidFieldTypeError extends errors_1.BadRequest {
31
- constructor(fieldType) {
32
- const err = new Error(`Invalid field type ${fieldType}`);
33
- super([err], null, null);
34
- this.message = 'INVALID_FIELD_TYPE';
35
- }
36
- }
37
- exports.InvalidFieldTypeError = InvalidFieldTypeError;
38
- class InvalidValueError extends errors_1.BadRequest {
39
- constructor(value, fieldDefinitionName, joiValidationError) {
40
- const formattedErrorMessage = joiValidationError.message
41
- .replace(/"/g, '')
42
- .replace('value', `'${fieldDefinitionName}'`);
43
- const formattedValue = typeof value === 'object' ? JSON.stringify(value) : value;
44
- const invalidValueMessage = `Invalid Value on field '${fieldDefinitionName}'. ${formattedErrorMessage}. received: '${formattedValue}'`;
45
- const err = new Error(invalidValueMessage);
46
- super([err], null, null);
47
- this.message = invalidValueMessage;
48
- }
49
- }
50
- exports.InvalidValueError = InvalidValueError;
51
- class InvalidEntriesError extends errors_1.BadRequest {
52
- constructor(modelId, validationErrors) {
53
- const errors = validationErrors.map((validationError) => new InvalidValueError(validationError.value, validationError.fieldDefinitionName, validationError.joiValidationError));
54
- super(errors, null, null);
55
- this.message = `Invalid entries on ${modelId}\n${validationErrors.map((validationError) => (`${validationError.fieldDefinitionName} - ${validationError.joiValidationError.message}`)).join('\n')}`;
56
- }
57
- }
58
- exports.InvalidEntriesError = InvalidEntriesError;
59
- class MissingDefinitionError extends errors_1.BadRequest {
60
- constructor(fieldNames) {
61
- const err = new Error(`Missing custom field definition for field ${fieldNames.join(',')}`);
62
- super([err], null, null);
63
- this.message = 'MISSING_DEFINITION';
64
- }
65
- }
66
- exports.MissingDefinitionError = MissingDefinitionError;
@@ -1,4 +0,0 @@
1
- import Events from '@autofleet/events';
2
- declare const events: Events;
3
- export declare const sendDimEvent: (instance: any) => void;
4
- export default events;
@@ -1,50 +0,0 @@
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.sendDimEvent = void 0;
7
- const events_1 = __importDefault(require("@autofleet/events"));
8
- const logger_1 = __importDefault(require("../utils/logger"));
9
- const events = new events_1.default({ logger: logger_1.default });
10
- const KEYS_TO_CONVERT = ['value', 'defaultValue', 'blockEditingFromUI'];
11
- const stringifyBooleans = (savedObject, keysToConvert) => {
12
- const savedObjectKeySet = new Set(Object.keys(savedObject));
13
- if (keysToConvert.every((key) => !savedObjectKeySet.has(key))) {
14
- return savedObject;
15
- }
16
- return {
17
- ...savedObject,
18
- ...Object.fromEntries(keysToConvert.map((key) => [key, typeof savedObject[key] === 'boolean' ? savedObject[key].toString() : savedObject[key]])),
19
- };
20
- };
21
- const modelTableMapping = {
22
- CustomFieldDefinition: {
23
- tableName: 'dim_custom_field_definition',
24
- eventVersion: '1',
25
- },
26
- CustomFieldValue: {
27
- tableName: 'dim_custom_field_value',
28
- eventVersion: '1',
29
- },
30
- CustomFieldEntries: {
31
- tableName: 'dim_custom_field_entries',
32
- eventVersion: '1',
33
- },
34
- };
35
- const sendDimEvent = (instance) => {
36
- const mapping = modelTableMapping[instance.constructor.name];
37
- if (!mapping) {
38
- return;
39
- }
40
- let objectToSend = instance.get();
41
- try {
42
- objectToSend = stringifyBooleans(instance.get(), KEYS_TO_CONVERT);
43
- }
44
- catch (err) {
45
- logger_1.default.error('Failed to convert booleans in dim event payload', err);
46
- }
47
- events.sendObject(mapping.tableName, mapping.eventVersion, objectToSend).catch(() => null);
48
- };
49
- exports.sendDimEvent = sendDimEvent;
50
- exports.default = events;
@@ -1,10 +0,0 @@
1
- import type { CustomFieldOptions, ModelOptions } from '../types';
2
- /**
3
- * A hook to create the custom fields when updating a model (more then one instance).
4
- */
5
- export declare const beforeBulkCreate: (options: any) => void;
6
- /**
7
- * A hook to create the custom fields when updating a model instance.
8
- * TODO - cleanup if update fail
9
- */
10
- export declare const beforeCreate: (scopeAttributes: string[], modelOptions?: ModelOptions, sadotOptions?: Pick<CustomFieldOptions, 'useCustomFieldsEntries'>) => (instance: any, options: any) => Promise<void>;
@@ -1,95 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- var __importDefault = (this && this.__importDefault) || function (mod) {
26
- return (mod && mod.__esModule) ? mod : { "default": mod };
27
- };
28
- Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.beforeCreate = exports.beforeBulkCreate = void 0;
30
- const logger_1 = __importDefault(require("../utils/logger"));
31
- const DefinitionRepo = __importStar(require("../repository/definition"));
32
- const errors_1 = require("../errors");
33
- const scopeAttributes_1 = __importDefault(require("../utils/scopeAttributes"));
34
- const updateInstanceValues_1 = __importDefault(require("./utils/updateInstanceValues"));
35
- /**
36
- * A hook to create the custom fields when updating a model (more then one instance).
37
- */
38
- const beforeBulkCreate = (options) => {
39
- // This will activate the beforeCreate hook on each updating instance.
40
- // eslint-disable-next-line no-param-reassign
41
- options.individualHooks = true;
42
- };
43
- exports.beforeBulkCreate = beforeBulkCreate;
44
- /**
45
- * A hook to create the custom fields when updating a model instance.
46
- * TODO - cleanup if update fail
47
- */
48
- const beforeCreate = (scopeAttributes, modelOptions = {}, sadotOptions = { useCustomFieldsEntries: false }) => async (instance, options) => {
49
- logger_1.default.debug('sadot - before create hook');
50
- const { fields } = options;
51
- const { include, useEntityIdFromInclude } = modelOptions;
52
- const modelType = instance.constructor.name;
53
- const identifiers = (0, scopeAttributes_1.default)(instance, scopeAttributes);
54
- const where = {
55
- modelType,
56
- disabled: false,
57
- ...(!useEntityIdFromInclude && { entityId: identifiers }),
58
- };
59
- const fieldDefinitions = await DefinitionRepo.findAll(where, { withDisabled: false, transaction: options.transaction, include: include?.(identifiers) });
60
- const requiredFieldsNames = Array.from(new Set(fieldDefinitions.filter(({ required }) => required).map(({ name }) => name)));
61
- const fieldsWithDefaultValue = fieldDefinitions.filter((def) => ![null, undefined].includes(def.defaultValue));
62
- if (fieldsWithDefaultValue.length) {
63
- // eslint-disable-next-line no-param-reassign
64
- instance.customFields || (instance.customFields = {});
65
- fieldsWithDefaultValue.filter((def) => (instance.customFields?.[def.name] === undefined)).forEach(({ name, defaultValue }) => {
66
- // eslint-disable-next-line no-param-reassign
67
- instance.customFields[name] = defaultValue;
68
- });
69
- }
70
- const { customFields } = instance;
71
- const fieldsNames = Object.keys(customFields ?? {});
72
- const missingFields = requiredFieldsNames.filter((name) => !fieldsNames.includes(name));
73
- if (missingFields?.length) {
74
- throw new errors_1.MissingRequiredCustomFieldError(missingFields);
75
- }
76
- const customFieldsIdx = fields.indexOf('customFields');
77
- if (customFieldsIdx === -1 || !customFields || !Object.keys(customFields).length) {
78
- // After checking for required fields and fields with default values, and we have no custom fields.
79
- return;
80
- }
81
- await (0, updateInstanceValues_1.default)({
82
- modelId: instance.id,
83
- modelType,
84
- identifiers,
85
- customFields,
86
- options: {
87
- useCustomFieldsEntries: sadotOptions.useCustomFieldsEntries,
88
- transaction: options.transaction,
89
- modelOptions,
90
- },
91
- });
92
- // eslint-disable-next-line no-param-reassign
93
- fields.splice(customFieldsIdx, 1);
94
- };
95
- exports.beforeCreate = beforeCreate;
@@ -1,30 +0,0 @@
1
- import type { Transaction } from 'sequelize';
2
- import type CustomFieldValue from '../models/CustomFieldValue';
3
- import type { CustomFieldOptions, ModelOptions } from '../types';
4
- type SupportedHookTypes = 'afterFind' | 'afterCreate' | 'afterUpdate';
5
- type CustomFieldEntries = Record<string, any>;
6
- interface GetValuesGroupByInstanceResponse {
7
- [modelId: string]: CustomFieldValue[];
8
- }
9
- interface GetCustomFieldEntriesByInstanceIdResponse {
10
- [modelId: string]: CustomFieldEntries;
11
- }
12
- export declare const getCustomFieldEntriesByInstanceId: ({ instancesIds, options, sadotOptions, }: {
13
- instancesIds: string[];
14
- options?: {
15
- transaction: Transaction;
16
- };
17
- sadotOptions: Pick<CustomFieldOptions, 'useCustomFieldsEntries'>;
18
- }) => Promise<GetCustomFieldEntriesByInstanceIdResponse>;
19
- export declare const getValuesGroupByInstance: ({ instancesIds, options, sadotOptions, }: {
20
- instancesIds: string[];
21
- options?: {
22
- transaction: Transaction;
23
- };
24
- sadotOptions: Pick<CustomFieldOptions, 'useCustomFieldsEntries'>;
25
- }) => Promise<GetValuesGroupByInstanceResponse>;
26
- /**
27
- * A hook to attach the custom fields when fetching a model instances.
28
- */
29
- declare const enrichResults: (modelType: string, scopeAttributes: string[], hookType?: SupportedHookTypes, modelOptions?: ModelOptions, sadotOptions?: Pick<CustomFieldOptions, 'useCustomFieldsEntries'>) => (instancesOrInstance: any | any[], options: any) => Promise<void>;
30
- export default enrichResults;
@@ -1,159 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- var __importDefault = (this && this.__importDefault) || function (mod) {
26
- return (mod && mod.__esModule) ? mod : { "default": mod };
27
- };
28
- Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.getValuesGroupByInstance = exports.getCustomFieldEntriesByInstanceId = void 0;
30
- const ValueRepo = __importStar(require("../repository/value"));
31
- const DefinitionRepo = __importStar(require("../repository/definition"));
32
- const EntriesRepo = __importStar(require("../repository/entries"));
33
- const scopeAttributes_1 = __importDefault(require("../utils/scopeAttributes"));
34
- const getCustomFieldEntriesByInstanceId = async ({ instancesIds, options, sadotOptions, }) => {
35
- if (!sadotOptions.useCustomFieldsEntries) {
36
- return {};
37
- }
38
- const customFieldEntries = await EntriesRepo.findEntriesByModelIds(instancesIds, options ?? {});
39
- const customFieldEntriesByInstanceId = Object.fromEntries(customFieldEntries.map((instanceEntries) => {
40
- const { modelId, customFields } = instanceEntries?.dataValues ?? {};
41
- if (!modelId) {
42
- return undefined;
43
- }
44
- return [modelId, customFields];
45
- }).filter(Boolean));
46
- instancesIds.forEach((instanceId) => {
47
- customFieldEntriesByInstanceId[instanceId] ?? (customFieldEntriesByInstanceId[instanceId] = {});
48
- });
49
- return customFieldEntriesByInstanceId;
50
- };
51
- exports.getCustomFieldEntriesByInstanceId = getCustomFieldEntriesByInstanceId;
52
- const getValuesGroupByInstance = async ({ instancesIds, options, sadotOptions, }) => {
53
- if (sadotOptions.useCustomFieldsEntries) {
54
- return {};
55
- }
56
- const customFieldValues = await ValueRepo.findValuesByModelIds(instancesIds, options ?? {});
57
- // Group fields by modelId
58
- return customFieldValues.reduce((acc, v) => {
59
- const { modelId } = v;
60
- acc[modelId] ?? (acc[modelId] = []);
61
- acc[modelId].push(v);
62
- return acc;
63
- }, {});
64
- };
65
- exports.getValuesGroupByInstance = getValuesGroupByInstance;
66
- /**
67
- * Serialize custom fields value into the format of {[name] -> [fieldData]}
68
- */
69
- const serializeCustomFields = (customFieldValues, customFieldDefinitionsHash) => {
70
- const customFields = customFieldValues.reduce((acc, cfv) => ({
71
- ...acc,
72
- ...(customFieldDefinitionsHash[cfv.customFieldDefinitionId]
73
- && { [customFieldDefinitionsHash[cfv.customFieldDefinitionId].name]: cfv.value }),
74
- }), {});
75
- return customFields;
76
- };
77
- /**
78
- * A hook to attach the custom fields when fetching a model instances.
79
- */
80
- const enrichResults = (modelType, scopeAttributes, hookType, modelOptions = {}, sadotOptions = { useCustomFieldsEntries: false }) => async (instancesOrInstance, options) => {
81
- if (options.originalAttributes?.length > 0
82
- && !options.originalAttributes?.includes?.('customFields')) {
83
- return;
84
- }
85
- const primaryKey = 'id';
86
- let instances = Array.isArray(instancesOrInstance)
87
- ? instancesOrInstance
88
- : [instancesOrInstance];
89
- instances = instances.filter(Boolean);
90
- const identifiers = (0, scopeAttributes_1.default)(instances, scopeAttributes);
91
- const uniqueIdentifiers = [...new Set(identifiers)].filter(Boolean);
92
- const identifierCustomFieldDefinitionsMapping = uniqueIdentifiers.reduce((map, identifier) => ({
93
- ...map,
94
- [identifier]: [],
95
- }), {});
96
- const customFieldDefinitions = await DefinitionRepo.findByEntityIds(modelType, uniqueIdentifiers, { transaction: options.transaction, modelOptions });
97
- if (modelOptions?.include && modelOptions.useEntityIdFromInclude) {
98
- // if we pass useEntityIdFromInclude,
99
- // map the entity from the options to the identifierCustomFieldDefinitionsMapping
100
- modelOptions.include(identifiers).forEach(({ model }) => {
101
- customFieldDefinitions.forEach((cfd) => {
102
- const entityId = cfd[`${model.name}.entityId`];
103
- identifierCustomFieldDefinitionsMapping[entityId] = [];
104
- });
105
- });
106
- }
107
- const definitionsMap = customFieldDefinitions.reduce((map, definition) => ({
108
- ...map,
109
- [definition.id]: definition,
110
- }), {});
111
- customFieldDefinitions.forEach((cfd) => {
112
- identifierCustomFieldDefinitionsMapping[cfd.entityId].push(cfd);
113
- });
114
- // Get the values per instates ids:
115
- const instancesIds = instances.map((i) => i[primaryKey]);
116
- // Group fields by modelId
117
- const valuesGroupByInstance = await (0, exports.getValuesGroupByInstance)({
118
- instancesIds,
119
- options,
120
- sadotOptions,
121
- });
122
- const customFieldEntriesByInstanceId = await (0, exports.getCustomFieldEntriesByInstanceId)({
123
- instancesIds,
124
- options,
125
- sadotOptions,
126
- });
127
- // Attach custom fields to the instances
128
- instances.forEach((instance) => {
129
- const { id } = instance;
130
- const instanceValues = valuesGroupByInstance[id];
131
- const serializedCustomFieldsValues = instanceValues ? serializeCustomFields(instanceValues, definitionsMap) : {};
132
- const customFields = sadotOptions.useCustomFieldsEntries
133
- ? customFieldEntriesByInstanceId[id]
134
- : serializedCustomFieldsValues;
135
- scopeAttributes.forEach((attribute) => {
136
- const identifier = instance[attribute];
137
- const entityCustomFieldDefinitions = identifierCustomFieldDefinitionsMapping[identifier];
138
- if (entityCustomFieldDefinitions?.length > 0) {
139
- entityCustomFieldDefinitions.forEach((customFieldDefinition) => {
140
- if (customFields[customFieldDefinition.name] === undefined) {
141
- customFields[customFieldDefinition.name] = null;
142
- }
143
- });
144
- }
145
- });
146
- instance.customFields = customFields;
147
- options.attributesToRemove?.forEach?.((attribute) => {
148
- delete instance.dataValues?.[attribute];
149
- // if raw:
150
- delete instance?.[attribute];
151
- });
152
- // sequelize will think customFields changed also in 'find', so we need to mark it as unchanged
153
- if (hookType === 'afterFind') {
154
- // changed() could be undefined, i.e in raw: true
155
- instance?.changed?.('customFields', false);
156
- }
157
- });
158
- };
159
- exports.default = enrichResults;
@@ -1 +0,0 @@
1
- export declare const beforeFind: (scopeAttributes: string[]) => (options: any) => void;
@@ -1,29 +0,0 @@
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.beforeFind = void 0;
7
- /* eslint-disable no-param-reassign */
8
- const logger_1 = __importDefault(require("../utils/logger"));
9
- const doScopeAttributesMissing = (scopeAttributes, queryAttributes) => {
10
- const attributes = scopeAttributes
11
- .filter((attribute) => !queryAttributes.includes(attribute));
12
- if (!queryAttributes.includes?.('id')) {
13
- attributes.push('id');
14
- }
15
- return attributes;
16
- };
17
- // eslint-disable-next-line import/prefer-default-export
18
- const beforeFind = (scopeAttributes) => (options) => {
19
- const { attributes: queryAttributes } = options;
20
- if (queryAttributes?.includes?.('customFields')) {
21
- const missingScopeAttributes = doScopeAttributesMissing(scopeAttributes, queryAttributes);
22
- logger_1.default.debug('sadot - before find hook');
23
- if (missingScopeAttributes?.length > 0) {
24
- queryAttributes.push(...missingScopeAttributes);
25
- options.attributesToRemove = missingScopeAttributes;
26
- }
27
- }
28
- };
29
- exports.beforeFind = beforeFind;
@@ -1,6 +0,0 @@
1
- import enrichResults from './enrich';
2
- import { beforeFind } from './find';
3
- import { beforeBulkUpdate, beforeUpdate } from './update';
4
- import { beforeBulkCreate, beforeCreate } from './create';
5
- import workaround from './workaround';
6
- export { enrichResults, beforeFind, beforeBulkUpdate, beforeUpdate, beforeBulkCreate, beforeCreate, workaround, };
@@ -1,18 +0,0 @@
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.workaround = exports.beforeCreate = exports.beforeBulkCreate = exports.beforeUpdate = exports.beforeBulkUpdate = exports.beforeFind = exports.enrichResults = void 0;
7
- const enrich_1 = __importDefault(require("./enrich"));
8
- exports.enrichResults = enrich_1.default;
9
- const find_1 = require("./find");
10
- Object.defineProperty(exports, "beforeFind", { enumerable: true, get: function () { return find_1.beforeFind; } });
11
- const update_1 = require("./update");
12
- Object.defineProperty(exports, "beforeBulkUpdate", { enumerable: true, get: function () { return update_1.beforeBulkUpdate; } });
13
- Object.defineProperty(exports, "beforeUpdate", { enumerable: true, get: function () { return update_1.beforeUpdate; } });
14
- const create_1 = require("./create");
15
- Object.defineProperty(exports, "beforeBulkCreate", { enumerable: true, get: function () { return create_1.beforeBulkCreate; } });
16
- Object.defineProperty(exports, "beforeCreate", { enumerable: true, get: function () { return create_1.beforeCreate; } });
17
- const workaround_1 = __importDefault(require("./workaround"));
18
- exports.workaround = workaround_1.default;
@@ -1,10 +0,0 @@
1
- import type { CustomFieldOptions, ModelOptions } from '../types';
2
- /**
3
- * A hook to update the custom fields when updating a model (more then one instance).
4
- */
5
- export declare const beforeBulkUpdate: (options: any) => void;
6
- /**
7
- * A hook to update the custom fields when updating a model instance.
8
- * TODO - cleanup if update fail
9
- */
10
- export declare const beforeUpdate: (scopeAttributes: string[], modelOptions?: ModelOptions, sadotOptions?: Pick<CustomFieldOptions, 'useCustomFieldsEntries'>) => (instance: any, options: any) => Promise<void>;
@@ -1,49 +0,0 @@
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.beforeUpdate = exports.beforeBulkUpdate = void 0;
7
- const logger_1 = __importDefault(require("../utils/logger"));
8
- const scopeAttributes_1 = __importDefault(require("../utils/scopeAttributes"));
9
- const updateInstanceValues_1 = __importDefault(require("./utils/updateInstanceValues"));
10
- /**
11
- * A hook to update the custom fields when updating a model (more then one instance).
12
- */
13
- const beforeBulkUpdate = (options) => {
14
- // This will activate the beforeUpdate hook on each updating instance.
15
- // eslint-disable-next-line no-param-reassign
16
- options.individualHooks = true;
17
- };
18
- exports.beforeBulkUpdate = beforeBulkUpdate;
19
- /**
20
- * A hook to update the custom fields when updating a model instance.
21
- * TODO - cleanup if update fail
22
- */
23
- const beforeUpdate = (scopeAttributes, modelOptions = {}, sadotOptions = { useCustomFieldsEntries: false }) => async (instance, options) => {
24
- logger_1.default.debug('sadot - before update hook');
25
- const { fields } = options;
26
- const modelType = instance.constructor.name;
27
- const identifiers = (0, scopeAttributes_1.default)(instance, scopeAttributes);
28
- const customFieldsIdx = fields.indexOf('customFields');
29
- if (customFieldsIdx > -1) {
30
- const { customFields } = instance;
31
- if (!Object.keys(customFields).length) {
32
- return;
33
- }
34
- await (0, updateInstanceValues_1.default)({
35
- modelId: instance.id,
36
- modelType,
37
- identifiers,
38
- customFields,
39
- options: {
40
- useCustomFieldsEntries: sadotOptions.useCustomFieldsEntries,
41
- transaction: options.transaction,
42
- modelOptions,
43
- },
44
- });
45
- // eslint-disable-next-line no-param-reassign
46
- fields.splice(customFieldsIdx, 1);
47
- }
48
- };
49
- exports.beforeUpdate = beforeUpdate;
@@ -1,15 +0,0 @@
1
- import type { Transaction } from 'sequelize';
2
- import type { ModelOptions } from '../../types';
3
- interface UpdateInstanceValuesParams {
4
- modelId: string;
5
- modelType: string;
6
- identifiers: string[];
7
- customFields: Record<string, any>;
8
- options?: {
9
- transaction?: Transaction;
10
- modelOptions?: ModelOptions;
11
- useCustomFieldsEntries?: boolean;
12
- };
13
- }
14
- declare const updateInstanceValues: ({ modelId, modelType, identifiers, customFields, options, }: UpdateInstanceValuesParams) => Promise<void>;
15
- export default updateInstanceValues;
@@ -1,50 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- const ValueRepo = __importStar(require("../../repository/value"));
27
- const EntriesRepo = __importStar(require("../../repository/entries"));
28
- const updateInstanceValues = async ({ modelId, modelType, identifiers, customFields, options = {
29
- modelOptions: {},
30
- useCustomFieldsEntries: false,
31
- }, }) => {
32
- await ValueRepo.updateValues(modelType, modelId, identifiers, customFields, {
33
- ...options,
34
- modelOptions: options.modelOptions ?? {},
35
- });
36
- /*
37
- T.Y TODO - Once we're ready to switch from custom_field_values to custom_field_entries, we should remove the ValueRepo.updateValues call.
38
- Currently, We're updating both tables to keep the data in sync, but not all microservices are using the new table yet.
39
- */
40
- if (!options?.useCustomFieldsEntries) {
41
- return;
42
- }
43
- const { dataValues: { customFields: oldCustomFields } } = await EntriesRepo.findEntriesByModelId(modelId, options) ?? { dataValues: {} };
44
- const newCustomFields = { ...oldCustomFields, ...customFields };
45
- await EntriesRepo.updateEntries(modelId, modelType, newCustomFields, identifiers, {
46
- ...options,
47
- modelOptions: options.modelOptions ?? {},
48
- });
49
- };
50
- exports.default = updateInstanceValues;
@@ -1,10 +0,0 @@
1
- /**
2
- * Workaround to a bug in sequelize.🐛
3
- *
4
- * **afterFind hook** isn't working on nested (included) models.
5
- * The solution here is to add a global afterFind hook,
6
- * which manually calls the afterFind hook of each model, recursively
7
- * https://github.com/sequelize/sequelize/issues/4627
8
- */
9
- declare const handleChildrenAfterFindHook: (instances: any, options: any, level?: number) => any;
10
- export default handleChildrenAfterFindHook;
@@ -1,37 +0,0 @@
1
- "use strict";
2
- /**
3
- * Workaround to a bug in sequelize.🐛
4
- *
5
- * **afterFind hook** isn't working on nested (included) models.
6
- * The solution here is to add a global afterFind hook,
7
- * which manually calls the afterFind hook of each model, recursively
8
- * https://github.com/sequelize/sequelize/issues/4627
9
- */
10
- Object.defineProperty(exports, "__esModule", { value: true });
11
- const handleChildrenAfterFindHook = async (instances, options, level = 0) => {
12
- if (!instances)
13
- return Promise.resolve();
14
- if (Array.isArray(instances)) {
15
- return Promise.all(instances.map((instance) => {
16
- const { options: instanceOptions } = instance.constructor;
17
- return handleChildrenAfterFindHook(instance, instanceOptions, level);
18
- }));
19
- }
20
- const instance = instances;
21
- const { constructor } = instance;
22
- /**
23
- * Root model will have already run their "afterFind" hook.
24
- * Only run children "afterFind" hooks.
25
- */
26
- if (level >= 1) {
27
- await constructor.runHooks('afterFind', instance, options);
28
- }
29
- const { associations } = constructor;
30
- const associatedNames = Object.keys(instance).filter((attribute) => Object.keys(associations).includes(attribute));
31
- if (associatedNames.length) {
32
- const childInstances = associatedNames.map((name) => instance[name]);
33
- return handleChildrenAfterFindHook(childInstances, options, level + 1);
34
- }
35
- return Promise.resolve();
36
- };
37
- exports.default = handleChildrenAfterFindHook;