@webiny/api-headless-cms-testing 6.6.0-alpha.0 → 6.6.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,8 @@
1
1
  import { createTestHttpHandler } from "@webiny/event-handler-core/features/testing";
2
2
  import { ApiCoreFeature, registerApiCoreStorageOperations } from "@webiny/api-core";
3
3
  import { GraphQLContextualSchema, GraphQLEngineFeature } from "@webiny/api-graphql";
4
- import { loadWcpLicense } from "@webiny/api-core/features/wcp/loadWcpLicense.js";
5
- import { getStorageOps } from "@webiny/project-utils/testing/environment/index.js";
4
+ import { WcpLicenseLoader } from "@webiny/api-core/features/wcp/WcpLicenseLoader.js";
5
+ import { getStorageOps } from "@webiny/api-core/testing/environment.js";
6
6
  import { createTestWcpLicense } from "@webiny/wcp/testing/createTestWcpLicense.js";
7
7
  import { buildSchema, getIntrospectionQuery } from "graphql";
8
8
  import { HeadlessCmsFeature } from "@webiny/api-headless-cms/HeadlessCmsFeature.js";
@@ -35,7 +35,7 @@ const createCmsTestHandler = (params = {})=>{
35
35
  container.registerDecorator(RootTenantInitializer);
36
36
  };
37
37
  const setupRequest = async (container)=>{
38
- const wcpLicense = await loadWcpLicense(params.testProjectLicense ?? createTestWcpLicense());
38
+ const wcpLicense = await WcpLicenseLoader.load(params.testProjectLicense ?? createTestWcpLicense());
39
39
  registerApiCoreStorageOperations(container, apiCoreStorage.storageOperations);
40
40
  ApiCoreFeature.register(container, {
41
41
  wcpLicense
@@ -60,7 +60,7 @@ const createCmsTestHandler = (params = {})=>{
60
60
  };
61
61
  const handler = createTestHttpHandler({
62
62
  root: setupRoot,
63
- request: async (container)=>{
63
+ child: async (container)=>{
64
64
  await setupRequest(container);
65
65
  GraphQLEngineFeature.register(container);
66
66
  }
@@ -101,7 +101,7 @@ const createCmsTestHandler = (params = {})=>{
101
101
  const captured = {};
102
102
  const ctxHandler = createTestHttpHandler({
103
103
  root: setupRoot,
104
- request: async (container)=>{
104
+ child: async (container)=>{
105
105
  await setupRequest(container);
106
106
  container.registerInstance(GraphQLContextualSchema, {
107
107
  async build (ctx) {
@@ -1 +1 @@
1
- {"version":3,"file":"createCmsTestHandler.js","sources":["../src/createCmsTestHandler.ts"],"sourcesContent":["import { createTestHttpHandler } from \"@webiny/event-handler-core/features/testing\";\nimport type { Container } from \"@webiny/di\";\nimport { ApiCoreFeature, registerApiCoreStorageOperations } from \"@webiny/api-core\";\nimport { GraphQLEngineFeature, GraphQLContextualSchema } from \"@webiny/api-graphql\";\nimport { loadWcpLicense } from \"@webiny/api-core/features/wcp/loadWcpLicense.js\";\nimport { getStorageOps } from \"@webiny/project-utils/testing/environment/index.js\";\nimport { createTestWcpLicense } from \"@webiny/wcp/testing/createTestWcpLicense.js\";\nimport { buildSchema, getIntrospectionQuery } from \"graphql\";\nimport type { GraphQLSchema } from \"graphql\";\nimport type { ApiCoreStorageOperations } from \"@webiny/api-core/types/core.js\";\nimport type { IdentityData } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport type { SecurityPermission } from \"@webiny/api-core/types/security.js\";\nimport type { DecryptedWcpProjectLicense } from \"@webiny/wcp/types.js\";\nimport { HeadlessCmsFeature } from \"@webiny/api-headless-cms/HeadlessCmsFeature.js\";\nimport { TestIdentity, TestAuthenticator } from \"@webiny/api-core-testing\";\nimport { TestPermissions, TestAuthorizer } from \"@webiny/api-core-testing\";\nimport { AuthTriggerHandler } from \"@webiny/api-core-testing\";\nimport { RootTenantInitializer } from \"@webiny/api-core-testing\";\nimport { processLegacyPlugins } from \"./processLegacyPlugins.js\";\n\nconst DEFAULT_IDENTITY: IdentityData = {\n id: \"id-12345678\",\n type: \"admin\",\n displayName: \"John Doe\"\n};\n\nconst STUB_SCHEMA: GraphQLSchema = buildSchema(\"type Query { _empty: String }\");\n\nexport interface CmsTestHandlerParams {\n /** Identity for the request. `undefined` → a default admin; `null` → anonymous. */\n identity?: IdentityData | null;\n permissions?: SecurityPermission[];\n testProjectLicense?: DecryptedWcpProjectLicense;\n /** CMS endpoint type to build. Defaults to \"manage\". */\n cmsType?: \"manage\" | \"read\" | \"preview\";\n /** Plugins forwarded to `HeadlessCmsFeature.register` as `extraPlugins` (e.g. CMS model plugins). */\n extraCmsPlugins?: any[];\n /**\n * Legacy escape hatch (being retired — prefer `setup`). A mixed array, dispatched like the old\n * `useContextHandler`:\n * - RegisterExtensionPlugins are applied at register() time (DI registration);\n * - static plugins (CmsModelPlugin, GraphQLSchemaPlugin, …) are forwarded to HeadlessCmsFeature\n * as extraPlugins so their models reach the container before any initializer caches them;\n * - plain `container => {}` functions run LAST (after `setup`), so they can override defaults.\n */\n legacyPlugins?: any;\n /**\n * Register the consuming package's own features here (e.g. AcoFeature, FileModel, plus its own\n * getStorageOps presets via processLegacyPlugins). Runs in the request phase AFTER ApiCore + CMS\n * storage + HeadlessCmsFeature, and BEFORE the GraphQL engine — i.e. before any initializer or\n * resolver, the same window the real app handler uses.\n */\n setup?: (container: Container) => void | Promise<void>;\n}\n\nexport interface InvokeParams {\n httpMethod?: \"POST\";\n type?: string;\n body: { query: string; variables?: Record<string, any> };\n headers?: Record<string, string>;\n}\n\n/**\n * Shared integration test handler that wires the real CMS base (ApiCore + HeadlessCms + GraphQL\n * engine + the CMS manage route) the same way the AWS app handler does — auth via Test\n * authenticator/authorizer, root tenant seeded, storage via getStorageOps. Consuming packages add\n * their own features through `params.setup` and build their SDKs on top of `invoke`/`invokeCms`,\n * or grab the fully-initialized request context via `getContext()`.\n */\nexport const createCmsTestHandler = (params: CmsTestHandlerParams = {}) => {\n const apiCoreStorage = getStorageOps<ApiCoreStorageOperations>(\"apiCore\");\n const cmsStorage = getStorageOps(\"cms\");\n\n const identity = params.identity === undefined ? DEFAULT_IDENTITY : params.identity;\n const permissions = params.permissions === undefined ? [{ name: \"*\" }] : params.permissions;\n const cmsType = params.cmsType ?? \"manage\";\n\n const setupRoot = (container: Container) => {\n container.registerInstance(TestIdentity, identity);\n container.registerInstance(TestPermissions, { list: permissions });\n container.register(TestAuthenticator);\n container.register(TestAuthorizer);\n container.registerDecorator(AuthTriggerHandler);\n container.registerDecorator(RootTenantInitializer);\n };\n\n // Everything up to (but not including) the GraphQL engine — shared by the HTTP handler and the\n // context-capture handler.\n const setupRequest = async (container: Container) => {\n const wcpLicense = await loadWcpLicense(\n params.testProjectLicense ?? createTestWcpLicense()\n );\n\n registerApiCoreStorageOperations(container, apiCoreStorage.storageOperations);\n ApiCoreFeature.register(container, { wcpLicense });\n\n // CMS storage preset. All storage presets are RegisterExtensionPlugins (registerDynamoDBCore,\n // registerCmsOpenSearchStorageOperations, dbPlugins, ...); processLegacyPlugins runs them at\n // register() time — before HeadlessCmsFeature builds storage, mirroring the real app's\n // registerExtensions.\n processLegacyPlugins(container, cmsStorage.plugins);\n\n // `legacyPlugins` is a mixed bag: plain `container => {}` functions (called last, after\n // `setup`) plus legacy plugin objects — RegisterExtensionPlugins (register-time) or static\n // Plugins (extraPlugins).\n const legacyItems = [params.legacyPlugins].flat(Infinity as 1).filter(Boolean);\n const isFn = (p: any) => typeof p === \"function\" && !p.prototype;\n\n const legacyObjects = legacyItems.filter(p => !isFn(p));\n processLegacyPlugins(container, legacyObjects);\n const staticPlugins = legacyObjects.filter(\n p => typeof (p as any).apply !== \"function\" && typeof p !== \"function\"\n );\n HeadlessCmsFeature.register(container, {\n type: cmsType,\n extraPlugins: [...(params.extraCmsPlugins ?? []), ...staticPlugins]\n });\n\n await params.setup?.(container);\n\n // Function plugins in `legacyPlugins` run LAST — after the consuming package's own `setup` —\n // so they can override defaults it registered (last-wins).\n for (const plugin of legacyItems.filter(isFn)) {\n (plugin as (container: any) => void)(container);\n }\n };\n\n const handler = createTestHttpHandler({\n root: setupRoot,\n request: async container => {\n await setupRequest(container);\n GraphQLEngineFeature.register(container);\n }\n });\n\n const invoke = async ({ httpMethod = \"POST\", body, headers = {} }: InvokeParams) => {\n const response = await handler({\n method: httpMethod,\n path: \"/graphql\",\n headers: { \"x-tenant\": \"root\", \"content-type\": \"application/json\", ...headers },\n body\n });\n return [response.body, response] as const;\n };\n\n const invokeCms = async ({\n httpMethod = \"POST\",\n type = \"manage\",\n body,\n headers = {}\n }: InvokeParams) => {\n const response = await handler({\n method: httpMethod,\n path: `/cms/${type}`,\n headers: { \"x-tenant\": \"root\", \"content-type\": \"application/json\", ...headers },\n body\n });\n return [response.body, response] as const;\n };\n\n /**\n * Build the request once and return the fully-initialized context (after auth, tenant, CMS and\n * all consumer features). Uses the same GraphQLContextualSchema.build(ctx) capture trick the\n * legacy `useContextHandler` does — for tests that resolve services directly off the context\n * rather than issuing GraphQL queries.\n */\n const getContext = async <\n C extends Record<string, any> = Record<string, any>\n >(): Promise<C> => {\n const captured: { value?: Record<string, any> } = {};\n\n const ctxHandler = createTestHttpHandler({\n root: setupRoot,\n request: async container => {\n await setupRequest(container);\n container.registerInstance(GraphQLContextualSchema, {\n async build(ctx: Record<string, any>): Promise<GraphQLSchema> {\n captured.value = ctx;\n return STUB_SCHEMA;\n }\n });\n GraphQLEngineFeature.register(container);\n }\n });\n\n await ctxHandler({\n method: \"POST\",\n path: \"/graphql\",\n headers: { \"x-tenant\": \"root\", \"content-type\": \"application/json\" },\n body: { query: \"{ __typename }\" }\n });\n\n return captured.value as C;\n };\n\n // Convenience wrappers mirroring the retired `useGraphQLHandler` — thin builders over `invoke`\n // (the main `/graphql` endpoint) so consumers can issue typed queries/mutations directly.\n const createQuery = <T extends Record<string, any> = Record<string, any>>(query: string) => {\n return (variables?: Record<string, any>, headers: Record<string, string> = {}) =>\n invoke({ body: { query, variables: variables || undefined }, headers }) as Promise<\n readonly [T, any]\n >;\n };\n\n const createMutation = <T extends Record<string, any> = Record<string, any>>(\n mutation: string\n ) => {\n return (variables?: Record<string, any>, headers: Record<string, string> = {}) =>\n invoke({\n body: { query: mutation, variables: variables || undefined },\n headers\n }) as Promise<readonly [T, any]>;\n };\n\n const introspect = () => invoke({ body: { query: getIntrospectionQuery() } });\n\n return {\n handler,\n invoke,\n invokeCms,\n getContext,\n createQuery,\n createMutation,\n introspect,\n identity,\n tenant: { id: \"root\", name: \"Root\", parent: null }\n };\n};\n"],"names":["DEFAULT_IDENTITY","STUB_SCHEMA","buildSchema","createCmsTestHandler","params","apiCoreStorage","getStorageOps","cmsStorage","identity","undefined","permissions","cmsType","setupRoot","container","TestIdentity","TestPermissions","TestAuthenticator","TestAuthorizer","AuthTriggerHandler","RootTenantInitializer","setupRequest","wcpLicense","loadWcpLicense","createTestWcpLicense","registerApiCoreStorageOperations","ApiCoreFeature","processLegacyPlugins","legacyItems","Infinity","Boolean","isFn","p","legacyObjects","staticPlugins","HeadlessCmsFeature","plugin","handler","createTestHttpHandler","GraphQLEngineFeature","invoke","httpMethod","body","headers","response","invokeCms","type","getContext","captured","ctxHandler","GraphQLContextualSchema","ctx","createQuery","query","variables","createMutation","mutation","introspect","getIntrospectionQuery"],"mappings":"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"}
1
+ {"version":3,"file":"createCmsTestHandler.js","sources":["../src/createCmsTestHandler.ts"],"sourcesContent":["import { createTestHttpHandler } from \"@webiny/event-handler-core/features/testing\";\nimport type { Container } from \"@webiny/di\";\nimport { ApiCoreFeature, registerApiCoreStorageOperations } from \"@webiny/api-core\";\nimport { GraphQLEngineFeature, GraphQLContextualSchema } from \"@webiny/api-graphql\";\nimport { WcpLicenseLoader } from \"@webiny/api-core/features/wcp/WcpLicenseLoader.js\";\nimport { getStorageOps } from \"@webiny/api-core/testing/environment.js\";\nimport { createTestWcpLicense } from \"@webiny/wcp/testing/createTestWcpLicense.js\";\nimport { buildSchema, getIntrospectionQuery } from \"graphql\";\nimport type { GraphQLSchema } from \"graphql\";\nimport type { ApiCoreStorageOperations } from \"@webiny/api-core/types/core.js\";\nimport type { IdentityData } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport type { SecurityPermission } from \"@webiny/api-core/types/security.js\";\nimport type { DecryptedWcpProjectLicense } from \"@webiny/wcp/types.js\";\nimport { HeadlessCmsFeature } from \"@webiny/api-headless-cms/HeadlessCmsFeature.js\";\nimport { TestIdentity, TestAuthenticator } from \"@webiny/api-core-testing\";\nimport { TestPermissions, TestAuthorizer } from \"@webiny/api-core-testing\";\nimport { AuthTriggerHandler } from \"@webiny/api-core-testing\";\nimport { RootTenantInitializer } from \"@webiny/api-core-testing\";\nimport { processLegacyPlugins } from \"./processLegacyPlugins.js\";\n\nconst DEFAULT_IDENTITY: IdentityData = {\n id: \"id-12345678\",\n type: \"admin\",\n displayName: \"John Doe\"\n};\n\nconst STUB_SCHEMA: GraphQLSchema = buildSchema(\"type Query { _empty: String }\");\n\nexport interface CmsTestHandlerParams {\n /** Identity for the request. `undefined` → a default admin; `null` → anonymous. */\n identity?: IdentityData | null;\n permissions?: SecurityPermission[];\n testProjectLicense?: DecryptedWcpProjectLicense;\n /** CMS endpoint type to build. Defaults to \"manage\". */\n cmsType?: \"manage\" | \"read\" | \"preview\";\n /** Plugins forwarded to `HeadlessCmsFeature.register` as `extraPlugins` (e.g. CMS model plugins). */\n extraCmsPlugins?: any[];\n /**\n * Legacy escape hatch (being retired — prefer `setup`). A mixed array, dispatched like the old\n * `useContextHandler`:\n * - RegisterExtensionPlugins are applied at register() time (DI registration);\n * - static plugins (CmsModelPlugin, GraphQLSchemaPlugin, …) are forwarded to HeadlessCmsFeature\n * as extraPlugins so their models reach the container before any initializer caches them;\n * - plain `container => {}` functions run LAST (after `setup`), so they can override defaults.\n */\n legacyPlugins?: any;\n /**\n * Register the consuming package's own features here (e.g. AcoFeature, FileModel, plus its own\n * getStorageOps presets via processLegacyPlugins). Runs in the request phase AFTER ApiCore + CMS\n * storage + HeadlessCmsFeature, and BEFORE the GraphQL engine — i.e. before any initializer or\n * resolver, the same window the real app handler uses.\n */\n setup?: (container: Container) => void | Promise<void>;\n}\n\nexport interface InvokeParams {\n httpMethod?: \"POST\";\n type?: string;\n body: { query: string; variables?: Record<string, any> };\n headers?: Record<string, string>;\n}\n\n/**\n * Shared integration test handler that wires the real CMS base (ApiCore + HeadlessCms + GraphQL\n * engine + the CMS manage route) the same way the AWS app handler does — auth via Test\n * authenticator/authorizer, root tenant seeded, storage via getStorageOps. Consuming packages add\n * their own features through `params.setup` and build their SDKs on top of `invoke`/`invokeCms`,\n * or grab the fully-initialized request context via `getContext()`.\n */\nexport const createCmsTestHandler = (params: CmsTestHandlerParams = {}) => {\n const apiCoreStorage = getStorageOps<ApiCoreStorageOperations>(\"apiCore\");\n const cmsStorage = getStorageOps(\"cms\");\n\n const identity = params.identity === undefined ? DEFAULT_IDENTITY : params.identity;\n const permissions = params.permissions === undefined ? [{ name: \"*\" }] : params.permissions;\n const cmsType = params.cmsType ?? \"manage\";\n\n const setupRoot = (container: Container) => {\n container.registerInstance(TestIdentity, identity);\n container.registerInstance(TestPermissions, { list: permissions });\n container.register(TestAuthenticator);\n container.register(TestAuthorizer);\n container.registerDecorator(AuthTriggerHandler);\n container.registerDecorator(RootTenantInitializer);\n };\n\n // Everything up to (but not including) the GraphQL engine — shared by the HTTP handler and the\n // context-capture handler.\n const setupRequest = async (container: Container) => {\n const wcpLicense = await WcpLicenseLoader.load(\n params.testProjectLicense ?? createTestWcpLicense()\n );\n\n registerApiCoreStorageOperations(container, apiCoreStorage.storageOperations);\n ApiCoreFeature.register(container, { wcpLicense });\n\n // CMS storage preset. All storage presets are RegisterExtensionPlugins (registerDynamoDBCore,\n // registerCmsOpenSearchStorageOperations, dbPlugins, ...); processLegacyPlugins runs them at\n // register() time — before HeadlessCmsFeature builds storage, mirroring the real app's\n // registerExtensions.\n processLegacyPlugins(container, cmsStorage.plugins);\n\n // `legacyPlugins` is a mixed bag: plain `container => {}` functions (called last, after\n // `setup`) plus legacy plugin objects — RegisterExtensionPlugins (register-time) or static\n // Plugins (extraPlugins).\n const legacyItems = [params.legacyPlugins].flat(Infinity as 1).filter(Boolean);\n const isFn = (p: any) => typeof p === \"function\" && !p.prototype;\n\n const legacyObjects = legacyItems.filter(p => !isFn(p));\n processLegacyPlugins(container, legacyObjects);\n const staticPlugins = legacyObjects.filter(\n p => typeof (p as any).apply !== \"function\" && typeof p !== \"function\"\n );\n HeadlessCmsFeature.register(container, {\n type: cmsType,\n extraPlugins: [...(params.extraCmsPlugins ?? []), ...staticPlugins]\n });\n\n await params.setup?.(container);\n\n // Function plugins in `legacyPlugins` run LAST — after the consuming package's own `setup` —\n // so they can override defaults it registered (last-wins).\n for (const plugin of legacyItems.filter(isFn)) {\n (plugin as (container: any) => void)(container);\n }\n };\n\n const handler = createTestHttpHandler({\n root: setupRoot,\n child: async container => {\n await setupRequest(container);\n GraphQLEngineFeature.register(container);\n }\n });\n\n const invoke = async ({ httpMethod = \"POST\", body, headers = {} }: InvokeParams) => {\n const response = await handler({\n method: httpMethod,\n path: \"/graphql\",\n headers: { \"x-tenant\": \"root\", \"content-type\": \"application/json\", ...headers },\n body\n });\n return [response.body, response] as const;\n };\n\n const invokeCms = async ({\n httpMethod = \"POST\",\n type = \"manage\",\n body,\n headers = {}\n }: InvokeParams) => {\n const response = await handler({\n method: httpMethod,\n path: `/cms/${type}`,\n headers: { \"x-tenant\": \"root\", \"content-type\": \"application/json\", ...headers },\n body\n });\n return [response.body, response] as const;\n };\n\n /**\n * Build the request once and return the fully-initialized context (after auth, tenant, CMS and\n * all consumer features). Uses the same GraphQLContextualSchema.build(ctx) capture trick the\n * legacy `useContextHandler` does — for tests that resolve services directly off the context\n * rather than issuing GraphQL queries.\n */\n const getContext = async <\n C extends Record<string, any> = Record<string, any>\n >(): Promise<C> => {\n const captured: { value?: Record<string, any> } = {};\n\n const ctxHandler = createTestHttpHandler({\n root: setupRoot,\n child: async container => {\n await setupRequest(container);\n container.registerInstance(GraphQLContextualSchema, {\n async build(ctx: Record<string, any>): Promise<GraphQLSchema> {\n captured.value = ctx;\n return STUB_SCHEMA;\n }\n });\n GraphQLEngineFeature.register(container);\n }\n });\n\n await ctxHandler({\n method: \"POST\",\n path: \"/graphql\",\n headers: { \"x-tenant\": \"root\", \"content-type\": \"application/json\" },\n body: { query: \"{ __typename }\" }\n });\n\n return captured.value as C;\n };\n\n // Convenience wrappers mirroring the retired `useGraphQLHandler` — thin builders over `invoke`\n // (the main `/graphql` endpoint) so consumers can issue typed queries/mutations directly.\n const createQuery = <T extends Record<string, any> = Record<string, any>>(query: string) => {\n return (variables?: Record<string, any>, headers: Record<string, string> = {}) =>\n invoke({ body: { query, variables: variables || undefined }, headers }) as Promise<\n readonly [T, any]\n >;\n };\n\n const createMutation = <T extends Record<string, any> = Record<string, any>>(\n mutation: string\n ) => {\n return (variables?: Record<string, any>, headers: Record<string, string> = {}) =>\n invoke({\n body: { query: mutation, variables: variables || undefined },\n headers\n }) as Promise<readonly [T, any]>;\n };\n\n const introspect = () => invoke({ body: { query: getIntrospectionQuery() } });\n\n return {\n handler,\n invoke,\n invokeCms,\n getContext,\n createQuery,\n createMutation,\n introspect,\n identity,\n tenant: { id: \"root\", name: \"Root\", parent: null }\n };\n};\n"],"names":["DEFAULT_IDENTITY","STUB_SCHEMA","buildSchema","createCmsTestHandler","params","apiCoreStorage","getStorageOps","cmsStorage","identity","undefined","permissions","cmsType","setupRoot","container","TestIdentity","TestPermissions","TestAuthenticator","TestAuthorizer","AuthTriggerHandler","RootTenantInitializer","setupRequest","wcpLicense","WcpLicenseLoader","createTestWcpLicense","registerApiCoreStorageOperations","ApiCoreFeature","processLegacyPlugins","legacyItems","Infinity","Boolean","isFn","p","legacyObjects","staticPlugins","HeadlessCmsFeature","plugin","handler","createTestHttpHandler","GraphQLEngineFeature","invoke","httpMethod","body","headers","response","invokeCms","type","getContext","captured","ctxHandler","GraphQLContextualSchema","ctx","createQuery","query","variables","createMutation","mutation","introspect","getIntrospectionQuery"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webiny/api-headless-cms-testing",
3
- "version": "6.6.0-alpha.0",
3
+ "version": "6.6.0-alpha.2",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -15,18 +15,17 @@
15
15
  "author": "Webiny Ltd.",
16
16
  "license": "MIT",
17
17
  "dependencies": {
18
- "@webiny/api-core": "6.6.0-alpha.0",
19
- "@webiny/api-core-testing": "6.6.0-alpha.0",
20
- "@webiny/api-graphql": "6.6.0-alpha.0",
21
- "@webiny/api-headless-cms": "6.6.0-alpha.0",
22
- "@webiny/di": "1.0.2",
23
- "@webiny/event-handler-core": "6.6.0-alpha.0",
24
- "@webiny/project-utils": "6.6.0-alpha.0",
25
- "@webiny/wcp": "6.6.0-alpha.0",
18
+ "@webiny/api-core": "6.6.0-alpha.2",
19
+ "@webiny/api-core-testing": "6.6.0-alpha.2",
20
+ "@webiny/api-graphql": "6.6.0-alpha.2",
21
+ "@webiny/api-headless-cms": "6.6.0-alpha.2",
22
+ "@webiny/di": "1.1.0",
23
+ "@webiny/event-handler-core": "6.6.0-alpha.2",
24
+ "@webiny/wcp": "6.6.0-alpha.2",
26
25
  "graphql": "16.14.2"
27
26
  },
28
27
  "devDependencies": {
29
- "@webiny/build-tools": "6.6.0-alpha.0",
28
+ "@webiny/build-tools": "6.6.0-alpha.2",
30
29
  "rimraf": "6.1.3",
31
30
  "typescript": "7.0.2"
32
31
  },
@@ -1 +1 @@
1
- {"version":3,"file":"processLegacyPlugins.js","sources":["../src/processLegacyPlugins.ts"],"sourcesContent":["import type { Container } from \"@webiny/di\";\n\nconst REGISTER_EXTENSION_TYPE = \"handler.register.extension\";\n\n/**\n * Apply legacy RegisterExtensionPlugins (e.g. the storage-operations presets returned by\n * getStorageOps(...).plugins) against the request container — the test-time equivalent of how the\n * app registers them.\n *\n * Detection is by `plugin.type` rather than `instanceof RegisterExtensionPlugin`: a consumer's\n * dependency tree can resolve a second copy of `@webiny/handler`, giving the storage-preset plugins\n * a different class identity than the one this (shipped) module imports, which would make an\n * `instanceof` check silently miss them.\n */\nexport function processLegacyPlugins(container: Container, plugins: any[]): void {\n const flat = [plugins].flat(Infinity as 1);\n for (const plugin of flat) {\n if (\n plugin &&\n plugin.type === REGISTER_EXTENSION_TYPE &&\n typeof plugin.apply === \"function\"\n ) {\n plugin.apply({ container } as any);\n }\n }\n}\n"],"names":["REGISTER_EXTENSION_TYPE","processLegacyPlugins","container","plugins","flat","Infinity","plugin"],"mappings":"AAEA,MAAMA,0BAA0B;AAYzB,SAASC,qBAAqBC,SAAoB,EAAEC,OAAc;IACrE,MAAMC,OAAO;QAACD;KAAQ,CAAC,IAAI,CAACE;IAC5B,KAAK,MAAMC,UAAUF,KACjB,IACIE,UACAA,OAAO,IAAI,KAAKN,2BAChB,AAAwB,cAAxB,OAAOM,OAAO,KAAK,EAEnBA,OAAO,KAAK,CAAC;QAAEJ;IAAU;AAGrC"}
1
+ {"version":3,"file":"processLegacyPlugins.js","sources":["../src/processLegacyPlugins.ts"],"sourcesContent":["import type { Container } from \"@webiny/di\";\n\nconst REGISTER_EXTENSION_TYPE = \"handler.register.extension\";\n\n/**\n * Apply legacy RegisterExtensionPlugins (e.g. the storage-operations presets returned by\n * getStorageOps(...).plugins) against the request container — the test-time equivalent of how the\n * app registers them.\n *\n * Detection is by `plugin.type` rather than `instanceof RegisterExtensionPlugin`: a consumer's\n * dependency tree can resolve a second copy of `@webiny/handler`, giving the storage-preset plugins\n * a different class identity than the one this (shipped) module imports, which would make an\n * `instanceof` check silently miss them.\n */\nexport function processLegacyPlugins(container: Container, plugins: any[]): void {\n const flat = [plugins].flat(Infinity as 1);\n for (const plugin of flat) {\n if (\n plugin &&\n plugin.type === REGISTER_EXTENSION_TYPE &&\n typeof plugin.apply === \"function\"\n ) {\n plugin.apply({ container } as any);\n }\n }\n}\n"],"names":["REGISTER_EXTENSION_TYPE","processLegacyPlugins","container","plugins","flat","Infinity","plugin"],"mappings":"AAEA,MAAMA,0BAA0B;AAYzB,SAASC,qBAAqBC,SAAoB,EAAEC,OAAc;IACrE,MAAMC,OAAO;QAACD;KAAQ,CAAC,IAAI,CAACE,KAAQ;IACpC,KAAK,MAAMC,UAAUF,KACjB,IACIE,UACAA,OAAO,IAAI,KAAKN,2BAChB,AAAwB,cAAxB,OAAOM,OAAO,KAAK,EAEnBA,OAAO,KAAK,CAAC;QAAEJ;IAAU;AAGrC"}