@editframe/vite-plugin 0.6.0-beta.9 → 0.7.0-beta.4

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.
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const forbidRelativePaths = (req) => {
4
+ if (req.url?.includes("..")) {
5
+ throw new Error("Relative paths are forbidden");
6
+ }
7
+ };
8
+ exports.forbidRelativePaths = forbidRelativePaths;
@@ -0,0 +1,8 @@
1
+ const forbidRelativePaths = (req) => {
2
+ if (req.url?.includes("..")) {
3
+ throw new Error("Relative paths are forbidden");
4
+ }
5
+ };
6
+ export {
7
+ forbidRelativePaths
8
+ };
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const path = require("node:path");
4
+ const debug = require("debug");
5
+ const assets = require("@editframe/assets");
6
+ const forbidRelativePaths = require("./forbidRelativePaths.cjs");
7
+ const sendTaskResult = require("./sendTaskResult.cjs");
8
+ const vitePluginEditframe = (options) => {
9
+ return {
10
+ name: "vite-plugin-editframe",
11
+ configureServer(server) {
12
+ server.middlewares.use(async (req, res, next) => {
13
+ const log = debug("ef:vite-plugin");
14
+ if (req.url?.startsWith("/@ef")) {
15
+ forbidRelativePaths.forbidRelativePaths(req);
16
+ } else {
17
+ return next();
18
+ }
19
+ log(`Handling ${req.url}`);
20
+ const requestPath = req.url.replace(/^\/@ef-[^\/]+\//, "");
21
+ const assetPath = requestPath.replace(/\?.*$/, "");
22
+ const absolutePath = path.join(options.root, assetPath).replace("dist/", "src/");
23
+ options.cacheRoot = options.cacheRoot.replace("dist/", "src/");
24
+ const efPrefix = req.url.split("/")[1];
25
+ switch (efPrefix) {
26
+ case "@ef-asset": {
27
+ if (req.method !== "HEAD") {
28
+ res.writeHead(405, { Allow: "HEAD" });
29
+ res.end();
30
+ }
31
+ assets.md5FilePath(absolutePath).then((md5) => {
32
+ res.writeHead(200, {
33
+ etag: md5
34
+ });
35
+ res.end();
36
+ }).catch(next);
37
+ break;
38
+ }
39
+ case "@ef-track-fragment-index": {
40
+ log(`Serving track fragment index for ${absolutePath}`);
41
+ assets.generateTrackFragmentIndex(options.cacheRoot, absolutePath).then((taskResult) => sendTaskResult.sendTaskResult(req, res, taskResult)).catch(next);
42
+ break;
43
+ }
44
+ case "@ef-track": {
45
+ log(`Serving track for ${absolutePath}`);
46
+ assets.generateTrack(options.cacheRoot, absolutePath, req.url).then((taskResult) => sendTaskResult.sendTaskResult(req, res, taskResult)).catch(next);
47
+ break;
48
+ }
49
+ case "@ef-captions":
50
+ log(`Serving captions for ${absolutePath}`);
51
+ assets.findOrCreateCaptions(options.cacheRoot, absolutePath).then((taskResult) => sendTaskResult.sendTaskResult(req, res, taskResult)).catch(next);
52
+ break;
53
+ case "@ef-image":
54
+ log(`Serving image file ${absolutePath}`);
55
+ assets.cacheImage(options.cacheRoot, absolutePath).then((taskResult) => sendTaskResult.sendTaskResult(req, res, taskResult)).catch(next);
56
+ break;
57
+ default:
58
+ log(`Unknown asset type ${efPrefix}`);
59
+ break;
60
+ }
61
+ });
62
+ }
63
+ };
64
+ };
65
+ exports.vitePluginEditframe = vitePluginEditframe;
@@ -0,0 +1,65 @@
1
+ import path from "node:path";
2
+ import debug from "debug";
3
+ import { cacheImage, findOrCreateCaptions, generateTrack, generateTrackFragmentIndex, md5FilePath } from "@editframe/assets";
4
+ import { forbidRelativePaths } from "./forbidRelativePaths.js";
5
+ import { sendTaskResult } from "./sendTaskResult.js";
6
+ const vitePluginEditframe = (options) => {
7
+ return {
8
+ name: "vite-plugin-editframe",
9
+ configureServer(server) {
10
+ server.middlewares.use(async (req, res, next) => {
11
+ const log = debug("ef:vite-plugin");
12
+ if (req.url?.startsWith("/@ef")) {
13
+ forbidRelativePaths(req);
14
+ } else {
15
+ return next();
16
+ }
17
+ log(`Handling ${req.url}`);
18
+ const requestPath = req.url.replace(/^\/@ef-[^\/]+\//, "");
19
+ const assetPath = requestPath.replace(/\?.*$/, "");
20
+ const absolutePath = path.join(options.root, assetPath).replace("dist/", "src/");
21
+ options.cacheRoot = options.cacheRoot.replace("dist/", "src/");
22
+ const efPrefix = req.url.split("/")[1];
23
+ switch (efPrefix) {
24
+ case "@ef-asset": {
25
+ if (req.method !== "HEAD") {
26
+ res.writeHead(405, { Allow: "HEAD" });
27
+ res.end();
28
+ }
29
+ md5FilePath(absolutePath).then((md5) => {
30
+ res.writeHead(200, {
31
+ etag: md5
32
+ });
33
+ res.end();
34
+ }).catch(next);
35
+ break;
36
+ }
37
+ case "@ef-track-fragment-index": {
38
+ log(`Serving track fragment index for ${absolutePath}`);
39
+ generateTrackFragmentIndex(options.cacheRoot, absolutePath).then((taskResult) => sendTaskResult(req, res, taskResult)).catch(next);
40
+ break;
41
+ }
42
+ case "@ef-track": {
43
+ log(`Serving track for ${absolutePath}`);
44
+ generateTrack(options.cacheRoot, absolutePath, req.url).then((taskResult) => sendTaskResult(req, res, taskResult)).catch(next);
45
+ break;
46
+ }
47
+ case "@ef-captions":
48
+ log(`Serving captions for ${absolutePath}`);
49
+ findOrCreateCaptions(options.cacheRoot, absolutePath).then((taskResult) => sendTaskResult(req, res, taskResult)).catch(next);
50
+ break;
51
+ case "@ef-image":
52
+ log(`Serving image file ${absolutePath}`);
53
+ cacheImage(options.cacheRoot, absolutePath).then((taskResult) => sendTaskResult(req, res, taskResult)).catch(next);
54
+ break;
55
+ default:
56
+ log(`Unknown asset type ${efPrefix}`);
57
+ break;
58
+ }
59
+ });
60
+ }
61
+ };
62
+ };
63
+ export {
64
+ vitePluginEditframe
65
+ };
@@ -0,0 +1,3 @@
1
+ import { IncomingMessage } from 'connect';
2
+
3
+ export declare const forbidRelativePaths: (req: IncomingMessage) => void;
@@ -0,0 +1,9 @@
1
+ interface VitePluginEditframeOptions {
2
+ root: string;
3
+ cacheRoot: string;
4
+ }
5
+ export declare const vitePluginEditframe: (options: VitePluginEditframeOptions) => {
6
+ name: string;
7
+ configureServer(this: void, server: import('vite').ViteDevServer): void;
8
+ };
9
+ export {};
@@ -0,0 +1,5 @@
1
+ import { ServerResponse } from 'node:http';
2
+ import { IncomingMessage } from 'connect';
3
+ import { TaskResult } from '../../assets/src';
4
+
5
+ export declare const sendTaskResult: (req: IncomingMessage, res: ServerResponse<IncomingMessage>, taskResult: TaskResult) => ServerResponse<IncomingMessage> | undefined;
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const node_fs = require("node:fs");
4
+ const mime = require("mime");
5
+ const debug = require("debug");
6
+ const sendTaskResult = (req, res, taskResult) => {
7
+ const { cachePath, md5Sum } = taskResult;
8
+ const filePath = cachePath;
9
+ const headers = {
10
+ etag: md5Sum
11
+ };
12
+ const log = debug("ef:sendfile");
13
+ try {
14
+ log(`Sending file ${filePath}`);
15
+ const stats = node_fs.statSync(filePath);
16
+ if (req.headers.range) {
17
+ const [x, y] = req.headers.range.replace("bytes=", "").split("-");
18
+ let end = Number.parseInt(y ?? "0", 10) || stats.size - 1;
19
+ const start = Number.parseInt(x ?? "0", 10) || 0;
20
+ if (end >= stats.size) {
21
+ end = stats.size - 1;
22
+ }
23
+ if (start >= stats.size) {
24
+ log("Range start is greater than file size");
25
+ res.setHeader("Content-Range", `bytes */${stats.size}`);
26
+ res.statusCode = 416;
27
+ return res.end();
28
+ }
29
+ res.writeHead(206, {
30
+ ...headers,
31
+ "Content-Type": mime.getType(filePath) || "text/plain",
32
+ "Cache-Control": "max-age=3600",
33
+ "Content-Range": `bytes ${start}-${end}/${stats.size}`,
34
+ "Content-Length": end - start + 1,
35
+ "Accept-Ranges": "bytes"
36
+ });
37
+ log(`Sending ${filePath} range ${start}-${end}/${stats.size}`);
38
+ const readStream = node_fs.createReadStream(filePath, { start, end });
39
+ readStream.pipe(res);
40
+ } else {
41
+ res.writeHead(200, {
42
+ ...headers,
43
+ "Content-Type": mime.getType(filePath) || "text/plain",
44
+ "Cache-Control": "max-age=3600",
45
+ "Contetn-Length": stats.size
46
+ });
47
+ log(`Sending ${filePath}`);
48
+ const readStream = node_fs.createReadStream(filePath);
49
+ readStream.pipe(res);
50
+ }
51
+ } catch (error) {
52
+ log("Error sending file", error);
53
+ console.error(error);
54
+ }
55
+ };
56
+ exports.sendTaskResult = sendTaskResult;
@@ -0,0 +1,56 @@
1
+ import { statSync, createReadStream } from "node:fs";
2
+ import mime from "mime";
3
+ import debug from "debug";
4
+ const sendTaskResult = (req, res, taskResult) => {
5
+ const { cachePath, md5Sum } = taskResult;
6
+ const filePath = cachePath;
7
+ const headers = {
8
+ etag: md5Sum
9
+ };
10
+ const log = debug("ef:sendfile");
11
+ try {
12
+ log(`Sending file ${filePath}`);
13
+ const stats = statSync(filePath);
14
+ if (req.headers.range) {
15
+ const [x, y] = req.headers.range.replace("bytes=", "").split("-");
16
+ let end = Number.parseInt(y ?? "0", 10) || stats.size - 1;
17
+ const start = Number.parseInt(x ?? "0", 10) || 0;
18
+ if (end >= stats.size) {
19
+ end = stats.size - 1;
20
+ }
21
+ if (start >= stats.size) {
22
+ log("Range start is greater than file size");
23
+ res.setHeader("Content-Range", `bytes */${stats.size}`);
24
+ res.statusCode = 416;
25
+ return res.end();
26
+ }
27
+ res.writeHead(206, {
28
+ ...headers,
29
+ "Content-Type": mime.getType(filePath) || "text/plain",
30
+ "Cache-Control": "max-age=3600",
31
+ "Content-Range": `bytes ${start}-${end}/${stats.size}`,
32
+ "Content-Length": end - start + 1,
33
+ "Accept-Ranges": "bytes"
34
+ });
35
+ log(`Sending ${filePath} range ${start}-${end}/${stats.size}`);
36
+ const readStream = createReadStream(filePath, { start, end });
37
+ readStream.pipe(res);
38
+ } else {
39
+ res.writeHead(200, {
40
+ ...headers,
41
+ "Content-Type": mime.getType(filePath) || "text/plain",
42
+ "Cache-Control": "max-age=3600",
43
+ "Contetn-Length": stats.size
44
+ });
45
+ log(`Sending ${filePath}`);
46
+ const readStream = createReadStream(filePath);
47
+ readStream.pipe(res);
48
+ }
49
+ } catch (error) {
50
+ log("Error sending file", error);
51
+ console.error(error);
52
+ }
53
+ };
54
+ export {
55
+ sendTaskResult
56
+ };
package/package.json CHANGED
@@ -1,14 +1,19 @@
1
1
  {
2
2
  "name": "@editframe/vite-plugin",
3
- "version": "0.6.0-beta.9",
3
+ "version": "0.7.0-beta.4",
4
4
  "description": "Editframe vite plugin",
5
5
  "exports": {
6
6
  ".": {
7
- "import": "./dist/packages/vite-plugin/index.js",
8
- "require": "./dist/packages/vite-plugin/index.cjs"
7
+ "import": {
8
+ "default": "./dist/packages/vite-plugin/index.js",
9
+ "types": "./dist/packages/vite-plugin/index.d.ts"
10
+ },
11
+ "require": {
12
+ "default": "./dist/packages/vite-plugin/index.cjs",
13
+ "types": "./dist/packages/vite-plugin/index.d.ts"
14
+ }
9
15
  }
10
16
  },
11
- "types": "./dist/packages/vite-plugin/index.d.ts",
12
17
  "scripts": {
13
18
  "typecheck": "tsc --noEmit --emitDeclarationOnly false",
14
19
  "build": "vite build",
@@ -18,8 +23,8 @@
18
23
  "author": "",
19
24
  "license": "UNLICENSED",
20
25
  "dependencies": {
21
- "@editframe/assets": "0.6.0-beta.9",
22
- "debug": "^4.3.4",
26
+ "@editframe/assets": "0.7.0-beta.4",
27
+ "debug": "^4.3.5",
23
28
  "mime": "^4.0.3",
24
29
  "node-html-parser": "^6.1.13",
25
30
  "vite": "^5.2.11"