UNPKG

one

Version:

One is a new React Framework that makes Vite serve both native and web.

220 lines (218 loc) 8.93 kB
import path from "path"; import { parse } from "oxc-parser"; import { normalizePath } from "vite"; function _type_of(obj) { "@swc/helpers - typeof"; return obj && typeof Symbol < "u" && obj.constructor === Symbol ? "symbol" : typeof obj; } async function findJsxElements(code, filename) { var result = await parse(filename, code); if (result.errors.length > 0) return []; var locations = []; function getJsxName(node) { if (!node) return null; if (node.type === "JSXIdentifier") return node.name; if (node.type === "JSXMemberExpression") { var _node_property, obj = getJsxName(node.object); return obj ? `${obj}.${(_node_property = node.property) === null || _node_property === void 0 ? void 0 : _node_property.name}` : null; } return null; } function getLocation(offset) { var before = code.slice(0, offset), lines = before.split(` `); return { line: lines.length, column: lines[lines.length - 1].length + 1 }; } function walk(node) { if (!(!node || (typeof node > "u" ? "undefined" : _type_of(node)) !== "object")) { if (node.type === "JSXOpeningElement" && node.name) { var tagName = getJsxName(node.name); if (tagName && tagName !== "Fragment" && !tagName.endsWith(".Fragment")) { var _node_attributes, hasSourceAttr = (_node_attributes = node.attributes) === null || _node_attributes === void 0 ? void 0 : _node_attributes.some(function (attr) { var _attr_name; return attr.type === "JSXAttribute" && ((_attr_name = attr.name) === null || _attr_name === void 0 ? void 0 : _attr_name.name) === "data-one-source"; }); if (!hasSourceAttr) { var nameEnd = node.name.end, loc = getLocation(node.start); locations.push({ insertOffset: nameEnd, line: loc.line, column: loc.column }); } } } var _iteratorNormalCompletion = !0, _didIteratorError = !1, _iteratorError = void 0; try { for (var _iterator = Object.keys(node)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = !0) { var key = _step.value; if (key !== "parent") { var value = node[key]; if (Array.isArray(value)) { var _iteratorNormalCompletion1 = !0, _didIteratorError1 = !1, _iteratorError1 = void 0; try { for (var _iterator1 = value[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = !0) { var child = _step1.value; walk(child); } } catch (err) { _didIteratorError1 = !0, _iteratorError1 = err; } finally { try { !_iteratorNormalCompletion1 && _iterator1.return != null && _iterator1.return(); } finally { if (_didIteratorError1) throw _iteratorError1; } } } else value && (typeof value > "u" ? "undefined" : _type_of(value)) === "object" && walk(value); } } } catch (err) { _didIteratorError = !0, _iteratorError = err; } finally { try { !_iteratorNormalCompletion && _iterator.return != null && _iterator.return(); } finally { if (_didIteratorError) throw _iteratorError; } } } } return walk(result.program), locations.sort(function (a, b) { return b.insertOffset - a.insertOffset; }); } async function injectSourceToJsx(code, id) { var [filePath] = id.split("?"); if (filePath) { var location = filePath.replace(normalizePath(process.cwd()), ""); if (!(!code.includes("<") || !code.includes(">"))) { var jsxLocations = await findJsxElements(code, filePath); if (jsxLocations.length !== 0) { var result = code, _iteratorNormalCompletion = !0, _didIteratorError = !1, _iteratorError = void 0; try { for (var _iterator = jsxLocations[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = !0) { var jsx = _step.value, sourceAttr = ` data-one-source="${location}:${jsx.line}:${jsx.column}"`; result = result.slice(0, jsx.insertOffset) + sourceAttr + result.slice(jsx.insertOffset); } } catch (err) { _didIteratorError = !0, _iteratorError = err; } finally { try { !_iteratorNormalCompletion && _iterator.return != null && _iterator.return(); } finally { if (_didIteratorError) throw _iteratorError; } } return { code: result, map: null }; } } } } async function openInEditor(filePath, line, column) { try { var launch = (await import("launch-editor")).default, fullPath = path.join(process.cwd(), filePath), location = `${fullPath}${line ? `:${line}` : ""}${column ? `:${column}` : ""}`; launch(location, void 0, function (filename, errorMessage) { errorMessage && console.warn(`[one:source-inspector] Failed to open ${filename} in editor:`, errorMessage); }); } catch (err) { console.warn("[one:source-inspector] Failed to launch editor:", err); } } var vscodeClients = /* @__PURE__ */new Set(); function sourceInspectorPlugin() { var cache = /* @__PURE__ */new Map(); return [ // Transform plugin - injects data-one-source attributes { name: "one:source-inspector-transform", enforce: "pre", apply: "serve", async transform(code, id) { var _this_environment, envName = (_this_environment = this.environment) === null || _this_environment === void 0 ? void 0 : _this_environment.name; if (!(envName === "ios" || envName === "android") && !(id.includes("node_modules") || id.includes("?raw") || id.includes("dist") || id.includes("build")) && !(!id.endsWith(".jsx") && !id.endsWith(".tsx"))) { if (cache.has(code)) return cache.get(code); var out = await injectSourceToJsx(code, id); return cache.set(code, out), cache.size > 100 && cache.clear(), out; } } }, // Note: Inspector UI script is now injected via DevHead.tsx for SSR compatibility // Server plugin - handles open-source requests and cursor WebSocket { name: "one:source-inspector-server", apply: "serve", configureServer(server) { var wss = null; import("ws").then(function (param) { var { WebSocketServer } = param, _server_httpServer; wss = new WebSocketServer({ noServer: !0 }), (_server_httpServer = server.httpServer) === null || _server_httpServer === void 0 || _server_httpServer.on("upgrade", function (req, socket, head) { req.url === "/__one/cursor" && wss.handleUpgrade(req, socket, head, function (ws) { vscodeClients.add(ws), ws.on("message", function (data) { try { var message = JSON.parse(data.toString()); message.type === "cursor-position" ? server.hot.send("one:cursor-highlight", { file: message.file, line: message.line, column: message.column }) : message.type === "cursor-clear" && server.hot.send("one:cursor-highlight", { clear: !0 }); } catch {} }), ws.on("close", function () { vscodeClients.delete(ws), server.hot.send("one:cursor-highlight", { clear: !0 }); }); }); }); }), server.middlewares.use(async function (req, res, next) { var _req_url; if (!(!((_req_url = req.url) === null || _req_url === void 0) && _req_url.startsWith("/__one/open-source"))) return next(); try { var url = new URL(req.url, "http://localhost"), source = url.searchParams.get("source"); if (!source) { res.statusCode = 400, res.end("Missing source parameter"); return; } var parts = source.split(":"), column = parts.pop(), line = parts.pop(), filePath = parts.join(":"); await openInEditor(filePath, line, column), res.statusCode = 200, res.end("OK"); } catch (err) { console.error("[one:source-inspector] Error:", err), res.statusCode = 500, res.end("Internal server error"); } }); } }]; } export { sourceInspectorPlugin }; //# sourceMappingURL=sourceInspectorPlugin.native.js.map