diff --git a/packages/api-headless-cms/__tests__/contentAPI/benchmark.test.ts b/packages/api-headless-cms/__tests__/contentAPI/benchmark.test.ts index e9dc674726a..c73fde453be 100644 --- a/packages/api-headless-cms/__tests__/contentAPI/benchmark.test.ts +++ b/packages/api-headless-cms/__tests__/contentAPI/benchmark.test.ts @@ -1,6 +1,8 @@ import { describe, it, expect, beforeEach, vi } from "vitest"; import { useGraphQLHandler } from "~tests/testHelpers/useGraphQLHandler"; -import { BenchmarkAbstraction, ContextPlugin } from "@webiny/api"; +import { BenchmarkAbstraction } from "@webiny/api"; +import { RequestContextInitializer } from "@webiny/event-handler-core"; +import type { Container } from "@webiny/di"; import { createIcon } from "~tests/__helpers/icon.js"; describe("benchmark points", () => { @@ -9,16 +11,22 @@ describe("benchmark points", () => { const { createContentModelGroupMutation } = useGraphQLHandler({ path: "manage", topPlugins: [ - new ContextPlugin(async context => { - // Benchmark moved from `context.benchmark` to the DI container during the - // DI migration; resolve the same instance createCmsRoute flushes per request. - const benchmark = context.container.resolve(BenchmarkAbstraction); - benchmark.enable(); + (container: Container) => { + // Benchmark moved from `context.benchmark` to the DI container during the DI + // migration; resolve the same instance createCmsRoute flushes per request. It's + // registered by HeadlessCmsFeature (after the plugins loop), so enable it from a + // post-auth initializer where the abstraction is resolvable. + container.registerInstance(RequestContextInitializer, { + async init(ctx: Record) { + const benchmark = ctx.container.resolve(BenchmarkAbstraction); + benchmark.enable(); - benchmark.onOutput(async ({ benchmark }) => { - elapsed = benchmark.elapsed; + benchmark.onOutput(async ({ benchmark }: any) => { + elapsed = benchmark.elapsed; + }); + } }); - }) + } ] }); beforeEach(async () => { diff --git a/packages/api-headless-cms/__tests__/contentAPI/contentModelGroup.extension.test.ts b/packages/api-headless-cms/__tests__/contentAPI/contentModelGroup.extension.test.ts index 10525bf8715..92512cc2e41 100644 --- a/packages/api-headless-cms/__tests__/contentAPI/contentModelGroup.extension.test.ts +++ b/packages/api-headless-cms/__tests__/contentAPI/contentModelGroup.extension.test.ts @@ -1,5 +1,4 @@ import { describe, expect, test } from "vitest"; -import { createContextPlugin } from "@webiny/api"; import { useGraphQLHandler } from "../testHelpers/useGraphQLHandler"; import { ModelGroupFactory } from "~/features/contentModelGroup/shared/abstractions.js"; @@ -28,9 +27,9 @@ describe("ModelGroupFactory test", () => { const { listContentModelGroupsQuery } = useGraphQLHandler({ path: "manage", plugins: [ - createContextPlugin(context => { - context.container.register(MyGroupsFactory); - }) + container => { + container.register(MyGroupsFactory); + } ] }); diff --git a/packages/api-headless-cms/__tests__/contentAPI/dynamicZoneField.test.ts b/packages/api-headless-cms/__tests__/contentAPI/dynamicZoneField.test.ts index b689dd551bc..d0252cb6740 100644 --- a/packages/api-headless-cms/__tests__/contentAPI/dynamicZoneField.test.ts +++ b/packages/api-headless-cms/__tests__/contentAPI/dynamicZoneField.test.ts @@ -5,8 +5,8 @@ import { usePageManageHandler } from "../testHelpers/usePageManageHandler"; import { usePageReadHandler } from "../testHelpers/usePageReadHandler"; import { useAuthorManageHandler } from "~tests/testHelpers/useAuthorManageHandler"; import type { TestCmsModel } from "~tests/types"; -import { ContextPlugin } from "@webiny/api"; -import type { CmsContext, CmsEntry } from "~/types"; +import type { Container } from "@webiny/di"; +import type { CmsEntry } from "~/types"; import { EntryAfterCreateEventHandler, EntryBeforeCreateEventHandler @@ -326,8 +326,8 @@ describe("dynamicZone field", () => { afterUpdate: undefined }; - const lifecycleEvents = new ContextPlugin(async (context: CmsContext) => { - context.container.registerFactory(EntryBeforeCreateEventHandler, () => ({ + const lifecycleEvents = async (container: Container) => { + container.registerFactory(EntryBeforeCreateEventHandler, () => ({ async handle(event) { eventEntryContent.beforeCreate = structuredClone( event.payload.entry @@ -335,7 +335,7 @@ describe("dynamicZone field", () => { } })); - context.container.registerFactory(EntryAfterCreateEventHandler, () => ({ + container.registerFactory(EntryAfterCreateEventHandler, () => ({ async handle(event) { eventEntryContent.afterCreate = structuredClone( event.payload.entry @@ -343,7 +343,7 @@ describe("dynamicZone field", () => { } })); - context.container.registerFactory(EntryBeforeUpdateEventHandler, () => ({ + container.registerFactory(EntryBeforeUpdateEventHandler, () => ({ async handle(event) { eventEntryContent.beforeUpdate = structuredClone( event.payload.entry @@ -351,14 +351,14 @@ describe("dynamicZone field", () => { } })); - context.container.registerFactory(EntryAfterUpdateEventHandler, () => ({ + container.registerFactory(EntryAfterUpdateEventHandler, () => ({ async handle(event) { eventEntryContent.afterUpdate = structuredClone( event.payload.entry ) as CmsEntry; } })); - }); + }; const manage = usePageManageHandler({ ...manageOpts, bottomPlugins: [lifecycleEvents] }); diff --git a/packages/api-headless-cms/__tests__/contentAPI/httpOptions.test.ts b/packages/api-headless-cms/__tests__/contentAPI/httpOptions.test.ts index d7830ef7724..c97e4f746e2 100644 --- a/packages/api-headless-cms/__tests__/contentAPI/httpOptions.test.ts +++ b/packages/api-headless-cms/__tests__/contentAPI/httpOptions.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from "vitest"; -import { ContextPlugin } from "@webiny/api"; -import type { CmsContext } from "~/types/index.js"; +import { RequestContextInitializer } from "@webiny/event-handler-core"; +import type { Container } from "@webiny/di"; import { useCategoryManageHandler } from "../testHelpers/useCategoryManageHandler.js"; /** @@ -15,9 +15,15 @@ describe("HTTP Options request", () => { const manageOpts = { path: "manage", plugins: [ - new ContextPlugin(async () => { - throw new Error("This should not register."); - }) + // A post-auth initializer that must NOT run for an OPTIONS preflight (which short- + // circuits before the request context is initialized). If it runs, the test fails. + (container: Container) => { + container.registerInstance(RequestContextInitializer, { + async init() { + throw new Error("This should not register."); + } + }); + } ] }; diff --git a/packages/api-headless-cms/__tests__/contentAPI/mocks/lifecycleHooks.ts b/packages/api-headless-cms/__tests__/contentAPI/mocks/lifecycleHooks.ts index 819e53e0b28..693e9d2cc3b 100644 --- a/packages/api-headless-cms/__tests__/contentAPI/mocks/lifecycleHooks.ts +++ b/packages/api-headless-cms/__tests__/contentAPI/mocks/lifecycleHooks.ts @@ -1,5 +1,4 @@ -import type { CmsContext } from "~/types"; -import { ContextPlugin } from "@webiny/api"; +import type { Container } from "@webiny/di"; import { ModelBeforeCreateEventHandler, ModelAfterCreateEventHandler @@ -71,141 +70,141 @@ class PubSubTracker { export const pubSubTracker = new PubSubTracker(); export const assignModelEvents = () => { - return new ContextPlugin(async context => { - context.container.registerFactory(ModelBeforeCreateEventHandler, () => ({ + return async (container: Container) => { + container.registerFactory(ModelBeforeCreateEventHandler, () => ({ async handle() { pubSubTracker.track("contentModel:beforeCreate"); } })); - context.container.registerFactory(ModelAfterCreateEventHandler, () => ({ + container.registerFactory(ModelAfterCreateEventHandler, () => ({ async handle() { pubSubTracker.track("contentModel:afterCreate"); } })); - context.container.registerFactory(ModelBeforeCreateFromEventHandler, () => ({ + container.registerFactory(ModelBeforeCreateFromEventHandler, () => ({ async handle() { pubSubTracker.track("contentModel:beforeCreateFrom"); } })); - context.container.registerFactory(ModelAfterCreateFromEventHandler, () => ({ + container.registerFactory(ModelAfterCreateFromEventHandler, () => ({ async handle() { pubSubTracker.track("contentModel:afterCreateFrom"); } })); - context.container.registerFactory(ModelBeforeUpdateEventHandler, () => ({ + container.registerFactory(ModelBeforeUpdateEventHandler, () => ({ async handle() { pubSubTracker.track("contentModel:beforeUpdate"); } })); - context.container.registerFactory(ModelAfterUpdateEventHandler, () => ({ + container.registerFactory(ModelAfterUpdateEventHandler, () => ({ async handle() { pubSubTracker.track("contentModel:afterUpdate"); } })); - context.container.registerFactory(ModelBeforeDeleteEventHandler, () => ({ + container.registerFactory(ModelBeforeDeleteEventHandler, () => ({ async handle() { pubSubTracker.track("contentModel:beforeDelete"); } })); - context.container.registerFactory(ModelAfterDeleteEventHandler, () => ({ + container.registerFactory(ModelAfterDeleteEventHandler, () => ({ async handle() { pubSubTracker.track("contentModel:afterDelete"); } })); - }); + }; }; export const assignEntryEvents = () => { - return new ContextPlugin(async (context: CmsContext) => { - context.container.registerFactory(EntryBeforeCreateEventHandler, () => ({ + return async (container: Container) => { + container.registerFactory(EntryBeforeCreateEventHandler, () => ({ async handle() { pubSubTracker.track("contentEntry:beforeCreate"); } })); - context.container.registerFactory(EntryAfterCreateEventHandler, () => ({ + container.registerFactory(EntryAfterCreateEventHandler, () => ({ async handle() { pubSubTracker.track("contentEntry:afterCreate"); } })); - context.container.registerFactory(EntryRevisionBeforeCreateEventHandler, () => ({ + container.registerFactory(EntryRevisionBeforeCreateEventHandler, () => ({ async handle() { pubSubTracker.track("contentEntry:beforeCreateRevisionFrom"); } })); - context.container.registerFactory(EntryRevisionAfterCreateEventHandler, () => ({ + container.registerFactory(EntryRevisionAfterCreateEventHandler, () => ({ async handle() { pubSubTracker.track("contentEntry:afterCreateRevisionFrom"); } })); - context.container.registerFactory(EntryBeforeUpdateEventHandler, () => ({ + container.registerFactory(EntryBeforeUpdateEventHandler, () => ({ async handle() { pubSubTracker.track("contentEntry:beforeUpdate"); } })); - context.container.registerFactory(EntryAfterUpdateEventHandler, () => ({ + container.registerFactory(EntryAfterUpdateEventHandler, () => ({ async handle() { pubSubTracker.track("contentEntry:afterUpdate"); } })); - context.container.registerFactory(EntryBeforeDeleteEventHandler, () => ({ + container.registerFactory(EntryBeforeDeleteEventHandler, () => ({ async handle() { pubSubTracker.track("contentEntry:beforeDelete"); } })); - context.container.registerFactory(EntryAfterDeleteEventHandler, () => ({ + container.registerFactory(EntryAfterDeleteEventHandler, () => ({ async handle() { pubSubTracker.track("contentEntry:afterDelete"); } })); - context.container.registerFactory(EntryRevisionBeforeDeleteEventHandler, () => ({ + container.registerFactory(EntryRevisionBeforeDeleteEventHandler, () => ({ async handle() { pubSubTracker.track("contentEntry:beforeDeleteRevision"); } })); - context.container.registerFactory(EntryRevisionAfterDeleteEventHandler, () => ({ + container.registerFactory(EntryRevisionAfterDeleteEventHandler, () => ({ async handle() { pubSubTracker.track("contentEntry:afterDeleteRevision"); } })); - context.container.registerFactory(EntryBeforePublishEventHandler, () => ({ + container.registerFactory(EntryBeforePublishEventHandler, () => ({ async handle() { pubSubTracker.track("contentEntry:beforePublish"); } })); - context.container.registerFactory(EntryAfterPublishEventHandler, () => ({ + container.registerFactory(EntryAfterPublishEventHandler, () => ({ async handle() { pubSubTracker.track("contentEntry:afterPublish"); } })); - context.container.registerFactory(EntryBeforeUnpublishEventHandler, () => ({ + container.registerFactory(EntryBeforeUnpublishEventHandler, () => ({ async handle() { pubSubTracker.track("contentEntry:beforeUnpublish"); } })); - context.container.registerFactory(EntryAfterUnpublishEventHandler, () => ({ + container.registerFactory(EntryAfterUnpublishEventHandler, () => ({ async handle() { pubSubTracker.track("contentEntry:afterUnpublish"); } })); - }); + }; }; diff --git a/packages/api-headless-cms/__tests__/lifecycleHooks/onBeforeEntryPublish.test.ts b/packages/api-headless-cms/__tests__/lifecycleHooks/onBeforeEntryPublish.test.ts index 3fab9752e34..717c624c3a3 100644 --- a/packages/api-headless-cms/__tests__/lifecycleHooks/onBeforeEntryPublish.test.ts +++ b/packages/api-headless-cms/__tests__/lifecycleHooks/onBeforeEntryPublish.test.ts @@ -1,9 +1,7 @@ import { HeadlessCms } from "~/features/shared/abstractions.js"; import { describe, expect, it } from "vitest"; -import { ContextPlugin } from "@webiny/handler"; import { useHandler } from "~tests/testHelpers/useHandler"; import { articleModel } from "./mocks/article.model"; -import type { CmsContext } from "~/types"; import { EntryBeforePublishEventHandler } from "~/features/contentEntry/PublishEntry/index.js"; describe("onEntryBeforePublish", () => { @@ -11,8 +9,8 @@ describe("onEntryBeforePublish", () => { const { handler, tenant } = useHandler({ plugins: [ articleModel, - new ContextPlugin(context => { - context.container.registerFactory(EntryBeforePublishEventHandler, () => ({ + container => { + container.registerFactory(EntryBeforePublishEventHandler, () => ({ async handle(event) { const { model, entry } = event.payload; @@ -26,7 +24,7 @@ describe("onEntryBeforePublish", () => { } } })); - }) + } ] }); diff --git a/packages/api-headless-cms/__tests__/testHelpers/enableBenchmarkOnEnvironmentVariable.ts b/packages/api-headless-cms/__tests__/testHelpers/enableBenchmarkOnEnvironmentVariable.ts deleted file mode 100644 index 3533f1ea6da..00000000000 --- a/packages/api-headless-cms/__tests__/testHelpers/enableBenchmarkOnEnvironmentVariable.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ContextPlugin } from "@webiny/api"; - -export const enableBenchmarkOnEnvironmentVariable = () => { - return new ContextPlugin(async context => { - context.benchmark.enableOn(async () => { - return process.env.BENCHMARK_ENABLE === "true"; - }); - }); -}; diff --git a/packages/api-headless-cms/__tests__/testHelpers/outputBenchmarkLogs.ts b/packages/api-headless-cms/__tests__/testHelpers/outputBenchmarkLogs.ts deleted file mode 100644 index 9c302cb3d87..00000000000 --- a/packages/api-headless-cms/__tests__/testHelpers/outputBenchmarkLogs.ts +++ /dev/null @@ -1,33 +0,0 @@ -import pathPackage from "path"; -import { writeJsonFileSync } from "write-json-file"; -import { ContextPlugin } from "@webiny/handler"; - -/** - * Do not use in the CI as this will generate logs in it. - * Use the required environment variable to turn on the logs. - */ -export const createOutputBenchmarkLogs = () => { - if (process.env.WEBINY_API_TEST_OUTPUT_CMS_BENCHMARK_LOGS !== "true") { - return []; - } - return [ - new ContextPlugin(async context => { - context.benchmark.onOutput(async ({ benchmark, stop }) => { - const target = pathPackage.join( - __dirname, - "../logs", - `${new Date().toISOString()}.json` - ); - writeJsonFileSync( - target, - { - elapsed: benchmark.elapsed, - measurements: benchmark.measurements - }, - { indent: 4 } - ); - return stop(); - }); - }) - ]; -};