Browse Source

chore: adds builtin transformers

e22m4u 1 year ago
parent
commit
2229443b47

+ 5 - 1
README.md

@@ -314,6 +314,9 @@ schema.defineModel({
 нужно производить с входящими данными.
 
 - `trim` удаление пробельных символов с начала и конца строки
+- `toUpperCase` перевод строки в верхний регистр
+- `toLowerCase` перевод строки в нижний регистр
+- `toTitleCase` перевод строки в регистр заголовка
 
 **Пример**
 
@@ -330,7 +333,8 @@ schema.defineModel({
     name: {
       type: DataType.STRING,
       transform: [ // трансформеры свойства "name"
-        'trim', // обрезать пробелы в начале и в конце строки
+        'trim', // удалить пробелы в начале и конце строки
+        'toTitleCase', // перевод в регистр заголовка
       ],
     },
   },

+ 4 - 1
docs/index.html

@@ -150,6 +150,9 @@
 нужно производить с входящими данными.</p>
 <ul>
 <li><code>trim</code> удаление пробельных символов с начала и конца строки</li>
+<li><code>toUpperCase</code> перевод строки в верхний регистр</li>
+<li><code>toLowerCase</code> перевод строки в нижний регистр</li>
+<li><code>toTitleCase</code> перевод строки в регистр заголовка</li>
 </ul>
 <p><strong>Пример</strong></p>
 <p>Трансформеры указываются в объявлении свойства модели параметром
@@ -157,7 +160,7 @@
 указать несколько названий, то используется массив. Если трансформер
 имеет настройки, то используется объект, где ключом является название
 трансформера, а значением его параметры.</p>
-<pre><code class="language-js"><span class="hl-4">schema</span><span class="hl-1">.</span><span class="hl-0">defineModel</span><span class="hl-1">({</span><br/><span class="hl-1">  </span><span class="hl-4">name:</span><span class="hl-1"> </span><span class="hl-2">&#39;user&#39;</span><span class="hl-1">,</span><br/><span class="hl-1">  </span><span class="hl-4">properties:</span><span class="hl-1"> {</span><br/><span class="hl-1">    </span><span class="hl-4">name:</span><span class="hl-1"> {</span><br/><span class="hl-1">      </span><span class="hl-4">type:</span><span class="hl-1"> </span><span class="hl-4">DataType</span><span class="hl-1">.</span><span class="hl-7">STRING</span><span class="hl-1">,</span><br/><span class="hl-1">      </span><span class="hl-4">transform:</span><span class="hl-1"> [ </span><span class="hl-5">// трансформеры свойства &quot;name&quot;</span><br/><span class="hl-1">        </span><span class="hl-2">&#39;trim&#39;</span><span class="hl-1">, </span><span class="hl-5">// обрезать пробелы в начале и в конце строки</span><br/><span class="hl-1">      ],</span><br/><span class="hl-1">    },</span><br/><span class="hl-1">  },</span><br/><span class="hl-1">});</span>
+<pre><code class="language-js"><span class="hl-4">schema</span><span class="hl-1">.</span><span class="hl-0">defineModel</span><span class="hl-1">({</span><br/><span class="hl-1">  </span><span class="hl-4">name:</span><span class="hl-1"> </span><span class="hl-2">&#39;user&#39;</span><span class="hl-1">,</span><br/><span class="hl-1">  </span><span class="hl-4">properties:</span><span class="hl-1"> {</span><br/><span class="hl-1">    </span><span class="hl-4">name:</span><span class="hl-1"> {</span><br/><span class="hl-1">      </span><span class="hl-4">type:</span><span class="hl-1"> </span><span class="hl-4">DataType</span><span class="hl-1">.</span><span class="hl-7">STRING</span><span class="hl-1">,</span><br/><span class="hl-1">      </span><span class="hl-4">transform:</span><span class="hl-1"> [ </span><span class="hl-5">// трансформеры свойства &quot;name&quot;</span><br/><span class="hl-1">        </span><span class="hl-2">&#39;trim&#39;</span><span class="hl-1">, </span><span class="hl-5">// удалить пробелы в начале и конце строки</span><br/><span class="hl-1">        </span><span class="hl-2">&#39;toTitleCase&#39;</span><span class="hl-1">, </span><span class="hl-5">// перевод в регистр заголовка</span><br/><span class="hl-1">      ],</span><br/><span class="hl-1">    },</span><br/><span class="hl-1">  },</span><br/><span class="hl-1">});</span>
 </code><button>Copy</button></pre>
 <a id="md:репозиторий" class="tsd-anchor"></a><h2><a href="#md:репозиторий">Репозиторий</a></h2><p>Выполняет операции чтения и записи документов определенной модели.
 Получить репозиторий можно методом <code>getRepository</code> экземпляра схемы.</p>

+ 3 - 0
src/definition/model/properties/property-transformer/builtin/index.d.ts

@@ -1 +1,4 @@
 export * from './trim-transformer.js';
+export * from './to-lower-case-transformer.js';
+export * from './to-upper-case-transformer.js';
+export * from './to-title-case-transformer.js';

+ 3 - 0
src/definition/model/properties/property-transformer/builtin/index.js

@@ -1 +1,4 @@
 export * from './trim-transformer.js';
+export * from './to-lower-case-transformer.js';
+export * from './to-upper-case-transformer.js';
+export * from './to-title-case-transformer.js';

+ 6 - 0
src/definition/model/properties/property-transformer/builtin/to-lower-case-transformer.d.ts

@@ -0,0 +1,6 @@
+import {PropertyTransformer} from '../property-transformer.js';
+
+/**
+ * To lower case transformer.
+ */
+export declare type toLowerCaseTransformer = PropertyTransformer;

+ 19 - 0
src/definition/model/properties/property-transformer/builtin/to-lower-case-transformer.js

@@ -0,0 +1,19 @@
+import {InvalidArgumentError} from '../../../../../errors/index.js';
+
+/**
+ * To lower case transformer.
+ *
+ * @param {*} value
+ * @param {undefined} options
+ * @param {object} context
+ * @returns {string|undefined|null}
+ */
+export function toLowerCaseTransformer(value, options, context) {
+  if (value == null) return value;
+  if (typeof value === 'string') return value.toLowerCase();
+  throw new InvalidArgumentError(
+    'The property transformer %v requires a String value, but %v given.',
+    context.transformerName,
+    value,
+  );
+}

+ 39 - 0
src/definition/model/properties/property-transformer/builtin/to-lower-case-transformer.spec.js

@@ -0,0 +1,39 @@
+import {expect} from 'chai';
+import {format} from '@e22m4u/js-format';
+import {toLowerCaseTransformer} from './to-lower-case-transformer.js';
+
+describe('toLowerCaseTransformer', function () {
+  it('returns undefined and null values as is', function () {
+    const res1 = toLowerCaseTransformer(undefined, undefined, {});
+    const res2 = toLowerCaseTransformer(null, undefined, {});
+    expect(res1).to.be.undefined;
+    expect(res2).to.be.null;
+  });
+
+  it('converts the given string to lower case', function () {
+    const res = toLowerCaseTransformer('TEST', undefined, {});
+    expect(res).to.be.eq('test');
+  });
+
+  it('throws an error if the given value is not a string', function () {
+    const throwable = v => () =>
+      toLowerCaseTransformer(v, undefined, {
+        transformerName: 'toLowerCase',
+      });
+    const error = v =>
+      format(
+        'The property transformer "toLowerCase" requires a String value, but %s given.',
+        v,
+      );
+    expect(throwable(10)).to.throw(error('10'));
+    expect(throwable(0)).to.throw(error('0'));
+    expect(throwable(true)).to.throw(error('true'));
+    expect(throwable(false)).to.throw(error('false'));
+    expect(throwable({})).to.throw(error('Object'));
+    expect(throwable([])).to.throw(error('Array'));
+    throwable('str')();
+    throwable('')();
+    throwable(undefined)();
+    throwable(null)();
+  });
+});

+ 6 - 0
src/definition/model/properties/property-transformer/builtin/to-title-case-transformer.d.ts

@@ -0,0 +1,6 @@
+import {PropertyTransformer} from '../property-transformer.js';
+
+/**
+ * To title case transformer.
+ */
+export declare type toTitleCaseTransformer = PropertyTransformer;

+ 22 - 0
src/definition/model/properties/property-transformer/builtin/to-title-case-transformer.js

@@ -0,0 +1,22 @@
+import {InvalidArgumentError} from '../../../../../errors/index.js';
+
+/**
+ * To title case transformer.
+ *
+ * @param {*} value
+ * @param {undefined} options
+ * @param {object} context
+ * @returns {string|undefined|null}
+ */
+export function toTitleCaseTransformer(value, options, context) {
+  if (value == null) return value;
+  if (typeof value === 'string')
+    return value.replace(/\p{L}\S*/gu, text => {
+      return text.charAt(0).toUpperCase() + text.substring(1).toLowerCase();
+    });
+  throw new InvalidArgumentError(
+    'The property transformer %v requires a String value, but %v given.',
+    context.transformerName,
+    value,
+  );
+}

+ 41 - 0
src/definition/model/properties/property-transformer/builtin/to-title-case-transformer.spec.js

@@ -0,0 +1,41 @@
+import {expect} from 'chai';
+import {format} from '@e22m4u/js-format';
+import {toTitleCaseTransformer} from './to-title-case-transformer.js';
+
+describe('toTitleCaseTransformer', function () {
+  it('returns undefined and null values as is', function () {
+    const res1 = toTitleCaseTransformer(undefined, undefined, {});
+    const res2 = toTitleCaseTransformer(null, undefined, {});
+    expect(res1).to.be.undefined;
+    expect(res2).to.be.null;
+  });
+
+  it('converts the given string to title case', function () {
+    const res1 = toTitleCaseTransformer('TEST', undefined, {});
+    const res2 = toTitleCaseTransformer('test', undefined, {});
+    expect(res1).to.be.eq('Test');
+    expect(res2).to.be.eq('Test');
+  });
+
+  it('throws an error if the given value is not a string', function () {
+    const throwable = v => () =>
+      toTitleCaseTransformer(v, undefined, {
+        transformerName: 'toTitleCase',
+      });
+    const error = v =>
+      format(
+        'The property transformer "toTitleCase" requires a String value, but %s given.',
+        v,
+      );
+    expect(throwable(10)).to.throw(error('10'));
+    expect(throwable(0)).to.throw(error('0'));
+    expect(throwable(true)).to.throw(error('true'));
+    expect(throwable(false)).to.throw(error('false'));
+    expect(throwable({})).to.throw(error('Object'));
+    expect(throwable([])).to.throw(error('Array'));
+    throwable('str')();
+    throwable('')();
+    throwable(undefined)();
+    throwable(null)();
+  });
+});

+ 6 - 0
src/definition/model/properties/property-transformer/builtin/to-upper-case-transformer.d.ts

@@ -0,0 +1,6 @@
+import {PropertyTransformer} from '../property-transformer.js';
+
+/**
+ * To upper case transformer.
+ */
+export declare type toUpperCaseTransformer = PropertyTransformer;

+ 19 - 0
src/definition/model/properties/property-transformer/builtin/to-upper-case-transformer.js

@@ -0,0 +1,19 @@
+import {InvalidArgumentError} from '../../../../../errors/index.js';
+
+/**
+ * To upper case transformer.
+ *
+ * @param {*} value
+ * @param {undefined} options
+ * @param {object} context
+ * @returns {string|undefined|null}
+ */
+export function toUpperCaseTransformer(value, options, context) {
+  if (value == null) return value;
+  if (typeof value === 'string') return value.toUpperCase();
+  throw new InvalidArgumentError(
+    'The property transformer %v requires a String value, but %v given.',
+    context.transformerName,
+    value,
+  );
+}

+ 39 - 0
src/definition/model/properties/property-transformer/builtin/to-upper-case-transformer.spec.js

@@ -0,0 +1,39 @@
+import {expect} from 'chai';
+import {format} from '@e22m4u/js-format';
+import {toUpperCaseTransformer} from './to-upper-case-transformer.js';
+
+describe('toUpperCaseTransformer', function () {
+  it('returns undefined and null values as is', function () {
+    const res1 = toUpperCaseTransformer(undefined, undefined, {});
+    const res2 = toUpperCaseTransformer(null, undefined, {});
+    expect(res1).to.be.undefined;
+    expect(res2).to.be.null;
+  });
+
+  it('converts the given string to upper case', function () {
+    const res = toUpperCaseTransformer('test', undefined, {});
+    expect(res).to.be.eq('TEST');
+  });
+
+  it('throws an error if the given value is not a string', function () {
+    const throwable = v => () =>
+      toUpperCaseTransformer(v, undefined, {
+        transformerName: 'toUpperCase',
+      });
+    const error = v =>
+      format(
+        'The property transformer "toUpperCase" requires a String value, but %s given.',
+        v,
+      );
+    expect(throwable(10)).to.throw(error('10'));
+    expect(throwable(0)).to.throw(error('0'));
+    expect(throwable(true)).to.throw(error('true'));
+    expect(throwable(false)).to.throw(error('false'));
+    expect(throwable({})).to.throw(error('Object'));
+    expect(throwable([])).to.throw(error('Array'));
+    throwable('str')();
+    throwable('')();
+    throwable(undefined)();
+    throwable(null)();
+  });
+});

+ 6 - 0
src/definition/model/properties/property-transformer/property-transformer-registry.js

@@ -1,5 +1,8 @@
 import {Service} from '@e22m4u/js-service';
 import {trimTransformer} from './builtin/index.js';
+import {toUpperCaseTransformer} from './builtin/index.js';
+import {toLowerCaseTransformer} from './builtin/index.js';
+import {toTitleCaseTransformer} from './builtin/index.js';
 import {InvalidArgumentError} from '../../../../errors/index.js';
 
 /**
@@ -13,6 +16,9 @@ export class PropertyTransformerRegistry extends Service {
    */
   _transformers = {
     trim: trimTransformer,
+    toUpperCase: toUpperCaseTransformer,
+    toLowerCase: toLowerCaseTransformer,
+    toTitleCase: toTitleCaseTransformer,
   };
 
   /**

+ 6 - 0
src/definition/model/properties/property-transformer/property-transformer-registry.spec.js

@@ -1,6 +1,9 @@
 import {expect} from 'chai';
 import {format} from '@e22m4u/js-format';
 import {trimTransformer} from './builtin/index.js';
+import {toUpperCaseTransformer} from './builtin/index.js';
+import {toLowerCaseTransformer} from './builtin/index.js';
+import {toTitleCaseTransformer} from './builtin/index.js';
 import {PropertyTransformerRegistry} from './property-transformer-registry.js';
 
 describe('PropertyTransformerRegistry', function () {
@@ -9,6 +12,9 @@ describe('PropertyTransformerRegistry', function () {
       const S = new PropertyTransformerRegistry();
       expect(S['_transformers']).to.be.eql({
         trim: trimTransformer,
+        toUpperCase: toUpperCaseTransformer,
+        toLowerCase: toLowerCaseTransformer,
+        toTitleCase: toTitleCaseTransformer,
       });
     });