@e22m4u/js-repository 0.0.31

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 (183) hide show
  1. package/.c8rc +9 -0
  2. package/.commitlintrc +5 -0
  3. package/.editorconfig +13 -0
  4. package/.eslintignore +1 -0
  5. package/.eslintrc.cjs +27 -0
  6. package/.husky/commit-msg +4 -0
  7. package/.husky/pre-commit +9 -0
  8. package/.mocharc.cjs +7 -0
  9. package/.prettierrc +7 -0
  10. package/LICENSE +21 -0
  11. package/README.md +523 -0
  12. package/mocha.setup.js +10 -0
  13. package/package.json +57 -0
  14. package/src/adapter/adapter-loader.d.ts +16 -0
  15. package/src/adapter/adapter-loader.js +63 -0
  16. package/src/adapter/adapter-loader.spec.js +31 -0
  17. package/src/adapter/adapter-registry.d.ts +14 -0
  18. package/src/adapter/adapter-registry.js +36 -0
  19. package/src/adapter/adapter-registry.spec.js +36 -0
  20. package/src/adapter/adapter.d.ts +118 -0
  21. package/src/adapter/adapter.js +181 -0
  22. package/src/adapter/adapter.spec.js +144 -0
  23. package/src/adapter/builtin/memory-adapter.d.ts +118 -0
  24. package/src/adapter/builtin/memory-adapter.js +342 -0
  25. package/src/adapter/builtin/memory-adapter.spec.js +2925 -0
  26. package/src/adapter/decorator/data-sanitizing-decorator.d.ts +13 -0
  27. package/src/adapter/decorator/data-sanitizing-decorator.js +44 -0
  28. package/src/adapter/decorator/data-sanitizing-decorator.spec.js +59 -0
  29. package/src/adapter/decorator/data-validation-decorator.d.ts +13 -0
  30. package/src/adapter/decorator/data-validation-decorator.js +41 -0
  31. package/src/adapter/decorator/data-validation-decorator.spec.js +59 -0
  32. package/src/adapter/decorator/default-values-decorator.d.ts +13 -0
  33. package/src/adapter/decorator/default-values-decorator.js +57 -0
  34. package/src/adapter/decorator/default-values-decorator.spec.js +141 -0
  35. package/src/adapter/decorator/fields-filtering-decorator.d.ts +13 -0
  36. package/src/adapter/decorator/fields-filtering-decorator.js +72 -0
  37. package/src/adapter/decorator/fields-filtering-decorator.spec.js +119 -0
  38. package/src/adapter/decorator/inclusion-decorator.d.ts +13 -0
  39. package/src/adapter/decorator/inclusion-decorator.js +78 -0
  40. package/src/adapter/decorator/inclusion-decorator.spec.js +117 -0
  41. package/src/adapter/decorator/index.d.ts +5 -0
  42. package/src/adapter/decorator/index.js +5 -0
  43. package/src/adapter/index.d.ts +3 -0
  44. package/src/adapter/index.js +3 -0
  45. package/src/definition/datasource/datasource-definition-validator.d.ts +14 -0
  46. package/src/definition/datasource/datasource-definition-validator.js +33 -0
  47. package/src/definition/datasource/datasource-definition-validator.spec.js +63 -0
  48. package/src/definition/datasource/datasource-definition.d.ts +7 -0
  49. package/src/definition/datasource/index.d.ts +2 -0
  50. package/src/definition/datasource/index.js +1 -0
  51. package/src/definition/definition-registry.d.ts +50 -0
  52. package/src/definition/definition-registry.js +98 -0
  53. package/src/definition/definition-registry.spec.js +78 -0
  54. package/src/definition/index.d.ts +3 -0
  55. package/src/definition/index.js +3 -0
  56. package/src/definition/model/index.d.ts +7 -0
  57. package/src/definition/model/index.js +6 -0
  58. package/src/definition/model/model-data-sanitizer.d.ts +15 -0
  59. package/src/definition/model/model-data-sanitizer.js +33 -0
  60. package/src/definition/model/model-data-validator.d.ts +32 -0
  61. package/src/definition/model/model-data-validator.js +144 -0
  62. package/src/definition/model/model-data-validator.spec.js +1889 -0
  63. package/src/definition/model/model-definition-utils.d.ts +161 -0
  64. package/src/definition/model/model-definition-utils.js +371 -0
  65. package/src/definition/model/model-definition-utils.spec.js +1474 -0
  66. package/src/definition/model/model-definition-validator.d.ts +14 -0
  67. package/src/definition/model/model-definition-validator.js +83 -0
  68. package/src/definition/model/model-definition-validator.spec.js +143 -0
  69. package/src/definition/model/model-definition.d.ts +28 -0
  70. package/src/definition/model/properties/data-type.d.ts +11 -0
  71. package/src/definition/model/properties/data-type.js +11 -0
  72. package/src/definition/model/properties/default-values-definition-validator.d.ts +15 -0
  73. package/src/definition/model/properties/default-values-definition-validator.js +53 -0
  74. package/src/definition/model/properties/default-values-definition-validator.spec.js +136 -0
  75. package/src/definition/model/properties/index.d.ts +5 -0
  76. package/src/definition/model/properties/index.js +4 -0
  77. package/src/definition/model/properties/primary-keys-definition-validator.d.ts +15 -0
  78. package/src/definition/model/properties/primary-keys-definition-validator.js +55 -0
  79. package/src/definition/model/properties/primary-keys-definition-validator.spec.js +145 -0
  80. package/src/definition/model/properties/properties-definition-validator.d.ts +15 -0
  81. package/src/definition/model/properties/properties-definition-validator.js +194 -0
  82. package/src/definition/model/properties/properties-definition-validator.spec.js +373 -0
  83. package/src/definition/model/properties/property-definition.d.ts +20 -0
  84. package/src/definition/model/relations/index.d.ts +3 -0
  85. package/src/definition/model/relations/index.js +2 -0
  86. package/src/definition/model/relations/relation-definition.d.ts +254 -0
  87. package/src/definition/model/relations/relation-type.d.ts +9 -0
  88. package/src/definition/model/relations/relation-type.js +9 -0
  89. package/src/definition/model/relations/relations-definition-validator.d.ts +15 -0
  90. package/src/definition/model/relations/relations-definition-validator.js +449 -0
  91. package/src/definition/model/relations/relations-definition-validator.spec.js +772 -0
  92. package/src/errors/index.d.ts +3 -0
  93. package/src/errors/index.js +3 -0
  94. package/src/errors/invalid-argument-error.d.ts +6 -0
  95. package/src/errors/invalid-argument-error.js +6 -0
  96. package/src/errors/invalid-argument-error.spec.js +33 -0
  97. package/src/errors/invalid-operator-value-error.d.ts +13 -0
  98. package/src/errors/invalid-operator-value-error.js +24 -0
  99. package/src/errors/invalid-operator-value-error.spec.js +11 -0
  100. package/src/errors/not-implemented-error.d.ts +6 -0
  101. package/src/errors/not-implemented-error.js +6 -0
  102. package/src/errors/not-implemented-error.spec.js +33 -0
  103. package/src/filter/fields-clause-tool.d.ts +38 -0
  104. package/src/filter/fields-clause-tool.js +88 -0
  105. package/src/filter/fields-clause-tool.spec.js +133 -0
  106. package/src/filter/filter.d.ts +335 -0
  107. package/src/filter/include-clause-tool.d.ts +53 -0
  108. package/src/filter/include-clause-tool.js +364 -0
  109. package/src/filter/include-clause-tool.spec.js +653 -0
  110. package/src/filter/index.d.ts +7 -0
  111. package/src/filter/index.js +6 -0
  112. package/src/filter/operator-clause-tool.d.ts +223 -0
  113. package/src/filter/operator-clause-tool.js +515 -0
  114. package/src/filter/operator-clause-tool.spec.js +1064 -0
  115. package/src/filter/order-clause-tool.d.ts +32 -0
  116. package/src/filter/order-clause-tool.js +97 -0
  117. package/src/filter/order-clause-tool.spec.js +438 -0
  118. package/src/filter/slice-clause-tool.d.ts +30 -0
  119. package/src/filter/slice-clause-tool.js +65 -0
  120. package/src/filter/slice-clause-tool.spec.js +117 -0
  121. package/src/filter/where-clause-tool.d.ts +23 -0
  122. package/src/filter/where-clause-tool.js +165 -0
  123. package/src/filter/where-clause-tool.spec.js +280 -0
  124. package/src/index.d.ts +9 -0
  125. package/src/index.js +8 -0
  126. package/src/relations/belongs-to-resolver.d.ts +46 -0
  127. package/src/relations/belongs-to-resolver.js +242 -0
  128. package/src/relations/belongs-to-resolver.spec.js +1047 -0
  129. package/src/relations/has-many-resolver.d.ts +67 -0
  130. package/src/relations/has-many-resolver.js +317 -0
  131. package/src/relations/has-many-resolver.spec.js +2911 -0
  132. package/src/relations/has-one-resolver.d.ts +67 -0
  133. package/src/relations/has-one-resolver.js +311 -0
  134. package/src/relations/has-one-resolver.spec.js +2274 -0
  135. package/src/relations/index.d.ts +4 -0
  136. package/src/relations/index.js +4 -0
  137. package/src/relations/references-many-resolver.d.ts +27 -0
  138. package/src/relations/references-many-resolver.js +113 -0
  139. package/src/relations/references-many-resolver.spec.js +631 -0
  140. package/src/repository/index.d.ts +2 -0
  141. package/src/repository/index.js +2 -0
  142. package/src/repository/repository-registry.d.ts +29 -0
  143. package/src/repository/repository-registry.js +57 -0
  144. package/src/repository/repository-registry.spec.js +38 -0
  145. package/src/repository/repository.d.ts +164 -0
  146. package/src/repository/repository.js +207 -0
  147. package/src/repository/repository.spec.js +202 -0
  148. package/src/schema.d.ts +37 -0
  149. package/src/schema.js +41 -0
  150. package/src/types.d.ts +30 -0
  151. package/src/utils/capitalize.d.ts +6 -0
  152. package/src/utils/capitalize.js +10 -0
  153. package/src/utils/capitalize.spec.js +14 -0
  154. package/src/utils/clone-deep.d.ts +6 -0
  155. package/src/utils/clone-deep.js +61 -0
  156. package/src/utils/clone-deep.spec.js +28 -0
  157. package/src/utils/exclude-object-keys.d.ts +10 -0
  158. package/src/utils/exclude-object-keys.js +20 -0
  159. package/src/utils/exclude-object-keys.spec.js +49 -0
  160. package/src/utils/get-ctor-name.d.ts +6 -0
  161. package/src/utils/get-ctor-name.js +11 -0
  162. package/src/utils/get-ctor-name.spec.js +17 -0
  163. package/src/utils/get-value-by-path.d.ts +12 -0
  164. package/src/utils/get-value-by-path.js +23 -0
  165. package/src/utils/get-value-by-path.spec.js +36 -0
  166. package/src/utils/index.d.ts +10 -0
  167. package/src/utils/index.js +10 -0
  168. package/src/utils/is-ctor.d.ts +7 -0
  169. package/src/utils/is-ctor.js +10 -0
  170. package/src/utils/is-ctor.spec.js +26 -0
  171. package/src/utils/is-pure-object.d.ts +6 -0
  172. package/src/utils/is-pure-object.js +15 -0
  173. package/src/utils/is-pure-object.spec.js +25 -0
  174. package/src/utils/select-object-keys.d.ts +10 -0
  175. package/src/utils/select-object-keys.js +37 -0
  176. package/src/utils/select-object-keys.spec.js +40 -0
  177. package/src/utils/singularize.d.ts +6 -0
  178. package/src/utils/singularize.js +22 -0
  179. package/src/utils/singularize.spec.js +23 -0
  180. package/src/utils/string-to-regexp.d.ts +10 -0
  181. package/src/utils/string-to-regexp.js +22 -0
  182. package/src/utils/string-to-regexp.spec.js +35 -0
  183. package/tsconfig.json +9 -0
@@ -0,0 +1,3 @@
1
+ export * from './not-implemented-error.js';
2
+ export * from './invalid-argument-error.js';
3
+ export * from './invalid-operator-value-error.js';
@@ -0,0 +1,3 @@
1
+ export * from './not-implemented-error.js';
2
+ export * from './invalid-argument-error.js';
3
+ export * from './invalid-operator-value-error.js';
@@ -0,0 +1,6 @@
1
+ import {Errorf} from '@e22m4u/js-format';
2
+
3
+ /**
4
+ * Invalid argument error.
5
+ */
6
+ export declare class InvalidArgumentError extends Errorf {}
@@ -0,0 +1,6 @@
1
+ import {Errorf} from '@e22m4u/js-format';
2
+
3
+ /**
4
+ * Invalid argument error.
5
+ */
6
+ export class InvalidArgumentError extends Errorf {}
@@ -0,0 +1,33 @@
1
+ import {expect} from 'chai';
2
+ import {format} from '@e22m4u/js-format';
3
+ import {InvalidArgumentError} from './invalid-argument-error.js';
4
+
5
+ describe('InvalidArgumentError', function () {
6
+ it('inherits from Error class', function () {
7
+ const error = new InvalidArgumentError();
8
+ expect(error).to.be.instanceof(Error);
9
+ });
10
+
11
+ it('sets a given message', function () {
12
+ const error = new InvalidArgumentError('This is the Error');
13
+ expect(error.message).to.be.eq('This is the Error');
14
+ });
15
+
16
+ it('interpolates a given pattern with variables', function () {
17
+ const throwable = v => () => {
18
+ throw new InvalidArgumentError('%v', v);
19
+ };
20
+ const error = v => format('%s', v);
21
+ expect(throwable('str')).to.throw(error('"str"'));
22
+ expect(throwable('')).to.throw(error('""'));
23
+ expect(throwable(10)).to.throw(error('10'));
24
+ expect(throwable(0)).to.throw(error(0));
25
+ expect(throwable(true)).to.throw(error('true'));
26
+ expect(throwable(false)).to.throw(error('false'));
27
+ expect(throwable({})).to.throw(error('Object'));
28
+ expect(throwable([])).to.throw(error('Array'));
29
+ expect(throwable(undefined)).to.throw(error('undefined'));
30
+ expect(throwable(null)).to.throw(error('null'));
31
+ expect(throwable(() => undefined)).to.throw(error('Function'));
32
+ });
33
+ });
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Invalid operator value error.
3
+ */
4
+ export declare class InvalidOperatorValueError extends Error {
5
+ /**
6
+ * Constructor.
7
+ *
8
+ * @param operator
9
+ * @param expects
10
+ * @param value
11
+ */
12
+ constructor(operator: string, expects: string, value: unknown);
13
+ }
@@ -0,0 +1,24 @@
1
+ import {format} from '@e22m4u/js-format';
2
+
3
+ /**
4
+ * Invalid operator value error.
5
+ */
6
+ export class InvalidOperatorValueError extends Error {
7
+ /**
8
+ * Constructor.
9
+ *
10
+ * @param {string} operator
11
+ * @param {string} expected
12
+ * @param {*} value
13
+ */
14
+ constructor(operator, expected, value) {
15
+ super(
16
+ format(
17
+ 'Condition of {%s: ...} should have %s, %v given.',
18
+ operator,
19
+ expected,
20
+ value,
21
+ ),
22
+ );
23
+ }
24
+ }
@@ -0,0 +1,11 @@
1
+ import {expect} from 'chai';
2
+ import {InvalidOperatorValueError} from './invalid-operator-value-error.js';
3
+
4
+ describe('InvalidOperatorValueError', function () {
5
+ it('sets specific message', function () {
6
+ const error = new InvalidOperatorValueError('exists', 'a boolean', '');
7
+ const message =
8
+ 'Condition of {exists: ...} should have a boolean, "" given.';
9
+ expect(error.message).to.be.eq(message);
10
+ });
11
+ });
@@ -0,0 +1,6 @@
1
+ import {Errorf} from '@e22m4u/js-format';
2
+
3
+ /**
4
+ * Not implemented error.
5
+ */
6
+ export declare class NotImplementedError extends Errorf {}
@@ -0,0 +1,6 @@
1
+ import {Errorf} from '@e22m4u/js-format';
2
+
3
+ /**
4
+ * Not implemented error.
5
+ */
6
+ export class NotImplementedError extends Errorf {}
@@ -0,0 +1,33 @@
1
+ import {expect} from 'chai';
2
+ import {format} from '@e22m4u/js-format';
3
+ import {NotImplementedError} from './not-implemented-error.js';
4
+
5
+ describe('NotImplementedError', function () {
6
+ it('inherits from Error class', function () {
7
+ const error = new NotImplementedError();
8
+ expect(error).to.be.instanceof(Error);
9
+ });
10
+
11
+ it('sets a given message', function () {
12
+ const error = new NotImplementedError('This is the Error');
13
+ expect(error.message).to.be.eq('This is the Error');
14
+ });
15
+
16
+ it('interpolates a given pattern with variables', function () {
17
+ const throwable = v => () => {
18
+ throw new NotImplementedError('%v', v);
19
+ };
20
+ const error = v => format('%s', v);
21
+ expect(throwable('str')).to.throw(error('"str"'));
22
+ expect(throwable('')).to.throw(error('""'));
23
+ expect(throwable(10)).to.throw(error('10'));
24
+ expect(throwable(0)).to.throw(error(0));
25
+ expect(throwable(true)).to.throw(error('true'));
26
+ expect(throwable(false)).to.throw(error('false'));
27
+ expect(throwable({})).to.throw(error('Object'));
28
+ expect(throwable([])).to.throw(error('Array'));
29
+ expect(throwable(undefined)).to.throw(error('undefined'));
30
+ expect(throwable(null)).to.throw(error('null'));
31
+ expect(throwable(() => undefined)).to.throw(error('Function'));
32
+ });
33
+ });
@@ -0,0 +1,38 @@
1
+ import {ModelData} from '../types.js';
2
+ import {FieldsClause} from './filter.js';
3
+ import {Service} from '@e22m4u/js-service';
4
+ import {NormalizedFieldsClause} from './filter.js';
5
+
6
+ /**
7
+ * Field clause tool.
8
+ */
9
+ export declare class FieldsClauseTool extends Service {
10
+ /**
11
+ * Filter.
12
+ *
13
+ * @param entities
14
+ * @param modelName
15
+ * @param clause
16
+ */
17
+ filter<T extends ModelData | ModelData[]>(
18
+ entities: T,
19
+ modelName: string,
20
+ clause: FieldsClause | undefined,
21
+ ): T;
22
+
23
+ /**
24
+ * Validate fields clause.
25
+ *
26
+ * @param clause
27
+ */
28
+ static validateFieldsClause(clause: FieldsClause | undefined): void;
29
+
30
+ /**
31
+ * Normalize fields clause.
32
+ *
33
+ * @param clause
34
+ */
35
+ static normalizeFieldsClause(
36
+ clause: FieldsClause | undefined,
37
+ ): NormalizedFieldsClause | undefined;
38
+ }
@@ -0,0 +1,88 @@
1
+ import {Service} from '@e22m4u/js-service';
2
+ import {selectObjectKeys} from '../utils/index.js';
3
+ import {InvalidArgumentError} from '../errors/index.js';
4
+ import {ModelDefinitionUtils} from '../definition/index.js';
5
+
6
+ /**
7
+ * Field clause tool.
8
+ */
9
+ export class FieldsClauseTool extends Service {
10
+ /**
11
+ * Filter.
12
+ *
13
+ * @param {object|object[]} entities
14
+ * @param {string} modelName
15
+ * @param {string|string[]|undefined} clause
16
+ * @returns {object|object[]}
17
+ */
18
+ filter(entities, modelName, clause) {
19
+ const isArray = Array.isArray(entities);
20
+ entities = isArray ? entities : [entities];
21
+ entities.forEach(entity => {
22
+ if (!entity || typeof entity !== 'object' || Array.isArray(entity))
23
+ throw new InvalidArgumentError(
24
+ 'A first argument of FieldClauseTool.filter should be an Object or ' +
25
+ 'an Array of Object, but %v given.',
26
+ entity,
27
+ );
28
+ });
29
+
30
+ if (!clause) return entities;
31
+ const fields = Array.isArray(clause) ? clause.slice() : [clause];
32
+ fields.forEach(field => {
33
+ if (!field || typeof field !== 'string')
34
+ throw new InvalidArgumentError(
35
+ 'The provided option "fields" should be a String ' +
36
+ 'or an Array of String, but %v given.',
37
+ field,
38
+ );
39
+ });
40
+
41
+ const pkPropName =
42
+ this.getService(ModelDefinitionUtils).getPrimaryKeyAsPropertyName(
43
+ modelName,
44
+ );
45
+ if (fields.indexOf(pkPropName) === -1) fields.push(pkPropName);
46
+
47
+ entities = entities.map(entity => selectObjectKeys(entity, fields));
48
+ return isArray ? entities : entities[0];
49
+ }
50
+
51
+ /**
52
+ * Validate fields clause.
53
+ *
54
+ * @param {string|string[]|undefined} clause
55
+ */
56
+ static validateFieldsClause(clause) {
57
+ if (!clause) return;
58
+ const tempClause = Array.isArray(clause) ? clause : [clause];
59
+ tempClause.forEach(key => {
60
+ if (!key || typeof key !== 'string')
61
+ throw new InvalidArgumentError(
62
+ 'The provided option "fields" should be a non-empty String ' +
63
+ 'or an Array of String, but %v given.',
64
+ key,
65
+ );
66
+ });
67
+ }
68
+
69
+ /**
70
+ * Normalize fields clause.
71
+ *
72
+ * @param {string|string[]|undefined} clause
73
+ * @returns {string[]|undefined}
74
+ */
75
+ static normalizeFieldsClause(clause) {
76
+ if (!clause) return;
77
+ clause = Array.isArray(clause) ? clause : [clause];
78
+ clause.forEach(key => {
79
+ if (!key || typeof key !== 'string')
80
+ throw new InvalidArgumentError(
81
+ 'The provided option "fields" should be a non-empty String ' +
82
+ 'or an Array of String, but %v given.',
83
+ key,
84
+ );
85
+ });
86
+ return clause;
87
+ }
88
+ }
@@ -0,0 +1,133 @@
1
+ import {expect} from 'chai';
2
+ import {Schema} from '../schema.js';
3
+ import {format} from '@e22m4u/js-format';
4
+ import {FieldsClauseTool} from './fields-clause-tool.js';
5
+ import {DEFAULT_PRIMARY_KEY_PROPERTY_NAME as DEF_PK} from '../definition/index.js';
6
+
7
+ const S = new Schema();
8
+ const MODEL_NAME = 'model';
9
+ S.defineModel({name: MODEL_NAME});
10
+ const T = S.getService(FieldsClauseTool);
11
+
12
+ describe('FieldsClauseTool', function () {
13
+ describe('filter', function () {
14
+ it('returns an object with selected fields', function () {
15
+ const value = {foo: 'fooVal', bar: 'barVal', baz: 'bazVal'};
16
+ const fields = ['bar', 'baz'];
17
+ const result = T.filter(value, MODEL_NAME, fields);
18
+ expect(result).to.be.eql({bar: 'barVal', baz: 'bazVal'});
19
+ });
20
+
21
+ it('returns an array with selected fields', function () {
22
+ const value = [
23
+ {foo: 'fooVal', bar: 'barVal', baz: 'bazVal'},
24
+ {foo: 'fooVal', bar: 'barVal', baz: 'bazVal'},
25
+ {foo: 'fooVal', bar: 'barVal', baz: 'bazVal'},
26
+ ];
27
+ const fields = ['bar', 'baz'];
28
+ const result = T.filter(value, MODEL_NAME, fields);
29
+ expect(result[0]).to.be.eql({bar: 'barVal', baz: 'bazVal'});
30
+ expect(result[1]).to.be.eql({bar: 'barVal', baz: 'bazVal'});
31
+ expect(result[2]).to.be.eql({bar: 'barVal', baz: 'bazVal'});
32
+ });
33
+
34
+ it('includes a primary key', function () {
35
+ const value = {[DEF_PK]: 10, foo: 'fooVal', bar: 'barVal', baz: 'bazVal'};
36
+ const fields = ['bar', 'baz'];
37
+ const result = T.filter(value, MODEL_NAME, fields);
38
+ expect(result).to.be.eql({[DEF_PK]: 10, bar: 'barVal', baz: 'bazVal'});
39
+ });
40
+
41
+ it('throws an error if a first argument is not an object', function () {
42
+ const throwable = () => T.filter(10, MODEL_NAME, ['bar']);
43
+ expect(throwable).to.throw(
44
+ 'A first argument of FieldClauseTool.filter should be an Object or ' +
45
+ 'an Array of Object, but 10 given.',
46
+ );
47
+ });
48
+
49
+ it('throws an error if elements of a first argument is not an object', function () {
50
+ const throwable = () => T.filter([10], MODEL_NAME, ['bar']);
51
+ expect(throwable).to.throw(
52
+ 'A first argument of FieldClauseTool.filter should be an Object or ' +
53
+ 'an Array of Object, but 10 given.',
54
+ );
55
+ });
56
+
57
+ it('throws an error if a second argument is not a string', function () {
58
+ const throwable = () => T.filter({}, MODEL_NAME, 10);
59
+ expect(throwable).to.throw(
60
+ 'The provided option "fields" should be a String ' +
61
+ 'or an Array of String, but 10 given.',
62
+ );
63
+ });
64
+
65
+ it('throws an error if elements of a second argument is not a string', function () {
66
+ const throwable = () => T.filter({}, MODEL_NAME, [10]);
67
+ expect(throwable).to.throw(
68
+ 'The provided option "fields" should be a String ' +
69
+ 'or an Array of String, but 10 given.',
70
+ );
71
+ });
72
+ });
73
+
74
+ describe('validateFieldsClause', function () {
75
+ it('requires a non-empty string or an array of non-empty strings', function () {
76
+ const validate = v => () => FieldsClauseTool.validateFieldsClause(v);
77
+ const error = v =>
78
+ format(
79
+ 'The provided option "fields" should be a non-empty String ' +
80
+ 'or an Array of String, but %s given.',
81
+ v,
82
+ );
83
+ expect(validate(10)).to.throw(error('10'));
84
+ expect(validate(true)).to.throw(error('true'));
85
+ expect(validate({})).to.throw(error('Object'));
86
+ expect(validate([''])).to.throw(error('""'));
87
+ expect(validate([10])).to.throw(error('10'));
88
+ expect(validate([true])).to.throw(error('true'));
89
+ expect(validate([false])).to.throw(error('false'));
90
+ expect(validate([undefined])).to.throw(error('undefined'));
91
+ expect(validate([null])).to.throw(error('null'));
92
+ validate('')();
93
+ validate(false)();
94
+ validate(undefined)();
95
+ validate(null)();
96
+ validate('foo')();
97
+ validate(['foo'])();
98
+ });
99
+ });
100
+
101
+ describe('normalizeFieldsClause', function () {
102
+ it('returns an array of strings', function () {
103
+ const fn = FieldsClauseTool.normalizeFieldsClause;
104
+ expect(fn('foo')).to.be.eql(['foo']);
105
+ expect(fn(['foo'])).to.be.eql(['foo']);
106
+ });
107
+
108
+ it('requires a non-empty string or an array of non-empty strings', function () {
109
+ const fn = clause => () => FieldsClauseTool.normalizeFieldsClause(clause);
110
+ const error = v =>
111
+ format(
112
+ 'The provided option "fields" should be a non-empty String ' +
113
+ 'or an Array of String, but %s given.',
114
+ v,
115
+ );
116
+ expect(fn(10)).to.throw(error('10'));
117
+ expect(fn(true)).to.throw(error('true'));
118
+ expect(fn({})).to.throw(error('Object'));
119
+ expect(fn([''])).to.throw(error('""'));
120
+ expect(fn([10])).to.throw(error('10'));
121
+ expect(fn([true])).to.throw(error('true'));
122
+ expect(fn([false])).to.throw(error('false'));
123
+ expect(fn([undefined])).to.throw(error('undefined'));
124
+ expect(fn([null])).to.throw(error('null'));
125
+ expect(fn('')()).to.be.undefined;
126
+ expect(fn(false)()).to.be.undefined;
127
+ expect(fn(undefined)()).to.be.undefined;
128
+ expect(fn(null)()).to.be.undefined;
129
+ expect(fn('foo')()).to.be.eql(['foo']);
130
+ expect(fn(['foo'])()).to.be.eql(['foo']);
131
+ });
132
+ });
133
+ });