@agimon-ai/po-build 0.0.0-alpha.53 → 0.0.0-alpha.55
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.
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../constants/layout.cjs"),n=require("../renderMcpWidgets/index.cjs"),r=require("../generate/index.cjs"),i=require("../syncManifest/index.cjs"),a=require("../serverContracts/index.cjs"),o=require("../unistylesBabel/index.cjs");let s=require("node:fs");s=e.__toESM(s,1);let c=require("node:path");c=e.__toESM(c,1);let l=require("node:fs/promises");l=e.__toESM(l,1);const u=`src/exports`,d=`apiContracts`;function f(e,t){let n=c.default.join(e,t);if(!s.default.existsSync(n))return{};let r={};for(let e of s.default.readdirSync(n)){if(!e.endsWith(`.ts`)||e.endsWith(`.d.ts`))continue;let n=e.slice(0,-3);r[n]=`${t}/${e}`}return r}function p(e,n=u){let r=`${t.GENERATED_DIR}/server.ts`;return{...f(e,n),...s.default.existsSync(c.default.join(e,r))?{"extensions/server":r}:{}}}function m(e,t,n){let r=c.default.join(e,t);if(!s.default.existsSync(r))return{};let i={};for(let e of s.default.readdirSync(r,{encoding:`utf8`,recursive:!0})){if(!n(e))continue;let r=e.split(c.default.sep).join(`/`);i[`./${t}/${r}`]=`./${t}/${r}`}return i}function h(e){let t=JSON.parse(s.default.readFileSync(c.default.join(e,`package.json`),`utf8`)),n=t.exports!==null&&typeof t.exports==`object`&&!Array.isArray(t.exports)?Object.fromEntries(Object.entries(t.exports).filter(([,e])=>typeof e==`string`)):{};return{...m(e,`skills`,e=>c.default.basename(e)===`SKILL.md`),...m(e,`themes`,e=>e.endsWith(`.json`)),...n}}function g(){return{name:`po-query-assets`,resolveId(e,t){let n=e.indexOf(`?`);if(n<0||t===void 0||!e.startsWith(`.`))return;let r=t.split(`?`)[0];return`${c.default.resolve(c.default.dirname(r),e.slice(0,n))}${e.slice(n)}`},async load(e){let t=e.indexOf(`?`);if(t<0)return;let n=e.slice(0,t),r=new URLSearchParams(e.slice(t+1));if(!r.has(`url`))return;let i=r.has(`worker`);return`export default import.meta.ROLLUP_FILE_URL_${this.emitFile(i?{type:`chunk`,id:n,name:c.default.basename(n,c.default.extname(n))}:{type:`asset`,name:c.default.basename(n),source:await l.default.readFile(n)})};`}}}function _(e=`web`){return{entry:{[`extensions/${e}`]:`${t.GENERATED_DIR}/${e}.ts`},clean:!1,dts:!1,exports:!1,format:[`esm`],platform:`browser`,fixedExtension:!0,external:e=>!e.startsWith(`.`)&&!c.default.isAbsolute(e),plugins:[g()],sourcemap:!0,unbundle:!1,tsconfig:e===`web`?`tsconfig.web.json`:`tsconfig.mcp.json`}}function v(e){return{entry:{"extensions/native":`${t.GENERATED_DIR}/native.ts`},clean:!1,dts:!1,exports:!1,format:[`esm`],platform:`neutral`,fixedExtension:!0,external:e=>!e.startsWith(`.`)&&!c.default.isAbsolute(e),plugins:[o.unistylesBabel(e)],sourcemap:!0,unbundle:!1,tsconfig:`tsconfig.native.json`}}const y=/^(?:extensions\/mcp(?:-ui)?|.+\.mcp)\.(?:mjs|cjs|d\.mts|d\.cts)(?:\.map)?$/u;function b(e,t){let n=c.default.join(e,`dist`);if(s.default.existsSync(n))for(let e of s.default.readdirSync(n,{recursive:!0,encoding:`utf8`})){if(y.test(e.split(c.default.sep).join(`/`))!==(t===`mcp`))continue;let r=c.default.join(n,e);s.default.lstatSync(r,{throwIfNoEntry:!1})?.isFile()&&s.default.rmSync(r)}}function x(e={packageDir:process.cwd()}){let o=e.packageDir??process.cwd(),s=r.generateExtension({...e,packageDir:o,check:e.check??!1});for(let e of s.notices)process.stderr.write(`[po-build] ${e.path}: ${e.message}\n`);let p=e.target===`mcp`;e.check||b(o,p?`mcp`:`normal`);let m=p&&!s.targets.includes(`mcp`),g=`\0po-empty-mcp`;m&&!e.check&&i.writeMcpManifest(o,!1);let y=p?s.targets.includes(`mcp`)?{"extensions/mcp":`${t.GENERATED_DIR}/mcp.ts`}:{"extensions/mcp":g}:{...f(o,e.exportsDir??u),...s.targets.includes(`server`)?{"extensions/server":`${t.GENERATED_DIR}/server.ts`}:{},...e.entry},x={clean:!1,dts:!m&&{incremental:!0,parallel:!1,eager:!0},...m?{write:!1,plugins:[{name:`po-empty-mcp`,resolveId:e=>e===g?g:void 0,load:e=>e===g?`export {};`:void 0}]}:{},exports:!p&&{customExports:e=>{let t=Object.keys(y),n=t[0];return{...h(o),...e,...t.length===1&&n!==void 0&&n!==`index`&&!n.startsWith(`extensions/`)?{[`./${n}`]:e[`.`]}:{}}}},format:{esm:{},cjs:{dts:!1}},platform:`node`,outExtensions:({format:e})=>({js:e===`es`?`.mjs`:`.cjs`,dts:e===`es`?`.d.mts`:`.d.cts`}),sourcemap:!0},S=
|
|
1
|
+
const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../constants/layout.cjs"),n=require("../renderMcpWidgets/index.cjs"),r=require("../generate/index.cjs"),i=require("../syncManifest/index.cjs"),a=require("../serverContracts/index.cjs"),o=require("../unistylesBabel/index.cjs");let s=require("node:fs");s=e.__toESM(s,1);let c=require("node:path");c=e.__toESM(c,1);let l=require("node:fs/promises");l=e.__toESM(l,1);const u=`src/exports`,d=`apiContracts`;function f(e,t){let n=c.default.join(e,t);if(!s.default.existsSync(n))return{};let r={};for(let e of s.default.readdirSync(n)){if(!e.endsWith(`.ts`)||e.endsWith(`.d.ts`))continue;let n=e.slice(0,-3);r[n]=`${t}/${e}`}return r}function p(e,n=u){let r=`${t.GENERATED_DIR}/server.ts`;return{...f(e,n),...s.default.existsSync(c.default.join(e,r))?{"extensions/server":r}:{}}}function m(e,t,n){let r=c.default.join(e,t);if(!s.default.existsSync(r))return{};let i={};for(let e of s.default.readdirSync(r,{encoding:`utf8`,recursive:!0})){if(!n(e))continue;let r=e.split(c.default.sep).join(`/`);i[`./${t}/${r}`]=`./${t}/${r}`}return i}function h(e){let t=JSON.parse(s.default.readFileSync(c.default.join(e,`package.json`),`utf8`)),n=t.exports!==null&&typeof t.exports==`object`&&!Array.isArray(t.exports)?Object.fromEntries(Object.entries(t.exports).filter(([,e])=>typeof e==`string`)):{};return{...m(e,`skills`,e=>c.default.basename(e)===`SKILL.md`),...m(e,`themes`,e=>e.endsWith(`.json`)),...n}}function g(){return{name:`po-query-assets`,resolveId(e,t){let n=e.indexOf(`?`);if(n<0||t===void 0||!e.startsWith(`.`))return;let r=t.split(`?`)[0];return`${c.default.resolve(c.default.dirname(r),e.slice(0,n))}${e.slice(n)}`},async load(e){let t=e.indexOf(`?`);if(t<0)return;let n=e.slice(0,t),r=new URLSearchParams(e.slice(t+1));if(!r.has(`url`))return;let i=r.has(`worker`);return`export default import.meta.ROLLUP_FILE_URL_${this.emitFile(i?{type:`chunk`,id:n,name:c.default.basename(n,c.default.extname(n))}:{type:`asset`,name:c.default.basename(n),source:await l.default.readFile(n)})};`}}}function _(e=`web`){return{entry:{[`extensions/${e}`]:`${t.GENERATED_DIR}/${e}.ts`},clean:!1,dts:!1,exports:!1,format:[`esm`],platform:`browser`,fixedExtension:!0,external:e=>!e.startsWith(`.`)&&!c.default.isAbsolute(e),plugins:[g()],sourcemap:!0,unbundle:!1,tsconfig:e===`web`?`tsconfig.web.json`:`tsconfig.mcp.json`}}function v(e){return{entry:{"extensions/native":`${t.GENERATED_DIR}/native.ts`},clean:!1,dts:!1,exports:!1,format:[`esm`],platform:`neutral`,fixedExtension:!0,external:e=>!e.startsWith(`.`)&&!c.default.isAbsolute(e),plugins:[o.unistylesBabel(e)],sourcemap:!0,unbundle:!1,tsconfig:`tsconfig.native.json`}}const y=/^(?:extensions\/mcp(?:-ui)?|.+\.mcp)\.(?:mjs|cjs|d\.mts|d\.cts)(?:\.map)?$/u;function b(e,t){let n=c.default.join(e,`dist`);if(s.default.existsSync(n))for(let e of s.default.readdirSync(n,{recursive:!0,encoding:`utf8`})){if(y.test(e.split(c.default.sep).join(`/`))!==(t===`mcp`))continue;let r=c.default.join(n,e);s.default.lstatSync(r,{throwIfNoEntry:!1})?.isFile()&&s.default.rmSync(r)}}function x(e={packageDir:process.cwd()}){let o=e.packageDir??process.cwd(),s=r.generateExtension({...e,packageDir:o,check:e.check??!1});for(let e of s.notices)process.stderr.write(`[po-build] ${e.path}: ${e.message}\n`);let p=e.target===`mcp`;e.check||b(o,p?`mcp`:`normal`);let m=p&&!s.targets.includes(`mcp`),g=`\0po-empty-mcp`;m&&!e.check&&i.writeMcpManifest(o,!1);let y=p?s.targets.includes(`mcp`)?{"extensions/mcp":`${t.GENERATED_DIR}/mcp.ts`}:{"extensions/mcp":g}:{...f(o,e.exportsDir??u),...s.targets.includes(`server`)?{"extensions/server":`${t.GENERATED_DIR}/server.ts`}:{},...e.entry},x={clean:!1,dts:!m&&{incremental:!0,parallel:!1,eager:!0},...m?{write:!1,plugins:[{name:`po-empty-mcp`,resolveId:e=>e===g?g:void 0,load:e=>e===g?`export {};`:void 0}]}:{},exports:!p&&{customExports:e=>{let t=Object.keys(y),n=t[0];return{...h(o),...e,...t.length===1&&n!==void 0&&n!==`index`&&!n.startsWith(`extensions/`)?{[`./${n}`]:e[`.`]}:{}}}},format:{esm:{},cjs:{dts:!1}},platform:`node`,outExtensions:({format:e})=>({js:e===`es`?`.mjs`:`.cjs`,dts:e===`es`?`.d.mts`:`.d.cts`}),sourcemap:!0},S=async()=>{p?i.writeMcpManifest(o,s.targets.includes(`mcp`),n.renderMcpWidgets(s.graph,s.packageName,t.GENERATED_DIR).names):i.writeManifest({packageDir:o,manifest:JSON.parse(await l.default.readFile(c.default.join(o,`package.json`),`utf8`)),graph:s.graph,targets:s.targets,pluginId:s.pluginId,...s.targets.includes(`server`)?{serverContracts:await a.readServerContracts(o,t.SERVER_DIST)}:{}})},C,w=(e,t)=>({...x,entry:e,unbundle:!1,hooks:{"build:done":()=>C??=S().finally(()=>{C=void 0})}}),T=!p&&d in y&&Object.keys(y).length>1?[((e,t)=>({...x,entry:e,unbundle:t}))({[d]:y[d]},!1),w(Object.fromEntries(Object.entries(y).filter(([e])=>e!==d)),!0)]:[w(y,!p)];if(p&&s.files.has(`generated/mcp-ui.ts`))return[...T,_(`mcp-ui`)];let E=p?[]:[...s.targets.includes(`web`)?[_()]:[],...s.targets.includes(`native`)?[v(o)]:[]];if(E.length>0){if(Object.keys(y).length>0)return[...T,...E];let[e,...t]=E;return[{...e,hooks:T[0].hooks},...t]}return T.length===1?T[0]:T}exports.extensionSourceEntries=p,exports.poExtension=x;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["path","fs","GENERATED_DIR","fsPromises","unistylesBabel","generateExtension","renderMcpWidgets","readServerContracts","SERVER_DIST","require_runtime","require_layout","require_index","require_index$1","require_index$2","require_index$3","require_index$4","node_fs","node_path","node_fs_promises","DEFAULT_EXPORTS_DIR","API_CONTRACTS_ENTRY","exportEntries","absolute","packageDir","exportsDir","entries","file","stem","extensionSourceEntries","server","resourceEntries","root","directory","relative","matches","normalized","staticExports","manifest","declared","target","queryAssetPlugin","queryAt","source","importer","importerFile","id","query","worker","browserConfig","nativeConfig","MCP_OUTPUT","cleanOutput","dist","owner","poExtension","options","result","notice","mcpOnly","emptyMcp","emptyEntry","entry","baseNode","names","name","generated","format","node","configs","frontends","first","rest"],"sources":["../../../src/services/tsdownPreset/index.ts"],"sourcesContent":["// sync: Exported poExtension/extensionSourceEntries and the host customExports callback retain synchronous contracts.\nimport fs from 'node:fs';\nimport fsPromises from 'node:fs/promises';\nimport path from 'node:path';\n\nimport { GENERATED_DIR, SERVER_DIST } from '../../constants/layout';\nimport { generateExtension } from '../generate';\nimport type { GenerateOptions } from '../generate/type';\nimport { renderMcpWidgets } from '../renderMcpWidgets';\nimport { readServerContracts } from '../serverContracts';\nimport { writeManifest, writeMcpManifest } from '../syncManifest';\nimport { unistylesBabel } from '../unistylesBabel';\nimport type { UnistylesBabelPlugin } from '../unistylesBabel/type';\n\ninterface EmittedFile {\n readonly type: 'asset' | 'chunk';\n readonly id?: string;\n readonly name: string;\n readonly source?: Buffer;\n}\n\ninterface QueryAssetPlugin {\n readonly name: string;\n resolveId(source: string, importer: string | undefined): string | undefined;\n load(this: { emitFile(file: EmittedFile): string }, id: string): string | undefined | Promise<string | undefined>;\n}\n\n/** The shape a tsdown config needs from this preset, without importing tsdown's types. */\ninterface BrowserPresetConfig {\n entry: Record<string, string>;\n clean: boolean;\n dts: false;\n exports: boolean;\n format: 'esm'[];\n platform: 'browser';\n fixedExtension: boolean;\n external: (id: string) => boolean;\n plugins: QueryAssetPlugin[];\n sourcemap: boolean;\n unbundle: boolean;\n tsconfig: string;\n hooks?: PresetConfig['hooks'];\n}\n\n/** The separately bundled native half, shaped like the browser one. */\ninterface NativePresetConfig extends Omit<BrowserPresetConfig, 'platform' | 'plugins'> {\n platform: 'neutral';\n plugins: UnistylesBabelPlugin[];\n}\n\ninterface GeneratedExports {\n customExports: (exports: Record<string, unknown>) => Record<string, unknown>;\n}\n\ninterface BasePresetConfig {\n entry: Record<string, string>;\n clean: boolean;\n dts: false | { incremental: boolean; parallel: boolean; eager: boolean };\n write?: false;\n plugins?: QueryAssetPlugin[];\n exports: boolean | GeneratedExports;\n format: { esm: Record<string, never>; cjs: { dts: false } };\n platform: 'node';\n sourcemap: boolean;\n unbundle: boolean;\n outExtensions: ({ format }: { format: string }) => {\n js: string;\n dts: string;\n };\n}\n\ninterface PresetConfig extends BasePresetConfig {\n hooks?: { 'build:done': () => void | Promise<void> };\n}\n\nconst DEFAULT_EXPORTS_DIR = 'src/exports';\nconst API_CONTRACTS_ENTRY = 'apiContracts';\n\n/** `src/exports/apiContracts.ts` becomes the `apiContracts` entry; index keeps its name. */\nfunction exportEntries(packageDir: string, exportsDir: string): Record<string, string> {\n const absolute = path.join(packageDir, exportsDir);\n if (!fs.existsSync(absolute)) return {};\n const entries: Record<string, string> = {};\n for (const file of fs.readdirSync(absolute)) {\n if (!file.endsWith('.ts') || file.endsWith('.d.ts')) continue;\n const stem = file.slice(0, -'.ts'.length);\n entries[stem] = `${exportsDir}/${file}`;\n }\n return entries;\n}\n\n/**\n * Source file behind each published subpath of a folder-routed extension, keyed like\n * tsdown entries (`index`, `apiContracts`, `extensions/server`). Read from disk without\n * regenerating, so `generated/server.ts` must already exist. The private Worker build\n * uses this to bundle workspace sources instead of `dist/`.\n */\nexport function extensionSourceEntries(\n packageDir: string,\n exportsDir: string = DEFAULT_EXPORTS_DIR,\n): Record<string, string> {\n const server = `${GENERATED_DIR}/server.ts`;\n return {\n ...exportEntries(packageDir, exportsDir),\n ...(fs.existsSync(path.join(packageDir, server)) ? { 'extensions/server': server } : {}),\n };\n}\n\n/** Static resources receive package export entries without becoming tsdown inputs. */\nfunction resourceEntries(\n packageDir: string,\n directory: string,\n matches: (relative: string) => boolean,\n): Record<string, string> {\n const root = path.join(packageDir, directory);\n if (!fs.existsSync(root)) return {};\n const entries: Record<string, string> = {};\n for (const relative of fs.readdirSync(root, { encoding: 'utf8', recursive: true })) {\n if (!matches(relative)) continue;\n const normalized = relative.split(path.sep).join('/');\n entries[`./${directory}/${normalized}`] = `./${directory}/${normalized}`;\n }\n return entries;\n}\n\n/** Preserves declared resources and discovers default skill and theme resource exports. */\nfunction staticExports(packageDir: string): Record<string, unknown> {\n const manifest = JSON.parse(fs.readFileSync(path.join(packageDir, 'package.json'), 'utf8')) as Record<\n string,\n unknown\n >;\n const declared =\n manifest.exports !== null && typeof manifest.exports === 'object' && !Array.isArray(manifest.exports)\n ? Object.fromEntries(Object.entries(manifest.exports).filter(([, target]) => typeof target === 'string'))\n : {};\n return {\n ...resourceEntries(packageDir, 'skills', (relative) => path.basename(relative) === 'SKILL.md'),\n ...resourceEntries(packageDir, 'themes', (relative) => relative.endsWith('.json')),\n ...declared,\n };\n}\n/**\n * One tsdown config for a folder-routed extension.\n *\n * Entries come from the tree rather than a hand-written list, and the manifest\n * blocks that restate the tree are written after the build rather than kept in\n * step by hand. Browser contributions are emitted through a second bundled\n * config because their routed source is not published.\n */\nexport interface ExtensionPresetOptions extends GenerateOptions {\n /** Extra tsdown entries beyond the derived ones. */\n readonly entry?: Record<string, string>;\n /** Public export modules, package-relative. Defaults to `src/exports`. */\n readonly exportsDir?: string;\n}\n\n/**\n * Implements the Vite query imports extension browser code already uses.\n *\n * `?url` copies an opaque asset and `?worker&url` emits a separately bundled\n * worker chunk. Rolldown then replaces its file reference with an URL relative\n * to the extension bundle, which remains valid when the cockpit composes it.\n */\nfunction queryAssetPlugin(): QueryAssetPlugin {\n return {\n name: 'po-query-assets',\n resolveId(source, importer) {\n const queryAt = source.indexOf('?');\n if (queryAt < 0 || importer === undefined || !source.startsWith('.')) return undefined;\n const importerFile = importer.split('?')[0] as string;\n return `${path.resolve(path.dirname(importerFile), source.slice(0, queryAt))}${source.slice(queryAt)}`;\n },\n async load(id) {\n const queryAt = id.indexOf('?');\n if (queryAt < 0) return undefined;\n const file = id.slice(0, queryAt);\n const query = new URLSearchParams(id.slice(queryAt + 1));\n if (!query.has('url')) return undefined;\n const worker = query.has('worker');\n const reference = this.emitFile(\n worker\n ? { type: 'chunk', id: file, name: path.basename(file, path.extname(file)) }\n : { type: 'asset', name: path.basename(file), source: await fsPromises.readFile(file) },\n );\n return `export default import.meta.ROLLUP_FILE_URL_${reference};`;\n },\n };\n}\n\n/** The separately bundled browser half of a routed extension. */\nfunction browserConfig(target: 'web' | 'mcp-ui' = 'web'): BrowserPresetConfig {\n return {\n entry: { [`extensions/${target}`]: `${GENERATED_DIR}/${target}.ts` },\n clean: false,\n // No declarations. Nothing imports this as a typed module: it has no\n // export subpath, and the cockpit consumes it as a bundle. The browser\n // half is still typechecked, by tsconfig.web.json in the typecheck script.\n dts: false,\n exports: false,\n format: ['esm'],\n platform: 'browser',\n // platform browser turns tsdown's fixedExtension off, which would emit\n // .js. The manifest names .mjs like the other two entries, so ask for it.\n fixedExtension: true,\n // Every bare specifier stays external and the cockpit resolves it, which\n // is what keeps one React and one store in the page no matter how many\n // plugins are installed. An allowlist would have to be kept in step with\n // the cockpit's; this cannot drift.\n //\n // A predicate rather than a pattern: rolldown tests `external` against the\n // resolved id, so /^[^.]/ also matches the absolute path of this package's\n // own routed file and would leave a dangling import to unbuilt .tsx.\n external: (id: string) => !id.startsWith('.') && !path.isAbsolute(id),\n plugins: [queryAssetPlugin()],\n sourcemap: true,\n // Bundled, unlike the node half. Unbundling would emit an import to the\n // routed source file, which is not published and is .tsx besides. One\n // module with only bare specifiers external is what the cockpit wants.\n unbundle: false,\n // Browser routes are excluded from the node tsconfig. Every browser-capable\n // extension owns this focused config for its matching typecheck.\n tsconfig: target === 'web' ? 'tsconfig.web.json' : 'tsconfig.mcp.json',\n };\n}\n\n/**\n * The separately bundled native half of a routed extension.\n *\n * Neutral rather than browser: React Native has neither the DOM nor Node, so\n * no condition set fits it better, and every bare specifier stays external\n * anyway. The CLI bundles this module into the signed composition and refuses\n * any import outside the native host module list, so nothing here has to.\n */\nfunction nativeConfig(packageDir: string): NativePresetConfig {\n return {\n entry: { 'extensions/native': `${GENERATED_DIR}/native.ts` },\n clean: false,\n dts: false,\n exports: false,\n format: ['esm'],\n platform: 'neutral',\n fixedExtension: true,\n // The same predicate as the browser half, for the same reason: the host\n // supplies React, React Native and Unistyles, one copy each.\n external: (id: string) => !id.startsWith('.') && !path.isAbsolute(id),\n plugins: [unistylesBabel(packageDir)],\n sourcemap: true,\n unbundle: false,\n // Native routes import react-native, which the DOM-typed web config must\n // not see, so they typecheck under their own config.\n tsconfig: 'tsconfig.native.json',\n };\n}\n\nconst MCP_OUTPUT = /^(?:extensions\\/mcp(?:-ui)?|.+\\.mcp)\\.(?:mjs|cjs|d\\.mts|d\\.cts)(?:\\.map)?$/u;\n\n/**\n * Removes files from dist that one build owns, so an entry deleted from the source tree does\n * not live on as a stale file (and in the Nx cache). The MCP build removes only its own files;\n * the normal build removes everything else and keeps the MCP files the other build wrote.\n */\nfunction cleanOutput(packageDir: string, owner: 'mcp' | 'normal'): void {\n const dist = path.join(packageDir, 'dist');\n if (!fs.existsSync(dist)) return;\n for (const relative of fs.readdirSync(dist, { recursive: true, encoding: 'utf8' })) {\n const isMcp = MCP_OUTPUT.test(relative.split(path.sep).join('/'));\n if (isMcp !== (owner === 'mcp')) continue;\n const absolute = path.join(dist, relative);\n if (fs.lstatSync(absolute, { throwIfNoEntry: false })?.isFile()) fs.rmSync(absolute);\n }\n}\n\nexport function poExtension(\n options: ExtensionPresetOptions = { packageDir: process.cwd() },\n): PresetConfig | (PresetConfig | BrowserPresetConfig | NativePresetConfig)[] {\n const packageDir = options.packageDir ?? process.cwd();\n const result = generateExtension({ ...options, packageDir, check: options.check ?? false });\n\n for (const notice of result.notices) process.stderr.write(`[po-build] ${notice.path}: ${notice.message}\\n`);\n\n const mcpOnly = options.target === 'mcp';\n // ponytail: the normal build cleans at config load, so it must run before the MCP build (every\n // build script does). Hashed assets of an mcp-ui bundle are not recognised and are rebuilt after.\n if (!options.check) cleanOutput(packageDir, mcpOnly ? 'mcp' : 'normal');\n const emptyMcp = mcpOnly && !result.targets.includes('mcp');\n const emptyEntry = '\\0po-empty-mcp';\n if (emptyMcp && !options.check) writeMcpManifest(packageDir, false);\n const entry: Record<string, string> = mcpOnly\n ? result.targets.includes('mcp')\n ? { 'extensions/mcp': `${GENERATED_DIR}/mcp.ts` }\n : { 'extensions/mcp': emptyEntry }\n : {\n ...exportEntries(packageDir, options.exportsDir ?? DEFAULT_EXPORTS_DIR),\n ...(result.targets.includes('server') ? { 'extensions/server': `${GENERATED_DIR}/server.ts` } : {}),\n ...options.entry,\n };\n\n const baseNode: Omit<BasePresetConfig, 'entry' | 'unbundle'> = {\n // MCP shares dist/ with the normal build, so neither build may erase the other.\n clean: false,\n dts: emptyMcp ? false : { incremental: true, parallel: false, eager: true },\n // tsdown rejects both an empty entry and an empty config array. A virtual\n // input completes its normal lifecycle without publishing an empty facet.\n ...(emptyMcp\n ? {\n write: false as const,\n plugins: [\n {\n name: 'po-empty-mcp',\n resolveId: (source: string) => (source === emptyEntry ? emptyEntry : undefined),\n load: (id: string) => (id === emptyEntry ? 'export {};' : undefined),\n },\n ],\n }\n : {}),\n exports: mcpOnly\n ? false\n : {\n customExports: (generated) => {\n const names = Object.keys(entry);\n const name = names[0];\n return {\n ...staticExports(packageDir),\n ...generated,\n ...(names.length === 1 && name !== undefined && name !== 'index' && !name.startsWith('extensions/')\n ? { [`./${name}`]: generated['.'] }\n : {}),\n };\n },\n },\n // CommonJS keeps its JavaScript but emits no declarations. Every export map\n // resolves types through .d.mts, and a CJS declaration build would rerun\n // the same whole-program tsgo emit a second time.\n format: { esm: {}, cjs: { dts: false } },\n // No minify. This is a library build, and a mangled stack trace inside a\n // published extension is far more expensive than the bytes it saves.\n // Native server entries use the .mjs filenames their hosts require.\n platform: 'node',\n outExtensions: ({ format }) => ({\n js: format === 'es' ? '.mjs' : '.cjs',\n dts: format === 'es' ? '.d.mts' : '.d.cts',\n }),\n sourcemap: true,\n };\n\n // Contract bundles are published as a self-contained graph. Normal extension\n // entries remain unbundled for routed runtime resources, while MCP remains\n // isolated from the shared dist directory.\n const node = (entries: Record<string, string>, _unbundle: boolean): PresetConfig => ({\n ...baseNode,\n entry: entries,\n // Public entry facades must remain bundled. Otherwise their relative\n // imports target unbundled implementation chunks, which Vite treats as\n // source files when resolving a workspace package.\n unbundle: false,\n hooks: {\n 'build:done': async () => {\n if (mcpOnly) {\n writeMcpManifest(\n packageDir,\n result.targets.includes('mcp'),\n renderMcpWidgets(result.graph, result.packageName, GENERATED_DIR).names,\n );\n return;\n }\n writeManifest({\n packageDir,\n manifest: JSON.parse(await fsPromises.readFile(path.join(packageDir, 'package.json'), 'utf8')) as Record<\n string,\n unknown\n >,\n graph: result.graph,\n targets: result.targets,\n pluginId: result.pluginId,\n ...(result.targets.includes('server')\n ? { serverContracts: await readServerContracts(packageDir, SERVER_DIST) }\n : {}),\n });\n },\n },\n });\n const unsyncedNode = (entries: Record<string, string>, unbundle: boolean): PresetConfig => ({\n ...baseNode,\n entry: entries,\n unbundle,\n });\n const configs =\n !mcpOnly && API_CONTRACTS_ENTRY in entry && Object.keys(entry).length > 1\n ? [\n unsyncedNode({ [API_CONTRACTS_ENTRY]: entry[API_CONTRACTS_ENTRY] }, false),\n node(Object.fromEntries(Object.entries(entry).filter(([name]) => name !== API_CONTRACTS_ENTRY)), true),\n ]\n : [node(entry, !mcpOnly)];\n if (mcpOnly && result.files.has(`${GENERATED_DIR}/mcp-ui.ts`)) return [...configs, browserConfig('mcp-ui')];\n const frontends: (BrowserPresetConfig | NativePresetConfig)[] = mcpOnly\n ? []\n : [\n ...(result.targets.includes('web') ? [browserConfig()] : []),\n ...(result.targets.includes('native') ? [nativeConfig(packageDir)] : []),\n ];\n if (frontends.length > 0) {\n if (Object.keys(entry).length > 0) return [...configs, ...frontends];\n // No node entry to carry the manifest sync, so the first frontend build does.\n const [first, ...rest] = frontends;\n return [{ ...first!, hooks: configs[0]!.hooks }, ...rest];\n }\n return configs.length === 1 ? configs[0]! : configs;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["path","fs","GENERATED_DIR","fsPromises","unistylesBabel","generateExtension","renderMcpWidgets","readServerContracts","SERVER_DIST","require_runtime","require_layout","require_index","require_index$1","require_index$2","require_index$3","require_index$4","node_fs","node_path","node_fs_promises","DEFAULT_EXPORTS_DIR","API_CONTRACTS_ENTRY","exportEntries","absolute","packageDir","exportsDir","entries","file","stem","extensionSourceEntries","server","resourceEntries","root","directory","relative","matches","normalized","staticExports","manifest","declared","target","queryAssetPlugin","queryAt","source","importer","importerFile","id","query","worker","browserConfig","nativeConfig","MCP_OUTPUT","cleanOutput","dist","owner","poExtension","options","result","notice","mcpOnly","emptyMcp","emptyEntry","entry","baseNode","names","name","generated","format","syncBuiltManifest","syncing","node","configs","frontends","first","rest"],"sources":["../../../src/services/tsdownPreset/index.ts"],"sourcesContent":["// sync: Exported poExtension/extensionSourceEntries and the host customExports callback retain synchronous contracts.\nimport fs from 'node:fs';\nimport fsPromises from 'node:fs/promises';\nimport path from 'node:path';\n\nimport { GENERATED_DIR, SERVER_DIST } from '../../constants/layout';\nimport { generateExtension } from '../generate';\nimport type { GenerateOptions } from '../generate/type';\nimport { renderMcpWidgets } from '../renderMcpWidgets';\nimport { readServerContracts } from '../serverContracts';\nimport { writeManifest, writeMcpManifest } from '../syncManifest';\nimport { unistylesBabel } from '../unistylesBabel';\nimport type { UnistylesBabelPlugin } from '../unistylesBabel/type';\n\ninterface EmittedFile {\n readonly type: 'asset' | 'chunk';\n readonly id?: string;\n readonly name: string;\n readonly source?: Buffer;\n}\n\ninterface QueryAssetPlugin {\n readonly name: string;\n resolveId(source: string, importer: string | undefined): string | undefined;\n load(this: { emitFile(file: EmittedFile): string }, id: string): string | undefined | Promise<string | undefined>;\n}\n\n/** The shape a tsdown config needs from this preset, without importing tsdown's types. */\ninterface BrowserPresetConfig {\n entry: Record<string, string>;\n clean: boolean;\n dts: false;\n exports: boolean;\n format: 'esm'[];\n platform: 'browser';\n fixedExtension: boolean;\n external: (id: string) => boolean;\n plugins: QueryAssetPlugin[];\n sourcemap: boolean;\n unbundle: boolean;\n tsconfig: string;\n hooks?: PresetConfig['hooks'];\n}\n\n/** The separately bundled native half, shaped like the browser one. */\ninterface NativePresetConfig extends Omit<BrowserPresetConfig, 'platform' | 'plugins'> {\n platform: 'neutral';\n plugins: UnistylesBabelPlugin[];\n}\n\ninterface GeneratedExports {\n customExports: (exports: Record<string, unknown>) => Record<string, unknown>;\n}\n\ninterface BasePresetConfig {\n entry: Record<string, string>;\n clean: boolean;\n dts: false | { incremental: boolean; parallel: boolean; eager: boolean };\n write?: false;\n plugins?: QueryAssetPlugin[];\n exports: boolean | GeneratedExports;\n format: { esm: Record<string, never>; cjs: { dts: false } };\n platform: 'node';\n sourcemap: boolean;\n unbundle: boolean;\n outExtensions: ({ format }: { format: string }) => {\n js: string;\n dts: string;\n };\n}\n\ninterface PresetConfig extends BasePresetConfig {\n hooks?: { 'build:done': () => void | Promise<void> };\n}\n\nconst DEFAULT_EXPORTS_DIR = 'src/exports';\nconst API_CONTRACTS_ENTRY = 'apiContracts';\n\n/** `src/exports/apiContracts.ts` becomes the `apiContracts` entry; index keeps its name. */\nfunction exportEntries(packageDir: string, exportsDir: string): Record<string, string> {\n const absolute = path.join(packageDir, exportsDir);\n if (!fs.existsSync(absolute)) return {};\n const entries: Record<string, string> = {};\n for (const file of fs.readdirSync(absolute)) {\n if (!file.endsWith('.ts') || file.endsWith('.d.ts')) continue;\n const stem = file.slice(0, -'.ts'.length);\n entries[stem] = `${exportsDir}/${file}`;\n }\n return entries;\n}\n\n/**\n * Source file behind each published subpath of a folder-routed extension, keyed like\n * tsdown entries (`index`, `apiContracts`, `extensions/server`). Read from disk without\n * regenerating, so `generated/server.ts` must already exist. The private Worker build\n * uses this to bundle workspace sources instead of `dist/`.\n */\nexport function extensionSourceEntries(\n packageDir: string,\n exportsDir: string = DEFAULT_EXPORTS_DIR,\n): Record<string, string> {\n const server = `${GENERATED_DIR}/server.ts`;\n return {\n ...exportEntries(packageDir, exportsDir),\n ...(fs.existsSync(path.join(packageDir, server)) ? { 'extensions/server': server } : {}),\n };\n}\n\n/** Static resources receive package export entries without becoming tsdown inputs. */\nfunction resourceEntries(\n packageDir: string,\n directory: string,\n matches: (relative: string) => boolean,\n): Record<string, string> {\n const root = path.join(packageDir, directory);\n if (!fs.existsSync(root)) return {};\n const entries: Record<string, string> = {};\n for (const relative of fs.readdirSync(root, { encoding: 'utf8', recursive: true })) {\n if (!matches(relative)) continue;\n const normalized = relative.split(path.sep).join('/');\n entries[`./${directory}/${normalized}`] = `./${directory}/${normalized}`;\n }\n return entries;\n}\n\n/** Preserves declared resources and discovers default skill and theme resource exports. */\nfunction staticExports(packageDir: string): Record<string, unknown> {\n const manifest = JSON.parse(fs.readFileSync(path.join(packageDir, 'package.json'), 'utf8')) as Record<\n string,\n unknown\n >;\n const declared =\n manifest.exports !== null && typeof manifest.exports === 'object' && !Array.isArray(manifest.exports)\n ? Object.fromEntries(Object.entries(manifest.exports).filter(([, target]) => typeof target === 'string'))\n : {};\n return {\n ...resourceEntries(packageDir, 'skills', (relative) => path.basename(relative) === 'SKILL.md'),\n ...resourceEntries(packageDir, 'themes', (relative) => relative.endsWith('.json')),\n ...declared,\n };\n}\n/**\n * One tsdown config for a folder-routed extension.\n *\n * Entries come from the tree rather than a hand-written list, and the manifest\n * blocks that restate the tree are written after the build rather than kept in\n * step by hand. Browser contributions are emitted through a second bundled\n * config because their routed source is not published.\n */\nexport interface ExtensionPresetOptions extends GenerateOptions {\n /** Extra tsdown entries beyond the derived ones. */\n readonly entry?: Record<string, string>;\n /** Public export modules, package-relative. Defaults to `src/exports`. */\n readonly exportsDir?: string;\n}\n\n/**\n * Implements the Vite query imports extension browser code already uses.\n *\n * `?url` copies an opaque asset and `?worker&url` emits a separately bundled\n * worker chunk. Rolldown then replaces its file reference with an URL relative\n * to the extension bundle, which remains valid when the cockpit composes it.\n */\nfunction queryAssetPlugin(): QueryAssetPlugin {\n return {\n name: 'po-query-assets',\n resolveId(source, importer) {\n const queryAt = source.indexOf('?');\n if (queryAt < 0 || importer === undefined || !source.startsWith('.')) return undefined;\n const importerFile = importer.split('?')[0] as string;\n return `${path.resolve(path.dirname(importerFile), source.slice(0, queryAt))}${source.slice(queryAt)}`;\n },\n async load(id) {\n const queryAt = id.indexOf('?');\n if (queryAt < 0) return undefined;\n const file = id.slice(0, queryAt);\n const query = new URLSearchParams(id.slice(queryAt + 1));\n if (!query.has('url')) return undefined;\n const worker = query.has('worker');\n const reference = this.emitFile(\n worker\n ? { type: 'chunk', id: file, name: path.basename(file, path.extname(file)) }\n : { type: 'asset', name: path.basename(file), source: await fsPromises.readFile(file) },\n );\n return `export default import.meta.ROLLUP_FILE_URL_${reference};`;\n },\n };\n}\n\n/** The separately bundled browser half of a routed extension. */\nfunction browserConfig(target: 'web' | 'mcp-ui' = 'web'): BrowserPresetConfig {\n return {\n entry: { [`extensions/${target}`]: `${GENERATED_DIR}/${target}.ts` },\n clean: false,\n // No declarations. Nothing imports this as a typed module: it has no\n // export subpath, and the cockpit consumes it as a bundle. The browser\n // half is still typechecked, by tsconfig.web.json in the typecheck script.\n dts: false,\n exports: false,\n format: ['esm'],\n platform: 'browser',\n // platform browser turns tsdown's fixedExtension off, which would emit\n // .js. The manifest names .mjs like the other two entries, so ask for it.\n fixedExtension: true,\n // Every bare specifier stays external and the cockpit resolves it, which\n // is what keeps one React and one store in the page no matter how many\n // plugins are installed. An allowlist would have to be kept in step with\n // the cockpit's; this cannot drift.\n //\n // A predicate rather than a pattern: rolldown tests `external` against the\n // resolved id, so /^[^.]/ also matches the absolute path of this package's\n // own routed file and would leave a dangling import to unbuilt .tsx.\n external: (id: string) => !id.startsWith('.') && !path.isAbsolute(id),\n plugins: [queryAssetPlugin()],\n sourcemap: true,\n // Bundled, unlike the node half. Unbundling would emit an import to the\n // routed source file, which is not published and is .tsx besides. One\n // module with only bare specifiers external is what the cockpit wants.\n unbundle: false,\n // Browser routes are excluded from the node tsconfig. Every browser-capable\n // extension owns this focused config for its matching typecheck.\n tsconfig: target === 'web' ? 'tsconfig.web.json' : 'tsconfig.mcp.json',\n };\n}\n\n/**\n * The separately bundled native half of a routed extension.\n *\n * Neutral rather than browser: React Native has neither the DOM nor Node, so\n * no condition set fits it better, and every bare specifier stays external\n * anyway. The CLI bundles this module into the signed composition and refuses\n * any import outside the native host module list, so nothing here has to.\n */\nfunction nativeConfig(packageDir: string): NativePresetConfig {\n return {\n entry: { 'extensions/native': `${GENERATED_DIR}/native.ts` },\n clean: false,\n dts: false,\n exports: false,\n format: ['esm'],\n platform: 'neutral',\n fixedExtension: true,\n // The same predicate as the browser half, for the same reason: the host\n // supplies React, React Native and Unistyles, one copy each.\n external: (id: string) => !id.startsWith('.') && !path.isAbsolute(id),\n plugins: [unistylesBabel(packageDir)],\n sourcemap: true,\n unbundle: false,\n // Native routes import react-native, which the DOM-typed web config must\n // not see, so they typecheck under their own config.\n tsconfig: 'tsconfig.native.json',\n };\n}\n\nconst MCP_OUTPUT = /^(?:extensions\\/mcp(?:-ui)?|.+\\.mcp)\\.(?:mjs|cjs|d\\.mts|d\\.cts)(?:\\.map)?$/u;\n\n/**\n * Removes files from dist that one build owns, so an entry deleted from the source tree does\n * not live on as a stale file (and in the Nx cache). The MCP build removes only its own files;\n * the normal build removes everything else and keeps the MCP files the other build wrote.\n */\nfunction cleanOutput(packageDir: string, owner: 'mcp' | 'normal'): void {\n const dist = path.join(packageDir, 'dist');\n if (!fs.existsSync(dist)) return;\n for (const relative of fs.readdirSync(dist, { recursive: true, encoding: 'utf8' })) {\n const isMcp = MCP_OUTPUT.test(relative.split(path.sep).join('/'));\n if (isMcp !== (owner === 'mcp')) continue;\n const absolute = path.join(dist, relative);\n if (fs.lstatSync(absolute, { throwIfNoEntry: false })?.isFile()) fs.rmSync(absolute);\n }\n}\n\nexport function poExtension(\n options: ExtensionPresetOptions = { packageDir: process.cwd() },\n): PresetConfig | (PresetConfig | BrowserPresetConfig | NativePresetConfig)[] {\n const packageDir = options.packageDir ?? process.cwd();\n const result = generateExtension({ ...options, packageDir, check: options.check ?? false });\n\n for (const notice of result.notices) process.stderr.write(`[po-build] ${notice.path}: ${notice.message}\\n`);\n\n const mcpOnly = options.target === 'mcp';\n // ponytail: the normal build cleans at config load, so it must run before the MCP build (every\n // build script does). Hashed assets of an mcp-ui bundle are not recognised and are rebuilt after.\n if (!options.check) cleanOutput(packageDir, mcpOnly ? 'mcp' : 'normal');\n const emptyMcp = mcpOnly && !result.targets.includes('mcp');\n const emptyEntry = '\\0po-empty-mcp';\n if (emptyMcp && !options.check) writeMcpManifest(packageDir, false);\n const entry: Record<string, string> = mcpOnly\n ? result.targets.includes('mcp')\n ? { 'extensions/mcp': `${GENERATED_DIR}/mcp.ts` }\n : { 'extensions/mcp': emptyEntry }\n : {\n ...exportEntries(packageDir, options.exportsDir ?? DEFAULT_EXPORTS_DIR),\n ...(result.targets.includes('server') ? { 'extensions/server': `${GENERATED_DIR}/server.ts` } : {}),\n ...options.entry,\n };\n\n const baseNode: Omit<BasePresetConfig, 'entry' | 'unbundle'> = {\n // MCP shares dist/ with the normal build, so neither build may erase the other.\n clean: false,\n dts: emptyMcp ? false : { incremental: true, parallel: false, eager: true },\n // tsdown rejects both an empty entry and an empty config array. A virtual\n // input completes its normal lifecycle without publishing an empty facet.\n ...(emptyMcp\n ? {\n write: false as const,\n plugins: [\n {\n name: 'po-empty-mcp',\n resolveId: (source: string) => (source === emptyEntry ? emptyEntry : undefined),\n load: (id: string) => (id === emptyEntry ? 'export {};' : undefined),\n },\n ],\n }\n : {}),\n exports: mcpOnly\n ? false\n : {\n customExports: (generated) => {\n const names = Object.keys(entry);\n const name = names[0];\n return {\n ...staticExports(packageDir),\n ...generated,\n ...(names.length === 1 && name !== undefined && name !== 'index' && !name.startsWith('extensions/')\n ? { [`./${name}`]: generated['.'] }\n : {}),\n };\n },\n },\n // CommonJS keeps its JavaScript but emits no declarations. Every export map\n // resolves types through .d.mts, and a CJS declaration build would rerun\n // the same whole-program tsgo emit a second time.\n format: { esm: {}, cjs: { dts: false } },\n // No minify. This is a library build, and a mangled stack trace inside a\n // published extension is far more expensive than the bytes it saves.\n // Native server entries use the .mjs filenames their hosts require.\n platform: 'node',\n outExtensions: ({ format }) => ({\n js: format === 'es' ? '.mjs' : '.cjs',\n dts: format === 'es' ? '.d.mts' : '.d.cts',\n }),\n sourcemap: true,\n };\n\n // Contract bundles are published as a self-contained graph. Normal extension\n // entries remain unbundled for routed runtime resources, while MCP remains\n // isolated from the shared dist directory.\n const syncBuiltManifest = async (): Promise<void> => {\n if (mcpOnly) {\n writeMcpManifest(\n packageDir,\n result.targets.includes('mcp'),\n renderMcpWidgets(result.graph, result.packageName, GENERATED_DIR).names,\n );\n return;\n }\n writeManifest({\n packageDir,\n manifest: JSON.parse(await fsPromises.readFile(path.join(packageDir, 'package.json'), 'utf8')) as Record<\n string,\n unknown\n >,\n graph: result.graph,\n targets: result.targets,\n pluginId: result.pluginId,\n ...(result.targets.includes('server')\n ? { serverContracts: await readServerContracts(packageDir, SERVER_DIST) }\n : {}),\n });\n };\n // tsdown releases every format of one package together once it has written\n // the exports, so the esm and cjs builds call build:done at the same moment.\n // They share one sync: two would read package.json while the other writes it.\n let syncing: Promise<void> | undefined;\n const node = (entries: Record<string, string>, _unbundle: boolean): PresetConfig => ({\n ...baseNode,\n entry: entries,\n // Public entry facades must remain bundled. Otherwise their relative\n // imports target unbundled implementation chunks, which Vite treats as\n // source files when resolving a workspace package.\n unbundle: false,\n hooks: {\n 'build:done': () =>\n (syncing ??= syncBuiltManifest().finally(() => {\n syncing = undefined;\n })),\n },\n });\n const unsyncedNode = (entries: Record<string, string>, unbundle: boolean): PresetConfig => ({\n ...baseNode,\n entry: entries,\n unbundle,\n });\n const configs =\n !mcpOnly && API_CONTRACTS_ENTRY in entry && Object.keys(entry).length > 1\n ? [\n unsyncedNode({ [API_CONTRACTS_ENTRY]: entry[API_CONTRACTS_ENTRY] }, false),\n node(Object.fromEntries(Object.entries(entry).filter(([name]) => name !== API_CONTRACTS_ENTRY)), true),\n ]\n : [node(entry, !mcpOnly)];\n if (mcpOnly && result.files.has(`${GENERATED_DIR}/mcp-ui.ts`)) return [...configs, browserConfig('mcp-ui')];\n const frontends: (BrowserPresetConfig | NativePresetConfig)[] = mcpOnly\n ? []\n : [\n ...(result.targets.includes('web') ? [browserConfig()] : []),\n ...(result.targets.includes('native') ? [nativeConfig(packageDir)] : []),\n ];\n if (frontends.length > 0) {\n if (Object.keys(entry).length > 0) return [...configs, ...frontends];\n // No node entry to carry the manifest sync, so the first frontend build does.\n const [first, ...rest] = frontends;\n return [{ ...first!, hooks: configs[0]!.hooks }, ...rest];\n }\n return configs.length === 1 ? configs[0]! : configs;\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{GENERATED_DIR as e,SERVER_DIST as t}from"../../constants/layout.mjs";import{renderMcpWidgets as n}from"../renderMcpWidgets/index.mjs";import{generateExtension as r}from"../generate/index.mjs";import{writeManifest as i,writeMcpManifest as a}from"../syncManifest/index.mjs";import{readServerContracts as o}from"../serverContracts/index.mjs";import{unistylesBabel as s}from"../unistylesBabel/index.mjs";import c from"node:fs";import l from"node:path";import u from"node:fs/promises";const d=`src/exports`,f=`apiContracts`;function p(e,t){let n=l.join(e,t);if(!c.existsSync(n))return{};let r={};for(let e of c.readdirSync(n)){if(!e.endsWith(`.ts`)||e.endsWith(`.d.ts`))continue;let n=e.slice(0,-3);r[n]=`${t}/${e}`}return r}function m(t,n=d){let r=`${e}/server.ts`;return{...p(t,n),...c.existsSync(l.join(t,r))?{"extensions/server":r}:{}}}function h(e,t,n){let r=l.join(e,t);if(!c.existsSync(r))return{};let i={};for(let e of c.readdirSync(r,{encoding:`utf8`,recursive:!0})){if(!n(e))continue;let r=e.split(l.sep).join(`/`);i[`./${t}/${r}`]=`./${t}/${r}`}return i}function g(e){let t=JSON.parse(c.readFileSync(l.join(e,`package.json`),`utf8`)),n=t.exports!==null&&typeof t.exports==`object`&&!Array.isArray(t.exports)?Object.fromEntries(Object.entries(t.exports).filter(([,e])=>typeof e==`string`)):{};return{...h(e,`skills`,e=>l.basename(e)===`SKILL.md`),...h(e,`themes`,e=>e.endsWith(`.json`)),...n}}function _(){return{name:`po-query-assets`,resolveId(e,t){let n=e.indexOf(`?`);if(n<0||t===void 0||!e.startsWith(`.`))return;let r=t.split(`?`)[0];return`${l.resolve(l.dirname(r),e.slice(0,n))}${e.slice(n)}`},async load(e){let t=e.indexOf(`?`);if(t<0)return;let n=e.slice(0,t),r=new URLSearchParams(e.slice(t+1));if(!r.has(`url`))return;let i=r.has(`worker`);return`export default import.meta.ROLLUP_FILE_URL_${this.emitFile(i?{type:`chunk`,id:n,name:l.basename(n,l.extname(n))}:{type:`asset`,name:l.basename(n),source:await u.readFile(n)})};`}}}function v(t=`web`){return{entry:{[`extensions/${t}`]:`${e}/${t}.ts`},clean:!1,dts:!1,exports:!1,format:[`esm`],platform:`browser`,fixedExtension:!0,external:e=>!e.startsWith(`.`)&&!l.isAbsolute(e),plugins:[_()],sourcemap:!0,unbundle:!1,tsconfig:t===`web`?`tsconfig.web.json`:`tsconfig.mcp.json`}}function y(t){return{entry:{"extensions/native":`${e}/native.ts`},clean:!1,dts:!1,exports:!1,format:[`esm`],platform:`neutral`,fixedExtension:!0,external:e=>!e.startsWith(`.`)&&!l.isAbsolute(e),plugins:[s(t)],sourcemap:!0,unbundle:!1,tsconfig:`tsconfig.native.json`}}const b=/^(?:extensions\/mcp(?:-ui)?|.+\.mcp)\.(?:mjs|cjs|d\.mts|d\.cts)(?:\.map)?$/u;function x(e,t){let n=l.join(e,`dist`);if(c.existsSync(n))for(let e of c.readdirSync(n,{recursive:!0,encoding:`utf8`})){if(b.test(e.split(l.sep).join(`/`))!==(t===`mcp`))continue;let r=l.join(n,e);c.lstatSync(r,{throwIfNoEntry:!1})?.isFile()&&c.rmSync(r)}}function S(s={packageDir:process.cwd()}){let c=s.packageDir??process.cwd(),m=r({...s,packageDir:c,check:s.check??!1});for(let e of m.notices)process.stderr.write(`[po-build] ${e.path}: ${e.message}\n`);let h=s.target===`mcp`;s.check||x(c,h?`mcp`:`normal`);let _=h&&!m.targets.includes(`mcp`),b=`\0po-empty-mcp`;_&&!s.check&&a(c,!1);let S=h?m.targets.includes(`mcp`)?{"extensions/mcp":`${e}/mcp.ts`}:{"extensions/mcp":b}:{...p(c,s.exportsDir??d),...m.targets.includes(`server`)?{"extensions/server":`${e}/server.ts`}:{},...s.entry},C={clean:!1,dts:!_&&{incremental:!0,parallel:!1,eager:!0},..._?{write:!1,plugins:[{name:`po-empty-mcp`,resolveId:e=>e===b?b:void 0,load:e=>e===b?`export {};`:void 0}]}:{},exports:!h&&{customExports:e=>{let t=Object.keys(S),n=t[0];return{...g(c),...e,...t.length===1&&n!==void 0&&n!==`index`&&!n.startsWith(`extensions/`)?{[`./${n}`]:e[`.`]}:{}}}},format:{esm:{},cjs:{dts:!1}},platform:`node`,outExtensions:({format:e})=>({js:e===`es`?`.mjs`:`.cjs`,dts:e===`es`?`.d.mts`:`.d.cts`}),sourcemap:!0},w=
|
|
1
|
+
import{GENERATED_DIR as e,SERVER_DIST as t}from"../../constants/layout.mjs";import{renderMcpWidgets as n}from"../renderMcpWidgets/index.mjs";import{generateExtension as r}from"../generate/index.mjs";import{writeManifest as i,writeMcpManifest as a}from"../syncManifest/index.mjs";import{readServerContracts as o}from"../serverContracts/index.mjs";import{unistylesBabel as s}from"../unistylesBabel/index.mjs";import c from"node:fs";import l from"node:path";import u from"node:fs/promises";const d=`src/exports`,f=`apiContracts`;function p(e,t){let n=l.join(e,t);if(!c.existsSync(n))return{};let r={};for(let e of c.readdirSync(n)){if(!e.endsWith(`.ts`)||e.endsWith(`.d.ts`))continue;let n=e.slice(0,-3);r[n]=`${t}/${e}`}return r}function m(t,n=d){let r=`${e}/server.ts`;return{...p(t,n),...c.existsSync(l.join(t,r))?{"extensions/server":r}:{}}}function h(e,t,n){let r=l.join(e,t);if(!c.existsSync(r))return{};let i={};for(let e of c.readdirSync(r,{encoding:`utf8`,recursive:!0})){if(!n(e))continue;let r=e.split(l.sep).join(`/`);i[`./${t}/${r}`]=`./${t}/${r}`}return i}function g(e){let t=JSON.parse(c.readFileSync(l.join(e,`package.json`),`utf8`)),n=t.exports!==null&&typeof t.exports==`object`&&!Array.isArray(t.exports)?Object.fromEntries(Object.entries(t.exports).filter(([,e])=>typeof e==`string`)):{};return{...h(e,`skills`,e=>l.basename(e)===`SKILL.md`),...h(e,`themes`,e=>e.endsWith(`.json`)),...n}}function _(){return{name:`po-query-assets`,resolveId(e,t){let n=e.indexOf(`?`);if(n<0||t===void 0||!e.startsWith(`.`))return;let r=t.split(`?`)[0];return`${l.resolve(l.dirname(r),e.slice(0,n))}${e.slice(n)}`},async load(e){let t=e.indexOf(`?`);if(t<0)return;let n=e.slice(0,t),r=new URLSearchParams(e.slice(t+1));if(!r.has(`url`))return;let i=r.has(`worker`);return`export default import.meta.ROLLUP_FILE_URL_${this.emitFile(i?{type:`chunk`,id:n,name:l.basename(n,l.extname(n))}:{type:`asset`,name:l.basename(n),source:await u.readFile(n)})};`}}}function v(t=`web`){return{entry:{[`extensions/${t}`]:`${e}/${t}.ts`},clean:!1,dts:!1,exports:!1,format:[`esm`],platform:`browser`,fixedExtension:!0,external:e=>!e.startsWith(`.`)&&!l.isAbsolute(e),plugins:[_()],sourcemap:!0,unbundle:!1,tsconfig:t===`web`?`tsconfig.web.json`:`tsconfig.mcp.json`}}function y(t){return{entry:{"extensions/native":`${e}/native.ts`},clean:!1,dts:!1,exports:!1,format:[`esm`],platform:`neutral`,fixedExtension:!0,external:e=>!e.startsWith(`.`)&&!l.isAbsolute(e),plugins:[s(t)],sourcemap:!0,unbundle:!1,tsconfig:`tsconfig.native.json`}}const b=/^(?:extensions\/mcp(?:-ui)?|.+\.mcp)\.(?:mjs|cjs|d\.mts|d\.cts)(?:\.map)?$/u;function x(e,t){let n=l.join(e,`dist`);if(c.existsSync(n))for(let e of c.readdirSync(n,{recursive:!0,encoding:`utf8`})){if(b.test(e.split(l.sep).join(`/`))!==(t===`mcp`))continue;let r=l.join(n,e);c.lstatSync(r,{throwIfNoEntry:!1})?.isFile()&&c.rmSync(r)}}function S(s={packageDir:process.cwd()}){let c=s.packageDir??process.cwd(),m=r({...s,packageDir:c,check:s.check??!1});for(let e of m.notices)process.stderr.write(`[po-build] ${e.path}: ${e.message}\n`);let h=s.target===`mcp`;s.check||x(c,h?`mcp`:`normal`);let _=h&&!m.targets.includes(`mcp`),b=`\0po-empty-mcp`;_&&!s.check&&a(c,!1);let S=h?m.targets.includes(`mcp`)?{"extensions/mcp":`${e}/mcp.ts`}:{"extensions/mcp":b}:{...p(c,s.exportsDir??d),...m.targets.includes(`server`)?{"extensions/server":`${e}/server.ts`}:{},...s.entry},C={clean:!1,dts:!_&&{incremental:!0,parallel:!1,eager:!0},..._?{write:!1,plugins:[{name:`po-empty-mcp`,resolveId:e=>e===b?b:void 0,load:e=>e===b?`export {};`:void 0}]}:{},exports:!h&&{customExports:e=>{let t=Object.keys(S),n=t[0];return{...g(c),...e,...t.length===1&&n!==void 0&&n!==`index`&&!n.startsWith(`extensions/`)?{[`./${n}`]:e[`.`]}:{}}}},format:{esm:{},cjs:{dts:!1}},platform:`node`,outExtensions:({format:e})=>({js:e===`es`?`.mjs`:`.cjs`,dts:e===`es`?`.d.mts`:`.d.cts`}),sourcemap:!0},w=async()=>{h?a(c,m.targets.includes(`mcp`),n(m.graph,m.packageName,e).names):i({packageDir:c,manifest:JSON.parse(await u.readFile(l.join(c,`package.json`),`utf8`)),graph:m.graph,targets:m.targets,pluginId:m.pluginId,...m.targets.includes(`server`)?{serverContracts:await o(c,t)}:{}})},T,E=(e,t)=>({...C,entry:e,unbundle:!1,hooks:{"build:done":()=>T??=w().finally(()=>{T=void 0})}}),D=!h&&f in S&&Object.keys(S).length>1?[((e,t)=>({...C,entry:e,unbundle:t}))({[f]:S[f]},!1),E(Object.fromEntries(Object.entries(S).filter(([e])=>e!==f)),!0)]:[E(S,!h)];if(h&&m.files.has(`generated/mcp-ui.ts`))return[...D,v(`mcp-ui`)];let O=h?[]:[...m.targets.includes(`web`)?[v()]:[],...m.targets.includes(`native`)?[y(c)]:[]];if(O.length>0){if(Object.keys(S).length>0)return[...D,...O];let[e,...t]=O;return[{...e,hooks:D[0].hooks},...t]}return D.length===1?D[0]:D}export{m as extensionSourceEntries,S as poExtension};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["fsPromises","fs","path","fs$1","DEFAULT_EXPORTS_DIR","API_CONTRACTS_ENTRY","exportEntries","absolute","packageDir","exportsDir","entries","file","stem","extensionSourceEntries","server","GENERATED_DIR","resourceEntries","root","directory","relative","matches","normalized","staticExports","manifest","declared","target","queryAssetPlugin","queryAt","source","importer","importerFile","id","query","worker","browserConfig","nativeConfig","unistylesBabel","MCP_OUTPUT","cleanOutput","dist","owner","poExtension","options","result","generateExtension","notice","mcpOnly","emptyMcp","emptyEntry","writeMcpManifest","entry","baseNode","names","name","generated","format","node","renderMcpWidgets","writeManifest","readServerContracts","SERVER_DIST","configs","frontends","first","rest"],"sources":["../../../src/services/tsdownPreset/index.ts"],"sourcesContent":["// sync: Exported poExtension/extensionSourceEntries and the host customExports callback retain synchronous contracts.\nimport fs from 'node:fs';\nimport fsPromises from 'node:fs/promises';\nimport path from 'node:path';\n\nimport { GENERATED_DIR, SERVER_DIST } from '../../constants/layout';\nimport { generateExtension } from '../generate';\nimport type { GenerateOptions } from '../generate/type';\nimport { renderMcpWidgets } from '../renderMcpWidgets';\nimport { readServerContracts } from '../serverContracts';\nimport { writeManifest, writeMcpManifest } from '../syncManifest';\nimport { unistylesBabel } from '../unistylesBabel';\nimport type { UnistylesBabelPlugin } from '../unistylesBabel/type';\n\ninterface EmittedFile {\n readonly type: 'asset' | 'chunk';\n readonly id?: string;\n readonly name: string;\n readonly source?: Buffer;\n}\n\ninterface QueryAssetPlugin {\n readonly name: string;\n resolveId(source: string, importer: string | undefined): string | undefined;\n load(this: { emitFile(file: EmittedFile): string }, id: string): string | undefined | Promise<string | undefined>;\n}\n\n/** The shape a tsdown config needs from this preset, without importing tsdown's types. */\ninterface BrowserPresetConfig {\n entry: Record<string, string>;\n clean: boolean;\n dts: false;\n exports: boolean;\n format: 'esm'[];\n platform: 'browser';\n fixedExtension: boolean;\n external: (id: string) => boolean;\n plugins: QueryAssetPlugin[];\n sourcemap: boolean;\n unbundle: boolean;\n tsconfig: string;\n hooks?: PresetConfig['hooks'];\n}\n\n/** The separately bundled native half, shaped like the browser one. */\ninterface NativePresetConfig extends Omit<BrowserPresetConfig, 'platform' | 'plugins'> {\n platform: 'neutral';\n plugins: UnistylesBabelPlugin[];\n}\n\ninterface GeneratedExports {\n customExports: (exports: Record<string, unknown>) => Record<string, unknown>;\n}\n\ninterface BasePresetConfig {\n entry: Record<string, string>;\n clean: boolean;\n dts: false | { incremental: boolean; parallel: boolean; eager: boolean };\n write?: false;\n plugins?: QueryAssetPlugin[];\n exports: boolean | GeneratedExports;\n format: { esm: Record<string, never>; cjs: { dts: false } };\n platform: 'node';\n sourcemap: boolean;\n unbundle: boolean;\n outExtensions: ({ format }: { format: string }) => {\n js: string;\n dts: string;\n };\n}\n\ninterface PresetConfig extends BasePresetConfig {\n hooks?: { 'build:done': () => void | Promise<void> };\n}\n\nconst DEFAULT_EXPORTS_DIR = 'src/exports';\nconst API_CONTRACTS_ENTRY = 'apiContracts';\n\n/** `src/exports/apiContracts.ts` becomes the `apiContracts` entry; index keeps its name. */\nfunction exportEntries(packageDir: string, exportsDir: string): Record<string, string> {\n const absolute = path.join(packageDir, exportsDir);\n if (!fs.existsSync(absolute)) return {};\n const entries: Record<string, string> = {};\n for (const file of fs.readdirSync(absolute)) {\n if (!file.endsWith('.ts') || file.endsWith('.d.ts')) continue;\n const stem = file.slice(0, -'.ts'.length);\n entries[stem] = `${exportsDir}/${file}`;\n }\n return entries;\n}\n\n/**\n * Source file behind each published subpath of a folder-routed extension, keyed like\n * tsdown entries (`index`, `apiContracts`, `extensions/server`). Read from disk without\n * regenerating, so `generated/server.ts` must already exist. The private Worker build\n * uses this to bundle workspace sources instead of `dist/`.\n */\nexport function extensionSourceEntries(\n packageDir: string,\n exportsDir: string = DEFAULT_EXPORTS_DIR,\n): Record<string, string> {\n const server = `${GENERATED_DIR}/server.ts`;\n return {\n ...exportEntries(packageDir, exportsDir),\n ...(fs.existsSync(path.join(packageDir, server)) ? { 'extensions/server': server } : {}),\n };\n}\n\n/** Static resources receive package export entries without becoming tsdown inputs. */\nfunction resourceEntries(\n packageDir: string,\n directory: string,\n matches: (relative: string) => boolean,\n): Record<string, string> {\n const root = path.join(packageDir, directory);\n if (!fs.existsSync(root)) return {};\n const entries: Record<string, string> = {};\n for (const relative of fs.readdirSync(root, { encoding: 'utf8', recursive: true })) {\n if (!matches(relative)) continue;\n const normalized = relative.split(path.sep).join('/');\n entries[`./${directory}/${normalized}`] = `./${directory}/${normalized}`;\n }\n return entries;\n}\n\n/** Preserves declared resources and discovers default skill and theme resource exports. */\nfunction staticExports(packageDir: string): Record<string, unknown> {\n const manifest = JSON.parse(fs.readFileSync(path.join(packageDir, 'package.json'), 'utf8')) as Record<\n string,\n unknown\n >;\n const declared =\n manifest.exports !== null && typeof manifest.exports === 'object' && !Array.isArray(manifest.exports)\n ? Object.fromEntries(Object.entries(manifest.exports).filter(([, target]) => typeof target === 'string'))\n : {};\n return {\n ...resourceEntries(packageDir, 'skills', (relative) => path.basename(relative) === 'SKILL.md'),\n ...resourceEntries(packageDir, 'themes', (relative) => relative.endsWith('.json')),\n ...declared,\n };\n}\n/**\n * One tsdown config for a folder-routed extension.\n *\n * Entries come from the tree rather than a hand-written list, and the manifest\n * blocks that restate the tree are written after the build rather than kept in\n * step by hand. Browser contributions are emitted through a second bundled\n * config because their routed source is not published.\n */\nexport interface ExtensionPresetOptions extends GenerateOptions {\n /** Extra tsdown entries beyond the derived ones. */\n readonly entry?: Record<string, string>;\n /** Public export modules, package-relative. Defaults to `src/exports`. */\n readonly exportsDir?: string;\n}\n\n/**\n * Implements the Vite query imports extension browser code already uses.\n *\n * `?url` copies an opaque asset and `?worker&url` emits a separately bundled\n * worker chunk. Rolldown then replaces its file reference with an URL relative\n * to the extension bundle, which remains valid when the cockpit composes it.\n */\nfunction queryAssetPlugin(): QueryAssetPlugin {\n return {\n name: 'po-query-assets',\n resolveId(source, importer) {\n const queryAt = source.indexOf('?');\n if (queryAt < 0 || importer === undefined || !source.startsWith('.')) return undefined;\n const importerFile = importer.split('?')[0] as string;\n return `${path.resolve(path.dirname(importerFile), source.slice(0, queryAt))}${source.slice(queryAt)}`;\n },\n async load(id) {\n const queryAt = id.indexOf('?');\n if (queryAt < 0) return undefined;\n const file = id.slice(0, queryAt);\n const query = new URLSearchParams(id.slice(queryAt + 1));\n if (!query.has('url')) return undefined;\n const worker = query.has('worker');\n const reference = this.emitFile(\n worker\n ? { type: 'chunk', id: file, name: path.basename(file, path.extname(file)) }\n : { type: 'asset', name: path.basename(file), source: await fsPromises.readFile(file) },\n );\n return `export default import.meta.ROLLUP_FILE_URL_${reference};`;\n },\n };\n}\n\n/** The separately bundled browser half of a routed extension. */\nfunction browserConfig(target: 'web' | 'mcp-ui' = 'web'): BrowserPresetConfig {\n return {\n entry: { [`extensions/${target}`]: `${GENERATED_DIR}/${target}.ts` },\n clean: false,\n // No declarations. Nothing imports this as a typed module: it has no\n // export subpath, and the cockpit consumes it as a bundle. The browser\n // half is still typechecked, by tsconfig.web.json in the typecheck script.\n dts: false,\n exports: false,\n format: ['esm'],\n platform: 'browser',\n // platform browser turns tsdown's fixedExtension off, which would emit\n // .js. The manifest names .mjs like the other two entries, so ask for it.\n fixedExtension: true,\n // Every bare specifier stays external and the cockpit resolves it, which\n // is what keeps one React and one store in the page no matter how many\n // plugins are installed. An allowlist would have to be kept in step with\n // the cockpit's; this cannot drift.\n //\n // A predicate rather than a pattern: rolldown tests `external` against the\n // resolved id, so /^[^.]/ also matches the absolute path of this package's\n // own routed file and would leave a dangling import to unbuilt .tsx.\n external: (id: string) => !id.startsWith('.') && !path.isAbsolute(id),\n plugins: [queryAssetPlugin()],\n sourcemap: true,\n // Bundled, unlike the node half. Unbundling would emit an import to the\n // routed source file, which is not published and is .tsx besides. One\n // module with only bare specifiers external is what the cockpit wants.\n unbundle: false,\n // Browser routes are excluded from the node tsconfig. Every browser-capable\n // extension owns this focused config for its matching typecheck.\n tsconfig: target === 'web' ? 'tsconfig.web.json' : 'tsconfig.mcp.json',\n };\n}\n\n/**\n * The separately bundled native half of a routed extension.\n *\n * Neutral rather than browser: React Native has neither the DOM nor Node, so\n * no condition set fits it better, and every bare specifier stays external\n * anyway. The CLI bundles this module into the signed composition and refuses\n * any import outside the native host module list, so nothing here has to.\n */\nfunction nativeConfig(packageDir: string): NativePresetConfig {\n return {\n entry: { 'extensions/native': `${GENERATED_DIR}/native.ts` },\n clean: false,\n dts: false,\n exports: false,\n format: ['esm'],\n platform: 'neutral',\n fixedExtension: true,\n // The same predicate as the browser half, for the same reason: the host\n // supplies React, React Native and Unistyles, one copy each.\n external: (id: string) => !id.startsWith('.') && !path.isAbsolute(id),\n plugins: [unistylesBabel(packageDir)],\n sourcemap: true,\n unbundle: false,\n // Native routes import react-native, which the DOM-typed web config must\n // not see, so they typecheck under their own config.\n tsconfig: 'tsconfig.native.json',\n };\n}\n\nconst MCP_OUTPUT = /^(?:extensions\\/mcp(?:-ui)?|.+\\.mcp)\\.(?:mjs|cjs|d\\.mts|d\\.cts)(?:\\.map)?$/u;\n\n/**\n * Removes files from dist that one build owns, so an entry deleted from the source tree does\n * not live on as a stale file (and in the Nx cache). The MCP build removes only its own files;\n * the normal build removes everything else and keeps the MCP files the other build wrote.\n */\nfunction cleanOutput(packageDir: string, owner: 'mcp' | 'normal'): void {\n const dist = path.join(packageDir, 'dist');\n if (!fs.existsSync(dist)) return;\n for (const relative of fs.readdirSync(dist, { recursive: true, encoding: 'utf8' })) {\n const isMcp = MCP_OUTPUT.test(relative.split(path.sep).join('/'));\n if (isMcp !== (owner === 'mcp')) continue;\n const absolute = path.join(dist, relative);\n if (fs.lstatSync(absolute, { throwIfNoEntry: false })?.isFile()) fs.rmSync(absolute);\n }\n}\n\nexport function poExtension(\n options: ExtensionPresetOptions = { packageDir: process.cwd() },\n): PresetConfig | (PresetConfig | BrowserPresetConfig | NativePresetConfig)[] {\n const packageDir = options.packageDir ?? process.cwd();\n const result = generateExtension({ ...options, packageDir, check: options.check ?? false });\n\n for (const notice of result.notices) process.stderr.write(`[po-build] ${notice.path}: ${notice.message}\\n`);\n\n const mcpOnly = options.target === 'mcp';\n // ponytail: the normal build cleans at config load, so it must run before the MCP build (every\n // build script does). Hashed assets of an mcp-ui bundle are not recognised and are rebuilt after.\n if (!options.check) cleanOutput(packageDir, mcpOnly ? 'mcp' : 'normal');\n const emptyMcp = mcpOnly && !result.targets.includes('mcp');\n const emptyEntry = '\\0po-empty-mcp';\n if (emptyMcp && !options.check) writeMcpManifest(packageDir, false);\n const entry: Record<string, string> = mcpOnly\n ? result.targets.includes('mcp')\n ? { 'extensions/mcp': `${GENERATED_DIR}/mcp.ts` }\n : { 'extensions/mcp': emptyEntry }\n : {\n ...exportEntries(packageDir, options.exportsDir ?? DEFAULT_EXPORTS_DIR),\n ...(result.targets.includes('server') ? { 'extensions/server': `${GENERATED_DIR}/server.ts` } : {}),\n ...options.entry,\n };\n\n const baseNode: Omit<BasePresetConfig, 'entry' | 'unbundle'> = {\n // MCP shares dist/ with the normal build, so neither build may erase the other.\n clean: false,\n dts: emptyMcp ? false : { incremental: true, parallel: false, eager: true },\n // tsdown rejects both an empty entry and an empty config array. A virtual\n // input completes its normal lifecycle without publishing an empty facet.\n ...(emptyMcp\n ? {\n write: false as const,\n plugins: [\n {\n name: 'po-empty-mcp',\n resolveId: (source: string) => (source === emptyEntry ? emptyEntry : undefined),\n load: (id: string) => (id === emptyEntry ? 'export {};' : undefined),\n },\n ],\n }\n : {}),\n exports: mcpOnly\n ? false\n : {\n customExports: (generated) => {\n const names = Object.keys(entry);\n const name = names[0];\n return {\n ...staticExports(packageDir),\n ...generated,\n ...(names.length === 1 && name !== undefined && name !== 'index' && !name.startsWith('extensions/')\n ? { [`./${name}`]: generated['.'] }\n : {}),\n };\n },\n },\n // CommonJS keeps its JavaScript but emits no declarations. Every export map\n // resolves types through .d.mts, and a CJS declaration build would rerun\n // the same whole-program tsgo emit a second time.\n format: { esm: {}, cjs: { dts: false } },\n // No minify. This is a library build, and a mangled stack trace inside a\n // published extension is far more expensive than the bytes it saves.\n // Native server entries use the .mjs filenames their hosts require.\n platform: 'node',\n outExtensions: ({ format }) => ({\n js: format === 'es' ? '.mjs' : '.cjs',\n dts: format === 'es' ? '.d.mts' : '.d.cts',\n }),\n sourcemap: true,\n };\n\n // Contract bundles are published as a self-contained graph. Normal extension\n // entries remain unbundled for routed runtime resources, while MCP remains\n // isolated from the shared dist directory.\n const node = (entries: Record<string, string>, _unbundle: boolean): PresetConfig => ({\n ...baseNode,\n entry: entries,\n // Public entry facades must remain bundled. Otherwise their relative\n // imports target unbundled implementation chunks, which Vite treats as\n // source files when resolving a workspace package.\n unbundle: false,\n hooks: {\n 'build:done': async () => {\n if (mcpOnly) {\n writeMcpManifest(\n packageDir,\n result.targets.includes('mcp'),\n renderMcpWidgets(result.graph, result.packageName, GENERATED_DIR).names,\n );\n return;\n }\n writeManifest({\n packageDir,\n manifest: JSON.parse(await fsPromises.readFile(path.join(packageDir, 'package.json'), 'utf8')) as Record<\n string,\n unknown\n >,\n graph: result.graph,\n targets: result.targets,\n pluginId: result.pluginId,\n ...(result.targets.includes('server')\n ? { serverContracts: await readServerContracts(packageDir, SERVER_DIST) }\n : {}),\n });\n },\n },\n });\n const unsyncedNode = (entries: Record<string, string>, unbundle: boolean): PresetConfig => ({\n ...baseNode,\n entry: entries,\n unbundle,\n });\n const configs =\n !mcpOnly && API_CONTRACTS_ENTRY in entry && Object.keys(entry).length > 1\n ? [\n unsyncedNode({ [API_CONTRACTS_ENTRY]: entry[API_CONTRACTS_ENTRY] }, false),\n node(Object.fromEntries(Object.entries(entry).filter(([name]) => name !== API_CONTRACTS_ENTRY)), true),\n ]\n : [node(entry, !mcpOnly)];\n if (mcpOnly && result.files.has(`${GENERATED_DIR}/mcp-ui.ts`)) return [...configs, browserConfig('mcp-ui')];\n const frontends: (BrowserPresetConfig | NativePresetConfig)[] = mcpOnly\n ? []\n : [\n ...(result.targets.includes('web') ? [browserConfig()] : []),\n ...(result.targets.includes('native') ? [nativeConfig(packageDir)] : []),\n ];\n if (frontends.length > 0) {\n if (Object.keys(entry).length > 0) return [...configs, ...frontends];\n // No node entry to carry the manifest sync, so the first frontend build does.\n const [first, ...rest] = frontends;\n return [{ ...first!, hooks: configs[0]!.hooks }, ...rest];\n }\n return configs.length === 1 ? configs[0]! : configs;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["fsPromises","fs","path","fs$1","DEFAULT_EXPORTS_DIR","API_CONTRACTS_ENTRY","exportEntries","absolute","packageDir","exportsDir","entries","file","stem","extensionSourceEntries","server","GENERATED_DIR","resourceEntries","root","directory","relative","matches","normalized","staticExports","manifest","declared","target","queryAssetPlugin","queryAt","source","importer","importerFile","id","query","worker","browserConfig","nativeConfig","unistylesBabel","MCP_OUTPUT","cleanOutput","dist","owner","poExtension","options","result","generateExtension","notice","mcpOnly","emptyMcp","emptyEntry","writeMcpManifest","entry","baseNode","names","name","generated","format","syncBuiltManifest","renderMcpWidgets","writeManifest","readServerContracts","SERVER_DIST","syncing","node","configs","frontends","first","rest"],"sources":["../../../src/services/tsdownPreset/index.ts"],"sourcesContent":["// sync: Exported poExtension/extensionSourceEntries and the host customExports callback retain synchronous contracts.\nimport fs from 'node:fs';\nimport fsPromises from 'node:fs/promises';\nimport path from 'node:path';\n\nimport { GENERATED_DIR, SERVER_DIST } from '../../constants/layout';\nimport { generateExtension } from '../generate';\nimport type { GenerateOptions } from '../generate/type';\nimport { renderMcpWidgets } from '../renderMcpWidgets';\nimport { readServerContracts } from '../serverContracts';\nimport { writeManifest, writeMcpManifest } from '../syncManifest';\nimport { unistylesBabel } from '../unistylesBabel';\nimport type { UnistylesBabelPlugin } from '../unistylesBabel/type';\n\ninterface EmittedFile {\n readonly type: 'asset' | 'chunk';\n readonly id?: string;\n readonly name: string;\n readonly source?: Buffer;\n}\n\ninterface QueryAssetPlugin {\n readonly name: string;\n resolveId(source: string, importer: string | undefined): string | undefined;\n load(this: { emitFile(file: EmittedFile): string }, id: string): string | undefined | Promise<string | undefined>;\n}\n\n/** The shape a tsdown config needs from this preset, without importing tsdown's types. */\ninterface BrowserPresetConfig {\n entry: Record<string, string>;\n clean: boolean;\n dts: false;\n exports: boolean;\n format: 'esm'[];\n platform: 'browser';\n fixedExtension: boolean;\n external: (id: string) => boolean;\n plugins: QueryAssetPlugin[];\n sourcemap: boolean;\n unbundle: boolean;\n tsconfig: string;\n hooks?: PresetConfig['hooks'];\n}\n\n/** The separately bundled native half, shaped like the browser one. */\ninterface NativePresetConfig extends Omit<BrowserPresetConfig, 'platform' | 'plugins'> {\n platform: 'neutral';\n plugins: UnistylesBabelPlugin[];\n}\n\ninterface GeneratedExports {\n customExports: (exports: Record<string, unknown>) => Record<string, unknown>;\n}\n\ninterface BasePresetConfig {\n entry: Record<string, string>;\n clean: boolean;\n dts: false | { incremental: boolean; parallel: boolean; eager: boolean };\n write?: false;\n plugins?: QueryAssetPlugin[];\n exports: boolean | GeneratedExports;\n format: { esm: Record<string, never>; cjs: { dts: false } };\n platform: 'node';\n sourcemap: boolean;\n unbundle: boolean;\n outExtensions: ({ format }: { format: string }) => {\n js: string;\n dts: string;\n };\n}\n\ninterface PresetConfig extends BasePresetConfig {\n hooks?: { 'build:done': () => void | Promise<void> };\n}\n\nconst DEFAULT_EXPORTS_DIR = 'src/exports';\nconst API_CONTRACTS_ENTRY = 'apiContracts';\n\n/** `src/exports/apiContracts.ts` becomes the `apiContracts` entry; index keeps its name. */\nfunction exportEntries(packageDir: string, exportsDir: string): Record<string, string> {\n const absolute = path.join(packageDir, exportsDir);\n if (!fs.existsSync(absolute)) return {};\n const entries: Record<string, string> = {};\n for (const file of fs.readdirSync(absolute)) {\n if (!file.endsWith('.ts') || file.endsWith('.d.ts')) continue;\n const stem = file.slice(0, -'.ts'.length);\n entries[stem] = `${exportsDir}/${file}`;\n }\n return entries;\n}\n\n/**\n * Source file behind each published subpath of a folder-routed extension, keyed like\n * tsdown entries (`index`, `apiContracts`, `extensions/server`). Read from disk without\n * regenerating, so `generated/server.ts` must already exist. The private Worker build\n * uses this to bundle workspace sources instead of `dist/`.\n */\nexport function extensionSourceEntries(\n packageDir: string,\n exportsDir: string = DEFAULT_EXPORTS_DIR,\n): Record<string, string> {\n const server = `${GENERATED_DIR}/server.ts`;\n return {\n ...exportEntries(packageDir, exportsDir),\n ...(fs.existsSync(path.join(packageDir, server)) ? { 'extensions/server': server } : {}),\n };\n}\n\n/** Static resources receive package export entries without becoming tsdown inputs. */\nfunction resourceEntries(\n packageDir: string,\n directory: string,\n matches: (relative: string) => boolean,\n): Record<string, string> {\n const root = path.join(packageDir, directory);\n if (!fs.existsSync(root)) return {};\n const entries: Record<string, string> = {};\n for (const relative of fs.readdirSync(root, { encoding: 'utf8', recursive: true })) {\n if (!matches(relative)) continue;\n const normalized = relative.split(path.sep).join('/');\n entries[`./${directory}/${normalized}`] = `./${directory}/${normalized}`;\n }\n return entries;\n}\n\n/** Preserves declared resources and discovers default skill and theme resource exports. */\nfunction staticExports(packageDir: string): Record<string, unknown> {\n const manifest = JSON.parse(fs.readFileSync(path.join(packageDir, 'package.json'), 'utf8')) as Record<\n string,\n unknown\n >;\n const declared =\n manifest.exports !== null && typeof manifest.exports === 'object' && !Array.isArray(manifest.exports)\n ? Object.fromEntries(Object.entries(manifest.exports).filter(([, target]) => typeof target === 'string'))\n : {};\n return {\n ...resourceEntries(packageDir, 'skills', (relative) => path.basename(relative) === 'SKILL.md'),\n ...resourceEntries(packageDir, 'themes', (relative) => relative.endsWith('.json')),\n ...declared,\n };\n}\n/**\n * One tsdown config for a folder-routed extension.\n *\n * Entries come from the tree rather than a hand-written list, and the manifest\n * blocks that restate the tree are written after the build rather than kept in\n * step by hand. Browser contributions are emitted through a second bundled\n * config because their routed source is not published.\n */\nexport interface ExtensionPresetOptions extends GenerateOptions {\n /** Extra tsdown entries beyond the derived ones. */\n readonly entry?: Record<string, string>;\n /** Public export modules, package-relative. Defaults to `src/exports`. */\n readonly exportsDir?: string;\n}\n\n/**\n * Implements the Vite query imports extension browser code already uses.\n *\n * `?url` copies an opaque asset and `?worker&url` emits a separately bundled\n * worker chunk. Rolldown then replaces its file reference with an URL relative\n * to the extension bundle, which remains valid when the cockpit composes it.\n */\nfunction queryAssetPlugin(): QueryAssetPlugin {\n return {\n name: 'po-query-assets',\n resolveId(source, importer) {\n const queryAt = source.indexOf('?');\n if (queryAt < 0 || importer === undefined || !source.startsWith('.')) return undefined;\n const importerFile = importer.split('?')[0] as string;\n return `${path.resolve(path.dirname(importerFile), source.slice(0, queryAt))}${source.slice(queryAt)}`;\n },\n async load(id) {\n const queryAt = id.indexOf('?');\n if (queryAt < 0) return undefined;\n const file = id.slice(0, queryAt);\n const query = new URLSearchParams(id.slice(queryAt + 1));\n if (!query.has('url')) return undefined;\n const worker = query.has('worker');\n const reference = this.emitFile(\n worker\n ? { type: 'chunk', id: file, name: path.basename(file, path.extname(file)) }\n : { type: 'asset', name: path.basename(file), source: await fsPromises.readFile(file) },\n );\n return `export default import.meta.ROLLUP_FILE_URL_${reference};`;\n },\n };\n}\n\n/** The separately bundled browser half of a routed extension. */\nfunction browserConfig(target: 'web' | 'mcp-ui' = 'web'): BrowserPresetConfig {\n return {\n entry: { [`extensions/${target}`]: `${GENERATED_DIR}/${target}.ts` },\n clean: false,\n // No declarations. Nothing imports this as a typed module: it has no\n // export subpath, and the cockpit consumes it as a bundle. The browser\n // half is still typechecked, by tsconfig.web.json in the typecheck script.\n dts: false,\n exports: false,\n format: ['esm'],\n platform: 'browser',\n // platform browser turns tsdown's fixedExtension off, which would emit\n // .js. The manifest names .mjs like the other two entries, so ask for it.\n fixedExtension: true,\n // Every bare specifier stays external and the cockpit resolves it, which\n // is what keeps one React and one store in the page no matter how many\n // plugins are installed. An allowlist would have to be kept in step with\n // the cockpit's; this cannot drift.\n //\n // A predicate rather than a pattern: rolldown tests `external` against the\n // resolved id, so /^[^.]/ also matches the absolute path of this package's\n // own routed file and would leave a dangling import to unbuilt .tsx.\n external: (id: string) => !id.startsWith('.') && !path.isAbsolute(id),\n plugins: [queryAssetPlugin()],\n sourcemap: true,\n // Bundled, unlike the node half. Unbundling would emit an import to the\n // routed source file, which is not published and is .tsx besides. One\n // module with only bare specifiers external is what the cockpit wants.\n unbundle: false,\n // Browser routes are excluded from the node tsconfig. Every browser-capable\n // extension owns this focused config for its matching typecheck.\n tsconfig: target === 'web' ? 'tsconfig.web.json' : 'tsconfig.mcp.json',\n };\n}\n\n/**\n * The separately bundled native half of a routed extension.\n *\n * Neutral rather than browser: React Native has neither the DOM nor Node, so\n * no condition set fits it better, and every bare specifier stays external\n * anyway. The CLI bundles this module into the signed composition and refuses\n * any import outside the native host module list, so nothing here has to.\n */\nfunction nativeConfig(packageDir: string): NativePresetConfig {\n return {\n entry: { 'extensions/native': `${GENERATED_DIR}/native.ts` },\n clean: false,\n dts: false,\n exports: false,\n format: ['esm'],\n platform: 'neutral',\n fixedExtension: true,\n // The same predicate as the browser half, for the same reason: the host\n // supplies React, React Native and Unistyles, one copy each.\n external: (id: string) => !id.startsWith('.') && !path.isAbsolute(id),\n plugins: [unistylesBabel(packageDir)],\n sourcemap: true,\n unbundle: false,\n // Native routes import react-native, which the DOM-typed web config must\n // not see, so they typecheck under their own config.\n tsconfig: 'tsconfig.native.json',\n };\n}\n\nconst MCP_OUTPUT = /^(?:extensions\\/mcp(?:-ui)?|.+\\.mcp)\\.(?:mjs|cjs|d\\.mts|d\\.cts)(?:\\.map)?$/u;\n\n/**\n * Removes files from dist that one build owns, so an entry deleted from the source tree does\n * not live on as a stale file (and in the Nx cache). The MCP build removes only its own files;\n * the normal build removes everything else and keeps the MCP files the other build wrote.\n */\nfunction cleanOutput(packageDir: string, owner: 'mcp' | 'normal'): void {\n const dist = path.join(packageDir, 'dist');\n if (!fs.existsSync(dist)) return;\n for (const relative of fs.readdirSync(dist, { recursive: true, encoding: 'utf8' })) {\n const isMcp = MCP_OUTPUT.test(relative.split(path.sep).join('/'));\n if (isMcp !== (owner === 'mcp')) continue;\n const absolute = path.join(dist, relative);\n if (fs.lstatSync(absolute, { throwIfNoEntry: false })?.isFile()) fs.rmSync(absolute);\n }\n}\n\nexport function poExtension(\n options: ExtensionPresetOptions = { packageDir: process.cwd() },\n): PresetConfig | (PresetConfig | BrowserPresetConfig | NativePresetConfig)[] {\n const packageDir = options.packageDir ?? process.cwd();\n const result = generateExtension({ ...options, packageDir, check: options.check ?? false });\n\n for (const notice of result.notices) process.stderr.write(`[po-build] ${notice.path}: ${notice.message}\\n`);\n\n const mcpOnly = options.target === 'mcp';\n // ponytail: the normal build cleans at config load, so it must run before the MCP build (every\n // build script does). Hashed assets of an mcp-ui bundle are not recognised and are rebuilt after.\n if (!options.check) cleanOutput(packageDir, mcpOnly ? 'mcp' : 'normal');\n const emptyMcp = mcpOnly && !result.targets.includes('mcp');\n const emptyEntry = '\\0po-empty-mcp';\n if (emptyMcp && !options.check) writeMcpManifest(packageDir, false);\n const entry: Record<string, string> = mcpOnly\n ? result.targets.includes('mcp')\n ? { 'extensions/mcp': `${GENERATED_DIR}/mcp.ts` }\n : { 'extensions/mcp': emptyEntry }\n : {\n ...exportEntries(packageDir, options.exportsDir ?? DEFAULT_EXPORTS_DIR),\n ...(result.targets.includes('server') ? { 'extensions/server': `${GENERATED_DIR}/server.ts` } : {}),\n ...options.entry,\n };\n\n const baseNode: Omit<BasePresetConfig, 'entry' | 'unbundle'> = {\n // MCP shares dist/ with the normal build, so neither build may erase the other.\n clean: false,\n dts: emptyMcp ? false : { incremental: true, parallel: false, eager: true },\n // tsdown rejects both an empty entry and an empty config array. A virtual\n // input completes its normal lifecycle without publishing an empty facet.\n ...(emptyMcp\n ? {\n write: false as const,\n plugins: [\n {\n name: 'po-empty-mcp',\n resolveId: (source: string) => (source === emptyEntry ? emptyEntry : undefined),\n load: (id: string) => (id === emptyEntry ? 'export {};' : undefined),\n },\n ],\n }\n : {}),\n exports: mcpOnly\n ? false\n : {\n customExports: (generated) => {\n const names = Object.keys(entry);\n const name = names[0];\n return {\n ...staticExports(packageDir),\n ...generated,\n ...(names.length === 1 && name !== undefined && name !== 'index' && !name.startsWith('extensions/')\n ? { [`./${name}`]: generated['.'] }\n : {}),\n };\n },\n },\n // CommonJS keeps its JavaScript but emits no declarations. Every export map\n // resolves types through .d.mts, and a CJS declaration build would rerun\n // the same whole-program tsgo emit a second time.\n format: { esm: {}, cjs: { dts: false } },\n // No minify. This is a library build, and a mangled stack trace inside a\n // published extension is far more expensive than the bytes it saves.\n // Native server entries use the .mjs filenames their hosts require.\n platform: 'node',\n outExtensions: ({ format }) => ({\n js: format === 'es' ? '.mjs' : '.cjs',\n dts: format === 'es' ? '.d.mts' : '.d.cts',\n }),\n sourcemap: true,\n };\n\n // Contract bundles are published as a self-contained graph. Normal extension\n // entries remain unbundled for routed runtime resources, while MCP remains\n // isolated from the shared dist directory.\n const syncBuiltManifest = async (): Promise<void> => {\n if (mcpOnly) {\n writeMcpManifest(\n packageDir,\n result.targets.includes('mcp'),\n renderMcpWidgets(result.graph, result.packageName, GENERATED_DIR).names,\n );\n return;\n }\n writeManifest({\n packageDir,\n manifest: JSON.parse(await fsPromises.readFile(path.join(packageDir, 'package.json'), 'utf8')) as Record<\n string,\n unknown\n >,\n graph: result.graph,\n targets: result.targets,\n pluginId: result.pluginId,\n ...(result.targets.includes('server')\n ? { serverContracts: await readServerContracts(packageDir, SERVER_DIST) }\n : {}),\n });\n };\n // tsdown releases every format of one package together once it has written\n // the exports, so the esm and cjs builds call build:done at the same moment.\n // They share one sync: two would read package.json while the other writes it.\n let syncing: Promise<void> | undefined;\n const node = (entries: Record<string, string>, _unbundle: boolean): PresetConfig => ({\n ...baseNode,\n entry: entries,\n // Public entry facades must remain bundled. Otherwise their relative\n // imports target unbundled implementation chunks, which Vite treats as\n // source files when resolving a workspace package.\n unbundle: false,\n hooks: {\n 'build:done': () =>\n (syncing ??= syncBuiltManifest().finally(() => {\n syncing = undefined;\n })),\n },\n });\n const unsyncedNode = (entries: Record<string, string>, unbundle: boolean): PresetConfig => ({\n ...baseNode,\n entry: entries,\n unbundle,\n });\n const configs =\n !mcpOnly && API_CONTRACTS_ENTRY in entry && Object.keys(entry).length > 1\n ? [\n unsyncedNode({ [API_CONTRACTS_ENTRY]: entry[API_CONTRACTS_ENTRY] }, false),\n node(Object.fromEntries(Object.entries(entry).filter(([name]) => name !== API_CONTRACTS_ENTRY)), true),\n ]\n : [node(entry, !mcpOnly)];\n if (mcpOnly && result.files.has(`${GENERATED_DIR}/mcp-ui.ts`)) return [...configs, browserConfig('mcp-ui')];\n const frontends: (BrowserPresetConfig | NativePresetConfig)[] = mcpOnly\n ? []\n : [\n ...(result.targets.includes('web') ? [browserConfig()] : []),\n ...(result.targets.includes('native') ? [nativeConfig(packageDir)] : []),\n ];\n if (frontends.length > 0) {\n if (Object.keys(entry).length > 0) return [...configs, ...frontends];\n // No node entry to carry the manifest sync, so the first frontend build does.\n const [first, ...rest] = frontends;\n return [{ ...first!, hooks: configs[0]!.hooks }, ...rest];\n }\n return configs.length === 1 ? configs[0]! : configs;\n}\n"],"mappings":"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"}
|