Skip to content

Commit e89e18f

Browse files
V16: Item and Detail Base Repository should use correct typings for return types (#19447)
* fix: add a catcher to most `asPromise` for stores to prevent cascading errors * fix: remove conditional instances - they should be able to be undefined * fix: check for missing store and extract UmbProblemDetails * fix: only append data if no error * fix: adds error handling to missing stores and to extract the ProblemDetails object * revert commit * fix: ignore errors completely instead of unsetting stores * revert commit * chore: cleanup imports * fix: do not unset store * stop observation in a proper way * stop observation of for document-user-permissions * check for manager twice * save action * save action optional * fix: ensure the right types are used for base stores --------- Co-authored-by: Niels Lyngsø <[email protected]>
1 parent cfcb708 commit e89e18f

File tree

9 files changed

+45
-62
lines changed

9 files changed

+45
-62
lines changed

src/Umbraco.Web.UI.Client/src/packages/content/content-type/structure/content-type-structure-manager.class.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ export class UmbContentTypeStructureManager<
175175
* @param {string} unique - The unique of the ContentType to load.
176176
* @returns {Promise} - Promise resolved
177177
*/
178-
public async loadType(unique: string): Promise<UmbRepositoryResponseWithAsObservable<T>> {
178+
public async loadType(unique: string): Promise<UmbRepositoryResponseWithAsObservable<T | undefined>> {
179179
if (this.#ownerContentTypeUnique === unique) {
180180
// Its the same, but we do not know if its done loading jet, so we will wait for the load promise to finish. [NL]
181181
await this.#init;

src/Umbraco.Web.UI.Client/src/packages/core/repository/detail/detail-repository-base.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export abstract class UmbDetailRepositoryBase<
6060
* @returns {*}
6161
* @memberof UmbDetailRepositoryBase
6262
*/
63-
async requestByUnique(unique: string): Promise<UmbRepositoryResponseWithAsObservable<DetailModelType>> {
63+
async requestByUnique(unique: string): Promise<UmbRepositoryResponseWithAsObservable<DetailModelType | undefined>> {
6464
if (!unique) throw new Error('Unique is missing');
6565
await this.#init;
6666

@@ -73,7 +73,7 @@ export abstract class UmbDetailRepositoryBase<
7373
return {
7474
data,
7575
error,
76-
asObservable: () => this.#detailStore!.byUnique(unique),
76+
asObservable: () => this.#detailStore?.byUnique(unique),
7777
};
7878
}
7979

src/Umbraco.Web.UI.Client/src/packages/core/repository/detail/read/read-detail-repository.interface.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
33
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
44

55
export interface UmbReadDetailRepository<DetailModelType> extends UmbApi {
6-
requestByUnique(unique: string): Promise<UmbRepositoryResponseWithAsObservable<DetailModelType>>;
6+
requestByUnique(unique: string): Promise<UmbRepositoryResponseWithAsObservable<DetailModelType | undefined>>;
77
byUnique(unique: string): Promise<Observable<DetailModelType | undefined>>;
88
}

src/Umbraco.Web.UI.Client/src/packages/core/repository/item/item-repository-base.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,18 @@ export class UmbItemRepositoryBase<ItemType extends { unique: string }>
4141
try {
4242
await this._init;
4343
} catch {
44-
return {};
44+
return {
45+
asObservable: () => undefined,
46+
};
4547
}
4648

4749
const { data, error } = await this.#itemSource.getItems(uniques);
4850

49-
if (!this._itemStore) {
50-
// If store is gone, then we are most likely in a disassembled state.
51-
return {};
52-
}
53-
5451
if (data) {
55-
this._itemStore.appendItems(data);
52+
this._itemStore?.appendItems(data);
5653
}
5754

58-
// TODO: Fix the type of error, it should be UmbApiError, but currently it is any.
59-
return { data, error: error as any, asObservable: () => this._itemStore!.items(uniques) };
55+
return { data, error, asObservable: () => this._itemStore?.items(uniques) };
6056
}
6157

6258
/**
Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
1+
import type { UmbRepositoryResponseWithAsObservable } from '../types.js';
12
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
23
import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
3-
import type { UmbProblemDetails } from '@umbraco-cms/backoffice/resources';
44

55
export interface UmbItemRepository<ItemType> extends UmbApi {
6-
requestItems: (uniques: string[]) => Promise<{
7-
data?: Array<ItemType> | undefined;
8-
error?: UmbProblemDetails | undefined;
9-
asObservable?: () => Observable<Array<ItemType>>;
10-
}>;
6+
requestItems: (uniques: string[]) => Promise<UmbRepositoryResponseWithAsObservable<ItemType[] | undefined>>;
117
items: (uniques: string[]) => Promise<Observable<Array<ItemType>> | undefined>;
128
}

src/Umbraco.Web.UI.Client/src/packages/core/repository/repository-items.manager.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,8 @@ export class UmbRepositoryItemsManager<ItemType extends { unique: string }> exte
250250
}
251251
}
252252

253-
#sortByUniques(data: Array<ItemType>): Array<ItemType> {
253+
#sortByUniques(data?: Array<ItemType>): Array<ItemType> {
254+
if (!data) return [];
254255
const uniques = this.getUniques();
255256
return [...data].sort((a, b) => {
256257
const aIndex = uniques.indexOf(this.#getUnique(a) ?? '');

src/Umbraco.Web.UI.Client/src/packages/core/repository/types.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,13 @@ export interface UmbRepositoryResponse<T> extends UmbDataSourceResponse<T> {}
1111
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
1212
export interface UmbRepositoryErrorResponse extends UmbDataSourceErrorResponse {}
1313

14-
export interface UmbRepositoryResponseWithAsObservable<T> extends UmbRepositoryResponse<T> {
15-
asObservable: () => Observable<T | undefined>;
14+
/**
15+
* Interface for a repository that can return a paged model.
16+
* @template T - The type of items in the paged model.
17+
* @template T$ - The type of items returned by the asObservable method, defaults to T. You should only use this if you want to return a different type from the asObservable method.
18+
*/
19+
export interface UmbRepositoryResponseWithAsObservable<T, T$ = T> extends UmbRepositoryResponse<T> {
20+
asObservable: () => Observable<T$> | undefined;
1621
}
1722

1823
export type * from './data-mapper/mapping/types.js';

src/Umbraco.Web.UI.Client/src/packages/core/tree/data/tree-repository-base.ts

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@ import type {
77
UmbTreeChildrenOfRequestArgs,
88
UmbTreeRootItemsRequestArgs,
99
} from './types.js';
10-
import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository';
10+
import { UmbRepositoryBase, type UmbRepositoryResponse } from '@umbraco-cms/backoffice/repository';
1111
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
1212
import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
1313
import type { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
14-
import type { UmbProblemDetails } from '@umbraco-cms/backoffice/resources';
1514
import { of } from '@umbraco-cms/backoffice/external/rxjs';
1615

1716
/**
@@ -74,7 +73,7 @@ export abstract class UmbTreeRepositoryBase<
7473
* @returns {*}
7574
* @memberof UmbTreeRepositoryBase
7675
*/
77-
abstract requestTreeRoot(): Promise<{ data?: TreeRootType; error?: UmbProblemDetails }>;
76+
abstract requestTreeRoot(): Promise<UmbRepositoryResponse<TreeRootType>>;
7877

7978
/**
8079
* Requests root items of a tree
@@ -89,15 +88,16 @@ export abstract class UmbTreeRepositoryBase<
8988

9089
if (!this._treeStore) {
9190
// If the tree store is not available, then we most likely are in a destructed setting.
92-
return {};
91+
return {
92+
asObservable: () => undefined,
93+
};
9394
}
9495

9596
if (data) {
9697
this._treeStore.appendItems(data.items);
9798
}
9899

99-
// TODO: Fix the type of error, it should be UmbApiError, but currently it is any.
100-
return { data, error: error as any, asObservable: () => this._treeStore!.rootItems };
100+
return { data, error, asObservable: () => this._treeStore?.rootItems };
101101
}
102102

103103
/**
@@ -117,15 +117,16 @@ export abstract class UmbTreeRepositoryBase<
117117

118118
if (!this._treeStore) {
119119
// If the tree store is not available, then we most likely are in a destructed setting.
120-
return {};
120+
return {
121+
asObservable: () => undefined,
122+
};
121123
}
122124

123125
if (data) {
124126
this._treeStore.appendItems(data.items);
125127
}
126128

127-
// TODO: Fix the type of error, it should be UmbApiError, but currently it is any.
128-
return { data, error: error as any, asObservable: () => this._treeStore!.childrenOf(args.parent.unique) };
129+
return { data, error, asObservable: () => this._treeStore?.childrenOf(args.parent.unique) };
129130
}
130131

131132
/**
@@ -153,12 +154,7 @@ export abstract class UmbTreeRepositoryBase<
153154
async rootTreeItems() {
154155
await this._init;
155156

156-
if (!this._treeStore) {
157-
// If the tree store is not available, then we most likely are in a destructed setting.
158-
return of([]);
159-
}
160-
161-
return this._treeStore.rootItems;
157+
return this._treeStore?.rootItems ?? of([]);
162158
}
163159

164160
/**
@@ -171,11 +167,6 @@ export abstract class UmbTreeRepositoryBase<
171167
if (parentUnique === undefined) throw new Error('Parent unique is missing');
172168
await this._init;
173169

174-
if (!this._treeStore) {
175-
// If the tree store is not available, then we most likely are in a destructed setting.
176-
return of([]);
177-
}
178-
179-
return this._treeStore.childrenOf(parentUnique);
170+
return this._treeStore?.childrenOf(parentUnique) ?? of([]);
180171
}
181172
}

src/Umbraco.Web.UI.Client/src/packages/core/tree/data/tree-repository.interface.ts

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@ import type {
44
UmbTreeAncestorsOfRequestArgs,
55
UmbTreeRootItemsRequestArgs,
66
} from './types.js';
7-
import type { UmbPagedModel } from '@umbraco-cms/backoffice/repository';
7+
import type {
8+
UmbPagedModel,
9+
UmbRepositoryResponse,
10+
UmbRepositoryResponseWithAsObservable,
11+
} from '@umbraco-cms/backoffice/repository';
812
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
913
import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
10-
import type { UmbProblemDetails } from '@umbraco-cms/backoffice/resources';
1114

1215
/**
1316
* Interface for a tree repository.
@@ -27,41 +30,32 @@ export interface UmbTreeRepository<
2730
* Requests the root of the tree.
2831
* @memberof UmbTreeRepository
2932
*/
30-
requestTreeRoot: () => Promise<{
31-
data?: TreeRootType;
32-
error?: UmbProblemDetails;
33-
}>;
33+
requestTreeRoot: () => Promise<UmbRepositoryResponse<TreeRootType>>;
3434

3535
/**
3636
* Requests the root items of the tree.
3737
* @param {UmbTreeRootItemsRequestArgs} args
3838
* @memberof UmbTreeRepository
3939
*/
40-
requestTreeRootItems: (args: TreeRootItemsRequestArgsType) => Promise<{
41-
data?: UmbPagedModel<TreeItemType>;
42-
error?: UmbProblemDetails;
43-
asObservable?: () => Observable<TreeItemType[]>;
44-
}>;
40+
requestTreeRootItems: (
41+
args: TreeRootItemsRequestArgsType,
42+
) => Promise<UmbRepositoryResponseWithAsObservable<UmbPagedModel<TreeItemType>, TreeItemType[]>>;
4543

4644
/**
4745
* Requests the children of the given parent item.
4846
* @param {UmbTreeChildrenOfRequestArgs} args
4947
* @memberof UmbTreeRepository
5048
*/
51-
requestTreeItemsOf: (args: TreeChildrenOfRequestArgsType) => Promise<{
52-
data?: UmbPagedModel<TreeItemType>;
53-
error?: UmbProblemDetails;
54-
asObservable?: () => Observable<TreeItemType[]>;
55-
}>;
49+
requestTreeItemsOf: (
50+
args: TreeChildrenOfRequestArgsType,
51+
) => Promise<UmbRepositoryResponseWithAsObservable<UmbPagedModel<TreeItemType>, TreeItemType[]>>;
5652

5753
/**
5854
* Requests the ancestors of the given item.
5955
* @param {UmbTreeAncestorsOfRequestArgs} args
6056
* @memberof UmbTreeRepository
6157
*/
62-
requestTreeItemAncestors: (
63-
args: TreeAncestorsOfRequestArgsType,
64-
) => Promise<{ data?: TreeItemType[]; error?: UmbProblemDetails; asObservable?: () => Observable<TreeItemType[]> }>;
58+
requestTreeItemAncestors: (args: TreeAncestorsOfRequestArgsType) => Promise<UmbRepositoryResponse<TreeItemType[]>>;
6559

6660
/**
6761
* Returns an observable of the root items of the tree.

0 commit comments

Comments
 (0)