@gjsify/cli 0.13.2 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.gjs.mjs +7 -5
- package/lib/commands/storybook.d.ts +1 -0
- package/lib/commands/storybook.js +51 -9
- package/lib/utils/run-node.d.ts +20 -0
- package/lib/utils/run-node.js +85 -0
- package/package.json +17 -17
package/dist/cli.gjs.mjs
CHANGED
|
@@ -743,7 +743,7 @@ function load() {
|
|
|
743
743
|
cached = require('@gjsify/node-gi/gi').requireGi(${JSON.stringify(n)}${S});\n }\n return cached;\n}\nexport default new Proxy(Object.create(null), {\n get(_target, prop) { return load()[prop]; },\n has(_target, prop) { return prop in load(); },\n});\n`}function gjsGiNodePlugin(){return{name:`gjsify-gi-node`,resolveId:{order:`pre`,filter:{id:/^gi:\/\//},handler(n){let a=parseGiSpecifier(n);if(a===null)return null;let S=a.version?`@${a.version}`:``;return{id:`${vA}${a.namespace}${S}`}}},load(n){if(!n.startsWith(vA))return null;let a=n.slice(16),S=a.lastIndexOf(`@`);return{code:giNodeShimSource(S===-1?a:a.slice(0,S),S===-1?void 0:a.slice(S+1)),moduleSideEffects:!1}}}}function gjsBuiltinModulesNodePlugin(n){let a=Object.keys(n),S=a.length>0?{id:RegExp(`^(?:${a.map(n=>n.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)).join(`|`)})$`)}:void 0;return{name:`gjsify-builtin-modules-node`,resolveId:{order:`pre`,...S?{filter:S}:{},handler(a){let S=n[a];return S?{id:S,external:!0}:null}}}}var vA,yA=__esmMin(()=>{vA=`\0gjsify-gi-node:`});function flattenAliases$3(n){let a={};for(let[S,C]of Object.entries(n))C&&(a[S]=C);return a}var bA,xA,setupForNode,SA=__esmMin(()=>{Yb(),tC(),c_(),l_(),Nv(),Fk(),cA(),_A(),yA(),pA(),bA=`@gjsify/node-gi/globals`,xA=[`@gjsify/node-gi/system`,`@gjsify/node-gi/gettext`],setupForNode=async n=>{let a=n.userExternal??[],S=[...Qg,`node-datachannel`,`@gjsify/node-gi`,`@gjsify/node-gi/gi`,bA,...xA,...a],external=n=>!!(S.includes(n)||n===`@gjsify/node-gi`||n.startsWith(`@gjsify/node-gi/`)),C=n.pluginOptions.format??`esm`,N=n.pluginOptions.exclude??[],F=await globToEntryPoints(n.input,N),I=[];n.pluginOptions.nodeGiGlobalsInject&&I.push(bA);let H=wrapInputWithSideEffects(F,I),W=H.input,K={...getAliasesForNode({external}),...n.pluginOptions.aliases,...n.userAliases},q=getBundleDirFromOutput(n.output);return{options:{input:W,platform:`node`,external:S,resolve:{mainFields:C===`esm`?[`module`,`main`,`browser`]:[`main`,`module`,`browser`],conditionNames:C===`esm`?[`require`,`node`,`module`]:[`require`]},transform:{target:`node24`,define:{global:`globalThis`,window:`globalThis`}},output:{...n.output,format:C,sourcemap:!1,banner:void 0,codeSplitting:!1},treeshake:!0},plugins:[...H.plugin?[H.plugin]:[],gjsGiNodePlugin(),gjsBuiltinModulesNodePlugin(o_),gjsImportsEmptyPlugin({emptyGirs:!n.pluginOptions.nodeGiGlobalsInject}),aliasPlugin({entries:flattenAliases$3(K)}),deepkitPlugin({reflection:n.pluginOptions.reflection}),cssAsStringPlugin(),nodeModulesPathRewritePlugin({bundleDir:q})]}},__name$1(flattenAliases$3,`flattenAliases`)});function flattenAliases$2(n){let a={};for(let[S,C]of Object.entries(n))C&&(a[S]=C);return a}var setupForBrowser,CA=__esmMin(()=>{Yb(),tC(),kk(),c_(),Nv(),_A(),cA(),setupForBrowser=async n=>{let a=[...n.userExternal??[]],S=n.pluginOptions.exclude??[],C=await globToEntryPoints(n.input,S),N={};for(let[n,a]of Object.entries(n_))N[n]=a,N[`node:${n}`]=a;let F={},I={...getDerivedAliasesSync(`browser`),...N,...F,...n.pluginOptions.aliases,...n.userAliases};return{options:{input:C,platform:`browser`,external:a,resolve:{mainFields:[`browser`,`module`,`main`],conditionNames:[`import`,`browser`]},transform:{target:`esnext`,define:{global:`globalThis`,window:`globalThis`}},output:{...n.output,format:`esm`,sourcemap:!1,codeSplitting:!1},treeshake:!0},plugins:[gjsImportsEmptyPlugin(),aliasPlugin({entries:flattenAliases$2(I)}),blueprintPlugin(),deepkitPlugin({reflection:n.pluginOptions.reflection}),cssAsStringPlugin()]}},__name$1(flattenAliases$2,`flattenAliases`)});function isPlatform(n){return wA.includes(n)}function platformResolvePlugin(n={}){let a=n.platform,S=a?[a,`native`]:[`native`];return{name:`gjsify-nativescript-platform-resolve`,resolveId:{order:`pre`,async handler(n,a,C){if(!a||!n.startsWith(`./`)&&!n.startsWith(`../`))return null;let N=TA.exec(n),F=N?N[0]:``,I=F?n.slice(0,-F.length):n;for(let N of S){let S=F&&`${I}.${N}`!=`${I}.${N}${F}`?[`${I}.${N}`,`${I}.${N}${F}`]:[`${I}.${N}`];for(let N of S){if(N===n)continue;let S=await this.resolve(N,a,{skipSelf:!0,...C?.kind?{kind:C.kind}:{}});if(S&&!S.external)return S}}return null}}}}function detectNativescriptPlatform(n=process.env){let a=n.NATIVESCRIPT_PLATFORM??n.NS_PLATFORM;if(a&&isPlatform(a))return a;let S=n.NATIVESCRIPT_BUNDLER_ENV??n.NATIVESCRIPT_WEBPACK_ENV;if(S)try{let n=JSON.parse(S);if(n.android===!0)return`android`;if(n.ios===!0)return`ios`;if(n.visionos===!0)return`visionos`;if(typeof n.platform==`string`&&isPlatform(n.platform))return n.platform}catch{}}function nativescriptPlatformDefines(n,a={}){let S=n===`android`,C=n===`ios`,N=n===`visionos`;return{__ANDROID__:String(S),__IOS__:String(C),__VISIONOS__:String(N),__APPLE__:String(C||N),__DEV__:String(a.dev??!1)}}var wA,TA,EA=__esmMin(()=>{wA=[`android`,`ios`,`visionos`],TA=/\.(tsx?|jsx?|mts|cts|mjs|cjs)$/});function flattenAliases$1(n){let a={};for(let[S,C]of Object.entries(n))C&&(a[S]=C);return a}var setupForNativescript,DA=__esmMin(()=>{Yb(),tC(),c_(),Nv(),_A(),EA(),setupForNativescript=async n=>{let a=[...n.userExternal??[]],S=n.pluginOptions.exclude??[],C=await globToEntryPoints(n.input,S),N=detectNativescriptPlatform(),F={};for(let[n,a]of Object.entries(r_))F[n]=a,F[`node:${n}`]=a;let I={},H={...getDerivedAliasesSync(`nativescript`),...F,...I,...n.pluginOptions.aliases,...n.userAliases};return{options:{input:C,platform:`browser`,external:a,resolve:{mainFields:[`nativescript`,`module`,`main`],conditionNames:[`import`,`nativescript`]},transform:{target:`esnext`,define:{global:`globalThis`,...nativescriptPlatformDefines(N,{dev:!1})}},output:{...n.output,format:`esm`,sourcemap:!1,codeSplitting:!1},treeshake:!0},plugins:[gjsImportsEmptyPlugin(),platformResolvePlugin({platform:N}),aliasPlugin({entries:flattenAliases$1(H)}),deepkitPlugin({reflection:n.pluginOptions.reflection})]}},__name$1(flattenAliases$1,`flattenAliases`)}),OA=__esmMin(()=>{hA(),SA(),CA(),DA()});function isExternalSpecifier(n){return!(n.startsWith(`./`)||n.startsWith(`../`)||n.startsWith(`/`)||n.startsWith(`\0`)||n.startsWith(`data:`))}function computeCommonRoot(n){let a=n===void 0?[]:typeof n==`string`?[n]:Array.isArray(n)?n:Object.values(n);if(a.length===0)return`src`;let S=a.map(n=>n.split(`/`).filter(Boolean)),C=S[0],N=0;for(;N<C.length;N++){let n=C[N];if(!S.every(a=>a[N]===n))break}if(N===0)return`src`;let F=C.slice(0,N);return S.some(n=>n.length>N)?F.join(`/`):F.slice(0,-1).join(`/`)||`src`}function flattenAliases(n){let a={};for(let[S,C]of Object.entries(n))C&&(a[S]=C);return a}var setupLib,kA=__esmMin(()=>{Yb(),cA(),Xb(),Nv(),setupLib=async n=>{let a=n.pluginOptions.format??n.pluginOptions.library??`esm`,S=n.pluginOptions.exclude??[],C=await globToEntryPoints(n.input,S),N=computeCommonRoot(C),F={...n.pluginOptions.aliases,...n.userAliases};return{options:{input:C,platform:`neutral`,resolve:{mainFields:a===`esm`?[`module`,`main`]:[`main`],conditionNames:a===`esm`?[`module`,`import`]:[`require`]},transform:{target:`esnext`},output:{...n.output,format:a,preserveModules:!0,preserveModulesRoot:N,sourcemap:!1},treeshake:!1},plugins:[aliasPlugin({entries:flattenAliases(F)}),externalsPlugin(isExternalSpecifier,{name:`gjsify-lib-externalize`}),cssAsStringPlugin()]}}}),AA=__esmMin(()=>{kA()});function mimeForExtension(n){return jA[n.toLowerCase()]??`application/octet-stream`}function textLoaderPlugin(n={}){let a=n.loaders??{},S=Object.entries(a),C=S.filter(([,n])=>n===`text`).map(([n])=>n),N=S.filter(([,n])=>n===`dataurl`).map(([n])=>n),F=[...C,...N];if(F.length===0)return null;let I=F.map(n=>n.replace(/^\./,``).replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)),H=RegExp(`\\.(?:${I.join(`|`)})$`),W=new Map(S.map(([n,a])=>[n.toLowerCase(),a]));return{name:`gjsify-asset-loader`,async load(n){if(!H.test(n))return null;let a=n.lastIndexOf(`.`),S=a>=0?n.slice(a).toLowerCase():``;if((W.get(S)??`text`)===`dataurl`){let a=await readFile$1(n),C=mimeForExtension(S),N=a.toString(`base64`);return{code:`export default ${JSON.stringify(`data:${C};base64,${N}`)};`,moduleType:`js`}}let C=await readFile$1(n,`utf8`);return{code:`export default ${JSON.stringify(C)};`,moduleType:`js`}}}}var jA,MA=__esmMin(()=>{kc(),jA={".png":`image/png`,".jpg":`image/jpeg`,".jpeg":`image/jpeg`,".gif":`image/gif`,".webp":`image/webp`,".svg":`image/svg+xml`,".ico":`image/x-icon`,".avif":`image/avif`,".bmp":`image/bmp`,".tiff":`image/tiff`,".tif":`image/tiff`,".wasm":`application/wasm`}}),gjsifyPlugin,NA=__esmMin(()=>{OA(),AA(),gjsifyPlugin=async(n,a={})=>{if(a.library)switch(a.library){case`esm`:case`cjs`:return await setupLib({input:n.input,output:n.output,userAliases:n.userAliases,pluginOptions:a});default:throw TypeError(`Unknown library type: `+a.library)}let S=a.app??`gjs`;switch(S){case`gjs`:return await setupForGjs({input:n.input,output:n.output,userExternal:n.userExternal,userBanner:n.userBanner,userAliases:n.userAliases,shebang:n.shebang,pluginOptions:a});case`node`:return await setupForNode({input:n.input,output:n.output,userExternal:n.userExternal,userAliases:n.userAliases,pluginOptions:a});case`browser`:return await setupForBrowser({input:n.input,output:n.output,userExternal:n.userExternal,userAliases:n.userAliases,pluginOptions:a});case`nativescript`:return await setupForNativescript({input:n.input,output:n.output,userExternal:n.userExternal,userAliases:n.userAliases,pluginOptions:a});default:throw TypeError(`Unknown app platform: `+S)}}}),PA=__esmMin(()=>{Kg(),Jb(),OA(),AA(),Fk(),Vk(),cA(),MA(),fA(),_A(),Xb(),EA(),NA(),NA(),c_()});function isPluginByName(n){return typeof n==`object`&&!!n&&typeof n.name==`string`&&!(`apply`in n)&&!(`resolveId`in n)&&!(`load`in n)&&!(`transform`in n)&&!(`renderChunk`in n)&&!(`generateBundle`in n)}async function resolveUserPlugins(n,a,S={}){let C=S.loadModule??defaultLoadModule,N=createRequire(ns(a,`package.json`)),F=[];for(let S of n){if(!isPluginByName(S)){F.push(S);continue}let n;try{n=N.resolve(S.name)}catch(n){throw Error(`gjsify config: failed to resolve plugin "${S.name}" from ${a}. Add it to your project's dependencies, or pass a Plugin object directly. (${n.message})`)}let I=await C(n,S.name),H=S.export??`default`,W=I[H];if(typeof W!=`function`){let n=Object.keys(I).filter(n=>typeof I[n]==`function`);throw Error(`gjsify config: plugin "${S.name}" has no function export "${H}". Available function exports: ${n.length?n.join(`, `):`(none)`}.`)}let K=await W(S.options);if(K==null)throw Error(`gjsify config: plugin "${S.name}" factory returned ${K}. Check the plugin's signature — it should return a Rolldown/Vite plugin object.`);F.push(K)}return F}var defaultLoadModule,FA=__esmMin(()=>{Uo(),ps(),mn(),defaultLoadModule=async n=>await import(pathToFileURL(n).href)}),IA,LA=__esmMin(()=>{IA={"@gjsify/buffer/register":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`clearTimeout`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/dom-elements/register/canvas":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`HTMLCanvasElement`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`clearTimeout`,`document`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/dom-elements/register/document":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`HTMLCanvasElement`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`clearTimeout`,`document`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/dom-elements/register/font-face":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/dom-elements/register/image":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`HTMLCanvasElement`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`document`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/dom-elements/register/location":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/dom-elements/register/match-media":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/dom-elements/register/navigator":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`navigator`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/dom-elements/register/observers":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/domparser/register":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/gamepad/register":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/node-globals/register/buffer":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`clearTimeout`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/node-globals/register/encoding":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/node-globals/register/microtask":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/node-globals/register/process":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`clearTimeout`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/node-globals/register/structured-clone":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/node-globals/register/timers":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`clearTimeout`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/node-globals/register/url":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`URL`,`URLSearchParams`,`WritableStream`,`atob`,`btoa`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/web-globals/register/formdata":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`FormData`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`clearTimeout`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/web-globals/register/performance":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/webaudio/register":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/webrtc/register/data-channel":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`Event`,`EventTarget`,`File`,`MessageEvent`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`clearTimeout`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/webrtc/register/error":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`Event`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/webrtc/register/media":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`Event`,`EventTarget`,`File`,`MediaStream`,`MediaStreamTrack`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/webrtc/register/media-devices":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`Event`,`EventTarget`,`File`,`MediaStream`,`MediaStreamTrack`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"@gjsify/webrtc/register/peer-connection":`AbortController.AbortSignal.Blob.Buffer.ByteLengthQueuingStrategy.CountQueuingStrategy.DOMException.Event.EventTarget.File.MediaStream.MediaStreamTrack.MessageEvent.RTCSessionDescription.ReadableStream.TextDecoderStream.TextEncoderStream.TransformStream.WritableStream.atob.btoa.clearTimeout.performance.process.queueMicrotask.setTimeout.structuredClone`.split(`.`),"abort-controller/register":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`clearTimeout`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"compression-streams/register":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CompressionStream`,`CountQueuingStrategy`,`DOMException`,`DecompressionStream`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`clearTimeout`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"dom-events/register/custom-events":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"dom-events/register/event-target":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"dom-events/register/ui-events":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"dom-exception/register":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"eventsource/register":`AbortController.AbortSignal.Blob.Buffer.ByteLengthQueuingStrategy.CompressionStream.CountQueuingStrategy.DOMException.DecompressionStream.Event.EventSource.EventTarget.File.Headers.MessageEvent.ReadableStream.Request.Response.TextDecoderStream.TextEncoderStream.TransformStream.URL.URLSearchParams.WritableStream.atob.btoa.clearTimeout.fetch.performance.process.queueMicrotask.setTimeout.structuredClone`.split(`.`),"fetch/register/fetch":`AbortController.AbortSignal.Blob.Buffer.ByteLengthQueuingStrategy.CompressionStream.CountQueuingStrategy.DOMException.DecompressionStream.File.Headers.ReadableStream.Request.Response.TextDecoderStream.TextEncoderStream.TransformStream.URL.URLSearchParams.WritableStream.atob.btoa.clearTimeout.fetch.performance.process.queueMicrotask.setTimeout.structuredClone`.split(`.`),"fetch/register/xhr":`AbortController.AbortSignal.Blob.Buffer.ByteLengthQueuingStrategy.CompressionStream.CountQueuingStrategy.DOMException.DecompressionStream.Event.EventTarget.File.Headers.ProgressEvent.ReadableStream.Request.Response.TextDecoderStream.TextEncoderStream.TransformStream.URL.URLSearchParams.WritableStream.XMLHttpRequest.XMLHttpRequestUpload.atob.btoa.clearTimeout.fetch.performance.process.queueMicrotask.setTimeout.structuredClone`.split(`.`),"message-channel/register":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`MessageChannel`,`MessagePort`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"web-streams/register/queuing":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`clearTimeout`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"web-streams/register/readable":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`clearTimeout`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"web-streams/register/text-streams":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`clearTimeout`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"web-streams/register/transform":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`clearTimeout`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"web-streams/register/writable":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`clearTimeout`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"webassembly/register/promise":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WebAssembly`,`WritableStream`,`atob`,`btoa`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"webcrypto/register":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`clearTimeout`,`crypto`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`],"websocket/register":[`AbortController`,`AbortSignal`,`Blob`,`Buffer`,`ByteLengthQueuingStrategy`,`CountQueuingStrategy`,`DOMException`,`File`,`ReadableStream`,`TextDecoderStream`,`TextEncoderStream`,`TransformStream`,`WritableStream`,`atob`,`btoa`,`clearTimeout`,`performance`,`process`,`queueMicrotask`,`setTimeout`,`structuredClone`]}});function expandWithClosure(n,a){let S=new Set(n),C=[...n];for(;C.length>0;){let n=RA[C.pop()];if(!n)continue;let N=zA[n];if(N)for(let n of N)a.has(n)||RA[n]&&(S.has(n)||(S.add(n),C.push(n)))}return S}function isSubset(n,a){for(let S of n)if(!a.has(S))return!1;return!0}async function applyExcludeGlobals(n,a,S,C,N){if(C?.length)for(let a of C)n.delete(a);let F=detectedToRegisterPaths(n);for(let n of S)F.add(n);if(emitGiBackedDiagnostic(F,n,N),!C?.length)return{detected:n,injectPath:a};let I=N?filterResolvableRegisterPaths(F,N):F;return{detected:n,injectPath:I.size>0?await writeRegisterInjectFile(I,N)??void 0:void 0}}function detectedToRegisterPaths(n){let a=new Set;for(let S of n){let n=RA[S];n&&a.add(n)}return a}function giNamespacesForRegister(n){for(let a of Object.keys(BA))if(n===a||n.startsWith(a+`/`))return BA[a];return null}function describeGiBackedInjection(n,a){let S=new Set,C=new Set;for(let a of n){let n=giNamespacesForRegister(a);if(n){S.add(a);for(let a of n)C.add(a)}}if(S.size===0)return null;let N=[...a].filter(n=>{let a=RA[n];return!!a&&S.has(a)}).sort();return`[gjsify] note: --globals auto injected GTK/GNOME-backed register(s) — this bundle now requires ${[...C].sort().map(n=>`gi://${n}`).join(`, `)} at load.`+(N.length?` Triggered by: ${N.join(`, `)}.`:``)+` If it runs headless / SSR / in a GTK-less container it will throw "Typelib … not found"; drop those globals via excludeGlobals or pin an explicit --globals allowlist (e.g. node).`}function emitGiBackedDiagnostic(n,a,S){if(HA)return;let C=new Set;for(let a of n)giNamespacesForRegister(a)&&(S&&!isRegisterPathResolvable(a,S)||C.add(a));let N=describeGiBackedInjection(C,a);N&&(HA=!0,ke.warn(N))}function isFullConfig(n){return typeof n==`object`&&!!n&&!Array.isArray(n)&&`plugins`in n&&`options`in n}async function detectAutoGlobals(n,a,S,C,N={},F=defaultBundler){let I=N.extraGlobalsList?resolveGlobalsList(N.extraGlobalsList):new Set,H=new Set(N.excludeGlobals??[]),W=N.cwd,K=new Set,q;I.size>0&&(q=await writeRegisterInjectFile(W?filterResolvableRegisterPaths(I,W):I,W)??void 0);let Y=(n.plugins??[]).filter(n=>{let a=n&&typeof n==`object`&&`name`in n?n.name:void 0;return a!==`gjsify`&&a!==`gjsify-orchestrator`});for(let X=1;X<=VA;X++){let te=await S({...a,autoGlobalsInject:q}),ne,re;isFullConfig(te)?(re=te.options,ne=te.plugins):ne=te;let ie=q?appendInjectAsEntry(n.input,q):n.input,ae=n.resolve??re?.resolve,oe=n.external??re?.external,Z=n.transform??re?.transform,se=re?.treeshake,ce=Array.isArray(ne)?ne:[ne],le=await F({rolldownInput:{input:ie,external:oe,resolve:ae,transform:Z,plugins:[...Y,...ce],logLevel:`silent`,...se===void 0?{}:{treeshake:se}},format:n.format??`esm`});if(le.length===0)return{detected:new Set,injectPath:q};let ue=new Set;for(let n=0;n<le.length;n++){let a=le[n]??``;try{for(let n of detectFreeGlobals(a))ue.add(n)}catch(S){if(globalThis.process?.env?.GJSIFY_DEBUG_AUTO_GLOBALS){let S=`/tmp/gjsify-auto-globals-failed-chunk-${n}.mjs`;try{(await Promise.resolve().then(()=>(Zc(),Jc))).writeFileSync(S,a),ke.error(`[gjsify-auto-globals] parse failed on chunk #${n} — wrote ${S} for inspection`)}catch{}}throw S}}if(H.size>0)for(let n of H)ue.delete(n);if(isSubset(ue,K)){if(C){let n=[...K].sort(),a=I.size>0?` (+ ${I.size} extra register module(s))`:``;ke.debug(`[gjsify] --globals auto: converged after ${X-1} iteration(s), ${K.size} global(s)${n.length?`: `+n.join(`, `):``}${a}`)}return applyExcludeGlobals(K,q,I,N.excludeGlobals,W)}let de=N.disableClosureExpansion?ue:expandWithClosure(ue,H);C&&de.size>ue.size&&ke.debug(`[gjsify] --globals auto: closure map expanded ${ue.size} → ${de.size} global(s)`),X>1&&C&&ke.debug("[gjsify] --globals auto: detection grew past the closure-map expansion — the committed register-globals-closure map looks stale. Regenerate via `node packages/infra/cli/scripts/generate-register-closure.mjs`."),K=new Set([...K,...de]);let fe=detectedToRegisterPaths(K);for(let n of I)fe.add(n);if(W&&(fe=filterResolvableRegisterPaths(fe,W)),fe.size===0)return{detected:K,injectPath:void 0};if(q=await writeRegisterInjectFile(fe,W)??void 0,C){let n=[...K].sort();ke.debug(`[gjsify] --globals auto: iteration ${X}, ${K.size} global(s)${n.length?`: `+n.join(`, `):``}`)}}return C&&ke.debug(`[gjsify] --globals auto: hit max iterations (${VA}), using last detected set`),applyExcludeGlobals(K,q,I,N.excludeGlobals,W)}async function detectNodeGiGlobals(n,a,S,C=defaultBundler){let N=await S(a),F,I;isFullConfig(N)?(I=N.options,F=N.plugins):F=N;let H=(n.plugins??[]).filter(n=>{let a=n&&typeof n==`object`&&`name`in n?n.name:void 0;return a!==`gjsify`&&a!==`gjsify-orchestrator`}),W=Array.isArray(F)?F:[F],K=I?{...I}:{};delete K.output;let q;try{q=await C({rolldownInput:{...K,input:n.input,external:n.external??K.external,resolve:n.resolve??K.resolve,transform:n.transform??K.transform,plugins:[...H,...W],logLevel:`silent`},format:n.format??`esm`})}catch(n){return ke.warn(`[gjsify] --app node: could not analyse the bundle for GJS ambient globals (${n instanceof Error?n.message:String(n)}); skipping @gjsify/node-gi/globals injection. If this build uses print/imports/ARGV, add \`import '@gjsify/node-gi/globals'\` to the entry or pass --globals.`),!1}for(let n of q)if(detectGjsAmbientGlobals(n).size>0)return!0;return!1}function appendInjectAsEntry(n,a){return n===void 0?[a]:typeof n==`string`?[n,a]:Array.isArray(n)?[...n,a]:{...n,__gjsify_inject:a}}var defaultBundler,RA,zA,BA,VA,HA,UA=__esmMin(()=>{Ae(),Vb(),Gb(),Fb(),LA(),defaultBundler=async({rolldownInput:n,format:a})=>{let S=await(await import(`rolldown`)).rolldown(n);try{let n=await S.generate({format:a,minify:!1,sourcemap:!1}),C=[];for(let a of n.output)a.type===`chunk`&&C.push(a.code);return C}finally{await S.close()}},RA=Nb,zA=IA,BA=Pb,VA=5,HA=!1}),WA=__esmMin(()=>{Gb(),Vb(),UA()});function findPnpRoot(n){let a=n;for(;;){if(existsSync(ns(a,`.pnp.cjs`)))return a;let n=as(a);if(n===a)return null;a=n}}async function loadPnpApi(){try{let n=await import(`pnpapi`);return n.default??n}catch{return null}}async function pnpPlugin(n={}){let a=n.issuerUrl??import.meta.url;if(!findPnpRoot(process.cwd()))return null;let S=await loadPnpApi();if(S===null)return null;let C=fileURLToPath(a),N=createRequire(C),F=n.relayPackages??[`@gjsify/node-polyfills`,`@gjsify/web-polyfills`],I=[];for(let n of F)try{I.push(N.resolve(`${n}/package.json`))}catch{}return{name:`gjsify-pnp`,resolveId:{order:`pre`,async handler(n,a){if(n.startsWith(`.`)||n.startsWith(`/`))return null;if(n.startsWith(`gi://`))return{id:n,external:!0};if(n.startsWith(`node:`))return await this.resolve(n,a,{skipSelf:!0});if(!a)return null;let N=a.startsWith(`file://`)?fileURLToPath(a):a;try{let a=S.resolveRequest(n,N);return a===null?null:{id:a}}catch(a){if(!isUndeclaredDependency(a))throw a;try{let a=S.resolveRequest(n,C);if(a!==null)return{id:a}}catch(n){if(!isUndeclaredDependency(n))throw n}for(let a of I)try{let C=S.resolveRequest(n,a);if(C!==null)return{id:C}}catch(n){if(!isUndeclaredDependency(n))throw n}return null}}},async load(n){if(!n.includes(`/.yarn/`)&&!n.includes(`.zip/`))return null;try{return{code:await readFile$1(n,`utf8`)}}catch(a){let S=a instanceof Error?a.message:String(a);this.error(`gjsify-pnp: failed to read ${n}: ${S}`)}}}}function isUndeclaredDependency(n){return typeof n==`object`&&!!n&&`pnpCode`in n&&n.pnpCode===`UNDECLARED_DEPENDENCY`}var GA=__esmMin(()=>{Uo(),mn(),ps(),Zc(),kc()});function normalizeBundlerOptions(n){let a=n.bundler??{},S=a;if(typeof a.define==`object`&&a.define!==null){qA||(qA=!0,ke.warn(`[gjsify] WARNING: 'bundler.define' is not a valid Rolldown option and would be silently ignored — it has been auto-mapped to 'bundler.transform.define'. Move 'define' under 'bundler.transform.define' in your config to suppress this warning and avoid a ReferenceError at GJS load time.`));let{define:n,...C}=a;S={...C,transform:{...C.transform,define:{...n,...C.transform?.define}}}}if(!n.esbuild)return S;KA||(KA=!0,ke.warn(`[gjsify] DEPRECATION: the 'esbuild' config key is deprecated and will be removed in 0.5.0. Rename it to 'bundler' (typed as RolldownOptions). See the migration notes in the gjsify CHANGELOG.`));let C=legacyEsbuildToRolldown(n.esbuild),N={...C,...S};return(C.output||S.output)&&(N.output={...C.output,...S.output}),(C.transform||S.transform)&&(N.transform={...C.transform,...S.transform},(C.transform?.define||S.transform?.define)&&(N.transform.define={...C.transform?.define,...S.transform?.define})),(C.resolve||S.resolve)&&(N.resolve={...C.resolve,...S.resolve}),N}function legacyEsbuildToRolldown(n){let a={},S={},C={},N={};return n.outfile!==void 0&&(S.file=n.outfile),n.outdir!==void 0&&(S.dir=n.outdir),n.format!==void 0&&(S.format=n.format),n.minify!==void 0&&(S.minify=n.minify),n.sourcemap!==void 0&&(S.sourcemap=n.sourcemap===`inline`?`inline`:!!n.sourcemap),n.banner?.js!==void 0&&(S.banner=n.banner.js),n.target!==void 0&&(C.target=Array.isArray(n.target)?n.target.join(`,`):n.target),n.define!==void 0&&(C.define=n.define),n.mainFields!==void 0&&(N.mainFields=n.mainFields),n.conditions!==void 0&&(N.conditionNames=n.conditions),n.external!==void 0&&(a.external=n.external),n.platform!==void 0&&(a.platform=n.platform),Object.keys(S).length>0&&(a.output=S),Object.keys(C).length>0&&(a.transform=C),Object.keys(N).length>0&&(a.resolve=N),a}function mergeBundlerOptions(n,a){let{input:S,external:C,...N}=a,F={...n,...N};return(n.output||a.output)&&(F.output={...n.output,...a.output}),(n.transform||a.transform)&&(F.transform={...n.transform,...a.transform},(n.transform?.define||a.transform?.define)&&(F.transform.define={...n.transform?.define,...a.transform?.define})),(n.resolve||a.resolve)&&(F.resolve={...n.resolve,...a.resolve}),F}var KA,qA,JA=__esmMin(()=>{Ae(),KA=!1,qA=!1});function isUnsafeDefaultOutput(n){if(/\.[cm]?tsx?$/i.test(n))return!0;let a=n.replace(/\\/g,`/`);return!!/(?:^|\/)src\//.test(a)}async function buildPnpPlugin(){return pnpPlugin({issuerUrl:import.meta.url})}function shortHash(n){let a=5381;for(let S=0;S<n.length;S++)a=(a<<5)+a+n.charCodeAt(S)>>>0;return a.toString(16).padStart(8,`0`)}function isTruthyEnv(n){return n===`1`||n===`true`||n===`yes`}async function newestLockfileMtime(n){let a=0;for(let S of XA)try{let C=await stat$1(ns(n,S));C.mtimeMs>a&&(a=C.mtimeMs)}catch{}return a}async function runOneLibraryBuild(n){let a=await gjsifyPlugin({input:n.userBundler.input,output:n.output,userAliases:n.userAliases},n.pluginOpts);return await runBundle({...mergeBundlerOptions(a.options,n.userBundler),plugins:[...n.pnpPlugins,...a.plugins]})}var YA,XA,ZA,QA=__esmMin(()=>{Ae(),Hg(),PA(),zg(),FA(),WA(),GA(),ps(),mn(),kc(),JA(),YA=`#!/usr/bin/env -S gjs -m`,XA=[`gjsify-lock.json`,`package-lock.json`,`yarn.lock`,`pnpm-lock.yaml`],ZA=class BuildAction{configData;constructor(n={}){this.configData=n}async buildLibrary(){let{verbose:n,library:a,typescript:S,exclude:C,aliases:N}=this.configData,F=a??{},I=normalizeBundlerOptions(this.configData),H=F.module?as(F.module):void 0,W=F.main?as(F.main):void 0,K=F.module?ss(F.module):`.js`,q=F.main?ss(F.main):`.js`,Y=H&&W&&H!==W,X=await buildPnpPlugin(),te=X?[X]:[],ne=[];if(Y){let a=H.includes(`/cjs`)||K===`.cjs`?`cjs`:`esm`;ne.push(await runOneLibraryBuild({pluginOpts:{debug:n,library:a,exclude:C,reflection:S?.reflection,jsExtension:K},userBundler:I,output:{dir:H},userAliases:N,pnpPlugins:te}));let F=W.includes(`/cjs`)||q===`.cjs`?`cjs`:`esm`;ne.push(await runOneLibraryBuild({pluginOpts:{debug:n,library:F,exclude:C,reflection:S?.reflection,jsExtension:q},userBundler:I,output:{dir:W},userAliases:N,pnpPlugins:te}))}else{let a=I.output?.file??F.module??F.main,H=a?ss(a):`.js`,W=I.output?.dir??(a?as(a):void 0),K=I.output?.format??(W?.includes(`/cjs`)||H===`.cjs`?`cjs`:`esm`);ne.push(await runOneLibraryBuild({pluginOpts:{debug:n,library:K,exclude:C,reflection:S?.reflection,jsExtension:H},userBundler:I,output:{dir:W},userAliases:N,pnpPlugins:te}))}return ne}parseGlobalsValue(n){if(n===void 0)return{autoMode:!0,extras:``};if(n===`none`||n===``)return{autoMode:!1,extras:``};let a=n.split(`,`).map(n=>n.trim()).filter(Boolean);return{autoMode:a.includes(`auto`),extras:a.filter(n=>n!==`auto`).join(`,`)}}async resolveGlobalsInject(n,a,S){if(n!==`gjs`||!a)return;let C=resolveGlobalsList(a);if(C.size===0)return;let N=await writeRegisterInjectFile(C,process.cwd());return S&&N&&ke.debug(`[gjsify] globals: injected ${C.size} register module(s) from --globals ${a}`),N??void 0}async applyShebang(n,a,S){if(!a){S&&ke.warn(`[gjsify] --shebang skipped: no single outfile (use --outfile for executables)`);return}let C=n===`node`?uA:YA,N=resolveShebangLine(this.configData.shebang,C)??C,F=await readFile$1(a,`utf-8`);F.startsWith(`#!`)?S&&ke.debug(`[gjsify] --shebang skipped: ${a} already starts with a shebang`):await writeFile$1(a,N+`
|
|
744
744
|
`+F),await chmod$1(a,493),S&&ke.debug(`[gjsify] --shebang: wrote ${N} + chmod 0o755 to ${a}`)}async loadPluginViaGjsBundle(n,a,S){let C=await this.bundlePluginForGjs(n,a,S);try{return await import(pathToFileURL(C).href)}catch(n){throw Error(`gjsify config: failed to import the GJS bundle for plugin "${a}" (bundled to ${C}). (${n.message})`)}}async bundlePluginForGjs(n,a,S){let C=process.cwd(),N=ns(C,`node_modules`,`.cache`,`gjsify`,`plugins`),F=ns(N,`${a.replace(/[^a-zA-Z0-9._-]/g,`_`)}-${shortHash(n)}.mjs`);if(!isTruthyEnv(process.env.GJSIFY_NO_PLUGIN_CACHE)&&await this.isPluginBundleFresh(F,n,C))return S&&ke.debug(`[gjsify] plugin "${a}": reusing cached GJS bundle ${F}`),F;S&&ke.debug(`[gjsify] plugin "${a}": bundling for GJS → ${F}`);try{await mkdir$1(N,{recursive:!0}),await new BuildAction({verbose:S,bundler:{input:n,output:{file:F}}}).buildApp(`gjs`,{preserveDefaultExport:!0})}catch(n){throw Error(`gjsify config: failed to bundle plugin "${a}" for GJS (needed because GJS can't import packages that use exports-map subpaths directly; cache dir ${N}). (${n.message})`)}return F}async isPluginBundleFresh(n,a,S){try{let C=await stat$1(n),N=await stat$1(a),F=await newestLockfileMtime(S);return C.mtimeMs>=Math.max(N.mtimeMs,F)}catch{return!1}}async buildApp(n=`gjs`,a={}){let{verbose:S,typescript:C,exclude:N,library:F,aliases:I,excludeGlobals:H}=this.configData,W=normalizeBundlerOptions(this.configData),K=W.output?.format??(W.output?.file?.endsWith(`.cjs`)?`cjs`:`esm`),q=K===`iife`?`esm`:K,Y=W.output?.file,X=W.output?.dir;if(!Y&&!X&&(F?.main||F?.module)){let n=q===`cjs`?F.main??F.module:F.module??F.main;if(n&&isUnsafeDefaultOutput(n))throw Error(`gjsify build: refusing to default --outfile to ${n} (would overwrite a TypeScript source file). Pass --outfile/--outdir explicitly, or set "gjsify.bundler.output.file" in package.json.`);Y=n}let{consoleShim:te,globals:ne}=this.configData,re=Array.isArray(W.external)?W.external:void 0,ie=typeof W.output?.banner==`string`?W.output.banner:void 0,ae={debug:S,app:n,format:q,exclude:N,reflection:C?.reflection,consoleShim:te,...I?{aliases:I}:{},...a.preserveDefaultExport?{preserveDefaultExport:!0}:{}},{autoMode:oe,extras:Z}=this.parseGlobalsValue(ne),se=await buildPnpPlugin(),ce=se?[se]:[],le=textLoaderPlugin({loaders:this.configData.loaders}),ue=le?[le]:[];if(W.plugins?.length){let n=await resolveUserPlugins(W.plugins,process.cwd(),isGjs()?{loadModule:(n,a)=>this.loadPluginViaGjsBundle(n,a,S)}:{});ue.push(...n)}if(n===`gjs`&&oe){let gjsifyPluginFactory=async n=>{let a=await gjsifyPlugin({input:W.input,output:{file:Y,dir:X},userExternal:re,userBanner:ie,userAliases:I,shebang:this.configData.shebang},n);return{options:a.options,plugins:a.plugins}},{injectPath:n}=await detectAutoGlobals({input:W.input,plugins:[...ce,...ue],external:W.external,transform:W.transform,format:q},ae,gjsifyPluginFactory,S,{extraGlobalsList:Z,excludeGlobals:H,cwd:process.cwd()},bundleToChunks);ae.autoGlobalsInject=n}else if(n===`node`&&oe){let gjsifyPluginFactory=async n=>{let a=await gjsifyPlugin({input:W.input,output:{file:Y,dir:X},userExternal:re,userBanner:ie,userAliases:I,shebang:this.configData.shebang},n);return{options:a.options,plugins:a.plugins}};await detectNodeGiGlobals({input:W.input,plugins:[...ce,...ue],external:W.external,transform:W.transform,format:q},ae,gjsifyPluginFactory,bundleToChunks)&&(ae.nodeGiGlobalsInject=!0)}else Z&&(ae.autoGlobalsInject=await this.resolveGlobalsInject(n,Z,S));let de=await gjsifyPlugin({input:W.input,output:{file:Y,dir:X},userExternal:re,userBanner:ie,userAliases:I,shebang:this.configData.shebang},ae),fe={...mergeBundlerOptions(de.options,W),plugins:[...ce,...ue,...de.plugins]};if(a.watch)return await this.runWatchLoop(fe,n,Y,S),[];let pe=await runBundle(fe);return(n===`gjs`||n===`node`)&&this.configData.shebang&&await this.applyShebang(n,Y,S),[pe]}async runWatchLoop(n,a,S,C){let N=await runWatch(n),F=new Promise(n=>{N.on(`close`,()=>n())}),I=!1,shutdown=async()=>{if(!I){I=!0,ke.log(`
|
|
745
745
|
[gjsify build --watch] stopping watcher…`);try{await N.close()}catch(n){ke.error(`[gjsify build --watch] watcher close error:`,n)}}};process.on(`SIGINT`,shutdown),process.on(`SIGTERM`,shutdown),N.on(`event`,async n=>{switch(n.code){case`START`:C&&ke.log(`[gjsify build --watch] rebuild start`);break;case`BUNDLE_START`:ke.log(`[gjsify build --watch] building…`);break;case`BUNDLE_END`:ke.log(`[gjsify build --watch] built in ${n.duration}ms`);try{(a===`gjs`||a===`node`)&&this.configData.shebang&&await this.applyShebang(a,S,C)}finally{await n.result.close()}break;case`END`:ke.log(`[gjsify build --watch] waiting for changes…`);break;case`ERROR`:ke.error(`[gjsify build --watch] build failed:`,n.error?.message??n.error),C&&n.error?.stack&&ke.error(n.error.stack);try{await n.result.close()}catch{}break}}),C&&N.on(`change`,(n,a)=>{ke.log(`[gjsify build --watch] ${a.event}: ${n}`)}),await F}async start(n={app:`gjs`}){if(n.library){if(n.watch)throw Error(`gjsify build: --watch is not supported with --library (library mode would emit watcher rebuilds for every produced format; use --app gjs|node|browser instead).`);return await this.buildLibrary()}return await this.buildApp(n.app,{watch:n.watch})}}}),$A,ej=__esmMin(()=>{Fg(),QA(),$A={command:`build [entryPoints..]`,description:`Build and bundle your Gjs project`,builder:n=>n.option(`entry-points`,{description:`The entry points you want to bundle. Defaults to bundler.input from package.json#gjsify or .gjsifyrc.js, falling back to src/index.ts when neither is set.`,array:!0,type:`string`,normalize:!0,defaultDescription:`src/index.ts (fallback)`,coerce:n=>[...new Set(n)]}).option(`exclude`,{description:`An array of glob patterns to exclude entry-points and aliases`,array:!0,type:`string`,normalize:!0,default:[]}).option(`verbose`,{description:`Switch on the verbose mode`,type:`boolean`,normalize:!0,default:!1}).option(`app`,{description:`Use this if you want to build an application, the platform node is usually only used for tests`,type:`string`,choices:[`gjs`,`node`,`browser`,`nativescript`],normalize:!0,default:`gjs`}).option(`format`,{description:`Override the default output format`,type:`string`,choices:[`iife`,`esm`,`cjs`],normalize:!0}).option(`minify`,{description:`Minify the bundled output. Defaults to true; use --no-minify to emit pretty-printed code (e.g. for debugging or readable bundle review).`,type:`boolean`,normalize:!0,defaultDescription:`true`}).option(`library`,{description:`Use this if you want to build a library for Gjsify`,type:`boolean`,normalize:!0,default:!1}).option(`outfile`,{alias:`o`,description:`Sets the output file name for the build operation. If no outfile is specified, the outfile will be parsed from the package.json. Only used if application mode is active`,type:`string`,normalize:!0}).option(`outdir`,{alias:`d`,description:`Sets the output directory for the build operation. If no outdir is specified, the outdir will be parsed from the package.json. Only used if library mode is active`,type:`string`,normalize:!0}).option(`reflection`,{alias:`r`,description:`Enables TypeScript types on runtime using Deepkit's type compiler`,type:`boolean`,normalize:!0,default:!1}).option(`log-level`,{description:`The log level can be changed to prevent esbuild from printing warning and/or error messages to the terminal`,type:`string`,choices:[`silent`,`error`,`warning`,`info`,`debug`,`verbose`],normalize:!0,default:`warning`}).option(`console-shim`,{description:`Inject a console shim into GJS builds for clean output without the GLib prefix and with working ANSI colors. Use --no-console-shim to disable. Only applies to GJS app builds.`,type:`boolean`,normalize:!0,default:!0}).option(`globals`,{description:"Comma-separated list of global identifiers, 'auto' (default) to detect automatically from the bundled output, or 'none' to disable. The 'auto' token may be combined with explicit identifiers/groups (e.g. 'auto,dom') for cases where the detector cannot statically see a global because it's accessed via indirection. Each identifier is mapped to the corresponding `@gjsify/<pkg>/register` module and injected into the bundle. See the CLI Reference docs for the full list of known identifiers. Only applies to GJS app builds.",type:`string`,normalize:!0}).option(`shebang`,{description:"Prepend a target-appropriate shebang to the output and mark it executable (chmod 755): `#!/usr/bin/env -S gjs -m` for --app gjs, `#!/usr/bin/env node` for --app node. Applies to GJS and Node app builds with a single --outfile. Default: false (use --shebang to enable, or set `shebang: true` in `.gjsifyrc.js`).",type:`boolean`,normalize:!0}).option(`external`,{description:"Module names that should NOT be bundled — EXACT package names only, matched literally on both bundler engines (no globs). Repeat the flag or pass a comma-separated list (e.g. --external typedoc,prettier). Appended to the per-app built-in externals; register subpaths (`<pkg>/register[/…]`) are always force-inlined for --app gjs regardless of this flag.",array:!0,type:`string`,default:[],coerce:n=>n.flatMap(n=>n.split(`,`).map(n=>n.trim()).filter(Boolean))}).option(`define`,{description:`Substitute compile-time constants. Each entry is KEY=VALUE where VALUE is a JS expression (string literals must be quoted: --define VERSION='"1.2.3"'). Repeat the flag or pass comma-separated. See https://esbuild.github.io/api/#define`,array:!0,type:`string`,default:[]}).option(`alias`,{description:`Map module specifiers at bundle time. Each entry is FROM=TO (e.g. --alias typedoc=@gjsify/empty). Layered on top of the built-in alias map. Useful for stubbing heavy deps the test scenario never executes.`,array:!0,type:`string`,default:[],coerce:n=>n.flatMap(n=>n.split(`,`).map(n=>n.trim()).filter(Boolean))}).option(`exclude-globals`,{description:`Comma-separated global identifiers to remove from auto-detection results. Use for false positives from dead browser-compat code whose polyfills require unavailable native libraries (e.g. --exclude-globals fetch,XMLHttpRequest).`,type:`string`,normalize:!0}).option(`watch`,{alias:`w`,description:"Watch source files and rebuild on change. Logs each rebuild with duration; clean SIGINT shutdown. Only valid with --app gjs|node|browser (rejected with --library). Requires the npm `rolldown` engine — run under Node, not the GJS-bundled CLI.",type:`boolean`,normalize:!0,default:!1}),handler:async n=>{await new ZA(await new Config().forBuild(n)).start({library:n.library,app:n.app,watch:n.watch})}}});function nodeArchToLinuxArch(n){return{x64:`x86_64`,arm64:`aarch64`,arm:`armv7`,ia32:`i686`}[n]??n}function readPackageJson$3(n){try{return JSON.parse(readFileSync(n,`utf-8`))}catch{return null}}function scanNodeModules(n,a){let S=[];if(!existsSync(n))return S;let C;try{C=readdirSync(n)}catch{return S}for(let N of C)if(!N.startsWith(`.`))if(N.startsWith(`@`)){let C=ns(n,N),F;try{F=readdirSync(C)}catch{continue}for(let n of F){let F=checkPackage(ns(C,n),`${N}/${n}`,a);F&&S.push(F)}}else{let C=checkPackage(ns(n,N),N,a);C&&S.push(C)}return S}function checkPackage(n,a,S){let C=readPackageJson$3(ns(n,`package.json`));if(!C)return null;let N=C.gjsify;if(!N||typeof N!=`object`)return null;let F=N.prebuilds;if(typeof F!=`string`)return null;let I=ns(n,F,`linux-${S}`);return existsSync(I)?{name:a,prebuildsDir:I}:null}function detectNativePackages(n){let a=nodeArchToLinuxArch(process.arch),S=[],C=new Set,N=$o(n);for(;;){let n=ns(N,`node_modules`);if(existsSync(n))for(let N of scanNodeModules(n,a))C.has(N.name)||(C.add(N.name),S.push(N));let F=$o(N,`..`);if(F===N)break;N=F}return S}function buildNativeEnv(n){let a=n.map(n=>n.prebuildsDir),S=process.env.LD_LIBRARY_PATH??``,C=process.env.GI_TYPELIB_PATH??``;return{LD_LIBRARY_PATH:[...a,...S?[S]:[]].join(`:`),GI_TYPELIB_PATH:[...a,...C?[C]:[]].join(`:`)}}var tj=__esmMin(()=>{Zc(),ps(),__name$1(readPackageJson$3,`readPackageJson`)}),nj=__exportAll$3({computeNativeEnvForBundle:()=>computeNativeEnvForBundle,runGjsBundle:()=>runGjsBundle});function computeNativeEnvForBundle(n,a=process.cwd()){let S=$o(n),C=detectNativePackages(a),N=detectNativePackages(as(S)),F=new Set(C.map(n=>n.name)),I=buildNativeEnv([...C,...N.filter(n=>!F.has(n.name))]);return{env:I,envPrefix:Object.entries(I).filter(([,n])=>n!==void 0&&n!==``).map(([n,a])=>`${n}=${a}`).join(` `)}}async function runGjsBundle(n,a=[],S={}){let{env:C,envPrefix:N}=computeNativeEnvForBundle(n),F={...process.env,...C},I=[`-m`,n,...a],H=[`gjs`,...I.map(n=>n.includes(` `)?`"${n}"`:n)].join(` `);ke.error(`$ ${N?`${N} `:``}${H}`);let W=spawn(`gjs`,I,{env:F,stdio:`inherit`});await new Promise((n,a)=>{W.on(`close`,S=>{S===0?n():a(Error(`gjs exited with code ${S}`))}),W.on(`error`,a)}).catch(n=>{ke.error(n.message),process.exit(1)}),S.exitOnSuccess&&process.exit(0)}var rj=__esmMin(()=>{Ae(),cC(),ps(),tj()});async function buildTestBundle(n,a,S,C){let N=await new Config().forBuild({entryPoints:[n],outfile:a,app:S,verbose:C??!1,logLevel:`warning`,exclude:[]});N.library={...N.library},N.bundler={...N.bundler,input:[n],output:{...N.bundler?.output,file:a}},await new ZA(N).start({app:S,library:!1})}async function runTestBundle(n,a){if(a===`gjs`){await runGjsBundle(n);return}await new Promise((a,S)=>{let C=spawn(`node`,[n],{stdio:`inherit`});C.on(`error`,S),C.on(`exit`,n=>{n===0?a():S(Error(`node exited with code ${n}`))})})}function isFresh(n,a){if(!existsSync(n))return!1;let S=statSync(n).mtimeMs,C=as(a);try{return S>=newestMtimeUnder(existsSync(C)?C:a)}catch{return!1}}function newestMtimeUnder(n){let a=statSync(n);if(a.isFile())return a.mtimeMs;let S=a.mtimeMs;for(let a of readdirSync(n,{withFileTypes:!0})){if(a.name===`node_modules`||a.name===`dist`||a.name===`lib`||a.name.startsWith(`.`))continue;let C=newestMtimeUnder(ns(n,a.name));C>S&&(S=C)}return S}var ij,aj=__esmMin(()=>{Ae(),Zc(),ps(),cC(),Fg(),QA(),rj(),ij={command:`test`,description:"Build + run the package’s `src/test.mts` suite on GJS and Node and aggregate the results. Replaces the per-package `build:test:{gjs,node}` + `test:{gjs,node}` script boilerplate.",builder:n=>n.option(`runtime`,{description:`Target runtime. Default: both.`,type:`string`,choices:[`gjs`,`node`,`all`],default:`all`}).option(`entry`,{description:"Path to the test entry. Default: `src/test.mts` (or `gjsify.test.entry`).",type:`string`,normalize:!0}).option(`outdir`,{description:"Output directory for the built test bundles. Default: `dist/`.",type:`string`,normalize:!0}).option(`rebuild`,{description:`Always rebuild the test bundles, even when they look up-to-date.`,type:`boolean`,default:!1}).option(`build`,{description:`Build before running. Default: true (use --no-build to skip when bundles already exist).`,type:`boolean`,default:!0}).option(`verbose`,{description:`Print resolved entry/outdir + per-step timing.`,type:`boolean`,default:!1}),handler:async n=>{let a=process.cwd(),S=(await new Config().forBuild({}).catch(()=>({}))).test??{},C=$o(a,n.entry??S.entry??`src/test.mts`),N=$o(a,n.outdir??S.outdir??`dist`);existsSync(C)||(ke.error(`[gjsify test] no test entry at ${rs(a,C)} — add an \`src/test.mts\` that aggregates your \`@gjsify/unit\` suites, or set \`gjsify.test.entry\` in package.json.`),process.exit(1));let F=n.runtime===`gjs`?[`gjs`]:n.runtime===`node`?[`node`]:S.runtimes&&S.runtimes.length>0?S.runtimes:[`gjs`,`node`],I=[];for(let S of F){let F=ns(N,`test.${S}.mjs`);if(n.build!==!1)if(n.rebuild||!isFresh(F,C)){let N=Date.now();n.verbose&&ke.log(`[gjsify test] building → ${rs(a,F)} (—app ${S})`);try{await buildTestBundle(C,F,S,n.verbose),n.verbose&&ke.log(`[gjsify test] built ${S} in ${Date.now()-N}ms`)}catch(n){ke.error(`[gjsify test] build failed for ${S}:`,n.message),I.push({runtime:S,ok:!1,durationMs:0,error:`build failed`});continue}}else n.verbose&&ke.log(`[gjsify test] ${S}: bundle is up-to-date — skipping build (use --rebuild to force)`);else if(!existsSync(F)){ke.error(`[gjsify test] --no-build but ${rs(a,F)} doesn't exist. Build first or drop --no-build.`),I.push({runtime:S,ok:!1,durationMs:0,error:`no bundle`});continue}let H=Date.now();try{await runTestBundle(F,S),I.push({runtime:S,ok:!0,durationMs:Date.now()-H})}catch(n){I.push({runtime:S,ok:!1,durationMs:Date.now()-H,error:n.message})}}let H=I.map(n=>`${n.ok?`✅`:`❌`} ${n.runtime} (${n.durationMs}ms)${n.error?` — ${n.error}`:``}`).join(` `);ke.log(`[gjsify test] ${H}`),I.some(n=>!n.ok)&&process.exit(1),process.exit(0)}}});function readPackageJson$2(n){if(!existsSync(n))return null;let a=readFileSync(n,`utf-8`);try{return JSON.parse(a)}catch(a){throw Error(`gjsify install: ${n} is not valid JSON: ${a.message}`)}}function writePackageJson(n,a){let S=sortKnownDepFields(a);writeFileSync(n,JSON.stringify(S,null,2)+`
|
|
746
|
-
`,`utf-8`)}function parseSpec$2(n){if(n.startsWith(`@`)){let a=n.indexOf(`/`);if(a===-1)return{name:n};let S=n.indexOf(`@`,a+1);return S===-1?{name:n}:{name:n.slice(0,S),range:n.slice(S+1)}}let a=n.indexOf(`@`);return a===-1?{name:n}:{name:n.slice(0,a),range:n.slice(a+1)}}function projectSpecsFromPackageJson(n){let a=[];for(let S of[`dependencies`,`devDependencies`,`optionalDependencies`]){let C=n[S];if(C)for(let[n,S]of Object.entries(C))typeof S==`string`&&(/^(workspace|link|file|portal|git\+|https?):/.test(S)||a.push(`${n}@${S}`))}return a}function addDependencyEntry(n,a,S,C){n[C]===void 0&&(n[C]={}),n[C][a]=S}function defaultRangeFromVersion(n){return`^${n}`}function sortKnownDepFields(n){let a={...n};for(let n of[`dependencies`,`devDependencies`,`peerDependencies`,`optionalDependencies`]){let S=a[n];S&&(a[n]=Object.fromEntries(Object.entries(S).sort(([n],[a])=>n<a?-1:+(n>a))))}return a}var oj=__esmMin(()=>{Zc(),__name$1(readPackageJson$2,`readPackageJson`),__name$1(parseSpec$2,`parseSpec`)});function looksLikeFile(n){if(n.startsWith(`./`)||n.startsWith(`../`)||n.startsWith(`/`)||n.includes(`/`)||n.includes(`\\`)||/\.(c?js|mjs|cjs|gjs)$/.test(n))return!0;try{return statSync(n).isFile()}catch{return!1}}async function runScript(n,a){let S=process.cwd(),C=ns(S,`package.json`),N=readPackageJson$2(C);N||(ke.error(`gjsify run: no package.json in ${S}`),process.exit(1));let F=N.scripts??{},I=F[n];if(typeof I!=`string`){let a=Object.keys(F).join(`, `)||`<none>`;ke.error(`gjsify run: no script "${n}" in ${C} (available: ${a})`),process.exit(1)}let H=findWorkspaceRoot(S),W=[ns(S,`node_modules`,`.bin`)];H&&H!==S&&W.push(ns(H,`node_modules`,`.bin`)),process.env.GJSIFY_SHIM_DIR&&W.unshift(process.env.GJSIFY_SHIM_DIR);let K=process.env.FORCE_COLOR!==void 0||process.env.NO_COLOR!==void 0?{}:{FORCE_COLOR:`1`},q={...process.env,...K,PATH:[...W,process.env.PATH??``].filter(Boolean).join(ds),npm_lifecycle_event:n,npm_package_name:N.name??``,npm_package_version:N.version??``},Y=isGjs()?gjsifyInProcessArgv(I,a):null;if(Y){process.env.PATH=q.PATH,process.env.npm_lifecycle_event=q.npm_lifecycle_event,process.env.npm_package_name=q.npm_package_name,process.env.npm_package_version=q.npm_package_version,q.FORCE_COLOR!==void 0&&(process.env.FORCE_COLOR=q.FORCE_COLOR);try{let{runCli:n}=await Promise.resolve().then(()=>(
|
|
746
|
+
`,`utf-8`)}function parseSpec$2(n){if(n.startsWith(`@`)){let a=n.indexOf(`/`);if(a===-1)return{name:n};let S=n.indexOf(`@`,a+1);return S===-1?{name:n}:{name:n.slice(0,S),range:n.slice(S+1)}}let a=n.indexOf(`@`);return a===-1?{name:n}:{name:n.slice(0,a),range:n.slice(a+1)}}function projectSpecsFromPackageJson(n){let a=[];for(let S of[`dependencies`,`devDependencies`,`optionalDependencies`]){let C=n[S];if(C)for(let[n,S]of Object.entries(C))typeof S==`string`&&(/^(workspace|link|file|portal|git\+|https?):/.test(S)||a.push(`${n}@${S}`))}return a}function addDependencyEntry(n,a,S,C){n[C]===void 0&&(n[C]={}),n[C][a]=S}function defaultRangeFromVersion(n){return`^${n}`}function sortKnownDepFields(n){let a={...n};for(let n of[`dependencies`,`devDependencies`,`peerDependencies`,`optionalDependencies`]){let S=a[n];S&&(a[n]=Object.fromEntries(Object.entries(S).sort(([n],[a])=>n<a?-1:+(n>a))))}return a}var oj=__esmMin(()=>{Zc(),__name$1(readPackageJson$2,`readPackageJson`),__name$1(parseSpec$2,`parseSpec`)});function looksLikeFile(n){if(n.startsWith(`./`)||n.startsWith(`../`)||n.startsWith(`/`)||n.includes(`/`)||n.includes(`\\`)||/\.(c?js|mjs|cjs|gjs)$/.test(n))return!0;try{return statSync(n).isFile()}catch{return!1}}async function runScript(n,a){let S=process.cwd(),C=ns(S,`package.json`),N=readPackageJson$2(C);N||(ke.error(`gjsify run: no package.json in ${S}`),process.exit(1));let F=N.scripts??{},I=F[n];if(typeof I!=`string`){let a=Object.keys(F).join(`, `)||`<none>`;ke.error(`gjsify run: no script "${n}" in ${C} (available: ${a})`),process.exit(1)}let H=findWorkspaceRoot(S),W=[ns(S,`node_modules`,`.bin`)];H&&H!==S&&W.push(ns(H,`node_modules`,`.bin`)),process.env.GJSIFY_SHIM_DIR&&W.unshift(process.env.GJSIFY_SHIM_DIR);let K=process.env.FORCE_COLOR!==void 0||process.env.NO_COLOR!==void 0?{}:{FORCE_COLOR:`1`},q={...process.env,...K,PATH:[...W,process.env.PATH??``].filter(Boolean).join(ds),npm_lifecycle_event:n,npm_package_name:N.name??``,npm_package_version:N.version??``},Y=isGjs()?gjsifyInProcessArgv(I,a):null;if(Y){process.env.PATH=q.PATH,process.env.npm_lifecycle_event=q.npm_lifecycle_event,process.env.npm_package_name=q.npm_package_name,process.env.npm_package_version=q.npm_package_version,q.FORCE_COLOR!==void 0&&(process.env.FORCE_COLOR=q.FORCE_COLOR);try{let{runCli:n}=await Promise.resolve().then(()=>(kP(),OP));await n(Y)}catch(n){ke.error(n.message),process.exit(1)}process.exit(process.exitCode==null?0:Number(process.exitCode))}let X=a.length>0?`${I} ${a.map(shellEscape).join(` `)}`:I;await new Promise((a,C)=>{let N=spawn(X,[],{cwd:S,env:q,stdio:`inherit`,shell:!0});N.on(`close`,S=>{S===0?a():C(Error(`script "${n}" exited with code ${S}`))}),N.on(`error`,C)}).catch(n=>{ke.error(n.message),process.exit(1)}),process.exit(0)}function shellEscape(n){return/^[a-zA-Z0-9_\-./=:@,]+$/.test(n)?n:`'${n.replace(/'/g,`'\\''`)}'`}function gjsifyInProcessArgv(n,a){let S=tokenizeSimpleCommand(n);return!S||S.length<2||S[0]!==`gjsify`?null:[...S.slice(1),...a]}function tokenizeSimpleCommand(n){let a=[],S=``,C=!1,N=null;for(let F=0;F<n.length;F++){let I=n[F];if(N===`'`){I===`'`?N=null:S+=I;continue}if(N===`"`){if(I===`"`)N=null;else if(I===`\\`&&(n[F+1]===`"`||n[F+1]===`\\`))S+=n[++F];else if(I===`$`||I==="`")return null;else S+=I;continue}if(I===`'`||I===`"`){N=I,C=!0;continue}if(I===` `||I===` `){C&&=(a.push(S),S=``,!1);continue}if(`|&;<>\`$()\\
|
|
747
747
|
\r*?{}[]~#!`.includes(I))return null;S+=I,C=!0}return N?null:(C&&a.push(S),a)}var sj,cj=__esmMin(()=>{Ae(),Zc(),ps(),cC(),rj(),oj(),Lg(),zg(),sj={command:`run <target> [args..]`,description:"Run a script from package.json (yarn-run-style) or a GJS bundle file. If <target> resolves to a file on disk (or has a path-like prefix), it is launched via gjs with LD_LIBRARY_PATH + GI_TYPELIB_PATH set for native packages. Otherwise it is looked up in the current package.json `scripts`.",builder:n=>n.positional(`target`,{description:"Either a script name (looked up in package.json `scripts`) or a path to a GJS bundle (e.g. dist/gjs.js).",type:`string`,demandOption:!0}).positional(`args`,{description:`Extra arguments passed through to the script / gjs.`,type:`string`,array:!0,default:[]}).parserConfiguration({"populate--":!0,"unknown-options-as-args":!0}),handler:async n=>{let a=n.target,S=n.args??[],C=(n[`--`]??[]).filter(n=>typeof n==`string`),N=[...S,...C],F=readPackageJson$2(ns(process.cwd(),`package.json`));if(!(F?.scripts&&typeof F.scripts[a]==`string`)&&looksLikeFile(a)){await runGjsBundle($o(a),N,{exitOnSuccess:!0});return}await runScript(a,N)}}}),lj,uj=__esmMin(()=>{Ae(),ps(),tj(),lj={command:`info [file]`,description:`Show native gjsify packages detected in node_modules and the env vars needed to run a GJS bundle directly with gjs.`,builder:n=>n.positional(`file`,{description:`Optional: the GJS bundle path to include in the example command (e.g. dist/gjs.js)`,type:`string`,normalize:!0}).option(`export`,{description:`Output only shell export statements suitable for eval (eval $(gjsify info --export))`,type:`boolean`,default:!1}),handler:async n=>{let a=process.cwd(),S=n.file?$o(n.file):null,C=detectNativePackages(a),{LD_LIBRARY_PATH:N,GI_TYPELIB_PATH:F}=buildNativeEnv(C);if(n.export){ke.log(`export LD_LIBRARY_PATH="${N}"`),ke.log(`export GI_TYPELIB_PATH="${F}"`);return}if(C.length===0){ke.log(`No native gjsify packages detected in node_modules.`),ke.log(`Native packages declare "gjsify": { "prebuilds": "<dir>" } in their package.json.`);return}ke.log(`Native packages detected:`);for(let n of C)ke.log(` ${n.name} → ${n.prebuildsDir}`);ke.log(``),ke.log(`To run your app directly with gjs, set:`),ke.log(` export LD_LIBRARY_PATH="${N}"`),ke.log(` export GI_TYPELIB_PATH="${F}"`),S?ke.log(` gjs -m ${S}`):ke.log(` gjs -m <your-bundle.js>`),ke.log(``),ke.log(`Or use gjsify run to handle this automatically:`),S?ke.log(` gjsify run ${n.file}`):ke.log(` gjsify run <your-bundle.js>`)}}});function tryExecFile(n,a){try{return execFileSync(n,a,{encoding:`utf-8`,stdio:[`ignore`,`pipe`,`ignore`]}).trim()}catch{return null}}function checkBinary(n,a,S,C,N,F,I){let H=tryExecFile(S,C);return H===null?{id:n,name:a,found:!1,severity:N,requiredBy:I}:{id:n,name:a,found:!0,version:F?F(H):H.split(`
|
|
748
748
|
`)[0]??H,severity:N,requiredBy:I}}function checkPkgConfig(n,a,S,C,N){let F=tryExecFile(`pkg-config`,[`--modversion`,S]);return F===null?{id:n,name:a,found:!1,severity:C,requiredBy:N}:{id:n,name:a,found:!0,version:F.split(`
|
|
749
749
|
`)[0],severity:C,requiredBy:N}}function checkNpmPackage(n,a,S,C,N,F){try{return createRequire(pathToFileURL(ns(C,`_check_.js`)).href).resolve(S),{id:n,name:a,found:!0,severity:N,requiredBy:F}}catch{}try{return createRequire(import.meta.url).resolve(S),{id:n,name:a,found:!0,severity:N,requiredBy:F}}catch{return{id:n,name:a,found:!1,severity:N,requiredBy:F}}}function detectPackageManager$2(){for(let n of[`apt`,`dnf`,`pacman`,`zypper`,`apk`])if(tryExecFile(`which`,[n])!==null)return n;return`unknown`}function findProjectRoot(n){let a=$o(n);for(;;){if(existsSync(ns(a,`package.json`)))return a;let n=$o(a,`..`);if(n===a)return null;a=n}}function discoverGjsifyPackages(n){let a=findProjectRoot(n);if(!a)return null;let S=ns(a,`node_modules`,`@gjsify`);if(!existsSync(S))return new Set;let C=ns(a,`package.json`),N={};try{N=JSON.parse(readFileSync(C,`utf-8`))}catch{}let F={...N.dependencies,...N.devDependencies},I=new Set;try{for(let n of readdirSync(S,{withFileTypes:!0}))(n.isDirectory()||n.isSymbolicLink())&&I.add(`@gjsify/${n.name}`)}catch{}for(let n of Object.keys(F))n.startsWith(`@gjsify/`)&&I.add(n);return I}function computeNeededOptionalDeps(n){let a=discoverGjsifyPackages(n);if(a===null)return null;let S=new Set;for(let n of a){let a=fj[n];if(a)for(let n of a)S.add(n)}return S}function runAllChecks(n){let a=computeNeededOptionalDeps(n);return[...runMinimalChecks(),...runRequiredChecks(n),...runOptionalChecks(a,n)]}function runMinimalChecks(){let n=[];return n.push({id:`nodejs`,name:`Node.js`,found:!0,version:process.version,severity:`required`}),n.push(checkBinary(`gjs`,`GJS`,`gjs`,[`--version`],`required`,n=>n.replace(/^GJS\s+/i,``).split(`
|
|
@@ -836,7 +836,9 @@ Select upgrades: comma- or space-separated indices, `+rP.bold+`a`+rP.reset+` for
|
|
|
836
836
|
`).filter(Boolean)}function readStdinLines(){return readFileSync(0,`utf8`).split(`
|
|
837
837
|
`).map(n=>n.trim()).filter(Boolean)}function emit(n,a){if(n===`json`){process.stdout.write(JSON.stringify(a)+`
|
|
838
838
|
`);return}if(n===`globs`){for(let n of a.workspaces)process.stdout.write(`${n}\n`);return}if(n===`github-actions`){let n=a.global?``:a.workspaces.map(n=>`--include '${escSingleQuote(n)}'`).join(` `),S=process.env.GITHUB_OUTPUT,C=[`skip-all=${a.skipAll}`,`global=${a.global}`,`include-args=${n}`,`run-integration=${a.runIntegration}`,`run-e2e=${a.runE2E}`,`reason=${a.reason}`];if(S){let{appendFileSync:n}=(Zc(),__toCommonJS(Jc));for(let a of C)n(S,`${a}\n`)}else for(let n of C)process.stdout.write(`${n}\n`);return}process.stdout.write(`affected:
|
|
839
|
-
`),process.stdout.write(` reason: ${a.reason}\n`),process.stdout.write(` global: ${a.global}\n`),process.stdout.write(` skip-all: ${a.skipAll}\n`),process.stdout.write(` run-integration: ${a.runIntegration}\n`),process.stdout.write(` run-e2e: ${a.runE2E}\n`),process.stdout.write(` workspaces (${a.workspaces.length}):\n`);for(let n of a.workspaces)process.stdout.write(` - ${n}\n`)}function escSingleQuote(n){return n.replace(/'/g,`'\\''`)}var fP,pP,mP,hP,gP=__esmMin(()=>{cC(),Zc(),Ig(),Lg(),fP={command:`affected`,description:"Classify changed files against the workspace tree and print the set of workspaces affected (seeds + transitive dependents). Designed for CI to gate `gjsify foreach test --include …` so unrelated workspaces are not re-tested on every PR.",builder:n=>n.option(`base`,{description:"Diff base. Default: `origin/main`. Resolved via `git rev-parse`. On a PR set this to `${{ github.event.pull_request.base.sha }}`.",type:`string`}).option(`head`,{description:"Diff head. Default: `HEAD`.",type:`string`,default:`HEAD`}).option(`format`,{description:`Output shape.`,choices:[`text`,`json`,`globs`,`github-actions`],default:`text`}).option(`changed-from-stdin`,{description:"Skip `git diff`. Read a newline-separated list of repo-relative paths from stdin instead. Lets callers — tests, ad-hoc scripts — control the input exactly.",type:`boolean`,default:!1}).option(`cwd`,{description:"Workspace root. Default: discovered from `process.cwd()`.",type:`string`}),handler:async n=>{let a=n.cwd??findWorkspaceRoot(process.cwd())??process.cwd(),S=classifyAndExpand(discoverWorkspaces(a,{includeRoot:!0}),a,n[`changed-from-stdin`]?readStdinLines():runGitDiff(a,n.base??`origin/main`,n.head??`HEAD`));emit(n.format,S)}},pP=[/^packages\/infra\/workspace\//,/^packages\/infra\/cli\//,/^packages\/infra\/rolldown-plugin-gjsify\//,/^packages\/infra\/resolve-npm\//,/^packages\/gjs\/unit\//,/^gjsify-lock\.json$/,/^package\.json$/,/^tsconfig[^/]*\.json$/,/^\.github\/workflows\/main\.yml$/,/^scripts\/audit-runtimes\.mjs$/],mP=[/\.md$/i,/^refs\//,/^website\//,/^docs\//,/^\.github\/workflows\/(deploy-docs|commitlint|release|audit-runtimes|prebuilds|node-gi)\.yml$/,/^\.githooks\//,/^packages\/node-gi\//,/^flatpak\//,/^LICENSE/,/^\.gitignore$/,/^\.gjsify-[^/]*\.md$/,/^STATUS\.md$/,/^CHANGELOG\.md$/,/^AGENTS\.md$/,/^CLAUDE\.md$/,/^README\.md$/],hP=[/\.spec\.[mc]?[tj]sx?$/,/^tests\/(e2e|integration)\//]});function
|
|
839
|
+
`),process.stdout.write(` reason: ${a.reason}\n`),process.stdout.write(` global: ${a.global}\n`),process.stdout.write(` skip-all: ${a.skipAll}\n`),process.stdout.write(` run-integration: ${a.runIntegration}\n`),process.stdout.write(` run-e2e: ${a.runE2E}\n`),process.stdout.write(` workspaces (${a.workspaces.length}):\n`);for(let n of a.workspaces)process.stdout.write(` - ${n}\n`)}function escSingleQuote(n){return n.replace(/'/g,`'\\''`)}var fP,pP,mP,hP,gP=__esmMin(()=>{cC(),Zc(),Ig(),Lg(),fP={command:`affected`,description:"Classify changed files against the workspace tree and print the set of workspaces affected (seeds + transitive dependents). Designed for CI to gate `gjsify foreach test --include …` so unrelated workspaces are not re-tested on every PR.",builder:n=>n.option(`base`,{description:"Diff base. Default: `origin/main`. Resolved via `git rev-parse`. On a PR set this to `${{ github.event.pull_request.base.sha }}`.",type:`string`}).option(`head`,{description:"Diff head. Default: `HEAD`.",type:`string`,default:`HEAD`}).option(`format`,{description:`Output shape.`,choices:[`text`,`json`,`globs`,`github-actions`],default:`text`}).option(`changed-from-stdin`,{description:"Skip `git diff`. Read a newline-separated list of repo-relative paths from stdin instead. Lets callers — tests, ad-hoc scripts — control the input exactly.",type:`boolean`,default:!1}).option(`cwd`,{description:"Workspace root. Default: discovered from `process.cwd()`.",type:`string`}),handler:async n=>{let a=n.cwd??findWorkspaceRoot(process.cwd())??process.cwd(),S=classifyAndExpand(discoverWorkspaces(a,{includeRoot:!0}),a,n[`changed-from-stdin`]?readStdinLines():runGitDiff(a,n.base??`origin/main`,n.head??`HEAD`));emit(n.format,S)}},pP=[/^packages\/infra\/workspace\//,/^packages\/infra\/cli\//,/^packages\/infra\/rolldown-plugin-gjsify\//,/^packages\/infra\/resolve-npm\//,/^packages\/gjs\/unit\//,/^gjsify-lock\.json$/,/^package\.json$/,/^tsconfig[^/]*\.json$/,/^\.github\/workflows\/main\.yml$/,/^scripts\/audit-runtimes\.mjs$/],mP=[/\.md$/i,/^refs\//,/^website\//,/^docs\//,/^\.github\/workflows\/(deploy-docs|commitlint|release|audit-runtimes|prebuilds|node-gi)\.yml$/,/^\.githooks\//,/^packages\/node-gi\//,/^flatpak\//,/^LICENSE/,/^\.gitignore$/,/^\.gjsify-[^/]*\.md$/,/^STATUS\.md$/,/^CHANGELOG\.md$/,/^AGENTS\.md$/,/^CLAUDE\.md$/,/^README\.md$/],hP=[/\.spec\.[mc]?[tj]sx?$/,/^tests\/(e2e|integration)\//]}),_P=__exportAll$3({nodeBinary:()=>nodeBinary,resolveNodeGi:()=>resolveNodeGi,runNodeBundle:()=>runNodeBundle});function resolveNodeGi(n){let a=$o(n);for(;;){if(existsSync(ns(a,`node_modules`,`@gjsify`,`node-gi`,`package.json`)))return ns(a,`node_modules`,`@gjsify`,`node-gi`);let n=$o(a,`..`);if(n===a)return null;a=n}}function nodeBinary(){return isNode()&&process.execPath?process.execPath:`node`}async function runNodeBundle(n,a=[],S={}){let C=process.cwd();if(!resolveNodeGi(C))throw Error(`Cannot run the storybook on Node: \`@gjsify/node-gi\` is not installed.
|
|
840
|
+
Add @gjsify/node-gi as a dependency to run the storybook on Node, e.g.:
|
|
841
|
+
"devDependencies": { "@gjsify/node-gi": "^0.13.0" }`);let{env:N,envPrefix:F}=computeNativeEnvForBundle(n,C),I={...process.env,...N},H=nodeBinary(),W=[n,...a],K=[H,...W.map(n=>n.includes(` `)?`"${n}"`:n)].join(` `);ke.error(`$ ${F?`${F} `:``}${K}`);let q=spawn(H,W,{env:I,stdio:`inherit`});await new Promise((n,a)=>{q.on(`close`,S=>{S===0?n():a(Error(`node exited with code ${S}`))}),q.on(`error`,a)}).catch(n=>{ke.error(n.message),process.exit(1)}),S.exitOnSuccess&&process.exit(0)}var vP=__esmMin(()=>{Ae(),cC(),Zc(),ps(),zg(),rj()});function readPackage$2(n){try{return JSON.parse(readFileSync(ns(n,`package.json`),`utf8`))}catch{return{}}}function deriveAppId(n){return n?`org.gjsify.storybook.${n.replace(/^@/,``).replace(/[^a-zA-Z0-9]+/g,`.`).replace(/^\.+|\.+$/g,``)}`:`org.gjsify.Storybook`}function findStoryFiles(n){let a=[];if(!existsSync(n))return a;for(let S of readdirSync(n,{withFileTypes:!0})){if(S.name===`node_modules`||S.name.startsWith(`.`))continue;let C=ns(n,S.name);S.isDirectory()?a.push(...findStoryFiles(C)):/\.story\.(ts|js|mts|mjs)$/.test(S.name)&&a.push(C)}return a}function generateEntry$2(n,a,S){let C=n.map((n,a)=>`import * as m${a} from ${JSON.stringify(n)};`).join(`
|
|
840
842
|
`),N=n.map((n,a)=>`m${a}`).join(`, `),F=S?`\n title: ${JSON.stringify(S)},`:``;return`// Auto-generated by \`gjsify storybook\` — do not edit by hand.
|
|
841
843
|
import { collectStoryModules, runStorybook } from '@gjsify/storybook';
|
|
842
844
|
${C}
|
|
@@ -845,7 +847,7 @@ await runStorybook({
|
|
|
845
847
|
applicationId: ${JSON.stringify(a)},${F}
|
|
846
848
|
stories: collectStoryModules([${N}]),
|
|
847
849
|
});
|
|
848
|
-
`}var
|
|
850
|
+
`}var yP,bP=__esmMin(()=>{Ae(),cC(),Zc(),ps(),__name$1(readPackage$2,`readPackage`),__name$1(generateEntry$2,`generateEntry`),yP={command:`storybook`,description:`Discover *.story.ts in this project and launch the GTK storybook browser.`,builder:n=>n.option(`stories`,{description:`Directory scanned recursively for *.story.ts (default: src, or gjsify.storybook.stories)`,type:`string`}).option(`app-id`,{description:`GApplication id (default: gjsify.storybook.applicationId or derived from the package name)`,type:`string`}).option(`title`,{description:`Window title`,type:`string`}).option(`globals`,{description:"Value for `gjsify build --globals` (default: auto; use auto,dom for canvas/DOM stories)",type:`string`}).option(`out`,{description:`Output bundle path (default: node_modules/.cache/gjsify-storybook)`,type:`string`}).option(`runtime`,{description:`Runtime to build for and launch on: gjs (default) or node (via @gjsify/node-gi). node requires @gjsify/node-gi installed in the project.`,type:`string`,choices:[`gjs`,`node`],default:`gjs`}).option(`watch`,{description:`Rebuild and relaunch when a story file changes`,type:`boolean`,default:!1}).option(`build-only`,{description:`Build the bundle but do not launch it`,type:`boolean`,default:!1}),handler:async n=>{let a=process.cwd(),S=readPackage$2(a),C=S.gjsify?.storybook??{},N=$o(a,n.stories??C.stories??`src`),F=n.appId??C.applicationId??deriveAppId(S.name),I=n.title??C.title,H=n.globals??C.globals??`auto`,W=n.runtime??C.runtime??`gjs`,K=W===`node`?`node`:`gjs`,q=ns(a,`node_modules`,`.cache`,`gjsify-storybook`);mkdirSync(q,{recursive:!0});let Y=ns(q,`entry.ts`),X=n.out?$o(a,n.out):ns(q,`storybook.${K}.mjs`),writeEntry=()=>{let n=findStoryFiles(N).sort();return writeFileSync(Y,generateEntry$2(n,F,I)),n.length},te=writeEntry();te===0&&(ke.error(`No *.story.ts files found under ${rs(a,N)||N}`),process.exit(1)),ke.log(`Found ${te} story file(s) under ${rs(a,N)||`.`} (runtime: ${W})`);let{runCli:ne}=await Promise.resolve().then(()=>(kP(),OP)),buildBundle=()=>ne([`build`,Y,`--app`,K,`--globals`,H,`--outfile`,X]),launch=async()=>{if(W===`node`){let{runNodeBundle:n}=await Promise.resolve().then(()=>(vP(),_P));await n(X,[],{exitOnSuccess:!0})}else{let{runGjsBundle:n}=await Promise.resolve().then(()=>(rj(),nj));await n(X,[],{exitOnSuccess:!0})}};if(!n.watch){if(await buildBundle(),n.buildOnly)return;await launch();return}let{watch:re}=await Promise.resolve().then(()=>(Zc(),Jc)),spawnChild=async()=>{if(W===`node`){let{computeNativeEnvForBundle:n}=await Promise.resolve().then(()=>(rj(),nj)),{resolveNodeGi:S,nodeBinary:C}=await Promise.resolve().then(()=>(vP(),_P));if(!S(a))throw Error("Cannot run the storybook on Node: `@gjsify/node-gi` is not installed. Add @gjsify/node-gi as a dependency to run the storybook on Node.");let{env:N}=n(X,a);return spawn(C(),[X],{stdio:`inherit`,env:{...process.env,...N}})}return spawn(`gjs`,[`-m`,X],{stdio:`inherit`})},ie=null,ae=!1,oe=!1,rebuild=async()=>{if(ae){oe=!0;return}ae=!0;try{writeEntry(),ie&&=(ie.kill(),null),await buildBundle(),n.buildOnly||(ie=await spawnChild())}catch(n){ke.error(`[storybook] rebuild failed: ${n.message}`)}finally{ae=!1,oe&&(oe=!1,rebuild())}};await rebuild();let Z=null;re(N,{recursive:!0},()=>{Z&&clearTimeout(Z),Z=setTimeout(()=>void rebuild(),200)}),ke.log(`[storybook] watching ${rs(a,N)||`.`} — press Ctrl+C to stop`)}}});function readPackage$1(n){try{return JSON.parse(readFileSync(ns(n,`package.json`),`utf8`))}catch{return{}}}function deriveStorybookAppId(n){return n?`org.gjsify.storybook.${n.replace(/^@/,``).replace(/[^a-zA-Z0-9]+/g,`.`).replace(/^\.+|\.+$/g,``)}`:`org.gjsify.Storybook`}function deriveBrowserAppId$1(n){return n?`org.gjsify.browser.${n.replace(/^@/,``).replace(/[^a-zA-Z0-9]+/g,`.`).replace(/^\.+|\.+$/g,``)}`:`org.gjsify.Browser`}function hasDep(n,a){return!!(n.dependencies?.[a]||n.devDependencies?.[a])}function generateEntry$1(n,a,S,C){return n===`storybook`?`// Auto-generated by \`gjsify debug\` — do not edit by hand.
|
|
849
851
|
import { runDevtoolsMcp, storybookProfile } from '@gjsify/devtools-mcp';
|
|
850
852
|
|
|
851
853
|
await runDevtoolsMcp(storybookProfile(${JSON.stringify(a)}));
|
|
@@ -865,10 +867,10 @@ await runDevtoolsMcp({
|
|
|
865
867
|
version: ${JSON.stringify(C)},
|
|
866
868
|
busNameBase: ${JSON.stringify(a)},
|
|
867
869
|
});
|
|
868
|
-
`}var
|
|
870
|
+
`}var xP,SP=__esmMin(()=>{Ae(),Zc(),ps(),__name$1(readPackage$1,`readPackage`),__name$1(deriveBrowserAppId$1,`deriveBrowserAppId`),__name$1(generateEntry$1,`generateEntry`),xP={command:`debug`,description:`Launch an MCP bridge for a devtools-enabled gjsify app (org.gjsify.Devtools).`,builder:n=>n.option(`bus-name`,{description:`App DBus base name (default: gjsify.devtools.busNameBase, or the storybook app-id)`,type:`string`}).option(`profile`,{description:`Tool profile: generic | storybook | browser | cdp (default: auto — storybook if @gjsify/storybook is a dep, browser if @gjsify/devtools-browser is, cdp if @gjsify/devtools-cdp is, else generic)`,type:`string`}).option(`globals`,{description:"Value for `gjsify build --globals` (default: auto)",type:`string`}).option(`out`,{description:`Output bundle path (default: node_modules/.cache/gjsify-debug)`,type:`string`}).option(`build-only`,{description:`Build the bridge bundle but do not launch it (for a .mcp.json command pointing at the bundle)`,type:`boolean`,default:!1}),handler:async n=>{let a=process.cwd(),S=readPackage$1(a),C=S.gjsify?.devtools??{},N=n.profile??C.profile??(hasDep(S,`@gjsify/storybook`)?`storybook`:hasDep(S,`@gjsify/devtools-browser`)?`browser`:hasDep(S,`@gjsify/devtools-cdp`)?`cdp`:`generic`),F=n.busName??C.busNameBase??(N===`storybook`?S.gjsify?.storybook?.applicationId??deriveStorybookAppId(S.name):N===`browser`||N===`cdp`?S.gjsify?.browse?.applicationId??deriveBrowserAppId$1(S.name):void 0);F||(ke.error(`gjsify debug: no bus name — set package.json#gjsify.devtools.busNameBase or pass --bus-name <org.example.App>`),process.exit(1));let I=n.globals??C.globals??`auto`,H=S.name?`${S.name}-devtools`:`gjsify-devtools`,W=ns(a,`node_modules`,`.cache`,`gjsify-debug`);mkdirSync(W,{recursive:!0});let K=ns(W,`entry.ts`),q=n.out?$o(a,n.out):ns(W,`bridge.gjs.mjs`);writeFileSync(K,generateEntry$1(N,F,H,`0.8.0`)),ke.error(`[gjsify debug] profile=${N} bus=${F}`);let{runCli:Y}=await Promise.resolve().then(()=>(kP(),OP));if(await Y([`build`,K,`--app`,`gjs`,`--shebang`,`--globals`,I,`--outfile`,q]),n.buildOnly){ke.error(`[gjsify debug] built ${q}`);return}let{runGjsBundle:X}=await Promise.resolve().then(()=>(rj(),nj));await X(q,[],{exitOnSuccess:!0})}}});function readPackage(n){try{return JSON.parse(readFileSync(ns(n,`package.json`),`utf8`))}catch{return{}}}function deriveBrowserAppId(n){return n?`org.gjsify.browser.${n.replace(/^@/,``).replace(/[^a-zA-Z0-9]+/g,`.`).replace(/^\.+|\.+$/g,``)}`:`org.gjsify.Browser`}function generateEntry(n,a,S,C,N){let F=S?`\n title: ${JSON.stringify(S)},`:``,I=a?`\n homeUrl: ${JSON.stringify(a)},`:``,H=C===void 0?``:`\n inspectorPort: ${C},`,W=N?`\n screenshot: ${JSON.stringify(N)},`:``;return`// Auto-generated by \`gjsify browse\` — do not edit by hand.
|
|
869
871
|
import { runBrowserDevtools } from '@gjsify/devtools-browser';
|
|
870
872
|
|
|
871
873
|
await runBrowserDevtools({
|
|
872
874
|
applicationId: ${JSON.stringify(n)},${F}${I}${H}${W}
|
|
873
875
|
});
|
|
874
|
-
`}var
|
|
876
|
+
`}var CP,wP=__esmMin(()=>{Ae(),Zc(),ps(),CP={command:`browse [url]`,description:`Launch the Adwaita web browser, optionally pointed at a URL.`,builder:n=>n.positional(`url`,{description:`Initial URL to load (default: page:welcome)`,type:`string`}).option(`app-id`,{description:`GApplication id (default: gjsify.browse.applicationId or derived from the package name)`,type:`string`}).option(`title`,{description:`Window title`,type:`string`}).option(`globals`,{description:"Value for `gjsify build --globals` (default: auto,dom — WebKit/iframe need DOM globals)",type:`string`}).option(`out`,{description:`Output bundle path (default: node_modules/.cache/gjsify-browse)`,type:`string`}).option(`devtools`,{description:`Enable the MCP devtools control plane (sets GJSIFY_DEVTOOLS=1)`,type:`boolean`,default:!1}).option(`inspector-port`,{description:`Enable WebKit's remote inspector protocol on this port + the Cdp* methods (implies --devtools)`,type:`number`}).option(`screenshot`,{description:`One-shot: load the URL, capture a WebKit screenshot to this path, and exit (CI / quick captures).`,type:`string`}).option(`build-only`,{description:`Build the bundle but do not launch it`,type:`boolean`,default:!1}),handler:async n=>{let a=process.cwd(),S=readPackage(a),C=S.gjsify?.browse??{},N=n.appId??C.applicationId??deriveBrowserAppId(S.name),F=n.title??C.title,I=n.globals??C.globals??`auto,dom`,H=n.url,W=n.inspectorPort??C.inspectorPort,K=n.devtools||W!==void 0,q=ns(a,`node_modules`,`.cache`,`gjsify-browse`);mkdirSync(q,{recursive:!0});let Y=ns(q,`entry.ts`),X=n.out?$o(a,n.out):ns(q,`browse.gjs.mjs`);writeFileSync(Y,generateEntry(N,H,F,W,n.screenshot?$o(a,n.screenshot):void 0)),ke.log(`[gjsify browse] app=${N}${H?` url=${H}`:``}${K?` devtools=1`:``}${W===void 0?``:` inspector-port=${W}`}`);let{runCli:te}=await Promise.resolve().then(()=>(kP(),OP));if(await te([`build`,Y,`--app`,`gjs`,`--globals`,I,`--outfile`,X]),n.buildOnly){ke.log(`[gjsify browse] built ${X}`);return}K&&(process.env.GJSIFY_DEVTOOLS=`1`),W!==void 0&&(process.env.WEBKIT_INSPECTOR_HTTP_SERVER=`127.0.0.1:${W}`);let{runGjsBundle:ne}=await Promise.resolve().then(()=>(rj(),nj));await ne(X,[],{exitOnSuccess:!0})}}}),TP=__esmMin(()=>{ej(),aj(),cj(),uj(),_j(),bj(),Cj(),Mj(),Fj(),Rj(),Vj(),_M(),eN(),aN(),uN(),fN(),gN(),CN(),TN(),MN(),PN(),RN(),VN(),WN(),KN(),JN(),XN(),QN(),iP(),lP(),dP(),gP(),bP(),SP(),wP()});function ensureGjsifyShimOnPath(){if(EP||!isGjs())return;EP=!0;let n=process.env.GJSIFY_SHIM_DIR;if(n&&existsSync(ns(n,`gjsify`))){(process.env.PATH??``).split(ds).includes(n)||(process.env.PATH=n+ds+(process.env.PATH??``));return}let a=fileURLToPath(import.meta.url),S=process.env.GJS_CONSOLE||`gjs`,C=mkdtempSync(ns(tmpdir(),`gjsify-shim-`)),N=ns(C,`gjsify`);writeFileSync(N,`#!/bin/sh\nexec "${S}" -m "${a}" "$@"\n`,{mode:493}),chmodSync(N,493),process.env.GJSIFY_SHIM_DIR=C,process.env.PATH=C+ds+(process.env.PATH??``)}var EP,DP=__esmMin(()=>{Zc(),Wp(),ps(),mn(),zg(),EP=!1}),OP=__exportAll$3({runCli:()=>runCli});function runtimeLabel(){try{let n=globalThis.imports?.system;if(n?.version!==void 0){let a=Number(n.version);return`GJS ${Math.floor(a/1e4)}.${Math.floor(a%1e4/100)}.${a%100} (SpiderMonkey)`}}catch{}return isNode()?`Node.js ${process.version}`:`unknown runtime`}function readBundleVersion(){try{let n=as(fileURLToPath(import.meta.url)),a=JSON.parse(readFileSync(ns(n,`..`,`package.json`),`utf8`));return typeof a.version==`string`?a.version:`unknown`}catch{return`unknown`}}async function runCli(n){ensureGjsifyShimOnPath();let a=Zd(n);await a.scriptName($d).version(readBundleVersion()).strict().wrap(a.terminalWidth()).command(jj.command,jj.description,jj.builder,jj.handler).command(iN.command,iN.description,iN.builder,iN.handler).command($A.command,$A.description,$A.builder,$A.handler).command(ij.command,ij.description,ij.builder,ij.handler).command(sj.command,sj.description,sj.builder,sj.handler).command($M.command,$M.description,$M.builder,$M.handler).command(lj.command,lj.description,lj.builder,lj.handler).command(gj.command,gj.description,gj.builder,gj.handler).command(yj.command,yj.description,yj.builder,yj.handler).command(Sj.command,Sj.description,Sj.builder,Sj.handler).command(Pj.command,Pj.description,Pj.builder,Pj.handler).command(Lj.command,Lj.description,Lj.builder,Lj.handler).command(Bj.command,Bj.description,Bj.builder,Bj.handler).command(gM.command,gM.description,gM.builder,gM.handler).command(lN.command,lN.description,lN.builder,lN.handler).command(dN.command,dN.description,dN.builder,dN.handler).command(mN.command,mN.description,mN.builder,mN.handler).command(SN.command,SN.description,SN.builder,SN.handler).command(wN.command,wN.description,wN.builder,wN.handler).command(jN.command,jN.description,jN.builder,jN.handler).command(NN.command,NN.description,NN.builder,NN.handler).command(LN.command,LN.description,LN.builder,LN.handler).command(BN.command,BN.description,BN.builder,BN.handler).command(UN.command,UN.description,UN.builder,UN.handler).command(GN.command,GN.description,GN.builder,GN.handler).command(tP.command,tP.description,tP.builder,tP.handler).command(qN.command,qN.description,qN.builder,qN.handler).command(YN.command,YN.description,YN.builder,YN.handler).command(ZN.command,ZN.description,ZN.builder,ZN.handler).command(cP.command,cP.description,cP.builder,cP.handler).command(uP.command,uP.description,uP.builder,uP.handler).command(fP.command,fP.description,fP.builder,fP.handler).command(yP.command,yP.description,yP.builder,yP.handler).command(xP.command,xP.description,xP.builder,xP.handler).command(CP.command,CP.description,CP.builder,CP.handler).demandCommand(1).epilogue(`Running on ${runtimeLabel()}`).help().parseAsync()}var kP=__esmMin(()=>{Zc(),ps(),mn(),Qd(),TP(),ef(),zg(),DP()});Ae(),kP();try{await runCli(hideBin(process.argv))}catch(n){ke.error(n instanceof Error?n.message:String(n)),process.env.GJSIFY_DEBUG&&n instanceof Error&&n.stack&&ke.error(n.stack),process.exitCode=1,globalThis.imports?.system?.exit?.(1)}
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
// `gjsify storybook` — discover every *.story.ts in a project, generate a tiny
|
|
2
|
-
// entry that registers them, then build
|
|
2
|
+
// entry that registers them, then build and launch the generic
|
|
3
3
|
// @gjsify/storybook component browser. No per-project storybook app needed.
|
|
4
4
|
//
|
|
5
|
+
// `--runtime gjs` (default) builds `--app gjs` and runs it with `gjs -m`.
|
|
6
|
+
// `--runtime node` builds `--app node` (gi:// → @gjsify/node-gi reverse bridge)
|
|
7
|
+
// and runs it with `node` — the SAME storybook source rendering on Node.js. The
|
|
8
|
+
// node path wires GI_TYPELIB_PATH/LD_LIBRARY_PATH like `gjsify run` (so any
|
|
9
|
+
// native @gjsify bridge a story uses resolves) and requires `@gjsify/node-gi`
|
|
10
|
+
// installed in the project (kept external by the bundler, a native addon).
|
|
11
|
+
//
|
|
5
12
|
// Dispatch is IN-PROCESS (runCli + runGjsBundle), not a re-spawn of the CLI:
|
|
6
13
|
// the showcase-style `spawn(process.execPath, [cliBin, …])` pattern assumes
|
|
7
14
|
// Node, but under the committed GJS bundle `process.execPath` is `gjs` and the
|
|
@@ -82,6 +89,13 @@ export const storybookCommand = {
|
|
|
82
89
|
.option('out', {
|
|
83
90
|
description: 'Output bundle path (default: node_modules/.cache/gjsify-storybook)',
|
|
84
91
|
type: 'string',
|
|
92
|
+
})
|
|
93
|
+
.option('runtime', {
|
|
94
|
+
description: 'Runtime to build for and launch on: gjs (default) or node (via @gjsify/node-gi). ' +
|
|
95
|
+
'node requires @gjsify/node-gi installed in the project.',
|
|
96
|
+
type: 'string',
|
|
97
|
+
choices: ['gjs', 'node'],
|
|
98
|
+
default: 'gjs',
|
|
85
99
|
})
|
|
86
100
|
.option('watch', {
|
|
87
101
|
description: 'Rebuild and relaunch when a story file changes',
|
|
@@ -97,10 +111,16 @@ export const storybookCommand = {
|
|
|
97
111
|
const applicationId = args.appId ?? config.applicationId ?? deriveAppId(pkg.name);
|
|
98
112
|
const title = args.title ?? config.title;
|
|
99
113
|
const globals = args.globals ?? config.globals ?? 'auto';
|
|
114
|
+
const runtime = (args.runtime ?? config.runtime ?? 'gjs');
|
|
115
|
+
// The runtime drives BOTH the build target (`gjsify build --app <app>`)
|
|
116
|
+
// and the launcher: `gjs` builds an `--app gjs` bundle run by `gjs -m`,
|
|
117
|
+
// `node` builds an `--app node` bundle (gi:// → @gjsify/node-gi) run by
|
|
118
|
+
// `node`. Same generated entry + `--globals auto` for both.
|
|
119
|
+
const app = runtime === 'node' ? 'node' : 'gjs';
|
|
100
120
|
const cacheDir = join(cwd, 'node_modules', '.cache', 'gjsify-storybook');
|
|
101
121
|
mkdirSync(cacheDir, { recursive: true });
|
|
102
122
|
const entryPath = join(cacheDir, 'entry.ts');
|
|
103
|
-
const outPath = args.out ? resolve(cwd, args.out) : join(cacheDir,
|
|
123
|
+
const outPath = args.out ? resolve(cwd, args.out) : join(cacheDir, `storybook.${app}.mjs`);
|
|
104
124
|
const writeEntry = () => {
|
|
105
125
|
const files = findStoryFiles(storiesDir).sort();
|
|
106
126
|
writeFileSync(entryPath, generateEntry(files, applicationId, title));
|
|
@@ -111,24 +131,46 @@ export const storybookCommand = {
|
|
|
111
131
|
console.error(`No *.story.ts files found under ${relative(cwd, storiesDir) || storiesDir}`);
|
|
112
132
|
process.exit(1);
|
|
113
133
|
}
|
|
114
|
-
console.log(`Found ${initialCount} story file(s) under ${relative(cwd, storiesDir) || '.'}`);
|
|
134
|
+
console.log(`Found ${initialCount} story file(s) under ${relative(cwd, storiesDir) || '.'} (runtime: ${runtime})`);
|
|
115
135
|
// In-process build — runtime-agnostic (Node uses npm rolldown, GJS uses
|
|
116
136
|
// the @gjsify/rolldown-native facade), no re-spawn of the CLI binary.
|
|
117
137
|
const { runCli } = await import('../cli-app.js');
|
|
118
|
-
const buildBundle = () => runCli(['build', entryPath, '--app',
|
|
138
|
+
const buildBundle = () => runCli(['build', entryPath, '--app', app, '--globals', globals, '--outfile', outPath]);
|
|
139
|
+
const launch = async () => {
|
|
140
|
+
if (runtime === 'node') {
|
|
141
|
+
const { runNodeBundle } = await import('../utils/run-node.js');
|
|
142
|
+
await runNodeBundle(outPath, [], { exitOnSuccess: true });
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
const { runGjsBundle } = await import('../utils/run-gjs.js');
|
|
146
|
+
await runGjsBundle(outPath, [], { exitOnSuccess: true });
|
|
147
|
+
}
|
|
148
|
+
};
|
|
119
149
|
if (!args.watch) {
|
|
120
150
|
await buildBundle();
|
|
121
151
|
if (args.buildOnly)
|
|
122
152
|
return;
|
|
123
|
-
|
|
124
|
-
await runGjsBundle(outPath, [], { exitOnSuccess: true });
|
|
153
|
+
await launch();
|
|
125
154
|
return;
|
|
126
155
|
}
|
|
127
156
|
// Watch mode: rebuild + relaunch on any change under the stories dir.
|
|
128
157
|
// The storybook bundle only needs system Gtk/Adw typelibs at runtime
|
|
129
|
-
// (no @gjsify native bridges), so a plain `gjs -m` child is
|
|
130
|
-
// stays killable for relaunch.
|
|
158
|
+
// (no @gjsify native bridges), so a plain `gjs -m` / `node` child is
|
|
159
|
+
// enough and stays killable for relaunch.
|
|
131
160
|
const { watch } = await import('node:fs');
|
|
161
|
+
const spawnChild = async () => {
|
|
162
|
+
if (runtime === 'node') {
|
|
163
|
+
const { computeNativeEnvForBundle } = await import('../utils/run-gjs.js');
|
|
164
|
+
const { resolveNodeGi, nodeBinary } = await import('../utils/run-node.js');
|
|
165
|
+
if (!resolveNodeGi(cwd)) {
|
|
166
|
+
throw new Error('Cannot run the storybook on Node: `@gjsify/node-gi` is not installed. ' +
|
|
167
|
+
'Add @gjsify/node-gi as a dependency to run the storybook on Node.');
|
|
168
|
+
}
|
|
169
|
+
const { env: nativeEnv } = computeNativeEnvForBundle(outPath, cwd);
|
|
170
|
+
return spawn(nodeBinary(), [outPath], { stdio: 'inherit', env: { ...process.env, ...nativeEnv } });
|
|
171
|
+
}
|
|
172
|
+
return spawn('gjs', ['-m', outPath], { stdio: 'inherit' });
|
|
173
|
+
};
|
|
132
174
|
let child = null;
|
|
133
175
|
let rebuilding = false;
|
|
134
176
|
let pending = false;
|
|
@@ -146,7 +188,7 @@ export const storybookCommand = {
|
|
|
146
188
|
}
|
|
147
189
|
await buildBundle();
|
|
148
190
|
if (!args.buildOnly) {
|
|
149
|
-
child =
|
|
191
|
+
child = await spawnChild();
|
|
150
192
|
}
|
|
151
193
|
}
|
|
152
194
|
catch (err) {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Walk up from `startDir` looking for `<node_modules>/@gjsify/node-gi`. Returns
|
|
3
|
+
* the package directory, or null when it is not installed anywhere on the chain.
|
|
4
|
+
* A plain fs walk (works identically on Node and GJS) — Node's own resolver is
|
|
5
|
+
* not available under the GJS-bundled CLI.
|
|
6
|
+
*/
|
|
7
|
+
export declare function resolveNodeGi(startDir: string): string | null;
|
|
8
|
+
/** Pick the node executable: the current one when on Node, else PATH `node`. */
|
|
9
|
+
export declare function nodeBinary(): string;
|
|
10
|
+
export interface RunNodeBundleOptions {
|
|
11
|
+
/** Exit this process with code 0 once the child succeeds (terminal callers). */
|
|
12
|
+
exitOnSuccess?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Run a `--app node` bundle on Node.js, auto-setting LD_LIBRARY_PATH and
|
|
16
|
+
* GI_TYPELIB_PATH for any installed native gjsify packages (same detection as
|
|
17
|
+
* {@link runGjsBundle}). Verifies `@gjsify/node-gi` is resolvable first and
|
|
18
|
+
* throws a clear, actionable error otherwise.
|
|
19
|
+
*/
|
|
20
|
+
export declare function runNodeBundle(bundlePath: string, extraArgs?: string[], options?: RunNodeBundleOptions): Promise<void>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// Shared utility for running a `--app node` bundle on Node.js with the native
|
|
2
|
+
// typelib env wired the same way `runGjsBundle` does.
|
|
3
|
+
//
|
|
4
|
+
// A `gjsify build --app node` bundle of a `gi://` source runs the GObject stack
|
|
5
|
+
// through `@gjsify/node-gi` (the Axis-5 reverse bridge). Two things have to be
|
|
6
|
+
// true at runtime:
|
|
7
|
+
//
|
|
8
|
+
// 1. `@gjsify/node-gi` must resolve from the project — it is kept EXTERNAL by
|
|
9
|
+
// the bundler (a native addon), so it has to physically exist in the
|
|
10
|
+
// consumer's node_modules. We verify this up front and emit a clear hint
|
|
11
|
+
// instead of letting Node throw `ERR_MODULE_NOT_FOUND` deep in the bundle.
|
|
12
|
+
// 2. `gi://Gtk` / `gi://Adw` etc. must resolve. System typelibs come from the
|
|
13
|
+
// default GI search path, but any `@gjsify/*` Vala bridge a story pulls in
|
|
14
|
+
// ships its typelib in `prebuilds/` — so we reuse the SAME
|
|
15
|
+
// `computeNativeEnvForBundle()` walker `runGjsBundle` uses to prepend
|
|
16
|
+
// `GI_TYPELIB_PATH` / `LD_LIBRARY_PATH`. It is a no-op when no native
|
|
17
|
+
// gjsify packages are present (the storybook's common case).
|
|
18
|
+
//
|
|
19
|
+
// The node binary is `process.execPath` when the CLI itself runs under Node, and
|
|
20
|
+
// the PATH `node` otherwise (under the committed GJS bundle `process.execPath` is
|
|
21
|
+
// `gjs`, which cannot run a `--app node` bundle).
|
|
22
|
+
import { spawn } from 'node:child_process';
|
|
23
|
+
import { existsSync } from 'node:fs';
|
|
24
|
+
import { join, resolve } from 'node:path';
|
|
25
|
+
import { isNode } from '@gjsify/rolldown-plugin-gjsify/runtime';
|
|
26
|
+
import { computeNativeEnvForBundle } from './run-gjs.js';
|
|
27
|
+
/**
|
|
28
|
+
* Walk up from `startDir` looking for `<node_modules>/@gjsify/node-gi`. Returns
|
|
29
|
+
* the package directory, or null when it is not installed anywhere on the chain.
|
|
30
|
+
* A plain fs walk (works identically on Node and GJS) — Node's own resolver is
|
|
31
|
+
* not available under the GJS-bundled CLI.
|
|
32
|
+
*/
|
|
33
|
+
export function resolveNodeGi(startDir) {
|
|
34
|
+
let dir = resolve(startDir);
|
|
35
|
+
while (true) {
|
|
36
|
+
const candidate = join(dir, 'node_modules', '@gjsify', 'node-gi', 'package.json');
|
|
37
|
+
if (existsSync(candidate))
|
|
38
|
+
return join(dir, 'node_modules', '@gjsify', 'node-gi');
|
|
39
|
+
const parent = resolve(dir, '..');
|
|
40
|
+
if (parent === dir)
|
|
41
|
+
return null;
|
|
42
|
+
dir = parent;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** Pick the node executable: the current one when on Node, else PATH `node`. */
|
|
46
|
+
export function nodeBinary() {
|
|
47
|
+
return isNode() && process.execPath ? process.execPath : 'node';
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Run a `--app node` bundle on Node.js, auto-setting LD_LIBRARY_PATH and
|
|
51
|
+
* GI_TYPELIB_PATH for any installed native gjsify packages (same detection as
|
|
52
|
+
* {@link runGjsBundle}). Verifies `@gjsify/node-gi` is resolvable first and
|
|
53
|
+
* throws a clear, actionable error otherwise.
|
|
54
|
+
*/
|
|
55
|
+
export async function runNodeBundle(bundlePath, extraArgs = [], options = {}) {
|
|
56
|
+
const cwd = process.cwd();
|
|
57
|
+
if (!resolveNodeGi(cwd)) {
|
|
58
|
+
throw new Error('Cannot run the storybook on Node: `@gjsify/node-gi` is not installed.\n' +
|
|
59
|
+
'Add @gjsify/node-gi as a dependency to run the storybook on Node, e.g.:\n' +
|
|
60
|
+
' "devDependencies": { "@gjsify/node-gi": "^0.13.0" }');
|
|
61
|
+
}
|
|
62
|
+
const { env: nativeEnv, envPrefix } = computeNativeEnvForBundle(bundlePath, cwd);
|
|
63
|
+
const env = { ...process.env, ...nativeEnv };
|
|
64
|
+
const nodeBin = nodeBinary();
|
|
65
|
+
const nodeArgs = [bundlePath, ...extraArgs];
|
|
66
|
+
// Echo the exact command (stderr, so a child speaking a protocol on stdout
|
|
67
|
+
// stays uncontaminated) so users can reproduce the run without the wrapper.
|
|
68
|
+
const cmd = [nodeBin, ...nodeArgs.map((a) => (a.includes(' ') ? `"${a}"` : a))].join(' ');
|
|
69
|
+
console.error(`$ ${envPrefix ? `${envPrefix} ` : ''}${cmd}`);
|
|
70
|
+
const child = spawn(nodeBin, nodeArgs, { env, stdio: 'inherit' });
|
|
71
|
+
await new Promise((resolvePromise, reject) => {
|
|
72
|
+
child.on('close', (code) => {
|
|
73
|
+
if (code !== 0)
|
|
74
|
+
reject(new Error(`node exited with code ${code}`));
|
|
75
|
+
else
|
|
76
|
+
resolvePromise();
|
|
77
|
+
});
|
|
78
|
+
child.on('error', reject);
|
|
79
|
+
}).catch((err) => {
|
|
80
|
+
console.error(err.message);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
});
|
|
83
|
+
if (options.exitOnSuccess)
|
|
84
|
+
process.exit(0);
|
|
85
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "CLI for Gjsify",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -121,19 +121,19 @@
|
|
|
121
121
|
"cli"
|
|
122
122
|
],
|
|
123
123
|
"dependencies": {
|
|
124
|
-
"@gjsify/buffer": "^0.
|
|
125
|
-
"@gjsify/create-app": "^0.
|
|
126
|
-
"@gjsify/node-globals": "^0.
|
|
127
|
-
"@gjsify/node-polyfills": "^0.
|
|
128
|
-
"@gjsify/npm-registry": "^0.
|
|
129
|
-
"@gjsify/resolve-npm": "^0.
|
|
130
|
-
"@gjsify/rolldown-plugin-gjsify": "^0.
|
|
131
|
-
"@gjsify/rolldown-plugin-pnp": "^0.
|
|
132
|
-
"@gjsify/semver": "^0.
|
|
133
|
-
"@gjsify/tar": "^0.
|
|
134
|
-
"@gjsify/tsc": "^0.
|
|
135
|
-
"@gjsify/web-polyfills": "^0.
|
|
136
|
-
"@gjsify/workspace": "^0.
|
|
124
|
+
"@gjsify/buffer": "^0.14.0",
|
|
125
|
+
"@gjsify/create-app": "^0.14.0",
|
|
126
|
+
"@gjsify/node-globals": "^0.14.0",
|
|
127
|
+
"@gjsify/node-polyfills": "^0.14.0",
|
|
128
|
+
"@gjsify/npm-registry": "^0.14.0",
|
|
129
|
+
"@gjsify/resolve-npm": "^0.14.0",
|
|
130
|
+
"@gjsify/rolldown-plugin-gjsify": "^0.14.0",
|
|
131
|
+
"@gjsify/rolldown-plugin-pnp": "^0.14.0",
|
|
132
|
+
"@gjsify/semver": "^0.14.0",
|
|
133
|
+
"@gjsify/tar": "^0.14.0",
|
|
134
|
+
"@gjsify/tsc": "^0.14.0",
|
|
135
|
+
"@gjsify/web-polyfills": "^0.14.0",
|
|
136
|
+
"@gjsify/workspace": "^0.14.0",
|
|
137
137
|
"cosmiconfig": "^9.0.2",
|
|
138
138
|
"get-tsconfig": "^4.14.0",
|
|
139
139
|
"pkg-types": "^2.3.1",
|
|
@@ -141,13 +141,13 @@
|
|
|
141
141
|
"yargs": "^18.0.0"
|
|
142
142
|
},
|
|
143
143
|
"devDependencies": {
|
|
144
|
-
"@gjsify/unit": "^0.
|
|
144
|
+
"@gjsify/unit": "^0.14.0",
|
|
145
145
|
"@types/yargs": "^17.0.35",
|
|
146
146
|
"typescript": "^6.0.3"
|
|
147
147
|
},
|
|
148
148
|
"peerDependencies": {
|
|
149
|
-
"@gjsify/oxfmt-native": "^0.
|
|
150
|
-
"@gjsify/rolldown-native": "^0.
|
|
149
|
+
"@gjsify/oxfmt-native": "^0.14.0",
|
|
150
|
+
"@gjsify/rolldown-native": "^0.14.0"
|
|
151
151
|
},
|
|
152
152
|
"peerDependenciesMeta": {
|
|
153
153
|
"@gjsify/oxfmt-native": {
|