Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/web-shared/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ See `npx workflow inspect --help` for more information.
If you're deploying this as part of your Vercel NextJS app, setting `WORKFLOW_TARGET_WORLD` to `vercel` is enough
to infer your other project details from the Vercel environment variables.

**Important:** When using the UI to inspect different worlds, all relevant environment variables should be passed via the `EnvMap` parameter to the hooks and components, rather than setting them directly on your Next.js instance via `process.env`. The server-side World caching is based on the `EnvMap` configuration, so setting environment variables directly on `process.env` may cause cached World instances to operate with incorrect environment configuration.

## Styling

In order for tailwind classes to be picked up correctly, you might need to configure your NextJS app
Expand Down
34 changes: 33 additions & 1 deletion packages/web-shared/src/api/workflow-server-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type {
Step,
WorkflowRun,
WorkflowRunStatus,
World,
} from '@workflow/world';

export type EnvMap = Record<string, string | undefined>;
Expand Down Expand Up @@ -38,14 +39,45 @@ export type ServerActionResult<T> =
| { success: true; data: T }
| { success: false; error: ServerActionError };

/**
* Cache for World instances keyed by envMap
*
* IMPORTANT: This cache works under the assumption that if the UI is used to look at
* different worlds, the user should pass all relevant variables via EnvMap, instead of
* setting them directly on their Next.js instance. If environment variables are set
* directly on process.env, the cached World may operate with incorrect environment
* configuration.
*/
const worldCache = new Map<string, World>();

function getWorldFromEnv(envMap: EnvMap) {
// Generate stable cache key from envMap
const sortedKeys = Object.keys(envMap).sort();
const sortedEntries = sortedKeys.map((key) => [key, envMap[key]]);
const cacheKey = JSON.stringify(Object.fromEntries(sortedEntries));

// Check if we have a cached World for this configuration
// Note: This returns the cached World without re-setting process.env.
// See comment above worldCache for important usage assumptions.
const cachedWorld = worldCache.get(cacheKey);
if (cachedWorld) {
return cachedWorld;
}

// No cached World found, create a new one
for (const [key, value] of Object.entries(envMap)) {
if (value === undefined || value === null || value === '') {
continue;
}
process.env[key] = value;
}
return createWorld();

const world = createWorld();

// Cache the newly created World
worldCache.set(cacheKey, world);

return world;
}

/**
Expand Down