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ø <niels.lyngso@gmail.com>
This commit is contained in:
@@ -175,7 +175,7 @@ export class UmbContentTypeStructureManager<
|
||||
* @param {string} unique - The unique of the ContentType to load.
|
||||
* @returns {Promise} - Promise resolved
|
||||
*/
|
||||
public async loadType(unique: string): Promise<UmbRepositoryResponseWithAsObservable<T>> {
|
||||
public async loadType(unique: string): Promise<UmbRepositoryResponseWithAsObservable<T | undefined>> {
|
||||
if (this.#ownerContentTypeUnique === unique) {
|
||||
// Its the same, but we do not know if its done loading jet, so we will wait for the load promise to finish. [NL]
|
||||
await this.#init;
|
||||
|
||||
@@ -60,7 +60,7 @@ export abstract class UmbDetailRepositoryBase<
|
||||
* @returns {*}
|
||||
* @memberof UmbDetailRepositoryBase
|
||||
*/
|
||||
async requestByUnique(unique: string): Promise<UmbRepositoryResponseWithAsObservable<DetailModelType>> {
|
||||
async requestByUnique(unique: string): Promise<UmbRepositoryResponseWithAsObservable<DetailModelType | undefined>> {
|
||||
if (!unique) throw new Error('Unique is missing');
|
||||
await this.#init;
|
||||
|
||||
@@ -73,7 +73,7 @@ export abstract class UmbDetailRepositoryBase<
|
||||
return {
|
||||
data,
|
||||
error,
|
||||
asObservable: () => this.#detailStore!.byUnique(unique),
|
||||
asObservable: () => this.#detailStore?.byUnique(unique),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,6 @@ import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
|
||||
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
|
||||
|
||||
export interface UmbReadDetailRepository<DetailModelType> extends UmbApi {
|
||||
requestByUnique(unique: string): Promise<UmbRepositoryResponseWithAsObservable<DetailModelType>>;
|
||||
requestByUnique(unique: string): Promise<UmbRepositoryResponseWithAsObservable<DetailModelType | undefined>>;
|
||||
byUnique(unique: string): Promise<Observable<DetailModelType | undefined>>;
|
||||
}
|
||||
|
||||
@@ -41,22 +41,18 @@ export class UmbItemRepositoryBase<ItemType extends { unique: string }>
|
||||
try {
|
||||
await this._init;
|
||||
} catch {
|
||||
return {};
|
||||
return {
|
||||
asObservable: () => undefined,
|
||||
};
|
||||
}
|
||||
|
||||
const { data, error } = await this.#itemSource.getItems(uniques);
|
||||
|
||||
if (!this._itemStore) {
|
||||
// If store is gone, then we are most likely in a disassembled state.
|
||||
return {};
|
||||
}
|
||||
|
||||
if (data) {
|
||||
this._itemStore.appendItems(data);
|
||||
this._itemStore?.appendItems(data);
|
||||
}
|
||||
|
||||
// TODO: Fix the type of error, it should be UmbApiError, but currently it is any.
|
||||
return { data, error: error as any, asObservable: () => this._itemStore!.items(uniques) };
|
||||
return { data, error, asObservable: () => this._itemStore?.items(uniques) };
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
import type { UmbRepositoryResponseWithAsObservable } from '../types.js';
|
||||
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
|
||||
import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
|
||||
import type { UmbProblemDetails } from '@umbraco-cms/backoffice/resources';
|
||||
|
||||
export interface UmbItemRepository<ItemType> extends UmbApi {
|
||||
requestItems: (uniques: string[]) => Promise<{
|
||||
data?: Array<ItemType> | undefined;
|
||||
error?: UmbProblemDetails | undefined;
|
||||
asObservable?: () => Observable<Array<ItemType>>;
|
||||
}>;
|
||||
requestItems: (uniques: string[]) => Promise<UmbRepositoryResponseWithAsObservable<ItemType[] | undefined>>;
|
||||
items: (uniques: string[]) => Promise<Observable<Array<ItemType>> | undefined>;
|
||||
}
|
||||
|
||||
@@ -250,7 +250,8 @@ export class UmbRepositoryItemsManager<ItemType extends { unique: string }> exte
|
||||
}
|
||||
}
|
||||
|
||||
#sortByUniques(data: Array<ItemType>): Array<ItemType> {
|
||||
#sortByUniques(data?: Array<ItemType>): Array<ItemType> {
|
||||
if (!data) return [];
|
||||
const uniques = this.getUniques();
|
||||
return [...data].sort((a, b) => {
|
||||
const aIndex = uniques.indexOf(this.#getUnique(a) ?? '');
|
||||
|
||||
@@ -11,8 +11,13 @@ export interface UmbRepositoryResponse<T> extends UmbDataSourceResponse<T> {}
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||
export interface UmbRepositoryErrorResponse extends UmbDataSourceErrorResponse {}
|
||||
|
||||
export interface UmbRepositoryResponseWithAsObservable<T> extends UmbRepositoryResponse<T> {
|
||||
asObservable: () => Observable<T | undefined>;
|
||||
/**
|
||||
* Interface for a repository that can return a paged model.
|
||||
* @template T - The type of items in the paged model.
|
||||
* @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.
|
||||
*/
|
||||
export interface UmbRepositoryResponseWithAsObservable<T, T$ = T> extends UmbRepositoryResponse<T> {
|
||||
asObservable: () => Observable<T$> | undefined;
|
||||
}
|
||||
|
||||
export type * from './data-mapper/mapping/types.js';
|
||||
|
||||
@@ -7,11 +7,10 @@ import type {
|
||||
UmbTreeChildrenOfRequestArgs,
|
||||
UmbTreeRootItemsRequestArgs,
|
||||
} from './types.js';
|
||||
import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository';
|
||||
import { UmbRepositoryBase, type UmbRepositoryResponse } from '@umbraco-cms/backoffice/repository';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
|
||||
import type { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import type { UmbProblemDetails } from '@umbraco-cms/backoffice/resources';
|
||||
import { of } from '@umbraco-cms/backoffice/external/rxjs';
|
||||
|
||||
/**
|
||||
@@ -74,7 +73,7 @@ export abstract class UmbTreeRepositoryBase<
|
||||
* @returns {*}
|
||||
* @memberof UmbTreeRepositoryBase
|
||||
*/
|
||||
abstract requestTreeRoot(): Promise<{ data?: TreeRootType; error?: UmbProblemDetails }>;
|
||||
abstract requestTreeRoot(): Promise<UmbRepositoryResponse<TreeRootType>>;
|
||||
|
||||
/**
|
||||
* Requests root items of a tree
|
||||
@@ -89,15 +88,16 @@ export abstract class UmbTreeRepositoryBase<
|
||||
|
||||
if (!this._treeStore) {
|
||||
// If the tree store is not available, then we most likely are in a destructed setting.
|
||||
return {};
|
||||
return {
|
||||
asObservable: () => undefined,
|
||||
};
|
||||
}
|
||||
|
||||
if (data) {
|
||||
this._treeStore.appendItems(data.items);
|
||||
}
|
||||
|
||||
// TODO: Fix the type of error, it should be UmbApiError, but currently it is any.
|
||||
return { data, error: error as any, asObservable: () => this._treeStore!.rootItems };
|
||||
return { data, error, asObservable: () => this._treeStore?.rootItems };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,15 +117,16 @@ export abstract class UmbTreeRepositoryBase<
|
||||
|
||||
if (!this._treeStore) {
|
||||
// If the tree store is not available, then we most likely are in a destructed setting.
|
||||
return {};
|
||||
return {
|
||||
asObservable: () => undefined,
|
||||
};
|
||||
}
|
||||
|
||||
if (data) {
|
||||
this._treeStore.appendItems(data.items);
|
||||
}
|
||||
|
||||
// TODO: Fix the type of error, it should be UmbApiError, but currently it is any.
|
||||
return { data, error: error as any, asObservable: () => this._treeStore!.childrenOf(args.parent.unique) };
|
||||
return { data, error, asObservable: () => this._treeStore?.childrenOf(args.parent.unique) };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,12 +154,7 @@ export abstract class UmbTreeRepositoryBase<
|
||||
async rootTreeItems() {
|
||||
await this._init;
|
||||
|
||||
if (!this._treeStore) {
|
||||
// If the tree store is not available, then we most likely are in a destructed setting.
|
||||
return of([]);
|
||||
}
|
||||
|
||||
return this._treeStore.rootItems;
|
||||
return this._treeStore?.rootItems ?? of([]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,11 +167,6 @@ export abstract class UmbTreeRepositoryBase<
|
||||
if (parentUnique === undefined) throw new Error('Parent unique is missing');
|
||||
await this._init;
|
||||
|
||||
if (!this._treeStore) {
|
||||
// If the tree store is not available, then we most likely are in a destructed setting.
|
||||
return of([]);
|
||||
}
|
||||
|
||||
return this._treeStore.childrenOf(parentUnique);
|
||||
return this._treeStore?.childrenOf(parentUnique) ?? of([]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,13 @@ import type {
|
||||
UmbTreeAncestorsOfRequestArgs,
|
||||
UmbTreeRootItemsRequestArgs,
|
||||
} from './types.js';
|
||||
import type { UmbPagedModel } from '@umbraco-cms/backoffice/repository';
|
||||
import type {
|
||||
UmbPagedModel,
|
||||
UmbRepositoryResponse,
|
||||
UmbRepositoryResponseWithAsObservable,
|
||||
} from '@umbraco-cms/backoffice/repository';
|
||||
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
|
||||
import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
|
||||
import type { UmbProblemDetails } from '@umbraco-cms/backoffice/resources';
|
||||
|
||||
/**
|
||||
* Interface for a tree repository.
|
||||
@@ -27,41 +30,32 @@ export interface UmbTreeRepository<
|
||||
* Requests the root of the tree.
|
||||
* @memberof UmbTreeRepository
|
||||
*/
|
||||
requestTreeRoot: () => Promise<{
|
||||
data?: TreeRootType;
|
||||
error?: UmbProblemDetails;
|
||||
}>;
|
||||
requestTreeRoot: () => Promise<UmbRepositoryResponse<TreeRootType>>;
|
||||
|
||||
/**
|
||||
* Requests the root items of the tree.
|
||||
* @param {UmbTreeRootItemsRequestArgs} args
|
||||
* @memberof UmbTreeRepository
|
||||
*/
|
||||
requestTreeRootItems: (args: TreeRootItemsRequestArgsType) => Promise<{
|
||||
data?: UmbPagedModel<TreeItemType>;
|
||||
error?: UmbProblemDetails;
|
||||
asObservable?: () => Observable<TreeItemType[]>;
|
||||
}>;
|
||||
requestTreeRootItems: (
|
||||
args: TreeRootItemsRequestArgsType,
|
||||
) => Promise<UmbRepositoryResponseWithAsObservable<UmbPagedModel<TreeItemType>, TreeItemType[]>>;
|
||||
|
||||
/**
|
||||
* Requests the children of the given parent item.
|
||||
* @param {UmbTreeChildrenOfRequestArgs} args
|
||||
* @memberof UmbTreeRepository
|
||||
*/
|
||||
requestTreeItemsOf: (args: TreeChildrenOfRequestArgsType) => Promise<{
|
||||
data?: UmbPagedModel<TreeItemType>;
|
||||
error?: UmbProblemDetails;
|
||||
asObservable?: () => Observable<TreeItemType[]>;
|
||||
}>;
|
||||
requestTreeItemsOf: (
|
||||
args: TreeChildrenOfRequestArgsType,
|
||||
) => Promise<UmbRepositoryResponseWithAsObservable<UmbPagedModel<TreeItemType>, TreeItemType[]>>;
|
||||
|
||||
/**
|
||||
* Requests the ancestors of the given item.
|
||||
* @param {UmbTreeAncestorsOfRequestArgs} args
|
||||
* @memberof UmbTreeRepository
|
||||
*/
|
||||
requestTreeItemAncestors: (
|
||||
args: TreeAncestorsOfRequestArgsType,
|
||||
) => Promise<{ data?: TreeItemType[]; error?: UmbProblemDetails; asObservable?: () => Observable<TreeItemType[]> }>;
|
||||
requestTreeItemAncestors: (args: TreeAncestorsOfRequestArgsType) => Promise<UmbRepositoryResponse<TreeItemType[]>>;
|
||||
|
||||
/**
|
||||
* Returns an observable of the root items of the tree.
|
||||
|
||||
Reference in New Issue
Block a user