@empathyco/x-adapter 8.0.0-alpha.17 → 8.0.0-alpha.19
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.
package/README.md
CHANGED
|
@@ -74,7 +74,7 @@ passed.
|
|
|
74
74
|
###### Types definition
|
|
75
75
|
|
|
76
76
|
```ts
|
|
77
|
-
// API
|
|
77
|
+
// API models
|
|
78
78
|
interface ApiRequest {
|
|
79
79
|
q?: string;
|
|
80
80
|
id?: number;
|
|
@@ -89,7 +89,7 @@ interface ApiProduct {
|
|
|
89
89
|
price: number;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
// App
|
|
92
|
+
// App models
|
|
93
93
|
interface AppSearchRequest {
|
|
94
94
|
query: string;
|
|
95
95
|
}
|
|
@@ -243,7 +243,7 @@ the value somehow.
|
|
|
243
243
|
###### Types definition
|
|
244
244
|
|
|
245
245
|
```ts
|
|
246
|
-
// API
|
|
246
|
+
// API models
|
|
247
247
|
interface ApiUserRequest {
|
|
248
248
|
q: string;
|
|
249
249
|
}
|
|
@@ -256,7 +256,7 @@ interface ApiUser {
|
|
|
256
256
|
firstName: string;
|
|
257
257
|
}
|
|
258
258
|
|
|
259
|
-
// App
|
|
259
|
+
// App models
|
|
260
260
|
interface AppUserRequest {
|
|
261
261
|
query: string;
|
|
262
262
|
}
|
|
@@ -307,7 +307,7 @@ them you just have to provide with the `Path` of the data to map, and the `Schem
|
|
|
307
307
|
###### Types definition
|
|
308
308
|
|
|
309
309
|
```ts
|
|
310
|
-
// API
|
|
310
|
+
// API models
|
|
311
311
|
interface ApiRequest {
|
|
312
312
|
q: string;
|
|
313
313
|
}
|
|
@@ -328,7 +328,7 @@ interface ApiAddress {
|
|
|
328
328
|
postalCode: string;
|
|
329
329
|
}
|
|
330
330
|
|
|
331
|
-
//
|
|
331
|
+
// App models
|
|
332
332
|
interface AppRequest {
|
|
333
333
|
query: string;
|
|
334
334
|
}
|
|
@@ -408,34 +408,262 @@ export const searchUsersWithContactInfo = endpointAdapterFactory({
|
|
|
408
408
|
|
|
409
409
|
#### Using a mutable schema
|
|
410
410
|
|
|
411
|
-
This feature lets you have some default
|
|
412
|
-
implementations. To do so, you
|
|
413
|
-
|
|
411
|
+
This feature lets you have some default schemas, and modify or extend them for some concrete
|
|
412
|
+
implementations. To do so, you can use the `createMutableSchema` function, passing a `Source` and
|
|
413
|
+
`Target` type parameters to map your models. This function will return a `MutableSchema` that apart
|
|
414
|
+
from the mapping information will also contain some methods to create new schemas or modify the
|
|
415
|
+
current one.
|
|
416
|
+
|
|
417
|
+
In the example below we will create a `MutableSchema` to have a default object that will be reused
|
|
418
|
+
for different endpoint calls.
|
|
419
|
+
|
|
420
|
+
###### Types definition and MutableSchema
|
|
421
|
+
|
|
422
|
+
```ts
|
|
423
|
+
// API models
|
|
424
|
+
export interface ApiBaseObject {
|
|
425
|
+
id: number;
|
|
426
|
+
body: string;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// APP models
|
|
430
|
+
export interface AppBaseObject {
|
|
431
|
+
id: string;
|
|
432
|
+
text: string;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// Mutable Schema
|
|
436
|
+
export const baseObjectSchema = createMutableSchema<ApiBaseObject, AppBaseObject>({
|
|
437
|
+
id: ({ id }) => id.toString(),
|
|
438
|
+
text: 'body'
|
|
439
|
+
});
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
Once we have the `MutableSchema`, we can use the following methods to fit our different APIs needs:
|
|
443
|
+
|
|
444
|
+
- `$extends`: Creates a new `MutableSchema` based on the original one. The original remains
|
|
445
|
+
unchanged. This can be useful if we need to create a new `EndpointAdapter` with models based on
|
|
446
|
+
another API.
|
|
447
|
+
- `$override`: Merges/modifies the original `MutableSchema` partially, so the change will affect to
|
|
448
|
+
all the `EndpointAdapter`(s) that are using it. It can be used to change the structure of our
|
|
449
|
+
request/response mappers, or to add them new fields. Useful for clients with few differences in
|
|
450
|
+
their APIs. For example, you can create a library with a default adapter and use this library from
|
|
451
|
+
the customer projects overriding only the needed field (e.g. retrieve the images from `pictures`
|
|
452
|
+
instead of `images` in a products API).
|
|
453
|
+
- `$replace`: Replaces completely the original `MutableSchema` by a new one, it won't exist anymore.
|
|
454
|
+
The change will affect to all the `EndpointAdapter`(s) that were using it. Useful for clients with
|
|
455
|
+
a completely different API/response to the standard you have been working with.
|
|
456
|
+
|
|
457
|
+
###### Extend a MutableSchema to reuse it in two different endpoints with more fields
|
|
458
|
+
|
|
459
|
+
```ts
|
|
460
|
+
import { ApiBaseObject, AppBaseObject, baseObjectSchema } from '@/base-types';
|
|
461
|
+
|
|
462
|
+
// Api models
|
|
463
|
+
interface ApiPost extends ApiBaseObject {
|
|
464
|
+
title: string;
|
|
465
|
+
}
|
|
466
|
+
interface ApiPostsResponse {
|
|
467
|
+
posts: ApiPost[];
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
interface ApiComment extends ApiBaseObject {
|
|
471
|
+
postId: number;
|
|
472
|
+
}
|
|
473
|
+
interface ApiCommentsResponse {
|
|
474
|
+
comments: ApiComment[];
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// App models
|
|
478
|
+
interface AppPost extends AppBaseObject {
|
|
479
|
+
postTitle: string;
|
|
480
|
+
}
|
|
481
|
+
interface AppPostsResponse {
|
|
482
|
+
posts: AppPost[];
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
interface AppComment extends AppBaseObject {
|
|
486
|
+
postId: number;
|
|
487
|
+
}
|
|
488
|
+
interface AppCommentsResponse {
|
|
489
|
+
comments: AppComment[];
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// Extend for posts endpoint
|
|
493
|
+
const postSchema = baseObjectSchema.$extends<ApiPost, AppPost>({
|
|
494
|
+
postTitle: 'title'
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
const postsResponse = schemaMapperFactory<ApiPostsResponse, AppPostsResponse>({
|
|
498
|
+
posts: {
|
|
499
|
+
$subSchema: postSchema,
|
|
500
|
+
$path: 'posts'
|
|
501
|
+
}
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
export const searchPosts = endpointAdapterFactory({
|
|
505
|
+
endpoint: 'https://dummyjson.com/posts',
|
|
506
|
+
responseMapper: postsResponse
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
// Extend for comments endpoint
|
|
510
|
+
const commentSchema = baseObjectSchema.$extends<ApiComment, AppComment>({
|
|
511
|
+
postId: 'postId'
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
const commentsResponse = schemaMapperFactory<ApiCommentsResponse, AppCommentsResponse>({
|
|
515
|
+
comments: {
|
|
516
|
+
$subSchema: commentSchema,
|
|
517
|
+
$path: 'comments'
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
export const searchComments = endpointAdapterFactory({
|
|
522
|
+
endpoint: 'https://dummyjson.com/comments',
|
|
523
|
+
responseMapper: commentsResponse
|
|
524
|
+
});
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
###### Override a MutableSchema to add more fields
|
|
528
|
+
|
|
529
|
+
As said above, the suitable context for using the `override` method would be a project with an API
|
|
530
|
+
that doesn't differ too much against the one used in our "base project". That means we can reuse
|
|
531
|
+
most of the types and schemas definitions, so we would only add a few new fields from the new API.
|
|
414
532
|
|
|
415
533
|
```ts
|
|
416
|
-
|
|
534
|
+
import { ApiBaseObject, AppBaseObject, baseObjectSchema } from '@/base-types';
|
|
535
|
+
|
|
536
|
+
// Api models
|
|
537
|
+
interface ApiTodo {
|
|
538
|
+
completed: boolean;
|
|
539
|
+
todo: string;
|
|
540
|
+
userId: number;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
interface ApiTodosResponse {
|
|
544
|
+
todos: ApiBaseObject[];
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// App models
|
|
548
|
+
interface AppTodo {
|
|
549
|
+
completed: boolean;
|
|
550
|
+
text: string;
|
|
551
|
+
userId: string;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
interface AppTodosResponse {
|
|
555
|
+
todos: AppBaseObject[];
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// Response mapper
|
|
559
|
+
const todosResponse = schemaMapperFactory<ApiTodosResponse, AppTodosResponse>({
|
|
560
|
+
todos: {
|
|
561
|
+
$subSchema: baseObjectSchema,
|
|
562
|
+
$path: 'todos'
|
|
563
|
+
}
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
// Endpoint Adapter
|
|
567
|
+
export const searchTodos = endpointAdapterFactory({
|
|
568
|
+
endpoint: 'https://dummyjson.com/todos',
|
|
569
|
+
responseMapper: todosResponse
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
// Override the original Schema. The Schema changes to map: 'id', 'completed', 'text' and 'userId''
|
|
573
|
+
baseObjectSchema.$override<ApiTodo, AppTodo>({
|
|
574
|
+
completed: 'completed',
|
|
575
|
+
text: 'todo',
|
|
576
|
+
userId: ({ userId }) => userId.toString()
|
|
577
|
+
});
|
|
417
578
|
```
|
|
418
579
|
|
|
419
|
-
|
|
420
|
-
it:
|
|
580
|
+
###### Replace a MutableSchema to completely change it
|
|
421
581
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
582
|
+
In this case we are facing too many differences between API responses. We don't need to write a
|
|
583
|
+
whole adapter from scratch, as there are other parts of the API that aren't changing so much, but we
|
|
584
|
+
should replace some `endpointAdapter`'s schemas.
|
|
425
585
|
|
|
426
586
|
```ts
|
|
427
|
-
|
|
587
|
+
import { ApiBaseObject, AppBaseObject, baseObjectSchema } from '@/base-types';
|
|
588
|
+
|
|
589
|
+
// Api models
|
|
590
|
+
interface ApiQuote {
|
|
591
|
+
id: number;
|
|
592
|
+
quote: string;
|
|
593
|
+
author: string;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
interface ApiQuotesResponse {
|
|
597
|
+
quotes: ApiBaseObject[];
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// App models
|
|
601
|
+
interface AppQuote {
|
|
602
|
+
quoteId: string;
|
|
603
|
+
quote: string;
|
|
604
|
+
author: string;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
interface AppQuotesResponse {
|
|
608
|
+
quotes: AppBaseObject[];
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
// Response mapper
|
|
612
|
+
const quotesResponse = schemaMapperFactory<ApiQuotesResponse, AppQuotesResponse>({
|
|
613
|
+
quotes: {
|
|
614
|
+
$subSchema: baseObjectSchema,
|
|
615
|
+
$path: 'quotes'
|
|
616
|
+
}
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
// Endpoint Adapter
|
|
620
|
+
export const searchQuotes = endpointAdapterFactory({
|
|
621
|
+
endpoint: 'https://dummyjson.com/quotes',
|
|
622
|
+
responseMapper: quotesResponse
|
|
623
|
+
});
|
|
624
|
+
|
|
625
|
+
// Replace the original Schema
|
|
626
|
+
baseObjectSchema.$replace<ApiQuote, AppQuote>({
|
|
627
|
+
quoteId: ({ id }) => id.toString(),
|
|
628
|
+
quote: 'quote',
|
|
629
|
+
author: 'author'
|
|
630
|
+
});
|
|
428
631
|
```
|
|
429
632
|
|
|
430
633
|
<br>
|
|
431
634
|
|
|
432
635
|
### Extend an adapter that uses schemas
|
|
433
636
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
637
|
+
Imagine you have a new setup and that you can reuse most of the stuff you have developed. Probably
|
|
638
|
+
you have built an adapter instance as a configuration object that contains all of your
|
|
639
|
+
`EndpointAdapter` calls, so you only need to extend the endpoint you need to change.
|
|
640
|
+
|
|
641
|
+
```ts
|
|
642
|
+
export const adapter = {
|
|
643
|
+
searchItem: getItemById,
|
|
644
|
+
searchList: searchComments
|
|
645
|
+
// Any endpoint adapter you are using to communicate with your API
|
|
646
|
+
};
|
|
647
|
+
|
|
648
|
+
adapter.searchList = searchComments.extends({
|
|
649
|
+
endpoint: 'https://dummyjson.com/comments/',
|
|
650
|
+
defaultRequestOptions: {
|
|
651
|
+
// If you need to send an id, a header...
|
|
652
|
+
},
|
|
653
|
+
defaultRequestOptions: {
|
|
654
|
+
parameters: {
|
|
655
|
+
limit: 10,
|
|
656
|
+
skip: 10
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
});
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
For further detail, you can check the
|
|
663
|
+
[x-platform-adapter](https://github.com/empathyco/x/tree/main/packages/x-adapter-platform) package.
|
|
664
|
+
It is a whole adapter implementation using this `x-adapter` library to suit the
|
|
665
|
+
[Search Platform API](https://docs.empathy.co/develop-empathy-platform/api-reference/search-api.html)
|
|
666
|
+
needs.
|
|
439
667
|
|
|
440
668
|
## Test
|
|
441
669
|
|
|
@@ -452,9 +680,9 @@ npm test
|
|
|
452
680
|
|
|
453
681
|
## Contributing
|
|
454
682
|
|
|
455
|
-
To start contributing to the project, please take a look to
|
|
456
|
-
|
|
457
|
-
|
|
683
|
+
To start contributing to the project, please take a look to our
|
|
684
|
+
**[Contributing Guide](https://github.com/empathyco/x/blob/main/.github/CONTRIBUTING.md).** Take in
|
|
685
|
+
account that `x-adapter` is developed using [Typescript](https://www.typescriptlang.org/), so we
|
|
458
686
|
recommend you check it out.
|
|
459
687
|
|
|
460
688
|
## License
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/schemas/types.ts"],"names":[],"mappings":"","sourcesContent":["import {\n AnyFunction,\n DeepPartial,\n ExtractPath,\n ExtractPathByType,\n ExtractType,\n Primitive\n} from '@empathyco/x-utils';\nimport { MapperContext } from '../mappers/types';\n\n// TODO: EX-5830 - Enhance Schema type to support optional properties in the Source object\n/**\n * Template object to transform a source object to a target object.\n *\n * @remarks The source object must not have optional properties, as it could cause infinite\n * type instantiations.\n * @param Source - The source object.\n * @param Target - The target object.\n * @example\n * ```typescript\n * interface Source {\n * id: string;\n * price: {\n * max: number;\n * min: number;\n * };\n * images: string[];\n * }\n *\n * interface Target {\n * identifier: string;\n * maxPrice: number;\n * minPrice: number;\n * img: string[]\n * }\n *\n * const schema: Schema<Source, Target> = {\n * identifier: 'id',\n * maxPrice: 'price.max',\n * minPrice: ({ price }) => Math.min(0, price.min),\n * img: 'images'\n * };\n * ```\n * @public\n */\nexport type Schema<Source = any, Target = any> = {\n [TargetKey in keyof Target]: SchemaTransformer<Source, Target, TargetKey>;\n};\n\n/**\n * A {@link Schema | schema} with extended functionality to: completely replace\n * the original schema, partially override it or create a new one.\n *\n * @param OriginalSchema - The {@link Schema | schema} that will be mutable.\n * @public\n */\nexport type MutableSchema<Source, Target> = Schema<Source, Target> & {\n /**\n * Replaces all usages of the original {@link Schema | schema} with the given one.\n *\n * @param newSchema - The {@link Schema | schema} to use instead of the original one.\n * @returns The new {@link Schema | schema} that will be used.\n */\n $replace<NewSource, NewTarget>(\n newSchema: Schema<NewSource, NewTarget>\n ): MutableSchema<NewSource, NewTarget>;\n /**\n * Merges the original {@link Schema | schema} with the given one.\n *\n * @param newSchema - The {@link Schema | schema} to use to merge with the original one.\n * @returns The {@link Schema | schema} returned by the merge.\n */\n // eslint-disable-next-line @typescript-eslint/ban-types\n $override<NewSource, NewTarget = {}>(\n newSchema: DeepPartial<Schema<Source & NewSource, Target>> &\n Schema<Source & NewSource, NewTarget>\n ): MutableSchema<Source & NewSource, Target & NewTarget>;\n /**\n * Creates a new {@link Schema | schema} using the original one as starting point.\n * The original {@link Schema | schema} will remain unchanged.\n *\n * @param newSchema - The {@link Schema | schema} to be used to extend the original one.\n * @returns The {@link Schema | schema} created.\n */\n // eslint-disable-next-line @typescript-eslint/ban-types\n $extends<NewSource, NewTarget = {}>(\n newSchema: DeepPartial<Schema<Source & NewSource, Target>> &\n Schema<Source & NewSource, NewTarget>\n ): MutableSchema<Source & NewSource, Target & NewTarget>;\n /**\n * Returns a string representing of the {@link Schema | schema}.\n *\n * @param includeInternalMethods - Flag to include in the string representation\n * the internal methods. Disabled by default.\n * @returns The string representation.\n */\n toString(includeInternalMethods?: boolean): string;\n};\n/**\n * The possible transformers to apply to the target key.\n *\n * @param Source - The source object.\n * @param Target - The target object.\n * @param TargetKey - The target key to apply the transformation.\n * @public\n */\nexport type SchemaTransformer<Source, Target, TargetKey extends keyof Target> =\n | PathTransformer<Source, Target[TargetKey]>\n | FunctionTransformer<Source, Target[TargetKey]>\n | SubSchemaTransformer<Source, Target[TargetKey]>\n | Schema<Source, Exclude<Target[TargetKey], AnyFunction | Primitive>>;\n\n/**\n * A function with the source object and mapper context as parameters that returns the value of a\n * target's property.\n *\n * @param Source - The source object.\n * @param Target - The target object.\n * @example\n * ```typescript\n * interface Source {\n * id: string;\n * count: number;\n * }\n *\n * interface Target {\n * title: string;\n * hits: number;\n * }\n *\n * const subSchema: Schema<Source, Target> = {\n * title: 'id',\n * hits: 'count'\n * };\n *\n * const wrongSubSchema: Schema<Source, Target> = {\n * // @ts-expect-error\n * title: 'count', // This raises a TS error\n * hits: 'count'\n * };\n * ```\n * @public\n */\nexport type PathTransformer<Source, Target> = ExtractPathByType<Source, Target>;\n\n/**\n * A function with the source object and mapper context as parameters that returns the value of a\n * target's property.\n *\n * @param Source - The source object.\n * @param Target - The target object.\n * @example\n * ```typescript\n * interface Source {\n * id: string;\n * count: number;\n * }\n *\n * interface Target {\n * title: string;\n * hits: number;\n * }\n *\n * const subSchema: Schema<Source, Target> = {\n * title: source => source.id,\n * hits: (source, context) => context.requestParameters.query === 'example'\n * ? source.count\n * : 0\n * };\n * ```\n * @public\n */\nexport type FunctionTransformer<Source, Target> = (\n source: Source,\n context?: MapperContext\n) => Target;\n\n/**\n * An object containing a schema narrowing its source object based on the given path.\n *\n * @param Source - The source object.\n * @param Target - The target object.\n * @example\n * ```typescript\n * interface Source {\n * id: string;\n * facets: {\n * name: string;\n * count: number;\n * };\n * images: string[];\n * }\n *\n * interface Target {\n * identifier: string;\n * filters: {\n * id: string;\n * numFound: number;\n * };\n * img: string[]\n * }\n *\n * const subSchema: SubSchemaTransformer<Source, Target['filters']> = {\n * $path: 'facets',\n * $subSchema: {\n * id: 'name',\n * numFound: 'count'\n * }\n * };\n * ```\n * @public\n */\nexport type SubSchemaTransformer<Source, Target> = {\n [Path in ExtractPath<Source>]: {\n $context?: MapperContext;\n $path: Path;\n $subSchema:\n | SubSchema<Source, Target, Path>\n | '$self'\n | ((source: Source) => SubSchema<Source, Target, Path>);\n };\n}[ExtractPath<Source>];\n\n/**\n * A {@link Schema | schema} that will be applied to an inner path of an object.\n *\n * @param Source - The source object.\n * @param Target - The target object.\n * @param Path - The path where the schema will be applied.\n * @public\n */\nexport type SubSchema<Source, Target, Path extends ExtractPath<Source>> = ExtractType<\n Source,\n Path\n> extends (infer SourceArrayType)[]\n ? Target extends (infer TargetArrayType)[]\n ? Schema<SourceArrayType, TargetArrayType>\n : never\n : Target extends []\n ? never\n : Schema<ExtractType<Source, Path>, Target>;\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/schemas/types.ts"],"names":[],"mappings":"","sourcesContent":["import {\n AnyFunction,\n DeepPartial,\n ExtractPath,\n ExtractPathByType,\n ExtractType,\n Primitive\n} from '@empathyco/x-utils';\nimport { MapperContext } from '../mappers/types';\n\n// TODO: EX-5830 - Enhance Schema type to support optional properties in the Source object\n/**\n * Template object to transform a source object to a target object.\n *\n * @remarks The source object must not have optional properties, as it could cause infinite\n * type instantiations.\n * @param Source - The source object.\n * @param Target - The target object.\n * @example\n * ```typescript\n * interface Source {\n * id: string;\n * price: {\n * max: number;\n * min: number;\n * };\n * images: string[];\n * }\n *\n * interface Target {\n * identifier: string;\n * maxPrice: number;\n * minPrice: number;\n * img: string[]\n * }\n *\n * const schema: Schema<Source, Target> = {\n * identifier: 'id',\n * maxPrice: 'price.max',\n * minPrice: ({ price }) => Math.min(0, price.min),\n * img: 'images'\n * };\n * ```\n * @public\n */\nexport type Schema<Source = any, Target = any> = {\n [TargetKey in keyof Target]: SchemaTransformer<Source, Target, TargetKey>;\n};\n\n/**\n * A {@link Schema | schema} with extended functionality to: completely replace\n * the original schema, partially override it or create a new one.\n *\n * @param OriginalSchema - The {@link Schema | schema} that will be mutable.\n * @public\n */\nexport type MutableSchema<Source, Target> = Schema<Source, Target> & {\n /**\n * Replaces all usages of the original {@link Schema | schema} with the given one.\n *\n * @param newSchema - The {@link Schema | schema} to use instead of the original one.\n * @returns The new {@link Schema | schema} that will be used.\n */\n $replace<NewSource, NewTarget>(\n newSchema: Schema<NewSource, NewTarget>\n ): MutableSchema<NewSource, NewTarget>;\n /**\n * Merges the original {@link Schema | schema} with the given one.\n *\n * @param newSchema - The {@link Schema | schema} to use to merge with the original one.\n * @returns The {@link Schema | schema} returned by the merge.\n */\n // eslint-disable-next-line @typescript-eslint/ban-types\n $override<NewSource, NewTarget = {}>(\n newSchema: DeepPartial<Schema<Source & NewSource, Target>> &\n Schema<Source & NewSource, NewTarget>\n ): MutableSchema<Source & NewSource, Target & NewTarget>;\n /**\n * Creates a new {@link Schema | schema} using the original one as starting point.\n * The original {@link Schema | schema} will remain unchanged.\n *\n * @param newSchema - The {@link Schema | schema} to be used to extend the original one.\n * Both schema's Target and Source can be unique or also be extending from another one.\n * @returns The {@link Schema | schema} created.\n */\n $extends<NewSource extends Source, NewTarget extends Target>(\n newSchema: DeepPartial<Schema<Source & NewSource, Target>> &\n Schema<Source & NewSource, Omit<NewTarget, keyof Target>>\n ): MutableSchema<Source & NewSource, Target & NewTarget>;\n // eslint-disable-next-line @typescript-eslint/ban-types\n $extends<NewSource, NewTarget = {}>(\n newSchema: DeepPartial<Schema<Source & NewSource, Target>> &\n Schema<Source & NewSource, NewTarget>\n ): MutableSchema<Source & NewSource, Target & NewTarget>;\n /**\n * Returns a string representing of the {@link Schema | schema}.\n *\n * @param includeInternalMethods - Flag to include in the string representation\n * the internal methods. Disabled by default.\n * @returns The string representation.\n */\n toString(includeInternalMethods?: boolean): string;\n};\n/**\n * The possible transformers to apply to the target key.\n *\n * @param Source - The source object.\n * @param Target - The target object.\n * @param TargetKey - The target key to apply the transformation.\n * @public\n */\nexport type SchemaTransformer<Source, Target, TargetKey extends keyof Target> =\n | PathTransformer<Source, Target[TargetKey]>\n | FunctionTransformer<Source, Target[TargetKey]>\n | SubSchemaTransformer<Source, Target[TargetKey]>\n | Schema<Source, Exclude<Target[TargetKey], AnyFunction | Primitive>>;\n\n/**\n * A function with the source object and mapper context as parameters that returns the value of a\n * target's property.\n *\n * @param Source - The source object.\n * @param Target - The target object.\n * @example\n * ```typescript\n * interface Source {\n * id: string;\n * count: number;\n * }\n *\n * interface Target {\n * title: string;\n * hits: number;\n * }\n *\n * const subSchema: Schema<Source, Target> = {\n * title: 'id',\n * hits: 'count'\n * };\n *\n * const wrongSubSchema: Schema<Source, Target> = {\n * // @ts-expect-error\n * title: 'count', // This raises a TS error\n * hits: 'count'\n * };\n * ```\n * @public\n */\nexport type PathTransformer<Source, Target> = ExtractPathByType<Source, Target>;\n\n/**\n * A function with the source object and mapper context as parameters that returns the value of a\n * target's property.\n *\n * @param Source - The source object.\n * @param Target - The target object.\n * @example\n * ```typescript\n * interface Source {\n * id: string;\n * count: number;\n * }\n *\n * interface Target {\n * title: string;\n * hits: number;\n * }\n *\n * const subSchema: Schema<Source, Target> = {\n * title: source => source.id,\n * hits: (source, context) => context.requestParameters.query === 'example'\n * ? source.count\n * : 0\n * };\n * ```\n * @public\n */\nexport type FunctionTransformer<Source, Target> = (\n source: Source,\n context?: MapperContext\n) => Target;\n\n/**\n * An object containing a schema narrowing its source object based on the given path.\n *\n * @param Source - The source object.\n * @param Target - The target object.\n * @example\n * ```typescript\n * interface Source {\n * id: string;\n * facets: {\n * name: string;\n * count: number;\n * };\n * images: string[];\n * }\n *\n * interface Target {\n * identifier: string;\n * filters: {\n * id: string;\n * numFound: number;\n * };\n * img: string[]\n * }\n *\n * const subSchema: SubSchemaTransformer<Source, Target['filters']> = {\n * $path: 'facets',\n * $subSchema: {\n * id: 'name',\n * numFound: 'count'\n * }\n * };\n * ```\n * @public\n */\nexport type SubSchemaTransformer<Source, Target> = {\n [Path in ExtractPath<Source>]: {\n $context?: MapperContext;\n $path: Path;\n $subSchema:\n | SubSchema<Source, Target, Path>\n | '$self'\n | ((source: Source) => SubSchema<Source, Target, Path>);\n };\n}[ExtractPath<Source>];\n\n/**\n * A {@link Schema | schema} that will be applied to an inner path of an object.\n *\n * @param Source - The source object.\n * @param Target - The target object.\n * @param Path - The path where the schema will be applied.\n * @public\n */\nexport type SubSchema<Source, Target, Path extends ExtractPath<Source>> = ExtractType<\n Source,\n Path\n> extends (infer SourceArrayType)[]\n ? Target extends (infer TargetArrayType)[]\n ? Schema<SourceArrayType, TargetArrayType>\n : never\n : Target extends []\n ? never\n : Schema<ExtractType<Source, Path>, Target>;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/schemas/utils.ts"],"names":[],"mappings":";;;AAAA,0DAAoD;AACpD,gDAAmE;AAGnE;;GAEG;AACH,MAAM,6BAA6B,GAAa,CAAC,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;AAElG;;;;;;;;GAQG;AACH,SAAgB,mBAAmB,CACjC,MAA8B;IAE9B,OAAO;QACL,GAAG,MAAM;QACT,QAAQ,CAAC,SAAS;YAChB,IAAA,iBAAO,EAAC,IAAI,EAAE,GAAG,CAAC,EAAE;gBAClB,IAAI,gBAAgB,CAAC,GAAa,CAAC,EAAE;oBACnC,OAAO;iBACR;gBACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;YACnB,CAAC,CAAC,CAAC;YACH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YAC/B;+EACmE;YACnE,OAAO,IAAW,CAAC;QACrB,CAAC;QACD,SAAS,CAAC,SAAS;YACjB,OAAO,IAAA,wBAAS,EAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACpC,CAAC;QACD,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/schemas/utils.ts"],"names":[],"mappings":";;;AAAA,0DAAoD;AACpD,gDAAmE;AAGnE;;GAEG;AACH,MAAM,6BAA6B,GAAa,CAAC,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;AAElG;;;;;;;;GAQG;AACH,SAAgB,mBAAmB,CACjC,MAA8B;IAE9B,OAAO;QACL,GAAG,MAAM;QACT,QAAQ,CAAC,SAAS;YAChB,IAAA,iBAAO,EAAC,IAAI,EAAE,GAAG,CAAC,EAAE;gBAClB,IAAI,gBAAgB,CAAC,GAAa,CAAC,EAAE;oBACnC,OAAO;iBACR;gBACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;YACnB,CAAC,CAAC,CAAC;YACH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YAC/B;+EACmE;YACnE,OAAO,IAAW,CAAC;QACrB,CAAC;QACD,SAAS,CAAC,SAAS;YACjB,OAAO,IAAA,wBAAS,EAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACpC,CAAC;QACD,QAAQ,CAAC,SAAkB;YACzB,OAAO,IAAA,wBAAS,EAAC,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QACxC,CAAC;QACD,QAAQ,CAAC,sBAAsB,GAAG,KAAK;YACrC,OAAO,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,sBAAsB,CAAC,CAAC;QACnD,CAAC;KACF,CAAC;AACJ,CAAC;AA3BD,kDA2BC;AAED;;;;;;;;;GASG;AACH,SAAgB,gBAAgB,CAAC,IAAY;IAC3C,OAAO,6BAA6B,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACtD,CAAC;AAFD,4CAEC;AAED;;;;;;;;GAQG;AACH,SAAS,SAAS,CAChB,IAA6B,EAC7B,sBAA+B,EAC/B,IAAI,GAAG,CAAC;IAER,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAA,iBAAO,EAAC,IAAI,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;QAC3B,IAAI,IAAA,kBAAQ,EAAC,KAAK,CAAC,EAAE;YACnB,MAAM,IAAI,GAAG,WAAW,GAAG,GAAG,QAAQ,SAAS,CAC7C,KAAK,EACL,sBAAsB,EACtB,EAAE,IAAI,CACP,GAAG,WAAW,MAAM,CAAC;SACvB;aAAM,IAAI,CAAC,IAAA,oBAAU,EAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,sBAAsB,EAAE;YACjF,4EAA4E;YAC5E,MAAM,IAAI,GAAG,WAAW,GAAG,GAAG,KAAK,KAAK,KAAK,CAAC;SAC/C;IACH,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import { deepMerge } from '@empathyco/x-deep-merge';\nimport { forEach, isFunction, isObject } from '@empathyco/x-utils';\nimport { MutableSchema, Schema } from './types';\n\n/**\n * Collection of internal method names for {@link MutableSchema | mutable schemas}.\n */\nconst mutableSchemasInternalMethods: string[] = ['$replace', '$override', '$extends', 'toString'];\n\n/**\n * Creates a {@link MutableSchema | mutable schema } version of a given {@link Schema | schema}.\n *\n * @param schema - The {@link Schema | schema} to make mutable.\n *\n * @returns A {@link MutableSchema | mutable schema} version of the given {@link Schema | schema}.\n *\n * @public\n */\nexport function createMutableSchema<Source, Target>(\n schema: Schema<Source, Target>\n): MutableSchema<Source, Target> {\n return {\n ...schema,\n $replace(newSchema) {\n forEach(this, key => {\n if (isInternalMethod(key as string)) {\n return;\n }\n delete this[key];\n });\n Object.assign(this, newSchema);\n /* We are replacing the schema with a completely new schema , so it makes sense that TS\n complains that the old schema and the new one are not the same. */\n return this as any;\n },\n $override(newSchema) {\n return deepMerge(this, newSchema);\n },\n $extends(newSchema: unknown) {\n return deepMerge({}, this, newSchema);\n },\n toString(includeInternalMethods = false) {\n return serialize(this, !!includeInternalMethods);\n }\n };\n}\n\n/**\n * Checks if the given key is a {@link MutableSchema | mutableSchema} method.\n *\n * @param name - The key to check.\n *\n * @returns True if it is a {@link MutableSchema | mutableSchema} method,\n * false otherwise.\n *\n * @public\n */\nexport function isInternalMethod(name: string): boolean {\n return mutableSchemasInternalMethods.includes(name);\n}\n\n/**\n * Returns a string representing of the given object.\n *\n * @param data - The object to get the string representation from.\n * @param includeInternalMethods - Flag to include in the string representation\n * the internal methods. Disabled by default.\n * @param deep - The level of indentation.\n * @returns The string representation.\n */\nfunction serialize(\n data: Record<string, unknown>,\n includeInternalMethods: boolean,\n deep = 0\n): string {\n const indentation = ' '.repeat(deep);\n let output = '';\n forEach(data, (key, value) => {\n if (isObject(value)) {\n output += `${indentation}${key}: {\\n${serialize(\n value,\n includeInternalMethods,\n ++deep\n )}${indentation}},\\n`;\n } else if (!isFunction(value) || !isInternalMethod(key) || includeInternalMethods) {\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n output += `${indentation}${key}: ${value},\\n`;\n }\n });\n return output;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/schemas/types.ts"],"names":[],"mappings":"","sourcesContent":["import {\n AnyFunction,\n DeepPartial,\n ExtractPath,\n ExtractPathByType,\n ExtractType,\n Primitive\n} from '@empathyco/x-utils';\nimport { MapperContext } from '../mappers/types';\n\n// TODO: EX-5830 - Enhance Schema type to support optional properties in the Source object\n/**\n * Template object to transform a source object to a target object.\n *\n * @remarks The source object must not have optional properties, as it could cause infinite\n * type instantiations.\n * @param Source - The source object.\n * @param Target - The target object.\n * @example\n * ```typescript\n * interface Source {\n * id: string;\n * price: {\n * max: number;\n * min: number;\n * };\n * images: string[];\n * }\n *\n * interface Target {\n * identifier: string;\n * maxPrice: number;\n * minPrice: number;\n * img: string[]\n * }\n *\n * const schema: Schema<Source, Target> = {\n * identifier: 'id',\n * maxPrice: 'price.max',\n * minPrice: ({ price }) => Math.min(0, price.min),\n * img: 'images'\n * };\n * ```\n * @public\n */\nexport type Schema<Source = any, Target = any> = {\n [TargetKey in keyof Target]: SchemaTransformer<Source, Target, TargetKey>;\n};\n\n/**\n * A {@link Schema | schema} with extended functionality to: completely replace\n * the original schema, partially override it or create a new one.\n *\n * @param OriginalSchema - The {@link Schema | schema} that will be mutable.\n * @public\n */\nexport type MutableSchema<Source, Target> = Schema<Source, Target> & {\n /**\n * Replaces all usages of the original {@link Schema | schema} with the given one.\n *\n * @param newSchema - The {@link Schema | schema} to use instead of the original one.\n * @returns The new {@link Schema | schema} that will be used.\n */\n $replace<NewSource, NewTarget>(\n newSchema: Schema<NewSource, NewTarget>\n ): MutableSchema<NewSource, NewTarget>;\n /**\n * Merges the original {@link Schema | schema} with the given one.\n *\n * @param newSchema - The {@link Schema | schema} to use to merge with the original one.\n * @returns The {@link Schema | schema} returned by the merge.\n */\n // eslint-disable-next-line @typescript-eslint/ban-types\n $override<NewSource, NewTarget = {}>(\n newSchema: DeepPartial<Schema<Source & NewSource, Target>> &\n Schema<Source & NewSource, NewTarget>\n ): MutableSchema<Source & NewSource, Target & NewTarget>;\n /**\n * Creates a new {@link Schema | schema} using the original one as starting point.\n * The original {@link Schema | schema} will remain unchanged.\n *\n * @param newSchema - The {@link Schema | schema} to be used to extend the original one.\n * @returns The {@link Schema | schema} created.\n */\n // eslint-disable-next-line @typescript-eslint/ban-types\n $extends<NewSource, NewTarget = {}>(\n newSchema: DeepPartial<Schema<Source & NewSource, Target>> &\n Schema<Source & NewSource, NewTarget>\n ): MutableSchema<Source & NewSource, Target & NewTarget>;\n /**\n * Returns a string representing of the {@link Schema | schema}.\n *\n * @param includeInternalMethods - Flag to include in the string representation\n * the internal methods. Disabled by default.\n * @returns The string representation.\n */\n toString(includeInternalMethods?: boolean): string;\n};\n/**\n * The possible transformers to apply to the target key.\n *\n * @param Source - The source object.\n * @param Target - The target object.\n * @param TargetKey - The target key to apply the transformation.\n * @public\n */\nexport type SchemaTransformer<Source, Target, TargetKey extends keyof Target> =\n | PathTransformer<Source, Target[TargetKey]>\n | FunctionTransformer<Source, Target[TargetKey]>\n | SubSchemaTransformer<Source, Target[TargetKey]>\n | Schema<Source, Exclude<Target[TargetKey], AnyFunction | Primitive>>;\n\n/**\n * A function with the source object and mapper context as parameters that returns the value of a\n * target's property.\n *\n * @param Source - The source object.\n * @param Target - The target object.\n * @example\n * ```typescript\n * interface Source {\n * id: string;\n * count: number;\n * }\n *\n * interface Target {\n * title: string;\n * hits: number;\n * }\n *\n * const subSchema: Schema<Source, Target> = {\n * title: 'id',\n * hits: 'count'\n * };\n *\n * const wrongSubSchema: Schema<Source, Target> = {\n * // @ts-expect-error\n * title: 'count', // This raises a TS error\n * hits: 'count'\n * };\n * ```\n * @public\n */\nexport type PathTransformer<Source, Target> = ExtractPathByType<Source, Target>;\n\n/**\n * A function with the source object and mapper context as parameters that returns the value of a\n * target's property.\n *\n * @param Source - The source object.\n * @param Target - The target object.\n * @example\n * ```typescript\n * interface Source {\n * id: string;\n * count: number;\n * }\n *\n * interface Target {\n * title: string;\n * hits: number;\n * }\n *\n * const subSchema: Schema<Source, Target> = {\n * title: source => source.id,\n * hits: (source, context) => context.requestParameters.query === 'example'\n * ? source.count\n * : 0\n * };\n * ```\n * @public\n */\nexport type FunctionTransformer<Source, Target> = (\n source: Source,\n context?: MapperContext\n) => Target;\n\n/**\n * An object containing a schema narrowing its source object based on the given path.\n *\n * @param Source - The source object.\n * @param Target - The target object.\n * @example\n * ```typescript\n * interface Source {\n * id: string;\n * facets: {\n * name: string;\n * count: number;\n * };\n * images: string[];\n * }\n *\n * interface Target {\n * identifier: string;\n * filters: {\n * id: string;\n * numFound: number;\n * };\n * img: string[]\n * }\n *\n * const subSchema: SubSchemaTransformer<Source, Target['filters']> = {\n * $path: 'facets',\n * $subSchema: {\n * id: 'name',\n * numFound: 'count'\n * }\n * };\n * ```\n * @public\n */\nexport type SubSchemaTransformer<Source, Target> = {\n [Path in ExtractPath<Source>]: {\n $context?: MapperContext;\n $path: Path;\n $subSchema:\n | SubSchema<Source, Target, Path>\n | '$self'\n | ((source: Source) => SubSchema<Source, Target, Path>);\n };\n}[ExtractPath<Source>];\n\n/**\n * A {@link Schema | schema} that will be applied to an inner path of an object.\n *\n * @param Source - The source object.\n * @param Target - The target object.\n * @param Path - The path where the schema will be applied.\n * @public\n */\nexport type SubSchema<Source, Target, Path extends ExtractPath<Source>> = ExtractType<\n Source,\n Path\n> extends (infer SourceArrayType)[]\n ? Target extends (infer TargetArrayType)[]\n ? Schema<SourceArrayType, TargetArrayType>\n : never\n : Target extends []\n ? never\n : Schema<ExtractType<Source, Path>, Target>;\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/schemas/types.ts"],"names":[],"mappings":"","sourcesContent":["import {\n AnyFunction,\n DeepPartial,\n ExtractPath,\n ExtractPathByType,\n ExtractType,\n Primitive\n} from '@empathyco/x-utils';\nimport { MapperContext } from '../mappers/types';\n\n// TODO: EX-5830 - Enhance Schema type to support optional properties in the Source object\n/**\n * Template object to transform a source object to a target object.\n *\n * @remarks The source object must not have optional properties, as it could cause infinite\n * type instantiations.\n * @param Source - The source object.\n * @param Target - The target object.\n * @example\n * ```typescript\n * interface Source {\n * id: string;\n * price: {\n * max: number;\n * min: number;\n * };\n * images: string[];\n * }\n *\n * interface Target {\n * identifier: string;\n * maxPrice: number;\n * minPrice: number;\n * img: string[]\n * }\n *\n * const schema: Schema<Source, Target> = {\n * identifier: 'id',\n * maxPrice: 'price.max',\n * minPrice: ({ price }) => Math.min(0, price.min),\n * img: 'images'\n * };\n * ```\n * @public\n */\nexport type Schema<Source = any, Target = any> = {\n [TargetKey in keyof Target]: SchemaTransformer<Source, Target, TargetKey>;\n};\n\n/**\n * A {@link Schema | schema} with extended functionality to: completely replace\n * the original schema, partially override it or create a new one.\n *\n * @param OriginalSchema - The {@link Schema | schema} that will be mutable.\n * @public\n */\nexport type MutableSchema<Source, Target> = Schema<Source, Target> & {\n /**\n * Replaces all usages of the original {@link Schema | schema} with the given one.\n *\n * @param newSchema - The {@link Schema | schema} to use instead of the original one.\n * @returns The new {@link Schema | schema} that will be used.\n */\n $replace<NewSource, NewTarget>(\n newSchema: Schema<NewSource, NewTarget>\n ): MutableSchema<NewSource, NewTarget>;\n /**\n * Merges the original {@link Schema | schema} with the given one.\n *\n * @param newSchema - The {@link Schema | schema} to use to merge with the original one.\n * @returns The {@link Schema | schema} returned by the merge.\n */\n // eslint-disable-next-line @typescript-eslint/ban-types\n $override<NewSource, NewTarget = {}>(\n newSchema: DeepPartial<Schema<Source & NewSource, Target>> &\n Schema<Source & NewSource, NewTarget>\n ): MutableSchema<Source & NewSource, Target & NewTarget>;\n /**\n * Creates a new {@link Schema | schema} using the original one as starting point.\n * The original {@link Schema | schema} will remain unchanged.\n *\n * @param newSchema - The {@link Schema | schema} to be used to extend the original one.\n * Both schema's Target and Source can be unique or also be extending from another one.\n * @returns The {@link Schema | schema} created.\n */\n $extends<NewSource extends Source, NewTarget extends Target>(\n newSchema: DeepPartial<Schema<Source & NewSource, Target>> &\n Schema<Source & NewSource, Omit<NewTarget, keyof Target>>\n ): MutableSchema<Source & NewSource, Target & NewTarget>;\n // eslint-disable-next-line @typescript-eslint/ban-types\n $extends<NewSource, NewTarget = {}>(\n newSchema: DeepPartial<Schema<Source & NewSource, Target>> &\n Schema<Source & NewSource, NewTarget>\n ): MutableSchema<Source & NewSource, Target & NewTarget>;\n /**\n * Returns a string representing of the {@link Schema | schema}.\n *\n * @param includeInternalMethods - Flag to include in the string representation\n * the internal methods. Disabled by default.\n * @returns The string representation.\n */\n toString(includeInternalMethods?: boolean): string;\n};\n/**\n * The possible transformers to apply to the target key.\n *\n * @param Source - The source object.\n * @param Target - The target object.\n * @param TargetKey - The target key to apply the transformation.\n * @public\n */\nexport type SchemaTransformer<Source, Target, TargetKey extends keyof Target> =\n | PathTransformer<Source, Target[TargetKey]>\n | FunctionTransformer<Source, Target[TargetKey]>\n | SubSchemaTransformer<Source, Target[TargetKey]>\n | Schema<Source, Exclude<Target[TargetKey], AnyFunction | Primitive>>;\n\n/**\n * A function with the source object and mapper context as parameters that returns the value of a\n * target's property.\n *\n * @param Source - The source object.\n * @param Target - The target object.\n * @example\n * ```typescript\n * interface Source {\n * id: string;\n * count: number;\n * }\n *\n * interface Target {\n * title: string;\n * hits: number;\n * }\n *\n * const subSchema: Schema<Source, Target> = {\n * title: 'id',\n * hits: 'count'\n * };\n *\n * const wrongSubSchema: Schema<Source, Target> = {\n * // @ts-expect-error\n * title: 'count', // This raises a TS error\n * hits: 'count'\n * };\n * ```\n * @public\n */\nexport type PathTransformer<Source, Target> = ExtractPathByType<Source, Target>;\n\n/**\n * A function with the source object and mapper context as parameters that returns the value of a\n * target's property.\n *\n * @param Source - The source object.\n * @param Target - The target object.\n * @example\n * ```typescript\n * interface Source {\n * id: string;\n * count: number;\n * }\n *\n * interface Target {\n * title: string;\n * hits: number;\n * }\n *\n * const subSchema: Schema<Source, Target> = {\n * title: source => source.id,\n * hits: (source, context) => context.requestParameters.query === 'example'\n * ? source.count\n * : 0\n * };\n * ```\n * @public\n */\nexport type FunctionTransformer<Source, Target> = (\n source: Source,\n context?: MapperContext\n) => Target;\n\n/**\n * An object containing a schema narrowing its source object based on the given path.\n *\n * @param Source - The source object.\n * @param Target - The target object.\n * @example\n * ```typescript\n * interface Source {\n * id: string;\n * facets: {\n * name: string;\n * count: number;\n * };\n * images: string[];\n * }\n *\n * interface Target {\n * identifier: string;\n * filters: {\n * id: string;\n * numFound: number;\n * };\n * img: string[]\n * }\n *\n * const subSchema: SubSchemaTransformer<Source, Target['filters']> = {\n * $path: 'facets',\n * $subSchema: {\n * id: 'name',\n * numFound: 'count'\n * }\n * };\n * ```\n * @public\n */\nexport type SubSchemaTransformer<Source, Target> = {\n [Path in ExtractPath<Source>]: {\n $context?: MapperContext;\n $path: Path;\n $subSchema:\n | SubSchema<Source, Target, Path>\n | '$self'\n | ((source: Source) => SubSchema<Source, Target, Path>);\n };\n}[ExtractPath<Source>];\n\n/**\n * A {@link Schema | schema} that will be applied to an inner path of an object.\n *\n * @param Source - The source object.\n * @param Target - The target object.\n * @param Path - The path where the schema will be applied.\n * @public\n */\nexport type SubSchema<Source, Target, Path extends ExtractPath<Source>> = ExtractType<\n Source,\n Path\n> extends (infer SourceArrayType)[]\n ? Target extends (infer TargetArrayType)[]\n ? Schema<SourceArrayType, TargetArrayType>\n : never\n : Target extends []\n ? never\n : Schema<ExtractType<Source, Path>, Target>;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/schemas/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAGnE;;GAEG;AACH,MAAM,6BAA6B,GAAa,CAAC,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;AAElG;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CACjC,MAA8B;IAE9B,OAAO;QACL,GAAG,MAAM;QACT,QAAQ,CAAC,SAAS;YAChB,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE;gBAClB,IAAI,gBAAgB,CAAC,GAAa,CAAC,EAAE;oBACnC,OAAO;iBACR;gBACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;YACnB,CAAC,CAAC,CAAC;YACH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YAC/B;+EACmE;YACnE,OAAO,IAAW,CAAC;QACrB,CAAC;QACD,SAAS,CAAC,SAAS;YACjB,OAAO,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACpC,CAAC;QACD,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/schemas/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAGnE;;GAEG;AACH,MAAM,6BAA6B,GAAa,CAAC,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;AAElG;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CACjC,MAA8B;IAE9B,OAAO;QACL,GAAG,MAAM;QACT,QAAQ,CAAC,SAAS;YAChB,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE;gBAClB,IAAI,gBAAgB,CAAC,GAAa,CAAC,EAAE;oBACnC,OAAO;iBACR;gBACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;YACnB,CAAC,CAAC,CAAC;YACH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YAC/B;+EACmE;YACnE,OAAO,IAAW,CAAC;QACrB,CAAC;QACD,SAAS,CAAC,SAAS;YACjB,OAAO,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACpC,CAAC;QACD,QAAQ,CAAC,SAAkB;YACzB,OAAO,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QACxC,CAAC;QACD,QAAQ,CAAC,sBAAsB,GAAG,KAAK;YACrC,OAAO,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,sBAAsB,CAAC,CAAC;QACnD,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,6BAA6B,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACtD,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,SAAS,CAChB,IAA6B,EAC7B,sBAA+B,EAC/B,IAAI,GAAG,CAAC;IAER,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,OAAO,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;QAC3B,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE;YACnB,MAAM,IAAI,GAAG,WAAW,GAAG,GAAG,QAAQ,SAAS,CAC7C,KAAK,EACL,sBAAsB,EACtB,EAAE,IAAI,CACP,GAAG,WAAW,MAAM,CAAC;SACvB;aAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,sBAAsB,EAAE;YACjF,4EAA4E;YAC5E,MAAM,IAAI,GAAG,WAAW,GAAG,GAAG,KAAK,KAAK,KAAK,CAAC;SAC/C;IACH,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import { deepMerge } from '@empathyco/x-deep-merge';\nimport { forEach, isFunction, isObject } from '@empathyco/x-utils';\nimport { MutableSchema, Schema } from './types';\n\n/**\n * Collection of internal method names for {@link MutableSchema | mutable schemas}.\n */\nconst mutableSchemasInternalMethods: string[] = ['$replace', '$override', '$extends', 'toString'];\n\n/**\n * Creates a {@link MutableSchema | mutable schema } version of a given {@link Schema | schema}.\n *\n * @param schema - The {@link Schema | schema} to make mutable.\n *\n * @returns A {@link MutableSchema | mutable schema} version of the given {@link Schema | schema}.\n *\n * @public\n */\nexport function createMutableSchema<Source, Target>(\n schema: Schema<Source, Target>\n): MutableSchema<Source, Target> {\n return {\n ...schema,\n $replace(newSchema) {\n forEach(this, key => {\n if (isInternalMethod(key as string)) {\n return;\n }\n delete this[key];\n });\n Object.assign(this, newSchema);\n /* We are replacing the schema with a completely new schema , so it makes sense that TS\n complains that the old schema and the new one are not the same. */\n return this as any;\n },\n $override(newSchema) {\n return deepMerge(this, newSchema);\n },\n $extends(newSchema: unknown) {\n return deepMerge({}, this, newSchema);\n },\n toString(includeInternalMethods = false) {\n return serialize(this, !!includeInternalMethods);\n }\n };\n}\n\n/**\n * Checks if the given key is a {@link MutableSchema | mutableSchema} method.\n *\n * @param name - The key to check.\n *\n * @returns True if it is a {@link MutableSchema | mutableSchema} method,\n * false otherwise.\n *\n * @public\n */\nexport function isInternalMethod(name: string): boolean {\n return mutableSchemasInternalMethods.includes(name);\n}\n\n/**\n * Returns a string representing of the given object.\n *\n * @param data - The object to get the string representation from.\n * @param includeInternalMethods - Flag to include in the string representation\n * the internal methods. Disabled by default.\n * @param deep - The level of indentation.\n * @returns The string representation.\n */\nfunction serialize(\n data: Record<string, unknown>,\n includeInternalMethods: boolean,\n deep = 0\n): string {\n const indentation = ' '.repeat(deep);\n let output = '';\n forEach(data, (key, value) => {\n if (isObject(value)) {\n output += `${indentation}${key}: {\\n${serialize(\n value,\n includeInternalMethods,\n ++deep\n )}${indentation}},\\n`;\n } else if (!isFunction(value) || !isInternalMethod(key) || includeInternalMethods) {\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n output += `${indentation}${key}: ${value},\\n`;\n }\n });\n return output;\n}\n"]}
|
|
@@ -64,8 +64,10 @@ export declare type MutableSchema<Source, Target> = Schema<Source, Target> & {
|
|
|
64
64
|
* The original {@link Schema | schema} will remain unchanged.
|
|
65
65
|
*
|
|
66
66
|
* @param newSchema - The {@link Schema | schema} to be used to extend the original one.
|
|
67
|
+
* Both schema's Target and Source can be unique or also be extending from another one.
|
|
67
68
|
* @returns The {@link Schema | schema} created.
|
|
68
69
|
*/
|
|
70
|
+
$extends<NewSource extends Source, NewTarget extends Target>(newSchema: DeepPartial<Schema<Source & NewSource, Target>> & Schema<Source & NewSource, Omit<NewTarget, keyof Target>>): MutableSchema<Source & NewSource, Target & NewTarget>;
|
|
69
71
|
$extends<NewSource, NewTarget = {}>(newSchema: DeepPartial<Schema<Source & NewSource, Target>> & Schema<Source & NewSource, NewTarget>): MutableSchema<Source & NewSource, Target & NewTarget>;
|
|
70
72
|
/**
|
|
71
73
|
* Returns a string representing of the {@link Schema | schema}.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@empathyco/x-adapter",
|
|
3
|
-
"version": "8.0.0-alpha.
|
|
3
|
+
"version": "8.0.0-alpha.19",
|
|
4
4
|
"description": "A utils library to create a client for any API",
|
|
5
5
|
"author": "Empathy Systems Corporation S.L.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
"prepublishOnly": "npm run build"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@empathyco/x-deep-merge": "^1.3.0-alpha.
|
|
39
|
-
"@empathyco/x-utils": "^1.0.0-alpha.
|
|
40
|
-
"tslib": "~2.
|
|
38
|
+
"@empathyco/x-deep-merge": "^1.3.0-alpha.27",
|
|
39
|
+
"@empathyco/x-utils": "^1.0.0-alpha.13",
|
|
40
|
+
"tslib": "~2.4.1"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/jest": "~27.0.3",
|
|
@@ -50,5 +50,5 @@
|
|
|
50
50
|
"publishConfig": {
|
|
51
51
|
"access": "public"
|
|
52
52
|
},
|
|
53
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "b5640ccccd296584a4775a8db625f9039b6025e9"
|
|
54
54
|
}
|