@clairejs/server 3.28.13 → 3.28.15

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
@@ -1,5 +1,13 @@
1
1
  ## Change Log
2
2
 
3
+ #### 3.28.15
4
+
5
+ - fix uri mapper for expanded & has many fields
6
+
7
+ #### 3.28.14
8
+
9
+ - implement @Expand and paralel run in getMany
10
+
3
11
  #### 3.28.13
4
12
 
5
13
  - fix update records handle undefined result
@@ -202,7 +202,8 @@ export class ModelRepository extends AbstractRepository {
202
202
  const value = record[field.name];
203
203
  if (!value)
204
204
  continue;
205
- if (field.elementDto && value) {
205
+ //-- expand and hasMany fields are already mapped using the repo get many
206
+ if (field.elementDto && value && !field.expand && !field.hasMany) {
206
207
  mapRecords(field.vectorProps ? value : [value], field.elementDto);
207
208
  }
208
209
  else if (field.uriMapper) {
@@ -572,8 +573,13 @@ export class ModelRepository extends AbstractRepository {
572
573
  //-- check if there is any multi-local fields in projection
573
574
  const multiLocaleFields = this.modelMetadata.fields.filter((f) => f.isMultiLocale && (!queries?.projection || queries.projection.includes(f.name)));
574
575
  const localeOfFields = this.modelMetadata.fields.filter((f) => multiLocaleFields.find((locale) => locale.name === f.multiLocaleColumn));
576
+ const expandFields = this.modelMetadata.fields.filter((f) => f.expand && (!queries?.projection || queries.projection.includes(f.name)));
575
577
  const finalProjection = queries?.projection && [
576
- ...queries.projection.filter((fieldName) => !this.modelMetadata.fields.find((f) => f.name === fieldName && !!f.hasMany)),
578
+ ...queries.projection.filter((fieldName) => !this.modelMetadata.fields.find((f) => f.name === fieldName && (!!f.hasMany || !!f.expand))),
579
+ //-- include FK columns for expand fields so we can resolve them
580
+ ...expandFields
581
+ .map((f) => f.expand.column)
582
+ .filter((col) => !queries.projection.includes(col)),
577
583
  ...localeOfFields.map((f) => f.name),
578
584
  ];
579
585
  const result = await this.db.use(this.model, tx).getMany(conditions.length ? { _and: conditions } : {}, {
@@ -590,65 +596,93 @@ export class ModelRepository extends AbstractRepository {
590
596
  .flatMap((ids) => ids)
591
597
  .filter((id) => id);
592
598
  const systemLocale = getSystemLocale();
593
- const translations = !allLocaleEntries.length
594
- ? []
599
+ //-- fetch translations, has many, and expand fields in parallel
600
+ const hasManyFields = this.modelMetadata.fields.filter((f) => f.hasMany && (!queries?.projection || queries.projection.includes(f.name)));
601
+ const translationsPromise = !allLocaleEntries.length
602
+ ? Promise.resolve([])
595
603
  : !queries?.locale
596
604
  ? //-- if locale is not specified then get translation for all locales
597
- await this.db.use(LocaleTranslation, tx).getRecords({
605
+ this.db.use(LocaleTranslation, tx).getRecords({
598
606
  _in: { entryId: allLocaleEntries },
599
607
  }, { projection: ["entryId", "localeCode", "translation"] })
600
608
  : //-- if locale is specified then get only the translation of that locale
601
609
  queries.locale.toLowerCase() !== systemLocale
602
- ? await this.db.use(LocaleTranslation, tx).getRecords({
610
+ ? this.db.use(LocaleTranslation, tx).getRecords({
603
611
  _in: { entryId: allLocaleEntries },
604
612
  _eq: { localeCode: queries.locale },
605
613
  }, { projection: ["entryId", "localeCode", "translation"] })
606
614
  : //-- locale is system locale, no need to fetch translation
607
- [];
608
- for (const record of result.records) {
609
- for (const field of localeOfFields) {
610
- //-- map back translation
611
- if (!queries?.locale) {
612
- //-- map as object
613
- const fieldTranslations = translations
614
- .filter((t) => t.entryId === record[field.name])
615
- .map((t) => [t.localeCode, t.translation]);
616
- if (systemLocale) {
617
- fieldTranslations.push([systemLocale, record[field.multiLocaleColumn]]);
615
+ Promise.resolve([]);
616
+ await Promise.all([
617
+ //-- translations
618
+ translationsPromise.then((translations) => {
619
+ for (const record of result.records) {
620
+ for (const field of localeOfFields) {
621
+ //-- map back translation
622
+ if (!queries?.locale) {
623
+ //-- map as object
624
+ const fieldTranslations = translations
625
+ .filter((t) => t.entryId === record[field.name])
626
+ .map((t) => [t.localeCode, t.translation]);
627
+ if (systemLocale) {
628
+ fieldTranslations.push([systemLocale, record[field.multiLocaleColumn]]);
629
+ }
630
+ record[field.name] = Object.fromEntries(fieldTranslations);
631
+ }
632
+ else {
633
+ //-- replace value
634
+ const translation = translations.find((t) => t.localeCode === queries.locale && t.entryId === record[field.name]);
635
+ if (translation) {
636
+ record[field.multiLocaleColumn] = translation.translation;
637
+ }
638
+ }
618
639
  }
619
- record[field.name] = Object.fromEntries(fieldTranslations);
620
640
  }
621
- else {
622
- //-- replace value
623
- const translation = translations.find((t) => t.localeCode === queries.locale && t.entryId === record[field.name]);
624
- if (translation) {
625
- record[field.multiLocaleColumn] = translation.translation;
626
- }
641
+ }),
642
+ //-- has many
643
+ ...hasManyFields.map(async (field) => {
644
+ const model = getModelById(field.hasMany.relationDto.id);
645
+ if (!model) {
646
+ throw Errors.NOT_FOUND(`Model not found by id: ${field.hasMany.relationDto.id}`);
627
647
  }
628
- }
629
- }
630
- //-- get has many fields
631
- for (const field of this.modelMetadata.fields) {
632
- if (!field.hasMany || (queries?.projection && !queries.projection.includes(field.name))) {
633
- continue;
634
- }
635
- const model = getModelById(field.hasMany.relationDto.id);
636
- if (!model) {
637
- throw Errors.NOT_FOUND(`Model not found by id: ${field.hasMany.relationDto.id}`);
638
- }
639
- const service = new ModelRepository(model, this.db);
640
- const innerRecords = !recordIds.length
641
- ? { records: [] }
642
- : await service.getMany({
643
- queries: { fields: { [field.hasMany.column]: recordIds }, limit: field.hasMany.single ? 1 : 0 },
644
- tx,
645
- });
646
- //-- filter corresponding inner records for each master record
647
- for (const record of result.records) {
648
- const finalRecords = innerRecords.records.filter((r) => r[field.hasMany.column] === record.id);
649
- record[field.name] = (field.hasMany.single ? finalRecords[0] : finalRecords);
650
- }
651
- }
648
+ const service = new ModelRepository(model, this.db);
649
+ const innerRecords = !recordIds.length
650
+ ? { records: [] }
651
+ : await service.getMany({
652
+ queries: { fields: { [field.hasMany.column]: recordIds }, limit: field.hasMany.single ? 1 : 0 },
653
+ tx,
654
+ });
655
+ //-- filter corresponding inner records for each master record
656
+ for (const record of result.records) {
657
+ const finalRecords = innerRecords.records.filter((r) => r[field.hasMany.column] === record.id);
658
+ record[field.name] = (field.hasMany.single ? finalRecords[0] : finalRecords);
659
+ }
660
+ }),
661
+ //-- expand
662
+ ...expandFields.map(async (field) => {
663
+ const model = getModelById(field.expand.relationDto.id);
664
+ if (!model) {
665
+ throw Errors.NOT_FOUND(`Model not found by id: ${field.expand.relationDto.id}`);
666
+ }
667
+ //-- collect unique FK values from current records
668
+ const fkValues = result.records
669
+ .map((r) => r[field.expand.column])
670
+ .filter((v) => v !== undefined && v !== null)
671
+ .reduce(uniqueReducer, []);
672
+ const service = new ModelRepository(model, this.db);
673
+ const expandedRecords = !fkValues.length
674
+ ? { records: [] }
675
+ : await service.getMany({
676
+ queries: { fields: { id: fkValues } },
677
+ tx,
678
+ });
679
+ //-- assign expanded record to each master record
680
+ for (const record of result.records) {
681
+ const fkValue = record[field.expand.column];
682
+ record[field.name] = expandedRecords.records.find((r) => r.id === fkValue);
683
+ }
684
+ }),
685
+ ]);
652
686
  await this.beforeReturning(result.records);
653
687
  return {
654
688
  total: result.total,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clairejs/server",
3
- "version": "3.28.13",
3
+ "version": "3.28.15",
4
4
  "description": "Claire server NodeJs framework written in Typescript.",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
@@ -35,8 +35,8 @@
35
35
  },
36
36
  "peerDependencies": {
37
37
  "@clairejs/client": "^3.5.1",
38
- "@clairejs/core": "^3.9.4",
39
- "@clairejs/orm": "^3.17.2"
38
+ "@clairejs/core": "^3.9.5",
39
+ "@clairejs/orm": "^3.19.11"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/cookie-parser": "^1.4.3",