@autofleet/sadot 1.0.1-beta → 1.0.2

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.
@@ -4,34 +4,36 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const joi_1 = __importDefault(require("joi"));
7
+ // Schema for validating JSON Schema objects
7
8
  const jsonSchemaValidation = joi_1.default.object().unknown(true);
8
- const schemaObject = joi_1.default.object({
9
- type: joi_1.default.string().valid('object'),
10
- properties: joi_1.default.object({
11
- before: jsonSchemaValidation,
12
- after: jsonSchemaValidation,
13
- }).required(),
14
- required: joi_1.default.array().items(joi_1.default.string()), // 👈 כאן הוספנו
15
- allOf: joi_1.default.array().items(joi_1.default.object()), // 👈 אופציונלי
16
- anyOf: joi_1.default.array().items(joi_1.default.object()), // 👈 אופציונלי
17
- oneOf: joi_1.default.array().items(joi_1.default.object()), // 👈 אופציונלי
18
- additionalProperties: joi_1.default.alternatives().try(joi_1.default.boolean(), joi_1.default.object()),
19
- $id: joi_1.default.string(),
20
- $schema: joi_1.default.string(),
21
- if: joi_1.default.object(),
22
- then: joi_1.default.object(),
23
- else: joi_1.default.object(),
24
- });
25
9
  const validationSchemas = {
26
10
  create: joi_1.default.object({
27
11
  entityId: joi_1.default.string().uuid().required(),
28
12
  entityType: joi_1.default.string().required(),
29
- schema: schemaObject.required(), // schema חייב להיות קיים
13
+ schema: joi_1.default.object({
14
+ type: joi_1.default.string().valid('object').required(),
15
+ properties: joi_1.default.object({
16
+ before: jsonSchemaValidation,
17
+ after: jsonSchemaValidation,
18
+ }).required(),
19
+ if: joi_1.default.object().optional(),
20
+ then: joi_1.default.object().optional(),
21
+ else: joi_1.default.object().optional(),
22
+ }).required(),
30
23
  }),
31
24
  update: joi_1.default.object({
32
25
  entityId: joi_1.default.string().uuid(),
33
26
  entityType: joi_1.default.string(),
34
- schema: schemaObject,
27
+ schema: joi_1.default.object({
28
+ type: joi_1.default.string().valid('object'),
29
+ properties: joi_1.default.object({
30
+ before: jsonSchemaValidation,
31
+ after: jsonSchemaValidation,
32
+ }),
33
+ if: joi_1.default.object().optional(),
34
+ then: joi_1.default.object().optional(),
35
+ else: joi_1.default.object().optional(),
36
+ }),
35
37
  disabled: joi_1.default.boolean(),
36
38
  }).min(1),
37
39
  };
@@ -90,19 +90,6 @@ const getCompleteCustomFields = async (instance, options) => {
90
90
  }
91
91
  return instance.customFields || {};
92
92
  };
93
- const buildBeforeFromInstance = (instance) => {
94
- const beforeFull = { ...instance.dataValues };
95
- const changedKeys = instance.changed?.() || [];
96
- for (const k of changedKeys) {
97
- const prevVal = instance.previous?.(k);
98
- if (prevVal !== undefined)
99
- beforeFull[k] = prevVal;
100
- }
101
- const prevCF = instance.previous?.('customFields');
102
- if (prevCF !== undefined)
103
- beforeFull.customFields = prevCF;
104
- return beforeFull;
105
- };
106
93
  const formatAjvErrors = (errors) => errors.reduce((acc, err) => {
107
94
  const basePath = (err.instancePath || '')
108
95
  .split('/')
@@ -148,10 +135,7 @@ const validateModel = async (instance, options, scopeAttributes, modelOptions =
148
135
  validatorsPromise = ValidatorRepo.findAllByModelType(modelType, entityId, {
149
136
  transaction: options.transaction,
150
137
  attributes: CUSTOM_VALIDATOR_ATTRIBUTES_TO_PULL,
151
- ...(modelOptions.include && {
152
- include: modelOptions.include?.(entityId),
153
- }),
154
- raw: true,
138
+ modelOptions,
155
139
  });
156
140
  if (options.transaction) {
157
141
  options?.transaction?.validationsCache.set(cacheKey, validatorsPromise);
@@ -166,7 +150,10 @@ const validateModel = async (instance, options, scopeAttributes, modelOptions =
166
150
  // For updates, get the previous values
167
151
  let originalValues = null;
168
152
  if (!isCreate) {
169
- originalValues = buildBeforeFromInstance(instance);
153
+ // Create originalValues with our helper function
154
+ originalValues = manualObjectCopy(instance.previous());
155
+ // Add customFields separately
156
+ originalValues.customFields = instance.previous('customFields') || {};
170
157
  }
171
158
  // Get complete custom fields by merging DB values with update values
172
159
  // This is especially important for partial updates to ensure all related fields are available
package/dist/index.d.ts CHANGED
@@ -8,6 +8,6 @@ export * from './utils/helpers';
8
8
  * Adding custom fields enrichment to the models inside the MODELS_FILE_NAME json file
9
9
  * @see {@link 'custom-fields/config'} for configurations
10
10
  */
11
- declare const useCustomFields: (app: Application | null, getModel: ModelFetcher, options: CustomFieldOptions) => Promise<Sequelize>;
11
+ declare const useCustomFields: (app: Pick<Application, 'use'> | null, getModel: ModelFetcher, options: CustomFieldOptions) => Promise<Sequelize>;
12
12
  export default useCustomFields;
13
13
  export declare const disableCustomFields: (models: Models[], getModel: ModelFetcher) => void;
@@ -1,5 +1,6 @@
1
- import type { IncludeOptions, Transactionable } from 'sequelize';
1
+ import type { FindOptions, IncludeOptions, Transactionable } from 'sequelize';
2
2
  import { CustomValidator } from '../models';
3
+ import type { ModelOptions } from '../types';
3
4
  export interface FindValidatorOptions extends Transactionable {
4
5
  withDisabled?: boolean;
5
6
  attributes?: string[];
@@ -15,7 +16,13 @@ export interface ValidatorAttributes {
15
16
  [key: string]: unknown;
16
17
  }
17
18
  export declare const create: (validatorAttributes: ValidatorAttributes, options?: Transactionable) => Promise<CustomValidator>;
18
- export declare const findAll: (where?: {}, options?: FindValidatorOptions) => Promise<CustomValidator[]>;
19
- export declare const findAllByModelType: (modelType: string, entityId: string, options?: FindValidatorOptions) => Promise<CustomValidator[]>;
19
+ export declare const findAll: (where?: {}, options?: FindOptions & {
20
+ modelOptions?: ModelOptions;
21
+ withDisabled?: boolean;
22
+ }) => Promise<CustomValidator[]>;
23
+ export declare const findAllByModelType: (modelType: string, entityId: string, options?: FindOptions & {
24
+ modelOptions?: ModelOptions;
25
+ withDisabled?: boolean;
26
+ }) => Promise<CustomValidator[]>;
20
27
  export declare const update: (id: string, updates: Partial<ValidatorAttributes>, options?: Transactionable) => Promise<[number, CustomValidator[]]>;
21
28
  export declare const disable: (id: string, options?: Transactionable) => Promise<[number, CustomValidator[]]>;
@@ -13,9 +13,9 @@ const create = async (validatorAttributes, options = {}) => {
13
13
  return validator;
14
14
  };
15
15
  exports.create = create;
16
- const findAll = async (where = {}, options = { withDisabled: false }) => {
16
+ const findAll = async (where = {}, options = {}) => {
17
17
  logger_1.default.debug('custom-validator - find all validators');
18
- const { transaction, withDisabled } = options;
18
+ const { transaction, withDisabled, include, attributes, raw, } = options;
19
19
  let validators;
20
20
  if (withDisabled) {
21
21
  // If withDisabled is true, use unscoped to ignore the default scope that filters disabled items
@@ -23,6 +23,9 @@ const findAll = async (where = {}, options = { withDisabled: false }) => {
23
23
  validators = await models_1.CustomValidator.unscoped().scope('userScope').findAll({
24
24
  where,
25
25
  transaction,
26
+ include,
27
+ attributes,
28
+ raw,
26
29
  });
27
30
  }
28
31
  else {
@@ -31,19 +34,23 @@ const findAll = async (where = {}, options = { withDisabled: false }) => {
31
34
  validators = await models_1.CustomValidator.scope(['defaultScope', 'userScope']).findAll({
32
35
  where,
33
36
  transaction,
37
+ include,
38
+ attributes,
39
+ raw,
34
40
  });
35
41
  }
36
42
  return validators;
37
43
  };
38
44
  exports.findAll = findAll;
39
- const findAllByModelType = async (modelType, entityId, options = { withDisabled: false }) => {
45
+ const findAllByModelType = async (modelType, entityId, options = {}) => {
40
46
  logger_1.default.debug('custom-validator - find all validators by model type');
41
47
  return (0, exports.findAll)({
42
48
  modelType,
43
- ...(!options.include && {
44
- entityId,
45
- }),
46
- }, options);
49
+ ...(!options?.modelOptions?.useEntityIdFromInclude && { entityId }),
50
+ }, {
51
+ ...options,
52
+ include: options?.modelOptions?.include?.(entityId),
53
+ });
47
54
  };
48
55
  exports.findAllByModelType = findAllByModelType;
49
56
  const update = async (id, updates, options) => {
@@ -14,7 +14,7 @@ export type ModelOptions = {
14
14
  /**
15
15
  * Include options for the model
16
16
  */
17
- include?: (entityIds: string[]) => IncludeOptions[];
17
+ include?: (entityIds: string | string[]) => IncludeOptions[];
18
18
  /**
19
19
  * Custom association for the model
20
20
  * @param model - The model to associate with
@@ -106,6 +106,7 @@ exports.addScopes = addScopes;
106
106
  const applyCustomAssociation = (models) => {
107
107
  models.forEach(({ modelOptions }) => {
108
108
  modelOptions?.customAssociation?.(models_1.CustomFieldDefinition);
109
+ modelOptions?.customAssociation?.(models_1.CustomValidator);
109
110
  });
110
111
  };
111
112
  exports.applyCustomAssociation = applyCustomAssociation;
@@ -1,4 +1,27 @@
1
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
+ };
2
25
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
27
  };
@@ -8,8 +31,8 @@ const logger_1 = __importDefault(require("@autofleet/logger"));
8
31
  const logger = (0, logger_1.default)();
9
32
  async function tryAddingTraceIdMiddleware() {
10
33
  try {
11
- // const { outbreak } = await import('@autofleet/zehut');
12
- // logger.addContextMiddleware(() => ({ traceId: outbreak.getCurrentContextTraceId() }));
34
+ const { outbreak } = await Promise.resolve().then(() => __importStar(require('@autofleet/zehut')));
35
+ logger.addContextMiddleware(() => ({ traceId: outbreak.getCurrentContextTraceId() }));
13
36
  }
14
37
  catch (err) {
15
38
  logger.error('Failed to add traceId middleware', { err });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autofleet/sadot",
3
- "version": "1.0.1-beta",
3
+ "version": "1.0.2",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -1,36 +1,37 @@
1
1
  import Joi from 'joi';
2
2
 
3
+ // Schema for validating JSON Schema objects
3
4
  const jsonSchemaValidation = Joi.object().unknown(true);
4
5
 
5
- const schemaObject = Joi.object({
6
- type: Joi.string().valid('object'),
7
- properties: Joi.object({
8
- before: jsonSchemaValidation,
9
- after: jsonSchemaValidation,
10
- }).required(),
11
- required: Joi.array().items(Joi.string()),
12
- allOf: Joi.array().items(Joi.object()),
13
- anyOf: Joi.array().items(Joi.object()),
14
- oneOf: Joi.array().items(Joi.object()),
15
- additionalProperties: Joi.alternatives().try(Joi.boolean(), Joi.object()),
16
- $id: Joi.string(),
17
- $schema: Joi.string(),
18
- if: Joi.object(),
19
- then: Joi.object(),
20
- else: Joi.object(),
21
- });
22
-
23
6
  const validationSchemas = {
24
7
  create: Joi.object({
25
8
  entityId: Joi.string().uuid().required(),
26
9
  entityType: Joi.string().required(),
27
- schema: schemaObject.required(),
10
+ schema: Joi.object({
11
+ type: Joi.string().valid('object').required(),
12
+ properties: Joi.object({
13
+ before: jsonSchemaValidation,
14
+ after: jsonSchemaValidation,
15
+ }).required(),
16
+ if: Joi.object().optional(),
17
+ then: Joi.object().optional(),
18
+ else: Joi.object().optional(),
19
+ }).required(),
28
20
  }),
29
21
 
30
22
  update: Joi.object({
31
23
  entityId: Joi.string().uuid(),
32
24
  entityType: Joi.string(),
33
- schema: schemaObject,
25
+ schema: Joi.object({
26
+ type: Joi.string().valid('object'),
27
+ properties: Joi.object({
28
+ before: jsonSchemaValidation,
29
+ after: jsonSchemaValidation,
30
+ }),
31
+ if: Joi.object().optional(),
32
+ then: Joi.object().optional(),
33
+ else: Joi.object().optional(),
34
+ }),
34
35
  disabled: Joi.boolean(),
35
36
  }).min(1),
36
37
  };
@@ -78,25 +78,6 @@ const getCompleteCustomFields = async (instance, options): Promise<Record<string
78
78
  return instance.customFields || {};
79
79
  };
80
80
 
81
- const buildBeforeFromInstance = (instance: any) => {
82
- const beforeFull: any = { ...instance.dataValues };
83
-
84
- const changedKeys: string[] = instance.changed?.() || [];
85
- changedKeys.forEach((key) => {
86
- const prevVal = instance.previous?.(key);
87
- if (prevVal !== undefined) {
88
- beforeFull[key] = prevVal;
89
- }
90
- });
91
-
92
- const prevCF = instance.previous?.('customFields');
93
- if (prevCF !== undefined) {
94
- beforeFull.customFields = prevCF;
95
- }
96
-
97
- return beforeFull;
98
- };
99
-
100
81
  const formatAjvErrors = (
101
82
  errors: {
102
83
  instancePath?: string;
@@ -169,10 +150,7 @@ const validateModel = async (
169
150
  {
170
151
  transaction: options.transaction,
171
152
  attributes: CUSTOM_VALIDATOR_ATTRIBUTES_TO_PULL,
172
- ...(modelOptions.include && {
173
- include: modelOptions.include?.(entityId),
174
- }),
175
- raw: true,
153
+ modelOptions,
176
154
  },
177
155
  );
178
156
  if (options.transaction) {
@@ -191,7 +169,11 @@ const validateModel = async (
191
169
  // For updates, get the previous values
192
170
  let originalValues = null;
193
171
  if (!isCreate) {
194
- originalValues = buildBeforeFromInstance(instance);
172
+ // Create originalValues with our helper function
173
+ originalValues = manualObjectCopy(instance.previous());
174
+
175
+ // Add customFields separately
176
+ originalValues.customFields = instance.previous('customFields') || {};
195
177
  }
196
178
 
197
179
  // Get complete custom fields by merging DB values with update values
package/src/index.ts CHANGED
@@ -22,7 +22,7 @@ export * from './utils/helpers';
22
22
  * @see {@link 'custom-fields/config'} for configurations
23
23
  */
24
24
  const useCustomFields = async (
25
- app: Application | null,
25
+ app: Pick<Application, 'use'> | null,
26
26
  getModel: ModelFetcher,
27
27
  options: CustomFieldOptions,
28
28
  ): Promise<Sequelize> => {
@@ -1,6 +1,7 @@
1
- import type { IncludeOptions, Transactionable } from 'sequelize';
1
+ import type { FindOptions, IncludeOptions, Transactionable } from 'sequelize';
2
2
  import logger from '../utils/logger';
3
3
  import { CustomValidator } from '../models';
4
+ import type { ModelOptions } from '../types';
4
5
 
5
6
  export interface FindValidatorOptions extends Transactionable {
6
7
  withDisabled?: boolean;
@@ -33,11 +34,16 @@ export const create = async (
33
34
 
34
35
  export const findAll = async (
35
36
  where = {},
36
- options: FindValidatorOptions = { withDisabled: false },
37
+ options: FindOptions & {
38
+ modelOptions?: ModelOptions,
39
+ withDisabled?: boolean
40
+ } = {},
37
41
  ): Promise<CustomValidator[]> => {
38
42
  logger.debug('custom-validator - find all validators');
39
43
 
40
- const { transaction, withDisabled } = options;
44
+ const {
45
+ transaction, withDisabled, include, attributes, raw,
46
+ } = options;
41
47
 
42
48
  let validators;
43
49
  if (withDisabled) {
@@ -46,6 +52,9 @@ export const findAll = async (
46
52
  validators = await CustomValidator.unscoped().scope('userScope').findAll({
47
53
  where,
48
54
  transaction,
55
+ include,
56
+ attributes,
57
+ raw,
49
58
  });
50
59
  } else {
51
60
  // Use defaultScope and userScope to filter both disabled and by permissions
@@ -53,6 +62,9 @@ export const findAll = async (
53
62
  validators = await CustomValidator.scope(['defaultScope', 'userScope']).findAll({
54
63
  where,
55
64
  transaction,
65
+ include,
66
+ attributes,
67
+ raw,
56
68
  });
57
69
  }
58
70
 
@@ -62,18 +74,21 @@ export const findAll = async (
62
74
  export const findAllByModelType = async (
63
75
  modelType: string,
64
76
  entityId: string,
65
- options: FindValidatorOptions = { withDisabled: false },
77
+ options: FindOptions & {
78
+ modelOptions?: ModelOptions,
79
+ withDisabled?: boolean
80
+ } = {},
66
81
  ): Promise<CustomValidator[]> => {
67
82
  logger.debug('custom-validator - find all validators by model type');
68
-
69
83
  return findAll(
70
84
  {
71
85
  modelType,
72
- ...(!options.include && {
73
- entityId,
74
- }),
86
+ ...(!options?.modelOptions?.useEntityIdFromInclude && { entityId }),
87
+ },
88
+ {
89
+ ...options,
90
+ include: options?.modelOptions?.include?.(entityId),
75
91
  },
76
- options,
77
92
  );
78
93
  };
79
94
 
@@ -17,7 +17,7 @@ export type ModelOptions = {
17
17
  /**
18
18
  * Include options for the model
19
19
  */
20
- include?: (entityIds: string[]) => IncludeOptions[];
20
+ include?: (entityIds: string | string[]) => IncludeOptions[];
21
21
  /**
22
22
  * Custom association for the model
23
23
  * @param model - The model to associate with
package/src/utils/init.ts CHANGED
@@ -5,6 +5,7 @@ import { CUSTOM_FIELDS_SORT_SCOPE } from '@autofleet/common-types/lib/custom-fie
5
5
  import {
6
6
  CustomFieldDefinition,
7
7
  CustomFieldValue,
8
+ CustomValidator,
8
9
  } from '../models';
9
10
  import {
10
11
  beforeFind,
@@ -116,5 +117,6 @@ export const addScopes = (models: Models[], getModel: ModelFetcher, options: Pic
116
117
  export const applyCustomAssociation = (models: Models[]): void => {
117
118
  models.forEach(({ modelOptions }) => {
118
119
  modelOptions?.customAssociation?.(CustomFieldDefinition);
120
+ modelOptions?.customAssociation?.(CustomValidator);
119
121
  });
120
122
  };