@rspnseapp/dev-inspector 0.4.0 → 0.5.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/dist/index.cjs ADDED
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ rspnseInspector: () => rspnseInspector
24
+ });
25
+ module.exports = __toCommonJS(index_exports);
26
+
27
+ // src/vite-plugin.ts
28
+ var import_fs = require("fs");
29
+ var import_path = require("path");
30
+ var import_url = require("url");
31
+ var import_meta = {};
32
+ function getDirname() {
33
+ if (typeof import_meta !== "undefined" && import_meta.url) {
34
+ return (0, import_path.dirname)((0, import_url.fileURLToPath)(import_meta.url));
35
+ }
36
+ if (typeof __dirname !== "undefined") {
37
+ return __dirname;
38
+ }
39
+ return process.cwd();
40
+ }
41
+ var moduleDir = getDirname();
42
+ function rspnseInspector(options = {}) {
43
+ const { enabled = true, trustedOrigins } = options;
44
+ let inspectorScript = null;
45
+ function getInspectorScript() {
46
+ if (inspectorScript) return inspectorScript;
47
+ try {
48
+ const scriptPath = (0, import_path.resolve)(moduleDir, "../dist/index.inspector.js");
49
+ inspectorScript = (0, import_fs.readFileSync)(scriptPath, "utf-8");
50
+ } catch {
51
+ try {
52
+ const scriptPath = (0, import_path.resolve)(moduleDir, "./index.inspector.js");
53
+ inspectorScript = (0, import_fs.readFileSync)(scriptPath, "utf-8");
54
+ } catch {
55
+ console.warn(
56
+ "[@rspnseapp/dev-inspector] Could not load inspector script. Run `npm run build` first."
57
+ );
58
+ inspectorScript = "// Inspector script not found";
59
+ }
60
+ }
61
+ return inspectorScript;
62
+ }
63
+ return {
64
+ name: "rspnse-inspector",
65
+ // Only apply in dev mode
66
+ apply: "serve",
67
+ configureServer(server) {
68
+ if (!enabled) return;
69
+ server.middlewares.use((req, res, next) => {
70
+ if (req.url === "/@rspnse-inspector/inspector.js") {
71
+ res.setHeader("Content-Type", "application/javascript");
72
+ res.setHeader("Cache-Control", "no-cache");
73
+ let script = getInspectorScript();
74
+ if (trustedOrigins && trustedOrigins.length > 0) {
75
+ const originsArray = JSON.stringify(trustedOrigins);
76
+ script = `window.__RSPNSE_TRUSTED_ORIGINS__ = ${originsArray};
77
+ ${script}`;
78
+ }
79
+ res.end(script);
80
+ return;
81
+ }
82
+ next();
83
+ });
84
+ },
85
+ transformIndexHtml(html) {
86
+ if (!enabled) return html;
87
+ const scriptTag = `<script src="/@rspnse-inspector/inspector.js" defer></script>`;
88
+ if (html.includes("</head>")) {
89
+ return html.replace("</head>", `${scriptTag}
90
+ </head>`);
91
+ }
92
+ if (html.includes("<body")) {
93
+ return html.replace(/<body([^>]*)>/, `<body$1>
94
+ ${scriptTag}`);
95
+ }
96
+ return scriptTag + "\n" + html;
97
+ }
98
+ };
99
+ }
100
+ // Annotate the CommonJS export names for ESM import in node:
101
+ 0 && (module.exports = {
102
+ rspnseInspector
103
+ });
104
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/vite-plugin.ts"],"sourcesContent":["/**\n * @rspnseapp/dev-inspector\n *\n * A Vite plugin that enables Rspnse inspect functionality on localhost dev servers.\n * Works across all browsers without requiring a browser extension.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { rspnseInspector } from '@rspnseapp/dev-inspector';\n *\n * export default defineConfig({\n * plugins: [rspnseInspector()]\n * });\n * ```\n *\n * Then open your site in rspnse.net and use the inspect feature!\n */\n\nexport { rspnseInspector } from './vite-plugin';\nexport type {\n RspnseInspectorOptions,\n InspectedElement,\n BreadcrumbItem,\n StyleEntry,\n} from './types';\n","import type { Plugin } from 'vite';\nimport { readFileSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport type { RspnseInspectorOptions } from './types';\n\n// Get the directory of this module (works in both ESM and CJS)\nfunction getDirname(): string {\n // ESM: use import.meta.url\n if (typeof import.meta !== 'undefined' && import.meta.url) {\n return dirname(fileURLToPath(import.meta.url));\n }\n // CJS: __dirname is globally available (injected by bundler)\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n if (typeof __dirname !== 'undefined') {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return __dirname;\n }\n // Fallback: use process.cwd()\n return process.cwd();\n}\n\nconst moduleDir = getDirname();\n\n/**\n * Vite plugin that injects the Rspnse inspector script into dev server pages.\n * This enables inspect functionality from rspnse.net without a browser extension.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { rspnseInspector } from '@rspnseapp/dev-inspector';\n *\n * export default {\n * plugins: [rspnseInspector()]\n * }\n * ```\n */\nexport function rspnseInspector(options: RspnseInspectorOptions = {}): Plugin {\n const { enabled = true, trustedOrigins } = options;\n\n // Cache the inspector script content\n let inspectorScript: string | null = null;\n\n function getInspectorScript(): string {\n if (inspectorScript) return inspectorScript;\n\n try {\n // Try to load the bundled inspector script\n const scriptPath = resolve(moduleDir, '../dist/index.inspector.js');\n inspectorScript = readFileSync(scriptPath, 'utf-8');\n } catch {\n // Fallback: load from same directory (during development)\n try {\n const scriptPath = resolve(moduleDir, './index.inspector.js');\n inspectorScript = readFileSync(scriptPath, 'utf-8');\n } catch {\n console.warn(\n '[@rspnseapp/dev-inspector] Could not load inspector script. Run `npm run build` first.'\n );\n inspectorScript = '// Inspector script not found';\n }\n }\n\n return inspectorScript;\n }\n\n return {\n name: 'rspnse-inspector',\n\n // Only apply in dev mode\n apply: 'serve',\n\n configureServer(server) {\n if (!enabled) return;\n\n // Serve the inspector script at a special path\n server.middlewares.use((req, res, next) => {\n if (req.url === '/@rspnse-inspector/inspector.js') {\n res.setHeader('Content-Type', 'application/javascript');\n res.setHeader('Cache-Control', 'no-cache');\n\n let script = getInspectorScript();\n\n // If custom trusted origins are provided, inject them\n if (trustedOrigins && trustedOrigins.length > 0) {\n const originsArray = JSON.stringify(trustedOrigins);\n script = `window.__RSPNSE_TRUSTED_ORIGINS__ = ${originsArray};\\n${script}`;\n }\n\n res.end(script);\n return;\n }\n next();\n });\n },\n\n transformIndexHtml(html) {\n if (!enabled) return html;\n\n // Inject the inspector script before </head>\n const scriptTag = `<script src=\"/@rspnse-inspector/inspector.js\" defer></script>`;\n\n if (html.includes('</head>')) {\n return html.replace('</head>', `${scriptTag}\\n</head>`);\n }\n\n // Fallback: inject at start of body if no head tag\n if (html.includes('<body')) {\n return html.replace(/<body([^>]*)>/, `<body$1>\\n${scriptTag}`);\n }\n\n // Last resort: prepend to html\n return scriptTag + '\\n' + html;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCA,gBAA6B;AAC7B,kBAAiC;AACjC,iBAA8B;AAH9B;AAOA,SAAS,aAAqB;AAE5B,MAAI,OAAO,gBAAgB,eAAe,YAAY,KAAK;AACzD,eAAO,yBAAQ,0BAAc,YAAY,GAAG,CAAC;AAAA,EAC/C;AAIA,MAAI,OAAO,cAAc,aAAa;AAGpC,WAAO;AAAA,EACT;AAEA,SAAO,QAAQ,IAAI;AACrB;AAEA,IAAM,YAAY,WAAW;AAgBtB,SAAS,gBAAgB,UAAkC,CAAC,GAAW;AAC5E,QAAM,EAAE,UAAU,MAAM,eAAe,IAAI;AAG3C,MAAI,kBAAiC;AAErC,WAAS,qBAA6B;AACpC,QAAI,gBAAiB,QAAO;AAE5B,QAAI;AAEF,YAAM,iBAAa,qBAAQ,WAAW,4BAA4B;AAClE,4BAAkB,wBAAa,YAAY,OAAO;AAAA,IACpD,QAAQ;AAEN,UAAI;AACF,cAAM,iBAAa,qBAAQ,WAAW,sBAAsB;AAC5D,8BAAkB,wBAAa,YAAY,OAAO;AAAA,MACpD,QAAQ;AACN,gBAAQ;AAAA,UACN;AAAA,QACF;AACA,0BAAkB;AAAA,MACpB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,MAAM;AAAA;AAAA,IAGN,OAAO;AAAA,IAEP,gBAAgB,QAAQ;AACtB,UAAI,CAAC,QAAS;AAGd,aAAO,YAAY,IAAI,CAAC,KAAK,KAAK,SAAS;AACzC,YAAI,IAAI,QAAQ,mCAAmC;AACjD,cAAI,UAAU,gBAAgB,wBAAwB;AACtD,cAAI,UAAU,iBAAiB,UAAU;AAEzC,cAAI,SAAS,mBAAmB;AAGhC,cAAI,kBAAkB,eAAe,SAAS,GAAG;AAC/C,kBAAM,eAAe,KAAK,UAAU,cAAc;AAClD,qBAAS,uCAAuC,YAAY;AAAA,EAAM,MAAM;AAAA,UAC1E;AAEA,cAAI,IAAI,MAAM;AACd;AAAA,QACF;AACA,aAAK;AAAA,MACP,CAAC;AAAA,IACH;AAAA,IAEA,mBAAmB,MAAM;AACvB,UAAI,CAAC,QAAS,QAAO;AAGrB,YAAM,YAAY;AAElB,UAAI,KAAK,SAAS,SAAS,GAAG;AAC5B,eAAO,KAAK,QAAQ,WAAW,GAAG,SAAS;AAAA,QAAW;AAAA,MACxD;AAGA,UAAI,KAAK,SAAS,OAAO,GAAG;AAC1B,eAAO,KAAK,QAAQ,iBAAiB;AAAA,EAAa,SAAS,EAAE;AAAA,MAC/D;AAGA,aAAO,YAAY,OAAO;AAAA,IAC5B;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,49 @@
1
+ import { Plugin } from 'vite';
2
+
3
+ interface BreadcrumbItem {
4
+ label: string;
5
+ index: number;
6
+ }
7
+ interface InspectedElement {
8
+ selector: string;
9
+ tagName: string;
10
+ classList: string[];
11
+ id: string | null;
12
+ computedStyles: Record<string, string>;
13
+ }
14
+ interface StyleEntry {
15
+ type: 'inline' | 'external';
16
+ index?: number;
17
+ href?: string;
18
+ css: string | null;
19
+ error?: string;
20
+ }
21
+ interface RspnseInspectorOptions {
22
+ /**
23
+ * Enable/disable the inspector. Defaults to true in development.
24
+ */
25
+ enabled?: boolean;
26
+ /**
27
+ * Trusted origins that can communicate with the inspector.
28
+ * Defaults to ['https://rspnse.net', 'http://localhost']
29
+ */
30
+ trustedOrigins?: string[];
31
+ }
32
+
33
+ /**
34
+ * Vite plugin that injects the Rspnse inspector script into dev server pages.
35
+ * This enables inspect functionality from rspnse.net without a browser extension.
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * // vite.config.ts
40
+ * import { rspnseInspector } from '@rspnseapp/dev-inspector';
41
+ *
42
+ * export default {
43
+ * plugins: [rspnseInspector()]
44
+ * }
45
+ * ```
46
+ */
47
+ declare function rspnseInspector(options?: RspnseInspectorOptions): Plugin;
48
+
49
+ export { type BreadcrumbItem, type InspectedElement, type RspnseInspectorOptions, type StyleEntry, rspnseInspector };
package/dist/index.js CHANGED
@@ -2,18 +2,27 @@
2
2
  import { readFileSync } from "fs";
3
3
  import { resolve, dirname } from "path";
4
4
  import { fileURLToPath } from "url";
5
- var __dirname = dirname(fileURLToPath(import.meta.url));
5
+ function getDirname() {
6
+ if (typeof import.meta !== "undefined" && import.meta.url) {
7
+ return dirname(fileURLToPath(import.meta.url));
8
+ }
9
+ if (typeof __dirname !== "undefined") {
10
+ return __dirname;
11
+ }
12
+ return process.cwd();
13
+ }
14
+ var moduleDir = getDirname();
6
15
  function rspnseInspector(options = {}) {
7
16
  const { enabled = true, trustedOrigins } = options;
8
17
  let inspectorScript = null;
9
18
  function getInspectorScript() {
10
19
  if (inspectorScript) return inspectorScript;
11
20
  try {
12
- const scriptPath = resolve(__dirname, "../dist/index.inspector.js");
21
+ const scriptPath = resolve(moduleDir, "../dist/index.inspector.js");
13
22
  inspectorScript = readFileSync(scriptPath, "utf-8");
14
23
  } catch {
15
24
  try {
16
- const scriptPath = resolve(__dirname, "./index.inspector.js");
25
+ const scriptPath = resolve(moduleDir, "./index.inspector.js");
17
26
  inspectorScript = readFileSync(scriptPath, "utf-8");
18
27
  } catch {
19
28
  console.warn(
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/vite-plugin.ts"],"sourcesContent":["import type { Plugin } from 'vite';\nimport { readFileSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport type { RspnseInspectorOptions } from './types';\n\n// Get the directory of this module\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n/**\n * Vite plugin that injects the Rspnse inspector script into dev server pages.\n * This enables inspect functionality from rspnse.net without a browser extension.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { rspnseInspector } from '@rspnseapp/dev-inspector';\n *\n * export default {\n * plugins: [rspnseInspector()]\n * }\n * ```\n */\nexport function rspnseInspector(options: RspnseInspectorOptions = {}): Plugin {\n const { enabled = true, trustedOrigins } = options;\n\n // Cache the inspector script content\n let inspectorScript: string | null = null;\n\n function getInspectorScript(): string {\n if (inspectorScript) return inspectorScript;\n\n try {\n // Try to load the bundled inspector script\n const scriptPath = resolve(__dirname, '../dist/index.inspector.js');\n inspectorScript = readFileSync(scriptPath, 'utf-8');\n } catch {\n // Fallback: load from same directory (during development)\n try {\n const scriptPath = resolve(__dirname, './index.inspector.js');\n inspectorScript = readFileSync(scriptPath, 'utf-8');\n } catch {\n console.warn(\n '[@rspnseapp/dev-inspector] Could not load inspector script. Run `npm run build` first.'\n );\n inspectorScript = '// Inspector script not found';\n }\n }\n\n return inspectorScript;\n }\n\n return {\n name: 'rspnse-inspector',\n\n // Only apply in dev mode\n apply: 'serve',\n\n configureServer(server) {\n if (!enabled) return;\n\n // Serve the inspector script at a special path\n server.middlewares.use((req, res, next) => {\n if (req.url === '/@rspnse-inspector/inspector.js') {\n res.setHeader('Content-Type', 'application/javascript');\n res.setHeader('Cache-Control', 'no-cache');\n\n let script = getInspectorScript();\n\n // If custom trusted origins are provided, inject them\n if (trustedOrigins && trustedOrigins.length > 0) {\n const originsArray = JSON.stringify(trustedOrigins);\n script = `window.__RSPNSE_TRUSTED_ORIGINS__ = ${originsArray};\\n${script}`;\n }\n\n res.end(script);\n return;\n }\n next();\n });\n },\n\n transformIndexHtml(html) {\n if (!enabled) return html;\n\n // Inject the inspector script before </head>\n const scriptTag = `<script src=\"/@rspnse-inspector/inspector.js\" defer></script>`;\n\n if (html.includes('</head>')) {\n return html.replace('</head>', `${scriptTag}\\n</head>`);\n }\n\n // Fallback: inject at start of body if no head tag\n if (html.includes('<body')) {\n return html.replace(/<body([^>]*)>/, `<body$1>\\n${scriptTag}`);\n }\n\n // Last resort: prepend to html\n return scriptTag + '\\n' + html;\n },\n };\n}\n"],"mappings":";AACA,SAAS,oBAAoB;AAC7B,SAAS,SAAS,eAAe;AACjC,SAAS,qBAAqB;AAI9B,IAAM,YAAY,QAAQ,cAAc,YAAY,GAAG,CAAC;AAgBjD,SAAS,gBAAgB,UAAkC,CAAC,GAAW;AAC5E,QAAM,EAAE,UAAU,MAAM,eAAe,IAAI;AAG3C,MAAI,kBAAiC;AAErC,WAAS,qBAA6B;AACpC,QAAI,gBAAiB,QAAO;AAE5B,QAAI;AAEF,YAAM,aAAa,QAAQ,WAAW,4BAA4B;AAClE,wBAAkB,aAAa,YAAY,OAAO;AAAA,IACpD,QAAQ;AAEN,UAAI;AACF,cAAM,aAAa,QAAQ,WAAW,sBAAsB;AAC5D,0BAAkB,aAAa,YAAY,OAAO;AAAA,MACpD,QAAQ;AACN,gBAAQ;AAAA,UACN;AAAA,QACF;AACA,0BAAkB;AAAA,MACpB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,MAAM;AAAA;AAAA,IAGN,OAAO;AAAA,IAEP,gBAAgB,QAAQ;AACtB,UAAI,CAAC,QAAS;AAGd,aAAO,YAAY,IAAI,CAAC,KAAK,KAAK,SAAS;AACzC,YAAI,IAAI,QAAQ,mCAAmC;AACjD,cAAI,UAAU,gBAAgB,wBAAwB;AACtD,cAAI,UAAU,iBAAiB,UAAU;AAEzC,cAAI,SAAS,mBAAmB;AAGhC,cAAI,kBAAkB,eAAe,SAAS,GAAG;AAC/C,kBAAM,eAAe,KAAK,UAAU,cAAc;AAClD,qBAAS,uCAAuC,YAAY;AAAA,EAAM,MAAM;AAAA,UAC1E;AAEA,cAAI,IAAI,MAAM;AACd;AAAA,QACF;AACA,aAAK;AAAA,MACP,CAAC;AAAA,IACH;AAAA,IAEA,mBAAmB,MAAM;AACvB,UAAI,CAAC,QAAS,QAAO;AAGrB,YAAM,YAAY;AAElB,UAAI,KAAK,SAAS,SAAS,GAAG;AAC5B,eAAO,KAAK,QAAQ,WAAW,GAAG,SAAS;AAAA,QAAW;AAAA,MACxD;AAGA,UAAI,KAAK,SAAS,OAAO,GAAG;AAC1B,eAAO,KAAK,QAAQ,iBAAiB;AAAA,EAAa,SAAS,EAAE;AAAA,MAC/D;AAGA,aAAO,YAAY,OAAO;AAAA,IAC5B;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/vite-plugin.ts"],"sourcesContent":["import type { Plugin } from 'vite';\nimport { readFileSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport type { RspnseInspectorOptions } from './types';\n\n// Get the directory of this module (works in both ESM and CJS)\nfunction getDirname(): string {\n // ESM: use import.meta.url\n if (typeof import.meta !== 'undefined' && import.meta.url) {\n return dirname(fileURLToPath(import.meta.url));\n }\n // CJS: __dirname is globally available (injected by bundler)\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n if (typeof __dirname !== 'undefined') {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return __dirname;\n }\n // Fallback: use process.cwd()\n return process.cwd();\n}\n\nconst moduleDir = getDirname();\n\n/**\n * Vite plugin that injects the Rspnse inspector script into dev server pages.\n * This enables inspect functionality from rspnse.net without a browser extension.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { rspnseInspector } from '@rspnseapp/dev-inspector';\n *\n * export default {\n * plugins: [rspnseInspector()]\n * }\n * ```\n */\nexport function rspnseInspector(options: RspnseInspectorOptions = {}): Plugin {\n const { enabled = true, trustedOrigins } = options;\n\n // Cache the inspector script content\n let inspectorScript: string | null = null;\n\n function getInspectorScript(): string {\n if (inspectorScript) return inspectorScript;\n\n try {\n // Try to load the bundled inspector script\n const scriptPath = resolve(moduleDir, '../dist/index.inspector.js');\n inspectorScript = readFileSync(scriptPath, 'utf-8');\n } catch {\n // Fallback: load from same directory (during development)\n try {\n const scriptPath = resolve(moduleDir, './index.inspector.js');\n inspectorScript = readFileSync(scriptPath, 'utf-8');\n } catch {\n console.warn(\n '[@rspnseapp/dev-inspector] Could not load inspector script. Run `npm run build` first.'\n );\n inspectorScript = '// Inspector script not found';\n }\n }\n\n return inspectorScript;\n }\n\n return {\n name: 'rspnse-inspector',\n\n // Only apply in dev mode\n apply: 'serve',\n\n configureServer(server) {\n if (!enabled) return;\n\n // Serve the inspector script at a special path\n server.middlewares.use((req, res, next) => {\n if (req.url === '/@rspnse-inspector/inspector.js') {\n res.setHeader('Content-Type', 'application/javascript');\n res.setHeader('Cache-Control', 'no-cache');\n\n let script = getInspectorScript();\n\n // If custom trusted origins are provided, inject them\n if (trustedOrigins && trustedOrigins.length > 0) {\n const originsArray = JSON.stringify(trustedOrigins);\n script = `window.__RSPNSE_TRUSTED_ORIGINS__ = ${originsArray};\\n${script}`;\n }\n\n res.end(script);\n return;\n }\n next();\n });\n },\n\n transformIndexHtml(html) {\n if (!enabled) return html;\n\n // Inject the inspector script before </head>\n const scriptTag = `<script src=\"/@rspnse-inspector/inspector.js\" defer></script>`;\n\n if (html.includes('</head>')) {\n return html.replace('</head>', `${scriptTag}\\n</head>`);\n }\n\n // Fallback: inject at start of body if no head tag\n if (html.includes('<body')) {\n return html.replace(/<body([^>]*)>/, `<body$1>\\n${scriptTag}`);\n }\n\n // Last resort: prepend to html\n return scriptTag + '\\n' + html;\n },\n };\n}\n"],"mappings":";AACA,SAAS,oBAAoB;AAC7B,SAAS,SAAS,eAAe;AACjC,SAAS,qBAAqB;AAI9B,SAAS,aAAqB;AAE5B,MAAI,OAAO,gBAAgB,eAAe,YAAY,KAAK;AACzD,WAAO,QAAQ,cAAc,YAAY,GAAG,CAAC;AAAA,EAC/C;AAIA,MAAI,OAAO,cAAc,aAAa;AAGpC,WAAO;AAAA,EACT;AAEA,SAAO,QAAQ,IAAI;AACrB;AAEA,IAAM,YAAY,WAAW;AAgBtB,SAAS,gBAAgB,UAAkC,CAAC,GAAW;AAC5E,QAAM,EAAE,UAAU,MAAM,eAAe,IAAI;AAG3C,MAAI,kBAAiC;AAErC,WAAS,qBAA6B;AACpC,QAAI,gBAAiB,QAAO;AAE5B,QAAI;AAEF,YAAM,aAAa,QAAQ,WAAW,4BAA4B;AAClE,wBAAkB,aAAa,YAAY,OAAO;AAAA,IACpD,QAAQ;AAEN,UAAI;AACF,cAAM,aAAa,QAAQ,WAAW,sBAAsB;AAC5D,0BAAkB,aAAa,YAAY,OAAO;AAAA,MACpD,QAAQ;AACN,gBAAQ;AAAA,UACN;AAAA,QACF;AACA,0BAAkB;AAAA,MACpB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,MAAM;AAAA;AAAA,IAGN,OAAO;AAAA,IAEP,gBAAgB,QAAQ;AACtB,UAAI,CAAC,QAAS;AAGd,aAAO,YAAY,IAAI,CAAC,KAAK,KAAK,SAAS;AACzC,YAAI,IAAI,QAAQ,mCAAmC;AACjD,cAAI,UAAU,gBAAgB,wBAAwB;AACtD,cAAI,UAAU,iBAAiB,UAAU;AAEzC,cAAI,SAAS,mBAAmB;AAGhC,cAAI,kBAAkB,eAAe,SAAS,GAAG;AAC/C,kBAAM,eAAe,KAAK,UAAU,cAAc;AAClD,qBAAS,uCAAuC,YAAY;AAAA,EAAM,MAAM;AAAA,UAC1E;AAEA,cAAI,IAAI,MAAM;AACd;AAAA,QACF;AACA,aAAK;AAAA,MACP,CAAC;AAAA,IACH;AAAA,IAEA,mBAAmB,MAAM;AACvB,UAAI,CAAC,QAAS,QAAO;AAGrB,YAAM,YAAY;AAElB,UAAI,KAAK,SAAS,SAAS,GAAG;AAC5B,eAAO,KAAK,QAAQ,WAAW,GAAG,SAAS;AAAA,QAAW;AAAA,MACxD;AAGA,UAAI,KAAK,SAAS,OAAO,GAAG;AAC1B,eAAO,KAAK,QAAQ,iBAAiB;AAAA,EAAa,SAAS,EAAE;AAAA,MAC/D;AAGA,aAAO,YAAY,OAAO;AAAA,IAC5B;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/webpack.ts
21
+ var webpack_exports = {};
22
+ __export(webpack_exports, {
23
+ RspnseInspectorPlugin: () => RspnseInspectorPlugin,
24
+ rspnseInspector: () => rspnseInspector
25
+ });
26
+ module.exports = __toCommonJS(webpack_exports);
27
+
28
+ // src/webpack-plugin.ts
29
+ var import_fs = require("fs");
30
+ var import_path = require("path");
31
+ var import_url = require("url");
32
+ var import_meta = {};
33
+ var PLUGIN_NAME = "RspnseInspectorPlugin";
34
+ var INSPECTOR_PATH = "/__rspnse-inspector__/inspector.js";
35
+ function getDirname() {
36
+ if (typeof import_meta !== "undefined" && import_meta.url) {
37
+ return (0, import_path.dirname)((0, import_url.fileURLToPath)(import_meta.url));
38
+ }
39
+ if (typeof __dirname !== "undefined") {
40
+ return __dirname;
41
+ }
42
+ return process.cwd();
43
+ }
44
+ var moduleDir = getDirname();
45
+ var RspnseInspectorPlugin = class {
46
+ constructor(options = {}) {
47
+ this.inspectorScript = null;
48
+ this.options = {
49
+ enabled: true,
50
+ ...options
51
+ };
52
+ }
53
+ getInspectorScript() {
54
+ if (this.inspectorScript) return this.inspectorScript;
55
+ try {
56
+ const scriptPath = (0, import_path.resolve)(moduleDir, "index.inspector.js");
57
+ this.inspectorScript = (0, import_fs.readFileSync)(scriptPath, "utf-8");
58
+ } catch {
59
+ console.warn(
60
+ `[${PLUGIN_NAME}] Could not load inspector script from ${moduleDir}.`
61
+ );
62
+ this.inspectorScript = "// Inspector script not found";
63
+ }
64
+ return this.inspectorScript;
65
+ }
66
+ apply(compiler) {
67
+ if (!this.options.enabled) return;
68
+ if (compiler.options.mode !== "development") return;
69
+ const { trustedOrigins } = this.options;
70
+ compiler.hooks.afterEnvironment.tap(PLUGIN_NAME, () => {
71
+ const devServer = compiler.options.devServer;
72
+ if (!devServer) return;
73
+ const originalSetupMiddlewares = devServer.setupMiddlewares;
74
+ devServer.setupMiddlewares = (middlewares, devServerInstance) => {
75
+ middlewares.unshift({
76
+ name: PLUGIN_NAME,
77
+ path: INSPECTOR_PATH,
78
+ middleware: (_req, res) => {
79
+ res.setHeader("Content-Type", "application/javascript");
80
+ res.setHeader("Cache-Control", "no-cache");
81
+ let script = this.getInspectorScript();
82
+ if (trustedOrigins && trustedOrigins.length > 0) {
83
+ const originsArray = JSON.stringify(trustedOrigins);
84
+ script = `window.__RSPNSE_TRUSTED_ORIGINS__ = ${originsArray};
85
+ ${script}`;
86
+ }
87
+ res.end(script);
88
+ }
89
+ });
90
+ if (originalSetupMiddlewares) {
91
+ return originalSetupMiddlewares(middlewares, devServerInstance);
92
+ }
93
+ return middlewares;
94
+ };
95
+ });
96
+ compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
97
+ compilation.hooks.processAssets.tap(
98
+ {
99
+ name: PLUGIN_NAME,
100
+ // Run after HTML has been generated
101
+ stage: 1e3
102
+ },
103
+ (assets) => {
104
+ const scriptTag = `<script src="${INSPECTOR_PATH}" defer></script>`;
105
+ for (const name of Object.keys(assets)) {
106
+ if (name.endsWith(".html")) {
107
+ const asset = assets[name];
108
+ let html = asset.source().toString();
109
+ if (html.includes(INSPECTOR_PATH)) continue;
110
+ if (html.includes("</head>")) {
111
+ html = html.replace("</head>", `${scriptTag}
112
+ </head>`);
113
+ } else if (html.includes("<body")) {
114
+ html = html.replace(/<body([^>]*)>/, `<body$1>
115
+ ${scriptTag}`);
116
+ } else {
117
+ html = scriptTag + "\n" + html;
118
+ }
119
+ const webpack = require("webpack");
120
+ compilation.updateAsset(name, new webpack.sources.RawSource(html));
121
+ }
122
+ }
123
+ }
124
+ );
125
+ });
126
+ }
127
+ };
128
+ function rspnseInspector(options = {}) {
129
+ return new RspnseInspectorPlugin(options);
130
+ }
131
+ // Annotate the CommonJS export names for ESM import in node:
132
+ 0 && (module.exports = {
133
+ RspnseInspectorPlugin,
134
+ rspnseInspector
135
+ });
136
+ //# sourceMappingURL=webpack.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/webpack.ts","../src/webpack-plugin.ts"],"sourcesContent":["/**\n * @rspnseapp/dev-inspector/webpack\n *\n * A Webpack plugin that enables Rspnse inspect functionality on localhost dev servers.\n * Works across all browsers without requiring a browser extension.\n *\n * @example\n * ```ts\n * // webpack.config.js\n * const { RspnseInspectorPlugin } = require('@rspnseapp/dev-inspector/webpack');\n *\n * module.exports = {\n * plugins: [new RspnseInspectorPlugin()]\n * };\n * ```\n *\n * Or using the factory function:\n * ```ts\n * const { rspnseInspector } = require('@rspnseapp/dev-inspector/webpack');\n *\n * module.exports = {\n * plugins: [rspnseInspector()]\n * };\n * ```\n *\n * Then open your site in rspnse.net and use the inspect feature!\n */\n\nexport { RspnseInspectorPlugin, rspnseInspector } from './webpack-plugin';\nexport type {\n RspnseInspectorOptions,\n InspectedElement,\n BreadcrumbItem,\n StyleEntry,\n} from './types';\n","import type { Compiler } from 'webpack';\nimport { readFileSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport type { RspnseInspectorOptions } from './types';\n\nconst PLUGIN_NAME = 'RspnseInspectorPlugin';\nconst INSPECTOR_PATH = '/__rspnse-inspector__/inspector.js';\n\n// Get the directory of this module (works in both ESM and CJS)\nfunction getDirname(): string {\n // ESM: use import.meta.url\n if (typeof import.meta !== 'undefined' && import.meta.url) {\n return dirname(fileURLToPath(import.meta.url));\n }\n // CJS: __dirname is globally available (injected by bundler)\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n if (typeof __dirname !== 'undefined') {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return __dirname;\n }\n // Fallback: use process.cwd()\n return process.cwd();\n}\n\nconst moduleDir = getDirname();\n\n/**\n * Webpack plugin that injects the Rspnse inspector script into dev server pages.\n * This enables inspect functionality from rspnse.net without a browser extension.\n *\n * @example\n * ```ts\n * // webpack.config.js (ESM)\n * import { RspnseInspectorPlugin } from '@rspnseapp/dev-inspector/webpack';\n *\n * export default {\n * plugins: [new RspnseInspectorPlugin()]\n * }\n * ```\n */\nexport class RspnseInspectorPlugin {\n private options: Required<Pick<RspnseInspectorOptions, 'enabled'>> &\n RspnseInspectorOptions;\n private inspectorScript: string | null = null;\n\n constructor(options: RspnseInspectorOptions = {}) {\n this.options = {\n enabled: true,\n ...options,\n };\n }\n\n private getInspectorScript(): string {\n if (this.inspectorScript) return this.inspectorScript;\n\n try {\n // Load the bundled inspector script from dist\n const scriptPath = resolve(moduleDir, 'index.inspector.js');\n this.inspectorScript = readFileSync(scriptPath, 'utf-8');\n } catch {\n console.warn(\n `[${PLUGIN_NAME}] Could not load inspector script from ${moduleDir}.`\n );\n this.inspectorScript = '// Inspector script not found';\n }\n\n return this.inspectorScript;\n }\n\n apply(compiler: Compiler): void {\n if (!this.options.enabled) return;\n\n // Only apply in development mode\n if (compiler.options.mode !== 'development') return;\n\n const { trustedOrigins } = this.options;\n\n // Add middleware to serve the inspector script via devServer\n compiler.hooks.afterEnvironment.tap(PLUGIN_NAME, () => {\n const devServer = compiler.options.devServer as\n | {\n setupMiddlewares?: (\n middlewares: Array<{\n name: string;\n path: string;\n middleware: (\n req: unknown,\n res: { setHeader: (k: string, v: string) => void; end: (s: string) => void }\n ) => void;\n }>,\n devServer: unknown\n ) => unknown[];\n }\n | undefined;\n\n if (!devServer) return;\n\n // Store original setupMiddlewares if it exists\n const originalSetupMiddlewares = devServer.setupMiddlewares;\n\n devServer.setupMiddlewares = (middlewares, devServerInstance) => {\n // Add our middleware first\n middlewares.unshift({\n name: PLUGIN_NAME,\n path: INSPECTOR_PATH,\n middleware: (_req, res) => {\n res.setHeader('Content-Type', 'application/javascript');\n res.setHeader('Cache-Control', 'no-cache');\n\n let script = this.getInspectorScript();\n\n // If custom trusted origins are provided, inject them\n if (trustedOrigins && trustedOrigins.length > 0) {\n const originsArray = JSON.stringify(trustedOrigins);\n script = `window.__RSPNSE_TRUSTED_ORIGINS__ = ${originsArray};\\n${script}`;\n }\n\n res.end(script);\n },\n });\n\n // Call original setupMiddlewares if it exists\n if (originalSetupMiddlewares) {\n return originalSetupMiddlewares(middlewares, devServerInstance) as typeof middlewares;\n }\n\n return middlewares;\n };\n });\n\n // Inject script tag into HTML assets\n compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {\n compilation.hooks.processAssets.tap(\n {\n name: PLUGIN_NAME,\n // Run after HTML has been generated\n stage: 1000,\n },\n (assets) => {\n const scriptTag = `<script src=\"${INSPECTOR_PATH}\" defer></script>`;\n\n for (const name of Object.keys(assets)) {\n if (name.endsWith('.html')) {\n const asset = assets[name];\n let html = asset.source().toString();\n\n // Don't inject twice\n if (html.includes(INSPECTOR_PATH)) continue;\n\n if (html.includes('</head>')) {\n html = html.replace('</head>', `${scriptTag}\\n</head>`);\n } else if (html.includes('<body')) {\n html = html.replace(/<body([^>]*)>/, `<body$1>\\n${scriptTag}`);\n } else {\n html = scriptTag + '\\n' + html;\n }\n\n // Update the asset - use webpack's sources API\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const webpack = require('webpack') as typeof import('webpack');\n compilation.updateAsset(name, new webpack.sources.RawSource(html));\n }\n }\n }\n );\n });\n }\n}\n\n/**\n * Factory function for creating the plugin (alternative to class instantiation)\n */\nexport function rspnseInspector(\n options: RspnseInspectorOptions = {}\n): RspnseInspectorPlugin {\n return new RspnseInspectorPlugin(options);\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,59 @@
1
+ import { Compiler } from 'webpack';
2
+
3
+ interface BreadcrumbItem {
4
+ label: string;
5
+ index: number;
6
+ }
7
+ interface InspectedElement {
8
+ selector: string;
9
+ tagName: string;
10
+ classList: string[];
11
+ id: string | null;
12
+ computedStyles: Record<string, string>;
13
+ }
14
+ interface StyleEntry {
15
+ type: 'inline' | 'external';
16
+ index?: number;
17
+ href?: string;
18
+ css: string | null;
19
+ error?: string;
20
+ }
21
+ interface RspnseInspectorOptions {
22
+ /**
23
+ * Enable/disable the inspector. Defaults to true in development.
24
+ */
25
+ enabled?: boolean;
26
+ /**
27
+ * Trusted origins that can communicate with the inspector.
28
+ * Defaults to ['https://rspnse.net', 'http://localhost']
29
+ */
30
+ trustedOrigins?: string[];
31
+ }
32
+
33
+ /**
34
+ * Webpack plugin that injects the Rspnse inspector script into dev server pages.
35
+ * This enables inspect functionality from rspnse.net without a browser extension.
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * // webpack.config.js (ESM)
40
+ * import { RspnseInspectorPlugin } from '@rspnseapp/dev-inspector/webpack';
41
+ *
42
+ * export default {
43
+ * plugins: [new RspnseInspectorPlugin()]
44
+ * }
45
+ * ```
46
+ */
47
+ declare class RspnseInspectorPlugin {
48
+ private options;
49
+ private inspectorScript;
50
+ constructor(options?: RspnseInspectorOptions);
51
+ private getInspectorScript;
52
+ apply(compiler: Compiler): void;
53
+ }
54
+ /**
55
+ * Factory function for creating the plugin (alternative to class instantiation)
56
+ */
57
+ declare function rspnseInspector(options?: RspnseInspectorOptions): RspnseInspectorPlugin;
58
+
59
+ export { type BreadcrumbItem, type InspectedElement, type RspnseInspectorOptions, RspnseInspectorPlugin, type StyleEntry, rspnseInspector };
package/dist/webpack.js CHANGED
@@ -11,7 +11,16 @@ import { resolve, dirname } from "path";
11
11
  import { fileURLToPath } from "url";
12
12
  var PLUGIN_NAME = "RspnseInspectorPlugin";
13
13
  var INSPECTOR_PATH = "/__rspnse-inspector__/inspector.js";
14
- var __dirname = dirname(fileURLToPath(import.meta.url));
14
+ function getDirname() {
15
+ if (typeof import.meta !== "undefined" && import.meta.url) {
16
+ return dirname(fileURLToPath(import.meta.url));
17
+ }
18
+ if (typeof __dirname !== "undefined") {
19
+ return __dirname;
20
+ }
21
+ return process.cwd();
22
+ }
23
+ var moduleDir = getDirname();
15
24
  var RspnseInspectorPlugin = class {
16
25
  constructor(options = {}) {
17
26
  this.inspectorScript = null;
@@ -23,11 +32,11 @@ var RspnseInspectorPlugin = class {
23
32
  getInspectorScript() {
24
33
  if (this.inspectorScript) return this.inspectorScript;
25
34
  try {
26
- const scriptPath = resolve(__dirname, "index.inspector.js");
35
+ const scriptPath = resolve(moduleDir, "index.inspector.js");
27
36
  this.inspectorScript = readFileSync(scriptPath, "utf-8");
28
37
  } catch {
29
38
  console.warn(
30
- `[${PLUGIN_NAME}] Could not load inspector script from ${__dirname}.`
39
+ `[${PLUGIN_NAME}] Could not load inspector script from ${moduleDir}.`
31
40
  );
32
41
  this.inspectorScript = "// Inspector script not found";
33
42
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/webpack-plugin.ts"],"sourcesContent":["import type { Compiler } from 'webpack';\nimport { readFileSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport type { RspnseInspectorOptions } from './types';\n\nconst PLUGIN_NAME = 'RspnseInspectorPlugin';\nconst INSPECTOR_PATH = '/__rspnse-inspector__/inspector.js';\n\n// Get the directory of this module (ESM)\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n/**\n * Webpack plugin that injects the Rspnse inspector script into dev server pages.\n * This enables inspect functionality from rspnse.net without a browser extension.\n *\n * @example\n * ```ts\n * // webpack.config.js (ESM)\n * import { RspnseInspectorPlugin } from '@rspnseapp/dev-inspector/webpack';\n *\n * export default {\n * plugins: [new RspnseInspectorPlugin()]\n * }\n * ```\n */\nexport class RspnseInspectorPlugin {\n private options: Required<Pick<RspnseInspectorOptions, 'enabled'>> &\n RspnseInspectorOptions;\n private inspectorScript: string | null = null;\n\n constructor(options: RspnseInspectorOptions = {}) {\n this.options = {\n enabled: true,\n ...options,\n };\n }\n\n private getInspectorScript(): string {\n if (this.inspectorScript) return this.inspectorScript;\n\n try {\n // Load the bundled inspector script from dist\n const scriptPath = resolve(__dirname, 'index.inspector.js');\n this.inspectorScript = readFileSync(scriptPath, 'utf-8');\n } catch {\n console.warn(\n `[${PLUGIN_NAME}] Could not load inspector script from ${__dirname}.`\n );\n this.inspectorScript = '// Inspector script not found';\n }\n\n return this.inspectorScript;\n }\n\n apply(compiler: Compiler): void {\n if (!this.options.enabled) return;\n\n // Only apply in development mode\n if (compiler.options.mode !== 'development') return;\n\n const { trustedOrigins } = this.options;\n\n // Add middleware to serve the inspector script via devServer\n compiler.hooks.afterEnvironment.tap(PLUGIN_NAME, () => {\n const devServer = compiler.options.devServer as\n | {\n setupMiddlewares?: (\n middlewares: Array<{\n name: string;\n path: string;\n middleware: (\n req: unknown,\n res: { setHeader: (k: string, v: string) => void; end: (s: string) => void }\n ) => void;\n }>,\n devServer: unknown\n ) => unknown[];\n }\n | undefined;\n\n if (!devServer) return;\n\n // Store original setupMiddlewares if it exists\n const originalSetupMiddlewares = devServer.setupMiddlewares;\n\n devServer.setupMiddlewares = (middlewares, devServerInstance) => {\n // Add our middleware first\n middlewares.unshift({\n name: PLUGIN_NAME,\n path: INSPECTOR_PATH,\n middleware: (_req, res) => {\n res.setHeader('Content-Type', 'application/javascript');\n res.setHeader('Cache-Control', 'no-cache');\n\n let script = this.getInspectorScript();\n\n // If custom trusted origins are provided, inject them\n if (trustedOrigins && trustedOrigins.length > 0) {\n const originsArray = JSON.stringify(trustedOrigins);\n script = `window.__RSPNSE_TRUSTED_ORIGINS__ = ${originsArray};\\n${script}`;\n }\n\n res.end(script);\n },\n });\n\n // Call original setupMiddlewares if it exists\n if (originalSetupMiddlewares) {\n return originalSetupMiddlewares(middlewares, devServerInstance) as typeof middlewares;\n }\n\n return middlewares;\n };\n });\n\n // Inject script tag into HTML assets\n compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {\n compilation.hooks.processAssets.tap(\n {\n name: PLUGIN_NAME,\n // Run after HTML has been generated\n stage: 1000,\n },\n (assets) => {\n const scriptTag = `<script src=\"${INSPECTOR_PATH}\" defer></script>`;\n\n for (const name of Object.keys(assets)) {\n if (name.endsWith('.html')) {\n const asset = assets[name];\n let html = asset.source().toString();\n\n // Don't inject twice\n if (html.includes(INSPECTOR_PATH)) continue;\n\n if (html.includes('</head>')) {\n html = html.replace('</head>', `${scriptTag}\\n</head>`);\n } else if (html.includes('<body')) {\n html = html.replace(/<body([^>]*)>/, `<body$1>\\n${scriptTag}`);\n } else {\n html = scriptTag + '\\n' + html;\n }\n\n // Update the asset - use webpack's sources API\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const webpack = require('webpack') as typeof import('webpack');\n compilation.updateAsset(name, new webpack.sources.RawSource(html));\n }\n }\n }\n );\n });\n }\n}\n\n/**\n * Factory function for creating the plugin (alternative to class instantiation)\n */\nexport function rspnseInspector(\n options: RspnseInspectorOptions = {}\n): RspnseInspectorPlugin {\n return new RspnseInspectorPlugin(options);\n}\n"],"mappings":";;;;;;;;AACA,SAAS,oBAAoB;AAC7B,SAAS,SAAS,eAAe;AACjC,SAAS,qBAAqB;AAG9B,IAAM,cAAc;AACpB,IAAM,iBAAiB;AAGvB,IAAM,YAAY,QAAQ,cAAc,YAAY,GAAG,CAAC;AAgBjD,IAAM,wBAAN,MAA4B;AAAA,EAKjC,YAAY,UAAkC,CAAC,GAAG;AAFlD,SAAQ,kBAAiC;AAGvC,SAAK,UAAU;AAAA,MACb,SAAS;AAAA,MACT,GAAG;AAAA,IACL;AAAA,EACF;AAAA,EAEQ,qBAA6B;AACnC,QAAI,KAAK,gBAAiB,QAAO,KAAK;AAEtC,QAAI;AAEF,YAAM,aAAa,QAAQ,WAAW,oBAAoB;AAC1D,WAAK,kBAAkB,aAAa,YAAY,OAAO;AAAA,IACzD,QAAQ;AACN,cAAQ;AAAA,QACN,IAAI,WAAW,0CAA0C,SAAS;AAAA,MACpE;AACA,WAAK,kBAAkB;AAAA,IACzB;AAEA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,UAA0B;AAC9B,QAAI,CAAC,KAAK,QAAQ,QAAS;AAG3B,QAAI,SAAS,QAAQ,SAAS,cAAe;AAE7C,UAAM,EAAE,eAAe,IAAI,KAAK;AAGhC,aAAS,MAAM,iBAAiB,IAAI,aAAa,MAAM;AACrD,YAAM,YAAY,SAAS,QAAQ;AAgBnC,UAAI,CAAC,UAAW;AAGhB,YAAM,2BAA2B,UAAU;AAE3C,gBAAU,mBAAmB,CAAC,aAAa,sBAAsB;AAE/D,oBAAY,QAAQ;AAAA,UAClB,MAAM;AAAA,UACN,MAAM;AAAA,UACN,YAAY,CAAC,MAAM,QAAQ;AACzB,gBAAI,UAAU,gBAAgB,wBAAwB;AACtD,gBAAI,UAAU,iBAAiB,UAAU;AAEzC,gBAAI,SAAS,KAAK,mBAAmB;AAGrC,gBAAI,kBAAkB,eAAe,SAAS,GAAG;AAC/C,oBAAM,eAAe,KAAK,UAAU,cAAc;AAClD,uBAAS,uCAAuC,YAAY;AAAA,EAAM,MAAM;AAAA,YAC1E;AAEA,gBAAI,IAAI,MAAM;AAAA,UAChB;AAAA,QACF,CAAC;AAGD,YAAI,0BAA0B;AAC5B,iBAAO,yBAAyB,aAAa,iBAAiB;AAAA,QAChE;AAEA,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAGD,aAAS,MAAM,YAAY,IAAI,aAAa,CAAC,gBAAgB;AAC3D,kBAAY,MAAM,cAAc;AAAA,QAC9B;AAAA,UACE,MAAM;AAAA;AAAA,UAEN,OAAO;AAAA,QACT;AAAA,QACA,CAAC,WAAW;AACV,gBAAM,YAAY,gBAAgB,cAAc;AAEhD,qBAAW,QAAQ,OAAO,KAAK,MAAM,GAAG;AACtC,gBAAI,KAAK,SAAS,OAAO,GAAG;AAC1B,oBAAM,QAAQ,OAAO,IAAI;AACzB,kBAAI,OAAO,MAAM,OAAO,EAAE,SAAS;AAGnC,kBAAI,KAAK,SAAS,cAAc,EAAG;AAEnC,kBAAI,KAAK,SAAS,SAAS,GAAG;AAC5B,uBAAO,KAAK,QAAQ,WAAW,GAAG,SAAS;AAAA,QAAW;AAAA,cACxD,WAAW,KAAK,SAAS,OAAO,GAAG;AACjC,uBAAO,KAAK,QAAQ,iBAAiB;AAAA,EAAa,SAAS,EAAE;AAAA,cAC/D,OAAO;AACL,uBAAO,YAAY,OAAO;AAAA,cAC5B;AAIA,oBAAM,UAAU,UAAQ,SAAS;AACjC,0BAAY,YAAY,MAAM,IAAI,QAAQ,QAAQ,UAAU,IAAI,CAAC;AAAA,YACnE;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAKO,SAAS,gBACd,UAAkC,CAAC,GACZ;AACvB,SAAO,IAAI,sBAAsB,OAAO;AAC1C;","names":[]}
1
+ {"version":3,"sources":["../src/webpack-plugin.ts"],"sourcesContent":["import type { Compiler } from 'webpack';\nimport { readFileSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport type { RspnseInspectorOptions } from './types';\n\nconst PLUGIN_NAME = 'RspnseInspectorPlugin';\nconst INSPECTOR_PATH = '/__rspnse-inspector__/inspector.js';\n\n// Get the directory of this module (works in both ESM and CJS)\nfunction getDirname(): string {\n // ESM: use import.meta.url\n if (typeof import.meta !== 'undefined' && import.meta.url) {\n return dirname(fileURLToPath(import.meta.url));\n }\n // CJS: __dirname is globally available (injected by bundler)\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n if (typeof __dirname !== 'undefined') {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return __dirname;\n }\n // Fallback: use process.cwd()\n return process.cwd();\n}\n\nconst moduleDir = getDirname();\n\n/**\n * Webpack plugin that injects the Rspnse inspector script into dev server pages.\n * This enables inspect functionality from rspnse.net without a browser extension.\n *\n * @example\n * ```ts\n * // webpack.config.js (ESM)\n * import { RspnseInspectorPlugin } from '@rspnseapp/dev-inspector/webpack';\n *\n * export default {\n * plugins: [new RspnseInspectorPlugin()]\n * }\n * ```\n */\nexport class RspnseInspectorPlugin {\n private options: Required<Pick<RspnseInspectorOptions, 'enabled'>> &\n RspnseInspectorOptions;\n private inspectorScript: string | null = null;\n\n constructor(options: RspnseInspectorOptions = {}) {\n this.options = {\n enabled: true,\n ...options,\n };\n }\n\n private getInspectorScript(): string {\n if (this.inspectorScript) return this.inspectorScript;\n\n try {\n // Load the bundled inspector script from dist\n const scriptPath = resolve(moduleDir, 'index.inspector.js');\n this.inspectorScript = readFileSync(scriptPath, 'utf-8');\n } catch {\n console.warn(\n `[${PLUGIN_NAME}] Could not load inspector script from ${moduleDir}.`\n );\n this.inspectorScript = '// Inspector script not found';\n }\n\n return this.inspectorScript;\n }\n\n apply(compiler: Compiler): void {\n if (!this.options.enabled) return;\n\n // Only apply in development mode\n if (compiler.options.mode !== 'development') return;\n\n const { trustedOrigins } = this.options;\n\n // Add middleware to serve the inspector script via devServer\n compiler.hooks.afterEnvironment.tap(PLUGIN_NAME, () => {\n const devServer = compiler.options.devServer as\n | {\n setupMiddlewares?: (\n middlewares: Array<{\n name: string;\n path: string;\n middleware: (\n req: unknown,\n res: { setHeader: (k: string, v: string) => void; end: (s: string) => void }\n ) => void;\n }>,\n devServer: unknown\n ) => unknown[];\n }\n | undefined;\n\n if (!devServer) return;\n\n // Store original setupMiddlewares if it exists\n const originalSetupMiddlewares = devServer.setupMiddlewares;\n\n devServer.setupMiddlewares = (middlewares, devServerInstance) => {\n // Add our middleware first\n middlewares.unshift({\n name: PLUGIN_NAME,\n path: INSPECTOR_PATH,\n middleware: (_req, res) => {\n res.setHeader('Content-Type', 'application/javascript');\n res.setHeader('Cache-Control', 'no-cache');\n\n let script = this.getInspectorScript();\n\n // If custom trusted origins are provided, inject them\n if (trustedOrigins && trustedOrigins.length > 0) {\n const originsArray = JSON.stringify(trustedOrigins);\n script = `window.__RSPNSE_TRUSTED_ORIGINS__ = ${originsArray};\\n${script}`;\n }\n\n res.end(script);\n },\n });\n\n // Call original setupMiddlewares if it exists\n if (originalSetupMiddlewares) {\n return originalSetupMiddlewares(middlewares, devServerInstance) as typeof middlewares;\n }\n\n return middlewares;\n };\n });\n\n // Inject script tag into HTML assets\n compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {\n compilation.hooks.processAssets.tap(\n {\n name: PLUGIN_NAME,\n // Run after HTML has been generated\n stage: 1000,\n },\n (assets) => {\n const scriptTag = `<script src=\"${INSPECTOR_PATH}\" defer></script>`;\n\n for (const name of Object.keys(assets)) {\n if (name.endsWith('.html')) {\n const asset = assets[name];\n let html = asset.source().toString();\n\n // Don't inject twice\n if (html.includes(INSPECTOR_PATH)) continue;\n\n if (html.includes('</head>')) {\n html = html.replace('</head>', `${scriptTag}\\n</head>`);\n } else if (html.includes('<body')) {\n html = html.replace(/<body([^>]*)>/, `<body$1>\\n${scriptTag}`);\n } else {\n html = scriptTag + '\\n' + html;\n }\n\n // Update the asset - use webpack's sources API\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const webpack = require('webpack') as typeof import('webpack');\n compilation.updateAsset(name, new webpack.sources.RawSource(html));\n }\n }\n }\n );\n });\n }\n}\n\n/**\n * Factory function for creating the plugin (alternative to class instantiation)\n */\nexport function rspnseInspector(\n options: RspnseInspectorOptions = {}\n): RspnseInspectorPlugin {\n return new RspnseInspectorPlugin(options);\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,19 +1,35 @@
1
1
  {
2
2
  "name": "@rspnseapp/dev-inspector",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Dev server plugins for Rspnse inspect functionality (Vite & Webpack)",
5
5
  "type": "module",
6
- "main": "./dist/index.js",
6
+ "main": "./dist/index.cjs",
7
7
  "module": "./dist/index.js",
8
8
  "types": "./dist/index.d.ts",
9
9
  "exports": {
10
10
  ".": {
11
- "types": "./dist/index.d.ts",
12
- "import": "./dist/index.js"
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
13
19
  },
14
20
  "./webpack": {
15
- "types": "./dist/webpack.d.ts",
16
- "import": "./dist/webpack.js"
21
+ "import": {
22
+ "types": "./dist/webpack.d.ts",
23
+ "default": "./dist/webpack.js"
24
+ },
25
+ "require": {
26
+ "types": "./dist/webpack.d.cts",
27
+ "default": "./dist/webpack.cjs"
28
+ }
29
+ },
30
+ "./inspector": {
31
+ "types": "./dist/index.d.ts",
32
+ "default": "./dist/index.inspector.js"
17
33
  }
18
34
  },
19
35
  "files": [
@@ -35,13 +51,17 @@
35
51
  "css",
36
52
  "devtools"
37
53
  ],
38
- "author": "",
54
+ "author": "AlexBoghh",
39
55
  "license": "MIT",
56
+ "homepage": "https://rspnse.net",
40
57
  "repository": {
41
58
  "type": "git",
42
59
  "url": "git+https://github.com/AlexBoghh/Rspnse.git",
43
60
  "directory": "packages/dev-inspector"
44
61
  },
62
+ "bugs": {
63
+ "url": "https://github.com/AlexBoghh/Rspnse/issues"
64
+ },
45
65
  "peerDependencies": {
46
66
  "vite": ">=4.0.0",
47
67
  "webpack": ">=5.0.0"