almostnode 0.1.0 → 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 +163 -1
- package/dist/index.cjs +70 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +52 -9
- package/dist/index.mjs.map +1 -1
- package/dist/next-plugin.cjs +56 -0
- package/dist/next-plugin.cjs.map +1 -0
- package/dist/next-plugin.d.ts +62 -0
- package/dist/next-plugin.d.ts.map +1 -0
- package/dist/next-plugin.mjs +30 -0
- package/dist/next-plugin.mjs.map +1 -0
- package/dist/sandbox-helpers.d.ts +29 -6
- package/dist/sandbox-helpers.d.ts.map +1 -1
- package/dist/server-bridge.d.ts +10 -1
- package/dist/server-bridge.d.ts.map +1 -1
- package/dist/vite-plugin.cjs +56 -0
- package/dist/vite-plugin.cjs.map +1 -0
- package/dist/vite-plugin.d.ts +36 -0
- package/dist/vite-plugin.d.ts.map +1 -0
- package/dist/vite-plugin.mjs +30 -0
- package/dist/vite-plugin.mjs.map +1 -0
- package/package.json +21 -1
- package/src/frameworks/next-dev-server.ts +2 -2
- package/src/index.ts +1 -0
- package/src/next-plugin.ts +96 -0
- package/src/sandbox-helpers.ts +101 -9
- package/src/server-bridge.ts +14 -2
- package/src/vite-plugin.ts +76 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const url = require('url');
|
|
8
|
+
|
|
9
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
10
|
+
function _interopNamespaceDefault(e) {
|
|
11
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } });
|
|
12
|
+
if (e) {
|
|
13
|
+
for (const k in e) {
|
|
14
|
+
if (k !== 'default') {
|
|
15
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
16
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
get: () => e[k]
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
n.default = e;
|
|
24
|
+
return Object.freeze(n);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
|
|
28
|
+
const path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
|
|
29
|
+
|
|
30
|
+
const __dirname$1 = path__namespace.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('next-plugin.cjs', document.baseURI).href))));
|
|
31
|
+
function getServiceWorkerContent() {
|
|
32
|
+
let swFilePath = path__namespace.join(__dirname$1, "__sw__.js");
|
|
33
|
+
if (!fs__namespace.existsSync(swFilePath)) {
|
|
34
|
+
swFilePath = path__namespace.join(__dirname$1, "../dist/__sw__.js");
|
|
35
|
+
}
|
|
36
|
+
if (!fs__namespace.existsSync(swFilePath)) {
|
|
37
|
+
throw new Error("Service worker file not found. Make sure almostnode is built.");
|
|
38
|
+
}
|
|
39
|
+
return fs__namespace.readFileSync(swFilePath, "utf-8");
|
|
40
|
+
}
|
|
41
|
+
function getServiceWorkerPath() {
|
|
42
|
+
let swFilePath = path__namespace.join(__dirname$1, "__sw__.js");
|
|
43
|
+
if (!fs__namespace.existsSync(swFilePath)) {
|
|
44
|
+
swFilePath = path__namespace.join(__dirname$1, "../dist/__sw__.js");
|
|
45
|
+
}
|
|
46
|
+
if (!fs__namespace.existsSync(swFilePath)) {
|
|
47
|
+
throw new Error("Service worker file not found. Make sure almostnode is built.");
|
|
48
|
+
}
|
|
49
|
+
return swFilePath;
|
|
50
|
+
}
|
|
51
|
+
const nextPlugin = { getServiceWorkerContent, getServiceWorkerPath };
|
|
52
|
+
|
|
53
|
+
exports.default = nextPlugin;
|
|
54
|
+
exports.getServiceWorkerContent = getServiceWorkerContent;
|
|
55
|
+
exports.getServiceWorkerPath = getServiceWorkerPath;
|
|
56
|
+
//# sourceMappingURL=next-plugin.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"next-plugin.cjs","sources":["../src/next-plugin.ts"],"sourcesContent":["/**\n * Next.js Plugin for almostnode\n *\n * Provides utilities for serving the service worker file in Next.js applications.\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { fileURLToPath } from 'url';\n\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore - import.meta.url is available in ESM\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\n/**\n * Get the contents of the almostnode service worker file.\n * Use this in a Next.js API route or middleware to serve the service worker.\n *\n * @example\n * ```typescript\n * // app/api/__sw__/route.ts (App Router)\n * import { getServiceWorkerContent } from 'almostnode/next';\n *\n * export async function GET() {\n * const content = getServiceWorkerContent();\n * return new Response(content, {\n * headers: {\n * 'Content-Type': 'application/javascript',\n * 'Cache-Control': 'no-cache',\n * },\n * });\n * }\n * ```\n *\n * @example\n * ```typescript\n * // pages/api/__sw__.ts (Pages Router)\n * import { getServiceWorkerContent } from 'almostnode/next';\n * import type { NextApiRequest, NextApiResponse } from 'next';\n *\n * export default function handler(req: NextApiRequest, res: NextApiResponse) {\n * const content = getServiceWorkerContent();\n * res.setHeader('Content-Type', 'application/javascript');\n * res.setHeader('Cache-Control', 'no-cache');\n * res.send(content);\n * }\n * ```\n */\nexport function getServiceWorkerContent(): string {\n // The service worker file is in the dist directory relative to this file\n // In src: ../dist/__sw__.js\n // In dist: ./__sw__.js\n let swFilePath = path.join(__dirname, '__sw__.js');\n\n // If running from src directory during development, look in dist\n if (!fs.existsSync(swFilePath)) {\n swFilePath = path.join(__dirname, '../dist/__sw__.js');\n }\n\n if (!fs.existsSync(swFilePath)) {\n throw new Error('Service worker file not found. Make sure almostnode is built.');\n }\n\n return fs.readFileSync(swFilePath, 'utf-8');\n}\n\n/**\n * Get the path to the almostnode service worker file.\n * Useful if you want to copy it to your public directory.\n *\n * @example\n * ```javascript\n * // scripts/copy-sw.js\n * const { getServiceWorkerPath } = require('almostnode/next');\n * const fs = require('fs');\n * const path = require('path');\n *\n * const swPath = getServiceWorkerPath();\n * fs.copyFileSync(swPath, path.join(__dirname, '../public/__sw__.js'));\n * ```\n */\nexport function getServiceWorkerPath(): string {\n let swFilePath = path.join(__dirname, '__sw__.js');\n\n if (!fs.existsSync(swFilePath)) {\n swFilePath = path.join(__dirname, '../dist/__sw__.js');\n }\n\n if (!fs.existsSync(swFilePath)) {\n throw new Error('Service worker file not found. Make sure almostnode is built.');\n }\n\n return swFilePath;\n}\n\nexport default { getServiceWorkerContent, getServiceWorkerPath };\n"],"names":["__dirname","path","fileURLToPath","fs"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,MAAMA,cAAYC,eAAA,CAAK,OAAA,CAAQC,iBAAA,CAAc,iQAAe,CAAC,CAAA;AAoCtD,SAAS,uBAAA,GAAkC;AAIhD,EAAA,IAAI,UAAA,GAAaD,eAAA,CAAK,IAAA,CAAKD,WAAA,EAAW,WAAW,CAAA;AAGjD,EAAA,IAAI,CAACG,aAAA,CAAG,UAAA,CAAW,UAAU,CAAA,EAAG;AAC9B,IAAA,UAAA,GAAaF,eAAA,CAAK,IAAA,CAAKD,WAAA,EAAW,mBAAmB,CAAA;AAAA,EACvD;AAEA,EAAA,IAAI,CAACG,aAAA,CAAG,UAAA,CAAW,UAAU,CAAA,EAAG;AAC9B,IAAA,MAAM,IAAI,MAAM,+DAA+D,CAAA;AAAA,EACjF;AAEA,EAAA,OAAOA,aAAA,CAAG,YAAA,CAAa,UAAA,EAAY,OAAO,CAAA;AAC5C;AAiBO,SAAS,oBAAA,GAA+B;AAC7C,EAAA,IAAI,UAAA,GAAaF,eAAA,CAAK,IAAA,CAAKD,WAAA,EAAW,WAAW,CAAA;AAEjD,EAAA,IAAI,CAACG,aAAA,CAAG,UAAA,CAAW,UAAU,CAAA,EAAG;AAC9B,IAAA,UAAA,GAAaF,eAAA,CAAK,IAAA,CAAKD,WAAA,EAAW,mBAAmB,CAAA;AAAA,EACvD;AAEA,EAAA,IAAI,CAACG,aAAA,CAAG,UAAA,CAAW,UAAU,CAAA,EAAG;AAC9B,IAAA,MAAM,IAAI,MAAM,+DAA+D,CAAA;AAAA,EACjF;AAEA,EAAA,OAAO,UAAA;AACT;AAEA,mBAAe,EAAE,yBAAyB,oBAAA,EAAqB;;;;;;"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Next.js Plugin for almostnode
|
|
3
|
+
*
|
|
4
|
+
* Provides utilities for serving the service worker file in Next.js applications.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Get the contents of the almostnode service worker file.
|
|
8
|
+
* Use this in a Next.js API route or middleware to serve the service worker.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* // app/api/__sw__/route.ts (App Router)
|
|
13
|
+
* import { getServiceWorkerContent } from 'almostnode/next';
|
|
14
|
+
*
|
|
15
|
+
* export async function GET() {
|
|
16
|
+
* const content = getServiceWorkerContent();
|
|
17
|
+
* return new Response(content, {
|
|
18
|
+
* headers: {
|
|
19
|
+
* 'Content-Type': 'application/javascript',
|
|
20
|
+
* 'Cache-Control': 'no-cache',
|
|
21
|
+
* },
|
|
22
|
+
* });
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* // pages/api/__sw__.ts (Pages Router)
|
|
29
|
+
* import { getServiceWorkerContent } from 'almostnode/next';
|
|
30
|
+
* import type { NextApiRequest, NextApiResponse } from 'next';
|
|
31
|
+
*
|
|
32
|
+
* export default function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
33
|
+
* const content = getServiceWorkerContent();
|
|
34
|
+
* res.setHeader('Content-Type', 'application/javascript');
|
|
35
|
+
* res.setHeader('Cache-Control', 'no-cache');
|
|
36
|
+
* res.send(content);
|
|
37
|
+
* }
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function getServiceWorkerContent(): string;
|
|
41
|
+
/**
|
|
42
|
+
* Get the path to the almostnode service worker file.
|
|
43
|
+
* Useful if you want to copy it to your public directory.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```javascript
|
|
47
|
+
* // scripts/copy-sw.js
|
|
48
|
+
* const { getServiceWorkerPath } = require('almostnode/next');
|
|
49
|
+
* const fs = require('fs');
|
|
50
|
+
* const path = require('path');
|
|
51
|
+
*
|
|
52
|
+
* const swPath = getServiceWorkerPath();
|
|
53
|
+
* fs.copyFileSync(swPath, path.join(__dirname, '../public/__sw__.js'));
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export declare function getServiceWorkerPath(): string;
|
|
57
|
+
declare const _default: {
|
|
58
|
+
getServiceWorkerContent: typeof getServiceWorkerContent;
|
|
59
|
+
getServiceWorkerPath: typeof getServiceWorkerPath;
|
|
60
|
+
};
|
|
61
|
+
export default _default;
|
|
62
|
+
//# sourceMappingURL=next-plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"next-plugin.d.ts","sourceRoot":"","sources":["../src/next-plugin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAUH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAgBhD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAY7C;;;;;AAED,wBAAiE"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
const __dirname$1 = path.dirname(fileURLToPath(import.meta.url));
|
|
5
|
+
function getServiceWorkerContent() {
|
|
6
|
+
let swFilePath = path.join(__dirname$1, "__sw__.js");
|
|
7
|
+
if (!fs.existsSync(swFilePath)) {
|
|
8
|
+
swFilePath = path.join(__dirname$1, "../dist/__sw__.js");
|
|
9
|
+
}
|
|
10
|
+
if (!fs.existsSync(swFilePath)) {
|
|
11
|
+
throw new Error("Service worker file not found. Make sure almostnode is built.");
|
|
12
|
+
}
|
|
13
|
+
return fs.readFileSync(swFilePath, "utf-8");
|
|
14
|
+
}
|
|
15
|
+
function getServiceWorkerPath() {
|
|
16
|
+
let swFilePath = path.join(__dirname$1, "__sw__.js");
|
|
17
|
+
if (!fs.existsSync(swFilePath)) {
|
|
18
|
+
swFilePath = path.join(__dirname$1, "../dist/__sw__.js");
|
|
19
|
+
}
|
|
20
|
+
if (!fs.existsSync(swFilePath)) {
|
|
21
|
+
throw new Error("Service worker file not found. Make sure almostnode is built.");
|
|
22
|
+
}
|
|
23
|
+
return swFilePath;
|
|
24
|
+
}
|
|
25
|
+
const nextPlugin = { getServiceWorkerContent, getServiceWorkerPath };
|
|
26
|
+
export {
|
|
27
|
+
nextPlugin as default,
|
|
28
|
+
getServiceWorkerContent,
|
|
29
|
+
getServiceWorkerPath
|
|
30
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"next-plugin.mjs","sources":["../src/next-plugin.ts"],"sourcesContent":["/**\n * Next.js Plugin for almostnode\n *\n * Provides utilities for serving the service worker file in Next.js applications.\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { fileURLToPath } from 'url';\n\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore - import.meta.url is available in ESM\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\n/**\n * Get the contents of the almostnode service worker file.\n * Use this in a Next.js API route or middleware to serve the service worker.\n *\n * @example\n * ```typescript\n * // app/api/__sw__/route.ts (App Router)\n * import { getServiceWorkerContent } from 'almostnode/next';\n *\n * export async function GET() {\n * const content = getServiceWorkerContent();\n * return new Response(content, {\n * headers: {\n * 'Content-Type': 'application/javascript',\n * 'Cache-Control': 'no-cache',\n * },\n * });\n * }\n * ```\n *\n * @example\n * ```typescript\n * // pages/api/__sw__.ts (Pages Router)\n * import { getServiceWorkerContent } from 'almostnode/next';\n * import type { NextApiRequest, NextApiResponse } from 'next';\n *\n * export default function handler(req: NextApiRequest, res: NextApiResponse) {\n * const content = getServiceWorkerContent();\n * res.setHeader('Content-Type', 'application/javascript');\n * res.setHeader('Cache-Control', 'no-cache');\n * res.send(content);\n * }\n * ```\n */\nexport function getServiceWorkerContent(): string {\n // The service worker file is in the dist directory relative to this file\n // In src: ../dist/__sw__.js\n // In dist: ./__sw__.js\n let swFilePath = path.join(__dirname, '__sw__.js');\n\n // If running from src directory during development, look in dist\n if (!fs.existsSync(swFilePath)) {\n swFilePath = path.join(__dirname, '../dist/__sw__.js');\n }\n\n if (!fs.existsSync(swFilePath)) {\n throw new Error('Service worker file not found. Make sure almostnode is built.');\n }\n\n return fs.readFileSync(swFilePath, 'utf-8');\n}\n\n/**\n * Get the path to the almostnode service worker file.\n * Useful if you want to copy it to your public directory.\n *\n * @example\n * ```javascript\n * // scripts/copy-sw.js\n * const { getServiceWorkerPath } = require('almostnode/next');\n * const fs = require('fs');\n * const path = require('path');\n *\n * const swPath = getServiceWorkerPath();\n * fs.copyFileSync(swPath, path.join(__dirname, '../public/__sw__.js'));\n * ```\n */\nexport function getServiceWorkerPath(): string {\n let swFilePath = path.join(__dirname, '__sw__.js');\n\n if (!fs.existsSync(swFilePath)) {\n swFilePath = path.join(__dirname, '../dist/__sw__.js');\n }\n\n if (!fs.existsSync(swFilePath)) {\n throw new Error('Service worker file not found. Make sure almostnode is built.');\n }\n\n return swFilePath;\n}\n\nexport default { getServiceWorkerContent, getServiceWorkerPath };\n"],"names":["__dirname"],"mappings":";;;;AAYA,MAAMA,cAAY,IAAA,CAAK,OAAA,CAAQ,aAAA,CAAc,MAAA,CAAA,IAAA,CAAY,GAAG,CAAC,CAAA;AAoCtD,SAAS,uBAAA,GAAkC;AAIhD,EAAA,IAAI,UAAA,GAAa,IAAA,CAAK,IAAA,CAAKA,WAAA,EAAW,WAAW,CAAA;AAGjD,EAAA,IAAI,CAAC,EAAA,CAAG,UAAA,CAAW,UAAU,CAAA,EAAG;AAC9B,IAAA,UAAA,GAAa,IAAA,CAAK,IAAA,CAAKA,WAAA,EAAW,mBAAmB,CAAA;AAAA,EACvD;AAEA,EAAA,IAAI,CAAC,EAAA,CAAG,UAAA,CAAW,UAAU,CAAA,EAAG;AAC9B,IAAA,MAAM,IAAI,MAAM,+DAA+D,CAAA;AAAA,EACjF;AAEA,EAAA,OAAO,EAAA,CAAG,YAAA,CAAa,UAAA,EAAY,OAAO,CAAA;AAC5C;AAiBO,SAAS,oBAAA,GAA+B;AAC7C,EAAA,IAAI,UAAA,GAAa,IAAA,CAAK,IAAA,CAAKA,WAAA,EAAW,WAAW,CAAA;AAEjD,EAAA,IAAI,CAAC,EAAA,CAAG,UAAA,CAAW,UAAU,CAAA,EAAG;AAC9B,IAAA,UAAA,GAAa,IAAA,CAAK,IAAA,CAAKA,WAAA,EAAW,mBAAmB,CAAA;AAAA,EACvD;AAEA,EAAA,IAAI,CAAC,EAAA,CAAG,UAAA,CAAW,UAAU,CAAA,EAAG;AAC9B,IAAA,MAAM,IAAI,MAAM,+DAA+D,CAAA;AAAA,EACjF;AAEA,EAAA,OAAO,UAAA;AACT;AAEA,mBAAe,EAAE,yBAAyB,oBAAA,EAAqB;;;;"}
|
|
@@ -4,36 +4,59 @@
|
|
|
4
4
|
* The sandbox runs on a different origin (e.g., myapp-sandbox.vercel.app)
|
|
5
5
|
* to provide browser-enforced isolation from the main application.
|
|
6
6
|
*/
|
|
7
|
+
export interface SandboxHtmlOptions {
|
|
8
|
+
/**
|
|
9
|
+
* URL to load almostnode from (e.g., unpkg, jsdelivr, or your CDN)
|
|
10
|
+
* @default 'https://unpkg.com/almostnode/dist/index.js'
|
|
11
|
+
*/
|
|
12
|
+
almostnodeUrl?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Whether to include service worker registration for dev server support.
|
|
15
|
+
* When true, the sandbox can run ViteDevServer/NextDevServer with URL access.
|
|
16
|
+
* @default true
|
|
17
|
+
*/
|
|
18
|
+
includeServiceWorker?: boolean;
|
|
19
|
+
}
|
|
7
20
|
/**
|
|
8
21
|
* HTML template for the sandbox page.
|
|
9
22
|
* This loads almostnode and handles postMessage communication with the parent.
|
|
10
23
|
*
|
|
11
|
-
* @param
|
|
24
|
+
* @param options - Configuration options or legacy URL string
|
|
12
25
|
*/
|
|
13
|
-
export declare function getSandboxHtml(
|
|
26
|
+
export declare function getSandboxHtml(options?: SandboxHtmlOptions | string): string;
|
|
14
27
|
/**
|
|
15
28
|
* Get vercel.json configuration for the sandbox.
|
|
16
29
|
* Sets up CORS headers to allow embedding as a cross-origin iframe.
|
|
17
30
|
*/
|
|
18
31
|
export declare function getSandboxVercelConfig(): object;
|
|
32
|
+
export interface GenerateSandboxFilesOptions extends SandboxHtmlOptions {
|
|
33
|
+
}
|
|
19
34
|
/**
|
|
20
|
-
* Generate all files needed for deploying a sandbox to Vercel.
|
|
35
|
+
* Generate all files needed for deploying a sandbox to Vercel or other platforms.
|
|
21
36
|
*
|
|
22
|
-
* @param
|
|
37
|
+
* @param options - Configuration options or legacy URL string
|
|
23
38
|
* @returns Object with file names as keys and content as values
|
|
24
39
|
*
|
|
25
40
|
* @example
|
|
26
41
|
* ```typescript
|
|
27
|
-
* import { generateSandboxFiles } from 'almostnode
|
|
42
|
+
* import { generateSandboxFiles } from 'almostnode';
|
|
43
|
+
* import fs from 'fs';
|
|
28
44
|
*
|
|
29
45
|
* const files = generateSandboxFiles();
|
|
46
|
+
*
|
|
30
47
|
* // Write files to sandbox/ directory
|
|
48
|
+
* fs.mkdirSync('sandbox', { recursive: true });
|
|
49
|
+
* for (const [filename, content] of Object.entries(files)) {
|
|
50
|
+
* fs.writeFileSync(`sandbox/${filename}`, content);
|
|
51
|
+
* }
|
|
52
|
+
*
|
|
31
53
|
* // Deploy to Vercel: cd sandbox && vercel --prod
|
|
32
54
|
* ```
|
|
33
55
|
*/
|
|
34
|
-
export declare function generateSandboxFiles(
|
|
56
|
+
export declare function generateSandboxFiles(options?: GenerateSandboxFilesOptions | string): {
|
|
35
57
|
'index.html': string;
|
|
36
58
|
'vercel.json': string;
|
|
59
|
+
'__sw__.js'?: string;
|
|
37
60
|
};
|
|
38
61
|
/**
|
|
39
62
|
* Instructions for setting up a sandbox on Vercel.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox-helpers.d.ts","sourceRoot":"","sources":["../src/sandbox-helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"sandbox-helpers.d.ts","sourceRoot":"","sources":["../src/sandbox-helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAgCH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,kBAAkB,GAAG,MAAW,GAAG,MAAM,CA6GhF;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAY/C;AAED,MAAM,WAAW,2BAA4B,SAAQ,kBAAkB;CAEtE;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,2BAA2B,GAAG,MAAW,GAAG;IACxF,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAuBA;AAED;;;GAGG;AACH,eAAO,MAAM,0BAA0B,QAmB/B,CAAC"}
|
package/dist/server-bridge.d.ts
CHANGED
|
@@ -26,6 +26,13 @@ export interface BridgeOptions {
|
|
|
26
26
|
baseUrl?: string;
|
|
27
27
|
onServerReady?: (port: number, url: string) => void;
|
|
28
28
|
}
|
|
29
|
+
export interface InitServiceWorkerOptions {
|
|
30
|
+
/**
|
|
31
|
+
* The URL path to the service worker file
|
|
32
|
+
* @default '/__sw__.js'
|
|
33
|
+
*/
|
|
34
|
+
swUrl?: string;
|
|
35
|
+
}
|
|
29
36
|
/**
|
|
30
37
|
* Server Bridge manages virtual HTTP servers and routes requests
|
|
31
38
|
*/
|
|
@@ -58,8 +65,10 @@ export declare class ServerBridge extends EventEmitter {
|
|
|
58
65
|
handleRequest(port: number, method: string, url: string, headers: Record<string, string>, body?: ArrayBuffer): Promise<ResponseData>;
|
|
59
66
|
/**
|
|
60
67
|
* Initialize Service Worker communication
|
|
68
|
+
* @param options - Configuration options for the service worker
|
|
69
|
+
* @param options.swUrl - Custom URL path to the service worker file (default: '/__sw__.js')
|
|
61
70
|
*/
|
|
62
|
-
initServiceWorker(): Promise<void>;
|
|
71
|
+
initServiceWorker(options?: InitServiceWorkerOptions): Promise<void>;
|
|
63
72
|
/**
|
|
64
73
|
* Handle messages from Service Worker
|
|
65
74
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-bridge.d.ts","sourceRoot":"","sources":["../src/server-bridge.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,MAAM,EACN,YAAY,EAIb,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAExC;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACpE,aAAa,CACX,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GACrB,OAAO,CAAC,YAAY,CAAC,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,GAAG,cAAc,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACrD;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,YAAY;IAC5C,OAAO,CAAC,OAAO,CAAyC;IACxD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,kBAAkB,CAAkB;gBAEhC,OAAO,GAAE,aAAkB;IAqBvC;;OAEG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAkB,GAAG,IAAI;IAejG;;OAEG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKpC;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIlC;;OAEG;IACH,cAAc,IAAI,MAAM,EAAE;IAI1B;;OAEG;IACG,aAAa,CACjB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,IAAI,CAAC,EAAE,WAAW,GACjB,OAAO,CAAC,YAAY,CAAC;IA0BxB
|
|
1
|
+
{"version":3,"file":"server-bridge.d.ts","sourceRoot":"","sources":["../src/server-bridge.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,MAAM,EACN,YAAY,EAIb,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAExC;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACpE,aAAa,CACX,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GACrB,OAAO,CAAC,YAAY,CAAC,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,GAAG,cAAc,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACrD;AAED,MAAM,WAAW,wBAAwB;IACvC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,YAAY;IAC5C,OAAO,CAAC,OAAO,CAAyC;IACxD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,kBAAkB,CAAkB;gBAEhC,OAAO,GAAE,aAAkB;IAqBvC;;OAEG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAkB,GAAG,IAAI;IAejG;;OAEG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKpC;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIlC;;OAEG;IACH,cAAc,IAAI,MAAM,EAAE;IAI1B;;OAEG;IACG,aAAa,CACjB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,IAAI,CAAC,EAAE,WAAW,GACjB,OAAO,CAAC,YAAY,CAAC;IA0BxB;;;;OAIG;IACG,iBAAiB,CAAC,OAAO,CAAC,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;IA4C1E;;OAEG;YACW,0BAA0B;IAyDxC;;OAEG;YACW,sBAAsB;IA+FpC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAM3B;;OAEG;IACH,kBAAkB,IAAI,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC;CA0C9D;AAKD;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,YAAY,CAKrE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAED,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const url = require('url');
|
|
8
|
+
|
|
9
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
10
|
+
function _interopNamespaceDefault(e) {
|
|
11
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } });
|
|
12
|
+
if (e) {
|
|
13
|
+
for (const k in e) {
|
|
14
|
+
if (k !== 'default') {
|
|
15
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
16
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
get: () => e[k]
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
n.default = e;
|
|
24
|
+
return Object.freeze(n);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
|
|
28
|
+
const path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
|
|
29
|
+
|
|
30
|
+
const __dirname$1 = path__namespace.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('vite-plugin.cjs', document.baseURI).href))));
|
|
31
|
+
function almostnodePlugin(options = {}) {
|
|
32
|
+
const swPath = options.swPath || "/__sw__.js";
|
|
33
|
+
return {
|
|
34
|
+
name: "almostnode",
|
|
35
|
+
configureServer(server) {
|
|
36
|
+
server.middlewares.use(swPath, (_req, res) => {
|
|
37
|
+
let swFilePath = path__namespace.join(__dirname$1, "__sw__.js");
|
|
38
|
+
if (!fs__namespace.existsSync(swFilePath)) {
|
|
39
|
+
swFilePath = path__namespace.join(__dirname$1, "../dist/__sw__.js");
|
|
40
|
+
}
|
|
41
|
+
if (!fs__namespace.existsSync(swFilePath)) {
|
|
42
|
+
res.statusCode = 404;
|
|
43
|
+
res.end("Service worker file not found. Make sure almostnode is built.");
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
res.setHeader("Content-Type", "application/javascript");
|
|
47
|
+
res.setHeader("Cache-Control", "no-cache");
|
|
48
|
+
res.end(fs__namespace.readFileSync(swFilePath));
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
exports.almostnodePlugin = almostnodePlugin;
|
|
55
|
+
exports.default = almostnodePlugin;
|
|
56
|
+
//# sourceMappingURL=vite-plugin.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vite-plugin.cjs","sources":["../src/vite-plugin.ts"],"sourcesContent":["/**\n * Vite Plugin for almostnode\n *\n * Serves the service worker file from the package's dist directory,\n * enabling seamless integration when almostnode is installed as an npm package.\n */\n\nimport type { Plugin, ViteDevServer } from 'vite';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { fileURLToPath } from 'url';\n\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore - import.meta.url is available in ESM\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface AlmostnodePluginOptions {\n /**\n * The URL path where the service worker will be served\n * @default '/__sw__.js'\n */\n swPath?: string;\n}\n\n/**\n * Vite plugin that serves the almostnode service worker file.\n *\n * When almostnode is installed as an npm package, the service worker file\n * is located at node_modules/almostnode/dist/__sw__.js but the browser\n * tries to load it from the root URL (/__sw__.js). This plugin intercepts\n * requests to the service worker path and serves the file from the correct location.\n *\n * @example\n * ```typescript\n * // vite.config.ts\n * import { defineConfig } from 'vite';\n * import { almostnodePlugin } from 'almostnode/vite';\n *\n * export default defineConfig({\n * plugins: [almostnodePlugin()]\n * });\n * ```\n */\nexport function almostnodePlugin(options: AlmostnodePluginOptions = {}): Plugin {\n const swPath = options.swPath || '/__sw__.js';\n\n return {\n name: 'almostnode',\n\n configureServer(server: ViteDevServer) {\n server.middlewares.use(swPath, (_req, res) => {\n // The service worker file is in the dist directory relative to this file\n // In src: ../dist/__sw__.js\n // In dist: ./__sw__.js\n let swFilePath = path.join(__dirname, '__sw__.js');\n\n // If running from src directory during development, look in dist\n if (!fs.existsSync(swFilePath)) {\n swFilePath = path.join(__dirname, '../dist/__sw__.js');\n }\n\n if (!fs.existsSync(swFilePath)) {\n res.statusCode = 404;\n res.end('Service worker file not found. Make sure almostnode is built.');\n return;\n }\n\n res.setHeader('Content-Type', 'application/javascript');\n res.setHeader('Cache-Control', 'no-cache');\n res.end(fs.readFileSync(swFilePath));\n });\n },\n };\n}\n\nexport default almostnodePlugin;\n"],"names":["__dirname","path","fileURLToPath","fs"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAcA,MAAMA,cAAYC,eAAA,CAAK,OAAA,CAAQC,iBAAA,CAAc,iQAAe,CAAC,CAAA;AA6BtD,SAAS,gBAAA,CAAiB,OAAA,GAAmC,EAAC,EAAW;AAC9E,EAAA,MAAM,MAAA,GAAS,QAAQ,MAAA,IAAU,YAAA;AAEjC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,YAAA;AAAA,IAEN,gBAAgB,MAAA,EAAuB;AACrC,MAAA,MAAA,CAAO,WAAA,CAAY,GAAA,CAAI,MAAA,EAAQ,CAAC,MAAM,GAAA,KAAQ;AAI5C,QAAA,IAAI,UAAA,GAAaD,eAAA,CAAK,IAAA,CAAKD,WAAA,EAAW,WAAW,CAAA;AAGjD,QAAA,IAAI,CAACG,aAAA,CAAG,UAAA,CAAW,UAAU,CAAA,EAAG;AAC9B,UAAA,UAAA,GAAaF,eAAA,CAAK,IAAA,CAAKD,WAAA,EAAW,mBAAmB,CAAA;AAAA,QACvD;AAEA,QAAA,IAAI,CAACG,aAAA,CAAG,UAAA,CAAW,UAAU,CAAA,EAAG;AAC9B,UAAA,GAAA,CAAI,UAAA,GAAa,GAAA;AACjB,UAAA,GAAA,CAAI,IAAI,+DAA+D,CAAA;AACvE,UAAA;AAAA,QACF;AAEA,QAAA,GAAA,CAAI,SAAA,CAAU,gBAAgB,wBAAwB,CAAA;AACtD,QAAA,GAAA,CAAI,SAAA,CAAU,iBAAiB,UAAU,CAAA;AACzC,QAAA,GAAA,CAAI,GAAA,CAAIA,aAAA,CAAG,YAAA,CAAa,UAAU,CAAC,CAAA;AAAA,MACrC,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AACF;;;;;"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vite Plugin for almostnode
|
|
3
|
+
*
|
|
4
|
+
* Serves the service worker file from the package's dist directory,
|
|
5
|
+
* enabling seamless integration when almostnode is installed as an npm package.
|
|
6
|
+
*/
|
|
7
|
+
import type { Plugin } from 'vite';
|
|
8
|
+
export interface AlmostnodePluginOptions {
|
|
9
|
+
/**
|
|
10
|
+
* The URL path where the service worker will be served
|
|
11
|
+
* @default '/__sw__.js'
|
|
12
|
+
*/
|
|
13
|
+
swPath?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Vite plugin that serves the almostnode service worker file.
|
|
17
|
+
*
|
|
18
|
+
* When almostnode is installed as an npm package, the service worker file
|
|
19
|
+
* is located at node_modules/almostnode/dist/__sw__.js but the browser
|
|
20
|
+
* tries to load it from the root URL (/__sw__.js). This plugin intercepts
|
|
21
|
+
* requests to the service worker path and serves the file from the correct location.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* // vite.config.ts
|
|
26
|
+
* import { defineConfig } from 'vite';
|
|
27
|
+
* import { almostnodePlugin } from 'almostnode/vite';
|
|
28
|
+
*
|
|
29
|
+
* export default defineConfig({
|
|
30
|
+
* plugins: [almostnodePlugin()]
|
|
31
|
+
* });
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare function almostnodePlugin(options?: AlmostnodePluginOptions): Plugin;
|
|
35
|
+
export default almostnodePlugin;
|
|
36
|
+
//# sourceMappingURL=vite-plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../src/vite-plugin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAiB,MAAM,MAAM,CAAC;AASlD,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,uBAA4B,GAAG,MAAM,CA8B9E;AAED,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
const __dirname$1 = path.dirname(fileURLToPath(import.meta.url));
|
|
5
|
+
function almostnodePlugin(options = {}) {
|
|
6
|
+
const swPath = options.swPath || "/__sw__.js";
|
|
7
|
+
return {
|
|
8
|
+
name: "almostnode",
|
|
9
|
+
configureServer(server) {
|
|
10
|
+
server.middlewares.use(swPath, (_req, res) => {
|
|
11
|
+
let swFilePath = path.join(__dirname$1, "__sw__.js");
|
|
12
|
+
if (!fs.existsSync(swFilePath)) {
|
|
13
|
+
swFilePath = path.join(__dirname$1, "../dist/__sw__.js");
|
|
14
|
+
}
|
|
15
|
+
if (!fs.existsSync(swFilePath)) {
|
|
16
|
+
res.statusCode = 404;
|
|
17
|
+
res.end("Service worker file not found. Make sure almostnode is built.");
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
res.setHeader("Content-Type", "application/javascript");
|
|
21
|
+
res.setHeader("Cache-Control", "no-cache");
|
|
22
|
+
res.end(fs.readFileSync(swFilePath));
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export {
|
|
28
|
+
almostnodePlugin,
|
|
29
|
+
almostnodePlugin as default
|
|
30
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vite-plugin.mjs","sources":["../src/vite-plugin.ts"],"sourcesContent":["/**\n * Vite Plugin for almostnode\n *\n * Serves the service worker file from the package's dist directory,\n * enabling seamless integration when almostnode is installed as an npm package.\n */\n\nimport type { Plugin, ViteDevServer } from 'vite';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { fileURLToPath } from 'url';\n\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore - import.meta.url is available in ESM\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface AlmostnodePluginOptions {\n /**\n * The URL path where the service worker will be served\n * @default '/__sw__.js'\n */\n swPath?: string;\n}\n\n/**\n * Vite plugin that serves the almostnode service worker file.\n *\n * When almostnode is installed as an npm package, the service worker file\n * is located at node_modules/almostnode/dist/__sw__.js but the browser\n * tries to load it from the root URL (/__sw__.js). This plugin intercepts\n * requests to the service worker path and serves the file from the correct location.\n *\n * @example\n * ```typescript\n * // vite.config.ts\n * import { defineConfig } from 'vite';\n * import { almostnodePlugin } from 'almostnode/vite';\n *\n * export default defineConfig({\n * plugins: [almostnodePlugin()]\n * });\n * ```\n */\nexport function almostnodePlugin(options: AlmostnodePluginOptions = {}): Plugin {\n const swPath = options.swPath || '/__sw__.js';\n\n return {\n name: 'almostnode',\n\n configureServer(server: ViteDevServer) {\n server.middlewares.use(swPath, (_req, res) => {\n // The service worker file is in the dist directory relative to this file\n // In src: ../dist/__sw__.js\n // In dist: ./__sw__.js\n let swFilePath = path.join(__dirname, '__sw__.js');\n\n // If running from src directory during development, look in dist\n if (!fs.existsSync(swFilePath)) {\n swFilePath = path.join(__dirname, '../dist/__sw__.js');\n }\n\n if (!fs.existsSync(swFilePath)) {\n res.statusCode = 404;\n res.end('Service worker file not found. Make sure almostnode is built.');\n return;\n }\n\n res.setHeader('Content-Type', 'application/javascript');\n res.setHeader('Cache-Control', 'no-cache');\n res.end(fs.readFileSync(swFilePath));\n });\n },\n };\n}\n\nexport default almostnodePlugin;\n"],"names":["__dirname"],"mappings":";;;;AAcA,MAAMA,cAAY,IAAA,CAAK,OAAA,CAAQ,aAAA,CAAc,MAAA,CAAA,IAAA,CAAY,GAAG,CAAC,CAAA;AA6BtD,SAAS,gBAAA,CAAiB,OAAA,GAAmC,EAAC,EAAW;AAC9E,EAAA,MAAM,MAAA,GAAS,QAAQ,MAAA,IAAU,YAAA;AAEjC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,YAAA;AAAA,IAEN,gBAAgB,MAAA,EAAuB;AACrC,MAAA,MAAA,CAAO,WAAA,CAAY,GAAA,CAAI,MAAA,EAAQ,CAAC,MAAM,GAAA,KAAQ;AAI5C,QAAA,IAAI,UAAA,GAAa,IAAA,CAAK,IAAA,CAAKA,WAAA,EAAW,WAAW,CAAA;AAGjD,QAAA,IAAI,CAAC,EAAA,CAAG,UAAA,CAAW,UAAU,CAAA,EAAG;AAC9B,UAAA,UAAA,GAAa,IAAA,CAAK,IAAA,CAAKA,WAAA,EAAW,mBAAmB,CAAA;AAAA,QACvD;AAEA,QAAA,IAAI,CAAC,EAAA,CAAG,UAAA,CAAW,UAAU,CAAA,EAAG;AAC9B,UAAA,GAAA,CAAI,UAAA,GAAa,GAAA;AACjB,UAAA,GAAA,CAAI,IAAI,+DAA+D,CAAA;AACvE,UAAA;AAAA,QACF;AAEA,QAAA,GAAA,CAAI,SAAA,CAAU,gBAAgB,wBAAwB,CAAA;AACtD,QAAA,GAAA,CAAI,SAAA,CAAU,iBAAiB,UAAU,CAAA;AACzC,QAAA,GAAA,CAAI,GAAA,CAAI,EAAA,CAAG,YAAA,CAAa,UAAU,CAAC,CAAA;AAAA,MACrC,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AACF;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "almostnode",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Node.js in your browser. Just like that.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,6 +40,26 @@
|
|
|
40
40
|
"types": "./dist/index.d.ts",
|
|
41
41
|
"default": "./dist/index.cjs"
|
|
42
42
|
}
|
|
43
|
+
},
|
|
44
|
+
"./vite": {
|
|
45
|
+
"import": {
|
|
46
|
+
"types": "./dist/vite-plugin.d.ts",
|
|
47
|
+
"default": "./dist/vite-plugin.mjs"
|
|
48
|
+
},
|
|
49
|
+
"require": {
|
|
50
|
+
"types": "./dist/vite-plugin.d.ts",
|
|
51
|
+
"default": "./dist/vite-plugin.cjs"
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"./next": {
|
|
55
|
+
"import": {
|
|
56
|
+
"types": "./dist/next-plugin.d.ts",
|
|
57
|
+
"default": "./dist/next-plugin.mjs"
|
|
58
|
+
},
|
|
59
|
+
"require": {
|
|
60
|
+
"types": "./dist/next-plugin.d.ts",
|
|
61
|
+
"default": "./dist/next-plugin.cjs"
|
|
62
|
+
}
|
|
43
63
|
}
|
|
44
64
|
},
|
|
45
65
|
"files": [
|
|
@@ -1846,8 +1846,8 @@ export class NextDevServer extends DevServer {
|
|
|
1846
1846
|
React.useEffect(() => {
|
|
1847
1847
|
const handlePopState = () => {
|
|
1848
1848
|
setCurrentPath(window.location.pathname);
|
|
1849
|
-
//
|
|
1850
|
-
window.location.reload();
|
|
1849
|
+
// Defer reload outside React's update cycle
|
|
1850
|
+
setTimeout(() => window.location.reload(), 0);
|
|
1851
1851
|
};
|
|
1852
1852
|
|
|
1853
1853
|
window.addEventListener('popstate', handlePopState);
|
package/src/index.ts
CHANGED
|
@@ -27,6 +27,7 @@ export * as util from './shims/util';
|
|
|
27
27
|
export * as npm from './npm';
|
|
28
28
|
export { PackageManager, install } from './npm';
|
|
29
29
|
export { ServerBridge, getServerBridge, resetServerBridge } from './server-bridge';
|
|
30
|
+
export type { InitServiceWorkerOptions } from './server-bridge';
|
|
30
31
|
// Dev servers
|
|
31
32
|
export { DevServer } from './dev-server';
|
|
32
33
|
export type { DevServerOptions, ResponseData, HMRUpdate } from './dev-server';
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Next.js Plugin for almostnode
|
|
3
|
+
*
|
|
4
|
+
* Provides utilities for serving the service worker file in Next.js applications.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import { fileURLToPath } from 'url';
|
|
10
|
+
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
12
|
+
// @ts-ignore - import.meta.url is available in ESM
|
|
13
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Get the contents of the almostnode service worker file.
|
|
17
|
+
* Use this in a Next.js API route or middleware to serve the service worker.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* // app/api/__sw__/route.ts (App Router)
|
|
22
|
+
* import { getServiceWorkerContent } from 'almostnode/next';
|
|
23
|
+
*
|
|
24
|
+
* export async function GET() {
|
|
25
|
+
* const content = getServiceWorkerContent();
|
|
26
|
+
* return new Response(content, {
|
|
27
|
+
* headers: {
|
|
28
|
+
* 'Content-Type': 'application/javascript',
|
|
29
|
+
* 'Cache-Control': 'no-cache',
|
|
30
|
+
* },
|
|
31
|
+
* });
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* // pages/api/__sw__.ts (Pages Router)
|
|
38
|
+
* import { getServiceWorkerContent } from 'almostnode/next';
|
|
39
|
+
* import type { NextApiRequest, NextApiResponse } from 'next';
|
|
40
|
+
*
|
|
41
|
+
* export default function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
42
|
+
* const content = getServiceWorkerContent();
|
|
43
|
+
* res.setHeader('Content-Type', 'application/javascript');
|
|
44
|
+
* res.setHeader('Cache-Control', 'no-cache');
|
|
45
|
+
* res.send(content);
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export function getServiceWorkerContent(): string {
|
|
50
|
+
// The service worker file is in the dist directory relative to this file
|
|
51
|
+
// In src: ../dist/__sw__.js
|
|
52
|
+
// In dist: ./__sw__.js
|
|
53
|
+
let swFilePath = path.join(__dirname, '__sw__.js');
|
|
54
|
+
|
|
55
|
+
// If running from src directory during development, look in dist
|
|
56
|
+
if (!fs.existsSync(swFilePath)) {
|
|
57
|
+
swFilePath = path.join(__dirname, '../dist/__sw__.js');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (!fs.existsSync(swFilePath)) {
|
|
61
|
+
throw new Error('Service worker file not found. Make sure almostnode is built.');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return fs.readFileSync(swFilePath, 'utf-8');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Get the path to the almostnode service worker file.
|
|
69
|
+
* Useful if you want to copy it to your public directory.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```javascript
|
|
73
|
+
* // scripts/copy-sw.js
|
|
74
|
+
* const { getServiceWorkerPath } = require('almostnode/next');
|
|
75
|
+
* const fs = require('fs');
|
|
76
|
+
* const path = require('path');
|
|
77
|
+
*
|
|
78
|
+
* const swPath = getServiceWorkerPath();
|
|
79
|
+
* fs.copyFileSync(swPath, path.join(__dirname, '../public/__sw__.js'));
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export function getServiceWorkerPath(): string {
|
|
83
|
+
let swFilePath = path.join(__dirname, '__sw__.js');
|
|
84
|
+
|
|
85
|
+
if (!fs.existsSync(swFilePath)) {
|
|
86
|
+
swFilePath = path.join(__dirname, '../dist/__sw__.js');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!fs.existsSync(swFilePath)) {
|
|
90
|
+
throw new Error('Service worker file not found. Make sure almostnode is built.');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return swFilePath;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export default { getServiceWorkerContent, getServiceWorkerPath };
|