@netlify/vite-plugin 0.2.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/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # @netlify/vite-plugin
2
+
3
+ > [!WARNING] This is an experimental Vite plugin for Netlify. It is under active development and does **not** yet support all Netlify platform features.
4
+
5
+ A Vite plugin that integrates with Netlify's platform features.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @netlify/vite-plugin
11
+ ```
12
+
13
+ ## Configuration options
14
+
15
+ The plugin accepts the following options:
16
+
17
+ - `middleware` (boolean, default: `true`): Attach a Vite middleware that intercepts requests and handles them in the same way as the Netlify production environment
18
+ - `blobs`: Configure blob storage functionality
19
+ - `functions`: Configure serverless functions
20
+ - `redirects`: Configure URL redirects
21
+ - `staticFiles`: Configure static file serving
22
+
23
+ ## Usage
24
+
25
+ Add the plugin to your `vite.config.js` or `vite.config.ts`:
26
+
27
+ ```js
28
+ import { defineConfig } from 'vite'
29
+ import netlify from '@netlify/vite-plugin'
30
+
31
+ export default defineConfig({
32
+ plugins: [netlify()]
33
+ })
34
+ ```
package/dist/main.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ import { Features } from '@netlify/dev';
2
+
3
+ interface NetlifyPluginOptions extends Features {
4
+ /**
5
+ * Attach a Vite middleware that intercepts requests and handles them in the
6
+ * same way as the Netlify production environment.
7
+ */
8
+ middleware?: boolean;
9
+ }
10
+ declare function netlify(options?: NetlifyPluginOptions): any;
11
+
12
+ export { type NetlifyPluginOptions, netlify };
package/dist/main.js ADDED
@@ -0,0 +1,100 @@
1
+ // src/main.ts
2
+ import { NetlifyDev } from "@netlify/dev";
3
+
4
+ // src/lib/logger.ts
5
+ import chalk from "chalk";
6
+ var NETLIFY_CYAN = chalk.rgb(40, 180, 170);
7
+ var banner = NETLIFY_CYAN("\u25C8 Netlify \u25C8");
8
+ var logger = {
9
+ error: (...data) => data.length === 0 ? console.error(...data) : console.error(banner, ...data),
10
+ log: (...data) => data.length === 0 ? console.log(...data) : console.log(banner, ...data),
11
+ warn: (...data) => data.length === 0 ? console.warn(...data) : console.warn(banner, ...data)
12
+ };
13
+
14
+ // src/lib/reqres.ts
15
+ import { Readable } from "node:stream";
16
+ var normalizeHeaders = (headers) => {
17
+ const result = [];
18
+ for (const [key, value] of Object.entries(headers)) {
19
+ if (Array.isArray(value)) {
20
+ result.push([key, value.join(",")]);
21
+ } else if (typeof value === "string") {
22
+ result.push([key, value]);
23
+ }
24
+ }
25
+ return result;
26
+ };
27
+ var toWebRequest = (nodeReq, urlPath) => {
28
+ const { method, headers, url = "" } = nodeReq;
29
+ const ac = new AbortController();
30
+ const origin = `http://${headers.host}`;
31
+ const fullUrl = new URL(urlPath ?? url, origin);
32
+ const webStream = Readable.toWeb(nodeReq);
33
+ nodeReq.once("aborted", () => ac.abort());
34
+ return new Request(fullUrl.href, {
35
+ method,
36
+ headers: normalizeHeaders(headers),
37
+ body: method === "GET" || method === "HEAD" ? null : webStream,
38
+ // @ts-expect-error Not typed
39
+ duplex: "half"
40
+ });
41
+ };
42
+ var fromWebResponse = async (webRes, res) => {
43
+ res.statusCode = webRes.status;
44
+ webRes.headers.forEach((value, name) => {
45
+ res.setHeader(name, value);
46
+ });
47
+ if (webRes.body) {
48
+ const reader = webRes.body.getReader();
49
+ const writer = res;
50
+ while (true) {
51
+ const { done, value } = await reader.read();
52
+ if (done) {
53
+ break;
54
+ }
55
+ writer.write(value);
56
+ }
57
+ }
58
+ res.end();
59
+ };
60
+
61
+ // src/main.ts
62
+ function netlify(options = {}) {
63
+ const plugin = {
64
+ name: "vite-plugin-netlify",
65
+ async configureServer(viteDevServer) {
66
+ const { blobs, functions, middleware = true, redirects, staticFiles } = options;
67
+ const netlifyDev = new NetlifyDev({
68
+ blobs,
69
+ functions,
70
+ logger,
71
+ redirects,
72
+ staticFiles,
73
+ projectRoot: viteDevServer.config.root
74
+ });
75
+ await netlifyDev.start();
76
+ if (!netlifyDev.siteIsLinked) {
77
+ logger.log(
78
+ "Your project is not linked to a Netlify site. Refer to https://ntl.fyi/vite-link for more information."
79
+ );
80
+ }
81
+ if (middleware) {
82
+ return () => {
83
+ viteDevServer.middlewares.use(async (nodeReq, nodeRes, next) => {
84
+ const req = toWebRequest(nodeReq, nodeReq.originalUrl);
85
+ const res = await netlifyDev.handle(req);
86
+ if (res) {
87
+ fromWebResponse(res, nodeRes);
88
+ } else {
89
+ next();
90
+ }
91
+ });
92
+ };
93
+ }
94
+ }
95
+ };
96
+ return [plugin];
97
+ }
98
+ export {
99
+ netlify
100
+ };
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@netlify/vite-plugin",
3
+ "version": "0.2.0",
4
+ "description": "Netlify Vite plugin",
5
+ "type": "module",
6
+ "engines": {
7
+ "node": ">=16.0.0"
8
+ },
9
+ "main": "./dist/main.js",
10
+ "types": "./dist/main.d.ts",
11
+ "files": [
12
+ "dist/**/*"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsup-node",
16
+ "prepack": "npm run build",
17
+ "test": "vitest run",
18
+ "test:dev": "vitest",
19
+ "test:ci": "npm run build && vitest run",
20
+ "dev": "tsup-node --watch"
21
+ },
22
+ "keywords": [],
23
+ "license": "MIT",
24
+ "repository": "netlify/primitives",
25
+ "bugs": {
26
+ "url": "https://github.com/netlify/primitives/issues"
27
+ },
28
+ "author": "Netlify Inc.",
29
+ "devDependencies": {
30
+ "@types/node": "^22.14.1",
31
+ "tsup": "^8.0.0",
32
+ "vite": "^6.3.4",
33
+ "vitest": "^3.0.0"
34
+ },
35
+ "dependencies": {
36
+ "@netlify/dev": "2.1.0",
37
+ "chalk": "^5.4.1"
38
+ },
39
+ "peerDependencies": {
40
+ "vite": "^6.2"
41
+ }
42
+ }