@webiny/api-headless-cms-tasks 6.4.11 → 6.6.0-alpha.1
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/HcmsTasksFeature.d.ts +4 -0
- package/HcmsTasksFeature.js +21 -0
- package/HcmsTasksFeature.js.map +1 -0
- package/features/DeleteModelTask/DeleteModel.js +19 -11
- package/features/DeleteModelTask/DeleteModel.js.map +1 -1
- package/features/DeleteModelTask/DeleteModelTask.d.ts +1 -1
- package/features/DeleteModelTask/types.d.ts +0 -3
- package/features/DeleteModelTask/types.js.map +1 -1
- package/features/DisableModel/BlockActionIfModelDisabled.d.ts +17 -4
- package/features/DisableModel/BlockActionIfModelDisabled.js +13 -5
- package/features/DisableModel/BlockActionIfModelDisabled.js.map +1 -1
- package/features/DisableModel/feature.d.ts +1 -5
- package/features/DisableModel/feature.js +3 -4
- package/features/DisableModel/feature.js.map +1 -1
- package/graphql/deleteModel/DeleteModelOperationsImpl.d.ts +43 -0
- package/graphql/deleteModel/DeleteModelOperationsImpl.js +91 -0
- package/graphql/deleteModel/DeleteModelOperationsImpl.js.map +1 -0
- package/graphql/deleteModel/abstractions.d.ts +12 -0
- package/graphql/deleteModel/abstractions.js +5 -0
- package/graphql/deleteModel/abstractions.js.map +1 -0
- package/graphql/deleteModel/assertModelDeletable.d.ts +11 -0
- package/graphql/deleteModel/assertModelDeletable.js +17 -0
- package/graphql/deleteModel/assertModelDeletable.js.map +1 -0
- package/graphql/deleteModel/cancelDeleteModel.d.ts +9 -2
- package/graphql/deleteModel/cancelDeleteModel.js +18 -29
- package/graphql/deleteModel/cancelDeleteModel.js.map +1 -1
- package/graphql/deleteModel/fullyDeleteModel.d.ts +10 -2
- package/graphql/deleteModel/fullyDeleteModel.js +15 -21
- package/graphql/deleteModel/fullyDeleteModel.js.map +1 -1
- package/graphql/deleteModel/getDeleteModelProgress.d.ts +8 -2
- package/graphql/deleteModel/getDeleteModelProgress.js +14 -18
- package/graphql/deleteModel/getDeleteModelProgress.js.map +1 -1
- package/graphql/deleteModel/index.d.ts +21 -2
- package/graphql/deleteModel/index.js +37 -19
- package/graphql/deleteModel/index.js.map +1 -1
- package/helpers/store.d.ts +12 -7
- package/helpers/store.js +32 -3
- package/helpers/store.js.map +1 -1
- package/index.d.ts +1 -2
- package/index.js +1 -22
- package/package.json +20 -20
- package/types.d.ts +0 -10
- package/graphql/deleteModel/crud.d.ts +0 -3
- package/graphql/deleteModel/crud.js +0 -63
- package/graphql/deleteModel/crud.js.map +0 -1
- package/index.js.map +0 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createFeature } from "@webiny/feature/api";
|
|
2
|
+
import { HcmsBulkActionsFeature } from "@webiny/api-headless-cms-bulk-actions";
|
|
3
|
+
import { DeleteModelTaskFeature } from "./features/DeleteModelTask/feature.js";
|
|
4
|
+
import { DisableModelFeature } from "./features/DisableModel/feature.js";
|
|
5
|
+
import { DeleteModelOperationsImplementation } from "./graphql/deleteModel/DeleteModelOperationsImpl.js";
|
|
6
|
+
import { DeleteModelGraphQLSchemaFactoryImpl } from "./graphql/deleteModel/index.js";
|
|
7
|
+
const HcmsTasksFeature = createFeature({
|
|
8
|
+
name: "HcmsTasks",
|
|
9
|
+
register (container) {
|
|
10
|
+
HcmsBulkActionsFeature.register(container, {
|
|
11
|
+
batchSize: 100
|
|
12
|
+
});
|
|
13
|
+
DeleteModelTaskFeature.register(container);
|
|
14
|
+
container.register(DeleteModelOperationsImplementation);
|
|
15
|
+
DisableModelFeature.register(container);
|
|
16
|
+
container.register(DeleteModelGraphQLSchemaFactoryImpl);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
export { HcmsTasksFeature };
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=HcmsTasksFeature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HcmsTasksFeature.js","sources":["../src/HcmsTasksFeature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { HcmsBulkActionsFeature } from \"@webiny/api-headless-cms-bulk-actions\";\nimport { DeleteModelTaskFeature } from \"./features/DeleteModelTask/feature.js\";\nimport { DisableModelFeature } from \"./features/DisableModel/feature.js\";\nimport { DeleteModelOperationsImplementation } from \"./graphql/deleteModel/DeleteModelOperationsImpl.js\";\nimport { DeleteModelGraphQLSchemaFactoryImpl } from \"./graphql/deleteModel/index.js\";\n\nexport const HcmsTasksFeature = createFeature({\n name: \"HcmsTasks\",\n register(container) {\n // Bulk actions (entries) + the empty-trash-bin task.\n HcmsBulkActionsFeature.register(container, { batchSize: 100 });\n\n DeleteModelTaskFeature.register(container);\n\n container.register(DeleteModelOperationsImplementation);\n DisableModelFeature.register(container);\n\n container.register(DeleteModelGraphQLSchemaFactoryImpl);\n }\n});\n"],"names":["HcmsTasksFeature","createFeature","container","HcmsBulkActionsFeature","DeleteModelTaskFeature","DeleteModelOperationsImplementation","DisableModelFeature","DeleteModelGraphQLSchemaFactoryImpl"],"mappings":";;;;;;AAOO,MAAMA,mBAAmBC,cAAc;IAC1C,MAAM;IACN,UAASC,SAAS;QAEdC,uBAAuB,QAAQ,CAACD,WAAW;YAAE,WAAW;QAAI;QAE5DE,uBAAuB,QAAQ,CAACF;QAEhCA,UAAU,QAAQ,CAACG;QACnBC,oBAAoB,QAAQ,CAACJ;QAE7BA,UAAU,QAAQ,CAACK;IACvB;AACJ"}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { ListFoldersUseCase } from "@webiny/api-aco/features/folder/ListFolders/index.js";
|
|
2
2
|
import { DeleteFolderUseCase } from "@webiny/api-aco/features/folder/DeleteFolder/index.js";
|
|
3
|
-
import {
|
|
3
|
+
import { ListEntriesStorageOperation } from "@webiny/api-headless-cms/features/shared/storageOperations/entry/ListEntriesStorageOperation.js";
|
|
4
|
+
import { GetModelUseCase } from "@webiny/api-headless-cms/features/contentModel/GetModel/index.js";
|
|
5
|
+
import { DeleteModelUseCase } from "@webiny/api-headless-cms/features/contentModel/DeleteModel/index.js";
|
|
6
|
+
import { DeleteEntryUseCase } from "@webiny/api-headless-cms/features/contentEntry/DeleteEntry/index.js";
|
|
7
|
+
import { GlobalKeyValueStore } from "@webiny/api-core/features/keyValueStore/abstractions.js";
|
|
8
|
+
import { createDeleteModelStore } from "../../helpers/store.js";
|
|
4
9
|
class DeleteModel {
|
|
5
10
|
constructor(context){
|
|
6
11
|
this.context = context;
|
|
@@ -23,7 +28,8 @@ class DeleteModel {
|
|
|
23
28
|
latest: true
|
|
24
29
|
};
|
|
25
30
|
if (lastDeletedId) where.entryId_gte = lastDeletedId;
|
|
26
|
-
const
|
|
31
|
+
const listEntries = this.context.container.resolve(ListEntriesStorageOperation);
|
|
32
|
+
const { items, hasMoreItems: metaHasMoreItems } = await listEntries.execute(model, {
|
|
27
33
|
limit: 1000,
|
|
28
34
|
where,
|
|
29
35
|
sort: [
|
|
@@ -32,10 +38,11 @@ class DeleteModel {
|
|
|
32
38
|
});
|
|
33
39
|
for (const item of items){
|
|
34
40
|
try {
|
|
35
|
-
await this.context.
|
|
41
|
+
const deleteResult = await this.context.container.resolve(DeleteEntryUseCase).execute(model, item.id, {
|
|
36
42
|
permanently: true,
|
|
37
43
|
force: true
|
|
38
44
|
});
|
|
45
|
+
if (deleteResult.isFail()) throw deleteResult.error;
|
|
39
46
|
} catch {
|
|
40
47
|
console.error("Failed to delete entry.", {
|
|
41
48
|
model: model.modelId,
|
|
@@ -47,7 +54,8 @@ class DeleteModel {
|
|
|
47
54
|
}
|
|
48
55
|
hasMoreItems = metaHasMoreItems;
|
|
49
56
|
}while (hasMoreItems)
|
|
50
|
-
const
|
|
57
|
+
const listEntries = this.context.container.resolve(ListEntriesStorageOperation);
|
|
58
|
+
const { items } = await listEntries.execute(model, {
|
|
51
59
|
limit: 1,
|
|
52
60
|
where: {
|
|
53
61
|
latest: true
|
|
@@ -71,7 +79,6 @@ class DeleteModel {
|
|
|
71
79
|
},
|
|
72
80
|
limit: 1000
|
|
73
81
|
});
|
|
74
|
-
if (listResult.isFail()) return controller.response.error(listResult.error);
|
|
75
82
|
const { folders, meta } = listResult.value;
|
|
76
83
|
for (const item of folders){
|
|
77
84
|
const result = await deleteFolder.execute(item.id);
|
|
@@ -82,7 +89,8 @@ class DeleteModel {
|
|
|
82
89
|
await this.removeBeingDeleted(model);
|
|
83
90
|
if (model.isPlugin) return controller.response.done();
|
|
84
91
|
try {
|
|
85
|
-
await this.context.
|
|
92
|
+
const deleteModelResult = await this.context.container.resolve(DeleteModelUseCase).execute(model.modelId);
|
|
93
|
+
if (deleteModelResult.isFail()) throw deleteModelResult.error;
|
|
86
94
|
} catch (ex) {
|
|
87
95
|
const message = `Failed to delete model "${model.modelId}".`;
|
|
88
96
|
console.error(message);
|
|
@@ -91,13 +99,13 @@ class DeleteModel {
|
|
|
91
99
|
return controller.response.done();
|
|
92
100
|
}
|
|
93
101
|
async getModel(modelId) {
|
|
94
|
-
const
|
|
95
|
-
if (
|
|
96
|
-
return
|
|
102
|
+
const result = await this.context.container.resolve(GetModelUseCase).execute(modelId);
|
|
103
|
+
if (result.isFail()) throw result.error;
|
|
104
|
+
return result.value;
|
|
97
105
|
}
|
|
98
106
|
async removeBeingDeleted(model) {
|
|
99
|
-
const
|
|
100
|
-
await
|
|
107
|
+
const store = createDeleteModelStore(this.context.container.resolve(GlobalKeyValueStore), model.tenant);
|
|
108
|
+
await store.remove(model.modelId);
|
|
101
109
|
}
|
|
102
110
|
}
|
|
103
111
|
export { DeleteModel };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/DeleteModelTask/DeleteModel.js","sources":["../../../src/features/DeleteModelTask/DeleteModel.ts"],"sourcesContent":["import type { CmsEntryListWhere } from \"@webiny/api-headless-cms/types/index.js\";\nimport type { CmsModel } from \"@webiny/api-headless-cms/types/index.js\";\nimport { ListFoldersUseCase } from \"@webiny/api-aco/features/folder/ListFolders/index.js\";\nimport { DeleteFolderUseCase } from \"@webiny/api-aco/features/folder/DeleteFolder/index.js\";\nimport { CmsContext } from \"@webiny/api-headless-cms/features/shared/abstractions.js\";\nimport { TaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport type { IDeleteModelTaskInput } from \"./types.js\";\nimport type { IDeleteModelTaskOutput } from \"./types.js\";\nimport { createStoreKey } from \"~/helpers/store.js\";\n\ntype IRunParams = TaskDefinition.RunParams<IDeleteModelTaskInput, IDeleteModelTaskOutput>;\n\nexport interface IDeleteModel {\n run(\n params: IRunParams\n ): Promise<TaskDefinition.Result<IDeleteModelTaskInput, IDeleteModelTaskOutput>>;\n}\n\nexport class DeleteModel implements IDeleteModel {\n constructor(private context: CmsContext.Interface) {}\n\n public async run(\n params: IRunParams\n ): Promise<TaskDefinition.Result<IDeleteModelTaskInput, IDeleteModelTaskOutput>> {\n const { input, controller } = params;\n\n const model = await this.getModel(input.modelId);\n\n let hasMoreItems = false;\n let lastDeletedId: string | undefined = input.lastDeletedId;\n do {\n if (controller.runtime.isAborted()) {\n /**\n * If the task was aborted, we need to remove the task tag from the model.\n */\n await this.removeBeingDeleted(model);\n return controller.response.aborted();\n } else if (controller.runtime.isCloseToTimeout()) {\n return controller.response.continue({\n ...input,\n lastDeletedId\n });\n }\n const where: CmsEntryListWhere = {\n latest: true\n };\n if (lastDeletedId) {\n where.entryId_gte = lastDeletedId;\n }\n const { items, hasMoreItems: metaHasMoreItems } =\n await this.context.cms.storageOperations.entries.list(model, {\n limit: 1000,\n where,\n sort: [\"entryId_ASC\"]\n });\n for (const item of items) {\n try {\n await this.context.cms.deleteEntry(model, item.id, {\n permanently: true,\n force: true\n });\n } catch {\n console.error(\"Failed to delete entry.\", {\n model: model.modelId,\n id: item.id\n });\n return controller.response.error(\n new Error(`Failed to delete entry \"${item.id}\". Cannot continue.`)\n );\n }\n lastDeletedId = item.entryId;\n }\n\n hasMoreItems = metaHasMoreItems;\n } while (hasMoreItems);\n /**\n * Let's do one more check. If there are items, continue the task with 5 seconds delay.\n */\n const { items } = await this.context.cms.storageOperations.entries.list(model, {\n limit: 1,\n where: {\n latest: true\n }\n });\n if (items.length > 0) {\n console.log(\"There are still items to be deleted. Continuing the task.\");\n return controller.response.continue(\n {\n ...input\n },\n {\n seconds: 5\n }\n );\n }\n\n let hasMoreFolders = false;\n\n const listFolders = this.context.container.resolve(ListFoldersUseCase);\n const deleteFolder = this.context.container.resolve(DeleteFolderUseCase);\n\n do {\n const listResult = await listFolders.execute({\n where: {\n type: `cms:${model.modelId}`\n },\n limit: 1000\n });\n\n if (listResult.isFail()) {\n return controller.response.error(listResult.error);\n }\n\n const { folders, meta } = listResult.value;\n\n for (const item of folders) {\n const result = await deleteFolder.execute(item.id);\n if (result.isFail()) {\n return controller.response.error(result.error);\n }\n }\n\n hasMoreFolders = meta.hasMoreItems;\n } while (hasMoreFolders);\n\n /**\n * When there is no more records to be deleted, let's delete the model, if it's not a plugin.\n */\n await this.removeBeingDeleted(model);\n if (model.isPlugin) {\n return controller.response.done();\n }\n try {\n await this.context.cms.deleteModel(model.modelId);\n } catch (ex) {\n const message = `Failed to delete model \"${model.modelId}\".`;\n console.error(message);\n return controller.response.error(ex);\n }\n\n return controller.response.done();\n }\n\n private async getModel(modelId: string): Promise<CmsModel> {\n const model = await this.context.cms.getModel(modelId);\n if (!model) {\n throw new Error(`Model \"${modelId}\" not found.`);\n }\n return model;\n }\n\n private async removeBeingDeleted(model: Pick<CmsModel, \"modelId\" | \"tenant\">): Promise<void> {\n const key = createStoreKey(model);\n await this.context.db.store.removeValue(key);\n }\n}\n"],"names":["DeleteModel","context","params","input","controller","model","hasMoreItems","lastDeletedId","where","items","metaHasMoreItems","item","console","Error","hasMoreFolders","listFolders","ListFoldersUseCase","deleteFolder","DeleteFolderUseCase","listResult","folders","meta","result","ex","message","modelId","key","createStoreKey"],"mappings":";;;AAkBO,MAAMA;IACT,YAAoBC,OAA6B,CAAE;aAA/BA,OAAO,GAAPA;IAAgC;IAEpD,MAAa,IACTC,MAAkB,EAC2D;QAC7E,MAAM,EAAEC,KAAK,EAAEC,UAAU,EAAE,GAAGF;QAE9B,MAAMG,QAAQ,MAAM,IAAI,CAAC,QAAQ,CAACF,MAAM,OAAO;QAE/C,IAAIG,eAAe;QACnB,IAAIC,gBAAoCJ,MAAM,aAAa;QAC3D,GAAG;YACC,IAAIC,WAAW,OAAO,CAAC,SAAS,IAAI;gBAIhC,MAAM,IAAI,CAAC,kBAAkB,CAACC;gBAC9B,OAAOD,WAAW,QAAQ,CAAC,OAAO;YACtC;YAAO,IAAIA,WAAW,OAAO,CAAC,gBAAgB,IAC1C,OAAOA,WAAW,QAAQ,CAAC,QAAQ,CAAC;gBAChC,GAAGD,KAAK;gBACRI;YACJ;YAEJ,MAAMC,QAA2B;gBAC7B,QAAQ;YACZ;YACA,IAAID,eACAC,MAAM,WAAW,GAAGD;YAExB,MAAM,EAAEE,KAAK,EAAE,cAAcC,gBAAgB,EAAE,GAC3C,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,OAAO,CAAC,IAAI,CAACL,OAAO;gBACzD,OAAO;gBACPG;gBACA,MAAM;oBAAC;iBAAc;YACzB;YACJ,KAAK,MAAMG,QAAQF,MAAO;gBACtB,IAAI;oBACA,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAACJ,OAAOM,KAAK,EAAE,EAAE;wBAC/C,aAAa;wBACb,OAAO;oBACX;gBACJ,EAAE,OAAM;oBACJC,QAAQ,KAAK,CAAC,2BAA2B;wBACrC,OAAOP,MAAM,OAAO;wBACpB,IAAIM,KAAK,EAAE;oBACf;oBACA,OAAOP,WAAW,QAAQ,CAAC,KAAK,CAC5B,IAAIS,MAAM,CAAC,wBAAwB,EAAEF,KAAK,EAAE,CAAC,mBAAmB,CAAC;gBAEzE;gBACAJ,gBAAgBI,KAAK,OAAO;YAChC;YAEAL,eAAeI;QACnB,QAASJ,aAAc;QAIvB,MAAM,EAAEG,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,OAAO,CAAC,IAAI,CAACJ,OAAO;YAC3E,OAAO;YACP,OAAO;gBACH,QAAQ;YACZ;QACJ;QACA,IAAII,MAAM,MAAM,GAAG,GAAG;YAClBG,QAAQ,GAAG,CAAC;YACZ,OAAOR,WAAW,QAAQ,CAAC,QAAQ,CAC/B;gBACI,GAAGD,KAAK;YACZ,GACA;gBACI,SAAS;YACb;QAER;QAEA,IAAIW,iBAAiB;QAErB,MAAMC,cAAc,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAACC;QACnD,MAAMC,eAAe,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAACC;QAEpD,GAAG;YACC,MAAMC,aAAa,MAAMJ,YAAY,OAAO,CAAC;gBACzC,OAAO;oBACH,MAAM,CAAC,IAAI,EAAEV,MAAM,OAAO,EAAE;gBAChC;gBACA,OAAO;YACX;YAEA,IAAIc,WAAW,MAAM,IACjB,OAAOf,WAAW,QAAQ,CAAC,KAAK,CAACe,WAAW,KAAK;YAGrD,MAAM,EAAEC,OAAO,EAAEC,IAAI,EAAE,GAAGF,WAAW,KAAK;YAE1C,KAAK,MAAMR,QAAQS,QAAS;gBACxB,MAAME,SAAS,MAAML,aAAa,OAAO,CAACN,KAAK,EAAE;gBACjD,IAAIW,OAAO,MAAM,IACb,OAAOlB,WAAW,QAAQ,CAAC,KAAK,CAACkB,OAAO,KAAK;YAErD;YAEAR,iBAAiBO,KAAK,YAAY;QACtC,QAASP,eAAgB;QAKzB,MAAM,IAAI,CAAC,kBAAkB,CAACT;QAC9B,IAAIA,MAAM,QAAQ,EACd,OAAOD,WAAW,QAAQ,CAAC,IAAI;QAEnC,IAAI;YACA,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAACC,MAAM,OAAO;QACpD,EAAE,OAAOkB,IAAI;YACT,MAAMC,UAAU,CAAC,wBAAwB,EAAEnB,MAAM,OAAO,CAAC,EAAE,CAAC;YAC5DO,QAAQ,KAAK,CAACY;YACd,OAAOpB,WAAW,QAAQ,CAAC,KAAK,CAACmB;QACrC;QAEA,OAAOnB,WAAW,QAAQ,CAAC,IAAI;IACnC;IAEA,MAAc,SAASqB,OAAe,EAAqB;QACvD,MAAMpB,QAAQ,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAACoB;QAC9C,IAAI,CAACpB,OACD,MAAM,IAAIQ,MAAM,CAAC,OAAO,EAAEY,QAAQ,YAAY,CAAC;QAEnD,OAAOpB;IACX;IAEA,MAAc,mBAAmBA,KAA2C,EAAiB;QACzF,MAAMqB,MAAMC,eAAetB;QAC3B,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAACqB;IAC5C;AACJ"}
|
|
1
|
+
{"version":3,"file":"features/DeleteModelTask/DeleteModel.js","sources":["../../../src/features/DeleteModelTask/DeleteModel.ts"],"sourcesContent":["import type { CmsEntryListWhere } from \"@webiny/api-headless-cms/types/index.js\";\nimport type { CmsModel } from \"@webiny/api-headless-cms/types/index.js\";\nimport { ListFoldersUseCase } from \"@webiny/api-aco/features/folder/ListFolders/index.js\";\nimport { DeleteFolderUseCase } from \"@webiny/api-aco/features/folder/DeleteFolder/index.js\";\nimport { CmsContext } from \"@webiny/api-headless-cms/features/shared/abstractions.js\";\nimport { ListEntriesStorageOperation } from \"@webiny/api-headless-cms/features/shared/storageOperations/entry/ListEntriesStorageOperation.js\";\nimport { GetModelUseCase } from \"@webiny/api-headless-cms/features/contentModel/GetModel/index.js\";\nimport { DeleteModelUseCase } from \"@webiny/api-headless-cms/features/contentModel/DeleteModel/index.js\";\nimport { DeleteEntryUseCase } from \"@webiny/api-headless-cms/features/contentEntry/DeleteEntry/index.js\";\nimport { GlobalKeyValueStore } from \"@webiny/api-core/features/keyValueStore/abstractions.js\";\nimport { TaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport type { IDeleteModelTaskInput } from \"./types.js\";\nimport type { IDeleteModelTaskOutput } from \"./types.js\";\nimport { createDeleteModelStore } from \"~/helpers/store.js\";\n\ntype IRunParams = TaskDefinition.RunParams<IDeleteModelTaskInput, IDeleteModelTaskOutput>;\n\nexport interface IDeleteModel {\n run(\n params: IRunParams\n ): Promise<TaskDefinition.Result<IDeleteModelTaskInput, IDeleteModelTaskOutput>>;\n}\n\nexport class DeleteModel implements IDeleteModel {\n constructor(private context: CmsContext.Interface) {}\n\n public async run(\n params: IRunParams\n ): Promise<TaskDefinition.Result<IDeleteModelTaskInput, IDeleteModelTaskOutput>> {\n const { input, controller } = params;\n\n const model = await this.getModel(input.modelId);\n\n let hasMoreItems = false;\n let lastDeletedId: string | undefined = input.lastDeletedId;\n do {\n if (controller.runtime.isAborted()) {\n /**\n * If the task was aborted, we need to remove the task tag from the model.\n */\n await this.removeBeingDeleted(model);\n return controller.response.aborted();\n } else if (controller.runtime.isCloseToTimeout()) {\n return controller.response.continue({\n ...input,\n lastDeletedId\n });\n }\n const where: CmsEntryListWhere = {\n latest: true\n };\n if (lastDeletedId) {\n where.entryId_gte = lastDeletedId;\n }\n const listEntries = this.context.container.resolve(ListEntriesStorageOperation);\n const { items, hasMoreItems: metaHasMoreItems } = await listEntries.execute(model, {\n limit: 1000,\n where,\n sort: [\"entryId_ASC\"]\n });\n for (const item of items) {\n try {\n const deleteResult = await this.context.container\n .resolve(DeleteEntryUseCase)\n .execute(model, item.id, {\n permanently: true,\n force: true\n });\n if (deleteResult.isFail()) {\n throw deleteResult.error;\n }\n } catch {\n console.error(\"Failed to delete entry.\", {\n model: model.modelId,\n id: item.id\n });\n return controller.response.error(\n new Error(`Failed to delete entry \"${item.id}\". Cannot continue.`)\n );\n }\n lastDeletedId = item.entryId;\n }\n\n hasMoreItems = metaHasMoreItems;\n } while (hasMoreItems);\n /**\n * Let's do one more check. If there are items, continue the task with 5 seconds delay.\n */\n const listEntries = this.context.container.resolve(ListEntriesStorageOperation);\n const { items } = await listEntries.execute(model, {\n limit: 1,\n where: {\n latest: true\n }\n });\n if (items.length > 0) {\n console.log(\"There are still items to be deleted. Continuing the task.\");\n return controller.response.continue(\n {\n ...input\n },\n {\n seconds: 5\n }\n );\n }\n\n let hasMoreFolders = false;\n\n const listFolders = this.context.container.resolve(ListFoldersUseCase);\n const deleteFolder = this.context.container.resolve(DeleteFolderUseCase);\n\n do {\n const listResult = await listFolders.execute({\n where: {\n type: `cms:${model.modelId}`\n },\n limit: 1000\n });\n\n const { folders, meta } = listResult.value;\n\n for (const item of folders) {\n const result = await deleteFolder.execute(item.id);\n if (result.isFail()) {\n return controller.response.error(result.error);\n }\n }\n\n hasMoreFolders = meta.hasMoreItems;\n } while (hasMoreFolders);\n\n /**\n * When there is no more records to be deleted, let's delete the model, if it's not a plugin.\n */\n await this.removeBeingDeleted(model);\n if (model.isPlugin) {\n return controller.response.done();\n }\n try {\n const deleteModelResult = await this.context.container\n .resolve(DeleteModelUseCase)\n .execute(model.modelId);\n if (deleteModelResult.isFail()) {\n throw deleteModelResult.error;\n }\n } catch (ex) {\n const message = `Failed to delete model \"${model.modelId}\".`;\n console.error(message);\n return controller.response.error(ex);\n }\n\n return controller.response.done();\n }\n\n private async getModel(modelId: string): Promise<CmsModel> {\n const result = await this.context.container.resolve(GetModelUseCase).execute(modelId);\n if (result.isFail()) {\n throw result.error;\n }\n return result.value;\n }\n\n private async removeBeingDeleted(model: Pick<CmsModel, \"modelId\" | \"tenant\">): Promise<void> {\n const store = createDeleteModelStore(\n this.context.container.resolve(GlobalKeyValueStore),\n model.tenant\n );\n await store.remove(model.modelId);\n }\n}\n"],"names":["DeleteModel","context","params","input","controller","model","hasMoreItems","lastDeletedId","where","listEntries","ListEntriesStorageOperation","items","metaHasMoreItems","item","deleteResult","DeleteEntryUseCase","console","Error","hasMoreFolders","listFolders","ListFoldersUseCase","deleteFolder","DeleteFolderUseCase","listResult","folders","meta","result","deleteModelResult","DeleteModelUseCase","ex","message","modelId","GetModelUseCase","store","createDeleteModelStore","GlobalKeyValueStore"],"mappings":"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"}
|
|
@@ -11,7 +11,7 @@ declare class DeleteModelTaskDefinition implements TaskDefinition.Interface<IDel
|
|
|
11
11
|
isPrivate: boolean;
|
|
12
12
|
databaseLogs: boolean;
|
|
13
13
|
description: string;
|
|
14
|
-
readonly selfCleanup: ("
|
|
14
|
+
readonly selfCleanup: ("onAbort" | "onSuccess")[];
|
|
15
15
|
constructor(context: CmsContext.Interface);
|
|
16
16
|
run(params: IRunParams): Promise<TaskDefinition.Result<IDeleteModelTaskInput, IDeleteModelTaskOutput>>;
|
|
17
17
|
createInputValidation({ validator }: TaskDefinition.CreateInputValidationParams): {
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import type { CmsIdentity } from "@webiny/api-headless-cms/types/index.js";
|
|
2
|
-
import type { ListValuesResult } from "@webiny/db";
|
|
3
|
-
import type { GenericRecord } from "@webiny/api/types.js";
|
|
4
2
|
import { TaskDefinition } from "@webiny/api-core/features/task/TaskDefinition/index.js";
|
|
5
3
|
export interface IDeleteModelTaskInput {
|
|
6
4
|
modelId: string;
|
|
@@ -29,4 +27,3 @@ export interface IStoreValue {
|
|
|
29
27
|
identity: CmsIdentity;
|
|
30
28
|
task: string;
|
|
31
29
|
}
|
|
32
|
-
export type ListStoreKeysResult = Promise<ListValuesResult<GenericRecord<string, IStoreValue>>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/DeleteModelTask/types.js","sources":["../../../src/features/DeleteModelTask/types.ts"],"sourcesContent":["import type { CmsIdentity } from \"@webiny/api-headless-cms/types/index.js\";\nimport
|
|
1
|
+
{"version":3,"file":"features/DeleteModelTask/types.js","sources":["../../../src/features/DeleteModelTask/types.ts"],"sourcesContent":["import type { CmsIdentity } from \"@webiny/api-headless-cms/types/index.js\";\nimport { TaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\n\nexport interface IDeleteModelTaskInput {\n modelId: string;\n lastDeletedId?: string;\n}\n\nexport interface IDeleteModelTaskOutput extends TaskDefinition.TaskOutput {\n total?: number;\n deleted?: number;\n}\n\nexport enum DeleteCmsModelTaskStatus {\n RUNNING = \"running\",\n DONE = \"done\",\n ERROR = \"error\",\n CANCELED = \"canceled\"\n}\n\nexport interface IDeleteCmsModelTask {\n id: string;\n status: DeleteCmsModelTaskStatus;\n total: number;\n deleted: number;\n message?: string;\n}\n\nexport interface IStoreValue {\n modelId: string;\n tenant: string;\n identity: CmsIdentity;\n task: string;\n}\n"],"names":["DeleteCmsModelTaskStatus"],"mappings":"AAaO,IAAKA,iCAAwBA,WAAAA,GAAAA,SAAxBA,wBAAwB;;;;;WAAxBA"}
|
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
import type { CmsModel } from "@webiny/api-headless-cms/types/index.js";
|
|
2
2
|
import { BlockActionIfModelDisabled as Abstraction } from "./abstractions.js";
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
private
|
|
6
|
-
constructor(
|
|
3
|
+
import { DeleteModelOperations } from "../../graphql/deleteModel/abstractions.js";
|
|
4
|
+
declare class BlockActionIfModelDisabledImpl implements Abstraction.Interface {
|
|
5
|
+
private readonly deleteModelOperations;
|
|
6
|
+
constructor(deleteModelOperations: DeleteModelOperations.Interface);
|
|
7
7
|
execute(model: CmsModel): Promise<void>;
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Takes `DeleteModelOperations` itself, not a pre-bound `isModelBeingDeleted`.
|
|
11
|
+
*
|
|
12
|
+
* Binding the method meant the feature had to `container.resolve(DeleteModelOperations)` while
|
|
13
|
+
* registering, which constructs it — and therefore everything it depends on — at register time.
|
|
14
|
+
* `HcmsTasksFeature` registers before `BackgroundTasksFeature`, so the moment the operations class
|
|
15
|
+
* declared its own task use cases that resolve threw "No registration found for
|
|
16
|
+
* Tasks/TriggerTaskUseCase". Depending on the abstraction defers construction to first use.
|
|
17
|
+
*/
|
|
18
|
+
export declare const BlockActionIfModelDisabledImplementation: typeof BlockActionIfModelDisabledImpl & {
|
|
19
|
+
__abstraction: import("@webiny/di").Abstraction<import("./abstractions.js").IBlockActionIfModelDisabled>;
|
|
20
|
+
};
|
|
21
|
+
export {};
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
import { WebinyError } from "@webiny/error";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import { BlockActionIfModelDisabled } from "./abstractions.js";
|
|
3
|
+
import { DeleteModelOperations } from "../../graphql/deleteModel/abstractions.js";
|
|
4
|
+
class BlockActionIfModelDisabledImpl {
|
|
5
|
+
constructor(deleteModelOperations){
|
|
6
|
+
this.deleteModelOperations = deleteModelOperations;
|
|
5
7
|
}
|
|
6
8
|
async execute(model) {
|
|
7
|
-
const isBeingDeleted = await this.isModelBeingDeleted(model.modelId);
|
|
9
|
+
const isBeingDeleted = await this.deleteModelOperations.isModelBeingDeleted(model.modelId);
|
|
8
10
|
if (!isBeingDeleted) return;
|
|
9
11
|
throw new WebinyError(`Model "${model.name}" is being deleted and you cannot create, update or delete any entries of this model.`);
|
|
10
12
|
}
|
|
11
13
|
}
|
|
12
|
-
|
|
14
|
+
const BlockActionIfModelDisabledImplementation = BlockActionIfModelDisabled.createImplementation({
|
|
15
|
+
implementation: BlockActionIfModelDisabledImpl,
|
|
16
|
+
dependencies: [
|
|
17
|
+
DeleteModelOperations
|
|
18
|
+
]
|
|
19
|
+
});
|
|
20
|
+
export { BlockActionIfModelDisabledImplementation };
|
|
13
21
|
|
|
14
22
|
//# sourceMappingURL=BlockActionIfModelDisabled.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/DisableModel/BlockActionIfModelDisabled.js","sources":["../../../src/features/DisableModel/BlockActionIfModelDisabled.ts"],"sourcesContent":["import { WebinyError } from \"@webiny/error\";\nimport type { CmsModel } from \"@webiny/api-headless-cms/types/index.js\";\nimport { BlockActionIfModelDisabled as Abstraction } from \"./abstractions.js\";\nimport
|
|
1
|
+
{"version":3,"file":"features/DisableModel/BlockActionIfModelDisabled.js","sources":["../../../src/features/DisableModel/BlockActionIfModelDisabled.ts"],"sourcesContent":["import { WebinyError } from \"@webiny/error\";\nimport type { CmsModel } from \"@webiny/api-headless-cms/types/index.js\";\nimport { BlockActionIfModelDisabled as Abstraction } from \"./abstractions.js\";\nimport { DeleteModelOperations } from \"~/graphql/deleteModel/abstractions.js\";\n\nclass BlockActionIfModelDisabledImpl implements Abstraction.Interface {\n constructor(private readonly deleteModelOperations: DeleteModelOperations.Interface) {}\n\n async execute(model: CmsModel): Promise<void> {\n const isBeingDeleted = await this.deleteModelOperations.isModelBeingDeleted(model.modelId);\n if (!isBeingDeleted) {\n return;\n }\n\n throw new WebinyError(\n `Model \"${model.name}\" is being deleted and you cannot create, update or delete any entries of this model.`\n );\n }\n}\n\n/**\n * Takes `DeleteModelOperations` itself, not a pre-bound `isModelBeingDeleted`.\n *\n * Binding the method meant the feature had to `container.resolve(DeleteModelOperations)` while\n * registering, which constructs it — and therefore everything it depends on — at register time.\n * `HcmsTasksFeature` registers before `BackgroundTasksFeature`, so the moment the operations class\n * declared its own task use cases that resolve threw \"No registration found for\n * Tasks/TriggerTaskUseCase\". Depending on the abstraction defers construction to first use.\n */\nexport const BlockActionIfModelDisabledImplementation = Abstraction.createImplementation({\n implementation: BlockActionIfModelDisabledImpl,\n dependencies: [DeleteModelOperations]\n});\n"],"names":["BlockActionIfModelDisabledImpl","deleteModelOperations","model","isBeingDeleted","WebinyError","BlockActionIfModelDisabledImplementation","Abstraction","DeleteModelOperations"],"mappings":";;;AAKA,MAAMA;IACF,YAA6BC,qBAAsD,CAAE;aAAxDA,qBAAqB,GAArBA;IAAyD;IAEtF,MAAM,QAAQC,KAAe,EAAiB;QAC1C,MAAMC,iBAAiB,MAAM,IAAI,CAAC,qBAAqB,CAAC,mBAAmB,CAACD,MAAM,OAAO;QACzF,IAAI,CAACC,gBACD;QAGJ,MAAM,IAAIC,YACN,CAAC,OAAO,EAAEF,MAAM,IAAI,CAAC,qFAAqF,CAAC;IAEnH;AACJ;AAWO,MAAMG,2CAA2CC,2BAAAA,oBAAgC,CAAC;IACrF,gBAAgBN;IAChB,cAAc;QAACO;KAAsB;AACzC"}
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import type { HeadlessCmsFullyDeleteModel } from "../../types.js";
|
|
2
|
-
export interface LegacyDeps {
|
|
3
|
-
isModelBeingDeleted: HeadlessCmsFullyDeleteModel["isModelBeingDeleted"];
|
|
4
|
-
}
|
|
5
1
|
export declare const DisableModelFeature: {
|
|
6
2
|
name: string;
|
|
7
|
-
register(container: import("@webiny/di").Container
|
|
3
|
+
register(container: import("@webiny/di").Container): void;
|
|
8
4
|
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { createFeature } from "@webiny/feature/api";
|
|
2
|
-
import {
|
|
3
|
-
import { BlockActionIfModelDisabled as external_BlockActionIfModelDisabled_js_BlockActionIfModelDisabled } from "./BlockActionIfModelDisabled.js";
|
|
2
|
+
import { BlockActionIfModelDisabledImplementation } from "./BlockActionIfModelDisabled.js";
|
|
4
3
|
import { BlockModelActionOnEntryBeforeCreate } from "./handlers/BlockModelActionOnEntryBeforeCreate.js";
|
|
5
4
|
import { BlockModelActionOnEntryRevisionBeforeCreate } from "./handlers/BlockModelActionOnEntryRevisionBeforeCreate.js";
|
|
6
5
|
import { BlockModelActionOnEntryBeforeUpdate } from "./handlers/BlockModelActionOnEntryBeforeUpdate.js";
|
|
@@ -13,8 +12,8 @@ import { BlockModelActionOnModelBeforeUpdate } from "./handlers/BlockModelAction
|
|
|
13
12
|
import { BlockModelActionOnModelBeforeCreateFrom } from "./handlers/BlockModelActionOnModelBeforeCreateFrom.js";
|
|
14
13
|
const DisableModelFeature = createFeature({
|
|
15
14
|
name: "DisableModel",
|
|
16
|
-
register (container
|
|
17
|
-
container.
|
|
15
|
+
register (container) {
|
|
16
|
+
container.register(BlockActionIfModelDisabledImplementation);
|
|
18
17
|
container.register(BlockModelActionOnEntryBeforeCreate);
|
|
19
18
|
container.register(BlockModelActionOnEntryRevisionBeforeCreate);
|
|
20
19
|
container.register(BlockModelActionOnEntryBeforeUpdate);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/DisableModel/feature.js","sources":["../../../src/features/DisableModel/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport {
|
|
1
|
+
{"version":3,"file":"features/DisableModel/feature.js","sources":["../../../src/features/DisableModel/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { BlockActionIfModelDisabledImplementation } from \"./BlockActionIfModelDisabled.js\";\nimport { BlockModelActionOnEntryBeforeCreate } from \"./handlers/BlockModelActionOnEntryBeforeCreate.js\";\nimport { BlockModelActionOnEntryRevisionBeforeCreate } from \"./handlers/BlockModelActionOnEntryRevisionBeforeCreate.js\";\nimport { BlockModelActionOnEntryBeforeUpdate } from \"./handlers/BlockModelActionOnEntryBeforeUpdate.js\";\nimport { BlockModelActionOnEntryBeforeUnpublish } from \"./handlers/BlockModelActionOnEntryBeforeUnpublish.js\";\nimport { BlockModelActionOnEntryBeforePublish } from \"./handlers/BlockModelActionOnEntryBeforePublish.js\";\nimport { BlockModelActionOnEntryBeforeRepublish } from \"./handlers/BlockModelActionOnEntryBeforeRepublish.js\";\nimport { BlockModelActionOnEntryBeforeRestoreFromBin } from \"./handlers/BlockModelActionOnEntryBeforeRestoreFromBin.js\";\nimport { BlockModelActionOnEntryBeforeMove } from \"./handlers/BlockModelActionOnEntryBeforeMove.js\";\nimport { BlockModelActionOnModelBeforeUpdate } from \"./handlers/BlockModelActionOnModelBeforeUpdate.js\";\nimport { BlockModelActionOnModelBeforeCreateFrom } from \"./handlers/BlockModelActionOnModelBeforeCreateFrom.js\";\n\nexport const DisableModelFeature = createFeature({\n name: \"DisableModel\",\n register(container) {\n container.register(BlockActionIfModelDisabledImplementation);\n\n container.register(BlockModelActionOnEntryBeforeCreate);\n container.register(BlockModelActionOnEntryRevisionBeforeCreate);\n container.register(BlockModelActionOnEntryBeforeUpdate);\n container.register(BlockModelActionOnEntryBeforeUnpublish);\n container.register(BlockModelActionOnEntryBeforePublish);\n container.register(BlockModelActionOnEntryBeforeRepublish);\n container.register(BlockModelActionOnEntryBeforeRestoreFromBin);\n container.register(BlockModelActionOnEntryBeforeMove);\n\n container.register(BlockModelActionOnModelBeforeUpdate);\n container.register(BlockModelActionOnModelBeforeCreateFrom);\n }\n});\n"],"names":["DisableModelFeature","createFeature","container","BlockActionIfModelDisabledImplementation","BlockModelActionOnEntryBeforeCreate","BlockModelActionOnEntryRevisionBeforeCreate","BlockModelActionOnEntryBeforeUpdate","BlockModelActionOnEntryBeforeUnpublish","BlockModelActionOnEntryBeforePublish","BlockModelActionOnEntryBeforeRepublish","BlockModelActionOnEntryBeforeRestoreFromBin","BlockModelActionOnEntryBeforeMove","BlockModelActionOnModelBeforeUpdate","BlockModelActionOnModelBeforeCreateFrom"],"mappings":";;;;;;;;;;;;AAaO,MAAMA,sBAAsBC,cAAc;IAC7C,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC;QAEnBD,UAAU,QAAQ,CAACE;QACnBF,UAAU,QAAQ,CAACG;QACnBH,UAAU,QAAQ,CAACI;QACnBJ,UAAU,QAAQ,CAACK;QACnBL,UAAU,QAAQ,CAACM;QACnBN,UAAU,QAAQ,CAACO;QACnBP,UAAU,QAAQ,CAACQ;QACnBR,UAAU,QAAQ,CAACS;QAEnBT,UAAU,QAAQ,CAACU;QACnBV,UAAU,QAAQ,CAACW;IACvB;AACJ"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { TenantContext } from "@webiny/api-core/features/tenancy/TenantContext/abstractions.js";
|
|
2
|
+
import { GlobalKeyValueStore } from "@webiny/api-core/features/keyValueStore/abstractions.js";
|
|
3
|
+
import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/abstractions.js";
|
|
4
|
+
import { AccessControl } from "@webiny/api-headless-cms/features/shared/abstractions.js";
|
|
5
|
+
import { GetModelUseCase } from "@webiny/api-headless-cms/features/contentModel/GetModel/index.js";
|
|
6
|
+
import { AbortTaskUseCase, GetTaskUseCase, TriggerTaskUseCase } from "@webiny/background-tasks/api";
|
|
7
|
+
import type { IStoreValue } from "../../features/DeleteModelTask/types.js";
|
|
8
|
+
import { DeleteModelOperations } from "../../graphql/deleteModel/abstractions.js";
|
|
9
|
+
/**
|
|
10
|
+
* Delete-model operations, previously assembled inside a `RequestContextInitializer`
|
|
11
|
+
* (`createDeleteModelCrud`) from closures over the request context.
|
|
12
|
+
*
|
|
13
|
+
* Nothing here needed a per-request hook: every member is already async, and the tenant is read
|
|
14
|
+
* lazily at call time rather than at construction. As an ordinary DI implementation it is
|
|
15
|
+
* sync-constructible, which also lets `DisableModelFeature` keep resolving it at register time.
|
|
16
|
+
*
|
|
17
|
+
* The in-memory cache is KEPT. Unlike the CMS model providers — where `ModelsFetcher`/`ModelCache`
|
|
18
|
+
* already cached a layer down — nothing caches these key-value reads, so without it every
|
|
19
|
+
* `isModelBeingDeleted()` check would hit the store. It is cleared on mutation, as before.
|
|
20
|
+
*/
|
|
21
|
+
declare class DeleteModelOperationsImpl implements DeleteModelOperations.Interface {
|
|
22
|
+
private readonly tenantContext;
|
|
23
|
+
private readonly keyValueStore;
|
|
24
|
+
private readonly identityContext;
|
|
25
|
+
private readonly getModel;
|
|
26
|
+
private readonly accessControl;
|
|
27
|
+
private readonly triggerTask;
|
|
28
|
+
private readonly getTask;
|
|
29
|
+
private readonly abortTask;
|
|
30
|
+
private readonly cache;
|
|
31
|
+
constructor(tenantContext: TenantContext.Interface, keyValueStore: GlobalKeyValueStore.Interface, identityContext: IdentityContext.Interface, getModel: GetModelUseCase.Interface, accessControl: AccessControl.Interface, triggerTask: TriggerTaskUseCase.Interface, getTask: GetTaskUseCase.Interface, abortTask: AbortTaskUseCase.Interface);
|
|
32
|
+
listModelsBeingDeleted(): Promise<IStoreValue[]>;
|
|
33
|
+
isModelBeingDeleted(modelId: string): Promise<boolean>;
|
|
34
|
+
fullyDeleteModel(modelId: string): Promise<import("~/features/DeleteModelTask/types.js").IDeleteCmsModelTask>;
|
|
35
|
+
cancelFullyDeleteModel(modelId: string): Promise<import("~/features/DeleteModelTask/types.js").IDeleteCmsModelTask>;
|
|
36
|
+
getDeleteModelProgress(modelId: string): Promise<import("~/features/DeleteModelTask/types.js").IDeleteCmsModelTask>;
|
|
37
|
+
private getTenant;
|
|
38
|
+
private getStore;
|
|
39
|
+
}
|
|
40
|
+
export declare const DeleteModelOperationsImplementation: typeof DeleteModelOperationsImpl & {
|
|
41
|
+
__abstraction: import("@webiny/di").Abstraction<import("~/graphql/deleteModel/abstractions.js").IDeleteModelOperations>;
|
|
42
|
+
};
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { TenantContext } from "@webiny/api-core/features/tenancy/TenantContext/abstractions.js";
|
|
2
|
+
import { GlobalKeyValueStore } from "@webiny/api-core/features/keyValueStore/abstractions.js";
|
|
3
|
+
import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/abstractions.js";
|
|
4
|
+
import { createCacheKey, createMemoryCache } from "@webiny/api-headless-cms/utils/index.js";
|
|
5
|
+
import { AccessControl } from "@webiny/api-headless-cms/features/shared/abstractions.js";
|
|
6
|
+
import { GetModelUseCase } from "@webiny/api-headless-cms/features/contentModel/GetModel/index.js";
|
|
7
|
+
import { AbortTaskUseCase, GetTaskUseCase, TriggerTaskUseCase } from "@webiny/background-tasks/api";
|
|
8
|
+
import { createDeleteModelStore } from "../../helpers/store.js";
|
|
9
|
+
import { fullyDeleteModel } from "./fullyDeleteModel.js";
|
|
10
|
+
import { cancelDeleteModel } from "./cancelDeleteModel.js";
|
|
11
|
+
import { getDeleteModelProgress } from "./getDeleteModelProgress.js";
|
|
12
|
+
import { DeleteModelOperations } from "./abstractions.js";
|
|
13
|
+
class DeleteModelOperationsImpl {
|
|
14
|
+
constructor(tenantContext, keyValueStore, identityContext, getModel, accessControl, triggerTask, getTask, abortTask){
|
|
15
|
+
this.tenantContext = tenantContext;
|
|
16
|
+
this.keyValueStore = keyValueStore;
|
|
17
|
+
this.identityContext = identityContext;
|
|
18
|
+
this.getModel = getModel;
|
|
19
|
+
this.accessControl = accessControl;
|
|
20
|
+
this.triggerTask = triggerTask;
|
|
21
|
+
this.getTask = getTask;
|
|
22
|
+
this.abortTask = abortTask;
|
|
23
|
+
this.cache = createMemoryCache();
|
|
24
|
+
}
|
|
25
|
+
async listModelsBeingDeleted() {
|
|
26
|
+
const cacheKey = createCacheKey({
|
|
27
|
+
tenant: this.getTenant(),
|
|
28
|
+
type: "deleteModel"
|
|
29
|
+
});
|
|
30
|
+
return this.cache.getOrSet(cacheKey, ()=>this.getStore().list());
|
|
31
|
+
}
|
|
32
|
+
async isModelBeingDeleted(modelId) {
|
|
33
|
+
const items = await this.listModelsBeingDeleted();
|
|
34
|
+
return items.some((item)=>item.modelId === modelId);
|
|
35
|
+
}
|
|
36
|
+
async fullyDeleteModel(modelId) {
|
|
37
|
+
const result = await fullyDeleteModel({
|
|
38
|
+
getModel: this.getModel,
|
|
39
|
+
accessControl: this.accessControl,
|
|
40
|
+
keyValueStore: this.keyValueStore,
|
|
41
|
+
triggerTask: this.triggerTask,
|
|
42
|
+
identityContext: this.identityContext,
|
|
43
|
+
modelId
|
|
44
|
+
});
|
|
45
|
+
this.cache.clear();
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
async cancelFullyDeleteModel(modelId) {
|
|
49
|
+
const result = await cancelDeleteModel({
|
|
50
|
+
getModel: this.getModel,
|
|
51
|
+
accessControl: this.accessControl,
|
|
52
|
+
keyValueStore: this.keyValueStore,
|
|
53
|
+
getTask: this.getTask,
|
|
54
|
+
abortTask: this.abortTask,
|
|
55
|
+
modelId
|
|
56
|
+
});
|
|
57
|
+
this.cache.clear();
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
async getDeleteModelProgress(modelId) {
|
|
61
|
+
return getDeleteModelProgress({
|
|
62
|
+
getModel: this.getModel,
|
|
63
|
+
accessControl: this.accessControl,
|
|
64
|
+
keyValueStore: this.keyValueStore,
|
|
65
|
+
getTask: this.getTask,
|
|
66
|
+
modelId
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
getTenant() {
|
|
70
|
+
return this.tenantContext.getTenant().id;
|
|
71
|
+
}
|
|
72
|
+
getStore() {
|
|
73
|
+
return createDeleteModelStore(this.keyValueStore, this.getTenant());
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const DeleteModelOperationsImplementation = DeleteModelOperations.createImplementation({
|
|
77
|
+
implementation: DeleteModelOperationsImpl,
|
|
78
|
+
dependencies: [
|
|
79
|
+
TenantContext,
|
|
80
|
+
GlobalKeyValueStore,
|
|
81
|
+
IdentityContext,
|
|
82
|
+
GetModelUseCase,
|
|
83
|
+
AccessControl,
|
|
84
|
+
TriggerTaskUseCase,
|
|
85
|
+
GetTaskUseCase,
|
|
86
|
+
AbortTaskUseCase
|
|
87
|
+
]
|
|
88
|
+
});
|
|
89
|
+
export { DeleteModelOperationsImplementation };
|
|
90
|
+
|
|
91
|
+
//# sourceMappingURL=DeleteModelOperationsImpl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphql/deleteModel/DeleteModelOperationsImpl.js","sources":["../../../src/graphql/deleteModel/DeleteModelOperationsImpl.ts"],"sourcesContent":["import { TenantContext } from \"@webiny/api-core/features/tenancy/TenantContext/abstractions.js\";\nimport { GlobalKeyValueStore } from \"@webiny/api-core/features/keyValueStore/abstractions.js\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/abstractions.js\";\nimport { createCacheKey, createMemoryCache } from \"@webiny/api-headless-cms/utils/index.js\";\nimport { AccessControl } from \"@webiny/api-headless-cms/features/shared/abstractions.js\";\nimport { GetModelUseCase } from \"@webiny/api-headless-cms/features/contentModel/GetModel/index.js\";\nimport { AbortTaskUseCase, GetTaskUseCase, TriggerTaskUseCase } from \"@webiny/background-tasks/api\";\nimport type { IStoreValue } from \"~/features/DeleteModelTask/types.js\";\nimport { createDeleteModelStore } from \"~/helpers/store.js\";\nimport { fullyDeleteModel } from \"~/graphql/deleteModel/fullyDeleteModel.js\";\nimport { cancelDeleteModel } from \"~/graphql/deleteModel/cancelDeleteModel.js\";\nimport { getDeleteModelProgress } from \"~/graphql/deleteModel/getDeleteModelProgress.js\";\nimport { DeleteModelOperations } from \"~/graphql/deleteModel/abstractions.js\";\n\n/**\n * Delete-model operations, previously assembled inside a `RequestContextInitializer`\n * (`createDeleteModelCrud`) from closures over the request context.\n *\n * Nothing here needed a per-request hook: every member is already async, and the tenant is read\n * lazily at call time rather than at construction. As an ordinary DI implementation it is\n * sync-constructible, which also lets `DisableModelFeature` keep resolving it at register time.\n *\n * The in-memory cache is KEPT. Unlike the CMS model providers — where `ModelsFetcher`/`ModelCache`\n * already cached a layer down — nothing caches these key-value reads, so without it every\n * `isModelBeingDeleted()` check would hit the store. It is cleared on mutation, as before.\n */\nclass DeleteModelOperationsImpl implements DeleteModelOperations.Interface {\n private readonly cache = createMemoryCache<Promise<IStoreValue[]>>();\n\n constructor(\n private readonly tenantContext: TenantContext.Interface,\n private readonly keyValueStore: GlobalKeyValueStore.Interface,\n private readonly identityContext: IdentityContext.Interface,\n private readonly getModel: GetModelUseCase.Interface,\n private readonly accessControl: AccessControl.Interface,\n private readonly triggerTask: TriggerTaskUseCase.Interface,\n private readonly getTask: GetTaskUseCase.Interface,\n private readonly abortTask: AbortTaskUseCase.Interface\n ) {}\n\n async listModelsBeingDeleted(): Promise<IStoreValue[]> {\n const cacheKey = createCacheKey({ tenant: this.getTenant(), type: \"deleteModel\" });\n return this.cache.getOrSet(cacheKey, () => this.getStore().list());\n }\n\n async isModelBeingDeleted(modelId: string): Promise<boolean> {\n const items = await this.listModelsBeingDeleted();\n return items.some(item => item.modelId === modelId);\n }\n\n async fullyDeleteModel(modelId: string) {\n const result = await fullyDeleteModel({\n getModel: this.getModel,\n accessControl: this.accessControl,\n keyValueStore: this.keyValueStore,\n triggerTask: this.triggerTask,\n identityContext: this.identityContext,\n modelId\n });\n this.cache.clear();\n return result;\n }\n\n async cancelFullyDeleteModel(modelId: string) {\n const result = await cancelDeleteModel({\n getModel: this.getModel,\n accessControl: this.accessControl,\n keyValueStore: this.keyValueStore,\n getTask: this.getTask,\n abortTask: this.abortTask,\n modelId\n });\n this.cache.clear();\n return result;\n }\n\n async getDeleteModelProgress(modelId: string) {\n return getDeleteModelProgress({\n getModel: this.getModel,\n accessControl: this.accessControl,\n keyValueStore: this.keyValueStore,\n getTask: this.getTask,\n modelId\n });\n }\n\n private getTenant(): string {\n return this.tenantContext.getTenant().id;\n }\n\n private getStore() {\n return createDeleteModelStore(this.keyValueStore, this.getTenant());\n }\n}\n\nexport const DeleteModelOperationsImplementation = DeleteModelOperations.createImplementation({\n implementation: DeleteModelOperationsImpl,\n dependencies: [\n TenantContext,\n GlobalKeyValueStore,\n IdentityContext,\n GetModelUseCase,\n AccessControl,\n TriggerTaskUseCase,\n GetTaskUseCase,\n AbortTaskUseCase\n ]\n});\n"],"names":["DeleteModelOperationsImpl","tenantContext","keyValueStore","identityContext","getModel","accessControl","triggerTask","getTask","abortTask","createMemoryCache","cacheKey","createCacheKey","modelId","items","item","result","fullyDeleteModel","cancelDeleteModel","getDeleteModelProgress","createDeleteModelStore","DeleteModelOperationsImplementation","DeleteModelOperations","TenantContext","GlobalKeyValueStore","IdentityContext","GetModelUseCase","AccessControl","TriggerTaskUseCase","GetTaskUseCase","AbortTaskUseCase"],"mappings":";;;;;;;;;;;;AA0BA,MAAMA;IAGF,YACqBC,aAAsC,EACtCC,aAA4C,EAC5CC,eAA0C,EAC1CC,QAAmC,EACnCC,aAAsC,EACtCC,WAAyC,EACzCC,OAAiC,EACjCC,SAAqC,CACxD;aARmBP,aAAa,GAAbA;aACAC,aAAa,GAAbA;aACAC,eAAe,GAAfA;aACAC,QAAQ,GAARA;aACAC,aAAa,GAAbA;aACAC,WAAW,GAAXA;aACAC,OAAO,GAAPA;aACAC,SAAS,GAATA;aAVJ,KAAK,GAAGC;IAWtB;IAEH,MAAM,yBAAiD;QACnD,MAAMC,WAAWC,eAAe;YAAE,QAAQ,IAAI,CAAC,SAAS;YAAI,MAAM;QAAc;QAChF,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAACD,UAAU,IAAM,IAAI,CAAC,QAAQ,GAAG,IAAI;IACnE;IAEA,MAAM,oBAAoBE,OAAe,EAAoB;QACzD,MAAMC,QAAQ,MAAM,IAAI,CAAC,sBAAsB;QAC/C,OAAOA,MAAM,IAAI,CAACC,CAAAA,OAAQA,KAAK,OAAO,KAAKF;IAC/C;IAEA,MAAM,iBAAiBA,OAAe,EAAE;QACpC,MAAMG,SAAS,MAAMC,iBAAiB;YAClC,UAAU,IAAI,CAAC,QAAQ;YACvB,eAAe,IAAI,CAAC,aAAa;YACjC,eAAe,IAAI,CAAC,aAAa;YACjC,aAAa,IAAI,CAAC,WAAW;YAC7B,iBAAiB,IAAI,CAAC,eAAe;YACrCJ;QACJ;QACA,IAAI,CAAC,KAAK,CAAC,KAAK;QAChB,OAAOG;IACX;IAEA,MAAM,uBAAuBH,OAAe,EAAE;QAC1C,MAAMG,SAAS,MAAME,kBAAkB;YACnC,UAAU,IAAI,CAAC,QAAQ;YACvB,eAAe,IAAI,CAAC,aAAa;YACjC,eAAe,IAAI,CAAC,aAAa;YACjC,SAAS,IAAI,CAAC,OAAO;YACrB,WAAW,IAAI,CAAC,SAAS;YACzBL;QACJ;QACA,IAAI,CAAC,KAAK,CAAC,KAAK;QAChB,OAAOG;IACX;IAEA,MAAM,uBAAuBH,OAAe,EAAE;QAC1C,OAAOM,uBAAuB;YAC1B,UAAU,IAAI,CAAC,QAAQ;YACvB,eAAe,IAAI,CAAC,aAAa;YACjC,eAAe,IAAI,CAAC,aAAa;YACjC,SAAS,IAAI,CAAC,OAAO;YACrBN;QACJ;IACJ;IAEQ,YAAoB;QACxB,OAAO,IAAI,CAAC,aAAa,CAAC,SAAS,GAAG,EAAE;IAC5C;IAEQ,WAAW;QACf,OAAOO,uBAAuB,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS;IACpE;AACJ;AAEO,MAAMC,sCAAsCC,sBAAsB,oBAAoB,CAAC;IAC1F,gBAAgBrB;IAChB,cAAc;QACVsB;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;KACH;AACL"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { IDeleteCmsModelTask, IStoreValue } from "../../features/DeleteModelTask/types.js";
|
|
2
|
+
export interface IDeleteModelOperations {
|
|
3
|
+
listModelsBeingDeleted(): Promise<IStoreValue[]>;
|
|
4
|
+
isModelBeingDeleted(modelId: string): Promise<boolean>;
|
|
5
|
+
fullyDeleteModel(modelId: string): Promise<IDeleteCmsModelTask>;
|
|
6
|
+
cancelFullyDeleteModel(modelId: string): Promise<IDeleteCmsModelTask>;
|
|
7
|
+
getDeleteModelProgress(modelId: string): Promise<IDeleteCmsModelTask>;
|
|
8
|
+
}
|
|
9
|
+
export declare const DeleteModelOperations: import("@webiny/di").Abstraction<IDeleteModelOperations>;
|
|
10
|
+
export declare namespace DeleteModelOperations {
|
|
11
|
+
type Interface = IDeleteModelOperations;
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphql/deleteModel/abstractions.js","sources":["../../../src/graphql/deleteModel/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/api\";\nimport type { IDeleteCmsModelTask, IStoreValue } from \"~/features/DeleteModelTask/types.js\";\n\nexport interface IDeleteModelOperations {\n listModelsBeingDeleted(): Promise<IStoreValue[]>;\n isModelBeingDeleted(modelId: string): Promise<boolean>;\n fullyDeleteModel(modelId: string): Promise<IDeleteCmsModelTask>;\n cancelFullyDeleteModel(modelId: string): Promise<IDeleteCmsModelTask>;\n getDeleteModelProgress(modelId: string): Promise<IDeleteCmsModelTask>;\n}\n\nexport const DeleteModelOperations =\n createAbstraction<IDeleteModelOperations>(\"DeleteModelOperations\");\n\nexport namespace DeleteModelOperations {\n export type Interface = IDeleteModelOperations;\n}\n"],"names":["DeleteModelOperations","createAbstraction"],"mappings":";AAWO,MAAMA,wBACTC,kBAA0C"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CmsModel } from "@webiny/api-headless-cms/types/index.js";
|
|
2
|
+
import type { AccessControl } from "@webiny/api-headless-cms/features/shared/abstractions.js";
|
|
3
|
+
export interface IAssertModelDeletableParams {
|
|
4
|
+
readonly accessControl: AccessControl.Interface;
|
|
5
|
+
readonly model: CmsModel;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The access checks every delete-model operation makes: delete on the model, write on its entries.
|
|
9
|
+
* All three operations ran this same pair inline.
|
|
10
|
+
*/
|
|
11
|
+
export declare const assertModelDeletable: (params: IAssertModelDeletableParams) => Promise<void>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { NotAuthorizedError } from "@webiny/api-headless-cms/utils/errors.js";
|
|
2
|
+
const assertModelDeletable = async (params)=>{
|
|
3
|
+
const { accessControl, model } = params;
|
|
4
|
+
const canAccessModel = await accessControl.canAccessModel({
|
|
5
|
+
model,
|
|
6
|
+
rwd: "d"
|
|
7
|
+
});
|
|
8
|
+
if (!canAccessModel) throw new NotAuthorizedError(`Not allowed to access content model "${model.name}".`);
|
|
9
|
+
const canAccessEntry = await accessControl.canAccessEntry({
|
|
10
|
+
model,
|
|
11
|
+
rwd: "w"
|
|
12
|
+
});
|
|
13
|
+
if (!canAccessEntry) throw new NotAuthorizedError(`Not allowed to access "${model.modelId}" entries.`);
|
|
14
|
+
};
|
|
15
|
+
export { assertModelDeletable };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=assertModelDeletable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphql/deleteModel/assertModelDeletable.js","sources":["../../../src/graphql/deleteModel/assertModelDeletable.ts"],"sourcesContent":["import type { CmsModel } from \"@webiny/api-headless-cms/types/index.js\";\nimport { NotAuthorizedError } from \"@webiny/api-headless-cms/utils/errors.js\";\nimport type { AccessControl } from \"@webiny/api-headless-cms/features/shared/abstractions.js\";\n\nexport interface IAssertModelDeletableParams {\n readonly accessControl: AccessControl.Interface;\n readonly model: CmsModel;\n}\n\n/**\n * The access checks every delete-model operation makes: delete on the model, write on its entries.\n * All three operations ran this same pair inline.\n */\nexport const assertModelDeletable = async (params: IAssertModelDeletableParams): Promise<void> => {\n const { accessControl, model } = params;\n\n const canAccessModel = await accessControl.canAccessModel({ model, rwd: \"d\" });\n if (!canAccessModel) {\n throw new NotAuthorizedError(`Not allowed to access content model \"${model.name}\".`);\n }\n\n const canAccessEntry = await accessControl.canAccessEntry({ model, rwd: \"w\" });\n if (!canAccessEntry) {\n throw new NotAuthorizedError(`Not allowed to access \"${model.modelId}\" entries.`);\n }\n};\n"],"names":["assertModelDeletable","params","accessControl","model","canAccessModel","NotAuthorizedError","canAccessEntry"],"mappings":";AAaO,MAAMA,uBAAuB,OAAOC;IACvC,MAAM,EAAEC,aAAa,EAAEC,KAAK,EAAE,GAAGF;IAEjC,MAAMG,iBAAiB,MAAMF,cAAc,cAAc,CAAC;QAAEC;QAAO,KAAK;IAAI;IAC5E,IAAI,CAACC,gBACD,MAAM,IAAIC,mBAAmB,CAAC,qCAAqC,EAAEF,MAAM,IAAI,CAAC,EAAE,CAAC;IAGvF,MAAMG,iBAAiB,MAAMJ,cAAc,cAAc,CAAC;QAAEC;QAAO,KAAK;IAAI;IAC5E,IAAI,CAACG,gBACD,MAAM,IAAID,mBAAmB,CAAC,uBAAuB,EAAEF,MAAM,OAAO,CAAC,UAAU,CAAC;AAExF"}
|
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
import type { HcmsTasksContext } from "../../types.js";
|
|
2
1
|
import type { IDeleteCmsModelTask } from "../../features/DeleteModelTask/types.js";
|
|
2
|
+
import type { AccessControl } from "@webiny/api-headless-cms/features/shared/abstractions.js";
|
|
3
|
+
import type { GetModelUseCase } from "@webiny/api-headless-cms/features/contentModel/GetModel/index.js";
|
|
4
|
+
import type { GlobalKeyValueStore } from "@webiny/api-core/features/keyValueStore/abstractions.js";
|
|
5
|
+
import type { GetTaskUseCase, AbortTaskUseCase } from "@webiny/background-tasks/api";
|
|
3
6
|
export interface ICancelDeleteModelParams {
|
|
4
|
-
readonly
|
|
7
|
+
readonly getModel: GetModelUseCase.Interface;
|
|
8
|
+
readonly accessControl: AccessControl.Interface;
|
|
9
|
+
readonly keyValueStore: GlobalKeyValueStore.Interface;
|
|
10
|
+
readonly getTask: GetTaskUseCase.Interface;
|
|
11
|
+
readonly abortTask: AbortTaskUseCase.Interface;
|
|
5
12
|
readonly modelId: string;
|
|
6
13
|
}
|
|
7
14
|
export declare const cancelDeleteModel: (params: ICancelDeleteModelParams) => Promise<IDeleteCmsModelTask>;
|