@gjsify/cli 0.4.27 → 0.4.28

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 CHANGED
@@ -737,7 +737,7 @@ var S=Object.getOwnPropertySymbols,C=Object.prototype.hasOwnProperty,N=Object.pr
737
737
  `+N:``)}function processStubPlugin(n={}){let a=composeBanner((n.captureBundleUrl?`globalThis.__gjsifyBundleUrl??=import.meta.url;`:``)+`if(typeof globalThis.process==="undefined"){const _s=imports.system,_G=imports.gi.GLib;const _h=t=>t?[0,0]:[0,0];_h.bigint=()=>0n;globalThis.process={platform:"linux",arch:"x64",version:"v20.0.0",env:new Proxy({},{get(_,p){return typeof p==="string"?(_G.getenv(p)??undefined):undefined},set(_,p,v){if(typeof p==="string")_G.setenv(p,String(v),true);return true},has(_,p){return typeof p==="string"&&_G.getenv(p)!==null},deleteProperty(_,p){if(typeof p==="string")_G.unsetenv(p);return true},ownKeys(){return _G.listenv()??[]},getOwnPropertyDescriptor(_,p){const v=_G.getenv(p);return v!==null?{value:v,writable:true,enumerable:true,configurable:true}:undefined}}),argv:_s?.programArgs?["gjs",_s.programInvocationName||"",..._s.programArgs]:["gjs"],versions:{},config:{},cwd(){return _G.get_current_dir()||"/"},exit(c){_s.exit(c??0)},stderr:{write(s){printerr(s)}},stdout:{write(s){print(s)}},stdin:null,exitCode:undefined,nextTick(fn,...a){Promise.resolve().then(()=>fn(...a))},hrtime:_h,};}`,n.userBanner??``);return{name:`gjsify-process-stub`,renderChunk:{order:`post`,handler(n,S){return S.isEntry?{code:a+`
738
738
  `+n,map:null}:null}}}}var NT=__commonJSMin(((n,a)=>{let isLinux=()=>process.platform===`linux`,S=null,getReport=()=>{if(!S)if(isLinux()&&process.report){let n=process.report.excludeNetwork;process.report.excludeNetwork=!0,S=process.report.getReport(),process.report.excludeNetwork=n}else S={};return S};a.exports={isLinux,getReport}})),PT=__commonJSMin(((n,a)=>{let S=(As(),__toCommonJS(Ds)),C=2048,readFileSync=n=>{let a=S.openSync(n,`r`),N=Buffer.alloc(C),F=S.readSync(a,N,0,C,0);return S.close(a,()=>{}),N.subarray(0,F)},readFile=n=>new Promise((a,N)=>{S.open(n,`r`,(n,F)=>{if(n)N(n);else{let n=Buffer.alloc(C);S.read(F,n,0,C,0,(C,N)=>{a(n.subarray(0,N)),S.close(F,()=>{})})}})});a.exports={LDD_PATH:`/usr/bin/ldd`,SELF_PATH:`/proc/self/exe`,readFileSync,readFile}})),FT=__commonJSMin(((n,a)=>{let interpreterPath=n=>{if(n.length<64||n.readUInt32BE(0)!==2135247942||n.readUInt8(4)!==2||n.readUInt8(5)!==1)return null;let a=n.readUInt32LE(32),S=n.readUInt16LE(54),C=n.readUInt16LE(56);for(let N=0;N<C;N++){let C=a+N*S;if(n.readUInt32LE(C)===3){let a=n.readUInt32LE(C+8),S=n.readUInt32LE(C+32);return n.subarray(a,a+S).toString().replace(/\0.*$/g,``)}}return null};a.exports={interpreterPath}})),IT=__commonJSMin(((n,a)=>{let S=(Hx(),__toCommonJS(zx)),{isLinux:C,getReport:N}=NT(),{LDD_PATH:F,SELF_PATH:I,readFile:H,readFileSync:W}=PT(),{interpreterPath:K}=FT(),q,Y,X,te=`getconf GNU_LIBC_VERSION 2>&1 || true; ldd --version 2>&1 || true`,ne=``,safeCommand=()=>ne||new Promise(n=>{S.exec(te,(a,S)=>{ne=a?` `:S,n(ne)})}),safeCommandSync=()=>{if(!ne)try{ne=S.execSync(te,{encoding:`utf8`})}catch{ne=` `}return ne},re=`glibc`,ie=/LIBC[a-z0-9 \-).]*?(\d+\.\d+)/i,ae=`musl`,isFileMusl=n=>n.includes(`libc.musl-`)||n.includes(`ld-musl-`),familyFromReport=()=>{let n=N();return n.header&&n.header.glibcVersionRuntime?re:Array.isArray(n.sharedObjects)&&n.sharedObjects.some(isFileMusl)?ae:null},familyFromCommand=n=>{let[a,S]=n.split(/[\r\n]+/);return a&&a.includes(re)?re:S&&S.includes(ae)?ae:null},familyFromInterpreterPath=n=>{if(n){if(n.includes(`/ld-musl-`))return ae;if(n.includes(`/ld-linux-`))return re}return null},getFamilyFromLddContent=n=>(n=n.toString(),n.includes(`musl`)?ae:n.includes(`GNU C Library`)?re:null),familyFromFilesystem=async()=>{if(Y!==void 0)return Y;Y=null;try{Y=getFamilyFromLddContent(await H(F))}catch{}return Y},familyFromFilesystemSync=()=>{if(Y!==void 0)return Y;Y=null;try{Y=getFamilyFromLddContent(W(F))}catch{}return Y},familyFromInterpreter=async()=>{if(q!==void 0)return q;q=null;try{q=familyFromInterpreterPath(K(await H(I)))}catch{}return q},familyFromInterpreterSync=()=>{if(q!==void 0)return q;q=null;try{q=familyFromInterpreterPath(K(W(I)))}catch{}return q},family=async()=>{let n=null;return C()&&(n=await familyFromInterpreter(),n||(n=await familyFromFilesystem(),n||=familyFromReport(),n||=familyFromCommand(await safeCommand()))),n},familySync=()=>{let n=null;return C()&&(n=familyFromInterpreterSync(),n||(n=familyFromFilesystemSync(),n||=familyFromReport(),n||=familyFromCommand(safeCommandSync()))),n},isNonGlibcLinux=async()=>C()&&await family()!==re,isNonGlibcLinuxSync=()=>C()&&familySync()!==re,versionFromFilesystem=async()=>{if(X!==void 0)return X;X=null;try{let n=(await H(F)).match(ie);n&&(X=n[1])}catch{}return X},versionFromFilesystemSync=()=>{if(X!==void 0)return X;X=null;try{let n=W(F).match(ie);n&&(X=n[1])}catch{}return X},versionFromReport=()=>{let n=N();return n.header&&n.header.glibcVersionRuntime?n.header.glibcVersionRuntime:null},versionSuffix=n=>n.trim().split(/\s+/)[1],versionFromCommand=n=>{let[a,S,C]=n.split(/[\r\n]+/);return a&&a.includes(re)?versionSuffix(a):S&&C&&S.includes(ae)?versionSuffix(C):null},version=async()=>{let n=null;return C()&&(n=await versionFromFilesystem(),n||=versionFromReport(),n||=versionFromCommand(await safeCommand())),n},versionSync=()=>{let n=null;return C()&&(n=versionFromFilesystemSync(),n||=versionFromReport(),n||=versionFromCommand(safeCommandSync())),n};a.exports={GLIBC:re,MUSL:ae,family,familySync,isNonGlibcLinux,isNonGlibcLinuxSync,version,versionSync}})),LT=__commonJSMin(((n,a)=>{let S={and_chr:`chrome`,and_ff:`firefox`,ie_mob:`ie`,op_mob:`opera`,and_qq:null,and_uc:null,baidu:null,bb:null,kaios:null,op_mini:null};function browserslistToTargets(n){let a={};for(let C of n){let[n,N]=C.split(` `);if(S[n]===null)continue;let F=parseVersion(N);F!=null&&(a[n]==null||F<a[n])&&(a[n]=F)}return a}function parseVersion(n){let[a,S=0,C=0]=n.split(`-`)[0].split(`.`).map(n=>parseInt(n,10));return isNaN(a)||isNaN(S)||isNaN(C)?null:a<<16|S<<8|C}a.exports=browserslistToTargets})),RT=__commonJSMin(((n,a)=>{function composeVisitors(n){if(n.length===1)return n[0];if(n.some(n=>typeof n==`function`))return a=>composeVisitors(n.map(n=>typeof n==`function`?n(a):n));let a={};return composeSimpleVisitors(a,n,`StyleSheet`),composeSimpleVisitors(a,n,`StyleSheetExit`),composeObjectVisitors(a,n,`Rule`,ruleVisitor,wrapCustomAndUnknownAtRule),composeObjectVisitors(a,n,`RuleExit`,ruleVisitor,wrapCustomAndUnknownAtRule),composeObjectVisitors(a,n,`Declaration`,declarationVisitor,wrapCustomProperty),composeObjectVisitors(a,n,`DeclarationExit`,declarationVisitor,wrapCustomProperty),composeSimpleVisitors(a,n,`Url`),composeSimpleVisitors(a,n,`Color`),composeSimpleVisitors(a,n,`Image`),composeSimpleVisitors(a,n,`ImageExit`),composeSimpleVisitors(a,n,`Length`),composeSimpleVisitors(a,n,`Angle`),composeSimpleVisitors(a,n,`Ratio`),composeSimpleVisitors(a,n,`Resolution`),composeSimpleVisitors(a,n,`Time`),composeSimpleVisitors(a,n,`CustomIdent`),composeSimpleVisitors(a,n,`DashedIdent`),composeArrayFunctions(a,n,`MediaQuery`),composeArrayFunctions(a,n,`MediaQueryExit`),composeSimpleVisitors(a,n,`SupportsCondition`),composeSimpleVisitors(a,n,`SupportsConditionExit`),composeArrayFunctions(a,n,`Selector`),composeTokenVisitors(a,n,`Token`,`token`,!1),composeTokenVisitors(a,n,`Function`,`function`,!1),composeTokenVisitors(a,n,`FunctionExit`,`function`,!0),composeTokenVisitors(a,n,`Variable`,`var`,!1),composeTokenVisitors(a,n,`VariableExit`,`var`,!0),composeTokenVisitors(a,n,`EnvironmentVariable`,`env`,!1),composeTokenVisitors(a,n,`EnvironmentVariableExit`,`env`,!0),a}a.exports=composeVisitors;function wrapCustomAndUnknownAtRule(n,a){return n===`unknown`?(n=>a({type:`unknown`,value:n})):n===`custom`?(n=>a({type:`custom`,value:n})):a}function wrapCustomProperty(n,a){return n===`custom`?(n=>a({property:`custom`,value:n})):a}function ruleVisitor(n,a){if(typeof n==`object`){if(a.type===`unknown`){let S=n.unknown;return typeof S==`object`&&(S=S[a.value.name]),S?.(a.value)}if(a.type===`custom`){let S=n.custom;return typeof S==`object`&&(S=S[a.value.name]),S?.(a.value)}return n[a.type]?.(a)}return n?.(a)}function declarationVisitor(n,a){if(typeof n==`object`){let S=a.property;if(a.property===`unparsed`)S=a.value.propertyId.property;else if(a.property===`custom`){let S=n.custom;return typeof S==`object`&&(S=S[a.value.name]),S?.(a.value)}return n[S]?.(a)}return n?.(a)}function extractObjectsOrFunctions(n,a){let S=[],C=!1,N=new Set;for(let F of n){let n=F[a];if(n){if(typeof n==`function`)C=!0;else for(let a in n)N.add(a);S.push(n)}}return[S,C,N]}function composeObjectVisitors(n,a,S,C,N){let[F,I,H]=extractObjectsOrFunctions(a,S);if(F.length===0)return;if(F.length===1){n[S]=F[0];return}let W=createArrayVisitor(a,(n,a)=>C(n[S],a));if(I)n[S]=W;else{let a={};for(let n of H)a[n]=N(n,W);n[S]=a}}function composeTokenVisitors(n,a,S,C,N){let[F,I,H]=extractObjectsOrFunctions(a,S);if(F.length===0)return;if(F.length===1){n[S]=F[0];return}let W=createTokenVisitor(a,C,N);if(I)n[S]=W;else{let a={};for(let n of H)a[n]=W;n[S]=a}}function createTokenVisitor(n,a,S){let C=createArrayVisitor(n,(n,a)=>{let C;switch(a.type){case`token`:C=n.Token,typeof C==`object`&&(C=C[a.value.type]);break;case`function`:C=S?n.FunctionExit:n.Function,typeof C==`object`&&(C=C[a.value.name]);break;case`var`:C=S?n.VariableExit:n.Variable;break;case`env`:if(C=S?n.EnvironmentVariableExit:n.EnvironmentVariable,typeof C==`object`){let n;switch(a.value.name.type){case`ua`:case`unknown`:n=a.value.name.value;break;case`custom`:n=a.value.name.ident;break}C=C[n]}break;case`color`:C=n.Color;break;case`url`:C=n.Url;break;case`length`:C=n.Length;break;case`angle`:C=n.Angle;break;case`time`:C=n.Time;break;case`resolution`:C=n.Resolution;break;case`dashed-ident`:C=n.DashedIdent;break}if(!C)return;let N=C(a.value);switch(a.type){case`color`:case`url`:case`length`:case`angle`:case`time`:case`resolution`:case`dashed-ident`:Array.isArray(N)?N=N.map(n=>({type:a.type,value:n})):N&&={type:a.type,value:N};break}return N});return n=>C({type:a,value:n})}function extractFunctions(n,a){let S=[];for(let C of n){let n=C[a];n&&S.push(n)}return S}function composeSimpleVisitors(n,a,S){let C=extractFunctions(a,S);if(C.length!==0){if(C.length===1){n[S]=C[0];return}n[S]=n=>{let a=!1;for(let S of C){let C=S(n);C&&(n=C,a=!0)}return a?n:void 0}}}function composeArrayFunctions(n,a,S){let C=extractFunctions(a,S);if(C.length!==0){if(C.length===1){n[S]=C[0];return}n[S]=createArrayVisitor(C,(n,a)=>n(a))}}function createArrayVisitor(n,a){let S=new Bitset(n.length);return C=>{let N=[C],F=!1;S.clear();for(let C=0;C<N.length;C++)for(let I=0;I<n.length&&C<N.length;){if(S.get(I)){I++;continue}let H=N[C],W=n[I],K=a(W,H);Array.isArray(K)?(K.length===0?N.splice(C,1):K.length===1?N[C]=K[0]:N.splice(C,1,...K),F=!0,S.set(I),I=0):K?(N[C]=K,F=!0,S.set(I),I=0):I++}if(F)return N.length===1?N[0]:N}}var Bitset=class{constructor(n=32){this.bits=0,this.more=n>32?new Uint32Array(Math.ceil((n-32)/32)):null}get(n){if(n>=32&&this.more){let a=Math.floor((n-32)/32),S=n%32;return!!(this.more[a]&1<<S)}else return!!(this.bits&1<<n)}set(n){if(n>=32&&this.more){let a=Math.floor((n-32)/32),S=n%32;this.more[a]|=1<<S}else this.bits|=1<<n}clear(){this.bits=0,this.more&&this.more.fill(0)}}})),zT=__commonJSMin((n=>{n.Features={Nesting:1,NotSelectorList:2,DirSelector:4,LangSelectorList:8,IsSelector:16,TextDecorationThicknessPercent:32,MediaIntervalSyntax:64,MediaRangeSyntax:128,CustomMediaQueries:256,ClampFunction:512,ColorFunction:1024,OklabColors:2048,LabColors:4096,P3Colors:8192,HexAlphaColors:16384,SpaceSeparatedColorNotation:32768,FontFamilySystemUi:65536,DoublePositionGradients:131072,VendorPrefixes:262144,LogicalProperties:524288,LightDark:1048576,Selectors:31,MediaQueries:448,Colors:1113088}})),BT=__commonJSMin(((n,a)=>{let S=[process.platform,process.arch];if(process.platform===`linux`){let{MUSL:n,familySync:a}=IT();a()===n?S.push(`musl`):process.arch===`arm`?S.push(`gnueabihf`):S.push(`gnu`)}else process.platform===`win32`&&S.push(`msvc`);let C;try{C=K(`lightningcss-${S.join(`-`)}`)}catch{C=K(`../lightningcss.${S.join(`-`)}.node`)}a.exports.transform=wrap(C.transform),a.exports.transformStyleAttribute=wrap(C.transformStyleAttribute),a.exports.bundle=wrap(C.bundle),a.exports.bundleAsync=wrap(C.bundleAsync),a.exports.browserslistToTargets=LT(),a.exports.composeVisitors=RT(),a.exports.Features=zT().Features;function wrap(n){return a=>{if(typeof a.visitor==`function`){let S=[];a.visitor=a.visitor({addDependency(n){S.push(n)}});let C=n(a);return C instanceof Promise?C=C.then(n=>(S.length&&(n.dependencies??=[],n.dependencies.push(...S)),n)):S.length&&(C.dependencies??=[],C.dependencies.push(...S)),C}else return n(a)}}})),VT=__exportAll$3({Features:()=>YT,browserslistToTargets:()=>qT,bundle:()=>GT,bundleAsync:()=>KT,composeVisitors:()=>JT,transform:()=>UT,transformStyleAttribute:()=>WT}),HT,UT,WT,GT,KT,qT,JT,YT,XT=__esmMin(()=>{HT=__toESM(BT(),1),{transform:UT,transformStyleAttribute:WT,bundle:GT,bundleAsync:KT,browserslistToTargets:qT,composeVisitors:JT,Features:YT}=HT.default});ss(),zs(),Ho(),rn();let ZT=null;async function pickBundler(){let n=globalThis.process?.env?.GJSIFY_CSS_BACKEND;if(n===`npm`)return loadNpmBundler();if(n===`native`){let n=await tryLoadNativeBundler();if(!n)throw Error(`GJSIFY_CSS_BACKEND=native but @gjsify/lightningcss-native is not loadable`);return n}return await tryLoadNativeBundler()??loadNpmBundler()}async function tryLoadNativeBundler(){if(globalThis.imports?.gi===void 0)return null;try{let n=await import(`@gjsify/lightningcss-native`);return n.hasNativeLightningcss()?async(a,S)=>{let C=targetsToBrowserslist(S);return n.bundle({filename:a,targets:C,minify:!1,sourceMap:!1,errorRecovery:!0})}:null}catch{return null}}async function loadNpmBundler(){let{bundleAsync:n}=await Promise.resolve().then(()=>(XT(),VT));return async(a,S)=>({code:(await n({filename:a,targets:S,minify:!1,errorRecovery:!0,resolver:QT})).code})}const QT={resolve(n,a){return Ao(n)?n:n.startsWith(`./`)||n.startsWith(`../`)?Oo(Po(a),n):createRequire(pathToFileURL(a).href).resolve(n)}};function targetsToBrowserslist(n){if(!n)return;let a=[];for(let[S,C]of Object.entries(n)){if(typeof C!=`number`)continue;let n=C>>>16&255;if(n===0)continue;let N=S===`ios_saf`?`ios`:S;a.push(`${N} >= ${n}`)}return a.length?a.join(`, `):void 0}function cssAsStringPlugin(n={}){let{targets:a,bundle:S=!0}=n;return{name:`gjsify-css-as-string`,load:{filter:{id:/\.css$/},async handler(n){let C=S?new TextDecoder(`utf-8`).decode(await loadAndBundleCss(n,a)):await readFile$1(n,`utf8`);return{code:`export default ${JSON.stringify(C)};`,moduleType:`js`}}}}}async function loadAndBundleCss(n,a){ZT||=pickBundler();let{code:S}=await(await ZT)(n,a);return S}const $T=/^#![^\n]*\n/;function inputShebangStripPlugin(){return{name:`gjsify-input-shebang-strip`,transform:{order:`pre`,handler(n){return n.startsWith(`#!`)?{code:n.replace($T,``),map:null}:null}}}}function shebangPlugin(n={}){if(!n.enabled)return null;let a=n.line??`#!/usr/bin/env -S gjs -m`;return{name:`gjsify-shebang`,renderChunk:{order:`post`,handler(n,S){return!S.isEntry||n.startsWith(`#!`)?null:{code:a+`
739
739
  `+n,map:null}}}}}function expandEnvTemplate(n,a=process.env){return n.replace(/\$\{env:([A-Za-z_][A-Za-z0-9_]*)(?::-([^}]*))?\}/g,(n,S,C)=>{let N=a[S];return N!==void 0&&N!==``?N:C??``})}function resolveShebangLine(n,a=`#!/usr/bin/env -S gjs -m`){if(n===void 0||n===!1)return null;if(n===!0)return a;let S=expandEnvTemplate(n);return S.trim()?S.startsWith(`#!`)?S:`#!`+S:null}rn(),Ho();const eE=Po(fileURLToPath(import.meta.url));function resolveConsoleShim(){let n=Oo(eE,`../shims/console-gjs.js`),a=null;try{a=(As(),__toCommonJS(Ds))}catch{return n}if(a.existsSync(n))return n;try{return(zs(),__toCommonJS(Fs)).createRequire(import.meta.url).resolve(`@gjsify/rolldown-plugin-gjsify/shims/console-gjs`)}catch{return n}}const setupForGjs=async n=>{let a=[`cairo`,`gettext`,`system`,...n.userExternal??[]],external=n=>!!(n.startsWith(`gi://`)||a.includes(n)),S=n.pluginOptions.format??`esm`,C=n.pluginOptions.exclude??[],N=await globToEntryPoints(n.input,C),F=Oo(eE,`../shims/unicorn-magic.js`),I={...getAliasesForGjs({external}),"unicorn-magic":F,...n.pluginOptions.aliases??{},...n.userAliases??{}},H=n.pluginOptions.consoleShim===!1?null:resolveConsoleShim(),W=[];n.pluginOptions.autoGlobalsInject&&W.push(n.pluginOptions.autoGlobalsInject);let K=wrapInputWithSideEffects(N,W),q={input:K.input,platform:`neutral`,external,resolve:{mainFields:S===`esm`?[`browser`,`module`,`main`]:[`browser`,`main`,`module`],conditionNames:S===`esm`?[`browser`,`import`]:[`browser`,`require`,`import`]},transform:{target:`firefox140`,define:{global:`globalThis`,window:`globalThis`,"process.env.READABLE_STREAM":`"disable"`},...H?{inject:{console:[H,`console`]}}:{}},output:{...n.output,format:S,sourcemap:!1,codeSplitting:!1},treeshake:!0},Y=getBundleDirFromOutput(n.output);return{options:q,plugins:[...K.plugin?[K.plugin]:[],inputShebangStripPlugin(),aliasPlugin({entries:{"random-access-file":`random-access-file/index.js`,...flattenAliases$3(I)}}),blueprintPlugin(),deepkitPlugin({reflection:n.pluginOptions.reflection}),cssAsStringPlugin({targets:{firefox:60<<16}}),nodeModulesPathRewritePlugin({bundleDir:Y,runtimeResolve:S===`esm`}),processStubPlugin({userBanner:n.userBanner,captureBundleUrl:S===`esm`}),(()=>{let a=resolveShebangLine(n.shebang);return shebangPlugin({enabled:a!==null,line:a??void 0})})()]}};function wrapInputWithSideEffects(n,a){if(a.length===0||n===void 0)return{input:n,plugin:null};let S=new Map,C=`\0gjsify-entry:`;function wrap(n){let a=C+n;return S.set(a,n),a}let N;if(typeof n==`string`)N=wrap(n);else if(Array.isArray(n))N=n.map(wrap);else{let a={};for(let[S,C]of Object.entries(n))a[S]=wrap(C);N=a}let F=a.map(n=>`import ${JSON.stringify(n)};`).join(`
740
- `),I=new Set;return{input:N,plugin:{name:`gjsify-virtual-entry`,async resolveId(n,a){return n.startsWith(C)?n:I.has(n)?{id:n,moduleSideEffects:`no-treeshake`}:null},async load(n){if(!n.startsWith(C))return null;let a=S.get(n);if(!a)return null;let N=(await this.resolve(a,void 0,{skipSelf:!0}))?.id??a;return I.add(N),{code:`${F}\nimport ${JSON.stringify(N)};\nexport * from ${JSON.stringify(N)};\n`,moduleSideEffects:`no-treeshake`}}}}}function flattenAliases$3(n){let a={};for(let[S,C]of Object.entries(n))C&&(a[S]=C);return a}__name$1(flattenAliases$3,`flattenAliases`);const setupForNode=async n=>{let a=n.userExternal??[],S=[...rg,`node-datachannel`,...a],external=n=>!!(n.startsWith(`gi://`)||n.startsWith(`@girs/`)||S.includes(n)),C=n.pluginOptions.format??`esm`,N=n.pluginOptions.exclude??[],F=await globToEntryPoints(n.input,N),I={...getAliasesForNode({external}),...n.pluginOptions.aliases??{},...n.userAliases??{}},H=getBundleDirFromOutput(n.output);return{options:{input:F,platform:`node`,external,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:[aliasPlugin({entries:flattenAliases$2(I)}),deepkitPlugin({reflection:n.pluginOptions.reflection}),cssAsStringPlugin(),nodeModulesPathRewritePlugin({bundleDir:H})]}};function flattenAliases$2(n){let a={};for(let[S,C]of Object.entries(n))C&&(a[S]=C);return a}__name$1(flattenAliases$2,`flattenAliases`);const tE=`\0gjsify-empty-gjs-import`;function gjsImportsEmptyPlugin(){return{name:`gjsify-gjs-imports-empty`,resolveId:{order:`pre`,filter:{id:/^(@girs\/|gi:\/\/)/},handler(n){return{id:tE}}},load(n){return n===tE?{code:`export {}; export default {};`,moduleSideEffects:!1}:null}}}const setupForBrowser=async n=>{let a=[...n.userExternal??[]],S=n.pluginOptions.exclude??[],C=await globToEntryPoints(n.input,S),N={process:`@gjsify/empty`,"node:process":`@gjsify/empty`,assert:`@gjsify/assert`,"node:assert":`@gjsify/assert`,...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$1(N)}),blueprintPlugin(),deepkitPlugin({reflection:n.pluginOptions.reflection}),cssAsStringPlugin()]}};function flattenAliases$1(n){let a={};for(let[S,C]of Object.entries(n))C&&(a[S]=C);return a}__name$1(flattenAliases$1,`flattenAliases`);const 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??{}},external=n=>!(n.startsWith(`./`)||n.startsWith(`../`)||n.startsWith(`/`));return{options:{input:C,platform:`neutral`,external,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)}),cssAsStringPlugin()]}};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}ss();function textLoaderPlugin(n={}){let a=Object.entries(n.loaders??{}).filter(([,n])=>n===`text`).map(([n])=>n);if(a.length===0)return null;let S=a.map(n=>n.replace(/^\./,``).replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)),C=RegExp(`\\.(?:${S.join(`|`)})$`);return{name:`gjsify-text-loader`,async load(n){if(!C.test(n))return null;let a=await readFile$1(n,`utf8`);return{code:`export default ${JSON.stringify(a)};`,moduleType:`js`}}}}const 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});default:throw TypeError(`Unknown app platform: `+S)}};zs(),Ho(),rn();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){let S=createRequire(jo(a,`package.json`)),C=[];for(let N of n){if(!isPluginByName(N)){C.push(N);continue}let n;try{n=S.resolve(N.name)}catch(n){throw Error(`gjsify config: failed to resolve plugin "${N.name}" from ${a}. Add it to your project's dependencies, or pass a Plugin object directly. (${n.message})`)}let F=await import(pathToFileURL(n).href),I=N.export??`default`,H=F[I];if(typeof H!=`function`){let n=Object.keys(F).filter(n=>typeof F[n]==`function`);throw Error(`gjsify config: plugin "${N.name}" has no function export "${I}". Available function exports: ${n.length?n.join(`, `):`(none)`}.`)}let W=await H(N.options);if(W==null)throw Error(`gjsify config: plugin "${N.name}" factory returned ${W}. Check the plugin's signature — it should return a Rolldown/Vite plugin object.`);C.push(W)}return C}Ie();const 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()}},nE=Ey;function setsEqual(n,a){if(n.size!==a.size)return!1;for(let S of n)if(!a.has(S))return!1;return!0}async function applyExcludeGlobals(n,a,S,C){if(!C?.length)return{detected:n,injectPath:a};for(let a of C)n.delete(a);let N=detectedToRegisterPaths(n);for(let n of S)N.add(n);return{detected:n,injectPath:N.size>0?await writeRegisterInjectFile(N)??void 0:void 0}}function detectedToRegisterPaths(n){let a=new Set;for(let S of n){let n=nE[S];n&&a.add(n)}return a}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=new Set,K;I.size>0&&(K=await writeRegisterInjectFile(I)??void 0);let q=(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 Y=1;Y<=5;Y++){let X=await S({...a,autoGlobalsInject:K}),te,ne;isFullConfig(X)?(ne=X.options,te=X.plugins):te=X;let re=K?appendInjectAsEntry(n.input,K):n.input,ie=n.resolve??ne?.resolve,ae=n.external??ne?.external,oe=n.transform??ne?.transform,Z=ne?.treeshake,se=Array.isArray(te)?te:[te],ce=await F({rolldownInput:{input:re,external:ae,resolve:ie,transform:oe,plugins:[...q,...se],logLevel:`silent`,...Z===void 0?{}:{treeshake:Z}},format:n.format??`esm`});if(ce.length===0)return{detected:new Set,injectPath:K};let le=new Set;for(let n=0;n<ce.length;n++){let a=ce[n]??``;try{for(let n of detectFreeGlobals(a))le.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(()=>(As(),Ds))).writeFileSync(S,a),Fe.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)le.delete(n);if(setsEqual(W,le)){if(C){let n=[...W].sort(),a=I.size>0?` (+ ${I.size} extra register module(s))`:``;Fe.debug(`[gjsify] --globals auto: converged after ${Y-1} iteration(s), ${W.size} global(s)${n.length?`: `+n.join(`, `):``}${a}`)}return applyExcludeGlobals(W,K,I,N.excludeGlobals)}W=le;let ue=detectedToRegisterPaths(W);for(let n of I)ue.add(n);if(ue.size===0)return{detected:W,injectPath:void 0};if(K=await writeRegisterInjectFile(ue)??void 0,C){let n=[...W].sort();Fe.debug(`[gjsify] --globals auto: iteration ${Y}, ${W.size} global(s)${n.length?`: `+n.join(`, `):``}`)}}return C&&Fe.debug(`[gjsify] --globals auto: hit max iterations (5), using last detected set`),applyExcludeGlobals(W,K,I,N.excludeGlobals)}function appendInjectAsEntry(n,a){return n===void 0?[a]:typeof n==`string`?[n,a]:Array.isArray(n)?[...n,a]:{...n,__gjsify_inject:a}}zs(),rn(),Ho(),As(),ss();function findPnpRoot(n){let a=n;for(;;){if(existsSync(jo(a,`.pnp.cjs`)))return a;let n=Po(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(!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`}Ie();let rE=!1;function normalizeBundlerOptions(n){let a=n.bundler??{};if(!n.esbuild)return a;rE||(rE=!0,Fe.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 S=legacyEsbuildToRolldown(n.esbuild),C={...S,...a};return(S.output||a.output)&&(C.output={...S.output??{},...a.output??{}}),(S.transform||a.transform)&&(C.transform={...S.transform??{},...a.transform??{}},(S.transform?.define||a.transform?.define)&&(C.transform.define={...S.transform?.define??{},...a.transform?.define??{}})),(S.resolve||a.resolve)&&(C.resolve={...S.resolve??{},...a.resolve??{}}),C}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}Ie(),Ho(),ss();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})}var BuildAction=class{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?Po(F.module):void 0,W=F.main?Po(F.main):void 0,K=F.module?Io(F.module):`.js`,q=F.main?Io(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?Io(a):`.js`,W=I.output?.dir??(a?Po(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&&Fe.debug(`[gjsify] globals: injected ${C.size} register module(s) from --globals ${a}`),N??void 0}async applyShebang(n,a,S){if(!a){S&&Fe.warn(`[gjsify] --shebang skipped: no single outfile (use --outfile for executables)`);return}let C=n===`node`?`#!/usr/bin/env node`:`#!/usr/bin/env -S gjs -m`,N=resolveShebangLine(this.configData.shebang,C)??C,F=await readFile$1(a,`utf-8`);F.startsWith(`#!`)?S&&Fe.debug(`[gjsify] --shebang skipped: ${a} already starts with a shebang`):await writeFile$1(a,N+`
740
+ `),I=new Set;return{input:N,plugin:{name:`gjsify-virtual-entry`,async resolveId(n,a){return n.startsWith(C)?n:I.has(n)?{id:n,moduleSideEffects:`no-treeshake`}:null},async load(n){if(!n.startsWith(C))return null;let a=S.get(n);if(!a)return null;let N=(await this.resolve(a,void 0,{skipSelf:!0}))?.id??a;return I.add(N),{code:`${F}\nimport ${JSON.stringify(N)};\nexport * from ${JSON.stringify(N)};\n`,moduleSideEffects:`no-treeshake`}}}}}function flattenAliases$3(n){let a={};for(let[S,C]of Object.entries(n))C&&(a[S]=C);return a}__name$1(flattenAliases$3,`flattenAliases`);const setupForNode=async n=>{let a=n.userExternal??[],S=[...rg,`node-datachannel`,...a],external=n=>!!(n.startsWith(`gi://`)||n.startsWith(`@girs/`)||S.includes(n)),C=n.pluginOptions.format??`esm`,N=n.pluginOptions.exclude??[],F=await globToEntryPoints(n.input,N),I={...getAliasesForNode({external}),...n.pluginOptions.aliases??{},...n.userAliases??{}},H=getBundleDirFromOutput(n.output);return{options:{input:F,platform:`node`,external,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:[aliasPlugin({entries:flattenAliases$2(I)}),deepkitPlugin({reflection:n.pluginOptions.reflection}),cssAsStringPlugin(),nodeModulesPathRewritePlugin({bundleDir:H})]}};function flattenAliases$2(n){let a={};for(let[S,C]of Object.entries(n))C&&(a[S]=C);return a}__name$1(flattenAliases$2,`flattenAliases`);const tE=`\0gjsify-empty-gjs-import`;function gjsImportsEmptyPlugin(){return{name:`gjsify-gjs-imports-empty`,resolveId:{order:`pre`,filter:{id:/^(@girs\/|gi:\/\/)/},handler(n){return/^(@girs\/|gi:\/\/)/.test(n)?{id:tE}:null}},load(n){return n===tE?{code:`export {}; export default {};`,moduleSideEffects:!1}:null}}}const setupForBrowser=async n=>{let a=[...n.userExternal??[]],S=n.pluginOptions.exclude??[],C=await globToEntryPoints(n.input,S),N={process:`@gjsify/empty`,"node:process":`@gjsify/empty`,assert:`@gjsify/assert`,"node:assert":`@gjsify/assert`,...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$1(N)}),blueprintPlugin(),deepkitPlugin({reflection:n.pluginOptions.reflection}),cssAsStringPlugin()]}};function flattenAliases$1(n){let a={};for(let[S,C]of Object.entries(n))C&&(a[S]=C);return a}__name$1(flattenAliases$1,`flattenAliases`);const 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??{}},external=n=>!(n.startsWith(`./`)||n.startsWith(`../`)||n.startsWith(`/`));return{options:{input:C,platform:`neutral`,external,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)}),cssAsStringPlugin()]}};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}ss();function textLoaderPlugin(n={}){let a=Object.entries(n.loaders??{}).filter(([,n])=>n===`text`).map(([n])=>n);if(a.length===0)return null;let S=a.map(n=>n.replace(/^\./,``).replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)),C=RegExp(`\\.(?:${S.join(`|`)})$`);return{name:`gjsify-text-loader`,async load(n){if(!C.test(n))return null;let a=await readFile$1(n,`utf8`);return{code:`export default ${JSON.stringify(a)};`,moduleType:`js`}}}}const 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});default:throw TypeError(`Unknown app platform: `+S)}};zs(),Ho(),rn();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){let S=createRequire(jo(a,`package.json`)),C=[];for(let N of n){if(!isPluginByName(N)){C.push(N);continue}let n;try{n=S.resolve(N.name)}catch(n){throw Error(`gjsify config: failed to resolve plugin "${N.name}" from ${a}. Add it to your project's dependencies, or pass a Plugin object directly. (${n.message})`)}let F=await import(pathToFileURL(n).href),I=N.export??`default`,H=F[I];if(typeof H!=`function`){let n=Object.keys(F).filter(n=>typeof F[n]==`function`);throw Error(`gjsify config: plugin "${N.name}" has no function export "${I}". Available function exports: ${n.length?n.join(`, `):`(none)`}.`)}let W=await H(N.options);if(W==null)throw Error(`gjsify config: plugin "${N.name}" factory returned ${W}. Check the plugin's signature — it should return a Rolldown/Vite plugin object.`);C.push(W)}return C}Ie();const 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()}},nE=Ey;function setsEqual(n,a){if(n.size!==a.size)return!1;for(let S of n)if(!a.has(S))return!1;return!0}async function applyExcludeGlobals(n,a,S,C){if(!C?.length)return{detected:n,injectPath:a};for(let a of C)n.delete(a);let N=detectedToRegisterPaths(n);for(let n of S)N.add(n);return{detected:n,injectPath:N.size>0?await writeRegisterInjectFile(N)??void 0:void 0}}function detectedToRegisterPaths(n){let a=new Set;for(let S of n){let n=nE[S];n&&a.add(n)}return a}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=new Set,K;I.size>0&&(K=await writeRegisterInjectFile(I)??void 0);let q=(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 Y=1;Y<=5;Y++){let X=await S({...a,autoGlobalsInject:K}),te,ne;isFullConfig(X)?(ne=X.options,te=X.plugins):te=X;let re=K?appendInjectAsEntry(n.input,K):n.input,ie=n.resolve??ne?.resolve,ae=n.external??ne?.external,oe=n.transform??ne?.transform,Z=ne?.treeshake,se=Array.isArray(te)?te:[te],ce=await F({rolldownInput:{input:re,external:ae,resolve:ie,transform:oe,plugins:[...q,...se],logLevel:`silent`,...Z===void 0?{}:{treeshake:Z}},format:n.format??`esm`});if(ce.length===0)return{detected:new Set,injectPath:K};let le=new Set;for(let n=0;n<ce.length;n++){let a=ce[n]??``;try{for(let n of detectFreeGlobals(a))le.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(()=>(As(),Ds))).writeFileSync(S,a),Fe.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)le.delete(n);if(setsEqual(W,le)){if(C){let n=[...W].sort(),a=I.size>0?` (+ ${I.size} extra register module(s))`:``;Fe.debug(`[gjsify] --globals auto: converged after ${Y-1} iteration(s), ${W.size} global(s)${n.length?`: `+n.join(`, `):``}${a}`)}return applyExcludeGlobals(W,K,I,N.excludeGlobals)}W=le;let ue=detectedToRegisterPaths(W);for(let n of I)ue.add(n);if(ue.size===0)return{detected:W,injectPath:void 0};if(K=await writeRegisterInjectFile(ue)??void 0,C){let n=[...W].sort();Fe.debug(`[gjsify] --globals auto: iteration ${Y}, ${W.size} global(s)${n.length?`: `+n.join(`, `):``}`)}}return C&&Fe.debug(`[gjsify] --globals auto: hit max iterations (5), using last detected set`),applyExcludeGlobals(W,K,I,N.excludeGlobals)}function appendInjectAsEntry(n,a){return n===void 0?[a]:typeof n==`string`?[n,a]:Array.isArray(n)?[...n,a]:{...n,__gjsify_inject:a}}zs(),rn(),Ho(),As(),ss();function findPnpRoot(n){let a=n;for(;;){if(existsSync(jo(a,`.pnp.cjs`)))return a;let n=Po(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(!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`}Ie();let rE=!1;function normalizeBundlerOptions(n){let a=n.bundler??{};if(!n.esbuild)return a;rE||(rE=!0,Fe.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 S=legacyEsbuildToRolldown(n.esbuild),C={...S,...a};return(S.output||a.output)&&(C.output={...S.output??{},...a.output??{}}),(S.transform||a.transform)&&(C.transform={...S.transform??{},...a.transform??{}},(S.transform?.define||a.transform?.define)&&(C.transform.define={...S.transform?.define??{},...a.transform?.define??{}})),(S.resolve||a.resolve)&&(C.resolve={...S.resolve??{},...a.resolve??{}}),C}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}Ie(),Ho(),ss();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})}var BuildAction=class{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?Po(F.module):void 0,W=F.main?Po(F.main):void 0,K=F.module?Io(F.module):`.js`,q=F.main?Io(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?Io(a):`.js`,W=I.output?.dir??(a?Po(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&&Fe.debug(`[gjsify] globals: injected ${C.size} register module(s) from --globals ${a}`),N??void 0}async applyShebang(n,a,S){if(!a){S&&Fe.warn(`[gjsify] --shebang skipped: no single outfile (use --outfile for executables)`);return}let C=n===`node`?`#!/usr/bin/env node`:`#!/usr/bin/env -S gjs -m`,N=resolveShebangLine(this.configData.shebang,C)??C,F=await readFile$1(a,`utf-8`);F.startsWith(`#!`)?S&&Fe.debug(`[gjsify] --shebang skipped: ${a} already starts with a shebang`):await writeFile$1(a,N+`
741
741
  `+F),await chmod$1(a,493),S&&Fe.debug(`[gjsify] --shebang: wrote ${N} + chmod 0o755 to ${a}`)}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}:{}},{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());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},bundleToChunks);ae.autoGlobalsInject=n}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,Fe.log(`
742
742
  [gjsify build --watch] stopping watcher…`);try{await N.close()}catch(n){Fe.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&&Fe.log(`[gjsify build --watch] rebuild start`);break;case`BUNDLE_START`:Fe.log(`[gjsify build --watch] building…`);break;case`BUNDLE_END`:Fe.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`:Fe.log(`[gjsify build --watch] waiting for changes…`);break;case`ERROR`:Fe.error(`[gjsify build --watch] build failed:`,n.error?.message??n.error),C&&n.error?.stack&&Fe.error(n.error.stack);try{await n.result.close()}catch{}break}}),C&&N.on(`change`,(n,a)=>{Fe.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})}};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]})}const iE={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`],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,default:`auto`}).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. Repeat the flag or pass a comma-separated list (e.g. --external typedoc,prettier). Globs are forwarded to esbuild as-is. See https://esbuild.github.io/api/#external`,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 BuildAction(await new Config().forBuild(n)).start({library:n.library,app:n.app,watch:n.watch})}};As(),Ho();function nodeArchToLinuxArch(n){return{x64:`x86_64`,arm64:`aarch64`,arm:`armv7`,ia32:`i686`}[n]??n}function readPackageJson$4(n){try{return JSON.parse(readFileSync(n,`utf-8`))}catch{return null}}__name$1(readPackageJson$4,`readPackageJson`);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=jo(n,N),F;try{F=readdirSync(C)}catch{continue}for(let n of F){let F=checkPackage(jo(C,n),`${N}/${n}`,a);F&&S.push(F)}}else{let C=checkPackage(jo(n,N),N,a);C&&S.push(C)}return S}function checkPackage(n,a,S){let C=readPackageJson$4(jo(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=jo(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=Oo(n);for(;;){let n=jo(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=Oo(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(`:`)}}Ie(),Hx(),Ho();function computeNativeEnvForBundle(n,a=process.cwd()){let S=Oo(n),C=detectNativePackages(a),N=detectNativePackages(Po(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=[]){let{env:S,envPrefix:C}=computeNativeEnvForBundle(n),N={...process.env,...S},F=[`-m`,n,...a],I=[`gjs`,...F.map(n=>n.includes(` `)?`"${n}"`:n)].join(` `);Fe.log(`$ ${C?`${C} `:``}${I}`);let H=spawn(`gjs`,F,{env:N,stdio:`inherit`});await new Promise((n,a)=>{H.on(`close`,S=>{S===0?n():a(Error(`gjs exited with code ${S}`))}),H.on(`error`,a)}).catch(n=>{Fe.error(n.message),process.exit(1)})}Ie(),As(),Ho(),Hx();const aE={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=Oo(a,n.entry??S.entry??`src/test.mts`),N=Oo(a,n.outdir??S.outdir??`dist`);existsSync(C)||(Fe.error(`[gjsify test] no test entry at ${Mo(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=jo(N,`test.${S}.mjs`);if(n.build!==!1)if(n.rebuild||!isFresh(F,C,a)){let N=Date.now();n.verbose&&Fe.log(`[gjsify test] building → ${Mo(a,F)} (—app ${S})`);try{await buildTestBundle(C,F,S,n.verbose),n.verbose&&Fe.log(`[gjsify test] built ${S} in ${Date.now()-N}ms`)}catch(n){Fe.error(`[gjsify test] build failed for ${S}:`,n.message),I.push({runtime:S,ok:!1,durationMs:0,error:`build failed`});continue}}else n.verbose&&Fe.log(`[gjsify test] ${S}: bundle is up-to-date — skipping build (use --rebuild to force)`);else if(!existsSync(F)){Fe.error(`[gjsify test] --no-build but ${Mo(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(` `);Fe.log(`[gjsify test] ${H}`),I.some(n=>!n.ok)&&process.exit(1)}};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 BuildAction(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,S){if(!existsSync(n))return!1;let C=statSync(n).mtimeMs,N=Po(a);try{return C>=newestMtimeUnder(existsSync(N)?N: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(jo(n,a.name));C>S&&(S=C)}return S}As();function readPackageJson$3(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}`)}}__name$1(readPackageJson$3,`readPackageJson`);function writePackageJson$1(n,a){let S=sortKnownDepFields(a);writeFileSync(n,JSON.stringify(S,null,2)+`
743
743
  `,`utf-8`)}__name$1(writePackageJson$1,`writePackageJson`);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)}}__name$1(parseSpec$2,`parseSpec`);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}As(),Ho();function discoverWorkspaces(n,a={}){let S=jo(n,`package.json`);if(!existsSync(S))throw Error(`@gjsify/workspace: no package.json at ${n}`);let C=JSON.parse(readFileSync(S,`utf-8`)),N=a.patterns??extractWorkspacePatterns(C),F=[];a.includeRoot&&C.name&&F.push({location:n,relativeLocation:`.`,name:C.name,version:C.version??`0.0.0`,manifest:C,private:C.private===!0});for(let a of N)for(let S of expandPattern(n,a)){let a=jo(S,`package.json`);if(!existsSync(a))continue;let C;try{C=JSON.parse(readFileSync(a,`utf-8`))}catch{continue}C.name&&F.push({location:S,relativeLocation:Mo(n,S).split(zo).join(`/`),name:C.name,version:C.version??`0.0.0`,manifest:C,private:C.private===!0})}return F.sort((n,a)=>n.relativeLocation.localeCompare(a.relativeLocation)),F}function buildDependencyGraph(n,a={}){let S=a.includeDev??!1,C=a.includePeer??!1,N=a.includeOptional??!0,F=indexByName(n),I=new Map;for(let a of n){let n=new Set,H=a.manifest;for(let a of[H.dependencies,S?H.devDependencies:void 0,C?H.peerDependencies:void 0,N?H.optionalDependencies:void 0])if(a)for(let[S,C]of Object.entries(a))typeof C==`string`&&C.startsWith(`workspace:`)&&F.has(S)&&n.add(S);I.set(a.name,n)}return{edges:I,byName:F}}function topologicalSort(n){let a=new Map;for(let S of n.edges.keys())a.set(S,0);for(let S of n.edges.values())for(let n of S)a.has(n)&&a.set(n,(a.get(n)??0)+1);let S=new Map,C=new Map;for(let a of n.edges.keys())S.set(a,new Set),C.set(a,0);for(let[a,N]of n.edges)for(let n of N)S.has(n)&&(S.get(n).add(a),C.set(a,(C.get(a)??0)+1));let N=[];for(let[n,a]of C)a===0&&N.push(n);N.sort();let F=[];for(;N.length>0;){let a=N.shift(),I=n.byName.get(a);I&&F.push(I);let H=S.get(a);if(H){let n=[];for(let a of H){let S=(C.get(a)??1)-1;C.set(a,S),S===0&&n.push(a)}n.sort(),N.push(...n)}}if(F.length!==C.size){let n=[...C.entries()].filter(([,n])=>n>0).map(([n])=>n);throw Error(`@gjsify/workspace: dependency cycle detected involving ${n.join(`, `)}`)}return F}function filterWorkspaces(n,a){let S=a.include?.map(globToRegex$1),C=a.exclude?.map(globToRegex$1);return n.filter(n=>!(a.noPrivate&&n.private||S&&S.length>0&&!S.some(a=>a.test(n.name))||C&&C.length>0&&C.some(a=>a.test(n.name))))}function extractWorkspacePatterns(n){let a=n.workspaces;return a?Array.isArray(a)?a:a.packages??[]:[]}function expandPattern(n,a){let S=a.split(`/`).filter(Boolean),C=[Oo(n)];for(let n of S){let a=[];for(let S of C)if(n===`*`){let n=[];try{n=readdirSync(S)}catch{continue}for(let C of n){if(C.startsWith(`.`))continue;let n=jo(S,C);try{statSync(n).isDirectory()&&a.push(n)}catch{}}}else if(n.includes(`*`)){let C=globToRegex$1(n),N=[];try{N=readdirSync(S)}catch{continue}for(let n of N){if(n.startsWith(`.`)||!C.test(n))continue;let N=jo(S,n);try{statSync(N).isDirectory()&&a.push(N)}catch{}}}else{let C=jo(S,n);if(existsSync(C))try{statSync(C).isDirectory()&&a.push(C)}catch{}}C=a}return C}function globToRegex$1(n){let a=n.replace(/[.+?^${}()|[\]\\]/g,`\\$&`).replace(/\*/g,`[^/]*`);return RegExp(`^${a}$`)}__name$1(globToRegex$1,`globToRegex`);function indexByName(n){let a=new Map;for(let S of n)a.set(S.name,S);return a}As(),Ho();function readPackageJson$2(n){try{return JSON.parse(readFileSync(n,`utf-8`))}catch{return null}}__name$1(readPackageJson$2,`readPackageJson`);function findWorkspaceRoot(n){let a=n;for(let S=0;S<12;S++){let S=jo(a,`package.json`);if(existsSync(S)&&readPackageJson$2(S)?.workspaces!==void 0)try{let S=discoverWorkspaces(a);if(a===n||S.some(a=>a.location===n))return a}catch{}let C=Oo(a,`..`);if(C===a)break;a=C}return null}Ie(),As(),Ho(),Hx();const oE={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:[]}),handler:async n=>{let a=n.target,S=n.args??[],C=readPackageJson$3(jo(process.cwd(),`package.json`));if(!(C?.scripts&&typeof C.scripts[a]==`string`)&&looksLikeFile(a)){await runGjsBundle(Oo(a),S);return}await runScript(a,S)}};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=jo(S,`package.json`),N=readPackageJson$3(C);N||(Fe.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>`;Fe.error(`gjsify run: no script "${n}" in ${C} (available: ${a})`),process.exit(1)}let H=findWorkspaceRoot(S),W=[jo(S,`node_modules`,`.bin`)];H&&H!==S&&W.push(jo(H,`node_modules`,`.bin`));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(Bo),npm_lifecycle_event:n,npm_package_name:N.name??``,npm_package_version:N.version??``},Y=a.length>0?`${I} ${a.map(shellEscape).join(` `)}`:I;await new Promise((a,C)=>{let N=spawn(Y,[],{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=>{Fe.error(n.message),process.exit(1)}),process.exit(0)}function shellEscape(n){return/^[a-zA-Z0-9_\-./=:@,]+$/.test(n)?n:`'${n.replace(/'/g,`'\\''`)}'`}Ie(),Ho();const sE={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?Oo(n.file):null,C=detectNativePackages(a),{LD_LIBRARY_PATH:N,GI_TYPELIB_PATH:F}=buildNativeEnv(C);if(n.export){Fe.log(`export LD_LIBRARY_PATH="${N}"`),Fe.log(`export GI_TYPELIB_PATH="${F}"`);return}if(C.length===0){Fe.log(`No native gjsify packages detected in node_modules.`),Fe.log(`Native packages declare "gjsify": { "prebuilds": "<dir>" } in their package.json.`);return}Fe.log(`Native packages detected:`);for(let n of C)Fe.log(` ${n.name} → ${n.prebuildsDir}`);Fe.log(``),Fe.log(`To run your app directly with gjs, set:`),Fe.log(` export LD_LIBRARY_PATH="${N}"`),Fe.log(` export GI_TYPELIB_PATH="${F}"`),S?Fe.log(` gjs -m ${S}`):Fe.log(` gjs -m <your-bundle.js>`),Fe.log(``),Fe.log(`Or use gjsify run to handle this automatically:`),S?Fe.log(` gjsify run ${n.file}`):Fe.log(` gjsify run <your-bundle.js>`)}};Hx(),Ho(),zs(),rn(),As();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(`
@@ -786,7 +786,7 @@ jobs:
786
786
  cache-key: ${n.cacheKey}
787
787
  `}Ie(),As(),Ho(),Hx();const ME={command:`check [manifest]`,description:`Run Flathub pre-submission linters: appstreamcli validate + flatpak-builder-lint.`,builder:n=>n.positional(`manifest`,{description:"Path to the Flatpak manifest. Auto-detects `<app-id>.json` if omitted.",type:`string`,normalize:!0}).option(`repo`,{description:"Built ostree-repo path. If given, also runs `flatpak-builder-lint repo`.",type:`string`,normalize:!0}).option(`metainfo`,{description:"MetaInfo XML path. Default: `data/<app-id>.metainfo.xml.in`.",type:`string`,normalize:!0}).option(`appstream`,{description:"Run `appstreamcli validate --strict` (default: true).",type:`boolean`,default:!0}).option(`builder-lint`,{description:"Run `flatpak-builder-lint manifest` (default: true).",type:`boolean`,default:!0}).option(`verbose`,{description:`Stream linter stdout/stderr verbatim.`,type:`boolean`,default:!1}),handler:async n=>{let a=(await new Config().forBuild({}).catch(()=>({}))).flatpak??{},S=process.cwd(),C=resolveAppId(n.manifest,a,S),N=resolveManifestPath(n.manifest,C,S),F=Oo(S,n.metainfo??`data/${C??`unknown`}.metainfo.xml.in`),I=0;if(n.appstream!==!1&&(existsSync(F)?await runLinter(`appstreamcli`,[`validate`,`--strict`,F],n.verbose??!1)||I++:Fe.warn(`[gjsify flatpak check] skipping appstreamcli — ${F} not found`)),n.builderLint!==!1){if(!existsSync(N)){Fe.error(`[gjsify flatpak check] manifest not found: ${N}`),process.exit(1);return}await runLinter(`flatpak-builder-lint`,[`manifest`,N],n.verbose??!1)||I++,n.repo&&(await runLinter(`flatpak-builder-lint`,[`repo`,Oo(S,n.repo)],n.verbose??!1)||I++)}I>0&&(Fe.error(`\n[gjsify flatpak check] ${I} check(s) failed.`),process.exit(1)),Fe.log(`[gjsify flatpak check] all checks passed.`)}};function resolveAppId(n,a,S){if(a.appId)return a.appId;try{let n=readPackageJson(S);if(looksLikeAppId(n.name))return n.name}catch{}if(n)return n.replace(/\.json$/,``)}function resolveManifestPath(n,a,S){if(n)return Oo(S,n);if(a)return Oo(S,`${a}.json`);let C=readdirSync(S).filter(n=>n.endsWith(`.json`)&&!n.startsWith(`package`));if(C.length===1)return Oo(S,C[0]);throw Error(`gjsify flatpak check: no manifest path given and could not auto-detect. Pass the manifest as a positional argument.`)}function runLinter(n,a,S){return new Promise(C=>{let N=spawn(n,a,{stdio:S?`inherit`:[`ignore`,`pipe`,`pipe`]}),F=``,I=``;S||(N.stdout?.setEncoding(`utf-8`),N.stderr?.setEncoding(`utf-8`),N.stdout?.on(`data`,n=>{F+=n}),N.stderr?.on(`data`,n=>{I+=n})),N.on(`error`,a=>{let S=a;S.code===`ENOENT`?Fe.error(`[gjsify flatpak check] ${n} not found in PATH.\nInstall via:\n flatpak install -y flathub org.flatpak.Builder\n alias ${n}="flatpak run --command=${n} org.flatpak.Builder"`):Fe.error(`[gjsify flatpak check] ${n} failed to spawn: ${S.message}`),C(!1)}),N.on(`exit`,N=>{let H=N===0,W=H?`OK`:`FAIL`;Fe.log(`[gjsify flatpak check] ${W}: ${n} ${a.join(` `)}`),!H&&!S&&(F.trim()&&Fe.log(F.trimEnd()),I.trim()&&Fe.error(I.trimEnd())),C(H)})})}Ie(),As(),Ho(),kp(),Hx(),qc();const NE=promisify(execFile),PE={command:`sync-flathub`,description:`Update the per-app Flathub tracking-repo manifest to a new git tag + commit. Clones, edits, commits, optionally opens a PR.`,builder:n=>n.version(!1).option(`version`,{description:"Git tag to sync to. Default: `git describe --tags --abbrev=0` in cwd.",type:`string`}).option(`app-id`,{description:"Reverse-DNS app id. Default: `gjsify.flatpak.appId`.",type:`string`}).option(`flathub-repo`,{description:"Flathub tracking-repo (owner/name). Default: `flathub/<appId>`.",type:`string`}).option(`commit`,{description:"Commit SHA to pin. Default: resolved via `git rev-list -n 1 <version>` in cwd.",type:`string`}).option(`branch`,{description:"Branch name in the flathub-repo. Default: `update-to-<version>`.",type:`string`}).option(`source-index`,{description:"Index into modules[0].sources[] to update (when manifest has multiple sources). Default: first `type: git` source.",type:`number`}).option(`pr`,{description:"After commit + push, open a PR via `gh pr create`. Pass `--no-pr` to skip and stop after push.",type:`boolean`,default:!0}).option(`dry-run`,{description:`Show what would be edited; touch no files, run no git commands.`,type:`boolean`,default:!1}).option(`verbose`,{description:`Echo every git / gh invocation before running.`,type:`boolean`,default:!1}),handler:async n=>{let a=process.cwd(),S=(await new Config().forBuild({}).catch(()=>({}))).flatpak??{},C=n.appId??S.appId??readPackageJson(a).name;if(!C)throw Error(`[gjsify flatpak sync-flathub] no app id available — pass --app-id or set gjsify.flatpak.appId.`);let N=n.flathubRepo??S.flathubRepo??`flathub/${C}`,F=n.version??await resolveLatestTag$1(a,n.verbose);if(!F)throw Error(`[gjsify flatpak sync-flathub] no version resolved — pass --version vX.Y.Z or create a git tag locally.`);let I=n.commit??await resolveCommitForTag(a,F,n.verbose),H=n.branch??`update-to-${normaliseBranchSegment(F)}`;if(Fe.log(`[gjsify flatpak sync-flathub] appId=${C}`),Fe.log(`[gjsify flatpak sync-flathub] flathubRepo=${N}`),Fe.log(`[gjsify flatpak sync-flathub] version=${F}`),Fe.log(`[gjsify flatpak sync-flathub] commit=${I}`),Fe.log(`[gjsify flatpak sync-flathub] branch=${H}`),n.dryRun){Fe.log(`[gjsify flatpak sync-flathub] --dry-run set; not cloning / writing / pushing.`);return}let W=flathubCacheRoot(),K=jo(W,N.replace(`/`,`__`));mkdirSync(W,{recursive:!0}),await ensureClone(K,N,n.verbose);let q=jo(K,`${C}.json`);if(!existsSync(q))throw Error(`[gjsify flatpak sync-flathub] Flathub manifest not found at ${q} — wrong appId / wrong flathub-repo?`);let Y=readFileSync(q,`utf-8`),X=editManifest(Y,{tag:F,commit:I,sourceIndex:n.sourceIndex});if(X===Y){Fe.log(`[gjsify flatpak sync-flathub] manifest already at ${F} — nothing to do.`);return}if(writeFileSync(q,X,`utf-8`),Fe.log(`[gjsify flatpak sync-flathub] manifest patched at ${q}`),await gitInRepo(K,[`checkout`,`-B`,H],n.verbose),await gitInRepo(K,[`add`,`.`],n.verbose),await gitInRepo(K,[`commit`,`-m`,`Update to ${F}`],n.verbose),n.pr===!1){Fe.log(`[gjsify flatpak sync-flathub] --no-pr set; branch ${H} committed locally in ${K}.`);return}await gitInRepo(K,[`push`,`-u`,`origin`,H,`--force-with-lease`],n.verbose),await ghCreate(K,N,H,F,`Auto-generated by \`gjsify flatpak sync-flathub\`.\n\n- Version: \`${F}\`\n- Commit: \`${I}\`\n`,n.verbose)}};async function resolveLatestTag$1(n,a){try{let{stdout:S}=await NE(`git`,[`describe`,`--tags`,`--abbrev=0`],{cwd:n});return a&&Fe.log(`[gjsify flatpak sync-flathub] resolved latest tag → ${S.trim()}`),S.trim()||null}catch{return null}}__name$1(resolveLatestTag$1,`resolveLatestTag`);async function resolveCommitForTag(n,a,S){try{let{stdout:C}=await NE(`git`,[`rev-list`,`-n`,`1`,a],{cwd:n}),N=C.trim();if(!N)throw Error(`empty rev-list output`);return S&&Fe.log(`[gjsify flatpak sync-flathub] resolved ${a} → ${N}`),N}catch(n){throw Error(`[gjsify flatpak sync-flathub] tag ${a} not found locally. Run \`git fetch --tags\` or pass --commit <sha>.\n underlying error: ${n?.message??n}`)}}function normaliseBranchSegment(n){return n.replace(/^v/,``).replace(/[^A-Za-z0-9._-]/g,`-`)}function flathubCacheRoot(){return jo(process.env.XDG_CACHE_HOME||jo(homedir(),`.cache`),`gjsify`,`flathub-sync`)}async function ensureClone(n,a,S){if(existsSync(jo(n,`.git`))){S&&Fe.log(`[gjsify flatpak sync-flathub] reusing clone at ${n}`),await gitInRepo(n,[`fetch`,`origin`],S);let a=await detectDefaultBranch(n,S);await gitInRepo(n,[`checkout`,a],S),await gitInRepo(n,[`reset`,`--hard`,`origin/${a}`],S);return}mkdirSync(Oo(n,`..`),{recursive:!0});let C=`https://github.com/${a}.git`;S&&Fe.log(`[gjsify flatpak sync-flathub] git clone ${C} ${n}`);try{await NE(`git`,[`clone`,C,n])}catch(n){throw n?.code===`ENOENT`?Error("[gjsify flatpak sync-flathub] `git` not found. Install git from your distro (Fedora: `dnf install git`, Debian: `apt install git`)."):n}}async function detectDefaultBranch(n,a){try{let{stdout:S}=await NE(`git`,[`remote`,`show`,`origin`],{cwd:n}),C=S.match(/HEAD branch: (\S+)/);if(C&&C[1]&&C[1]!==`(unknown)`)return a&&Fe.log(`[gjsify flatpak sync-flathub] default branch → ${C[1]}`),C[1]}catch{}return`master`}function gitInRepo(n,a,S){return S&&Fe.log(`[gjsify flatpak sync-flathub] git ${a.join(` `)} (in ${n})`),new Promise((S,C)=>{let N=spawn(`git`,a,{cwd:n,stdio:`inherit`});N.on(`error`,n=>{n.code===`ENOENT`?C(Error("[gjsify flatpak sync-flathub] `git` not found. Install it from your distro.")):C(n)}),N.on(`exit`,n=>{n===0?S():C(Error(`git ${a[0]} exited ${n}`))})})}function ghCreate(n,a,S,C,N,F){let I=[`pr`,`create`,`--repo`,a,`--head`,S,`--title`,`Update to ${C}`,`--body`,N];return F&&Fe.log(`[gjsify flatpak sync-flathub] gh ${I.join(` `)} (in ${n})`),new Promise((a,S)=>{let C=spawn(`gh`,I,{cwd:n,stdio:`inherit`});C.on(`error`,n=>{n.code===`ENOENT`?S(Error("[gjsify flatpak sync-flathub] `gh` (GitHub CLI) not found. Install via `dnf install gh` (Fedora), `apt install gh` (Debian/Ubuntu), or `flatpak install -y flathub com.github.cli`.")):S(n)}),C.on(`exit`,n=>{n===0?a():S(Error(`gh pr create exited ${n}`))})})}function editManifest(n,a){let S=JSON.parse(n),C=S.modules??[];if(C.length===0)throw Error(`[gjsify flatpak sync-flathub] manifest has no modules`);let N=C[0].sources??[];if(N.length===0)throw Error(`[gjsify flatpak sync-flathub] modules[0] has no sources`);let F=a.sourceIndex??N.findIndex(n=>n.type===`git`);if(F<0||F>=N.length)throw Error(`[gjsify flatpak sync-flathub] no git source found in modules[0].sources (use --source-index <n>)`);let I=N[F];if(I.type!==`git`)throw Error(`[gjsify flatpak sync-flathub] modules[0].sources[${F}].type is "${I.type}", expected "git"`);I.tag=a.tag,I.commit=a.commit,I[`x-checker-data`]||={type:`git`,"tag-pattern":`^v(\\d+\\.\\d+\\.\\d+)$`,"version-scheme":`semantic`};let H=detectIndent$1(n);return JSON.stringify(S,null,H)+(n.endsWith(`
788
788
  `)?`
789
- `:``)}function detectIndent$1(n){let a=n.match(/^\{\n( +)/);return a?a[1].length:2}__name$1(detectIndent$1,`detectIndent`),Ie(),As(),Hx(),qc();const FE=promisify(execFile),IE={command:`diff`,description:`Compare the per-app Flathub tracking-repo manifest against the local git state and report version / commit drift.`,builder:n=>n.version(!1).option(`version`,{description:"Local version to compare against. Default: `git describe --tags --abbrev=0` in cwd.",type:`string`}).option(`app-id`,{description:"Reverse-DNS app id. Default: `gjsify.flatpak.appId`.",type:`string`}).option(`flathub-repo`,{description:"Flathub tracking-repo (owner/name). Default: `gjsify.flatpak.flathubRepo` or `flathub/<appId>`.",type:`string`}).option(`against`,{description:`Read the Flathub manifest from a local file instead of fetching it. Useful in CI or offline.`,type:`string`}).option(`detail`,{description:`Also print the full Flathub manifest source entry alongside the resolved local version.`,type:`boolean`,default:!1}).option(`source-index`,{description:`Index into modules[0].sources[] to inspect (when the manifest has multiple sources).`,type:`number`}).option(`verbose`,{description:`Echo fetch URL + resolved values.`,type:`boolean`,default:!1}),handler:async n=>{let a=process.cwd(),S=(await new Config().forBuild({}).catch(()=>({}))).flatpak??{},C=n.appId??S.appId??readPackageJson(a).name;if(!C)throw Error(`[gjsify flatpak diff] no app id available — pass --app-id or set gjsify.flatpak.appId.`);let N=n.flathubRepo??S.flathubRepo??`flathub/${C}`,F=n.version??await resolveLatestTag(a,n.verbose),I=await loadFlathubSource({appId:C,flathubRepo:N,against:n.against,verbose:n.verbose},n.sourceIndex),H=I?.tag,W=I?.commit;if(Fe.log(`[gjsify flatpak diff] appId=${C}`),Fe.log(`[gjsify flatpak diff] flathubRepo=${N}`),Fe.log(`[gjsify flatpak diff] flathub: tag=${H??`(missing)`} commit=${W??`(missing)`}`),Fe.log(`[gjsify flatpak diff] local: tag=${F??`(none)`}`),n.detail&&I&&(Fe.log(`[gjsify flatpak diff] flathub manifest source:`),Fe.log(JSON.stringify(I,null,2))),!F){Fe.warn("[gjsify flatpak diff] no local git tag found — cut a release (`git tag vX.Y.Z`) or pass --version vX.Y.Z to compare against an explicit value.");return}if(H||(Fe.warn("[gjsify flatpak diff] flathub manifest has no `tag` field on the inspected source."),process.exit(1)),H===F){Fe.log(`✅ in sync (${F})`);return}Fe.log(`❌ drift detected — flathub=${H} vs local=${F}`),Fe.log(` run \`gjsify flatpak sync-flathub --version ${F}\` to update the Flathub manifest.`),process.exit(1)}};async function loadFlathubSource(n,a){let S;if(n.against){if(!existsSync(n.against))throw Error(`[gjsify flatpak diff] --against path ${n.against} does not exist`);S=readFileSync(n.against,`utf-8`)}else S=await fetchFlathubManifest(n.flathubRepo,n.appId,n.verbose);let C;try{C=JSON.parse(S)}catch(n){throw Error(`[gjsify flatpak diff] failed to parse Flathub manifest as JSON: ${n.message}`)}let N=(C.modules??[])[0]?.sources??[];if(N.length===0)return null;let F=a??N.findIndex(n=>n?.type===`git`);return F<0||F>=N.length?null:N[F]??null}async function fetchFlathubManifest(n,a,S){for(let C of[`master`,`main`]){let N=`https://raw.githubusercontent.com/${n}/${C}/${a}.json`;S&&Fe.log(`[gjsify flatpak diff] fetch ${N}`);try{let n=await fetch(N);if(n.ok)return await n.text();S&&Fe.log(`[gjsify flatpak diff] ${C} → HTTP ${n.status}`)}catch(n){S&&Fe.log(`[gjsify flatpak diff] ${C} fetch error: ${n.message}`)}}throw Error(`[gjsify flatpak diff] could not fetch flathub manifest from ${n} on master or main`)}async function resolveLatestTag(n,a){try{let{stdout:S}=await FE(`git`,[`describe`,`--tags`,`--abbrev=0`],{cwd:n}),C=S.trim();return a&&Fe.log(`[gjsify flatpak diff] local latest tag → ${C}`),C||null}catch{return null}}Ie(),Hx(),qc(),rn(),Ho();const LE=promisify(execFile),RE={command:`release <version>`,description:"Cut a release end-to-end: regenerate Flathub assets, run linters, create + push the git tag, then open the Flathub PR. Each step delegates to the equivalent `gjsify flatpak <sub>` command.",builder:n=>n.version(!1).positional(`version`,{description:"Release tag, e.g. `v0.6.6`.",type:`string`,demandOption:!0}).option(`skip-init`,{description:"Skip the `flatpak init --force` regen step.",type:`boolean`,default:!1}).option(`skip-check`,{description:"Skip the `flatpak check` linter step.",type:`boolean`,default:!1}).option(`skip-tag`,{description:"Skip the `git tag` + `git push --tags` step (use when the tag was already created out-of-band).",type:`boolean`,default:!1}).option(`push-tag`,{description:`Push the created tag after creating it. Default: true.`,type:`boolean`,default:!0}).option(`flathub-repo`,{description:`Flathub tracking-repo override forwarded to sync-flathub.`,type:`string`}).option(`dry-run`,{description:`Print each step that would run without executing any of them.`,type:`boolean`,default:!1}).option(`verbose`,{description:`Echo every sub-command invocation.`,type:`boolean`,default:!1}),handler:async n=>{let a=typeof n.version==`string`?n.version.trim():``;if(!a)throw Error(`[gjsify flatpak release] missing <version> positional`);let S=resolveCliEntry(),C=process.cwd(),N=[];n.skipInit||N.push({name:`init`,args:[S,`flatpak`,`init`,`--force`]}),n.skipCheck||N.push({name:`check`,args:[S,`flatpak`,`check`]});let F=[S,`flatpak`,`sync-flathub`,`--version`,a];if(n.flathubRepo&&F.push(`--flathub-repo`,n.flathubRepo),n.verbose&&F.push(`--verbose`),Fe.log(`[gjsify flatpak release] starting release of ${a}`),n.dryRun){Fe.log(`[gjsify flatpak release] --dry-run set; printing plan only:`);for(let n of N)Fe.log(` · ${n.name}: node ${n.args.join(` `)}`);n.skipTag||Fe.log(` · tag: git tag ${a}${n.pushTag===!1?``:` && git push origin `+a}`),Fe.log(` · sync: node ${F.join(` `)}`);return}for(let a of N)n.verbose&&Fe.log(`[gjsify flatpak release] step ${a.name}: node ${a.args.join(` `)}`),await runNode(a.args,C),Fe.log(`[gjsify flatpak release] ${a.name} ✔`);if(!n.skipTag){n.verbose&&Fe.log(`[gjsify flatpak release] git tag ${a}`);try{await LE(`git`,[`tag`,a],{cwd:C}),Fe.log(`[gjsify flatpak release] tag ${a} created`)}catch(n){throw Error(`[gjsify flatpak release] git tag failed (${n.message}). If the tag already exists, re-run with --skip-tag.`)}n.pushTag!==!1&&(n.verbose&&Fe.log(`[gjsify flatpak release] git push origin ${a}`),await LE(`git`,[`push`,`origin`,a],{cwd:C}),Fe.log(`[gjsify flatpak release] tag pushed`))}n.verbose&&Fe.log(`[gjsify flatpak release] sync: node ${F.join(` `)}`),await runNode(F,C),Fe.log(`[gjsify flatpak release] ✅ release ${a} complete`)}};function resolveCliEntry(){return Oo(Oo(Po(fileURLToPath(import.meta.url)),`..`,`..`),`index.js`)}async function runNode(n,a){await new Promise((S,C)=>{let N=spawn(`node`,n,{cwd:a,stdio:`inherit`});N.on(`error`,C),N.on(`exit`,a=>{a===0?S():C(Error(`sub-command exited with code ${a}: node ${n.join(` `)}`))})})}const zE={command:`flatpak <subcommand>`,description:`Flatpak toolchain: init/build/deps/ci/check/sync-flathub/diff/release subcommands for shipping GJS apps and CLIs as Flatpaks.`,builder:n=>n.command(OE.command,OE.description,OE.builder,OE.handler).command(kE.command,kE.description,kE.builder,kE.handler).command(AE.command,AE.description,AE.builder,AE.handler).command(jE.command,jE.description,jE.builder,jE.handler).command(ME.command,ME.description,ME.builder,ME.handler).command(PE.command,PE.description,PE.builder,PE.handler).command(IE.command,IE.description,IE.builder,IE.handler).command(RE.command,RE.description,RE.builder,RE.handler).demandCommand(1).strict()};As(),Ho();const BE=/^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;function parseSpec$1(n){if(!n)throw Error(`dlx: empty package spec`);if(n.startsWith(`./`)||n.startsWith(`../`)||Ao(n)||existsSync(n))return{kind:`local`,path:Oo(n)};let a=n,S,C=n.lastIndexOf(`@`);if(C>0&&(a=n.slice(0,C),S=n.slice(C+1)),!BE.test(a))throw Error(`dlx: invalid package name "${a}"`);return{kind:`registry`,name:a,version:S,spec:n}}__name$1(parseSpec$1,`parseSpec`),As(),Ho();function resolveGjsEntry(n,a){let S=jo(n,`package.json`);if(!existsSync(S))throw Error(`dlx: no package.json found at ${n}`);let C=JSON.parse(readFileSync(S,`utf-8`)),N=C.gjsify?.bin,F=C.gjsify?.main,I=C.main,H,W=null,K=!1;if(a!==null){if(!N||!N[a]){let S=N?Object.keys(N).join(`, `):`(none)`;throw Error(`dlx: package "${C.name??n}" has no GJS bin named "${a}" — known: ${S}`)}H=N[a],W=a}else if(N&&Object.keys(N).length===1){let n=Object.keys(N)[0];H=N[n],W=n}else F?H=F:I&&(H=I,K=!0);if(N&&Object.keys(N).length>1&&a===null){let a=Object.keys(N).join(`, `);throw Error(`dlx: package "${C.name??n}" defines multiple GJS bins — pass one of: ${a}`)}if(!H)throw Error(`dlx: package "${C.name??n}" has no GJS entry — set \`gjsify.main\` (or \`gjsify.bin\`) in its package.json`);let q=Oo(n,H);if(!existsSync(q))throw Error(`dlx: GJS entry not found: ${q}`);return{bundlePath:q,binName:W,fromFallback:K}}Ga(),As(),kp(),Ho();function lexCompare(n,a){return n<a?-1:+(n>a)}function createCacheKey(n){let a=[...n.packages].sort(lexCompare),S=Object.entries(n.registries??{}).sort(([n],[a])=>lexCompare(n,a)),C=JSON.stringify([a,S]);return createHash(`sha256`).update(C).digest(`hex`)}function dlxCacheRoot(){let n=process.env.XDG_CACHE_HOME,a=jo(n&&n.length>0?n:jo(homedir(),`.cache`),`gjsify`,`dlx`);return mkdirSync(a,{recursive:!0}),a}function cacheDirFor(n){let a=jo(dlxCacheRoot(),n);return mkdirSync(a,{recursive:!0}),a}function makePrepareDir(n){let a=jo(n,`${Date.now().toString(16)}-${process.pid.toString(16)}`);return mkdirSync(a,{recursive:!0}),a}function getValidCachedPkg(n,a=10080){let S=jo(n,`pkg`),C;try{C=lstatSync(S)}catch(n){if(n.code===`ENOENT`)return;throw n}if(!C.isSymbolicLink())return;let N;try{N=realpathSync(S)}catch{return}return Date.now()-C.mtime.getTime()<=a*6e4?N:void 0}function symlinkSwap(n,a){let S=jo(n,`pkg`),C=jo(n,`pkg.tmp-${Date.now().toString(16)}-${process.pid.toString(16)}`);try{symlinkSync(a,C,`dir`)}catch(n){throw n}try{renameSync(C,S)}catch(n){let a=n.code;if(a===`EBUSY`||a===`EPERM`||a===`EEXIST`){try{rmSync(C)}catch{}return realpathSync(S)}throw n}return realpathSync(S)}function resolveInstalledPkgDir(n,a){return Oo(n,`node_modules`,a)}function parse(n){try{return new SemVer(n)}catch{return null}}function satisfies(n,a){let S=a instanceof UE?a:new UE(a),C=n instanceof SemVer?n:parse(String(n));return C?S.test(C):!1}function maxSatisfying(n,a){let S=a instanceof UE?a:new UE(a),C=null;for(let a of n){let n=parse(a);!n||!S.test(n)||(C===null||n.compare(C)>0)&&(C=n)}return C?C.version:null}function testComparator(n,a){if(n.semver===null)return!0;let S=a.compare(n.semver);switch(n.operator){case``:case`=`:return S===0;case`<`:return S<0;case`<=`:return S<=0;case`>`:return S>0;case`>=`:return S>=0}}function formatComparator(n){return n.semver===null?`*`:`${n.operator}${n.semver.version}`}function parseRangePart(n){let a=n.trim();if(a===``||a===`*`||a.toLowerCase()===`latest`)return[{operator:`>=`,semver:new SemVer(`0.0.0`)}];let S=a.match(/^\s*(\S+)\s+-\s+(\S+)\s*$/);if(S)return hyphenRange(S[1],S[2]);let C=a.replace(/(<=|>=|<|>|=)\s+(?=\S)/g,`$1`).split(/\s+/),N=[];for(let n of C)N.push(...parseSimple(n));return N}function parseSimple(n){if(n===`*`||n===``||n.toLowerCase()===`latest`)return[{operator:`>=`,semver:new SemVer(`0.0.0`)}];if(n.startsWith(`^`))return caretRange(n.slice(1));if(n.startsWith(`~`))return tildeRange(n.slice(1).replace(/^>/,``));let a=n.match(/^(<=|>=|<|>|=)\s*(.+)$/);if(a){let n=a[1];return primitiveRange(n,a[2])}return partialRange(n)}function parsePartial(n){let a=n.trim().replace(/^v/,``);if(a===``||a===`*`)return{major:null,minor:null,patch:null,pre:``,build:``};let S=``,C=``,N=a,F=N.indexOf(`+`);F>=0&&(C=N.slice(F+1),N=N.slice(0,F));let I=N.indexOf(`-`);I>=0&&(S=N.slice(I+1),N=N.slice(0,I));let H=N.split(`.`),xr=a=>{if(a===void 0||a===``||a===`x`||a===`X`||a===`*`)return null;if(!/^\d+$/.test(a))throw TypeError(`Invalid partial version: ${n}`);return Number(a)};return{major:xr(H[0]),minor:xr(H[1]),patch:xr(H[2]),pre:S,build:C}}function partialToVersion(n){return`${n.major??0}.${n.minor??0}.${n.patch??0}${n.pre?`-${n.pre}`:``}${n.build?`+${n.build}`:``}`}function partialRange(n){let a=parsePartial(n);return a.major===null?[{operator:`>=`,semver:new SemVer(`0.0.0`)}]:a.minor===null?[{operator:`>=`,semver:new SemVer(`${a.major}.0.0`)},{operator:`<`,semver:new SemVer(`${a.major+1}.0.0`)}]:a.patch===null?[{operator:`>=`,semver:new SemVer(`${a.major}.${a.minor}.0`)},{operator:`<`,semver:new SemVer(`${a.major}.${a.minor+1}.0`)}]:[{operator:`=`,semver:new SemVer(partialToVersion(a))}]}function caretRange(n){let a=parsePartial(n);if(a.major===null)return[{operator:`>=`,semver:new SemVer(`0.0.0`)}];let S=`${a.major}.${a.minor??0}.${a.patch??0}${a.pre?`-${a.pre}`:``}`,C;return C=a.major>0||a.minor===null?`${a.major+1}.0.0`:a.minor>0||a.patch===null?`0.${a.minor+1}.0`:`0.0.${a.patch+1}`,[{operator:`>=`,semver:new SemVer(S)},{operator:`<`,semver:new SemVer(C)}]}function tildeRange(n){let a=parsePartial(n);if(a.major===null)return[{operator:`>=`,semver:new SemVer(`0.0.0`)}];let S=`${a.major}.${a.minor??0}.${a.patch??0}${a.pre?`-${a.pre}`:``}`,C=a.minor===null?`${a.major+1}.0.0`:`${a.major}.${a.minor+1}.0`;return[{operator:`>=`,semver:new SemVer(S)},{operator:`<`,semver:new SemVer(C)}]}function primitiveRange(n,a){let S=parsePartial(a);return S.major===null?[{operator:`>=`,semver:new SemVer(`0.0.0`)}]:n===`=`||n===``?partialRange(a):n===`>`?S.minor===null?[{operator:`>=`,semver:new SemVer(`${S.major+1}.0.0`)}]:S.patch===null?[{operator:`>=`,semver:new SemVer(`${S.major}.${S.minor+1}.0`)}]:[{operator:`>`,semver:new SemVer(partialToVersion(S))}]:n===`<`?S.minor===null?[{operator:`<`,semver:new SemVer(`${S.major}.0.0`)}]:S.patch===null?[{operator:`<`,semver:new SemVer(`${S.major}.${S.minor}.0`)}]:[{operator:`<`,semver:new SemVer(partialToVersion(S))}]:n===`>=`?[{operator:`>=`,semver:new SemVer(partialToVersion(S))}]:S.minor===null?[{operator:`<`,semver:new SemVer(`${S.major+1}.0.0`)}]:S.patch===null?[{operator:`<`,semver:new SemVer(`${S.major}.${S.minor+1}.0`)}]:[{operator:`<=`,semver:new SemVer(partialToVersion(S))}]}function hyphenRange(n,a){let S=parsePartial(n),C=parsePartial(a),N=S.major===null?{operator:`>=`,semver:new SemVer(`0.0.0`)}:{operator:`>=`,semver:new SemVer(`${S.major}.${S.minor??0}.${S.patch??0}${S.pre?`-${S.pre}`:``}`)},F;return F=C.major===null?{operator:`>=`,semver:new SemVer(`0.0.0`)}:C.minor===null?{operator:`<`,semver:new SemVer(`${C.major+1}.0.0`)}:C.patch===null?{operator:`<`,semver:new SemVer(`${C.major}.${C.minor+1}.0`)}:{operator:`<=`,semver:new SemVer(`${C.major}.${C.minor}.${C.patch}${C.pre?`-${C.pre}`:``}`)},[N,F]}var VE,HE,SemVer,UE,WE=__esmMin(()=>{VE=/^(0|[1-9]\d*)$/,HE=/^(\d+)\.(\d+)\.(\d+)(?:-((?:[0-9A-Za-z-]+)(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/,SemVer=class{major;minor;patch;prerelease;build;version;constructor(n){let a=String(n).trim().replace(/^v/,``),S=HE.exec(a);if(!S)throw TypeError(`Invalid Version: ${n}`);this.major=Number(S[1]),this.minor=Number(S[2]),this.patch=Number(S[3]),this.prerelease=S[4]?S[4].split(`.`).map(n=>VE.test(n)?Number(n):n):[],this.build=S[5]?S[5].split(`.`):[],this.version=`${this.major}.${this.minor}.${this.patch}`+(this.prerelease.length?`-${this.prerelease.join(`.`)}`:``)+(this.build.length?`+${this.build.join(`.`)}`:``)}compare(n){return this.major===n.major?this.minor===n.minor?this.patch===n.patch?this.comparePre(n):this.patch<n.patch?-1:1:this.minor<n.minor?-1:1:this.major<n.major?-1:1}comparePre(n){let a=this.prerelease,S=n.prerelease;if(a.length===0&&S.length===0)return 0;if(a.length===0)return 1;if(S.length===0)return-1;for(let n=0;;n++){let C=a[n],N=S[n];if(C===void 0&&N===void 0)return 0;if(N===void 0)return 1;if(C===void 0)return-1;if(C===N)continue;let F=typeof C==`number`,I=typeof N==`number`;return F&&!I?-1:!F&&I?1:C<N?-1:1}}toString(){return this.version}},UE=class Range{raw;set;constructor(n){if(n instanceof Range){this.raw=n.raw,this.set=n.set;return}this.raw=String(n).trim();let a=this.raw.split(/\s*\|\|\s*/),S=[];for(let n of a){let a=parseRangePart(n);if(a.length===0)throw TypeError(`Invalid range: ${this.raw}`);S.push(a)}if(S.length===0)throw TypeError(`Invalid range: ${this.raw}`);this.set=S}test(n){let a=n instanceof SemVer?n:parse(String(n));if(!a)return!1;for(let n of this.set)if(n.every(n=>testComparator(n,a))){if(a.prerelease.length>0&&!n.some(n=>n.semver!==null&&n.semver.prerelease.length>0&&n.semver.major===a.major&&n.semver.minor===a.minor&&n.semver.patch===a.patch))continue;return!0}return!1}format(){return this.set.map(n=>n.map(formatComparator).join(` `)).join(` || `)}toString(){return this.format()}}});function assertPackument(n,a){if(!a||typeof a!=`object`)throw TypeError(`registry: ${n} packument is not an object`);let S=a;if(typeof S.name!=`string`)throw TypeError(`registry: ${n} packument missing string name`);if(!S.versions||typeof S.versions!=`object`)throw TypeError(`registry: ${n} packument missing versions map`)}function registryFor(n,a){if(a&&n.startsWith(`@`)){let S=n.slice(0,n.indexOf(`/`)),C=a.scopes[S];if(C)return ensureTrailingSlash$1(C)}return a?.registry?ensureTrailingSlash$1(a.registry):GE}function packumentUrl(n,a){let S=ensureTrailingSlash$1(a);if(n.startsWith(`@`)){let a=n.indexOf(`/`);if(a<0)throw TypeError(`Invalid scoped package name: ${n}`);let C=n.slice(0,a),N=n.slice(a+1);return`${S}${encodeURIComponent(C)}/${encodeURIComponent(N)}`}return`${S}${encodeURIComponent(n)}`}async function fetchPackument(n,a={}){let S=packumentUrl(n,a.registry??registryFor(n,a.npmrc)),C=buildHeaders(S,a);C.accept??=`application/vnd.npm.install-v1+json`;let N=await fetchWithRetry(S,{headers:C,signal:a.signal},a);if(!N.ok)throw N.status===404?new PackageNotFoundError(n,S):Error(`registry GET ${S} -> ${N.status} ${N.statusText}`);let F=await N.json();return assertPackument(n,F),F}async function fetchTarball(n,a={}){let S=buildHeaders(n,a);S.accept??=`application/octet-stream`;let C=await fetchWithRetry(n,{headers:S,signal:a.signal},a);if(!C.ok)throw Error(`tarball GET ${n} -> ${C.status} ${C.statusText}`);let N=new Uint8Array(await C.arrayBuffer());if(a.integrity&&!await verifyIntegrity(N,a.integrity))throw new IntegrityError(n,a.integrity);return N}async function fetchWithRetry(n,a,S){let C=S.fetch??globalThis.fetch;if(!C)throw Error(`@gjsify/npm-registry: globalThis.fetch is missing`);let N=Math.max(0,S.retries??3),F=Math.max(0,S.retryDelayMs??250),I=0,H;for(;;){if(a.signal?.aborted)throw signalAbortError(a.signal);try{let S=await C(n,a);if(S.ok||!isRetryableStatus(S.status)||I>=N)return S;try{await S.arrayBuffer()}catch{}H=Error(`HTTP ${S.status} ${S.statusText}`)}catch(n){if(!isRetryableError(n)||I>=N)throw n;H=n}let W=Math.min(F*2**I,8e3);S.onRetry?.({attempt:I+1,error:H,delayMs:W}),await delay(W,a.signal),I++}}function isRetryableStatus(n){return n===408||n===425||n===429||n===500||n===502||n===503||n===504||n===521||n===522||n===524||n===525}function isRetryableError(n){if(n&&typeof n==`object`&&`name`in n&&n.name===`AbortError`)return!1;if(n instanceof TypeError)return!0;if(n&&typeof n==`object`&&`name`in n){let a=n.name;if(a===`FetchError`)return!0;if(a===`AbortError`)return!1}let a=n?.cause;if(a&&typeof a==`object`&&`code`in a){let n=a.code;if(typeof n==`string`)return n===`ECONNRESET`||n===`ECONNREFUSED`||n===`ENETUNREACH`||n===`ENOTFOUND`||n===`ETIMEDOUT`||n===`EAI_AGAIN`||n===`UND_ERR_SOCKET`||n===`UND_ERR_CONNECT_TIMEOUT`}return!1}function delay(n,a){return n<=0?Promise.resolve():new Promise((S,C)=>{let N=setTimeout(()=>{a?.removeEventListener?.(`abort`,onAbort),S()},n),onAbort=()=>{clearTimeout(N),C(signalAbortError(a))};if(a?.aborted){clearTimeout(N),C(signalAbortError(a));return}a?.addEventListener?.(`abort`,onAbort,{once:!0})})}function signalAbortError(n){let a=n&&`reason`in n?n.reason:void 0;if(a instanceof Error)return a;let S=Error(`Aborted`);return S.name=`AbortError`,S}async function verifyIntegrity(n,a){let S=a.trim().split(/\s+/);for(let a of S){let S=a.indexOf(`-`);if(S<0)continue;let C=a.slice(0,S).toLowerCase(),N=a.slice(S+1),F=globalThis.crypto?.subtle;if(!F)throw Error(`@gjsify/npm-registry: globalThis.crypto.subtle is missing`);let I=subriToWebCryptoAlgo(C);if(!I)continue;let H=await F.digest(I,dataAsArrayBuffer(n));if(bytesToBase64(new Uint8Array(H))===N)return!0}return!1}function subriToWebCryptoAlgo(n){switch(n){case`sha1`:return`SHA-1`;case`sha256`:return`SHA-256`;case`sha384`:return`SHA-384`;case`sha512`:return`SHA-512`;default:return null}}function dataAsArrayBuffer(n){if(n.byteOffset===0&&n.byteLength===n.buffer.byteLength)return n.buffer;let a=new Uint8Array(n.byteLength);return a.set(n),a.buffer}function bytesToBase64(n){let a=``;for(let S=0;S<n.length;S++)a+=String.fromCharCode(n[S]);return btoa(a)}function parseNpmrc(n){let a={registry:GE,scopes:{},authTokens:{},basicAuth:{}},S=n.split(/\r?\n/),C={};for(let n of S){let S=n.replace(/^\s+|\s+$/g,``);if(!S||S.startsWith(`#`)||S.startsWith(`;`))continue;let N=S.indexOf(`=`);if(N<0)continue;let F=S.slice(0,N).trim(),I=expandEnv(stripQuotes(S.slice(N+1).trim()));if(F===`registry`){a.registry=ensureTrailingSlash$1(I);continue}let H=F.match(/^(@[^:]+):registry$/);if(H){a.scopes[H[1]]=ensureTrailingSlash$1(I);continue}let W=F.match(/^\/\/(.+):_authToken$/);if(W){a.authTokens[normalizeAuthHost(W[1])]=I;continue}let K=F.match(/^\/\/(.+):username$/);if(K){(C[normalizeAuthHost(K[1])]??={}).user=I;continue}let q=F.match(/^\/\/(.+):_password$/);if(q){let n=base64Decode(I);(C[normalizeAuthHost(q[1])]??={}).pass=n;continue}}for(let[n,S]of Object.entries(C))S.user&&S.pass!==void 0&&(a.basicAuth[n]={username:S.user,password:S.pass});return a}function buildHeaders(n,a){let S={"user-agent":`gjsify-install/0.3.7`,"accept-encoding":`identity`};if(a.npmrc){let C=resolveAuthForUrl(n,a.npmrc);C&&(S.authorization=C)}if(a.headers)for(let[n,C]of Object.entries(a.headers))S[n.toLowerCase()]=C;return S}function resolveAuthForUrl(n,a){let S=pathPrefixes(new URL(n));for(let n of S){let S=a.authTokens[n];if(S)return`Bearer ${S}`;let C=a.basicAuth[n];if(C)return`Basic ${btoa(`${C.username}:${C.password}`)}`}return null}function pathPrefixes(n){let a=n.pathname.split(`/`).filter(Boolean),S=[];for(let C=a.length;C>=0;C--){let N=a.slice(0,C).join(`/`);S.push(N?`//${n.host}/${N}`:`//${n.host}`)}return S}function normalizeAuthHost(n){return`//${n.replace(/\/+$/,``)}`}function ensureTrailingSlash$1(n){return n.endsWith(`/`)?n:n+`/`}function stripQuotes(n){return n.startsWith(`"`)&&n.endsWith(`"`)||n.startsWith(`'`)&&n.endsWith(`'`)?n.slice(1,-1):n}function expandEnv(n){return n.replace(/\$\{([A-Z0-9_]+)\}/gi,(n,a)=>globalThis.process?.env?.[a]??``)}function base64Decode(n){return atob(n)}var GE,PackageNotFoundError,IntegrityError,KE=__esmMin(()=>{GE=`https://registry.npmjs.org/`,__name$1(ensureTrailingSlash$1,`ensureTrailingSlash`),PackageNotFoundError=class extends Error{name;url;constructor(n,a){super(`Package not found in registry: ${n} (${a})`),this.name=n,this.url=a,this.name=`PackageNotFoundError`}},IntegrityError=class extends Error{url;integrity;constructor(n,a){super(`Tarball integrity mismatch for ${n} (expected ${a})`),this.url=n,this.integrity=a,this.name=`IntegrityError`}}});function parseTar(n){let a=[],S=null,C=null,N=null,F=0;for(;F+512<=n.length;){let I=n.subarray(F,F+512);if(allZeros(I)){let a=n.subarray(F+512,F+2*512);if(a.length===512&&allZeros(a))break;F+=512;continue}if(!validateChecksum(I))throw new TarParseError(`Bad header checksum at offset ${F} — file is not a valid tar archive`);let H=readString(I,0,100),W=parseOctal(I,100,8),K=parseOctal(I,124,12),q=parseOctal(I,136,12),Y=String.fromCharCode(I[156]||0),X=readString(I,157,100),te=readString(I,257,6),ne=readString(I,345,155),re=readString(I,265,32),ie=readString(I,297,32);F+=512;let ae=n.subarray(F,F+K);if(F+=alignToBlock(K),Y===`x`){S=parsePaxRecords(ae);continue}if(Y===`g`)continue;if(Y===`L`){C=bytesToString(ae).replace(/\0+$/,``);continue}if(Y===`K`){N=bytesToString(ae).replace(/\0+$/,``);continue}let oe=H;te===`ustar`&&ne!==``&&(oe=`${ne}/${H}`),C!==null&&(oe=C,C=null);let Z=X;if(N!==null&&(Z=N,N=null),S!==null){let C=S.get(`path`);C!==void 0&&(oe=C);let N=S.get(`linkpath`);N!==void 0&&(Z=N);let I=S.get(`size`);if(I!==void 0){let C=Number(I);if(Number.isFinite(C)){let N=F-alignToBlock(K),I=n.subarray(N,N+C);F=N+alignToBlock(C),S=null,a.push(buildEntry(oe,Z,Y,W,q,re,ie,I));continue}}S=null}a.push(buildEntry(oe,Z,Y,W,q,re,ie,ae))}return a}function buildEntry(n,a,S,C,N,F,I,H){return{name:n,linkname:a,type:typeflagToType(S,n),mode:C,mtime:N,body:H,uname:F,gname:I}}function typeflagToType(n,a){switch(n){case`0`:case`\0`:case``:return a.endsWith(`/`)?`directory`:`file`;case`1`:return`hardlink`;case`2`:return`symlink`;case`5`:return`directory`;case`x`:return`pax-header`;case`g`:return`pax-global`;case`L`:return`gnu-longname`;case`K`:return`gnu-longlink`;default:return`unknown`}}function parsePaxRecords(n){let a=new Map,S=0;for(;S<n.length;){let C=S;for(;C<n.length&&n[C]!==32;)C++;if(C>=n.length)break;let N=bytesToString(n.subarray(S,C)),F=Number(N);if(!Number.isFinite(F)||F<=0)break;let I=S+F;if(I>n.length)break;let H=bytesToString(n.subarray(C+1,I-1)),W=H.indexOf(`=`);if(W>0){let n=H.slice(0,W),S=H.slice(W+1);a.set(n,S)}S=I}return a}function readString(n,a,S){let C=a,N=a+S;for(;C<N&&n[C]!==0;)C++;return bytesToString(n.subarray(a,C))}function bytesToString(n){return new TextDecoder(`utf-8`,{fatal:!1}).decode(n)}function parseOctal(n,a,S){if(S>0&&n[a]&128){let C=n[a]&127;for(let N=1;N<S;N++)C=C*256+n[a+N];return C}let C=``;for(let N=0;N<S;N++){let S=n[a+N];S===0||S===32||(C+=String.fromCharCode(S))}return C===``?0:parseInt(C,8)}function alignToBlock(n){return Math.ceil(n/512)*512}function allZeros(n){for(let a=0;a<n.length;a++)if(n[a]!==0)return!1;return!0}function validateChecksum(n){let a=parseOctal(n,148,8),S=0,C=0;for(let a=0;a<512;a++){let N=a>=148&&a<156?32:n[a];S+=N,C+=N>127?N-256:N}return a===S||a===C}var TarParseError,qE=__esmMin(()=>{TarParseError=class extends Error{constructor(n){super(n),this.name=`TarParseError`}}});function createTarball(n){let a=[];for(let S of n){if(`directory`in S&&S.directory===!0){a.push(buildHeader(ensureTrailingSlash(S.name),0,`5`,S.mode??493,S.mtime??0));continue}let n=S,C=typeof n.body==`string`?new TextEncoder().encode(n.body):n.body,N=n.mode??defaultFileMode(C);a.push(buildHeader(n.name,C.byteLength,`0`,N,n.mtime??0)),a.push(C);let F=padTo512(C.byteLength);F>0&&a.push(new Uint8Array(F))}return a.push(new Uint8Array(512*2)),concatChunks(a)}function buildHeader(n,a,S,C,N){let{prefix:F,basename:I}=splitPathForUstar(n),H=new Uint8Array(512);writeAscii(H,I,0,100),writeOctal(H,C&4095,100,7),H[107]=0,writeOctal(H,0,108,7),H[115]=0,writeOctal(H,0,116,7),H[123]=0,writeOctal(H,a,124,11),H[135]=0,writeOctal(H,N,136,11),H[147]=0;for(let n=148;n<156;n++)H[n]=32;H[156]=S.charCodeAt(0),writeAscii(H,`ustar\0`,257,6),writeAscii(H,`00`,263,2),F&&writeAscii(H,F,345,155);let W=0;for(let n=0;n<512;n++)W+=H[n];return writeAscii(H,W.toString(8).padStart(6,`0`),148,6),H[154]=0,H[155]=32,H}function splitPathForUstar(n){if(n.length<=100)return{prefix:``,basename:n};if(n.length>255)throw Error(`createTarball: path too long (${n.length} > 255 chars): ${n}`);for(let a=Math.min(n.length-1,155);a>0;a--)if(n[a]===`/`&&n.length-a-1<=100)return{prefix:n.slice(0,a),basename:n.slice(a+1)};throw Error(`createTarball: cannot split path into ustar prefix+basename (basename slot is 100 chars): ${n}`)}function writeAscii(n,a,S,C){let N=new TextEncoder().encode(a);if(N.length>C)throw Error(`createTarball: field too long (${N.length} > ${C}): "${a}"`);n.set(N,S)}function writeOctal(n,a,S,C){writeAscii(n,a.toString(8).padStart(C,`0`),S,C)}function padTo512(n){let a=n%512;return a===0?0:512-a}function ensureTrailingSlash(n){return n.endsWith(`/`)?n:`${n}/`}function defaultFileMode(n){return n.length>=2&&n[0]===35&&n[1]===33?493:420}function concatChunks(n){let a=0;for(let S of n)a+=S.byteLength;let S=new Uint8Array(a),C=0;for(let a of n)S.set(a,C),C+=a.byteLength;return S}var JE=__esmMin(()=>{});async function extractTarball(n,a,S={}){let C=n instanceof Uint8Array?n:new Uint8Array(n),N=parseTar(S.gzip??(C.length>=2&&C[0]===31&&C[1]===139)?await gunzip(C):C);mkdirSync(a,{recursive:!0});let F=S.strip??1,I=S.preventEscape??!0,H={files:[],directories:[],symlinks:[],skipped:0};for(let n of N){let C=stripComponents(n.name,F);if(C===null||C===``){H.skipped++;continue}let N=Oo(a,C);if(I&&!isInside(N,a))throw Error(`tar: refusing to extract ${n.name} outside ${a} (resolved=${N})`);if(S.filter&&!S.filter(n,N)){H.skipped++;continue}if(n.type===`directory`){mkdirSync(N,{recursive:!0}),H.directories.push(N);continue}if(n.type===`file`){mkdirSync(Po(N),{recursive:!0}),writeFileSync(N,n.body);let a=S.chmod?.(n,N)??n.mode&511;if(a>0)try{chmodSync(N,a)}catch{}H.files.push(N);continue}if(n.type===`symlink`){mkdirSync(Po(N),{recursive:!0});try{symlinkSync(n.linkname,N),H.symlinks.push(N)}catch{writeFileSync(N,n.linkname),H.files.push(N)}continue}H.skipped++}return H}async function gunzip(n){let a=globalThis.DecompressionStream;if(typeof a!=`function`)throw Error(`@gjsify/tar: globalThis.DecompressionStream is not available — import '@gjsify/compression-streams/register' on GJS to register it`);return drainStream(new Blob([new Uint8Array(n)]).stream().pipeThrough(new a(`gzip`)))}async function gzip(n){let a=globalThis.CompressionStream;if(typeof a!=`function`)throw Error(`@gjsify/tar: globalThis.CompressionStream is not available — import '@gjsify/compression-streams/register' on GJS to register it`);return drainStream(new Blob([new Uint8Array(n)]).stream().pipeThrough(new a(`gzip`)))}async function drainStream(n){let a=[],S=0,C=n.getReader();for(;;){let{value:n,done:N}=await C.read();if(N)break;let F=n instanceof Uint8Array?n:new Uint8Array(n);a.push(F),S+=F.length}let N=new Uint8Array(S),F=0;for(let n of a)N.set(n,F),F+=n.length;return N}function stripComponents(n,a){if(a<=0)return n;let S=n.split(`/`).filter(n=>n!==``);return S.length<=a?null:S.slice(a).join(`/`)}function isInside(n,a){let S=Mo(a,n);return S!==``&&!S.startsWith(`..`)&&!Ao(S)}var YE=__esmMin(()=>{qE(),As(),Ho()}),XE=__exportAll$3({BLOCK_SIZE:()=>512,TarParseError:()=>TarParseError,createTarball:()=>createTarball,extractTarball:()=>extractTarball,gunzip:()=>gunzip,gzip:()=>gzip,parseTar:()=>parseTar}),ZE=__esmMin(()=>{qE(),JE(),YE()}),QE=__exportAll$3({installPackagesNative:()=>installPackagesNative,parseSpec:()=>parseSpec,pickVersion:()=>pickVersion});async function installPackagesNative(n){if(n.specs.length===0)throw Error(`installPackagesNative: empty specs list`);mkdirSync(n.prefix,{recursive:!0});let a=await loadNpmrc$1(n),S=makeLogger(n.verbose??!1),C=jo(n.prefix,eD),N=readLockfile(C),F;if(n.frozen){if(!N)throw Error(`install: --immutable requires ${eD} at ${n.prefix} — none found. Run \`gjsify install\` (without --immutable) to generate one and commit it.`);let a=describeLockfileDrift(N,n.specs);if(a)throw Error(`install: --immutable but ${C} is stale.\n${a}\nRe-run \`gjsify install\` (without --immutable) to refresh the lockfile.`);S(`install: --immutable, using lockfile (%d package(s))`,Object.keys(N.packages).length),F=lockfileToNodes(N)}else N&&lockfileMatchesRequest(N,n.specs)?(S(`install: using lockfile (%d package(s))`,Object.keys(N.packages).length),F=lockfileToNodes(N)):(S(`install: resolving %d top-level spec(s) → %s`,n.specs.length,n.prefix),F=await resolveDeps(n.specs,a,S,n.overrides),n.lockfile&&(writeLockfile(C,n.specs,F),S(`install: wrote %s (%d entries)`,eD,F.length)));return S(`install: downloading %d tarball(s)`,F.length),await downloadAndExtractAll(F,n.prefix,a,S),await linkBins(F,n.prefix,S),S(`install: done`),topLevelResolutions(n.specs,F)}function errMsg(n){return n instanceof Error?n.message:String(n)}function topLevelResolutions(n,a){let S=new Map;for(let n of a)n.installPath===`node_modules/${n.name}`&&S.set(n.name,n);let C=[];for(let a of n){let n=parseSpecName(a),N=S.get(n);N&&C.push({name:N.name,version:N.version})}return C}function parseSpecName(n){if(n.startsWith(`@`)){let a=n.indexOf(`/`);if(a===-1)return n;let S=n.indexOf(`@`,a+1);return S===-1?n:n.slice(0,S)}let a=n.indexOf(`@`);return a===-1?n:n.slice(0,a)}async function resolveDeps(n,a,S,C){let applyOverride=(n,a)=>{if(!C)return a;let N=C[n];return typeof N!=`string`||N.length===0||N===a?a:(S(`install: override %s %s → %s`,n,a,N),N)},N=new Map,fetchPkg=n=>{let C=N.get(n);if(C)return C;let F=fetchPackument(n,{npmrc:a,onRetry:({attempt:a,error:C,delayMs:N})=>{S(`packument %s: retry %d after %dms (%s)`,n,a,N,errMsg(C))}});return N.set(n,F),F},F=new Map,I=new Map,H=n.map(parseSpec).map(n=>({from:null,name:n.name,range:applyOverride(n.name,n.range),required:!0}));for(;H.length>0;){let n=H.shift(),a=findVisible(n.from,n.name,F);if(a&&satisfiesRange(a.version,n.range))continue;let C=null;try{let a=await fetchPkg(n.name);if(C=pickVersion(a,n.range),!C){if(!n.required)continue;throw Error(`No version of ${n.name} satisfies ${n.range}`)}let N=a.versions[C];if(!N)throw Error(`Packument for ${n.name} promised ${C} but no entry exists`);let W=decidePlacement(n.from,n.name,C,I),K={name:n.name,version:C,tarballUrl:N.dist.tarball,integrity:N.dist.integrity,installPath:W,dependencies:N.dependencies??{},optionalDependencies:N.optionalDependencies??{},bin:N.bin};F.set(W,K),W===`node_modules/${n.name}`&&I.set(n.name,K),S(`resolve: %s@%s ← %s (at %s)`,n.name,C,n.range,W);for(let[n,a]of Object.entries(K.dependencies))H.push({from:W,name:n,range:applyOverride(n,a),required:!0});for(let[n,a]of Object.entries(K.optionalDependencies))H.push({from:W,name:n,range:applyOverride(n,a),required:!1})}catch(a){if(!n.required){S(`resolve: optional dep %s@%s skipped (%s)`,n.name,n.range,a.message);continue}throw a}}return Array.from(F.values())}function findVisible(n,a,S){let C=[];if(n!==null){C.push(`${n}/node_modules/${a}`);let S=n;for(;;){let n=S.lastIndexOf(`/node_modules/`);if(n<0||(S=S.slice(0,n),C.push(`${S}/node_modules/${a}`),S===``))break}}C.push(`node_modules/${a}`);for(let n of C){let a=S.get(n);if(a)return a}return null}function decidePlacement(n,a,S,C){let N=C.get(a);return!N||N.version===S||n===null?`node_modules/${a}`:`${n}/node_modules/${a}`}function satisfiesRange(n,a){try{return satisfies(n,new UE(a))}catch{return!1}}function readLockfile(n){if(!existsSync(n))return null;try{let a=JSON.parse(readFileSync(n,`utf-8`));return a.lockfileVersion!==tD||!a.packages||typeof a.packages!=`object`?null:a}catch{return null}}function writeLockfile(n,a,S){let C={},N=[...S].sort((n,a)=>n.installPath<a.installPath?-1:+(n.installPath>a.installPath));for(let n of N)C[n.installPath]={version:n.version,resolved:n.tarballUrl,integrity:n.integrity,dependencies:Object.keys(n.dependencies).length>0?n.dependencies:void 0,bin:n.bin};let F={lockfileVersion:tD,requested:[...a],packages:C};writeFileSync(n,JSON.stringify(F,null,2)+`
789
+ `:``)}function detectIndent$1(n){let a=n.match(/^\{\n( +)/);return a?a[1].length:2}__name$1(detectIndent$1,`detectIndent`),Ie(),As(),Hx(),qc();const FE=promisify(execFile),IE={command:`diff`,description:`Compare the per-app Flathub tracking-repo manifest against the local git state and report version / commit drift.`,builder:n=>n.version(!1).option(`version`,{description:"Local version to compare against. Default: `git describe --tags --abbrev=0` in cwd.",type:`string`}).option(`app-id`,{description:"Reverse-DNS app id. Default: `gjsify.flatpak.appId`.",type:`string`}).option(`flathub-repo`,{description:"Flathub tracking-repo (owner/name). Default: `gjsify.flatpak.flathubRepo` or `flathub/<appId>`.",type:`string`}).option(`against`,{description:`Read the Flathub manifest from a local file instead of fetching it. Useful in CI or offline.`,type:`string`}).option(`detail`,{description:`Also print the full Flathub manifest source entry alongside the resolved local version.`,type:`boolean`,default:!1}).option(`source-index`,{description:`Index into modules[0].sources[] to inspect (when the manifest has multiple sources).`,type:`number`}).option(`verbose`,{description:`Echo fetch URL + resolved values.`,type:`boolean`,default:!1}),handler:async n=>{let a=process.cwd(),S=(await new Config().forBuild({}).catch(()=>({}))).flatpak??{},C=n.appId??S.appId??readPackageJson(a).name;if(!C)throw Error(`[gjsify flatpak diff] no app id available — pass --app-id or set gjsify.flatpak.appId.`);let N=n.flathubRepo??S.flathubRepo??`flathub/${C}`,F=n.version??await resolveLatestTag(a,n.verbose),I=await loadFlathubSource({appId:C,flathubRepo:N,against:n.against,verbose:n.verbose},n.sourceIndex),H=I?.tag,W=I?.commit;if(Fe.log(`[gjsify flatpak diff] appId=${C}`),Fe.log(`[gjsify flatpak diff] flathubRepo=${N}`),Fe.log(`[gjsify flatpak diff] flathub: tag=${H??`(missing)`} commit=${W??`(missing)`}`),Fe.log(`[gjsify flatpak diff] local: tag=${F??`(none)`}`),n.detail&&I&&(Fe.log(`[gjsify flatpak diff] flathub manifest source:`),Fe.log(JSON.stringify(I,null,2))),!F){Fe.warn("[gjsify flatpak diff] no local git tag found — cut a release (`git tag vX.Y.Z`) or pass --version vX.Y.Z to compare against an explicit value.");return}if(H||(Fe.warn("[gjsify flatpak diff] flathub manifest has no `tag` field on the inspected source."),process.exit(1)),H===F){Fe.log(`✅ in sync (${F})`);return}Fe.log(`❌ drift detected — flathub=${H} vs local=${F}`),Fe.log(` run \`gjsify flatpak sync-flathub --version ${F}\` to update the Flathub manifest.`),process.exit(1)}};async function loadFlathubSource(n,a){let S;if(n.against){if(!existsSync(n.against))throw Error(`[gjsify flatpak diff] --against path ${n.against} does not exist`);S=readFileSync(n.against,`utf-8`)}else S=await fetchFlathubManifest(n.flathubRepo,n.appId,n.verbose);let C;try{C=JSON.parse(S)}catch(n){throw Error(`[gjsify flatpak diff] failed to parse Flathub manifest as JSON: ${n.message}`)}let N=(C.modules??[])[0]?.sources??[];if(N.length===0)return null;let F=a??N.findIndex(n=>n?.type===`git`);return F<0||F>=N.length?null:N[F]??null}async function fetchFlathubManifest(n,a,S){for(let C of[`master`,`main`]){let N=`https://raw.githubusercontent.com/${n}/${C}/${a}.json`;S&&Fe.log(`[gjsify flatpak diff] fetch ${N}`);try{let n=await fetch(N);if(n.ok)return await n.text();S&&Fe.log(`[gjsify flatpak diff] ${C} → HTTP ${n.status}`)}catch(n){S&&Fe.log(`[gjsify flatpak diff] ${C} fetch error: ${n.message}`)}}throw Error(`[gjsify flatpak diff] could not fetch flathub manifest from ${n} on master or main`)}async function resolveLatestTag(n,a){try{let{stdout:S}=await FE(`git`,[`describe`,`--tags`,`--abbrev=0`],{cwd:n}),C=S.trim();return a&&Fe.log(`[gjsify flatpak diff] local latest tag → ${C}`),C||null}catch{return null}}Ie(),Hx(),qc(),rn(),Ho();const LE=promisify(execFile),RE={command:`release <version>`,description:"Cut a release end-to-end: regenerate Flathub assets, run linters, create + push the git tag, then open the Flathub PR. Each step delegates to the equivalent `gjsify flatpak <sub>` command.",builder:n=>n.version(!1).positional(`version`,{description:"Release tag, e.g. `v0.6.6`.",type:`string`,demandOption:!0}).option(`skip-init`,{description:"Skip the `flatpak init --force` regen step.",type:`boolean`,default:!1}).option(`skip-check`,{description:"Skip the `flatpak check` linter step.",type:`boolean`,default:!1}).option(`skip-tag`,{description:"Skip the `git tag` + `git push --tags` step (use when the tag was already created out-of-band).",type:`boolean`,default:!1}).option(`push-tag`,{description:`Push the created tag after creating it. Default: true.`,type:`boolean`,default:!0}).option(`flathub-repo`,{description:`Flathub tracking-repo override forwarded to sync-flathub.`,type:`string`}).option(`dry-run`,{description:`Print each step that would run without executing any of them.`,type:`boolean`,default:!1}).option(`verbose`,{description:`Echo every sub-command invocation.`,type:`boolean`,default:!1}),handler:async n=>{let a=typeof n.version==`string`?n.version.trim():``;if(!a)throw Error(`[gjsify flatpak release] missing <version> positional`);let S=resolveCliEntry(),C=process.cwd(),N=[];n.skipInit||N.push({name:`init`,args:[S,`flatpak`,`init`,`--force`]}),n.skipCheck||N.push({name:`check`,args:[S,`flatpak`,`check`]});let F=[S,`flatpak`,`sync-flathub`,`--version`,a];if(n.flathubRepo&&F.push(`--flathub-repo`,n.flathubRepo),n.verbose&&F.push(`--verbose`),Fe.log(`[gjsify flatpak release] starting release of ${a}`),n.dryRun){Fe.log(`[gjsify flatpak release] --dry-run set; printing plan only:`);for(let n of N)Fe.log(` · ${n.name}: node ${n.args.join(` `)}`);n.skipTag||Fe.log(` · tag: git tag ${a}${n.pushTag===!1?``:` && git push origin `+a}`),Fe.log(` · sync: node ${F.join(` `)}`);return}for(let a of N)n.verbose&&Fe.log(`[gjsify flatpak release] step ${a.name}: node ${a.args.join(` `)}`),await runNode(a.args,C),Fe.log(`[gjsify flatpak release] ${a.name} ✔`);if(!n.skipTag){n.verbose&&Fe.log(`[gjsify flatpak release] git tag ${a}`);try{await LE(`git`,[`tag`,a],{cwd:C}),Fe.log(`[gjsify flatpak release] tag ${a} created`)}catch(n){throw Error(`[gjsify flatpak release] git tag failed (${n.message}). If the tag already exists, re-run with --skip-tag.`)}n.pushTag!==!1&&(n.verbose&&Fe.log(`[gjsify flatpak release] git push origin ${a}`),await LE(`git`,[`push`,`origin`,a],{cwd:C}),Fe.log(`[gjsify flatpak release] tag pushed`))}n.verbose&&Fe.log(`[gjsify flatpak release] sync: node ${F.join(` `)}`),await runNode(F,C),Fe.log(`[gjsify flatpak release] ✅ release ${a} complete`)}};function resolveCliEntry(){return Oo(Oo(Po(fileURLToPath(import.meta.url)),`..`,`..`),`index.js`)}async function runNode(n,a){await new Promise((S,C)=>{let N=spawn(`node`,n,{cwd:a,stdio:`inherit`});N.on(`error`,C),N.on(`exit`,a=>{a===0?S():C(Error(`sub-command exited with code ${a}: node ${n.join(` `)}`))})})}const zE={command:`flatpak <subcommand>`,description:`Flatpak toolchain: init/build/deps/ci/check/sync-flathub/diff/release subcommands for shipping GJS apps and CLIs as Flatpaks.`,builder:n=>n.command(OE.command,OE.description,OE.builder,OE.handler).command(kE.command,kE.description,kE.builder,kE.handler).command(AE.command,AE.description,AE.builder,AE.handler).command(jE.command,jE.description,jE.builder,jE.handler).command(ME.command,ME.description,ME.builder,ME.handler).command(PE.command,PE.description,PE.builder,PE.handler).command(IE.command,IE.description,IE.builder,IE.handler).command(RE.command,RE.description,RE.builder,RE.handler).demandCommand(1).strict()};As(),Ho();const BE=/^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;function parseSpec$1(n){if(!n)throw Error(`dlx: empty package spec`);if(n.startsWith(`./`)||n.startsWith(`../`)||Ao(n)||existsSync(n))return{kind:`local`,path:Oo(n)};let a=n,S,C=n.lastIndexOf(`@`);if(C>0&&(a=n.slice(0,C),S=n.slice(C+1)),!BE.test(a))throw Error(`dlx: invalid package name "${a}"`);return{kind:`registry`,name:a,version:S,spec:n}}__name$1(parseSpec$1,`parseSpec`),As(),Ho();function resolveGjsEntry(n,a){let S=jo(n,`package.json`);if(!existsSync(S))throw Error(`dlx: no package.json found at ${n}`);let C=JSON.parse(readFileSync(S,`utf-8`)),N=C.gjsify?.bin,F=C.gjsify?.main,I=C.main,H,W=null,K=!1;if(a!==null){if(!N||!N[a]){let S=N?Object.keys(N).join(`, `):`(none)`;throw Error(`dlx: package "${C.name??n}" has no GJS bin named "${a}" — known: ${S}`)}H=N[a],W=a}else if(N&&Object.keys(N).length===1){let n=Object.keys(N)[0];H=N[n],W=n}else F?H=F:I&&(H=I,K=!0);if(N&&Object.keys(N).length>1&&a===null){let a=Object.keys(N).join(`, `);throw Error(`dlx: package "${C.name??n}" defines multiple GJS bins — pass one of: ${a}`)}if(!H)throw Error(`dlx: package "${C.name??n}" has no GJS entry — set \`gjsify.main\` (or \`gjsify.bin\`) in its package.json`);let q=Oo(n,H);if(!existsSync(q))throw Error(`dlx: GJS entry not found: ${q}`);return{bundlePath:q,binName:W,fromFallback:K}}Ga(),As(),kp(),Ho();function lexCompare(n,a){return n<a?-1:+(n>a)}function createCacheKey(n){let a=[...n.packages].sort(lexCompare),S=Object.entries(n.registries??{}).sort(([n],[a])=>lexCompare(n,a)),C=JSON.stringify([a,S]);return createHash(`sha256`).update(C).digest(`hex`)}function dlxCacheRoot(){let n=process.env.XDG_CACHE_HOME,a=jo(n&&n.length>0?n:jo(homedir(),`.cache`),`gjsify`,`dlx`);return mkdirSync(a,{recursive:!0}),a}function cacheDirFor(n){let a=jo(dlxCacheRoot(),n);return mkdirSync(a,{recursive:!0}),a}function makePrepareDir(n){let a=jo(n,`${Date.now().toString(16)}-${process.pid.toString(16)}`);return mkdirSync(a,{recursive:!0}),a}function getValidCachedPkg(n,a=10080){let S=jo(n,`pkg`),C;try{C=lstatSync(S)}catch(n){if(n.code===`ENOENT`)return;throw n}if(!C.isSymbolicLink())return;let N;try{N=realpathSync(S)}catch{return}return Date.now()-C.mtime.getTime()<=a*6e4?N:void 0}function symlinkSwap(n,a){let S=jo(n,`pkg`),C=jo(n,`pkg.tmp-${Date.now().toString(16)}-${process.pid.toString(16)}`);try{symlinkSync(a,C,`dir`)}catch(n){throw n}try{renameSync(C,S)}catch(n){let a=n.code;if(a===`EBUSY`||a===`EPERM`||a===`EEXIST`){try{rmSync(C)}catch{}return realpathSync(S)}throw n}return realpathSync(S)}function resolveInstalledPkgDir(n,a){return Oo(n,`node_modules`,a)}function parse(n){try{return new SemVer(n)}catch{return null}}function satisfies(n,a){let S=a instanceof UE?a:new UE(a),C=n instanceof SemVer?n:parse(String(n));return C?S.test(C):!1}function maxSatisfying(n,a){let S=a instanceof UE?a:new UE(a),C=null;for(let a of n){let n=parse(a);!n||!S.test(n)||(C===null||n.compare(C)>0)&&(C=n)}return C?C.version:null}function testComparator(n,a){if(n.semver===null)return!0;let S=a.compare(n.semver);switch(n.operator){case``:case`=`:return S===0;case`<`:return S<0;case`<=`:return S<=0;case`>`:return S>0;case`>=`:return S>=0}}function formatComparator(n){return n.semver===null?`*`:`${n.operator}${n.semver.version}`}function parseRangePart(n){let a=n.trim();if(a===``||a===`*`||a.toLowerCase()===`latest`)return[{operator:`>=`,semver:new SemVer(`0.0.0`)}];let S=a.match(/^\s*(\S+)\s+-\s+(\S+)\s*$/);if(S)return hyphenRange(S[1],S[2]);let C=a.replace(/(<=|>=|<|>|=)\s+(?=\S)/g,`$1`).split(/\s+/),N=[];for(let n of C)N.push(...parseSimple(n));return N}function parseSimple(n){if(n===`*`||n===``||n.toLowerCase()===`latest`)return[{operator:`>=`,semver:new SemVer(`0.0.0`)}];if(n.startsWith(`^`))return caretRange(n.slice(1));if(n.startsWith(`~`))return tildeRange(n.slice(1).replace(/^>/,``));let a=n.match(/^(<=|>=|<|>|=)\s*(.+)$/);if(a){let n=a[1];return primitiveRange(n,a[2])}return partialRange(n)}function parsePartial(n){let a=n.trim().replace(/^v/,``);if(a===``||a===`*`)return{major:null,minor:null,patch:null,pre:``,build:``};let S=``,C=``,N=a,F=N.indexOf(`+`);F>=0&&(C=N.slice(F+1),N=N.slice(0,F));let I=N.indexOf(`-`);I>=0&&(S=N.slice(I+1),N=N.slice(0,I));let H=N.split(`.`),xr=a=>{if(a===void 0||a===``||a===`x`||a===`X`||a===`*`)return null;if(!/^\d+$/.test(a))throw TypeError(`Invalid partial version: ${n}`);return Number(a)};return{major:xr(H[0]),minor:xr(H[1]),patch:xr(H[2]),pre:S,build:C}}function partialToVersion(n){return`${n.major??0}.${n.minor??0}.${n.patch??0}${n.pre?`-${n.pre}`:``}${n.build?`+${n.build}`:``}`}function partialRange(n){let a=parsePartial(n);return a.major===null?[{operator:`>=`,semver:new SemVer(`0.0.0`)}]:a.minor===null?[{operator:`>=`,semver:new SemVer(`${a.major}.0.0`)},{operator:`<`,semver:new SemVer(`${a.major+1}.0.0`)}]:a.patch===null?[{operator:`>=`,semver:new SemVer(`${a.major}.${a.minor}.0`)},{operator:`<`,semver:new SemVer(`${a.major}.${a.minor+1}.0`)}]:[{operator:`=`,semver:new SemVer(partialToVersion(a))}]}function caretRange(n){let a=parsePartial(n);if(a.major===null)return[{operator:`>=`,semver:new SemVer(`0.0.0`)}];let S=`${a.major}.${a.minor??0}.${a.patch??0}${a.pre?`-${a.pre}`:``}`,C;return C=a.major>0||a.minor===null?`${a.major+1}.0.0`:a.minor>0||a.patch===null?`0.${a.minor+1}.0`:`0.0.${a.patch+1}`,[{operator:`>=`,semver:new SemVer(S)},{operator:`<`,semver:new SemVer(C)}]}function tildeRange(n){let a=parsePartial(n);if(a.major===null)return[{operator:`>=`,semver:new SemVer(`0.0.0`)}];let S=`${a.major}.${a.minor??0}.${a.patch??0}${a.pre?`-${a.pre}`:``}`,C=a.minor===null?`${a.major+1}.0.0`:`${a.major}.${a.minor+1}.0`;return[{operator:`>=`,semver:new SemVer(S)},{operator:`<`,semver:new SemVer(C)}]}function primitiveRange(n,a){let S=parsePartial(a);return S.major===null?[{operator:`>=`,semver:new SemVer(`0.0.0`)}]:n===`=`||n===``?partialRange(a):n===`>`?S.minor===null?[{operator:`>=`,semver:new SemVer(`${S.major+1}.0.0`)}]:S.patch===null?[{operator:`>=`,semver:new SemVer(`${S.major}.${S.minor+1}.0`)}]:[{operator:`>`,semver:new SemVer(partialToVersion(S))}]:n===`<`?S.minor===null?[{operator:`<`,semver:new SemVer(`${S.major}.0.0`)}]:S.patch===null?[{operator:`<`,semver:new SemVer(`${S.major}.${S.minor}.0`)}]:[{operator:`<`,semver:new SemVer(partialToVersion(S))}]:n===`>=`?[{operator:`>=`,semver:new SemVer(partialToVersion(S))}]:S.minor===null?[{operator:`<`,semver:new SemVer(`${S.major+1}.0.0`)}]:S.patch===null?[{operator:`<`,semver:new SemVer(`${S.major}.${S.minor+1}.0`)}]:[{operator:`<=`,semver:new SemVer(partialToVersion(S))}]}function hyphenRange(n,a){let S=parsePartial(n),C=parsePartial(a),N=S.major===null?{operator:`>=`,semver:new SemVer(`0.0.0`)}:{operator:`>=`,semver:new SemVer(`${S.major}.${S.minor??0}.${S.patch??0}${S.pre?`-${S.pre}`:``}`)},F;return F=C.major===null?{operator:`>=`,semver:new SemVer(`0.0.0`)}:C.minor===null?{operator:`<`,semver:new SemVer(`${C.major+1}.0.0`)}:C.patch===null?{operator:`<`,semver:new SemVer(`${C.major}.${C.minor+1}.0`)}:{operator:`<=`,semver:new SemVer(`${C.major}.${C.minor}.${C.patch}${C.pre?`-${C.pre}`:``}`)},[N,F]}var VE,HE,SemVer,UE,WE=__esmMin(()=>{VE=/^(0|[1-9]\d*)$/,HE=/^(\d+)\.(\d+)\.(\d+)(?:-((?:[0-9A-Za-z-]+)(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/,SemVer=class{major;minor;patch;prerelease;build;version;constructor(n){let a=String(n).trim().replace(/^v/,``),S=HE.exec(a);if(!S)throw TypeError(`Invalid Version: ${n}`);this.major=Number(S[1]),this.minor=Number(S[2]),this.patch=Number(S[3]),this.prerelease=S[4]?S[4].split(`.`).map(n=>VE.test(n)?Number(n):n):[],this.build=S[5]?S[5].split(`.`):[],this.version=`${this.major}.${this.minor}.${this.patch}`+(this.prerelease.length?`-${this.prerelease.join(`.`)}`:``)+(this.build.length?`+${this.build.join(`.`)}`:``)}compare(n){return this.major===n.major?this.minor===n.minor?this.patch===n.patch?this.comparePre(n):this.patch<n.patch?-1:1:this.minor<n.minor?-1:1:this.major<n.major?-1:1}comparePre(n){let a=this.prerelease,S=n.prerelease;if(a.length===0&&S.length===0)return 0;if(a.length===0)return 1;if(S.length===0)return-1;for(let n=0;;n++){let C=a[n],N=S[n];if(C===void 0&&N===void 0)return 0;if(N===void 0)return 1;if(C===void 0)return-1;if(C===N)continue;let F=typeof C==`number`,I=typeof N==`number`;return F&&!I?-1:!F&&I?1:C<N?-1:1}}toString(){return this.version}},UE=class Range{raw;set;constructor(n){if(n instanceof Range){this.raw=n.raw,this.set=n.set;return}this.raw=String(n).trim();let a=this.raw.split(/\s*\|\|\s*/),S=[];for(let n of a){let a=parseRangePart(n);if(a.length===0)throw TypeError(`Invalid range: ${this.raw}`);S.push(a)}if(S.length===0)throw TypeError(`Invalid range: ${this.raw}`);this.set=S}test(n){let a=n instanceof SemVer?n:parse(String(n));if(!a)return!1;for(let n of this.set)if(n.every(n=>testComparator(n,a))){if(a.prerelease.length>0&&!n.some(n=>n.semver!==null&&n.semver.prerelease.length>0&&n.semver.major===a.major&&n.semver.minor===a.minor&&n.semver.patch===a.patch))continue;return!0}return!1}format(){return this.set.map(n=>n.map(formatComparator).join(` `)).join(` || `)}toString(){return this.format()}}});function assertPackument(n,a){if(!a||typeof a!=`object`)throw TypeError(`registry: ${n} packument is not an object`);let S=a;if(typeof S.name!=`string`)throw TypeError(`registry: ${n} packument missing string name`);if(!S.versions||typeof S.versions!=`object`)throw TypeError(`registry: ${n} packument missing versions map`)}function registryFor(n,a){if(a&&n.startsWith(`@`)){let S=n.slice(0,n.indexOf(`/`)),C=a.scopes[S];if(C)return ensureTrailingSlash$1(C)}return a?.registry?ensureTrailingSlash$1(a.registry):GE}function packumentUrl(n,a){let S=ensureTrailingSlash$1(a);if(n.startsWith(`@`)){let a=n.indexOf(`/`);if(a<0)throw TypeError(`Invalid scoped package name: ${n}`);let C=n.slice(0,a),N=n.slice(a+1);return`${S}${encodeURIComponent(C)}/${encodeURIComponent(N)}`}return`${S}${encodeURIComponent(n)}`}async function fetchPackument(n,a={}){let S=packumentUrl(n,a.registry??registryFor(n,a.npmrc)),C=buildHeaders(S,a);C.accept??=`application/vnd.npm.install-v1+json`;let N=await fetchWithRetry(S,{headers:C,signal:a.signal},a);if(!N.ok)throw N.status===404||N.status===406?new PackageNotFoundError(n,S):Error(`registry GET ${S} -> ${N.status} ${N.statusText}`);let F=await N.json();return assertPackument(n,F),F}async function fetchTarball(n,a={}){let S=buildHeaders(n,a);S.accept??=`application/octet-stream`;let C=await fetchWithRetry(n,{headers:S,signal:a.signal},a);if(!C.ok)throw Error(`tarball GET ${n} -> ${C.status} ${C.statusText}`);let N=new Uint8Array(await C.arrayBuffer());if(a.integrity&&!await verifyIntegrity(N,a.integrity))throw new IntegrityError(n,a.integrity);return N}async function fetchWithRetry(n,a,S){let C=S.fetch??globalThis.fetch;if(!C)throw Error(`@gjsify/npm-registry: globalThis.fetch is missing`);let N=Math.max(0,S.retries??3),F=Math.max(0,S.retryDelayMs??250),I=0,H;for(;;){if(a.signal?.aborted)throw signalAbortError(a.signal);try{let S=await C(n,a);if(S.ok||!isRetryableStatus(S.status)||I>=N)return S;try{await S.arrayBuffer()}catch{}H=Error(`HTTP ${S.status} ${S.statusText}`)}catch(n){if(!isRetryableError(n)||I>=N)throw n;H=n}let W=Math.min(F*2**I,8e3);S.onRetry?.({attempt:I+1,error:H,delayMs:W}),await delay(W,a.signal),I++}}function isRetryableStatus(n){return n===408||n===425||n===429||n===500||n===502||n===503||n===504||n===521||n===522||n===524||n===525}function isRetryableError(n){if(n&&typeof n==`object`&&`name`in n&&n.name===`AbortError`)return!1;if(n instanceof TypeError)return!0;if(n&&typeof n==`object`&&`name`in n){let a=n.name;if(a===`FetchError`)return!0;if(a===`AbortError`)return!1}let a=n?.cause;if(a&&typeof a==`object`&&`code`in a){let n=a.code;if(typeof n==`string`)return n===`ECONNRESET`||n===`ECONNREFUSED`||n===`ENETUNREACH`||n===`ENOTFOUND`||n===`ETIMEDOUT`||n===`EAI_AGAIN`||n===`UND_ERR_SOCKET`||n===`UND_ERR_CONNECT_TIMEOUT`}return!1}function delay(n,a){return n<=0?Promise.resolve():new Promise((S,C)=>{let N=setTimeout(()=>{a?.removeEventListener?.(`abort`,onAbort),S()},n),onAbort=()=>{clearTimeout(N),C(signalAbortError(a))};if(a?.aborted){clearTimeout(N),C(signalAbortError(a));return}a?.addEventListener?.(`abort`,onAbort,{once:!0})})}function signalAbortError(n){let a=n&&`reason`in n?n.reason:void 0;if(a instanceof Error)return a;let S=Error(`Aborted`);return S.name=`AbortError`,S}async function verifyIntegrity(n,a){let S=a.trim().split(/\s+/);for(let a of S){let S=a.indexOf(`-`);if(S<0)continue;let C=a.slice(0,S).toLowerCase(),N=a.slice(S+1),F=globalThis.crypto?.subtle;if(!F)throw Error(`@gjsify/npm-registry: globalThis.crypto.subtle is missing`);let I=subriToWebCryptoAlgo(C);if(!I)continue;let H=await F.digest(I,dataAsArrayBuffer(n));if(bytesToBase64(new Uint8Array(H))===N)return!0}return!1}function subriToWebCryptoAlgo(n){switch(n){case`sha1`:return`SHA-1`;case`sha256`:return`SHA-256`;case`sha384`:return`SHA-384`;case`sha512`:return`SHA-512`;default:return null}}function dataAsArrayBuffer(n){if(n.byteOffset===0&&n.byteLength===n.buffer.byteLength)return n.buffer;let a=new Uint8Array(n.byteLength);return a.set(n),a.buffer}function bytesToBase64(n){let a=``;for(let S=0;S<n.length;S++)a+=String.fromCharCode(n[S]);return btoa(a)}function parseNpmrc(n){let a={registry:GE,scopes:{},authTokens:{},basicAuth:{}},S=n.split(/\r?\n/),C={};for(let n of S){let S=n.replace(/^\s+|\s+$/g,``);if(!S||S.startsWith(`#`)||S.startsWith(`;`))continue;let N=S.indexOf(`=`);if(N<0)continue;let F=S.slice(0,N).trim(),I=expandEnv(stripQuotes(S.slice(N+1).trim()));if(F===`registry`){a.registry=ensureTrailingSlash$1(I);continue}let H=F.match(/^(@[^:]+):registry$/);if(H){a.scopes[H[1]]=ensureTrailingSlash$1(I);continue}let W=F.match(/^\/\/(.+):_authToken$/);if(W){a.authTokens[normalizeAuthHost(W[1])]=I;continue}let K=F.match(/^\/\/(.+):username$/);if(K){(C[normalizeAuthHost(K[1])]??={}).user=I;continue}let q=F.match(/^\/\/(.+):_password$/);if(q){let n=base64Decode(I);(C[normalizeAuthHost(q[1])]??={}).pass=n;continue}}for(let[n,S]of Object.entries(C))S.user&&S.pass!==void 0&&(a.basicAuth[n]={username:S.user,password:S.pass});return a}function buildHeaders(n,a){let S={"user-agent":`gjsify-install/0.3.7`,"accept-encoding":`identity`};if(a.npmrc){let C=resolveAuthForUrl(n,a.npmrc);C&&(S.authorization=C)}if(a.headers)for(let[n,C]of Object.entries(a.headers))S[n.toLowerCase()]=C;return S}function resolveAuthForUrl(n,a){let S=pathPrefixes(new URL(n));for(let n of S){let S=a.authTokens[n];if(S)return`Bearer ${S}`;let C=a.basicAuth[n];if(C)return`Basic ${btoa(`${C.username}:${C.password}`)}`}return null}function pathPrefixes(n){let a=n.pathname.split(`/`).filter(Boolean),S=[];for(let C=a.length;C>=0;C--){let N=a.slice(0,C).join(`/`);S.push(N?`//${n.host}/${N}`:`//${n.host}`)}return S}function normalizeAuthHost(n){return`//${n.replace(/\/+$/,``)}`}function ensureTrailingSlash$1(n){return n.endsWith(`/`)?n:n+`/`}function stripQuotes(n){return n.startsWith(`"`)&&n.endsWith(`"`)||n.startsWith(`'`)&&n.endsWith(`'`)?n.slice(1,-1):n}function expandEnv(n){return n.replace(/\$\{([A-Z0-9_]+)\}/gi,(n,a)=>globalThis.process?.env?.[a]??``)}function base64Decode(n){return atob(n)}var GE,PackageNotFoundError,IntegrityError,KE=__esmMin(()=>{GE=`https://registry.npmjs.org/`,__name$1(ensureTrailingSlash$1,`ensureTrailingSlash`),PackageNotFoundError=class extends Error{name;url;constructor(n,a){super(`Package not found in registry: ${n} (${a})`),this.name=n,this.url=a,this.name=`PackageNotFoundError`}},IntegrityError=class extends Error{url;integrity;constructor(n,a){super(`Tarball integrity mismatch for ${n} (expected ${a})`),this.url=n,this.integrity=a,this.name=`IntegrityError`}}});function parseTar(n){let a=[],S=null,C=null,N=null,F=0;for(;F+512<=n.length;){let I=n.subarray(F,F+512);if(allZeros(I)){let a=n.subarray(F+512,F+2*512);if(a.length===512&&allZeros(a))break;F+=512;continue}if(!validateChecksum(I))throw new TarParseError(`Bad header checksum at offset ${F} — file is not a valid tar archive`);let H=readString(I,0,100),W=parseOctal(I,100,8),K=parseOctal(I,124,12),q=parseOctal(I,136,12),Y=String.fromCharCode(I[156]||0),X=readString(I,157,100),te=readString(I,257,6),ne=readString(I,345,155),re=readString(I,265,32),ie=readString(I,297,32);F+=512;let ae=n.subarray(F,F+K);if(F+=alignToBlock(K),Y===`x`){S=parsePaxRecords(ae);continue}if(Y===`g`)continue;if(Y===`L`){C=bytesToString(ae).replace(/\0+$/,``);continue}if(Y===`K`){N=bytesToString(ae).replace(/\0+$/,``);continue}let oe=H;te===`ustar`&&ne!==``&&(oe=`${ne}/${H}`),C!==null&&(oe=C,C=null);let Z=X;if(N!==null&&(Z=N,N=null),S!==null){let C=S.get(`path`);C!==void 0&&(oe=C);let N=S.get(`linkpath`);N!==void 0&&(Z=N);let I=S.get(`size`);if(I!==void 0){let C=Number(I);if(Number.isFinite(C)){let N=F-alignToBlock(K),I=n.subarray(N,N+C);F=N+alignToBlock(C),S=null,a.push(buildEntry(oe,Z,Y,W,q,re,ie,I));continue}}S=null}a.push(buildEntry(oe,Z,Y,W,q,re,ie,ae))}return a}function buildEntry(n,a,S,C,N,F,I,H){return{name:n,linkname:a,type:typeflagToType(S,n),mode:C,mtime:N,body:H,uname:F,gname:I}}function typeflagToType(n,a){switch(n){case`0`:case`\0`:case``:return a.endsWith(`/`)?`directory`:`file`;case`1`:return`hardlink`;case`2`:return`symlink`;case`5`:return`directory`;case`x`:return`pax-header`;case`g`:return`pax-global`;case`L`:return`gnu-longname`;case`K`:return`gnu-longlink`;default:return`unknown`}}function parsePaxRecords(n){let a=new Map,S=0;for(;S<n.length;){let C=S;for(;C<n.length&&n[C]!==32;)C++;if(C>=n.length)break;let N=bytesToString(n.subarray(S,C)),F=Number(N);if(!Number.isFinite(F)||F<=0)break;let I=S+F;if(I>n.length)break;let H=bytesToString(n.subarray(C+1,I-1)),W=H.indexOf(`=`);if(W>0){let n=H.slice(0,W),S=H.slice(W+1);a.set(n,S)}S=I}return a}function readString(n,a,S){let C=a,N=a+S;for(;C<N&&n[C]!==0;)C++;return bytesToString(n.subarray(a,C))}function bytesToString(n){return new TextDecoder(`utf-8`,{fatal:!1}).decode(n)}function parseOctal(n,a,S){if(S>0&&n[a]&128){let C=n[a]&127;for(let N=1;N<S;N++)C=C*256+n[a+N];return C}let C=``;for(let N=0;N<S;N++){let S=n[a+N];S===0||S===32||(C+=String.fromCharCode(S))}return C===``?0:parseInt(C,8)}function alignToBlock(n){return Math.ceil(n/512)*512}function allZeros(n){for(let a=0;a<n.length;a++)if(n[a]!==0)return!1;return!0}function validateChecksum(n){let a=parseOctal(n,148,8),S=0,C=0;for(let a=0;a<512;a++){let N=a>=148&&a<156?32:n[a];S+=N,C+=N>127?N-256:N}return a===S||a===C}var TarParseError,qE=__esmMin(()=>{TarParseError=class extends Error{constructor(n){super(n),this.name=`TarParseError`}}});function createTarball(n){let a=[];for(let S of n){if(`directory`in S&&S.directory===!0){a.push(buildHeader(ensureTrailingSlash(S.name),0,`5`,S.mode??493,S.mtime??0));continue}let n=S,C=typeof n.body==`string`?new TextEncoder().encode(n.body):n.body,N=n.mode??defaultFileMode(C);a.push(buildHeader(n.name,C.byteLength,`0`,N,n.mtime??0)),a.push(C);let F=padTo512(C.byteLength);F>0&&a.push(new Uint8Array(F))}return a.push(new Uint8Array(512*2)),concatChunks(a)}function buildHeader(n,a,S,C,N){let{prefix:F,basename:I}=splitPathForUstar(n),H=new Uint8Array(512);writeAscii(H,I,0,100),writeOctal(H,C&4095,100,7),H[107]=0,writeOctal(H,0,108,7),H[115]=0,writeOctal(H,0,116,7),H[123]=0,writeOctal(H,a,124,11),H[135]=0,writeOctal(H,N,136,11),H[147]=0;for(let n=148;n<156;n++)H[n]=32;H[156]=S.charCodeAt(0),writeAscii(H,`ustar\0`,257,6),writeAscii(H,`00`,263,2),F&&writeAscii(H,F,345,155);let W=0;for(let n=0;n<512;n++)W+=H[n];return writeAscii(H,W.toString(8).padStart(6,`0`),148,6),H[154]=0,H[155]=32,H}function splitPathForUstar(n){if(n.length<=100)return{prefix:``,basename:n};if(n.length>255)throw Error(`createTarball: path too long (${n.length} > 255 chars): ${n}`);for(let a=Math.min(n.length-1,155);a>0;a--)if(n[a]===`/`&&n.length-a-1<=100)return{prefix:n.slice(0,a),basename:n.slice(a+1)};throw Error(`createTarball: cannot split path into ustar prefix+basename (basename slot is 100 chars): ${n}`)}function writeAscii(n,a,S,C){let N=new TextEncoder().encode(a);if(N.length>C)throw Error(`createTarball: field too long (${N.length} > ${C}): "${a}"`);n.set(N,S)}function writeOctal(n,a,S,C){writeAscii(n,a.toString(8).padStart(C,`0`),S,C)}function padTo512(n){let a=n%512;return a===0?0:512-a}function ensureTrailingSlash(n){return n.endsWith(`/`)?n:`${n}/`}function defaultFileMode(n){return n.length>=2&&n[0]===35&&n[1]===33?493:420}function concatChunks(n){let a=0;for(let S of n)a+=S.byteLength;let S=new Uint8Array(a),C=0;for(let a of n)S.set(a,C),C+=a.byteLength;return S}var JE=__esmMin(()=>{});async function extractTarball(n,a,S={}){let C=n instanceof Uint8Array?n:new Uint8Array(n),N=parseTar(S.gzip??(C.length>=2&&C[0]===31&&C[1]===139)?await gunzip(C):C);mkdirSync(a,{recursive:!0});let F=S.strip??1,I=S.preventEscape??!0,H={files:[],directories:[],symlinks:[],skipped:0};for(let n of N){let C=stripComponents(n.name,F);if(C===null||C===``){H.skipped++;continue}let N=Oo(a,C);if(I&&!isInside(N,a))throw Error(`tar: refusing to extract ${n.name} outside ${a} (resolved=${N})`);if(S.filter&&!S.filter(n,N)){H.skipped++;continue}if(n.type===`directory`){mkdirSync(N,{recursive:!0}),H.directories.push(N);continue}if(n.type===`file`){mkdirSync(Po(N),{recursive:!0}),writeFileSync(N,n.body);let a=S.chmod?.(n,N)??n.mode&511;if(a>0)try{chmodSync(N,a)}catch{}H.files.push(N);continue}if(n.type===`symlink`){mkdirSync(Po(N),{recursive:!0});try{symlinkSync(n.linkname,N),H.symlinks.push(N)}catch{writeFileSync(N,n.linkname),H.files.push(N)}continue}H.skipped++}return H}async function gunzip(n){let a=globalThis.DecompressionStream;if(typeof a!=`function`)throw Error(`@gjsify/tar: globalThis.DecompressionStream is not available — import '@gjsify/compression-streams/register' on GJS to register it`);return drainStream(new Blob([new Uint8Array(n)]).stream().pipeThrough(new a(`gzip`)))}async function gzip(n){let a=globalThis.CompressionStream;if(typeof a!=`function`)throw Error(`@gjsify/tar: globalThis.CompressionStream is not available — import '@gjsify/compression-streams/register' on GJS to register it`);return drainStream(new Blob([new Uint8Array(n)]).stream().pipeThrough(new a(`gzip`)))}async function drainStream(n){let a=[],S=0,C=n.getReader();for(;;){let{value:n,done:N}=await C.read();if(N)break;let F=n instanceof Uint8Array?n:new Uint8Array(n);a.push(F),S+=F.length}let N=new Uint8Array(S),F=0;for(let n of a)N.set(n,F),F+=n.length;return N}function stripComponents(n,a){if(a<=0)return n;let S=n.split(`/`).filter(n=>n!==``);return S.length<=a?null:S.slice(a).join(`/`)}function isInside(n,a){let S=Mo(a,n);return S!==``&&!S.startsWith(`..`)&&!Ao(S)}var YE=__esmMin(()=>{qE(),As(),Ho()}),XE=__exportAll$3({BLOCK_SIZE:()=>512,TarParseError:()=>TarParseError,createTarball:()=>createTarball,extractTarball:()=>extractTarball,gunzip:()=>gunzip,gzip:()=>gzip,parseTar:()=>parseTar}),ZE=__esmMin(()=>{qE(),JE(),YE()}),QE=__exportAll$3({installPackagesNative:()=>installPackagesNative,parseSpec:()=>parseSpec,pickVersion:()=>pickVersion});async function installPackagesNative(n){if(n.specs.length===0)throw Error(`installPackagesNative: empty specs list`);mkdirSync(n.prefix,{recursive:!0});let a=await loadNpmrc$1(n),S=makeLogger(n.verbose??!1),C=jo(n.prefix,eD),N=readLockfile(C),F;if(n.frozen){if(!N)throw Error(`install: --immutable requires ${eD} at ${n.prefix} — none found. Run \`gjsify install\` (without --immutable) to generate one and commit it.`);let a=describeLockfileDrift(N,n.specs);if(a)throw Error(`install: --immutable but ${C} is stale.\n${a}\nRe-run \`gjsify install\` (without --immutable) to refresh the lockfile.`);S(`install: --immutable, using lockfile (%d package(s))`,Object.keys(N.packages).length),F=lockfileToNodes(N)}else N&&lockfileMatchesRequest(N,n.specs)?(S(`install: using lockfile (%d package(s))`,Object.keys(N.packages).length),F=lockfileToNodes(N)):(S(`install: resolving %d top-level spec(s) → %s`,n.specs.length,n.prefix),F=await resolveDeps(n.specs,a,S,n.overrides,n.skipDeps),n.lockfile&&(writeLockfile(C,n.specs,F),S(`install: wrote %s (%d entries)`,eD,F.length)));return S(`install: downloading %d tarball(s)`,F.length),await downloadAndExtractAll(F,n.prefix,a,S),await linkBins(F,n.prefix,S),S(`install: done`),topLevelResolutions(n.specs,F)}function errMsg(n){return n instanceof Error?n.message:String(n)}function topLevelResolutions(n,a){let S=new Map;for(let n of a)n.installPath===`node_modules/${n.name}`&&S.set(n.name,n);let C=[];for(let a of n){let n=parseSpecName(a),N=S.get(n);N&&C.push({name:N.name,version:N.version})}return C}function parseSpecName(n){if(n.startsWith(`@`)){let a=n.indexOf(`/`);if(a===-1)return n;let S=n.indexOf(`@`,a+1);return S===-1?n:n.slice(0,S)}let a=n.indexOf(`@`);return a===-1?n:n.slice(0,a)}async function resolveDeps(n,a,S,C,N){let applyOverride=(n,a)=>{if(!C)return a;let N=C[n];return typeof N!=`string`||N.length===0||N===a?a:(S(`install: override %s %s → %s`,n,a,N),N)},F=new Map,fetchPkg=n=>{let C=F.get(n);if(C)return C;let N=fetchPackument(n,{npmrc:a,onRetry:({attempt:a,error:C,delayMs:N})=>{S(`packument %s: retry %d after %dms (%s)`,n,a,N,errMsg(C))}});return F.set(n,N),N},I=new Map,H=new Map,W=n.map(parseSpec).map(n=>({from:null,name:n.name,range:applyOverride(n.name,n.range),required:!0}));for(;W.length>0;){let n=W.shift(),a=findVisible(n.from,n.name,I);if(a&&satisfiesRange(a.version,n.range))continue;let C=null;try{let a=await fetchPkg(n.name);if(C=pickVersion(a,n.range),!C){if(!n.required)continue;throw Error(`No version of ${n.name} satisfies ${n.range}`)}let F=a.versions[C];if(!F)throw Error(`Packument for ${n.name} promised ${C} but no entry exists`);let K=decidePlacement(n.from,n.name,C,H),q={name:n.name,version:C,tarballUrl:F.dist.tarball,integrity:F.dist.integrity,installPath:K,dependencies:F.dependencies??{},optionalDependencies:F.optionalDependencies??{},bin:F.bin};if(I.set(K,q),K===`node_modules/${n.name}`&&H.set(n.name,q),S(`resolve: %s@%s ← %s (at %s)`,n.name,C,n.range,K),!N){for(let[n,a]of Object.entries(q.dependencies))W.push({from:K,name:n,range:applyOverride(n,a),required:!0});for(let[n,a]of Object.entries(q.optionalDependencies))W.push({from:K,name:n,range:applyOverride(n,a),required:!1})}}catch(a){if(!n.required){S(`resolve: optional dep %s@%s skipped (%s)`,n.name,n.range,a.message);continue}throw a}}return Array.from(I.values())}function findVisible(n,a,S){let C=[];if(n!==null){C.push(`${n}/node_modules/${a}`);let S=n;for(;;){let n=S.lastIndexOf(`/node_modules/`);if(n<0||(S=S.slice(0,n),C.push(`${S}/node_modules/${a}`),S===``))break}}C.push(`node_modules/${a}`);for(let n of C){let a=S.get(n);if(a)return a}return null}function decidePlacement(n,a,S,C){let N=C.get(a);return!N||N.version===S||n===null?`node_modules/${a}`:`${n}/node_modules/${a}`}function satisfiesRange(n,a){try{return satisfies(n,new UE(a))}catch{return!1}}function readLockfile(n){if(!existsSync(n))return null;try{let a=JSON.parse(readFileSync(n,`utf-8`));return a.lockfileVersion!==tD||!a.packages||typeof a.packages!=`object`?null:a}catch{return null}}function writeLockfile(n,a,S){let C={},N=[...S].sort((n,a)=>n.installPath<a.installPath?-1:+(n.installPath>a.installPath));for(let n of N)C[n.installPath]={version:n.version,resolved:n.tarballUrl,integrity:n.integrity,dependencies:Object.keys(n.dependencies).length>0?n.dependencies:void 0,bin:n.bin};let F={lockfileVersion:tD,requested:[...a],packages:C};writeFileSync(n,JSON.stringify(F,null,2)+`
790
790
  `)}function lockfileToNodes(n){return Object.entries(n.packages).map(([n,a])=>({name:nameFromInstallPath(n),version:a.version,tarballUrl:a.resolved,integrity:a.integrity,installPath:n,dependencies:a.dependencies??{},optionalDependencies:{},bin:a.bin}))}function nameFromInstallPath(n){let a=n.lastIndexOf(`/node_modules/`);return a<0?n.replace(/^node_modules\//,``):n.slice(a+14)}function lockfileMatchesRequest(n,a){if(n.requested.length!==a.length)return!1;let S=[...n.requested].sort(),C=[...a].sort();return S.every((n,a)=>n===C[a])}function describeLockfileDrift(n,a){let S=new Set(n.requested),C=new Set(a),N=[],F=[];for(let n of C)S.has(n)||N.push(n);for(let n of S)C.has(n)||F.push(n);if(N.length===0&&F.length===0)return null;let I=[];return N.length>0&&I.push(` + ${N.sort().join(`
791
791
  + `)}`),F.length>0&&I.push(` - ${F.sort().join(`
792
792
  - `)}`),I.join(`
@@ -797,12 +797,14 @@ jobs:
797
797
  `))!==-1;)a.write(S+C.slice(0,N+1)),C=C.slice(N+1)}),n.on(`end`,()=>{C.length>0&&a.write(S+C+`
798
798
  `)})}Ie(),Hx();const sD={command:`workspace <name> <script> [args..]`,description:"Run a workspace script (`yarn workspace <name> run <script>` equivalent).",builder:n=>n.positional(`name`,{description:"Workspace name (matches package.json `name` field).",type:`string`,demandOption:!0}).positional(`script`,{description:`Script name to run inside that workspace.`,type:`string`,demandOption:!0}).positional(`args`,{description:`Extra arguments forwarded to the script.`,type:`string`,array:!0}),handler:async n=>{let a=discoverWorkspaces(findWorkspaceRoot(process.cwd())??process.cwd()),S=a.find(a=>a.name===n.name);S||(Fe.error(`gjsify workspace: no workspace named "${n.name}" — discovered ${a.length} workspace(s)`),process.exit(1)),typeof(S.manifest.scripts??{})[n.script]!=`string`&&(Fe.error(`gjsify workspace: workspace "${n.name}" has no script "${n.script}"`),process.exit(1));let C=detectPackageManager(),N=C===`gjsify`?[`run`,n.script,...n.args??[]]:[`run`,n.script,...n.args&&n.args.length>0?[`--`,...n.args]:[]],F=process.env.FORCE_COLOR!==void 0||process.env.NO_COLOR!==void 0?{}:{FORCE_COLOR:`1`};await new Promise((n,a)=>{let I=spawn(C,N,{cwd:S.location,stdio:`inherit`,env:{...process.env,...F}});I.on(`close`,S=>{S===0?n():a(Error(`${C} ${N.join(` `)} exited with code ${S}`))}),I.on(`error`,a)}).catch(n=>{Fe.error(n.message),process.exit(1)}),process.exit(0)}};function detectPackageManager(){let n=process.env.npm_config_user_agent??``;return n.startsWith(`yarn/`)?`yarn`:n.startsWith(`gjsify/`)?`gjsify`:`npm`}Hx(),Ho();async function runLifecycleScript(n,a,S,C={}){let N=(a.scripts??{})[S];if(typeof N!=`string`){if(C.optional!==!1)return!1;throw Error(`gjsify lifecycle-script: no "${S}" in ${n}/package.json`)}let F=findWorkspaceRoot(n),I=[jo(n,`node_modules`,`.bin`)];F&&F!==n&&I.push(jo(F,`node_modules`,`.bin`));let H=process.env.FORCE_COLOR!==void 0||process.env.NO_COLOR!==void 0?{}:{FORCE_COLOR:`1`},W={...process.env,...H,PATH:[...I,process.env.PATH??``].filter(Boolean).join(Bo),npm_lifecycle_event:S,npm_package_name:a.name??``,npm_package_version:a.version??``,...C.env??{}},K=C.stdio===`inherit-stderr`?[`inherit`,2,2]:C.stdio??`inherit`;return await new Promise((a,C)=>{let F=spawn(N,[],{cwd:n,env:W,stdio:K,shell:!0});F.on(`close`,N=>{N===0?a():C(Error(`gjsify lifecycle-script: "${S}" in ${n} exited with code ${N}`))}),F.on(`error`,C)}),!0}Ie(),As(),Ga(),Ho(),ZE();const cD={command:`pack [path]`,description:`Produce an npm-compatible .tgz tarball for the workspace at <path> (default: cwd). Rewrites workspace:^/~/* deps to resolved versions.`,builder:n=>n.positional(`path`,{description:`Workspace path (default: cwd).`,type:`string`}).option(`pack-destination`,{description:`Directory to write the tarball into. Default: workspace cwd.`,type:`string`}).option(`json`,{description:"Emit pack metadata as JSON on stdout (mirrors `npm pack --json`).",type:`boolean`,default:!1}).option(`dry-run`,{description:`Compute everything but do not write the .tgz.`,type:`boolean`,default:!1}).option(`ignore-scripts`,{description:"Skip the `prepack` lifecycle script before packing. Mirrors `npm pack --ignore-scripts`. Use when scripts are already run by the outer workflow.",type:`boolean`,default:!1}),handler:async n=>{let a=await packWorkspace(Oo(n.path??process.cwd()),{destination:n[`pack-destination`],dryRun:n[`dry-run`]===!0,lifecycleScripts:n[`ignore-scripts`]?[]:[`prepack`],lifecycleStdio:n.json?`inherit-stderr`:`inherit`});n.json?process.stdout.write(`${JSON.stringify([a],null,2)}\n`):process.stdout.write(`${a.filename}\n`)}};async function packWorkspace(n,a={}){let S=jo(n,`package.json`);if(!existsSync(S))throw Error(`gjsify pack: no package.json at ${n}`);let C=readFileSync(S,`utf-8`),N=JSON.parse(C),F=typeof N.name==`string`?N.name:``,I=typeof N.version==`string`?N.version:`0.0.0`;if(!F)throw Error(`gjsify pack: package.json at ${n} has no "name"`);let H=a.lifecycleScripts??[`prepack`];for(let S of H)await runLifecycleScript(n,N,S,{optional:!0,stdio:a.lifecycleStdio});let W=readFileSync(S,`utf-8`),K=W===C?N:JSON.parse(W),q=a.skipWorkspaceRewrite?K:rewriteWorkspaceDeps(K,n),Y=JSON.stringify(q,null,indentOf(W))+`
799
799
  `,X=collectFiles(n,K),te=[{name:`package/`,directory:!0,mode:493}],ne=[],re=0;for(let a of X){let S;S=a===`package.json`?new TextEncoder().encode(Y):new Uint8Array(readFileSync(jo(n,a)));let C=statSync(jo(n,a)).mode&511;te.push({name:`package/${a}`,body:S,mode:C,mtime:0}),ne.push({path:a,size:S.byteLength,mode:C}),re+=S.byteLength}let ie=await gzip(createTarball(te)),ae=`${F.startsWith(`@`)?F.slice(1).replace(`/`,`-`):F}-${I}.tgz`,oe=createHash(`sha1`).update(ie).digest(`hex`),Z=`sha512-${createHash(`sha512`).update(ie).digest(`base64`)}`,se=a.destination?Oo(a.destination):n,ce=jo(se,ae);return a.dryRun||(mkdirSync(se,{recursive:!0}),writeFileSync(ce,ie)),{filename:ae,name:F,version:I,size:ie.byteLength,unpackedSize:re,shasum:oe,integrity:Z,entryCount:ne.length,files:ne,absolutePath:a.dryRun?null:ce}}function collectFiles(n,a){let S=forceIncluded(a),C=Array.isArray(a.files)?a.files.filter(n=>typeof n==`string`):null,N;N=C?expandFilesPatterns(n,C):walkAll(n);let F=loadIgnore(n),I=new Set;for(let n of N)F(n)||I.add(n);for(let a of S)existsSync(jo(n,a))&&I.add(a);return[...I].sort()}const lD=new Set([`.git`,`.svn`,`.hg`,`.gitignore`,`.gitattributes`,`.npmrc`,`CVS`,`.DS_Store`,`node_modules`,`.npmignore`,`package-lock.json`,`gjsify-lock.json`,`yarn.lock`,`yarn-error.log`,`.yarn`,`.pnp.cjs`,`.pnp.loader.mjs`,`tsconfig.tsbuildinfo`]);function forceIncluded(n){let a=new Set;a.add(`package.json`);for(let n of[`README`,`README.md`,`LICENSE`,`LICENSE.md`,`NOTICE`,`NOTICE.md`])a.add(n);let S=typeof n.main==`string`?n.main:null;S&&a.add(S.replace(/^\.\//,``));let C=n.bin;if(typeof C==`string`)a.add(C.replace(/^\.\//,``));else if(C&&typeof C==`object`)for(let n of Object.values(C))typeof n==`string`&&a.add(n.replace(/^\.\//,``));return[...a]}function walkAll(n,a=``){let S=[],C=a?jo(n,a):n,N;try{N=readdirSync(C,{withFileTypes:!0})}catch{return S}for(let C of N){if(lD.has(C.name)||C.name.startsWith(`.tsbuildinfo`))continue;let N=a?`${a}/${C.name}`:C.name;C.isDirectory()?S.push(...walkAll(n,N)):C.isFile()&&S.push(N)}return S}function expandFilesPatterns(n,a){let S=new Set;for(let C of a){let a=C.replace(/^\.\//,``).replace(/\/$/,``),N=jo(n,a);if(!existsSync(N))continue;let F=statSync(N);if(F.isDirectory())for(let C of walkAll(n,a))S.add(C);else F.isFile()&&S.add(a);!existsSync(N)&&/[*?[]/.test(C)&&Fe.warn(`gjsify pack: files entry "${C}" looks like a glob but glob expansion isn't implemented — pass literal files/dirs`)}return[...S]}function loadIgnore(n){let a=jo(n,`.npmignore`),S=jo(n,`.gitignore`),C=[],N=existsSync(a)?a:existsSync(S)?S:null;if(N){let n=readFileSync(N,`utf-8`).split(`
800
- `);for(let a of n){let n=a.trim();!n||n.startsWith(`#`)||n.startsWith(`!`)||C.push(globToRegex(n))}}return n=>{for(let a of C)if(a.test(n))return!0;return!1}}function globToRegex(n){let a=n.replace(/^\//,``);return a=a.replace(/[.+^${}()|[\]\\]/g,`\\$&`),a=a.replace(/\*\*/g,`__DOUBLESTAR__`).replace(/\*/g,`[^/]*`).replace(/__DOUBLESTAR__/g,`.*`),a=a.replace(/\?/g,`[^/]`),RegExp(`^${a}($|/)`)}function rewriteWorkspaceDeps(n,a){let S=findWorkspaceRoot(a);if(!S)return n;let C=new Map;for(let n of discoverWorkspaces(S))n.name&&n.version&&C.set(n.name,n.version);let N=JSON.parse(JSON.stringify(n));for(let n of[`dependencies`,`devDependencies`,`peerDependencies`,`optionalDependencies`]){let a=N[n];if(a)for(let[n,F]of Object.entries(a)){if(typeof F!=`string`||!F.startsWith(`workspace:`))continue;let I=C.get(n);if(!I)throw Error(`gjsify pack: ${N.name} declares workspace:^ on ${n} but no sibling workspace with that name exists in the monorepo at ${S}`);let H=F.slice(10);H===`*`||H===``?a[n]=I:H===`^`||H===`~`?a[n]=`${H}${I}`:a[n]=H}}return N}function indentOf(n){let a=n.match(/\n([ \t]+)"/);return a?a[1]:` `}var OidcUnavailableError=class extends Error{reason;constructor(n,a){super(n),this.reason=a,this.name=`OidcUnavailableError`}},OidcExchangeError=class extends Error{status;body;packageName;constructor(n,a,S,C){super(n),this.status=a,this.body=S,this.packageName=C,this.name=`OidcExchangeError`}};function hasGithubOidcEnv(){return!!(process.env.ACTIONS_ID_TOKEN_REQUEST_URL&&process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN)}async function fetchGithubOidcToken(n,a){let S=process.env.ACTIONS_ID_TOKEN_REQUEST_URL,C=process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN;if(!S||!C)throw new OidcUnavailableError("GitHub Actions OIDC env vars (ACTIONS_ID_TOKEN_REQUEST_{URL,TOKEN}) not set. The calling workflow needs `permissions: id-token: write`.",`no-env`);let N=new URL(S);N.searchParams.set(`audience`,n),a?.(`gjsify oidc: GET ${N.href.replace(C,`<bearer>`)}`);let F=await fetch(N.href,{method:`GET`,headers:{Accept:`application/json`,Authorization:`Bearer ${C}`}});if(!F.ok){let n=await F.text().catch(()=>`<no body>`);throw new OidcUnavailableError(`Failed to fetch GitHub OIDC id_token: ${F.status} ${F.statusText} — ${n.slice(0,200)}`,`fetch-id-token`)}let I=await F.json().catch(()=>({}));if(!I.value)throw new OidcUnavailableError("GitHub OIDC response missing `value` field",`no-id-token`);return I.value}async function exchangeOidcForNpmToken(n){let{packageName:a,registry:S,idToken:C,log:N}=n,F=`${S.endsWith(`/`)?S.slice(0,-1):S}/-/npm/v1/oidc/token/exchange/package/${a.startsWith(`@`)?(()=>{let n=a.indexOf(`/`),S=a.slice(1,n),C=a.slice(n+1);return`@${encodeURIComponent(S)}%2f${encodeURIComponent(C)}`})():encodeURIComponent(a)}`;N?.(`gjsify oidc: POST ${F}`);let I=await fetch(F,{method:`POST`,headers:{Authorization:`Bearer ${C}`,"Content-Type":`application/json`,Accept:`application/json`},body:`{}`}),H=await I.text().catch(()=>``);if(!I.ok)throw new OidcExchangeError(`npm OIDC token exchange failed for ${a}: ${I.status} ${I.statusText} — ${H.slice(0,300)}`,I.status,H,a);let W;try{W=JSON.parse(H)}catch{throw new OidcExchangeError(`npm OIDC token exchange returned non-JSON body for ${a}: ${H.slice(0,200)}`,I.status,H,a)}if(!W.token)throw new OidcExchangeError(`npm OIDC token exchange returned no \`token\` field for ${a}`,I.status,H,a);return W.token}async function getNpmTrustedToken(n){let a=`npm:${new URL(n.registry).hostname}`,S=await fetchGithubOidcToken(a,n.log);return{token:await exchangeOidcForNpmToken({...n,idToken:S}),audience:a}}Ie(),As(),kp(),Ho(),KE();const uD={command:`publish [path]`,description:"Pack + upload the workspace at <path> (default: cwd) to its npm registry. Drop-in for `npm publish` with workspace:^ rewrite handled automatically.",builder:n=>n.positional(`path`,{description:`Workspace path (default: cwd).`,type:`string`}).option(`tag`,{description:`Dist-tag to publish under. Default: latest.`,type:`string`,default:`latest`}).option(`access`,{description:"Package access — `public` or `restricted` (required for first publish of scoped packages on the public registry).",type:`string`}).option(`tolerate-republish`,{description:'Treat "version already published" as success — covers both classic 409 Conflict and the npm OIDC-path 403 Forbidden + `"previously published"` body shape. Matches yarn `--tolerate-republish`.',type:`boolean`,default:!1}).option(`tolerate-untrusted-new`,{description:'Skip (exit 0) when OIDC token exchange returns `package not found` AND no fallback token is configured — i.e. a never-before-published `@scope/<name>` whose Trusted Publisher entry hasn\'t been set up on npmjs.com yet. Without this flag, one un-bootstrapped new package breaks the entire serialized `gjsify foreach publish` loop. Pair with `--tolerate-republish` in CI release workflows so a fresh-merged package gracefully skips its first CI publish, leaving the manual-bootstrap step to a maintainer (see AGENTS.md "New @gjsify/* package: first-publish + Trusted Publisher bootstrap").',type:`boolean`,default:!1}).option(`provenance`,{description:`Pass-through flag — recorded in the payload but no signing happens (gjsify doesn't ship a sigstore signer yet).`,type:`boolean`,default:!1}).option(`dry-run`,{description:`Pack only, do not PUT.`,type:`boolean`,default:!1}).option(`json`,{description:`Emit publish metadata as JSON on stdout.`,type:`boolean`,default:!1}).option(`trusted`,{description:"Authenticate via npm Trusted Publishing (OIDC): exchange the GitHub Actions id-token for a short-lived npm token. Pass `--trusted` to force this mode (errors if env vars missing). Omit to auto-detect: OIDC is used iff `ACTIONS_ID_TOKEN_REQUEST_URL`+`_TOKEN` are set AND no `_authToken` is present in the resolved npmrc; otherwise the long-lived token path is used. Requires the calling workflow to declare `permissions: id-token: write` AND the target package to have a Trusted Publisher configured on npmjs.com.",type:`boolean`,default:void 0}).option(`check-trusted`,{description:"Diagnostic mode: perform the OIDC id-token request + npm token exchange, report success/failure, then exit WITHOUT publishing. Useful as a bulk-verifier (e.g. via `gjsify foreach publish --check-trusted`) to confirm Trusted Publisher config across many packages.",type:`boolean`,default:!1}),handler:async n=>{let a=Oo(n.path??process.cwd()),S=n.tag??`latest`,C=n.access,N=n[`tolerate-republish`]===!0,F=n[`tolerate-untrusted-new`]===!0,I=n.provenance===!0,H=n[`dry-run`]===!0,W=n[`check-trusted`]===!0,K=n.trusted,q=!!process.env.GJSIFY_PUBLISH_DEBUG;if(I&&Fe.warn(`gjsify publish: --provenance recorded but not signed (no sigstore integration yet).`),W){let S=jo(a,`package.json`),C=JSON.parse(readFileSync(S,`utf-8`));if(typeof C.name!=`string`&&(process.stderr.write(`gjsify publish --check-trusted: ${S} has no \`name\` field\n`),process.exit(2)),C.private===!0){let a={ok:!0,action:`check-trusted`,name:C.name,skipped:`private`};n.json?process.stdout.write(`${JSON.stringify(a)}\n`):process.stdout.write(`- ${C.name}: skipped (private package)\n`);return}let N=await loadNpmrc(a),F=process.env.npm_config_registry??registryFor(C.name,N)??GE;try{await getNpmTrustedToken({packageName:C.name,registry:F,log:q?n=>Fe.error(n):void 0});let a={ok:!0,action:`check-trusted`,name:C.name,registry:F};n.json?process.stdout.write(`${JSON.stringify(a)}\n`):process.stdout.write(`✓ ${C.name}: trusted publisher OK\n`);return}catch(a){handleOidcFailure(a,C.name,n.json===!0);return}}let Y=await packWorkspace(a,{dryRun:!0,lifecycleScripts:[`prepublishOnly`,`prepack`],lifecycleStdio:n.json?`inherit-stderr`:`inherit`}),X=await packWorkspaceToBytes(a),te=readFileSync(jo(a,`package.json`),`utf-8`),ne=await loadRewrittenManifest(a,JSON.parse(te));if(H){let a={ok:!0,action:`dry-run`,name:Y.name,version:Y.version,filename:Y.filename,size:Y.size,shasum:Y.shasum,integrity:Y.integrity};n.json?process.stdout.write(`${JSON.stringify(a,null,2)}\n`):process.stdout.write(`+ ${Y.name}@${Y.version} (dry-run, ${Y.size} bytes, ${Y.entryCount} files)\n`);return}let re=await loadNpmrc(a),ie=process.env.npm_config_registry??registryFor(Y.name,re)??GE,ae=ie.endsWith(`/`)?ie.slice(0,-1):ie,oe=`${ae}/${Y.name.startsWith(`@`)?(()=>{let n=Y.name.indexOf(`/`),a=Y.name.slice(1,n),S=Y.name.slice(n+1);return`@${encodeURIComponent(a)}%2f${encodeURIComponent(S)}`})():encodeURIComponent(Y.name)}`,Z=`${Y.name.includes(`/`)?Y.name.slice(Y.name.indexOf(`/`)+1):Y.name}-${Y.version}.tgz`,se=buildPublishPayload({pkg:ne,tag:S,access:C,tarballBytes:X,tarballUrl:`${ae}/${Y.name}/-/${Z}`,packed:{...Y,wireFilename:Z},provenance:I}),ce=buildHeaders(oe,{npmrc:re});ce[`content-type`]=`application/json`,ce.accept=`*/*`;let le=K===!0||K===void 0&&hasGithubOidcEnv()&&!process.env.NODE_AUTH_TOKEN,ue=`token`;if(le)try{let{token:n,audience:a}=await getNpmTrustedToken({packageName:Y.name,registry:ie,log:q?n=>Fe.error(n):void 0});ce.authorization=`Bearer ${n}`,ue=`oidc`,q&&Fe.error(`gjsify publish: OIDC token obtained (audience=${a})`)}catch(a){if(a instanceof OidcExchangeError&&a.status===404&&/package not found/i.test(a.body)&&F){let a=`${Y.name}@${Y.version} (skipped — no Trusted Publisher on npm, see AGENTS.md "New @gjsify/* package: first-publish + Trusted Publisher bootstrap")`;n.json?process.stdout.write(`${JSON.stringify({ok:!0,action:`skipped-untrusted-new`,name:Y.name,version:Y.version,reason:`no-trusted-publisher`},null,2)}\n`):process.stdout.write(`~ ${a}\n`);return}if(K===!0&&(handleOidcFailure(a,Y.name,n.json===!0),process.exit(1)),q){let n=a instanceof Error?a.message:String(a);Fe.error(`gjsify publish: OIDC auto-detect failed (${n}) — falling back to token auth`)}}q&&(Fe.error(`gjsify publish: PUT ${oe} (${Y.name}@${Y.version})`),Fe.error(` auth-mode: ${ue}`),Fe.error(` authorization: ${ce.authorization?`(set)`:`(none)`}`),Fe.error(` payload size: ${JSON.stringify(se).length} bytes`));let de=await fetch(oe,{method:`PUT`,headers:ce,body:JSON.stringify(se)});if(de.ok){let a={ok:!0,name:Y.name,version:Y.version,filename:Y.filename,size:Y.size,integrity:Y.integrity,tag:S,registry:ae};n.json?process.stdout.write(`${JSON.stringify(a,null,2)}\n`):process.stdout.write(`+ ${Y.name}@${Y.version}\n`);return}let fe=await de.text().catch(()=>`<no body>`);if((de.status===409||de.status===403&&/previously published/i.test(fe))&&N){let a={ok:!0,action:`republish-tolerated`,name:Y.name,version:Y.version,status:de.status};n.json?process.stdout.write(`${JSON.stringify(a,null,2)}\n`):process.stdout.write(`= ${Y.name}@${Y.version} (already published, tolerated)\n`);return}Fe.error(`gjsify publish: ${Y.name}@${Y.version} — ${de.status} ${de.statusText}`),Fe.error(fe),process.exit(1)}};async function packWorkspaceToBytes(n){let a=`/tmp/gjsify-publish-${process.pid}-${Date.now()}`,S=await packWorkspace(n,{destination:a,dryRun:!1,lifecycleScripts:[]});if(!S.absolutePath)throw Error(`gjsify publish: pack did not produce a file`);let C=new Uint8Array(readFileSync(S.absolutePath));try{(await Promise.resolve().then(()=>(As(),Ds))).rmSync(S.absolutePath)}catch{}try{(await Promise.resolve().then(()=>(As(),Ds))).rmdirSync(a)}catch{}return C}async function loadRewrittenManifest(n,a){let S=`/tmp/gjsify-publish-manifest-${process.pid}-${Date.now()}.tgz`,C=await packWorkspace(n,{destination:S.substring(0,S.lastIndexOf(`/`)),dryRun:!1}),{rmSync:N}=await Promise.resolve().then(()=>(As(),Ds));if(!C.absolutePath)throw Error(`gjsify publish: pack did not produce a file`);let{gunzip:F,parseTar:I}=await Promise.resolve().then(()=>(ZE(),XE)),H=new Uint8Array(readFileSync(C.absolutePath));N(C.absolutePath);let W=await F(H);for(let n of I(W))if(n.name===`package/package.json`&&n.body)return JSON.parse(new TextDecoder().decode(n.body));return a}async function loadNpmrc(n){let a=[],S=jo(n,`.npmrc`);existsSync(S)&&a.push(readFileSync(S,`utf-8`));let C=process.env.NPM_CONFIG_USERCONFIG;if(C&&existsSync(C))a.push(readFileSync(C,`utf-8`));else{let n=jo(homedir(),`.npmrc`);existsSync(n)&&a.push(readFileSync(n,`utf-8`))}return parseNpmrc(a.join(`
801
- `).replace(/\$\{([A-Z_][A-Z0-9_]*)\}/gi,(n,a)=>process.env[a]??``))}function buildPublishPayload(n){let{pkg:a,tag:S,access:C,tarballBytes:N,tarballUrl:F,packed:I,provenance:H}=n,W={...a,_id:`${I.name}@${I.version}`,dist:{integrity:I.integrity,shasum:I.shasum,tarball:F}};H&&(W._hasShrinkwrap=!1);let K={_id:I.name,name:I.name,description:typeof a.description==`string`?a.description:``,"dist-tags":{[S]:I.version},versions:{[I.version]:W},readme:``,_attachments:{[I.wireFilename]:{content_type:`application/octet-stream`,data:base64Encode(N),length:N.byteLength}}};return C&&(K.access=C),K}function base64Encode(n){let a=``,S=32768;for(let C=0;C<n.length;C+=S)a+=String.fromCharCode(...n.subarray(C,C+S));return btoa(a)}function handleOidcFailure(n,a,S){if(n instanceof OidcUnavailableError){let C=`gjsify publish: OIDC not available${n.message}`;S?process.stdout.write(`${JSON.stringify({ok:!1,name:a,error:`oidc-unavailable`,reason:n.reason,message:n.message})}\n`):process.stderr.write(`${C}\n`);return}if(n instanceof OidcExchangeError){let C=n.status===401||n.status===403?`npm rejected the OIDC exchange (${n.status})check that ${a} has a Trusted Publisher configured at https://www.npmjs.com/package/${encodeURIComponent(a)}/access pointing at this workflow.`:n.message;S?process.stdout.write(`${JSON.stringify({ok:!1,name:a,error:`oidc-exchange`,status:n.status,body:n.body,message:n.message})}\n`):process.stderr.write(`✗ ${a}: ${C}\n`);return}let C=n instanceof Error?n.message:String(n);S?process.stdout.write(`${JSON.stringify({ok:!1,name:a,error:`unknown`,message:C})}\n`):process.stderr.write(`✗ ${a}: ${C}\n`)}Ie(),As(),Ho(),rn(),KE();const dD=`@gjsify/cli`,fD={command:`self-update`,description:`Update the installed ${dD} to the latest release (or pinned --tag).`,builder:n=>n.option(`check`,{description:`Only check whether a newer version is available; do not install.`,type:`boolean`,default:!1}).option(`force`,{description:`Reinstall even when the current version already matches the target tag.`,type:`boolean`,default:!1}).option(`tag`,{description:"npm dist-tag or pinned version to install (e.g. `latest`, `next`, `0.5.0`).",type:`string`,default:`latest`}),handler:async n=>{let a=defaultGlobalLayout(),S=jo(jo(a.prefix,`node_modules`,dD),`package.json`),C=readCurrentVersion(),N=existsSync(S);Fe.log(`Current ${dD}: v${C??`(unknown)`}`),N||Fe.warn(`\nWarning: no @gjsify/cli install found under ${a.prefix}.\nself-update only manages installs created by install.mjs or \`gjsify install -g\`.\nIf you installed via \`npm install -g\`, remove that and use:\n curl -fsSL https://github.com/gjsify/gjsify/releases/latest/download/install.mjs -o /tmp/g.mjs && gjs -m /tmp/g.mjs && rm /tmp/g.mjs`),Fe.log(`Fetching dist-tags for ${dD}@${n.tag} ...`);let F;try{F=await fetchPackument(dD)}catch(n){let a=n instanceof Error?n.message:String(n);Fe.error(`Failed to fetch packument: ${a}`),process.exit(1);return}let I=resolveTag(F,n.tag);if(!I){Fe.error(`Unknown dist-tag '${n.tag}' on ${dD}. Known tags: ${Object.keys(F[`dist-tags`]??{}).join(`, `)||`(none)`}`),process.exit(1);return}if(Fe.log(`Latest matching --tag ${n.tag}: v${I}`),C===I&&!n.force){Fe.log(`Already up to date (v${I}).`),n.check||Fe.log(`Run with --force to reinstall anyway.`);return}if(n.check){Fe.log(C?`Update available: v${C} → v${I}`:`Install required: → v${I}`),process.exit(1);return}Fe.log(`Installing ${dD}@${I} ...`),await installPackages({prefix:a.prefix,specs:[`${dD}@${I}`],verbose:!1});let H=linkGlobalBins([dD],a);if(H.length===0)Fe.warn("self-update: install completed but no bins were linked — package.json may be missing a `bin` field.");else for(let n of H)Fe.log(` • ${n.link} → ${n.target}`);Fe.log(`\nUpdated ${dD} to v${I}.`)}};function readCurrentVersion(){try{let n=Po(Oo(fileURLToPath(import.meta.url)));for(let a=0;a<8&&n!==Po(n);a++){let a=jo(n,`package.json`);if(existsSync(a)){let n=JSON.parse(readFileSync(a,`utf-8`));if(n.name===dD&&typeof n.version==`string`)return n.version}n=Po(n)}}catch{}return null}function resolveTag(n,a){let S=n[`dist-tags`]??{};return S[a]?S[a]:n.versions&&typeof n.versions==`object`&&n.versions[a]?a:null}Ie(),As(),Ho();function loadInstallerTemplate(){return readFileSync(new URL(`../templates/install.mjs.tmpl`,import.meta.url),`utf-8`)}const pD={command:`generate-installer [target]`,description:`Scaffold an install.mjs in the current directory for a GJS-runnable npm package.`,builder:n=>n.positional(`target`,{description:`Npm package name to install (default: current package.json name).`,type:`string`}).option(`bin-name`,{description:"Bin name produced by the installer (default: first key of `gjsify.bin` or `bin`).",type:`string`}).option(`bootstrap-url`,{description:`Override the cli.gjs.mjs bootstrap bundle URL (default: gjsify GitHub releases/latest).`,type:`string`}).option(`output`,{description:`Where to write the generated installer.`,type:`string`,default:`install.mjs`}).option(`force`,{description:`Overwrite an existing output file.`,type:`boolean`,default:!1}),handler:n=>{let a=Oo(process.cwd(),n.output);if(existsSync(a)&&!n.force){Fe.error(`${n.output} already exists. Re-run with --force to overwrite.`),process.exit(1);return}let S=Oo(process.cwd(),`package.json`),C=null;if(existsSync(S))try{C=JSON.parse(readFileSync(S,`utf-8`))}catch{}let N=n.target??C?.name;if(!N){Fe.error("No target package: pass `gjsify generate-installer <pkg>` or run inside a directory with a package.json."),process.exit(1);return}let F=n[`bin-name`]??pickDefaultBinName(C,N),I=n[`bootstrap-url`]??`https://github.com/gjsify/gjsify/releases/latest/download/cli.gjs.mjs`;writeFileSync(a,loadInstallerTemplate().replace(/const DEFAULT_TARGET = '[^']+';/,`const DEFAULT_TARGET = ${JSON.stringify(N)};`).replace(/const DEFAULT_BIN_NAME = '[^']+';/,`const DEFAULT_BIN_NAME = ${JSON.stringify(F)};`).replace(/const DEFAULT_BOOTSTRAP_URL =\s*'[^']+';/,`const DEFAULT_BOOTSTRAP_URL = ${JSON.stringify(I)};`),{mode:493}),Fe.log(`Wrote ${n.output} (target=${N}, bin=${F}).`),Fe.log(``),Fe.log(`Install one-liner for your README:`),Fe.log(` curl -fsSL https://github.com/<you>/<repo>/raw/main/${n.output} -o /tmp/i.mjs \\`),Fe.log(` && gjs -m /tmp/i.mjs && rm /tmp/i.mjs`)}};function pickDefaultBinName(n,a){let S=n?.gjsify?.bin;if(S&&typeof S==`object`){let n=Object.keys(S)[0];if(n)return n}let C=n?.bin;if(C&&typeof C==`object`){let n=Object.keys(C)[0];if(n)return n}return a.startsWith(`@`)?a.slice(a.indexOf(`/`)+1):a}Ie(),As(),Ho();const mD={command:`uninstall <packages..>`,description:"Uninstall a previously installed package. Currently only `--global` mode is supported.",builder:n=>n.positional(`packages`,{description:`Package(s) to uninstall (npm names, optionally with version).`,type:`string`,array:!0,demandOption:!0}).option(`global`,{description:`Uninstall from the user-global XDG location (the install -g target).`,type:`boolean`,alias:`g`,default:!1}).option(`dry-run`,{description:`Show what would be removed without touching the filesystem.`,type:`boolean`,default:!1}).option(`verbose`,{description:`Verbose logging.`,type:`boolean`,default:!1}),handler:n=>{if(!n.global){Fe.error("gjsify uninstall currently only supports --global. For project-local removal, edit package.json + re-run `gjsify install`."),process.exit(1);return}let a=defaultGlobalLayout(),S=n[`dry-run`]??!1,C=n.verbose??!1,N=`gjsify uninstall${S?` (dry-run)`:``} --global`;Fe.log(`${N} ← ${a.prefix}`),Fe.log(`${` `.repeat(N.length)} bins ← ${a.binDir}`);let F=!1;for(let N of n.packages){let n=specToPackageName(N),I=jo(a.prefix,`node_modules`,n);if(!existsSync(I)){Fe.warn(` ✗ ${n} — not installed at ${I}`);continue}let H=findBinShimsForPackage(a.binDir,I,C);if(S){Fe.log(` • would remove ${I}`);for(let n of H)Fe.log(` • would remove ${n}`)}else{rmSync(I,{recursive:!0,force:!0}),Fe.log(` • removed ${I}`);for(let n of H)unlinkSync(n),Fe.log(` • removed ${n}`)}F=!0}F||(Fe.error(`
800
+ `);for(let a of n){let n=a.trim();!n||n.startsWith(`#`)||n.startsWith(`!`)||C.push(globToRegex(n))}}return n=>{for(let a of C)if(a.test(n))return!0;return!1}}function globToRegex(n){let a=n.replace(/^\//,``);return a=a.replace(/[.+^${}()|[\]\\]/g,`\\$&`),a=a.replace(/\*\*/g,`__DOUBLESTAR__`).replace(/\*/g,`[^/]*`).replace(/__DOUBLESTAR__/g,`.*`),a=a.replace(/\?/g,`[^/]`),RegExp(`^${a}($|/)`)}function rewriteWorkspaceDeps(n,a){let S=findWorkspaceRoot(a);if(!S)return n;let C=new Map;for(let n of discoverWorkspaces(S))n.name&&n.version&&C.set(n.name,n.version);let N=JSON.parse(JSON.stringify(n));for(let n of[`dependencies`,`devDependencies`,`peerDependencies`,`optionalDependencies`]){let a=N[n];if(a)for(let[n,F]of Object.entries(a)){if(typeof F!=`string`||!F.startsWith(`workspace:`))continue;let I=C.get(n);if(!I)throw Error(`gjsify pack: ${N.name} declares workspace:^ on ${n} but no sibling workspace with that name exists in the monorepo at ${S}`);let H=F.slice(10);H===`*`||H===``?a[n]=I:H===`^`||H===`~`?a[n]=`${H}${I}`:a[n]=H}}return N}function indentOf(n){let a=n.match(/\n([ \t]+)"/);return a?a[1]:` `}var OidcUnavailableError=class extends Error{reason;constructor(n,a){super(n),this.reason=a,this.name=`OidcUnavailableError`}},OidcExchangeError=class extends Error{status;body;packageName;constructor(n,a,S,C){super(n),this.status=a,this.body=S,this.packageName=C,this.name=`OidcExchangeError`}};function hasGithubOidcEnv(){return!!(process.env.ACTIONS_ID_TOKEN_REQUEST_URL&&process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN)}async function fetchGithubOidcToken(n,a){let S=process.env.ACTIONS_ID_TOKEN_REQUEST_URL,C=process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN;if(!S||!C)throw new OidcUnavailableError("GitHub Actions OIDC env vars (ACTIONS_ID_TOKEN_REQUEST_{URL,TOKEN}) not set. The calling workflow needs `permissions: id-token: write`.",`no-env`);let N=new URL(S);N.searchParams.set(`audience`,n),a?.(`gjsify oidc: GET ${N.href.replace(C,`<bearer>`)}`);let F=await fetch(N.href,{method:`GET`,headers:{Accept:`application/json`,Authorization:`Bearer ${C}`}});if(!F.ok){let n=await F.text().catch(()=>`<no body>`);throw new OidcUnavailableError(`Failed to fetch GitHub OIDC id_token: ${F.status} ${F.statusText} — ${n.slice(0,200)}`,`fetch-id-token`)}let I=await F.json().catch(()=>({}));if(!I.value)throw new OidcUnavailableError("GitHub OIDC response missing `value` field",`no-id-token`);return I.value}async function exchangeOidcForNpmToken(n){let{packageName:a,registry:S,idToken:C,log:N}=n,F=`${S.endsWith(`/`)?S.slice(0,-1):S}/-/npm/v1/oidc/token/exchange/package/${a.startsWith(`@`)?(()=>{let n=a.indexOf(`/`),S=a.slice(1,n),C=a.slice(n+1);return`@${encodeURIComponent(S)}%2f${encodeURIComponent(C)}`})():encodeURIComponent(a)}`;N?.(`gjsify oidc: POST ${F}`);let I=await fetch(F,{method:`POST`,headers:{Authorization:`Bearer ${C}`,"Content-Type":`application/json`,Accept:`application/json`},body:`{}`}),H=await I.text().catch(()=>``);if(!I.ok)throw new OidcExchangeError(`npm OIDC token exchange failed for ${a}: ${I.status} ${I.statusText} — ${H.slice(0,300)}`,I.status,H,a);let W;try{W=JSON.parse(H)}catch{throw new OidcExchangeError(`npm OIDC token exchange returned non-JSON body for ${a}: ${H.slice(0,200)}`,I.status,H,a)}if(!W.token)throw new OidcExchangeError(`npm OIDC token exchange returned no \`token\` field for ${a}`,I.status,H,a);return W.token}async function getNpmTrustedToken(n){let a=`npm:${new URL(n.registry).hostname}`,S=await fetchGithubOidcToken(a,n.log);return{token:await exchangeOidcForNpmToken({...n,idToken:S}),audience:a}}Ie(),As(),kp(),Ho(),KE();const uD={command:`publish [path]`,description:"Pack + upload the workspace at <path> (default: cwd) to its npm registry. Drop-in for `npm publish` with workspace:^ rewrite handled automatically.",builder:n=>n.positional(`path`,{description:`Workspace path (default: cwd).`,type:`string`}).option(`tag`,{description:`Dist-tag to publish under. Default: latest.`,type:`string`,default:`latest`}).option(`access`,{description:"Package access — `public` or `restricted` (required for first publish of scoped packages on the public registry).",type:`string`}).option(`otp`,{description:"npm 2FA one-time code; sent as the `npm-otp` header. Required for manual publishes from a 2FA-enabled account.",type:`string`}).option(`tolerate-republish`,{description:'Treat "version already published" as success — covers both classic 409 Conflict and the npm OIDC-path 403 Forbidden + `"previously published"` body shape. Matches yarn `--tolerate-republish`.',type:`boolean`,default:!1}).option(`tolerate-untrusted-new`,{description:'Skip (exit 0) when OIDC token exchange returns `package not found` AND no fallback token is configured — i.e. a never-before-published `@scope/<name>` whose Trusted Publisher entry hasn\'t been set up on npmjs.com yet. Without this flag, one un-bootstrapped new package breaks the entire serialized `gjsify foreach publish` loop. Pair with `--tolerate-republish` in CI release workflows so a fresh-merged package gracefully skips its first CI publish, leaving the manual-bootstrap step to a maintainer (see AGENTS.md "New @gjsify/* package: first-publish + Trusted Publisher bootstrap").',type:`boolean`,default:!1}).option(`provenance`,{description:`Pass-through flag — recorded in the payload but no signing happens (gjsify doesn't ship a sigstore signer yet).`,type:`boolean`,default:!1}).option(`dry-run`,{description:`Pack only, do not PUT.`,type:`boolean`,default:!1}).option(`json`,{description:`Emit publish metadata as JSON on stdout.`,type:`boolean`,default:!1}).option(`trusted`,{description:"Authenticate via npm Trusted Publishing (OIDC): exchange the GitHub Actions id-token for a short-lived npm token. Pass `--trusted` to force this mode (errors if env vars missing). Omit to auto-detect: OIDC is used iff `ACTIONS_ID_TOKEN_REQUEST_URL`+`_TOKEN` are set AND no `_authToken` is present in the resolved npmrc; otherwise the long-lived token path is used. Requires the calling workflow to declare `permissions: id-token: write` AND the target package to have a Trusted Publisher configured on npmjs.com.",type:`boolean`,default:void 0}).option(`check-trusted`,{description:"Diagnostic mode: perform the OIDC id-token request + npm token exchange, report success/failure, then exit WITHOUT publishing. Useful as a bulk-verifier (e.g. via `gjsify foreach publish --check-trusted`) to confirm Trusted Publisher config across many packages.",type:`boolean`,default:!1}),handler:async n=>{let a=Oo(n.path??process.cwd()),S=n.tag??`latest`,C=n.access,N=n.otp,F=n[`tolerate-republish`]===!0,I=n[`tolerate-untrusted-new`]===!0,H=n.provenance===!0,W=n[`dry-run`]===!0,K=n[`check-trusted`]===!0,q=n.trusted,Y=!!process.env.GJSIFY_PUBLISH_DEBUG;if(H&&Fe.warn(`gjsify publish: --provenance recorded but not signed (no sigstore integration yet).`),K){let S=jo(a,`package.json`),C=JSON.parse(readFileSync(S,`utf-8`));if(typeof C.name!=`string`&&(process.stderr.write(`gjsify publish --check-trusted: ${S} has no \`name\` field\n`),process.exit(2)),C.private===!0){let a={ok:!0,action:`check-trusted`,name:C.name,skipped:`private`};n.json?process.stdout.write(`${JSON.stringify(a)}\n`):process.stdout.write(`- ${C.name}: skipped (private package)\n`);return}let N=await loadNpmrc(a),F=process.env.npm_config_registry??registryFor(C.name,N)??GE;try{await getNpmTrustedToken({packageName:C.name,registry:F,log:Y?n=>Fe.error(n):void 0});let a={ok:!0,action:`check-trusted`,name:C.name,registry:F};n.json?process.stdout.write(`${JSON.stringify(a)}\n`):process.stdout.write(`✓ ${C.name}: trusted publisher OK\n`);return}catch(a){handleOidcFailure(a,C.name,n.json===!0);return}}let X=await packWorkspace(a,{dryRun:!0,lifecycleScripts:[`prepublishOnly`,`prepack`],lifecycleStdio:n.json?`inherit-stderr`:`inherit`}),te=await packWorkspaceToBytes(a),ne=readFileSync(jo(a,`package.json`),`utf-8`),re=await loadRewrittenManifest(a,JSON.parse(ne));if(W){let a={ok:!0,action:`dry-run`,name:X.name,version:X.version,filename:X.filename,size:X.size,shasum:X.shasum,integrity:X.integrity};n.json?process.stdout.write(`${JSON.stringify(a,null,2)}\n`):process.stdout.write(`+ ${X.name}@${X.version} (dry-run, ${X.size} bytes, ${X.entryCount} files)\n`);return}let ie=await loadNpmrc(a),ae=process.env.npm_config_registry??registryFor(X.name,ie)??GE,oe=ae.endsWith(`/`)?ae.slice(0,-1):ae,Z=`${oe}/${X.name.startsWith(`@`)?(()=>{let n=X.name.indexOf(`/`),a=X.name.slice(1,n),S=X.name.slice(n+1);return`@${encodeURIComponent(a)}%2f${encodeURIComponent(S)}`})():encodeURIComponent(X.name)}`,se=`${X.name.includes(`/`)?X.name.slice(X.name.indexOf(`/`)+1):X.name}-${X.version}.tgz`,ce=buildPublishPayload({pkg:re,tag:S,access:C,tarballBytes:te,tarballUrl:`${oe}/${X.name}/-/${se}`,packed:{...X,wireFilename:se},provenance:H}),le=buildHeaders(Z,{npmrc:ie});le[`content-type`]=`application/json`,le.accept=`*/*`,N&&(le[`npm-otp`]=N);let ue=q===!0||q===void 0&&hasGithubOidcEnv()&&!process.env.NODE_AUTH_TOKEN,de=`token`;if(ue)try{let{token:n,audience:a}=await getNpmTrustedToken({packageName:X.name,registry:ae,log:Y?n=>Fe.error(n):void 0});le.authorization=`Bearer ${n}`,de=`oidc`,Y&&Fe.error(`gjsify publish: OIDC token obtained (audience=${a})`)}catch(a){if(a instanceof OidcExchangeError&&a.status===404&&/package not found/i.test(a.body)&&I){let a=`${X.name}@${X.version} (skipped — no Trusted Publisher on npm, see AGENTS.md "New @gjsify/* package: first-publish + Trusted Publisher bootstrap")`;n.json?process.stdout.write(`${JSON.stringify({ok:!0,action:`skipped-untrusted-new`,name:X.name,version:X.version,reason:`no-trusted-publisher`},null,2)}\n`):process.stdout.write(`~ ${a}\n`);return}if(q===!0&&(handleOidcFailure(a,X.name,n.json===!0),process.exit(1)),Y){let n=a instanceof Error?a.message:String(a);Fe.error(`gjsify publish: OIDC auto-detect failed (${n}) — falling back to token auth`)}}Y&&(Fe.error(`gjsify publish: PUT ${Z} (${X.name}@${X.version})`),Fe.error(` auth-mode: ${de}`),Fe.error(` authorization: ${le.authorization?`(set)`:`(none)`}`),Fe.error(` otp: ${le[`npm-otp`]?`(set)`:`(none)`}`),Fe.error(` payload size: ${JSON.stringify(ce).length} bytes`));let fe=JSON.stringify(ce);async function doPut(n){return fetch(Z,{method:`PUT`,headers:n,body:fe})}let pe=await doPut(le);if(!N&&pe.status===401){let n=pe.headers.get(`www-authenticate`)??``,a=await pe.text().catch(()=>``);if(n.toLowerCase().split(/,\s*/).includes(`otp`)||/one-time pass/i.test(a))if(process.stdin.isTTY&&process.stdout.isTTY){process.stdout.write(`This operation requires a one-time password.
801
+ Enter OTP: `);let n=await readLineFromStdin();n?pe=await doPut({...le,"npm-otp":n}):(Fe.error("gjsify publish: no OTP enteredre-run with `--otp <code>`"),process.exit(1))}else Fe.error("gjsify publish: npm requires a 2FA one-time codere-run with `--otp <code>`"),process.exit(1)}if(pe.ok){let a={ok:!0,name:X.name,version:X.version,filename:X.filename,size:X.size,integrity:X.integrity,tag:S,registry:oe};n.json?process.stdout.write(`${JSON.stringify(a,null,2)}\n`):process.stdout.write(`+ ${X.name}@${X.version}\n`);return}let me=await pe.text().catch(()=>`<no body>`);if((pe.status===409||pe.status===403&&/previously published/i.test(me))&&F){let a={ok:!0,action:`republish-tolerated`,name:X.name,version:X.version,status:pe.status};n.json?process.stdout.write(`${JSON.stringify(a,null,2)}\n`):process.stdout.write(`= ${X.name}@${X.version} (already published, tolerated)\n`);return}Fe.error(`gjsify publish: ${X.name}@${X.version} ${pe.status} ${pe.statusText}`),Fe.error(me),process.exit(1)}};async function packWorkspaceToBytes(n){let a=`/tmp/gjsify-publish-${process.pid}-${Date.now()}`,S=await packWorkspace(n,{destination:a,dryRun:!1,lifecycleScripts:[]});if(!S.absolutePath)throw Error(`gjsify publish: pack did not produce a file`);let C=new Uint8Array(readFileSync(S.absolutePath));try{(await Promise.resolve().then(()=>(As(),Ds))).rmSync(S.absolutePath)}catch{}try{(await Promise.resolve().then(()=>(As(),Ds))).rmdirSync(a)}catch{}return C}async function loadRewrittenManifest(n,a){let S=`/tmp/gjsify-publish-manifest-${process.pid}-${Date.now()}.tgz`,C=await packWorkspace(n,{destination:S.substring(0,S.lastIndexOf(`/`)),dryRun:!1}),{rmSync:N}=await Promise.resolve().then(()=>(As(),Ds));if(!C.absolutePath)throw Error(`gjsify publish: pack did not produce a file`);let{gunzip:F,parseTar:I}=await Promise.resolve().then(()=>(ZE(),XE)),H=new Uint8Array(readFileSync(C.absolutePath));N(C.absolutePath);let W=await F(H);for(let n of I(W))if(n.name===`package/package.json`&&n.body)return JSON.parse(new TextDecoder().decode(n.body));return a}async function loadNpmrc(n){let a=[],S=jo(n,`.npmrc`);existsSync(S)&&a.push(readFileSync(S,`utf-8`));let C=process.env.NPM_CONFIG_USERCONFIG;if(C&&existsSync(C))a.push(readFileSync(C,`utf-8`));else{let n=jo(homedir(),`.npmrc`);existsSync(n)&&a.push(readFileSync(n,`utf-8`))}return parseNpmrc(a.join(`
802
+ `).replace(/\$\{([A-Z_][A-Z0-9_]*)\}/gi,(n,a)=>process.env[a]??``))}function buildPublishPayload(n){let{pkg:a,tag:S,access:C,tarballBytes:N,tarballUrl:F,packed:I,provenance:H}=n,W={...a,_id:`${I.name}@${I.version}`,dist:{integrity:I.integrity,shasum:I.shasum,tarball:F}};H&&(W._hasShrinkwrap=!1);let K={_id:I.name,name:I.name,description:typeof a.description==`string`?a.description:``,"dist-tags":{[S]:I.version},versions:{[I.version]:W},readme:``,_attachments:{[I.wireFilename]:{content_type:`application/octet-stream`,data:base64Encode(N),length:N.byteLength}}};return C&&(K.access=C),K}function base64Encode(n){let a=``,S=32768;for(let C=0;C<n.length;C+=S)a+=String.fromCharCode(...n.subarray(C,C+S));return btoa(a)}async function readLineFromStdin(){return new Promise(n=>{let a=``,onData=S=>{a+=typeof S==`string`?S:S.toString(`utf-8`);let C=a.indexOf(`
803
+ `);C>=0&&(cleanup(),n(a.slice(0,C).trim()))},onEnd=()=>{cleanup(),n(a.trim())},onError=()=>{cleanup(),n(``)},cleanup=()=>{process.stdin.removeListener(`data`,onData),process.stdin.removeListener(`end`,onEnd),process.stdin.removeListener(`error`,onError),typeof process.stdin.unref==`function`&&process.stdin.unref?.()};process.stdin.setEncoding(`utf-8`),process.stdin.isPaused()&&process.stdin.resume(),process.stdin.once(`data`,onData),process.stdin.once(`end`,onEnd),process.stdin.once(`error`,onError)})}function handleOidcFailure(n,a,S){if(n instanceof OidcUnavailableError){let C=`gjsify publish: OIDC not available — ${n.message}`;S?process.stdout.write(`${JSON.stringify({ok:!1,name:a,error:`oidc-unavailable`,reason:n.reason,message:n.message})}\n`):process.stderr.write(`${C}\n`);return}if(n instanceof OidcExchangeError){let C=n.status===401||n.status===403?`npm rejected the OIDC exchange (${n.status}) — check that ${a} has a Trusted Publisher configured at https://www.npmjs.com/package/${encodeURIComponent(a)}/access pointing at this workflow.`:n.message;S?process.stdout.write(`${JSON.stringify({ok:!1,name:a,error:`oidc-exchange`,status:n.status,body:n.body,message:n.message})}\n`):process.stderr.write(`✗ ${a}: ${C}\n`);return}let C=n instanceof Error?n.message:String(n);S?process.stdout.write(`${JSON.stringify({ok:!1,name:a,error:`unknown`,message:C})}\n`):process.stderr.write(`✗ ${a}: ${C}\n`)}Ie(),As(),Ho(),rn(),KE();const dD=`@gjsify/cli`,fD={command:`self-update`,description:`Update the installed ${dD} to the latest release (or pinned --tag).`,builder:n=>n.option(`check`,{description:`Only check whether a newer version is available; do not install.`,type:`boolean`,default:!1}).option(`force`,{description:`Reinstall even when the current version already matches the target tag.`,type:`boolean`,default:!1}).option(`tag`,{description:"npm dist-tag or pinned version to install (e.g. `latest`, `next`, `0.5.0`).",type:`string`,default:`latest`}),handler:async n=>{let a=defaultGlobalLayout(),S=jo(jo(a.prefix,`node_modules`,dD),`package.json`),C=readCurrentVersion(),N=existsSync(S);Fe.log(`Current ${dD}: v${C??`(unknown)`}`),N||Fe.warn(`\nWarning: no @gjsify/cli install found under ${a.prefix}.\nself-update only manages installs created by install.mjs or \`gjsify install -g\`.\nIf you installed via \`npm install -g\`, remove that and use:\n curl -fsSL https://github.com/gjsify/gjsify/releases/latest/download/install.mjs -o /tmp/g.mjs && gjs -m /tmp/g.mjs && rm /tmp/g.mjs`),Fe.log(`Fetching dist-tags for ${dD}@${n.tag} ...`);let F;try{F=await fetchPackument(dD)}catch(n){let a=n instanceof Error?n.message:String(n);Fe.error(`Failed to fetch packument: ${a}`),process.exit(1);return}let I=resolveTag(F,n.tag);if(!I){Fe.error(`Unknown dist-tag '${n.tag}' on ${dD}. Known tags: ${Object.keys(F[`dist-tags`]??{}).join(`, `)||`(none)`}`),process.exit(1);return}if(Fe.log(`Latest matching --tag ${n.tag}: v${I}`),C===I&&!n.force){Fe.log(`Already up to date (v${I}).`),n.check||Fe.log(`Run with --force to reinstall anyway.`);return}if(n.check){Fe.log(C?`Update available: v${C} → v${I}`:`Install required: → v${I}`),process.exit(1);return}Fe.log(`Installing ${dD}@${I} ...`);try{await installPackages({prefix:a.prefix,specs:[`${dD}@${I}`],verbose:!1,skipDeps:!0})}catch(n){let a=n instanceof Error?n.message:String(n);Fe.error(`self-update: install failed — ${a}`),Fe.error("Re-run `gjsify self-update` to retry."),process.exit(1);return}let H=linkGlobalBins([dD],a);if(H.length===0)Fe.warn("self-update: install completed but no bins were linked — package.json may be missing a `bin` field.");else for(let n of H)Fe.log(` • ${n.link} → ${n.target}`);Fe.log(`\nUpdated ${dD} to v${I}.`)}};function readCurrentVersion(){try{let n=process.env.GJSIFY_CLI_PACKAGE_JSON;if(n){let a=JSON.parse(readFileSync(n,`utf-8`));return a.name===dD&&typeof a.version==`string`?a.version:null}let a=Po(Oo(fileURLToPath(import.meta.url)));for(let n=0;n<8&&a!==Po(a);n++){let n=jo(a,`package.json`);if(existsSync(n)){let a=JSON.parse(readFileSync(n,`utf-8`));if(a.name===dD&&typeof a.version==`string`)return a.version}a=Po(a)}}catch{}return null}function resolveTag(n,a){let S=n[`dist-tags`]??{};return S[a]?S[a]:n.versions&&typeof n.versions==`object`&&n.versions[a]?a:null}Ie(),As(),Ho();function loadInstallerTemplate(){return readFileSync(new URL(`../templates/install.mjs.tmpl`,import.meta.url),`utf-8`)}const pD={command:`generate-installer [target]`,description:`Scaffold an install.mjs in the current directory for a GJS-runnable npm package.`,builder:n=>n.positional(`target`,{description:`Npm package name to install (default: current package.json name).`,type:`string`}).option(`bin-name`,{description:"Bin name produced by the installer (default: first key of `gjsify.bin` or `bin`).",type:`string`}).option(`bootstrap-url`,{description:`Override the cli.gjs.mjs bootstrap bundle URL (default: gjsify GitHub releases/latest).`,type:`string`}).option(`output`,{description:`Where to write the generated installer.`,type:`string`,default:`install.mjs`}).option(`force`,{description:`Overwrite an existing output file.`,type:`boolean`,default:!1}),handler:n=>{let a=Oo(process.cwd(),n.output);if(existsSync(a)&&!n.force){Fe.error(`${n.output} already exists. Re-run with --force to overwrite.`),process.exit(1);return}let S=Oo(process.cwd(),`package.json`),C=null;if(existsSync(S))try{C=JSON.parse(readFileSync(S,`utf-8`))}catch{}let N=n.target??C?.name;if(!N){Fe.error("No target package: pass `gjsify generate-installer <pkg>` or run inside a directory with a package.json."),process.exit(1);return}let F=n[`bin-name`]??pickDefaultBinName(C,N),I=n[`bootstrap-url`]??`https://github.com/gjsify/gjsify/releases/latest/download/cli.gjs.mjs`;writeFileSync(a,loadInstallerTemplate().replace(/const DEFAULT_TARGET = '[^']+';/,`const DEFAULT_TARGET = ${JSON.stringify(N)};`).replace(/const DEFAULT_BIN_NAME = '[^']+';/,`const DEFAULT_BIN_NAME = ${JSON.stringify(F)};`).replace(/const DEFAULT_BOOTSTRAP_URL =\s*'[^']+';/,`const DEFAULT_BOOTSTRAP_URL = ${JSON.stringify(I)};`),{mode:493}),Fe.log(`Wrote ${n.output} (target=${N}, bin=${F}).`),Fe.log(``),Fe.log(`Install one-liner for your README:`),Fe.log(` curl -fsSL https://github.com/<you>/<repo>/raw/main/${n.output} -o /tmp/i.mjs \\`),Fe.log(` && gjs -m /tmp/i.mjs && rm /tmp/i.mjs`)}};function pickDefaultBinName(n,a){let S=n?.gjsify?.bin;if(S&&typeof S==`object`){let n=Object.keys(S)[0];if(n)return n}let C=n?.bin;if(C&&typeof C==`object`){let n=Object.keys(C)[0];if(n)return n}return a.startsWith(`@`)?a.slice(a.indexOf(`/`)+1):a}Ie(),As(),Ho();const mD={command:`uninstall <packages..>`,description:"Uninstall a previously installed package. Currently only `--global` mode is supported.",builder:n=>n.positional(`packages`,{description:`Package(s) to uninstall (npm names, optionally with version).`,type:`string`,array:!0,demandOption:!0}).option(`global`,{description:`Uninstall from the user-global XDG location (the install -g target).`,type:`boolean`,alias:`g`,default:!1}).option(`dry-run`,{description:`Show what would be removed without touching the filesystem.`,type:`boolean`,default:!1}).option(`verbose`,{description:`Verbose logging.`,type:`boolean`,default:!1}),handler:n=>{if(!n.global){Fe.error("gjsify uninstall currently only supports --global. For project-local removal, edit package.json + re-run `gjsify install`."),process.exit(1);return}let a=defaultGlobalLayout(),S=n[`dry-run`]??!1,C=n.verbose??!1,N=`gjsify uninstall${S?` (dry-run)`:``} --global`;Fe.log(`${N} ← ${a.prefix}`),Fe.log(`${` `.repeat(N.length)} bins ← ${a.binDir}`);let F=!1;for(let N of n.packages){let n=specToPackageName(N),I=jo(a.prefix,`node_modules`,n);if(!existsSync(I)){Fe.warn(` ✗ ${n} — not installed at ${I}`);continue}let H=findBinShimsForPackage(a.binDir,I,C);if(S){Fe.log(` • would remove ${I}`);for(let n of H)Fe.log(` • would remove ${n}`)}else{rmSync(I,{recursive:!0,force:!0}),Fe.log(` • removed ${I}`);for(let n of H)unlinkSync(n),Fe.log(` • removed ${n}`)}F=!0}F||(Fe.error(`
802
804
  No packages removed.`),process.exit(1))}};function findBinShimsForPackage(n,a,S){if(!existsSync(n))return[];let C=[],N;try{N=readdirSync(n)}catch{return[]}for(let F of N){let N=jo(n,F);try{if(!statSync(N).isFile())continue;let n=readFileSync(N,`utf-8`);if(!n.startsWith(`#!/bin/sh`))continue;let S=n.split(`
803
805
  `).find(n=>/^exec (?:gjs -m )?'/.test(n));if(!S)continue;let F=S.match(/'([^']+)'/);if(!F)continue;let I=F[1];(I.startsWith(a+`/`)||I===a)&&C.push(N)}catch(n){S&&Fe.warn(` ? could not inspect ${N}: ${n.message}`)}}return C}Ie(),As(),Ho();const hD={command:`format [paths..]`,description:`Format source files via Biome (native binary spawn — no Node launcher).`,builder:n=>n.positional(`paths`,{description:"Files or directories to format. Default: `.`",type:`string`,array:!0}).option(`write`,{description:`Modify files in place (default: stdout / report).`,type:`boolean`,default:!1}).option(`check`,{description:`Report formatting drift without modifying files; exit non-zero if any file is unformatted. Useful for CI.`,type:`boolean`,default:!1}).option(`config-path`,{description:`Path to a biome.json. Default: walks up from cwd to find one.`,type:`string`,normalize:!0}).option(`init`,{description:`Write a recommended biome.json into cwd (skips if one exists; --force to overwrite).`,type:`boolean`,default:!1}).option(`force`,{description:`Overwrite an existing biome.json with --init.`,type:`boolean`,default:!1}).option(`verbose`,{description:`Echo the resolved biome binary + args before spawning.`,type:`boolean`,default:!1}),handler:async n=>{let a=process.cwd();if(n.init){await handleInit({cwd:a,force:n.force??!1});return}let S=n.paths?.length?n.paths:[`.`],C=[`format`];n.write&&!n.check&&C.push(`--write`);let N=n.configPath??findBiomeConfig(a)??void 0;N&&C.push(`--config-path=${Oo(N,`..`)}`),C.push(...S);try{let S=await runBiome(C,{cwd:a,verbose:n.verbose});process.exitCode=S}catch(n){if(n instanceof BiomeNotFoundError){printBiomeNotFound(n),process.exitCode=1;return}throw n}}};async function handleInit({cwd:n,force:a}){let S=Oo(n,`biome.json`);if(existsSync(S)&&!a){Fe.log(`[gjsify format] biome.json exists at ${S} — pass --force to overwrite.`),process.exitCode=0;return}writeFileSync(S,loadBiomeTemplate(),`utf-8`),Fe.log(`[gjsify format] wrote ${S}`),Fe.log("[gjsify format] Run `gjsify format --write .` to apply the formatter to the project.")}Ho();const gD={command:`lint [paths..]`,description:`Run Biome lint diagnostics (native binary spawn — no Node launcher).`,builder:n=>n.positional(`paths`,{description:"Files or directories to lint. Default: `.`",type:`string`,array:!0}).option(`write`,{description:`Apply safe lint fixes in place.`,type:`boolean`,default:!1}).option(`config-path`,{description:`Path to a biome.json. Default: walks up from cwd to find one.`,type:`string`,normalize:!0}).option(`verbose`,{description:`Echo the resolved biome binary + args before spawning.`,type:`boolean`,default:!1}),handler:async n=>{let a=process.cwd(),S=n.paths?.length?n.paths:[`.`],C=[`lint`];n.write&&C.push(`--write`);let N=n.configPath??findBiomeConfig(a)??void 0;N&&C.push(`--config-path=${Oo(N,`..`)}`),C.push(...S);try{let S=await runBiome(C,{cwd:a,verbose:n.verbose});process.exitCode=S}catch(n){if(n instanceof BiomeNotFoundError){printBiomeNotFound(n),process.exitCode=1;return}throw n}}};Ho();const _D={command:`fix [paths..]`,description:`Run Biome check --write — format + safe-lint-fix + organize-imports in one pass.`,builder:n=>n.positional(`paths`,{description:"Files or directories to fix. Default: `.`",type:`string`,array:!0}).option(`write`,{description:`Apply fixes in place (default: true). Pass --no-write to report only.`,type:`boolean`,default:!0}).option(`config-path`,{description:`Path to a biome.json. Default: walks up from cwd to find one.`,type:`string`,normalize:!0}).option(`verbose`,{description:`Echo the resolved biome binary + args before spawning.`,type:`boolean`,default:!1}),handler:async n=>{let a=process.cwd(),S=n.paths?.length?n.paths:[`.`],C=[`check`];n.write!==!1&&C.push(`--write`);let N=n.configPath??findBiomeConfig(a)??void 0;N&&C.push(`--config-path=${Oo(N,`..`)}`),C.push(...S);try{let S=await runBiome(C,{cwd:a,verbose:n.verbose});process.exitCode=S}catch(n){if(n instanceof BiomeNotFoundError){printBiomeNotFound(n),process.exitCode=1;return}throw n}}};vs();var Interface=class extends Interface$1{question(n,a){return new Promise(a=>{super.question(n,a)})}};function createInterface(n,a){return typeof n==`object`&&n&&!(`read`in n&&typeof n.read==`function`)?new Interface(n):new Interface({input:n,output:a})}Ie(),As(),Ho(),kp(),WE(),KE();const vD={command:`upgrade`,description:"Check the npm registry for newer versions of declared dependencies and update package.json. Interactive by default; `--latest` / `--minor` / `--patch` switch to non-interactive bulk-update mode.",builder:n=>n.option(`latest`,{description:`Non-interactive: bump every dependency to its latest version (allows major).`,type:`boolean`,default:!1}).option(`minor`,{description:`Non-interactive: bump every dependency to the latest within the same major (semver-minor + semver-patch).`,type:`boolean`,default:!1}).option(`patch`,{description:`Non-interactive: bump every dependency to the latest within the same minor (semver-patch only).`,type:`boolean`,default:!1}).option(`filter`,{description:`Only consider packages whose name matches this substring (case-insensitive). Repeatable; comma-separated values are split.`,type:`string`}).option(`dry-run`,{description:`Print the upgrade plan without writing package.json.`,type:`boolean`,default:!1}).option(`cwd`,{description:`Project directory. Default: process.cwd().`,type:`string`}).option(`yes`,{alias:`y`,description:`Interactive mode: select all without prompting.`,type:`boolean`,default:!1}).option(`verbose`,{description:`Print extra resolution details.`,type:`boolean`,default:!1}),handler:async n=>{let a=Oo(n.cwd??process.cwd()),S=jo(a,`package.json`);if(!existsSync(S))throw Error(`[gjsify upgrade] no package.json at ${S}`);let C=readFileSync(S,`utf-8`),N=JSON.parse(C),F=collectExternalDeps(N,n.filter?n.filter.split(`,`).map(n=>n.trim().toLowerCase()).filter(Boolean):[]);if(F.length===0){Fe.log(`[gjsify upgrade] no external npm dependencies to check.`);return}let I=await loadNpmrcLight(a),H=n.latest?`latest`:n.minor?`minor`:n.patch?`patch`:`interactive`;Fe.log(`[gjsify upgrade] checking ${F.length} dependencies against ${I.registry}…`);let W=await resolveCandidates(F,I,n.verbose??!1,H);if(W.length===0){Fe.log(`✅ all dependencies are up to date`);return}printTable(W);let K;if(H===`interactive`&&!n.yes?K=await promptSelection(W):(n.yes&&H===`interactive`&&Fe.log(`[gjsify upgrade] -y / --yes: selecting all`),K=W),K.length===0){Fe.log(`[gjsify upgrade] nothing selected; package.json unchanged.`);return}if(n.dryRun){Fe.log(`[gjsify upgrade] --dry-run: would update ${K.length} dependencies (no write).`);return}writePackageJson(S,C,N,K),Fe.log(`✏️ updated ${K.length} dependencies in ${S}. Run \`gjsify install\` to apply.`)}},yD=[`dependencies`,`devDependencies`,`optionalDependencies`,`peerDependencies`];function collectExternalDeps(n,a){let S=[];for(let C of yD){let N=n[C];if(!(!N||typeof N!=`object`))for(let[n,F]of Object.entries(N)){if(typeof F!=`string`||a.length&&!a.some(a=>n.toLowerCase().includes(a))||F.startsWith(`workspace:`)||F.startsWith(`file:`)||F.startsWith(`link:`)||F.startsWith(`git+`)||F.startsWith(`git:`)||F.startsWith(`http`)||F.startsWith(`npm:`)||F===`*`||F===`latest`)continue;let{prefix:N,version:I}=splitRange(F);S.push({name:n,field:C,currentRange:F,currentVersion:I,prefix:N})}}return S}function splitRange(n){let a=n.match(/^(\^|~|>=|<=|>|<|=)?\s*([0-9].*)$/);if(!a)return{prefix:``,version:null};let S=a[1]??``,C=a[2]?.split(/\s|[|&,]/)[0]??null;return{prefix:S,version:(C?parse(C):null)?.version??null}}async function resolveCandidates(n,a,S,C){let N=[],F=0;async function worker(){for(;;){let I=F++;if(I>=n.length)return;let H=n[I];try{let n=(await fetchPackument(H.name,{npmrc:a}))[`dist-tags`]?.latest;if(!n){S&&Fe.warn(` ${H.name}: no dist-tags.latest, skipping`);continue}if(!H.currentVersion){S&&Fe.warn(` ${H.name}: unable to parse current range "${H.currentRange}"`);continue}let F=classifyDiff(H.currentVersion,n);if(F===`none`||C===`minor`&&F===`major`||C===`patch`&&(F===`major`||F===`minor`))continue;N.push({...H,latestVersion:n,diff:F})}catch(n){S&&Fe.warn(` ${H.name}: fetch failed (${n.message})`)}}}return await Promise.all(Array.from({length:8},()=>worker())),N.sort((n,a)=>n.name.localeCompare(a.name)),N}function classifyDiff(n,a){let S=parse(n),C=parse(a);return!S||!C?`none`:S.major===C.major?S.minor===C.minor?S.patch===C.patch?(S.prerelease??[]).join(`.`)===(C.prerelease??[]).join(`.`)?`none`:`prerelease`:C.patch>S.patch?`patch`:`none`:C.minor>S.minor?`minor`:`none`:C.major>S.major?`major`:`none`}const bD={reset:`\x1B[0m`,bold:`\x1B[1m`,dim:`\x1B[2m`,red:`\x1B[31m`,yellow:`\x1B[33m`,green:`\x1B[32m`,cyan:`\x1B[36m`};function colorForDiff(n){switch(n){case`major`:return bD.red;case`minor`:return bD.yellow;case`patch`:return bD.green;case`prerelease`:return bD.cyan;default:return``}}function printTable(n){let a=Math.max(...n.map(n=>n.name.length),4),S=Math.max(...n.map(n=>n.currentRange.length),7),C=Math.max(...n.map(n=>n.latestVersion.length),6),N=String(n.length).length+2,F=` `.repeat(N)+bD.bold+`name`.padEnd(a)+` `+`current`.padEnd(S)+` `+`latest`.padEnd(C)+` kind`+bD.reset;Fe.log(F),Fe.log(` `.repeat(N)+bD.dim+`─`.repeat(a+S+C+12)+bD.reset);for(let F=0;F<n.length;F++){let I=n[F],H=`${F+1}.`.padEnd(N),W=colorForDiff(I.diff);Fe.log(H+I.name.padEnd(a)+` `+bD.dim+I.currentRange.padEnd(S)+bD.reset+` `+W+I.latestVersion.padEnd(C)+bD.reset+` `+W+I.diff+bD.reset)}}async function promptSelection(n){if(!process.stdin.isTTY)return Fe.log(`[gjsify upgrade] non-TTY stdin: pass --latest / --minor / --patch (or --yes for interactive-all) to upgrade non-interactively.`),[];let a=createInterface({input:process.stdin,output:process.stdout});try{Fe.log(`
804
806
  Select upgrades: comma- or space-separated indices, `+bD.bold+`a`+bD.reset+` for all, ranges like `+bD.bold+`1-3`+bD.reset+`, or `+bD.bold+`ENTER`+bD.reset+` to skip:`);let S=(await a.question(`> `)).trim();if(!S)return[];if(S.toLowerCase()===`a`||S.toLowerCase()===`all`)return n;let C=new Set;for(let n of S.split(/[\s,]+/).filter(Boolean)){let a=n.match(/^(\d+)-(\d+)$/);if(a){let n=Number(a[1]),S=Number(a[2]);for(let a=Math.min(n,S);a<=Math.max(n,S);a++)C.add(a-1)}else /^\d+$/.test(n)&&C.add(Number(n)-1)}return[...C].filter(a=>a>=0&&a<n.length).map(a=>n[a])}finally{a.close()}}function writePackageJson(n,a,S,C){for(let n of C){let a=S[n.field];a&&(a[n.name]=n.prefix+n.latestVersion)}let N=detectIndent(a);writeFileSync(n,JSON.stringify(S,null,N)+(a.endsWith(`
805
807
  `)?`
806
808
  `:``),`utf-8`)}function detectIndent(n){let a=n.match(/^\{\n( +)/);return a?a[1].length:2}async function loadNpmrcLight(n){let a={registry:GE,scopes:{},authTokens:{},basicAuth:{}};for(let S of[jo(homedir(),`.npmrc`),jo(n,`.npmrc`)])if(existsSync(S))try{let n=parseNpmrc(readFileSync(S,`utf-8`));a={...a,...n,scopes:{...a.scopes,...n.scopes}}}catch{}return process.env.npm_config_registry&&(a.registry=process.env.npm_config_registry),a}Ie(),ss(),Ho();const xD=[`\\.test\\.`,`\\.spec\\.`,`\\.test-data\\.`],SD=/\.(ts|tsx|mts|cts)$/;async function generateBarrels(n){let a=n.singleQuotes?`'`:`"`,S=n.noSemicolon?``:`;`,C=n.extension===`none`?``:`.${n.extension}`,N=0;for(let F of n.paths){let I=Oo(n.baseDir,F),H=Fo(I)===`types`,W;try{W=(await readdir$1(I,{withFileTypes:!0})).filter(n=>n.isFile()).filter(n=>SD.test(n.name)).filter(n=>n.name!==`index.ts`).filter(a=>!n.exclude.some(n=>n.test(a.name))).sort((n,a)=>n.name.localeCompare(a.name))}catch(a){n.verbose&&Fe.error(`[gjsify barrels] skip ${I}: ${a.message}`);continue}let K=W.map(n=>{let N=Fo(n.name,Io(n.name));return`${H?`export type *`:`export *`} from ${a}./${N}${C}${a}${S}`}),q=K.length?`${K.join(`
807
809
  `)}\n`:`export {};
808
- `,Y=`${n.header}\n\n${q}`,X=jo(I,`index.ts`);if(await readFile$1(X,`utf-8`).catch(()=>``)===Y){n.verbose&&Fe.log(`[gjsify barrels] up-to-date: ${X}`);continue}n.check?(Fe.error(`[gjsify barrels] drift: ${X}`),N++):(await writeFile$1(X,Y,`utf-8`),n.verbose&&Fe.log(`[gjsify barrels] wrote: ${X}`))}return N}Ie();const CD={command:`barrels [paths..]`,description:"Regenerate `index.ts` barrel files for the given directories. Drop-in replacement for `barrelsby`.",builder:n=>n.positional(`paths`,{description:"Directories whose `index.ts` to (re)generate. May also be passed via `--paths`.",type:`string`,array:!0}).option(`paths`,{alias:`p`,description:`Alternative to positional — repeatable list of directories.`,type:`string`,array:!0}).option(`ext`,{description:"Import-specifier extension. Default: `none` (bundler-mode resolution).",type:`string`,choices:[`js`,`ts`,`none`],default:`none`}).option(`base-dir`,{alias:`b`,description:"Resolve `paths` against this directory. Default: cwd.",type:`string`}).option(`exclude`,{description:"Regex(es) of file names to skip. Repeatable. Defaults: `\\.test\\.`, `\\.spec\\.`, `\\.test-data\\.`.",type:`string`,array:!0}).option(`header`,{description:`Header comment prepended to every generated file.`,type:`string`}).option(`semicolon`,{description:"Emit trailing `;` on each export line. Negate with `--no-semicolon`. Default: omitted.",type:`boolean`,default:!1}).option(`single-quotes`,{description:"Use `'` for import specifiers. Default: true. Pass `--no-single-quotes` for `\"`.",type:`boolean`,default:!0}).option(`check`,{description:`Report drift without modifying files; exit non-zero if any barrel is stale.`,type:`boolean`,default:!1}).option(`verbose`,{description:`Log each file scanned + written.`,type:`boolean`,default:!1}),handler:async n=>{let a=Array.from(new Set((n.paths??[]).filter(Boolean)));if(a.length===0){Fe.error(`[gjsify barrels] no paths provided. Pass directories as positional arguments or via --paths.`),process.exitCode=1;return}let S=n.exclude?.length?n.exclude:[...xD],C=await generateBarrels({paths:a,extension:n.ext??`none`,baseDir:n.baseDir??process.cwd(),exclude:S.map(n=>new RegExp(n)),header:n.header??"// Auto-generated by `gjsify barrels` — do not edit by hand.",noSemicolon:n.semicolon===!1||n.semicolon===void 0,singleQuotes:n.singleQuotes!==!1,check:n.check??!1,verbose:n.verbose??!1});n.check&&C>0&&(Fe.error(`[gjsify barrels] ${C} barrel file(s) drifted. Run without --check to fix.`),process.exitCode=1)}};As(),Ho(),rn();function readBundleVersion(){try{let n=Po(fileURLToPath(import.meta.url)),a=JSON.parse(readFileSync(jo(n,`..`,`package.json`),`utf8`));return typeof a.version==`string`?a.version:`unknown`}catch{return`unknown`}}const wD=Nu(hideBin(process.argv));await wD.scriptName(Pu).version(readBundleVersion()).strict().wrap(wD.terminalWidth()).command(yE.command,yE.description,yE.builder,yE.handler).command(aD.command,aD.description,aD.builder,aD.handler).command(iE.command,iE.description,iE.builder,iE.handler).command(aE.command,aE.description,aE.builder,aE.handler).command(oE.command,oE.description,oE.builder,oE.handler).command(iD.command,iD.description,iD.builder,iD.handler).command(sE.command,sE.description,sE.builder,sE.handler).command(fE.command,fE.description,fE.builder,fE.handler).command(pE.command,pE.description,pE.builder,pE.handler).command(mE.command,mE.description,mE.builder,mE.handler).command(xE.command,xE.description,xE.builder,xE.handler).command(CE.command,CE.description,CE.builder,CE.handler).command(TE.command,TE.description,TE.builder,TE.handler).command(zE.command,zE.description,zE.builder,zE.handler).command(oD.command,oD.description,oD.builder,oD.handler).command(sD.command,sD.description,sD.builder,sD.handler).command(cD.command,cD.description,cD.builder,cD.handler).command(uD.command,uD.description,uD.builder,uD.handler).command(fD.command,fD.description,fD.builder,fD.handler).command(pD.command,pD.description,pD.builder,pD.handler).command(mD.command,mD.description,mD.builder,mD.handler).command(vD.command,vD.description,vD.builder,vD.handler).command(hD.command,hD.description,hD.builder,hD.handler).command(gD.command,gD.description,gD.builder,gD.handler).command(_D.command,_D.description,_D.builder,_D.handler).command(CD.command,CD.description,CD.builder,CD.handler).demandCommand(1).help().parseAsync();
810
+ `,Y=`${n.header}\n\n${q}`,X=jo(I,`index.ts`);if(await readFile$1(X,`utf-8`).catch(()=>``)===Y){n.verbose&&Fe.log(`[gjsify barrels] up-to-date: ${X}`);continue}n.check?(Fe.error(`[gjsify barrels] drift: ${X}`),N++):(await writeFile$1(X,Y,`utf-8`),n.verbose&&Fe.log(`[gjsify barrels] wrote: ${X}`))}return N}Ie();const CD={command:`barrels [paths..]`,description:"Regenerate `index.ts` barrel files for the given directories. Drop-in replacement for `barrelsby`.",builder:n=>n.positional(`paths`,{description:"Directories whose `index.ts` to (re)generate. May also be passed via `--paths`.",type:`string`,array:!0}).option(`paths`,{alias:`p`,description:`Alternative to positional — repeatable list of directories.`,type:`string`,array:!0}).option(`ext`,{description:"Import-specifier extension. Default: `none` (bundler-mode resolution).",type:`string`,choices:[`js`,`ts`,`none`],default:`none`}).option(`base-dir`,{alias:`b`,description:"Resolve `paths` against this directory. Default: cwd.",type:`string`}).option(`exclude`,{description:"Regex(es) of file names to skip. Repeatable. Defaults: `\\.test\\.`, `\\.spec\\.`, `\\.test-data\\.`.",type:`string`,array:!0}).option(`header`,{description:`Header comment prepended to every generated file.`,type:`string`}).option(`semicolon`,{description:"Emit trailing `;` on each export line. Negate with `--no-semicolon`. Default: omitted.",type:`boolean`,default:!1}).option(`single-quotes`,{description:"Use `'` for import specifiers. Default: true. Pass `--no-single-quotes` for `\"`.",type:`boolean`,default:!0}).option(`check`,{description:`Report drift without modifying files; exit non-zero if any barrel is stale.`,type:`boolean`,default:!1}).option(`verbose`,{description:`Log each file scanned + written.`,type:`boolean`,default:!1}),handler:async n=>{let a=Array.from(new Set((n.paths??[]).filter(Boolean)));if(a.length===0){Fe.error(`[gjsify barrels] no paths provided. Pass directories as positional arguments or via --paths.`),process.exitCode=1;return}let S=n.exclude?.length?n.exclude:[...xD],C=await generateBarrels({paths:a,extension:n.ext??`none`,baseDir:n.baseDir??process.cwd(),exclude:S.map(n=>new RegExp(n)),header:n.header??"// Auto-generated by `gjsify barrels` — do not edit by hand.",noSemicolon:n.semicolon===!1||n.semicolon===void 0,singleQuotes:n.singleQuotes!==!1,check:n.check??!1,verbose:n.verbose??!1});n.check&&C>0&&(Fe.error(`[gjsify barrels] ${C} barrel file(s) drifted. Run without --check to fix.`),process.exitCode=1)}};As(),Ho(),rn();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 typeof process<`u`&&typeof process.versions?.node==`string`?`Node.js ${process.version}`:`unknown runtime`}function readBundleVersion(){try{let n=Po(fileURLToPath(import.meta.url)),a=JSON.parse(readFileSync(jo(n,`..`,`package.json`),`utf8`));return typeof a.version==`string`?a.version:`unknown`}catch{return`unknown`}}const wD=Nu(hideBin(process.argv));await wD.scriptName(Pu).version(readBundleVersion()).strict().wrap(wD.terminalWidth()).command(yE.command,yE.description,yE.builder,yE.handler).command(aD.command,aD.description,aD.builder,aD.handler).command(iE.command,iE.description,iE.builder,iE.handler).command(aE.command,aE.description,aE.builder,aE.handler).command(oE.command,oE.description,oE.builder,oE.handler).command(iD.command,iD.description,iD.builder,iD.handler).command(sE.command,sE.description,sE.builder,sE.handler).command(fE.command,fE.description,fE.builder,fE.handler).command(pE.command,pE.description,pE.builder,pE.handler).command(mE.command,mE.description,mE.builder,mE.handler).command(xE.command,xE.description,xE.builder,xE.handler).command(CE.command,CE.description,CE.builder,CE.handler).command(TE.command,TE.description,TE.builder,TE.handler).command(zE.command,zE.description,zE.builder,zE.handler).command(oD.command,oD.description,oD.builder,oD.handler).command(sD.command,sD.description,sD.builder,sD.handler).command(cD.command,cD.description,cD.builder,cD.handler).command(uD.command,uD.description,uD.builder,uD.handler).command(fD.command,fD.description,fD.builder,fD.handler).command(pD.command,pD.description,pD.builder,pD.handler).command(mD.command,mD.description,mD.builder,mD.handler).command(vD.command,vD.description,vD.builder,vD.handler).command(hD.command,hD.description,hD.builder,hD.handler).command(gD.command,gD.description,gD.builder,gD.handler).command(_D.command,_D.description,_D.builder,_D.handler).command(CD.command,CD.description,CD.builder,CD.handler).demandCommand(1).epilogue(`Running on ${runtimeLabel()}`).help().parseAsync();
@@ -3,6 +3,7 @@ interface PublishOptions {
3
3
  path?: string;
4
4
  tag?: string;
5
5
  access?: string;
6
+ otp?: string;
6
7
  'tolerate-republish'?: boolean;
7
8
  'tolerate-untrusted-new'?: boolean;
8
9
  provenance?: boolean;
@@ -52,6 +52,10 @@ export const publishCommand = {
52
52
  .option('access', {
53
53
  description: 'Package access — `public` or `restricted` (required for first publish of scoped packages on the public registry).',
54
54
  type: 'string',
55
+ })
56
+ .option('otp', {
57
+ description: 'npm 2FA one-time code; sent as the `npm-otp` header. Required for manual publishes from a 2FA-enabled account.',
58
+ type: 'string',
55
59
  })
56
60
  .option('tolerate-republish', {
57
61
  description: 'Treat "version already published" as success — covers both classic 409 Conflict and the npm OIDC-path 403 Forbidden + `"previously published"` body shape. Matches yarn `--tolerate-republish`.',
@@ -95,6 +99,7 @@ export const publishCommand = {
95
99
  const wsDir = resolve(args.path ?? process.cwd());
96
100
  const tag = args.tag ?? 'latest';
97
101
  const access = args.access;
102
+ const otp = args.otp;
98
103
  const tolerate = args['tolerate-republish'] === true;
99
104
  const tolerateUntrustedNew = args['tolerate-untrusted-new'] === true;
100
105
  const provenance = args.provenance === true;
@@ -240,6 +245,11 @@ export const publishCommand = {
240
245
  const headers = buildHeaders(url, { npmrc });
241
246
  headers['content-type'] = 'application/json';
242
247
  headers['accept'] = '*/*';
248
+ // 2FA OTP — sent as the `npm-otp` header (npm-registry-fetch convention,
249
+ // verified in refs/npm-cli/node_modules/npm-registry-fetch/lib/index.js
250
+ // line ~243: `if (opts.otp) headers['npm-otp'] = opts.otp`).
251
+ if (otp)
252
+ headers['npm-otp'] = otp;
243
253
  // Trusted Publishing path. `--trusted` forces OIDC (errors if env
244
254
  // vars are missing); the default `undefined` triggers auto-detect:
245
255
  // OIDC is used iff GitHub OIDC env vars are present AND no
@@ -306,13 +316,56 @@ export const publishCommand = {
306
316
  console.error(`gjsify publish: PUT ${url} (${packed.name}@${packed.version})`);
307
317
  console.error(` auth-mode: ${authMode}`);
308
318
  console.error(` authorization: ${headers['authorization'] ? '(set)' : '(none)'}`);
319
+ console.error(` otp: ${headers['npm-otp'] ? '(set)' : '(none)'}`);
309
320
  console.error(` payload size: ${JSON.stringify(payload).length} bytes`);
310
321
  }
311
- const res = await fetch(url, {
312
- method: 'PUT',
313
- headers,
314
- body: JSON.stringify(payload),
315
- });
322
+ const bodyStr = JSON.stringify(payload);
323
+ // Helper that PUTs with a given header set and returns the response.
324
+ async function doPut(reqHeaders) {
325
+ return fetch(url, {
326
+ method: 'PUT',
327
+ headers: reqHeaders,
328
+ body: bodyStr,
329
+ });
330
+ }
331
+ let res = await doPut(headers);
332
+ // EOTP handling — mirrors npm's otplease.js (refs/npm-cli/lib/utils/auth.js).
333
+ // npm signals "OTP required" via:
334
+ // - HTTP 401 + `www-authenticate` header containing "otp"
335
+ // (refs/npm-cli/node_modules/npm-registry-fetch/lib/check-response.js
336
+ // line ~83: `auth.indexOf('otp') !== -1` → HttpErrorAuthOTP)
337
+ // - HTTP 401 + body containing "one-time pass" (heuristic for
338
+ // malformed responses missing the www-authenticate header —
339
+ // same check-response.js lines ~92-98)
340
+ // We check both shapes, exactly matching npm's logic.
341
+ // If the caller already supplied --otp we skip this (they set the
342
+ // header; if the registry still 401s that is a wrong-code error).
343
+ if (!otp && res.status === 401) {
344
+ const wwwAuth = res.headers.get('www-authenticate') ?? '';
345
+ const body401 = await res.text().catch(() => '');
346
+ const needsOtp = wwwAuth.toLowerCase().split(/,\s*/).includes('otp') ||
347
+ /one-time pass/i.test(body401);
348
+ if (needsOtp) {
349
+ // Interactive path: if stdin is a TTY, prompt and retry once.
350
+ if (process.stdin.isTTY && process.stdout.isTTY) {
351
+ process.stdout.write('This operation requires a one-time password.\nEnter OTP: ');
352
+ const enteredOtp = await readLineFromStdin();
353
+ if (enteredOtp) {
354
+ const retryHeaders = { ...headers, 'npm-otp': enteredOtp };
355
+ res = await doPut(retryHeaders);
356
+ }
357
+ else {
358
+ console.error(`gjsify publish: no OTP entered — re-run with \`--otp <code>\``);
359
+ process.exit(1);
360
+ }
361
+ }
362
+ else {
363
+ // Non-interactive: give the maintainer a clear, actionable message.
364
+ console.error(`gjsify publish: npm requires a 2FA one-time code — re-run with \`--otp <code>\``);
365
+ process.exit(1);
366
+ }
367
+ }
368
+ }
316
369
  if (res.ok) {
317
370
  const out = {
318
371
  ok: true,
@@ -480,6 +533,46 @@ function base64Encode(bytes) {
480
533
  }
481
534
  return btoa(str);
482
535
  }
536
+ /**
537
+ * Read a single line from stdin (blocking via async iterator). Used for the
538
+ * interactive OTP prompt path (mirrors npm's `read.otp()`). Resolves with the
539
+ * trimmed line or an empty string if stdin closed without input.
540
+ */
541
+ async function readLineFromStdin() {
542
+ return new Promise((resolve) => {
543
+ let buf = '';
544
+ const onData = (chunk) => {
545
+ buf += typeof chunk === 'string' ? chunk : chunk.toString('utf-8');
546
+ const nl = buf.indexOf('\n');
547
+ if (nl >= 0) {
548
+ cleanup();
549
+ resolve(buf.slice(0, nl).trim());
550
+ }
551
+ };
552
+ const onEnd = () => {
553
+ cleanup();
554
+ resolve(buf.trim());
555
+ };
556
+ const onError = () => {
557
+ cleanup();
558
+ resolve('');
559
+ };
560
+ const cleanup = () => {
561
+ process.stdin.removeListener('data', onData);
562
+ process.stdin.removeListener('end', onEnd);
563
+ process.stdin.removeListener('error', onError);
564
+ if (typeof process.stdin.unref === 'function') {
565
+ process.stdin.unref?.();
566
+ }
567
+ };
568
+ process.stdin.setEncoding('utf-8');
569
+ if (process.stdin.isPaused())
570
+ process.stdin.resume();
571
+ process.stdin.once('data', onData);
572
+ process.stdin.once('end', onEnd);
573
+ process.stdin.once('error', onError);
574
+ });
575
+ }
483
576
  function handleOidcFailure(err, packageName, asJson) {
484
577
  if (err instanceof OidcUnavailableError) {
485
578
  const msg = `gjsify publish: OIDC not available — ${err.message}`;
@@ -83,11 +83,29 @@ export const selfUpdateCommand = {
83
83
  return;
84
84
  }
85
85
  console.log(`Installing ${PACKAGE_NAME}@${target} ...`);
86
- await installPackages({
87
- prefix: layout.prefix,
88
- specs: [`${PACKAGE_NAME}@${target}`],
89
- verbose: false,
90
- });
86
+ // `@gjsify/cli` is a self-contained GJS bundle: every workspace dep
87
+ // (`@gjsify/node-polyfills`, `@gjsify/v8`, …) is bundled into the
88
+ // published `dist/cli.gjs.mjs` artifact and must NOT be resolved as
89
+ // a separate npm package. `skipDeps: true` limits the native install
90
+ // backend to fetching the top-level tarball only, avoiding spurious
91
+ // packument requests for workspace-internal packages that are not
92
+ // published to the public registry (which previously caused a
93
+ // 406 Not Acceptable → fatal crash on the `@gjsify/v8` packument).
94
+ try {
95
+ await installPackages({
96
+ prefix: layout.prefix,
97
+ specs: [`${PACKAGE_NAME}@${target}`],
98
+ verbose: false,
99
+ skipDeps: true,
100
+ });
101
+ }
102
+ catch (err) {
103
+ const msg = err instanceof Error ? err.message : String(err);
104
+ console.error(`self-update: install failed — ${msg}`);
105
+ console.error(`Re-run \`gjsify self-update\` to retry.`);
106
+ process.exit(1);
107
+ return;
108
+ }
91
109
  const linked = linkGlobalBins([PACKAGE_NAME], layout);
92
110
  if (linked.length === 0) {
93
111
  console.warn('self-update: install completed but no bins were linked — package.json may be missing a `bin` field.');
@@ -107,6 +125,18 @@ export const selfUpdateCommand = {
107
125
  */
108
126
  function readCurrentVersion() {
109
127
  try {
128
+ // Escape hatch for tests: point GJSIFY_CLI_PACKAGE_JSON at a synthetic
129
+ // package.json to override the upward-walk discovery. When set to a
130
+ // file whose `name` does not equal PACKAGE_NAME the function returns
131
+ // null, which is the correct production behaviour for "version unknown".
132
+ const override = process.env.GJSIFY_CLI_PACKAGE_JSON;
133
+ if (override) {
134
+ const pkg = JSON.parse(readFileSync(override, 'utf-8'));
135
+ if (pkg.name === PACKAGE_NAME && typeof pkg.version === 'string') {
136
+ return pkg.version;
137
+ }
138
+ return null;
139
+ }
110
140
  const here = fileURLToPath(import.meta.url);
111
141
  let dir = dirname(resolve(here));
112
142
  for (let i = 0; i < 8 && dir !== dirname(dir); i++) {
package/lib/index.js CHANGED
@@ -6,6 +6,24 @@ import yargs from 'yargs';
6
6
  import { hideBin } from 'yargs/helpers';
7
7
  import { buildCommand as build, testCommand as test, runCommand as run, infoCommand as info, systemCheckCommand as systemCheck, checkCommand as check, showcaseCommand as showcase, createCommand as create, gresourceCommand as gresource, gettextCommand as gettext, gsettingsCommand as gsettings, flatpakCommand as flatpak, dlxCommand as dlx, installCommand as install, foreachCommand as foreach, workspaceCommand as workspace, packCommand as pack, publishCommand as publish, selfUpdateCommand as selfUpdate, generateInstallerCommand as generateInstaller, uninstallCommand as uninstall, formatCommand as format, lintCommand as lint, fixCommand as fix, upgradeCommand as upgrade, barrelsCommand as barrels, } from './commands/index.js';
8
8
  import { APP_NAME } from './constants.js';
9
+ // Detect which runtime is executing the CLI (GJS or Node.js).
10
+ // GJS MUST be checked first because @gjsify/process sets
11
+ // `process.versions.node = '20.0.0'` for compatibility — a plain
12
+ // `process.versions.node` check would be a false Node positive under GJS.
13
+ function runtimeLabel() {
14
+ try {
15
+ const sys = globalThis.imports?.system;
16
+ if (sys?.version !== undefined) {
17
+ const v = Number(sys.version);
18
+ return `GJS ${Math.floor(v / 10000)}.${Math.floor((v % 10000) / 100)}.${v % 100} (SpiderMonkey)`;
19
+ }
20
+ }
21
+ catch { /* not GJS */ }
22
+ if (typeof process !== 'undefined' && typeof process.versions?.node === 'string') {
23
+ return `Node.js ${process.version}`;
24
+ }
25
+ return 'unknown runtime';
26
+ }
9
27
  // Read the version from package.json adjacent to the bundle. yargs's
10
28
  // auto-version-discovery (its `pkg-up`-driven default) doesn't reach
11
29
  // through the bundled `dist/cli.gjs.mjs` path on GJS — falls back to
@@ -68,5 +86,6 @@ await cli
68
86
  .command(fix.command, fix.description, fix.builder, fix.handler)
69
87
  .command(barrels.command, barrels.description, barrels.builder, barrels.handler)
70
88
  .demandCommand(1)
89
+ .epilogue(`Running on ${runtimeLabel()}`)
71
90
  .help()
72
91
  .parseAsync();
@@ -56,7 +56,7 @@ export async function installPackagesNative(opts) {
56
56
  }
57
57
  else {
58
58
  log("install: resolving %d top-level spec(s) → %s", opts.specs.length, opts.prefix);
59
- nodes = await resolveDeps(opts.specs, npmrc, log, opts.overrides);
59
+ nodes = await resolveDeps(opts.specs, npmrc, log, opts.overrides, opts.skipDeps);
60
60
  if (opts.lockfile) {
61
61
  writeLockfile(lockfilePath, opts.specs, nodes);
62
62
  log("install: wrote %s (%d entries)", LOCKFILE_NAME, nodes.length);
@@ -119,7 +119,7 @@ function parseSpecName(spec) {
119
119
  * the root. Each placement returns a `ResolvedNode` whose `installPath`
120
120
  * captures where it lives in the tree.
121
121
  */
122
- async function resolveDeps(specs, npmrc, log, overrides) {
122
+ async function resolveDeps(specs, npmrc, log, overrides, skipDeps) {
123
123
  const applyOverride = (name, range) => {
124
124
  if (!overrides)
125
125
  return range;
@@ -201,11 +201,13 @@ async function resolveDeps(specs, npmrc, log, overrides) {
201
201
  root.set(edge.name, node);
202
202
  }
203
203
  log("resolve: %s@%s ← %s (at %s)", edge.name, version, edge.range, installPath);
204
- for (const [depName, depRange] of Object.entries(node.dependencies)) {
205
- queue.push({ from: installPath, name: depName, range: applyOverride(depName, depRange), required: true });
206
- }
207
- for (const [depName, depRange] of Object.entries(node.optionalDependencies)) {
208
- queue.push({ from: installPath, name: depName, range: applyOverride(depName, depRange), required: false });
204
+ if (!skipDeps) {
205
+ for (const [depName, depRange] of Object.entries(node.dependencies)) {
206
+ queue.push({ from: installPath, name: depName, range: applyOverride(depName, depRange), required: true });
207
+ }
208
+ for (const [depName, depRange] of Object.entries(node.optionalDependencies)) {
209
+ queue.push({ from: installPath, name: depName, range: applyOverride(depName, depRange), required: false });
210
+ }
209
211
  }
210
212
  }
211
213
  catch (e) {
@@ -27,6 +27,19 @@ export interface InstallOptions {
27
27
  * forcing `typescript@~5.9` across every `typescript@*` devDep.
28
28
  */
29
29
  overrides?: Record<string, string>;
30
+ /**
31
+ * Native backend only: skip transitive dependency resolution and only
32
+ * install the top-level requested packages. Use this when the packages
33
+ * are self-contained bundles whose declared `dependencies` are either
34
+ * bundled into the artifact (e.g. `@gjsify/cli`'s GJS bundle) or
35
+ * workspace-only packages not published to npm separately. Setting this
36
+ * avoids spurious packument fetches for workspace-internal packages.
37
+ *
38
+ * Has no effect when `frozen: true` (the lockfile already contains the
39
+ * full resolved tree and is used verbatim) or when `GJSIFY_INSTALL_BACKEND=npm`
40
+ * (npm does its own resolution and does not consult this flag).
41
+ */
42
+ skipDeps?: boolean;
30
43
  }
31
44
  export interface InstallResult {
32
45
  /** Top-level packages that were requested, with the version each
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/cli",
3
- "version": "0.4.27",
3
+ "version": "0.4.28",
4
4
  "description": "CLI for Gjsify",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -120,18 +120,18 @@
120
120
  "cli"
121
121
  ],
122
122
  "dependencies": {
123
- "@gjsify/buffer": "^0.4.27",
124
- "@gjsify/create-app": "^0.4.27",
125
- "@gjsify/node-globals": "^0.4.27",
126
- "@gjsify/node-polyfills": "^0.4.27",
127
- "@gjsify/npm-registry": "^0.4.27",
128
- "@gjsify/resolve-npm": "^0.4.27",
129
- "@gjsify/rolldown-plugin-gjsify": "^0.4.27",
130
- "@gjsify/rolldown-plugin-pnp": "^0.4.27",
131
- "@gjsify/semver": "^0.4.27",
132
- "@gjsify/tar": "^0.4.27",
133
- "@gjsify/web-polyfills": "^0.4.27",
134
- "@gjsify/workspace": "^0.4.27",
123
+ "@gjsify/buffer": "^0.4.28",
124
+ "@gjsify/create-app": "^0.4.28",
125
+ "@gjsify/node-globals": "^0.4.28",
126
+ "@gjsify/node-polyfills": "^0.4.28",
127
+ "@gjsify/npm-registry": "^0.4.28",
128
+ "@gjsify/resolve-npm": "^0.4.28",
129
+ "@gjsify/rolldown-plugin-gjsify": "^0.4.28",
130
+ "@gjsify/rolldown-plugin-pnp": "^0.4.28",
131
+ "@gjsify/semver": "^0.4.28",
132
+ "@gjsify/tar": "^0.4.28",
133
+ "@gjsify/web-polyfills": "^0.4.28",
134
+ "@gjsify/workspace": "^0.4.28",
135
135
  "cosmiconfig": "^9.0.1",
136
136
  "get-tsconfig": "^4.14.0",
137
137
  "pkg-types": "^2.3.1",
@@ -139,12 +139,12 @@
139
139
  "yargs": "^18.0.0"
140
140
  },
141
141
  "devDependencies": {
142
- "@gjsify/unit": "^0.4.27",
142
+ "@gjsify/unit": "^0.4.28",
143
143
  "@types/yargs": "^17.0.35",
144
144
  "typescript": "^6.0.3"
145
145
  },
146
146
  "peerDependencies": {
147
- "@gjsify/rolldown-native": "^0.4.27"
147
+ "@gjsify/rolldown-native": "^0.4.28"
148
148
  },
149
149
  "peerDependenciesMeta": {
150
150
  "@gjsify/rolldown-native": {