@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.
Files changed (46) hide show
  1. package/HcmsTasksFeature.d.ts +4 -0
  2. package/HcmsTasksFeature.js +21 -0
  3. package/HcmsTasksFeature.js.map +1 -0
  4. package/features/DeleteModelTask/DeleteModel.js +19 -11
  5. package/features/DeleteModelTask/DeleteModel.js.map +1 -1
  6. package/features/DeleteModelTask/DeleteModelTask.d.ts +1 -1
  7. package/features/DeleteModelTask/types.d.ts +0 -3
  8. package/features/DeleteModelTask/types.js.map +1 -1
  9. package/features/DisableModel/BlockActionIfModelDisabled.d.ts +17 -4
  10. package/features/DisableModel/BlockActionIfModelDisabled.js +13 -5
  11. package/features/DisableModel/BlockActionIfModelDisabled.js.map +1 -1
  12. package/features/DisableModel/feature.d.ts +1 -5
  13. package/features/DisableModel/feature.js +3 -4
  14. package/features/DisableModel/feature.js.map +1 -1
  15. package/graphql/deleteModel/DeleteModelOperationsImpl.d.ts +43 -0
  16. package/graphql/deleteModel/DeleteModelOperationsImpl.js +91 -0
  17. package/graphql/deleteModel/DeleteModelOperationsImpl.js.map +1 -0
  18. package/graphql/deleteModel/abstractions.d.ts +12 -0
  19. package/graphql/deleteModel/abstractions.js +5 -0
  20. package/graphql/deleteModel/abstractions.js.map +1 -0
  21. package/graphql/deleteModel/assertModelDeletable.d.ts +11 -0
  22. package/graphql/deleteModel/assertModelDeletable.js +17 -0
  23. package/graphql/deleteModel/assertModelDeletable.js.map +1 -0
  24. package/graphql/deleteModel/cancelDeleteModel.d.ts +9 -2
  25. package/graphql/deleteModel/cancelDeleteModel.js +18 -29
  26. package/graphql/deleteModel/cancelDeleteModel.js.map +1 -1
  27. package/graphql/deleteModel/fullyDeleteModel.d.ts +10 -2
  28. package/graphql/deleteModel/fullyDeleteModel.js +15 -21
  29. package/graphql/deleteModel/fullyDeleteModel.js.map +1 -1
  30. package/graphql/deleteModel/getDeleteModelProgress.d.ts +8 -2
  31. package/graphql/deleteModel/getDeleteModelProgress.js +14 -18
  32. package/graphql/deleteModel/getDeleteModelProgress.js.map +1 -1
  33. package/graphql/deleteModel/index.d.ts +21 -2
  34. package/graphql/deleteModel/index.js +37 -19
  35. package/graphql/deleteModel/index.js.map +1 -1
  36. package/helpers/store.d.ts +12 -7
  37. package/helpers/store.js +32 -3
  38. package/helpers/store.js.map +1 -1
  39. package/index.d.ts +1 -2
  40. package/index.js +1 -22
  41. package/package.json +20 -20
  42. package/types.d.ts +0 -10
  43. package/graphql/deleteModel/crud.d.ts +0 -3
  44. package/graphql/deleteModel/crud.js +0 -63
  45. package/graphql/deleteModel/crud.js.map +0 -1
  46. package/index.js.map +0 -1
@@ -1,37 +1,26 @@
1
1
  import { WebinyError } from "@webiny/error";
2
- import { createStoreKey } from "../../helpers/store.js";
2
+ import { createDeleteModelStore } from "../../helpers/store.js";
3
3
  import { DELETE_MODEL_TASK } from "../../constants.js";
4
4
  import { getStatus } from "./status.js";
5
- import { NotAuthorizedError } from "@webiny/api-headless-cms/utils/errors.js";
6
- import { AccessControl } from "@webiny/api-headless-cms/features/shared/abstractions.js";
5
+ import { assertModelDeletable } from "./assertModelDeletable.js";
7
6
  const cancelDeleteModel = async (params)=>{
8
- const { context, modelId } = params;
9
- const model = await context.cms.getModel(modelId);
10
- const accessControl = context.container.resolve(AccessControl);
11
- const canAccessModel = await accessControl.canAccessModel({
12
- model,
13
- rwd: "d"
7
+ const { getModel, accessControl, keyValueStore, getTask, abortTask, modelId } = params;
8
+ const modelResult = await getModel.execute(modelId);
9
+ if (modelResult.isFail()) throw modelResult.error;
10
+ const model = modelResult.value;
11
+ await assertModelDeletable({
12
+ accessControl,
13
+ model
14
14
  });
15
- if (!canAccessModel) throw new NotAuthorizedError(`Not allowed to access content model "${model.name}".`);
16
- const canAccessEntry = await accessControl.canAccessEntry({
17
- model,
18
- rwd: "w"
15
+ const store = createDeleteModelStore(keyValueStore, model.tenant);
16
+ const existing = await store.get(model.modelId);
17
+ const taskId = existing?.task;
18
+ await store.remove(model.modelId);
19
+ if (!taskId) throw new WebinyError({
20
+ message: `Model "${modelId}" is not being deleted.`,
21
+ code: "MODEL_NOT_BEING_DELETED"
19
22
  });
20
- if (!canAccessEntry) throw new NotAuthorizedError(`Not allowed to access "${model.modelId}" entries.`);
21
- const storeKey = createStoreKey(model);
22
- const result = await context.db.store.getValue(storeKey);
23
- const taskId = result.data?.task;
24
- await context.db.store.removeValue(storeKey);
25
- if (!taskId) {
26
- if (result.error) throw WebinyError.from(result.error, {
27
- code: "DELETE_MODEL_NO_TASK_DEFINED"
28
- });
29
- throw new WebinyError({
30
- message: `Model "${modelId}" is not being deleted.`,
31
- code: "MODEL_NOT_BEING_DELETED"
32
- });
33
- }
34
- const task = await context.tasks.getTask(taskId);
23
+ const task = await getTask.execute(taskId);
35
24
  if (task?.definitionId !== DELETE_MODEL_TASK) throw new WebinyError({
36
25
  message: `The task which is deleting a model cannot be found. Please check Step Functions for more info. Task id: ${taskId}`,
37
26
  code: "DELETE_MODEL_TASK_NOT_FOUND",
@@ -40,7 +29,7 @@ const cancelDeleteModel = async (params)=>{
40
29
  task: taskId
41
30
  }
42
31
  });
43
- const abortResult = await context.tasks.abort({
32
+ const abortResult = await abortTask.execute({
44
33
  id: task.id,
45
34
  message: "User canceled the task."
46
35
  });
@@ -1 +1 @@
1
- {"version":3,"file":"graphql/deleteModel/cancelDeleteModel.js","sources":["../../../src/graphql/deleteModel/cancelDeleteModel.ts"],"sourcesContent":["import type { HcmsTasksContext } from \"~/types.js\";\nimport { WebinyError } from \"@webiny/error\";\nimport type {\n IDeleteCmsModelTask,\n IDeleteModelTaskInput,\n IDeleteModelTaskOutput,\n IStoreValue\n} from \"~/features/DeleteModelTask/types.js\";\nimport { createStoreKey } from \"~/helpers/store.js\";\nimport { DELETE_MODEL_TASK } from \"~/constants.js\";\nimport { getStatus } from \"~/graphql/deleteModel/status.js\";\nimport { NotAuthorizedError } from \"@webiny/api-headless-cms/utils/errors.js\";\nimport { AccessControl } from \"@webiny/api-headless-cms/features/shared/abstractions.js\";\n\nexport interface ICancelDeleteModelParams {\n readonly context: Pick<HcmsTasksContext, \"cms\" | \"tasks\" | \"db\" | \"container\">;\n readonly modelId: string;\n}\n\nexport const cancelDeleteModel = async (\n params: ICancelDeleteModelParams\n): Promise<IDeleteCmsModelTask> => {\n const { context, modelId } = params;\n\n const model = await context.cms.getModel(modelId);\n const accessControl = context.container.resolve(AccessControl);\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 const storeKey = createStoreKey(model);\n\n const result = await context.db.store.getValue<IStoreValue>(storeKey);\n\n const taskId = result.data?.task;\n\n await context.db.store.removeValue(storeKey);\n if (!taskId) {\n if (result.error) {\n throw WebinyError.from(result.error, {\n code: \"DELETE_MODEL_NO_TASK_DEFINED\"\n });\n }\n throw new WebinyError({\n message: `Model \"${modelId}\" is not being deleted.`,\n code: \"MODEL_NOT_BEING_DELETED\"\n });\n }\n\n const task = await context.tasks.getTask<IDeleteModelTaskInput, IDeleteModelTaskOutput>(taskId);\n if (task?.definitionId !== DELETE_MODEL_TASK) {\n throw new WebinyError({\n message: `The task which is deleting a model cannot be found. Please check Step Functions for more info. Task id: ${taskId}`,\n code: \"DELETE_MODEL_TASK_NOT_FOUND\",\n data: {\n model: model.modelId,\n task: taskId\n }\n });\n }\n\n const abortResult = await context.tasks.abort<IDeleteModelTaskInput, IDeleteModelTaskOutput>({\n id: task.id,\n message: \"User canceled the task.\"\n });\n\n const canceledTask = abortResult.value;\n\n return {\n id: canceledTask.id,\n status: getStatus(canceledTask.taskStatus),\n total: canceledTask.output?.total || 0,\n deleted: canceledTask.output?.deleted || 0\n };\n};\n"],"names":["cancelDeleteModel","params","context","modelId","model","accessControl","AccessControl","canAccessModel","NotAuthorizedError","canAccessEntry","storeKey","createStoreKey","result","taskId","WebinyError","task","DELETE_MODEL_TASK","abortResult","canceledTask","getStatus"],"mappings":";;;;;;AAmBO,MAAMA,oBAAoB,OAC7BC;IAEA,MAAM,EAAEC,OAAO,EAAEC,OAAO,EAAE,GAAGF;IAE7B,MAAMG,QAAQ,MAAMF,QAAQ,GAAG,CAAC,QAAQ,CAACC;IACzC,MAAME,gBAAgBH,QAAQ,SAAS,CAAC,OAAO,CAACI;IAEhD,MAAMC,iBAAiB,MAAMF,cAAc,cAAc,CAAC;QAAED;QAAO,KAAK;IAAI;IAC5E,IAAI,CAACG,gBACD,MAAM,IAAIC,mBAAmB,CAAC,qCAAqC,EAAEJ,MAAM,IAAI,CAAC,EAAE,CAAC;IAGvF,MAAMK,iBAAiB,MAAMJ,cAAc,cAAc,CAAC;QAAED;QAAO,KAAK;IAAI;IAC5E,IAAI,CAACK,gBACD,MAAM,IAAID,mBAAmB,CAAC,uBAAuB,EAAEJ,MAAM,OAAO,CAAC,UAAU,CAAC;IAGpF,MAAMM,WAAWC,eAAeP;IAEhC,MAAMQ,SAAS,MAAMV,QAAQ,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAcQ;IAE5D,MAAMG,SAASD,OAAO,IAAI,EAAE;IAE5B,MAAMV,QAAQ,EAAE,CAAC,KAAK,CAAC,WAAW,CAACQ;IACnC,IAAI,CAACG,QAAQ;QACT,IAAID,OAAO,KAAK,EACZ,MAAME,YAAY,IAAI,CAACF,OAAO,KAAK,EAAE;YACjC,MAAM;QACV;QAEJ,MAAM,IAAIE,YAAY;YAClB,SAAS,CAAC,OAAO,EAAEX,QAAQ,uBAAuB,CAAC;YACnD,MAAM;QACV;IACJ;IAEA,MAAMY,OAAO,MAAMb,QAAQ,KAAK,CAAC,OAAO,CAAgDW;IACxF,IAAIE,MAAM,iBAAiBC,mBACvB,MAAM,IAAIF,YAAY;QAClB,SAAS,CAAC,wGAAwG,EAAED,QAAQ;QAC5H,MAAM;QACN,MAAM;YACF,OAAOT,MAAM,OAAO;YACpB,MAAMS;QACV;IACJ;IAGJ,MAAMI,cAAc,MAAMf,QAAQ,KAAK,CAAC,KAAK,CAAgD;QACzF,IAAIa,KAAK,EAAE;QACX,SAAS;IACb;IAEA,MAAMG,eAAeD,YAAY,KAAK;IAEtC,OAAO;QACH,IAAIC,aAAa,EAAE;QACnB,QAAQC,UAAUD,aAAa,UAAU;QACzC,OAAOA,aAAa,MAAM,EAAE,SAAS;QACrC,SAASA,aAAa,MAAM,EAAE,WAAW;IAC7C;AACJ"}
1
+ {"version":3,"file":"graphql/deleteModel/cancelDeleteModel.js","sources":["../../../src/graphql/deleteModel/cancelDeleteModel.ts"],"sourcesContent":["import { WebinyError } from \"@webiny/error\";\nimport type {\n IDeleteCmsModelTask,\n IDeleteModelTaskInput,\n IDeleteModelTaskOutput\n} from \"~/features/DeleteModelTask/types.js\";\nimport { createDeleteModelStore } from \"~/helpers/store.js\";\nimport { DELETE_MODEL_TASK } from \"~/constants.js\";\nimport { getStatus } from \"~/graphql/deleteModel/status.js\";\nimport { assertModelDeletable } from \"~/graphql/deleteModel/assertModelDeletable.js\";\nimport type { AccessControl } from \"@webiny/api-headless-cms/features/shared/abstractions.js\";\nimport type { GetModelUseCase } from \"@webiny/api-headless-cms/features/contentModel/GetModel/index.js\";\nimport type { GlobalKeyValueStore } from \"@webiny/api-core/features/keyValueStore/abstractions.js\";\nimport type { GetTaskUseCase, AbortTaskUseCase } from \"@webiny/background-tasks/api\";\n\nexport interface ICancelDeleteModelParams {\n readonly getModel: GetModelUseCase.Interface;\n readonly accessControl: AccessControl.Interface;\n readonly keyValueStore: GlobalKeyValueStore.Interface;\n readonly getTask: GetTaskUseCase.Interface;\n readonly abortTask: AbortTaskUseCase.Interface;\n readonly modelId: string;\n}\n\nexport const cancelDeleteModel = async (\n params: ICancelDeleteModelParams\n): Promise<IDeleteCmsModelTask> => {\n const { getModel, accessControl, keyValueStore, getTask, abortTask, modelId } = params;\n\n const modelResult = await getModel.execute(modelId);\n if (modelResult.isFail()) {\n throw modelResult.error;\n }\n const model = modelResult.value;\n\n await assertModelDeletable({ accessControl, model });\n\n const store = createDeleteModelStore(keyValueStore, model.tenant);\n const existing = await store.get(model.modelId);\n const taskId = existing?.task;\n\n await store.remove(model.modelId);\n if (!taskId) {\n throw new WebinyError({\n message: `Model \"${modelId}\" is not being deleted.`,\n code: \"MODEL_NOT_BEING_DELETED\"\n });\n }\n\n const task = await getTask.execute<IDeleteModelTaskInput, IDeleteModelTaskOutput>(taskId);\n if (task?.definitionId !== DELETE_MODEL_TASK) {\n throw new WebinyError({\n message: `The task which is deleting a model cannot be found. Please check Step Functions for more info. Task id: ${taskId}`,\n code: \"DELETE_MODEL_TASK_NOT_FOUND\",\n data: {\n model: model.modelId,\n task: taskId\n }\n });\n }\n\n const abortResult = await abortTask.execute<IDeleteModelTaskInput, IDeleteModelTaskOutput>({\n id: task.id,\n message: \"User canceled the task.\"\n });\n\n const canceledTask = abortResult.value;\n\n return {\n id: canceledTask.id,\n status: getStatus(canceledTask.taskStatus),\n total: canceledTask.output?.total || 0,\n deleted: canceledTask.output?.deleted || 0\n };\n};\n"],"names":["cancelDeleteModel","params","getModel","accessControl","keyValueStore","getTask","abortTask","modelId","modelResult","model","assertModelDeletable","store","createDeleteModelStore","existing","taskId","WebinyError","task","DELETE_MODEL_TASK","abortResult","canceledTask","getStatus"],"mappings":";;;;;AAwBO,MAAMA,oBAAoB,OAC7BC;IAEA,MAAM,EAAEC,QAAQ,EAAEC,aAAa,EAAEC,aAAa,EAAEC,OAAO,EAAEC,SAAS,EAAEC,OAAO,EAAE,GAAGN;IAEhF,MAAMO,cAAc,MAAMN,SAAS,OAAO,CAACK;IAC3C,IAAIC,YAAY,MAAM,IAClB,MAAMA,YAAY,KAAK;IAE3B,MAAMC,QAAQD,YAAY,KAAK;IAE/B,MAAME,qBAAqB;QAAEP;QAAeM;IAAM;IAElD,MAAME,QAAQC,uBAAuBR,eAAeK,MAAM,MAAM;IAChE,MAAMI,WAAW,MAAMF,MAAM,GAAG,CAACF,MAAM,OAAO;IAC9C,MAAMK,SAASD,UAAU;IAEzB,MAAMF,MAAM,MAAM,CAACF,MAAM,OAAO;IAChC,IAAI,CAACK,QACD,MAAM,IAAIC,YAAY;QAClB,SAAS,CAAC,OAAO,EAAER,QAAQ,uBAAuB,CAAC;QACnD,MAAM;IACV;IAGJ,MAAMS,OAAO,MAAMX,QAAQ,OAAO,CAAgDS;IAClF,IAAIE,MAAM,iBAAiBC,mBACvB,MAAM,IAAIF,YAAY;QAClB,SAAS,CAAC,wGAAwG,EAAED,QAAQ;QAC5H,MAAM;QACN,MAAM;YACF,OAAOL,MAAM,OAAO;YACpB,MAAMK;QACV;IACJ;IAGJ,MAAMI,cAAc,MAAMZ,UAAU,OAAO,CAAgD;QACvF,IAAIU,KAAK,EAAE;QACX,SAAS;IACb;IAEA,MAAMG,eAAeD,YAAY,KAAK;IAEtC,OAAO;QACH,IAAIC,aAAa,EAAE;QACnB,QAAQC,UAAUD,aAAa,UAAU;QACzC,OAAOA,aAAa,MAAM,EAAE,SAAS;QACrC,SAASA,aAAa,MAAM,EAAE,WAAW;IAC7C;AACJ"}
@@ -1,7 +1,15 @@
1
- import type { HcmsTasksContext } from "../../types.js";
1
+ import type { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/abstractions.js";
2
2
  import type { IDeleteCmsModelTask } from "../../features/DeleteModelTask/types.js";
3
+ import type { AccessControl } from "@webiny/api-headless-cms/features/shared/abstractions.js";
4
+ import type { GetModelUseCase } from "@webiny/api-headless-cms/features/contentModel/GetModel/index.js";
5
+ import type { GlobalKeyValueStore } from "@webiny/api-core/features/keyValueStore/abstractions.js";
6
+ import type { TriggerTaskUseCase } from "@webiny/background-tasks/api";
3
7
  export interface IFullyDeleteModelParams {
4
- readonly context: Pick<HcmsTasksContext, "cms" | "tasks" | "db" | "security">;
8
+ readonly getModel: GetModelUseCase.Interface;
9
+ readonly accessControl: AccessControl.Interface;
10
+ readonly keyValueStore: GlobalKeyValueStore.Interface;
11
+ readonly triggerTask: TriggerTaskUseCase.Interface;
12
+ readonly identityContext: IdentityContext.Interface;
5
13
  readonly modelId: string;
6
14
  }
7
15
  export declare const fullyDeleteModel: (params: IFullyDeleteModelParams) => Promise<IDeleteCmsModelTask>;
@@ -1,27 +1,21 @@
1
- import { createStoreKey, createStoreValue } from "../../helpers/store.js";
1
+ import { createDeleteModelStore, createStoreValue } from "../../helpers/store.js";
2
2
  import { DELETE_MODEL_TASK } from "../../constants.js";
3
3
  import { getStatus } from "./status.js";
4
- import { NotAuthorizedError } from "@webiny/api-headless-cms/utils/errors.js";
4
+ import { assertModelDeletable } from "./assertModelDeletable.js";
5
5
  const fullyDeleteModel = async (params)=>{
6
- const { context, modelId } = params;
7
- const model = await context.cms.getModel(modelId);
6
+ const { getModel, accessControl, keyValueStore, triggerTask, identityContext, modelId } = params;
7
+ const modelResult = await getModel.execute(modelId);
8
+ if (modelResult.isFail()) throw modelResult.error;
9
+ const model = modelResult.value;
8
10
  if (model.isPrivate) throw new Error("Cannot delete private model.");
9
- const canAccessModel = await context.cms.accessControl.canAccessModel({
10
- model,
11
- rwd: "d"
11
+ await assertModelDeletable({
12
+ accessControl,
13
+ model
12
14
  });
13
- if (!canAccessModel) throw new NotAuthorizedError(`Not allowed to access content model "${model.name}".`);
14
- const canAccessEntry = await context.cms.accessControl.canAccessEntry({
15
- model,
16
- rwd: "w"
17
- });
18
- if (!canAccessEntry) throw new NotAuthorizedError(`Not allowed to access "${model.modelId}" entries.`);
19
- if (!model) throw new Error(`Model "${modelId}" not found.`);
20
- const storeKey = createStoreKey(model);
21
- const result = await context.db.store.getValue(storeKey);
22
- const taskId = result.data?.task;
23
- if (taskId) throw new Error(`Model "${modelId}" is already getting deleted. Task id: ${taskId}.`);
24
- const triggerResult = await context.tasks.trigger({
15
+ const store = createDeleteModelStore(keyValueStore, model.tenant);
16
+ const existing = await store.get(model.modelId);
17
+ if (existing?.task) throw new Error(`Model "${modelId}" is already getting deleted. Task id: ${existing.task}.`);
18
+ const triggerResult = await triggerTask.execute({
25
19
  input: {
26
20
  modelId
27
21
  },
@@ -29,8 +23,8 @@ const fullyDeleteModel = async (params)=>{
29
23
  name: `Fully delete model: ${modelId}`
30
24
  });
31
25
  const task = triggerResult.value;
32
- const identity = context.security.getIdentity();
33
- await context.db.store.storeValue(storeKey, createStoreValue({
26
+ const identity = identityContext.getIdentity();
27
+ await store.set(createStoreValue({
34
28
  ...model,
35
29
  identity: {
36
30
  id: identity.id,
@@ -1 +1 @@
1
- {"version":3,"file":"graphql/deleteModel/fullyDeleteModel.js","sources":["../../../src/graphql/deleteModel/fullyDeleteModel.ts"],"sourcesContent":["import type { HcmsTasksContext } from \"~/types.js\";\nimport type {\n IDeleteCmsModelTask,\n IDeleteModelTaskInput,\n IStoreValue\n} from \"~/features/DeleteModelTask/types.js\";\nimport { createStoreKey, createStoreValue } from \"~/helpers/store.js\";\nimport { DELETE_MODEL_TASK } from \"~/constants.js\";\nimport { getStatus } from \"~/graphql/deleteModel/status.js\";\nimport { NotAuthorizedError } from \"@webiny/api-headless-cms/utils/errors.js\";\n\nexport interface IFullyDeleteModelParams {\n readonly context: Pick<HcmsTasksContext, \"cms\" | \"tasks\" | \"db\" | \"security\">;\n readonly modelId: string;\n}\n\nexport const fullyDeleteModel = async (\n params: IFullyDeleteModelParams\n): Promise<IDeleteCmsModelTask> => {\n const { context, modelId } = params;\n\n const model = await context.cms.getModel(modelId);\n\n if (model.isPrivate) {\n throw new Error(`Cannot delete private model.`);\n }\n\n const canAccessModel = await context.cms.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 context.cms.accessControl.canAccessEntry({ model, rwd: \"w\" });\n if (!canAccessEntry) {\n throw new NotAuthorizedError(`Not allowed to access \"${model.modelId}\" entries.`);\n }\n\n if (!model) {\n throw new Error(`Model \"${modelId}\" not found.`);\n }\n const storeKey = createStoreKey(model);\n const result = await context.db.store.getValue<IStoreValue>(storeKey);\n const taskId = result.data?.task;\n if (taskId) {\n throw new Error(`Model \"${modelId}\" is already getting deleted. Task id: ${taskId}.`);\n }\n\n const triggerResult = await context.tasks.trigger<IDeleteModelTaskInput>({\n input: {\n modelId\n },\n definition: DELETE_MODEL_TASK,\n name: `Fully delete model: ${modelId}`\n });\n\n const task = triggerResult.value;\n\n const identity = context.security.getIdentity();\n\n await context.db.store.storeValue(\n storeKey,\n createStoreValue({\n ...model,\n identity: {\n id: identity.id,\n type: identity.type,\n displayName: identity.displayName\n },\n task: task.id\n })\n );\n\n return {\n id: task.id,\n status: getStatus(task.taskStatus),\n total: 0,\n deleted: 0\n };\n};\n"],"names":["fullyDeleteModel","params","context","modelId","model","Error","canAccessModel","NotAuthorizedError","canAccessEntry","storeKey","createStoreKey","result","taskId","triggerResult","DELETE_MODEL_TASK","task","identity","createStoreValue","getStatus"],"mappings":";;;;AAgBO,MAAMA,mBAAmB,OAC5BC;IAEA,MAAM,EAAEC,OAAO,EAAEC,OAAO,EAAE,GAAGF;IAE7B,MAAMG,QAAQ,MAAMF,QAAQ,GAAG,CAAC,QAAQ,CAACC;IAEzC,IAAIC,MAAM,SAAS,EACf,MAAM,IAAIC,MAAM;IAGpB,MAAMC,iBAAiB,MAAMJ,QAAQ,GAAG,CAAC,aAAa,CAAC,cAAc,CAAC;QAAEE;QAAO,KAAK;IAAI;IACxF,IAAI,CAACE,gBACD,MAAM,IAAIC,mBAAmB,CAAC,qCAAqC,EAAEH,MAAM,IAAI,CAAC,EAAE,CAAC;IAGvF,MAAMI,iBAAiB,MAAMN,QAAQ,GAAG,CAAC,aAAa,CAAC,cAAc,CAAC;QAAEE;QAAO,KAAK;IAAI;IACxF,IAAI,CAACI,gBACD,MAAM,IAAID,mBAAmB,CAAC,uBAAuB,EAAEH,MAAM,OAAO,CAAC,UAAU,CAAC;IAGpF,IAAI,CAACA,OACD,MAAM,IAAIC,MAAM,CAAC,OAAO,EAAEF,QAAQ,YAAY,CAAC;IAEnD,MAAMM,WAAWC,eAAeN;IAChC,MAAMO,SAAS,MAAMT,QAAQ,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAcO;IAC5D,MAAMG,SAASD,OAAO,IAAI,EAAE;IAC5B,IAAIC,QACA,MAAM,IAAIP,MAAM,CAAC,OAAO,EAAEF,QAAQ,uCAAuC,EAAES,OAAO,CAAC,CAAC;IAGxF,MAAMC,gBAAgB,MAAMX,QAAQ,KAAK,CAAC,OAAO,CAAwB;QACrE,OAAO;YACHC;QACJ;QACA,YAAYW;QACZ,MAAM,CAAC,oBAAoB,EAAEX,SAAS;IAC1C;IAEA,MAAMY,OAAOF,cAAc,KAAK;IAEhC,MAAMG,WAAWd,QAAQ,QAAQ,CAAC,WAAW;IAE7C,MAAMA,QAAQ,EAAE,CAAC,KAAK,CAAC,UAAU,CAC7BO,UACAQ,iBAAiB;QACb,GAAGb,KAAK;QACR,UAAU;YACN,IAAIY,SAAS,EAAE;YACf,MAAMA,SAAS,IAAI;YACnB,aAAaA,SAAS,WAAW;QACrC;QACA,MAAMD,KAAK,EAAE;IACjB;IAGJ,OAAO;QACH,IAAIA,KAAK,EAAE;QACX,QAAQG,UAAUH,KAAK,UAAU;QACjC,OAAO;QACP,SAAS;IACb;AACJ"}
1
+ {"version":3,"file":"graphql/deleteModel/fullyDeleteModel.js","sources":["../../../src/graphql/deleteModel/fullyDeleteModel.ts"],"sourcesContent":["import type { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/abstractions.js\";\nimport type {\n IDeleteCmsModelTask,\n IDeleteModelTaskInput\n} from \"~/features/DeleteModelTask/types.js\";\nimport { createDeleteModelStore, createStoreValue } from \"~/helpers/store.js\";\nimport { DELETE_MODEL_TASK } from \"~/constants.js\";\nimport { getStatus } from \"~/graphql/deleteModel/status.js\";\nimport { assertModelDeletable } from \"~/graphql/deleteModel/assertModelDeletable.js\";\nimport type { AccessControl } from \"@webiny/api-headless-cms/features/shared/abstractions.js\";\nimport type { GetModelUseCase } from \"@webiny/api-headless-cms/features/contentModel/GetModel/index.js\";\nimport type { GlobalKeyValueStore } from \"@webiny/api-core/features/keyValueStore/abstractions.js\";\nimport type { TriggerTaskUseCase } from \"@webiny/background-tasks/api\";\n\nexport interface IFullyDeleteModelParams {\n readonly getModel: GetModelUseCase.Interface;\n readonly accessControl: AccessControl.Interface;\n readonly keyValueStore: GlobalKeyValueStore.Interface;\n readonly triggerTask: TriggerTaskUseCase.Interface;\n readonly identityContext: IdentityContext.Interface;\n readonly modelId: string;\n}\n\nexport const fullyDeleteModel = async (\n params: IFullyDeleteModelParams\n): Promise<IDeleteCmsModelTask> => {\n const { getModel, accessControl, keyValueStore, triggerTask, identityContext, modelId } =\n params;\n\n const modelResult = await getModel.execute(modelId);\n if (modelResult.isFail()) {\n throw modelResult.error;\n }\n const model = modelResult.value;\n\n if (model.isPrivate) {\n throw new Error(`Cannot delete private model.`);\n }\n\n await assertModelDeletable({ accessControl, model });\n\n const store = createDeleteModelStore(keyValueStore, model.tenant);\n const existing = await store.get(model.modelId);\n if (existing?.task) {\n throw new Error(\n `Model \"${modelId}\" is already getting deleted. Task id: ${existing.task}.`\n );\n }\n\n const triggerResult = await triggerTask.execute<IDeleteModelTaskInput>({\n input: {\n modelId\n },\n definition: DELETE_MODEL_TASK,\n name: `Fully delete model: ${modelId}`\n });\n\n const task = triggerResult.value;\n\n const identity = identityContext.getIdentity();\n\n await store.set(\n createStoreValue({\n ...model,\n identity: {\n id: identity.id,\n type: identity.type,\n displayName: identity.displayName\n },\n task: task.id\n })\n );\n\n return {\n id: task.id,\n status: getStatus(task.taskStatus),\n total: 0,\n deleted: 0\n };\n};\n"],"names":["fullyDeleteModel","params","getModel","accessControl","keyValueStore","triggerTask","identityContext","modelId","modelResult","model","Error","assertModelDeletable","store","createDeleteModelStore","existing","triggerResult","DELETE_MODEL_TASK","task","identity","createStoreValue","getStatus"],"mappings":";;;;AAuBO,MAAMA,mBAAmB,OAC5BC;IAEA,MAAM,EAAEC,QAAQ,EAAEC,aAAa,EAAEC,aAAa,EAAEC,WAAW,EAAEC,eAAe,EAAEC,OAAO,EAAE,GACnFN;IAEJ,MAAMO,cAAc,MAAMN,SAAS,OAAO,CAACK;IAC3C,IAAIC,YAAY,MAAM,IAClB,MAAMA,YAAY,KAAK;IAE3B,MAAMC,QAAQD,YAAY,KAAK;IAE/B,IAAIC,MAAM,SAAS,EACf,MAAM,IAAIC,MAAM;IAGpB,MAAMC,qBAAqB;QAAER;QAAeM;IAAM;IAElD,MAAMG,QAAQC,uBAAuBT,eAAeK,MAAM,MAAM;IAChE,MAAMK,WAAW,MAAMF,MAAM,GAAG,CAACH,MAAM,OAAO;IAC9C,IAAIK,UAAU,MACV,MAAM,IAAIJ,MACN,CAAC,OAAO,EAAEH,QAAQ,uCAAuC,EAAEO,SAAS,IAAI,CAAC,CAAC,CAAC;IAInF,MAAMC,gBAAgB,MAAMV,YAAY,OAAO,CAAwB;QACnE,OAAO;YACHE;QACJ;QACA,YAAYS;QACZ,MAAM,CAAC,oBAAoB,EAAET,SAAS;IAC1C;IAEA,MAAMU,OAAOF,cAAc,KAAK;IAEhC,MAAMG,WAAWZ,gBAAgB,WAAW;IAE5C,MAAMM,MAAM,GAAG,CACXO,iBAAiB;QACb,GAAGV,KAAK;QACR,UAAU;YACN,IAAIS,SAAS,EAAE;YACf,MAAMA,SAAS,IAAI;YACnB,aAAaA,SAAS,WAAW;QACrC;QACA,MAAMD,KAAK,EAAE;IACjB;IAGJ,OAAO;QACH,IAAIA,KAAK,EAAE;QACX,QAAQG,UAAUH,KAAK,UAAU;QACjC,OAAO;QACP,SAAS;IACb;AACJ"}
@@ -1,7 +1,13 @@
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 } from "@webiny/background-tasks/api";
3
6
  export interface IGetDeleteModelProgress {
4
- readonly context: Pick<HcmsTasksContext, "cms" | "tasks" | "db">;
7
+ readonly getModel: GetModelUseCase.Interface;
8
+ readonly accessControl: AccessControl.Interface;
9
+ readonly keyValueStore: GlobalKeyValueStore.Interface;
10
+ readonly getTask: GetTaskUseCase.Interface;
5
11
  readonly modelId: string;
6
12
  }
7
13
  export declare const getDeleteModelProgress: (params: IGetDeleteModelProgress) => Promise<IDeleteCmsModelTask>;
@@ -1,14 +1,16 @@
1
1
  import { WebinyError } from "@webiny/error";
2
- import { NotFoundError } from "@webiny/handler-graphql";
3
- import { createStoreKey } from "../../helpers/store.js";
2
+ import { NotFoundError } from "@webiny/api-graphql";
3
+ import { createDeleteModelStore } from "../../helpers/store.js";
4
4
  import { DELETE_MODEL_TASK } from "../../constants.js";
5
5
  import { getStatus } from "./status.js";
6
- import { NotAuthorizedError } from "@webiny/api-headless-cms/utils/errors.js";
6
+ import { assertModelDeletable } from "./assertModelDeletable.js";
7
7
  const getDeleteModelProgress = async (params)=>{
8
- const { context, modelId } = params;
8
+ const { getModel, accessControl, keyValueStore, getTask, modelId } = params;
9
9
  let model;
10
10
  try {
11
- model = await context.cms.getModel(modelId);
11
+ const modelResult = await getModel.execute(modelId);
12
+ if (modelResult.isFail()) throw modelResult.error;
13
+ model = modelResult.value;
12
14
  } catch (ex) {
13
15
  if (ex instanceof NotFoundError === false) throw ex;
14
16
  throw new WebinyError({
@@ -19,21 +21,15 @@ const getDeleteModelProgress = async (params)=>{
19
21
  }
20
22
  });
21
23
  }
22
- const canAccessModel = await context.cms.accessControl.canAccessModel({
23
- model,
24
- rwd: "d"
24
+ await assertModelDeletable({
25
+ accessControl,
26
+ model
25
27
  });
26
- if (!canAccessModel) throw new NotAuthorizedError(`Not allowed to access content model "${model.name}".`);
27
- const canAccessEntry = await context.cms.accessControl.canAccessEntry({
28
- model,
29
- rwd: "w"
30
- });
31
- if (!canAccessEntry) throw new NotAuthorizedError(`Not allowed to access "${model.modelId}" entries.`);
32
- const storeKey = createStoreKey(model);
33
- const result = await context.db.store.getValue(storeKey);
34
- const taskId = result.data?.task;
28
+ const store = createDeleteModelStore(keyValueStore, model.tenant);
29
+ const existing = await store.get(model.modelId);
30
+ const taskId = existing?.task;
35
31
  if (!taskId) throw new Error(`Model "${modelId}" is not being deleted.`);
36
- const task = await context.tasks.getTask(taskId);
32
+ const task = await getTask.execute(taskId);
37
33
  if (task?.definitionId !== DELETE_MODEL_TASK) throw new WebinyError({
38
34
  message: "The task which is deleting a model cannot be found.",
39
35
  code: "DELETE_MODEL_TASK_NOT_FOUND",
@@ -1 +1 @@
1
- {"version":3,"file":"graphql/deleteModel/getDeleteModelProgress.js","sources":["../../../src/graphql/deleteModel/getDeleteModelProgress.ts"],"sourcesContent":["import type { HcmsTasksContext } from \"~/types.js\";\nimport { WebinyError } from \"@webiny/error\";\nimport { NotFoundError } from \"@webiny/handler-graphql\";\nimport type { CmsModel } from \"@webiny/api-headless-cms/types/index.js\";\nimport type {\n IDeleteCmsModelTask,\n IDeleteModelTaskInput,\n IDeleteModelTaskOutput,\n IStoreValue\n} from \"~/features/DeleteModelTask/types.js\";\nimport { createStoreKey } from \"~/helpers/store.js\";\nimport { DELETE_MODEL_TASK } from \"~/constants.js\";\nimport { getStatus } from \"~/graphql/deleteModel/status.js\";\nimport { NotAuthorizedError } from \"@webiny/api-headless-cms/utils/errors.js\";\n\nexport interface IGetDeleteModelProgress {\n readonly context: Pick<HcmsTasksContext, \"cms\" | \"tasks\" | \"db\">;\n readonly modelId: string;\n}\n\nexport const getDeleteModelProgress = async (\n params: IGetDeleteModelProgress\n): Promise<IDeleteCmsModelTask> => {\n const { context, modelId } = params;\n\n let model: CmsModel;\n try {\n model = await context.cms.getModel(modelId);\n } catch (ex) {\n if (ex instanceof NotFoundError === false) {\n throw ex;\n }\n throw new WebinyError({\n message: \"Model not found. It must have been deleted already.\",\n code: \"MODEL_ALREADY_DELETED_FOUND\",\n data: {\n model: modelId\n }\n });\n }\n\n const canAccessModel = await context.cms.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 context.cms.accessControl.canAccessEntry({ model, rwd: \"w\" });\n if (!canAccessEntry) {\n throw new NotAuthorizedError(`Not allowed to access \"${model.modelId}\" entries.`);\n }\n\n const storeKey = createStoreKey(model);\n const result = await context.db.store.getValue<IStoreValue>(storeKey);\n\n const taskId = result.data?.task;\n if (!taskId) {\n throw new Error(`Model \"${modelId}\" is not being deleted.`);\n }\n\n const task = await context.tasks.getTask<IDeleteModelTaskInput, IDeleteModelTaskOutput>(taskId);\n if (task?.definitionId !== DELETE_MODEL_TASK) {\n throw new WebinyError({\n message: `The task which is deleting a model cannot be found.`,\n code: \"DELETE_MODEL_TASK_NOT_FOUND\",\n data: {\n model: model.modelId,\n task: taskId\n }\n });\n }\n return {\n id: task.id,\n status: getStatus(task.taskStatus),\n total: task.output?.total || 0,\n deleted: task.output?.deleted || 0\n };\n};\n"],"names":["getDeleteModelProgress","params","context","modelId","model","ex","NotFoundError","WebinyError","canAccessModel","NotAuthorizedError","canAccessEntry","storeKey","createStoreKey","result","taskId","Error","task","DELETE_MODEL_TASK","getStatus"],"mappings":";;;;;;AAoBO,MAAMA,yBAAyB,OAClCC;IAEA,MAAM,EAAEC,OAAO,EAAEC,OAAO,EAAE,GAAGF;IAE7B,IAAIG;IACJ,IAAI;QACAA,QAAQ,MAAMF,QAAQ,GAAG,CAAC,QAAQ,CAACC;IACvC,EAAE,OAAOE,IAAI;QACT,IAAIA,cAAcC,kBAAkB,OAChC,MAAMD;QAEV,MAAM,IAAIE,YAAY;YAClB,SAAS;YACT,MAAM;YACN,MAAM;gBACF,OAAOJ;YACX;QACJ;IACJ;IAEA,MAAMK,iBAAiB,MAAMN,QAAQ,GAAG,CAAC,aAAa,CAAC,cAAc,CAAC;QAAEE;QAAO,KAAK;IAAI;IACxF,IAAI,CAACI,gBACD,MAAM,IAAIC,mBAAmB,CAAC,qCAAqC,EAAEL,MAAM,IAAI,CAAC,EAAE,CAAC;IAGvF,MAAMM,iBAAiB,MAAMR,QAAQ,GAAG,CAAC,aAAa,CAAC,cAAc,CAAC;QAAEE;QAAO,KAAK;IAAI;IACxF,IAAI,CAACM,gBACD,MAAM,IAAID,mBAAmB,CAAC,uBAAuB,EAAEL,MAAM,OAAO,CAAC,UAAU,CAAC;IAGpF,MAAMO,WAAWC,eAAeR;IAChC,MAAMS,SAAS,MAAMX,QAAQ,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAcS;IAE5D,MAAMG,SAASD,OAAO,IAAI,EAAE;IAC5B,IAAI,CAACC,QACD,MAAM,IAAIC,MAAM,CAAC,OAAO,EAAEZ,QAAQ,uBAAuB,CAAC;IAG9D,MAAMa,OAAO,MAAMd,QAAQ,KAAK,CAAC,OAAO,CAAgDY;IACxF,IAAIE,MAAM,iBAAiBC,mBACvB,MAAM,IAAIV,YAAY;QAClB,SAAS;QACT,MAAM;QACN,MAAM;YACF,OAAOH,MAAM,OAAO;YACpB,MAAMU;QACV;IACJ;IAEJ,OAAO;QACH,IAAIE,KAAK,EAAE;QACX,QAAQE,UAAUF,KAAK,UAAU;QACjC,OAAOA,KAAK,MAAM,EAAE,SAAS;QAC7B,SAASA,KAAK,MAAM,EAAE,WAAW;IACrC;AACJ"}
1
+ {"version":3,"file":"graphql/deleteModel/getDeleteModelProgress.js","sources":["../../../src/graphql/deleteModel/getDeleteModelProgress.ts"],"sourcesContent":["import { WebinyError } from \"@webiny/error\";\nimport { NotFoundError } from \"@webiny/api-graphql\";\nimport type { CmsModel } from \"@webiny/api-headless-cms/types/index.js\";\nimport type {\n IDeleteCmsModelTask,\n IDeleteModelTaskInput,\n IDeleteModelTaskOutput\n} from \"~/features/DeleteModelTask/types.js\";\nimport { createDeleteModelStore } from \"~/helpers/store.js\";\nimport { DELETE_MODEL_TASK } from \"~/constants.js\";\nimport { getStatus } from \"~/graphql/deleteModel/status.js\";\nimport { assertModelDeletable } from \"~/graphql/deleteModel/assertModelDeletable.js\";\nimport type { AccessControl } from \"@webiny/api-headless-cms/features/shared/abstractions.js\";\nimport type { GetModelUseCase } from \"@webiny/api-headless-cms/features/contentModel/GetModel/index.js\";\nimport type { GlobalKeyValueStore } from \"@webiny/api-core/features/keyValueStore/abstractions.js\";\nimport type { GetTaskUseCase } from \"@webiny/background-tasks/api\";\n\nexport interface IGetDeleteModelProgress {\n readonly getModel: GetModelUseCase.Interface;\n readonly accessControl: AccessControl.Interface;\n readonly keyValueStore: GlobalKeyValueStore.Interface;\n readonly getTask: GetTaskUseCase.Interface;\n readonly modelId: string;\n}\n\nexport const getDeleteModelProgress = async (\n params: IGetDeleteModelProgress\n): Promise<IDeleteCmsModelTask> => {\n const { getModel, accessControl, keyValueStore, getTask, modelId } = params;\n\n let model: CmsModel;\n try {\n const modelResult = await getModel.execute(modelId);\n if (modelResult.isFail()) {\n throw modelResult.error;\n }\n model = modelResult.value;\n } catch (ex) {\n if (ex instanceof NotFoundError === false) {\n throw ex;\n }\n throw new WebinyError({\n message: \"Model not found. It must have been deleted already.\",\n code: \"MODEL_ALREADY_DELETED_FOUND\",\n data: {\n model: modelId\n }\n });\n }\n\n await assertModelDeletable({ accessControl, model });\n\n const store = createDeleteModelStore(keyValueStore, model.tenant);\n const existing = await store.get(model.modelId);\n\n const taskId = existing?.task;\n if (!taskId) {\n throw new Error(`Model \"${modelId}\" is not being deleted.`);\n }\n\n const task = await getTask.execute<IDeleteModelTaskInput, IDeleteModelTaskOutput>(taskId);\n if (task?.definitionId !== DELETE_MODEL_TASK) {\n throw new WebinyError({\n message: `The task which is deleting a model cannot be found.`,\n code: \"DELETE_MODEL_TASK_NOT_FOUND\",\n data: {\n model: model.modelId,\n task: taskId\n }\n });\n }\n return {\n id: task.id,\n status: getStatus(task.taskStatus),\n total: task.output?.total || 0,\n deleted: task.output?.deleted || 0\n };\n};\n"],"names":["getDeleteModelProgress","params","getModel","accessControl","keyValueStore","getTask","modelId","model","modelResult","ex","NotFoundError","WebinyError","assertModelDeletable","store","createDeleteModelStore","existing","taskId","Error","task","DELETE_MODEL_TASK","getStatus"],"mappings":";;;;;;AAyBO,MAAMA,yBAAyB,OAClCC;IAEA,MAAM,EAAEC,QAAQ,EAAEC,aAAa,EAAEC,aAAa,EAAEC,OAAO,EAAEC,OAAO,EAAE,GAAGL;IAErE,IAAIM;IACJ,IAAI;QACA,MAAMC,cAAc,MAAMN,SAAS,OAAO,CAACI;QAC3C,IAAIE,YAAY,MAAM,IAClB,MAAMA,YAAY,KAAK;QAE3BD,QAAQC,YAAY,KAAK;IAC7B,EAAE,OAAOC,IAAI;QACT,IAAIA,cAAcC,kBAAkB,OAChC,MAAMD;QAEV,MAAM,IAAIE,YAAY;YAClB,SAAS;YACT,MAAM;YACN,MAAM;gBACF,OAAOL;YACX;QACJ;IACJ;IAEA,MAAMM,qBAAqB;QAAET;QAAeI;IAAM;IAElD,MAAMM,QAAQC,uBAAuBV,eAAeG,MAAM,MAAM;IAChE,MAAMQ,WAAW,MAAMF,MAAM,GAAG,CAACN,MAAM,OAAO;IAE9C,MAAMS,SAASD,UAAU;IACzB,IAAI,CAACC,QACD,MAAM,IAAIC,MAAM,CAAC,OAAO,EAAEX,QAAQ,uBAAuB,CAAC;IAG9D,MAAMY,OAAO,MAAMb,QAAQ,OAAO,CAAgDW;IAClF,IAAIE,MAAM,iBAAiBC,mBACvB,MAAM,IAAIR,YAAY;QAClB,SAAS;QACT,MAAM;QACN,MAAM;YACF,OAAOJ,MAAM,OAAO;YACpB,MAAMS;QACV;IACJ;IAEJ,OAAO;QACH,IAAIE,KAAK,EAAE;QACX,QAAQE,UAAUF,KAAK,UAAU;QACjC,OAAOA,KAAK,MAAM,EAAE,SAAS;QAC7B,SAASA,KAAK,MAAM,EAAE,WAAW;IACrC;AACJ"}
@@ -1,3 +1,22 @@
1
- import { ContextPlugin } from "@webiny/api";
1
+ import { TenantContext } from "@webiny/api-core/features/tenancy/TenantContext/abstractions.js";
2
+ import { Logger } from "@webiny/api-core/features/logger/index.js";
3
+ import { CmsGraphQLSchemaPlugin, CmsGraphQLSchemaFactory } from "@webiny/api-headless-cms";
4
+ import { HeadlessCms } from "@webiny/api-headless-cms/features/shared/abstractions.js";
2
5
  import type { HcmsTasksContext } from "../../types.js";
3
- export declare const createDeleteModelGraphQl: <T extends HcmsTasksContext = HcmsTasksContext>() => ContextPlugin<T>;
6
+ /**
7
+ * Contributes the fullyDeleteModel schema. Previously a `RequestContextInitializer` that built the
8
+ * plugin and then registered a `CmsGraphQLSchemaFactory` holding it; since `execute()` is already
9
+ * awaited by `generateSchema`, the readiness check and the plugin construction can simply live
10
+ * there instead.
11
+ */
12
+ declare class DeleteModelGraphQLSchemaFactory implements CmsGraphQLSchemaFactory.Interface {
13
+ private readonly tenantContext;
14
+ private readonly headlessCms;
15
+ private readonly logger;
16
+ constructor(tenantContext: TenantContext.Interface, headlessCms: HeadlessCms.Interface, logger: Logger.Interface);
17
+ execute(): Promise<CmsGraphQLSchemaPlugin<HcmsTasksContext>[]>;
18
+ }
19
+ export declare const DeleteModelGraphQLSchemaFactoryImpl: typeof DeleteModelGraphQLSchemaFactory & {
20
+ __abstraction: import("@webiny/di").Abstraction<import("@webiny/api-headless-cms").ICmsGraphQLSchemaFactory>;
21
+ };
22
+ export {};
@@ -1,7 +1,10 @@
1
1
  import zod from "zod";
2
- import { ContextPlugin } from "@webiny/api";
3
- import { CmsGraphQLSchemaPlugin, isHeadlessCmsReady } from "@webiny/api-headless-cms";
4
- import { ErrorResponse, Response, createResolverDecorator, resolve } from "@webiny/handler-graphql";
2
+ import { TenantContext } from "@webiny/api-core/features/tenancy/TenantContext/abstractions.js";
3
+ import { Logger } from "@webiny/api-core/features/logger/index.js";
4
+ import { CmsGraphQLSchemaFactory, CmsGraphQLSchemaPlugin } from "@webiny/api-headless-cms";
5
+ import { HeadlessCms } from "@webiny/api-headless-cms/features/shared/abstractions.js";
6
+ import { DeleteModelOperations } from "./abstractions.js";
7
+ import { ErrorResponse, Response, createResolverDecorator, resolve } from "@webiny/api-graphql";
5
8
  import { createZodError } from "@webiny/utils";
6
9
  import { validateConfirmation } from "../../helpers/confirmation.js";
7
10
  const deleteValidation = zod.object({
@@ -24,10 +27,14 @@ const cancelValidation = zod.object({
24
27
  const getValidation = zod.object({
25
28
  modelId: zod.string()
26
29
  }).readonly();
27
- const createDeleteModelGraphQl = ()=>{
28
- const contextPlugin = new ContextPlugin(async (inputContext)=>{
29
- const ready = await isHeadlessCmsReady(inputContext);
30
- if (!ready || !inputContext.cms.MANAGE) return;
30
+ class DeleteModelGraphQLSchemaFactory {
31
+ constructor(tenantContext, headlessCms, logger){
32
+ this.tenantContext = tenantContext;
33
+ this.headlessCms = headlessCms;
34
+ this.logger = logger;
35
+ }
36
+ async execute() {
37
+ if (!this.tenantContext.getTenant() || !this.headlessCms.MANAGE) return [];
31
38
  const plugin = new CmsGraphQLSchemaPlugin({
32
39
  typeDefs: `
33
40
  enum DeleteCmsModelTaskStatus {
@@ -81,9 +88,12 @@ const createDeleteModelGraphQl = ()=>{
81
88
  CmsContentModel: {
82
89
  isBeingDeleted: async (model, _, context)=>{
83
90
  try {
84
- return await context.cms.isModelBeingDeleted(model.modelId);
91
+ return await context.container.resolve(DeleteModelOperations).isModelBeingDeleted(model.modelId);
85
92
  } catch (ex) {
86
- console.error(ex);
93
+ this.logger.error({
94
+ error: ex,
95
+ modelId: model.modelId
96
+ }, "Failed to read the delete-model status.");
87
97
  }
88
98
  return true;
89
99
  }
@@ -92,19 +102,19 @@ const createDeleteModelGraphQl = ()=>{
92
102
  getDeleteModelProgress: async (_, args, context)=>resolve(async ()=>{
93
103
  const input = getValidation.safeParse(args);
94
104
  if (input.error) throw createZodError(input.error);
95
- return await context.cms.getDeleteModelProgress(input.data.modelId);
105
+ return context.container.resolve(DeleteModelOperations).getDeleteModelProgress(input.data.modelId);
96
106
  })
97
107
  },
98
108
  Mutation: {
99
109
  fullyDeleteModel: async (_, args, context)=>resolve(async ()=>{
100
110
  const input = deleteValidation.safeParse(args);
101
111
  if (input.error) throw createZodError(input.error);
102
- return await context.cms.fullyDeleteModel(input.data.modelId);
112
+ return context.container.resolve(DeleteModelOperations).fullyDeleteModel(input.data.modelId);
103
113
  }),
104
114
  cancelFullyDeleteModel: async (_, args, context)=>resolve(async ()=>{
105
115
  const input = cancelValidation.safeParse(args);
106
116
  if (input.error) throw createZodError(input.error);
107
- return await context.cms.cancelFullyDeleteModel(input.data.modelId);
117
+ return context.container.resolve(DeleteModelOperations).cancelFullyDeleteModel(input.data.modelId);
108
118
  })
109
119
  }
110
120
  },
@@ -116,7 +126,7 @@ const createDeleteModelGraphQl = ()=>{
116
126
  if (args?.includeBeingDeleted !== false) return result;
117
127
  const listed = result.data;
118
128
  try {
119
- const beingDeletedList = await context.cms.listModelsBeingDeleted();
129
+ const beingDeletedList = await context.container.resolve(DeleteModelOperations).listModelsBeingDeleted();
120
130
  return new Response(listed.filter((model)=>{
121
131
  if (!model?.modelId) return false;
122
132
  if (beingDeletedList.some((item)=>item.modelId === model.modelId)) return false;
@@ -130,11 +140,19 @@ const createDeleteModelGraphQl = ()=>{
130
140
  }
131
141
  });
132
142
  plugin.name = "headless-cms.graphql.fullyDeleteModel";
133
- inputContext.plugins.register(plugin);
134
- });
135
- contextPlugin.name = "headless-cms.context.createDeleteModelGraphQl";
136
- return contextPlugin;
137
- };
138
- export { createDeleteModelGraphQl };
143
+ return [
144
+ plugin
145
+ ];
146
+ }
147
+ }
148
+ const DeleteModelGraphQLSchemaFactoryImpl = CmsGraphQLSchemaFactory.createImplementation({
149
+ implementation: DeleteModelGraphQLSchemaFactory,
150
+ dependencies: [
151
+ TenantContext,
152
+ HeadlessCms,
153
+ Logger
154
+ ]
155
+ });
156
+ export { DeleteModelGraphQLSchemaFactoryImpl };
139
157
 
140
158
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"graphql/deleteModel/index.js","sources":["../../../src/graphql/deleteModel/index.ts"],"sourcesContent":["import zod from \"zod\";\nimport { ContextPlugin } from \"@webiny/api\";\nimport { CmsGraphQLSchemaPlugin } from \"@webiny/api-headless-cms\";\nimport { isHeadlessCmsReady } from \"@webiny/api-headless-cms\";\nimport type { HcmsTasksContext } from \"~/types.js\";\nimport { createResolverDecorator } from \"@webiny/handler-graphql\";\nimport { ErrorResponse } from \"@webiny/handler-graphql\";\nimport { resolve } from \"@webiny/handler-graphql\";\nimport { Response } from \"@webiny/handler-graphql\";\nimport { createZodError } from \"@webiny/utils\";\nimport type { IDeleteCmsModelTask } from \"~/features/DeleteModelTask/types.js\";\nimport type { CmsModel } from \"@webiny/api-headless-cms/types/index.js\";\nimport { validateConfirmation } from \"~/helpers/confirmation.js\";\n\nconst deleteValidation = zod\n .object({\n modelId: zod.string(),\n confirmation: zod.string()\n })\n .superRefine((value, context) => {\n if (validateConfirmation(value)) {\n return;\n }\n context.addIssue({\n code: zod.ZodIssueCode.custom,\n message: `Confirmation input does not match.`,\n fatal: true,\n path: [\"confirmation\"]\n });\n })\n .readonly();\n\nconst cancelValidation = zod\n .object({\n modelId: zod.string()\n })\n .readonly();\n\nconst getValidation = zod\n .object({\n modelId: zod.string()\n })\n .readonly();\n\nexport const createDeleteModelGraphQl = <T extends HcmsTasksContext = HcmsTasksContext>() => {\n const contextPlugin = new ContextPlugin<T>(async inputContext => {\n const ready = await isHeadlessCmsReady(inputContext);\n\n if (!ready || !inputContext.cms.MANAGE) {\n return;\n }\n\n const plugin = new CmsGraphQLSchemaPlugin<T>({\n typeDefs: /* GraphQL */ `\n enum DeleteCmsModelTaskStatus {\n running\n done\n error\n canceled\n }\n type DeleteCmsModelTask {\n id: ID!\n status: DeleteCmsModelTaskStatus!\n deleted: Int!\n total: Int!\n }\n\n type GetDeleteCmsModelProgressResponse {\n data: DeleteCmsModelTask\n error: CmsError\n }\n\n type FullyDeleteCmsModelResponse {\n data: DeleteCmsModelTask\n error: CmsError\n }\n\n type CancelDeleteCmsModelResponse {\n data: DeleteCmsModelTask\n error: CmsError\n }\n\n extend type CmsContentModel {\n isBeingDeleted: Boolean!\n }\n\n extend type Query {\n getDeleteModelProgress(modelId: ID!): GetDeleteCmsModelProgressResponse!\n listContentModels(\n includeBeingDeleted: Boolean = false\n ): CmsContentModelListResponse\n }\n\n extend type Mutation {\n fullyDeleteModel(\n modelId: ID!\n confirmation: String!\n ): FullyDeleteCmsModelResponse!\n cancelFullyDeleteModel(modelId: ID!): CancelDeleteCmsModelResponse!\n }\n `,\n resolvers: {\n CmsContentModel: {\n isBeingDeleted: async (model: CmsModel, _: unknown, context) => {\n try {\n return await context.cms.isModelBeingDeleted(model.modelId);\n } catch (ex) {\n console.error(ex);\n }\n return true;\n }\n },\n Query: {\n getDeleteModelProgress: async (_: unknown, args: unknown, context) => {\n return resolve<IDeleteCmsModelTask>(async () => {\n const input = getValidation.safeParse(args);\n if (input.error) {\n throw createZodError(input.error);\n }\n return await context.cms.getDeleteModelProgress(input.data.modelId);\n });\n }\n },\n Mutation: {\n fullyDeleteModel: async (_: unknown, args: unknown, context) => {\n return resolve<IDeleteCmsModelTask>(async () => {\n const input = deleteValidation.safeParse(args);\n if (input.error) {\n throw createZodError(input.error);\n }\n return await context.cms.fullyDeleteModel(input.data.modelId);\n });\n },\n cancelFullyDeleteModel: async (_: unknown, args: unknown, context) => {\n return resolve<IDeleteCmsModelTask>(async () => {\n const input = cancelValidation.safeParse(args);\n if (input.error) {\n throw createZodError(input.error);\n }\n return await context.cms.cancelFullyDeleteModel(input.data.modelId);\n });\n }\n }\n },\n resolverDecorators: {\n [\"Query.listContentModels\"]: [\n createResolverDecorator<any, any, HcmsTasksContext>(\n resolver => async (parent, args, context, info) => {\n // TODO @bruno figure out how to fix these types\n const result = (await resolver(parent, args, context, info)) as any;\n if (result.error || !Array.isArray(result.data)) {\n return result;\n }\n\n if (args?.includeBeingDeleted !== false) {\n return result;\n }\n\n const listed = result.data as CmsModel[];\n\n try {\n const beingDeletedList = await context.cms.listModelsBeingDeleted();\n\n return new Response(\n listed.filter(model => {\n if (!model?.modelId) {\n return false;\n } else if (\n beingDeletedList.some(\n item => item.modelId === model.modelId\n )\n ) {\n return false;\n }\n return true;\n })\n );\n } catch (ex) {\n return new ErrorResponse(ex);\n }\n }\n )\n ]\n }\n });\n plugin.name = \"headless-cms.graphql.fullyDeleteModel\";\n inputContext.plugins.register(plugin);\n });\n contextPlugin.name = \"headless-cms.context.createDeleteModelGraphQl\";\n return contextPlugin;\n};\n"],"names":["deleteValidation","zod","value","context","validateConfirmation","cancelValidation","getValidation","createDeleteModelGraphQl","contextPlugin","ContextPlugin","inputContext","ready","isHeadlessCmsReady","plugin","CmsGraphQLSchemaPlugin","model","_","ex","console","args","resolve","input","createZodError","createResolverDecorator","resolver","parent","info","result","Array","listed","beingDeletedList","Response","item","ErrorResponse"],"mappings":"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"}
1
+ {"version":3,"file":"graphql/deleteModel/index.js","sources":["../../../src/graphql/deleteModel/index.ts"],"sourcesContent":["import zod from \"zod\";\nimport { TenantContext } from \"@webiny/api-core/features/tenancy/TenantContext/abstractions.js\";\nimport { Logger } from \"@webiny/api-core/features/logger/index.js\";\nimport { CmsGraphQLSchemaPlugin, CmsGraphQLSchemaFactory } from \"@webiny/api-headless-cms\";\nimport { HeadlessCms } from \"@webiny/api-headless-cms/features/shared/abstractions.js\";\nimport { DeleteModelOperations } from \"~/graphql/deleteModel/abstractions.js\";\nimport type { HcmsTasksContext } from \"~/types.js\";\nimport { createResolverDecorator } from \"@webiny/api-graphql\";\nimport { ErrorResponse } from \"@webiny/api-graphql\";\nimport { resolve } from \"@webiny/api-graphql\";\nimport { Response } from \"@webiny/api-graphql\";\nimport { createZodError } from \"@webiny/utils\";\nimport type { IDeleteCmsModelTask } from \"~/features/DeleteModelTask/types.js\";\nimport type { CmsModel } from \"@webiny/api-headless-cms/types/index.js\";\nimport { validateConfirmation } from \"~/helpers/confirmation.js\";\n\nconst deleteValidation = zod\n .object({\n modelId: zod.string(),\n confirmation: zod.string()\n })\n .superRefine((value, context) => {\n if (validateConfirmation(value)) {\n return;\n }\n context.addIssue({\n code: zod.ZodIssueCode.custom,\n message: `Confirmation input does not match.`,\n fatal: true,\n path: [\"confirmation\"]\n });\n })\n .readonly();\n\nconst cancelValidation = zod\n .object({\n modelId: zod.string()\n })\n .readonly();\n\nconst getValidation = zod\n .object({\n modelId: zod.string()\n })\n .readonly();\n\n/**\n * Contributes the fullyDeleteModel schema. Previously a `RequestContextInitializer` that built the\n * plugin and then registered a `CmsGraphQLSchemaFactory` holding it; since `execute()` is already\n * awaited by `generateSchema`, the readiness check and the plugin construction can simply live\n * there instead.\n */\nclass DeleteModelGraphQLSchemaFactory implements CmsGraphQLSchemaFactory.Interface {\n constructor(\n private readonly tenantContext: TenantContext.Interface,\n private readonly headlessCms: HeadlessCms.Interface,\n private readonly logger: Logger.Interface\n ) {}\n\n async execute() {\n type T = HcmsTasksContext;\n\n // On a fresh project there is no tenant until installation completes; and the delete-model\n // schema only belongs on the MANAGE endpoint. (`isHeadlessCmsReady` only checks the tenant.)\n if (!this.tenantContext.getTenant() || !this.headlessCms.MANAGE) {\n return [];\n }\n\n const plugin = new CmsGraphQLSchemaPlugin<T>({\n typeDefs: /* GraphQL */ `\n enum DeleteCmsModelTaskStatus {\n running\n done\n error\n canceled\n }\n type DeleteCmsModelTask {\n id: ID!\n status: DeleteCmsModelTaskStatus!\n deleted: Int!\n total: Int!\n }\n\n type GetDeleteCmsModelProgressResponse {\n data: DeleteCmsModelTask\n error: CmsError\n }\n\n type FullyDeleteCmsModelResponse {\n data: DeleteCmsModelTask\n error: CmsError\n }\n\n type CancelDeleteCmsModelResponse {\n data: DeleteCmsModelTask\n error: CmsError\n }\n\n extend type CmsContentModel {\n isBeingDeleted: Boolean!\n }\n\n extend type Query {\n getDeleteModelProgress(modelId: ID!): GetDeleteCmsModelProgressResponse!\n listContentModels(\n includeBeingDeleted: Boolean = false\n ): CmsContentModelListResponse\n }\n\n extend type Mutation {\n fullyDeleteModel(\n modelId: ID!\n confirmation: String!\n ): FullyDeleteCmsModelResponse!\n cancelFullyDeleteModel(modelId: ID!): CancelDeleteCmsModelResponse!\n }\n `,\n resolvers: {\n CmsContentModel: {\n isBeingDeleted: async (model: CmsModel, _: unknown, context) => {\n try {\n return await context.container\n .resolve(DeleteModelOperations)\n .isModelBeingDeleted(model.modelId);\n } catch (ex) {\n this.logger.error(\n { error: ex, modelId: model.modelId },\n \"Failed to read the delete-model status.\"\n );\n }\n return true;\n }\n },\n Query: {\n getDeleteModelProgress: async (_: unknown, args: unknown, context) => {\n return resolve<IDeleteCmsModelTask>(async () => {\n const input = getValidation.safeParse(args);\n if (input.error) {\n throw createZodError(input.error);\n }\n return context.container\n .resolve(DeleteModelOperations)\n .getDeleteModelProgress(input.data.modelId);\n });\n }\n },\n Mutation: {\n fullyDeleteModel: async (_: unknown, args: unknown, context) => {\n return resolve<IDeleteCmsModelTask>(async () => {\n const input = deleteValidation.safeParse(args);\n if (input.error) {\n throw createZodError(input.error);\n }\n return context.container\n .resolve(DeleteModelOperations)\n .fullyDeleteModel(input.data.modelId);\n });\n },\n cancelFullyDeleteModel: async (_: unknown, args: unknown, context) => {\n return resolve<IDeleteCmsModelTask>(async () => {\n const input = cancelValidation.safeParse(args);\n if (input.error) {\n throw createZodError(input.error);\n }\n return context.container\n .resolve(DeleteModelOperations)\n .cancelFullyDeleteModel(input.data.modelId);\n });\n }\n }\n },\n resolverDecorators: {\n [\"Query.listContentModels\"]: [\n createResolverDecorator<any, any, HcmsTasksContext>(\n resolver => async (parent, args, context, info) => {\n // TODO @bruno figure out how to fix these types\n const result = (await resolver(parent, args, context, info)) as any;\n if (result.error || !Array.isArray(result.data)) {\n return result;\n }\n\n if (args?.includeBeingDeleted !== false) {\n return result;\n }\n\n const listed = result.data as CmsModel[];\n\n try {\n const beingDeletedList = await context.container\n .resolve(DeleteModelOperations)\n .listModelsBeingDeleted();\n\n return new Response(\n listed.filter(model => {\n if (!model?.modelId) {\n return false;\n } else if (\n beingDeletedList.some(\n item => item.modelId === model.modelId\n )\n ) {\n return false;\n }\n return true;\n })\n );\n } catch (ex) {\n return new ErrorResponse(ex);\n }\n }\n )\n ]\n }\n });\n plugin.name = \"headless-cms.graphql.fullyDeleteModel\";\n return [plugin];\n }\n}\n\nexport const DeleteModelGraphQLSchemaFactoryImpl = CmsGraphQLSchemaFactory.createImplementation({\n implementation: DeleteModelGraphQLSchemaFactory,\n dependencies: [TenantContext, HeadlessCms, Logger]\n});\n"],"names":["deleteValidation","zod","value","context","validateConfirmation","cancelValidation","getValidation","DeleteModelGraphQLSchemaFactory","tenantContext","headlessCms","logger","plugin","CmsGraphQLSchemaPlugin","model","_","DeleteModelOperations","ex","args","resolve","input","createZodError","createResolverDecorator","resolver","parent","info","result","Array","listed","beingDeletedList","Response","item","ErrorResponse","DeleteModelGraphQLSchemaFactoryImpl","CmsGraphQLSchemaFactory","TenantContext","HeadlessCms","Logger"],"mappings":"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"}
@@ -1,9 +1,14 @@
1
- import type { StorageKey } from "@webiny/db/types.js";
1
+ import { GlobalKeyValueStore } from "@webiny/api-core/features/keyValueStore/abstractions.js";
2
2
  import type { IStoreValue } from "../features/DeleteModelTask/types.js";
3
- export interface ICreateStoreKeyParams {
4
- modelId: string;
5
- tenant: string;
6
- }
7
- export declare const createStoreNamespace: (params: Pick<ICreateStoreKeyParams, "tenant">) => string;
8
- export declare const createStoreKey: (params: ICreateStoreKeyParams) => StorageKey;
9
3
  export declare const createStoreValue: (params: IStoreValue) => IStoreValue;
4
+ export interface IDeleteModelStore {
5
+ list(): Promise<IStoreValue[]>;
6
+ get(modelId: string): Promise<IStoreValue | null>;
7
+ set(value: IStoreValue): Promise<void>;
8
+ remove(modelId: string): Promise<void>;
9
+ }
10
+ /**
11
+ * Delete-model tracking store, backed by the flavour-agnostic api-core key-value store (registered
12
+ * by both the DynamoDB and SQL cores). Replaces the old `@webiny/db` `DbInstance.store`.
13
+ */
14
+ export declare const createDeleteModelStore: (store: GlobalKeyValueStore.Interface, tenant: string) => IDeleteModelStore;
package/helpers/store.js CHANGED
@@ -1,11 +1,40 @@
1
- const createStoreNamespace = (params)=>`deletingCmsModel#T#${params.tenant}#`;
2
- const createStoreKey = (params)=>`${createStoreNamespace(params)}${params.modelId}`;
1
+ const STORE_KEY = "cmsModelsBeingDeleted";
3
2
  const createStoreValue = (params)=>({
4
3
  modelId: params.modelId,
5
4
  task: params.task,
6
5
  identity: params.identity,
7
6
  tenant: params.tenant
8
7
  });
9
- export { createStoreKey, createStoreNamespace, createStoreValue };
8
+ const createDeleteModelStore = (store, tenant)=>{
9
+ const options = {
10
+ scope: tenant
11
+ };
12
+ const readMap = async ()=>{
13
+ const result = await store.get(STORE_KEY, options);
14
+ return result.isFail() ? {} : result.value ?? {};
15
+ };
16
+ const writeMap = (map)=>store.set(STORE_KEY, map, options).then(()=>void 0);
17
+ return {
18
+ async list () {
19
+ return Object.values(await readMap());
20
+ },
21
+ async get (modelId) {
22
+ const map = await readMap();
23
+ return map[modelId] ?? null;
24
+ },
25
+ async set (value) {
26
+ const map = await readMap();
27
+ map[value.modelId] = value;
28
+ await writeMap(map);
29
+ },
30
+ async remove (modelId) {
31
+ const map = await readMap();
32
+ if (!(modelId in map)) return;
33
+ delete map[modelId];
34
+ await writeMap(map);
35
+ }
36
+ };
37
+ };
38
+ export { createDeleteModelStore, createStoreValue };
10
39
 
11
40
  //# sourceMappingURL=store.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"helpers/store.js","sources":["../../src/helpers/store.ts"],"sourcesContent":["import type { StorageKey } from \"@webiny/db/types.js\";\nimport type { IStoreValue } from \"~/features/DeleteModelTask/types.js\";\n\nexport interface ICreateStoreKeyParams {\n modelId: string;\n tenant: string;\n}\n\nexport const createStoreNamespace = (params: Pick<ICreateStoreKeyParams, \"tenant\">) => {\n return `deletingCmsModel#T#${params.tenant}#`;\n};\n\nexport const createStoreKey = (params: ICreateStoreKeyParams): StorageKey => {\n return `${createStoreNamespace(params)}${params.modelId}`;\n};\n\nexport const createStoreValue = (params: IStoreValue): IStoreValue => {\n return {\n modelId: params.modelId,\n task: params.task,\n identity: params.identity,\n tenant: params.tenant\n };\n};\n"],"names":["createStoreNamespace","params","createStoreKey","createStoreValue"],"mappings":"AAQO,MAAMA,uBAAuB,CAACC,SAC1B,CAAC,mBAAmB,EAAEA,OAAO,MAAM,CAAC,CAAC,CAAC;AAG1C,MAAMC,iBAAiB,CAACD,SACpB,GAAGD,qBAAqBC,UAAUA,OAAO,OAAO,EAAE;AAGtD,MAAME,mBAAmB,CAACF,SACtB;QACH,SAASA,OAAO,OAAO;QACvB,MAAMA,OAAO,IAAI;QACjB,UAAUA,OAAO,QAAQ;QACzB,QAAQA,OAAO,MAAM;IACzB"}
1
+ {"version":3,"file":"helpers/store.js","sources":["../../src/helpers/store.ts"],"sourcesContent":["import { GlobalKeyValueStore } from \"@webiny/api-core/features/keyValueStore/abstractions.js\";\nimport type { IStoreValue } from \"~/features/DeleteModelTask/types.js\";\n\n/**\n * A single key per tenant holds the map of models currently being deleted (modelId -> record). The\n * api-core key-value store is get/set/delete only (no prefix scan), so we keep ONE map entry and\n * enumerate in memory rather than one entry per model. Tenant isolation comes from the store scope.\n */\nconst STORE_KEY = \"cmsModelsBeingDeleted\";\n\ntype StoreMap = Record<string, IStoreValue>;\n\nexport const createStoreValue = (params: IStoreValue): IStoreValue => {\n return {\n modelId: params.modelId,\n task: params.task,\n identity: params.identity,\n tenant: params.tenant\n };\n};\n\nexport interface IDeleteModelStore {\n list(): Promise<IStoreValue[]>;\n get(modelId: string): Promise<IStoreValue | null>;\n set(value: IStoreValue): Promise<void>;\n remove(modelId: string): Promise<void>;\n}\n\n/**\n * Delete-model tracking store, backed by the flavour-agnostic api-core key-value store (registered\n * by both the DynamoDB and SQL cores). Replaces the old `@webiny/db` `DbInstance.store`.\n */\nexport const createDeleteModelStore = (\n store: GlobalKeyValueStore.Interface,\n tenant: string\n): IDeleteModelStore => {\n const options = { scope: tenant };\n\n const readMap = async (): Promise<StoreMap> => {\n const result = await store.get<StoreMap>(STORE_KEY, options);\n // A missing key is a failed Result (KeyNotFound) — treat as an empty map.\n return result.isFail() ? {} : (result.value ?? {});\n };\n\n const writeMap = (map: StoreMap): Promise<void> => {\n return store.set(STORE_KEY, map, options).then(() => undefined);\n };\n\n return {\n async list() {\n return Object.values(await readMap());\n },\n async get(modelId) {\n const map = await readMap();\n return map[modelId] ?? null;\n },\n async set(value) {\n const map = await readMap();\n map[value.modelId] = value;\n await writeMap(map);\n },\n async remove(modelId) {\n const map = await readMap();\n if (!(modelId in map)) {\n return;\n }\n delete map[modelId];\n await writeMap(map);\n }\n };\n};\n"],"names":["STORE_KEY","createStoreValue","params","createDeleteModelStore","store","tenant","options","readMap","result","writeMap","map","undefined","Object","modelId","value"],"mappings":"AAQA,MAAMA,YAAY;AAIX,MAAMC,mBAAmB,CAACC,SACtB;QACH,SAASA,OAAO,OAAO;QACvB,MAAMA,OAAO,IAAI;QACjB,UAAUA,OAAO,QAAQ;QACzB,QAAQA,OAAO,MAAM;IACzB;AAcG,MAAMC,yBAAyB,CAClCC,OACAC;IAEA,MAAMC,UAAU;QAAE,OAAOD;IAAO;IAEhC,MAAME,UAAU;QACZ,MAAMC,SAAS,MAAMJ,MAAM,GAAG,CAAWJ,WAAWM;QAEpD,OAAOE,OAAO,MAAM,KAAK,CAAC,IAAKA,OAAO,KAAK,IAAI,CAAC;IACpD;IAEA,MAAMC,WAAW,CAACC,MACPN,MAAM,GAAG,CAACJ,WAAWU,KAAKJ,SAAS,IAAI,CAAC,IAAMK;IAGzD,OAAO;QACH,MAAM;YACF,OAAOC,OAAO,MAAM,CAAC,MAAML;QAC/B;QACA,MAAM,KAAIM,OAAO;YACb,MAAMH,MAAM,MAAMH;YAClB,OAAOG,GAAG,CAACG,QAAQ,IAAI;QAC3B;QACA,MAAM,KAAIC,KAAK;YACX,MAAMJ,MAAM,MAAMH;YAClBG,GAAG,CAACI,MAAM,OAAO,CAAC,GAAGA;YACrB,MAAML,SAASC;QACnB;QACA,MAAM,QAAOG,OAAO;YAChB,MAAMH,MAAM,MAAMH;YAClB,IAAI,CAAEM,CAAAA,WAAWH,GAAE,GACf;YAEJ,OAAOA,GAAG,CAACG,QAAQ;YACnB,MAAMJ,SAASC;QACnB;IACJ;AACJ"}
package/index.d.ts CHANGED
@@ -1,2 +1 @@
1
- export declare const createDeleteModelTask: () => import("@webiny/api").ContextPlugin<import("./types").HcmsTasksContext>[];
2
- export declare const createHcmsTasks: () => (import("@webiny/api").ContextPlugin<import("@webiny/api/types").Context> | (import("@webiny/api").ContextPlugin<import("@webiny/api/types").Context> | (import("@webiny/handler-aws/eventBridge").EventBridgeEventHandler<"WebinyEmptyTrashBin", Record<string, any>, any> | import("@webiny/handler/index").HandlerOnRequestPlugin<import("@webiny/handler/types").Context>)[] | import("@webiny/handler/index").BeforeHandlerPlugin<import("@webiny/api-headless-cms-bulk-actions/types").HcmsBulkActionsContext>)[])[];
1
+ export { HcmsTasksFeature } from "./HcmsTasksFeature.js";
package/index.js CHANGED
@@ -1,22 +1 @@
1
- import { createEmptyTrashBinsTask, createHcmsBulkActions } from "@webiny/api-headless-cms-bulk-actions";
2
- import { createContextPlugin } from "@webiny/api";
3
- import { DeleteModelTaskFeature } from "./features/DeleteModelTask/feature.js";
4
- import { createDeleteModelCrud } from "./graphql/deleteModel/crud.js";
5
- import { createDeleteModelGraphQl } from "./graphql/deleteModel/index.js";
6
- const createDeleteModelTask = ()=>[
7
- createDeleteModelCrud(),
8
- createDeleteModelGraphQl(),
9
- createContextPlugin((context)=>{
10
- DeleteModelTaskFeature.register(context.container);
11
- })
12
- ];
13
- const createHcmsTasks = ()=>[
14
- createHcmsBulkActions({
15
- batchSize: 100
16
- }),
17
- createEmptyTrashBinsTask(),
18
- createDeleteModelTask()
19
- ];
20
- export { createDeleteModelTask, createHcmsTasks };
21
-
22
- //# sourceMappingURL=index.js.map
1
+ export { HcmsTasksFeature } from "./HcmsTasksFeature.js";