Skip to content

Commit 4cc91ba

Browse files
authored
Expose cosmos.fixtures.json with renderer URLs (#1629)
1 parent f83799a commit 4cc91ba

12 files changed

Lines changed: 167 additions & 20 deletions

File tree

packages/react-cosmos-core/src/fixtureTree/createFixtureTree/createRawFixtureTree.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
FixtureListItem,
55
} from '../../userModules/fixtureTypes.js';
66
import { addTreeNodeChild } from '../../utils/tree.js';
7+
import { removeFixtureNameExtension } from '../fixtureUtils.js';
78
import { FixtureTreeNode } from '../types.js';
89

910
export function createRawFixtureTree(fixtures: FixtureList): FixtureTreeNode {
@@ -55,10 +56,6 @@ function parseFixturePath(fixturePath: string) {
5556
};
5657
}
5758

58-
function removeFixtureNameExtension(fixtureName: string) {
59-
return fixtureName.replace(/\.(js|jsx|ts|tsx|md|mdx)$/, '');
60-
}
61-
6259
function injectNode(
6360
rootNode: FixtureTreeNode,
6461
parents: string[],

packages/react-cosmos-core/src/fixtureTree/createFixtureTree/hideFixtureSuffix.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { removeFixtureNameSuffix } from '../fixtureUtils.js';
12
import { FixtureTreeNode } from '../types.js';
23

34
export function hideFixtureSuffix(
@@ -25,10 +26,3 @@ export function hideFixtureSuffix(
2526
}, {}),
2627
};
2728
}
28-
29-
function removeFixtureNameSuffix(
30-
fixtureNameWithoutExtension: string,
31-
suffix: string
32-
) {
33-
return fixtureNameWithoutExtension.replace(new RegExp(`\\.${suffix}$`), '');
34-
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export function removeFixtureNameExtension(fixtureName: string) {
2+
return fixtureName.replace(/\.(js|jsx|ts|tsx|md|mdx)$/, '');
3+
}
4+
5+
export function removeFixtureNameSuffix(
6+
fixtureNameWithoutExtension: string,
7+
suffix: string
8+
) {
9+
return fixtureNameWithoutExtension.replace(new RegExp(`\\.${suffix}$`), '');
10+
}

packages/react-cosmos-core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export * from './fixtureState/propsTypes.js';
99
export * from './fixtureState/types.js';
1010
export * from './fixtureState/viewport.js';
1111
export * from './fixtureTree/createFixtureTree/index.js';
12+
export * from './fixtureTree/fixtureUtils.js';
1213
export * from './fixtureTree/flattenFixtureTree.js';
1314
export * from './fixtureTree/types.js';
1415
export * from './message/serverMessage.js';

packages/react-cosmos-core/src/renderer/rendererUrl.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { CosmosCommand } from '../server/serverTypes.js';
33
import { FixtureId } from '../userModules/fixtureTypes.js';
44
import { buildRendererQueryString } from './rendererQueryString.js';
55

6+
export type CosmosRendererUrl = null | string | { dev: string; export: string };
7+
68
export function createRendererUrl(
79
rendererUrl: string,
810
fixtureId?: FixtureId,
@@ -24,7 +26,7 @@ export function createRendererUrl(
2426
}
2527

2628
export function pickRendererUrl(
27-
rendererUrl: undefined | null | string | { dev: string; export: string },
29+
rendererUrl: undefined | CosmosRendererUrl,
2830
command: CosmosCommand
2931
): null | string {
3032
return rendererUrl && typeof rendererUrl === 'object'
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import express from 'express';
2+
import fs from 'node:fs/promises';
3+
import path from 'node:path';
4+
import {
5+
CosmosCommand,
6+
createRendererUrl,
7+
pickRendererUrl,
8+
removeFixtureNameExtension,
9+
removeFixtureNameSuffix,
10+
} from 'react-cosmos-core';
11+
import { CosmosConfig } from '../cosmosConfig/types.js';
12+
import { CosmosServerPlugin } from '../cosmosPlugin/types.js';
13+
import { findUserModulePaths } from '../userModules/findUserModulePaths.js';
14+
import { importKeyPath } from '../userModules/shared.js';
15+
16+
export type CosmosFixtureJson = {
17+
filePath: string;
18+
cleanPath: string[];
19+
rendererUrl: string;
20+
};
21+
22+
export type CosmosFixturesJson = {
23+
rendererUrl: string | null;
24+
fixtures: CosmosFixtureJson[];
25+
};
26+
27+
export const fixturesJsonPlugin: CosmosServerPlugin = {
28+
name: 'fixturesJson',
29+
30+
devServer({ cosmosConfig, expressApp }) {
31+
expressApp.get(
32+
'/cosmos.fixtures.json',
33+
(req: express.Request, res: express.Response) => {
34+
res.json(createFixtureItems(cosmosConfig, 'dev'));
35+
}
36+
);
37+
},
38+
39+
async export({ cosmosConfig }) {
40+
const { exportPath } = cosmosConfig;
41+
const json = createFixtureItems(cosmosConfig, 'export');
42+
await fs.writeFile(
43+
path.join(exportPath, 'cosmos.fixtures.json'),
44+
JSON.stringify(json, null, 2)
45+
);
46+
},
47+
};
48+
49+
function createFixtureItems(
50+
cosmosConfig: CosmosConfig,
51+
command: CosmosCommand
52+
): CosmosFixturesJson {
53+
const rendererUrl = pickRendererUrl(cosmosConfig.rendererUrl, command);
54+
if (!rendererUrl) {
55+
return {
56+
rendererUrl: null,
57+
fixtures: [],
58+
};
59+
}
60+
61+
const { fixturesDir, fixtureFileSuffix } = cosmosConfig;
62+
const { fixturePaths } = findUserModulePaths(cosmosConfig);
63+
64+
return {
65+
rendererUrl,
66+
fixtures: fixturePaths.map(filePath => {
67+
const relPath = importKeyPath(filePath, cosmosConfig.rootDir);
68+
const fixtureId = { path: relPath };
69+
return {
70+
filePath: relPath,
71+
cleanPath: cleanFixturePath(relPath, fixturesDir, fixtureFileSuffix),
72+
rendererUrl: createRendererUrl(rendererUrl, fixtureId, true),
73+
};
74+
}),
75+
};
76+
}
77+
78+
function cleanFixturePath(
79+
filePath: string,
80+
fixturesDir: string,
81+
fixtureSuffix: string
82+
) {
83+
const paths = filePath.split('/').filter(p => p !== fixturesDir);
84+
return [
85+
...paths.slice(0, -1),
86+
removeFixtureNameSuffix(
87+
removeFixtureNameExtension(paths[paths.length - 1]),
88+
fixtureSuffix
89+
),
90+
];
91+
}

packages/react-cosmos/src/corePlugins/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { CosmosServerPlugin } from '../cosmosPlugin/types.js';
22
import { fixtureWatcherPlugin } from './fixtureWatcherPlugin.js';
3+
import { fixturesJsonPlugin } from './fixturesJsonPlugin.js';
34
import { httpProxyPlugin } from './httpProxyPlugin.js';
45
import { openFilePlugin } from './openFilePlugin.js';
56
import { pluginEndpointPlugin } from './pluginEndpointPlugin.js';
67
import { portRetryPlugin } from './portRetryPlugin.js';
78

89
export const coreServerPlugins: CosmosServerPlugin[] = [
910
portRetryPlugin,
11+
fixturesJsonPlugin,
1012
httpProxyPlugin,
1113
openFilePlugin,
1214
pluginEndpointPlugin,

packages/react-cosmos/src/cosmosConfig/types.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { CosmosRendererUrl } from 'react-cosmos-core';
2+
13
interface HttpsOptions {
24
keyPath: string;
35
certPath: string;
@@ -34,7 +36,7 @@ export type CosmosConfig = {
3436
portRetries: number;
3537
plugins: string[];
3638
publicUrl: string;
37-
rendererUrl: null | string | { dev: string; export: string };
39+
rendererUrl: CosmosRendererUrl;
3840
rootDir: string;
3941
staticPath: null | string;
4042
watchDirs: string[];

packages/react-cosmos/src/getFixtures/importUserModules.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
import path from 'path';
21
import {
32
ByPath,
43
ReactDecoratorModule,
54
ReactFixtureModule,
65
} from 'react-cosmos-core';
76
import { CosmosConfig } from '../cosmosConfig/types.js';
87
import { findUserModulePaths } from '../userModules/findUserModulePaths.js';
9-
import { slash } from '../utils/slash.js';
8+
import { importKeyPath } from '../userModules/shared.js';
109

1110
type UserModules = {
1211
fixtures: ByPath<ReactFixtureModule>;
@@ -33,10 +32,7 @@ export function importUserModules({
3332

3433
function importModules<T>(paths: string[], rootDir: string) {
3534
const modules = paths.map(p => {
36-
// Converting to forward slashes on Windows is important because the
37-
// slashes are used for generating a sorted list of fixtures and
38-
// decorators.
39-
const relPath = slash(path.relative(rootDir, p));
35+
const relPath = importKeyPath(p, rootDir);
4036
return { relPath, module: require(p) };
4137
});
4238

packages/react-cosmos/src/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
export {
2+
CosmosFixtureJson,
3+
CosmosFixturesJson,
4+
} from './corePlugins/fixturesJsonPlugin.js';
15
export * from './cosmosConfig/createCosmosConfig.js';
26
export * from './cosmosConfig/detectCosmosConfig.js';
37
export * from './cosmosConfig/getCosmosConfigAtPath.js';

0 commit comments

Comments
 (0)