annotask 0.0.0 → 0.0.2
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/LICENSE +21 -0
- package/README.md +45 -3
- package/dist/chunk-GHDLRMQG.js +61 -0
- package/dist/chunk-GHDLRMQG.js.map +1 -0
- package/dist/chunk-HW7MHAEC.js +832 -0
- package/dist/chunk-HW7MHAEC.js.map +1 -0
- package/dist/chunk-JLOSPIJ4.js +340 -0
- package/dist/chunk-JLOSPIJ4.js.map +1 -0
- package/dist/chunk-JPNMDGZN.js +61 -0
- package/dist/chunk-JPNMDGZN.js.map +1 -0
- package/dist/chunk-R6P4MMZW.js +340 -0
- package/dist/chunk-R6P4MMZW.js.map +1 -0
- package/dist/chunk-TUINPVDZ.js +894 -0
- package/dist/chunk-TUINPVDZ.js.map +1 -0
- package/dist/chunk-VI4NPM6C.js +888 -0
- package/dist/chunk-VI4NPM6C.js.map +1 -0
- package/dist/chunk-VU7Z7EZA.js +362 -0
- package/dist/chunk-VU7Z7EZA.js.map +1 -0
- package/dist/chunk-X72ZX6VB.js +835 -0
- package/dist/chunk-X72ZX6VB.js.map +1 -0
- package/dist/chunk-XLNGAH3S.js +29 -0
- package/dist/chunk-XLNGAH3S.js.map +1 -0
- package/dist/cli.js +38 -10
- package/dist/index.d.ts +11 -0
- package/dist/index.js +19 -16
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +4 -1
- package/dist/server.js +1 -1
- package/dist/shell/assets/{index-BD3nZNWX.js → index-BcsdXOsJ.js} +25 -25
- package/dist/shell/favicon.ico +0 -0
- package/dist/shell/index.html +2 -1
- package/dist/standalone.js +3 -3
- package/dist/webpack-loader.js +1 -1
- package/dist/webpack.js +6 -8
- package/dist/webpack.js.map +1 -1
- package/package.json +3 -1
- package/skills/annotask-apply/SKILL.md +8 -0
- package/skills/annotask-watch/SKILL.md +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/plugin/bridge-client.ts"],"sourcesContent":["/**\n * Client bridge script injected into the user's app.\n * Communicates with the Annotask shell via postMessage.\n * Handles all DOM interactions: hover, click, style reads/writes,\n * element resolution, layout scanning, etc.\n *\n * Returned as an inline string (same pattern as toggle-button.ts).\n */\nexport function bridgeClientScript(): string {\n return `\n(function() {\n // Don't run inside the Annotask shell\n if (window.location.pathname.startsWith('/__annotask')) return;\n // Don't run if already initialized\n if (window.__ANNOTASK_BRIDGE__) return;\n window.__ANNOTASK_BRIDGE__ = true;\n\n // ── Element Registry ──────────────────────────────────\n var eidCounter = 0;\n var eidMap = new Map(); // eid string → WeakRef<Element>\n var elToEid = new WeakMap(); // Element → eid string\n\n function getEid(el) {\n if (!el) return null;\n var existing = elToEid.get(el);\n if (existing) return existing;\n eidCounter++;\n var eid = 'e-' + eidCounter;\n eidMap.set(eid, new WeakRef(el));\n elToEid.set(el, eid);\n return eid;\n }\n\n function getEl(eid) {\n var ref = eidMap.get(eid);\n return ref ? ref.deref() || null : null;\n }\n\n // ── PostMessage Helpers ───────────────────────────────\n var shellOrigin = '*'; // Will be tightened on first shell message\n\n function sendToShell(type, payload, id) {\n var msg = { type: type, payload: payload || {}, source: 'annotask-client' };\n if (id) msg.id = id;\n window.parent.postMessage(msg, shellOrigin);\n }\n\n function respond(id, payload) {\n sendToShell(null, payload, id);\n // type is not needed for responses — shell matches by id\n }\n\n // ── Source Element Resolution ─────────────────────────\n function hasSourceAttr(el) {\n return el.hasAttribute && (el.hasAttribute('data-annotask-file') || el.hasAttribute('data-astro-source-file'));\n }\n\n function findSourceElement(el) {\n var c = el;\n while (c) {\n if (hasSourceAttr(c)) return { sourceEl: c, targetEl: el };\n c = c.parentElement;\n }\n return { sourceEl: el, targetEl: el };\n }\n\n function getSourceData(el) {\n // Prefer data-annotask-* attributes, fall back to data-astro-source-* (Astro framework)\n var file = el.getAttribute('data-annotask-file') || '';\n var line = el.getAttribute('data-annotask-line') || '';\n var component = el.getAttribute('data-annotask-component') || '';\n\n if (!file && el.getAttribute('data-astro-source-file')) {\n var astroFile = el.getAttribute('data-astro-source-file') || '';\n // Convert absolute path to project-relative by finding src/ prefix\n var srcIdx = astroFile.indexOf('/src/');\n file = srcIdx !== -1 ? astroFile.slice(srcIdx + 1) : astroFile;\n }\n if ((!line || line === '0') && el.getAttribute('data-astro-source-loc')) {\n // data-astro-source-loc format: \"line:col\"\n line = (el.getAttribute('data-astro-source-loc') || '').split(':')[0];\n }\n if (!component && file) {\n // Derive component name from file path\n var parts = file.split('/');\n var fileName = parts[parts.length - 1] || '';\n component = fileName.replace(/\\.[^.]+$/, '');\n }\n\n var mfe = el.getAttribute('data-annotask-mfe') || '';\n\n return { file: file, line: line, component: component, mfe: mfe };\n }\n\n function getRect(el) {\n var r = el.getBoundingClientRect();\n return { x: r.x, y: r.y, width: r.width, height: r.height };\n }\n\n // ── Interaction Mode ──────────────────────────────────\n var storedMode = '';\n try { storedMode = localStorage.getItem('annotask:mode') || ''; } catch(e) {}\n var currentMode = storedMode || 'select';\n var inspectModes = { select: true, pin: true };\n\n // ── Event Handlers ────────────────────────────────────\n var lastHoverEid = null;\n var rafPending = false;\n var pendingHoverData = null;\n\n function onMouseOver(e) {\n if (!inspectModes[currentMode]) return;\n var el = e.target;\n if (!el || el === document.documentElement || el === document.body) return;\n var eid = getEid(el);\n if (eid === lastHoverEid) return;\n lastHoverEid = eid;\n\n var source = findSourceElement(el);\n var data = getSourceData(source.sourceEl);\n\n pendingHoverData = {\n eid: eid,\n tag: el.tagName.toLowerCase(),\n file: data.file,\n component: data.component,\n rect: getRect(el)\n };\n\n if (!rafPending) {\n rafPending = true;\n requestAnimationFrame(function() {\n rafPending = false;\n if (pendingHoverData) sendToShell('hover:enter', pendingHoverData);\n });\n }\n }\n\n function onMouseOut(e) {\n if (!inspectModes[currentMode]) return;\n // Only fire leave when truly leaving all elements\n if (e.relatedTarget && e.relatedTarget !== document.documentElement) return;\n lastHoverEid = null;\n pendingHoverData = null;\n sendToShell('hover:leave', {});\n }\n\n function onClick(e) {\n if (!inspectModes[currentMode]) return;\n e.preventDefault();\n e.stopPropagation();\n\n var el = e.target;\n if (!el) return;\n\n var source = findSourceElement(el);\n var data = getSourceData(source.sourceEl);\n var targetEl = source.targetEl;\n var classes = typeof targetEl.className === 'string' ? targetEl.className : '';\n\n sendToShell('click:element', {\n eid: getEid(targetEl),\n sourceEid: getEid(source.sourceEl),\n file: data.file,\n line: data.line,\n component: data.component,\n mfe: data.mfe,\n tag: targetEl.tagName.toLowerCase(),\n classes: classes,\n rect: getRect(targetEl),\n shiftKey: e.shiftKey,\n clientX: e.clientX,\n clientY: e.clientY\n });\n }\n\n function onMouseDown(e) {\n if (!inspectModes[currentMode]) return;\n e.stopPropagation();\n }\n\n function onMouseUp(e) {\n if (currentMode !== 'highlight') return;\n var sel = document.getSelection();\n var text = sel ? sel.toString().trim() : '';\n if (!text || text.length < 2) return;\n var anchorEl = sel.anchorNode ? sel.anchorNode.parentElement : null;\n if (!anchorEl) return;\n var source = findSourceElement(anchorEl);\n var data = getSourceData(source.sourceEl);\n\n sendToShell('selection:text', {\n text: text,\n eid: getEid(anchorEl),\n file: data.file,\n line: parseInt(data.line) || 0,\n component: data.component,\n mfe: data.mfe,\n tag: anchorEl.tagName.toLowerCase()\n });\n }\n\n function onContextMenu(e) {\n if (currentMode === 'interact') return;\n e.preventDefault();\n var el = e.target;\n if (!el) return;\n var source = findSourceElement(el);\n var data = getSourceData(source.sourceEl);\n var targetEl = source.targetEl;\n var classes = typeof targetEl.className === 'string' ? targetEl.className : '';\n\n sendToShell('contextmenu:element', {\n eid: getEid(targetEl),\n sourceEid: getEid(source.sourceEl),\n file: data.file,\n line: data.line,\n component: data.component,\n mfe: data.mfe,\n tag: targetEl.tagName.toLowerCase(),\n classes: classes,\n rect: getRect(targetEl),\n shiftKey: false,\n clientX: e.clientX,\n clientY: e.clientY\n });\n }\n\n function onKeyDown(e) {\n if ((e.ctrlKey || e.metaKey) && e.key === 'z' && !e.shiftKey) {\n e.preventDefault();\n sendToShell('keydown', { key: e.key, ctrlKey: e.ctrlKey, metaKey: e.metaKey, shiftKey: e.shiftKey });\n }\n }\n\n // Install event listeners\n document.addEventListener('mouseover', onMouseOver, { capture: true });\n document.addEventListener('mouseout', onMouseOut, { capture: true });\n document.addEventListener('mousedown', onMouseDown, { capture: true });\n document.addEventListener('click', onClick, { capture: true });\n document.addEventListener('mouseup', onMouseUp, { capture: true });\n document.addEventListener('keydown', onKeyDown, { capture: true });\n document.addEventListener('contextmenu', onContextMenu, { capture: true });\n\n // ── Route Tracking ────────────────────────────────────\n var lastRoute = window.location.pathname;\n\n function checkRoute() {\n var path = window.location.pathname;\n if (path !== lastRoute) {\n lastRoute = path;\n sendToShell('route:changed', { path: path });\n }\n }\n\n window.addEventListener('popstate', checkRoute);\n window.addEventListener('hashchange', checkRoute);\n setInterval(checkRoute, 2000); // safety net for pushState\n\n // ── Message Handler ───────────────────────────────────\n window.addEventListener('message', function(event) {\n var msg = event.data;\n if (!msg || msg.source !== 'annotask-shell') return;\n // Tighten origin on first shell message\n if (shellOrigin === '*' && event.origin) shellOrigin = event.origin;\n\n var type = msg.type;\n var payload = msg.payload || {};\n var id = msg.id;\n\n // ── Mode ──\n if (type === 'mode:set') {\n currentMode = payload.mode || 'select';\n try { localStorage.setItem('annotask:mode', currentMode); } catch(e) {}\n return;\n }\n\n // ── Ping ──\n if (type === 'bridge:ping') {\n respond(id, {});\n return;\n }\n\n // ── Element Resolution ──\n if (type === 'resolve:at-point') {\n var el = document.elementFromPoint(payload.x, payload.y);\n if (!el || el === document.documentElement || el === document.body) {\n respond(id, null);\n return;\n }\n var src = findSourceElement(el);\n var srcData = getSourceData(src.sourceEl);\n respond(id, {\n eid: getEid(src.targetEl),\n file: srcData.file,\n line: srcData.line,\n component: srcData.component,\n mfe: srcData.mfe,\n tag: src.sourceEl.tagName.toLowerCase(),\n rect: getRect(src.sourceEl),\n classes: typeof src.targetEl.className === 'string' ? src.targetEl.className : ''\n });\n return;\n }\n\n if (type === 'resolve:template-group') {\n var all = document.querySelectorAll(\n '[data-annotask-file=\"' + payload.file + '\"][data-annotask-line=\"' + payload.line + '\"]'\n );\n // Also check Astro source attributes\n if (all.length === 0 && payload.file && payload.line) {\n // Try matching by astro source attributes (absolute path ends with file, loc starts with line)\n var astroAll = document.querySelectorAll('[data-astro-source-file]');\n var matched = [];\n for (var ai = 0; ai < astroAll.length; ai++) {\n var af = astroAll[ai].getAttribute('data-astro-source-file') || '';\n var al = (astroAll[ai].getAttribute('data-astro-source-loc') || '').split(':')[0];\n if (af.endsWith('/' + payload.file) && al === payload.line) matched.push(astroAll[ai]);\n }\n if (matched.length > 0) all = matched;\n }\n var eids = [];\n var rects = [];\n for (var i = 0; i < all.length; i++) {\n if (all[i].tagName.toLowerCase() === payload.tagName) {\n eids.push(getEid(all[i]));\n rects.push(getRect(all[i]));\n }\n }\n respond(id, { eids: eids, rects: rects });\n return;\n }\n\n if (type === 'resolve:rect') {\n var rEl = getEl(payload.eid);\n respond(id, rEl ? { rect: getRect(rEl) } : null);\n return;\n }\n\n if (type === 'resolve:rects') {\n var results = [];\n for (var j = 0; j < payload.eids.length; j++) {\n var re = getEl(payload.eids[j]);\n results.push(re ? getRect(re) : null);\n }\n respond(id, { rects: results });\n return;\n }\n\n // ── Style Operations ──\n if (type === 'style:get-computed') {\n var sEl = getEl(payload.eid);\n if (!sEl) { respond(id, { styles: {} }); return; }\n var cs = window.getComputedStyle(sEl);\n var styles = {};\n for (var k = 0; k < payload.properties.length; k++) {\n styles[payload.properties[k]] = cs.getPropertyValue(payload.properties[k]);\n }\n respond(id, { styles: styles });\n return;\n }\n\n if (type === 'style:apply') {\n var aEl = getEl(payload.eid);\n if (!aEl) { respond(id, { before: '' }); return; }\n var before = window.getComputedStyle(aEl).getPropertyValue(payload.property);\n aEl.style.setProperty(payload.property, payload.value);\n respond(id, { before: before });\n return;\n }\n\n if (type === 'style:apply-batch') {\n var befores = [];\n for (var m = 0; m < payload.eids.length; m++) {\n var bEl = getEl(payload.eids[m]);\n if (bEl) {\n befores.push(window.getComputedStyle(bEl).getPropertyValue(payload.property));\n bEl.style.setProperty(payload.property, payload.value);\n } else {\n befores.push('');\n }\n }\n respond(id, { befores: befores });\n return;\n }\n\n if (type === 'style:undo') {\n var uEl = getEl(payload.eid);\n if (uEl) {\n if (payload.value) uEl.style.setProperty(payload.property, payload.value);\n else uEl.style.removeProperty(payload.property);\n }\n respond(id, {});\n return;\n }\n\n if (type === 'class:get') {\n var cEl = getEl(payload.eid);\n respond(id, { classes: cEl ? (typeof cEl.className === 'string' ? cEl.className : '') : '' });\n return;\n }\n\n if (type === 'class:set') {\n var csEl = getEl(payload.eid);\n if (!csEl) { respond(id, { before: '' }); return; }\n var classBefore = typeof csEl.className === 'string' ? csEl.className : '';\n csEl.className = payload.classes;\n respond(id, { before: classBefore });\n return;\n }\n\n if (type === 'class:set-batch') {\n var classBefores = [];\n for (var n = 0; n < payload.eids.length; n++) {\n var cbEl = getEl(payload.eids[n]);\n if (cbEl) {\n classBefores.push(typeof cbEl.className === 'string' ? cbEl.className : '');\n cbEl.className = payload.classes;\n } else {\n classBefores.push('');\n }\n }\n respond(id, { befores: classBefores });\n return;\n }\n\n if (type === 'class:undo') {\n var cuEl = getEl(payload.eid);\n if (cuEl) cuEl.className = payload.classes;\n respond(id, {});\n return;\n }\n\n // ── Classification ──\n if (type === 'classify:element') {\n var clEl = getEl(payload.eid);\n if (!clEl) { respond(id, null); return; }\n var tag = clEl.tagName.toLowerCase();\n var clCs = window.getComputedStyle(clEl);\n var display = clCs.display;\n var childCount = clEl.children.length;\n var isFlex = display.includes('flex');\n var isGrid = display.includes('grid');\n var semanticContainers = ['section','main','aside','nav','header','footer','article'];\n var role = 'content';\n if (clEl.hasAttribute('data-annotask-component')) {\n var comp = clEl.getAttribute('data-annotask-component') || '';\n if (comp && comp[0] === comp[0].toUpperCase() && comp[0] !== comp[0].toLowerCase()) {\n role = 'component';\n }\n }\n if (role !== 'component' && (isFlex || isGrid) && childCount > 0) role = 'container';\n if (role !== 'component' && role !== 'container' && semanticContainers.indexOf(tag) >= 0 && childCount > 0) role = 'container';\n\n respond(id, {\n role: role,\n display: display,\n isFlexContainer: isFlex,\n isGridContainer: isGrid,\n flexDirection: isFlex ? clCs.flexDirection : undefined,\n childCount: childCount,\n isComponentUnit: role === 'component'\n });\n return;\n }\n\n // ── Layout Scan ──\n if (type === 'layout:scan') {\n var layoutResults = [];\n var allEls = document.querySelectorAll('*');\n for (var li = 0; li < allEls.length; li++) {\n var lEl = allEls[li];\n if (lEl.nodeType !== 1) continue;\n var lCs = window.getComputedStyle(lEl);\n var lDisplay = lCs.display;\n if (!lDisplay.includes('flex') && !lDisplay.includes('grid')) continue;\n var lRect = lEl.getBoundingClientRect();\n if (lRect.width < 20 || lRect.height < 20) continue;\n var lIsGrid = lDisplay.includes('grid');\n var entry = {\n eid: getEid(lEl),\n display: lIsGrid ? 'grid' : 'flex',\n direction: lIsGrid ? 'grid' : lCs.flexDirection,\n rect: { x: lRect.x, y: lRect.y, width: lRect.width, height: lRect.height },\n columnGap: parseFloat(lCs.columnGap) || 0,\n rowGap: parseFloat(lCs.rowGap) || 0\n };\n if (lIsGrid) {\n var cols = lCs.gridTemplateColumns;\n var rows = lCs.gridTemplateRows;\n entry.templateColumns = cols;\n entry.templateRows = rows;\n if (cols && cols !== 'none') {\n entry.columns = cols.split(/\\\\s+/).map(function(s) { return parseFloat(s) || 0; }).filter(function(v) { return v > 0; });\n }\n if (rows && rows !== 'none') {\n entry.rows = rows.split(/\\\\s+/).map(function(s) { return parseFloat(s) || 0; }).filter(function(v) { return v > 0; });\n }\n }\n layoutResults.push(entry);\n }\n respond(id, { containers: layoutResults });\n return;\n }\n\n if (type === 'layout:add-track') {\n var ltEl = getEl(payload.eid);\n if (!ltEl) { respond(id, { property: '', before: '', after: '' }); return; }\n var ltCs = window.getComputedStyle(ltEl);\n var cssProp = payload.axis === 'col' ? 'grid-template-columns' : 'grid-template-rows';\n var ltBefore = ltCs.getPropertyValue(cssProp) || '';\n var ltAfter = ltBefore && ltBefore !== 'none' ? ltBefore + ' 1fr' : '1fr';\n ltEl.style.setProperty(cssProp, ltAfter);\n respond(id, { property: cssProp, before: ltBefore, after: ltAfter });\n return;\n }\n\n if (type === 'layout:add-child') {\n var lcEl = getEl(payload.eid);\n if (!lcEl) { respond(id, { childEid: '' }); return; }\n var child = document.createElement('div');\n child.style.minWidth = '60px';\n child.style.minHeight = '40px';\n child.style.border = '2px dashed #a855f7';\n child.style.borderRadius = '4px';\n child.style.background = 'rgba(168,85,247,0.05)';\n child.setAttribute('data-annotask-placeholder', 'true');\n lcEl.appendChild(child);\n respond(id, { childEid: getEid(child) });\n return;\n }\n\n // ── Theme ──\n if (type === 'theme:inject-css') {\n var existing = document.getElementById(payload.styleId);\n if (existing) {\n existing.textContent = payload.css;\n } else {\n var style = document.createElement('style');\n style.id = payload.styleId;\n style.textContent = payload.css;\n document.head.appendChild(style);\n }\n respond(id, {});\n return;\n }\n\n if (type === 'theme:remove-css') {\n var toRemove = document.getElementById(payload.styleId);\n if (toRemove) toRemove.remove();\n respond(id, {});\n return;\n }\n\n // ── Color Palette ──\n if (type === 'palette:scan-vars') {\n var swatches = [];\n try {\n var rootStyles = window.getComputedStyle(document.documentElement);\n var sheets = document.styleSheets;\n for (var si = 0; si < sheets.length; si++) {\n try {\n var rules = sheets[si].cssRules;\n for (var ri = 0; ri < rules.length; ri++) {\n var rule = rules[ri];\n if (rule.selectorText === ':root' || rule.selectorText === ':root, :host') {\n for (var pi = 0; pi < rule.style.length; pi++) {\n var prop = rule.style[pi];\n if (prop.startsWith('--')) {\n var val = rootStyles.getPropertyValue(prop).trim();\n if (val && isColor(val)) {\n swatches.push({ name: prop, value: val });\n }\n }\n }\n }\n }\n } catch(e) { /* cross-origin stylesheet */ }\n }\n } catch(e) {}\n respond(id, { swatches: swatches });\n return;\n }\n\n // ── Source Mapping Check ──\n if (type === 'check:source-mapping') {\n respond(id, { hasMapping: !!(document.querySelector('[data-annotask-file]') || document.querySelector('[data-astro-source-file]')) });\n return;\n }\n\n // ── Insert Placeholder ──\n if (type === 'insert:placeholder') {\n var ipTarget = getEl(payload.targetEid);\n if (!ipTarget) { respond(id, { placeholderEid: '' }); return; }\n var ipEl = createPlaceholder(payload);\n var ipRef = ipTarget;\n switch (payload.position) {\n case 'before': ipRef.parentElement && ipRef.parentElement.insertBefore(ipEl, ipRef); break;\n case 'after': ipRef.parentElement && ipRef.parentElement.insertBefore(ipEl, ipRef.nextSibling); break;\n case 'append': ipRef.appendChild(ipEl); break;\n case 'prepend': ipRef.insertBefore(ipEl, ipRef.firstChild); break;\n }\n // Match sibling sizes in flex/grid\n var insertParent = (payload.position === 'append' || payload.position === 'prepend') ? ipRef : ipRef.parentElement;\n if (insertParent) {\n var pCs = window.getComputedStyle(insertParent);\n if (pCs.display.includes('flex') || pCs.display.includes('grid')) {\n if (!ipEl.style.width) {\n var isRow = pCs.flexDirection === 'row' || pCs.flexDirection === 'row-reverse' || pCs.display.includes('grid');\n if (isRow) ipEl.style.flex = '1';\n }\n }\n }\n respond(id, { placeholderEid: getEid(ipEl) });\n return;\n }\n\n if (type === 'insert:remove') {\n var irEl = getEl(payload.eid);\n if (irEl) {\n var unmount = irEl.__annotask_unmount;\n if (unmount) unmount();\n irEl.remove();\n }\n respond(id, {});\n return;\n }\n\n if (type === 'move:element') {\n var meEl = getEl(payload.eid);\n var meTarget = getEl(payload.targetEid);\n if (meEl && meTarget) {\n switch (payload.position) {\n case 'before': meTarget.parentElement && meTarget.parentElement.insertBefore(meEl, meTarget); break;\n case 'after': meTarget.parentElement && meTarget.parentElement.insertBefore(meEl, meTarget.nextSibling); break;\n case 'append': meTarget.appendChild(meEl); break;\n case 'prepend': meTarget.insertBefore(meEl, meTarget.firstChild); break;\n }\n }\n respond(id, {});\n return;\n }\n\n if (type === 'insert:vue-component' || type === 'insert:component') {\n var vcTarget = getEl(payload.targetEid);\n if (!vcTarget) { respond(id, { eid: '', mounted: false }); return; }\n var vcContainer = document.createElement('div');\n vcContainer.setAttribute('data-annotask-placeholder', 'true');\n switch (payload.position) {\n case 'before': vcTarget.parentElement && vcTarget.parentElement.insertBefore(vcContainer, vcTarget); break;\n case 'after': vcTarget.parentElement && vcTarget.parentElement.insertBefore(vcContainer, vcTarget.nextSibling); break;\n case 'append': vcTarget.appendChild(vcContainer); break;\n case 'prepend': vcTarget.insertBefore(vcContainer, vcTarget.firstChild); break;\n }\n var mounted = tryMountComponent(vcContainer, payload.componentName, payload.props);\n respond(id, { eid: getEid(vcContainer), mounted: mounted });\n return;\n }\n\n // ── Get source data for an eid ──\n if (type === 'resolve:source') {\n var rsEl = getEl(payload.eid);\n if (!rsEl) { respond(id, null); return; }\n var rsSrc = findSourceElement(rsEl);\n var rsData = getSourceData(rsSrc.sourceEl);\n respond(id, {\n sourceEid: getEid(rsSrc.sourceEl),\n file: rsData.file,\n line: rsData.line,\n component: rsData.component,\n tag: rsSrc.sourceEl.tagName.toLowerCase()\n });\n return;\n }\n\n // ── Route ──\n if (type === 'route:current') {\n respond(id, { path: window.location.pathname });\n return;\n }\n });\n\n // ── Helpers ───────────────────────────────────────────\n function isColor(val) {\n if (val.startsWith('#') || val.startsWith('rgb') || val.startsWith('hsl')) return true;\n // Named colors — quick check with canvas\n try {\n var ctx = document.createElement('canvas').getContext('2d');\n ctx.fillStyle = '#000000';\n ctx.fillStyle = val;\n return ctx.fillStyle !== '#000000' || val === 'black' || val === '#000000';\n } catch(e) { return false; }\n }\n\n function createPlaceholder(payload) {\n var el = document.createElement(payload.tag);\n el.setAttribute('data-annotask-placeholder', 'true');\n if (payload.classes) el.className = payload.classes;\n var tag = payload.tag.toLowerCase();\n var isComponent = payload.tag.includes('-') || (payload.tag[0] === payload.tag[0].toUpperCase() && payload.tag[0] !== payload.tag[0].toLowerCase());\n\n if (tag === 'button') {\n el.textContent = payload.textContent || 'Button';\n el.style.cssText = 'padding:8px 16px;border-radius:6px;font-size:14px;font-weight:500;cursor:pointer;border:1px solid currentColor;background:var(--accent,#3b82f6);color:white;';\n } else if (tag === 'input') {\n el.type = 'text'; el.placeholder = 'Input field...';\n el.style.cssText = 'padding:8px 12px;border:1px solid #ccc;border-radius:6px;font-size:14px;width:100%;max-width:300px;background:white;color:#333;';\n } else if (tag === 'textarea') {\n el.placeholder = 'Text area...';\n el.style.cssText = 'padding:8px 12px;border:1px solid #ccc;border-radius:6px;font-size:14px;width:100%;min-height:60px;background:white;color:#333;resize:vertical;';\n } else if (tag === 'img') {\n el.style.cssText = 'width:200px;height:120px;background:#e5e7eb;border-radius:8px;display:flex;align-items:center;justify-content:center;';\n } else if (['h1','h2','h3','h4','h5','h6'].indexOf(tag) >= 0) {\n el.textContent = payload.textContent || 'Heading';\n var sizes = { h1:'2em', h2:'1.5em', h3:'1.25em', h4:'1.1em', h5:'1em', h6:'0.9em' };\n el.style.cssText = 'font-size:' + (sizes[tag]||'1em') + ';font-weight:700;margin:0.5em 0;';\n } else if (tag === 'p') {\n el.textContent = payload.textContent || 'Paragraph text goes here.';\n el.style.cssText = 'margin:0.5em 0;line-height:1.5;';\n } else if (tag === 'a') {\n el.textContent = payload.textContent || 'Link';\n el.style.cssText = 'color:var(--accent,#3b82f6);text-decoration:underline;cursor:pointer;';\n } else if (tag === 'section' || tag === 'div' || tag === 'nav' || tag === 'header' || tag === 'footer' || tag === 'aside' || tag === 'main') {\n if (!payload.classes && !payload.textContent) {\n el.style.cssText = 'min-height:40px;padding:12px;border:1.5px dashed rgba(59,130,246,0.3);border-radius:6px;background:rgba(59,130,246,0.03);';\n } else if (payload.textContent) {\n el.textContent = payload.textContent;\n }\n if (payload.category === 'layout-preset') {\n el.style.minHeight = '60px';\n el.style.padding = el.style.padding || '12px';\n el.style.border = '1.5px dashed rgba(34,197,94,0.3)';\n el.style.borderRadius = '6px';\n el.style.background = 'rgba(34,197,94,0.03)';\n }\n } else if (isComponent) {\n var vcMounted = tryMountComponent(el, payload.tag, payload.defaultProps);\n if (!vcMounted) {\n el.style.cssText = 'min-height:80px;padding:16px;border:1px solid rgba(168,85,247,0.2);border-radius:8px;background:rgba(168,85,247,0.03);display:flex;flex-direction:column;gap:8px;overflow:hidden;';\n var hdr = document.createElement('div');\n hdr.style.cssText = 'display:flex;align-items:center;gap:6px;margin-bottom:4px;';\n var dot = document.createElement('span');\n dot.style.cssText = 'width:6px;height:6px;border-radius:50%;background:#a855f7;';\n hdr.appendChild(dot);\n var tagLabel = document.createElement('span');\n tagLabel.style.cssText = 'font-size:11px;font-weight:600;color:#a855f7;';\n tagLabel.textContent = payload.tag;\n hdr.appendChild(tagLabel);\n el.appendChild(hdr);\n }\n } else {\n el.textContent = payload.textContent || '';\n }\n return el;\n }\n\n function tryMountComponent(container, componentName, props) {\n // Try Vue\n if (window.__ANNOTASK_VUE__) {\n var mounted = tryMountVueComponent(container, componentName, props);\n if (mounted) return true;\n }\n // Try React\n if (window.__ANNOTASK_REACT__) {\n var mounted = tryMountReactComponent(container, componentName, props);\n if (mounted) return true;\n }\n // Try Svelte\n if (window.__ANNOTASK_SVELTE__) {\n var mounted = tryMountSvelteComponent(container, componentName, props);\n if (mounted) return true;\n }\n return false;\n }\n\n function tryMountVueComponent(container, componentName, props) {\n try {\n var appEl = document.querySelector('#app');\n var vueApp = appEl && appEl.__vue_app__;\n if (!vueApp) return false;\n var annotaskVue = window.__ANNOTASK_VUE__;\n if (!annotaskVue || !annotaskVue.createApp || !annotaskVue.h) return false;\n var component = vueApp._context.components[componentName] || (window.__ANNOTASK_COMPONENTS__ && window.__ANNOTASK_COMPONENTS__[componentName]);\n if (!component) return false;\n var mountPoint = document.createElement('div');\n container.appendChild(mountPoint);\n var miniApp = annotaskVue.createApp({\n render: function() { return annotaskVue.h(component, props || {}); }\n });\n miniApp._context = vueApp._context;\n miniApp.mount(mountPoint);\n container.setAttribute('data-annotask-mounted', 'true');\n container.__annotask_unmount = function() { try { miniApp.unmount(); } catch(e) {} };\n return true;\n } catch(e) { return false; }\n }\n\n function tryMountReactComponent(container, componentName, props) {\n try {\n var annotaskReact = window.__ANNOTASK_REACT__;\n if (!annotaskReact || !annotaskReact.createElement || !annotaskReact.createRoot) return false;\n var component = window.__ANNOTASK_COMPONENTS__ && window.__ANNOTASK_COMPONENTS__[componentName];\n if (!component) return false;\n var mountPoint = document.createElement('div');\n container.appendChild(mountPoint);\n var root = annotaskReact.createRoot(mountPoint);\n root.render(annotaskReact.createElement(component, props || {}));\n container.setAttribute('data-annotask-mounted', 'true');\n container.__annotask_unmount = function() { try { root.unmount(); } catch(e) {} };\n return true;\n } catch(e) { return false; }\n }\n\n function tryMountSvelteComponent(container, componentName, props) {\n try {\n var annotaskSvelte = window.__ANNOTASK_SVELTE__;\n if (!annotaskSvelte || !annotaskSvelte.mount) return false;\n var component = window.__ANNOTASK_COMPONENTS__ && window.__ANNOTASK_COMPONENTS__[componentName];\n if (!component) return false;\n var mountPoint = document.createElement('div');\n container.appendChild(mountPoint);\n var instance = annotaskSvelte.mount(component, { target: mountPoint, props: props || {} });\n container.setAttribute('data-annotask-mounted', 'true');\n container.__annotask_unmount = function() {\n try {\n if (annotaskSvelte.unmount) annotaskSvelte.unmount(instance);\n } catch(e) {}\n };\n return true;\n } catch(e) { return false; }\n }\n\n // ── Ready ─────────────────────────────────────────────\n sendToShell('bridge:ready', { version: '1.0' });\n})();\n`.trim()\n}\n"],"mappings":";AAQO,SAAS,qBAA6B;AAC3C,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0zBP,KAAK;AACP;","names":[]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// src/server/discovery.ts
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
function writeServerInfo(projectRoot, port) {
|
|
5
|
+
const dir = path.join(projectRoot, ".annotask");
|
|
6
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
7
|
+
const info = { url: `http://localhost:${port}`, port, pid: process.pid };
|
|
8
|
+
fs.writeFileSync(path.join(dir, "server.json"), JSON.stringify(info, null, 2));
|
|
9
|
+
}
|
|
10
|
+
function writeMfeServerInfo(projectRoot, serverUrl, mfe) {
|
|
11
|
+
const dir = path.join(projectRoot, ".annotask");
|
|
12
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
13
|
+
const url = new URL(serverUrl);
|
|
14
|
+
const info = { url: serverUrl, port: parseInt(url.port) || 80, pid: 0, mfe };
|
|
15
|
+
fs.writeFileSync(path.join(dir, "server.json"), JSON.stringify(info, null, 2));
|
|
16
|
+
}
|
|
17
|
+
function removeServerInfo(projectRoot) {
|
|
18
|
+
try {
|
|
19
|
+
fs.unlinkSync(path.join(projectRoot, ".annotask", "server.json"));
|
|
20
|
+
} catch {
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export {
|
|
25
|
+
writeServerInfo,
|
|
26
|
+
writeMfeServerInfo,
|
|
27
|
+
removeServerInfo
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=chunk-XLNGAH3S.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server/discovery.ts"],"sourcesContent":["/**\n * Server discovery file — .annotask/server.json\n * Written on startup so skills and CLI know where to connect.\n */\nimport fs from 'node:fs'\nimport path from 'node:path'\n\nexport interface ServerInfo {\n url: string\n port: number\n pid: number\n mfe?: string\n}\n\nexport function writeServerInfo(projectRoot: string, port: number) {\n const dir = path.join(projectRoot, '.annotask')\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true })\n const info: ServerInfo = { url: `http://localhost:${port}`, port, pid: process.pid }\n fs.writeFileSync(path.join(dir, 'server.json'), JSON.stringify(info, null, 2))\n}\n\nexport function readServerInfo(projectRoot: string): ServerInfo | null {\n try {\n const raw = fs.readFileSync(path.join(projectRoot, '.annotask', 'server.json'), 'utf-8')\n return JSON.parse(raw)\n } catch { return null }\n}\n\nexport function writeMfeServerInfo(projectRoot: string, serverUrl: string, mfe: string) {\n const dir = path.join(projectRoot, '.annotask')\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true })\n const url = new URL(serverUrl)\n const info: ServerInfo = { url: serverUrl, port: parseInt(url.port) || 80, pid: 0, mfe }\n fs.writeFileSync(path.join(dir, 'server.json'), JSON.stringify(info, null, 2))\n}\n\nexport function removeServerInfo(projectRoot: string) {\n try { fs.unlinkSync(path.join(projectRoot, '.annotask', 'server.json')) } catch {}\n}\n"],"mappings":";AAIA,OAAO,QAAQ;AACf,OAAO,UAAU;AASV,SAAS,gBAAgB,aAAqB,MAAc;AACjE,QAAM,MAAM,KAAK,KAAK,aAAa,WAAW;AAC9C,MAAI,CAAC,GAAG,WAAW,GAAG,EAAG,IAAG,UAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAC9D,QAAM,OAAmB,EAAE,KAAK,oBAAoB,IAAI,IAAI,MAAM,KAAK,QAAQ,IAAI;AACnF,KAAG,cAAc,KAAK,KAAK,KAAK,aAAa,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAC/E;AASO,SAAS,mBAAmB,aAAqB,WAAmB,KAAa;AACtF,QAAM,MAAM,KAAK,KAAK,aAAa,WAAW;AAC9C,MAAI,CAAC,GAAG,WAAW,GAAG,EAAG,IAAG,UAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAC9D,QAAM,MAAM,IAAI,IAAI,SAAS;AAC7B,QAAM,OAAmB,EAAE,KAAK,WAAW,MAAM,SAAS,IAAI,IAAI,KAAK,IAAI,KAAK,GAAG,IAAI;AACvF,KAAG,cAAc,KAAK,KAAK,KAAK,aAAa,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAC/E;AAEO,SAAS,iBAAiB,aAAqB;AACpD,MAAI;AAAE,OAAG,WAAW,KAAK,KAAK,aAAa,aAAa,aAAa,CAAC;AAAA,EAAE,QAAQ;AAAA,EAAC;AACnF;","names":[]}
|
package/dist/cli.js
CHANGED
|
@@ -5,12 +5,26 @@ import WebSocket from "ws";
|
|
|
5
5
|
import { existsSync, mkdirSync, cpSync, readdirSync, symlinkSync, lstatSync, rmSync, readlinkSync } from "fs";
|
|
6
6
|
import { resolve, dirname, relative } from "path";
|
|
7
7
|
import { fileURLToPath } from "url";
|
|
8
|
+
import { readFileSync } from "fs";
|
|
8
9
|
var args = process.argv.slice(2);
|
|
9
10
|
var command = args[0] || "watch";
|
|
10
11
|
var port = args.find((a) => a.startsWith("--port="))?.split("=")[1] || "5173";
|
|
11
12
|
var host = args.find((a) => a.startsWith("--host="))?.split("=")[1] || "localhost";
|
|
12
|
-
var
|
|
13
|
-
var
|
|
13
|
+
var serverArg = args.find((a) => a.startsWith("--server="))?.split("=")[1] || "";
|
|
14
|
+
var mfeArg = args.find((a) => a.startsWith("--mfe="))?.split("=")[1] || "";
|
|
15
|
+
var baseUrl = "";
|
|
16
|
+
var mfeFilter = mfeArg;
|
|
17
|
+
try {
|
|
18
|
+
const serverJson = JSON.parse(readFileSync(".annotask/server.json", "utf-8"));
|
|
19
|
+
baseUrl = serverArg || serverJson.url || "";
|
|
20
|
+
if (!mfeFilter && serverJson.mfe) mfeFilter = serverJson.mfe;
|
|
21
|
+
} catch {
|
|
22
|
+
}
|
|
23
|
+
if (!baseUrl) {
|
|
24
|
+
baseUrl = serverArg || `http://${host}:${port}`;
|
|
25
|
+
}
|
|
26
|
+
var wsUrl = baseUrl.replace(/^http/, "ws") + "/__annotask/ws";
|
|
27
|
+
var apiUrl = baseUrl + "/__annotask/api";
|
|
14
28
|
var KNOWN_TARGETS = {
|
|
15
29
|
claude: ".claude/skills",
|
|
16
30
|
agents: ".agents/skills",
|
|
@@ -106,12 +120,21 @@ function watchChanges() {
|
|
|
106
120
|
}
|
|
107
121
|
async function fetchReport() {
|
|
108
122
|
try {
|
|
109
|
-
const
|
|
110
|
-
const
|
|
111
|
-
|
|
123
|
+
const tasksUrl = mfeFilter ? `${apiUrl}/tasks?mfe=${encodeURIComponent(mfeFilter)}` : `${apiUrl}/tasks`;
|
|
124
|
+
const reportUrl = `${apiUrl}/report`;
|
|
125
|
+
const [tasksRes, reportRes] = await Promise.all([
|
|
126
|
+
fetch(tasksUrl),
|
|
127
|
+
fetch(reportUrl)
|
|
128
|
+
]);
|
|
129
|
+
const tasks = await tasksRes.json();
|
|
130
|
+
const report = await reportRes.json();
|
|
131
|
+
console.log(JSON.stringify({ report, tasks }, null, 2));
|
|
132
|
+
if (mfeFilter) {
|
|
133
|
+
console.error(`\x1B[36m[Annotask]\x1B[0m Filtered by MFE: ${mfeFilter}`);
|
|
134
|
+
}
|
|
112
135
|
} catch (err) {
|
|
113
136
|
console.error(`\x1B[31m[Annotask]\x1B[0m Failed to fetch report: ${err.message}`);
|
|
114
|
-
console.error(`Make sure
|
|
137
|
+
console.error(`Make sure the Annotask server is running at ${baseUrl}`);
|
|
115
138
|
process.exit(1);
|
|
116
139
|
}
|
|
117
140
|
}
|
|
@@ -119,10 +142,11 @@ async function checkStatus() {
|
|
|
119
142
|
try {
|
|
120
143
|
const res = await fetch(`${apiUrl}/status`);
|
|
121
144
|
const data = await res.json();
|
|
122
|
-
console.log(`\x1B[32m[Annotask]\x1B[0m Server is running
|
|
145
|
+
console.log(`\x1B[32m[Annotask]\x1B[0m Server is running at ${baseUrl}`);
|
|
146
|
+
if (mfeFilter) console.log(`\x1B[36m[Annotask]\x1B[0m MFE filter: ${mfeFilter}`);
|
|
123
147
|
console.log(JSON.stringify(data, null, 2));
|
|
124
148
|
} catch {
|
|
125
|
-
console.log(`\x1B[31m[Annotask]\x1B[0m No Annotask server found
|
|
149
|
+
console.log(`\x1B[31m[Annotask]\x1B[0m No Annotask server found at ${baseUrl}`);
|
|
126
150
|
process.exit(1);
|
|
127
151
|
}
|
|
128
152
|
}
|
|
@@ -227,8 +251,10 @@ function printHelp() {
|
|
|
227
251
|
help Show this help
|
|
228
252
|
|
|
229
253
|
\x1B[33mOptions:\x1B[0m
|
|
230
|
-
--port=N
|
|
231
|
-
--host=H
|
|
254
|
+
--port=N Dev server port (default: 5173)
|
|
255
|
+
--host=H Dev server host (default: localhost)
|
|
256
|
+
--server=URL Annotask server URL (overrides .annotask/server.json)
|
|
257
|
+
--mfe=NAME Filter tasks by MFE identity (overrides server.json mfe)
|
|
232
258
|
--force Overwrite existing skills (for init-skills)
|
|
233
259
|
--target=NAME Comma-separated targets (default: claude,agents)
|
|
234
260
|
Built-in: claude, agents, copilot
|
|
@@ -239,7 +265,9 @@ function printHelp() {
|
|
|
239
265
|
annotask watch --port=3000 # Watch on custom port
|
|
240
266
|
annotask report # Get current report JSON
|
|
241
267
|
annotask report | jq # Pipe to jq for formatting
|
|
268
|
+
annotask report --mfe=@myorg/my-mfe # Report filtered by MFE
|
|
242
269
|
annotask status # Check connection
|
|
270
|
+
annotask status --server=http://localhost:24678 # Check remote server
|
|
243
271
|
annotask init-skills # Install to .claude + .agents (default)
|
|
244
272
|
annotask init-skills --target=claude # Only .claude/skills/
|
|
245
273
|
annotask init-skills --target=copilot # Only .copilot/skills/
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,17 @@ import { Plugin } from 'vite';
|
|
|
3
3
|
interface AnnotaskOptions {
|
|
4
4
|
/** @experimental Not yet implemented. OpenAPI spec path or URL */
|
|
5
5
|
openapi?: string;
|
|
6
|
+
/** MFE identity for multi-project setups (e.g. '@myorg/my-mfe').
|
|
7
|
+
* Adds data-annotask-mfe attribute to all elements.
|
|
8
|
+
* When used alone, annotask runs normally (shell + server available).
|
|
9
|
+
* When combined with `server`, the local server is skipped and
|
|
10
|
+
* .annotask/server.json points to the remote root server. */
|
|
11
|
+
mfe?: string;
|
|
12
|
+
/** Remote annotask server URL (e.g. 'http://localhost:24678').
|
|
13
|
+
* When set, the local annotask server is skipped — the root shell's
|
|
14
|
+
* plugin handles the server and UI injection. Writes .annotask/server.json
|
|
15
|
+
* pointing to this URL so skills/CLI connect to the root. */
|
|
16
|
+
server?: string;
|
|
6
17
|
}
|
|
7
18
|
declare function annotask(options?: AnnotaskOptions): Plugin[];
|
|
8
19
|
|
package/dist/index.js
CHANGED
|
@@ -1,27 +1,31 @@
|
|
|
1
1
|
import {
|
|
2
|
-
bridgeClientScript
|
|
3
|
-
|
|
4
|
-
} from "./chunk-2TUWBFQG.js";
|
|
2
|
+
bridgeClientScript
|
|
3
|
+
} from "./chunk-X72ZX6VB.js";
|
|
5
4
|
import {
|
|
5
|
+
writeMfeServerInfo,
|
|
6
6
|
writeServerInfo
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-XLNGAH3S.js";
|
|
8
8
|
import {
|
|
9
9
|
createAnnotaskServer
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-JLOSPIJ4.js";
|
|
11
11
|
import {
|
|
12
12
|
transformFile,
|
|
13
13
|
transformHTML
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-VU7Z7EZA.js";
|
|
15
15
|
|
|
16
16
|
// src/plugin/index.ts
|
|
17
17
|
function annotask(options = {}) {
|
|
18
18
|
let projectRoot = "";
|
|
19
|
+
const mfe = options.mfe;
|
|
19
20
|
const transformPlugin = {
|
|
20
21
|
name: "annotask:transform",
|
|
21
22
|
enforce: "pre",
|
|
22
23
|
apply: "serve",
|
|
23
24
|
configResolved(config) {
|
|
24
25
|
projectRoot = config.root;
|
|
26
|
+
if (mfe && options.server) {
|
|
27
|
+
writeMfeServerInfo(projectRoot, options.server, mfe);
|
|
28
|
+
}
|
|
25
29
|
},
|
|
26
30
|
transform(code, id) {
|
|
27
31
|
if (id.endsWith("/main.ts") || id.endsWith("/main.js") || id.endsWith("/main.tsx") || id.endsWith("/main.jsx")) {
|
|
@@ -48,7 +52,7 @@ window.__ANNOTASK_SVELTE__ = { mount: __uf_mount, unmount: __uf_unmount };
|
|
|
48
52
|
}
|
|
49
53
|
}
|
|
50
54
|
if (!id.endsWith(".vue") && !id.endsWith(".svelte") && !/\.[jt]sx$/.test(id)) return null;
|
|
51
|
-
const result = transformFile(code, id, projectRoot);
|
|
55
|
+
const result = transformFile(code, id, projectRoot, mfe);
|
|
52
56
|
if (!result) return null;
|
|
53
57
|
let output = result;
|
|
54
58
|
const importRegex = /import\s+(\w+)\s+from\s+['"]([^'"]+)['"]/g;
|
|
@@ -73,16 +77,13 @@ if (typeof window !== 'undefined') { window.__ANNOTASK_COMPONENTS__ = window.__A
|
|
|
73
77
|
return { code: output, map: null };
|
|
74
78
|
},
|
|
75
79
|
transformIndexHtml(html, ctx) {
|
|
76
|
-
const transformed = transformHTML(html, ctx.filename, projectRoot);
|
|
80
|
+
const transformed = transformHTML(html, ctx.filename, projectRoot, mfe);
|
|
81
|
+
if (options.server) {
|
|
82
|
+
return transformed ?? html;
|
|
83
|
+
}
|
|
77
84
|
return {
|
|
78
85
|
html: transformed ?? html,
|
|
79
86
|
tags: [
|
|
80
|
-
{
|
|
81
|
-
tag: "script",
|
|
82
|
-
attrs: { type: "module" },
|
|
83
|
-
children: toggleButtonScript(),
|
|
84
|
-
injectTo: "body"
|
|
85
|
-
},
|
|
86
87
|
{
|
|
87
88
|
tag: "script",
|
|
88
89
|
children: bridgeClientScript(),
|
|
@@ -147,8 +148,7 @@ if (typeof window !== 'undefined') { window.__ANNOTASK_COMPONENTS__ = window.__A
|
|
|
147
148
|
if (chunks.length > 0) {
|
|
148
149
|
let body = chunks.join("");
|
|
149
150
|
if (body.includes("</body>") && !body.includes("__ANNOTASK_BRIDGE__")) {
|
|
150
|
-
const scripts = `<script
|
|
151
|
-
<script>${bridgeClientScript()}</script>
|
|
151
|
+
const scripts = `<script>${bridgeClientScript()}</script>
|
|
152
152
|
`;
|
|
153
153
|
body = body.replace("</body>", scripts + "</body>");
|
|
154
154
|
}
|
|
@@ -161,6 +161,9 @@ if (typeof window !== 'undefined') { window.__ANNOTASK_COMPONENTS__ = window.__A
|
|
|
161
161
|
});
|
|
162
162
|
}
|
|
163
163
|
};
|
|
164
|
+
if (options.server) {
|
|
165
|
+
return [transformPlugin];
|
|
166
|
+
}
|
|
164
167
|
return [transformPlugin, servePlugin];
|
|
165
168
|
}
|
|
166
169
|
var plugin_default = annotask;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/plugin/index.ts"],"sourcesContent":["import type { Plugin, ViteDevServer } from 'vite'\nimport { transformFile, transformHTML } from './transform.js'\nimport { toggleButtonScript } from './toggle-button.js'\nimport { bridgeClientScript } from './bridge-client.js'\nimport { createAnnotaskServer } from '../server/index.js'\nimport { writeServerInfo } from '../server/discovery.js'\n\nexport interface AnnotaskOptions {\n /** @experimental Not yet implemented. OpenAPI spec path or URL */\n openapi?: string\n}\n\nexport function annotask(options: AnnotaskOptions = {}): Plugin[] {\n let projectRoot = ''\n\n const transformPlugin: Plugin = {\n name: 'annotask:transform',\n enforce: 'pre',\n apply: 'serve',\n\n configResolved(config) {\n projectRoot = config.root\n },\n\n transform(code, id) {\n // Expose framework runtime for Annotask component rendering\n if (id.endsWith('/main.ts') || id.endsWith('/main.js') || id.endsWith('/main.tsx') || id.endsWith('/main.jsx')) {\n let injection = ''\n if (code.includes(\"from 'vue'\") || code.includes('from \"vue\"')) {\n injection = `\\n;import { createApp as __uf_createApp, h as __uf_h } from 'vue';\\nwindow.__ANNOTASK_VUE__ = { createApp: __uf_createApp, h: __uf_h };\\n`\n } else if (code.includes(\"from 'react'\") || code.includes('from \"react\"')) {\n injection = `\\n;import { createElement as __uf_createElement } from 'react';\\nimport { createRoot as __uf_createRoot } from 'react-dom/client';\\nwindow.__ANNOTASK_REACT__ = { createElement: __uf_createElement, createRoot: __uf_createRoot };\\n`\n } else if (code.includes(\"from 'svelte'\") || code.includes('from \"svelte\"')) {\n injection = `\\n;import { mount as __uf_mount, unmount as __uf_unmount } from 'svelte';\\nwindow.__ANNOTASK_SVELTE__ = { mount: __uf_mount, unmount: __uf_unmount };\\n`\n }\n if (injection) {\n return { code: code + injection, map: null }\n }\n }\n\n // Transform source files to inject data-annotask-* attributes\n // Note: .astro files are excluded because Astro's compiler runs before\n // our transform (even with enforce: 'pre'). Astro source mapping is\n // handled via data-astro-source-* attributes in the bridge client.\n if (!id.endsWith('.vue') && !id.endsWith('.svelte') && !/\\.[jt]sx$/.test(id)) return null\n\n const result = transformFile(code, id, projectRoot)\n if (!result) return null\n\n // Register imported PascalCase components globally\n let output = result\n const importRegex = /import\\s+(\\w+)\\s+from\\s+['\"]([^'\"]+)['\"]/g\n let match\n const registrations: string[] = []\n while ((match = importRegex.exec(result)) !== null) {\n const [, name, source] = match\n if (name[0] === name[0].toUpperCase() && name[0] !== name[0].toLowerCase() && !source.startsWith('.')) {\n registrations.push(`window.__ANNOTASK_COMPONENTS__['${name}'] = ${name}`)\n }\n }\n if (registrations.length > 0) {\n const regCode = `\\nif (typeof window !== 'undefined') { window.__ANNOTASK_COMPONENTS__ = window.__ANNOTASK_COMPONENTS__ || {}; ${registrations.join('; ')} }\\n`\n // Vue SFCs: inject before </script>. JSX/Svelte: append to end of file.\n if (id.endsWith('.vue') && output.includes('</script>')) {\n output = output.replace(/<\\/script>/, regCode + '</script>')\n } else {\n output += regCode\n }\n }\n\n return { code: output, map: null }\n },\n\n transformIndexHtml(html, ctx) {\n const transformed = transformHTML(html, ctx.filename, projectRoot)\n return {\n html: transformed ?? html,\n tags: [\n {\n tag: 'script',\n attrs: { type: 'module' },\n children: toggleButtonScript(),\n injectTo: 'body',\n },\n {\n tag: 'script',\n children: bridgeClientScript(),\n injectTo: 'body',\n },\n ],\n }\n },\n }\n\n const servePlugin: Plugin = {\n name: 'annotask:serve',\n apply: 'serve',\n\n configureServer(server: ViteDevServer) {\n const uiServer = createAnnotaskServer({ projectRoot })\n\n // Mount middleware on Vite's connect instance\n server.middlewares.use(uiServer.middleware)\n\n // Handle WebSocket upgrades\n server.httpServer?.on('upgrade', (req, socket, head) => {\n if (req.url === '/__annotask/ws') {\n uiServer.handleUpgrade(req, socket, head)\n }\n })\n\n // Write server.json so skills/CLI know where to connect\n server.httpServer?.once('listening', () => {\n const addr = server.httpServer?.address()\n const port = typeof addr === 'object' && addr ? addr.port : 5173\n writeServerInfo(projectRoot, port)\n })\n\n console.log('[Annotask] Design tool available at /__annotask/')\n console.log('[Annotask] WebSocket: ws://localhost:<port>/__annotask/ws')\n console.log('[Annotask] API: http://localhost:<port>/__annotask/api/report')\n\n // Inject bridge scripts into SSR HTML responses (Astro, etc.)\n // Sniffs content-type from writeHead, buffers only HTML responses,\n // and injects scripts before </body>.\n server.middlewares.use((req: any, res: any, next: any) => {\n if (req.url?.startsWith('/__annotask')) return next()\n\n const _end = res.end\n const _write = res.write\n const _writeHead = res.writeHead\n const chunks: string[] = []\n let isHtml = false\n let decided = false\n\n res.writeHead = function (statusCode: any, ...rest: any[]) {\n if (!decided) {\n decided = true\n const headers = rest.find((a: any) => typeof a === 'object' && a !== null)\n if (headers) {\n const ct = headers['content-type'] || headers['Content-Type']\n if (typeof ct === 'string') isHtml = ct.includes('text/html')\n }\n if (!isHtml) {\n const ct = res.getHeader('content-type')\n if (typeof ct === 'string') isHtml = ct.includes('text/html')\n }\n }\n return _writeHead.apply(res, [statusCode, ...rest])\n }\n\n res.write = function (chunk: any, ...args: any[]) {\n if (isHtml) {\n if (chunk != null) chunks.push(typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString())\n return true\n }\n return _write.apply(res, [chunk, ...args] as any)\n }\n\n res.end = function (chunk: any, ...args: any[]) {\n if (isHtml) {\n if (chunk != null && chunk !== '') chunks.push(typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString())\n if (chunks.length > 0) {\n let body = chunks.join('')\n if (body.includes('</body>') && !body.includes('__ANNOTASK_BRIDGE__')) {\n const scripts = `<script type=\"module\">${toggleButtonScript()}</script>\\n<script>${bridgeClientScript()}</script>\\n`\n body = body.replace('</body>', scripts + '</body>')\n }\n return _end.call(res, body)\n }\n }\n return _end.apply(res, [chunk, ...args] as any)\n }\n\n next()\n })\n },\n }\n\n return [transformPlugin, servePlugin]\n}\n\nexport default annotask\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/plugin/index.ts"],"sourcesContent":["import type { Plugin, ViteDevServer } from 'vite'\nimport { transformFile, transformHTML } from './transform.js'\nimport { bridgeClientScript } from './bridge-client.js'\nimport { createAnnotaskServer } from '../server/index.js'\nimport { writeServerInfo, writeMfeServerInfo } from '../server/discovery.js'\n\nexport interface AnnotaskOptions {\n /** @experimental Not yet implemented. OpenAPI spec path or URL */\n openapi?: string\n /** MFE identity for multi-project setups (e.g. '@myorg/my-mfe').\n * Adds data-annotask-mfe attribute to all elements.\n * When used alone, annotask runs normally (shell + server available).\n * When combined with `server`, the local server is skipped and\n * .annotask/server.json points to the remote root server. */\n mfe?: string\n /** Remote annotask server URL (e.g. 'http://localhost:24678').\n * When set, the local annotask server is skipped — the root shell's\n * plugin handles the server and UI injection. Writes .annotask/server.json\n * pointing to this URL so skills/CLI connect to the root. */\n server?: string\n}\n\nexport function annotask(options: AnnotaskOptions = {}): Plugin[] {\n let projectRoot = ''\n const mfe = options.mfe\n\n const transformPlugin: Plugin = {\n name: 'annotask:transform',\n enforce: 'pre',\n apply: 'serve',\n\n configResolved(config) {\n projectRoot = config.root\n\n // When a remote server is specified, write server.json pointing to it\n // so skills/CLI in this repo connect to the root's annotask server.\n if (mfe && options.server) {\n writeMfeServerInfo(projectRoot, options.server, mfe)\n }\n },\n\n transform(code, id) {\n // Expose framework runtime for Annotask component rendering\n if (id.endsWith('/main.ts') || id.endsWith('/main.js') || id.endsWith('/main.tsx') || id.endsWith('/main.jsx')) {\n let injection = ''\n if (code.includes(\"from 'vue'\") || code.includes('from \"vue\"')) {\n injection = `\\n;import { createApp as __uf_createApp, h as __uf_h } from 'vue';\\nwindow.__ANNOTASK_VUE__ = { createApp: __uf_createApp, h: __uf_h };\\n`\n } else if (code.includes(\"from 'react'\") || code.includes('from \"react\"')) {\n injection = `\\n;import { createElement as __uf_createElement } from 'react';\\nimport { createRoot as __uf_createRoot } from 'react-dom/client';\\nwindow.__ANNOTASK_REACT__ = { createElement: __uf_createElement, createRoot: __uf_createRoot };\\n`\n } else if (code.includes(\"from 'svelte'\") || code.includes('from \"svelte\"')) {\n injection = `\\n;import { mount as __uf_mount, unmount as __uf_unmount } from 'svelte';\\nwindow.__ANNOTASK_SVELTE__ = { mount: __uf_mount, unmount: __uf_unmount };\\n`\n }\n if (injection) {\n return { code: code + injection, map: null }\n }\n }\n\n // Transform source files to inject data-annotask-* attributes\n // Note: .astro files are excluded because Astro's compiler runs before\n // our transform (even with enforce: 'pre'). Astro source mapping is\n // handled via data-astro-source-* attributes in the bridge client.\n if (!id.endsWith('.vue') && !id.endsWith('.svelte') && !/\\.[jt]sx$/.test(id)) return null\n\n const result = transformFile(code, id, projectRoot, mfe)\n if (!result) return null\n\n // Register imported PascalCase components globally\n let output = result\n const importRegex = /import\\s+(\\w+)\\s+from\\s+['\"]([^'\"]+)['\"]/g\n let match\n const registrations: string[] = []\n while ((match = importRegex.exec(result)) !== null) {\n const [, name, source] = match\n if (name[0] === name[0].toUpperCase() && name[0] !== name[0].toLowerCase() && !source.startsWith('.')) {\n registrations.push(`window.__ANNOTASK_COMPONENTS__['${name}'] = ${name}`)\n }\n }\n if (registrations.length > 0) {\n const regCode = `\\nif (typeof window !== 'undefined') { window.__ANNOTASK_COMPONENTS__ = window.__ANNOTASK_COMPONENTS__ || {}; ${registrations.join('; ')} }\\n`\n // Vue SFCs: inject before </script>. JSX/Svelte: append to end of file.\n if (id.endsWith('.vue') && output.includes('</script>')) {\n output = output.replace(/<\\/script>/, regCode + '</script>')\n } else {\n output += regCode\n }\n }\n\n return { code: output, map: null }\n },\n\n transformIndexHtml(html, ctx) {\n const transformed = transformHTML(html, ctx.filename, projectRoot, mfe)\n // When embedded in a root (server option set), skip bridge/toggle — root handles that\n if (options.server) {\n return transformed ?? html\n }\n return {\n html: transformed ?? html,\n tags: [\n {\n tag: 'script',\n children: bridgeClientScript(),\n injectTo: 'body',\n },\n ],\n }\n },\n }\n\n const servePlugin: Plugin = {\n name: 'annotask:serve',\n apply: 'serve',\n\n configureServer(server: ViteDevServer) {\n const uiServer = createAnnotaskServer({ projectRoot })\n\n // Mount middleware on Vite's connect instance\n server.middlewares.use(uiServer.middleware)\n\n // Handle WebSocket upgrades\n server.httpServer?.on('upgrade', (req, socket, head) => {\n if (req.url === '/__annotask/ws') {\n uiServer.handleUpgrade(req, socket, head)\n }\n })\n\n // Write server.json so skills/CLI know where to connect\n server.httpServer?.once('listening', () => {\n const addr = server.httpServer?.address()\n const port = typeof addr === 'object' && addr ? addr.port : 5173\n writeServerInfo(projectRoot, port)\n })\n\n console.log('[Annotask] Design tool available at /__annotask/')\n console.log('[Annotask] WebSocket: ws://localhost:<port>/__annotask/ws')\n console.log('[Annotask] API: http://localhost:<port>/__annotask/api/report')\n\n // Inject bridge scripts into SSR HTML responses (Astro, etc.)\n // Sniffs content-type from writeHead, buffers only HTML responses,\n // and injects scripts before </body>.\n server.middlewares.use((req: any, res: any, next: any) => {\n if (req.url?.startsWith('/__annotask')) return next()\n\n const _end = res.end\n const _write = res.write\n const _writeHead = res.writeHead\n const chunks: string[] = []\n let isHtml = false\n let decided = false\n\n res.writeHead = function (statusCode: any, ...rest: any[]) {\n if (!decided) {\n decided = true\n const headers = rest.find((a: any) => typeof a === 'object' && a !== null)\n if (headers) {\n const ct = headers['content-type'] || headers['Content-Type']\n if (typeof ct === 'string') isHtml = ct.includes('text/html')\n }\n if (!isHtml) {\n const ct = res.getHeader('content-type')\n if (typeof ct === 'string') isHtml = ct.includes('text/html')\n }\n }\n return _writeHead.apply(res, [statusCode, ...rest])\n }\n\n res.write = function (chunk: any, ...args: any[]) {\n if (isHtml) {\n if (chunk != null) chunks.push(typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString())\n return true\n }\n return _write.apply(res, [chunk, ...args] as any)\n }\n\n res.end = function (chunk: any, ...args: any[]) {\n if (isHtml) {\n if (chunk != null && chunk !== '') chunks.push(typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString())\n if (chunks.length > 0) {\n let body = chunks.join('')\n if (body.includes('</body>') && !body.includes('__ANNOTASK_BRIDGE__')) {\n const scripts = `<script>${bridgeClientScript()}</script>\\n`\n body = body.replace('</body>', scripts + '</body>')\n }\n return _end.call(res, body)\n }\n }\n return _end.apply(res, [chunk, ...args] as any)\n }\n\n next()\n })\n },\n }\n\n // When a remote server is specified, skip the serve plugin — no local\n // server, bridge, or toggle. The root shell's plugin handles all of that.\n // When only `mfe` is set (no server), annotask runs normally so the\n // shell is available for standalone testing.\n if (options.server) {\n return [transformPlugin]\n }\n\n return [transformPlugin, servePlugin]\n}\n\nexport default annotask\n"],"mappings":"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","names":[]}
|
package/dist/server.d.ts
CHANGED
|
@@ -27,7 +27,10 @@ interface APIOptions {
|
|
|
27
27
|
getReport: () => unknown;
|
|
28
28
|
getConfig: () => unknown;
|
|
29
29
|
getDesignSpec: () => unknown;
|
|
30
|
-
getTasks: () =>
|
|
30
|
+
getTasks: () => {
|
|
31
|
+
version: string;
|
|
32
|
+
tasks: any[];
|
|
33
|
+
};
|
|
31
34
|
updateTask: (id: string, updates: Record<string, unknown>) => unknown;
|
|
32
35
|
addTask: (task: Record<string, unknown>) => unknown;
|
|
33
36
|
}
|