@webiny/api-record-locking 6.6.0-alpha.7 → 6.6.0-alpha.9

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 (48) hide show
  1. package/RecordLockingAppFeature.js +4 -4
  2. package/RecordLockingAppFeature.js.map +1 -1
  3. package/domain/abstractions.d.ts +9 -3
  4. package/domain/abstractions.js +2 -2
  5. package/domain/abstractions.js.map +1 -1
  6. package/features/GetLockRecord/GetLockRecordRepository.d.ts +4 -3
  7. package/features/GetLockRecord/GetLockRecordRepository.js +20 -15
  8. package/features/GetLockRecord/GetLockRecordRepository.js.map +1 -1
  9. package/features/ListAllLockRecords/ListAllLockRecordsRepository.d.ts +3 -3
  10. package/features/ListAllLockRecords/ListAllLockRecordsRepository.js +7 -6
  11. package/features/ListAllLockRecords/ListAllLockRecordsRepository.js.map +1 -1
  12. package/features/ListLockRecords/ListLockRecordsRepository.d.ts +4 -3
  13. package/features/ListLockRecords/ListLockRecordsRepository.js +7 -6
  14. package/features/ListLockRecords/ListLockRecordsRepository.js.map +1 -1
  15. package/features/LockEntry/LockEntryRepository.d.ts +4 -3
  16. package/features/LockEntry/LockEntryRepository.js +6 -5
  17. package/features/LockEntry/LockEntryRepository.js.map +1 -1
  18. package/features/RecordLockingFeature.d.ts +0 -5
  19. package/features/RecordLockingFeature.js +3 -2
  20. package/features/RecordLockingFeature.js.map +1 -1
  21. package/features/RecordLockingModelProvider.d.ts +18 -0
  22. package/features/RecordLockingModelProvider.js +22 -0
  23. package/features/RecordLockingModelProvider.js.map +1 -0
  24. package/features/UnlockEntry/UnlockEntryRepository.d.ts +3 -3
  25. package/features/UnlockEntry/UnlockEntryRepository.js +6 -5
  26. package/features/UnlockEntry/UnlockEntryRepository.js.map +1 -1
  27. package/features/UnlockEntryRequest/UnlockEntryRequestRepository.d.ts +3 -3
  28. package/features/UnlockEntryRequest/UnlockEntryRequestRepository.js +6 -5
  29. package/features/UnlockEntryRequest/UnlockEntryRequestRepository.js.map +1 -1
  30. package/features/UpdateEntryLock/UpdateEntryLockRepository.d.ts +4 -3
  31. package/features/UpdateEntryLock/UpdateEntryLockRepository.js +7 -6
  32. package/features/UpdateEntryLock/UpdateEntryLockRepository.js.map +1 -1
  33. package/graphql/RecordLockingGraphQLSchema.d.ts +23 -0
  34. package/graphql/RecordLockingGraphQLSchema.js +372 -0
  35. package/graphql/RecordLockingGraphQLSchema.js.map +1 -0
  36. package/graphql/checkPermissions.d.ts +3 -3
  37. package/graphql/checkPermissions.js +1 -3
  38. package/graphql/checkPermissions.js.map +1 -1
  39. package/package.json +13 -15
  40. package/domain/RecordLockingAppConfig.d.ts +0 -4
  41. package/domain/RecordLockingAppConfig.js +0 -5
  42. package/domain/RecordLockingAppConfig.js.map +0 -1
  43. package/graphql/RecordLockingContextualSchema.d.ts +0 -16
  44. package/graphql/RecordLockingContextualSchema.js +0 -74
  45. package/graphql/RecordLockingContextualSchema.js.map +0 -1
  46. package/graphql/schema.d.ts +0 -11
  47. package/graphql/schema.js +0 -297
  48. package/graphql/schema.js.map +0 -1
@@ -1,5 +1,5 @@
1
- import type { ApiCoreContext } from "@webiny/api-core/types/core.js";
1
+ import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
2
2
  /**
3
- * Simple permission check. Only authenticated users can access the websockets API via GraphQL
3
+ * Simple permission check. Only authenticated users can access the record locking API via GraphQL.
4
4
  */
5
- export declare const checkPermissions: (context: ApiCoreContext) => Promise<void>;
5
+ export declare const checkPermissions: (identityContext: IdentityContext.Interface) => void;
@@ -1,7 +1,5 @@
1
- import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
2
1
  import { NotAuthorizedError } from "@webiny/api-core/features/security/shared";
3
- const checkPermissions = async (context)=>{
4
- const identityContext = context.container.resolve(IdentityContext);
2
+ const checkPermissions = (identityContext)=>{
5
3
  const identity = identityContext.getIdentity();
6
4
  if (identity.isAnonymous()) throw new NotAuthorizedError();
7
5
  };
@@ -1 +1 @@
1
- {"version":3,"file":"graphql/checkPermissions.js","sources":["../../src/graphql/checkPermissions.ts"],"sourcesContent":["import { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport { NotAuthorizedError } from \"@webiny/api-core/features/security/shared\";\nimport type { ApiCoreContext } from \"@webiny/api-core/types/core.js\";\n\n/**\n * Simple permission check. Only authenticated users can access the websockets API via GraphQL\n */\nexport const checkPermissions = async (context: ApiCoreContext): Promise<void> => {\n const identityContext = context.container.resolve(IdentityContext);\n const identity = identityContext.getIdentity();\n\n if (identity.isAnonymous()) {\n throw new NotAuthorizedError();\n }\n};\n"],"names":["checkPermissions","context","identityContext","IdentityContext","identity","NotAuthorizedError"],"mappings":";;AAOO,MAAMA,mBAAmB,OAAOC;IACnC,MAAMC,kBAAkBD,QAAQ,SAAS,CAAC,OAAO,CAACE;IAClD,MAAMC,WAAWF,gBAAgB,WAAW;IAE5C,IAAIE,SAAS,WAAW,IACpB,MAAM,IAAIC;AAElB"}
1
+ {"version":3,"file":"graphql/checkPermissions.js","sources":["../../src/graphql/checkPermissions.ts"],"sourcesContent":["import { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport { NotAuthorizedError } from \"@webiny/api-core/features/security/shared\";\n\n/**\n * Simple permission check. Only authenticated users can access the record locking API via GraphQL.\n */\nexport const checkPermissions = (identityContext: IdentityContext.Interface): void => {\n const identity = identityContext.getIdentity();\n\n if (identity.isAnonymous()) {\n throw new NotAuthorizedError();\n }\n};\n"],"names":["checkPermissions","identityContext","identity","NotAuthorizedError"],"mappings":";AAMO,MAAMA,mBAAmB,CAACC;IAC7B,MAAMC,WAAWD,gBAAgB,WAAW;IAE5C,IAAIC,SAAS,WAAW,IACpB,MAAM,IAAIC;AAElB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webiny/api-record-locking",
3
- "version": "6.6.0-alpha.7",
3
+ "version": "6.6.0-alpha.9",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -16,23 +16,21 @@
16
16
  ],
17
17
  "license": "MIT",
18
18
  "dependencies": {
19
- "@graphql-tools/merge": "9.2.3",
20
- "@graphql-tools/schema": "10.1.0",
21
- "@webiny/api": "6.6.0-alpha.7",
22
- "@webiny/api-graphql": "6.6.0-alpha.7",
23
- "@webiny/api-headless-cms": "6.6.0-alpha.7",
24
- "@webiny/api-websockets": "6.6.0-alpha.7",
25
- "@webiny/feature": "6.6.0-alpha.7",
26
- "@webiny/handler": "6.6.0-alpha.7",
27
- "@webiny/utils": "6.6.0-alpha.7"
19
+ "@webiny/api": "6.6.0-alpha.9",
20
+ "@webiny/api-graphql": "6.6.0-alpha.9",
21
+ "@webiny/api-headless-cms": "6.6.0-alpha.9",
22
+ "@webiny/api-websockets": "6.6.0-alpha.9",
23
+ "@webiny/feature": "6.6.0-alpha.9",
24
+ "@webiny/handler": "6.6.0-alpha.9",
25
+ "@webiny/utils": "6.6.0-alpha.9"
28
26
  },
29
27
  "devDependencies": {
30
- "@webiny/api-core": "6.6.0-alpha.7",
31
- "@webiny/api-core-testing": "6.6.0-alpha.7",
32
- "@webiny/build-tools": "6.6.0-alpha.7",
28
+ "@webiny/api-core": "6.6.0-alpha.9",
29
+ "@webiny/api-core-testing": "6.6.0-alpha.9",
30
+ "@webiny/build-tools": "6.6.0-alpha.9",
33
31
  "@webiny/di": "1.1.0",
34
- "@webiny/event-handler-core": "6.6.0-alpha.7",
35
- "@webiny/wcp": "6.6.0-alpha.7",
32
+ "@webiny/event-handler-core": "6.6.0-alpha.9",
33
+ "@webiny/wcp": "6.6.0-alpha.9",
36
34
  "graphql": "16.14.2",
37
35
  "rimraf": "6.1.3",
38
36
  "type-fest": "5.8.0",
@@ -1,4 +0,0 @@
1
- export interface IRecordLockingAppConfig {
2
- timeout: number;
3
- }
4
- export declare const RecordLockingAppConfig: import("@webiny/di").Abstraction<IRecordLockingAppConfig>;
@@ -1,5 +0,0 @@
1
- import { createAbstraction } from "@webiny/feature/api";
2
- const RecordLockingAppConfig = createAbstraction("RecordLockingAppConfig");
3
- export { RecordLockingAppConfig };
4
-
5
- //# sourceMappingURL=RecordLockingAppConfig.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"domain/RecordLockingAppConfig.js","sources":["../../src/domain/RecordLockingAppConfig.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/api\";\n\nexport interface IRecordLockingAppConfig {\n timeout: number;\n}\n\nexport const RecordLockingAppConfig =\n createAbstraction<IRecordLockingAppConfig>(\"RecordLockingAppConfig\");\n"],"names":["RecordLockingAppConfig","createAbstraction"],"mappings":";AAMO,MAAMA,yBACTC,kBAA2C"}
@@ -1,16 +0,0 @@
1
- import type { GraphQLSchema } from "graphql";
2
- import type { IGraphQLContextualSchema } from "@webiny/api-graphql";
3
- import { TenantContext } from "@webiny/api-core/features/tenancy/TenantContext/index.js";
4
- import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
5
- import { type IRecordLockingAppConfig } from "../domain/RecordLockingAppConfig.js";
6
- declare class RecordLockingContextualSchemaImpl implements IGraphQLContextualSchema {
7
- private tenantCtx;
8
- private identityCtx;
9
- private config;
10
- constructor(tenantCtx: TenantContext.Interface, identityCtx: IdentityContext.Interface, config: IRecordLockingAppConfig);
11
- build(ctx: Record<string, any>): Promise<GraphQLSchema>;
12
- }
13
- export declare const RecordLockingContextualSchema: typeof RecordLockingContextualSchemaImpl & {
14
- __abstraction: import("@webiny/di").Abstraction<IGraphQLContextualSchema>;
15
- };
16
- export {};
@@ -1,74 +0,0 @@
1
- import { makeExecutableSchema } from "@graphql-tools/schema";
2
- import { mergeResolvers } from "@graphql-tools/merge";
3
- import { GraphQLContextualSchema } from "@webiny/api-graphql";
4
- import { TenantContext } from "@webiny/api-core/features/tenancy/TenantContext/index.js";
5
- import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
6
- import { GetModelUseCase } from "@webiny/api-headless-cms/features/contentModel/GetModel";
7
- import { ListModelsUseCase } from "@webiny/api-headless-cms/features/contentModel/ListModels";
8
- import { CmsModelFieldToGraphQLRegistry } from "@webiny/api-headless-cms/exports/api/cms/graphql.js";
9
- import { createBaseContentSchema } from "@webiny/api-headless-cms/graphql/schema/baseContentSchema.js";
10
- import { RECORD_LOCKING_MODEL_ID } from "../domain/RecordLockingModel.js";
11
- import { RecordLockingAppConfig } from "../domain/RecordLockingAppConfig.js";
12
- import { RecordLockingFeature } from "../features/RecordLockingFeature.js";
13
- import { createGraphQLSchema } from "./schema.js";
14
- class RecordLockingContextualSchemaImpl {
15
- constructor(tenantCtx, identityCtx, config){
16
- this.tenantCtx = tenantCtx;
17
- this.identityCtx = identityCtx;
18
- this.config = config;
19
- }
20
- async build(ctx) {
21
- if (!this.tenantCtx.getTenant()) return makeExecutableSchema({
22
- typeDefs: "type Query\ntype Mutation",
23
- assumeValidSDL: true
24
- });
25
- const container = ctx.container;
26
- const getModel = container.resolve(GetModelUseCase);
27
- const listModels = container.resolve(ListModelsUseCase);
28
- const fieldRegistry = container.resolve(CmsModelFieldToGraphQLRegistry);
29
- const [model, publicModels] = await this.identityCtx.withoutAuthorization(async ()=>{
30
- const [modelResult, publicModelsResult] = await Promise.all([
31
- getModel.execute(RECORD_LOCKING_MODEL_ID),
32
- listModels.execute({
33
- includePrivate: false
34
- })
35
- ]);
36
- return [
37
- modelResult.value,
38
- publicModelsResult.value
39
- ];
40
- });
41
- RecordLockingFeature.register(container, {
42
- timeout: this.config.timeout,
43
- model
44
- });
45
- const plugin = await createGraphQLSchema({
46
- model,
47
- models: publicModels,
48
- fieldRegistry
49
- });
50
- const baseContent = createBaseContentSchema();
51
- return makeExecutableSchema({
52
- typeDefs: [
53
- baseContent.schema.typeDefs,
54
- plugin.schema.typeDefs
55
- ],
56
- resolvers: mergeResolvers([
57
- baseContent.schema.resolvers,
58
- plugin.schema.resolvers
59
- ]),
60
- inheritResolversFromInterfaces: true
61
- });
62
- }
63
- }
64
- const RecordLockingContextualSchema = GraphQLContextualSchema.createImplementation({
65
- implementation: RecordLockingContextualSchemaImpl,
66
- dependencies: [
67
- TenantContext,
68
- IdentityContext,
69
- RecordLockingAppConfig
70
- ]
71
- });
72
- export { RecordLockingContextualSchema };
73
-
74
- //# sourceMappingURL=RecordLockingContextualSchema.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"graphql/RecordLockingContextualSchema.js","sources":["../../src/graphql/RecordLockingContextualSchema.ts"],"sourcesContent":["import type { Container } from \"@webiny/di\";\nimport type { GraphQLSchema } from \"graphql\";\nimport { makeExecutableSchema } from \"@graphql-tools/schema\";\nimport { mergeResolvers } from \"@graphql-tools/merge\";\nimport { GraphQLContextualSchema } from \"@webiny/api-graphql\";\nimport type { IGraphQLContextualSchema } from \"@webiny/api-graphql\";\nimport { TenantContext } from \"@webiny/api-core/features/tenancy/TenantContext/index.js\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport { GetModelUseCase } from \"@webiny/api-headless-cms/features/contentModel/GetModel\";\nimport { ListModelsUseCase } from \"@webiny/api-headless-cms/features/contentModel/ListModels\";\nimport { CmsModelFieldToGraphQLRegistry } from \"@webiny/api-headless-cms/exports/api/cms/graphql.js\";\nimport { createBaseContentSchema } from \"@webiny/api-headless-cms/graphql/schema/baseContentSchema.js\";\nimport { RECORD_LOCKING_MODEL_ID } from \"~/domain/RecordLockingModel.js\";\nimport {\n RecordLockingAppConfig,\n type IRecordLockingAppConfig\n} from \"~/domain/RecordLockingAppConfig.js\";\nimport { RecordLockingFeature } from \"~/features/RecordLockingFeature.js\";\nimport { createGraphQLSchema } from \"~/graphql/schema.js\";\n\nclass RecordLockingContextualSchemaImpl implements IGraphQLContextualSchema {\n constructor(\n private tenantCtx: TenantContext.Interface,\n private identityCtx: IdentityContext.Interface,\n private config: IRecordLockingAppConfig\n ) {}\n\n async build(ctx: Record<string, any>): Promise<GraphQLSchema> {\n // Only registered when recordLocking is licensed (RecordLockingAppFeature gates on the flag),\n // so here we only fall back to an empty schema until the tenant is known.\n if (!this.tenantCtx.getTenant()) {\n return makeExecutableSchema({\n typeDefs: \"type Query\\ntype Mutation\",\n assumeValidSDL: true\n });\n }\n\n const container = ctx.container as Container;\n\n // Resolve the CMS use-cases lazily here (at build/request time) rather than as\n // constructor dependencies. They depend on AccessControl/CmsContext, which the CMS\n // initializer only registers during its own build() — so injecting them eagerly would\n // fail when the engine constructs all contextual schemas before any build() has run.\n const getModel = container.resolve(GetModelUseCase);\n const listModels = container.resolve(ListModelsUseCase);\n const fieldRegistry = container.resolve(CmsModelFieldToGraphQLRegistry);\n\n const [model, publicModels] = await this.identityCtx.withoutAuthorization(async () => {\n const [modelResult, publicModelsResult] = await Promise.all([\n getModel.execute(RECORD_LOCKING_MODEL_ID),\n listModels.execute({ includePrivate: false })\n ]);\n\n return [modelResult.value, publicModelsResult.value];\n });\n\n RecordLockingFeature.register(container, {\n timeout: this.config.timeout,\n model\n });\n\n const plugin = await createGraphQLSchema({\n model,\n models: publicModels,\n fieldRegistry\n });\n\n // The generated record-locking model schema references CMS base scalars (DateTime, JSON,\n // etc.). Include createBaseContentSchema() — which declares those scalars and their\n // resolvers — exactly as the normal CMS schema build (buildSchemaPlugins) does, so this\n // standalone schema is self-contained and valid before it is merged by the engine.\n const baseContent = createBaseContentSchema();\n\n return makeExecutableSchema({\n typeDefs: [baseContent.schema.typeDefs as string, plugin.schema.typeDefs as string],\n resolvers: mergeResolvers([\n baseContent.schema.resolvers as any,\n plugin.schema.resolvers as any\n ]),\n inheritResolversFromInterfaces: true\n });\n }\n}\n\nexport const RecordLockingContextualSchema = GraphQLContextualSchema.createImplementation({\n implementation: RecordLockingContextualSchemaImpl,\n dependencies: [TenantContext, IdentityContext, RecordLockingAppConfig]\n});\n"],"names":["RecordLockingContextualSchemaImpl","tenantCtx","identityCtx","config","ctx","makeExecutableSchema","container","getModel","GetModelUseCase","listModels","ListModelsUseCase","fieldRegistry","CmsModelFieldToGraphQLRegistry","model","publicModels","modelResult","publicModelsResult","Promise","RECORD_LOCKING_MODEL_ID","RecordLockingFeature","plugin","createGraphQLSchema","baseContent","createBaseContentSchema","mergeResolvers","RecordLockingContextualSchema","GraphQLContextualSchema","TenantContext","IdentityContext","RecordLockingAppConfig"],"mappings":";;;;;;;;;;;;;AAoBA,MAAMA;IACF,YACYC,SAAkC,EAClCC,WAAsC,EACtCC,MAA+B,CACzC;aAHUF,SAAS,GAATA;aACAC,WAAW,GAAXA;aACAC,MAAM,GAANA;IACT;IAEH,MAAM,MAAMC,GAAwB,EAA0B;QAG1D,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,IACzB,OAAOC,qBAAqB;YACxB,UAAU;YACV,gBAAgB;QACpB;QAGJ,MAAMC,YAAYF,IAAI,SAAS;QAM/B,MAAMG,WAAWD,UAAU,OAAO,CAACE;QACnC,MAAMC,aAAaH,UAAU,OAAO,CAACI;QACrC,MAAMC,gBAAgBL,UAAU,OAAO,CAACM;QAExC,MAAM,CAACC,OAAOC,aAAa,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,oBAAoB,CAAC;YACtE,MAAM,CAACC,aAAaC,mBAAmB,GAAG,MAAMC,QAAQ,GAAG,CAAC;gBACxDV,SAAS,OAAO,CAACW;gBACjBT,WAAW,OAAO,CAAC;oBAAE,gBAAgB;gBAAM;aAC9C;YAED,OAAO;gBAACM,YAAY,KAAK;gBAAEC,mBAAmB,KAAK;aAAC;QACxD;QAEAG,qBAAqB,QAAQ,CAACb,WAAW;YACrC,SAAS,IAAI,CAAC,MAAM,CAAC,OAAO;YAC5BO;QACJ;QAEA,MAAMO,SAAS,MAAMC,oBAAoB;YACrCR;YACA,QAAQC;YACRH;QACJ;QAMA,MAAMW,cAAcC;QAEpB,OAAOlB,qBAAqB;YACxB,UAAU;gBAACiB,YAAY,MAAM,CAAC,QAAQ;gBAAYF,OAAO,MAAM,CAAC,QAAQ;aAAW;YACnF,WAAWI,eAAe;gBACtBF,YAAY,MAAM,CAAC,SAAS;gBAC5BF,OAAO,MAAM,CAAC,SAAS;aAC1B;YACD,gCAAgC;QACpC;IACJ;AACJ;AAEO,MAAMK,gCAAgCC,wBAAwB,oBAAoB,CAAC;IACtF,gBAAgB1B;IAChB,cAAc;QAAC2B;QAAeC;QAAiBC;KAAuB;AAC1E"}
@@ -1,11 +0,0 @@
1
- import type { IGraphQLSchemaPlugin } from "@webiny/api-graphql";
2
- import type { ApiCoreContext } from "@webiny/api-core/types/core.js";
3
- import { CmsModel } from "@webiny/api-headless-cms/types/model.js";
4
- import type { CmsModelFieldToGraphQLRegistry } from "@webiny/api-headless-cms/exports/api/cms/graphql.js";
5
- interface Params {
6
- model: CmsModel;
7
- models: CmsModel[];
8
- fieldRegistry: CmsModelFieldToGraphQLRegistry.Interface;
9
- }
10
- export declare const createGraphQLSchema: (params: Params) => Promise<IGraphQLSchemaPlugin<ApiCoreContext>>;
11
- export {};
package/graphql/schema.js DELETED
@@ -1,297 +0,0 @@
1
- import { resolve, resolveList } from "./resolve.js";
2
- import { createGraphQLSchemaPlugin } from "@webiny/api-graphql";
3
- import { renderFields } from "@webiny/api-headless-cms/utils/renderFields.js";
4
- import { renderListFilterFields } from "@webiny/api-headless-cms/utils/renderListFilterFields.js";
5
- import { renderSortEnum } from "@webiny/api-headless-cms/utils/renderSortEnum.js";
6
- import { checkPermissions } from "./checkPermissions.js";
7
- import { IsEntryLockedUseCase } from "../features/IsEntryLocked/abstractions.js";
8
- import { GetLockRecordUseCase } from "../features/GetLockRecord/abstractions.js";
9
- import { GetLockedEntryLockRecordUseCase } from "../features/GetLockedEntryLockRecord/abstractions.js";
10
- import { ListLockRecordsUseCase } from "../features/ListLockRecords/abstractions.js";
11
- import { ListAllLockRecordsUseCase } from "../features/ListAllLockRecords/abstractions.js";
12
- import { LockEntryUseCase } from "../features/LockEntry/abstractions.js";
13
- import { UpdateEntryLockUseCase } from "../features/UpdateEntryLock/abstractions.js";
14
- import { UnlockEntryUseCase } from "../features/UnlockEntry/abstractions.js";
15
- import { UnlockEntryRequestUseCase } from "../features/UnlockEntryRequest/abstractions.js";
16
- const createGraphQLSchema = async (params)=>{
17
- const model = params.model;
18
- const models = params.models.filter((model)=>model.fields.length > 0);
19
- const fieldRegistry = params.fieldRegistry;
20
- const recordLockingFields = renderFields({
21
- models,
22
- model,
23
- fields: model.fields,
24
- type: "manage",
25
- fieldRegistry
26
- });
27
- const listFilterFieldsRender = renderListFilterFields({
28
- model,
29
- fields: model.fields,
30
- type: "manage",
31
- fieldRegistry,
32
- excludeFields: [
33
- "entryId"
34
- ]
35
- });
36
- const sortEnumRender = renderSortEnum({
37
- model,
38
- fields: model.fields,
39
- fieldRegistry,
40
- sorters: []
41
- });
42
- const plugin = createGraphQLSchemaPlugin({
43
- typeDefs: `
44
- ${recordLockingFields.map((f)=>f.typeDefs).join("\n")}
45
-
46
- type RecordLockingError {
47
- message: String
48
- code: String
49
- data: JSON
50
- stack: String
51
- }
52
-
53
- enum RecordLockingRecordActionType {
54
- requested
55
- approved
56
- denied
57
- }
58
-
59
- type RecordLockingIdentity {
60
- id: String!
61
- displayName: String
62
- type: String
63
- }
64
-
65
- type RecordLockingRecordAction {
66
- id: ID!
67
- type: RecordLockingRecordActionType!
68
- message: String
69
- createdBy: RecordLockingIdentity!
70
- createdOn: DateTime!
71
- }
72
-
73
- type RecordLockingRecord {
74
- id: ID!
75
- lockedBy: RecordLockingIdentity!
76
- lockedOn: DateTime!
77
- updatedOn: DateTime!
78
- expiresOn: DateTime!
79
- ${recordLockingFields.map((f)=>f.fields).join("\n")}
80
- }
81
-
82
- type RecordLockingIsEntryLockedResponse {
83
- data: Boolean
84
- error: RecordLockingError
85
- }
86
-
87
- type RecordLockingGetLockRecordResponse {
88
- data: RecordLockingRecord
89
- error: RecordLockingError
90
- }
91
-
92
- type RecordLockingGetLockedEntryLockRecordResponse {
93
- data: RecordLockingRecord
94
- error: RecordLockingError
95
- }
96
-
97
- type RecordLockingListLockRecordsResponse {
98
- data: [RecordLockingRecord!]
99
- error: RecordLockingError
100
- }
101
-
102
- type RecordLockingLockEntryResponse {
103
- data: RecordLockingRecord
104
- error: RecordLockingError
105
- }
106
-
107
- type RecordLockingUpdateLockResponse {
108
- data: RecordLockingRecord
109
- error: RecordLockingError
110
- }
111
-
112
- type RecordLockingUnlockEntryResponse {
113
- data: RecordLockingRecord
114
- error: RecordLockingError
115
- }
116
-
117
- type RecordLockingUnlockEntryRequestResponse {
118
- data: RecordLockingRecord
119
- error: RecordLockingError
120
- }
121
-
122
- input RecordLockingListWhereInput {
123
- ${listFilterFieldsRender.allFiltersAsString()}
124
- }
125
-
126
- enum RecordLockingListSorter {
127
- ${sortEnumRender}
128
- }
129
-
130
- type RecordLockingQuery {
131
- _empty: String
132
- }
133
-
134
- type RecordLockingMutation {
135
- _empty: String
136
- }
137
-
138
- extend type RecordLockingQuery {
139
- isEntryLocked(id: ID!, type: String!): RecordLockingIsEntryLockedResponse!
140
- getLockRecord(id: ID!, type: String!): RecordLockingGetLockRecordResponse!
141
- # Returns lock record or null - if entry is locked in context of the current user, does not throw an error like getLockRecord if no record in the DB
142
- getLockedEntryLockRecord(id: ID!, type: String!): RecordLockingGetLockedEntryLockRecordResponse!
143
- listAllLockRecords(
144
- where: RecordLockingListWhereInput
145
- sort: [RecordLockingListSorter!]
146
- limit: Int
147
- after: String
148
- ): RecordLockingListLockRecordsResponse!
149
- # Basically same as listAllLockRecords except this one will filter out records with expired lock.
150
- listLockRecords(
151
- where: RecordLockingListWhereInput
152
- sort: [RecordLockingListSorter!]
153
- limit: Int
154
- after: String
155
- ): RecordLockingListLockRecordsResponse!
156
- }
157
-
158
- extend type RecordLockingMutation {
159
- lockEntry(id: ID!, type: String!): RecordLockingLockEntryResponse!
160
- updateEntryLock(id: ID!, type: String!): RecordLockingUpdateLockResponse!
161
- unlockEntry(id: ID!, type: String!, force: Boolean): RecordLockingUnlockEntryResponse!
162
- unlockEntryRequest(
163
- id: ID!
164
- type: String!
165
- ): RecordLockingUnlockEntryRequestResponse!
166
- }
167
-
168
- extend type Query {
169
- recordLocking: RecordLockingQuery
170
- }
171
-
172
- extend type Mutation {
173
- recordLocking: RecordLockingMutation
174
- }
175
- `,
176
- resolvers: {
177
- Query: {
178
- recordLocking: async ()=>({})
179
- },
180
- Mutation: {
181
- recordLocking: async ()=>({})
182
- },
183
- RecordLockingQuery: {
184
- async isEntryLocked (_, args, context) {
185
- return resolve(async ()=>{
186
- await checkPermissions(context);
187
- const useCase = context.container.resolve(IsEntryLockedUseCase);
188
- const result = await useCase.execute({
189
- id: args.id,
190
- type: args.type
191
- });
192
- if (result.isFail()) throw result.error;
193
- return result.value;
194
- });
195
- },
196
- async getLockRecord (_, args, context) {
197
- return resolve(async ()=>{
198
- await checkPermissions(context);
199
- const useCase = context.container.resolve(GetLockRecordUseCase);
200
- const result = await useCase.execute({
201
- id: args.id,
202
- type: args.type
203
- });
204
- if (result.isFail()) throw result.error;
205
- return result.value;
206
- });
207
- },
208
- async getLockedEntryLockRecord (_, args, context) {
209
- return resolve(async ()=>{
210
- await checkPermissions(context);
211
- const useCase = context.container.resolve(GetLockedEntryLockRecordUseCase);
212
- const result = await useCase.execute({
213
- id: args.id,
214
- type: args.type
215
- });
216
- if (result.isFail()) return null;
217
- return result.value;
218
- });
219
- },
220
- async listLockRecords (_, args, context) {
221
- return resolveList(async ()=>{
222
- await checkPermissions(context);
223
- const useCase = context.container.resolve(ListLockRecordsUseCase);
224
- const result = await useCase.execute(args);
225
- if (result.isFail()) throw result.error;
226
- return result.value;
227
- });
228
- },
229
- listAllLockRecords (_, args, context) {
230
- return resolveList(async ()=>{
231
- await checkPermissions(context);
232
- const useCase = context.container.resolve(ListAllLockRecordsUseCase);
233
- const result = await useCase.execute(args);
234
- if (result.isFail()) throw result.error;
235
- return result.value;
236
- });
237
- }
238
- },
239
- RecordLockingMutation: {
240
- async lockEntry (_, args, context) {
241
- return resolve(async ()=>{
242
- await checkPermissions(context);
243
- const useCase = context.container.resolve(LockEntryUseCase);
244
- const result = await useCase.execute({
245
- id: args.id,
246
- type: args.type
247
- });
248
- if (result.isFail()) throw result.error;
249
- return result.value;
250
- });
251
- },
252
- async updateEntryLock (_, args, context) {
253
- return resolve(async ()=>{
254
- await checkPermissions(context);
255
- const useCase = context.container.resolve(UpdateEntryLockUseCase);
256
- const result = await useCase.execute({
257
- id: args.id,
258
- type: args.type
259
- });
260
- if (result.isFail()) throw result.error;
261
- return result.value;
262
- });
263
- },
264
- async unlockEntry (_, args, context) {
265
- return resolve(async ()=>{
266
- await checkPermissions(context);
267
- const useCase = context.container.resolve(UnlockEntryUseCase);
268
- const result = await useCase.execute({
269
- id: args.id,
270
- type: args.type,
271
- force: args.force
272
- });
273
- if (result.isFail()) throw result.error;
274
- return result.value;
275
- });
276
- },
277
- async unlockEntryRequest (_, args, context) {
278
- return resolve(async ()=>{
279
- await checkPermissions(context);
280
- const useCase = context.container.resolve(UnlockEntryRequestUseCase);
281
- const result = await useCase.execute({
282
- id: args.id,
283
- type: args.type
284
- });
285
- if (result.isFail()) throw result.error;
286
- return result.value;
287
- });
288
- }
289
- }
290
- }
291
- });
292
- plugin.name = "recordLocking.graphql.schema.locking";
293
- return plugin;
294
- };
295
- export { createGraphQLSchema };
296
-
297
- //# sourceMappingURL=schema.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"graphql/schema.js","sources":["../../src/graphql/schema.ts"],"sourcesContent":["import { resolve, resolveList } from \"./resolve.js\";\nimport type { IGraphQLSchemaPlugin } from \"@webiny/api-graphql\";\nimport { createGraphQLSchemaPlugin } from \"@webiny/api-graphql\";\nimport { renderFields } from \"@webiny/api-headless-cms/utils/renderFields.js\";\nimport { renderListFilterFields } from \"@webiny/api-headless-cms/utils/renderListFilterFields.js\";\nimport { renderSortEnum } from \"@webiny/api-headless-cms/utils/renderSortEnum.js\";\nimport { checkPermissions } from \"./checkPermissions.js\";\nimport { IsEntryLockedUseCase } from \"~/features/IsEntryLocked/abstractions.js\";\nimport { GetLockRecordUseCase } from \"~/features/GetLockRecord/abstractions.js\";\nimport { GetLockedEntryLockRecordUseCase } from \"~/features/GetLockedEntryLockRecord/abstractions.js\";\nimport { ListLockRecordsUseCase } from \"~/features/ListLockRecords/abstractions.js\";\nimport { ListAllLockRecordsUseCase } from \"~/features/ListAllLockRecords/abstractions.js\";\nimport { LockEntryUseCase } from \"~/features/LockEntry/abstractions.js\";\nimport { UpdateEntryLockUseCase } from \"~/features/UpdateEntryLock/abstractions.js\";\nimport { UnlockEntryUseCase } from \"~/features/UnlockEntry/abstractions.js\";\nimport { UnlockEntryRequestUseCase } from \"~/features/UnlockEntryRequest/abstractions.js\";\nimport type { ApiCoreContext } from \"@webiny/api-core/types/core.js\";\nimport { CmsModel } from \"@webiny/api-headless-cms/types/model.js\";\nimport type { CmsModelFieldToGraphQLRegistry } from \"@webiny/api-headless-cms/exports/api/cms/graphql.js\";\n\ninterface Params {\n model: CmsModel;\n models: CmsModel[];\n fieldRegistry: CmsModelFieldToGraphQLRegistry.Interface;\n}\nexport const createGraphQLSchema = async (\n params: Params\n): Promise<IGraphQLSchemaPlugin<ApiCoreContext>> => {\n const model = params.model;\n\n const models = params.models.filter(model => {\n return model.fields.length > 0;\n });\n\n const fieldRegistry = params.fieldRegistry;\n\n const recordLockingFields = renderFields({\n models,\n model,\n fields: model.fields,\n type: \"manage\",\n fieldRegistry\n });\n\n const listFilterFieldsRender = renderListFilterFields({\n model,\n fields: model.fields,\n type: \"manage\",\n fieldRegistry,\n excludeFields: [\"entryId\"]\n });\n\n const sortEnumRender = renderSortEnum({\n model,\n fields: model.fields,\n fieldRegistry,\n sorters: []\n });\n\n const plugin = createGraphQLSchemaPlugin<ApiCoreContext>({\n typeDefs: /* GraphQL */ `\n ${recordLockingFields.map(f => f.typeDefs).join(\"\\n\")}\n\n type RecordLockingError {\n message: String\n code: String\n data: JSON\n stack: String\n }\n\n enum RecordLockingRecordActionType {\n requested\n approved\n denied\n }\n\n type RecordLockingIdentity {\n id: String!\n displayName: String\n type: String\n }\n\n type RecordLockingRecordAction {\n id: ID!\n type: RecordLockingRecordActionType!\n message: String\n createdBy: RecordLockingIdentity!\n createdOn: DateTime!\n }\n\n type RecordLockingRecord {\n id: ID!\n lockedBy: RecordLockingIdentity!\n lockedOn: DateTime!\n updatedOn: DateTime!\n expiresOn: DateTime!\n ${recordLockingFields.map(f => f.fields).join(\"\\n\")}\n }\n\n type RecordLockingIsEntryLockedResponse {\n data: Boolean\n error: RecordLockingError\n }\n\n type RecordLockingGetLockRecordResponse {\n data: RecordLockingRecord\n error: RecordLockingError\n }\n\n type RecordLockingGetLockedEntryLockRecordResponse {\n data: RecordLockingRecord\n error: RecordLockingError\n }\n\n type RecordLockingListLockRecordsResponse {\n data: [RecordLockingRecord!]\n error: RecordLockingError\n }\n\n type RecordLockingLockEntryResponse {\n data: RecordLockingRecord\n error: RecordLockingError\n }\n \n type RecordLockingUpdateLockResponse {\n data: RecordLockingRecord\n error: RecordLockingError\n }\n\n type RecordLockingUnlockEntryResponse {\n data: RecordLockingRecord\n error: RecordLockingError\n }\n\n type RecordLockingUnlockEntryRequestResponse {\n data: RecordLockingRecord\n error: RecordLockingError\n }\n\n input RecordLockingListWhereInput {\n ${listFilterFieldsRender.allFiltersAsString()}\n }\n\n enum RecordLockingListSorter {\n ${sortEnumRender}\n }\n\n type RecordLockingQuery {\n _empty: String\n }\n\n type RecordLockingMutation {\n _empty: String\n }\n\n extend type RecordLockingQuery {\n isEntryLocked(id: ID!, type: String!): RecordLockingIsEntryLockedResponse!\n getLockRecord(id: ID!, type: String!): RecordLockingGetLockRecordResponse!\n # Returns lock record or null - if entry is locked in context of the current user, does not throw an error like getLockRecord if no record in the DB\n getLockedEntryLockRecord(id: ID!, type: String!): RecordLockingGetLockedEntryLockRecordResponse!\n listAllLockRecords(\n where: RecordLockingListWhereInput\n sort: [RecordLockingListSorter!]\n limit: Int\n after: String\n ): RecordLockingListLockRecordsResponse!\n # Basically same as listAllLockRecords except this one will filter out records with expired lock.\n listLockRecords(\n where: RecordLockingListWhereInput\n sort: [RecordLockingListSorter!]\n limit: Int\n after: String\n ): RecordLockingListLockRecordsResponse!\n }\n\n extend type RecordLockingMutation {\n lockEntry(id: ID!, type: String!): RecordLockingLockEntryResponse!\n updateEntryLock(id: ID!, type: String!): RecordLockingUpdateLockResponse!\n unlockEntry(id: ID!, type: String!, force: Boolean): RecordLockingUnlockEntryResponse!\n unlockEntryRequest(\n id: ID!\n type: String!\n ): RecordLockingUnlockEntryRequestResponse!\n }\n\n extend type Query {\n recordLocking: RecordLockingQuery\n }\n\n extend type Mutation {\n recordLocking: RecordLockingMutation\n }\n `,\n resolvers: {\n Query: {\n recordLocking: async () => ({})\n },\n Mutation: {\n recordLocking: async () => ({})\n },\n RecordLockingQuery: {\n async isEntryLocked(_, args, context) {\n return resolve(async () => {\n await checkPermissions(context);\n const useCase = context.container.resolve(IsEntryLockedUseCase);\n const result = await useCase.execute({\n id: args.id,\n type: args.type\n });\n if (result.isFail()) {\n throw result.error;\n }\n return result.value;\n });\n },\n async getLockRecord(_, args, context) {\n return resolve(async () => {\n await checkPermissions(context);\n const useCase = context.container.resolve(GetLockRecordUseCase);\n const result = await useCase.execute({\n id: args.id,\n type: args.type\n });\n if (result.isFail()) {\n throw result.error;\n }\n return result.value;\n });\n },\n async getLockedEntryLockRecord(_, args, context) {\n return resolve(async () => {\n await checkPermissions(context);\n const useCase = context.container.resolve(GetLockedEntryLockRecordUseCase);\n const result = await useCase.execute({\n id: args.id,\n type: args.type\n });\n // Returns null if not found/expired/locked by current user\n if (result.isFail()) {\n return null;\n }\n return result.value;\n });\n },\n\n async listLockRecords(_, args, context) {\n return resolveList(async () => {\n await checkPermissions(context);\n const useCase = context.container.resolve(ListLockRecordsUseCase);\n const result = await useCase.execute(args);\n if (result.isFail()) {\n throw result.error;\n }\n return result.value;\n });\n },\n listAllLockRecords(_, args, context) {\n return resolveList(async () => {\n await checkPermissions(context);\n const useCase = context.container.resolve(ListAllLockRecordsUseCase);\n const result = await useCase.execute(args);\n if (result.isFail()) {\n throw result.error;\n }\n return result.value;\n });\n }\n },\n RecordLockingMutation: {\n async lockEntry(_, args, context) {\n return resolve(async () => {\n await checkPermissions(context);\n const useCase = context.container.resolve(LockEntryUseCase);\n const result = await useCase.execute({\n id: args.id,\n type: args.type\n });\n if (result.isFail()) {\n throw result.error;\n }\n return result.value;\n });\n },\n async updateEntryLock(_, args, context) {\n return resolve(async () => {\n await checkPermissions(context);\n const useCase = context.container.resolve(UpdateEntryLockUseCase);\n const result = await useCase.execute({\n id: args.id,\n type: args.type\n });\n if (result.isFail()) {\n throw result.error;\n }\n return result.value;\n });\n },\n async unlockEntry(_, args, context) {\n return resolve(async () => {\n await checkPermissions(context);\n const useCase = context.container.resolve(UnlockEntryUseCase);\n const result = await useCase.execute({\n id: args.id,\n type: args.type,\n force: args.force\n });\n if (result.isFail()) {\n throw result.error;\n }\n return result.value;\n });\n },\n async unlockEntryRequest(_, args, context) {\n return resolve(async () => {\n await checkPermissions(context);\n const useCase = context.container.resolve(UnlockEntryRequestUseCase);\n const result = await useCase.execute({\n id: args.id,\n type: args.type\n });\n if (result.isFail()) {\n throw result.error;\n }\n return result.value;\n });\n }\n }\n }\n });\n\n plugin.name = \"recordLocking.graphql.schema.locking\";\n\n return plugin;\n};\n"],"names":["createGraphQLSchema","params","model","models","fieldRegistry","recordLockingFields","renderFields","listFilterFieldsRender","renderListFilterFields","sortEnumRender","renderSortEnum","plugin","createGraphQLSchemaPlugin","f","_","args","context","resolve","checkPermissions","useCase","IsEntryLockedUseCase","result","GetLockRecordUseCase","GetLockedEntryLockRecordUseCase","resolveList","ListLockRecordsUseCase","ListAllLockRecordsUseCase","LockEntryUseCase","UpdateEntryLockUseCase","UnlockEntryUseCase","UnlockEntryRequestUseCase"],"mappings":";;;;;;;;;;;;;;;AAyBO,MAAMA,sBAAsB,OAC/BC;IAEA,MAAMC,QAAQD,OAAO,KAAK;IAE1B,MAAME,SAASF,OAAO,MAAM,CAAC,MAAM,CAACC,CAAAA,QACzBA,MAAM,MAAM,CAAC,MAAM,GAAG;IAGjC,MAAME,gBAAgBH,OAAO,aAAa;IAE1C,MAAMI,sBAAsBC,aAAa;QACrCH;QACAD;QACA,QAAQA,MAAM,MAAM;QACpB,MAAM;QACNE;IACJ;IAEA,MAAMG,yBAAyBC,uBAAuB;QAClDN;QACA,QAAQA,MAAM,MAAM;QACpB,MAAM;QACNE;QACA,eAAe;YAAC;SAAU;IAC9B;IAEA,MAAMK,iBAAiBC,eAAe;QAClCR;QACA,QAAQA,MAAM,MAAM;QACpBE;QACA,SAAS,EAAE;IACf;IAEA,MAAMO,SAASC,0BAA0C;QACrD,UAAwB,CAAC;YACrB,EAAEP,oBAAoB,GAAG,CAACQ,CAAAA,IAAKA,EAAE,QAAQ,EAAE,IAAI,CAAC,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBAmClD,EAAER,oBAAoB,GAAG,CAACQ,CAAAA,IAAKA,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBA4CpD,EAAEN,uBAAuB,kBAAkB,GAAG;;;;gBAI9C,EAAEE,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAgDzB,CAAC;QACD,WAAW;YACP,OAAO;gBACH,eAAe,UAAa,EAAC;YACjC;YACA,UAAU;gBACN,eAAe,UAAa,EAAC;YACjC;YACA,oBAAoB;gBAChB,MAAM,eAAcK,CAAC,EAAEC,IAAI,EAAEC,OAAO;oBAChC,OAAOC,QAAQ;wBACX,MAAMC,iBAAiBF;wBACvB,MAAMG,UAAUH,QAAQ,SAAS,CAAC,OAAO,CAACI;wBAC1C,MAAMC,SAAS,MAAMF,QAAQ,OAAO,CAAC;4BACjC,IAAIJ,KAAK,EAAE;4BACX,MAAMA,KAAK,IAAI;wBACnB;wBACA,IAAIM,OAAO,MAAM,IACb,MAAMA,OAAO,KAAK;wBAEtB,OAAOA,OAAO,KAAK;oBACvB;gBACJ;gBACA,MAAM,eAAcP,CAAC,EAAEC,IAAI,EAAEC,OAAO;oBAChC,OAAOC,QAAQ;wBACX,MAAMC,iBAAiBF;wBACvB,MAAMG,UAAUH,QAAQ,SAAS,CAAC,OAAO,CAACM;wBAC1C,MAAMD,SAAS,MAAMF,QAAQ,OAAO,CAAC;4BACjC,IAAIJ,KAAK,EAAE;4BACX,MAAMA,KAAK,IAAI;wBACnB;wBACA,IAAIM,OAAO,MAAM,IACb,MAAMA,OAAO,KAAK;wBAEtB,OAAOA,OAAO,KAAK;oBACvB;gBACJ;gBACA,MAAM,0BAAyBP,CAAC,EAAEC,IAAI,EAAEC,OAAO;oBAC3C,OAAOC,QAAQ;wBACX,MAAMC,iBAAiBF;wBACvB,MAAMG,UAAUH,QAAQ,SAAS,CAAC,OAAO,CAACO;wBAC1C,MAAMF,SAAS,MAAMF,QAAQ,OAAO,CAAC;4BACjC,IAAIJ,KAAK,EAAE;4BACX,MAAMA,KAAK,IAAI;wBACnB;wBAEA,IAAIM,OAAO,MAAM,IACb,OAAO;wBAEX,OAAOA,OAAO,KAAK;oBACvB;gBACJ;gBAEA,MAAM,iBAAgBP,CAAC,EAAEC,IAAI,EAAEC,OAAO;oBAClC,OAAOQ,YAAY;wBACf,MAAMN,iBAAiBF;wBACvB,MAAMG,UAAUH,QAAQ,SAAS,CAAC,OAAO,CAACS;wBAC1C,MAAMJ,SAAS,MAAMF,QAAQ,OAAO,CAACJ;wBACrC,IAAIM,OAAO,MAAM,IACb,MAAMA,OAAO,KAAK;wBAEtB,OAAOA,OAAO,KAAK;oBACvB;gBACJ;gBACA,oBAAmBP,CAAC,EAAEC,IAAI,EAAEC,OAAO;oBAC/B,OAAOQ,YAAY;wBACf,MAAMN,iBAAiBF;wBACvB,MAAMG,UAAUH,QAAQ,SAAS,CAAC,OAAO,CAACU;wBAC1C,MAAML,SAAS,MAAMF,QAAQ,OAAO,CAACJ;wBACrC,IAAIM,OAAO,MAAM,IACb,MAAMA,OAAO,KAAK;wBAEtB,OAAOA,OAAO,KAAK;oBACvB;gBACJ;YACJ;YACA,uBAAuB;gBACnB,MAAM,WAAUP,CAAC,EAAEC,IAAI,EAAEC,OAAO;oBAC5B,OAAOC,QAAQ;wBACX,MAAMC,iBAAiBF;wBACvB,MAAMG,UAAUH,QAAQ,SAAS,CAAC,OAAO,CAACW;wBAC1C,MAAMN,SAAS,MAAMF,QAAQ,OAAO,CAAC;4BACjC,IAAIJ,KAAK,EAAE;4BACX,MAAMA,KAAK,IAAI;wBACnB;wBACA,IAAIM,OAAO,MAAM,IACb,MAAMA,OAAO,KAAK;wBAEtB,OAAOA,OAAO,KAAK;oBACvB;gBACJ;gBACA,MAAM,iBAAgBP,CAAC,EAAEC,IAAI,EAAEC,OAAO;oBAClC,OAAOC,QAAQ;wBACX,MAAMC,iBAAiBF;wBACvB,MAAMG,UAAUH,QAAQ,SAAS,CAAC,OAAO,CAACY;wBAC1C,MAAMP,SAAS,MAAMF,QAAQ,OAAO,CAAC;4BACjC,IAAIJ,KAAK,EAAE;4BACX,MAAMA,KAAK,IAAI;wBACnB;wBACA,IAAIM,OAAO,MAAM,IACb,MAAMA,OAAO,KAAK;wBAEtB,OAAOA,OAAO,KAAK;oBACvB;gBACJ;gBACA,MAAM,aAAYP,CAAC,EAAEC,IAAI,EAAEC,OAAO;oBAC9B,OAAOC,QAAQ;wBACX,MAAMC,iBAAiBF;wBACvB,MAAMG,UAAUH,QAAQ,SAAS,CAAC,OAAO,CAACa;wBAC1C,MAAMR,SAAS,MAAMF,QAAQ,OAAO,CAAC;4BACjC,IAAIJ,KAAK,EAAE;4BACX,MAAMA,KAAK,IAAI;4BACf,OAAOA,KAAK,KAAK;wBACrB;wBACA,IAAIM,OAAO,MAAM,IACb,MAAMA,OAAO,KAAK;wBAEtB,OAAOA,OAAO,KAAK;oBACvB;gBACJ;gBACA,MAAM,oBAAmBP,CAAC,EAAEC,IAAI,EAAEC,OAAO;oBACrC,OAAOC,QAAQ;wBACX,MAAMC,iBAAiBF;wBACvB,MAAMG,UAAUH,QAAQ,SAAS,CAAC,OAAO,CAACc;wBAC1C,MAAMT,SAAS,MAAMF,QAAQ,OAAO,CAAC;4BACjC,IAAIJ,KAAK,EAAE;4BACX,MAAMA,KAAK,IAAI;wBACnB;wBACA,IAAIM,OAAO,MAAM,IACb,MAAMA,OAAO,KAAK;wBAEtB,OAAOA,OAAO,KAAK;oBACvB;gBACJ;YACJ;QACJ;IACJ;IAEAV,OAAO,IAAI,GAAG;IAEd,OAAOA;AACX"}