UNPKG

5.23 kBJavaScriptView Raw
1import fs from 'fs';
2import { dirname, resolve, isAbsolute, join } from 'path';
3import { promisify } from 'util';
4import { fileURLToPath } from 'url';
5
6const copyFile = promisify(fs.copyFile);
7const mkdir = promisify(fs.mkdir);
8const readdir = promisify(fs.readdir);
9const readFile = promisify(fs.readFile);
10const stat = promisify(fs.stat);
11const __dirname = dirname(fileURLToPath(import.meta.url));
12
13/**
14 * Absolute path to the Partytown lib directory within the
15 * `@builder.io/partytown` package.
16 *
17 * https://partytown.builder.io/copy-library-files
18 *
19 * @public
20 */
21function libDirPath(opts) {
22 if (opts && opts.debugDir) {
23 return resolve(__dirname, '..', 'lib', 'debug');
24 }
25 return resolve(__dirname, '..', 'lib');
26}
27/**
28 * Utility to copy the Partytown library files to a destination on the server.
29 * Partytown requires its library files, such as `partytown.js` to be served
30 * as static files from the same origin. By default the library assumes all the
31 * files can be found at `/~partytown/`, but this can be configured.
32 *
33 * This utility function is to make it easier to locate the source library files
34 * and copy them to your server's correct location, for example: `./public/~partytown/`.
35 *
36 * By default, both the production and debug builds are copied to the destination.
37 * However, by setting the `debugDir` option to `false`, the debug directory will
38 * not be copied.
39 *
40 * https://partytown.builder.io/copy-library-files
41 *
42 * @public
43 */
44async function copyLibFiles(dest, opts) {
45 opts = opts || {};
46 if (typeof dest !== 'string' || dest.length === 0) {
47 throw new Error('Missing destination directory');
48 }
49 if (!isAbsolute(dest)) {
50 dest = resolve(process.cwd(), dest);
51 }
52 const src = libDirPath();
53 await copyLibDir(src, dest, opts);
54 return { src, dest };
55}
56async function copyLibDir(srcDir, destDir, opts) {
57 try {
58 await mkdir(destDir, { recursive: true });
59 }
60 catch (e) { }
61 const itemNames = await readdir(srcDir);
62 await Promise.all(itemNames.map(async (srcName) => {
63 if (srcName === 'debug' && opts.debugDir === false) {
64 return;
65 }
66 const srcPath = resolve(srcDir, srcName);
67 const destPath = resolve(destDir, srcName);
68 const s = await stat(srcPath);
69 if (s.isFile()) {
70 await copyFile(srcPath, destPath);
71 }
72 else if (s.isDirectory()) {
73 await copyLibDir(srcPath, destPath, opts);
74 }
75 }));
76}
77
78/**
79 * The Rollup plugin will copy Partytown `lib` directory to the given destination,
80 * which must be an absolute file path.
81 *
82 * https://partytown.builder.io/copy-library-files
83 *
84 * @public
85 */
86function partytownRollup(opts) {
87 opts = opts || {};
88 if (typeof opts.dest !== 'string' || opts.dest.length === 0) {
89 throw new Error(`Partytown plugin must have "dest" property.`);
90 }
91 if (!isAbsolute(opts.dest)) {
92 throw new Error(`Partytown plugin "dest" property must be an absolute path.`);
93 }
94 let hasCopied = false;
95 const plugin = {
96 name: 'rollup-plugin-partytown',
97 async writeBundle() {
98 if (!hasCopied) {
99 await copyLibFiles(opts.dest, { debugDir: opts.debug });
100 hasCopied = true;
101 }
102 },
103 };
104 return plugin;
105}
106
107/**
108 * The Vite plugin will copy Partytown `lib` directory to the given destination,
109 * which must be an absolute file path. When in dev mode, the Partytown
110 * lib files will be served using the Vite Dev Server.
111 *
112 * https://partytown.builder.io/copy-library-files
113 *
114 * @public
115 */
116function partytownVite(opts) {
117 opts = opts || {};
118 const plugin = partytownRollup(opts);
119 plugin.name = 'vite-plugin-partytown';
120 plugin.configureServer = (server) => {
121 if (server) {
122 server.middlewares.use(async (req, res, next) => {
123 var _a;
124 try {
125 const url = (_a = req.url) !== null && _a !== void 0 ? _a : '';
126 // drop query
127 const [pathname] = url.split('?');
128 if (pathname.includes('partytown') && !pathname.includes('.vite')) {
129 const fileName = pathname.split('/').pop();
130 if (fileName && fileName.endsWith('.js')) {
131 const libDir = libDirPath({ debugDir: pathname.includes('/debug/') });
132 const filePath = join(libDir, fileName);
133 const buf = await readFile(filePath);
134 res.writeHead(200, {
135 'Content-Type': 'application/javascript; charset=utf-8',
136 'X-Vite-Dev-Sever-Partytown': ':tada:',
137 });
138 res.end(buf);
139 return;
140 }
141 }
142 }
143 catch (e) {
144 console.error(`partytownVite.configureServer`, e);
145 }
146 next();
147 });
148 }
149 };
150 return plugin;
151}
152
153export { copyLibFiles, libDirPath, partytownRollup, partytownVite };