8000 [rush-serve-plugin] Allow serving single files · mstomar698/rushstack@9dcdf8b · GitHub
[go: up one dir, main page]

Skip to content

Commit 9dcdf8b

Browse files
committed
[rush-serve-plugin] Allow serving single files
1 parent a725488 commit 9dcdf8b

File tree

4 files changed

+100
-29
lines changed

4 files changed

+100
-29
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@rushstack/rush-serve-plugin",
5+
"comment": "Allow serving of single files, e.g. to serve a specific file at \"/\" (the root).",
6+
"type": "minor"
7+
}
8+
],
9+
"packageName": "@rushstack/rush-serve-plugin"
10+
}

rush-plugins/rush-serve-plugin/src/RushProjectServeConfigFile.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,24 @@ export interface IRushProjectServeJson {
1212
routing: IRoutingRuleJson[];
1313
}
1414

15-
export interface IRoutingRuleJson {
15+
export interface IRoutingFolderRuleJson {
16+
projectRelativeFile: undefined;
1617
projectRelativeFolder: string;
1718
servePath: string;
1819
immutable?: boolean;
1920
}
2021

22+
export interface IRoutingFileRuleJson {
23+
projectRelativeFile: string;
24+
projectRelativeFolder: undefined;
25+
servePath: string;
26+
immutable?: boolean;
27+
}
28+
29+
export type IRoutingRuleJson = IRoutingFileRuleJson | IRoutingFolderRuleJson;
30+
2131
export interface IRoutingRule {
32+
type: 'file' | 'folder';
2233
diskPath: string;
2334
servePath: string;
2435
immutable: boolean;
@@ -61,8 +72,11 @@ export class RushServeConfiguration {
6172
);
6273
if (serveJson) {
6374
for (const rule of serveJson.routing) {
75+
const { projectRelativeFile, projectRelativeFolder } = rule;
76+
const diskPath: string = projectRelativeFolder ?? projectRelativeFile;
6477
rules.push({
65-
diskPath: path.resolve(project.projectFolder, rule.projectRelativeFolder),
78+
type: projectRelativeFile ? 'file' : 'folder',
79+
diskPath: path.resolve(project.projectFolder, diskPath),
6680
servePath: rule.servePath,
6781
immutable: !!rule.immutable
6882
});

rush-plugins/rush-serve-plugin/src/phasedCommandHandler.ts

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -89,22 +89,44 @@ export async function phasedCommandHandler(options: IPhasedCommandHandlerOptions
8989
logger.terminal
9090
);
9191

92-
function setHeaders(response: express.Response, path: string, stat: unknown): void {
92+
const fileRoutingRules: Map<string, IRoutingRule> = new Map();
93+
94+
function setHeaders(response: express.Response, path?: string, stat?: unknown): void {
9395
response.set('Access-Control-Allow-Origin', '*');
94-
response.set('Access-Control-Allow-Methods', 'GET');
96+
response.set('Access-Control-Allow-Methods', 'GET, OPTIONS');
9597
}
9698

9799
for (const rule of routingRules) {
98-
app.use(
99-
rule.servePath,
100-
express.static(rule.diskPath, {
101-
dotfiles: 'ignore',
102-
immutable: rule.immutable,
103-
index: false,
104-
redirect: false,
105-
setHeaders
106-
})
107-
);
100+
const { diskPath, servePath } = rule;
101+
if (rule.type === 'file') {
102+
const 67ED existingRule: IRoutingRule | undefined = fileRoutingRules.get(servePath);
103+
if (existingRule) {
104+
throw new Error(
105+
`Request to serve "${diskPath}" at "${servePath}" conflicts with existing rule to serve "${existingRule.diskPath}" from this location.`
106+
);
107+
} else {
108+
fileRoutingRules.set(diskPath, rule);
109+
app.get(servePath, (request: express.Request, response: express.Response) => {
110+
response.sendFile(diskPath, {
111+
headers: {
112+
'Access-Control-Allow-Origin': '*',
113+
'Access-Control-Allow-Methods': 'GET, OPTIONS'
114+
}
115+
});
116+
});
117+
}
118+
} else {
119+
app.use(
120+
servePath,
121+
express.static(diskPath, {
122+
dotfiles: 'ignore',
123+
immutable: rule.immutable,
124+
index: false,
125+
redirect: false,
126+
setHeaders
127+
})
128+
);
129+
}
108130
}
109131

110132
const server: https.Server = https.createServer(

rush-plugins/rush-serve-plugin/src/schemas/rush-project-serve.schema.json

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,25 +20,50 @@
2020
"type": "array",
2121
"description": "Routing rules",
2222
"items": {
23-
"type": "object",
24-
"additionalProperties": false,
25-
"required": ["projectRelativeFolder", "servePath"],
26-
"properties": {
27-
"projectRelativeFolder": {
28-
"type": "string",
29-
"description": "The folder from which to read assets, relative to the root of the current project."
30-
},
23+
"oneOf": [
24+
{
25+
"type": "object",
26+
"additionalProperties": false,
27+
"required": ["projectRelativeFolder", "servePath"],
28+
"properties": {
29+
"projectRelativeFolder": {
30+
"type": "string",
31+
"description": "The folder from which to read assets, relative to the root of the current project."
32+
},
33+
34+
"servePath": {
35+
"type": "string",
36+
"description": "The server path at which to serve the assets in \"projectRelativeFolder\"."
37+
},
3138

32-
"servePath": {
33-
"type": "string",
34-
"description": "The server path at which to serve the assets in \"projectRelativeFolder\"."
39+
"immutable": {
40+
"type": "boolean",
41+
"description": "Enables or disables the `immutable` directive in the `Cache-Control` resoponse header. See (https://expressjs.com/en/4x/api.html#express.static)."
42+
}
43+
}
3544
},
45+
{
46+
"type": "object",
47+
"additionalProperties": false,
48+
"required": ["projectRelativeFile", "servePath"],
49+
"properties": {
50+
"projectRelativeFile": {
51+
"type": "string",
52+
"description": "The file to serve, relative to the root of the current project."
53+
},
54+
55+
"servePath": {
56+
"type": "string",
57+
"description": "The server path at which to serve \"projectRelativeFile\"."
58+
},
3659

37-
"immutable": {
38-
"type": "boolean",
39-
"description": "Enables or disables the `immutable` directive in the `Cache-Control` resoponse header. See (https://expressjs.com/en/4x/api.html#express.static)."
60+
"immutable": {
61+
"type": "boolean",
62+
"description": "Enables or disables the `immutable` directive in the `Cache-Control` resoponse header. See (https://expressjs.com/en/4x/api.html#express.static)."
63+
}
64+
}
4065
}
41-
}
66+
]
4267
}
4368
}
4469
}

0 commit comments

Comments
 (0)
0