@flink-app/static-files-plugin 0.12.1-alpha.9 → 0.13.0
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.
- package/CHANGELOG.md +12 -0
- package/dist/index.js +3 -2
- package/package.json +24 -27
- package/readme.md +489 -21
- package/src/index.ts +21 -23
- package/tsconfig.json +1 -1
package/CHANGELOG.md
ADDED
package/dist/index.js
CHANGED
|
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.staticFilesPlugin = void 0;
|
|
7
|
-
var express_1 = __importDefault(require("express"));
|
|
8
7
|
var node_color_log_1 = __importDefault(require("node-color-log"));
|
|
9
8
|
var staticFilesPlugin = function (options) {
|
|
10
9
|
return {
|
|
@@ -19,5 +18,7 @@ function init(app, options) {
|
|
|
19
18
|
throw new Error("Express app not initialized");
|
|
20
19
|
}
|
|
21
20
|
node_color_log_1.default.info("Registered static file route ".concat(options.path));
|
|
22
|
-
|
|
21
|
+
// Access express.static through the Express constructor
|
|
22
|
+
var express = expressApp.constructor;
|
|
23
|
+
expressApp.use(options.path, express.static(options.folder));
|
|
23
24
|
}
|
package/package.json
CHANGED
|
@@ -1,28 +1,25 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
},
|
|
27
|
-
"gitHead": "3007ad036607014176930446fde56203bde8d6f5"
|
|
28
|
-
}
|
|
2
|
+
"name": "@flink-app/static-files-plugin",
|
|
3
|
+
"version": "0.13.0",
|
|
4
|
+
"description": "Flink plugin that make flink serve static files",
|
|
5
|
+
"author": "johan@frost.se",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"types": "dist/index.d.ts",
|
|
11
|
+
"main": "dist/index.js",
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"node-color-log": "^5.3.1",
|
|
14
|
+
"@flink-app/flink": "0.13.0"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/node": "22.13.10"
|
|
18
|
+
},
|
|
19
|
+
"gitHead": "4243e3b3cd6d4e1ca001a61baa8436bf2bbe4113",
|
|
20
|
+
"scripts": {
|
|
21
|
+
"test": "echo \"Error: no test specified\"",
|
|
22
|
+
"build": "tsc",
|
|
23
|
+
"clean": "rimraf dist .flink"
|
|
24
|
+
}
|
|
25
|
+
}
|
package/readme.md
CHANGED
|
@@ -1,54 +1,522 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Static Files Plugin
|
|
2
2
|
|
|
3
|
-
A
|
|
3
|
+
A Flink plugin for serving static files (HTML, CSS, JavaScript, images, etc.) through your Flink application using Express's built-in static file serving middleware.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Installation
|
|
6
6
|
|
|
7
|
-
Install plugin to your
|
|
7
|
+
Install the plugin to your Flink app project:
|
|
8
8
|
|
|
9
|
-
```
|
|
10
|
-
npm
|
|
9
|
+
```bash
|
|
10
|
+
npm install @flink-app/static-files-plugin
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
## Configuration
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
### Basic Setup
|
|
16
|
+
|
|
17
|
+
Configure the plugin to serve static files from a directory:
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { FlinkApp } from "@flink-app/flink";
|
|
16
21
|
import { staticFilesPlugin } from "@flink-app/static-files-plugin";
|
|
22
|
+
import { join } from "path";
|
|
17
23
|
|
|
18
24
|
function start() {
|
|
19
25
|
new FlinkApp<AppContext>({
|
|
20
26
|
name: "My app",
|
|
21
27
|
plugins: [
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
})
|
|
28
|
+
staticFilesPlugin({
|
|
29
|
+
path: "/", // URL path to serve files from
|
|
30
|
+
folder: join(__dirname, "public") // Filesystem path to static files
|
|
31
|
+
})
|
|
27
32
|
],
|
|
28
33
|
}).start();
|
|
29
34
|
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Plugin Options:**
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
interface StaticOptions {
|
|
41
|
+
path: string; // Base URL path for static files (e.g., "/", "/assets", "/static")
|
|
42
|
+
folder: string; // Absolute path to the folder containing static files
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Usage Examples
|
|
47
|
+
|
|
48
|
+
### Serve Files from Root Path
|
|
49
|
+
|
|
50
|
+
Serve static files directly from the root URL:
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import { join } from "path";
|
|
54
|
+
|
|
55
|
+
staticFilesPlugin({
|
|
56
|
+
path: "/",
|
|
57
|
+
folder: join(__dirname, "public")
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
// Files accessible at:
|
|
61
|
+
// http://localhost:3000/index.html
|
|
62
|
+
// http://localhost:3000/styles.css
|
|
63
|
+
// http://localhost:3000/logo.png
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Serve Files from Subdirectory
|
|
67
|
+
|
|
68
|
+
Serve static files from a specific URL path:
|
|
30
69
|
|
|
70
|
+
```typescript
|
|
71
|
+
import { join } from "path";
|
|
72
|
+
|
|
73
|
+
staticFilesPlugin({
|
|
74
|
+
path: "/assets",
|
|
75
|
+
folder: join(__dirname, "public")
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
// Files accessible at:
|
|
79
|
+
// http://localhost:3000/assets/index.html
|
|
80
|
+
// http://localhost:3000/assets/styles.css
|
|
81
|
+
// http://localhost:3000/assets/logo.png
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Multiple Static Directories
|
|
85
|
+
|
|
86
|
+
Serve different directories at different paths:
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
import { join } from "path";
|
|
90
|
+
|
|
91
|
+
new FlinkApp<AppContext>({
|
|
92
|
+
name: "My app",
|
|
93
|
+
plugins: [
|
|
94
|
+
// Serve images
|
|
95
|
+
staticFilesPlugin({
|
|
96
|
+
path: "/images",
|
|
97
|
+
folder: join(__dirname, "assets/images")
|
|
98
|
+
}),
|
|
99
|
+
|
|
100
|
+
// Serve CSS/JS
|
|
101
|
+
staticFilesPlugin({
|
|
102
|
+
path: "/static",
|
|
103
|
+
folder: join(__dirname, "assets/static")
|
|
104
|
+
}),
|
|
105
|
+
|
|
106
|
+
// Serve HTML pages
|
|
107
|
+
staticFilesPlugin({
|
|
108
|
+
path: "/",
|
|
109
|
+
folder: join(__dirname, "public")
|
|
110
|
+
})
|
|
111
|
+
]
|
|
112
|
+
}).start();
|
|
113
|
+
|
|
114
|
+
// Files accessible at:
|
|
115
|
+
// http://localhost:3000/images/logo.png
|
|
116
|
+
// http://localhost:3000/static/app.js
|
|
117
|
+
// http://localhost:3000/index.html
|
|
31
118
|
```
|
|
32
119
|
|
|
33
|
-
|
|
120
|
+
## File Types Supported
|
|
121
|
+
|
|
122
|
+
The plugin can serve any static file type, including:
|
|
34
123
|
|
|
35
|
-
|
|
124
|
+
- **HTML**: `.html`, `.htm`
|
|
125
|
+
- **CSS**: `.css`
|
|
126
|
+
- **JavaScript**: `.js`, `.mjs`
|
|
127
|
+
- **Images**: `.jpg`, `.jpeg`, `.png`, `.gif`, `.svg`, `.webp`, `.ico`
|
|
128
|
+
- **Fonts**: `.woff`, `.woff2`, `.ttf`, `.eot`
|
|
129
|
+
- **Documents**: `.pdf`, `.txt`, `.json`, `.xml`
|
|
130
|
+
- **Media**: `.mp4`, `.webm`, `.mp3`, `.ogg`, `.wav`
|
|
131
|
+
- And more...
|
|
36
132
|
|
|
37
|
-
|
|
133
|
+
## Directory Structure Example
|
|
38
134
|
|
|
135
|
+
Typical project structure with static files:
|
|
39
136
|
|
|
40
137
|
```
|
|
41
|
-
|
|
138
|
+
my-flink-app/
|
|
139
|
+
├── src/
|
|
140
|
+
│ ├── index.ts # App startup
|
|
141
|
+
│ ├── handlers/ # API handlers
|
|
142
|
+
│ └── public/ # Static files (source)
|
|
143
|
+
│ ├── index.html
|
|
144
|
+
│ ├── styles.css
|
|
145
|
+
│ ├── app.js
|
|
146
|
+
│ └── images/
|
|
147
|
+
│ └── logo.png
|
|
148
|
+
└── dist/ # Built output
|
|
149
|
+
└── src/
|
|
150
|
+
└── public/ # Static files (copied)
|
|
42
151
|
```
|
|
43
152
|
|
|
44
|
-
|
|
153
|
+
## Copying Static Files to Dist
|
|
154
|
+
|
|
155
|
+
Flink's TypeScript compiler only copies `.ts` and `.json` files by default. Static files need to be copied manually to the `dist` folder.
|
|
156
|
+
|
|
157
|
+
### Method 1: Using copyfiles Package
|
|
158
|
+
|
|
159
|
+
Install the `copyfiles` package:
|
|
45
160
|
|
|
161
|
+
```bash
|
|
162
|
+
npm install --save-dev copyfiles
|
|
46
163
|
```
|
|
47
|
-
|
|
164
|
+
|
|
165
|
+
Add scripts to your `package.json`:
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"scripts": {
|
|
48
170
|
"copy-files": "copyfiles -u 1 src/public/**/* dist/src/",
|
|
49
171
|
"predev": "npm run copy-files",
|
|
172
|
+
"prebuild": "npm run copy-files",
|
|
173
|
+
"dev": "nodemon",
|
|
174
|
+
"build": "tsc -p tsconfig.dist.json"
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**Explanation:**
|
|
180
|
+
- `copyfiles -u 1 src/public/**/* dist/src/` copies all files from `src/public/` to `dist/src/public/`
|
|
181
|
+
- `-u 1` removes the first directory level (strips `src/`)
|
|
182
|
+
- `predev` and `prebuild` run automatically before `dev` and `build` scripts
|
|
183
|
+
|
|
184
|
+
### Method 2: Using npm-run-all
|
|
185
|
+
|
|
186
|
+
For parallel copying of multiple directories:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
npm install --save-dev npm-run-all copyfiles
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
```json
|
|
193
|
+
{
|
|
194
|
+
"scripts": {
|
|
195
|
+
"copy:public": "copyfiles -u 1 src/public/**/* dist/src/",
|
|
196
|
+
"copy:assets": "copyfiles -u 1 src/assets/**/* dist/src/",
|
|
197
|
+
"copy:all": "npm-run-all copy:*",
|
|
198
|
+
"predev": "npm run copy:all",
|
|
199
|
+
"prebuild": "npm run copy:all"
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Method 3: Using a Custom Script
|
|
205
|
+
|
|
206
|
+
Create a copy script (`scripts/copy-static.js`):
|
|
207
|
+
|
|
208
|
+
```javascript
|
|
209
|
+
const fs = require("fs-extra");
|
|
210
|
+
const path = require("path");
|
|
211
|
+
|
|
212
|
+
const source = path.join(__dirname, "../src/public");
|
|
213
|
+
const dest = path.join(__dirname, "../dist/src/public");
|
|
214
|
+
|
|
215
|
+
fs.copySync(source, dest, {
|
|
216
|
+
overwrite: true,
|
|
217
|
+
errorOnExist: false
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
console.log("Static files copied successfully!");
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Add to `package.json`:
|
|
224
|
+
|
|
225
|
+
```json
|
|
226
|
+
{
|
|
227
|
+
"scripts": {
|
|
228
|
+
"copy-files": "node scripts/copy-static.js",
|
|
229
|
+
"predev": "npm run copy-files",
|
|
50
230
|
"prebuild": "npm run copy-files"
|
|
51
|
-
|
|
231
|
+
}
|
|
232
|
+
}
|
|
52
233
|
```
|
|
53
234
|
|
|
54
|
-
|
|
235
|
+
## Complete Example
|
|
236
|
+
|
|
237
|
+
Here's a complete example of serving a frontend application:
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
import { FlinkApp } from "@flink-app/flink";
|
|
241
|
+
import { staticFilesPlugin } from "@flink-app/static-files-plugin";
|
|
242
|
+
import { join } from "path";
|
|
243
|
+
import { Ctx } from "./Ctx";
|
|
244
|
+
|
|
245
|
+
function start() {
|
|
246
|
+
new FlinkApp<Ctx>({
|
|
247
|
+
name: "My Full-Stack App",
|
|
248
|
+
db: {
|
|
249
|
+
uri: process.env.MONGODB_URI!
|
|
250
|
+
},
|
|
251
|
+
plugins: [
|
|
252
|
+
// Serve frontend application
|
|
253
|
+
staticFilesPlugin({
|
|
254
|
+
path: "/",
|
|
255
|
+
folder: join(__dirname, "public")
|
|
256
|
+
}),
|
|
257
|
+
|
|
258
|
+
// Serve uploaded files
|
|
259
|
+
staticFilesPlugin({
|
|
260
|
+
path: "/uploads",
|
|
261
|
+
folder: join(__dirname, "../uploads")
|
|
262
|
+
})
|
|
263
|
+
]
|
|
264
|
+
}).start();
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
start();
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
**Project Structure:**
|
|
271
|
+
```
|
|
272
|
+
dist/
|
|
273
|
+
└── src/
|
|
274
|
+
├── index.js # Compiled app
|
|
275
|
+
├── public/ # Frontend files
|
|
276
|
+
│ ├── index.html
|
|
277
|
+
│ ├── app.js
|
|
278
|
+
│ └── styles.css
|
|
279
|
+
└── uploads/ # User uploads
|
|
280
|
+
└── image.jpg
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
**Accessible URLs:**
|
|
284
|
+
- `http://localhost:3000/` → `dist/src/public/index.html`
|
|
285
|
+
- `http://localhost:3000/app.js` → `dist/src/public/app.js`
|
|
286
|
+
- `http://localhost:3000/styles.css` → `dist/src/public/styles.css`
|
|
287
|
+
- `http://localhost:3000/uploads/image.jpg` → `dist/src/uploads/image.jpg`
|
|
288
|
+
|
|
289
|
+
## Advanced Usage
|
|
290
|
+
|
|
291
|
+
### SPA (Single Page Application) Support
|
|
292
|
+
|
|
293
|
+
For React, Vue, Angular apps that use client-side routing:
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
import { FlinkApp } from "@flink-app/flink";
|
|
297
|
+
import { staticFilesPlugin } from "@flink-app/static-files-plugin";
|
|
298
|
+
import express from "express";
|
|
299
|
+
import { join } from "path";
|
|
300
|
+
|
|
301
|
+
const app = new FlinkApp<Ctx>({
|
|
302
|
+
name: "SPA App",
|
|
303
|
+
plugins: [
|
|
304
|
+
// Serve static assets
|
|
305
|
+
staticFilesPlugin({
|
|
306
|
+
path: "/",
|
|
307
|
+
folder: join(__dirname, "public")
|
|
308
|
+
})
|
|
309
|
+
]
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
// Fallback to index.html for client-side routing
|
|
313
|
+
app.expressApp?.get("*", (req, res) => {
|
|
314
|
+
res.sendFile(join(__dirname, "public/index.html"));
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
app.start();
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Serving with Cache Headers
|
|
321
|
+
|
|
322
|
+
Modify Express static options for better caching:
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
import { FlinkApp } from "@flink-app/flink";
|
|
326
|
+
import express from "express";
|
|
327
|
+
import { join } from "path";
|
|
328
|
+
|
|
329
|
+
const app = new FlinkApp<Ctx>({
|
|
330
|
+
name: "My app",
|
|
331
|
+
plugins: []
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
// Manually configure express.static with options
|
|
335
|
+
const staticPath = join(__dirname, "public");
|
|
336
|
+
app.expressApp?.use("/", express.static(staticPath, {
|
|
337
|
+
maxAge: "1d", // Cache for 1 day
|
|
338
|
+
etag: true, // Enable ETags
|
|
339
|
+
lastModified: true, // Enable Last-Modified headers
|
|
340
|
+
index: ["index.html"] // Default index files
|
|
341
|
+
}));
|
|
342
|
+
|
|
343
|
+
app.start();
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Serving Different Files in Development vs Production
|
|
347
|
+
|
|
348
|
+
```typescript
|
|
349
|
+
import { FlinkApp } from "@flink-app/flink";
|
|
350
|
+
import { staticFilesPlugin } from "@flink-app/static-files-plugin";
|
|
351
|
+
import { join } from "path";
|
|
352
|
+
|
|
353
|
+
const isDev = process.env.NODE_ENV !== "production";
|
|
354
|
+
|
|
355
|
+
new FlinkApp<Ctx>({
|
|
356
|
+
name: "My app",
|
|
357
|
+
plugins: [
|
|
358
|
+
staticFilesPlugin({
|
|
359
|
+
path: "/",
|
|
360
|
+
folder: isDev
|
|
361
|
+
? join(__dirname, "../public") // Development: src/public
|
|
362
|
+
: join(__dirname, "public") // Production: dist/src/public
|
|
363
|
+
})
|
|
364
|
+
]
|
|
365
|
+
}).start();
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
## Best Practices
|
|
369
|
+
|
|
370
|
+
### 1. Use Absolute Paths
|
|
371
|
+
|
|
372
|
+
Always use `join(__dirname, ...)` for absolute paths:
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
// Good
|
|
376
|
+
folder: join(__dirname, "public")
|
|
377
|
+
|
|
378
|
+
// Bad - relative paths can cause issues
|
|
379
|
+
folder: "./public"
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### 2. Order of Plugins Matters
|
|
383
|
+
|
|
384
|
+
Register API handlers before static file plugins to avoid conflicts:
|
|
385
|
+
|
|
386
|
+
```typescript
|
|
387
|
+
new FlinkApp<Ctx>({
|
|
388
|
+
name: "My app",
|
|
389
|
+
plugins: [
|
|
390
|
+
apiDocsPlugin({ path: "/docs" }), // API endpoints first
|
|
391
|
+
staticFilesPlugin({ path: "/" }) // Static files last
|
|
392
|
+
]
|
|
393
|
+
})
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
If static files are registered first, they might intercept API routes.
|
|
397
|
+
|
|
398
|
+
### 3. Use Subdirectories for Assets
|
|
399
|
+
|
|
400
|
+
Avoid serving from root in production:
|
|
401
|
+
|
|
402
|
+
```typescript
|
|
403
|
+
// Development - convenient
|
|
404
|
+
staticFilesPlugin({
|
|
405
|
+
path: "/",
|
|
406
|
+
folder: join(__dirname, "public")
|
|
407
|
+
})
|
|
408
|
+
|
|
409
|
+
// Production - better organization
|
|
410
|
+
staticFilesPlugin({
|
|
411
|
+
path: "/static",
|
|
412
|
+
folder: join(__dirname, "public")
|
|
413
|
+
})
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### 4. Security Considerations
|
|
417
|
+
|
|
418
|
+
- **Never serve sensitive files**: Don't put `.env`, config files, or database files in the static directory
|
|
419
|
+
- **Use proper permissions**: Ensure the static files directory has appropriate read permissions
|
|
420
|
+
- **Validate file paths**: The plugin uses Express's built-in static middleware which has path traversal protection
|
|
421
|
+
|
|
422
|
+
### 5. Performance Optimization
|
|
423
|
+
|
|
424
|
+
For production, consider:
|
|
425
|
+
- Using a CDN for static assets
|
|
426
|
+
- Setting up Nginx/Apache as a reverse proxy to serve static files
|
|
427
|
+
- Enabling gzip/brotli compression at the web server level
|
|
428
|
+
- Using `express.static` options for cache headers
|
|
429
|
+
|
|
430
|
+
## Common Issues
|
|
431
|
+
|
|
432
|
+
### Files Not Loading
|
|
433
|
+
|
|
434
|
+
1. **Check file path:**
|
|
435
|
+
```typescript
|
|
436
|
+
console.log(join(__dirname, "public"));
|
|
437
|
+
// Verify this path exists
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
2. **Verify files were copied:**
|
|
441
|
+
```bash
|
|
442
|
+
ls dist/src/public/
|
|
443
|
+
# Should show your static files
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
3. **Check URL path:**
|
|
447
|
+
```typescript
|
|
448
|
+
// If path is "/assets"
|
|
449
|
+
staticFilesPlugin({ path: "/assets", folder: "..." })
|
|
450
|
+
// Access at: http://localhost:3000/assets/file.html
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
### 404 Errors
|
|
454
|
+
|
|
455
|
+
1. **Case sensitivity**: File paths are case-sensitive on Linux/Mac
|
|
456
|
+
- `index.HTML` ≠ `index.html`
|
|
457
|
+
|
|
458
|
+
2. **Path matching**: Ensure URL path matches configured path
|
|
459
|
+
```typescript
|
|
460
|
+
// With path: "/static"
|
|
461
|
+
// ✓ http://localhost:3000/static/app.js
|
|
462
|
+
// ✗ http://localhost:3000/app.js
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
### Files Not Updating
|
|
466
|
+
|
|
467
|
+
1. **Clear browser cache**: Hard refresh (Ctrl+Shift+R / Cmd+Shift+R)
|
|
468
|
+
|
|
469
|
+
2. **Restart the server**: Changes to static files require restart unless using hot reload
|
|
470
|
+
|
|
471
|
+
3. **Re-run copy script**: If files are in `src/`, make sure they're copied to `dist/`
|
|
472
|
+
```bash
|
|
473
|
+
npm run copy-files
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
### MIME Type Issues
|
|
477
|
+
|
|
478
|
+
Express automatically sets correct MIME types. If you encounter issues:
|
|
479
|
+
|
|
480
|
+
```typescript
|
|
481
|
+
import express from "express";
|
|
482
|
+
import { join } from "path";
|
|
483
|
+
|
|
484
|
+
app.expressApp?.use("/", express.static(join(__dirname, "public"), {
|
|
485
|
+
setHeaders: (res, path) => {
|
|
486
|
+
if (path.endsWith(".js")) {
|
|
487
|
+
res.setHeader("Content-Type", "application/javascript");
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}));
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
## API Reference
|
|
494
|
+
|
|
495
|
+
### Plugin Options
|
|
496
|
+
|
|
497
|
+
```typescript
|
|
498
|
+
interface StaticOptions {
|
|
499
|
+
path: string; // Base URL path (must start with "/")
|
|
500
|
+
folder: string; // Absolute filesystem path to static files directory
|
|
501
|
+
}
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
### Plugin Function
|
|
505
|
+
|
|
506
|
+
```typescript
|
|
507
|
+
function staticFilesPlugin(options: StaticOptions): FlinkPlugin
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
**Returns:** A Flink plugin that registers Express static middleware.
|
|
511
|
+
|
|
512
|
+
**Logs:** When initialized, logs: `"Registered static file route {path}"`
|
|
513
|
+
|
|
514
|
+
## Notes
|
|
515
|
+
|
|
516
|
+
- The plugin uses Express's `express.static` middleware internally
|
|
517
|
+
- Files are served with appropriate MIME types automatically
|
|
518
|
+
- Directory listings are not enabled by default (returns 404 for directories)
|
|
519
|
+
- The plugin does not add any context to `ctx.plugins`
|
|
520
|
+
- Multiple instances can be registered for different paths
|
|
521
|
+
- The `folder` path should be absolute (use `join(__dirname, ...)`)
|
|
522
|
+
- Static files are served with default cache headers (can be customized via Express static options)
|
package/src/index.ts
CHANGED
|
@@ -1,37 +1,35 @@
|
|
|
1
1
|
import { FlinkApp, FlinkPlugin } from "@flink-app/flink";
|
|
2
|
-
import express from "express";
|
|
3
2
|
import log from "node-color-log";
|
|
4
3
|
|
|
5
4
|
export type StaticOptions = {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Base url
|
|
7
|
+
*/
|
|
8
|
+
path: string;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Path of template files
|
|
12
|
+
*/
|
|
13
|
+
folder: string;
|
|
16
14
|
};
|
|
17
15
|
|
|
18
16
|
export const staticFilesPlugin = (options: StaticOptions): FlinkPlugin => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
return {
|
|
18
|
+
id: "staticFiles",
|
|
19
|
+
init: (app) => init(app, options),
|
|
20
|
+
};
|
|
23
21
|
};
|
|
24
22
|
|
|
25
23
|
function init(app: FlinkApp<any>, options: StaticOptions) {
|
|
24
|
+
const { expressApp } = app;
|
|
26
25
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
throw new Error("Express app not initialized");
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
log.info(`Registered static file route ${options.path}`);
|
|
26
|
+
if (!expressApp) {
|
|
27
|
+
throw new Error("Express app not initialized");
|
|
28
|
+
}
|
|
34
29
|
|
|
35
|
-
|
|
30
|
+
log.info(`Registered static file route ${options.path}`);
|
|
36
31
|
|
|
32
|
+
// Access express.static through the Express constructor
|
|
33
|
+
const express = (expressApp as any).constructor;
|
|
34
|
+
expressApp.use(options.path, express.static(options.folder));
|
|
37
35
|
}
|