Batch item rest requests (#19233)

This commit is contained in:
Mads Rasmussen
2025-05-08 11:17:57 +02:00
committed by GitHub
parent 2c58c701ed
commit 822cfe9c28
37 changed files with 450 additions and 115 deletions

View File

@@ -1 +1,2 @@
export * from './item-data-api-get-request-controller/index.js';
export * from './entity-item-ref/index.js';

View File

@@ -0,0 +1 @@
export * from './item-data-api-get-request.controller.js';

View File

@@ -0,0 +1,66 @@
import type { UmbItemDataApiGetRequestControllerArgs } from './types.js';
import {
batchTryExecute,
tryExecute,
UmbError,
type UmbApiError,
type UmbCancelError,
type UmbDataApiResponse,
} from '@umbraco-cms/backoffice/resources';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { batchArray } from '@umbraco-cms/backoffice/utils';
import { umbPeekError } from '@umbraco-cms/backoffice/notification';
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
export class UmbItemDataApiGetRequestController<
ResponseModelType extends UmbDataApiResponse,
> extends UmbControllerBase {
#apiCallback: (args: { uniques: Array<string> }) => Promise<ResponseModelType>;
#uniques: Array<string>;
#batchSize: number = 40;
constructor(host: UmbControllerHost, args: UmbItemDataApiGetRequestControllerArgs<ResponseModelType>) {
super(host);
this.#apiCallback = args.api;
this.#uniques = args.uniques;
}
async request() {
if (!this.#uniques) throw new Error('Uniques are missing');
let data: ResponseModelType['data'] | undefined;
let error: UmbError | UmbApiError | UmbCancelError | Error | undefined;
if (this.#uniques.length > this.#batchSize) {
const chunks = batchArray<string>(this.#uniques, this.#batchSize);
const results = await batchTryExecute(this, chunks, (chunk) => this.#apiCallback({ uniques: chunk }));
const errors = results.filter((promiseResult) => promiseResult.status === 'rejected');
if (errors.length > 0) {
error = await this.#getAndHandleErrorResult(errors);
}
data = results
.filter((promiseResult) => promiseResult.status === 'fulfilled')
.flatMap((promiseResult) => promiseResult.value.data);
} else {
const result = await tryExecute(this, this.#apiCallback({ uniques: this.#uniques }));
data = result.data;
error = result.error;
}
return { data, error };
}
async #getAndHandleErrorResult(errors: Array<PromiseRejectedResult>) {
// TODO: We currently expect all the errors to be the same, but we should handle this better in the future.
const error = errors[0];
await umbPeekError(this, {
headline: 'Error fetching items',
message: 'An error occurred while fetching items.',
});
return new UmbError(error.reason);
}
}

View File

@@ -0,0 +1,6 @@
import type { UmbDataApiResponse } from '@umbraco-cms/backoffice/resources';
export interface UmbItemDataApiGetRequestControllerArgs<ResponseModelType extends UmbDataApiResponse> {
api: (args: { uniques: Array<string> }) => Promise<ResponseModelType>;
uniques: Array<string>;
}

View File

@@ -1,4 +1,5 @@
import type { UmbNamedEntityModel } from '@umbraco-cms/backoffice/entity';
export type * from './item-data-api-get-request-controller/types.js';
export interface UmbDefaultItemModel extends UmbNamedEntityModel {
icon?: string;

View File

@@ -1,10 +1,11 @@
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
import type { UmbDataSourceResponse } from '../data-source-response.interface.js';
import type { UmbItemDataSource } from './item-data-source.interface.js';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { tryExecute } from '@umbraco-cms/backoffice/resources';
export interface UmbItemServerDataSourceBaseArgs<ServerItemType, ClientItemType extends { unique: string }> {
getItems: (uniques: Array<string>) => Promise<UmbDataSourceResponse<Array<ServerItemType>>>;
getItems?: (uniques: Array<string>) => Promise<UmbDataSourceResponse<Array<ServerItemType>>>;
mapper: (item: ServerItemType) => ClientItemType;
}
@@ -14,10 +15,10 @@ export interface UmbItemServerDataSourceBaseArgs<ServerItemType, ClientItemType
* @implements {DocumentTreeDataSource}
*/
export abstract class UmbItemServerDataSourceBase<ServerItemType, ClientItemType extends { unique: string }>
extends UmbControllerBase
implements UmbItemDataSource<ClientItemType>
{
#host: UmbControllerHost;
#getItems: (uniques: Array<string>) => Promise<UmbDataSourceResponse<Array<ServerItemType>>>;
#getItems?: (uniques: Array<string>) => Promise<UmbDataSourceResponse<Array<ServerItemType>>>;
#mapper: (item: ServerItemType) => ClientItemType;
/**
@@ -27,7 +28,7 @@ export abstract class UmbItemServerDataSourceBase<ServerItemType, ClientItemType
* @memberof UmbItemServerDataSourceBase
*/
constructor(host: UmbControllerHost, args: UmbItemServerDataSourceBaseArgs<ServerItemType, ClientItemType>) {
this.#host = host;
super(host);
this.#getItems = args.getItems;
this.#mapper = args.mapper;
}
@@ -39,14 +40,17 @@ export abstract class UmbItemServerDataSourceBase<ServerItemType, ClientItemType
* @memberof UmbItemServerDataSourceBase
*/
async getItems(uniques: Array<string>) {
if (!this.#getItems) throw new Error('getItems is not implemented');
if (!uniques) throw new Error('Uniques are missing');
const { data, error } = await tryExecute(this.#host, this.#getItems(uniques));
if (data) {
const items = data.map((item) => this.#mapper(item));
return { data: items };
}
const { data, error } = await tryExecute(this, this.#getItems(uniques));
return { error };
return { data: this._getMappedItems(data), error };
}
protected _getMappedItems(items: Array<ServerItemType> | undefined): Array<ClientItemType> | undefined {
if (!items) return undefined;
if (!this.#mapper) throw new Error('Mapper is not implemented');
return items.map((item) => this.#mapper(item));
}
}

View File

@@ -0,0 +1,3 @@
export interface UmbDataApiResponse<ResponseType extends { data: unknown } = { data: unknown }> {
data: ResponseType['data'];
}

View File

@@ -1,12 +1,9 @@
export * from './api-interceptor.controller.js';
export * from './resource.controller.js';
export * from './try-execute.controller.js';
export * from './tryExecute.function.js';
export * from './tryExecuteAndNotify.function.js';
export * from './tryXhrRequest.function.js';
export * from './extractUmbNotificationColor.function.js';
export * from './extractUmbColorVariable.function.js';
export * from './isUmbNotifications.function.js';
export * from './apiTypeValidators.function.js';
export * from './extractUmbColorVariable.function.js';
export * from './extractUmbNotificationColor.function.js';
export * from './isUmbNotifications.function.js';
export * from './resource.controller.js';
export * from './try-execute/index.js';
export * from './umb-error.js';
export type * from './types.js';

View File

@@ -0,0 +1,17 @@
import { tryExecute } from './tryExecute.function.js';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
/**
* Batches promises and returns a promise that resolves to an array of results
* @param {UmbControllerHost} host - The host to use for the request and where notifications will be shown
* @param {Array<Array<BatchEntryType>>} chunks - The array of chunks to process
* @param {(chunk: Array<BatchEntryType>) => Promise<PromiseResult>} callback - The function to call for each chunk
* @returns {Promise<PromiseSettledResult<PromiseResult>[]>} - A promise that resolves to an array of results
*/
export function batchTryExecute<BatchEntryType, PromiseResult>(
host: UmbControllerHost,
chunks: Array<Array<BatchEntryType>>,
callback: (chunk: Array<BatchEntryType>) => Promise<PromiseResult>,
): Promise<PromiseSettledResult<PromiseResult>[]> {
return Promise.allSettled(chunks.map((chunk) => tryExecute(host, callback(chunk), { disableNotifications: true })));
}

View File

@@ -0,0 +1,5 @@
export * from './batch-try-execute.function.js';
export * from './try-execute.controller.js';
export * from './tryExecute.function.js';
export * from './tryExecuteAndNotify.function.js';
export * from './tryXhrRequest.function.js';

View File

@@ -1,7 +1,7 @@
import { isProblemDetailsLike } from './apiTypeValidators.function.js';
import { UmbResourceController } from './resource.controller.js';
import type { UmbApiResponse, UmbTryExecuteOptions } from './types.js';
import { UmbApiError, UmbCancelError } from './umb-error.js';
import { isProblemDetailsLike } from '../apiTypeValidators.function.js';
import { UmbResourceController } from '../resource.controller.js';
import type { UmbApiResponse, UmbTryExecuteOptions } from '../types.js';
import { UmbApiError, UmbCancelError } from '../umb-error.js';
export class UmbTryExecuteController<T> extends UmbResourceController<T> {
#abortSignal?: AbortSignal;

View File

@@ -1,5 +1,5 @@
import type { UmbApiResponse, UmbTryExecuteOptions } from '../types.js';
import { UmbTryExecuteController } from './try-execute.controller.js';
import type { UmbApiResponse, UmbTryExecuteOptions } from './types.js';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
/**

View File

@@ -1,5 +1,5 @@
import type { UmbApiResponse } from '../types.js';
import { UmbTryExecuteController } from './try-execute.controller.js';
import type { UmbApiResponse } from './types.js';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbDeprecation } from '@umbraco-cms/backoffice/utils';

View File

@@ -1,8 +1,8 @@
import { UmbCancelablePromise } from '../cancelable-promise.js';
import { UmbApiError } from '../umb-error.js';
import { isProblemDetailsLike } from '../apiTypeValidators.function.js';
import type { UmbApiResponse, XhrRequestOptions } from '../types.js';
import { UmbTryExecuteController } from './try-execute.controller.js';
import { UmbCancelablePromise } from './cancelable-promise.js';
import { UmbApiError } from './umb-error.js';
import { isProblemDetailsLike } from './apiTypeValidators.function.js';
import type { UmbApiResponse, XhrRequestOptions } from './types.js';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { umbHttpClient } from '@umbraco-cms/backoffice/http-client';

View File

@@ -1,4 +1,5 @@
import type { UmbApiError, UmbCancelError, UmbError } from './umb-error.js';
export type * from './data-api/types.js';
export interface XhrRequestOptions extends UmbTryExecuteOptions {
baseUrl?: string;

View File

@@ -0,0 +1,25 @@
import { expect } from '@open-wc/testing';
import { batchArray } from './batch-array.js';
describe('batchArray', () => {
it('should split an array into chunks of the specified size', () => {
const array = [1, 2, 3, 4, 5];
const batchSize = 2;
const result = batchArray(array, batchSize);
expect(result).to.deep.equal([[1, 2], [3, 4], [5]]);
});
it('should handle arrays smaller than the batch size', () => {
const array = [1];
const batchSize = 2;
const result = batchArray(array, batchSize);
expect(result).to.deep.equal([[1]]);
});
it('should handle empty arrays', () => {
const array: number[] = [];
const batchSize = 2;
const result = batchArray(array, batchSize);
expect(result).to.deep.equal([]);
});
});

View File

@@ -0,0 +1,16 @@
/**
* Splits an array into chunks of a specified size
* @param { Array<BatchEntryType> } array - The array to split
* @param {number }batchSize - The size of each chunk
* @returns {Array<Array<T>>} - An array of chunks
*/
export function batchArray<BatchEntryType>(
array: Array<BatchEntryType>,
batchSize: number,
): Array<Array<BatchEntryType>> {
const chunks: Array<Array<BatchEntryType>> = [];
for (let i = 0; i < array.length; i += batchSize) {
chunks.push(array.slice(i, i + batchSize));
}
return chunks;
}

View File

@@ -0,0 +1 @@
export * from './batch-array.js';

View File

@@ -1,3 +1,4 @@
export * from './array/index.js';
export * from './bytes/bytes.function.js';
export * from './debounce/debounce.function.js';
export * from './deprecation/index.js';

View File

@@ -6,6 +6,7 @@ import { DataTypeService } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
import type { ManifestPropertyEditorUi } from '@umbraco-cms/backoffice/property-editor';
import { UmbItemDataApiGetRequestController } from '@umbraco-cms/backoffice/entity-item';
let manifestPropertyEditorUis: Array<ManifestPropertyEditorUi> = [];
@@ -26,7 +27,6 @@ export class UmbDataTypeItemServerDataSource extends UmbItemServerDataSourceBase
constructor(host: UmbControllerHost) {
super(host, {
getItems,
mapper,
});
@@ -37,10 +37,21 @@ export class UmbDataTypeItemServerDataSource extends UmbItemServerDataSourceBase
})
.unsubscribe();
}
}
/* eslint-disable local-rules/no-direct-api-import */
const getItems = (uniques: Array<string>) => DataTypeService.getItemDataType({ query: { id: uniques } });
override async getItems(uniques: Array<string>) {
if (!uniques) throw new Error('Uniques are missing');
const itemRequestManager = new UmbItemDataApiGetRequestController(this, {
// eslint-disable-next-line local-rules/no-direct-api-import
api: (args) => DataTypeService.getItemDataType({ query: { id: args.uniques } }),
uniques,
});
const { data, error } = await itemRequestManager.request();
return { data: this._getMappedItems(data), error };
}
}
const mapper = (item: DataTypeItemResponseModel): UmbDataTypeItemModel => {
return {

View File

@@ -4,6 +4,7 @@ import { UmbItemServerDataSourceBase } from '@umbraco-cms/backoffice/repository'
import type { DictionaryItemItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
import { DictionaryService } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbItemDataApiGetRequestController } from '@umbraco-cms/backoffice/entity-item';
/**
* A server data source for Dictionary items
@@ -21,14 +22,24 @@ export class UmbDictionaryItemServerDataSource extends UmbItemServerDataSourceBa
*/
constructor(host: UmbControllerHost) {
super(host, {
getItems,
mapper,
});
}
}
/* eslint-disable local-rules/no-direct-api-import */
const getItems = (uniques: Array<string>) => DictionaryService.getItemDictionary({ query: { id: uniques } });
override async getItems(uniques: Array<string>) {
if (!uniques) throw new Error('Uniques are missing');
const itemRequestManager = new UmbItemDataApiGetRequestController(this, {
// eslint-disable-next-line local-rules/no-direct-api-import
api: (args) => DictionaryService.getItemDictionary({ query: { id: args.uniques } }),
uniques,
});
const { data, error } = await itemRequestManager.request();
return { data: this._getMappedItems(data), error };
}
}
const mapper = (item: DictionaryItemItemResponseModel): UmbDictionaryItemModel => {
return {

View File

@@ -5,6 +5,7 @@ import { UmbItemServerDataSourceBase } from '@umbraco-cms/backoffice/repository'
import type { DocumentBlueprintItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { tryExecute } from '@umbraco-cms/backoffice/resources';
import { UmbItemDataApiGetRequestController } from '@umbraco-cms/backoffice/entity-item';
/**
* A data source for Document Blueprint items that fetches data from the server
@@ -15,7 +16,6 @@ export class UmbDocumentBlueprintItemServerDataSource extends UmbItemServerDataS
DocumentBlueprintItemResponseModel,
UmbDocumentBlueprintItemModel
> {
#host: UmbControllerHost;
/**
* Creates an instance of UmbDocumentBlueprintItemServerDataSource.
* @param {UmbControllerHost} host - The controller host for this controller to be appended to
@@ -23,16 +23,14 @@ export class UmbDocumentBlueprintItemServerDataSource extends UmbItemServerDataS
*/
constructor(host: UmbControllerHost) {
super(host, {
getItems,
mapper,
});
this.#host = host;
}
async getItemsByDocumentType(unique: string) {
if (!unique) throw new Error('Unique is missing');
const { data, error } = await tryExecute(
this.#host,
this,
DocumentTypeService.getDocumentTypeByIdBlueprint({ path: { id: unique } }),
);
@@ -47,11 +45,21 @@ export class UmbDocumentBlueprintItemServerDataSource extends UmbItemServerDataS
return { error };
}
}
/* eslint-disable local-rules/no-direct-api-import */
const getItems = (uniques: Array<string>) =>
DocumentBlueprintService.getItemDocumentBlueprint({ query: { id: uniques } });
override async getItems(uniques: Array<string>) {
if (!uniques) throw new Error('Uniques are missing');
const itemRequestManager = new UmbItemDataApiGetRequestController(this, {
// eslint-disable-next-line local-rules/no-direct-api-import
api: (args) => DocumentBlueprintService.getItemDocumentBlueprint({ query: { id: args.uniques } }),
uniques,
});
const { data, error } = await itemRequestManager.request();
return { data: this._getMappedItems(data), error };
}
}
const mapper = (item: DocumentBlueprintItemResponseModel): UmbDocumentBlueprintItemModel => {
return {

View File

@@ -4,6 +4,7 @@ import { UmbItemServerDataSourceBase } from '@umbraco-cms/backoffice/repository'
import type { DocumentTypeItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
import { DocumentTypeService } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbItemDataApiGetRequestController } from '@umbraco-cms/backoffice/entity-item';
/**
* A data source for Document Type items that fetches data from the server
@@ -20,13 +21,24 @@ export class UmbDocumentTypeItemServerDataSource extends UmbItemServerDataSource
* @memberof UmbDocumentTypeItemServerDataSource
*/
constructor(host: UmbControllerHost) {
super(host, { getItems, mapper });
super(host, { mapper });
}
override async getItems(uniques: Array<string>) {
if (!uniques) throw new Error('Uniques are missing');
const itemRequestManager = new UmbItemDataApiGetRequestController(this, {
// eslint-disable-next-line local-rules/no-direct-api-import
api: (args) => DocumentTypeService.getItemDocumentType({ query: { id: args.uniques } }),
uniques,
});
const { data, error } = await itemRequestManager.request();
return { data: this._getMappedItems(data), error };
}
}
/* eslint-disable local-rules/no-direct-api-import */
const getItems = (uniques: Array<string>) => DocumentTypeService.getItemDocumentType({ query: { id: uniques } });
const mapper = (item: DocumentTypeItemResponseModel): UmbDocumentTypeItemModel => {
return {
entityType: UMB_DOCUMENT_TYPE_ENTITY_TYPE,

View File

@@ -4,6 +4,7 @@ import type { DocumentItemResponseModel } from '@umbraco-cms/backoffice/external
import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbItemServerDataSourceBase } from '@umbraco-cms/backoffice/repository';
import { UmbItemDataApiGetRequestController } from '@umbraco-cms/backoffice/entity-item';
/**
* A data source for Document items that fetches data from the server
@@ -21,14 +22,24 @@ export class UmbDocumentItemServerDataSource extends UmbItemServerDataSourceBase
*/
constructor(host: UmbControllerHost) {
super(host, {
getItems,
mapper,
});
}
}
/* eslint-disable local-rules/no-direct-api-import */
const getItems = (uniques: Array<string>) => DocumentService.getItemDocument({ query: { id: uniques } });
override async getItems(uniques: Array<string>) {
if (!uniques) throw new Error('Uniques are missing');
const itemRequestManager = new UmbItemDataApiGetRequestController(this, {
// eslint-disable-next-line local-rules/no-direct-api-import
api: (args) => DocumentService.getItemDocument({ query: { id: args.uniques } }),
uniques,
});
const { data, error } = await itemRequestManager.request();
return { data: this._getMappedItems(data), error };
}
}
const mapper = (item: DocumentItemResponseModel): UmbDocumentItemModel => {
return {

View File

@@ -3,6 +3,7 @@ import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api';
import { UmbItemServerDataSourceBase } from '@umbraco-cms/backoffice/repository';
import type { DocumentUrlInfoResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbItemDataApiGetRequestController } from '@umbraco-cms/backoffice/entity-item';
/**
* A server data source for Document URLs
@@ -19,11 +20,22 @@ export class UmbDocumentUrlServerDataSource extends UmbItemServerDataSourceBase<
* @memberof UmbDocumentUrlServerDataSource
*/
constructor(host: UmbControllerHost) {
super(host, { getItems, mapper });
super(host, { mapper });
}
override async getItems(uniques: Array<string>) {
if (!uniques) throw new Error('Uniques are missing');
const itemRequestManager = new UmbItemDataApiGetRequestController(this, {
// eslint-disable-next-line local-rules/no-direct-api-import
api: (args) => DocumentService.getDocumentUrls({ query: { id: args.uniques } }),
uniques,
});
const { data, error } = await itemRequestManager.request();
return { data: this._getMappedItems(data), error };
}
}
/* eslint-disable local-rules/no-direct-api-import */
const getItems = (uniques: Array<string>) => DocumentService.getDocumentUrls({ query: { id: uniques } });
const mapper = (item: DocumentUrlInfoResponseModel): UmbDocumentUrlsModel => ({ unique: item.id, urls: item.urlInfos });

View File

@@ -4,6 +4,7 @@ import { UmbItemServerDataSourceBase } from '@umbraco-cms/backoffice/repository'
import type { LanguageItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
import { LanguageService } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbItemDataApiGetRequestController } from '@umbraco-cms/backoffice/entity-item';
/**
* A server data source for Language items
@@ -21,14 +22,24 @@ export class UmbLanguageItemServerDataSource extends UmbItemServerDataSourceBase
*/
constructor(host: UmbControllerHost) {
super(host, {
getItems,
mapper,
});
}
}
/* eslint-disable local-rules/no-direct-api-import */
const getItems = (uniques: Array<string>) => LanguageService.getItemLanguage({ query: { isoCode: uniques } });
override async getItems(uniques: Array<string>) {
if (!uniques) throw new Error('Uniques are missing');
const itemRequestManager = new UmbItemDataApiGetRequestController(this, {
// eslint-disable-next-line local-rules/no-direct-api-import
api: (args) => LanguageService.getItemLanguage({ query: { isoCode: args.uniques } }),
uniques,
});
const { data, error } = await itemRequestManager.request();
return { data: this._getMappedItems(data), error };
}
}
const mapper = (item: LanguageItemResponseModel): UmbLanguageItemModel => {
return {

View File

@@ -4,6 +4,7 @@ import { UmbItemServerDataSourceBase } from '@umbraco-cms/backoffice/repository'
import type { MediaTypeItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
import { MediaTypeService } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbItemDataApiGetRequestController } from '@umbraco-cms/backoffice/entity-item';
/**
* A data source for Media Type items that fetches data from the server
@@ -21,14 +22,24 @@ export class UmbMediaTypeItemServerDataSource extends UmbItemServerDataSourceBas
*/
constructor(host: UmbControllerHost) {
super(host, {
getItems,
mapper,
});
}
}
/* eslint-disable local-rules/no-direct-api-import */
const getItems = (uniques: Array<string>) => MediaTypeService.getItemMediaType({ query: { id: uniques } });
override async getItems(uniques: Array<string>) {
if (!uniques) throw new Error('Uniques are missing');
const itemRequestManager = new UmbItemDataApiGetRequestController(this, {
// eslint-disable-next-line local-rules/no-direct-api-import
api: (args) => MediaTypeService.getItemMediaType({ query: { id: args.uniques } }),
uniques,
});
const { data, error } = await itemRequestManager.request();
return { data: this._getMappedItems(data), error };
}
}
const mapper = (item: MediaTypeItemResponseModel): UmbMediaTypeItemModel => {
return {

View File

@@ -5,6 +5,7 @@ import { MediaService } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbItemServerDataSourceBase } from '@umbraco-cms/backoffice/repository';
import { tryExecute } from '@umbraco-cms/backoffice/resources';
import { UmbItemDataApiGetRequestController } from '@umbraco-cms/backoffice/entity-item';
/**
* A data source for Media items that fetches data from the server
@@ -15,7 +16,6 @@ export class UmbMediaItemServerDataSource extends UmbItemServerDataSourceBase<
MediaItemResponseModel,
UmbMediaItemModel
> {
#host: UmbControllerHost;
/**
* Creates an instance of UmbMediaItemServerDataSource.
* @param {UmbControllerHost} host - The controller host for this controller to be appended to
@@ -23,10 +23,8 @@ export class UmbMediaItemServerDataSource extends UmbItemServerDataSourceBase<
*/
constructor(host: UmbControllerHost) {
super(host, {
getItems,
mapper,
});
this.#host = host;
}
/**
@@ -38,17 +36,25 @@ export class UmbMediaItemServerDataSource extends UmbItemServerDataSourceBase<
* ```
*/
async search({ query, skip, take }: { query: string; skip: number; take: number }) {
const { data, error } = await tryExecute(
this.#host,
MediaService.getItemMediaSearch({ query: { query, skip, take } }),
);
const { data, error } = await tryExecute(this, MediaService.getItemMediaSearch({ query: { query, skip, take } }));
const mapped = data?.items.map((item) => mapper(item));
return { data: mapped, error };
}
}
/* eslint-disable local-rules/no-direct-api-import */
const getItems = (uniques: Array<string>) => MediaService.getItemMedia({ query: { id: uniques } });
override async getItems(uniques: Array<string>) {
if (!uniques) throw new Error('Uniques are missing');
const itemRequestManager = new UmbItemDataApiGetRequestController(this, {
// eslint-disable-next-line local-rules/no-direct-api-import
api: (args) => MediaService.getItemMedia({ query: { id: args.uniques } }),
uniques,
});
const { data, error } = await itemRequestManager.request();
return { data: this._getMappedItems(data), error };
}
}
const mapper = (item: MediaItemResponseModel): UmbMediaItemModel => {
return {

View File

@@ -1,5 +1,6 @@
import type { UmbMediaUrlModel } from './types.js';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbItemDataApiGetRequestController } from '@umbraco-cms/backoffice/entity-item';
import { MediaService, type MediaUrlInfoResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
import { UmbItemServerDataSourceBase } from '@umbraco-cms/backoffice/repository';
@@ -19,14 +20,24 @@ export class UmbMediaUrlServerDataSource extends UmbItemServerDataSourceBase<
*/
constructor(host: UmbControllerHost) {
super(host, {
getItems,
mapper,
});
}
}
/* eslint-disable local-rules/no-direct-api-import */
const getItems = (uniques: Array<string>) => MediaService.getMediaUrls({ query: { id: uniques } });
override async getItems(uniques: Array<string>) {
if (!uniques) throw new Error('Uniques are missing');
const itemRequestManager = new UmbItemDataApiGetRequestController(this, {
// eslint-disable-next-line local-rules/no-direct-api-import
api: (args) => MediaService.getMediaUrls({ query: { id: args.uniques } }),
uniques,
});
const { data, error } = await itemRequestManager.request();
return { data: this._getMappedItems(data), error };
}
}
const mapper = (item: MediaUrlInfoResponseModel): UmbMediaUrlModel => {
const url = item.urlInfos.length ? item.urlInfos[0].url : undefined;

View File

@@ -4,6 +4,7 @@ import { UmbItemServerDataSourceBase } from '@umbraco-cms/backoffice/repository'
import type { MemberGroupItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
import { MemberGroupService } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbItemDataApiGetRequestController } from '@umbraco-cms/backoffice/entity-item';
/**
* A server data source for Member Group items
@@ -21,14 +22,24 @@ export class UmbMemberGroupItemServerDataSource extends UmbItemServerDataSourceB
*/
constructor(host: UmbControllerHost) {
super(host, {
getItems,
mapper,
});
}
}
/* eslint-disable local-rules/no-direct-api-import */
const getItems = (uniques: Array<string>) => MemberGroupService.getItemMemberGroup({ query: { id: uniques } });
override async getItems(uniques: Array<string>) {
if (!uniques) throw new Error('Uniques are missing');
const itemRequestManager = new UmbItemDataApiGetRequestController(this, {
// eslint-disable-next-line local-rules/no-direct-api-import
api: (args) => MemberGroupService.getItemMemberGroup({ query: { id: args.uniques } }),
uniques,
});
const { data, error } = await itemRequestManager.request();
return { data: this._getMappedItems(data), error };
}
}
const mapper = (item: MemberGroupItemResponseModel): UmbMemberGroupItemModel => {
return {

View File

@@ -4,6 +4,7 @@ import { UmbItemServerDataSourceBase } from '@umbraco-cms/backoffice/repository'
import type { MemberTypeItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
import { MemberTypeService } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbItemDataApiGetRequestController } from '@umbraco-cms/backoffice/entity-item';
/**
* A server data source for Member Type items
@@ -21,14 +22,24 @@ export class UmbMemberTypeItemServerDataSource extends UmbItemServerDataSourceBa
*/
constructor(host: UmbControllerHost) {
super(host, {
getItems,
mapper,
});
}
}
/* eslint-disable local-rules/no-direct-api-import */
const getItems = (uniques: Array<string>) => MemberTypeService.getItemMemberType({ query: { id: uniques } });
override async getItems(uniques: Array<string>) {
if (!uniques) throw new Error('Uniques are missing');
const itemRequestManager = new UmbItemDataApiGetRequestController(this, {
// eslint-disable-next-line local-rules/no-direct-api-import
api: (args) => MemberTypeService.getItemMemberType({ query: { id: args.uniques } }),
uniques,
});
const { data, error } = await itemRequestManager.request();
return { data: this._getMappedItems(data), error };
}
}
const mapper = (item: MemberTypeItemResponseModel): UmbMemberTypeItemModel => {
return {

View File

@@ -4,6 +4,7 @@ import { UmbItemServerDataSourceBase } from '@umbraco-cms/backoffice/repository'
import type { MemberItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
import { MemberService } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbItemDataApiGetRequestController } from '@umbraco-cms/backoffice/entity-item';
/**
* A server data source for Member items
@@ -21,14 +22,24 @@ export class UmbMemberItemServerDataSource extends UmbItemServerDataSourceBase<
*/
constructor(host: UmbControllerHost) {
super(host, {
getItems,
mapper,
});
}
}
/* eslint-disable local-rules/no-direct-api-import */
const getItems = (uniques: Array<string>) => MemberService.getItemMember({ query: { id: uniques } });
override async getItems(uniques: Array<string>) {
if (!uniques) throw new Error('Uniques are missing');
const itemRequestManager = new UmbItemDataApiGetRequestController(this, {
// eslint-disable-next-line local-rules/no-direct-api-import
api: (args) => MemberService.getItemMember({ query: { id: args.uniques } }),
uniques,
});
const { data, error } = await itemRequestManager.request();
return { data: this._getMappedItems(data), error };
}
}
const mapper = (item: MemberItemResponseModel): UmbMemberItemModel => {
return {

View File

@@ -4,6 +4,7 @@ import type { StaticFileItemResponseModel } from '@umbraco-cms/backoffice/extern
import { StaticFileService } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbServerFilePathUniqueSerializer } from '@umbraco-cms/backoffice/server-file-system';
import { UmbItemDataApiGetRequestController } from '@umbraco-cms/backoffice/entity-item';
/**
* A server data source for Static File items
@@ -21,20 +22,28 @@ export class UmbStaticFileItemServerDataSource extends UmbItemServerDataSourceBa
*/
constructor(host: UmbControllerHost) {
super(host, {
getItems,
mapper,
});
}
override async getItems(uniques: Array<string>) {
if (!uniques) throw new Error('Uniques are missing');
const serializer = new UmbServerFilePathUniqueSerializer();
const paths = uniques.map((unique) => serializer.toServerPath(unique)!);
const itemRequestManager = new UmbItemDataApiGetRequestController(this, {
// eslint-disable-next-line local-rules/no-direct-api-import
api: (args) => StaticFileService.getItemStaticFile({ query: { path: args.uniques } }),
uniques: paths,
});
const { data, error } = await itemRequestManager.request();
return { data: this._getMappedItems(data), error };
}
}
const getItems = (uniques: Array<string>) => {
const serializer = new UmbServerFilePathUniqueSerializer();
const path = uniques.map((unique) => serializer.toServerPath(unique)!);
/* eslint-disable local-rules/no-direct-api-import */
return StaticFileService.getItemStaticFile({ query: { path } });
};
const mapper = (item: StaticFileItemResponseModel): UmbStaticFileItemModel => {
const serializer = new UmbServerFilePathUniqueSerializer();
return {

View File

@@ -4,6 +4,7 @@ import { UmbItemServerDataSourceBase } from '@umbraco-cms/backoffice/repository'
import type { TemplateItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
import { TemplateService } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbItemDataApiGetRequestController } from '@umbraco-cms/backoffice/entity-item';
/**
* A server data source for Template items
@@ -21,14 +22,24 @@ export class UmbTemplateItemServerDataSource extends UmbItemServerDataSourceBase
*/
constructor(host: UmbControllerHost) {
super(host, {
getItems,
mapper,
});
}
}
/* eslint-disable local-rules/no-direct-api-import */
const getItems = (uniques: Array<string>) => TemplateService.getItemTemplate({ query: { id: uniques } });
override async getItems(uniques: Array<string>) {
if (!uniques) throw new Error('Uniques are missing');
const itemRequestManager = new UmbItemDataApiGetRequestController(this, {
// eslint-disable-next-line local-rules/no-direct-api-import
api: (args) => TemplateService.getItemTemplate({ query: { id: args.uniques } }),
uniques,
});
const { data, error } = await itemRequestManager.request();
return { data: this._getMappedItems(data), error };
}
}
const mapper = (item: TemplateItemResponseModel): UmbTemplateItemModel => {
return {

View File

@@ -3,6 +3,7 @@ import type { UserGroupItemResponseModel } from '@umbraco-cms/backoffice/externa
import { UserGroupService } from '@umbraco-cms/backoffice/external/backend-api';
import { UmbItemServerDataSourceBase } from '@umbraco-cms/backoffice/repository';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbItemDataApiGetRequestController } from '@umbraco-cms/backoffice/entity-item';
/**
* A server data source for User Group items
@@ -20,14 +21,24 @@ export class UmbUserGroupItemServerDataSource extends UmbItemServerDataSourceBas
*/
constructor(host: UmbControllerHost) {
super(host, {
getItems,
mapper,
});
}
}
/* eslint-disable local-rules/no-direct-api-import */
const getItems = (uniques: Array<string>) => UserGroupService.getItemUserGroup({ query: { id: uniques } });
override async getItems(uniques: Array<string>) {
if (!uniques) throw new Error('Uniques are missing');
const itemRequestManager = new UmbItemDataApiGetRequestController(this, {
// eslint-disable-next-line local-rules/no-direct-api-import
api: (args) => UserGroupService.getItemUserGroup({ query: { id: args.uniques } }),
uniques,
});
const { data, error } = await itemRequestManager.request();
return { data: this._getMappedItems(data), error };
}
}
const mapper = (item: UserGroupItemResponseModel): UmbUserGroupItemModel => {
return {

View File

@@ -1,6 +1,7 @@
import { UMB_USER_ENTITY_TYPE } from '../../entity.js';
import type { UmbUserItemModel } from './types.js';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbItemDataApiGetRequestController } from '@umbraco-cms/backoffice/entity-item';
import type { UserItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
import { UserService } from '@umbraco-cms/backoffice/external/backend-api';
import { UmbItemServerDataSourceBase } from '@umbraco-cms/backoffice/repository';
@@ -18,14 +19,24 @@ export class UmbUserItemServerDataSource extends UmbItemServerDataSourceBase<Use
*/
constructor(host: UmbControllerHost) {
super(host, {
getItems,
mapper,
});
}
}
/* eslint-disable local-rules/no-direct-api-import */
const getItems = (uniques: Array<string>) => UserService.getItemUser({ query: { id: uniques } });
override async getItems(uniques: Array<string>) {
if (!uniques) throw new Error('Uniques are missing');
const itemRequestManager = new UmbItemDataApiGetRequestController(this, {
// eslint-disable-next-line local-rules/no-direct-api-import
api: (args) => UserService.getItemUser({ query: { id: args.uniques } }),
uniques,
});
const { data, error } = await itemRequestManager.request();
return { data: this._getMappedItems(data), error };
}
}
const mapper = (item: UserItemResponseModel): UmbUserItemModel => {
return {

View File

@@ -3,6 +3,7 @@ import { UmbItemServerDataSourceBase } from '@umbraco-cms/backoffice/repository'
import type { WebhookItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
import { WebhookService } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbItemDataApiGetRequestController } from '@umbraco-cms/backoffice/entity-item';
/**
* A server data source for Webhook items
@@ -20,14 +21,24 @@ export class UmbWebhookItemServerDataSource extends UmbItemServerDataSourceBase<
*/
constructor(host: UmbControllerHost) {
super(host, {
getItems,
mapper,
});
}
}
/* eslint-disable local-rules/no-direct-api-import */
const getItems = (uniques: Array<string>) => WebhookService.getItemWebhook({ query: { id: uniques } });
override async getItems(uniques: Array<string>) {
if (!uniques) throw new Error('Uniques are missing');
const itemRequestManager = new UmbItemDataApiGetRequestController(this, {
// eslint-disable-next-line local-rules/no-direct-api-import
api: (args) => WebhookService.getItemWebhook({ query: { id: args.uniques } }),
uniques,
});
const { data, error } = await itemRequestManager.request();
return { data: this._getMappedItems(data), error };
}
}
const mapper = (item: WebhookItemResponseModel): UmbWebhookItemModel => {
return {