@webiny/api-file-manager 6.6.0-alpha.0 → 6.6.0-alpha.2
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/FileManagerAppFeature.js +4 -4
- package/FileManagerAppFeature.js.map +1 -1
- package/delivery/AssetDelivery/AssetRequest.d.ts +1 -1
- package/delivery/AssetDelivery/AssetRequest.js.map +1 -1
- package/delivery/AssetDeliveryRoute.d.ts +15 -6
- package/delivery/AssetDeliveryRoute.js +25 -32
- package/delivery/AssetDeliveryRoute.js.map +1 -1
- package/domain/file/abstractions.d.ts +13 -5
- package/domain/file/abstractions.js +2 -2
- package/domain/file/abstractions.js.map +1 -1
- package/domain/file/file.model.d.ts +3 -3
- package/domain/file/file.model.js +10 -6
- package/domain/file/file.model.js.map +1 -1
- package/features/assetDelivery/abstractions/AssetType.d.ts +17 -0
- package/features/assetDelivery/abstractions/AssetType.js +5 -0
- package/features/assetDelivery/abstractions/AssetType.js.map +1 -0
- package/features/assetDelivery/{transformation → assetTypes/image}/AssetKeyGenerator.d.ts +5 -2
- package/features/assetDelivery/assetTypes/image/AssetKeyGenerator.js +30 -0
- package/features/assetDelivery/assetTypes/image/AssetKeyGenerator.js.map +1 -0
- package/features/assetDelivery/assetTypes/image/ImageAssetType.d.ts +9 -0
- package/features/assetDelivery/assetTypes/image/ImageAssetType.js +18 -0
- package/features/assetDelivery/assetTypes/image/ImageAssetType.js.map +1 -0
- package/features/assetDelivery/assetTypes/image/ImageAssetTypeHandler.d.ts +5 -0
- package/features/assetDelivery/assetTypes/image/ImageAssetTypeHandler.js +5 -0
- package/features/assetDelivery/assetTypes/image/ImageAssetTypeHandler.js.map +1 -0
- package/features/assetDelivery/assetTypes/image/SharpTransformer.d.ts +18 -0
- package/features/assetDelivery/assetTypes/image/SharpTransformer.js +47 -0
- package/features/assetDelivery/assetTypes/image/SharpTransformer.js.map +1 -0
- package/features/assetDelivery/assetTypes/image/WidthCollection.js.map +1 -0
- package/features/assetDelivery/assetTypes/image/imageFormat.d.ts +26 -0
- package/features/assetDelivery/assetTypes/image/imageFormat.js +51 -0
- package/features/assetDelivery/assetTypes/image/imageFormat.js.map +1 -0
- package/features/assetDelivery/assetTypes/image/imageTypes.d.ts +39 -0
- package/features/assetDelivery/assetTypes/image/imageTypes.js +0 -0
- package/features/assetDelivery/assetTypes/image/index.d.ts +5 -0
- package/features/assetDelivery/assetTypes/image/index.js +4 -0
- package/features/assetDelivery/assetTypes/image/normalizeImageOptions.d.ts +6 -0
- package/features/assetDelivery/assetTypes/image/normalizeImageOptions.js +56 -0
- package/features/assetDelivery/assetTypes/image/normalizeImageOptions.js.map +1 -0
- package/features/assetDelivery/assetTypes/image/transformImage.d.ts +59 -0
- package/features/assetDelivery/assetTypes/image/transformImage.js +146 -0
- package/features/assetDelivery/assetTypes/image/transformImage.js.map +1 -0
- package/features/assetDelivery/assetTypes/image/utils.d.ts +26 -0
- package/features/assetDelivery/assetTypes/image/utils.js +47 -0
- package/features/assetDelivery/assetTypes/image/utils.js.map +1 -0
- package/features/assetDelivery/feature.js +7 -7
- package/features/assetDelivery/feature.js.map +1 -1
- package/features/assetDelivery/privateFiles/PrivateFilesAssetProcessor.js.map +1 -1
- package/features/assetDelivery/transformation/TransformationAssetProcessor.d.ts +4 -6
- package/features/assetDelivery/transformation/TransformationAssetProcessor.js +13 -11
- package/features/assetDelivery/transformation/TransformationAssetProcessor.js.map +1 -1
- package/features/assetDelivery/transformation/index.d.ts +4 -3
- package/features/assetDelivery/transformation/index.js +3 -3
- package/features/file/CreateFile/CreateFileRepository.d.ts +3 -3
- package/features/file/CreateFile/CreateFileRepository.js +6 -5
- package/features/file/CreateFile/CreateFileRepository.js.map +1 -1
- package/features/file/DeleteFile/DeleteFileRepository.d.ts +3 -3
- package/features/file/DeleteFile/DeleteFileRepository.js +6 -5
- package/features/file/DeleteFile/DeleteFileRepository.js.map +1 -1
- package/features/file/FileModelProvider.d.ts +31 -0
- package/features/file/FileModelProvider.js +22 -0
- package/features/file/FileModelProvider.js.map +1 -0
- package/features/file/GetFile/GetFileRepository.d.ts +3 -3
- package/features/file/GetFile/GetFileRepository.js +6 -5
- package/features/file/GetFile/GetFileRepository.js.map +1 -1
- package/features/file/ListFiles/ListFilesRepository.d.ts +3 -3
- package/features/file/ListFiles/ListFilesRepository.js +8 -7
- package/features/file/ListFiles/ListFilesRepository.js.map +1 -1
- package/features/file/ListImagesByTagTool/ListImagesByTagTool.d.ts +5 -0
- package/features/file/ListImagesByTagTool/ListImagesByTagTool.js +5 -0
- package/features/file/ListImagesByTagTool/ListImagesByTagTool.js.map +1 -1
- package/features/file/ListTags/ListTagsRepository.d.ts +3 -3
- package/features/file/ListTags/ListTagsRepository.js +7 -6
- package/features/file/ListTags/ListTagsRepository.js.map +1 -1
- package/features/file/UpdateFile/UpdateFileRepository.d.ts +3 -3
- package/features/file/UpdateFile/UpdateFileRepository.js +6 -5
- package/features/file/UpdateFile/UpdateFileRepository.js.map +1 -1
- package/features/upload/WriteFileMetadata/WriteMetadataAfterUpdateHandler.d.ts +11 -0
- package/features/upload/WriteFileMetadata/WriteMetadataAfterUpdateHandler.js +22 -0
- package/features/upload/WriteFileMetadata/WriteMetadataAfterUpdateHandler.js.map +1 -0
- package/features/upload/WriteFileMetadata/feature.js +2 -0
- package/features/upload/WriteFileMetadata/feature.js.map +1 -1
- package/graphql/FmGraphQLSchema.d.ts +3 -3
- package/graphql/FmGraphQLSchema.js +13 -12
- package/graphql/FmGraphQLSchema.js.map +1 -1
- package/package.json +17 -18
- package/features/FileModelContextualSchema.d.ts +0 -13
- package/features/FileModelContextualSchema.js +0 -31
- package/features/FileModelContextualSchema.js.map +0 -1
- package/features/assetDelivery/transformation/AssetKeyGenerator.js +0 -24
- package/features/assetDelivery/transformation/AssetKeyGenerator.js.map +0 -1
- package/features/assetDelivery/transformation/PassthroughAssetTransformationStrategy.d.ts +0 -9
- package/features/assetDelivery/transformation/PassthroughAssetTransformationStrategy.js +0 -13
- package/features/assetDelivery/transformation/PassthroughAssetTransformationStrategy.js.map +0 -1
- package/features/assetDelivery/transformation/WidthCollection.js.map +0 -1
- package/features/assetDelivery/transformation/utils.d.ts +0 -9
- package/features/assetDelivery/transformation/utils.js +0 -31
- package/features/assetDelivery/transformation/utils.js.map +0 -1
- /package/features/assetDelivery/{transformation → assetTypes/image}/WidthCollection.d.ts +0 -0
- /package/features/assetDelivery/{transformation → assetTypes/image}/WidthCollection.js +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AssetType } from "../abstractions/AssetType.js";
|
|
2
2
|
class TransformationAssetProcessor {
|
|
3
|
-
constructor(
|
|
4
|
-
this.
|
|
3
|
+
constructor(container){
|
|
4
|
+
this.container = container;
|
|
5
5
|
}
|
|
6
6
|
async process(assetRequest, asset) {
|
|
7
7
|
const { original } = assetRequest.getOptions();
|
|
@@ -9,15 +9,17 @@ class TransformationAssetProcessor {
|
|
|
9
9
|
console.log("Skip transformations; original asset was requested.");
|
|
10
10
|
return asset;
|
|
11
11
|
}
|
|
12
|
-
|
|
12
|
+
const assetTypes = this.container.resolveAll(AssetType);
|
|
13
|
+
const match = assetTypes.find((assetType)=>assetType.canHandle(asset));
|
|
14
|
+
if (!match) return asset;
|
|
15
|
+
try {
|
|
16
|
+
const handler = this.container.resolve(match.getHandlerAbstraction());
|
|
17
|
+
return handler.handle(assetRequest, asset);
|
|
18
|
+
} catch {
|
|
19
|
+
return asset;
|
|
20
|
+
}
|
|
13
21
|
}
|
|
14
22
|
}
|
|
15
|
-
|
|
16
|
-
implementation: TransformationAssetProcessor,
|
|
17
|
-
dependencies: [
|
|
18
|
-
AssetTransformationStrategy
|
|
19
|
-
]
|
|
20
|
-
});
|
|
21
|
-
export { TransformationAssetProcessor, TransformationAssetProcessorImpl };
|
|
23
|
+
export { TransformationAssetProcessor };
|
|
22
24
|
|
|
23
25
|
//# sourceMappingURL=TransformationAssetProcessor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/assetDelivery/transformation/TransformationAssetProcessor.js","sources":["../../../../src/features/assetDelivery/transformation/TransformationAssetProcessor.ts"],"sourcesContent":["import type { Asset } from \"~/delivery/AssetDelivery/Asset.js\";\nimport type { AssetRequest } from \"~/delivery/AssetDelivery/AssetRequest.js\";\nimport
|
|
1
|
+
{"version":3,"file":"features/assetDelivery/transformation/TransformationAssetProcessor.js","sources":["../../../../src/features/assetDelivery/transformation/TransformationAssetProcessor.ts"],"sourcesContent":["import type { Container } from \"@webiny/di\";\nimport type { Asset } from \"~/delivery/AssetDelivery/Asset.js\";\nimport type { AssetRequest } from \"~/delivery/AssetDelivery/AssetRequest.js\";\nimport type { IAssetProcessor } from \"../abstractions.js\";\nimport { AssetType } from \"../abstractions/AssetType.js\";\n\nexport class TransformationAssetProcessor implements IAssetProcessor {\n constructor(private readonly container: Container) {}\n\n async process(assetRequest: AssetRequest, asset: Asset): Promise<Asset> {\n const { original } = assetRequest.getOptions();\n\n if (original) {\n console.log(\"Skip transformations; original asset was requested.\");\n return asset;\n }\n\n const assetTypes = this.container.resolveAll(AssetType);\n const match = assetTypes.find(assetType => assetType.canHandle(asset));\n\n if (!match) {\n return asset;\n }\n\n try {\n const handler = this.container.resolve(match.getHandlerAbstraction());\n return handler.handle(assetRequest, asset);\n } catch {\n return asset;\n }\n }\n}\n"],"names":["TransformationAssetProcessor","container","assetRequest","asset","original","console","assetTypes","AssetType","match","assetType","handler"],"mappings":";AAMO,MAAMA;IACT,YAA6BC,SAAoB,CAAE;aAAtBA,SAAS,GAATA;IAAuB;IAEpD,MAAM,QAAQC,YAA0B,EAAEC,KAAY,EAAkB;QACpE,MAAM,EAAEC,QAAQ,EAAE,GAAGF,aAAa,UAAU;QAE5C,IAAIE,UAAU;YACVC,QAAQ,GAAG,CAAC;YACZ,OAAOF;QACX;QAEA,MAAMG,aAAa,IAAI,CAAC,SAAS,CAAC,UAAU,CAACC;QAC7C,MAAMC,QAAQF,WAAW,IAAI,CAACG,CAAAA,YAAaA,UAAU,SAAS,CAACN;QAE/D,IAAI,CAACK,OACD,OAAOL;QAGX,IAAI;YACA,MAAMO,UAAU,IAAI,CAAC,SAAS,CAAC,OAAO,CAACF,MAAM,qBAAqB;YAClE,OAAOE,QAAQ,MAAM,CAACR,cAAcC;QACxC,EAAE,OAAM;YACJ,OAAOA;QACX;IACJ;AACJ"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export { AssetKeyGenerator } from "./AssetKeyGenerator.js";
|
|
2
1
|
export { CallableContentsReader } from "./CallableContentsReader.js";
|
|
3
|
-
export { WidthCollection } from "
|
|
4
|
-
export {
|
|
2
|
+
export { WidthCollection } from "../assetTypes/image/WidthCollection.js";
|
|
3
|
+
export { type ImageFormat, SUPPORTED_OUTPUT_FORMATS, DEFAULT_IMAGE_QUALITY, contentTypeForFormat, formatFromContentType, resolveRequestedFormat, clampQuality } from "../assetTypes/image/imageFormat.js";
|
|
4
|
+
export { ImageAssetType, ImageAssetTypeHandler, AssetKeyGenerator, SUPPORTED_TRANSFORMABLE_IMAGES, getImageKey, getCropSignature, getOptimizedImageKeyPrefix, getOptimizedTransformedImageKeyPrefix } from "../assetTypes/image/index.js";
|
|
5
|
+
export type { AssetCrop, AssetImageEdit } from "../assetTypes/image/index.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { AssetKeyGenerator } from "./AssetKeyGenerator.js";
|
|
2
1
|
export { CallableContentsReader } from "./CallableContentsReader.js";
|
|
3
|
-
export { WidthCollection } from "
|
|
4
|
-
export {
|
|
2
|
+
export { WidthCollection } from "../assetTypes/image/WidthCollection.js";
|
|
3
|
+
export { DEFAULT_IMAGE_QUALITY, SUPPORTED_OUTPUT_FORMATS, clampQuality, contentTypeForFormat, formatFromContentType, resolveRequestedFormat } from "../assetTypes/image/imageFormat.js";
|
|
4
|
+
export { AssetKeyGenerator, ImageAssetType, ImageAssetTypeHandler, SUPPORTED_TRANSFORMABLE_IMAGES, getCropSignature, getImageKey, getOptimizedImageKeyPrefix, getOptimizedTransformedImageKeyPrefix } from "../assetTypes/image/index.js";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Result } from "@webiny/feature/api";
|
|
2
2
|
import { CreateFileRepository as RepositoryAbstraction } from "./abstractions.js";
|
|
3
3
|
import { CreateEntryUseCase } from "@webiny/api-headless-cms/features/contentEntry/CreateEntry";
|
|
4
|
-
import {
|
|
4
|
+
import { FileModelProvider } from "../../../domain/file/abstractions.js";
|
|
5
5
|
import type { File, FileInput } from "../../../domain/file/types.js";
|
|
6
6
|
declare class CreateFileRepositoryImpl implements RepositoryAbstraction.Interface {
|
|
7
7
|
private createEntry;
|
|
8
|
-
private
|
|
9
|
-
constructor(createEntry: CreateEntryUseCase.Interface,
|
|
8
|
+
private fileModelProvider;
|
|
9
|
+
constructor(createEntry: CreateEntryUseCase.Interface, fileModelProvider: FileModelProvider.Interface);
|
|
10
10
|
execute(data: FileInput): Promise<Result<File, RepositoryAbstraction.Error>>;
|
|
11
11
|
}
|
|
12
12
|
export declare const CreateFileRepository: typeof CreateFileRepositoryImpl & {
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { Result } from "@webiny/feature/api";
|
|
2
2
|
import { CreateFileRepository } from "./abstractions.js";
|
|
3
3
|
import { CreateEntryUseCase } from "@webiny/api-headless-cms/features/contentEntry/CreateEntry";
|
|
4
|
-
import {
|
|
4
|
+
import { FileModelProvider } from "../../../domain/file/abstractions.js";
|
|
5
5
|
import { EntryToFileMapper } from "../shared/EntryToFileMapper.js";
|
|
6
6
|
import { FileNotAuthorizedError, FilePersistenceError } from "../../../domain/file/errors.js";
|
|
7
7
|
import { FileInputToEntryInputMapper } from "../shared/FileInputToEntryInputMapper.js";
|
|
8
8
|
class CreateFileRepositoryImpl {
|
|
9
|
-
constructor(createEntry,
|
|
9
|
+
constructor(createEntry, fileModelProvider){
|
|
10
10
|
this.createEntry = createEntry;
|
|
11
|
-
this.
|
|
11
|
+
this.fileModelProvider = fileModelProvider;
|
|
12
12
|
}
|
|
13
13
|
async execute(data) {
|
|
14
|
-
const
|
|
14
|
+
const fileModel = await this.fileModelProvider.get();
|
|
15
|
+
const result = await this.createEntry.execute(fileModel, FileInputToEntryInputMapper.toEntry(data));
|
|
15
16
|
if (result.isFail()) {
|
|
16
17
|
if ("Cms/Entry/NotAuthorized" === result.error.code) return Result.fail(new FileNotAuthorizedError());
|
|
17
18
|
return Result.fail(new FilePersistenceError(result.error));
|
|
@@ -24,7 +25,7 @@ const CreateFileRepository_CreateFileRepository = CreateFileRepository.createImp
|
|
|
24
25
|
implementation: CreateFileRepositoryImpl,
|
|
25
26
|
dependencies: [
|
|
26
27
|
CreateEntryUseCase,
|
|
27
|
-
|
|
28
|
+
FileModelProvider
|
|
28
29
|
]
|
|
29
30
|
});
|
|
30
31
|
export { CreateFileRepository_CreateFileRepository as CreateFileRepository };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/file/CreateFile/CreateFileRepository.js","sources":["../../../../src/features/file/CreateFile/CreateFileRepository.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { CreateFileRepository as RepositoryAbstraction } from \"./abstractions.js\";\nimport { CreateEntryUseCase } from \"@webiny/api-headless-cms/features/contentEntry/CreateEntry\";\nimport {
|
|
1
|
+
{"version":3,"file":"features/file/CreateFile/CreateFileRepository.js","sources":["../../../../src/features/file/CreateFile/CreateFileRepository.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { CreateFileRepository as RepositoryAbstraction } from \"./abstractions.js\";\nimport { CreateEntryUseCase } from \"@webiny/api-headless-cms/features/contentEntry/CreateEntry\";\nimport { FileModelProvider } from \"~/domain/file/abstractions.js\";\nimport type { File, FileInput } from \"~/domain/file/types.js\";\nimport { EntryToFileMapper } from \"../shared/EntryToFileMapper.js\";\nimport { FileNotAuthorizedError, FilePersistenceError } from \"~/domain/file/errors.js\";\nimport { FileInputToEntryInputMapper } from \"~/features/file/shared/FileInputToEntryInputMapper.js\";\n\nclass CreateFileRepositoryImpl implements RepositoryAbstraction.Interface {\n constructor(\n private createEntry: CreateEntryUseCase.Interface,\n private fileModelProvider: FileModelProvider.Interface\n ) {}\n\n async execute(data: FileInput): Promise<Result<File, RepositoryAbstraction.Error>> {\n const fileModel = await this.fileModelProvider.get();\n const result = await this.createEntry.execute(\n fileModel,\n FileInputToEntryInputMapper.toEntry(data)\n );\n\n if (result.isFail()) {\n if (result.error.code === \"Cms/Entry/NotAuthorized\") {\n return Result.fail(new FileNotAuthorizedError());\n }\n\n return Result.fail(new FilePersistenceError(result.error));\n }\n\n const file = EntryToFileMapper.toFile(result.value);\n return Result.ok(file);\n }\n}\n\nexport const CreateFileRepository = RepositoryAbstraction.createImplementation({\n implementation: CreateFileRepositoryImpl,\n dependencies: [CreateEntryUseCase, FileModelProvider]\n});\n"],"names":["CreateFileRepositoryImpl","createEntry","fileModelProvider","data","fileModel","result","FileInputToEntryInputMapper","Result","FileNotAuthorizedError","FilePersistenceError","file","EntryToFileMapper","CreateFileRepository","RepositoryAbstraction","CreateEntryUseCase","FileModelProvider"],"mappings":";;;;;;;AASA,MAAMA;IACF,YACYC,WAAyC,EACzCC,iBAA8C,CACxD;aAFUD,WAAW,GAAXA;aACAC,iBAAiB,GAAjBA;IACT;IAEH,MAAM,QAAQC,IAAe,EAAsD;QAC/E,MAAMC,YAAY,MAAM,IAAI,CAAC,iBAAiB,CAAC,GAAG;QAClD,MAAMC,SAAS,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CACzCD,WACAE,4BAA4B,OAAO,CAACH;QAGxC,IAAIE,OAAO,MAAM,IAAI;YACjB,IAAIA,AAAsB,8BAAtBA,OAAO,KAAK,CAAC,IAAI,EACjB,OAAOE,OAAO,IAAI,CAAC,IAAIC;YAG3B,OAAOD,OAAO,IAAI,CAAC,IAAIE,qBAAqBJ,OAAO,KAAK;QAC5D;QAEA,MAAMK,OAAOC,kBAAkB,MAAM,CAACN,OAAO,KAAK;QAClD,OAAOE,OAAO,EAAE,CAACG;IACrB;AACJ;AAEO,MAAME,4CAAuBC,qBAAAA,oBAA0C,CAAC;IAC3E,gBAAgBb;IAChB,cAAc;QAACc;QAAoBC;KAAkB;AACzD"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Result } from "@webiny/feature/api";
|
|
2
2
|
import { DeleteEntryUseCase } from "@webiny/api-headless-cms/features/contentEntry/DeleteEntry";
|
|
3
3
|
import { DeleteFileRepository as RepositoryAbstraction } from "./abstractions.js";
|
|
4
|
-
import {
|
|
4
|
+
import { FileModelProvider } from "../../../domain/file/abstractions.js";
|
|
5
5
|
import { File } from "../../../domain/file/types.js";
|
|
6
6
|
declare class DeleteFileRepositoryImpl implements RepositoryAbstraction.Interface {
|
|
7
7
|
private deleteEntry;
|
|
8
|
-
private
|
|
9
|
-
constructor(deleteEntry: DeleteEntryUseCase.Interface,
|
|
8
|
+
private fileModelProvider;
|
|
9
|
+
constructor(deleteEntry: DeleteEntryUseCase.Interface, fileModelProvider: FileModelProvider.Interface);
|
|
10
10
|
delete(file: File): Promise<Result<void, RepositoryAbstraction.Error>>;
|
|
11
11
|
}
|
|
12
12
|
export declare const DeleteFileRepository: typeof DeleteFileRepositoryImpl & {
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { Result } from "@webiny/feature/api";
|
|
2
2
|
import { DeleteEntryUseCase } from "@webiny/api-headless-cms/features/contentEntry/DeleteEntry";
|
|
3
3
|
import { DeleteFileRepository } from "./abstractions.js";
|
|
4
|
-
import {
|
|
4
|
+
import { FileModelProvider } from "../../../domain/file/abstractions.js";
|
|
5
5
|
import { FileNotFoundError, FilePersistenceError } from "../../../domain/file/errors.js";
|
|
6
6
|
class DeleteFileRepositoryImpl {
|
|
7
|
-
constructor(deleteEntry,
|
|
7
|
+
constructor(deleteEntry, fileModelProvider){
|
|
8
8
|
this.deleteEntry = deleteEntry;
|
|
9
|
-
this.
|
|
9
|
+
this.fileModelProvider = fileModelProvider;
|
|
10
10
|
}
|
|
11
11
|
async delete(file) {
|
|
12
12
|
const entryId = `${file.id}#0001`;
|
|
13
|
-
const
|
|
13
|
+
const fileModel = await this.fileModelProvider.get();
|
|
14
|
+
const result = await this.deleteEntry.execute(fileModel, entryId);
|
|
14
15
|
if (result.isFail()) {
|
|
15
16
|
const error = result.error;
|
|
16
17
|
if ("Cms/Entry/NotFound" === error.code) return Result.fail(new FileNotFoundError(file.id));
|
|
@@ -23,7 +24,7 @@ const DeleteFileRepository_DeleteFileRepository = DeleteFileRepository.createImp
|
|
|
23
24
|
implementation: DeleteFileRepositoryImpl,
|
|
24
25
|
dependencies: [
|
|
25
26
|
DeleteEntryUseCase,
|
|
26
|
-
|
|
27
|
+
FileModelProvider
|
|
27
28
|
]
|
|
28
29
|
});
|
|
29
30
|
export { DeleteFileRepository_DeleteFileRepository as DeleteFileRepository };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/file/DeleteFile/DeleteFileRepository.js","sources":["../../../../src/features/file/DeleteFile/DeleteFileRepository.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { DeleteEntryUseCase } from \"@webiny/api-headless-cms/features/contentEntry/DeleteEntry\";\nimport { DeleteFileRepository as RepositoryAbstraction } from \"./abstractions.js\";\nimport {
|
|
1
|
+
{"version":3,"file":"features/file/DeleteFile/DeleteFileRepository.js","sources":["../../../../src/features/file/DeleteFile/DeleteFileRepository.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { DeleteEntryUseCase } from \"@webiny/api-headless-cms/features/contentEntry/DeleteEntry\";\nimport { DeleteFileRepository as RepositoryAbstraction } from \"./abstractions.js\";\nimport { FileModelProvider } from \"~/domain/file/abstractions.js\";\nimport { FileNotFoundError, FilePersistenceError } from \"~/domain/file/errors.js\";\nimport { File } from \"~/domain/file/types.js\";\n\nclass DeleteFileRepositoryImpl implements RepositoryAbstraction.Interface {\n constructor(\n private deleteEntry: DeleteEntryUseCase.Interface,\n private fileModelProvider: FileModelProvider.Interface\n ) {}\n\n async delete(file: File): Promise<Result<void, RepositoryAbstraction.Error>> {\n // Files are not versioned, so we're always deleting the same revision\n const entryId = `${file.id}#0001`;\n\n const fileModel = await this.fileModelProvider.get();\n const result = await this.deleteEntry.execute(fileModel, entryId);\n\n if (result.isFail()) {\n const error = result.error;\n if (error.code === \"Cms/Entry/NotFound\") {\n return Result.fail(new FileNotFoundError(file.id));\n }\n return Result.fail(new FilePersistenceError(result.error));\n }\n\n return Result.ok();\n }\n}\n\nexport const DeleteFileRepository = RepositoryAbstraction.createImplementation({\n implementation: DeleteFileRepositoryImpl,\n dependencies: [DeleteEntryUseCase, FileModelProvider]\n});\n"],"names":["DeleteFileRepositoryImpl","deleteEntry","fileModelProvider","file","entryId","fileModel","result","error","Result","FileNotFoundError","FilePersistenceError","DeleteFileRepository","RepositoryAbstraction","DeleteEntryUseCase","FileModelProvider"],"mappings":";;;;;AAOA,MAAMA;IACF,YACYC,WAAyC,EACzCC,iBAA8C,CACxD;aAFUD,WAAW,GAAXA;aACAC,iBAAiB,GAAjBA;IACT;IAEH,MAAM,OAAOC,IAAU,EAAsD;QAEzE,MAAMC,UAAU,GAAGD,KAAK,EAAE,CAAC,KAAK,CAAC;QAEjC,MAAME,YAAY,MAAM,IAAI,CAAC,iBAAiB,CAAC,GAAG;QAClD,MAAMC,SAAS,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAACD,WAAWD;QAEzD,IAAIE,OAAO,MAAM,IAAI;YACjB,MAAMC,QAAQD,OAAO,KAAK;YAC1B,IAAIC,AAAe,yBAAfA,MAAM,IAAI,EACV,OAAOC,OAAO,IAAI,CAAC,IAAIC,kBAAkBN,KAAK,EAAE;YAEpD,OAAOK,OAAO,IAAI,CAAC,IAAIE,qBAAqBJ,OAAO,KAAK;QAC5D;QAEA,OAAOE,OAAO,EAAE;IACpB;AACJ;AAEO,MAAMG,4CAAuBC,qBAAAA,oBAA0C,CAAC;IAC3E,gBAAgBZ;IAChB,cAAc;QAACa;QAAoBC;KAAkB;AACzD"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { CmsModel } from "@webiny/api-headless-cms/types";
|
|
2
|
+
import { GetModelUseCase } from "@webiny/api-headless-cms/features/contentModel/GetModel/index.js";
|
|
3
|
+
import { FileModelProvider as Abstraction } from "../../domain/file/abstractions.js";
|
|
4
|
+
/**
|
|
5
|
+
* Resolves the tenant's `fmFile` model on demand.
|
|
6
|
+
*
|
|
7
|
+
* Two things this deliberately does NOT do, both of which the initializer it replaces did:
|
|
8
|
+
*
|
|
9
|
+
* - **No memoization.** `ModelsFetcher` already caches the model list per request (`ModelCache` is a
|
|
10
|
+
* per-request `createMemoryCache()`, see `ContentModelFeature`), so a second cache would buy only
|
|
11
|
+
* a repeat access-control check and an array lookup, at the cost of two lifetimes to reason about.
|
|
12
|
+
* - **No `withoutAuthorization`.** `fmFile` is a private model and `PrivateModelBuilder` sets
|
|
13
|
+
* `authorization: false`, which makes `AccessControl.modelAuthorizationDisabled()` short-circuit
|
|
14
|
+
* `canAccessModel()` to true for every identity — so the wrapper changed nothing. Confirmed
|
|
15
|
+
* against `filesSecurity.test.ts`, which exercises `fm.file`-only identities holding no CMS
|
|
16
|
+
* content-model permissions.
|
|
17
|
+
*
|
|
18
|
+
* `GetModelUseCase` is an ordinary constructor dependency: this provider is only constructed when a
|
|
19
|
+
* consumer first awaits `get()`, which happens during request handling — after the CMS has
|
|
20
|
+
* registered everything the use case needs. That timing is what previously forced the lazy
|
|
21
|
+
* `container.resolve()` inside the initializer.
|
|
22
|
+
*/
|
|
23
|
+
declare class FileModelProviderImpl implements Abstraction.Interface {
|
|
24
|
+
private getModel;
|
|
25
|
+
constructor(getModel: GetModelUseCase.Interface);
|
|
26
|
+
get(): Promise<CmsModel>;
|
|
27
|
+
}
|
|
28
|
+
export declare const FileModelProvider: typeof FileModelProviderImpl & {
|
|
29
|
+
__abstraction: import("@webiny/di").Abstraction<import("~/domain/file/abstractions.js").IFileModelProvider>;
|
|
30
|
+
};
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { GetModelUseCase } from "@webiny/api-headless-cms/features/contentModel/GetModel/index.js";
|
|
2
|
+
import { FileModelProvider } from "../../domain/file/abstractions.js";
|
|
3
|
+
import { FILE_MODEL_ID } from "../../domain/file/file.model.js";
|
|
4
|
+
class FileModelProviderImpl {
|
|
5
|
+
constructor(getModel){
|
|
6
|
+
this.getModel = getModel;
|
|
7
|
+
}
|
|
8
|
+
async get() {
|
|
9
|
+
const result = await this.getModel.execute(FILE_MODEL_ID);
|
|
10
|
+
if (result.isFail()) throw result.error;
|
|
11
|
+
return result.value;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
const FileModelProvider_FileModelProvider = FileModelProvider.createImplementation({
|
|
15
|
+
implementation: FileModelProviderImpl,
|
|
16
|
+
dependencies: [
|
|
17
|
+
GetModelUseCase
|
|
18
|
+
]
|
|
19
|
+
});
|
|
20
|
+
export { FileModelProvider_FileModelProvider as FileModelProvider };
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=FileModelProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"features/file/FileModelProvider.js","sources":["../../../src/features/file/FileModelProvider.ts"],"sourcesContent":["import type { CmsModel } from \"@webiny/api-headless-cms/types\";\nimport { GetModelUseCase } from \"@webiny/api-headless-cms/features/contentModel/GetModel/index.js\";\nimport { FileModelProvider as Abstraction } from \"~/domain/file/abstractions.js\";\nimport { FILE_MODEL_ID } from \"~/domain/file/file.model.js\";\n\n/**\n * Resolves the tenant's `fmFile` model on demand.\n *\n * Two things this deliberately does NOT do, both of which the initializer it replaces did:\n *\n * - **No memoization.** `ModelsFetcher` already caches the model list per request (`ModelCache` is a\n * per-request `createMemoryCache()`, see `ContentModelFeature`), so a second cache would buy only\n * a repeat access-control check and an array lookup, at the cost of two lifetimes to reason about.\n * - **No `withoutAuthorization`.** `fmFile` is a private model and `PrivateModelBuilder` sets\n * `authorization: false`, which makes `AccessControl.modelAuthorizationDisabled()` short-circuit\n * `canAccessModel()` to true for every identity — so the wrapper changed nothing. Confirmed\n * against `filesSecurity.test.ts`, which exercises `fm.file`-only identities holding no CMS\n * content-model permissions.\n *\n * `GetModelUseCase` is an ordinary constructor dependency: this provider is only constructed when a\n * consumer first awaits `get()`, which happens during request handling — after the CMS has\n * registered everything the use case needs. That timing is what previously forced the lazy\n * `container.resolve()` inside the initializer.\n */\nclass FileModelProviderImpl implements Abstraction.Interface {\n constructor(private getModel: GetModelUseCase.Interface) {}\n\n async get(): Promise<CmsModel> {\n const result = await this.getModel.execute(FILE_MODEL_ID);\n if (result.isFail()) {\n throw result.error;\n }\n return result.value;\n }\n}\n\nexport const FileModelProvider = Abstraction.createImplementation({\n implementation: FileModelProviderImpl,\n dependencies: [GetModelUseCase]\n});\n"],"names":["FileModelProviderImpl","getModel","result","FILE_MODEL_ID","FileModelProvider","Abstraction","GetModelUseCase"],"mappings":";;;AAwBA,MAAMA;IACF,YAAoBC,QAAmC,CAAE;aAArCA,QAAQ,GAARA;IAAsC;IAE1D,MAAM,MAAyB;QAC3B,MAAMC,SAAS,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAACC;QAC3C,IAAID,OAAO,MAAM,IACb,MAAMA,OAAO,KAAK;QAEtB,OAAOA,OAAO,KAAK;IACvB;AACJ;AAEO,MAAME,sCAAoBC,kBAAAA,oBAAgC,CAAC;IAC9D,gBAAgBL;IAChB,cAAc;QAACM;KAAgB;AACnC"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Result } from "@webiny/feature/api";
|
|
2
2
|
import { GetEntryByIdUseCase } from "@webiny/api-headless-cms/features/contentEntry/GetEntryById";
|
|
3
3
|
import { GetFileRepository as RepositoryAbstraction } from "./abstractions.js";
|
|
4
|
-
import {
|
|
4
|
+
import { FileModelProvider } from "../../../domain/file/abstractions.js";
|
|
5
5
|
import type { File } from "../../../domain/file/types.js";
|
|
6
6
|
declare class GetFileRepositoryImpl implements RepositoryAbstraction.Interface {
|
|
7
7
|
private getEntryById;
|
|
8
|
-
private
|
|
9
|
-
constructor(getEntryById: GetEntryByIdUseCase.Interface,
|
|
8
|
+
private fileModelProvider;
|
|
9
|
+
constructor(getEntryById: GetEntryByIdUseCase.Interface, fileModelProvider: FileModelProvider.Interface);
|
|
10
10
|
execute(id: string): Promise<Result<File, RepositoryAbstraction.Error>>;
|
|
11
11
|
}
|
|
12
12
|
export declare const GetFileRepository: typeof GetFileRepositoryImpl & {
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { Result } from "@webiny/feature/api";
|
|
2
2
|
import { GetEntryByIdUseCase } from "@webiny/api-headless-cms/features/contentEntry/GetEntryById";
|
|
3
3
|
import { GetFileRepository } from "./abstractions.js";
|
|
4
|
-
import {
|
|
4
|
+
import { FileModelProvider } from "../../../domain/file/abstractions.js";
|
|
5
5
|
import { FileNotAuthorizedError, FileNotFoundError, FilePersistenceError } from "../../../domain/file/errors.js";
|
|
6
6
|
import { EntryToFileMapper } from "../shared/EntryToFileMapper.js";
|
|
7
7
|
class GetFileRepositoryImpl {
|
|
8
|
-
constructor(getEntryById,
|
|
8
|
+
constructor(getEntryById, fileModelProvider){
|
|
9
9
|
this.getEntryById = getEntryById;
|
|
10
|
-
this.
|
|
10
|
+
this.fileModelProvider = fileModelProvider;
|
|
11
11
|
}
|
|
12
12
|
async execute(id) {
|
|
13
|
-
const
|
|
13
|
+
const fileModel = await this.fileModelProvider.get();
|
|
14
|
+
const result = await this.getEntryById.execute(fileModel, `${id}#0001`);
|
|
14
15
|
if (result.isFail()) {
|
|
15
16
|
const error = result.error;
|
|
16
17
|
if ("Cms/Entry/NotFound" === error.code) return Result.fail(new FileNotFoundError(id));
|
|
@@ -25,7 +26,7 @@ const GetFileRepository_GetFileRepository = GetFileRepository.createImplementati
|
|
|
25
26
|
implementation: GetFileRepositoryImpl,
|
|
26
27
|
dependencies: [
|
|
27
28
|
GetEntryByIdUseCase,
|
|
28
|
-
|
|
29
|
+
FileModelProvider
|
|
29
30
|
]
|
|
30
31
|
});
|
|
31
32
|
export { GetFileRepository_GetFileRepository as GetFileRepository };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/file/GetFile/GetFileRepository.js","sources":["../../../../src/features/file/GetFile/GetFileRepository.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { GetEntryByIdUseCase } from \"@webiny/api-headless-cms/features/contentEntry/GetEntryById\";\nimport { GetFileRepository as RepositoryAbstraction } from \"./abstractions.js\";\nimport {
|
|
1
|
+
{"version":3,"file":"features/file/GetFile/GetFileRepository.js","sources":["../../../../src/features/file/GetFile/GetFileRepository.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { GetEntryByIdUseCase } from \"@webiny/api-headless-cms/features/contentEntry/GetEntryById\";\nimport { GetFileRepository as RepositoryAbstraction } from \"./abstractions.js\";\nimport { FileModelProvider } from \"~/domain/file/abstractions.js\";\nimport type { File } from \"~/domain/file/types.js\";\nimport {\n FileNotAuthorizedError,\n FileNotFoundError,\n FilePersistenceError\n} from \"~/domain/file/errors.js\";\nimport { EntryToFileMapper } from \"../shared/EntryToFileMapper.js\";\n\nclass GetFileRepositoryImpl implements RepositoryAbstraction.Interface {\n constructor(\n private getEntryById: GetEntryByIdUseCase.Interface,\n private fileModelProvider: FileModelProvider.Interface\n ) {}\n\n async execute(id: string): Promise<Result<File, RepositoryAbstraction.Error>> {\n const fileModel = await this.fileModelProvider.get();\n const result = await this.getEntryById.execute(fileModel, `${id}#0001`);\n\n if (result.isFail()) {\n const error = result.error;\n\n if (error.code === \"Cms/Entry/NotFound\") {\n return Result.fail(new FileNotFoundError(id));\n }\n\n if (error.code === \"Cms/Entry/NotAuthorized\") {\n return Result.fail(new FileNotAuthorizedError());\n }\n return Result.fail(new FilePersistenceError(result.error));\n }\n\n const file = EntryToFileMapper.toFile(result.value);\n\n return Result.ok(file);\n }\n}\n\nexport const GetFileRepository = RepositoryAbstraction.createImplementation({\n implementation: GetFileRepositoryImpl,\n dependencies: [GetEntryByIdUseCase, FileModelProvider]\n});\n"],"names":["GetFileRepositoryImpl","getEntryById","fileModelProvider","id","fileModel","result","error","Result","FileNotFoundError","FileNotAuthorizedError","FilePersistenceError","file","EntryToFileMapper","GetFileRepository","RepositoryAbstraction","GetEntryByIdUseCase","FileModelProvider"],"mappings":";;;;;;AAYA,MAAMA;IACF,YACYC,YAA2C,EAC3CC,iBAA8C,CACxD;aAFUD,YAAY,GAAZA;aACAC,iBAAiB,GAAjBA;IACT;IAEH,MAAM,QAAQC,EAAU,EAAsD;QAC1E,MAAMC,YAAY,MAAM,IAAI,CAAC,iBAAiB,CAAC,GAAG;QAClD,MAAMC,SAAS,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,CAACD,WAAW,GAAGD,GAAG,KAAK,CAAC;QAEtE,IAAIE,OAAO,MAAM,IAAI;YACjB,MAAMC,QAAQD,OAAO,KAAK;YAE1B,IAAIC,AAAe,yBAAfA,MAAM,IAAI,EACV,OAAOC,OAAO,IAAI,CAAC,IAAIC,kBAAkBL;YAG7C,IAAIG,AAAe,8BAAfA,MAAM,IAAI,EACV,OAAOC,OAAO,IAAI,CAAC,IAAIE;YAE3B,OAAOF,OAAO,IAAI,CAAC,IAAIG,qBAAqBL,OAAO,KAAK;QAC5D;QAEA,MAAMM,OAAOC,kBAAkB,MAAM,CAACP,OAAO,KAAK;QAElD,OAAOE,OAAO,EAAE,CAACI;IACrB;AACJ;AAEO,MAAME,sCAAoBC,kBAAAA,oBAA0C,CAAC;IACxE,gBAAgBd;IAChB,cAAc;QAACe;QAAqBC;KAAkB;AAC1D"}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { Result } from "@webiny/feature/api";
|
|
2
2
|
import { ListLatestEntriesUseCase } from "@webiny/api-headless-cms/features/contentEntry/ListEntries/index.js";
|
|
3
3
|
import { ListFilesInput, ListFilesOutput, ListFilesRepository as RepositoryAbstraction } from "./abstractions.js";
|
|
4
|
-
import {
|
|
4
|
+
import { FileModelProvider } from "../../../domain/file/abstractions.js";
|
|
5
5
|
import { CmsWhereMapper } from "@webiny/api-headless-cms";
|
|
6
6
|
import { CmsSortMapper } from "@webiny/api-headless-cms";
|
|
7
7
|
declare class ListFilesRepositoryImpl implements RepositoryAbstraction.Interface {
|
|
8
8
|
private listLatestEntries;
|
|
9
|
-
private
|
|
9
|
+
private fileModelProvider;
|
|
10
10
|
private cmsWhereMapper;
|
|
11
11
|
private cmsSortMapper;
|
|
12
|
-
constructor(listLatestEntries: ListLatestEntriesUseCase.Interface,
|
|
12
|
+
constructor(listLatestEntries: ListLatestEntriesUseCase.Interface, fileModelProvider: FileModelProvider.Interface, cmsWhereMapper: CmsWhereMapper.Interface, cmsSortMapper: CmsSortMapper.Interface);
|
|
13
13
|
execute(input: ListFilesInput): Promise<Result<ListFilesOutput, RepositoryAbstraction.Error>>;
|
|
14
14
|
}
|
|
15
15
|
export declare const ListFilesRepository: typeof ListFilesRepositoryImpl & {
|
|
@@ -1,27 +1,28 @@
|
|
|
1
1
|
import { Result } from "@webiny/feature/api";
|
|
2
2
|
import { ListLatestEntriesUseCase } from "@webiny/api-headless-cms/features/contentEntry/ListEntries/index.js";
|
|
3
3
|
import { ListFilesRepository } from "./abstractions.js";
|
|
4
|
-
import {
|
|
4
|
+
import { FileModelProvider } from "../../../domain/file/abstractions.js";
|
|
5
5
|
import { FilePersistenceError } from "../../../domain/file/errors.js";
|
|
6
6
|
import { EntryToFileMapper } from "../shared/EntryToFileMapper.js";
|
|
7
7
|
import { CmsSortMapper, CmsWhereMapper } from "@webiny/api-headless-cms";
|
|
8
8
|
class ListFilesRepositoryImpl {
|
|
9
|
-
constructor(listLatestEntries,
|
|
9
|
+
constructor(listLatestEntries, fileModelProvider, cmsWhereMapper, cmsSortMapper){
|
|
10
10
|
this.listLatestEntries = listLatestEntries;
|
|
11
|
-
this.
|
|
11
|
+
this.fileModelProvider = fileModelProvider;
|
|
12
12
|
this.cmsWhereMapper = cmsWhereMapper;
|
|
13
13
|
this.cmsSortMapper = cmsSortMapper;
|
|
14
14
|
}
|
|
15
15
|
async execute(input) {
|
|
16
|
+
const fileModel = await this.fileModelProvider.get();
|
|
16
17
|
const where = this.cmsWhereMapper.map({
|
|
17
18
|
input: input.where || {},
|
|
18
|
-
fields:
|
|
19
|
+
fields: fileModel.fields
|
|
19
20
|
});
|
|
20
21
|
const sort = this.cmsSortMapper.map({
|
|
21
22
|
input: input.sort,
|
|
22
|
-
fields:
|
|
23
|
+
fields: fileModel.fields
|
|
23
24
|
});
|
|
24
|
-
const result = await this.listLatestEntries.execute(
|
|
25
|
+
const result = await this.listLatestEntries.execute(fileModel, {
|
|
25
26
|
where,
|
|
26
27
|
limit: input.limit || 40,
|
|
27
28
|
after: input.after || void 0,
|
|
@@ -43,7 +44,7 @@ const ListFilesRepository_ListFilesRepository = ListFilesRepository.createImplem
|
|
|
43
44
|
implementation: ListFilesRepositoryImpl,
|
|
44
45
|
dependencies: [
|
|
45
46
|
ListLatestEntriesUseCase,
|
|
46
|
-
|
|
47
|
+
FileModelProvider,
|
|
47
48
|
CmsWhereMapper,
|
|
48
49
|
CmsSortMapper
|
|
49
50
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/file/ListFiles/ListFilesRepository.js","sources":["../../../../src/features/file/ListFiles/ListFilesRepository.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { ListLatestEntriesUseCase } from \"@webiny/api-headless-cms/features/contentEntry/ListEntries/index.js\";\nimport {\n ListFilesInput,\n ListFilesOutput,\n ListFilesRepository as RepositoryAbstraction\n} from \"./abstractions.js\";\nimport {
|
|
1
|
+
{"version":3,"file":"features/file/ListFiles/ListFilesRepository.js","sources":["../../../../src/features/file/ListFiles/ListFilesRepository.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { ListLatestEntriesUseCase } from \"@webiny/api-headless-cms/features/contentEntry/ListEntries/index.js\";\nimport {\n ListFilesInput,\n ListFilesOutput,\n ListFilesRepository as RepositoryAbstraction\n} from \"./abstractions.js\";\nimport { FileModelProvider } from \"~/domain/file/abstractions.js\";\nimport { FilePersistenceError } from \"~/domain/file/errors.js\";\nimport { EntryToFileMapper } from \"../shared/EntryToFileMapper.js\";\nimport { CmsWhereMapper } from \"@webiny/api-headless-cms\";\nimport { CmsSortMapper } from \"@webiny/api-headless-cms\";\nimport { GenericRecord } from \"@webiny/api/types.js\";\n\nclass ListFilesRepositoryImpl implements RepositoryAbstraction.Interface {\n constructor(\n private listLatestEntries: ListLatestEntriesUseCase.Interface,\n private fileModelProvider: FileModelProvider.Interface,\n private cmsWhereMapper: CmsWhereMapper.Interface,\n private cmsSortMapper: CmsSortMapper.Interface\n ) {}\n\n async execute(\n input: ListFilesInput\n ): Promise<Result<ListFilesOutput, RepositoryAbstraction.Error>> {\n const fileModel = await this.fileModelProvider.get();\n\n const where = this.cmsWhereMapper.map<GenericRecord>({\n input: input.where || {},\n fields: fileModel.fields\n });\n\n const sort = this.cmsSortMapper.map({\n input: input.sort,\n fields: fileModel.fields\n });\n\n const result = await this.listLatestEntries.execute(fileModel, {\n where,\n limit: input.limit || 40,\n after: input.after || undefined,\n sort: sort || [\"id_DESC\"],\n search: input.search\n });\n\n if (result.isFail()) {\n return Result.fail(new FilePersistenceError(result.error));\n }\n\n const { entries, meta } = result.value;\n\n const files = entries.map(entry => EntryToFileMapper.toFile(entry));\n\n return Result.ok({\n items: files,\n meta\n });\n }\n}\n\nexport const ListFilesRepository = RepositoryAbstraction.createImplementation({\n implementation: ListFilesRepositoryImpl,\n dependencies: [ListLatestEntriesUseCase, FileModelProvider, CmsWhereMapper, CmsSortMapper]\n});\n"],"names":["ListFilesRepositoryImpl","listLatestEntries","fileModelProvider","cmsWhereMapper","cmsSortMapper","input","fileModel","where","sort","result","undefined","Result","FilePersistenceError","entries","meta","files","entry","EntryToFileMapper","ListFilesRepository","RepositoryAbstraction","ListLatestEntriesUseCase","FileModelProvider","CmsWhereMapper","CmsSortMapper"],"mappings":";;;;;;;AAcA,MAAMA;IACF,YACYC,iBAAqD,EACrDC,iBAA8C,EAC9CC,cAAwC,EACxCC,aAAsC,CAChD;aAJUH,iBAAiB,GAAjBA;aACAC,iBAAiB,GAAjBA;aACAC,cAAc,GAAdA;aACAC,aAAa,GAAbA;IACT;IAEH,MAAM,QACFC,KAAqB,EACwC;QAC7D,MAAMC,YAAY,MAAM,IAAI,CAAC,iBAAiB,CAAC,GAAG;QAElD,MAAMC,QAAQ,IAAI,CAAC,cAAc,CAAC,GAAG,CAAgB;YACjD,OAAOF,MAAM,KAAK,IAAI,CAAC;YACvB,QAAQC,UAAU,MAAM;QAC5B;QAEA,MAAME,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC;YAChC,OAAOH,MAAM,IAAI;YACjB,QAAQC,UAAU,MAAM;QAC5B;QAEA,MAAMG,SAAS,MAAM,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAACH,WAAW;YAC3DC;YACA,OAAOF,MAAM,KAAK,IAAI;YACtB,OAAOA,MAAM,KAAK,IAAIK;YACtB,MAAMF,QAAQ;gBAAC;aAAU;YACzB,QAAQH,MAAM,MAAM;QACxB;QAEA,IAAII,OAAO,MAAM,IACb,OAAOE,OAAO,IAAI,CAAC,IAAIC,qBAAqBH,OAAO,KAAK;QAG5D,MAAM,EAAEI,OAAO,EAAEC,IAAI,EAAE,GAAGL,OAAO,KAAK;QAEtC,MAAMM,QAAQF,QAAQ,GAAG,CAACG,CAAAA,QAASC,kBAAkB,MAAM,CAACD;QAE5D,OAAOL,OAAO,EAAE,CAAC;YACb,OAAOI;YACPD;QACJ;IACJ;AACJ;AAEO,MAAMI,0CAAsBC,oBAAAA,oBAA0C,CAAC;IAC1E,gBAAgBnB;IAChB,cAAc;QAACoB;QAA0BC;QAAmBC;QAAgBC;KAAc;AAC9F"}
|
|
@@ -14,10 +14,15 @@ interface ImageItem {
|
|
|
14
14
|
declare class ListImagesByTagToolImpl implements IAiSdkTool<Input> {
|
|
15
15
|
private listFiles;
|
|
16
16
|
readonly name = "listImagesByTag";
|
|
17
|
+
readonly title = "List images by tag";
|
|
17
18
|
readonly description = "Lists images from the file manager filtered by a given tag. Returns name, type, and tags for each image.";
|
|
18
19
|
readonly inputSchema: z.ZodObject<{
|
|
19
20
|
tag: z.ZodString;
|
|
20
21
|
}, z.core.$strip>;
|
|
22
|
+
readonly annotations: {
|
|
23
|
+
readOnlyHint: boolean;
|
|
24
|
+
idempotentHint: boolean;
|
|
25
|
+
};
|
|
21
26
|
constructor(listFiles: ListFilesUseCase.Interface);
|
|
22
27
|
execute(input: Input): Promise<ImageItem[]>;
|
|
23
28
|
}
|
|
@@ -8,8 +8,13 @@ class ListImagesByTagToolImpl {
|
|
|
8
8
|
constructor(listFiles){
|
|
9
9
|
this.listFiles = listFiles;
|
|
10
10
|
this.name = "listImagesByTag";
|
|
11
|
+
this.title = "List images by tag";
|
|
11
12
|
this.description = "Lists images from the file manager filtered by a given tag. Returns name, type, and tags for each image.";
|
|
12
13
|
this.inputSchema = inputSchema;
|
|
14
|
+
this.annotations = {
|
|
15
|
+
readOnlyHint: true,
|
|
16
|
+
idempotentHint: true
|
|
17
|
+
};
|
|
13
18
|
}
|
|
14
19
|
async execute(input) {
|
|
15
20
|
console.log("Call images tool", input);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/file/ListImagesByTagTool/ListImagesByTagTool.js","sources":["../../../../src/features/file/ListImagesByTagTool/ListImagesByTagTool.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { AiSdkTool, type IAiSdkTool } from \"@webiny/api-core/features/ai/index.js\";\nimport { ListFilesUseCase } from \"~/features/file/ListFiles/index.js\";\n\nconst inputSchema = z.object({\n tag: z.string().describe(\"Tag to filter images by\")\n});\n\ntype Input = z.infer<typeof inputSchema>;\n\ninterface ImageItem {\n id: string;\n name: string;\n type: string;\n tags: string[];\n}\n\nclass ListImagesByTagToolImpl implements IAiSdkTool<Input> {\n readonly name = \"listImagesByTag\";\n readonly description =\n \"Lists images from the file manager filtered by a given tag. Returns name, type, and tags for each image.\";\n readonly inputSchema = inputSchema;\n\n constructor(private listFiles: ListFilesUseCase.Interface) {}\n\n async execute(input: Input): Promise<ImageItem[]> {\n console.log(\"Call images tool\", input);\n const result = await this.listFiles.execute({\n where: {\n type_startsWith: \"image/\",\n tags_in: [input.tag]\n },\n limit: 50\n });\n\n if (result.isFail()) {\n return [];\n }\n\n return result.value.items.map(file => ({\n id: file.id,\n name: file.name,\n type: file.type,\n tags: file.tags\n }));\n }\n}\n\nexport const ListImagesByTagTool = AiSdkTool.createImplementation({\n implementation: ListImagesByTagToolImpl,\n dependencies: [ListFilesUseCase]\n});\n"],"names":["inputSchema","z","ListImagesByTagToolImpl","listFiles","input","console","result","file","ListImagesByTagTool","AiSdkTool","ListFilesUseCase"],"mappings":";;;AAIA,MAAMA,cAAcC,EAAE,MAAM,CAAC;IACzB,KAAKA,EAAE,MAAM,GAAG,QAAQ,CAAC;AAC7B;AAWA,MAAMC;
|
|
1
|
+
{"version":3,"file":"features/file/ListImagesByTagTool/ListImagesByTagTool.js","sources":["../../../../src/features/file/ListImagesByTagTool/ListImagesByTagTool.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { AiSdkTool, type IAiSdkTool } from \"@webiny/api-core/features/ai/index.js\";\nimport { ListFilesUseCase } from \"~/features/file/ListFiles/index.js\";\n\nconst inputSchema = z.object({\n tag: z.string().describe(\"Tag to filter images by\")\n});\n\ntype Input = z.infer<typeof inputSchema>;\n\ninterface ImageItem {\n id: string;\n name: string;\n type: string;\n tags: string[];\n}\n\nclass ListImagesByTagToolImpl implements IAiSdkTool<Input> {\n readonly name = \"listImagesByTag\";\n readonly title = \"List images by tag\";\n readonly description =\n \"Lists images from the file manager filtered by a given tag. Returns name, type, and tags for each image.\";\n readonly inputSchema = inputSchema;\n readonly annotations = { readOnlyHint: true, idempotentHint: true };\n\n constructor(private listFiles: ListFilesUseCase.Interface) {}\n\n async execute(input: Input): Promise<ImageItem[]> {\n console.log(\"Call images tool\", input);\n const result = await this.listFiles.execute({\n where: {\n type_startsWith: \"image/\",\n tags_in: [input.tag]\n },\n limit: 50\n });\n\n if (result.isFail()) {\n return [];\n }\n\n return result.value.items.map(file => ({\n id: file.id,\n name: file.name,\n type: file.type,\n tags: file.tags\n }));\n }\n}\n\nexport const ListImagesByTagTool = AiSdkTool.createImplementation({\n implementation: ListImagesByTagToolImpl,\n dependencies: [ListFilesUseCase]\n});\n"],"names":["inputSchema","z","ListImagesByTagToolImpl","listFiles","input","console","result","file","ListImagesByTagTool","AiSdkTool","ListFilesUseCase"],"mappings":";;;AAIA,MAAMA,cAAcC,EAAE,MAAM,CAAC;IACzB,KAAKA,EAAE,MAAM,GAAG,QAAQ,CAAC;AAC7B;AAWA,MAAMC;IAQF,YAAoBC,SAAqC,CAAE;aAAvCA,SAAS,GAATA;aAPX,IAAI,GAAG;aACP,KAAK,GAAG;aACR,WAAW,GAChB;aACK,WAAW,GAAGH;aACd,WAAW,GAAG;YAAE,cAAc;YAAM,gBAAgB;QAAK;IAEN;IAE5D,MAAM,QAAQI,KAAY,EAAwB;QAC9CC,QAAQ,GAAG,CAAC,oBAAoBD;QAChC,MAAME,SAAS,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;YACxC,OAAO;gBACH,iBAAiB;gBACjB,SAAS;oBAACF,MAAM,GAAG;iBAAC;YACxB;YACA,OAAO;QACX;QAEA,IAAIE,OAAO,MAAM,IACb,OAAO,EAAE;QAGb,OAAOA,OAAO,KAAK,CAAC,KAAK,CAAC,GAAG,CAACC,CAAAA,OAAS;gBACnC,IAAIA,KAAK,EAAE;gBACX,MAAMA,KAAK,IAAI;gBACf,MAAMA,KAAK,IAAI;gBACf,MAAMA,KAAK,IAAI;YACnB;IACJ;AACJ;AAEO,MAAMC,sBAAsBC,UAAU,oBAAoB,CAAC;IAC9D,gBAAgBP;IAChB,cAAc;QAACQ;KAAiB;AACpC"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { Result } from "@webiny/feature/api";
|
|
2
2
|
import { GetUniqueFieldValuesUseCase } from "@webiny/api-headless-cms/features/contentEntry/GetUniqueFieldValues";
|
|
3
3
|
import { ListTagsInput, ListTagsRepository as RepositoryAbstraction, TagItem } from "./abstractions.js";
|
|
4
|
-
import {
|
|
4
|
+
import { FileModelProvider } from "../../../domain/file/abstractions.js";
|
|
5
5
|
import { CmsWhereMapper } from "@webiny/api-headless-cms";
|
|
6
6
|
declare class ListTagsRepositoryImpl implements RepositoryAbstraction.Interface {
|
|
7
7
|
private getUniqueFieldValues;
|
|
8
|
-
private
|
|
8
|
+
private fileModelProvider;
|
|
9
9
|
private cmsWhereMapper;
|
|
10
|
-
constructor(getUniqueFieldValues: GetUniqueFieldValuesUseCase.Interface,
|
|
10
|
+
constructor(getUniqueFieldValues: GetUniqueFieldValuesUseCase.Interface, fileModelProvider: FileModelProvider.Interface, cmsWhereMapper: CmsWhereMapper.Interface);
|
|
11
11
|
execute(input: ListTagsInput): Promise<Result<TagItem[], RepositoryAbstraction.Error>>;
|
|
12
12
|
}
|
|
13
13
|
export declare const ListTagsRepository: typeof ListTagsRepositoryImpl & {
|
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
import { Result } from "@webiny/feature/api";
|
|
2
2
|
import { GetUniqueFieldValuesUseCase } from "@webiny/api-headless-cms/features/contentEntry/GetUniqueFieldValues";
|
|
3
3
|
import { ListTagsRepository } from "./abstractions.js";
|
|
4
|
-
import {
|
|
4
|
+
import { FileModelProvider } from "../../../domain/file/abstractions.js";
|
|
5
5
|
import { FilePersistenceError } from "../../../domain/file/errors.js";
|
|
6
6
|
import { CmsWhereMapper } from "@webiny/api-headless-cms";
|
|
7
7
|
class ListTagsRepositoryImpl {
|
|
8
|
-
constructor(getUniqueFieldValues,
|
|
8
|
+
constructor(getUniqueFieldValues, fileModelProvider, cmsWhereMapper){
|
|
9
9
|
this.getUniqueFieldValues = getUniqueFieldValues;
|
|
10
|
-
this.
|
|
10
|
+
this.fileModelProvider = fileModelProvider;
|
|
11
11
|
this.cmsWhereMapper = cmsWhereMapper;
|
|
12
12
|
}
|
|
13
13
|
async execute(input) {
|
|
14
|
-
const
|
|
14
|
+
const fileModel = await this.fileModelProvider.get();
|
|
15
|
+
const result = await this.getUniqueFieldValues.execute(fileModel, {
|
|
15
16
|
fieldId: "tags",
|
|
16
17
|
where: this.cmsWhereMapper.map({
|
|
17
18
|
input: {
|
|
18
19
|
...input.where || {},
|
|
19
20
|
latest: true
|
|
20
21
|
},
|
|
21
|
-
fields:
|
|
22
|
+
fields: fileModel.fields
|
|
22
23
|
})
|
|
23
24
|
});
|
|
24
25
|
if (result.isFail()) return Result.fail(new FilePersistenceError(result.error));
|
|
@@ -33,7 +34,7 @@ const ListTagsRepository_ListTagsRepository = ListTagsRepository.createImplement
|
|
|
33
34
|
implementation: ListTagsRepositoryImpl,
|
|
34
35
|
dependencies: [
|
|
35
36
|
GetUniqueFieldValuesUseCase,
|
|
36
|
-
|
|
37
|
+
FileModelProvider,
|
|
37
38
|
CmsWhereMapper
|
|
38
39
|
]
|
|
39
40
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/file/ListTags/ListTagsRepository.js","sources":["../../../../src/features/file/ListTags/ListTagsRepository.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { GetUniqueFieldValuesUseCase } from \"@webiny/api-headless-cms/features/contentEntry/GetUniqueFieldValues\";\nimport {\n ListTagsInput,\n ListTagsRepository as RepositoryAbstraction,\n TagItem\n} from \"./abstractions.js\";\nimport {
|
|
1
|
+
{"version":3,"file":"features/file/ListTags/ListTagsRepository.js","sources":["../../../../src/features/file/ListTags/ListTagsRepository.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { GetUniqueFieldValuesUseCase } from \"@webiny/api-headless-cms/features/contentEntry/GetUniqueFieldValues\";\nimport {\n ListTagsInput,\n ListTagsRepository as RepositoryAbstraction,\n TagItem\n} from \"./abstractions.js\";\nimport { FileModelProvider } from \"~/domain/file/abstractions.js\";\nimport { FilePersistenceError } from \"~/domain/file/errors.js\";\nimport { CmsWhereMapper } from \"@webiny/api-headless-cms\";\n\nclass ListTagsRepositoryImpl implements RepositoryAbstraction.Interface {\n constructor(\n private getUniqueFieldValues: GetUniqueFieldValuesUseCase.Interface,\n private fileModelProvider: FileModelProvider.Interface,\n private cmsWhereMapper: CmsWhereMapper.Interface\n ) {}\n\n async execute(input: ListTagsInput): Promise<Result<TagItem[], RepositoryAbstraction.Error>> {\n const fileModel = await this.fileModelProvider.get();\n\n const result = await this.getUniqueFieldValues.execute(fileModel, {\n fieldId: \"tags\",\n // TODO fix with proper types\n // @ts-expect-error\n where: this.cmsWhereMapper.map({\n input: {\n ...(input.where || {}),\n latest: true\n },\n fields: fileModel.fields\n })\n });\n\n if (result.isFail()) {\n return Result.fail(new FilePersistenceError(result.error));\n }\n\n // Map to TagItem format\n const tags: TagItem[] = result.value\n .map(uv => ({\n tag: uv.value as string,\n count: uv.count\n }))\n // Sort by tag name alphabetically\n .sort((a, b) => (a.tag < b.tag ? -1 : 1))\n // Then sort by count descending (most used first)\n .sort((a, b) => (a.count > b.count ? -1 : 1));\n\n return Result.ok(tags);\n }\n}\n\nexport const ListTagsRepository = RepositoryAbstraction.createImplementation({\n implementation: ListTagsRepositoryImpl,\n dependencies: [GetUniqueFieldValuesUseCase, FileModelProvider, CmsWhereMapper]\n});\n"],"names":["ListTagsRepositoryImpl","getUniqueFieldValues","fileModelProvider","cmsWhereMapper","input","fileModel","result","Result","FilePersistenceError","tags","uv","a","b","ListTagsRepository","RepositoryAbstraction","GetUniqueFieldValuesUseCase","FileModelProvider","CmsWhereMapper"],"mappings":";;;;;;AAWA,MAAMA;IACF,YACYC,oBAA2D,EAC3DC,iBAA8C,EAC9CC,cAAwC,CAClD;aAHUF,oBAAoB,GAApBA;aACAC,iBAAiB,GAAjBA;aACAC,cAAc,GAAdA;IACT;IAEH,MAAM,QAAQC,KAAoB,EAA2D;QACzF,MAAMC,YAAY,MAAM,IAAI,CAAC,iBAAiB,CAAC,GAAG;QAElD,MAAMC,SAAS,MAAM,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAACD,WAAW;YAC9D,SAAS;YAGT,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC;gBAC3B,OAAO;oBACH,GAAID,MAAM,KAAK,IAAI,CAAC,CAAC;oBACrB,QAAQ;gBACZ;gBACA,QAAQC,UAAU,MAAM;YAC5B;QACJ;QAEA,IAAIC,OAAO,MAAM,IACb,OAAOC,OAAO,IAAI,CAAC,IAAIC,qBAAqBF,OAAO,KAAK;QAI5D,MAAMG,OAAkBH,OAAO,KAAK,CAC/B,GAAG,CAACI,CAAAA,KAAO;gBACR,KAAKA,GAAG,KAAK;gBACb,OAAOA,GAAG,KAAK;YACnB,IAEC,IAAI,CAAC,CAACC,GAAGC,IAAOD,EAAE,GAAG,GAAGC,EAAE,GAAG,GAAG,KAAK,GAErC,IAAI,CAAC,CAACD,GAAGC,IAAOD,EAAE,KAAK,GAAGC,EAAE,KAAK,GAAG,KAAK;QAE9C,OAAOL,OAAO,EAAE,CAACE;IACrB;AACJ;AAEO,MAAMI,wCAAqBC,mBAAAA,oBAA0C,CAAC;IACzE,gBAAgBd;IAChB,cAAc;QAACe;QAA6BC;QAAmBC;KAAe;AAClF"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Result } from "@webiny/feature/api";
|
|
2
2
|
import { UpdateEntryUseCase } from "@webiny/api-headless-cms/features/contentEntry/UpdateEntry";
|
|
3
3
|
import { UpdateFileRepository as RepositoryAbstraction } from "./abstractions.js";
|
|
4
|
-
import {
|
|
4
|
+
import { FileModelProvider } from "../../../domain/file/abstractions.js";
|
|
5
5
|
import type { File } from "../../../domain/file/types.js";
|
|
6
6
|
declare class UpdateFileRepositoryImpl implements RepositoryAbstraction.Interface {
|
|
7
7
|
private updateEntry;
|
|
8
|
-
private
|
|
9
|
-
constructor(updateEntry: UpdateEntryUseCase.Interface,
|
|
8
|
+
private fileModelProvider;
|
|
9
|
+
constructor(updateEntry: UpdateEntryUseCase.Interface, fileModelProvider: FileModelProvider.Interface);
|
|
10
10
|
update(file: File): Promise<Result<void, RepositoryAbstraction.Error>>;
|
|
11
11
|
}
|
|
12
12
|
export declare const UpdateFileRepository: typeof UpdateFileRepositoryImpl & {
|