chore: Create publishable API key as part of the defaults (#14356)

* wip

* chore: fix tests

* Create tiny-carrots-bathe.md
This commit is contained in:
Oli Juhl
2026-01-02 11:27:03 +01:00
committed by GitHub
parent 11de7e3e34
commit 7e3ed913a6
5 changed files with 160 additions and 10 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@medusajs/core-flows": patch
---
chore: Create publishable API key in defaults
@@ -1,5 +1,5 @@
import { ApiKeyType } from "@medusajs/utils"
import { medusaIntegrationTestRunner } from "@medusajs/test-utils"
import { ApiKeyType } from "@medusajs/utils"
import {
adminHeaders,
createAdminUser,
@@ -74,7 +74,7 @@ medusaIntegrationTestRunner({
const listedApiKeys = await api.get(`/admin/api-keys`, adminHeaders)
expect(deleted.status).toEqual(200)
expect(listedApiKeys.data.api_keys).toHaveLength(0)
expect(listedApiKeys.data.api_keys).toHaveLength(1) // we still have the default publishable api key
})
it("should allow searching for api keys", async () => {
@@ -108,9 +108,16 @@ medusaIntegrationTestRunner({
expect(listedSecretKeys.data.api_keys[0].title).toEqual(
"Test Secret Key"
)
expect(listedPublishableKeys.data.api_keys).toHaveLength(1)
expect(listedPublishableKeys.data.api_keys[0].title).toEqual(
"Test Publishable Key"
expect(listedPublishableKeys.data.api_keys).toHaveLength(2)
expect(listedPublishableKeys.data.api_keys).toEqual(
expect.arrayContaining([
expect.objectContaining({
title: "Test Publishable Key",
}),
expect.objectContaining({
title: "Default Publishable API Key",
}),
])
)
})
@@ -61,7 +61,7 @@ medusaIntegrationTestRunner({
adminHeaders
)
expect(response.data.count).toBe(2)
expect(response.data.count).toBe(3) // two created keys and the default publishable api key
expect(response.data.limit).toBe(2)
expect(response.data.offset).toBe(0)
expect(response.data.api_keys).toHaveLength(2)
@@ -0,0 +1,91 @@
import { createDefaultsWorkflow } from "@medusajs/core-flows"
import { Query } from "@medusajs/modules-sdk"
import { medusaIntegrationTestRunner } from "@medusajs/test-utils"
jest.setTimeout(50000)
const env = {}
medusaIntegrationTestRunner({
env,
testSuite: ({ getContainer }) => {
describe("Defaults", () => {
let appContainer
let query: Query
beforeAll(async () => {
appContainer = getContainer()
query = appContainer.resolve("query")
})
it("should successfully create default data on first run", async () => {
const {
data: [store],
} = await query.graph({
entity: "store",
fields: ["id", "name", "default_sales_channel_id"],
})
const {
data: [salesChannel],
} = await query.graph({
entity: "sales_channel",
fields: ["id", "name"],
})
const {
data: [publishableApiKey],
} = await query.graph({
entity: "api_key",
fields: ["id", "type", "title"],
filters: {
type: "publishable",
},
})
expect(store).toEqual(
expect.objectContaining({
id: expect.any(String),
name: "Medusa Store",
default_sales_channel_id: salesChannel.id,
})
)
expect(salesChannel).toEqual(
expect.objectContaining({
id: expect.any(String),
name: "Default Sales Channel",
})
)
expect(publishableApiKey).toEqual(
expect.objectContaining({
id: expect.any(String),
title: "Default Publishable API Key",
type: "publishable",
})
)
})
it("should skip creating default data on n+1 runs", async () => {
await createDefaultsWorkflow(appContainer).run()
const { data: stores } = await query.graph({
entity: "store",
fields: ["id"],
})
const { data: salesChannels } = await query.graph({
entity: "sales_channel",
fields: ["id"],
})
const { data: publishableApiKeys } = await query.graph({
entity: "api_key",
fields: ["id", "type"],
filters: {
type: "publishable",
},
})
expect(stores.length).toEqual(1)
expect(salesChannels.length).toEqual(1)
expect(publishableApiKeys.length).toEqual(1)
})
})
},
})
@@ -1,7 +1,14 @@
import {
createWorkflow,
transform,
when,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
import {
createApiKeysStep,
linkSalesChannelsToApiKeyWorkflow,
} from "../../api-key"
import { useQueryGraphStep } from "../../common"
import { createDefaultSalesChannelStep } from "../../sales-channel"
import { createDefaultStoreStep } from "../steps/create-default-store"
@@ -10,16 +17,16 @@ export const createDefaultsWorkflowID = "create-defaults"
* This workflow creates default data for a Medusa application, including
* a default sales channel and store. The Medusa application uses this workflow
* to create the default data, if not existing, when the application is first started.
*
*
* You can use this workflow within your customizations or your own custom workflows, allowing you to
* create default data within your custom flows, such as seed scripts.
*
*
* @example
* const { result } = await createDefaultsWorkflow(container)
* .run()
*
*
* @summary
*
*
* Create default data for a Medusa application.
*/
export const createDefaultsWorkflow = createWorkflow(
@@ -37,6 +44,46 @@ export const createDefaultsWorkflow = createWorkflow(
},
})
const publishableApiKey = useQueryGraphStep({
entity: "api_key",
fields: ["id", "type"],
filters: {
type: "publishable",
},
options: {
isList: false,
},
})
when(
{ publishableApiKey },
({ publishableApiKey }) => !publishableApiKey?.data
).then(() => {
const createResult = createApiKeysStep({
api_keys: [
{
title: "Default Publishable API Key",
type: "publishable",
created_by: "",
},
],
})
const publishableApiKey = transform(
{ createResult },
({ createResult }) => {
return createResult[0]
}
)
linkSalesChannelsToApiKeyWorkflow.runAsStep({
input: {
id: publishableApiKey.id,
add: [salesChannel.id],
},
})
})
return new WorkflowResponse(store)
}
)