@nocobase/database 2.0.0-alpha.2 → 2.0.0-alpha.21

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.
@@ -93,9 +93,6 @@ export declare class Collection<TModelAttributes extends {} = any, TCreationAttr
93
93
  validate(options: {
94
94
  values: Record<string, any> | Record<string, any>[];
95
95
  operation: 'create' | 'update';
96
- context: {
97
- t: Function;
98
- };
99
96
  }): void;
100
97
  isMultiFilterTargetKey(): boolean;
101
98
  tableName(): any;
package/lib/collection.js CHANGED
@@ -58,6 +58,7 @@ var import_model = require("./model");
58
58
  var import_repository = require("./repository");
59
59
  var import_utils = require("./utils");
60
60
  var import_field_validation = require("./utils/field-validation");
61
+ var import_joi = __toESM(require("joi"));
61
62
  function EnsureAtomicity(target, propertyKey, descriptor) {
62
63
  const originalMethod = descriptor.value;
63
64
  descriptor.value = function(...args) {
@@ -161,50 +162,33 @@ const _Collection = class _Collection extends import_events.EventEmitter {
161
162
  }
162
163
  }
163
164
  validate(options) {
164
- const { values: updateValues, context, operation } = options;
165
+ const { values: updateValues, operation } = options;
165
166
  if (!updateValues) {
166
167
  return;
167
168
  }
168
169
  const values = Array.isArray(updateValues) ? updateValues : [updateValues];
169
- const { t } = context || { t: /* @__PURE__ */ __name((key, options2) => key, "t") };
170
- const unwrapTplLabel = /* @__PURE__ */ __name((label) => {
171
- if (typeof label !== "string") return label;
172
- const m = label.match(/^[\s\t]*\{\{\s*t\(\s*(['"])(.*?)\1(?:\s*,[\s\S]*)?\)\s*\}\}[\s\t]*$/);
173
- return m ? m[2] : label;
174
- }, "unwrapTplLabel");
175
170
  const helper = /* @__PURE__ */ __name((field, value) => {
176
- var _a, _b, _c;
171
+ var _a, _b;
177
172
  const val = value[field.name];
178
173
  if (!field.options.validation) {
179
174
  return;
180
175
  }
181
- const fieldLabel = unwrapTplLabel(((_a = field.options.uiSchema) == null ? void 0 : _a.title) || field.name);
182
176
  if (field instanceof import_fields.RelationField) {
183
- if ((_b = field.options) == null ? void 0 : _b.validation.rules) {
184
- const isRequired = (_c = field.options) == null ? void 0 : _c.validation.rules.some((rule) => rule.name === "required");
185
- if (isRequired && !val) {
186
- throw new Error(
187
- t("{{#label}} is required", {
188
- ns: "client",
189
- "#label": `${t("Collection", { ns: "client" })}: ${this.name}, ${t("Field", { ns: "client" })}: ${t(
190
- fieldLabel,
191
- { ns: "client" }
192
- )}`
193
- })
194
- );
177
+ const rules = ((_b = (_a = field.options) == null ? void 0 : _a.validation) == null ? void 0 : _b.rules) || [];
178
+ const required = rules.some((rule) => rule.name === "required");
179
+ if (required) {
180
+ const { error: error2 } = import_joi.default.any().empty(null).required().label(`${this.name}.${field.name}`).validate(val);
181
+ if (error2) {
182
+ throw error2;
195
183
  }
196
184
  }
197
185
  return;
198
186
  }
199
187
  const joiSchema = (0, import_field_validation.buildJoiSchema)(field.options.validation, {
200
- label: `${t("Collection", { ns: "client" })}: ${this.name}, ${t("Field", { ns: "client" })}: ${t(fieldLabel, {
201
- ns: "client"
202
- })}`,
188
+ label: `${this.name}.${field.name}`,
203
189
  value: val
204
190
  });
205
- const { error } = joiSchema.validate(val, {
206
- messages: (0, import_field_validation.getJoiErrorMessage)(t)
207
- });
191
+ const { error } = joiSchema.validate(val);
208
192
  if (error) {
209
193
  throw error;
210
194
  }
package/lib/database.js CHANGED
@@ -287,8 +287,8 @@ const _Database = class _Database extends import_events.EventEmitter {
287
287
  */
288
288
  initListener() {
289
289
  this.on("afterConnect", async (client) => {
290
- if (this.inDialect("postgres")) {
291
- await client.query("SET search_path = public");
290
+ if (this.isPostgresCompatibleDialect()) {
291
+ await client.query("SET search_path TO public");
292
292
  }
293
293
  });
294
294
  this.on("beforeDefine", (model, options) => {
@@ -797,12 +797,12 @@ const _Database = class _Database extends import_events.EventEmitter {
797
797
  if (!finalSQL.replace(/\s+/g, " ").trim()) {
798
798
  throw new Error("SQL cannot be empty");
799
799
  }
800
+ const queryGenerator = this.sequelize.getQueryInterface().queryGenerator;
800
801
  if (filter) {
801
802
  let where = {};
802
803
  const tmpCollection = new import_collection.Collection({ name: "tmp", underscored: false }, { database: this });
803
804
  const r = tmpCollection.repository;
804
805
  where = r.buildQueryOptions({ filter }).where;
805
- const queryGenerator = this.sequelize.getQueryInterface().queryGenerator;
806
806
  const wSQL = queryGenerator.getWhereConditions(where, null, null, { bindParam: true });
807
807
  if (wSQL) {
808
808
  let normalizedSQL = sql.replace(/\s+/g, " ").trim();
@@ -812,6 +812,9 @@ const _Database = class _Database extends import_events.EventEmitter {
812
812
  finalSQL = `SELECT * FROM (${normalizedSQL}) AS tmp WHERE ${wSQL}`;
813
813
  }
814
814
  }
815
+ if (this.options.schema && this.isPostgresCompatibleDialect()) {
816
+ finalSQL = `${queryGenerator.setSearchPath(this.options.schema)} ${finalSQL}`;
817
+ }
815
818
  this.logger.debug("runSQL", { finalSQL });
816
819
  const result = await this.sequelize.query(finalSQL, { bind, transaction });
817
820
  let data = result[0];
@@ -52,9 +52,6 @@ const _PostgresDialect = class _PostgresDialect extends import_base_dialect.Base
52
52
  if (!options.hooks["afterConnect"]) {
53
53
  options.hooks["afterConnect"] = [];
54
54
  }
55
- options.hooks["afterConnect"].push(async (connection) => {
56
- await connection.query("SET search_path TO public;");
57
- });
58
55
  return options;
59
56
  }
60
57
  getVersionGuard() {
package/lib/index.d.ts CHANGED
@@ -7,6 +7,7 @@
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
9
  export { BaseError, BelongsToGetAssociationMixin, DataTypes, fn, HasManyCountAssociationsMixin, HasManyCreateAssociationMixin, HasManyGetAssociationsMixin, literal, ModelStatic, Op, SyncOptions, Transaction, UniqueConstraintError, ValidationError, ValidationErrorItem, where, } from 'sequelize';
10
+ export { ValidationError as JoiValidationError } from 'joi';
10
11
  export * from './belongs-to-array/belongs-to-array-repository';
11
12
  export * from './collection';
12
13
  export * from './collection-group-manager';
package/lib/index.js CHANGED
@@ -44,6 +44,7 @@ __export(src_exports, {
44
44
  HasManyCountAssociationsMixin: () => import_sequelize.HasManyCountAssociationsMixin,
45
45
  HasManyCreateAssociationMixin: () => import_sequelize.HasManyCreateAssociationMixin,
46
46
  HasManyGetAssociationsMixin: () => import_sequelize.HasManyGetAssociationsMixin,
47
+ JoiValidationError: () => import_joi.ValidationError,
47
48
  ModelStatic: () => import_sequelize.ModelStatic,
48
49
  Op: () => import_sequelize.Op,
49
50
  SQLParserTypes: () => import_sql_parser.SQLParserTypes,
@@ -65,6 +66,7 @@ __export(src_exports, {
65
66
  });
66
67
  module.exports = __toCommonJS(src_exports);
67
68
  var import_sequelize = require("sequelize");
69
+ var import_joi = require("joi");
68
70
  __reExport(src_exports, require("./belongs-to-array/belongs-to-array-repository"), module.exports);
69
71
  __reExport(src_exports, require("./collection"), module.exports);
70
72
  __reExport(src_exports, require("./collection-group-manager"), module.exports);
@@ -110,6 +112,7 @@ var import_filter_include = require("./utils/filter-include");
110
112
  HasManyCountAssociationsMixin,
111
113
  HasManyCreateAssociationMixin,
112
114
  HasManyGetAssociationsMixin,
115
+ JoiValidationError,
113
116
  ModelStatic,
114
117
  Op,
115
118
  SQLParserTypes,
@@ -0,0 +1,10 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ declare const _default: Record<string, any>;
10
+ export default _default;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ var __defProp = Object.defineProperty;
11
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
+ var __getOwnPropNames = Object.getOwnPropertyNames;
13
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
14
+ var __export = (target, all) => {
15
+ for (var name in all)
16
+ __defProp(target, name, { get: all[name], enumerable: true });
17
+ };
18
+ var __copyProps = (to, from, except, desc) => {
19
+ if (from && typeof from === "object" || typeof from === "function") {
20
+ for (let key of __getOwnPropNames(from))
21
+ if (!__hasOwnProp.call(to, key) && key !== except)
22
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
23
+ }
24
+ return to;
25
+ };
26
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
27
+ var in_exports = {};
28
+ __export(in_exports, {
29
+ default: () => in_default
30
+ });
31
+ module.exports = __toCommonJS(in_exports);
32
+ var import_lodash = require("lodash");
33
+ var import_sequelize = require("sequelize");
34
+ var in_default = {
35
+ $in(val, ctx) {
36
+ return {
37
+ [import_sequelize.Op.in]: val == null ? [] : (0, import_lodash.castArray)(val)
38
+ };
39
+ }
40
+ };
@@ -46,6 +46,7 @@ var import_empty = __toESM(require("./empty"));
46
46
  var import_string = __toESM(require("./string"));
47
47
  var import_eq = __toESM(require("./eq"));
48
48
  var import_ne = __toESM(require("./ne"));
49
+ var import_in = __toESM(require("./in"));
49
50
  var import_notIn = __toESM(require("./notIn"));
50
51
  var import_boolean = __toESM(require("./boolean"));
51
52
  var import_child_collection = __toESM(require("./child-collection"));
@@ -57,6 +58,7 @@ var operators_default = {
57
58
  ...import_string.default,
58
59
  ...import_eq.default,
59
60
  ...import_ne.default,
61
+ ...import_in.default,
60
62
  ...import_notIn.default,
61
63
  ...import_boolean.default,
62
64
  ...import_child_collection.default
@@ -88,8 +88,7 @@ const _BelongsToManyRepository = class _BelongsToManyRepository extends import_m
88
88
  };
89
89
  this.collection.validate({
90
90
  values,
91
- operation: "create",
92
- context: options.context
91
+ operation: "create"
93
92
  });
94
93
  const instance = await sourceModel[createAccessor](values, createOptions);
95
94
  await (0, import_update_associations.updateAssociations)(instance, values, { ...options, transaction: transaction2 });
@@ -178,7 +178,7 @@ const _RelationRepository = class _RelationRepository {
178
178
  const values = options.values;
179
179
  const transaction2 = await this.getTransaction(options);
180
180
  const sourceModel = await this.getSourceModel(transaction2);
181
- this.collection.validate({ values, context: options.context, operation: "create" });
181
+ this.collection.validate({ values, operation: "create" });
182
182
  const instance = await sourceModel[createAccessor](guard.sanitize(options.values), { ...options, transaction: transaction2 });
183
183
  await (0, import_update_associations.updateAssociations)(instance, values, { ...options, transaction: transaction2 });
184
184
  if (options.hooks !== false) {
package/lib/repository.js CHANGED
@@ -453,7 +453,7 @@ const _Repository = class _Repository {
453
453
  underscored: this.collection.options.underscored
454
454
  });
455
455
  const values = this.model.callSetters(guard.sanitize(options.values || {}), options);
456
- this.validate({ values, context: options.context, operation: "create" });
456
+ this.validate({ values, operation: "create" });
457
457
  const instance = await this.model.create(values, {
458
458
  ...options,
459
459
  transaction: transaction2
@@ -498,7 +498,7 @@ const _Repository = class _Repository {
498
498
  const transaction2 = await this.getTransaction(options);
499
499
  const guard = import_update_guard.UpdateGuard.fromOptions(this.model, { ...options, underscored: this.collection.options.underscored });
500
500
  const values = this.model.callSetters(guard.sanitize(options.values || {}), options);
501
- this.validate({ values, context: options.context, operation: "update" });
501
+ this.validate({ values, operation: "update" });
502
502
  if (options.individualHooks === false) {
503
503
  const { model: Model2 } = this.collection;
504
504
  const primaryKeyField = Model2.primaryKeyField || Model2.primaryKeyAttribute;
@@ -81,8 +81,7 @@ async function updateModelByValues(instance, values, options) {
81
81
  }
82
82
  instance.constructor.collection.validate({
83
83
  values,
84
- operation: "update",
85
- context: options == null ? void 0 : options.context
84
+ operation: "update"
86
85
  });
87
86
  await instance.update(values, options);
88
87
  await updateAssociations(instance, values, options);
@@ -273,7 +272,6 @@ async function updateSingleAssociation(model, key, value, options = {}) {
273
272
  }
274
273
  association.target.collection.validate({
275
274
  values: value,
276
- context: options.context,
277
275
  operation: "create"
278
276
  });
279
277
  const instance = await model[createAccessor](value, { context, transaction });
@@ -368,7 +366,6 @@ async function updateMultipleAssociation(model, key, value, options = {}) {
368
366
  if ((0, import_utils.isUndefinedOrNull)(item[targetKey])) {
369
367
  association.target.collection.validate({
370
368
  values: item,
371
- context: options.context,
372
369
  operation: "create"
373
370
  });
374
371
  const instance = await model[createAccessor](item, accessorOptions);
@@ -390,7 +387,6 @@ async function updateMultipleAssociation(model, key, value, options = {}) {
390
387
  if (!instance) {
391
388
  association.target.collection.validate({
392
389
  values: item,
393
- context: options.context,
394
390
  operation: "create"
395
391
  });
396
392
  instance = await model[createAccessor](item, accessorOptions);
@@ -414,7 +410,6 @@ async function updateMultipleAssociation(model, key, value, options = {}) {
414
410
  }
415
411
  association.target.collection.validate({
416
412
  values: item,
417
- context: options.context,
418
413
  operation: "update"
419
414
  });
420
415
  await instance.update(item, { ...options, transaction });
@@ -12,48 +12,3 @@ export declare function buildJoiSchema(validation: ValidationOptions, options: {
12
12
  label?: string;
13
13
  value: string;
14
14
  }): AnySchema;
15
- export declare function getJoiErrorMessage(t: Function): {
16
- 'string.base': any;
17
- 'string.empty': any;
18
- 'string.min': any;
19
- 'string.max': any;
20
- 'string.length': any;
21
- 'string.alphanum': any;
22
- 'string.token': any;
23
- 'string.regex': any;
24
- 'string.email': any;
25
- 'string.uri': any;
26
- 'string.uriCustomScheme': any;
27
- 'string.isoDate': any;
28
- 'string.guid': any;
29
- 'string.hex': any;
30
- 'string.hostname': any;
31
- 'string.lowercase': any;
32
- 'string.uppercase': any;
33
- 'string.trim': any;
34
- 'string.creditCard': any;
35
- 'string.pattern.base': any;
36
- 'string.pattern.name': any;
37
- 'string.pattern.invert.base': any;
38
- 'string.pattern.invert.name': any;
39
- 'any.required': any;
40
- 'number.base': any;
41
- 'number.min': any;
42
- 'number.max': any;
43
- 'number.less': any;
44
- 'number.greater': any;
45
- 'number.float': any;
46
- 'number.integer': any;
47
- 'number.negative': any;
48
- 'number.positive': any;
49
- 'number.precision': any;
50
- 'number.multiple': any;
51
- 'number.port': any;
52
- 'number.unsafe': any;
53
- 'date.base': any;
54
- 'date.format': any;
55
- 'date.greater': any;
56
- 'date.less': any;
57
- 'date.max': any;
58
- 'date.min': any;
59
- };
@@ -37,8 +37,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
37
37
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
38
38
  var field_validation_exports = {};
39
39
  __export(field_validation_exports, {
40
- buildJoiSchema: () => buildJoiSchema,
41
- getJoiErrorMessage: () => getJoiErrorMessage
40
+ buildJoiSchema: () => buildJoiSchema
42
41
  });
43
42
  module.exports = __toCommonJS(field_validation_exports);
44
43
  var import_joi = __toESM(require("joi"));
@@ -80,64 +79,7 @@ function buildJoiSchema(validation, options) {
80
79
  return schema;
81
80
  }
82
81
  __name(buildJoiSchema, "buildJoiSchema");
83
- function getJoiErrorMessage(t) {
84
- const tOptions = { ns: "client" };
85
- const JoiErrorMessages = {
86
- "string.base": t("{{#label}} must be a string", tOptions),
87
- "string.empty": t("{{#label}} is not allowed to be empty", tOptions),
88
- "string.min": t("{{#label}} length must be at least {{#limit}} characters long", tOptions),
89
- "string.max": t("{{#label}} length must be less than or equal to {{#limit}} characters long", tOptions),
90
- "string.length": t("{{#label}} length must be {{#limit}} characters long", tOptions),
91
- "string.alphanum": t("{{#label}} must only contain alpha-numeric characters", tOptions),
92
- "string.token": t("{{#label}} must only contain alpha-numeric and underscore characters", tOptions),
93
- "string.regex": t("{{#label}} with value {{#value}} fails to match the required pattern", tOptions),
94
- "string.email": t("{{#label}} email address doesn\u2019t meet the required format", tOptions),
95
- "string.uri": t("{{#label}} must be a valid uri", tOptions),
96
- "string.uriCustomScheme": t(
97
- "{{#label}} must be a valid uri with a scheme matching the {{#scheme}} pattern",
98
- tOptions
99
- ),
100
- "string.isoDate": t("{{#label}} must be a valid ISO 8601 date", tOptions),
101
- "string.guid": t("{{#label}} must be a valid UUID", tOptions),
102
- "string.hex": t("{{#label}} must only contain hexadecimal characters", tOptions),
103
- "string.hostname": t("{{#label}} must be a valid hostname", tOptions),
104
- "string.lowercase": t("{{#label}} must only contain lowercase characters", tOptions),
105
- "string.uppercase": t("{{#label}} must only contain uppercase characters", tOptions),
106
- "string.trim": t("{{#label}} must not have leading or trailing whitespace", tOptions),
107
- "string.creditCard": t("{{#label}} must be a credit card", tOptions),
108
- "string.pattern.base": t('{{#label}} with value "{{#value}}" fails to match the required pattern', tOptions),
109
- "string.pattern.name": t('{{#label}} with value "{{#value}}" fails to match the {{#name}} pattern', tOptions),
110
- "string.pattern.invert.base": t('{{#label}} with value "{{#value}}" matches the inverted pattern', tOptions),
111
- "string.pattern.invert.name": t(
112
- '{{#label}} with value "{{#value}}" matches the inverted {{#name}} pattern',
113
- tOptions
114
- ),
115
- "any.required": t("{{#label}} is required", tOptions),
116
- "number.base": t("{{#label}} must be a number", tOptions),
117
- "number.min": t("{{#label}} must be greater than or equal to {{#limit}}", tOptions),
118
- "number.max": t("{{#label}} must be less than or equal to {{#limit}}", tOptions),
119
- "number.less": t("{{#label}} must be less than {{#limit}}", tOptions),
120
- "number.greater": t("{{#label}} must be greater than {{#limit}}", tOptions),
121
- "number.float": t("{{#label}} must be a float or double", tOptions),
122
- "number.integer": t("{{#label}} must be an integer", tOptions),
123
- "number.negative": t("{{#label}} must be a negative number", tOptions),
124
- "number.positive": t("{{#label}} must be a positive number", tOptions),
125
- "number.precision": t("{{#label}} must not have more than {{#limit}} decimal places", tOptions),
126
- "number.multiple": t("{{#label}} must be a multiple of {{#multiple}}", tOptions),
127
- "number.port": t("{{#label}} must be a valid port", tOptions),
128
- "number.unsafe": t("{{#label}} must be a safe number", tOptions),
129
- "date.base": t("{{#label}} must be a valid date", tOptions),
130
- "date.format": t("{{#label}} must be in {{#format}} format", tOptions),
131
- "date.greater": t("{{#label}} must be greater than {{#limit}}", tOptions),
132
- "date.less": t("{{#label}} must be less than {{#limit}}", tOptions),
133
- "date.max": t("{{#label}} must be less than or equal to {{#limit}}", tOptions),
134
- "date.min": t("{{#label}} must be greater than or equal to {{#limit}}", tOptions)
135
- };
136
- return JoiErrorMessages;
137
- }
138
- __name(getJoiErrorMessage, "getJoiErrorMessage");
139
82
  // Annotate the CommonJS export names for ESM import in node:
140
83
  0 && (module.exports = {
141
- buildJoiSchema,
142
- getJoiErrorMessage
84
+ buildJoiSchema
143
85
  });
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@nocobase/database",
3
- "version": "2.0.0-alpha.2",
3
+ "version": "2.0.0-alpha.21",
4
4
  "description": "",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./lib/index.d.ts",
7
7
  "license": "AGPL-3.0",
8
8
  "dependencies": {
9
- "@nocobase/logger": "2.0.0-alpha.2",
10
- "@nocobase/utils": "2.0.0-alpha.2",
9
+ "@nocobase/logger": "2.0.0-alpha.21",
10
+ "@nocobase/utils": "2.0.0-alpha.21",
11
11
  "async-mutex": "^0.3.2",
12
12
  "chalk": "^4.1.1",
13
13
  "cron-parser": "4.4.0",
@@ -39,5 +39,5 @@
39
39
  "url": "git+https://github.com/nocobase/nocobase.git",
40
40
  "directory": "packages/database"
41
41
  },
42
- "gitHead": "1322f486b248bef53ed8c8f42f0a39dfd02125fd"
42
+ "gitHead": "0398c85e979d09e834952e71c5c1a1ccf1a3a8e1"
43
43
  }