@gjsify/cli 0.64.21 → 0.64.22

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
@@ -146,7 +146,7 @@ fi
146
146
  `)}`:``;n.fail(N(`Missing required argument: %s`,`Missing required arguments: %s`,Object.keys(C).length,Object.keys(C).join(`, `)+S))}},F.unknownArguments=function unknownArguments(S,C,I,H,W=!0){let q=t.getInternalMethods().getCommandInstance().getCommands(),Y=[],X=t.getInternalMethods().getContext();if(Object.keys(S).forEach(n=>{!Ip.includes(n)&&!Object.prototype.hasOwnProperty.call(I,n)&&!Object.prototype.hasOwnProperty.call(t.getInternalMethods().getParseContext(),n)&&!F.isValidAndSomeAliasIsNotNew(n,C)&&Y.push(n)}),W&&(X.commands.length>0||q.length>0||H)&&S._.slice(X.commands.length).forEach(t=>{q.includes(``+t)||Y.push(``+t)}),W){let n=t.getDemandedCommands()._?.max||0,C=X.commands.length+n;C<S._.length&&S._.slice(C).forEach(t=>{t=String(t),!X.commands.includes(t)&&!Y.includes(t)&&Y.push(t)})}Y.length&&n.fail(N(`Unknown argument: %s`,`Unknown arguments: %s`,Y.length,Y.map(t=>t.trim()?t:`"${t}"`).join(`, `)))},F.unknownCommands=function unknownCommands(S){let C=t.getInternalMethods().getCommandInstance().getCommands(),F=[],I=t.getInternalMethods().getContext();return(I.commands.length>0||C.length>0)&&S._.slice(I.commands.length).forEach(t=>{C.includes(``+t)||F.push(``+t)}),F.length>0?(n.fail(N(`Unknown command: %s`,`Unknown commands: %s`,F.length,F.join(`, `))),!0):!1},F.isValidAndSomeAliasIsNotNew=function isValidAndSomeAliasIsNotNew(n,S){if(!Object.prototype.hasOwnProperty.call(S,n))return!1;let C=t.parsed.newAliases;return[n,...S[n]].some(t=>!Object.prototype.hasOwnProperty.call(C,t)||!C[n])},F.limitedChoices=function limitedChoices(S){let N=t.getOptions(),F={};if(!Object.keys(N.choices).length)return;Object.keys(S).forEach(t=>{Ip.indexOf(t)===-1&&Object.prototype.hasOwnProperty.call(N.choices,t)&&[].concat(S[t]).forEach(n=>{N.choices[t].indexOf(n)===-1&&n!==void 0&&(F[t]=(F[t]||[]).concat(n))})});let I=Object.keys(F);if(!I.length)return;let H=C(`Invalid values:`);I.forEach(t=>{H+=`\n ${C(`Argument: %s, Given: %s, Choices: %s`,t,n.stringifiedValues(F[t]),n.stringifiedValues(N.choices[t]))}`}),n.fail(H)};let I={};F.implies=function implies(n,C){argsert(`<string|object> [array|number|string]`,[n,C],arguments.length),typeof n==`object`?Object.keys(n).forEach(t=>{F.implies(t,n[t])}):(t.global(n),I[n]||(I[n]=[]),Array.isArray(C)?C.forEach(t=>F.implies(n,t)):(assertNotStrictEqual(C,void 0,S),I[n].push(C)))},F.getImplied=function getImplied(){return I};function keyExists(t,n){let S=Number(n);return n=isNaN(S)?n:S,typeof n==`number`?n=t._.length>=n:n.match(/^--no-.+/)?(n=n.match(/^--no-(.+)/)[1],n=!Object.prototype.hasOwnProperty.call(t,n)):n=Object.prototype.hasOwnProperty.call(t,n),n}F.implications=function implications(t){let S=[];if(Object.keys(I).forEach(n=>{let C=n;(I[n]||[]).forEach(n=>{let N=C,F=n;N=keyExists(t,N),n=keyExists(t,n),N&&!n&&S.push(` ${C} -> ${F}`)})}),S.length){let t=`${C(`Implications failed:`)}\n`;S.forEach(n=>{t+=n}),n.fail(t)}};let H={};F.conflicts=function conflicts(n,S){argsert(`<string|object> [array|string]`,[n,S],arguments.length),typeof n==`object`?Object.keys(n).forEach(t=>{F.conflicts(t,n[t])}):(t.global(n),H[n]||(H[n]=[]),Array.isArray(S)?S.forEach(t=>F.conflicts(n,t)):H[n].push(S))},F.getConflicting=()=>H,F.conflicting=function conflictingFn(N){Object.keys(N).forEach(t=>{H[t]&&H[t].forEach(S=>{S&&N[t]!==void 0&&N[S]!==void 0&&n.fail(C(`Arguments %s and %s are mutually exclusive`,t,S))})}),t.getInternalMethods().getParserConfiguration()[`strip-dashed`]&&Object.keys(H).forEach(t=>{H[t].forEach(F=>{F&&N[S.Parser.camelCase(t)]!==void 0&&N[S.Parser.camelCase(F)]!==void 0&&n.fail(C(`Arguments %s and %s are mutually exclusive`,t,F))})})},F.recommendCommands=function recommendCommands(t,S){S=S.sort((t,n)=>n.length-t.length);let N=null,F=1/0;for(let n=0,C;(C=S[n])!==void 0;n++){let n=levenshtein(t,C);n<=3&&n<F&&(F=n,N=C)}N&&n.fail(C(`Did you mean %s?`,N))},F.reset=function reset(t){return I=objFilter(I,n=>!t[n]),H=objFilter(H,n=>!t[n]),F};let W=[];return F.freeze=function freeze(){W.push({implied:I,conflicting:H})},F.unfreeze=function unfreeze(){let t=W.pop();assertNotStrictEqual(t,void 0,S),{implied:I,conflicting:H}=t},F}var Ip,Lp=__esmMin(()=>{Cp(),yp(),Fp(),Op(),Ip=[`$0`,`--`,`_`]});function YargsFactory(t){return(n=[],S=t.process.cwd(),C)=>{let N=new YargsInstance(n,S,C,t);return Object.defineProperty(N,"argv",{get:()=>N.parse(),enumerable:!0}),N.help(),N.version(),N}}function isYargsInstance(t){return!!t&&typeof t.getInternalMethods==`function`}var __classPrivateFieldSet,__classPrivateFieldGet,Rp,zp,Bp,Vp,Hp,Up,Wp,Gp,Kp,qp,Jp,Yp,Xp,Zp,Qp,$p,em,tm,nm,im,am,om,sm,cm,lm,um,dm,fm,pm,mm,hm,gm,_m,vm,ym,bm,xm,Sm,Cm,wm,Tm,Em,Dm,Om,km,Am,jm,Mm,Nm,Pm,Fm,Im,Lm,Rm,zm,Bm,Vm,Hm,Um,Wm,Gm,Km,qm,Jm,Ym,Xm,Zm,Qm,$m,eh,th,nh,YargsInstance,rh=__esmMin(()=>{_e(),Dp(),yp(),Ll(),Ap(),Cp(),Pp(),Lp(),Op(),Bl(),wp(),bp(),Tp(),kp(),__classPrivateFieldSet=function(t,n,S,C,N){if(C===`m`)throw TypeError(`Private method is not writable`);if(C===`a`&&!N)throw TypeError(`Private accessor was defined without a setter`);if(typeof n==`function`?t!==n||!N:!n.has(t))throw TypeError(`Cannot write private member to an object whose class did not declare it`);return C===`a`?N.call(t,S):N?N.value=S:n.set(t,S),S},__classPrivateFieldGet=function(t,n,S,C){if(S===`a`&&!C)throw TypeError(`Private accessor was defined without a getter`);if(typeof n==`function`?t!==n||!C:!n.has(t))throw TypeError(`Cannot read private member from an object whose class did not declare it`);return S===`m`?C:S===`a`?C.call(t):C?C.value:n.get(t)},bm=Symbol(`copyDoubleDash`),xm=Symbol(`copyDoubleDash`),Sm=Symbol(`deleteFromParserHintObject`),Cm=Symbol(`emitWarning`),wm=Symbol(`freeze`),Tm=Symbol(`getDollarZero`),Em=Symbol(`getParserConfiguration`),Dm=Symbol(`getUsageConfiguration`),Om=Symbol(`guessLocale`),km=Symbol(`guessVersion`),Am=Symbol(`parsePositionalNumbers`),jm=Symbol(`pkgUp`),Mm=Symbol(`populateParserHintArray`),Nm=Symbol(`populateParserHintSingleValueDictionary`),Pm=Symbol(`populateParserHintArrayDictionary`),Fm=Symbol(`populateParserHintDictionary`),Im=Symbol(`sanitizeKey`),Lm=Symbol(`setKey`),Rm=Symbol(`unfreeze`),zm=Symbol(`validateAsync`),Bm=Symbol(`getCommandInstance`),Vm=Symbol(`getContext`),Hm=Symbol(`getHasOutput`),Um=Symbol(`getLoggerInstance`),Wm=Symbol(`getParseContext`),Gm=Symbol(`getUsageInstance`),Km=Symbol(`getValidationInstance`),qm=Symbol(`hasParseCallback`),Jm=Symbol(`isGlobalContext`),Ym=Symbol(`postProcess`),Xm=Symbol(`rebase`),Zm=Symbol(`reset`),Qm=Symbol(`runYargsParserAndExecuteCommands`),$m=Symbol(`runValidation`),eh=Symbol(`setHasOutput`),th=Symbol(`kTrackManuallySetKeys`),nh=`en_US`,YargsInstance=class{constructor(t=[],n,S,C){this.customScriptName=!1,this.parsed=!1,Rp.set(this,void 0),zp.set(this,void 0),Bp.set(this,{commands:[],fullCommands:[]}),Vp.set(this,null),Hp.set(this,null),Up.set(this,`show-hidden`),Wp.set(this,null),Gp.set(this,!0),Kp.set(this,{}),qp.set(this,!0),Jp.set(this,[]),Yp.set(this,void 0),Xp.set(this,{}),Zp.set(this,!1),Qp.set(this,null),$p.set(this,!0),em.set(this,void 0),tm.set(this,``),nm.set(this,void 0),im.set(this,void 0),am.set(this,{}),om.set(this,null),sm.set(this,null),cm.set(this,{}),lm.set(this,{}),um.set(this,void 0),dm.set(this,!1),fm.set(this,void 0),pm.set(this,!1),mm.set(this,!1),hm.set(this,!1),gm.set(this,void 0),_m.set(this,{}),vm.set(this,null),ym.set(this,void 0),__classPrivateFieldSet(this,fm,C,`f`),__classPrivateFieldSet(this,um,t,`f`),__classPrivateFieldSet(this,zp,n,`f`),__classPrivateFieldSet(this,im,S,`f`),__classPrivateFieldSet(this,Yp,new GlobalMiddleware(this),`f`),this.$0=this[Tm](),this[Zm](),__classPrivateFieldSet(this,Rp,__classPrivateFieldGet(this,Rp,`f`),`f`),__classPrivateFieldSet(this,gm,__classPrivateFieldGet(this,gm,`f`),`f`),__classPrivateFieldSet(this,ym,__classPrivateFieldGet(this,ym,`f`),`f`),__classPrivateFieldSet(this,nm,__classPrivateFieldGet(this,nm,`f`),`f`),__classPrivateFieldGet(this,nm,`f`).showHiddenOpt=__classPrivateFieldGet(this,Up,`f`),__classPrivateFieldSet(this,em,this[xm](),`f`),__classPrivateFieldGet(this,fm,`f`).y18n.setLocale(nh)}addHelpOpt(t,n){return argsert(`[string|boolean] [string]`,[t,n],arguments.length),__classPrivateFieldGet(this,Qp,`f`)&&(this[Sm](__classPrivateFieldGet(this,Qp,`f`)),__classPrivateFieldSet(this,Qp,null,`f`)),t===!1&&n===void 0?this:(__classPrivateFieldSet(this,Qp,typeof t==`string`?t:`help`,`f`),this.boolean(__classPrivateFieldGet(this,Qp,`f`)),this.describe(__classPrivateFieldGet(this,Qp,`f`),n||__classPrivateFieldGet(this,gm,`f`).deferY18nLookup(`Show help`)),this)}help(t,n){return this.addHelpOpt(t,n)}addShowHiddenOpt(t,n){if(argsert(`[string|boolean] [string]`,[t,n],arguments.length),t===!1&&n===void 0)return this;let S=typeof t==`string`?t:__classPrivateFieldGet(this,Up,`f`);return this.boolean(S),this.describe(S,n||__classPrivateFieldGet(this,gm,`f`).deferY18nLookup(`Show hidden options`)),__classPrivateFieldGet(this,nm,`f`).showHiddenOpt=S,this}showHidden(t,n){return this.addShowHiddenOpt(t,n)}alias(t,n){return argsert(`<object|string|array> [string|array]`,[t,n],arguments.length),this[Pm](this.alias.bind(this),`alias`,t,n),this}array(t){return argsert(`<array|string>`,[t],arguments.length),this[Mm](`array`,t),this[th](t),this}boolean(t){return argsert(`<array|string>`,[t],arguments.length),this[Mm](`boolean`,t),this[th](t),this}check(t,n){return argsert(`<function> [boolean]`,[t,n],arguments.length),this.middleware((n,S)=>maybeAsyncResult(()=>t(n,S.getOptions()),S=>(S?(typeof S==`string`||S instanceof Error)&&__classPrivateFieldGet(this,gm,`f`).fail(S.toString(),S):__classPrivateFieldGet(this,gm,`f`).fail(__classPrivateFieldGet(this,fm,`f`).y18n.__(`Argument check failed: %s`,t.toString())),n),t=>(__classPrivateFieldGet(this,gm,`f`).fail(t.message?t.message:t.toString(),t),n)),!1,n),this}choices(t,n){return argsert(`<object|string|array> [string|array]`,[t,n],arguments.length),this[Pm](this.choices.bind(this),`choices`,t,n),this}coerce(t,n){if(argsert(`<object|string|array> [function]`,[t,n],arguments.length),Array.isArray(t)){if(!n)throw new Il(`coerce callback must be provided`);for(let S of t)this.coerce(S,n);return this}else if(typeof t==`object`){for(let n of Object.keys(t))this.coerce(n,t[n]);return this}if(!n)throw new Il(`coerce callback must be provided`);let S=t;return __classPrivateFieldGet(this,nm,`f`).key[S]=!0,__classPrivateFieldGet(this,Yp,`f`).addCoerceMiddleware((t,C)=>{let N=C.getAliases()[S]??[],F=[S,...N].filter(n=>Object.prototype.hasOwnProperty.call(t,n));return F.length===0?t:maybeAsyncResult(()=>n(t[F[0]]),n=>(F.forEach(S=>{t[S]=n}),t),t=>{throw new Il(t.message)})},S),this}conflicts(t,n){return argsert(`<string|object> [string|array]`,[t,n],arguments.length),__classPrivateFieldGet(this,ym,`f`).conflicts(t,n),this}config(t=`config`,n,S){return argsert(`[object|string] [string|function] [function]`,[t,n,S],arguments.length),typeof t==`object`&&!Array.isArray(t)?(t=applyExtends(t,__classPrivateFieldGet(this,zp,`f`),this[Em]()[`deep-merge-config`]||!1,__classPrivateFieldGet(this,fm,`f`)),__classPrivateFieldGet(this,nm,`f`).configObjects=(__classPrivateFieldGet(this,nm,`f`).configObjects||[]).concat(t),this):(typeof n==`function`&&(S=n,n=void 0),this.describe(t,n||__classPrivateFieldGet(this,gm,`f`).deferY18nLookup(`Path to JSON config file`)),(Array.isArray(t)?t:[t]).forEach(t=>{__classPrivateFieldGet(this,nm,`f`).config[t]=S||!0}),this)}completion(t,n,S){return argsert(`[string] [string|boolean|function] [function]`,[t,n,S],arguments.length),typeof n==`function`&&(S=n,n=void 0),__classPrivateFieldSet(this,Hp,t||__classPrivateFieldGet(this,Hp,`f`)||`completion`,`f`),!n&&n!==!1&&(n=`generate completion script`),this.command(__classPrivateFieldGet(this,Hp,`f`),n),S&&__classPrivateFieldGet(this,Vp,`f`).registerFunction(S),this}command(t,n,S,C,N,F){return argsert(`<string|array|object> [string|boolean] [function|object] [function] [array] [boolean|string]`,[t,n,S,C,N,F],arguments.length),__classPrivateFieldGet(this,Rp,`f`).addHandler(t,n,S,C,N,F),this}commands(t,n,S,C,N,F){return this.command(t,n,S,C,N,F)}commandDir(t,n){argsert(`<string> [object]`,[t,n],arguments.length);let S=__classPrivateFieldGet(this,im,`f`)||__classPrivateFieldGet(this,fm,`f`).require;return __classPrivateFieldGet(this,Rp,`f`).addDirectory(t,S,__classPrivateFieldGet(this,fm,`f`).getCallerFile(),n),this}count(t){return argsert(`<array|string>`,[t],arguments.length),this[Mm](`count`,t),this[th](t),this}default(t,n,S){return argsert(`<object|string|array> [*] [string]`,[t,n,S],arguments.length),S&&(assertSingleKey(t,__classPrivateFieldGet(this,fm,`f`)),__classPrivateFieldGet(this,nm,`f`).defaultDescription[t]=S),typeof n==`function`&&(assertSingleKey(t,__classPrivateFieldGet(this,fm,`f`)),__classPrivateFieldGet(this,nm,`f`).defaultDescription[t]||(__classPrivateFieldGet(this,nm,`f`).defaultDescription[t]=__classPrivateFieldGet(this,gm,`f`).functionDescription(n)),n=n.call()),this[Nm](this.default.bind(this),`default`,t,n),this}defaults(t,n,S){return this.default(t,n,S)}demandCommand(t=1,n,S,C){return argsert(`[number] [number|string] [string|null|undefined] [string|null|undefined]`,[t,n,S,C],arguments.length),typeof n!=`number`&&(S=n,n=1/0),this.global(`_`,!1),__classPrivateFieldGet(this,nm,`f`).demandedCommands._={min:t,max:n,minMsg:S,maxMsg:C},this}demand(t,n,S){return Array.isArray(n)?(n.forEach(t=>{assertNotStrictEqual(S,!0,__classPrivateFieldGet(this,fm,`f`)),this.demandOption(t,S)}),n=1/0):typeof n!=`number`&&(S=n,n=1/0),typeof t==`number`?(assertNotStrictEqual(S,!0,__classPrivateFieldGet(this,fm,`f`)),this.demandCommand(t,n,S,S)):Array.isArray(t)?t.forEach(t=>{assertNotStrictEqual(S,!0,__classPrivateFieldGet(this,fm,`f`)),this.demandOption(t,S)}):typeof S==`string`?this.demandOption(t,S):(S===!0||S===void 0)&&this.demandOption(t),this}demandOption(t,n){return argsert(`<object|string|array> [string]`,[t,n],arguments.length),this[Nm](this.demandOption.bind(this),`demandedOptions`,t,n),this}deprecateOption(t,n){return argsert(`<string> [string|boolean]`,[t,n],arguments.length),__classPrivateFieldGet(this,nm,`f`).deprecatedOptions[t]=n,this}describe(t,n){return argsert(`<object|string|array> [string]`,[t,n],arguments.length),this[Lm](t,!0),__classPrivateFieldGet(this,gm,`f`).describe(t,n),this}detectLocale(t){return argsert(`<boolean>`,[t],arguments.length),__classPrivateFieldSet(this,Gp,t,`f`),this}env(t){return argsert(`[string|boolean]`,[t],arguments.length),t===!1?delete __classPrivateFieldGet(this,nm,`f`).envPrefix:__classPrivateFieldGet(this,nm,`f`).envPrefix=t||``,this}epilogue(t){return argsert(`<string>`,[t],arguments.length),__classPrivateFieldGet(this,gm,`f`).epilog(t),this}epilog(t){return this.epilogue(t)}example(t,n){return argsert(`<string|array> [string]`,[t,n],arguments.length),Array.isArray(t)?t.forEach(t=>this.example(...t)):__classPrivateFieldGet(this,gm,`f`).example(t,n),this}exit(t,n){__classPrivateFieldSet(this,Zp,!0,`f`),__classPrivateFieldSet(this,Wp,n,`f`),__classPrivateFieldGet(this,qp,`f`)&&__classPrivateFieldGet(this,fm,`f`).process.exit(t)}exitProcess(t=!0){return argsert(`[boolean]`,[t],arguments.length),__classPrivateFieldSet(this,qp,t,`f`),this}fail(t){if(argsert(`<function|boolean>`,[t],arguments.length),typeof t==`boolean`&&t!==!1)throw new Il(`Invalid first argument. Expected function or boolean 'false'`);return __classPrivateFieldGet(this,gm,`f`).failFn(t),this}getAliases(){return this.parsed?this.parsed.aliases:{}}async getCompletion(t,n){return argsert(`<array> [function]`,[t,n],arguments.length),n?__classPrivateFieldGet(this,Vp,`f`).getCompletion(t,n):new Promise((n,S)=>{__classPrivateFieldGet(this,Vp,`f`).getCompletion(t,(t,C)=>{t?S(t):n(C)})})}getDemandedOptions(){return argsert([],0),__classPrivateFieldGet(this,nm,`f`).demandedOptions}getDemandedCommands(){return argsert([],0),__classPrivateFieldGet(this,nm,`f`).demandedCommands}getDeprecatedOptions(){return argsert([],0),__classPrivateFieldGet(this,nm,`f`).deprecatedOptions}getDetectLocale(){return __classPrivateFieldGet(this,Gp,`f`)}getExitProcess(){return __classPrivateFieldGet(this,qp,`f`)}getGroups(){return Object.assign({},__classPrivateFieldGet(this,Xp,`f`),__classPrivateFieldGet(this,lm,`f`))}getHelp(){if(__classPrivateFieldSet(this,Zp,!0,`f`),!__classPrivateFieldGet(this,gm,`f`).hasCachedHelpMessage()){if(!this.parsed){let t=this[Qm](__classPrivateFieldGet(this,um,`f`),void 0,void 0,0,!0);if(isPromise(t))return t.then(()=>__classPrivateFieldGet(this,gm,`f`).help())}let t=__classPrivateFieldGet(this,Rp,`f`).runDefaultBuilderOn(this);if(isPromise(t))return t.then(()=>__classPrivateFieldGet(this,gm,`f`).help())}return Promise.resolve(__classPrivateFieldGet(this,gm,`f`).help())}getOptions(){return __classPrivateFieldGet(this,nm,`f`)}getStrict(){return __classPrivateFieldGet(this,pm,`f`)}getStrictCommands(){return __classPrivateFieldGet(this,mm,`f`)}getStrictOptions(){return __classPrivateFieldGet(this,hm,`f`)}global(t,n){return argsert(`<string|array> [boolean]`,[t,n],arguments.length),t=[].concat(t),n===!1?t.forEach(t=>{__classPrivateFieldGet(this,nm,`f`).local.includes(t)||__classPrivateFieldGet(this,nm,`f`).local.push(t)}):__classPrivateFieldGet(this,nm,`f`).local=__classPrivateFieldGet(this,nm,`f`).local.filter(n=>t.indexOf(n)===-1),this}group(t,n){argsert(`<string|array> <string>`,[t,n],arguments.length);let S=__classPrivateFieldGet(this,lm,`f`)[n]||__classPrivateFieldGet(this,Xp,`f`)[n];__classPrivateFieldGet(this,lm,`f`)[n]&&delete __classPrivateFieldGet(this,lm,`f`)[n];let C={};return __classPrivateFieldGet(this,Xp,`f`)[n]=(S||[]).concat(t).filter(t=>C[t]?!1:C[t]=!0),this}hide(t){return argsert(`<string>`,[t],arguments.length),__classPrivateFieldGet(this,nm,`f`).hiddenOptions.push(t),this}implies(t,n){return argsert(`<string|object> [number|string|array]`,[t,n],arguments.length),__classPrivateFieldGet(this,ym,`f`).implies(t,n),this}locale(t){return argsert(`[string]`,[t],arguments.length),t===void 0?(this[Om](),__classPrivateFieldGet(this,fm,`f`).y18n.getLocale()):(__classPrivateFieldSet(this,Gp,!1,`f`),__classPrivateFieldGet(this,fm,`f`).y18n.setLocale(t),this)}middleware(t,n,S){return __classPrivateFieldGet(this,Yp,`f`).addMiddleware(t,!!n,S)}nargs(t,n){return argsert(`<string|object|array> [number]`,[t,n],arguments.length),this[Nm](this.nargs.bind(this),`narg`,t,n),this}normalize(t){return argsert(`<array|string>`,[t],arguments.length),this[Mm](`normalize`,t),this}number(t){return argsert(`<array|string>`,[t],arguments.length),this[Mm](`number`,t),this[th](t),this}option(t,n){if(argsert(`<string|object> [object]`,[t,n],arguments.length),typeof t==`object`)Object.keys(t).forEach(n=>{this.options(n,t[n])});else{typeof n!=`object`&&(n={}),this[th](t),__classPrivateFieldGet(this,vm,`f`)&&(t===`version`||n?.alias===`version`)&&this[Cm]([`"version" is a reserved word.`,`Please do one of the following:`,'- Disable version with `yargs.version(false)` if using "version" as an option',"- Use the built-in `yargs.version` method instead (if applicable)",`- Use a different option key`,`https://yargs.js.org/docs/#api-reference-version`].join(`
147
147
  `),void 0,`versionWarning`),__classPrivateFieldGet(this,nm,`f`).key[t]=!0,n.alias&&this.alias(t,n.alias);let S=n.deprecate||n.deprecated;S&&this.deprecateOption(t,S);let C=n.demand||n.required||n.require;C&&this.demand(t,C),n.demandOption&&this.demandOption(t,typeof n.demandOption==`string`?n.demandOption:void 0),n.conflicts&&this.conflicts(t,n.conflicts),`default`in n&&this.default(t,n.default),n.implies!==void 0&&this.implies(t,n.implies),n.nargs!==void 0&&this.nargs(t,n.nargs),n.config&&this.config(t,n.configParser),n.normalize&&this.normalize(t),n.choices&&this.choices(t,n.choices),n.coerce&&this.coerce(t,n.coerce),n.group&&this.group(t,n.group),(n.boolean||n.type===`boolean`)&&(this.boolean(t),n.alias&&this.boolean(n.alias)),(n.array||n.type===`array`)&&(this.array(t),n.alias&&this.array(n.alias)),(n.number||n.type===`number`)&&(this.number(t),n.alias&&this.number(n.alias)),(n.string||n.type===`string`)&&(this.string(t),n.alias&&this.string(n.alias)),(n.count||n.type===`count`)&&this.count(t),typeof n.global==`boolean`&&this.global(t,n.global),n.defaultDescription&&(__classPrivateFieldGet(this,nm,`f`).defaultDescription[t]=n.defaultDescription),n.skipValidation&&this.skipValidation(t);let N=n.describe||n.description||n.desc,F=__classPrivateFieldGet(this,gm,`f`).getDescriptions();(!Object.prototype.hasOwnProperty.call(F,t)||typeof N==`string`)&&this.describe(t,N),n.hidden&&this.hide(t),n.requiresArg&&this.requiresArg(t)}return this}options(t,n){return this.option(t,n)}parse(t,n,S){argsert(`[string|array] [function|boolean|object] [function]`,[t,n,S],arguments.length),this[wm](),t===void 0&&(t=__classPrivateFieldGet(this,um,`f`)),typeof n==`object`&&(__classPrivateFieldSet(this,sm,n,`f`),n=S),typeof n==`function`&&(__classPrivateFieldSet(this,om,n,`f`),n=!1),n||__classPrivateFieldSet(this,um,t,`f`),__classPrivateFieldGet(this,om,`f`)&&__classPrivateFieldSet(this,qp,!1,`f`);let C=this[Qm](t,!!n),N=this.parsed;return __classPrivateFieldGet(this,Vp,`f`).setParsed(this.parsed),isPromise(C)?C.then(t=>(__classPrivateFieldGet(this,om,`f`)&&__classPrivateFieldGet(this,om,`f`).call(this,__classPrivateFieldGet(this,Wp,`f`),t,__classPrivateFieldGet(this,tm,`f`)),t)).catch(t=>{throw __classPrivateFieldGet(this,om,`f`)&&__classPrivateFieldGet(this,om,`f`)(t,this.parsed.argv,__classPrivateFieldGet(this,tm,`f`)),t}).finally(()=>{this[Rm](),this.parsed=N}):(__classPrivateFieldGet(this,om,`f`)&&__classPrivateFieldGet(this,om,`f`).call(this,__classPrivateFieldGet(this,Wp,`f`),C,__classPrivateFieldGet(this,tm,`f`)),this[Rm](),this.parsed=N,C)}parseAsync(t,n,S){let C=this.parse(t,n,S);return isPromise(C)?C:Promise.resolve(C)}parseSync(t,n,S){let C=this.parse(t,n,S);if(isPromise(C))throw new Il(`.parseSync() must not be used with asynchronous builders, handlers, or middleware`);return C}parserConfiguration(t){return argsert(`<object>`,[t],arguments.length),__classPrivateFieldSet(this,am,t,`f`),this}pkgConf(t,n){argsert(`<string> [string]`,[t,n],arguments.length);let S=null,C=this[jm](n||__classPrivateFieldGet(this,zp,`f`));return C[t]&&typeof C[t]==`object`&&(S=applyExtends(C[t],n||__classPrivateFieldGet(this,zp,`f`),this[Em]()[`deep-merge-config`]||!1,__classPrivateFieldGet(this,fm,`f`)),__classPrivateFieldGet(this,nm,`f`).configObjects=(__classPrivateFieldGet(this,nm,`f`).configObjects||[]).concat(S)),this}positional(t,n){argsert(`<string> <object>`,[t,n],arguments.length);let S=[`default`,`defaultDescription`,`implies`,`normalize`,`choices`,`conflicts`,`coerce`,`type`,`describe`,`desc`,`description`,`alias`];n=objFilter(n,(t,n)=>t===`type`&&![`string`,`number`,`boolean`].includes(n)?!1:S.includes(t));let C=__classPrivateFieldGet(this,Bp,`f`).fullCommands[__classPrivateFieldGet(this,Bp,`f`).fullCommands.length-1],N=C?__classPrivateFieldGet(this,Rp,`f`).cmdToParseOptions(C):{array:[],alias:{},default:{},demand:{}};return objectKeys(N).forEach(S=>{let C=N[S];Array.isArray(C)?C.indexOf(t)!==-1&&(n[S]=!0):C[t]&&!(S in n)&&(n[S]=C[t])}),this.group(t,__classPrivateFieldGet(this,gm,`f`).getPositionalGroupName()),this.option(t,n)}recommendCommands(t=!0){return argsert(`[boolean]`,[t],arguments.length),__classPrivateFieldSet(this,dm,t,`f`),this}required(t,n,S){return this.demand(t,n,S)}require(t,n,S){return this.demand(t,n,S)}requiresArg(t){return argsert(`<array|string|object> [number]`,[t],arguments.length),typeof t==`string`&&__classPrivateFieldGet(this,nm,`f`).narg[t]||this[Nm](this.requiresArg.bind(this),`narg`,t,NaN),this}showCompletionScript(t,n){return argsert(`[string] [string]`,[t,n],arguments.length),t||=this.$0,__classPrivateFieldGet(this,em,`f`).log(__classPrivateFieldGet(this,Vp,`f`).generateCompletionScript(t,n||__classPrivateFieldGet(this,Hp,`f`)||`completion`)),this}showHelp(t){if(argsert(`[string|function]`,[t],arguments.length),__classPrivateFieldSet(this,Zp,!0,`f`),!__classPrivateFieldGet(this,gm,`f`).hasCachedHelpMessage()){if(!this.parsed){let n=this[Qm](__classPrivateFieldGet(this,um,`f`),void 0,void 0,0,!0);if(isPromise(n))return n.then(()=>{__classPrivateFieldGet(this,gm,`f`).showHelp(t)}),this}let n=__classPrivateFieldGet(this,Rp,`f`).runDefaultBuilderOn(this);if(isPromise(n))return n.then(()=>{__classPrivateFieldGet(this,gm,`f`).showHelp(t)}),this}return __classPrivateFieldGet(this,gm,`f`).showHelp(t),this}scriptName(t){return this.customScriptName=!0,this.$0=t,this}showHelpOnFail(t,n){return argsert(`[boolean|string] [string]`,[t,n],arguments.length),__classPrivateFieldGet(this,gm,`f`).showHelpOnFail(t,n),this}showVersion(t){return argsert(`[string|function]`,[t],arguments.length),__classPrivateFieldGet(this,gm,`f`).showVersion(t),this}skipValidation(t){return argsert(`<array|string>`,[t],arguments.length),this[Mm](`skipValidation`,t),this}strict(t){return argsert(`[boolean]`,[t],arguments.length),__classPrivateFieldSet(this,pm,t!==!1,`f`),this}strictCommands(t){return argsert(`[boolean]`,[t],arguments.length),__classPrivateFieldSet(this,mm,t!==!1,`f`),this}strictOptions(t){return argsert(`[boolean]`,[t],arguments.length),__classPrivateFieldSet(this,hm,t!==!1,`f`),this}string(t){return argsert(`<array|string>`,[t],arguments.length),this[Mm](`string`,t),this[th](t),this}terminalWidth(){return argsert([],0),__classPrivateFieldGet(this,fm,`f`).process.stdColumns}updateLocale(t){return this.updateStrings(t)}updateStrings(t){return argsert(`<object>`,[t],arguments.length),__classPrivateFieldSet(this,Gp,!1,`f`),__classPrivateFieldGet(this,fm,`f`).y18n.updateLocale(t),this}usage(t,n,S,C){if(argsert(`<string|null|undefined> [string|boolean] [function|object] [function]`,[t,n,S,C],arguments.length),n!==void 0){if(assertNotStrictEqual(t,null,__classPrivateFieldGet(this,fm,`f`)),(t||``).match(/^\$0( |$)/))return this.command(t,n,S,C);throw new Il(`.usage() description must start with $0 if being used as alias for .command()`)}else return __classPrivateFieldGet(this,gm,`f`).usage(t),this}usageConfiguration(t){return argsert(`<object>`,[t],arguments.length),__classPrivateFieldSet(this,_m,t,`f`),this}version(t,n,S){let C=`version`;if(argsert(`[boolean|string] [string] [string]`,[t,n,S],arguments.length),__classPrivateFieldGet(this,vm,`f`)&&(this[Sm](__classPrivateFieldGet(this,vm,`f`)),__classPrivateFieldGet(this,gm,`f`).version(void 0),__classPrivateFieldSet(this,vm,null,`f`)),arguments.length===0)S=this[km](),t=C;else if(arguments.length===1){if(t===!1)return this;S=t,t=C}else arguments.length===2&&(S=n,n=void 0);return __classPrivateFieldSet(this,vm,typeof t==`string`?t:C,`f`),n||=__classPrivateFieldGet(this,gm,`f`).deferY18nLookup(`Show version number`),__classPrivateFieldGet(this,gm,`f`).version(S||void 0),this.boolean(__classPrivateFieldGet(this,vm,`f`)),this.describe(__classPrivateFieldGet(this,vm,`f`),n),this}wrap(t){return argsert(`<number|null|undefined>`,[t],arguments.length),__classPrivateFieldGet(this,gm,`f`).wrap(t),this}[(Rp=new WeakMap,zp=new WeakMap,Bp=new WeakMap,Vp=new WeakMap,Hp=new WeakMap,Up=new WeakMap,Wp=new WeakMap,Gp=new WeakMap,Kp=new WeakMap,qp=new WeakMap,Jp=new WeakMap,Yp=new WeakMap,Xp=new WeakMap,Zp=new WeakMap,Qp=new WeakMap,$p=new WeakMap,em=new WeakMap,tm=new WeakMap,nm=new WeakMap,im=new WeakMap,am=new WeakMap,om=new WeakMap,sm=new WeakMap,cm=new WeakMap,lm=new WeakMap,um=new WeakMap,dm=new WeakMap,fm=new WeakMap,pm=new WeakMap,mm=new WeakMap,hm=new WeakMap,gm=new WeakMap,_m=new WeakMap,vm=new WeakMap,ym=new WeakMap,bm)](t){if(!t._||!t[`--`])return t;t._.push.apply(t._,t[`--`]);try{delete t[`--`]}catch{}return t}[xm](){return{log:(...t)=>{this[qm]()||ge.log(...t),__classPrivateFieldSet(this,Zp,!0,`f`),__classPrivateFieldGet(this,tm,`f`).length&&__classPrivateFieldSet(this,tm,__classPrivateFieldGet(this,tm,`f`)+`
148
148
  `,`f`),__classPrivateFieldSet(this,tm,__classPrivateFieldGet(this,tm,`f`)+t.join(` `),`f`)},error:(...t)=>{this[qm]()||ge.error(...t),__classPrivateFieldSet(this,Zp,!0,`f`),__classPrivateFieldGet(this,tm,`f`).length&&__classPrivateFieldSet(this,tm,__classPrivateFieldGet(this,tm,`f`)+`
149
- `,`f`),__classPrivateFieldSet(this,tm,__classPrivateFieldGet(this,tm,`f`)+t.join(` `),`f`)}}}[Sm](t){objectKeys(__classPrivateFieldGet(this,nm,`f`)).forEach(n=>{if((t=>t===`configObjects`)(n))return;let S=__classPrivateFieldGet(this,nm,`f`)[n];Array.isArray(S)?S.includes(t)&&S.splice(S.indexOf(t),1):typeof S==`object`&&delete S[t]}),delete __classPrivateFieldGet(this,gm,`f`).getDescriptions()[t]}[Cm](t,n,S){__classPrivateFieldGet(this,Kp,`f`)[S]||(__classPrivateFieldGet(this,fm,`f`).process.emitWarning(t,n),__classPrivateFieldGet(this,Kp,`f`)[S]=!0)}[wm](){__classPrivateFieldGet(this,Jp,`f`).push({options:__classPrivateFieldGet(this,nm,`f`),configObjects:__classPrivateFieldGet(this,nm,`f`).configObjects.slice(0),exitProcess:__classPrivateFieldGet(this,qp,`f`),groups:__classPrivateFieldGet(this,Xp,`f`),strict:__classPrivateFieldGet(this,pm,`f`),strictCommands:__classPrivateFieldGet(this,mm,`f`),strictOptions:__classPrivateFieldGet(this,hm,`f`),completionCommand:__classPrivateFieldGet(this,Hp,`f`),output:__classPrivateFieldGet(this,tm,`f`),exitError:__classPrivateFieldGet(this,Wp,`f`),hasOutput:__classPrivateFieldGet(this,Zp,`f`),parsed:this.parsed,parseFn:__classPrivateFieldGet(this,om,`f`),parseContext:__classPrivateFieldGet(this,sm,`f`)}),__classPrivateFieldGet(this,gm,`f`).freeze(),__classPrivateFieldGet(this,ym,`f`).freeze(),__classPrivateFieldGet(this,Rp,`f`).freeze(),__classPrivateFieldGet(this,Yp,`f`).freeze()}[Tm](){let t=``,n;return n=/\b(node|iojs|electron)(\.exe)?$/.test(__classPrivateFieldGet(this,fm,`f`).process.argv()[0])?__classPrivateFieldGet(this,fm,`f`).process.argv().slice(1,2):__classPrivateFieldGet(this,fm,`f`).process.argv().slice(0,1),t=n.map(t=>{let n=this[Xm](__classPrivateFieldGet(this,zp,`f`),t);return t.match(/^(\/|([a-zA-Z]:)?\\)/)&&n.length<t.length?n:t}).join(` `).trim(),__classPrivateFieldGet(this,fm,`f`).getEnv(`_`)&&__classPrivateFieldGet(this,fm,`f`).getProcessArgvBin()===__classPrivateFieldGet(this,fm,`f`).getEnv(`_`)&&(t=__classPrivateFieldGet(this,fm,`f`).getEnv(`_`).replace(`${__classPrivateFieldGet(this,fm,`f`).path.dirname(__classPrivateFieldGet(this,fm,`f`).process.execPath())}/`,``)),t}[Em](){return __classPrivateFieldGet(this,am,`f`)}[Dm](){return __classPrivateFieldGet(this,_m,`f`)}[Om](){if(!__classPrivateFieldGet(this,Gp,`f`))return;let t=__classPrivateFieldGet(this,fm,`f`).getEnv(`LC_ALL`)||__classPrivateFieldGet(this,fm,`f`).getEnv(`LC_MESSAGES`)||__classPrivateFieldGet(this,fm,`f`).getEnv(`LANG`)||__classPrivateFieldGet(this,fm,`f`).getEnv(`LANGUAGE`)||`en_US`;this.locale(t.replace(/[.:].*/,``))}[km](){return this[jm]().version||`unknown`}[Am](t){let n=t[`--`]?t[`--`]:t._;for(let t=0,S;(S=n[t])!==void 0;t++)__classPrivateFieldGet(this,fm,`f`).Parser.looksLikeNumber(S)&&Number.isSafeInteger(Math.floor(parseFloat(`${S}`)))&&(n[t]=Number(S));return t}[jm](t){let n=t||`*`;if(__classPrivateFieldGet(this,cm,`f`)[n])return __classPrivateFieldGet(this,cm,`f`)[n];let S={};try{let n=t||__classPrivateFieldGet(this,fm,`f`).mainFilename;__classPrivateFieldGet(this,fm,`f`).path.extname(n)&&(n=__classPrivateFieldGet(this,fm,`f`).path.dirname(n));let C=__classPrivateFieldGet(this,fm,`f`).findUp(n,(t,n)=>{if(n.includes(`package.json`))return`package.json`});assertNotStrictEqual(C,void 0,__classPrivateFieldGet(this,fm,`f`)),S=JSON.parse(__classPrivateFieldGet(this,fm,`f`).readFileSync(C,`utf8`))}catch{}return __classPrivateFieldGet(this,cm,`f`)[n]=S||{},__classPrivateFieldGet(this,cm,`f`)[n]}[Mm](t,n){n=[].concat(n),n.forEach(n=>{n=this[Im](n),__classPrivateFieldGet(this,nm,`f`)[t].push(n)})}[Nm](t,n,S,C){this[Fm](t,n,S,C,(t,n,S)=>{__classPrivateFieldGet(this,nm,`f`)[t][n]=S})}[Pm](t,n,S,C){this[Fm](t,n,S,C,(t,n,S)=>{__classPrivateFieldGet(this,nm,`f`)[t][n]=(__classPrivateFieldGet(this,nm,`f`)[t][n]||[]).concat(S)})}[Fm](t,n,S,C,N){if(Array.isArray(S))S.forEach(n=>{t(n,C)});else if((t=>typeof t==`object`)(S))for(let n of objectKeys(S))t(n,S[n]);else N(n,this[Im](S),C)}[Im](t){return t===`__proto__`?`___proto___`:t}[Lm](t,n){return this[Nm](this[Lm].bind(this),`key`,t,n),this}[Rm](){var t,n,S,C,N,F,I,H,W,q,Y,X;let Z=__classPrivateFieldGet(this,Jp,`f`).pop();assertNotStrictEqual(Z,void 0,__classPrivateFieldGet(this,fm,`f`));let te;t=this,n=this,S=this,C=this,N=this,F=this,I=this,H=this,W=this,q=this,Y=this,X=this,{options:{set value(n){__classPrivateFieldSet(t,nm,n,`f`)}}.value,configObjects:te,exitProcess:{set value(t){__classPrivateFieldSet(n,qp,t,`f`)}}.value,groups:{set value(t){__classPrivateFieldSet(S,Xp,t,`f`)}}.value,output:{set value(t){__classPrivateFieldSet(C,tm,t,`f`)}}.value,exitError:{set value(t){__classPrivateFieldSet(N,Wp,t,`f`)}}.value,hasOutput:{set value(t){__classPrivateFieldSet(F,Zp,t,`f`)}}.value,parsed:this.parsed,strict:{set value(t){__classPrivateFieldSet(I,pm,t,`f`)}}.value,strictCommands:{set value(t){__classPrivateFieldSet(H,mm,t,`f`)}}.value,strictOptions:{set value(t){__classPrivateFieldSet(W,hm,t,`f`)}}.value,completionCommand:{set value(t){__classPrivateFieldSet(q,Hp,t,`f`)}}.value,parseFn:{set value(t){__classPrivateFieldSet(Y,om,t,`f`)}}.value,parseContext:{set value(t){__classPrivateFieldSet(X,sm,t,`f`)}}.value}=Z,__classPrivateFieldGet(this,nm,`f`).configObjects=te,__classPrivateFieldGet(this,gm,`f`).unfreeze(),__classPrivateFieldGet(this,ym,`f`).unfreeze(),__classPrivateFieldGet(this,Rp,`f`).unfreeze(),__classPrivateFieldGet(this,Yp,`f`).unfreeze()}[zm](t,n){return maybeAsyncResult(n,n=>(t(n),n))}getInternalMethods(){return{getCommandInstance:this[Bm].bind(this),getContext:this[Vm].bind(this),getHasOutput:this[Hm].bind(this),getLoggerInstance:this[Um].bind(this),getParseContext:this[Wm].bind(this),getParserConfiguration:this[Em].bind(this),getUsageConfiguration:this[Dm].bind(this),getUsageInstance:this[Gm].bind(this),getValidationInstance:this[Km].bind(this),hasParseCallback:this[qm].bind(this),isGlobalContext:this[Jm].bind(this),postProcess:this[Ym].bind(this),reset:this[Zm].bind(this),runValidation:this[$m].bind(this),runYargsParserAndExecuteCommands:this[Qm].bind(this),setHasOutput:this[eh].bind(this)}}[Bm](){return __classPrivateFieldGet(this,Rp,`f`)}[Vm](){return __classPrivateFieldGet(this,Bp,`f`)}[Hm](){return __classPrivateFieldGet(this,Zp,`f`)}[Um](){return __classPrivateFieldGet(this,em,`f`)}[Wm](){return __classPrivateFieldGet(this,sm,`f`)||{}}[Gm](){return __classPrivateFieldGet(this,gm,`f`)}[Km](){return __classPrivateFieldGet(this,ym,`f`)}[qm](){return!!__classPrivateFieldGet(this,om,`f`)}[Jm](){return __classPrivateFieldGet(this,$p,`f`)}[Ym](t,n,S,C){return S||isPromise(t)?t:(n||(t=this[bm](t)),(this[Em]()[`parse-positional-numbers`]||this[Em]()[`parse-positional-numbers`]===void 0)&&(t=this[Am](t)),C&&(t=applyMiddleware(t,this,__classPrivateFieldGet(this,Yp,`f`).getMiddleware(),!1)),t)}[Zm](t={}){__classPrivateFieldSet(this,nm,__classPrivateFieldGet(this,nm,`f`)||{},`f`);let n={};n.local=__classPrivateFieldGet(this,nm,`f`).local||[],n.configObjects=__classPrivateFieldGet(this,nm,`f`).configObjects||[];let S={};return n.local.forEach(n=>{S[n]=!0,(t[n]||[]).forEach(t=>{S[t]=!0})}),Object.assign(__classPrivateFieldGet(this,lm,`f`),Object.keys(__classPrivateFieldGet(this,Xp,`f`)).reduce((t,n)=>{let C=__classPrivateFieldGet(this,Xp,`f`)[n].filter(t=>!(t in S));return C.length>0&&(t[n]=C),t},{})),__classPrivateFieldSet(this,Xp,{},`f`),[`array`,`boolean`,`string`,`skipValidation`,`count`,`normalize`,`number`,`hiddenOptions`].forEach(t=>{n[t]=(__classPrivateFieldGet(this,nm,`f`)[t]||[]).filter(t=>!S[t])}),[`narg`,`key`,`alias`,`default`,`defaultDescription`,`config`,`choices`,`demandedOptions`,`demandedCommands`,`deprecatedOptions`].forEach(t=>{n[t]=objFilter(__classPrivateFieldGet(this,nm,`f`)[t],t=>!S[t])}),n.envPrefix=__classPrivateFieldGet(this,nm,`f`).envPrefix,__classPrivateFieldSet(this,nm,n,`f`),__classPrivateFieldSet(this,gm,__classPrivateFieldGet(this,gm,`f`)?__classPrivateFieldGet(this,gm,`f`).reset(S):usage(this,__classPrivateFieldGet(this,fm,`f`)),`f`),__classPrivateFieldSet(this,ym,__classPrivateFieldGet(this,ym,`f`)?__classPrivateFieldGet(this,ym,`f`).reset(S):validation(this,__classPrivateFieldGet(this,gm,`f`),__classPrivateFieldGet(this,fm,`f`)),`f`),__classPrivateFieldSet(this,Rp,__classPrivateFieldGet(this,Rp,`f`)?__classPrivateFieldGet(this,Rp,`f`).reset():command(__classPrivateFieldGet(this,gm,`f`),__classPrivateFieldGet(this,ym,`f`),__classPrivateFieldGet(this,Yp,`f`),__classPrivateFieldGet(this,fm,`f`)),`f`),__classPrivateFieldGet(this,Vp,`f`)||__classPrivateFieldSet(this,Vp,completion(this,__classPrivateFieldGet(this,gm,`f`),__classPrivateFieldGet(this,Rp,`f`),__classPrivateFieldGet(this,fm,`f`)),`f`),__classPrivateFieldGet(this,Yp,`f`).reset(),__classPrivateFieldSet(this,Hp,null,`f`),__classPrivateFieldSet(this,tm,``,`f`),__classPrivateFieldSet(this,Wp,null,`f`),__classPrivateFieldSet(this,Zp,!1,`f`),this.parsed=!1,this}[Xm](t,n){return __classPrivateFieldGet(this,fm,`f`).path.relative(t,n)}[Qm](t,n,S,C=0,N=!1){let F=!!S||N;t||=__classPrivateFieldGet(this,um,`f`),__classPrivateFieldGet(this,nm,`f`).__=__classPrivateFieldGet(this,fm,`f`).y18n.__,__classPrivateFieldGet(this,nm,`f`).configuration=this[Em]();let I=!!__classPrivateFieldGet(this,nm,`f`).configuration[`populate--`],H=Object.assign({},__classPrivateFieldGet(this,nm,`f`).configuration,{"populate--":!0}),W=__classPrivateFieldGet(this,fm,`f`).Parser.detailed(t,Object.assign({},__classPrivateFieldGet(this,nm,`f`),{configuration:{"parse-positional-numbers":!1,...H}})),q=Object.assign(W.argv,__classPrivateFieldGet(this,sm,`f`)),Y,X=W.aliases,Z=!1,te=!1;Object.keys(q).forEach(t=>{t===__classPrivateFieldGet(this,Qp,`f`)&&q[t]?Z=!0:t===__classPrivateFieldGet(this,vm,`f`)&&q[t]&&(te=!0)}),q.$0=this.$0,this.parsed=W,C===0&&__classPrivateFieldGet(this,gm,`f`).clearCachedHelpMessage();try{if(this[Om](),n)return this[Ym](q,I,!!S,!1);__classPrivateFieldGet(this,Qp,`f`)&&[__classPrivateFieldGet(this,Qp,`f`)].concat(X[__classPrivateFieldGet(this,Qp,`f`)]||[]).filter(t=>t.length>1).includes(``+q._[q._.length-1])&&(q._.pop(),Z=!0),__classPrivateFieldSet(this,$p,!1,`f`);let H=__classPrivateFieldGet(this,Rp,`f`).getCommands(),ne=__classPrivateFieldGet(this,Vp,`f`)?.completionKey?[__classPrivateFieldGet(this,Vp,`f`)?.completionKey,...this.getAliases()[__classPrivateFieldGet(this,Vp,`f`)?.completionKey]??[]].some(t=>Object.prototype.hasOwnProperty.call(q,t)):!1,re=Z||ne||N;if(q._.length){if(H.length){let t;for(let n=C||0,F;q._[n]!==void 0;n++)if(F=String(q._[n]),H.includes(F)&&F!==__classPrivateFieldGet(this,Hp,`f`)){let t=__classPrivateFieldGet(this,Rp,`f`).runCommand(F,this,W,n+1,N,Z||te||N);return this[Ym](t,I,!!S,!1)}else if(!t&&F!==__classPrivateFieldGet(this,Hp,`f`)){t=F;break}!__classPrivateFieldGet(this,Rp,`f`).hasDefaultCommand()&&__classPrivateFieldGet(this,dm,`f`)&&t&&!re&&__classPrivateFieldGet(this,ym,`f`).recommendCommands(t,H)}__classPrivateFieldGet(this,Hp,`f`)&&q._.includes(__classPrivateFieldGet(this,Hp,`f`))&&!ne&&(__classPrivateFieldGet(this,qp,`f`)&&setBlocking(!0),this.showCompletionScript(),this.exit(0))}if(__classPrivateFieldGet(this,Rp,`f`).hasDefaultCommand()&&!re){let t=__classPrivateFieldGet(this,Rp,`f`).runCommand(null,this,W,0,N,Z||te||N);return this[Ym](t,I,!!S,!1)}if(ne){__classPrivateFieldGet(this,qp,`f`)&&setBlocking(!0),t=[].concat(t);let n=t.slice(t.indexOf(`--${__classPrivateFieldGet(this,Vp,`f`).completionKey}`)+1);return __classPrivateFieldGet(this,Vp,`f`).getCompletion(n,(t,n)=>{if(t)throw new Il(t.message);(n||[]).forEach(t=>{__classPrivateFieldGet(this,em,`f`).log(t)}),this.exit(0)}),this[Ym](q,!I,!!S,!1)}if(__classPrivateFieldGet(this,Zp,`f`)||(Z?(__classPrivateFieldGet(this,qp,`f`)&&setBlocking(!0),F=!0,this.showHelp(t=>{__classPrivateFieldGet(this,em,`f`).log(t),this.exit(0)})):te&&(__classPrivateFieldGet(this,qp,`f`)&&setBlocking(!0),F=!0,__classPrivateFieldGet(this,gm,`f`).showVersion(`log`),this.exit(0))),!F&&__classPrivateFieldGet(this,nm,`f`).skipValidation.length>0&&(F=Object.keys(q).some(t=>__classPrivateFieldGet(this,nm,`f`).skipValidation.indexOf(t)>=0&&q[t]===!0)),!F){if(W.error)throw new Il(W.error.message);if(!ne){let t=this[$m](X,{},W.error);S||(Y=applyMiddleware(q,this,__classPrivateFieldGet(this,Yp,`f`).getMiddleware(),!0)),Y=this[zm](t,Y??q),isPromise(Y)&&!S&&(Y=Y.then(()=>applyMiddleware(q,this,__classPrivateFieldGet(this,Yp,`f`).getMiddleware(),!1)))}}}catch(t){if(t instanceof Il)__classPrivateFieldGet(this,gm,`f`).fail(t.message,t);else throw t}return this[Ym](Y??q,I,!!S,!0)}[$m](t,n,S,C){let N={...this.getDemandedOptions()};return F=>{if(S)throw new Il(S.message);__classPrivateFieldGet(this,ym,`f`).nonOptionCount(F),__classPrivateFieldGet(this,ym,`f`).requiredArguments(F,N);let I=!1;__classPrivateFieldGet(this,mm,`f`)&&(I=__classPrivateFieldGet(this,ym,`f`).unknownCommands(F)),__classPrivateFieldGet(this,pm,`f`)&&!I?__classPrivateFieldGet(this,ym,`f`).unknownArguments(F,t,n,!!C):__classPrivateFieldGet(this,hm,`f`)&&__classPrivateFieldGet(this,ym,`f`).unknownArguments(F,t,{},!1,!1),__classPrivateFieldGet(this,ym,`f`).limitedChoices(F),__classPrivateFieldGet(this,ym,`f`).implications(F),__classPrivateFieldGet(this,ym,`f`).conflicting(F)}}[eh](){__classPrivateFieldSet(this,Zp,!0,`f`)}[th](t){if(typeof t==`string`)__classPrivateFieldGet(this,nm,`f`).key[t]=!0;else for(let n of t)__classPrivateFieldGet(this,nm,`f`).key[n]=!0}}}),ih,ah=__esmMin(()=>{vp(),rh(),ih=YargsFactory(gp)});function classifyCliFailure(t,n){return typeof t==`string`&&t.length>0?{kind:`usage`,message:t}:{kind:`runtime`}}var oh=__esmMin(()=>{});function buildHeaders(t,n){let S={"user-agent":`gjsify-install/0.64.21`,"accept-encoding":n.acceptEncoding??`identity`};if(n.npmrc){let C=resolveAuthForUrl(t,n.npmrc);C&&(S.authorization=C)}if(n.headers)for(let[t,C]of Object.entries(n.headers))S[t.toLowerCase()]=C;return S}function resolveAuthForUrl(t,n){let S=pathPrefixes(new URL(t));for(let t of S){let S=n.authTokens[t];if(S)return`Bearer ${S}`;let C=n.basicAuth[t];if(C)return`Basic ${btoa(`${C.username}:${C.password}`)}`}return null}function pathPrefixes(t){let n=t.pathname.split(`/`).filter(Boolean),S=[];for(let C=n.length;C>=0;C--){let N=n.slice(0,C).join(`/`);S.push(N?`//${t.host}/${N}`:`//${t.host}`)}return S}var sh=__esmMin(()=>{}),PackageNotFoundError,IntegrityError,RegistryTimeoutError,RegistryUnreachableError,ch=__esmMin(()=>{PackageNotFoundError=class extends Error{name;url;constructor(t,n){super(`Package not found in registry: ${t} (${n})`),this.name=t,this.url=n,this.name=`PackageNotFoundError`}},IntegrityError=class extends Error{url;integrity;constructor(t,n){super(`Tarball integrity mismatch for ${t} (expected ${n})`),this.url=t,this.integrity=n,this.name=`IntegrityError`}},RegistryTimeoutError=class extends Error{url;timeoutMs;attempts;constructor(t,n,S){let C=Math.round(n/100)/10,N=Math.round(n*S/100)/10;super(`@gjsify/npm-registry: GET ${t} timed out after ${C}s × ${S} attempt(s) (total ~${N}s). This usually means the registry CDN is slow or unreachable.`),this.url=t,this.timeoutMs=n,this.attempts=S,this.name=`RegistryTimeoutError`}},RegistryUnreachableError=class extends Error{url;attempts;elapsedMs;constructor(t,n,S,C){let N=Math.round(S/100)/10,F=C instanceof Error?C.message:String(C);super(`@gjsify/npm-registry: GET ${t} failed after ${n} attempt(s) over ~${N}s: ${F}. This usually means the registry or the network dropped out.`),this.url=t,this.attempts=n,this.elapsedMs=S,this.name=`RegistryUnreachableError`,this.cause=C}}});function registryFor(t,n){if(n&&t.startsWith(`@`)){let S=t.slice(0,t.indexOf(`/`)),C=n.scopes[S];if(C)return ensureTrailingSlash$1(C)}return n?.registry?ensureTrailingSlash$1(n.registry):lh}function parseNpmrc(t){let n={registry:lh,scopes:{},authTokens:{},basicAuth:{}},S=t.split(/\r?\n/),C={};for(let t of S){let S=t.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`){n.registry=ensureTrailingSlash$1(I);continue}let H=F.match(/^(@[^:]+):registry$/);if(H){n.scopes[H[1]]=ensureTrailingSlash$1(I);continue}let W=F.match(/^\/\/(.+):_authToken$/);if(W){n.authTokens[normalizeAuthHost(W[1])]=I;continue}let q=F.match(/^\/\/(.+):username$/);if(q){(C[normalizeAuthHost(q[1])]??={}).user=I;continue}let Y=F.match(/^\/\/(.+):_password$/);if(Y){let t=base64Decode$1(I);(C[normalizeAuthHost(Y[1])]??={}).pass=t;continue}}for(let[t,S]of Object.entries(C))S.user&&S.pass!==void 0&&(n.basicAuth[t]={username:S.user,password:S.pass});return n}function normalizeAuthHost(t){return`//${t.replace(/\/+$/,``)}`}function ensureTrailingSlash$1(t){return t.endsWith(`/`)?t:t+`/`}function stripQuotes(t){return t.startsWith(`"`)&&t.endsWith(`"`)||t.startsWith(`'`)&&t.endsWith(`'`)?t.slice(1,-1):t}function expandEnv(t){return t.replace(/\$\{([A-Z0-9_]+)\}/gi,(t,n)=>globalThis.process?.env?.[n]??``)}function base64Decode$1(t){return atob(t)}var lh,uh=__esmMin(()=>{lh=`https://registry.npmjs.org/`,__name$1(ensureTrailingSlash$1,`ensureTrailingSlash`),__name$1(base64Decode$1,`base64Decode`)});async function fetchWithRetry(t,n,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??5),F=Math.max(0,S.retryDelayMs??1e3),I=Math.max(0,S.timeoutMs??3e4),H=S.retryNotFound??!1,W=Date.now(),q=0,Y,X=0;for(;;){if(n.signal?.aborted)throw signalAbortError(n.signal);let Z=I>0?new AbortController:null,te=Z===null?null:setTimeout(()=>Z.abort(Error(`@gjsify/npm-registry: per-request timeout ${I}ms`)),I),ne=composeSignals(n.signal,Z?.signal);try{let F=await C(t,{...n,signal:ne}),I=isRetryableStatus(F.status)||H&&F.status===404;if(F.ok||!I||q>=N)return S.read?await S.read(F):F;try{await F.arrayBuffer()}catch{}Y=Error(`HTTP ${F.status} ${F.statusText}`)}catch(S){let C=Z!==null&&Z.signal.aborted,F=n.signal?.aborted===!0;if(C&&!F){if(X++,q>=N)throw new RegistryTimeoutError(t,I,X);Y=S}else if(F)throw signalAbortError(n.signal);else{if(!isRetryableError(S))throw S;if(q>=N)throw new RegistryUnreachableError(t,q+1,Date.now()-W,S);Y=S}}finally{te!==null&&clearTimeout(te)}let re=Math.min(F*2**q,8e3);S.onRetry?.({attempt:q+1,error:Y,delayMs:re}),await delay$1(re,n.signal),q++}}function composeSignals(t,n){return t?n?AbortSignal.any([t,n]):t:n}function isRetryableStatus(t){return t===408||t===425||t===429||t===500||t===502||t===503||t===504||t===521||t===522||t===524||t===525}function isRetryableError(t){if(t&&typeof t==`object`&&`name`in t&&t.name===`AbortError`)return!1;if(t instanceof TypeError)return!0;if(t&&typeof t==`object`&&`name`in t){let n=t.name;if(n===`FetchError`)return!0;if(n===`AbortError`)return!1}let n=t?.cause;if(n&&typeof n==`object`&&`code`in n){let t=n.code;if(typeof t==`string`)return t===`ECONNRESET`||t===`ECONNREFUSED`||t===`ENETUNREACH`||t===`ENOTFOUND`||t===`ETIMEDOUT`||t===`EAI_AGAIN`||t===`UND_ERR_SOCKET`||t===`UND_ERR_CONNECT_TIMEOUT`}return!1}function delay$1(t,n){return t<=0?Promise.resolve():new Promise((S,C)=>{let N=setTimeout(()=>{n?.removeEventListener?.(`abort`,onAbort),S()},t),onAbort=()=>{clearTimeout(N),C(signalAbortError(n))};if(n?.aborted){clearTimeout(N),C(signalAbortError(n));return}n?.addEventListener?.(`abort`,onAbort,{once:!0})})}function signalAbortError(t){let n=t&&`reason`in t?t.reason:void 0;if(n instanceof Error)return n;let S=Error(`Aborted`);return S.name=`AbortError`,S}var dh=__esmMin(()=>{ch(),__name$1(delay$1,`delay`)});async function verifyIntegrity(t,n){let S=n.trim().split(/\s+/);for(let n of S){let S=n.indexOf(`-`);if(S<0)continue;let C=n.slice(0,S).toLowerCase(),N=n.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(t));if(bytesToBase64(new Uint8Array(H))===N)return!0}return!1}function subriToWebCryptoAlgo(t){switch(t){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(t){if(t.byteOffset===0&&t.byteLength===t.buffer.byteLength)return t.buffer;let n=new Uint8Array(t.byteLength);return n.set(t),n.buffer}function bytesToBase64(t){let n=``;for(let S=0;S<t.length;S++)n+=String.fromCharCode(t[S]);return btoa(n)}var fh=__esmMin(()=>{});function assertPackument(t,n){if(!n||typeof n!=`object`)throw TypeError(`registry: ${t} packument is not an object`);let S=n;if(typeof S.name!=`string`)throw TypeError(`registry: ${t} packument missing string name`);if(!S.versions||typeof S.versions!=`object`)throw TypeError(`registry: ${t} packument missing versions map`)}function packumentUrl(t,n){let S=ensureTrailingSlash$1(n);if(t.startsWith(`@`)){let n=t.indexOf(`/`);if(n<0)throw TypeError(`Invalid scoped package name: ${t}`);let C=t.slice(0,n),N=t.slice(n+1);return`${S}${encodeURIComponent(C)}/${encodeURIComponent(N)}`}return`${S}${encodeURIComponent(t)}`}async function fetchPackumentConditional(t,n={}){let S=packumentUrl(t,n.registry??registryFor(t,n.npmrc)),C=buildHeaders(S,{...n,acceptEncoding:`gzip`});C.accept??=n.fullMetadata?`application/json`:`application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*`,n.ifNoneMatch&&(C[`if-none-match`]=n.ifNoneMatch);let N=await fetchWithRetry(S,{headers:C,signal:n.signal},{fetch:n.fetch,retries:n.retries,retryDelayMs:n.retryDelayMs,timeoutMs:n.timeoutMs,onRetry:n.onRetry,read:async n=>{if(n.status===304){try{await n.arrayBuffer()}catch{}return{status:`not-modified`}}if(!n.ok)throw n.status===404||n.status===406?new PackageNotFoundError(t,S):Error(`registry GET ${S} -> ${n.status} ${n.statusText}`);return{status:`fresh`,body:await decodeJsonBody(n),etag:n.headers.get(`etag`)??void 0}}});if(N.status===`not-modified`)return{status:`not-modified`,etag:n.ifNoneMatch};let F=N.body;return assertPackument(t,F),{status:`fresh`,packument:F,etag:N.etag}}async function decodeJsonBody(t){return t.json()}async function fetchPackument(t,n={}){let S=await fetchPackumentConditional(t,n);if(!S.packument)throw Error(`registry: ${t} returned 304 Not Modified to an unconditional request`);return S.packument}var ph=__esmMin(()=>{sh(),ch(),uh(),dh()});async function fetchTarball(t,n={}){let S=buildHeaders(t,{...n,acceptEncoding:`identity`});S.accept??=`application/octet-stream`;let C=await fetchWithRetry(t,{headers:S,signal:n.signal},{fetch:n.fetch,retries:n.retries,retryDelayMs:n.retryDelayMs,timeoutMs:n.timeoutMs,onRetry:n.onRetry,retryNotFound:n.retryNotFound??!0,read:async n=>{if(!n.ok)throw Error(`tarball GET ${t} -> ${n.status} ${n.statusText}`);return new Uint8Array(await n.arrayBuffer())}});if(n.integrity&&!await verifyIntegrity(C,n.integrity))throw new IntegrityError(t,n.integrity);return C}var mh=__esmMin(()=>{sh(),ch(),dh(),fh()});async function whoami(t,n){let S=`${ensureTrailingSlash$1(t)}-/whoami`,C=buildHeaders(S,{npmrc:n});C.accept=`application/json`;let N=globalThis.fetch;if(!N)throw Error(`@gjsify/npm-registry: globalThis.fetch is missing`);let F=await N(S,{method:`GET`,headers:C});if(!F.ok)throw Error(`whoami GET ${S} -> ${F.status} ${F.statusText}`);let I=await F.json();if(I&&typeof I==`object`&&`username`in I){let t=I.username;if(typeof t==`string`&&t.length>0)return{username:t}}return{}}var hh=__esmMin(()=>{sh(),uh()}),gh=__esmMin(()=>{sh(),ch(),uh(),fh(),ph(),mh(),hh()});function escapePackageName(t){return t.replace(`/`,`%2f`)}function buildPublishHeaders(t,n){let S=buildHeaders(t,{npmrc:n.npmrc});return S[`content-type`]=`application/json`,S[`npm-command`]=`publish`,S[`npm-auth-type`]=n.otp?`legacy`:`web`,S[`user-agent`]=n.userAgent??defaultUserAgent(),n.otp&&(S[`npm-otp`]=n.otp),n.authorization&&(S.authorization=n.authorization),S}function cliVersion(){return vh===void 0&&(vh=`0.64.21`),vh}function cliPackageDir(){let t=globalThis.process?.env?.GJSIFY_CLI_PACKAGE_JSON,n;try{n=zn(t||fileURLToPath(import.meta.url))}catch{return null}for(let t=0;t<12;t++){try{if(JSON.parse(readFileSync(`${n}/package.json`,`utf8`)).name===`@gjsify/cli`)return n}catch{}let t=zn(n);if(t===n)break;n=t}return null}function defaultUserAgent(){let t=globalThis.process,n=t?.arch??`x64`,S=t?.platform??`linux`;return`gjsify-publish/${cliVersion()} (${S} ${n})`}var vh,yh=__esmMin(()=>{ef(),qn(),ir(),gh()}),bh,xh=__esmMin(()=>{bh=`gjsify`});function parseDeclaredChannel(t,n){if(!(t===void 0||t===``)){if(Sh.includes(t))return t;throw Error(`${n}: "${String(t)}" is not a distribution channel. Known: ${Sh.join(`, `)}.`)}}function channelAllowsDonations(t){return t!==void 0&&Ch[t]===!0}var Sh,Ch,wh,Th=__esmMin(()=>{Sh=[`flathub`,`web`,`microsoft-store`,`apple-app-store`],Ch={flathub:!0,web:!0,"microsoft-store":!1,"apple-app-store":!1},wh=`GJSIFY_CHANNEL`}),Eh=__commonJSMin(((t,n)=>{let S=(qn(),__toCommonJS(jn)),C=(Xl(),__toCommonJS(Kl)),N=(ef(),__toCommonJS(Qd)),resolveFrom=(t,n,F)=>{if(typeof t!=`string`)throw TypeError(`Expected \`fromDir\` to be of type \`string\`, got \`${typeof t}\``);if(typeof n!=`string`)throw TypeError(`Expected \`moduleId\` to be of type \`string\`, got \`${typeof n}\``);try{t=N.realpathSync(t)}catch(n){if(n.code===`ENOENT`)t=S.resolve(t);else if(F)return null;else throw n}let I=S.join(t,`noop.js`),resolveFileName=()=>C._resolveFilename(n,{id:I,filename:I,paths:C._nodeModulePaths(t)});if(F)try{return resolveFileName()}catch{return null}return resolveFileName()};n.exports=(t,n)=>resolveFrom(t,n),n.exports.silent=(t,n)=>resolveFrom(t,n,!0)})),Dh=__commonJSMin(((t,n)=>{let callsites=()=>{let t=Error.prepareStackTrace;Error.prepareStackTrace=(t,n)=>n;let n=Error().stack.slice(1);return Error.prepareStackTrace=t,n};n.exports=callsites,n.exports.default=callsites})),Oh=__commonJSMin(((t,n)=>{let S=Dh();n.exports=t=>{let n=S();if(!t)return n[2].getFileName();let C=!1;n.shift();for(let S of n){let n=S.getFileName();if(typeof n==`string`){if(n===t){C=!0;continue}if(n!==`module.js`&&C&&n!==t)return n}}}})),kh=__commonJSMin(((t,n)=>{var{__gjsifyModuleDir:S,__gjsifyModuleFile:C}=(eu(),__toCommonJS(Zl)),N=S(`import-fresh/index.js`),F=C(`import-fresh/index.js`);let I=(qn(),__toCommonJS(jn)),H=Eh(),W=Oh();n.exports=t=>{if(typeof t!=`string`)throw TypeError(`Expected a string`);let n=W(F),S=n?I.dirname(n):N,C=H(S,t),q=Y.cache[C];if(q&&q.parent){let t=q.parent.children.length;for(;t--;)q.parent.children[t].id===C&&q.parent.children.splice(t,1)}delete Y.cache[C];let X=Y.cache[n];return X===void 0||X.require===void 0?Y(C):X.require(C)}})),Ah=__commonJSMin(((t,n)=>{n.exports=function isArrayish(t){return t?t instanceof Array||Array.isArray(t)||t.length>=0&&t.splice instanceof Function:!1}})),jh=__commonJSMin(((t,n)=>{var S=(zu(),__toCommonJS(Fu)),C=Ah(),N=function errorEx(t,n){(!t||t.constructor!==String)&&(n=t||{},t=Error.name);var N=function ErrorEXError(S){if(!this)return new ErrorEXError(S);S=S instanceof Error?S.message:S||this.message,Error.call(this,S),Error.captureStackTrace(this,N),this.name=t,Object.defineProperty(this,"message",{configurable:!0,enumerable:!1,get:function(){var t=S.split(/\r?\n/g);for(var N in n)if(n.hasOwnProperty(N)){var F=n[N];`message`in F&&(t=F.message(this[N],t)||t,C(t)||(t=[t]))}return t.join(`
149
+ `,`f`),__classPrivateFieldSet(this,tm,__classPrivateFieldGet(this,tm,`f`)+t.join(` `),`f`)}}}[Sm](t){objectKeys(__classPrivateFieldGet(this,nm,`f`)).forEach(n=>{if((t=>t===`configObjects`)(n))return;let S=__classPrivateFieldGet(this,nm,`f`)[n];Array.isArray(S)?S.includes(t)&&S.splice(S.indexOf(t),1):typeof S==`object`&&delete S[t]}),delete __classPrivateFieldGet(this,gm,`f`).getDescriptions()[t]}[Cm](t,n,S){__classPrivateFieldGet(this,Kp,`f`)[S]||(__classPrivateFieldGet(this,fm,`f`).process.emitWarning(t,n),__classPrivateFieldGet(this,Kp,`f`)[S]=!0)}[wm](){__classPrivateFieldGet(this,Jp,`f`).push({options:__classPrivateFieldGet(this,nm,`f`),configObjects:__classPrivateFieldGet(this,nm,`f`).configObjects.slice(0),exitProcess:__classPrivateFieldGet(this,qp,`f`),groups:__classPrivateFieldGet(this,Xp,`f`),strict:__classPrivateFieldGet(this,pm,`f`),strictCommands:__classPrivateFieldGet(this,mm,`f`),strictOptions:__classPrivateFieldGet(this,hm,`f`),completionCommand:__classPrivateFieldGet(this,Hp,`f`),output:__classPrivateFieldGet(this,tm,`f`),exitError:__classPrivateFieldGet(this,Wp,`f`),hasOutput:__classPrivateFieldGet(this,Zp,`f`),parsed:this.parsed,parseFn:__classPrivateFieldGet(this,om,`f`),parseContext:__classPrivateFieldGet(this,sm,`f`)}),__classPrivateFieldGet(this,gm,`f`).freeze(),__classPrivateFieldGet(this,ym,`f`).freeze(),__classPrivateFieldGet(this,Rp,`f`).freeze(),__classPrivateFieldGet(this,Yp,`f`).freeze()}[Tm](){let t=``,n;return n=/\b(node|iojs|electron)(\.exe)?$/.test(__classPrivateFieldGet(this,fm,`f`).process.argv()[0])?__classPrivateFieldGet(this,fm,`f`).process.argv().slice(1,2):__classPrivateFieldGet(this,fm,`f`).process.argv().slice(0,1),t=n.map(t=>{let n=this[Xm](__classPrivateFieldGet(this,zp,`f`),t);return t.match(/^(\/|([a-zA-Z]:)?\\)/)&&n.length<t.length?n:t}).join(` `).trim(),__classPrivateFieldGet(this,fm,`f`).getEnv(`_`)&&__classPrivateFieldGet(this,fm,`f`).getProcessArgvBin()===__classPrivateFieldGet(this,fm,`f`).getEnv(`_`)&&(t=__classPrivateFieldGet(this,fm,`f`).getEnv(`_`).replace(`${__classPrivateFieldGet(this,fm,`f`).path.dirname(__classPrivateFieldGet(this,fm,`f`).process.execPath())}/`,``)),t}[Em](){return __classPrivateFieldGet(this,am,`f`)}[Dm](){return __classPrivateFieldGet(this,_m,`f`)}[Om](){if(!__classPrivateFieldGet(this,Gp,`f`))return;let t=__classPrivateFieldGet(this,fm,`f`).getEnv(`LC_ALL`)||__classPrivateFieldGet(this,fm,`f`).getEnv(`LC_MESSAGES`)||__classPrivateFieldGet(this,fm,`f`).getEnv(`LANG`)||__classPrivateFieldGet(this,fm,`f`).getEnv(`LANGUAGE`)||`en_US`;this.locale(t.replace(/[.:].*/,``))}[km](){return this[jm]().version||`unknown`}[Am](t){let n=t[`--`]?t[`--`]:t._;for(let t=0,S;(S=n[t])!==void 0;t++)__classPrivateFieldGet(this,fm,`f`).Parser.looksLikeNumber(S)&&Number.isSafeInteger(Math.floor(parseFloat(`${S}`)))&&(n[t]=Number(S));return t}[jm](t){let n=t||`*`;if(__classPrivateFieldGet(this,cm,`f`)[n])return __classPrivateFieldGet(this,cm,`f`)[n];let S={};try{let n=t||__classPrivateFieldGet(this,fm,`f`).mainFilename;__classPrivateFieldGet(this,fm,`f`).path.extname(n)&&(n=__classPrivateFieldGet(this,fm,`f`).path.dirname(n));let C=__classPrivateFieldGet(this,fm,`f`).findUp(n,(t,n)=>{if(n.includes(`package.json`))return`package.json`});assertNotStrictEqual(C,void 0,__classPrivateFieldGet(this,fm,`f`)),S=JSON.parse(__classPrivateFieldGet(this,fm,`f`).readFileSync(C,`utf8`))}catch{}return __classPrivateFieldGet(this,cm,`f`)[n]=S||{},__classPrivateFieldGet(this,cm,`f`)[n]}[Mm](t,n){n=[].concat(n),n.forEach(n=>{n=this[Im](n),__classPrivateFieldGet(this,nm,`f`)[t].push(n)})}[Nm](t,n,S,C){this[Fm](t,n,S,C,(t,n,S)=>{__classPrivateFieldGet(this,nm,`f`)[t][n]=S})}[Pm](t,n,S,C){this[Fm](t,n,S,C,(t,n,S)=>{__classPrivateFieldGet(this,nm,`f`)[t][n]=(__classPrivateFieldGet(this,nm,`f`)[t][n]||[]).concat(S)})}[Fm](t,n,S,C,N){if(Array.isArray(S))S.forEach(n=>{t(n,C)});else if((t=>typeof t==`object`)(S))for(let n of objectKeys(S))t(n,S[n]);else N(n,this[Im](S),C)}[Im](t){return t===`__proto__`?`___proto___`:t}[Lm](t,n){return this[Nm](this[Lm].bind(this),`key`,t,n),this}[Rm](){var t,n,S,C,N,F,I,H,W,q,Y,X;let Z=__classPrivateFieldGet(this,Jp,`f`).pop();assertNotStrictEqual(Z,void 0,__classPrivateFieldGet(this,fm,`f`));let te;t=this,n=this,S=this,C=this,N=this,F=this,I=this,H=this,W=this,q=this,Y=this,X=this,{options:{set value(n){__classPrivateFieldSet(t,nm,n,`f`)}}.value,configObjects:te,exitProcess:{set value(t){__classPrivateFieldSet(n,qp,t,`f`)}}.value,groups:{set value(t){__classPrivateFieldSet(S,Xp,t,`f`)}}.value,output:{set value(t){__classPrivateFieldSet(C,tm,t,`f`)}}.value,exitError:{set value(t){__classPrivateFieldSet(N,Wp,t,`f`)}}.value,hasOutput:{set value(t){__classPrivateFieldSet(F,Zp,t,`f`)}}.value,parsed:this.parsed,strict:{set value(t){__classPrivateFieldSet(I,pm,t,`f`)}}.value,strictCommands:{set value(t){__classPrivateFieldSet(H,mm,t,`f`)}}.value,strictOptions:{set value(t){__classPrivateFieldSet(W,hm,t,`f`)}}.value,completionCommand:{set value(t){__classPrivateFieldSet(q,Hp,t,`f`)}}.value,parseFn:{set value(t){__classPrivateFieldSet(Y,om,t,`f`)}}.value,parseContext:{set value(t){__classPrivateFieldSet(X,sm,t,`f`)}}.value}=Z,__classPrivateFieldGet(this,nm,`f`).configObjects=te,__classPrivateFieldGet(this,gm,`f`).unfreeze(),__classPrivateFieldGet(this,ym,`f`).unfreeze(),__classPrivateFieldGet(this,Rp,`f`).unfreeze(),__classPrivateFieldGet(this,Yp,`f`).unfreeze()}[zm](t,n){return maybeAsyncResult(n,n=>(t(n),n))}getInternalMethods(){return{getCommandInstance:this[Bm].bind(this),getContext:this[Vm].bind(this),getHasOutput:this[Hm].bind(this),getLoggerInstance:this[Um].bind(this),getParseContext:this[Wm].bind(this),getParserConfiguration:this[Em].bind(this),getUsageConfiguration:this[Dm].bind(this),getUsageInstance:this[Gm].bind(this),getValidationInstance:this[Km].bind(this),hasParseCallback:this[qm].bind(this),isGlobalContext:this[Jm].bind(this),postProcess:this[Ym].bind(this),reset:this[Zm].bind(this),runValidation:this[$m].bind(this),runYargsParserAndExecuteCommands:this[Qm].bind(this),setHasOutput:this[eh].bind(this)}}[Bm](){return __classPrivateFieldGet(this,Rp,`f`)}[Vm](){return __classPrivateFieldGet(this,Bp,`f`)}[Hm](){return __classPrivateFieldGet(this,Zp,`f`)}[Um](){return __classPrivateFieldGet(this,em,`f`)}[Wm](){return __classPrivateFieldGet(this,sm,`f`)||{}}[Gm](){return __classPrivateFieldGet(this,gm,`f`)}[Km](){return __classPrivateFieldGet(this,ym,`f`)}[qm](){return!!__classPrivateFieldGet(this,om,`f`)}[Jm](){return __classPrivateFieldGet(this,$p,`f`)}[Ym](t,n,S,C){return S||isPromise(t)?t:(n||(t=this[bm](t)),(this[Em]()[`parse-positional-numbers`]||this[Em]()[`parse-positional-numbers`]===void 0)&&(t=this[Am](t)),C&&(t=applyMiddleware(t,this,__classPrivateFieldGet(this,Yp,`f`).getMiddleware(),!1)),t)}[Zm](t={}){__classPrivateFieldSet(this,nm,__classPrivateFieldGet(this,nm,`f`)||{},`f`);let n={};n.local=__classPrivateFieldGet(this,nm,`f`).local||[],n.configObjects=__classPrivateFieldGet(this,nm,`f`).configObjects||[];let S={};return n.local.forEach(n=>{S[n]=!0,(t[n]||[]).forEach(t=>{S[t]=!0})}),Object.assign(__classPrivateFieldGet(this,lm,`f`),Object.keys(__classPrivateFieldGet(this,Xp,`f`)).reduce((t,n)=>{let C=__classPrivateFieldGet(this,Xp,`f`)[n].filter(t=>!(t in S));return C.length>0&&(t[n]=C),t},{})),__classPrivateFieldSet(this,Xp,{},`f`),[`array`,`boolean`,`string`,`skipValidation`,`count`,`normalize`,`number`,`hiddenOptions`].forEach(t=>{n[t]=(__classPrivateFieldGet(this,nm,`f`)[t]||[]).filter(t=>!S[t])}),[`narg`,`key`,`alias`,`default`,`defaultDescription`,`config`,`choices`,`demandedOptions`,`demandedCommands`,`deprecatedOptions`].forEach(t=>{n[t]=objFilter(__classPrivateFieldGet(this,nm,`f`)[t],t=>!S[t])}),n.envPrefix=__classPrivateFieldGet(this,nm,`f`).envPrefix,__classPrivateFieldSet(this,nm,n,`f`),__classPrivateFieldSet(this,gm,__classPrivateFieldGet(this,gm,`f`)?__classPrivateFieldGet(this,gm,`f`).reset(S):usage(this,__classPrivateFieldGet(this,fm,`f`)),`f`),__classPrivateFieldSet(this,ym,__classPrivateFieldGet(this,ym,`f`)?__classPrivateFieldGet(this,ym,`f`).reset(S):validation(this,__classPrivateFieldGet(this,gm,`f`),__classPrivateFieldGet(this,fm,`f`)),`f`),__classPrivateFieldSet(this,Rp,__classPrivateFieldGet(this,Rp,`f`)?__classPrivateFieldGet(this,Rp,`f`).reset():command(__classPrivateFieldGet(this,gm,`f`),__classPrivateFieldGet(this,ym,`f`),__classPrivateFieldGet(this,Yp,`f`),__classPrivateFieldGet(this,fm,`f`)),`f`),__classPrivateFieldGet(this,Vp,`f`)||__classPrivateFieldSet(this,Vp,completion(this,__classPrivateFieldGet(this,gm,`f`),__classPrivateFieldGet(this,Rp,`f`),__classPrivateFieldGet(this,fm,`f`)),`f`),__classPrivateFieldGet(this,Yp,`f`).reset(),__classPrivateFieldSet(this,Hp,null,`f`),__classPrivateFieldSet(this,tm,``,`f`),__classPrivateFieldSet(this,Wp,null,`f`),__classPrivateFieldSet(this,Zp,!1,`f`),this.parsed=!1,this}[Xm](t,n){return __classPrivateFieldGet(this,fm,`f`).path.relative(t,n)}[Qm](t,n,S,C=0,N=!1){let F=!!S||N;t||=__classPrivateFieldGet(this,um,`f`),__classPrivateFieldGet(this,nm,`f`).__=__classPrivateFieldGet(this,fm,`f`).y18n.__,__classPrivateFieldGet(this,nm,`f`).configuration=this[Em]();let I=!!__classPrivateFieldGet(this,nm,`f`).configuration[`populate--`],H=Object.assign({},__classPrivateFieldGet(this,nm,`f`).configuration,{"populate--":!0}),W=__classPrivateFieldGet(this,fm,`f`).Parser.detailed(t,Object.assign({},__classPrivateFieldGet(this,nm,`f`),{configuration:{"parse-positional-numbers":!1,...H}})),q=Object.assign(W.argv,__classPrivateFieldGet(this,sm,`f`)),Y,X=W.aliases,Z=!1,te=!1;Object.keys(q).forEach(t=>{t===__classPrivateFieldGet(this,Qp,`f`)&&q[t]?Z=!0:t===__classPrivateFieldGet(this,vm,`f`)&&q[t]&&(te=!0)}),q.$0=this.$0,this.parsed=W,C===0&&__classPrivateFieldGet(this,gm,`f`).clearCachedHelpMessage();try{if(this[Om](),n)return this[Ym](q,I,!!S,!1);__classPrivateFieldGet(this,Qp,`f`)&&[__classPrivateFieldGet(this,Qp,`f`)].concat(X[__classPrivateFieldGet(this,Qp,`f`)]||[]).filter(t=>t.length>1).includes(``+q._[q._.length-1])&&(q._.pop(),Z=!0),__classPrivateFieldSet(this,$p,!1,`f`);let H=__classPrivateFieldGet(this,Rp,`f`).getCommands(),ne=__classPrivateFieldGet(this,Vp,`f`)?.completionKey?[__classPrivateFieldGet(this,Vp,`f`)?.completionKey,...this.getAliases()[__classPrivateFieldGet(this,Vp,`f`)?.completionKey]??[]].some(t=>Object.prototype.hasOwnProperty.call(q,t)):!1,re=Z||ne||N;if(q._.length){if(H.length){let t;for(let n=C||0,F;q._[n]!==void 0;n++)if(F=String(q._[n]),H.includes(F)&&F!==__classPrivateFieldGet(this,Hp,`f`)){let t=__classPrivateFieldGet(this,Rp,`f`).runCommand(F,this,W,n+1,N,Z||te||N);return this[Ym](t,I,!!S,!1)}else if(!t&&F!==__classPrivateFieldGet(this,Hp,`f`)){t=F;break}!__classPrivateFieldGet(this,Rp,`f`).hasDefaultCommand()&&__classPrivateFieldGet(this,dm,`f`)&&t&&!re&&__classPrivateFieldGet(this,ym,`f`).recommendCommands(t,H)}__classPrivateFieldGet(this,Hp,`f`)&&q._.includes(__classPrivateFieldGet(this,Hp,`f`))&&!ne&&(__classPrivateFieldGet(this,qp,`f`)&&setBlocking(!0),this.showCompletionScript(),this.exit(0))}if(__classPrivateFieldGet(this,Rp,`f`).hasDefaultCommand()&&!re){let t=__classPrivateFieldGet(this,Rp,`f`).runCommand(null,this,W,0,N,Z||te||N);return this[Ym](t,I,!!S,!1)}if(ne){__classPrivateFieldGet(this,qp,`f`)&&setBlocking(!0),t=[].concat(t);let n=t.slice(t.indexOf(`--${__classPrivateFieldGet(this,Vp,`f`).completionKey}`)+1);return __classPrivateFieldGet(this,Vp,`f`).getCompletion(n,(t,n)=>{if(t)throw new Il(t.message);(n||[]).forEach(t=>{__classPrivateFieldGet(this,em,`f`).log(t)}),this.exit(0)}),this[Ym](q,!I,!!S,!1)}if(__classPrivateFieldGet(this,Zp,`f`)||(Z?(__classPrivateFieldGet(this,qp,`f`)&&setBlocking(!0),F=!0,this.showHelp(t=>{__classPrivateFieldGet(this,em,`f`).log(t),this.exit(0)})):te&&(__classPrivateFieldGet(this,qp,`f`)&&setBlocking(!0),F=!0,__classPrivateFieldGet(this,gm,`f`).showVersion(`log`),this.exit(0))),!F&&__classPrivateFieldGet(this,nm,`f`).skipValidation.length>0&&(F=Object.keys(q).some(t=>__classPrivateFieldGet(this,nm,`f`).skipValidation.indexOf(t)>=0&&q[t]===!0)),!F){if(W.error)throw new Il(W.error.message);if(!ne){let t=this[$m](X,{},W.error);S||(Y=applyMiddleware(q,this,__classPrivateFieldGet(this,Yp,`f`).getMiddleware(),!0)),Y=this[zm](t,Y??q),isPromise(Y)&&!S&&(Y=Y.then(()=>applyMiddleware(q,this,__classPrivateFieldGet(this,Yp,`f`).getMiddleware(),!1)))}}}catch(t){if(t instanceof Il)__classPrivateFieldGet(this,gm,`f`).fail(t.message,t);else throw t}return this[Ym](Y??q,I,!!S,!0)}[$m](t,n,S,C){let N={...this.getDemandedOptions()};return F=>{if(S)throw new Il(S.message);__classPrivateFieldGet(this,ym,`f`).nonOptionCount(F),__classPrivateFieldGet(this,ym,`f`).requiredArguments(F,N);let I=!1;__classPrivateFieldGet(this,mm,`f`)&&(I=__classPrivateFieldGet(this,ym,`f`).unknownCommands(F)),__classPrivateFieldGet(this,pm,`f`)&&!I?__classPrivateFieldGet(this,ym,`f`).unknownArguments(F,t,n,!!C):__classPrivateFieldGet(this,hm,`f`)&&__classPrivateFieldGet(this,ym,`f`).unknownArguments(F,t,{},!1,!1),__classPrivateFieldGet(this,ym,`f`).limitedChoices(F),__classPrivateFieldGet(this,ym,`f`).implications(F),__classPrivateFieldGet(this,ym,`f`).conflicting(F)}}[eh](){__classPrivateFieldSet(this,Zp,!0,`f`)}[th](t){if(typeof t==`string`)__classPrivateFieldGet(this,nm,`f`).key[t]=!0;else for(let n of t)__classPrivateFieldGet(this,nm,`f`).key[n]=!0}}}),ih,ah=__esmMin(()=>{vp(),rh(),ih=YargsFactory(gp)});function classifyCliFailure(t,n){return typeof t==`string`&&t.length>0?{kind:`usage`,message:t}:{kind:`runtime`}}var oh=__esmMin(()=>{});function buildHeaders(t,n){let S={"user-agent":`gjsify-install/0.64.22`,"accept-encoding":n.acceptEncoding??`identity`};if(n.npmrc){let C=resolveAuthForUrl(t,n.npmrc);C&&(S.authorization=C)}if(n.headers)for(let[t,C]of Object.entries(n.headers))S[t.toLowerCase()]=C;return S}function resolveAuthForUrl(t,n){let S=pathPrefixes(new URL(t));for(let t of S){let S=n.authTokens[t];if(S)return`Bearer ${S}`;let C=n.basicAuth[t];if(C)return`Basic ${btoa(`${C.username}:${C.password}`)}`}return null}function pathPrefixes(t){let n=t.pathname.split(`/`).filter(Boolean),S=[];for(let C=n.length;C>=0;C--){let N=n.slice(0,C).join(`/`);S.push(N?`//${t.host}/${N}`:`//${t.host}`)}return S}var sh=__esmMin(()=>{}),PackageNotFoundError,IntegrityError,RegistryTimeoutError,RegistryUnreachableError,ch=__esmMin(()=>{PackageNotFoundError=class extends Error{name;url;constructor(t,n){super(`Package not found in registry: ${t} (${n})`),this.name=t,this.url=n,this.name=`PackageNotFoundError`}},IntegrityError=class extends Error{url;integrity;constructor(t,n){super(`Tarball integrity mismatch for ${t} (expected ${n})`),this.url=t,this.integrity=n,this.name=`IntegrityError`}},RegistryTimeoutError=class extends Error{url;timeoutMs;attempts;constructor(t,n,S){let C=Math.round(n/100)/10,N=Math.round(n*S/100)/10;super(`@gjsify/npm-registry: GET ${t} timed out after ${C}s × ${S} attempt(s) (total ~${N}s). This usually means the registry CDN is slow or unreachable.`),this.url=t,this.timeoutMs=n,this.attempts=S,this.name=`RegistryTimeoutError`}},RegistryUnreachableError=class extends Error{url;attempts;elapsedMs;constructor(t,n,S,C){let N=Math.round(S/100)/10,F=C instanceof Error?C.message:String(C);super(`@gjsify/npm-registry: GET ${t} failed after ${n} attempt(s) over ~${N}s: ${F}. This usually means the registry or the network dropped out.`),this.url=t,this.attempts=n,this.elapsedMs=S,this.name=`RegistryUnreachableError`,this.cause=C}}});function registryFor(t,n){if(n&&t.startsWith(`@`)){let S=t.slice(0,t.indexOf(`/`)),C=n.scopes[S];if(C)return ensureTrailingSlash$1(C)}return n?.registry?ensureTrailingSlash$1(n.registry):lh}function parseNpmrc(t){let n={registry:lh,scopes:{},authTokens:{},basicAuth:{}},S=t.split(/\r?\n/),C={};for(let t of S){let S=t.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`){n.registry=ensureTrailingSlash$1(I);continue}let H=F.match(/^(@[^:]+):registry$/);if(H){n.scopes[H[1]]=ensureTrailingSlash$1(I);continue}let W=F.match(/^\/\/(.+):_authToken$/);if(W){n.authTokens[normalizeAuthHost(W[1])]=I;continue}let q=F.match(/^\/\/(.+):username$/);if(q){(C[normalizeAuthHost(q[1])]??={}).user=I;continue}let Y=F.match(/^\/\/(.+):_password$/);if(Y){let t=base64Decode$1(I);(C[normalizeAuthHost(Y[1])]??={}).pass=t;continue}}for(let[t,S]of Object.entries(C))S.user&&S.pass!==void 0&&(n.basicAuth[t]={username:S.user,password:S.pass});return n}function normalizeAuthHost(t){return`//${t.replace(/\/+$/,``)}`}function ensureTrailingSlash$1(t){return t.endsWith(`/`)?t:t+`/`}function stripQuotes(t){return t.startsWith(`"`)&&t.endsWith(`"`)||t.startsWith(`'`)&&t.endsWith(`'`)?t.slice(1,-1):t}function expandEnv(t){return t.replace(/\$\{([A-Z0-9_]+)\}/gi,(t,n)=>globalThis.process?.env?.[n]??``)}function base64Decode$1(t){return atob(t)}var lh,uh=__esmMin(()=>{lh=`https://registry.npmjs.org/`,__name$1(ensureTrailingSlash$1,`ensureTrailingSlash`),__name$1(base64Decode$1,`base64Decode`)});async function fetchWithRetry(t,n,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??5),F=Math.max(0,S.retryDelayMs??1e3),I=Math.max(0,S.timeoutMs??3e4),H=S.retryNotFound??!1,W=Date.now(),q=0,Y,X=0;for(;;){if(n.signal?.aborted)throw signalAbortError(n.signal);let Z=I>0?new AbortController:null,te=Z===null?null:setTimeout(()=>Z.abort(Error(`@gjsify/npm-registry: per-request timeout ${I}ms`)),I),ne=composeSignals(n.signal,Z?.signal);try{let F=await C(t,{...n,signal:ne}),I=isRetryableStatus(F.status)||H&&F.status===404;if(F.ok||!I||q>=N)return S.read?await S.read(F):F;try{await F.arrayBuffer()}catch{}Y=Error(`HTTP ${F.status} ${F.statusText}`)}catch(S){let C=Z!==null&&Z.signal.aborted,F=n.signal?.aborted===!0;if(C&&!F){if(X++,q>=N)throw new RegistryTimeoutError(t,I,X);Y=S}else if(F)throw signalAbortError(n.signal);else{if(!isRetryableError(S))throw S;if(q>=N)throw new RegistryUnreachableError(t,q+1,Date.now()-W,S);Y=S}}finally{te!==null&&clearTimeout(te)}let re=Math.min(F*2**q,8e3);S.onRetry?.({attempt:q+1,error:Y,delayMs:re}),await delay$1(re,n.signal),q++}}function composeSignals(t,n){return t?n?AbortSignal.any([t,n]):t:n}function isRetryableStatus(t){return t===408||t===425||t===429||t===500||t===502||t===503||t===504||t===521||t===522||t===524||t===525}function isRetryableError(t){if(t&&typeof t==`object`&&`name`in t&&t.name===`AbortError`)return!1;if(t instanceof TypeError)return!0;if(t&&typeof t==`object`&&`name`in t){let n=t.name;if(n===`FetchError`)return!0;if(n===`AbortError`)return!1}let n=t?.cause;if(n&&typeof n==`object`&&`code`in n){let t=n.code;if(typeof t==`string`)return t===`ECONNRESET`||t===`ECONNREFUSED`||t===`ENETUNREACH`||t===`ENOTFOUND`||t===`ETIMEDOUT`||t===`EAI_AGAIN`||t===`UND_ERR_SOCKET`||t===`UND_ERR_CONNECT_TIMEOUT`}return!1}function delay$1(t,n){return t<=0?Promise.resolve():new Promise((S,C)=>{let N=setTimeout(()=>{n?.removeEventListener?.(`abort`,onAbort),S()},t),onAbort=()=>{clearTimeout(N),C(signalAbortError(n))};if(n?.aborted){clearTimeout(N),C(signalAbortError(n));return}n?.addEventListener?.(`abort`,onAbort,{once:!0})})}function signalAbortError(t){let n=t&&`reason`in t?t.reason:void 0;if(n instanceof Error)return n;let S=Error(`Aborted`);return S.name=`AbortError`,S}var dh=__esmMin(()=>{ch(),__name$1(delay$1,`delay`)});async function verifyIntegrity(t,n){let S=n.trim().split(/\s+/);for(let n of S){let S=n.indexOf(`-`);if(S<0)continue;let C=n.slice(0,S).toLowerCase(),N=n.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(t));if(bytesToBase64(new Uint8Array(H))===N)return!0}return!1}function subriToWebCryptoAlgo(t){switch(t){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(t){if(t.byteOffset===0&&t.byteLength===t.buffer.byteLength)return t.buffer;let n=new Uint8Array(t.byteLength);return n.set(t),n.buffer}function bytesToBase64(t){let n=``;for(let S=0;S<t.length;S++)n+=String.fromCharCode(t[S]);return btoa(n)}var fh=__esmMin(()=>{});function assertPackument(t,n){if(!n||typeof n!=`object`)throw TypeError(`registry: ${t} packument is not an object`);let S=n;if(typeof S.name!=`string`)throw TypeError(`registry: ${t} packument missing string name`);if(!S.versions||typeof S.versions!=`object`)throw TypeError(`registry: ${t} packument missing versions map`)}function packumentUrl(t,n){let S=ensureTrailingSlash$1(n);if(t.startsWith(`@`)){let n=t.indexOf(`/`);if(n<0)throw TypeError(`Invalid scoped package name: ${t}`);let C=t.slice(0,n),N=t.slice(n+1);return`${S}${encodeURIComponent(C)}/${encodeURIComponent(N)}`}return`${S}${encodeURIComponent(t)}`}async function fetchPackumentConditional(t,n={}){let S=packumentUrl(t,n.registry??registryFor(t,n.npmrc)),C=buildHeaders(S,{...n,acceptEncoding:`gzip`});C.accept??=n.fullMetadata?`application/json`:`application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*`,n.ifNoneMatch&&(C[`if-none-match`]=n.ifNoneMatch);let N=await fetchWithRetry(S,{headers:C,signal:n.signal},{fetch:n.fetch,retries:n.retries,retryDelayMs:n.retryDelayMs,timeoutMs:n.timeoutMs,onRetry:n.onRetry,read:async n=>{if(n.status===304){try{await n.arrayBuffer()}catch{}return{status:`not-modified`}}if(!n.ok)throw n.status===404||n.status===406?new PackageNotFoundError(t,S):Error(`registry GET ${S} -> ${n.status} ${n.statusText}`);return{status:`fresh`,body:await decodeJsonBody(n),etag:n.headers.get(`etag`)??void 0}}});if(N.status===`not-modified`)return{status:`not-modified`,etag:n.ifNoneMatch};let F=N.body;return assertPackument(t,F),{status:`fresh`,packument:F,etag:N.etag}}async function decodeJsonBody(t){return t.json()}async function fetchPackument(t,n={}){let S=await fetchPackumentConditional(t,n);if(!S.packument)throw Error(`registry: ${t} returned 304 Not Modified to an unconditional request`);return S.packument}var ph=__esmMin(()=>{sh(),ch(),uh(),dh()});async function fetchTarball(t,n={}){let S=buildHeaders(t,{...n,acceptEncoding:`identity`});S.accept??=`application/octet-stream`;let C=await fetchWithRetry(t,{headers:S,signal:n.signal},{fetch:n.fetch,retries:n.retries,retryDelayMs:n.retryDelayMs,timeoutMs:n.timeoutMs,onRetry:n.onRetry,retryNotFound:n.retryNotFound??!0,read:async n=>{if(!n.ok)throw Error(`tarball GET ${t} -> ${n.status} ${n.statusText}`);return new Uint8Array(await n.arrayBuffer())}});if(n.integrity&&!await verifyIntegrity(C,n.integrity))throw new IntegrityError(t,n.integrity);return C}var mh=__esmMin(()=>{sh(),ch(),dh(),fh()});async function whoami(t,n){let S=`${ensureTrailingSlash$1(t)}-/whoami`,C=buildHeaders(S,{npmrc:n});C.accept=`application/json`;let N=globalThis.fetch;if(!N)throw Error(`@gjsify/npm-registry: globalThis.fetch is missing`);let F=await N(S,{method:`GET`,headers:C});if(!F.ok)throw Error(`whoami GET ${S} -> ${F.status} ${F.statusText}`);let I=await F.json();if(I&&typeof I==`object`&&`username`in I){let t=I.username;if(typeof t==`string`&&t.length>0)return{username:t}}return{}}var hh=__esmMin(()=>{sh(),uh()}),gh=__esmMin(()=>{sh(),ch(),uh(),fh(),ph(),mh(),hh()});function escapePackageName(t){return t.replace(`/`,`%2f`)}function buildPublishHeaders(t,n){let S=buildHeaders(t,{npmrc:n.npmrc});return S[`content-type`]=`application/json`,S[`npm-command`]=`publish`,S[`npm-auth-type`]=n.otp?`legacy`:`web`,S[`user-agent`]=n.userAgent??defaultUserAgent(),n.otp&&(S[`npm-otp`]=n.otp),n.authorization&&(S.authorization=n.authorization),S}function cliVersion(){return vh===void 0&&(vh=`0.64.22`),vh}function cliPackageDir(){let t=globalThis.process?.env?.GJSIFY_CLI_PACKAGE_JSON,n;try{n=zn(t||fileURLToPath(import.meta.url))}catch{return null}for(let t=0;t<12;t++){try{if(JSON.parse(readFileSync(`${n}/package.json`,`utf8`)).name===`@gjsify/cli`)return n}catch{}let t=zn(n);if(t===n)break;n=t}return null}function defaultUserAgent(){let t=globalThis.process,n=t?.arch??`x64`,S=t?.platform??`linux`;return`gjsify-publish/${cliVersion()} (${S} ${n})`}var vh,yh=__esmMin(()=>{ef(),qn(),ir(),gh()}),bh,xh=__esmMin(()=>{bh=`gjsify`});function parseDeclaredChannel(t,n){if(!(t===void 0||t===``)){if(Sh.includes(t))return t;throw Error(`${n}: "${String(t)}" is not a distribution channel. Known: ${Sh.join(`, `)}.`)}}function channelAllowsDonations(t){return t!==void 0&&Ch[t]===!0}var Sh,Ch,wh,Th=__esmMin(()=>{Sh=[`flathub`,`web`,`microsoft-store`,`apple-app-store`],Ch={flathub:!0,web:!0,"microsoft-store":!1,"apple-app-store":!1},wh=`GJSIFY_CHANNEL`}),Eh=__commonJSMin(((t,n)=>{let S=(qn(),__toCommonJS(jn)),C=(Xl(),__toCommonJS(Kl)),N=(ef(),__toCommonJS(Qd)),resolveFrom=(t,n,F)=>{if(typeof t!=`string`)throw TypeError(`Expected \`fromDir\` to be of type \`string\`, got \`${typeof t}\``);if(typeof n!=`string`)throw TypeError(`Expected \`moduleId\` to be of type \`string\`, got \`${typeof n}\``);try{t=N.realpathSync(t)}catch(n){if(n.code===`ENOENT`)t=S.resolve(t);else if(F)return null;else throw n}let I=S.join(t,`noop.js`),resolveFileName=()=>C._resolveFilename(n,{id:I,filename:I,paths:C._nodeModulePaths(t)});if(F)try{return resolveFileName()}catch{return null}return resolveFileName()};n.exports=(t,n)=>resolveFrom(t,n),n.exports.silent=(t,n)=>resolveFrom(t,n,!0)})),Dh=__commonJSMin(((t,n)=>{let callsites=()=>{let t=Error.prepareStackTrace;Error.prepareStackTrace=(t,n)=>n;let n=Error().stack.slice(1);return Error.prepareStackTrace=t,n};n.exports=callsites,n.exports.default=callsites})),Oh=__commonJSMin(((t,n)=>{let S=Dh();n.exports=t=>{let n=S();if(!t)return n[2].getFileName();let C=!1;n.shift();for(let S of n){let n=S.getFileName();if(typeof n==`string`){if(n===t){C=!0;continue}if(n!==`module.js`&&C&&n!==t)return n}}}})),kh=__commonJSMin(((t,n)=>{var{__gjsifyModuleDir:S,__gjsifyModuleFile:C}=(eu(),__toCommonJS(Zl)),N=S(`import-fresh/index.js`),F=C(`import-fresh/index.js`);let I=(qn(),__toCommonJS(jn)),H=Eh(),W=Oh();n.exports=t=>{if(typeof t!=`string`)throw TypeError(`Expected a string`);let n=W(F),S=n?I.dirname(n):N,C=H(S,t),q=Y.cache[C];if(q&&q.parent){let t=q.parent.children.length;for(;t--;)q.parent.children[t].id===C&&q.parent.children.splice(t,1)}delete Y.cache[C];let X=Y.cache[n];return X===void 0||X.require===void 0?Y(C):X.require(C)}})),Ah=__commonJSMin(((t,n)=>{n.exports=function isArrayish(t){return t?t instanceof Array||Array.isArray(t)||t.length>=0&&t.splice instanceof Function:!1}})),jh=__commonJSMin(((t,n)=>{var S=(zu(),__toCommonJS(Fu)),C=Ah(),N=function errorEx(t,n){(!t||t.constructor!==String)&&(n=t||{},t=Error.name);var N=function ErrorEXError(S){if(!this)return new ErrorEXError(S);S=S instanceof Error?S.message:S||this.message,Error.call(this,S),Error.captureStackTrace(this,N),this.name=t,Object.defineProperty(this,"message",{configurable:!0,enumerable:!1,get:function(){var t=S.split(/\r?\n/g);for(var N in n)if(n.hasOwnProperty(N)){var F=n[N];`message`in F&&(t=F.message(this[N],t)||t,C(t)||(t=[t]))}return t.join(`
150
150
  `)},set:function(t){S=t}});var F=null,I=Object.getOwnPropertyDescriptor(this,`stack`),H=I.get,W=I.value;delete I.value,delete I.writable,I.set=function(t){F=t},I.get=function(){var t=(F||(H?H.call(this):W)).split(/\r?\n+/g);F||(t[0]=this.name+`: `+this.message);var S=1;for(var C in n)if(n.hasOwnProperty(C)){var N=n[C];if(`line`in N){var I=N.line(this[C]);I&&t.splice(S++,0,` `+I)}`stack`in N&&N.stack(this[C],t)}return t.join(`
151
151
  `)},Object.defineProperty(this,"stack",I)};return Object.setPrototypeOf?(Object.setPrototypeOf(N.prototype,Error.prototype),Object.setPrototypeOf(N,Error)):S.inherits(N,Error),N};N.append=function(t,n){return{message:function(S,C){return S||=n,S&&(C[0]+=` `+t.replace(`%s`,S.toString())),C}}},N.line=function(t,n){return{line:function(S){return S||=n,S?t.replace(`%s`,S.toString()):null}}},n.exports=N})),Mh=__commonJSMin(((t,n)=>{let hexify=t=>{let n=t.charCodeAt(0).toString(16).toUpperCase();return`0x`+(n.length%2?`0`:``)+n},parseError=(t,n,S)=>{if(!n)return{message:t.message+` while parsing empty string`,position:0};let C=t.message.match(/^Unexpected token (.) .*position\s+(\d+)/i),N=C?+C[2]:t.message.match(/^Unexpected end of JSON.*/i)?n.length-1:null,F=C?t.message.replace(/^Unexpected token ./,`Unexpected token ${JSON.stringify(C[1])} (${hexify(C[1])})`):t.message;if(N!=null){let t=N<=S?0:N-S,C=N+S>=n.length?n.length:N+S,I=(t===0?``:`...`)+n.slice(t,C)+(C===n.length?``:`...`);return{message:F+` while parsing ${n===I?``:`near `}${JSON.stringify(I)}`,position:N}}else return{message:F+` while parsing '${n.slice(0,S*2)}'`,position:0}};var JSONParseError=class extends SyntaxError{constructor(t,n,S,C){S||=20;let N=parseError(t,n,S);super(N.message),Object.assign(this,N),this.code=`EJSONPARSE`,this.systemError=t,Error.captureStackTrace(this,C||this.constructor)}get name(){return this.constructor.name}set name(t){}get[Symbol.toStringTag](){return this.constructor.name}};let S=Symbol.for(`indent`),C=Symbol.for(`newline`),N=/^\s*[{\[]((?:\r?\n)+)([\s\t]*)/,F=/^(?:\{\}|\[\])((?:\r?\n)+)?$/,parseJson=(t,n,I)=>{let H=stripBOM(t);I||=20;try{let[,t=`
152
152
  `,I=` `]=H.match(F)||H.match(N)||[,``,``],W=JSON.parse(H,n);return W&&typeof W==`object`&&(W[C]=t,W[S]=I),W}catch(n){if(typeof t!=`string`&&!Buffer.isBuffer(t)){let S=Array.isArray(t)&&t.length===0;throw Object.assign(TypeError(`Cannot parse ${S?`an empty array`:String(t)}`),{code:`EJSONPARSE`,systemError:n})}throw new JSONParseError(n,H,I,parseJson)}},stripBOM=t=>String(t).replace(/^\uFEFF/,``);n.exports=parseJson,parseJson.JSONParseError=JSONParseError,parseJson.noExceptions=(t,n)=>{try{return JSON.parse(stripBOM(t),n)}catch{}}})),Nh=__commonJSMin((t=>{t.__esModule=!0,t.LinesAndColumns=void 0;var n=`
@@ -951,7 +951,7 @@ Add @gjsify/node-gi as a dependency to run it on Node, e.g.:
951
951
  echo "gjsify: got: node $*" >&2
952
952
  exit 127 ;;
953
953
  esac
954
- `+S+`exec "${C}" -m "${n}" run --node-script "$@"\n`}var Iz,Lz,Rz,zz=__esmMin(()=>{fl(),ef(),$g(),qn(),ir(),D_(),yR(),nL(),LR(),Fz(),MI(),Iz=!1,Lz=!1,Rz=`node-shim`});function markDaemonCommand(){Bz=!0}function isDaemonCommand(){return Bz}var Bz,Vz=__esmMin(()=>{Bz=!1});async function runTargetOnRuntime(t,n,S){if(!looksLikeFile(n))return ge.error(`gjsify run: --runtime ${t} needs a bundle FILE, but "${n}" is not a path.\n Build first (e.g. \`gjsify build src/app.ts --app ${t===`gjs`?`gjs`:`node`} --outfile dist/app.${t===`gjs`?`gjs`:`node`}.mjs\`), then run the output file.`),process.exit(1);let C=readPackageJson$1(In(process.cwd(),`package.json`)),N=checkRuntimeSupported(t,readDeclaredRuntimes(C),C?.name??n);if(!N.ok)return ge.error(`gjsify run: ${N.message}`),process.exit(1);let F=Nn(n);t===`gjs`?await runGjsBundle(F,S,{completion:`exit`,exitOnSuccess:!0}):await runRuntimeBundle(t,F,S,{completion:`exit`,exitOnSuccess:!0})}function isLikelyGjsBundle(t){if(/\.gjs\.[mc]?js$/.test(t))return!0;try{let n=readFileSync(t,`utf-8`).slice(0,65536);return n.startsWith(`#!/usr/bin/env -S gjs`)||/(?:from|import)\s*["']gi:\/\//.test(n)||/\bimports\.(?:gi|system)\b/.test(n)}catch{return!1}}function looksLikeFile(t){if(t.startsWith(`./`)||t.startsWith(`../`)||t.startsWith(`/`)||t.includes(`/`)||t.includes(`\\`)||/\.(c?js|mjs|cjs|gjs)$/.test(t))return!0;try{return statSync(t).isFile()}catch{return!1}}async function runScriptInWorkspace(t,n,S){let C=findWorkspaceRoot(process.cwd())??process.cwd(),N;try{N=discoverWorkspaces(C)}catch(t){return ge.error(`gjsify run: could not read workspaces at ${C}: ${t.message}`),process.exit(1)}let F=N.find(n=>n.name===t||n.relativeLocation===t||Bn(n.location)===t);if(!F){let n=N.map(t=>t.relativeLocation).join(`, `)||`<none>`;return ge.error(`gjsify run: no workspace "${t}" under ${C} (available: ${n})`),process.exit(1)}await runScript(n,S,F.location)}async function runScript(t,n,S=process.cwd()){let C=In(S,`package.json`),N=readPackageJson$1(C);if(!N)return ge.error(`gjsify run: no package.json in ${S}`),process.exit(1);let F=N.scripts??{},I=F[t];if(typeof I!=`string`){let n=Object.keys(F).join(`, `)||`<none>`;return ge.error(`gjsify run: no script "${t}" in ${C} (available: ${n})`),process.exit(1)}let H=findWorkspaceRoot(S),W=[In(S,`node_modules`,`.bin`)];H&&H!==S&&W.push(In(H,`node_modules`,`.bin`)),process.env.GJSIFY_SHIM_DIR&&W.unshift(process.env.GJSIFY_SHIM_DIR);let q=nodeShimDir();q&&W.unshift(q);let Y=process.env.FORCE_COLOR!==void 0||process.env.NO_COLOR!==void 0?{}:{FORCE_COLOR:`1`},X={...process.env,...Y,PATH:[...W,process.env.PATH??``].filter(Boolean).join(Gn),npm_lifecycle_event:t,npm_package_name:N.name??``,npm_package_version:N.version??``},Z=isGjs()?gjsifyInProcessArgv(I,n):null;if(Z){process.env.PATH=X.PATH,process.env.npm_lifecycle_event=X.npm_lifecycle_event,process.env.npm_package_name=X.npm_package_name,process.env.npm_package_version=X.npm_package_version,X.FORCE_COLOR!==void 0&&(process.env.FORCE_COLOR=X.FORCE_COLOR),S!==process.cwd()&&process.chdir(S);let t=!1;try{let{runCli:t}=await Promise.resolve().then(()=>(iY(),rY));await t(Z)}catch(n){ge.error(n.message),t=!0}if(!t&&isDaemonCommand())return;let n=t?1:process.exitCode==null?0:Number(process.exitCode);return process.exit(n)}let te=n.length>0?`${I} ${n.map(shellEscape).join(` `)}`:I,ne;try{ne=await spawnToCompletion(te,[],{completion:`exit`,cwd:S,env:X,shell:!0})}catch(t){return ge.error(t.message),process.exit(1)}return ne.code===0?process.exit(0):(ge.error(`script "${t}" exited with ${describeExit(ne)}`),process.exit(1))}function shellEscape(t){return/^[a-zA-Z0-9_\-./=:@,]+$/.test(t)?t:`'${t.replace(/'/g,`'\\''`)}'`}function gjsifyInProcessArgv(t,n){let S=gjsifyCommandArgv(t);return S?[...S,...n]:null}var Hz,Uz=__esmMin(()=>{_e(),ef(),qn(),dR(),sv(),DR(),kR(),FR(),IR(),zz(),MI(),qL(),Vz(),AI(),D_(),uv(),Hz={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:t=>t.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:[]}).option(`workspace`,{alias:`w`,type:`string`,description:"Run <target> as a script in the named workspace (by name or path), like `npm run <script> -w <name>`."}).option(`node-script`,{type:`boolean`,default:!1,description:"Treat <target> as an unbundled Node-style script (imports `node:` builtins) and run it on the host runtime. Under GJS the file is bundled `--app gjs` on the fly first, which is what makes a repo script runnable on a host that has no Node."}).option(`runtime`,{type:`string`,choices:cv,description:"Runtime to launch a bundle FILE on: gjs (default, `--app gjs` bundle) | node | bun | deno (the `--app node` bundle). Forces file mode."}).version(!1).help(!1).parserConfiguration({"populate--":!0,"parse-positional-numbers":!1,"unknown-options-as-args":!0}),handler:async t=>{let n=t.target,S=[...t.args??[],...doubleDashArgs(t)];if(t.nodeScript===!0){let isSet=t=>typeof t==`string`&&t.length>0,C=isSet(t.runtime)?`--runtime`:isSet(t.workspace)?`--workspace`:null;if(C)return ge.error(`gjsify run: --node-script cannot be combined with ${C}.`),process.exit(1);await runNodeScript(n,S,{completion:`exit`,exitOnSuccess:!0});return}let C=t.runtime;if(typeof C==`string`&&C.length>0){if(typeof t.workspace==`string`&&t.workspace.length>0)return ge.error(`gjsify run: --runtime cannot be combined with --workspace (file mode vs script mode).`),process.exit(1);if(!isExampleRuntime(C))return ge.error(`gjsify run: unknown --runtime "${C}" (expected: ${cv.join(`, `)}).`),process.exit(1);await runTargetOnRuntime(C,n,S);return}if(typeof t.workspace==`string`&&t.workspace.length>0){await runScriptInWorkspace(t.workspace,n,S);return}let N=readPackageJson$1(In(process.cwd(),`package.json`));if(!(N?.scripts&&typeof N.scripts[n]==`string`)&&looksLikeFile(n)){let t=Nn(n),C=hostRuntime$1(),N=C===`gjs`||isLikelyGjsBundle(t)?`gjs`:C;N===`gjs`?await runGjsBundle(t,S,{completion:`exit`,exitOnSuccess:!0}):await runRuntimeBundle(N,t,S,{completion:`exit`,exitOnSuccess:!0});return}await runScript(n,S)}}}),Wz,Gz=__esmMin(()=>{_e(),qn(),nL(),Wz={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:t=>t.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 t=>{let n=process.cwd(),S=t.file?Nn(t.file):null,C=detectNativePackages(n),N=buildNativeEnv(C),F=Object.entries(N).filter(([,t])=>t!==void 0);if(t.export){for(let[t,n]of F)ge.log(`export ${t}="${n}"`);return}if(C.length===0){ge.log(`No native gjsify packages detected in node_modules.`),ge.log(`Native packages declare "gjsify": { "prebuilds": "<dir>" } in their package.json.`);return}ge.log(`Native packages detected:`);for(let t of C)ge.log(` ${t.name} → ${t.prebuildsDir}`);ge.log(``),ge.log(`To run your app directly with gjs, set:`);for(let[t,n]of F)ge.log(` export ${t}="${n}"`);S?ge.log(` gjs -m ${S}`):ge.log(` gjs -m <your-bundle.js>`),ge.log(``),ge.log(`Or use gjsify run to handle this automatically:`),S?ge.log(` gjsify run ${t.file}`):ge.log(` gjsify run <your-bundle.js>`)}}}),Kz,qz=__esmMin(()=>{_e(),ZI(),Kz={command:`system-check`,description:"Check that required system dependencies (GJS, GTK4, libsoup3, …) are installed. Optional dependencies are detected only when their @gjsify/* package is in your project. (Previously called `gjsify check`; the bare name now runs TypeScript checks across the workspace — see `gjsify check --help`.)",builder:t=>t.option(`json`,{description:`Output results as JSON`,type:`boolean`,default:!1}),handler:async t=>{let n=runAllChecks(process.cwd()),S=detectPackageManager$1(),C=checkTypeSkew(process.cwd()),N=n.filter(t=>!t.found&&t.severity===`required`),F=n.filter(t=>!t.found&&t.severity===`optional`),I=[...N,...F];if(t.json)return ge.log(JSON.stringify({packageManager:S,deps:n,typeSkew:C},null,2)),process.exit(+(N.length>0));ge.log(`System dependency check
954
+ `+S+`exec "${C}" -m "${n}" run --node-script "$@"\n`}var Iz,Lz,Rz,zz=__esmMin(()=>{fl(),ef(),$g(),qn(),ir(),D_(),yR(),nL(),LR(),Fz(),MI(),Iz=!1,Lz=!1,Rz=`node-shim`});function markDaemonCommand(){Bz=!0}function isDaemonCommand(){return Bz}var Bz,Vz=__esmMin(()=>{Bz=!1});async function runTargetOnRuntime(t,n,S){if(!looksLikeFile(n))return ge.error(`gjsify run: --runtime ${t} needs a bundle FILE, but "${n}" is not a path.\n Build first (e.g. \`gjsify build src/app.ts --app ${t===`gjs`?`gjs`:`node`} --outfile dist/app.${t===`gjs`?`gjs`:`node`}.mjs\`), then run the output file.`),process.exit(1);let C=readPackageJson$1(In(process.cwd(),`package.json`)),N=checkRuntimeSupported(t,readDeclaredRuntimes(C),C?.name??n);if(!N.ok)return ge.error(`gjsify run: ${N.message}`),process.exit(1);let F=Nn(n);t===`gjs`?await runGjsBundle(F,S,{completion:`exit`,exitOnSuccess:!0}):await runRuntimeBundle(t,F,S,{completion:`exit`,exitOnSuccess:!0})}function isLikelyGjsBundle(t){if(/\.gjs\.[mc]?js$/.test(t))return!0;try{let n=readFileSync(t,`utf-8`).slice(0,65536);return n.startsWith(`#!/usr/bin/env -S gjs`)||/(?:from|import)\s*["']gi:\/\//.test(n)||/\bimports\.(?:gi|system)\b/.test(n)}catch{return!1}}function looksLikeFile(t){if(t.startsWith(`./`)||t.startsWith(`../`)||t.startsWith(`/`)||t.includes(`/`)||t.includes(`\\`)||/\.(c?js|mjs|cjs|gjs)$/.test(t))return!0;try{return statSync(t).isFile()}catch{return!1}}async function runScriptInWorkspace(t,n,S){let C=findWorkspaceRoot(process.cwd())??process.cwd(),N;try{N=discoverWorkspaces(C)}catch(t){return ge.error(`gjsify run: could not read workspaces at ${C}: ${t.message}`),process.exit(1)}let F=N.find(n=>n.name===t||n.relativeLocation===t||Bn(n.location)===t);if(!F){let n=N.map(t=>t.relativeLocation).join(`, `)||`<none>`;return ge.error(`gjsify run: no workspace "${t}" under ${C} (available: ${n})`),process.exit(1)}await runScript(n,S,F.location)}async function runScript(t,n,S=process.cwd()){let C=In(S,`package.json`),N=readPackageJson$1(C);if(!N)return ge.error(`gjsify run: no package.json in ${S}`),process.exit(1);let F=N.scripts??{},I=F[t];if(typeof I!=`string`){let n=Object.keys(F).join(`, `)||`<none>`;return ge.error(`gjsify run: no script "${t}" in ${C} (available: ${n})`),process.exit(1)}let H=findWorkspaceRoot(S),W=[In(S,`node_modules`,`.bin`)];H&&H!==S&&W.push(In(H,`node_modules`,`.bin`)),process.env.GJSIFY_SHIM_DIR&&W.unshift(process.env.GJSIFY_SHIM_DIR);let q=nodeShimDir();q&&W.unshift(q);let Y=process.env.FORCE_COLOR!==void 0||process.env.NO_COLOR!==void 0?{}:{FORCE_COLOR:`1`},X={...process.env,...Y,PATH:[...W,process.env.PATH??``].filter(Boolean).join(Gn),npm_lifecycle_event:t,npm_package_name:N.name??``,npm_package_version:N.version??``},Z=isGjs()?gjsifyInProcessArgv(I,n):null;if(Z){process.env.PATH=X.PATH,process.env.npm_lifecycle_event=X.npm_lifecycle_event,process.env.npm_package_name=X.npm_package_name,process.env.npm_package_version=X.npm_package_version,X.FORCE_COLOR!==void 0&&(process.env.FORCE_COLOR=X.FORCE_COLOR),S!==process.cwd()&&process.chdir(S);let t=!1;try{let{runCli:t}=await Promise.resolve().then(()=>(aY(),iY));await t(Z)}catch(n){ge.error(n.message),t=!0}if(!t&&isDaemonCommand())return;let n=t?1:process.exitCode==null?0:Number(process.exitCode);return process.exit(n)}let te=n.length>0?`${I} ${n.map(shellEscape).join(` `)}`:I,ne;try{ne=await spawnToCompletion(te,[],{completion:`exit`,cwd:S,env:X,shell:!0})}catch(t){return ge.error(t.message),process.exit(1)}return ne.code===0?process.exit(0):(ge.error(`script "${t}" exited with ${describeExit(ne)}`),process.exit(1))}function shellEscape(t){return/^[a-zA-Z0-9_\-./=:@,]+$/.test(t)?t:`'${t.replace(/'/g,`'\\''`)}'`}function gjsifyInProcessArgv(t,n){let S=gjsifyCommandArgv(t);return S?[...S,...n]:null}var Hz,Uz=__esmMin(()=>{_e(),ef(),qn(),dR(),sv(),DR(),kR(),FR(),IR(),zz(),MI(),qL(),Vz(),AI(),D_(),uv(),Hz={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:t=>t.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:[]}).option(`workspace`,{alias:`w`,type:`string`,description:"Run <target> as a script in the named workspace (by name or path), like `npm run <script> -w <name>`."}).option(`node-script`,{type:`boolean`,default:!1,description:"Treat <target> as an unbundled Node-style script (imports `node:` builtins) and run it on the host runtime. Under GJS the file is bundled `--app gjs` on the fly first, which is what makes a repo script runnable on a host that has no Node."}).option(`runtime`,{type:`string`,choices:cv,description:"Runtime to launch a bundle FILE on: gjs (default, `--app gjs` bundle) | node | bun | deno (the `--app node` bundle). Forces file mode."}).version(!1).help(!1).parserConfiguration({"populate--":!0,"parse-positional-numbers":!1,"unknown-options-as-args":!0}),handler:async t=>{let n=t.target,S=[...t.args??[],...doubleDashArgs(t)];if(t.nodeScript===!0){let isSet=t=>typeof t==`string`&&t.length>0,C=isSet(t.runtime)?`--runtime`:isSet(t.workspace)?`--workspace`:null;if(C)return ge.error(`gjsify run: --node-script cannot be combined with ${C}.`),process.exit(1);await runNodeScript(n,S,{completion:`exit`,exitOnSuccess:!0});return}let C=t.runtime;if(typeof C==`string`&&C.length>0){if(typeof t.workspace==`string`&&t.workspace.length>0)return ge.error(`gjsify run: --runtime cannot be combined with --workspace (file mode vs script mode).`),process.exit(1);if(!isExampleRuntime(C))return ge.error(`gjsify run: unknown --runtime "${C}" (expected: ${cv.join(`, `)}).`),process.exit(1);await runTargetOnRuntime(C,n,S);return}if(typeof t.workspace==`string`&&t.workspace.length>0){await runScriptInWorkspace(t.workspace,n,S);return}let N=readPackageJson$1(In(process.cwd(),`package.json`));if(!(N?.scripts&&typeof N.scripts[n]==`string`)&&looksLikeFile(n)){let t=Nn(n),C=hostRuntime$1(),N=C===`gjs`||isLikelyGjsBundle(t)?`gjs`:C;N===`gjs`?await runGjsBundle(t,S,{completion:`exit`,exitOnSuccess:!0}):await runRuntimeBundle(N,t,S,{completion:`exit`,exitOnSuccess:!0});return}await runScript(n,S)}}}),Wz,Gz=__esmMin(()=>{_e(),qn(),nL(),Wz={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:t=>t.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 t=>{let n=process.cwd(),S=t.file?Nn(t.file):null,C=detectNativePackages(n),N=buildNativeEnv(C),F=Object.entries(N).filter(([,t])=>t!==void 0);if(t.export){for(let[t,n]of F)ge.log(`export ${t}="${n}"`);return}if(C.length===0){ge.log(`No native gjsify packages detected in node_modules.`),ge.log(`Native packages declare "gjsify": { "prebuilds": "<dir>" } in their package.json.`);return}ge.log(`Native packages detected:`);for(let t of C)ge.log(` ${t.name} → ${t.prebuildsDir}`);ge.log(``),ge.log(`To run your app directly with gjs, set:`);for(let[t,n]of F)ge.log(` export ${t}="${n}"`);S?ge.log(` gjs -m ${S}`):ge.log(` gjs -m <your-bundle.js>`),ge.log(``),ge.log(`Or use gjsify run to handle this automatically:`),S?ge.log(` gjsify run ${t.file}`):ge.log(` gjsify run <your-bundle.js>`)}}}),Kz,qz=__esmMin(()=>{_e(),ZI(),Kz={command:`system-check`,description:"Check that required system dependencies (GJS, GTK4, libsoup3, …) are installed. Optional dependencies are detected only when their @gjsify/* package is in your project. (Previously called `gjsify check`; the bare name now runs TypeScript checks across the workspace — see `gjsify check --help`.)",builder:t=>t.option(`json`,{description:`Output results as JSON`,type:`boolean`,default:!1}),handler:async t=>{let n=runAllChecks(process.cwd()),S=detectPackageManager$1(),C=checkTypeSkew(process.cwd()),N=n.filter(t=>!t.found&&t.severity===`required`),F=n.filter(t=>!t.found&&t.severity===`optional`),I=[...N,...F];if(t.json)return ge.log(JSON.stringify({packageManager:S,deps:n,typeSkew:C},null,2)),process.exit(+(N.length>0));ge.log(`System dependency check
955
955
  `);let H=n.filter(t=>t.severity===`required`),W=n.filter(t=>t.severity===`optional`);if(H.length>0){ge.log(`Required:`);for(let t of H){let n=t.found?`✓`:`✗`,S=t.version?` (${t.version})`:``;ge.log(` ${n} ${t.name}${S}`)}}if(W.length>0){ge.log(`
956
956
  Optional:`);for(let t of W){let n=t.found?`✓`:`⚠`,S=t.version?` (${t.version})`:``,C=t.requiredBy&&t.requiredBy.length>0?` — needed by ${t.requiredBy.join(`, `)}`:``;ge.log(` ${n} ${t.name}${S}${C}`)}}if(C.length>0){ge.log(`
957
957
  Type/runtime version skew:`);for(let t of C){let n=t.relation===`ahead`?`⚠`:`ℹ`;ge.log(` ${n} ${t.typePackage} describes ${t.declared}, installed ${t.pkgConfig} is ${t.installed}`)}C.some(t=>t.relation===`ahead`)&&ge.log(`
@@ -972,7 +972,7 @@ No install command available for your package manager. Install manually.`),proce
972
972
  bunx @gjsify/cli@latest showcase <name>
973
973
  deno run -A --reload --min-dep-age 0 npm:@gjsify/cli@latest showcase <name>`,hB={command:`showcase [name]`,description:`List or run curated gjsify showcase applications.`,builder:t=>t.positional(`name`,{description:`Showcase name to run (omit to list all)`,type:`string`}).option(`json`,{description:`Output as JSON`,type:`boolean`,default:!1}).option(`list`,{description:`List available showcases`,type:`boolean`,default:!1}).option(`runtime`,{type:`string`,choices:cv,defaultDescription:`gjs when gjs is installed, else the host runtime`,description:"Runtime to run the showcase on: gjs | node | bun | deno (default: gjs when installed, else the host runtime). node/bun/deno run its `--app node` bundle."}),handler:async t=>{if(!t.name||t.list){let n=discoverShowcases();if(t.json){ge.log(JSON.stringify(n,null,2));return}if(n.length===0){ge.log("No showcases found. The CLI ships a curated list in `showcases.json`; if it is missing the CLI install is incomplete.");return}let S=new Map;for(let t of n){let n=S.get(t.category)??[];n.push(t),S.set(t.category,n)}ge.log(`Available gjsify showcases:
974
974
  `);for(let[t,n]of S){ge.log(` ${t.toUpperCase()}:`);let S=Math.max(...n.map(t=>t.name.length));for(let t of n){let n=` `.repeat(S-t.name.length+2),C=t.description?`${n}${t.description}`:``;ge.log(` ${t.name}${C}`)}ge.log(``)}ge.log(`Run a showcase: gjsify showcase <name>`);return}let n=findShowcase(t.name);if(!n)return ge.error(`Unknown showcase: "${t.name}"`),ge.error(`Run "gjsify showcase" to list available showcases.`),process.exit(1);let S=t.runtime??defaultExampleRuntime();if(!isExampleRuntime(S))return ge.error(`Unknown --runtime "${S}" (expected: ${cv.join(`, `)}).`),process.exit(1);if(requiresGjsSystemDeps(S)){let t=runMinimalChecks().filter(t=>!t.found&&t.severity===`required`);if(t.length>0){ge.error(`Missing system dependencies:
975
- `);for(let n of t)ge.error(` ✗ ${n.name}`);let n=buildInstallCommand(detectPackageManager$1(),t);return n&&ge.error(`\nInstall with:\n ${n}`),process.exit(1)}}let C=readCliVersion();if(S!==`gjs`){await runShowcaseOnRuntime(n,S,C);return}let N=C?`${n.packageName}@${C}`:n.packageName;ge.log(`Running showcase: ${n.name} ${runningAs(C)}(via gjsify dlx ${N})\n`);try{let{runCli:t}=await Promise.resolve().then(()=>(iY(),rY));await t([`dlx`,N])}catch(t){ge.error(t.message),process.exit(1)}}}});function resolveTemplatesRoot(){let t=zn(fileURLToPath(import.meta.url)),n=[In(t,`..`,`dist-templates`),In(t,`dist-templates`)];try{let t=createRequire(import.meta.url).resolve(`@gjsify/create-app/package.json`);n.splice(1,0,In(zn(t),`dist-templates`))}catch{}return n.find(t=>existsSync(t))}function discoverTemplates(){let t=resolveTemplatesRoot();if(!t)return[];let n=[];for(let S of readdirSync(t)){let C=In(t,S),N=In(C,`package.json`);if(!statSync(C).isDirectory()||!existsSync(N))continue;let F=_B[S]??``;try{let t=JSON.parse(readFileSync(N,`utf-8`));typeof t.description==`string`&&t.description.trim()&&(F=t.description)}catch{}n.push({name:S,description:F,path:C})}return n.sort((t,n)=>t.name.localeCompare(n.name)),n}function findTemplate(t){return discoverTemplates().find(n=>n.name===t)}var _B,vB=__esmMin(()=>{ef(),Xl(),qn(),ir(),_B={"gtk-minimal":`Minimal GTK4 app — Gtk.ApplicationWindow + Gtk.Label, no Adwaita (Blueprint UI).`,cli:`Command-line tool using yargs (Node.js + GJS).`,"adw-canvas2d":`Adwaita app with HTML Canvas 2D rendering (Blueprint UI).`,"adw-webgl":`Adwaita app with WebGL + three.js (Blueprint UI).`,"adw-game":`Adwaita game shell using Excalibur.js, WebGL → Canvas2D fallback.`,"web-server-hono":`HTTP server using Hono (Web-standard fetch-style API).`,"web-server-express":`HTTP server using Express (familiar Node.js stack).`}});function installCommandLine(t){return[t,...bB[t]].join(` `)}function runScriptCommand(t){return xB[t]}function packageManagersForRuntime(t){return SB[t]}function hostRuntime(){let t=globalThis;return t.Bun===void 0?t.Deno===void 0?t.imports?.gi===void 0?`node`:`gjs`:`deno`:`bun`}function defaultRuntimeFor(t,n){if(n)return t.find(t=>packageManagersForRuntime(t)?.includes(n));let S=hostRuntime();return t.includes(S)?S:t[0]}function startScriptFor(t){return t===`gjs`?`start`:`start:${t}`}var yB,bB,xB,SB,CB,wB=__esmMin(()=>{yB=[`npm`,`yarn`,`pnpm`,`gjsify`,`bun`,`deno`],bB={npm:[`install`,`--no-audit`,`--no-fund`],yarn:[`install`],pnpm:[`install`],gjsify:[`install`],bun:[`install`],deno:[`install`]},xB={npm:`npm run`,yarn:`yarn`,pnpm:`pnpm`,gjsify:`gjsify run`,bun:`bun run`,deno:`deno task`},SB={gjs:[`gjsify`],node:[`npm`,`yarn`,`pnpm`,`gjsify`],bun:[`bun`],deno:[`deno`]},CB={gjs:`GNOME JavaScript — no Node.js needed at runtime.`,node:`Node.js — gi:// via the @gjsify/node-gi bridge.`,bun:`Bun — runs the same --app node bundle.`,deno:`Deno — runs the same --app node bundle.`}});function selectRuntime(t){let{flag:n,offered:S,manager:C,interactive:N}=t;if(n!==void 0)return S.length>0&&!S.includes(n)?{kind:`error`,message:`this template does not run on "${n}". Declared runtimes: ${S.join(`, `)}.`}:{kind:`value`,value:n};if(S.length===1)return{kind:`value`,value:S[0]};if(S.length===0)return{kind:`error`,message:`this template declares no runtime this scaffolder can install for.`};let F=defaultRuntimeFor(S,C);return F===void 0?{kind:`error`,message:`no runtime this template declares installs with "${C}". Declared runtimes: ${S.join(`, `)}.`}:C===void 0?N?{kind:`prompt`,choices:S,initial:F}:{kind:`auto`,value:F,notice:`--runtime not given, using "${F}". Runs on: ${S.join(`, `)}.`}:{kind:`auto`,value:F,notice:`Setting up for ${F} — the runtime ${C} installs for.`}}function selectPackageManager(t){let{flag:n,runtime:S,install:C,interactive:N}=t,F=packageManagersForRuntime(S);return F===void 0||F.length===0?{kind:`error`,message:`no package manager known for runtime "${S}".`}:n===void 0?F.length===1?{kind:`auto`,value:F[0],notice:`Using ${F[0]} — the only package manager that installs for ${S}.`}:N?{kind:`prompt`,choices:F,initial:F[0]}:C?{kind:`error`,message:`--package-manager is required with --install in non-interactive mode. Package managers for ${S}: ${F.join(`, `)}.`}:{kind:`auto`,value:F[0],notice:`--package-manager not given, using "${F[0]}" for ${S}.`}:F.includes(n)?{kind:`value`,value:n}:{kind:`error`,message:`"${n}" cannot install a project you intend to run on ${S}. Package managers for ${S}: ${F.join(`, `)}.`}}var TB=__esmMin(()=>{wB()});function applicationIdFor(t){let n=t.replace(/[^A-Za-z0-9_-]/g,`-`);return`org.gjsify.${/^[0-9]/.test(n)?`app-${n}`:n}`}function sanitizeProjectName(t){let n=t.trim();if(!n)throw Error(`Project name cannot be empty.`);let S=n.toLowerCase().replace(/[^a-z0-9._-]+/g,`-`).replace(/^[._-]+/,``).replace(/[._-]+$/,``);if(!S)throw Error(`"${t}" is not a valid npm package name.`);return S}function isDirEmpty(t){return existsSync(t)?readdirSync(t).length===0:!0}async function createProject(t){let n=sanitizeProjectName(t.projectName),{template:S,force:C=!1,install:N=!1}=t,F=findTemplate(S);if(!F){let t=discoverTemplates().map(t=>t.name).join(`, `);throw Error(`Unknown template "${S}". Available templates: ${t||`(none — run "yarn build" first)`}`)}let I=supportedRuntimes(F),H=t.runtime??defaultRuntimeFor(I,t.packageManager)??hostRuntime(),W=packageManagersForRuntime(H);if(!W)throw Error(`Template "${F.name}" was asked for runtime "${H}", which this version of @gjsify/create-app has no installer mapping for. Upgrade it, or pick one of: ${I.join(`, `)||`(none)`}.`);let q=t.packageManager??W[0];if(!W.includes(q))throw Error(`"${q}" cannot install a project you intend to run on ${H}. Package managers for ${H}: ${W.join(`, `)}.`);let Y=Nn(process.cwd(),n);if(existsSync(Y)&&!isDirEmpty(Y)&&!C)return ge.error(`Error: Directory "${n}" exists and is not empty. Use --force to scaffold into it anyway.`),process.exit(1);if(ge.log(`Creating new Gjsify project in ${Y} (template: ${F.name})...`),mkdirSync(Y,{recursive:!0}),cpSync(F.path,Y,{recursive:!0}),substituteTemplateSentinels(Y,n),N){let t=installCommandLine(q);ge.log(`Running ${t}...`);let n=spawnSync(t,{cwd:Y,stdio:`inherit`,shell:!0});n.error?ge.warn(`${q} install could not start (${n.error.message}); re-run it manually.`):n.status!==0&&ge.warn(`${q} install failed; re-run it manually in the project directory.`)}printNextSteps(n,F,N,q,H)}function substituteTemplateSentinels(t,n){let S=[[EB,n],[DB,applicationIdFor(n)]];renameSentinelPaths(t,S),substituteSentinelContents(t,S)}function renameSentinelPaths(t,n){for(let S of readdirSync(t,{withFileTypes:!0})){let C=S.name;for(let[t,S]of n)C=C.replaceAll(t,S);let N=In(t,S.name),F=In(t,C);F!==N&&renameSync(N,F),S.isDirectory()&&renameSentinelPaths(F,n)}}function substituteSentinelContents(t,n){let S=new Set([`node_modules`,`dist`,`lib`]),C=[t];for(;C.length>0;){let t=C.pop();for(let N of readdirSync(t,{withFileTypes:!0})){let F=In(t,N.name);if(N.isDirectory()){S.has(N.name)||C.push(F);continue}if(!N.isFile())continue;let I=N.name.lastIndexOf(`.`),H=I>=0?N.name.slice(I):``;if(!OB.has(H)&&!kB.has(N.name))continue;let W=readFileSync(F,`utf-8`),q=W;for(let[t,S]of n)q=q.replaceAll(t,S);q!==W&&writeFileSync(F,q)}}}function printNextSteps(t,n,S,C,N){let F=runScriptCommand(C),I=templateScripts(n),H=startScriptFor(N);ge.log(``),ge.log(`Project created from template "${n.name}", set up for ${N}.`),ge.log(``),ge.log(`Next steps:`),ge.log(` cd ${t}`),S||ge.log(` ${C} install`),N===`gjs`&&I.dev?ge.log(` ${F} dev`):(ge.log(` ${F} build`),ge.log(` ${F} ${H}`)),ge.log(``);let W=supportedRuntimes(n).filter(t=>t!==N&&I[startScriptFor(t)]);if(W.length>0){ge.log(`Also runs on ${W.join(`, `)}:`);for(let t of W)ge.log(` ${F} ${startScriptFor(t)}`);ge.log(``)}I.ship&&(ge.log(`Package it for a machine without gjsify:`),ge.log(` ${F} ship -- darwin`),ge.log(``))}function templateManifest(t){try{return JSON.parse(readFileSync(In(t.path,`package.json`),`utf-8`))}catch{return{}}}function templateScripts(t){let n=templateManifest(t).scripts;return n?Object.fromEntries(Object.entries(n).filter(t=>typeof t[1]==`string`)):{}}function supportedRuntimes(t){let n=templateManifest(t).gjsify?.example?.runtimes;return Array.isArray(n)?n.filter(t=>typeof t==`string`&&packageManagersForRuntime(t)!==void 0):[]}var EB,DB,OB,kB,AB=__esmMin(()=>{_e(),ev(),ef(),qn(),vB(),wB(),TB(),EB=`new-gjsify-app`,DB=`org.gjsify.example`,OB=new Set([`.json`,`.md`,`.ts`,`.tsx`,`.js`,`.mjs`,`.cjs`,`.blp`,`.html`,`.css`,`.scss`,`.xml`,`.ui`,`.txt`,`.svg`]),kB=new Set([`LICENSE`,`LICENCE`,`COPYING`,`NOTICE`])});function isCancelled(t){return t instanceof Error&&t.message===MB}function render(t,n,S){S||vn.write(`\x1b[${t.length}A`);for(let S=0;S<t.length;S++){let C=t[S],N=S===n?`${jB.cyan}❯${jB.reset}`:` `,F=S===n?`${jB.bold}${jB.green}${C.label}${jB.reset}`:C.label,I=C.description?` ${jB.dim}${C.description}${jB.reset}`:``;vn.write(`\x1b[2K\r ${N} ${F}${I}\n`)}}function promptChoice(t,n,S=0){return n.length===0?Promise.reject(Error(`Nothing to choose for "${t}".`)):new Promise((C,N)=>{let F=S>=0&&S<n.length?S:0;vn.write(`${jB.bold}${t}${jB.reset} ${jB.dim}(↑/↓ to navigate, Enter to confirm, Ctrl+C to cancel)${jB.reset}\n`),render(n,F,!0),emitKeypressEvents(yn),yn.isTTY&&yn.setRawMode(!0),yn.resume();let cleanup=()=>{yn.removeListener(`keypress`,onKeypress),yn.isTTY&&yn.setRawMode(!1),yn.pause()},onKeypress=(t,S)=>{if(S){if(S.ctrl&&S.name===`c`){cleanup(),vn.write(`
975
+ `);for(let n of t)ge.error(` ✗ ${n.name}`);let n=buildInstallCommand(detectPackageManager$1(),t);return n&&ge.error(`\nInstall with:\n ${n}`),process.exit(1)}}let C=readCliVersion();if(S!==`gjs`){await runShowcaseOnRuntime(n,S,C);return}let N=C?`${n.packageName}@${C}`:n.packageName;ge.log(`Running showcase: ${n.name} ${runningAs(C)}(via gjsify dlx ${N})\n`);try{let{runCli:t}=await Promise.resolve().then(()=>(aY(),iY));await t([`dlx`,N])}catch(t){ge.error(t.message),process.exit(1)}}}});function resolveTemplatesRoot(){let t=zn(fileURLToPath(import.meta.url)),n=[In(t,`..`,`dist-templates`),In(t,`dist-templates`)];try{let t=createRequire(import.meta.url).resolve(`@gjsify/create-app/package.json`);n.splice(1,0,In(zn(t),`dist-templates`))}catch{}return n.find(t=>existsSync(t))}function discoverTemplates(){let t=resolveTemplatesRoot();if(!t)return[];let n=[];for(let S of readdirSync(t)){let C=In(t,S),N=In(C,`package.json`);if(!statSync(C).isDirectory()||!existsSync(N))continue;let F=_B[S]??``;try{let t=JSON.parse(readFileSync(N,`utf-8`));typeof t.description==`string`&&t.description.trim()&&(F=t.description)}catch{}n.push({name:S,description:F,path:C})}return n.sort((t,n)=>t.name.localeCompare(n.name)),n}function findTemplate(t){return discoverTemplates().find(n=>n.name===t)}var _B,vB=__esmMin(()=>{ef(),Xl(),qn(),ir(),_B={"gtk-minimal":`Minimal GTK4 app — Gtk.ApplicationWindow + Gtk.Label, no Adwaita (Blueprint UI).`,cli:`Command-line tool using yargs (Node.js + GJS).`,"adw-canvas2d":`Adwaita app with HTML Canvas 2D rendering (Blueprint UI).`,"adw-webgl":`Adwaita app with WebGL + three.js (Blueprint UI).`,"adw-game":`Adwaita game shell using Excalibur.js, WebGL → Canvas2D fallback.`,"web-server-hono":`HTTP server using Hono (Web-standard fetch-style API).`,"web-server-express":`HTTP server using Express (familiar Node.js stack).`}});function installCommandLine(t){return[t,...bB[t]].join(` `)}function runScriptCommand(t){return xB[t]}function packageManagersForRuntime(t){return SB[t]}function hostRuntime(){let t=globalThis;return t.Bun===void 0?t.Deno===void 0?t.imports?.gi===void 0?`node`:`gjs`:`deno`:`bun`}function defaultRuntimeFor(t,n){if(n)return t.find(t=>packageManagersForRuntime(t)?.includes(n));let S=hostRuntime();return t.includes(S)?S:t[0]}function startScriptFor(t){return t===`gjs`?`start`:`start:${t}`}var yB,bB,xB,SB,CB,wB=__esmMin(()=>{yB=[`npm`,`yarn`,`pnpm`,`gjsify`,`bun`,`deno`],bB={npm:[`install`,`--no-audit`,`--no-fund`],yarn:[`install`],pnpm:[`install`],gjsify:[`install`],bun:[`install`],deno:[`install`]},xB={npm:`npm run`,yarn:`yarn`,pnpm:`pnpm`,gjsify:`gjsify run`,bun:`bun run`,deno:`deno task`},SB={gjs:[`gjsify`],node:[`npm`,`yarn`,`pnpm`,`gjsify`],bun:[`bun`],deno:[`deno`]},CB={gjs:`GNOME JavaScript — no Node.js needed at runtime.`,node:`Node.js — gi:// via the @gjsify/node-gi bridge.`,bun:`Bun — runs the same --app node bundle.`,deno:`Deno — runs the same --app node bundle.`}});function selectRuntime(t){let{flag:n,offered:S,manager:C,interactive:N}=t;if(n!==void 0)return S.length>0&&!S.includes(n)?{kind:`error`,message:`this template does not run on "${n}". Declared runtimes: ${S.join(`, `)}.`}:{kind:`value`,value:n};if(S.length===1)return{kind:`value`,value:S[0]};if(S.length===0)return{kind:`error`,message:`this template declares no runtime this scaffolder can install for.`};let F=defaultRuntimeFor(S,C);return F===void 0?{kind:`error`,message:`no runtime this template declares installs with "${C}". Declared runtimes: ${S.join(`, `)}.`}:C===void 0?N?{kind:`prompt`,choices:S,initial:F}:{kind:`auto`,value:F,notice:`--runtime not given, using "${F}". Runs on: ${S.join(`, `)}.`}:{kind:`auto`,value:F,notice:`Setting up for ${F} — the runtime ${C} installs for.`}}function selectPackageManager(t){let{flag:n,runtime:S,install:C,interactive:N}=t,F=packageManagersForRuntime(S);return F===void 0||F.length===0?{kind:`error`,message:`no package manager known for runtime "${S}".`}:n===void 0?F.length===1?{kind:`auto`,value:F[0],notice:`Using ${F[0]} — the only package manager that installs for ${S}.`}:N?{kind:`prompt`,choices:F,initial:F[0]}:C?{kind:`error`,message:`--package-manager is required with --install in non-interactive mode. Package managers for ${S}: ${F.join(`, `)}.`}:{kind:`auto`,value:F[0],notice:`--package-manager not given, using "${F[0]}" for ${S}.`}:F.includes(n)?{kind:`value`,value:n}:{kind:`error`,message:`"${n}" cannot install a project you intend to run on ${S}. Package managers for ${S}: ${F.join(`, `)}.`}}var TB=__esmMin(()=>{wB()});function applicationIdFor(t){let n=t.replace(/[^A-Za-z0-9_-]/g,`-`);return`org.gjsify.${/^[0-9]/.test(n)?`app-${n}`:n}`}function sanitizeProjectName(t){let n=t.trim();if(!n)throw Error(`Project name cannot be empty.`);let S=n.toLowerCase().replace(/[^a-z0-9._-]+/g,`-`).replace(/^[._-]+/,``).replace(/[._-]+$/,``);if(!S)throw Error(`"${t}" is not a valid npm package name.`);return S}function isDirEmpty(t){return existsSync(t)?readdirSync(t).length===0:!0}async function createProject(t){let n=sanitizeProjectName(t.projectName),{template:S,force:C=!1,install:N=!1}=t,F=findTemplate(S);if(!F){let t=discoverTemplates().map(t=>t.name).join(`, `);throw Error(`Unknown template "${S}". Available templates: ${t||`(none — run "yarn build" first)`}`)}let I=supportedRuntimes(F),H=t.runtime??defaultRuntimeFor(I,t.packageManager)??hostRuntime(),W=packageManagersForRuntime(H);if(!W)throw Error(`Template "${F.name}" was asked for runtime "${H}", which this version of @gjsify/create-app has no installer mapping for. Upgrade it, or pick one of: ${I.join(`, `)||`(none)`}.`);let q=t.packageManager??W[0];if(!W.includes(q))throw Error(`"${q}" cannot install a project you intend to run on ${H}. Package managers for ${H}: ${W.join(`, `)}.`);let Y=Nn(process.cwd(),n);if(existsSync(Y)&&!isDirEmpty(Y)&&!C)return ge.error(`Error: Directory "${n}" exists and is not empty. Use --force to scaffold into it anyway.`),process.exit(1);if(ge.log(`Creating new Gjsify project in ${Y} (template: ${F.name})...`),mkdirSync(Y,{recursive:!0}),cpSync(F.path,Y,{recursive:!0}),substituteTemplateSentinels(Y,n),N){let t=installCommandLine(q);ge.log(`Running ${t}...`);let n=spawnSync(t,{cwd:Y,stdio:`inherit`,shell:!0});n.error?ge.warn(`${q} install could not start (${n.error.message}); re-run it manually.`):n.status!==0&&ge.warn(`${q} install failed; re-run it manually in the project directory.`)}printNextSteps(n,F,N,q,H)}function substituteTemplateSentinels(t,n){let S=[[EB,n],[DB,applicationIdFor(n)]];renameSentinelPaths(t,S),substituteSentinelContents(t,S)}function renameSentinelPaths(t,n){for(let S of readdirSync(t,{withFileTypes:!0})){let C=S.name;for(let[t,S]of n)C=C.replaceAll(t,S);let N=In(t,S.name),F=In(t,C);F!==N&&renameSync(N,F),S.isDirectory()&&renameSentinelPaths(F,n)}}function substituteSentinelContents(t,n){let S=new Set([`node_modules`,`dist`,`lib`]),C=[t];for(;C.length>0;){let t=C.pop();for(let N of readdirSync(t,{withFileTypes:!0})){let F=In(t,N.name);if(N.isDirectory()){S.has(N.name)||C.push(F);continue}if(!N.isFile())continue;let I=N.name.lastIndexOf(`.`),H=I>=0?N.name.slice(I):``;if(!OB.has(H)&&!kB.has(N.name))continue;let W=readFileSync(F,`utf-8`),q=W;for(let[t,S]of n)q=q.replaceAll(t,S);q!==W&&writeFileSync(F,q)}}}function printNextSteps(t,n,S,C,N){let F=runScriptCommand(C),I=templateScripts(n),H=startScriptFor(N);ge.log(``),ge.log(`Project created from template "${n.name}", set up for ${N}.`),ge.log(``),ge.log(`Next steps:`),ge.log(` cd ${t}`),S||ge.log(` ${C} install`),N===`gjs`&&I.dev?ge.log(` ${F} dev`):(ge.log(` ${F} build`),ge.log(` ${F} ${H}`)),ge.log(``);let W=supportedRuntimes(n).filter(t=>t!==N&&I[startScriptFor(t)]);if(W.length>0){ge.log(`Also runs on ${W.join(`, `)}:`);for(let t of W)ge.log(` ${F} ${startScriptFor(t)}`);ge.log(``)}I.ship&&(ge.log(`Package it for a machine without gjsify:`),ge.log(` ${F} ship -- darwin`),ge.log(``))}function templateManifest(t){try{return JSON.parse(readFileSync(In(t.path,`package.json`),`utf-8`))}catch{return{}}}function templateScripts(t){let n=templateManifest(t).scripts;return n?Object.fromEntries(Object.entries(n).filter(t=>typeof t[1]==`string`)):{}}function supportedRuntimes(t){let n=templateManifest(t).gjsify?.example?.runtimes;return Array.isArray(n)?n.filter(t=>typeof t==`string`&&packageManagersForRuntime(t)!==void 0):[]}var EB,DB,OB,kB,AB=__esmMin(()=>{_e(),ev(),ef(),qn(),vB(),wB(),TB(),EB=`new-gjsify-app`,DB=`org.gjsify.example`,OB=new Set([`.json`,`.md`,`.ts`,`.tsx`,`.js`,`.mjs`,`.cjs`,`.blp`,`.html`,`.css`,`.scss`,`.xml`,`.ui`,`.txt`,`.svg`]),kB=new Set([`LICENSE`,`LICENCE`,`COPYING`,`NOTICE`])});function isCancelled(t){return t instanceof Error&&t.message===MB}function render(t,n,S){S||vn.write(`\x1b[${t.length}A`);for(let S=0;S<t.length;S++){let C=t[S],N=S===n?`${jB.cyan}❯${jB.reset}`:` `,F=S===n?`${jB.bold}${jB.green}${C.label}${jB.reset}`:C.label,I=C.description?` ${jB.dim}${C.description}${jB.reset}`:``;vn.write(`\x1b[2K\r ${N} ${F}${I}\n`)}}function promptChoice(t,n,S=0){return n.length===0?Promise.reject(Error(`Nothing to choose for "${t}".`)):new Promise((C,N)=>{let F=S>=0&&S<n.length?S:0;vn.write(`${jB.bold}${t}${jB.reset} ${jB.dim}(↑/↓ to navigate, Enter to confirm, Ctrl+C to cancel)${jB.reset}\n`),render(n,F,!0),emitKeypressEvents(yn),yn.isTTY&&yn.setRawMode(!0),yn.resume();let cleanup=()=>{yn.removeListener(`keypress`,onKeypress),yn.isTTY&&yn.setRawMode(!1),yn.pause()},onKeypress=(t,S)=>{if(S){if(S.ctrl&&S.name===`c`){cleanup(),vn.write(`
976
976
  `),N(Error(MB));return}S.name===`up`||S.name===`k`?(F=(F-1+n.length)%n.length,render(n,F,!1)):S.name===`down`||S.name===`j`?(F=(F+1)%n.length,render(n,F,!1)):(S.name===`return`||S.name===`enter`)&&(cleanup(),C(n[F].value))}};yn.on(`keypress`,onKeypress)})}function promptTemplate(t){return t.length===0?Promise.reject(Error(`No templates available.`)):promptChoice(`Select a template`,t.map(t=>({value:t,label:t.name,description:t.description})))}function promptRuntime(t,n){return promptChoice(`Select a runtime`,t.map(t=>({value:t,label:t,description:CB[t]??``})),t.indexOf(n))}function promptPackageManager(t,n){return promptChoice(`Select a package manager`,t.map(t=>({value:t,label:t,description:``})),t.indexOf(n))}async function settle(t,n){switch(t.kind){case`value`:return t.value;case`auto`:return ge.error(t.notice),t.value;case`prompt`:try{return await n(t.choices,t.initial)}catch(t){if(!isCancelled(t))throw t;ge.error(`Cancelled.`);return}case`error`:ge.error(`Error: ${t.message}`);return}}async function promptSetup(t){let{offered:n,install:S,interactive:C}=t,N=await settle(selectRuntime({flag:t.runtime,offered:n,manager:t.packageManager,interactive:C}),(t,n)=>promptRuntime(t,n));if(N===void 0)return;let F=await settle(selectPackageManager({flag:t.packageManager,runtime:N,install:S,interactive:C}),(t,n)=>promptPackageManager(t,n));if(F!==void 0)return{runtime:N,packageManager:F}}var jB,MB,NB=__esmMin(()=>{_e(),bn(),Kd(),wB(),TB(),jB={reset:`\x1B[0m`,bold:`\x1B[1m`,dim:`\x1B[2m`,cyan:`\x1B[36m`,green:`\x1B[32m`},MB=`Cancelled by user`}),PB,FB=__esmMin(()=>{_e(),AB(),NB(),PB={command:`create [project-name]`,description:`Scaffold a new Gjsify project in a new directory.`,builder:t=>{let n=discoverTemplates(),S=n.map(t=>t.name),C=[...new Set(n.flatMap(t=>supportedRuntimes(t)))];return t.positional(`project-name`,{describe:`Name of the project directory to create`,type:`string`,default:`my-gjs-app`}).option(`template`,{alias:`t`,describe:`Template to scaffold from`,type:`string`,choices:S.length>0?S:void 0}).option(`runtime`,{alias:`r`,describe:`Runtime to set the project up for. Decides which package managers are offered and which start script the next steps name.`,type:`string`,choices:C.length>0?C:void 0}).option(`force`,{alias:`f`,describe:`Scaffold into a non-empty directory`,type:`boolean`,default:!1}).option(`install`,{describe:`Install dependencies after scaffolding`,type:`boolean`,default:!1}).option(`package-manager`,{alias:`p`,describe:"Package manager to install with, and to name in the printed next steps. Must be one the chosen runtime can install for. `gjsify` is the only one that works on a host with no Node.js.",type:`string`,choices:yB})},handler:async t=>{let n=!!process.stdin.isTTY,S=discoverTemplates(),C=t.template;if(!C){if(!n){let t=S.map(t=>t.name).join(`, `);return ge.error(`Error: --template is required in non-interactive mode. Available templates: ${t||`(none)`}`),process.exit(1)}let t=await promptTemplate(S).catch(t=>{if(!isCancelled(t))throw t;ge.error(`Cancelled.`)});if(t===void 0)return process.exit(1);C=t.name}let N=S.find(t=>t.name===C),F=await promptSetup({offered:N?supportedRuntimes(N):[],runtime:t.runtime,packageManager:t[`package-manager`],install:t.install,interactive:n});if(F===void 0)return process.exit(1);await createProject({projectName:t[`project-name`],template:C,runtime:F.runtime,force:t.force,install:t.install,packageManager:F.packageManager})}}});function defaultTargetFor(t){let n=Bn(t,Vn(t));return Nn(zn(t),n)}var IB,LB,RB=__esmMin(()=>{_e(),ev(),Ld(),qn(),zu(),IB=promisify(execFile),LB={command:`gresource <xml>`,description:"Compile a GResource XML descriptor into a binary .gresource bundle (wraps `glib-compile-resources`).",builder:t=>t.positional(`xml`,{description:`Path to the .gresource.xml descriptor`,type:`string`,normalize:!0,demandOption:!0}).option(`sourcedir`,{description:`Directory containing the resource files referenced by <xml>`,type:`string`,normalize:!0}).option(`target`,{alias:`t`,description:`Output .gresource file (default: <xml-without-.xml> next to <xml>)`,type:`string`,normalize:!0}).option(`verbose`,{description:`Print the underlying glib-compile-resources invocation`,type:`boolean`,default:!1}),handler:async t=>{let n=Nn(t.xml),S=t.target?Nn(t.target):defaultTargetFor(n),C=[`--sourcedir=${t.sourcedir?Nn(t.sourcedir):zn(n)}`,`--target=${S}`,n];t.verbose&&ge.log(`[gjsify gresource] glib-compile-resources ${C.join(` `)}`),await mkdir$1(zn(S),{recursive:!0});try{let{stdout:n,stderr:N}=await IB(`glib-compile-resources`,C);n&&process.stdout.write(n),N&&process.stderr.write(N),t.verbose&&ge.log(`[gjsify gresource] wrote ${S}`)}catch(t){let n=t;n?.code===`ENOENT`?ge.error(`[gjsify gresource] glib-compile-resources not found. Install it via your distro (package: glib2-devel / libglib2.0-dev).`):(n?.stderr&&process.stderr.write(n.stderr),ge.error(`[gjsify gresource] glib-compile-resources failed${n?.code===void 0?``:` (exit ${n.code})`}`)),process.exitCode=typeof n?.code==`number`?n.code:1}}}});function mergeCatalogues(t){let n=t.template,S=new Set;for(let{locale:n}of t.catalogues){if(S.has(n))throw Error(`mergeCatalogues: two catalogues both claim locale "${n}". msgfmt APPENDS each --locale, so the chain would emit a duplicate key (desktop-file-validate: "multiple keys named Name[${n}]"; appstreamcli: "tag-duplicated") from two exit-0 calls. Merge them into one .po first (msgcat --use-first) and pass that.`);S.add(n)}for(let[S,C]of t.catalogues.entries()){let N=In(t.workDir,`${S}${t.extension}`),F=[t.mode,`--template=${n}`,`--locale=${C.locale}`,`--output-file=${N}`,C.po];t.onCall?.(F),execFileSync(`msgfmt`,F,{stdio:`pipe`}),n=N}return n}var zB=__esmMin(()=>{ev(),qn()});async function listLanguages(t){return(await readdir$1(t)).filter(t=>t.endsWith(`.po`)&&!t.startsWith(`.`)).map(t=>t.slice(0,-3)).sort()}function stripXmlComments(t){return t.replace(/<!--[\s\S]*?-->/g,``)}async function ensureDir(t){await mkdir$1(t,{recursive:!0})}async function fileExists(t){try{return await stat$1(t),!0}catch{return!1}}async function compileMerged(t){let n=await listLanguages(t.poDir);if(n.length===0){ge.warn(`[gjsify gettext] no .po files found in ${t.poDir}`);return}let S=In(t.outDir,t.filename);await ensureDir(t.outDir);let C=await mkdtemp$1(In(tmpdir(),`gjsify-gettext-`));try{let N=await readFile$1(mergeCatalogues({mode:`--${t.format}`,template:t.template,extension:`-${Bn(t.template).replace(/\.in$/,``)}`,catalogues:n.map(n=>({locale:n,po:In(t.poDir,`${n}.po`)})),workDir:C,onCall:t.verbose?t=>ge.log(`[gjsify gettext] msgfmt ${t.join(` `)}`):void 0}),`utf-8`);await writeFile$1(S,t.removeXmlComments&&t.format===`xml`?stripXmlComments(N):N)}finally{await rm$1(C,{recursive:!0,force:!0})}t.verbose&&ge.log(`[gjsify gettext] merged ${n.length} language(s) into ${S}`)}async function compileCatalogues(t){let n=await listLanguages(t.poDir);if(n.length===0){ge.warn(`[gjsify gettext] no .po files found in ${t.poDir}`);return}for(let S of n){let n=In(t.outDir,S,`LC_MESSAGES`);await ensureDir(n);let C=[`--output-file=${In(n,t.filename)}`,In(t.poDir,`${S}.po`)];t.verbose&&ge.log(`[gjsify gettext] msgfmt ${C.join(` `)}`),await BB(`msgfmt`,C)}t.verbose&&ge.log(`[gjsify gettext] compiled ${n.length} language(s) into ${t.outDir}`)}function defaultFilename(t,n,S){switch(n){case`mo`:return`${t}.mo`;case`desktop`:return`${t}.desktop`;case`xml`:return S?Bn(S.replace(/\.in$/,``)):`${t}.xml`}}var BB,VB,HB=__esmMin(()=>{_e(),ev(),Ld(),$g(),qn(),zu(),zB(),BB=promisify(execFile),VB={command:`gettext <poDir> <outDir>`,description:`Compile gettext .po files to .mo (per-language locale tree), or merge every catalogue into a .desktop / AppStream template via msgfmt --desktop / --xml.`,builder:t=>t.positional(`poDir`,{description:`Directory containing <lang>.po files`,type:`string`,normalize:!0,demandOption:!0}).positional(`outDir`,{description:`Output directory (locale tree for --format=mo, plain dir for xml/desktop)`,type:`string`,normalize:!0,demandOption:!0}).option(`domain`,{description:"Text domain / application ID (e.g. `org.pixelrpg.maker`)",type:`string`,normalize:!0,demandOption:!0}).option(`format`,{description:`Output format`,type:`string`,choices:[`mo`,`xml`,`desktop`],default:`mo`}).option(`template`,{description:"Required for --format=xml|desktop: the file msgfmt substitutes into. Its SUFFIX matters — msgfmt --xml finds its ITS rules by filename pattern, so an AppStream template must be named `*.metainfo.xml[.in]`.",type:`string`,normalize:!0}).option(`metainfo`,{description:`Deprecated alias for --template.`,type:`string`,normalize:!0,hidden:!0}).option(`filename`,{description:`Override the output filename (defaults to <domain>.<ext>)`,type:`string`,normalize:!0}).option(`remove-xml-comments`,{description:`For --format=xml: strip XML comments from the compiled output`,type:`boolean`,default:!0}).option(`verbose`,{description:`Print each msgfmt invocation`,type:`boolean`,default:!1}),handler:async t=>{let n=Nn(t.poDir),S=Nn(t.outDir),C=t.domain,N=t.format??`mo`,F=t.template??t.metainfo,I=F?Nn(F):void 0,H=t.filename??defaultFilename(C,N,I),W=!!t.verbose,q=!!t[`remove-xml-comments`];if(!await fileExists(n)){ge.error(`[gjsify gettext] PO directory does not exist: ${n}`),process.exitCode=1;return}if(N!==`mo`&&I===void 0){ge.error(`[gjsify gettext] --format=${N} needs a template to substitute into: pass \`--template <file>\`. msgfmt has no way to produce this format from .po files alone.`+(N===`xml`?" Name it `*.metainfo.xml[.in]` — msgfmt --xml finds its ITS rules by filename pattern.":``)),process.exitCode=1;return}try{N===`mo`?await compileCatalogues({poDir:n,outDir:S,filename:H,verbose:W}):await compileMerged({poDir:n,outDir:S,format:N,template:I,filename:H,removeXmlComments:q,verbose:W})}catch(t){let n=t;n?.code===`ENOENT`?ge.error(`[gjsify gettext] msgfmt not found. Install it via your distro (package: gettext).`):(n?.stderr&&process.stderr.write(n.stderr),ge.error(`[gjsify gettext] msgfmt failed${n?.code===void 0?``:` (exit ${n.code})`}`)),process.exitCode=typeof n?.code==`number`?n.code:1}}}}),UB,WB,GB=__esmMin(()=>{_e(),ev(),Ld(),qn(),zu(),UB=promisify(execFile),WB={command:`gsettings <schemadir>`,description:"Compile GSettings schema XML files into a binary gschemas.compiled (wraps `glib-compile-schemas`).",builder:t=>t.positional(`schemadir`,{description:`Directory containing *.gschema.xml descriptors`,type:`string`,normalize:!0,demandOption:!0}).option(`targetdir`,{alias:`t`,description:`Directory to write gschemas.compiled (default: <schemadir>)`,type:`string`,normalize:!0}).option(`strict`,{description:`Abort on any schema warning (passes --strict to glib-compile-schemas)`,type:`boolean`,default:!0}).option(`verbose`,{description:`Print the underlying glib-compile-schemas invocation`,type:`boolean`,default:!1}),handler:async t=>{let n=Nn(t.schemadir),S=t.targetdir?Nn(t.targetdir):n,C=[];t.strict&&C.push(`--strict`),C.push(`--targetdir=${S}`),C.push(n),t.verbose&&ge.log(`[gjsify gsettings] glib-compile-schemas ${C.join(` `)}`),await mkdir$1(S,{recursive:!0});try{let{stdout:n,stderr:N}=await UB(`glib-compile-schemas`,C);n&&process.stdout.write(n),N&&process.stderr.write(N),t.verbose&&ge.log(`[gjsify gsettings] wrote ${S}/gschemas.compiled`)}catch(t){let n=t;n?.code===`ENOENT`?ge.error(`[gjsify gsettings] glib-compile-schemas not found. Install it via your distro (package: glib2-devel / libglib2.0-dev).`):(n?.stderr&&process.stderr.write(n.stderr),ge.error(`[gjsify gsettings] glib-compile-schemas failed${n?.code===void 0?``:` (exit ${n.code})`}`)),process.exitCode=typeof n?.code==`number`?n.code:1}}}});function readPackageJson(t){let n=Nn(t,`package.json`),S;try{S=readFileSync(n,`utf-8`)}catch{throw Error(`gjsify flatpak: no package.json found at ${n}`)}try{return JSON.parse(S)}catch(t){throw Error(`gjsify flatpak: package.json at ${n} is not valid JSON: ${t.message}`)}}function looksLikeAppId(t){return typeof t==`string`&&/^[A-Za-z][A-Za-z0-9_-]*(\.[A-Za-z][A-Za-z0-9_-]*){2,}$/.test(t)}function defaultCiContainer(t,n){return`ghcr.io/flathub-infra/flatpak-github-actions:${`${t}-${n}`}`}var KB,qB=__esmMin(()=>{ef(),qn(),KB=`gjsify-sources.json`});function resolveRuntime(t,n){let S=n.runtime??t?.runtime??`gnome`;if(S!==`gnome`&&S!==`freedesktop`)throw Error(`gjsify flatpak: unknown runtime "${S}" (expected "gnome" or "freedesktop")`);let C=n.runtimeVersion??t?.runtimeVersion??(S===`gnome`?`51`:`24.08`);return S===`gnome`?{runtime:S,runtimeId:`org.gnome.Platform`,sdk:`org.gnome.Sdk`,runtimeVersion:C}:{runtime:S,runtimeId:`org.freedesktop.Platform`,sdk:`org.freedesktop.Sdk`,runtimeVersion:C}}function deriveAppendPath(t){let n=[];for(let S of t){let t=/^org\.freedesktop\.Sdk\.Extension\.([A-Za-z0-9-]+)$/.exec(S);t&&n.push(`/usr/lib/sdk/${t[1]}/bin`)}return n.push(`/app/bin`),n}var JB,YB,XB=__esmMin(()=>{JB=[`--device=dri`,`--share=ipc`,`--socket=fallback-x11`,`--socket=wayland`],YB=[]});function pickFlatpakBuildKeys(t,n){let S=t??{},C={},N=[];for(let t of QB){let F=S[t];if(F!==void 0){C[t]=F;continue}let I=n[t];I!==void 0&&N.push(t),C[t]=I}return{values:C,fromLegacy:N}}function resolveShipFlatpakSettings(t){let n=t.ship.flatpak??{},{values:S,fromLegacy:C}=pickFlatpakBuildKeys(n,t.flatpak),N=resolveRuntime(S,{}),F=S.sdkExtensions??[],{appendPath:I,finishArgs:H,cleanup:W}=S;return{settings:{runtime:N.runtimeId,runtimeVersion:N.runtimeVersion,sdk:N.sdk,branch:n.branch??`stable`,sdkExtensions:[...F],appendPath:I??(F.length>0?deriveAppendPath(F):[]),finishArgs:H??(t.kind===`cli`?YB:JB),cleanup:[...new Set([...W??[],...t.kind===`app`?[$B]:[]])]},warnings:C.length===0?[]:[deprecationWarning(C)]}}function assertNoDroppedFlatpakModules(t){let n=[`modules`,`extraModules`].filter(n=>(t[n]?.length??0)>0);if(n.length===0)return;let S=n.map(t=>`gjsify.flatpak.${t}`).join(` and `);throw Error(`gjsify ship: ${S} ${n.length>1?`are`:`is`} set, but the \`flatpak\` target renders ONE module, the staged payload, and would drop ${n.length>1?`them`:`it`} (ADR 0024 § 2). Build this Flatpak with \`gjsify flatpak init\` + \`gjsify flatpak build\`, which honour the key, or leave \`flatpak\` out of \`--target\` / \`gjsify.ship.targets\`.`)}function deprecationWarning(t){let n=t.map(t=>`gjsify.flatpak.${t}`).join(`, `),S=t.map(t=>`gjsify.ship.flatpak.${t}`).join(`, `);return`DEPRECATION: ${n} ${t.length>1?`are`:`is`} read by \`gjsify ship\` for compatibility and will be removed in ${ZB}. Move ${t.length>1?`them`:`it`} to ${S} — both spellings resolve until then, and \`gjsify.ship.flatpak\` wins where both are set. The app METADATA in \`gjsify.flatpak\` (name, summary, developer, categories, licence) is NOT deprecated: both blocks describe the same application and either may carry it (ADR 0024 § 8).`}var ZB,QB,$B,eV=__esmMin(()=>{XB(),ZB=`1.0.0`,QB=[`runtime`,`runtimeVersion`,`sdkExtensions`,`appendPath`,`finishArgs`,`cleanup`],$B=`/share/icons/hicolor/scalable`});function loadDesktopTemplate(){return tV}function validateAppMetadata(t){let n=t.metadata,S=t.configKey,C=[];return(!n.developer?.id||!n.developer?.name)&&C.push({field:`${S}.developer`,hint:`Set \`${S}.developer = { "id": "io.github.you", "name": "Your Name" }\` in package.json. The id is reverse-DNS.`}),n.summary||C.push({field:`${S}.summary`,hint:`One-line app summary, ≤80 chars, no trailing period. Example: "Learn 6502 assembly language".`}),n.description||C.push({field:`${S}.description`,hint:`Plain text (split on blank lines) or DescriptionBlock[] for rich content with bullet lists + translator hints.`}),n.license?.project||C.push({field:`${S}.license.project`,hint:`SPDX identifier of the project license, e.g. "MIT", "GPL-3.0-or-later".`}),n.homepageUrl||C.push({field:`${S}.homepageUrl`,hint:`Required by Flathub. Example: "https://github.com/you/your-repo".`}),C}function renderMetainfoApp$1(t){return renderMetainfo(t,`desktop-application`)}function renderMetainfoCli$1(t){return renderMetainfo(t,`console-application`)}function renderDesktopEntry(t){let n=t.metadata,S=(n.categories??[`Utility`]).join(`;`)+`;`,C=n.keywords?.length?`Keywords=${n.keywords.join(`;`)};\n`:``,N=n.provides?.mimetypes??[],F=N.length?`MimeType=${N.join(`;`)};\n`:``;return substitute(loadDesktopTemplate(),{NAME:t.name,SUMMARY:n.summary??t.name,COMMAND:`${t.command}${execFieldCode(N)}`,APP_ID:t.appId,CATEGORIES_LINE:S,KEYWORDS_LINE:C,MIMETYPES_LINE:F})}function execFieldCode(t){return t.some(t=>t.startsWith(`x-scheme-handler/`))?` %u`:t.length>0?` %f`:``}function renderMetainfo(t,n){let S=t.metadata,C=t.copyrightYear??new Date().getFullYear(),N=S.developer?.name??``,F=[];F.push(`<?xml version="1.0" encoding="UTF-8"?>`),F.push(`<!-- Copyright ${C} ${escapeXml(N)} -->`),F.push(`<component type="${n}">`),F.push(` <id>${escapeXml(t.appId)}</id>`),F.push(` <metadata_license>${escapeXml(S.license?.metadata??`CC0-1.0`)}</metadata_license>`),F.push(` <project_license>${escapeXml(S.license?.project??``)}</project_license>`),F.push(` <name>${escapeXml(t.name)}</name>`),pushTranslatorHint(F,S.summaryTranslatorHint,` `),F.push(` <summary>${escapeXml(S.summary??t.name)}</summary>`),S.iconRemote&&F.push(` <icon type="remote">${escapeXml(S.iconRemote)}</icon>`),F.push(` <description>`);for(let t of renderDescriptionBlocks(S.description??``,` `))F.push(t);if(F.push(` </description>`),S.developer?.id&&S.developer?.name){F.push(` <developer id="${escapeXml(S.developer.id)}">`);let t=S.developer.nameTranslatable===!0?``:` translate="no"`;F.push(` <name${t}>${escapeXml(S.developer.name)}</name>`),S.developer.email&&F.push(` <email>${escapeXml(S.developer.email)}</email>`),F.push(` </developer>`)}n===`desktop-application`&&F.push(` <launchable type="desktop-id">${escapeXml(t.appId)}.desktop</launchable>`),S.screenshots?.length&&(F.push(` <screenshots>`),S.screenshots.forEach((t,n)=>{let S=t.type??(n===0?`default`:void 0),C=S?` type="${escapeXml(S)}"`:``,N=t.environment?` environment="${escapeXml(t.environment)}"`:``;F.push(` <screenshot${C}${N}>`),F.push(` <image>${escapeXml(t.url)}</image>`);for(let[n,S]of Object.entries(t.localizedUrls??{}))F.push(` <image xml:lang="${escapeXml(n)}">${escapeXml(S)}</image>`);t.caption&&(pushTranslatorHint(F,t.captionTranslatorHint,` `),F.push(` <caption>${escapeXml(t.caption)}</caption>`)),F.push(` </screenshot>`)}),F.push(` </screenshots>`)),S.homepageUrl&&F.push(` <url type="homepage">${escapeXml(S.homepageUrl)}</url>`),S.bugtrackerUrl&&F.push(` <url type="bugtracker">${escapeXml(S.bugtrackerUrl)}</url>`),S.vcsBrowserUrl&&F.push(` <url type="vcs-browser">${escapeXml(S.vcsBrowserUrl)}</url>`),S.donationUrl&&channelAllowsDonations(t.channel)&&F.push(` <url type="donation">${escapeXml(S.donationUrl)}</url>`),S.translateUrl&&F.push(` <url type="translate">${escapeXml(S.translateUrl)}</url>`);let I=normaliseContentRating(S.contentRating);if(I.attributes&&Object.keys(I.attributes).length>0){F.push(` <content_rating type="${escapeXml(I.type)}">`);for(let[t,n]of Object.entries(I.attributes))F.push(` <content_attribute id="${escapeXml(t)}">${escapeXml(n)}</content_attribute>`);F.push(` </content_rating>`)}else F.push(` <content_rating type="${escapeXml(I.type)}" />`);if(S.releases?.length){F.push(` <releases>`);for(let t of S.releases)if(t.description===void 0)F.push(` <release version="${escapeXml(t.version)}" date="${escapeXml(t.date)}" />`);else{F.push(` <release version="${escapeXml(t.version)}" date="${escapeXml(t.date)}">`),F.push(` <description>`);for(let n of renderDescriptionBlocks(t.description,` `))F.push(n);F.push(` </description>`),F.push(` </release>`)}F.push(` </releases>`)}if(S.categories?.length){F.push(` <categories>`);for(let t of S.categories)F.push(` <category>${escapeXml(t)}</category>`);F.push(` </categories>`)}if(S.keywords?.length){F.push(` <keywords>`);for(let t of S.keywords)F.push(` <keyword>${escapeXml(t)}</keyword>`);F.push(` </keywords>`)}if(n===`desktop-application`&&S.branding&&(F.push(` <branding>`),F.push(` <color type="primary" scheme_preference="light">${escapeXml(S.branding.accentLight)}</color>`),F.push(` <color type="primary" scheme_preference="dark">${escapeXml(S.branding.accentDark)}</color>`),F.push(` </branding>`)),S.kudos?.length){F.push(` <kudos>`);for(let t of S.kudos)F.push(` <kudo>${escapeXml(t)}</kudo>`);F.push(` </kudos>`)}let H=S.provides?.binaries??[t.command],W=S.provides?.mimetypes??[],q=S.provides?.dbus??[];if(H.length||W.length||q.length){F.push(` <provides>`);for(let t of H)F.push(` <binary>${escapeXml(t)}</binary>`);for(let t of W)F.push(` <mediatype>${escapeXml(t)}</mediatype>`);for(let t of q)F.push(` <dbus type="${escapeXml(t.type)}">${escapeXml(t.id)}</dbus>`);F.push(` </provides>`)}if(S.supports?.controls?.length||S.supports?.internet){F.push(` <supports>`);for(let t of S.supports.controls??[])F.push(` <control>${escapeXml(t)}</control>`);S.supports.internet&&F.push(` <internet>${escapeXml(S.supports.internet)}</internet>`),F.push(` </supports>`)}if(S.requires?.displayLengthMin||S.requires?.controls?.length||S.requires?.internet){F.push(` <requires>`),S.requires.displayLengthMin&&F.push(` <display_length compare="ge">${S.requires.displayLengthMin}</display_length>`);for(let t of S.requires.controls??[])F.push(` <control>${escapeXml(t)}</control>`);S.requires.internet&&F.push(` <internet>${escapeXml(S.requires.internet)}</internet>`),F.push(` </requires>`)}if(S.recommends?.displayLengthMin||S.recommends?.controls?.length){F.push(` <recommends>`),S.recommends.displayLengthMin&&F.push(` <display_length compare="ge">${S.recommends.displayLengthMin}</display_length>`);for(let t of S.recommends.controls??[])F.push(` <control>${escapeXml(t)}</control>`);F.push(` </recommends>`)}return F.push(`</component>`),F.join(`
977
977
  `)+`
978
978
  `}function renderDescriptionBlocks(t,n){let S=typeof t==`string`?stringToBlocks(t):t,C=[];for(let t of S)if(`p`in t)pushTranslatorHint(C,t.translatorHint,n),C.push(`${n}<p>${escapeXml(t.p.trim().replace(/\s+/g,` `))}</p>`);else{pushTranslatorHint(C,t.translatorHint,n),C.push(`${n}<ul>`);for(let S of t.ul)typeof S==`string`?C.push(`${n} <li>${escapeXml(S)}</li>`):(pushTranslatorHint(C,S.translatorHint,`${n} `),C.push(`${n} <li>${escapeXml(S.item)}</li>`));C.push(`${n}</ul>`)}return C}function stringToBlocks(t){return t.trim().split(/\n\n+/).map(t=>({p:t.trim().replace(/\s+/g,` `)}))}function pushTranslatorHint(t,n,S){n&&t.push(`${S}<!-- TRANSLATORS: ${n} -->`)}function normaliseContentRating(t){return t===void 0?{type:`oars-1.1`}:typeof t==`string`?{type:t}:{type:t.type??`oars-1.1`,attributes:t.attributes}}function substitute(t,n){let S=t;for(let[t,C]of Object.entries(n))S=S.split(`{{${t}}}`).join(C);return S}function escapeXml(t){return t.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`)}var tV,nV=__esmMin(()=>{Th(),tV=`[Desktop Entry]
@@ -989,7 +989,7 @@ StartupWMClass={{APP_ID}}
989
989
  `}function loadFlathubCliTemplate(){return`{
990
990
  "skip-icons-check": true
991
991
  }
992
- `}function toMetadataInputs(t){return{appId:t.appId,name:t.name,command:t.command,kind:t.kind,metadata:t.flatpak,channel:`flathub`,configKey:`gjsify.flatpak`}}function validateScaffoldInputs(t){return validateAppMetadata(toMetadataInputs(t))}function renderMetainfoApp(t){return renderMetainfoApp$1(toMetadataInputs(t))}function renderMetainfoCli(t){return renderMetainfoCli$1(toMetadataInputs(t))}function renderDesktop(t){return renderDesktopEntry(toMetadataInputs(t))}function renderFlathubJson(t){return t===`cli`?loadFlathubCliTemplate():loadFlathubAppTemplate()}var rV=__esmMin(()=>{nV()});function oxcBindingSuffix(){let t=process.platform,n=process.arch,S;if(t===`linux`)S=`linux`;else if(t===`darwin`)S=`darwin`;else if(t===`win32`)S=`win32`;else throw Error(`[gjsify oxc] Unsupported platform: ${t}`);let C;if(n===`x64`)C=`x64`;else if(n===`arm64`)C=`arm64`;else throw Error(`[gjsify oxc] Unsupported arch on ${S}: ${n}`);if(S===`linux`){let t=hostLibc(`linux`)===`musl`?`musl`:`gnu`;return`${S}-${C}-${t}`}return S===`win32`?`${S}-${C}-msvc`:`${S}-${C}`}function bindingPackageName(t){return`${t===`oxlint`?`@oxlint`:`@oxfmt`}/binding-${oxcBindingSuffix()}`}function probeNodeModules(t,n,S){let C=In(t,`node_modules`,n,S);return existsSync(C)?C:null}function findOxcLauncher(t,n=process.cwd()){let S=In(`bin`,t),C=probeNodeModules(n,t,S);if(C)return C;let N=findWorkspaceRoot(n);if(N&&N!==n){let n=probeNodeModules(N,t,S);if(n)return n}let F=Nn(n,`..`);for(let n=0;n<6;n++){let n=probeNodeModules(F,t,S);if(n)return n;let C=Nn(F,`..`);if(C===F)break;F=C}throw new OxcNotFoundError(t,n)}function findOxlintConfig(t=process.cwd()){return findConfigFile(t,[`.oxlintrc.json`])}function findOxfmtConfig(t=process.cwd()){return findConfigFile(t,[`.oxfmtrc`,`.oxfmtrc.json`])}function findConfigFile(t,n){let S=t;for(let t=0;t<12;t++){for(let t of n){let n=In(S,t);if(existsSync(n))return n}let t=Nn(S,`..`);if(t===S)break;S=t}return null}async function tryLoadNativeOxfmt(){return iV||(iV=(async()=>{if(!isGjs())return null;try{activateNativePrebuilds();let t=`@gjsify/oxfmt-native`,n=await import(pathToFileURL(resolveNpmPackage(t,{bundleUrl:import.meta.url})??createRequire(import.meta.url).resolve(t)).href);if(!n.hasNativeOxfmt())return null;let S;try{let t=pathToFileURL(resolveNpmPackage(`@gjsify/utils/native-library`,{bundleUrl:import.meta.url})??createRequire(import.meta.url).resolve(`@gjsify/utils/native-library`)).href;({openNativeLibrary:S}=await import(t))}catch(t){return aV=t instanceof Error?t:Error(String(t)),null}return aV=S(`GjsifyOxfmt`),aV?null:n}catch{return null}})(),iV)}async function shouldUseNativeOxfmt(){let t=(globalThis.process?.env??{}).GJSIFY_OXFMT;if(t===`npm`)return!1;if(t===`native`){if(!await tryLoadNativeOxfmt())throw Error(`GJSIFY_OXFMT=native but @gjsify/oxfmt-native is not loadable (no prebuild for this architecture, or not running under GJS).`+(aV?`\n${aV.message}`:``));return!0}if(!isGjs())return!1;let n=await tryLoadNativeOxfmt()!==null;return!n&&aV&&ge.debug(aV.message),n}async function runOxc(t,n,S={}){if(t===`oxfmt`&&await shouldUseNativeOxfmt()){let t=await tryLoadNativeOxfmt();if(!t)throw Error(`@gjsify/oxfmt-native not loadable`);return S.verbose&&ge.log(`[gjsify oxc] @gjsify/oxfmt-native (in-process) ${n.join(` `)}`),t.runOxfmt(n)}return spawnOxcLauncher(t,n,S)}function spawnOxcLauncher(t,n,S={}){let C=S.cwd??process.cwd(),N=findOxcLauncher(t,C),F=nodeBinary();return S.verbose&&ge.log(`[gjsify oxc] ${F} ${N} ${n.join(` `)}`),spawnToCompletion(F,[N,...n],{completion:`return`,cwd:C,notFound:()=>new OxcNotFoundError(t,C,F)}).then(({code:n,signal:S})=>S===null?n??0:(ge.error(`[gjsify oxc] ${t} terminated by signal ${S}`),1))}function runOxlint(t,n={}){return runOxc(`oxlint`,t,n)}function runOxfmt(t,n={}){return runOxc(`oxfmt`,t,n)}function loadOxlintTemplate(){return`{
992
+ `}function toMetadataInputs(t){return{appId:t.appId,name:t.name,command:t.command,kind:t.kind,metadata:t.flatpak,channel:`flathub`,configKey:`gjsify.flatpak`}}function validateScaffoldInputs(t){return validateAppMetadata(toMetadataInputs(t))}function renderMetainfoApp(t){return renderMetainfoApp$1(toMetadataInputs(t))}function renderMetainfoCli(t){return renderMetainfoCli$1(toMetadataInputs(t))}function renderDesktop(t){return renderDesktopEntry(toMetadataInputs(t))}function renderFlathubJson(t){return t===`cli`?loadFlathubCliTemplate():loadFlathubAppTemplate()}var rV=__esmMin(()=>{nV()});function oxcBindingSuffix(){let t=process.platform,n=process.arch,S;if(t===`linux`)S=`linux`;else if(t===`darwin`)S=`darwin`;else if(t===`win32`)S=`win32`;else throw Error(`[gjsify oxc] Unsupported platform: ${t}`);let C;if(n===`x64`)C=`x64`;else if(n===`arm64`)C=`arm64`;else throw Error(`[gjsify oxc] Unsupported arch on ${S}: ${n}`);if(S===`linux`){let t=hostLibc(`linux`)===`musl`?`musl`:`gnu`;return`${S}-${C}-${t}`}return S===`win32`?`${S}-${C}-msvc`:`${S}-${C}`}function bindingPackageName(t){return`${t===`oxlint`?`@oxlint`:`@oxfmt`}/binding-${oxcBindingSuffix()}`}function probeNodeModules(t,n,S){let C=In(t,`node_modules`,n,S);return existsSync(C)?C:null}function findOxcLauncher(t,n=process.cwd()){let S=In(`bin`,t),C=probeNodeModules(n,t,S);if(C)return C;let N=findWorkspaceRoot(n);if(N&&N!==n){let n=probeNodeModules(N,t,S);if(n)return n}let F=Nn(n,`..`);for(let n=0;n<6;n++){let n=probeNodeModules(F,t,S);if(n)return n;let C=Nn(F,`..`);if(C===F)break;F=C}throw new OxcNotFoundError(t,n)}function findOxlintConfig(t=process.cwd()){return findConfigFile(t,[`.oxlintrc.json`])}function findOxfmtConfig(t=process.cwd()){return findConfigFile(t,[`.oxfmtrc`,`.oxfmtrc.json`])}function findConfigFile(t,n){let S=t;for(let t=0;t<12;t++){for(let t of n){let n=In(S,t);if(existsSync(n))return n}let t=Nn(S,`..`);if(t===S)break;S=t}return null}async function tryLoadNativeOxfmt(){return iV||(iV=(async()=>{if(!isGjs())return null;try{activateNativePrebuilds();let t=`@gjsify/oxfmt-native`,n=await import(pathToFileURL(resolveNpmPackage(t,{bundleUrl:import.meta.url})??createRequire(import.meta.url).resolve(t)).href);if(!n.hasNativeOxfmt())return null;let S;try{let t=pathToFileURL(resolveNpmPackage(`@gjsify/utils/native-library`,{bundleUrl:import.meta.url})??createRequire(import.meta.url).resolve(`@gjsify/utils/native-library`)).href;({openNativeLibrary:S}=await import(t))}catch(t){return aV=t instanceof Error?t:Error(String(t)),null}return aV=S(`GjsifyOxfmt`),aV?null:n}catch{return null}})(),iV)}function decideOxfmtEngine(t){let{isGjs:n,nativeLoadable:S,embeddedVersion:C,projectVersion:N,override:F}=t,I=C!==void 0&&N!==void 0&&normalizeVersion(C)!==normalizeVersion(N);return F===`npm`?{engine:`npm`}:F===`native`?S?I?{engine:`native`,warning:`GJSIFY_OXFMT=native: @gjsify/oxfmt-native embeds oxfmt ${C} but this project pins oxfmt ${N}; output can differ from the project's own oxfmt (and from CI).`}:{engine:`native`}:{engine:`native`,error:`GJSIFY_OXFMT=native but @gjsify/oxfmt-native is not loadable (no prebuild for this architecture, or not running under GJS).`}:!n||!S?{engine:`npm`}:{engine:I?`npm`:`native`}}function findProjectOxfmtVersion(t=process.cwd()){try{let n=findOxcLauncher(`oxfmt`,t),S=JSON.parse(readFileSync(In(zn(n),`..`,`package.json`),`utf-8`));return typeof S?.version==`string`?S.version:void 0}catch{return}}async function shouldUseNativeOxfmt(t=process.cwd()){let n=(globalThis.process?.env??{}).GJSIFY_OXFMT;if(n===`npm`||!isGjs()&&n!==`native`)return!1;let S=await tryLoadNativeOxfmt(),C=decideOxfmtEngine({isGjs:isGjs(),nativeLoadable:S!==null,embeddedVersion:S?.EMBEDDED_OXFMT_VERSION,projectVersion:findProjectOxfmtVersion(t),override:n});if(C.error)throw Error(C.error+(aV?`\n${aV.message}`:``));return C.warning&&!oV&&(oV=!0,ge.warn(`[gjsify oxc] ${C.warning}`)),!S&&aV&&C.engine===`npm`&&ge.debug(aV.message),C.engine===`native`}async function runOxc(t,n,S={}){if(t===`oxfmt`&&await shouldUseNativeOxfmt()){let t=await tryLoadNativeOxfmt();if(!t)throw Error(`@gjsify/oxfmt-native not loadable`);return S.verbose&&ge.log(`[gjsify oxc] @gjsify/oxfmt-native (in-process) ${n.join(` `)}`),t.runOxfmt(n)}return spawnOxcLauncher(t,n,S)}function spawnOxcLauncher(t,n,S={}){let C=S.cwd??process.cwd(),N=findOxcLauncher(t,C),F=nodeBinary();return S.verbose&&ge.log(`[gjsify oxc] ${F} ${N} ${n.join(` `)}`),spawnToCompletion(F,[N,...n],{completion:`return`,cwd:C,notFound:()=>new OxcNotFoundError(t,C,F)}).then(({code:n,signal:S})=>S===null?n??0:(ge.error(`[gjsify oxc] ${t} terminated by signal ${S}`),1))}function runOxlint(t,n={}){return runOxc(`oxlint`,t,n)}function runOxfmt(t,n={}){return runOxc(`oxfmt`,t,n)}function loadOxlintTemplate(){return`{
993
993
  "$schema": "./node_modules/oxlint/configuration_schema.json",
994
994
  "categories": {
995
995
  "correctness": "error"
@@ -1078,11 +1078,11 @@ StartupWMClass={{APP_ID}}
1078
1078
  "**/*.metainfo.xml"
1079
1079
  ]
1080
1080
  }
1081
- `}function printOxcNotFound(t){ge.error(t.message)}function setOxcExitCode(t){process.exitCode=t,t!==0&&gjsExit(t)}function hasOxcDevDep(t=process.cwd(),n=`oxfmt`){let S=In(t,`package.json`);if(!existsSync(S))return!1;try{let t=JSON.parse(readFileSync(S,`utf-8`));return!!(t?.devDependencies?.[n]||t?.dependencies?.[n])}catch{return!1}}var OxcNotFoundError,iV,aV,oV=__esmMin(()=>{_e(),ef(),qn(),Xl(),ir(),gz(),MI(),PI(),iL(),kR(),sv(),D_(),OxcNotFoundError=class extends Error{tool;cwd;missingInterpreter;constructor(t,n,S){let C=(()=>{try{return bindingPackageName(t)}catch{return`@${t===`oxlint`?`oxlint`:`oxfmt`}/binding-<platform>`}})();super(S===void 0?`[gjsify oxc] ${t} not found.\n Expected: ${t}/bin/${t} in node_modules of ${n} or any workspace root above it.\n Install it via: gjsify install -D ${t}\n (this adds ${t} to devDependencies; the matching ${C} napi binding lands automatically as an optionalDependency.)`:`[gjsify oxc] cannot run ${t}: no \`${S}\` binary on PATH.\n ${t} IS installed — its launcher was found. What is missing is the\n interpreter that runs it: ${t}'s launcher is a Node ESM script.\n`+(t===`oxfmt`?" For a Node-free formatter install the GI bridge:\n gjsify install -D @gjsify/oxfmt-native\n (`gjsify format`/`fix` then run oxfmt in-process under GJS.)":" oxlint has no native GJS bridge yet — its JS-plugin host lives in the\n Node launcher — so `gjsify lint` needs Node on the host for now.")),this.tool=t,this.cwd=n,this.missingInterpreter=S,this.name=`OxcNotFoundError`}},iV=null,aV=null});function writeIfFresh(t,n,S,C){return existsSync(t)&&!S?(ge.log(`[gjsify flatpak init] skipped ${C}: ${t} (exists; --force to overwrite)`),null):(mkdirSync(zn(t),{recursive:!0}),writeFileSync(t,n,`utf-8`),ge.log(`[gjsify flatpak init] wrote ${C}: ${t}`),t)}function friendlyName(t,n){if(t.startsWith(`@`))return t.slice(t.indexOf(`/`)+1);if(t===n){let t=n.split(`.`);return t[t.length-1]??n}return t}function mergeArrays(t,n){if(!(!t?.length&&!n?.length))return[...t??[],...n??[]]}function deriveModuleName(t){let n=t.split(`.`);return n[n.length-1]||t}var sV,cV=__esmMin(()=>{_e(),ef(),qn(),qB(),XB(),eV(),rV(),rR(),oV(),sV={command:`init`,description:"Generate Flatpak manifest + MetaInfo XML + .desktop + flathub.json from `gjsify.flatpak` config.",builder:t=>t.option(`app-id`,{description:"Reverse-DNS app id (default: `gjsify.flatpak.appId` or package.json#name)",type:`string`}).option(`runtime`,{description:`Runtime family`,choices:[`gnome`,`freedesktop`]}).option(`runtime-version`,{description:`Runtime version (default: gnome -> 50, freedesktop -> 24.08)`,type:`string`}).option(`kind`,{description:`App kind: "app" (default, desktop) or "cli" (console-application MetaInfo, no .desktop)`,choices:[`app`,`cli`]}).option(`cli-only`,{description:"(Deprecated) Alias for `--kind cli`. Use --kind instead.",type:`boolean`,default:!1}).option(`manifest`,{description:"Output path for the manifest. Default: `<app-id>.json` in cwd.",type:`string`,normalize:!0}).option(`metainfo`,{description:"Output path for the MetaInfo XML. Default: `data/<app-id>.metainfo.xml.in` in cwd.",type:`string`,normalize:!0}).option(`desktop`,{description:"Output path for the .desktop entry (app kind only). Default: `data/<app-id>.desktop.in`.",type:`string`,normalize:!0}).option(`flathub-json`,{description:"Output path for the flathub.json policy stub. Default: `flathub.json` in cwd.",type:`string`,normalize:!0}).option(`command`,{description:`Binary name in /app/bin (default: app id)`,type:`string`}).option(`sdk-extension`,{description:`Extra SDK extension (repeatable)`,type:`string`,array:!0}).option(`finish-arg`,{description:`Extra finish-arg (repeatable). Override defaults entirely with multiple --finish-arg.`,type:`string`,array:!0}).option(`force`,{description:`Overwrite existing output files (manifest, metainfo, desktop, flathub.json)`,type:`boolean`,default:!1}).option(`verbose`,{description:`Print the resolved manifest fields before writing`,type:`boolean`,default:!1}).option(`format`,{description:"Run `oxfmt --write` on the generated JS/TS files when `oxfmt` is detected in the project. Default: true. Pass --no-format to skip. Note: oxfmt formats JS/TS only — the JSON/XML/.desktop manifests generated here are not reformatted (CSS/JSON formatting was dropped in the oxc migration).",type:`boolean`,default:!0}),handler:async t=>{let n=await new Config().forCommand().catch(()=>({})),S=n.flatpak??{},C=process.cwd(),N=readPackageJson(C),F=t.appId??S.appId??(looksLikeAppId(N.name)?N.name:void 0);if(!F)throw Error(`gjsify flatpak init: no app id available. Pass --app-id, set gjsify.flatpak.appId in package.json, or rename the package to a reverse-DNS id like org.example.MyApp.`);let I=t.kind??S.kind??(t.cliOnly?`cli`:`app`),H=pickFlatpakBuildKeys(n.ship?.flatpak,S).values,{runtime:W,runtimeId:q,sdk:Y,runtimeVersion:X}=resolveRuntime(H,{runtime:t.runtime,runtimeVersion:t.runtimeVersion}),Z=mergeArrays(H.sdkExtensions,t.sdkExtension),te=H.appendPath??(Z?.length?deriveAppendPath(Z):void 0),ne=t.command??S.command??F,re=t.finishArg,ie=re===void 0?H.finishArgs??(I===`cli`?YB:JB):re,ae={id:F,runtime:q,"runtime-version":X,sdk:Y};Z?.length&&(ae[`sdk-extensions`]=Z),te?.length&&(ae[`build-options`]={"append-path":te.join(`:`)}),ae.command=ne,ae[`finish-args`]=ie;let oe=H.cleanup;oe?.length&&(ae.cleanup=oe);let Q=[];S.modules?.length?Q.push(...S.modules):(S.extraModules?.length&&Q.push(...S.extraModules),Q.push({name:deriveModuleName(F),buildsystem:`meson`,sources:[{type:`dir`,path:`.`}]})),ae.modules=Q;let se=[],trackWrite=t=>{t&&se.push(t)};trackWrite(writeIfFresh(Nn(C,t.manifest??`${F}.json`),JSON.stringify(ae,null,2)+`
1081
+ `}function printOxcNotFound(t){ge.error(t.message)}function setOxcExitCode(t){process.exitCode=t,t!==0&&gjsExit(t)}function hasOxcDevDep(t=process.cwd(),n=`oxfmt`){let S=In(t,`package.json`);if(!existsSync(S))return!1;try{let t=JSON.parse(readFileSync(S,`utf-8`));return!!(t?.devDependencies?.[n]||t?.dependencies?.[n])}catch{return!1}}var OxcNotFoundError,iV,aV,normalizeVersion,oV,sV=__esmMin(()=>{_e(),ef(),qn(),Xl(),ir(),gz(),MI(),PI(),iL(),kR(),sv(),D_(),OxcNotFoundError=class extends Error{tool;cwd;missingInterpreter;constructor(t,n,S){let C=(()=>{try{return bindingPackageName(t)}catch{return`@${t===`oxlint`?`oxlint`:`oxfmt`}/binding-<platform>`}})();super(S===void 0?`[gjsify oxc] ${t} not found.\n Expected: ${t}/bin/${t} in node_modules of ${n} or any workspace root above it.\n Install it via: gjsify install -D ${t}\n (this adds ${t} to devDependencies; the matching ${C} napi binding lands automatically as an optionalDependency.)`:`[gjsify oxc] cannot run ${t}: no \`${S}\` binary on PATH.\n ${t} IS installed — its launcher was found. What is missing is the\n interpreter that runs it: ${t}'s launcher is a Node ESM script.\n`+(t===`oxfmt`?" For a Node-free formatter install the GI bridge:\n gjsify install -D @gjsify/oxfmt-native\n (`gjsify format`/`fix` then run oxfmt in-process under GJS.)":" oxlint has no native GJS bridge yet — its JS-plugin host lives in the\n Node launcher — so `gjsify lint` needs Node on the host for now.")),this.tool=t,this.cwd=n,this.missingInterpreter=S,this.name=`OxcNotFoundError`}},iV=null,aV=null,normalizeVersion=t=>t.trim().replace(/^v/,``),oV=!1});function writeIfFresh(t,n,S,C){return existsSync(t)&&!S?(ge.log(`[gjsify flatpak init] skipped ${C}: ${t} (exists; --force to overwrite)`),null):(mkdirSync(zn(t),{recursive:!0}),writeFileSync(t,n,`utf-8`),ge.log(`[gjsify flatpak init] wrote ${C}: ${t}`),t)}function friendlyName(t,n){if(t.startsWith(`@`))return t.slice(t.indexOf(`/`)+1);if(t===n){let t=n.split(`.`);return t[t.length-1]??n}return t}function mergeArrays(t,n){if(!(!t?.length&&!n?.length))return[...t??[],...n??[]]}function deriveModuleName(t){let n=t.split(`.`);return n[n.length-1]||t}var cV,lV=__esmMin(()=>{_e(),ef(),qn(),qB(),XB(),eV(),rV(),rR(),sV(),cV={command:`init`,description:"Generate Flatpak manifest + MetaInfo XML + .desktop + flathub.json from `gjsify.flatpak` config.",builder:t=>t.option(`app-id`,{description:"Reverse-DNS app id (default: `gjsify.flatpak.appId` or package.json#name)",type:`string`}).option(`runtime`,{description:`Runtime family`,choices:[`gnome`,`freedesktop`]}).option(`runtime-version`,{description:`Runtime version (default: gnome -> 50, freedesktop -> 24.08)`,type:`string`}).option(`kind`,{description:`App kind: "app" (default, desktop) or "cli" (console-application MetaInfo, no .desktop)`,choices:[`app`,`cli`]}).option(`cli-only`,{description:"(Deprecated) Alias for `--kind cli`. Use --kind instead.",type:`boolean`,default:!1}).option(`manifest`,{description:"Output path for the manifest. Default: `<app-id>.json` in cwd.",type:`string`,normalize:!0}).option(`metainfo`,{description:"Output path for the MetaInfo XML. Default: `data/<app-id>.metainfo.xml.in` in cwd.",type:`string`,normalize:!0}).option(`desktop`,{description:"Output path for the .desktop entry (app kind only). Default: `data/<app-id>.desktop.in`.",type:`string`,normalize:!0}).option(`flathub-json`,{description:"Output path for the flathub.json policy stub. Default: `flathub.json` in cwd.",type:`string`,normalize:!0}).option(`command`,{description:`Binary name in /app/bin (default: app id)`,type:`string`}).option(`sdk-extension`,{description:`Extra SDK extension (repeatable)`,type:`string`,array:!0}).option(`finish-arg`,{description:`Extra finish-arg (repeatable). Override defaults entirely with multiple --finish-arg.`,type:`string`,array:!0}).option(`force`,{description:`Overwrite existing output files (manifest, metainfo, desktop, flathub.json)`,type:`boolean`,default:!1}).option(`verbose`,{description:`Print the resolved manifest fields before writing`,type:`boolean`,default:!1}).option(`format`,{description:"Run `oxfmt --write` on the generated JS/TS files when `oxfmt` is detected in the project. Default: true. Pass --no-format to skip. Note: oxfmt formats JS/TS only — the JSON/XML/.desktop manifests generated here are not reformatted (CSS/JSON formatting was dropped in the oxc migration).",type:`boolean`,default:!0}),handler:async t=>{let n=await new Config().forCommand().catch(()=>({})),S=n.flatpak??{},C=process.cwd(),N=readPackageJson(C),F=t.appId??S.appId??(looksLikeAppId(N.name)?N.name:void 0);if(!F)throw Error(`gjsify flatpak init: no app id available. Pass --app-id, set gjsify.flatpak.appId in package.json, or rename the package to a reverse-DNS id like org.example.MyApp.`);let I=t.kind??S.kind??(t.cliOnly?`cli`:`app`),H=pickFlatpakBuildKeys(n.ship?.flatpak,S).values,{runtime:W,runtimeId:q,sdk:Y,runtimeVersion:X}=resolveRuntime(H,{runtime:t.runtime,runtimeVersion:t.runtimeVersion}),Z=mergeArrays(H.sdkExtensions,t.sdkExtension),te=H.appendPath??(Z?.length?deriveAppendPath(Z):void 0),ne=t.command??S.command??F,re=t.finishArg,ie=re===void 0?H.finishArgs??(I===`cli`?YB:JB):re,ae={id:F,runtime:q,"runtime-version":X,sdk:Y};Z?.length&&(ae[`sdk-extensions`]=Z),te?.length&&(ae[`build-options`]={"append-path":te.join(`:`)}),ae.command=ne,ae[`finish-args`]=ie;let oe=H.cleanup;oe?.length&&(ae.cleanup=oe);let Q=[];S.modules?.length?Q.push(...S.modules):(S.extraModules?.length&&Q.push(...S.extraModules),Q.push({name:deriveModuleName(F),buildsystem:`meson`,sources:[{type:`dir`,path:`.`}]})),ae.modules=Q;let se=[],trackWrite=t=>{t&&se.push(t)};trackWrite(writeIfFresh(Nn(C,t.manifest??`${F}.json`),JSON.stringify(ae,null,2)+`
1082
1082
  `,t.force??!1,`manifest`));let ce=N.name??F,le={appId:F,name:S.name??friendlyName(ce,F),command:ne,kind:I,flatpak:S},ue=validateScaffoldInputs(le);if(ue.length>0){ge.warn(`[gjsify flatpak init] Manifest written, but MetaInfo / .desktop are skipped — config gaps:`);for(let t of ue)ge.warn(` - ${t.field}: ${t.hint}`);ge.warn(`
1083
- Fill these fields in package.json#gjsify.flatpak (or .gjsifyrc.*) and re-run with --force.`)}else{let n=I===`cli`?renderMetainfoCli(le):renderMetainfoApp(le);trackWrite(writeIfFresh(Nn(C,t.metainfo??`data/${F}.metainfo.xml.in`),n,t.force??!1,`metainfo`)),I===`app`&&(trackWrite(writeIfFresh(Nn(C,t.desktop??`data/${F}.desktop.in`),renderDesktop(le),t.force??!1,`desktop`)),S.icon||ge.warn(`[gjsify flatpak init] No gjsify.flatpak.icon set. Flathub requires a scalable SVG at\n data/icons/hicolor/scalable/apps/${F}.svg`)),trackWrite(writeIfFresh(Nn(C,t.flathubJson??`flathub.json`),renderFlathubJson(I),t.force??!1,`flathub.json`))}let de=se.filter(t=>/\.(ts|tsx|mts|cts|js|jsx|mjs|cjs)$/.test(t));if(de.length>0&&t.format!==!1&&hasOxcDevDep(C))try{await runOxfmt([`--write`,...de],{cwd:C})}catch(t){if(t instanceof OxcNotFoundError)ge.warn("[gjsify flatpak init] post-format skipped: oxfmt declared but binding not installed. Run `gjsify install` then re-run with --force, or pass --no-format.");else throw t}t.verbose&&(ge.log(`[gjsify flatpak init] kind=${I} runtime=${q} ${X} sdk=${Y}`),ge.log(`[gjsify flatpak init] command=${ne} finish-args=${JSON.stringify(ie)}`))}}});function findDefaultManifest(t){return scanForManifest(t)??`flatpak.json`}function scanForManifest(t){let n=[];try{n=readdirSync(t)}catch{return}for(let S of n)if(S.endsWith(`.json`)&&!(S===`package.json`||S===`tsconfig.json`||S.startsWith(`.`)))try{let n=JSON.parse(readFileSync(Nn(t,S),`utf-8`));if(typeof n.id==`string`&&typeof n.runtime==`string`&&Array.isArray(n.modules))return S}catch{}}function readManifestAppId(t){let n=readFileSync(t,`utf-8`),S=JSON.parse(n);if(typeof S.id!=`string`)throw Error(`gjsify flatpak build: ${t} has no string "id" field`);return S.id}async function runFlatpakBuilder(t,n){return runProc(`flatpak-builder`,t,n,{notFoundHint:"flatpak-builder not found. Install via your distro (Fedora: `sudo dnf install flatpak-builder`)."})}async function runFlatpak(t,n){return runProc(`flatpak`,t,n,{notFoundHint:`flatpak not found. Install via your distro and add Flathub: see https://flathub.org/setup.`})}async function runTar(t,n){return runProc(`tar`,t,n,{notFoundHint:`tar not found.`})}async function runProc(t,n,S,C){S.verbose&&ge.log(`[gjsify flatpak] ${t} ${n.join(` `)}`);let{code:N}=await spawnToCompletion(t,n,{completion:`exit`,notFound:()=>Error(`gjsify flatpak: ${C.notFoundHint}`)});if(N!==0)throw Error(`gjsify flatpak: ${t} exited with status ${N}`)}var lV,uV=__esmMin(()=>{_e(),ef(),qn(),sv(),lV={command:`build [manifest]`,description:"Build the Flatpak via `flatpak-builder`. Wraps a typical install + export + bundle + tarball pipeline.",builder:t=>t.positional(`manifest`,{description:`Path to the Flatpak manifest (default: first *.json that looks like a manifest in cwd)`,type:`string`,normalize:!0}).option(`build-dir`,{description:`flatpak-builder working directory`,type:`string`,default:`flatpak-build`,normalize:!0}).option(`install`,{description:"After build, run `flatpak-builder --user --install` to install locally",type:`boolean`,default:!1}).option(`repo`,{description:"Export the build into the given OSTree repo (passes `--repo=<dir>` to flatpak-builder)",type:`string`,normalize:!0}).option(`bundle`,{description:"After --repo export, build a single-file bundle (`flatpak build-bundle`) at this path",type:`string`,normalize:!0}).option(`tarball`,{description:`Create a tarball of the build dir (parity with the legacy build-flatpak.sh tarball step)`,type:`string`,normalize:!0}).option(`force-clean`,{description:`Pass --force-clean to flatpak-builder (default true)`,type:`boolean`,default:!0}).option(`sandbox`,{description:`Pass --sandbox to flatpak-builder (default true)`,type:`boolean`,default:!0}).option(`delete-build-dirs`,{description:`Pass --delete-build-dirs to flatpak-builder (default true)`,type:`boolean`,default:!0}).option(`install-deps-from`,{description:"Pass --install-deps-from to flatpak-builder (e.g. `flathub`)",type:`string`}).option(`verbose`,{description:`Print the underlying flatpak-builder invocations`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=Nn(n,t.manifest??findDefaultManifest(n));if(!existsSync(S))throw Error(`gjsify flatpak build: manifest ${S} not found`);let C=Nn(n,t.buildDir??`flatpak-build`),N=[];if(t.forceClean!==!1&&N.push(`--force-clean`),t.sandbox!==!1&&N.push(`--sandbox`),t.deleteBuildDirs!==!1&&N.push(`--delete-build-dirs`),t.installDepsFrom&&N.push(`--install-deps-from=${t.installDepsFrom}`),existsSync(C)&&rmSync(C,{recursive:!0,force:!0}),await runFlatpakBuilder([...N,C,S],{verbose:t.verbose}),t.install&&await runFlatpakBuilder([`--user`,`--install`,`--force-clean`,C,S],{verbose:t.verbose}),t.repo){let N=Nn(n,t.repo);mkdirSync(zn(N),{recursive:!0}),await runFlatpakBuilder([`--repo=${N}`,`--force-clean`,C,S],{verbose:t.verbose})}if(t.bundle){if(!t.repo)throw Error(`gjsify flatpak build: --bundle requires --repo (the bundle is built from the OSTree repo).`);let C=Nn(n,t.bundle);mkdirSync(zn(C),{recursive:!0}),await runFlatpak([`build-bundle`,Nn(n,t.repo),C,readManifestAppId(S)],{verbose:t.verbose})}if(t.tarball){let S=Nn(n,t.tarball);mkdirSync(zn(S),{recursive:!0}),await runTar([`-czf`,S,`-C`,C,`.`],{verbose:t.verbose})}return ge.log(`[gjsify flatpak build] done (${C})`),process.exit(0)}}});function detectLockfile(t){return existsSync(Nn(t,`yarn.lock`))?`yarn.lock`:existsSync(Nn(t,`package-lock.json`))?`package-lock.json`:`yarn.lock`}var dV,fV=__esmMin(()=>{_e(),sv(),ef(),qn(),dV={command:`deps`,description:"Generate Flatpak offline-cache sources from a yarn.lock / package-lock.json (wraps `flatpak-node-generator`).",builder:t=>t.option(`lockfile`,{description:`Path to lockfile (default: yarn.lock or package-lock.json in cwd)`,type:`string`,normalize:!0}).option(`type`,{description:`Lockfile type. Default: detected from filename.`,choices:[`yarn`,`npm`]}).option(`out`,{description:`Output JSON sources file`,type:`string`,default:`flatpak-node-sources.json`,normalize:!0}).option(`xdg-layout`,{description:`Pass --xdg-layout (recommended for Yarn Berry / PnP setups)`,type:`boolean`,default:!0}).option(`electron-node-headers`,{description:`Pass --electron-node-headers`,type:`boolean`,default:!1}).option(`verbose`,{description:`Print the underlying flatpak-node-generator invocation`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=Nn(n,t.lockfile??detectLockfile(n));if(!existsSync(S))throw Error(`gjsify flatpak deps: lockfile ${S} not found (use --lockfile to override)`);let C=t.type??(S.endsWith(`package-lock.json`)?`npm`:`yarn`),N=Nn(n,t.out??`flatpak-node-sources.json`);mkdirSync(zn(N),{recursive:!0});let F=[C,S,`-o`,N];t.xdgLayout!==!1&&F.push(`--xdg-layout`),t.electronNodeHeaders&&F.push(`--electron-node-headers`),t.verbose&&ge.log(`[gjsify flatpak deps] flatpak-node-generator ${F.join(` `)}`);let I=await spawnToCompletion(`flatpak-node-generator`,F,{completion:`return`,notFound:()=>Error("gjsify flatpak deps: flatpak-node-generator not found. Install via `pipx install flatpak-node-generator` (see https://github.com/flatpak/flatpak-builder-tools/tree/master/node).")});if(I.code!==0)throw Error(`gjsify flatpak deps: flatpak-node-generator exited with ${describeExit(I)}`);ge.log(`[gjsify flatpak deps] wrote ${N}`)}}});function classifyDependency(t,n,S){let C=S.get(t);return C&&!mV.test(n)?{kind:`workspace`,target:C}:n.startsWith(`workspace:`)?{kind:`missing-workspace`}:mV.test(n)?{kind:`ignored`}:{kind:`external`}}function planFocus(t,n,S){let C=new Map(t.map(t=>[t.name,t])),N=[...new Set(n)].filter(t=>!C.has(t));if(N.length>0){let t=[...C.keys()].sort(),n=t.slice(0,hV).join(`, `),F=t.length>hV?`, … (${t.length-hV} more)`:``;throw Error(`${S}: --focus names unknown workspace(s): ${N.join(`, `)}. Pass a package name from a workspace's package.json. Known workspaces: ${n}${F}.`)}let F=new Set(n.map(t=>C.get(t))),I=new Set;for(let t of F)for(let n of pV)for(let[S,N]of Object.entries(t.manifest[n]??{})){if(typeof N!=`string`)continue;let t=classifyDependency(S,N,C);t.kind===`workspace`?F.add(t.target):t.kind===`external`&&I.add(`${S}@${N}`)}return{workspaces:t.filter(t=>F.has(t)),specs:[...I]}}var pV,mV,hV,gV=__esmMin(()=>{pV=[`dependencies`,`devDependencies`,`optionalDependencies`],mV=/^(link|file|portal|git\+|https?):/,hV=20});function parseSri(t){if(!t)return null;let n=t.indexOf(`-`);if(n<=0||n===t.length-1)return null;let S=t.slice(0,n),C=t.slice(n+1).replace(/=+$/,``),N=ot.from(C,`base64`).toString(`hex`);return N.length<4?null:{algorithm:S,hex:N}}function parseNpmLike(t){let n=[],S=t,C=S.packages;if(C&&typeof C==`object`){for(let t of Object.values(C))t?.resolved&&t.integrity&&n.push({url:t.resolved,integrity:t.integrity});if(n.length>0)return n}return S.dependencies&&typeof S.dependencies==`object`&&collectV1Deps(S.dependencies,n),n}function collectV1Deps(t,n){for(let S of Object.values(t))S?.resolved&&S.integrity&&n.push({url:S.resolved,integrity:S.integrity}),S?.dependencies&&collectV1Deps(S.dependencies,n)}function parseYarnClassic(t){if(/^__metadata:/m.test(t))throw Error("gjsify flatpak sources: Yarn Berry (v2+) yarn.lock is not supported — its `checksum` is a cache hash, not a tarball SRI. Run `gjsify install` to produce a gjsify-lock.json, or use a classic (v1) yarn.lock.");let n=[],S=0;for(let C of t.split(/\n\s*\n/)){let t=C.match(/^\s+resolved\s+"([^"]+)"/m);if(!t)continue;let N=t[1].replace(/#.*$/,``),F=C.match(/^\s+integrity\s+(\S+)/m);if(!F){S++;continue}n.push({url:N,integrity:F[1]})}return S>0&&ge.warn(`[gjsify flatpak sources] ${S} yarn.lock entr(y/ies) had no integrity (pre-1.x format) and were skipped — re-lock with a modern yarn or use \`gjsify install\`.`),n}function parsePnpm(t){let n=[],S=!1,C=null;for(let N of t.split(`
1083
+ Fill these fields in package.json#gjsify.flatpak (or .gjsifyrc.*) and re-run with --force.`)}else{let n=I===`cli`?renderMetainfoCli(le):renderMetainfoApp(le);trackWrite(writeIfFresh(Nn(C,t.metainfo??`data/${F}.metainfo.xml.in`),n,t.force??!1,`metainfo`)),I===`app`&&(trackWrite(writeIfFresh(Nn(C,t.desktop??`data/${F}.desktop.in`),renderDesktop(le),t.force??!1,`desktop`)),S.icon||ge.warn(`[gjsify flatpak init] No gjsify.flatpak.icon set. Flathub requires a scalable SVG at\n data/icons/hicolor/scalable/apps/${F}.svg`)),trackWrite(writeIfFresh(Nn(C,t.flathubJson??`flathub.json`),renderFlathubJson(I),t.force??!1,`flathub.json`))}let de=se.filter(t=>/\.(ts|tsx|mts|cts|js|jsx|mjs|cjs)$/.test(t));if(de.length>0&&t.format!==!1&&hasOxcDevDep(C))try{await runOxfmt([`--write`,...de],{cwd:C})}catch(t){if(t instanceof OxcNotFoundError)ge.warn("[gjsify flatpak init] post-format skipped: oxfmt declared but binding not installed. Run `gjsify install` then re-run with --force, or pass --no-format.");else throw t}t.verbose&&(ge.log(`[gjsify flatpak init] kind=${I} runtime=${q} ${X} sdk=${Y}`),ge.log(`[gjsify flatpak init] command=${ne} finish-args=${JSON.stringify(ie)}`))}}});function findDefaultManifest(t){return scanForManifest(t)??`flatpak.json`}function scanForManifest(t){let n=[];try{n=readdirSync(t)}catch{return}for(let S of n)if(S.endsWith(`.json`)&&!(S===`package.json`||S===`tsconfig.json`||S.startsWith(`.`)))try{let n=JSON.parse(readFileSync(Nn(t,S),`utf-8`));if(typeof n.id==`string`&&typeof n.runtime==`string`&&Array.isArray(n.modules))return S}catch{}}function readManifestAppId(t){let n=readFileSync(t,`utf-8`),S=JSON.parse(n);if(typeof S.id!=`string`)throw Error(`gjsify flatpak build: ${t} has no string "id" field`);return S.id}async function runFlatpakBuilder(t,n){return runProc(`flatpak-builder`,t,n,{notFoundHint:"flatpak-builder not found. Install via your distro (Fedora: `sudo dnf install flatpak-builder`)."})}async function runFlatpak(t,n){return runProc(`flatpak`,t,n,{notFoundHint:`flatpak not found. Install via your distro and add Flathub: see https://flathub.org/setup.`})}async function runTar(t,n){return runProc(`tar`,t,n,{notFoundHint:`tar not found.`})}async function runProc(t,n,S,C){S.verbose&&ge.log(`[gjsify flatpak] ${t} ${n.join(` `)}`);let{code:N}=await spawnToCompletion(t,n,{completion:`exit`,notFound:()=>Error(`gjsify flatpak: ${C.notFoundHint}`)});if(N!==0)throw Error(`gjsify flatpak: ${t} exited with status ${N}`)}var uV,dV=__esmMin(()=>{_e(),ef(),qn(),sv(),uV={command:`build [manifest]`,description:"Build the Flatpak via `flatpak-builder`. Wraps a typical install + export + bundle + tarball pipeline.",builder:t=>t.positional(`manifest`,{description:`Path to the Flatpak manifest (default: first *.json that looks like a manifest in cwd)`,type:`string`,normalize:!0}).option(`build-dir`,{description:`flatpak-builder working directory`,type:`string`,default:`flatpak-build`,normalize:!0}).option(`install`,{description:"After build, run `flatpak-builder --user --install` to install locally",type:`boolean`,default:!1}).option(`repo`,{description:"Export the build into the given OSTree repo (passes `--repo=<dir>` to flatpak-builder)",type:`string`,normalize:!0}).option(`bundle`,{description:"After --repo export, build a single-file bundle (`flatpak build-bundle`) at this path",type:`string`,normalize:!0}).option(`tarball`,{description:`Create a tarball of the build dir (parity with the legacy build-flatpak.sh tarball step)`,type:`string`,normalize:!0}).option(`force-clean`,{description:`Pass --force-clean to flatpak-builder (default true)`,type:`boolean`,default:!0}).option(`sandbox`,{description:`Pass --sandbox to flatpak-builder (default true)`,type:`boolean`,default:!0}).option(`delete-build-dirs`,{description:`Pass --delete-build-dirs to flatpak-builder (default true)`,type:`boolean`,default:!0}).option(`install-deps-from`,{description:"Pass --install-deps-from to flatpak-builder (e.g. `flathub`)",type:`string`}).option(`verbose`,{description:`Print the underlying flatpak-builder invocations`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=Nn(n,t.manifest??findDefaultManifest(n));if(!existsSync(S))throw Error(`gjsify flatpak build: manifest ${S} not found`);let C=Nn(n,t.buildDir??`flatpak-build`),N=[];if(t.forceClean!==!1&&N.push(`--force-clean`),t.sandbox!==!1&&N.push(`--sandbox`),t.deleteBuildDirs!==!1&&N.push(`--delete-build-dirs`),t.installDepsFrom&&N.push(`--install-deps-from=${t.installDepsFrom}`),existsSync(C)&&rmSync(C,{recursive:!0,force:!0}),await runFlatpakBuilder([...N,C,S],{verbose:t.verbose}),t.install&&await runFlatpakBuilder([`--user`,`--install`,`--force-clean`,C,S],{verbose:t.verbose}),t.repo){let N=Nn(n,t.repo);mkdirSync(zn(N),{recursive:!0}),await runFlatpakBuilder([`--repo=${N}`,`--force-clean`,C,S],{verbose:t.verbose})}if(t.bundle){if(!t.repo)throw Error(`gjsify flatpak build: --bundle requires --repo (the bundle is built from the OSTree repo).`);let C=Nn(n,t.bundle);mkdirSync(zn(C),{recursive:!0}),await runFlatpak([`build-bundle`,Nn(n,t.repo),C,readManifestAppId(S)],{verbose:t.verbose})}if(t.tarball){let S=Nn(n,t.tarball);mkdirSync(zn(S),{recursive:!0}),await runTar([`-czf`,S,`-C`,C,`.`],{verbose:t.verbose})}return ge.log(`[gjsify flatpak build] done (${C})`),process.exit(0)}}});function detectLockfile(t){return existsSync(Nn(t,`yarn.lock`))?`yarn.lock`:existsSync(Nn(t,`package-lock.json`))?`package-lock.json`:`yarn.lock`}var fV,pV=__esmMin(()=>{_e(),sv(),ef(),qn(),fV={command:`deps`,description:"Generate Flatpak offline-cache sources from a yarn.lock / package-lock.json (wraps `flatpak-node-generator`).",builder:t=>t.option(`lockfile`,{description:`Path to lockfile (default: yarn.lock or package-lock.json in cwd)`,type:`string`,normalize:!0}).option(`type`,{description:`Lockfile type. Default: detected from filename.`,choices:[`yarn`,`npm`]}).option(`out`,{description:`Output JSON sources file`,type:`string`,default:`flatpak-node-sources.json`,normalize:!0}).option(`xdg-layout`,{description:`Pass --xdg-layout (recommended for Yarn Berry / PnP setups)`,type:`boolean`,default:!0}).option(`electron-node-headers`,{description:`Pass --electron-node-headers`,type:`boolean`,default:!1}).option(`verbose`,{description:`Print the underlying flatpak-node-generator invocation`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=Nn(n,t.lockfile??detectLockfile(n));if(!existsSync(S))throw Error(`gjsify flatpak deps: lockfile ${S} not found (use --lockfile to override)`);let C=t.type??(S.endsWith(`package-lock.json`)?`npm`:`yarn`),N=Nn(n,t.out??`flatpak-node-sources.json`);mkdirSync(zn(N),{recursive:!0});let F=[C,S,`-o`,N];t.xdgLayout!==!1&&F.push(`--xdg-layout`),t.electronNodeHeaders&&F.push(`--electron-node-headers`),t.verbose&&ge.log(`[gjsify flatpak deps] flatpak-node-generator ${F.join(` `)}`);let I=await spawnToCompletion(`flatpak-node-generator`,F,{completion:`return`,notFound:()=>Error("gjsify flatpak deps: flatpak-node-generator not found. Install via `pipx install flatpak-node-generator` (see https://github.com/flatpak/flatpak-builder-tools/tree/master/node).")});if(I.code!==0)throw Error(`gjsify flatpak deps: flatpak-node-generator exited with ${describeExit(I)}`);ge.log(`[gjsify flatpak deps] wrote ${N}`)}}});function classifyDependency(t,n,S){let C=S.get(t);return C&&!hV.test(n)?{kind:`workspace`,target:C}:n.startsWith(`workspace:`)?{kind:`missing-workspace`}:hV.test(n)?{kind:`ignored`}:{kind:`external`}}function planFocus(t,n,S){let C=new Map(t.map(t=>[t.name,t])),N=[...new Set(n)].filter(t=>!C.has(t));if(N.length>0){let t=[...C.keys()].sort(),n=t.slice(0,gV).join(`, `),F=t.length>gV?`, … (${t.length-gV} more)`:``;throw Error(`${S}: --focus names unknown workspace(s): ${N.join(`, `)}. Pass a package name from a workspace's package.json. Known workspaces: ${n}${F}.`)}let F=new Set(n.map(t=>C.get(t))),I=new Set;for(let t of F)for(let n of mV)for(let[S,N]of Object.entries(t.manifest[n]??{})){if(typeof N!=`string`)continue;let t=classifyDependency(S,N,C);t.kind===`workspace`?F.add(t.target):t.kind===`external`&&I.add(`${S}@${N}`)}return{workspaces:t.filter(t=>F.has(t)),specs:[...I]}}var mV,hV,gV,_V=__esmMin(()=>{mV=[`dependencies`,`devDependencies`,`optionalDependencies`],hV=/^(link|file|portal|git\+|https?):/,gV=20});function parseSri(t){if(!t)return null;let n=t.indexOf(`-`);if(n<=0||n===t.length-1)return null;let S=t.slice(0,n),C=t.slice(n+1).replace(/=+$/,``),N=ot.from(C,`base64`).toString(`hex`);return N.length<4?null:{algorithm:S,hex:N}}function parseNpmLike(t){let n=[],S=t,C=S.packages;if(C&&typeof C==`object`){for(let t of Object.values(C))t?.resolved&&t.integrity&&n.push({url:t.resolved,integrity:t.integrity});if(n.length>0)return n}return S.dependencies&&typeof S.dependencies==`object`&&collectV1Deps(S.dependencies,n),n}function collectV1Deps(t,n){for(let S of Object.values(t))S?.resolved&&S.integrity&&n.push({url:S.resolved,integrity:S.integrity}),S?.dependencies&&collectV1Deps(S.dependencies,n)}function parseYarnClassic(t){if(/^__metadata:/m.test(t))throw Error("gjsify flatpak sources: Yarn Berry (v2+) yarn.lock is not supported — its `checksum` is a cache hash, not a tarball SRI. Run `gjsify install` to produce a gjsify-lock.json, or use a classic (v1) yarn.lock.");let n=[],S=0;for(let C of t.split(/\n\s*\n/)){let t=C.match(/^\s+resolved\s+"([^"]+)"/m);if(!t)continue;let N=t[1].replace(/#.*$/,``),F=C.match(/^\s+integrity\s+(\S+)/m);if(!F){S++;continue}n.push({url:N,integrity:F[1]})}return S>0&&ge.warn(`[gjsify flatpak sources] ${S} yarn.lock entr(y/ies) had no integrity (pre-1.x format) and were skipped — re-lock with a modern yarn or use \`gjsify install\`.`),n}function parsePnpm(t){let n=[],S=!1,C=null;for(let N of t.split(`
1084
1084
  `)){let t=N.replace(/\r$/,``);if(/^packages:\s*$/.test(t)){S=!0;continue}if(S&&/^[^\s#]/.test(t)&&(S=!1),!S)continue;let F=t.match(/^ {2}(?:'([^']+)'|"([^"]+)"|([^\s#][^:]*)):\s*$/);if(F){C=F[1]??F[2]??F[3]??null;continue}let I=t.match(/resolution:\s*\{([^}]*)\}/);if(I&&C){let t=I[1].match(/integrity:\s*(sha\d+-[A-Za-z0-9+/=]+)/);if(!t)continue;let S=I[1].match(/tarball:\s*([^\s,}]+)/),N=S?S[1]:reconstructNpmTarballUrl(C);N&&n.push({url:N,integrity:t[1]})}}return n}function reconstructNpmTarballUrl(t){let n,S;if(t.startsWith(`/`)){let C=t.slice(1).replace(/_.*$/,``),N=C.lastIndexOf(`/`);if(N<=0)return null;n=C.slice(0,N),S=C.slice(N+1)}else{let C=t.replace(/\(.*\)$/,``),N=C.lastIndexOf(`@`);if(N<=0)return null;n=C.slice(0,N),S=C.slice(N+1)}if(!n||!S||/[@:/]/.test(S))return null;let C=n.slice(n.lastIndexOf(`/`)+1);return`https://registry.npmjs.org/${n}/-/${C}-${S}.tgz`}function detectType(t){let n=t.toLowerCase();return n.endsWith(`pnpm-lock.yaml`)?`pnpm`:n.endsWith(`yarn.lock`)?`yarn`:n.endsWith(`package-lock.json`)?`npm`:`gjsify`}function defaultLockfile(t){for(let n of[`gjsify-lock.json`,`package-lock.json`,`yarn.lock`,`pnpm-lock.yaml`])if(existsSync(In(t,n)))return n;return`gjsify-lock.json`}function focusedTarballs(t,n){let S=discoverWorkspaces(zn(t),{includeRoot:!0}),C=planFocus(S,n,`gjsify flatpak sources`),N=readLockfileNodes(t);if(!N)throw Error(`gjsify flatpak sources: ${t} is not a readable gjsify-lock.json.`);let F=reachableInstallPaths(N,C.specs.map(parseSpecName)),I=new Set(S.map(t=>t.name));return N.filter(t=>F.has(t.installPath)&&!I.has(t.name)).flatMap(t=>t.tarballUrl&&t.integrity?[{url:t.tarballUrl,integrity:t.integrity}]:[])}function parseLockfile(t,n){let S=readFileSync(t,`utf-8`);if(n===`yarn`)return parseYarnClassic(S);if(n===`pnpm`)return parsePnpm(S);let C;try{C=JSON.parse(S)}catch(n){throw Error(`gjsify flatpak sources: ${t} is not valid JSON: ${n.message}`)}return parseNpmLike(C)}function buildModuleSnippet(t,n){return[``,`# Add the generated sources to your app module and point XDG_CACHE_HOME`,`# at the vendored cache before running gjsify offline. Example module:`,`#`,`# {`,`# "name": "my-app",`,`# "buildsystem": "simple",`,`# "build-commands": [`,`# "export XDG_CACHE_HOME=\\"$(pwd)/${n}\\"",`,`# "gjsify install --immutable",`,`# "gjsify build src/main.ts --app gjs --outfile /app/bin/my-app"`,`# ],`,`# "sources": [`,`# { "type": "dir", "path": "." },`,`# "${t}"`,`# ]`,`# }`,``].join(`
1085
- `)}var _V,vV,yV=__esmMin(()=>{_e(),ef(),qn(),ht(),AI(),gV(),Oz(),qB(),_V=new Set([`sha256`,`sha512`]),vV={command:`sources`,description:"Generate an offline flatpak-builder `sources` array from any lockfile (gjsify-lock.json / package-lock.json / yarn.lock / pnpm-lock.yaml) for a no-network Flathub build.",builder:t=>t.option(`lockfile`,{description:`Path to the lockfile. Default: the first of gjsify-lock.json / package-lock.json / yarn.lock / pnpm-lock.yaml found in cwd.`,type:`string`,normalize:!0}).option(`type`,{description:`Lockfile format. Default: detected from the filename.`,choices:[`gjsify`,`npm`,`yarn`,`pnpm`]}).option(`out`,{description:`Output JSON sources file`,type:`string`,default:KB,normalize:!0}).option(`cache-root`,{description:`Relative dir the tarballs download into; point XDG_CACHE_HOME here in the build. Tarballs land at <cache-root>/gjsify/tarballs/v1/<algo>/<shard>/<hex>.tgz.`,type:`string`,default:`flatpak-gjsify-cache`}).option(`focus`,{description:"Only the tarballs the named workspaces (package names), the workspaces they depend on, and their external dependencies need, as `gjsify install --focus` installs them. gjsify-lock.json only.",type:`string`,array:!0}).option(`print-module`,{description:`Also print a ready-to-paste flatpak manifest module snippet to stderr`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=Nn(n,t.lockfile??defaultLockfile(n));if(!existsSync(S))throw Error(`gjsify flatpak sources: lockfile ${S} not found. Run \`gjsify install\` (or npm/yarn/pnpm) first, or pass --lockfile.`);let C=t.type??detectType(S),N=t.focus;if(N&&N.length>0&&C!==`gjsify`)throw Error(`gjsify flatpak sources: --focus reads the per-package edges of gjsify-lock.json; ${C} lockfiles are not supported with it.`);let F=N&&N.length>0?focusedTarballs(S,N):parseLockfile(S,C),I=t.cacheRoot??`flatpak-gjsify-cache`,H=new Map,W=0,q=0;for(let{url:t,integrity:n}of F){let S=parseSri(n);if(!S){W++;continue}if(!_V.has(S.algorithm)){q++;continue}let C=`${S.algorithm}:${S.hex}`;if(H.has(C))continue;let N={type:`file`,url:t,dest:`${I}/gjsify/tarballs/v1/${S.algorithm}/${S.hex.slice(0,2)}`,"dest-filename":`${S.hex}.tgz`};S.algorithm===`sha512`?N.sha512=S.hex:N.sha256=S.hex,H.set(C,N)}let Y=[...H.values()].sort((t,n)=>t.url<n.url?-1:+(t.url>n.url)),X=Nn(n,t.out??`gjsify-sources.json`);mkdirSync(zn(X),{recursive:!0}),writeFileSync(X,JSON.stringify(Y,null,2)+`
1085
+ `)}var vV,yV,bV=__esmMin(()=>{_e(),ef(),qn(),ht(),AI(),_V(),Oz(),qB(),vV=new Set([`sha256`,`sha512`]),yV={command:`sources`,description:"Generate an offline flatpak-builder `sources` array from any lockfile (gjsify-lock.json / package-lock.json / yarn.lock / pnpm-lock.yaml) for a no-network Flathub build.",builder:t=>t.option(`lockfile`,{description:`Path to the lockfile. Default: the first of gjsify-lock.json / package-lock.json / yarn.lock / pnpm-lock.yaml found in cwd.`,type:`string`,normalize:!0}).option(`type`,{description:`Lockfile format. Default: detected from the filename.`,choices:[`gjsify`,`npm`,`yarn`,`pnpm`]}).option(`out`,{description:`Output JSON sources file`,type:`string`,default:KB,normalize:!0}).option(`cache-root`,{description:`Relative dir the tarballs download into; point XDG_CACHE_HOME here in the build. Tarballs land at <cache-root>/gjsify/tarballs/v1/<algo>/<shard>/<hex>.tgz.`,type:`string`,default:`flatpak-gjsify-cache`}).option(`focus`,{description:"Only the tarballs the named workspaces (package names), the workspaces they depend on, and their external dependencies need, as `gjsify install --focus` installs them. gjsify-lock.json only.",type:`string`,array:!0}).option(`print-module`,{description:`Also print a ready-to-paste flatpak manifest module snippet to stderr`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=Nn(n,t.lockfile??defaultLockfile(n));if(!existsSync(S))throw Error(`gjsify flatpak sources: lockfile ${S} not found. Run \`gjsify install\` (or npm/yarn/pnpm) first, or pass --lockfile.`);let C=t.type??detectType(S),N=t.focus;if(N&&N.length>0&&C!==`gjsify`)throw Error(`gjsify flatpak sources: --focus reads the per-package edges of gjsify-lock.json; ${C} lockfiles are not supported with it.`);let F=N&&N.length>0?focusedTarballs(S,N):parseLockfile(S,C),I=t.cacheRoot??`flatpak-gjsify-cache`,H=new Map,W=0,q=0;for(let{url:t,integrity:n}of F){let S=parseSri(n);if(!S){W++;continue}if(!vV.has(S.algorithm)){q++;continue}let C=`${S.algorithm}:${S.hex}`;if(H.has(C))continue;let N={type:`file`,url:t,dest:`${I}/gjsify/tarballs/v1/${S.algorithm}/${S.hex.slice(0,2)}`,"dest-filename":`${S.hex}.tgz`};S.algorithm===`sha512`?N.sha512=S.hex:N.sha256=S.hex,H.set(C,N)}let Y=[...H.values()].sort((t,n)=>t.url<n.url?-1:+(t.url>n.url)),X=Nn(n,t.out??`gjsify-sources.json`);mkdirSync(zn(X),{recursive:!0}),writeFileSync(X,JSON.stringify(Y,null,2)+`
1086
1086
  `),ge.log(`[gjsify flatpak sources] wrote ${X} — ${Y.length} tarball source(s) from ${C} lockfile (${F.length} locked entr${F.length===1?`y`:`ies`})`+(W?`, ${W} without a usable integrity skipped`:``)+(q?`, ${q} non-sha256/512 skipped`:``)),t.printModule&&ge.error(buildModuleSnippet(t.out??`gjsify-sources.json`,I))}}});function renderWorkflow(t){let n=`[${t.branches.map(t=>JSON.stringify(t)).join(`, `)}]`;return`name: Flatpak
1087
1087
 
1088
1088
  on:
@@ -1111,20 +1111,20 @@ jobs:
1111
1111
  manifest-path: ${t.manifest}
1112
1112
  bundle: ${t.bundle}
1113
1113
  cache-key: ${t.cacheKey}
1114
- `}var bV,xV=__esmMin(()=>{_e(),ef(),qn(),rR(),qB(),XB(),eV(),bV={command:`ci`,description:`Scaffold .github/workflows/flatpak.yml using the flathub-infra container + flatpak-builder@v6 action.`,builder:t=>t.option(`manifest`,{description:`Manifest path the workflow points at (default: <app-id>.json)`,type:`string`,normalize:!0}).option(`bundle`,{description:`Bundle filename produced by the action (default: <app-id>.flatpak)`,type:`string`,normalize:!0}).option(`runtime-image`,{description:"Container image override. Default derived from gjsify.flatpak.runtime + runtimeVersion (e.g. `ghcr.io/flathub-infra/flatpak-github-actions:gnome-50`).",type:`string`}).option(`branches`,{description:`Branches the workflow runs on push for (default: main)`,type:`string`,array:!0}).option(`out`,{description:`Output path`,type:`string`,default:`.github/workflows/flatpak.yml`,normalize:!0}).option(`cache-key`,{description:"Override the action `cache-key` (default: `flatpak-builder-${{ github.sha }}`)",type:`string`}).option(`force`,{description:`Overwrite an existing workflow file`,type:`boolean`,default:!1}).option(`verbose`,{description:`Print resolved fields`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=await new Config().forCommand().catch(()=>({})),C=S.flatpak??{},N=readPackageJson(n),F=C.appId??(looksLikeAppId(N.name)?N.name:void 0);if(!F)throw Error(`gjsify flatpak ci: no app id available. Set gjsify.flatpak.appId in package.json or rename the package to a reverse-DNS id.`);let I=t.manifest??`${F}.json`,H=t.bundle??`${F}.flatpak`,W=pickFlatpakBuildKeys(S.ship?.flatpak,C).values,{runtime:q,runtimeVersion:Y}=resolveRuntime(W,{}),X=t.runtimeImage??C.ciContainer??defaultCiContainer(q,Y),Z=t.branches??C.ciBranches??[`main`],te=t.cacheKey??"flatpak-builder-${{ github.sha }}",ne=Nn(n,t.out??`.github/workflows/flatpak.yml`);if(existsSync(ne)&&!t.force){if(readFileSync(ne,`utf-8`)===renderWorkflow({manifest:I,bundle:H,runtimeImage:X,branches:Z,cacheKey:te})){ge.log(`[gjsify flatpak ci] ${ne} already up to date`);return}throw Error(`gjsify flatpak ci: ${ne} exists with different content. Pass --force to overwrite.`)}let re=renderWorkflow({manifest:I,bundle:H,runtimeImage:X,branches:Z,cacheKey:te});mkdirSync(zn(ne),{recursive:!0}),writeFileSync(ne,re,`utf-8`),t.verbose&&ge.log(`[gjsify flatpak ci] runtime-image=${X} manifest=${I} bundle=${H}`),ge.log(`[gjsify flatpak ci] wrote ${ne}`)}}});function buildTree$1(t){let n={name:`#root`,attrs:{},children:[],text:``},S=[n];for(let n of scanXml(t)){let t=S[S.length-1];if(n.kind===`text`)for(let t of S)t.text+=n.text;else if(n.kind===`open`){let C={name:EV(n.name),attrs:n.attributes,children:[],text:``};t.children.push(C),n.selfClosing||S.push(C)}else S.length>1&&S.pop()}return n}function localized(t,n){let S=new Map;for(let C of kids(t,n)){let t=DV(C.text);t!==``&&!S.has(lang(C))&&S.set(lang(C),t)}return S}function parseHex(t){let n=/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(t.trim());if(n===null)return null;let S=n[1];S.length===3&&(S=S.replace(/./g,t=>t+t));let C=Number.parseInt(S.slice(0,2),16)/255,N=Number.parseInt(S.slice(2,4),16)/255,F=Number.parseInt(S.slice(4,6),16)/255,I=Math.max(C,N,F),H=Math.min(C,N,F),W=(I+H)/2,q=I-H;return{s:q===0?0:q/(1-Math.abs(2*W-1)),l:W}}function readImageInfo(t){if(t.length>=24&&t[0]===137&&t[1]===80&&t[2]===78&&t[3]===71){let u32=n=>(t[n]<<24|t[n+1]<<16|t[n+2]<<8|t[n+3])>>>0;return{kind:`raster`,width:u32(16),height:u32(20)}}if(t.length>=4&&t[0]===255&&t[1]===216){let n=2;for(;n+9<t.length;){if(t[n]!==255){n++;continue}let S=t[n+1];if(S===255){n++;continue}if(S>=192&&S<=207&&S!==196&&S!==200&&S!==204)return{kind:`raster`,height:t[n+5]<<8|t[n+6],width:t[n+7]<<8|t[n+8]};n+=2+(t[n+2]<<8|t[n+3])}return null}let n=``;for(let S=0;S<Math.min(t.length,1024);S++)n+=String.fromCharCode(t[S]);return/<svg[\s>]/.test(n)?{kind:`svg`}:null}function termPattern(t,n=`iu`){let S=t.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`).replace(/\s+/g,`\\s+`);return RegExp(`(^|[^\\p{L}\\p{N}])${S}($|[^\\p{L}\\p{N}])`,n)}async function lintMetainfo(t,n={}){let S=[],add=(t,n,C,N,F)=>{S.push({rule:t,severity:n,message:F,location:N,url:`${SV}#${C}`})},C=child(buildTree$1(t),`component`);if(C===void 0)return add(`no-component`,`error`,`app-name`,`document`,`no <component> element found`),S;let loc=(t,n)=>n===``?t:`${t}[${n}]`,N=localized(C,`name`),F=localized(C,`summary`);for(let[t,n]of N){let S=loc(`name`,t),C=[...n].length;if(C>=20?add(`name-too-long`,`error`,`not-too-long`,S,`"${n}" is ${C} characters; a name must be shorter than 20`):C>15&&add(`name-long`,`warning`,`not-too-long`,S,`"${n}" is ${C} characters; ideally at most 15`),/\s[-–—:]\s|:\s|\(.+\)/.test(n)||/\b(web browser|editor|client|viewer|player)$/i.test(n)&&n.includes(` `))add(`name-extra-info`,`warning`,`just-the-name`,S,`"${n}" carries a description; keep just the name and put the rest in the summary`);else if(/[.-]/.test(n))add(`name-formatting`,`warning`,`no-weird-formatting`,S,`"${n}" contains a dot or dash; avoid punctuation in names`);else if(/\p{L}/u.test(n)){let t=n.replace(/[^\p{L}]/gu,``);n===n.toLowerCase()?add(`name-formatting`,`warning`,`no-weird-formatting`,S,`"${n}" is all lowercase`):t.length>1&&n===n.toUpperCase()?add(`name-formatting`,`warning`,`no-weird-formatting`,S,`"${n}" is all uppercase (exempt only for an established brand such as VLC)`):!/\s/.test(n)&&/\p{Ll}\p{Lu}/u.test(n)&&add(`name-formatting`,`warning`,`no-weird-formatting`,S,`"${n}" is camel/pascal case`)}}let I=(n.technicalTerms??[...CV]).map(t=>({term:t,re:termPattern(t)}));for(let[t,n]of F){let S=loc(`summary`,t),C=[...n].length;C>35?add(`summary-too-long`,`error`,`not-too-long-1`,S,`"${n}" is ${C} characters; at most 35 allowed`):(C>25||C<10)&&add(`summary-length`,`warning`,`not-too-long-1`,S,`"${n}" is ${C} characters; ideal is 10 to 25`),/[.。]$/.test(n)&&add(`summary-full-stop`,`warning`,`no-weird-formatting-1`,S,`a summary does not end with a full stop`);let F=n.split(/\s+/).filter(t=>/^\p{L}/u.test(t)),H=F.filter(t=>/^\p{Lu}/u.test(t)).length;F.length>=3&&H/F.length>=.75&&add(`summary-title-case`,`warning`,`no-weird-formatting-1`,S,`use sentence case, not Title Case`);let W=TV[langBase(t===``?`en`:t)],q=n.split(/\s+/)[0]?.toLowerCase();W?.includes(q)&&add(`summary-article`,`warning`,`dont-start-with-an-article`,S,`starts with the article "${q}"; omit it or phrase it with a verb`);let Y=N.get(t)??N.get(``);Y!==void 0&&[...Y].length>=3&&termPattern(Y,`u`).test(n)&&add(`summary-repeats-name`,`warning`,`dont-repeat-the-name`,S,`repeats the app name "${Y}"`);let X=I.find(({re:t})=>t.test(n));X!==void 0&&add(`summary-technical`,`warning`,`not-technical`,S,`mentions "${X.term}"; say what the app does for people, not how it is built`)}let H=kids(C,`description`).find(t=>lang(t)===``)??child(C,`description`);if(H!==void 0){let t=F.get(``)??``,n=kids(H,`p`).filter(t=>lang(t)===``).map(t=>DV(t.text)),S=n.join(` `);t!==``&&n.length>0&&n[0].replace(/[.!]$/,``).toLowerCase()===t.toLowerCase()&&add(`description-repeats-summary`,`warning`,`dont-repeat-the-summary`,`description`,`the first paragraph repeats the summary`),t!==``&&[...S].length<Math.max(80,3*[...t].length)&&add(`description-short`,`warning`,`not-too-short`,`description`,`${[...S].length} characters; it should be substantially longer than the summary`);for(let t of[...kids(H,`ul`),...kids(H,`ol`)]){let n=kids(t,`li`).filter(t=>lang(t)===``).length;n>10&&add(`description-long-list`,`warning`,`no-super-long-lists`,`description`,`a list with ${n} items; group them or use paragraphs (max 10)`)}}let W=kids(child(C,`branding`),`color`).filter(t=>t.attrs.type===`primary`),q=W.find(t=>t.attrs.scheme_preference===`light`),Y=W.find(t=>t.attrs.scheme_preference===`dark`);if(q===void 0||Y===void 0)add(`branding-missing`,`warning`,`has-primary-brand-colors`,`branding`,`set two primary brand colors, scheme_preference="light" and "dark"`);else{let t=DV(q.text).toLowerCase(),n=DV(Y.text).toLowerCase();t===n&&add(`branding-identical`,`warning`,`good-brand-colors`,`branding`,`light and dark primary colors are the same`);let S=parseHex(t),C=parseHex(n);for(let[N,F,I]of[[`light`,S,t],[`dark`,C,n]])F!==null&&(F.s<.15||F.l>.93||F.l<.07)&&add(`branding-dull`,`warning`,`good-brand-colors`,`branding/${N}`,`${I} is near white, black or gray; brand colors should be colorful`);S!==null&&C!==null&&t!==n&&C.l>=S.l&&add(`branding-dark-not-darker`,`warning`,`good-brand-colors`,`branding/dark`,`the dark variant should be darker than the light one`)}if(n.probeImage!==void 0)for(let t of n.iconRefs??[]){let S=await n.probeImage(t);if(S!==null){S.kind===`raster`&&(S.width===S.height?S.width<256&&add(`icon-too-small`,`error`,`icon-size`,`icon`,`${t} is ${S.width}×${S.height}; use SVG or at least 256×256`):add(`icon-not-square`,`error`,`icon-size`,`icon`,`${t} is ${S.width}×${S.height}; the icon has to be square`));break}}let X=kids(child(C,`screenshots`),`screenshot`);if(X.length===0)add(`screenshot-missing`,`warning`,`at-least-one-screenshot`,`screenshots`,`at least one screenshot is expected`);else{let englishTag=t=>t===``||langBase(t)===`en`,isEnglish=t=>{let n=kids(t,`image`).map(lang);return englishTag(lang(t))&&(n.length===0||n.some(englishTag))};X.some(isEnglish)||add(`screenshot-no-english`,`warning`,`at-least-one-screenshot`,`screenshots`,`no screenshot without xml:lang (or in English)`),X[0].attrs.type!=="default"&&add(`screenshot-default-not-first`,`warning`,`at-least-one-screenshot`,`screenshot[1]`,`the first screenshot should be type="default" — it is the one users see first`);for(let t=0;t<X.length;t++){let S=X[t],C=`screenshot[${t+1}]`,N=kids(S,`caption`);N.length===0&&add(`screenshot-caption-missing`,`warning`,`image-captions`,C,`no <caption>`);for(let t of N){let n=DV(t.text),S=`${C}/${loc(`caption`,lang(t))}`;/[.。]$/.test(n)&&add(`caption-full-stop`,`warning`,`image-captions`,S,`a caption does not end with a full stop`),/^\d/.test(n)&&add(`caption-starts-with-number`,`warning`,`image-captions`,S,`a caption does not start with a number`),/[.!?]\s+\p{Lu}/u.test(n)&&add(`caption-multiple-sentences`,`warning`,`image-captions`,S,`a caption is one sentence`)}if(n.probeImage!==void 0){let t=kids(S,`image`).find(t=>(t.attrs.type??`source`)===`source`),N=t===void 0?``:DV(t.text),F=N===``?null:await n.probeImage(N);F?.kind===`raster`&&(F.width>2e3||F.height>1400)&&add(`screenshot-too-large`,`warning`,`reasonable-window-size`,C,`${F.width}×${F.height}; keep the window at most 1000×700 (2000×1400 on HiDPI)`)}}}for(let t of kids(child(C,`releases`),`release`)){let n=`release ${t.attrs.version??`?`}`,S=child(t,`description`),C=S===void 0?``:DV(S.text);if(C===``){add(`release-notes-missing`,`warning`,`release-notes-for-every-release`,n,`no release notes`);continue}wV.some(t=>t.test(C.replace(/[.!]+$/,``)))?add(`release-notes-generic`,`warning`,`no-bug-fixes-and-performance-improvements`,n,`"${C}" says nothing about what changed`):([...C].length>600||kids(child(S,`ul`),`li`).length>10)&&add(`release-notes-long`,`warning`,`short-but-informative`,n,`release notes are long; summarise what changed for users`)}return S}function summarizeFindings(t,n){let S=0,C=0;for(let N of t)N.severity===`error`||n?S++:C++;return{errors:S,warnings:C}}function formatFinding(t,n){return`${(n?`error`:t.severity).padEnd(7)} ${t.rule} ${t.location}: ${t.message}\n ${t.url}`}var SV,CV,wV,TV,EV,child,kids,DV,lang,langBase,OV=__esmMin(()=>{Ye(),SV=`https://docs.flathub.org/docs/for-app-authors/metainfo-guidelines/quality-guidelines`,CV=`GTK.GTK3.GTK4.Qt.Qt5.Qt6.libadwaita.Electron.Rust.Python.JavaScript.TypeScript.GJS.Flatpak.written in.open source.open-source.free software.FOSS.app.application.tool.client.wrapper.App.Anwendung.Werkzeug`.split(`.`),wV=[/^(minor |various |general |misc(ellaneous)? )?bug ?fix(es)?( (and|&) (minor )?(performance )?(improvements?|fixes|tweaks))?$/i,/^(minor |various |general )?(performance )?improvements?( (and|&) (bug ?fix(es)?|fixes))?$/i,/^bug ?fix(es)?,? (and )?(performance|stability) improvements?$/i,/^(performance|stability) (improvements?|fixes)( (and|&) bug ?fix(es)?)?$/i,/^(fehlerbehebungen?|fehlerkorrekturen?|verbesserungen)( (und|&) (fehlerbehebungen?|verbesserungen|leistungsverbesserungen))?$/i,/^(kleinere )?(fehlerbehebungen|verbesserungen)$/i],TV={en:[`a`,`an`,`the`],de:[`ein`,`eine`,`einen`,`einem`,`einer`,`der`,`die`,`das`,`den`,`dem`]},EV=__name$1(t=>t.startsWith(`_`)?t.slice(1):t,`normName`),__name$1(buildTree$1,`buildTree`),child=(t,n)=>t?.children.find(t=>t.name===n),kids=(t,n)=>t?.children.filter(t=>t.name===n)??[],DV=__name$1(t=>t.replace(/\s+/g,` `).trim(),`clean`),lang=t=>t.attrs[`xml:lang`]??``,langBase=t=>t.split(/[_\-.@]/)[0].toLowerCase()});function appstreamValidateArgs(t,n=!1){return[`validate`,`--strict`,...n?[]:[`--no-net`],t]}async function runQuality(t,n,S){let C=zn(t),probeImage=async t=>{if(/^https?:\/\//.test(t)){if(!S.qualityNetwork)return null;try{let n=await fetch(t);return n.ok?readImageInfo(new Uint8Array(await n.arrayBuffer())):null}catch{return null}}let n=Nn(C,t);return existsSync(n)?readImageInfo(new Uint8Array(readFileSync(n))):null},N=n??``,F=N?[`icons/hicolor/scalable/apps/${N}.svg`,`icons/${N}.svg`,`${N}.svg`,`${N}.png`,`../data/icons/hicolor/scalable/apps/${N}.svg`]:[],I=await lintMetainfo(readFileSync(t,`utf-8`),{probeImage,iconRefs:F}),H=S.strict===!0,{errors:W,warnings:q}=summarizeFindings(I,H);if(S.json)ge.log(JSON.stringify({file:t,errors:W,warnings:q,findings:I.map(t=>({...t,severity:H?`error`:t.severity}))},null,2));else{for(let t of I)ge.log(formatFinding(t,H));ge.log(`[gjsify flatpak check] ${W===0?`OK`:`FAIL`}: quality ${t} — ${W} error(s), ${q} warning(s)`)}return W===0}function resolveAppId(t,n,S){if(n.appId)return n.appId;try{let t=readPackageJson(S);if(looksLikeAppId(t.name))return t.name}catch{}if(t)return t.replace(/\.json$/,``)}function resolveManifestPath(t,n,S){if(t)return Nn(S,t);if(n)return Nn(S,`${n}.json`);let C=readdirSync(S).filter(t=>t.endsWith(`.json`)&&!t.startsWith(`package`));if(C.length===1)return Nn(S,C[0]);throw Error(`gjsify flatpak check: no manifest path given and could not auto-detect. Pass the manifest as a positional argument.`)}async function runLinter(t,n,S){let C;try{C=await spawnToCompletion(t,n,{completion:`return`,stdio:S?`inherit`:`capture`})}catch(n){let S=n;return S.code===`ENOENT`?ge.error(`[gjsify flatpak check] ${t} not found in PATH.\nInstall via:\n flatpak install -y flathub org.flatpak.Builder\n alias ${t}="flatpak run --command=${t} org.flatpak.Builder"`):ge.error(`[gjsify flatpak check] ${t} failed to spawn: ${S.message}`),!1}let N=C.code===0;return ge.log(`[gjsify flatpak check] ${N?`OK`:`FAIL`}: ${t} ${n.join(` `)}`),!N&&!S&&(C.stdout?.trim()&&ge.log(C.stdout.trimEnd()),C.stderr?.trim()&&ge.error(C.stderr.trimEnd())),N}var kV,AV=__esmMin(()=>{_e(),ef(),qn(),sv(),qB(),rR(),OV(),kV={command:`check [manifest]`,description:`Run Flathub pre-submission linters: appstreamcli validate + flatpak-builder-lint.`,builder:t=>t.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 --no-net` (default: true).",type:`boolean`,default:!0}).option(`quality`,{description:`Run Flathub's quality guidelines (name, summary, branding, screenshots, release notes) on the MetaInfo (default: true).`,type:`boolean`,default:!0}).option(`strict`,{description:`Treat quality warnings as errors.`,type:`boolean`,default:!1}).option(`json`,{description:`Print the quality findings as JSON (and nothing else on stdout).`,type:`boolean`,default:!1}).option(`quality-network`,{description:`Let the quality check fetch http(s) screenshot/icon URLs to measure their size.`,type:`boolean`,default:!1}).option(`appstream-network`,{description:"Let `appstreamcli` fetch the MetaInfo URLs to check they are reachable.",type:`boolean`,default:!1}).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 t=>{let n=(await new Config().forCommand().catch(()=>({}))).flatpak??{},S=process.cwd(),C=resolveAppId(t.manifest,n,S),N=resolveManifestPath(t.manifest,C,S),F=Nn(S,t.metainfo??`data/${C??`unknown`}.metainfo.xml.in`),I=0;if(t.appstream!==!1&&(existsSync(F)?await runLinter(`appstreamcli`,appstreamValidateArgs(F,t.appstreamNetwork===!0),t.verbose??!1)||I++:ge.warn(`[gjsify flatpak check] skipping appstreamcli — ${F} not found`)),t.quality!==!1&&(existsSync(F)?await runQuality(F,C,t)||I++:ge.warn(`[gjsify flatpak check] skipping quality check — ${F} not found`)),t.builderLint!==!1&&!t.json){if(!existsSync(N))return ge.error(`[gjsify flatpak check] manifest not found: ${N}`),process.exit(1);await runLinter(`flatpak-builder-lint`,[`manifest`,N],t.verbose??!1)||I++,t.repo&&(await runLinter(`flatpak-builder-lint`,[`repo`,Nn(S,t.repo)],t.verbose??!1)||I++)}if(I>0)return ge.error(`\n[gjsify flatpak check] ${I} check(s) failed.`),process.exit(1);ge.log(`[gjsify flatpak check] all checks passed.`)}}});async function readSourceListAtTag(t,n,S,C){let N;try{let{stdout:C}=await jV(`git`,[`show`,`${n}:${S}`],{cwd:t,maxBuffer:64*1024*1024});N=C}catch(N){return await assertGitMeantAbsent(t,n,S,N),C&&ge.log(`[gjsify flatpak sync-flathub] ${S} not present at ${n} — skipping`),null}if(N.trim()===``)return C&&ge.log(`[gjsify flatpak sync-flathub] ${S} is empty at ${n} — skipping`),null;let F;try{F=JSON.parse(N)}catch(t){throw Error(`[gjsify flatpak sync-flathub] ${S} at ${n} is not JSON: `+(t instanceof Error?t.message:String(t)))}if(!Array.isArray(F)||F.length===0)throw Error(`[gjsify flatpak sync-flathub] ${S} at ${n} is not a non-empty array of flatpak sources`);return N}async function assertGitMeantAbsent(t,n,S,C){if(typeof C?.code!=`number`)throw Error(`[gjsify flatpak sync-flathub] could not run \`git show ${n}:${S}\` — `+(C instanceof Error?C.message:String(C)));if(!await jV(`git`,[`rev-parse`,`--verify`,`--quiet`,`${n}^{commit}`],{cwd:t}).then(({stdout:t})=>t.trim()).catch(()=>``))throw Error(`[gjsify flatpak sync-flathub] ${n} does not resolve in ${t}, so whether it carries ${S} is unanswered. Run \`git fetch --tags\`, pass --version <an existing tag>, or run from the app checkout.`)}async function resolveLatestTag$1(t,n){try{let{stdout:S}=await jV(`git`,[`describe`,`--tags`,`--abbrev=0`],{cwd:t});return n&&ge.log(`[gjsify flatpak sync-flathub] resolved latest tag → ${S.trim()}`),S.trim()||null}catch{return null}}async function resolveCommitForTag(t,n,S){try{let{stdout:C}=await jV(`git`,[`rev-list`,`-n`,`1`,n],{cwd:t}),N=C.trim();if(!N)throw Error(`empty rev-list output`);return S&&ge.log(`[gjsify flatpak sync-flathub] resolved ${n} → ${N}`),N}catch(t){throw Error(`[gjsify flatpak sync-flathub] tag ${n} not found locally. Run \`git fetch --tags\` or pass --commit <sha>.\n underlying error: ${t instanceof Error?t.message:String(t)}`)}}function normaliseBranchSegment(t){return t.replace(/^v/,``).replace(/[^A-Za-z0-9._-]/g,`-`)}function flathubCacheRoot(){return In(process.env.XDG_CACHE_HOME||In(homedir(),`.cache`),`gjsify`,`flathub-sync`)}async function ensureClone(t,n,S){if(existsSync(In(t,`.git`))){S&&ge.log(`[gjsify flatpak sync-flathub] reusing clone at ${t}`),await gitInRepo(t,[`fetch`,`origin`],S);let n=await detectDefaultBranch(t,S);await gitInRepo(t,[`checkout`,n],S),await gitInRepo(t,[`reset`,`--hard`,`origin/${n}`],S);return}mkdirSync(Nn(t,`..`),{recursive:!0});let C=`https://github.com/${n}.git`;S&&ge.log(`[gjsify flatpak sync-flathub] git clone ${C} ${t}`);try{await jV(`git`,[`clone`,C,t])}catch(t){throw t?.code===`ENOENT`?Error("[gjsify flatpak sync-flathub] `git` not found. Install git from your distro (Fedora: `dnf install git`, Debian: `apt install git`)."):t}}async function detectDefaultBranch(t,n){try{let{stdout:S}=await jV(`git`,[`remote`,`show`,`origin`],{cwd:t}),C=S.match(/HEAD branch: (\S+)/);if(C&&C[1]&&C[1]!==`(unknown)`)return n&&ge.log(`[gjsify flatpak sync-flathub] default branch → ${C[1]}`),C[1]}catch{}return`master`}async function gitInRepo(t,n,S){S&&ge.log(`[gjsify flatpak sync-flathub] git ${n.join(` `)} (in ${t})`);let C=await spawnToCompletion(`git`,n,{completion:`return`,cwd:t,notFound:()=>Error("[gjsify flatpak sync-flathub] `git` not found. Install it from your distro.")});if(C.code!==0)throw Error(`git ${n[0]} exited ${describeExit(C)}`)}async function ghCreate(t,n,S,C,N,F){let I=[`pr`,`create`,`--repo`,n,`--head`,S,`--title`,`Update to ${C}`,`--body`,N];F&&ge.log(`[gjsify flatpak sync-flathub] gh ${I.join(` `)} (in ${t})`);let H=await spawnToCompletion(`gh`,I,{completion:`return`,cwd:t,notFound:()=>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`.")});if(H.code!==0)throw Error(`gh pr create exited ${describeExit(H)}`)}function editManifest(t,n){let S=JSON.parse(t),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 isObject=t=>typeof t==`object`,F=n.sourceIndex??N.findIndex(t=>isObject(t)&&t.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(!isObject(I)||I.type!==`git`){let t=isObject(I)?`type is "${I.type}"`:`is the file reference "${I}"`;throw Error(`[gjsify flatpak sync-flathub] modules[0].sources[${F}] ${t}, expected a git source`)}let H=I;H.tag=n.tag,H.commit=n.commit,H[`x-checker-data`]||={type:`git`,"tag-pattern":`^v(\\d+\\.\\d+\\.\\d+)$`,"version-scheme":`semantic`},n.sourcesFile&&!namesFile(N,n.sourcesFile)&&N.push(n.sourcesFile);let W=detectIndent$1(t);return JSON.stringify(S,null,W)+(t.endsWith(`
1114
+ `}var xV,SV=__esmMin(()=>{_e(),ef(),qn(),rR(),qB(),XB(),eV(),xV={command:`ci`,description:`Scaffold .github/workflows/flatpak.yml using the flathub-infra container + flatpak-builder@v6 action.`,builder:t=>t.option(`manifest`,{description:`Manifest path the workflow points at (default: <app-id>.json)`,type:`string`,normalize:!0}).option(`bundle`,{description:`Bundle filename produced by the action (default: <app-id>.flatpak)`,type:`string`,normalize:!0}).option(`runtime-image`,{description:"Container image override. Default derived from gjsify.flatpak.runtime + runtimeVersion (e.g. `ghcr.io/flathub-infra/flatpak-github-actions:gnome-50`).",type:`string`}).option(`branches`,{description:`Branches the workflow runs on push for (default: main)`,type:`string`,array:!0}).option(`out`,{description:`Output path`,type:`string`,default:`.github/workflows/flatpak.yml`,normalize:!0}).option(`cache-key`,{description:"Override the action `cache-key` (default: `flatpak-builder-${{ github.sha }}`)",type:`string`}).option(`force`,{description:`Overwrite an existing workflow file`,type:`boolean`,default:!1}).option(`verbose`,{description:`Print resolved fields`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=await new Config().forCommand().catch(()=>({})),C=S.flatpak??{},N=readPackageJson(n),F=C.appId??(looksLikeAppId(N.name)?N.name:void 0);if(!F)throw Error(`gjsify flatpak ci: no app id available. Set gjsify.flatpak.appId in package.json or rename the package to a reverse-DNS id.`);let I=t.manifest??`${F}.json`,H=t.bundle??`${F}.flatpak`,W=pickFlatpakBuildKeys(S.ship?.flatpak,C).values,{runtime:q,runtimeVersion:Y}=resolveRuntime(W,{}),X=t.runtimeImage??C.ciContainer??defaultCiContainer(q,Y),Z=t.branches??C.ciBranches??[`main`],te=t.cacheKey??"flatpak-builder-${{ github.sha }}",ne=Nn(n,t.out??`.github/workflows/flatpak.yml`);if(existsSync(ne)&&!t.force){if(readFileSync(ne,`utf-8`)===renderWorkflow({manifest:I,bundle:H,runtimeImage:X,branches:Z,cacheKey:te})){ge.log(`[gjsify flatpak ci] ${ne} already up to date`);return}throw Error(`gjsify flatpak ci: ${ne} exists with different content. Pass --force to overwrite.`)}let re=renderWorkflow({manifest:I,bundle:H,runtimeImage:X,branches:Z,cacheKey:te});mkdirSync(zn(ne),{recursive:!0}),writeFileSync(ne,re,`utf-8`),t.verbose&&ge.log(`[gjsify flatpak ci] runtime-image=${X} manifest=${I} bundle=${H}`),ge.log(`[gjsify flatpak ci] wrote ${ne}`)}}});function buildTree$1(t){let n={name:`#root`,attrs:{},children:[],text:``},S=[n];for(let n of scanXml(t)){let t=S[S.length-1];if(n.kind===`text`)for(let t of S)t.text+=n.text;else if(n.kind===`open`){let C={name:DV(n.name),attrs:n.attributes,children:[],text:``};t.children.push(C),n.selfClosing||S.push(C)}else S.length>1&&S.pop()}return n}function localized(t,n){let S=new Map;for(let C of kids(t,n)){let t=OV(C.text);t!==``&&!S.has(lang(C))&&S.set(lang(C),t)}return S}function parseHex(t){let n=/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(t.trim());if(n===null)return null;let S=n[1];S.length===3&&(S=S.replace(/./g,t=>t+t));let C=Number.parseInt(S.slice(0,2),16)/255,N=Number.parseInt(S.slice(2,4),16)/255,F=Number.parseInt(S.slice(4,6),16)/255,I=Math.max(C,N,F),H=Math.min(C,N,F),W=(I+H)/2,q=I-H;return{s:q===0?0:q/(1-Math.abs(2*W-1)),l:W}}function readImageInfo(t){if(t.length>=24&&t[0]===137&&t[1]===80&&t[2]===78&&t[3]===71){let u32=n=>(t[n]<<24|t[n+1]<<16|t[n+2]<<8|t[n+3])>>>0;return{kind:`raster`,width:u32(16),height:u32(20)}}if(t.length>=4&&t[0]===255&&t[1]===216){let n=2;for(;n+9<t.length;){if(t[n]!==255){n++;continue}let S=t[n+1];if(S===255){n++;continue}if(S>=192&&S<=207&&S!==196&&S!==200&&S!==204)return{kind:`raster`,height:t[n+5]<<8|t[n+6],width:t[n+7]<<8|t[n+8]};n+=2+(t[n+2]<<8|t[n+3])}return null}let n=``;for(let S=0;S<Math.min(t.length,1024);S++)n+=String.fromCharCode(t[S]);return/<svg[\s>]/.test(n)?{kind:`svg`}:null}function termPattern(t,n=`iu`){let S=t.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`).replace(/\s+/g,`\\s+`);return RegExp(`(^|[^\\p{L}\\p{N}])${S}($|[^\\p{L}\\p{N}])`,n)}async function lintMetainfo(t,n={}){let S=[],add=(t,n,C,N,F)=>{S.push({rule:t,severity:n,message:F,location:N,url:`${CV}#${C}`})},C=child(buildTree$1(t),`component`);if(C===void 0)return add(`no-component`,`error`,`app-name`,`document`,`no <component> element found`),S;let loc=(t,n)=>n===``?t:`${t}[${n}]`,N=localized(C,`name`),F=localized(C,`summary`);for(let[t,n]of N){let S=loc(`name`,t),C=[...n].length;if(C>=20?add(`name-too-long`,`error`,`not-too-long`,S,`"${n}" is ${C} characters; a name must be shorter than 20`):C>15&&add(`name-long`,`warning`,`not-too-long`,S,`"${n}" is ${C} characters; ideally at most 15`),/\s[-–—:]\s|:\s|\(.+\)/.test(n)||/\b(web browser|editor|client|viewer|player)$/i.test(n)&&n.includes(` `))add(`name-extra-info`,`warning`,`just-the-name`,S,`"${n}" carries a description; keep just the name and put the rest in the summary`);else if(/[.-]/.test(n))add(`name-formatting`,`warning`,`no-weird-formatting`,S,`"${n}" contains a dot or dash; avoid punctuation in names`);else if(/\p{L}/u.test(n)){let t=n.replace(/[^\p{L}]/gu,``);n===n.toLowerCase()?add(`name-formatting`,`warning`,`no-weird-formatting`,S,`"${n}" is all lowercase`):t.length>1&&n===n.toUpperCase()?add(`name-formatting`,`warning`,`no-weird-formatting`,S,`"${n}" is all uppercase (exempt only for an established brand such as VLC)`):!/\s/.test(n)&&/\p{Ll}\p{Lu}/u.test(n)&&add(`name-formatting`,`warning`,`no-weird-formatting`,S,`"${n}" is camel/pascal case`)}}let I=(n.technicalTerms??[...wV]).map(t=>({term:t,re:termPattern(t)}));for(let[t,n]of F){let S=loc(`summary`,t),C=[...n].length;C>35?add(`summary-too-long`,`error`,`not-too-long-1`,S,`"${n}" is ${C} characters; at most 35 allowed`):(C>25||C<10)&&add(`summary-length`,`warning`,`not-too-long-1`,S,`"${n}" is ${C} characters; ideal is 10 to 25`),/[.。]$/.test(n)&&add(`summary-full-stop`,`warning`,`no-weird-formatting-1`,S,`a summary does not end with a full stop`);let F=n.split(/\s+/).filter(t=>/^\p{L}/u.test(t)),H=F.filter(t=>/^\p{Lu}/u.test(t)).length;F.length>=3&&H/F.length>=.75&&add(`summary-title-case`,`warning`,`no-weird-formatting-1`,S,`use sentence case, not Title Case`);let W=EV[langBase(t===``?`en`:t)],q=n.split(/\s+/)[0]?.toLowerCase();W?.includes(q)&&add(`summary-article`,`warning`,`dont-start-with-an-article`,S,`starts with the article "${q}"; omit it or phrase it with a verb`);let Y=N.get(t)??N.get(``);Y!==void 0&&[...Y].length>=3&&termPattern(Y,`u`).test(n)&&add(`summary-repeats-name`,`warning`,`dont-repeat-the-name`,S,`repeats the app name "${Y}"`);let X=I.find(({re:t})=>t.test(n));X!==void 0&&add(`summary-technical`,`warning`,`not-technical`,S,`mentions "${X.term}"; say what the app does for people, not how it is built`)}let H=kids(C,`description`).find(t=>lang(t)===``)??child(C,`description`);if(H!==void 0){let t=F.get(``)??``,n=kids(H,`p`).filter(t=>lang(t)===``).map(t=>OV(t.text)),S=n.join(` `);t!==``&&n.length>0&&n[0].replace(/[.!]$/,``).toLowerCase()===t.toLowerCase()&&add(`description-repeats-summary`,`warning`,`dont-repeat-the-summary`,`description`,`the first paragraph repeats the summary`),t!==``&&[...S].length<Math.max(80,3*[...t].length)&&add(`description-short`,`warning`,`not-too-short`,`description`,`${[...S].length} characters; it should be substantially longer than the summary`);for(let t of[...kids(H,`ul`),...kids(H,`ol`)]){let n=kids(t,`li`).filter(t=>lang(t)===``).length;n>10&&add(`description-long-list`,`warning`,`no-super-long-lists`,`description`,`a list with ${n} items; group them or use paragraphs (max 10)`)}}let W=kids(child(C,`branding`),`color`).filter(t=>t.attrs.type===`primary`),q=W.find(t=>t.attrs.scheme_preference===`light`),Y=W.find(t=>t.attrs.scheme_preference===`dark`);if(q===void 0||Y===void 0)add(`branding-missing`,`warning`,`has-primary-brand-colors`,`branding`,`set two primary brand colors, scheme_preference="light" and "dark"`);else{let t=OV(q.text).toLowerCase(),n=OV(Y.text).toLowerCase();t===n&&add(`branding-identical`,`warning`,`good-brand-colors`,`branding`,`light and dark primary colors are the same`);let S=parseHex(t),C=parseHex(n);for(let[N,F,I]of[[`light`,S,t],[`dark`,C,n]])F!==null&&(F.s<.15||F.l>.93||F.l<.07)&&add(`branding-dull`,`warning`,`good-brand-colors`,`branding/${N}`,`${I} is near white, black or gray; brand colors should be colorful`);S!==null&&C!==null&&t!==n&&C.l>=S.l&&add(`branding-dark-not-darker`,`warning`,`good-brand-colors`,`branding/dark`,`the dark variant should be darker than the light one`)}if(n.probeImage!==void 0)for(let t of n.iconRefs??[]){let S=await n.probeImage(t);if(S!==null){S.kind===`raster`&&(S.width===S.height?S.width<256&&add(`icon-too-small`,`error`,`icon-size`,`icon`,`${t} is ${S.width}×${S.height}; use SVG or at least 256×256`):add(`icon-not-square`,`error`,`icon-size`,`icon`,`${t} is ${S.width}×${S.height}; the icon has to be square`));break}}let X=kids(child(C,`screenshots`),`screenshot`);if(X.length===0)add(`screenshot-missing`,`warning`,`at-least-one-screenshot`,`screenshots`,`at least one screenshot is expected`);else{let englishTag=t=>t===``||langBase(t)===`en`,isEnglish=t=>{let n=kids(t,`image`).map(lang);return englishTag(lang(t))&&(n.length===0||n.some(englishTag))};X.some(isEnglish)||add(`screenshot-no-english`,`warning`,`at-least-one-screenshot`,`screenshots`,`no screenshot without xml:lang (or in English)`),X[0].attrs.type!=="default"&&add(`screenshot-default-not-first`,`warning`,`at-least-one-screenshot`,`screenshot[1]`,`the first screenshot should be type="default" — it is the one users see first`);for(let t=0;t<X.length;t++){let S=X[t],C=`screenshot[${t+1}]`,N=kids(S,`caption`);N.length===0&&add(`screenshot-caption-missing`,`warning`,`image-captions`,C,`no <caption>`);for(let t of N){let n=OV(t.text),S=`${C}/${loc(`caption`,lang(t))}`;/[.。]$/.test(n)&&add(`caption-full-stop`,`warning`,`image-captions`,S,`a caption does not end with a full stop`),/^\d/.test(n)&&add(`caption-starts-with-number`,`warning`,`image-captions`,S,`a caption does not start with a number`),/[.!?]\s+\p{Lu}/u.test(n)&&add(`caption-multiple-sentences`,`warning`,`image-captions`,S,`a caption is one sentence`)}if(n.probeImage!==void 0){let t=kids(S,`image`).find(t=>(t.attrs.type??`source`)===`source`),N=t===void 0?``:OV(t.text),F=N===``?null:await n.probeImage(N);F?.kind===`raster`&&(F.width>2e3||F.height>1400)&&add(`screenshot-too-large`,`warning`,`reasonable-window-size`,C,`${F.width}×${F.height}; keep the window at most 1000×700 (2000×1400 on HiDPI)`)}}}for(let t of kids(child(C,`releases`),`release`)){let n=`release ${t.attrs.version??`?`}`,S=child(t,`description`),C=S===void 0?``:OV(S.text);if(C===``){add(`release-notes-missing`,`warning`,`release-notes-for-every-release`,n,`no release notes`);continue}TV.some(t=>t.test(C.replace(/[.!]+$/,``)))?add(`release-notes-generic`,`warning`,`no-bug-fixes-and-performance-improvements`,n,`"${C}" says nothing about what changed`):([...C].length>600||kids(child(S,`ul`),`li`).length>10)&&add(`release-notes-long`,`warning`,`short-but-informative`,n,`release notes are long; summarise what changed for users`)}return S}function summarizeFindings(t,n){let S=0,C=0;for(let N of t)N.severity===`error`||n?S++:C++;return{errors:S,warnings:C}}function formatFinding(t,n){return`${(n?`error`:t.severity).padEnd(7)} ${t.rule} ${t.location}: ${t.message}\n ${t.url}`}var CV,wV,TV,EV,DV,child,kids,OV,lang,langBase,kV=__esmMin(()=>{Ye(),CV=`https://docs.flathub.org/docs/for-app-authors/metainfo-guidelines/quality-guidelines`,wV=`GTK.GTK3.GTK4.Qt.Qt5.Qt6.libadwaita.Electron.Rust.Python.JavaScript.TypeScript.GJS.Flatpak.written in.open source.open-source.free software.FOSS.app.application.tool.client.wrapper.App.Anwendung.Werkzeug`.split(`.`),TV=[/^(minor |various |general |misc(ellaneous)? )?bug ?fix(es)?( (and|&) (minor )?(performance )?(improvements?|fixes|tweaks))?$/i,/^(minor |various |general )?(performance )?improvements?( (and|&) (bug ?fix(es)?|fixes))?$/i,/^bug ?fix(es)?,? (and )?(performance|stability) improvements?$/i,/^(performance|stability) (improvements?|fixes)( (and|&) bug ?fix(es)?)?$/i,/^(fehlerbehebungen?|fehlerkorrekturen?|verbesserungen)( (und|&) (fehlerbehebungen?|verbesserungen|leistungsverbesserungen))?$/i,/^(kleinere )?(fehlerbehebungen|verbesserungen)$/i],EV={en:[`a`,`an`,`the`],de:[`ein`,`eine`,`einen`,`einem`,`einer`,`der`,`die`,`das`,`den`,`dem`]},DV=__name$1(t=>t.startsWith(`_`)?t.slice(1):t,`normName`),__name$1(buildTree$1,`buildTree`),child=(t,n)=>t?.children.find(t=>t.name===n),kids=(t,n)=>t?.children.filter(t=>t.name===n)??[],OV=__name$1(t=>t.replace(/\s+/g,` `).trim(),`clean`),lang=t=>t.attrs[`xml:lang`]??``,langBase=t=>t.split(/[_\-.@]/)[0].toLowerCase()});function appstreamValidateArgs(t,n=!1){return[`validate`,`--strict`,...n?[]:[`--no-net`],t]}async function runQuality(t,n,S){let C=zn(t),probeImage=async t=>{if(/^https?:\/\//.test(t)){if(!S.qualityNetwork)return null;try{let n=await fetch(t);return n.ok?readImageInfo(new Uint8Array(await n.arrayBuffer())):null}catch{return null}}let n=Nn(C,t);return existsSync(n)?readImageInfo(new Uint8Array(readFileSync(n))):null},N=n??``,F=N?[`icons/hicolor/scalable/apps/${N}.svg`,`icons/${N}.svg`,`${N}.svg`,`${N}.png`,`../data/icons/hicolor/scalable/apps/${N}.svg`]:[],I=await lintMetainfo(readFileSync(t,`utf-8`),{probeImage,iconRefs:F}),H=S.strict===!0,{errors:W,warnings:q}=summarizeFindings(I,H);if(S.json)ge.log(JSON.stringify({file:t,errors:W,warnings:q,findings:I.map(t=>({...t,severity:H?`error`:t.severity}))},null,2));else{for(let t of I)ge.log(formatFinding(t,H));ge.log(`[gjsify flatpak check] ${W===0?`OK`:`FAIL`}: quality ${t} — ${W} error(s), ${q} warning(s)`)}return W===0}function resolveAppId(t,n,S){if(n.appId)return n.appId;try{let t=readPackageJson(S);if(looksLikeAppId(t.name))return t.name}catch{}if(t)return t.replace(/\.json$/,``)}function resolveManifestPath(t,n,S){if(t)return Nn(S,t);if(n)return Nn(S,`${n}.json`);let C=readdirSync(S).filter(t=>t.endsWith(`.json`)&&!t.startsWith(`package`));if(C.length===1)return Nn(S,C[0]);throw Error(`gjsify flatpak check: no manifest path given and could not auto-detect. Pass the manifest as a positional argument.`)}async function runLinter(t,n,S){let C;try{C=await spawnToCompletion(t,n,{completion:`return`,stdio:S?`inherit`:`capture`})}catch(n){let S=n;return S.code===`ENOENT`?ge.error(`[gjsify flatpak check] ${t} not found in PATH.\nInstall via:\n flatpak install -y flathub org.flatpak.Builder\n alias ${t}="flatpak run --command=${t} org.flatpak.Builder"`):ge.error(`[gjsify flatpak check] ${t} failed to spawn: ${S.message}`),!1}let N=C.code===0;return ge.log(`[gjsify flatpak check] ${N?`OK`:`FAIL`}: ${t} ${n.join(` `)}`),!N&&!S&&(C.stdout?.trim()&&ge.log(C.stdout.trimEnd()),C.stderr?.trim()&&ge.error(C.stderr.trimEnd())),N}var AV,jV=__esmMin(()=>{_e(),ef(),qn(),sv(),qB(),rR(),kV(),AV={command:`check [manifest]`,description:`Run Flathub pre-submission linters: appstreamcli validate + flatpak-builder-lint.`,builder:t=>t.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 --no-net` (default: true).",type:`boolean`,default:!0}).option(`quality`,{description:`Run Flathub's quality guidelines (name, summary, branding, screenshots, release notes) on the MetaInfo (default: true).`,type:`boolean`,default:!0}).option(`strict`,{description:`Treat quality warnings as errors.`,type:`boolean`,default:!1}).option(`json`,{description:`Print the quality findings as JSON (and nothing else on stdout).`,type:`boolean`,default:!1}).option(`quality-network`,{description:`Let the quality check fetch http(s) screenshot/icon URLs to measure their size.`,type:`boolean`,default:!1}).option(`appstream-network`,{description:"Let `appstreamcli` fetch the MetaInfo URLs to check they are reachable.",type:`boolean`,default:!1}).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 t=>{let n=(await new Config().forCommand().catch(()=>({}))).flatpak??{},S=process.cwd(),C=resolveAppId(t.manifest,n,S),N=resolveManifestPath(t.manifest,C,S),F=Nn(S,t.metainfo??`data/${C??`unknown`}.metainfo.xml.in`),I=0;if(t.appstream!==!1&&(existsSync(F)?await runLinter(`appstreamcli`,appstreamValidateArgs(F,t.appstreamNetwork===!0),t.verbose??!1)||I++:ge.warn(`[gjsify flatpak check] skipping appstreamcli — ${F} not found`)),t.quality!==!1&&(existsSync(F)?await runQuality(F,C,t)||I++:ge.warn(`[gjsify flatpak check] skipping quality check — ${F} not found`)),t.builderLint!==!1&&!t.json){if(!existsSync(N))return ge.error(`[gjsify flatpak check] manifest not found: ${N}`),process.exit(1);await runLinter(`flatpak-builder-lint`,[`manifest`,N],t.verbose??!1)||I++,t.repo&&(await runLinter(`flatpak-builder-lint`,[`repo`,Nn(S,t.repo)],t.verbose??!1)||I++)}if(I>0)return ge.error(`\n[gjsify flatpak check] ${I} check(s) failed.`),process.exit(1);ge.log(`[gjsify flatpak check] all checks passed.`)}}});async function readSourceListAtTag(t,n,S,C){let N;try{let{stdout:C}=await MV(`git`,[`show`,`${n}:${S}`],{cwd:t,maxBuffer:64*1024*1024});N=C}catch(N){return await assertGitMeantAbsent(t,n,S,N),C&&ge.log(`[gjsify flatpak sync-flathub] ${S} not present at ${n} — skipping`),null}if(N.trim()===``)return C&&ge.log(`[gjsify flatpak sync-flathub] ${S} is empty at ${n} — skipping`),null;let F;try{F=JSON.parse(N)}catch(t){throw Error(`[gjsify flatpak sync-flathub] ${S} at ${n} is not JSON: `+(t instanceof Error?t.message:String(t)))}if(!Array.isArray(F)||F.length===0)throw Error(`[gjsify flatpak sync-flathub] ${S} at ${n} is not a non-empty array of flatpak sources`);return N}async function assertGitMeantAbsent(t,n,S,C){if(typeof C?.code!=`number`)throw Error(`[gjsify flatpak sync-flathub] could not run \`git show ${n}:${S}\` — `+(C instanceof Error?C.message:String(C)));if(!await MV(`git`,[`rev-parse`,`--verify`,`--quiet`,`${n}^{commit}`],{cwd:t}).then(({stdout:t})=>t.trim()).catch(()=>``))throw Error(`[gjsify flatpak sync-flathub] ${n} does not resolve in ${t}, so whether it carries ${S} is unanswered. Run \`git fetch --tags\`, pass --version <an existing tag>, or run from the app checkout.`)}async function resolveLatestTag$1(t,n){try{let{stdout:S}=await MV(`git`,[`describe`,`--tags`,`--abbrev=0`],{cwd:t});return n&&ge.log(`[gjsify flatpak sync-flathub] resolved latest tag → ${S.trim()}`),S.trim()||null}catch{return null}}async function resolveCommitForTag(t,n,S){try{let{stdout:C}=await MV(`git`,[`rev-list`,`-n`,`1`,n],{cwd:t}),N=C.trim();if(!N)throw Error(`empty rev-list output`);return S&&ge.log(`[gjsify flatpak sync-flathub] resolved ${n} → ${N}`),N}catch(t){throw Error(`[gjsify flatpak sync-flathub] tag ${n} not found locally. Run \`git fetch --tags\` or pass --commit <sha>.\n underlying error: ${t instanceof Error?t.message:String(t)}`)}}function normaliseBranchSegment(t){return t.replace(/^v/,``).replace(/[^A-Za-z0-9._-]/g,`-`)}function flathubCacheRoot(){return In(process.env.XDG_CACHE_HOME||In(homedir(),`.cache`),`gjsify`,`flathub-sync`)}async function ensureClone(t,n,S){if(existsSync(In(t,`.git`))){S&&ge.log(`[gjsify flatpak sync-flathub] reusing clone at ${t}`),await gitInRepo(t,[`fetch`,`origin`],S);let n=await detectDefaultBranch(t,S);await gitInRepo(t,[`checkout`,n],S),await gitInRepo(t,[`reset`,`--hard`,`origin/${n}`],S);return}mkdirSync(Nn(t,`..`),{recursive:!0});let C=`https://github.com/${n}.git`;S&&ge.log(`[gjsify flatpak sync-flathub] git clone ${C} ${t}`);try{await MV(`git`,[`clone`,C,t])}catch(t){throw t?.code===`ENOENT`?Error("[gjsify flatpak sync-flathub] `git` not found. Install git from your distro (Fedora: `dnf install git`, Debian: `apt install git`)."):t}}async function detectDefaultBranch(t,n){try{let{stdout:S}=await MV(`git`,[`remote`,`show`,`origin`],{cwd:t}),C=S.match(/HEAD branch: (\S+)/);if(C&&C[1]&&C[1]!==`(unknown)`)return n&&ge.log(`[gjsify flatpak sync-flathub] default branch → ${C[1]}`),C[1]}catch{}return`master`}async function gitInRepo(t,n,S){S&&ge.log(`[gjsify flatpak sync-flathub] git ${n.join(` `)} (in ${t})`);let C=await spawnToCompletion(`git`,n,{completion:`return`,cwd:t,notFound:()=>Error("[gjsify flatpak sync-flathub] `git` not found. Install it from your distro.")});if(C.code!==0)throw Error(`git ${n[0]} exited ${describeExit(C)}`)}async function ghCreate(t,n,S,C,N,F){let I=[`pr`,`create`,`--repo`,n,`--head`,S,`--title`,`Update to ${C}`,`--body`,N];F&&ge.log(`[gjsify flatpak sync-flathub] gh ${I.join(` `)} (in ${t})`);let H=await spawnToCompletion(`gh`,I,{completion:`return`,cwd:t,notFound:()=>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`.")});if(H.code!==0)throw Error(`gh pr create exited ${describeExit(H)}`)}function editManifest(t,n){let S=JSON.parse(t),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 isObject=t=>typeof t==`object`,F=n.sourceIndex??N.findIndex(t=>isObject(t)&&t.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(!isObject(I)||I.type!==`git`){let t=isObject(I)?`type is "${I.type}"`:`is the file reference "${I}"`;throw Error(`[gjsify flatpak sync-flathub] modules[0].sources[${F}] ${t}, expected a git source`)}let H=I;H.tag=n.tag,H.commit=n.commit,H[`x-checker-data`]||={type:`git`,"tag-pattern":`^v(\\d+\\.\\d+\\.\\d+)$`,"version-scheme":`semantic`},n.sourcesFile&&!namesFile(N,n.sourcesFile)&&N.push(n.sourcesFile);let W=detectIndent$1(t);return JSON.stringify(S,null,W)+(t.endsWith(`
1115
1115
  `)?`
1116
- `:``)}function namesFile(t,n){let S=stripDotSlash(n);return t.some(t=>typeof t==`string`&&stripDotSlash(t)===S)}function stripDotSlash(t){return t.replace(/^\.\//,``)}function detectIndent$1(t){let n=t.match(/^\{\n( +)/);return n?n[1].length:2}var jV,MV,NV=__esmMin(()=>{_e(),ef(),qn(),$g(),ev(),sv(),zu(),rR(),qB(),jV=promisify(execFile),MV={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:t=>t.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(`sources-file`,{description:`Generated offline tarball list to carry into the Flathub repo and name in the manifest. Default: \`${KB}\`. Skipped when the tag does not carry it.`,type:`string`,default:KB}).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 t=>{let n=process.cwd(),S=(await new Config().forCommand().catch(()=>({}))).flatpak??{},C=t.appId??S.appId??readPackageJson(n).name;if(!C)throw Error(`[gjsify flatpak sync-flathub] no app id available — pass --app-id or set gjsify.flatpak.appId.`);let N=t.flathubRepo??S.flathubRepo??`flathub/${C}`,F=t.version??await resolveLatestTag$1(n,t.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=t.commit??await resolveCommitForTag(n,F,t.verbose),H=t.branch??`update-to-${normaliseBranchSegment(F)}`;if(ge.log(`[gjsify flatpak sync-flathub] appId=${C}`),ge.log(`[gjsify flatpak sync-flathub] flathubRepo=${N}`),ge.log(`[gjsify flatpak sync-flathub] version=${F}`),ge.log(`[gjsify flatpak sync-flathub] commit=${I}`),ge.log(`[gjsify flatpak sync-flathub] branch=${H}`),t.dryRun){ge.log(`[gjsify flatpak sync-flathub] --dry-run set; not cloning / writing / pushing.`);return}let W=flathubCacheRoot(),q=In(W,N.replace(`/`,`__`));mkdirSync(W,{recursive:!0}),await ensureClone(q,N,t.verbose);let Y=In(q,`${C}.json`);if(!existsSync(Y))throw Error(`[gjsify flatpak sync-flathub] Flathub manifest not found at ${Y} — wrong appId / wrong flathub-repo?`);let X=t.sourcesFile??`gjsify-sources.json`,Z=await readSourceListAtTag(n,F,X,t.verbose),te=!1;if(Z!==null){let t=In(q,X);te=!existsSync(t)||readFileSync(t,`utf-8`)!==Z,te&&(writeFileSync(t,Z,`utf-8`),ge.log(`[gjsify flatpak sync-flathub] ${X} copied from ${F}`))}let ne=readFileSync(Y,`utf-8`),re=editManifest(ne,{tag:F,commit:I,sourceIndex:t.sourceIndex,sourcesFile:Z===null?void 0:X});if(re===ne&&!te){ge.log(`[gjsify flatpak sync-flathub] manifest already at ${F} — nothing to do.`);return}if(writeFileSync(Y,re,`utf-8`),ge.log(`[gjsify flatpak sync-flathub] manifest patched at ${Y}`),await gitInRepo(q,[`checkout`,`-B`,H],t.verbose),await gitInRepo(q,[`add`,`.`],t.verbose),await gitInRepo(q,[`commit`,`-m`,`Update to ${F}`],t.verbose),t.pr===!1){ge.log(`[gjsify flatpak sync-flathub] --no-pr set; branch ${H} committed locally in ${q}.`);return}await gitInRepo(q,[`push`,`-u`,`origin`,H,`--force-with-lease`],t.verbose),await ghCreate(q,N,H,F,`Auto-generated by \`gjsify flatpak sync-flathub\`.\n\n- Version: \`${F}\`\n- Commit: \`${I}\`\n`,t.verbose)}},__name$1(resolveLatestTag$1,`resolveLatestTag`),__name$1(detectIndent$1,`detectIndent`)});async function loadFlathubSource(t,n){let S;if(t.against){if(!existsSync(t.against))throw Error(`[gjsify flatpak diff] --against path ${t.against} does not exist`);S=readFileSync(t.against,`utf-8`)}else S=await fetchFlathubManifest(t.flathubRepo,t.appId,t.verbose);let C;try{C=JSON.parse(S)}catch(t){throw Error(`[gjsify flatpak diff] failed to parse Flathub manifest as JSON: ${t.message}`)}let N=(C.modules??[])[0]?.sources??[];if(N.length===0)return null;let F=n??N.findIndex(t=>isSourceObject(t)&&t.type===`git`);if(F<0||F>=N.length)return null;let I=N[F];return isSourceObject(I)?I:null}function isSourceObject(t){return typeof t==`object`&&!!t}async function fetchFlathubManifest(t,n,S){for(let C of[`master`,`main`]){let N=`https://raw.githubusercontent.com/${t}/${C}/${n}.json`;S&&ge.log(`[gjsify flatpak diff] fetch ${N}`);try{let t=await fetch(N);if(t.ok)return await t.text();S&&ge.log(`[gjsify flatpak diff] ${C} → HTTP ${t.status}`)}catch(t){S&&ge.log(`[gjsify flatpak diff] ${C} fetch error: ${t.message}`)}}throw Error(`[gjsify flatpak diff] could not fetch flathub manifest from ${t} on master or main`)}async function resolveLatestTag(t,n){try{let{stdout:S}=await PV(`git`,[`describe`,`--tags`,`--abbrev=0`],{cwd:t}),C=S.trim();return n&&ge.log(`[gjsify flatpak diff] local latest tag → ${C}`),C||null}catch{return null}}var PV,FV,IV=__esmMin(()=>{_e(),ef(),ev(),zu(),rR(),qB(),PV=promisify(execFile),FV={command:`diff`,description:`Compare the per-app Flathub tracking-repo manifest against the local git state and report version / commit drift.`,builder:t=>t.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 t=>{let n=process.cwd(),S=(await new Config().forCommand().catch(()=>({}))).flatpak??{},C=t.appId??S.appId??readPackageJson(n).name;if(!C)throw Error(`[gjsify flatpak diff] no app id available — pass --app-id or set gjsify.flatpak.appId.`);let N=t.flathubRepo??S.flathubRepo??`flathub/${C}`,F=t.version??await resolveLatestTag(n,t.verbose),I=await loadFlathubSource({appId:C,flathubRepo:N,against:t.against,verbose:t.verbose},t.sourceIndex),H=I?.tag,W=I?.commit;if(ge.log(`[gjsify flatpak diff] appId=${C}`),ge.log(`[gjsify flatpak diff] flathubRepo=${N}`),ge.log(`[gjsify flatpak diff] flathub: tag=${H??`(missing)`} commit=${W??`(missing)`}`),ge.log(`[gjsify flatpak diff] local: tag=${F??`(none)`}`),t.detail&&I&&(ge.log(`[gjsify flatpak diff] flathub manifest source:`),ge.log(JSON.stringify(I,null,2))),!F){ge.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)return ge.warn("[gjsify flatpak diff] flathub manifest has no `tag` field on the inspected source."),process.exit(1);if(H===F){ge.log(`✅ in sync (${F})`);return}ge.log(`❌ drift detected — flathub=${H} vs local=${F}`),ge.log(` run \`gjsify flatpak sync-flathub --version ${F}\` to update the Flathub manifest.`),process.exit(1)}}});function resolveCliEntry(){return Nn(Nn(zn(fileURLToPath(import.meta.url)),`..`,`..`),`index.js`)}async function runNode(t,n){let S=await spawnToCompletion(`node`,t,{completion:`return`,cwd:n});if(S.code!==0)throw Error(`sub-command exited with ${describeExit(S)}: node ${t.join(` `)}`)}var LV,RV,zV=__esmMin(()=>{_e(),ev(),sv(),zu(),ir(),qn(),LV=promisify(execFile),RV={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:t=>t.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 t=>{let n=typeof t.version==`string`?t.version.trim():``;if(!n)throw Error(`[gjsify flatpak release] missing <version> positional`);let S=resolveCliEntry(),C=process.cwd(),N=[];t.skipInit||N.push({name:`init`,args:[S,`flatpak`,`init`,`--force`]}),t.skipCheck||N.push({name:`check`,args:[S,`flatpak`,`check`]});let F=[S,`flatpak`,`sync-flathub`,`--version`,n];if(t.flathubRepo&&F.push(`--flathub-repo`,t.flathubRepo),t.verbose&&F.push(`--verbose`),ge.log(`[gjsify flatpak release] starting release of ${n}`),t.dryRun){ge.log(`[gjsify flatpak release] --dry-run set; printing plan only:`);for(let t of N)ge.log(` · ${t.name}: node ${t.args.join(` `)}`);t.skipTag||ge.log(` · tag: git tag ${n}${t.pushTag===!1?``:` && git push origin `+n}`),ge.log(` · sync: node ${F.join(` `)}`);return}for(let n of N)t.verbose&&ge.log(`[gjsify flatpak release] step ${n.name}: node ${n.args.join(` `)}`),await runNode(n.args,C),ge.log(`[gjsify flatpak release] ${n.name} ✔`);if(!t.skipTag){t.verbose&&ge.log(`[gjsify flatpak release] git tag ${n}`);try{await LV(`git`,[`tag`,n],{cwd:C}),ge.log(`[gjsify flatpak release] tag ${n} created`)}catch(t){throw Error(`[gjsify flatpak release] git tag failed (${t.message}). If the tag already exists, re-run with --skip-tag.`)}t.pushTag!==!1&&(t.verbose&&ge.log(`[gjsify flatpak release] git push origin ${n}`),await LV(`git`,[`push`,`origin`,n],{cwd:C}),ge.log(`[gjsify flatpak release] tag pushed`))}t.verbose&&ge.log(`[gjsify flatpak release] sync: node ${F.join(` `)}`),await runNode(F,C),ge.log(`[gjsify flatpak release] ✅ release ${n} complete`)}}}),BV,VV=__esmMin(()=>{cV(),uV(),fV(),yV(),xV(),AV(),NV(),IV(),zV(),BV={command:`flatpak <subcommand>`,description:`Flatpak toolchain: init/build/deps/sources/ci/check/sync-flathub/diff/release subcommands for shipping GJS apps and CLIs as Flatpaks.`,builder:t=>t.command(sV.command,sV.description,sV.builder,sV.handler).command(lV.command,lV.description,lV.builder,lV.handler).command(dV.command,dV.description,dV.builder,dV.handler).command(vV.command,vV.description,vV.builder,vV.handler).command(bV.command,bV.description,bV.builder,bV.handler).command(kV.command,kV.description,kV.builder,kV.handler).command(MV.command,MV.description,MV.builder,MV.handler).command(FV.command,FV.description,FV.builder,FV.handler).command(RV.command,RV.description,RV.builder,RV.handler).demandCommand(1).strict()}});function concatBytes(t){let n=0;for(let S of t)n+=S.byteLength;let S=new Uint8Array(n),C=0;for(let n of t)S.set(n,C),C+=n.byteLength;return S}function encodeUtf8(t){return new TextEncoder().encode(t)}var HV=__esmMin(()=>{});function createArArchive(t){let n=[encodeUtf8(UV)];for(let S of t)n.push(buildMemberHeader(S)),n.push(S.data),S.data.byteLength%2==1&&n.push(encodeUtf8(`
1116
+ `:``)}function namesFile(t,n){let S=stripDotSlash(n);return t.some(t=>typeof t==`string`&&stripDotSlash(t)===S)}function stripDotSlash(t){return t.replace(/^\.\//,``)}function detectIndent$1(t){let n=t.match(/^\{\n( +)/);return n?n[1].length:2}var MV,NV,PV=__esmMin(()=>{_e(),ef(),qn(),$g(),ev(),sv(),zu(),rR(),qB(),MV=promisify(execFile),NV={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:t=>t.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(`sources-file`,{description:`Generated offline tarball list to carry into the Flathub repo and name in the manifest. Default: \`${KB}\`. Skipped when the tag does not carry it.`,type:`string`,default:KB}).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 t=>{let n=process.cwd(),S=(await new Config().forCommand().catch(()=>({}))).flatpak??{},C=t.appId??S.appId??readPackageJson(n).name;if(!C)throw Error(`[gjsify flatpak sync-flathub] no app id available — pass --app-id or set gjsify.flatpak.appId.`);let N=t.flathubRepo??S.flathubRepo??`flathub/${C}`,F=t.version??await resolveLatestTag$1(n,t.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=t.commit??await resolveCommitForTag(n,F,t.verbose),H=t.branch??`update-to-${normaliseBranchSegment(F)}`;if(ge.log(`[gjsify flatpak sync-flathub] appId=${C}`),ge.log(`[gjsify flatpak sync-flathub] flathubRepo=${N}`),ge.log(`[gjsify flatpak sync-flathub] version=${F}`),ge.log(`[gjsify flatpak sync-flathub] commit=${I}`),ge.log(`[gjsify flatpak sync-flathub] branch=${H}`),t.dryRun){ge.log(`[gjsify flatpak sync-flathub] --dry-run set; not cloning / writing / pushing.`);return}let W=flathubCacheRoot(),q=In(W,N.replace(`/`,`__`));mkdirSync(W,{recursive:!0}),await ensureClone(q,N,t.verbose);let Y=In(q,`${C}.json`);if(!existsSync(Y))throw Error(`[gjsify flatpak sync-flathub] Flathub manifest not found at ${Y} — wrong appId / wrong flathub-repo?`);let X=t.sourcesFile??`gjsify-sources.json`,Z=await readSourceListAtTag(n,F,X,t.verbose),te=!1;if(Z!==null){let t=In(q,X);te=!existsSync(t)||readFileSync(t,`utf-8`)!==Z,te&&(writeFileSync(t,Z,`utf-8`),ge.log(`[gjsify flatpak sync-flathub] ${X} copied from ${F}`))}let ne=readFileSync(Y,`utf-8`),re=editManifest(ne,{tag:F,commit:I,sourceIndex:t.sourceIndex,sourcesFile:Z===null?void 0:X});if(re===ne&&!te){ge.log(`[gjsify flatpak sync-flathub] manifest already at ${F} — nothing to do.`);return}if(writeFileSync(Y,re,`utf-8`),ge.log(`[gjsify flatpak sync-flathub] manifest patched at ${Y}`),await gitInRepo(q,[`checkout`,`-B`,H],t.verbose),await gitInRepo(q,[`add`,`.`],t.verbose),await gitInRepo(q,[`commit`,`-m`,`Update to ${F}`],t.verbose),t.pr===!1){ge.log(`[gjsify flatpak sync-flathub] --no-pr set; branch ${H} committed locally in ${q}.`);return}await gitInRepo(q,[`push`,`-u`,`origin`,H,`--force-with-lease`],t.verbose),await ghCreate(q,N,H,F,`Auto-generated by \`gjsify flatpak sync-flathub\`.\n\n- Version: \`${F}\`\n- Commit: \`${I}\`\n`,t.verbose)}},__name$1(resolveLatestTag$1,`resolveLatestTag`),__name$1(detectIndent$1,`detectIndent`)});async function loadFlathubSource(t,n){let S;if(t.against){if(!existsSync(t.against))throw Error(`[gjsify flatpak diff] --against path ${t.against} does not exist`);S=readFileSync(t.against,`utf-8`)}else S=await fetchFlathubManifest(t.flathubRepo,t.appId,t.verbose);let C;try{C=JSON.parse(S)}catch(t){throw Error(`[gjsify flatpak diff] failed to parse Flathub manifest as JSON: ${t.message}`)}let N=(C.modules??[])[0]?.sources??[];if(N.length===0)return null;let F=n??N.findIndex(t=>isSourceObject(t)&&t.type===`git`);if(F<0||F>=N.length)return null;let I=N[F];return isSourceObject(I)?I:null}function isSourceObject(t){return typeof t==`object`&&!!t}async function fetchFlathubManifest(t,n,S){for(let C of[`master`,`main`]){let N=`https://raw.githubusercontent.com/${t}/${C}/${n}.json`;S&&ge.log(`[gjsify flatpak diff] fetch ${N}`);try{let t=await fetch(N);if(t.ok)return await t.text();S&&ge.log(`[gjsify flatpak diff] ${C} → HTTP ${t.status}`)}catch(t){S&&ge.log(`[gjsify flatpak diff] ${C} fetch error: ${t.message}`)}}throw Error(`[gjsify flatpak diff] could not fetch flathub manifest from ${t} on master or main`)}async function resolveLatestTag(t,n){try{let{stdout:S}=await FV(`git`,[`describe`,`--tags`,`--abbrev=0`],{cwd:t}),C=S.trim();return n&&ge.log(`[gjsify flatpak diff] local latest tag → ${C}`),C||null}catch{return null}}var FV,IV,LV=__esmMin(()=>{_e(),ef(),ev(),zu(),rR(),qB(),FV=promisify(execFile),IV={command:`diff`,description:`Compare the per-app Flathub tracking-repo manifest against the local git state and report version / commit drift.`,builder:t=>t.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 t=>{let n=process.cwd(),S=(await new Config().forCommand().catch(()=>({}))).flatpak??{},C=t.appId??S.appId??readPackageJson(n).name;if(!C)throw Error(`[gjsify flatpak diff] no app id available — pass --app-id or set gjsify.flatpak.appId.`);let N=t.flathubRepo??S.flathubRepo??`flathub/${C}`,F=t.version??await resolveLatestTag(n,t.verbose),I=await loadFlathubSource({appId:C,flathubRepo:N,against:t.against,verbose:t.verbose},t.sourceIndex),H=I?.tag,W=I?.commit;if(ge.log(`[gjsify flatpak diff] appId=${C}`),ge.log(`[gjsify flatpak diff] flathubRepo=${N}`),ge.log(`[gjsify flatpak diff] flathub: tag=${H??`(missing)`} commit=${W??`(missing)`}`),ge.log(`[gjsify flatpak diff] local: tag=${F??`(none)`}`),t.detail&&I&&(ge.log(`[gjsify flatpak diff] flathub manifest source:`),ge.log(JSON.stringify(I,null,2))),!F){ge.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)return ge.warn("[gjsify flatpak diff] flathub manifest has no `tag` field on the inspected source."),process.exit(1);if(H===F){ge.log(`✅ in sync (${F})`);return}ge.log(`❌ drift detected — flathub=${H} vs local=${F}`),ge.log(` run \`gjsify flatpak sync-flathub --version ${F}\` to update the Flathub manifest.`),process.exit(1)}}});function resolveCliEntry(){return Nn(Nn(zn(fileURLToPath(import.meta.url)),`..`,`..`),`index.js`)}async function runNode(t,n){let S=await spawnToCompletion(`node`,t,{completion:`return`,cwd:n});if(S.code!==0)throw Error(`sub-command exited with ${describeExit(S)}: node ${t.join(` `)}`)}var RV,zV,BV=__esmMin(()=>{_e(),ev(),sv(),zu(),ir(),qn(),RV=promisify(execFile),zV={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:t=>t.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 t=>{let n=typeof t.version==`string`?t.version.trim():``;if(!n)throw Error(`[gjsify flatpak release] missing <version> positional`);let S=resolveCliEntry(),C=process.cwd(),N=[];t.skipInit||N.push({name:`init`,args:[S,`flatpak`,`init`,`--force`]}),t.skipCheck||N.push({name:`check`,args:[S,`flatpak`,`check`]});let F=[S,`flatpak`,`sync-flathub`,`--version`,n];if(t.flathubRepo&&F.push(`--flathub-repo`,t.flathubRepo),t.verbose&&F.push(`--verbose`),ge.log(`[gjsify flatpak release] starting release of ${n}`),t.dryRun){ge.log(`[gjsify flatpak release] --dry-run set; printing plan only:`);for(let t of N)ge.log(` · ${t.name}: node ${t.args.join(` `)}`);t.skipTag||ge.log(` · tag: git tag ${n}${t.pushTag===!1?``:` && git push origin `+n}`),ge.log(` · sync: node ${F.join(` `)}`);return}for(let n of N)t.verbose&&ge.log(`[gjsify flatpak release] step ${n.name}: node ${n.args.join(` `)}`),await runNode(n.args,C),ge.log(`[gjsify flatpak release] ${n.name} ✔`);if(!t.skipTag){t.verbose&&ge.log(`[gjsify flatpak release] git tag ${n}`);try{await RV(`git`,[`tag`,n],{cwd:C}),ge.log(`[gjsify flatpak release] tag ${n} created`)}catch(t){throw Error(`[gjsify flatpak release] git tag failed (${t.message}). If the tag already exists, re-run with --skip-tag.`)}t.pushTag!==!1&&(t.verbose&&ge.log(`[gjsify flatpak release] git push origin ${n}`),await RV(`git`,[`push`,`origin`,n],{cwd:C}),ge.log(`[gjsify flatpak release] tag pushed`))}t.verbose&&ge.log(`[gjsify flatpak release] sync: node ${F.join(` `)}`),await runNode(F,C),ge.log(`[gjsify flatpak release] ✅ release ${n} complete`)}}}),VV,HV=__esmMin(()=>{lV(),dV(),pV(),bV(),SV(),jV(),PV(),LV(),BV(),VV={command:`flatpak <subcommand>`,description:`Flatpak toolchain: init/build/deps/sources/ci/check/sync-flathub/diff/release subcommands for shipping GJS apps and CLIs as Flatpaks.`,builder:t=>t.command(cV.command,cV.description,cV.builder,cV.handler).command(uV.command,uV.description,uV.builder,uV.handler).command(fV.command,fV.description,fV.builder,fV.handler).command(yV.command,yV.description,yV.builder,yV.handler).command(xV.command,xV.description,xV.builder,xV.handler).command(AV.command,AV.description,AV.builder,AV.handler).command(NV.command,NV.description,NV.builder,NV.handler).command(IV.command,IV.description,IV.builder,IV.handler).command(zV.command,zV.description,zV.builder,zV.handler).demandCommand(1).strict()}});function concatBytes(t){let n=0;for(let S of t)n+=S.byteLength;let S=new Uint8Array(n),C=0;for(let n of t)S.set(n,C),C+=n.byteLength;return S}function encodeUtf8(t){return new TextEncoder().encode(t)}var UV=__esmMin(()=>{});function createArArchive(t){let n=[encodeUtf8(WV)];for(let S of t)n.push(buildMemberHeader(S)),n.push(S.data),S.data.byteLength%2==1&&n.push(encodeUtf8(`
1117
1117
  `));return concatBytes(n)}function buildMemberHeader(t){let n=pad(t.name,16)+pad(String(t.mtime??0),12)+pad(`0`,6)+pad(`0`,6)+pad((t.mode??33188).toString(8),8)+pad(String(t.data.byteLength),10)+`\`
1118
- `;if(n.length!==WV)throw Error(`gjsify ship: internal error — ar header is ${n.length} bytes, expected ${WV}.`);return encodeUtf8(n)}function pad(t,n){if(t.length>n)throw Error(`gjsify ship: ar header field "${t}" does not fit in ${n} bytes.`);return t.padEnd(n,` `)}var UV,WV,GV=__esmMin(()=>{HV(),UV=`!<arch>
1119
- `,WV=60});function warnAboutGjsFloor(t,n){return!YV[t]||compareVersions(n,`1.82.3`)<=0||compareVersions(n,`1.88.1`)===0?[]:[`gjsify ship: \`Depends: gjs (>= ${n})\` is not satisfiable on Debian stable — ${JV}. The package installs on forky/sid and on distributions with a newer GJS. Set \`gjsify.ship.minGjsVersion\` if this bundle genuinely runs on an older GJS; do NOT lower it to make apt happy, because the result is an install that succeeds and an app that does not start.`]}function warnAboutNodeFloor(t,n){return!ZV[t]||compareVersions(n,`22`)<=0?[]:[`gjsify ship: \`Depends: nodejs (>= ${n})\` is not satisfiable on any current DEB stable/LTS — ${XV}. The package installs on forky/sid and on distributions with a newer Node. Set \`gjsify.ship.minNodeVersion\` if this bundle genuinely runs on an older Node; do NOT lower it to make apt happy, because the result is an install that succeeds and an app that dies on the first syntax or API the older interpreter does not have.`]}function compareVersions(t,n){let S=t.split(`.`).map(Number),C=n.split(`.`).map(Number);for(let t=0;t<Math.max(S.length,C.length);t++){let n=(S[t]??0)-(C[t]??0);if(n!==0)return n}return 0}function hostProvidedNamespaces(t,n=[]){let S=new Set;for(let t of n){let n=/([A-Za-z0-9]+)-([\d.]+)\.typelib$/.exec(t);n&&(S.add(`${n[1]}-${n[2]}`),S.add(n[1]))}return[...new Set(t)].sort().filter(t=>!$V.test(t)&&!S.has(t))}function deriveDepends(t,n){let S=n.interpreter===`node`?[`${KV[t]} >= ${n.minNodeVersion??`24`}`]:[`gjs >= ${n.minGjsVersion??`1.86`}`],C=[],N=new Set(n.optionalNamespaces??[]),F=[],I=[];for(let H of hostProvidedNamespaces(n.namespaces,n.bundledTypelibs)){let W=lookupTypelib(H,n.typelibPackages);if(W===void 0){(N.has(H)?I:F).push(H);continue}N.has(H)&&!S.includes(W[t])?C.push(W[t]):S.push(W[t])}if(F.length>0)throw Error(`gjsify ship: the bundle imports ${F.map(t=>`gi://${t.split(`-`)[0]}`).join(`, `)}, and no ${t} package is known to ship ${F.length>1?`those typelibs`:`that typelib`}. An undeclared runtime dependency does not fail here — it fails on a user's machine after the download. Fill the gap in package.json:
1118
+ `;if(n.length!==GV)throw Error(`gjsify ship: internal error — ar header is ${n.length} bytes, expected ${GV}.`);return encodeUtf8(n)}function pad(t,n){if(t.length>n)throw Error(`gjsify ship: ar header field "${t}" does not fit in ${n} bytes.`);return t.padEnd(n,` `)}var WV,GV,KV=__esmMin(()=>{UV(),WV=`!<arch>
1119
+ `,GV=60});function warnAboutGjsFloor(t,n){return!XV[t]||compareVersions(n,`1.82.3`)<=0||compareVersions(n,`1.88.1`)===0?[]:[`gjsify ship: \`Depends: gjs (>= ${n})\` is not satisfiable on Debian stable — ${YV}. The package installs on forky/sid and on distributions with a newer GJS. Set \`gjsify.ship.minGjsVersion\` if this bundle genuinely runs on an older GJS; do NOT lower it to make apt happy, because the result is an install that succeeds and an app that does not start.`]}function warnAboutNodeFloor(t,n){return!QV[t]||compareVersions(n,`22`)<=0?[]:[`gjsify ship: \`Depends: nodejs (>= ${n})\` is not satisfiable on any current DEB stable/LTS — ${ZV}. The package installs on forky/sid and on distributions with a newer Node. Set \`gjsify.ship.minNodeVersion\` if this bundle genuinely runs on an older Node; do NOT lower it to make apt happy, because the result is an install that succeeds and an app that dies on the first syntax or API the older interpreter does not have.`]}function compareVersions(t,n){let S=t.split(`.`).map(Number),C=n.split(`.`).map(Number);for(let t=0;t<Math.max(S.length,C.length);t++){let n=(S[t]??0)-(C[t]??0);if(n!==0)return n}return 0}function hostProvidedNamespaces(t,n=[]){let S=new Set;for(let t of n){let n=/([A-Za-z0-9]+)-([\d.]+)\.typelib$/.exec(t);n&&(S.add(`${n[1]}-${n[2]}`),S.add(n[1]))}return[...new Set(t)].sort().filter(t=>!eH.test(t)&&!S.has(t))}function deriveDepends(t,n){let S=n.interpreter===`node`?[`${qV[t]} >= ${n.minNodeVersion??`24`}`]:[`gjs >= ${n.minGjsVersion??`1.86`}`],C=[],N=new Set(n.optionalNamespaces??[]),F=[],I=[];for(let H of hostProvidedNamespaces(n.namespaces,n.bundledTypelibs)){let W=lookupTypelib(H,n.typelibPackages);if(W===void 0){(N.has(H)?I:F).push(H);continue}N.has(H)&&!S.includes(W[t])?C.push(W[t]):S.push(W[t])}if(F.length>0)throw Error(`gjsify ship: the bundle imports ${F.map(t=>`gi://${t.split(`-`)[0]}`).join(`, `)}, and no ${t} package is known to ship ${F.length>1?`those typelibs`:`that typelib`}. An undeclared runtime dependency does not fail here — it fails on a user's machine after the download. Fill the gap in package.json:
1120
1120
  "gjsify": { "ship": { "typelibPackages": { ${JSON.stringify(F[0])}: { "deb": "gir1.2-…", "rpm": "…" } } } }
1121
- and please contribute the mapping back to \`utils/ship/depends.ts\` so the next project does not have to. (\`gjsify.ship.depends.<format>\` is for dependencies that are not typelibs at all — it appends, and deliberately does not silence this.)`);return n.hasIcons&&S.push(`hicolor-icon-theme`),n.hasSchemas&&S.push(qV[t]),S.push(...n.extra),{requires:[...new Set(S)],recommends:[...new Set(C)].filter(t=>!S.includes(t)),unmappedOptional:I}}function lookupTypelib(t,n={}){let S={...QV,...n},C=S[t];if(C!==void 0)return C;if(t.includes(`-`))return;let N=Object.keys(S).filter(n=>n.startsWith(`${t}-`));if(N.length===1)return S[N[0]]}function parseDepend(t){let n=/^(\S+)\s*(>=|<=|=|>|<)\s*(\S+)$/.exec(t);return n?{name:n[1],relation:n[2],version:n[3]}:{name:t.trim()}}function formatDebDepend(t){let n=parseDepend(t);if(n.relation===void 0)return n.name;let S=n.relation===`>`?`>>`:n.relation===`<`?`<<`:n.relation;return`${n.name} (${S} ${n.version})`}var KV,qV,JV,YV,XV,ZV,QV,$V,eH=__esmMin(()=>{KV={deb:`nodejs`,rpm:`nodejs(engine)`},qV={deb:`libglib2.0-bin`,rpm:`glib2`},JV=`trixie ships 1.82.3 and forky 1.88.1; 1.84 and 1.86 were skipped`,YV={deb:!0,rpm:!1},XV=`trixie ships 20, forky 24; Ubuntu 24.04 LTS ships 18 and 26.04 LTS 22`,ZV={deb:!0,rpm:!1},QV={"GLib-2.0":{deb:`gir1.2-glib-2.0`,rpm:`glib2`},"GObject-2.0":{deb:`gir1.2-glib-2.0`,rpm:`glib2`},"Gio-2.0":{deb:`gir1.2-glib-2.0`,rpm:`glib2`},"GioUnix-2.0":{deb:`gir1.2-glib-2.0`,rpm:`glib2`},"GModule-2.0":{deb:`gir1.2-glib-2.0`,rpm:`glib2`},"Gtk-4.0":{deb:`gir1.2-gtk-4.0`,rpm:`gtk4`},"Gdk-4.0":{deb:`gir1.2-gtk-4.0`,rpm:`gtk4`},"Gsk-4.0":{deb:`gir1.2-gtk-4.0`,rpm:`gtk4`},"Adw-1":{deb:`gir1.2-adw-1`,rpm:`libadwaita`},"GdkPixbuf-2.0":{deb:`gir1.2-gdkpixbuf-2.0`,rpm:`gdk-pixbuf2`},"Pango-1.0":{deb:`gir1.2-pango-1.0`,rpm:`pango`},"PangoCairo-1.0":{deb:`gir1.2-pango-1.0`,rpm:`pango`},"Graphene-1.0":{deb:`gir1.2-graphene-1.0`,rpm:`graphene`},"cairo-1.0":{deb:`gir1.2-freedesktop`,rpm:`gobject-introspection`},"GtkSource-5":{deb:`gir1.2-gtksource-5`,rpm:`gtksourceview5`},"WebKit-6.0":{deb:`gir1.2-webkit-6.0`,rpm:`webkitgtk6.0`},"Soup-3.0":{deb:`gir1.2-soup-3.0`,rpm:`libsoup3`},"Json-1.0":{deb:`gir1.2-json-1.0`,rpm:`json-glib`},"Gst-1.0":{deb:`gir1.2-gstreamer-1.0`,rpm:`gstreamer1`},"Secret-1":{deb:`gir1.2-secret-1`,rpm:`libsecret`},"Notify-0.7":{deb:`gir1.2-notify-0.7`,rpm:`libnotify`},"Vte-3.91":{deb:`gir1.2-vte-3.91`,rpm:`vte291-gtk4`},"Manette-0.2":{deb:`gir1.2-manette-0.2`,rpm:`libmanette`}},$V=/^Gjsify[A-Z]/});async function gzipDeterministic(t,n){let S=await gzip(t,n===void 0?void 0:{level:n});if(S.byteLength<10||S[0]!==31||S[1]!==139)throw Error(`gjsify ship: internal error — gzip did not produce a gzip stream.`);return S[4]=0,S[5]=0,S[6]=0,S[7]=0,S[9]=3,S}var tH=__esmMin(()=>{KR()});function isUnder(t,n){return t.startsWith(`${n}/`)}var nH,rH=__esmMin(()=>{nH={applications:`share/applications`,icons:`share/icons/hicolor`,schemas:`share/glib-2.0/schemas`,mime:`share/mime/packages`,metainfo:`share/metainfo`,locale:`share/locale`,fonts:`share/fonts`}});function cacheRefreshCommands(t,n){let S=[];return t.hasDesktopEntry&&S.push({probe:`update-desktop-database`,run:`update-desktop-database -q ${n}/${nH.applications}`}),t.hasIcons&&S.push({probe:`gtk-update-icon-cache`,run:`gtk-update-icon-cache -q -t -f ${n}/${nH.icons}`}),t.hasMimeTypes&&S.push({probe:`update-mime-database`,run:`update-mime-database ${n}/share/mime`}),t.hasSchemas&&S.push({probe:`glib-compile-schemas`,run:`glib-compile-schemas ${n}/${nH.schemas}`}),S.map(({probe:t,run:n})=>`if command -v ${t} >/dev/null 2>&1; then ${n} || true; fi`)}function renderDebScripts(t,n){let S=cacheRefreshCommands(t,n);if(S.length===0)return{};let C=S.map(t=>` ${t}`).join(`
1121
+ and please contribute the mapping back to \`utils/ship/depends.ts\` so the next project does not have to. (\`gjsify.ship.depends.<format>\` is for dependencies that are not typelibs at all — it appends, and deliberately does not silence this.)`);return n.hasIcons&&S.push(`hicolor-icon-theme`),n.hasSchemas&&S.push(JV[t]),S.push(...n.extra),{requires:[...new Set(S)],recommends:[...new Set(C)].filter(t=>!S.includes(t)),unmappedOptional:I}}function lookupTypelib(t,n={}){let S={...$V,...n},C=S[t];if(C!==void 0)return C;if(t.includes(`-`))return;let N=Object.keys(S).filter(n=>n.startsWith(`${t}-`));if(N.length===1)return S[N[0]]}function parseDepend(t){let n=/^(\S+)\s*(>=|<=|=|>|<)\s*(\S+)$/.exec(t);return n?{name:n[1],relation:n[2],version:n[3]}:{name:t.trim()}}function formatDebDepend(t){let n=parseDepend(t);if(n.relation===void 0)return n.name;let S=n.relation===`>`?`>>`:n.relation===`<`?`<<`:n.relation;return`${n.name} (${S} ${n.version})`}var qV,JV,YV,XV,ZV,QV,$V,eH,tH=__esmMin(()=>{qV={deb:`nodejs`,rpm:`nodejs(engine)`},JV={deb:`libglib2.0-bin`,rpm:`glib2`},YV=`trixie ships 1.82.3 and forky 1.88.1; 1.84 and 1.86 were skipped`,XV={deb:!0,rpm:!1},ZV=`trixie ships 20, forky 24; Ubuntu 24.04 LTS ships 18 and 26.04 LTS 22`,QV={deb:!0,rpm:!1},$V={"GLib-2.0":{deb:`gir1.2-glib-2.0`,rpm:`glib2`},"GObject-2.0":{deb:`gir1.2-glib-2.0`,rpm:`glib2`},"Gio-2.0":{deb:`gir1.2-glib-2.0`,rpm:`glib2`},"GioUnix-2.0":{deb:`gir1.2-glib-2.0`,rpm:`glib2`},"GModule-2.0":{deb:`gir1.2-glib-2.0`,rpm:`glib2`},"Gtk-4.0":{deb:`gir1.2-gtk-4.0`,rpm:`gtk4`},"Gdk-4.0":{deb:`gir1.2-gtk-4.0`,rpm:`gtk4`},"Gsk-4.0":{deb:`gir1.2-gtk-4.0`,rpm:`gtk4`},"Adw-1":{deb:`gir1.2-adw-1`,rpm:`libadwaita`},"GdkPixbuf-2.0":{deb:`gir1.2-gdkpixbuf-2.0`,rpm:`gdk-pixbuf2`},"Pango-1.0":{deb:`gir1.2-pango-1.0`,rpm:`pango`},"PangoCairo-1.0":{deb:`gir1.2-pango-1.0`,rpm:`pango`},"Graphene-1.0":{deb:`gir1.2-graphene-1.0`,rpm:`graphene`},"cairo-1.0":{deb:`gir1.2-freedesktop`,rpm:`gobject-introspection`},"GtkSource-5":{deb:`gir1.2-gtksource-5`,rpm:`gtksourceview5`},"WebKit-6.0":{deb:`gir1.2-webkit-6.0`,rpm:`webkitgtk6.0`},"Soup-3.0":{deb:`gir1.2-soup-3.0`,rpm:`libsoup3`},"Json-1.0":{deb:`gir1.2-json-1.0`,rpm:`json-glib`},"Gst-1.0":{deb:`gir1.2-gstreamer-1.0`,rpm:`gstreamer1`},"Secret-1":{deb:`gir1.2-secret-1`,rpm:`libsecret`},"Notify-0.7":{deb:`gir1.2-notify-0.7`,rpm:`libnotify`},"Vte-3.91":{deb:`gir1.2-vte-3.91`,rpm:`vte291-gtk4`},"Manette-0.2":{deb:`gir1.2-manette-0.2`,rpm:`libmanette`}},eH=/^Gjsify[A-Z]/});async function gzipDeterministic(t,n){let S=await gzip(t,n===void 0?void 0:{level:n});if(S.byteLength<10||S[0]!==31||S[1]!==139)throw Error(`gjsify ship: internal error — gzip did not produce a gzip stream.`);return S[4]=0,S[5]=0,S[6]=0,S[7]=0,S[9]=3,S}var nH=__esmMin(()=>{KR()});function isUnder(t,n){return t.startsWith(`${n}/`)}var rH,iH=__esmMin(()=>{rH={applications:`share/applications`,icons:`share/icons/hicolor`,schemas:`share/glib-2.0/schemas`,mime:`share/mime/packages`,metainfo:`share/metainfo`,locale:`share/locale`,fonts:`share/fonts`}});function cacheRefreshCommands(t,n){let S=[];return t.hasDesktopEntry&&S.push({probe:`update-desktop-database`,run:`update-desktop-database -q ${n}/${rH.applications}`}),t.hasIcons&&S.push({probe:`gtk-update-icon-cache`,run:`gtk-update-icon-cache -q -t -f ${n}/${rH.icons}`}),t.hasMimeTypes&&S.push({probe:`update-mime-database`,run:`update-mime-database ${n}/share/mime`}),t.hasSchemas&&S.push({probe:`glib-compile-schemas`,run:`glib-compile-schemas ${n}/${rH.schemas}`}),S.map(({probe:t,run:n})=>`if command -v ${t} >/dev/null 2>&1; then ${n} || true; fi`)}function renderDebScripts(t,n){let S=cacheRefreshCommands(t,n);if(S.length===0)return{};let C=S.map(t=>` ${t}`).join(`
1122
1122
  `);return{postinst:[`#!/bin/sh`,`set -e`,`if [ "$1" = "configure" ]; then`,C,`fi`,``].join(`
1123
1123
  `),postrm:[`#!/bin/sh`,`set -e`,`if [ "$1" = "remove" ]; then`,C,`fi`,``].join(`
1124
1124
  `)}}function renderRpmScriptlets(t,n){let S=cacheRefreshCommands(t,n);if(S.length===0)return{};let C=`${S.join(`
1125
- `)}\n`;return{post:C,postun:C}}var iH=__esmMin(()=>{rH()});function isSymbolicIcon(t){return Vn(t).toLowerCase()===`.svg`?/(?:^|[\\/])symbolic[\\/]/.test(t)?!0:Bn(t,Vn(t)).endsWith(`-symbolic`):!1}function iconThemeDir(t){if(isSymbolicIcon(t))return`symbolic`;if(Vn(t).toLowerCase()===`.svg`)return`scalable`;let n=/(?:^|[\\/])(\d{1,4})x\1(?:[\\/]|$)/.exec(t);if(n)return`${n[1]}x${n[1]}`;let S=Bn(t,Vn(t)).split(/[-_.]/);for(let t=S.length-1;t>=0;t--){let n=S[t];if(n!==void 0&&/^\d{1,4}$/.test(n))return`${n}x${n}`}throw Error(`gjsify ship: cannot tell what size ${t} is. Put it in a \`<size>x<size>/\` directory, end its name with the size (\`icon-128.png\`), or ship an SVG.`)}function readPngSize(t,n){if(t.length<33||oH.some((n,S)=>t[S]!==n))throw Error(`gjsify ship: ${n} is not a PNG — it does not start with the PNG signature.`);let S=new DataView(t.buffer,t.byteOffset,t.byteLength);if(S.getUint32(8)!==13||Buffer.from(t.subarray(12,16)).toString(`latin1`)!==`IHDR`)throw Error(`gjsify ship: ${n} is not a PNG this command can read — its first chunk is not IHDR.`);let C=t.length-sH.length;if(sH.some((n,S)=>t[C+S]!==n))throw Error(`gjsify ship: ${n} is truncated — it does not end with an IEND chunk, so it would embed as a picture that decodes to nothing.`);return{width:S.getUint32(16),height:S.getUint32(20)}}function rasterizerEnv(t={}){return{...t.env??process.env,...buildNativeEnv([],t)}}async function rasterizeSvg(t){if(t.sizes.length===0)return new Map;let n=t.command??`gjsify ship`,S=await(t.spawn??spawnToCompletion)(`gjs`,[`-c`,cH,t.svg,...t.sizes.map(String)],{completion:`return`,stdio:`capture`,env:rasterizerEnv(),maxBuffer:64*1024*1024,notFound:()=>Error(`${n}: \`gjs\` is not on PATH, and it is what renders ${t.svg} into the sizes an icon needs on this OS. ${aH}.`)}),C=S.stdout??``;if(S.code!==0){let C=(S.stderr??``).trim(),N=/Rsvg|Typelib|cairo/i.test(C)?` The Rsvg typelib or GJS's cairo binding is missing. ${aH}.`:``;throw Error(`${n}: rendering ${t.svg} through gjs failed (exit ${S.code??S.signal}).${N}${C===``?``:`\n ${C.split(`
1125
+ `)}\n`;return{post:C,postun:C}}var aH=__esmMin(()=>{iH()});function isSymbolicIcon(t){return Vn(t).toLowerCase()===`.svg`?/(?:^|[\\/])symbolic[\\/]/.test(t)?!0:Bn(t,Vn(t)).endsWith(`-symbolic`):!1}function iconThemeDir(t){if(isSymbolicIcon(t))return`symbolic`;if(Vn(t).toLowerCase()===`.svg`)return`scalable`;let n=/(?:^|[\\/])(\d{1,4})x\1(?:[\\/]|$)/.exec(t);if(n)return`${n[1]}x${n[1]}`;let S=Bn(t,Vn(t)).split(/[-_.]/);for(let t=S.length-1;t>=0;t--){let n=S[t];if(n!==void 0&&/^\d{1,4}$/.test(n))return`${n}x${n}`}throw Error(`gjsify ship: cannot tell what size ${t} is. Put it in a \`<size>x<size>/\` directory, end its name with the size (\`icon-128.png\`), or ship an SVG.`)}function readPngSize(t,n){if(t.length<33||sH.some((n,S)=>t[S]!==n))throw Error(`gjsify ship: ${n} is not a PNG — it does not start with the PNG signature.`);let S=new DataView(t.buffer,t.byteOffset,t.byteLength);if(S.getUint32(8)!==13||Buffer.from(t.subarray(12,16)).toString(`latin1`)!==`IHDR`)throw Error(`gjsify ship: ${n} is not a PNG this command can read — its first chunk is not IHDR.`);let C=t.length-cH.length;if(cH.some((n,S)=>t[C+S]!==n))throw Error(`gjsify ship: ${n} is truncated — it does not end with an IEND chunk, so it would embed as a picture that decodes to nothing.`);return{width:S.getUint32(16),height:S.getUint32(20)}}function rasterizerEnv(t={}){return{...t.env??process.env,...buildNativeEnv([],t)}}async function rasterizeSvg(t){if(t.sizes.length===0)return new Map;let n=t.command??`gjsify ship`,S=await(t.spawn??spawnToCompletion)(`gjs`,[`-c`,lH,t.svg,...t.sizes.map(String)],{completion:`return`,stdio:`capture`,env:rasterizerEnv(),maxBuffer:64*1024*1024,notFound:()=>Error(`${n}: \`gjs\` is not on PATH, and it is what renders ${t.svg} into the sizes an icon needs on this OS. ${oH}.`)}),C=S.stdout??``;if(S.code!==0){let C=(S.stderr??``).trim(),N=/Rsvg|Typelib|cairo/i.test(C)?` The Rsvg typelib or GJS's cairo binding is missing. ${oH}.`:``;throw Error(`${n}: rendering ${t.svg} through gjs failed (exit ${S.code??S.signal}).${N}${C===``?``:`\n ${C.split(`
1126
1126
  `).join(`
1127
- `)}`}`)}let N;try{N=JSON.parse(C)}catch{throw Error(`${n}: gjs printed something other than the rendered icon while rendering ${t.svg}: ${C.slice(0,200)}`)}let F=new Map;for(let S of t.sizes){let C=N[String(S)];if(C===void 0)throw Error(`${n}: gjs rendered no ${S} px image of ${t.svg}.`);let I=new Uint8Array(Buffer.from(C,`base64`)),{width:H,height:W}=readPngSize(I,`the ${S} px render of ${t.svg}`);if(H!==S||W!==S)throw Error(`${n}: asked gjs for a ${S} px render of ${t.svg} and got ${H}×${W}.`);F.set(S,I)}return F}async function resolveAppIcon(t){let n=t.iconFiles.filter(t=>Vn(t).toLowerCase()===`.svg`&&!isSymbolicIcon(t)),S=t.iconFiles.filter(t=>Vn(t).toLowerCase()===`.png`&&!isSymbolicIcon(t)),C=`data/icons/hicolor/scalable/apps/${t.appId}.svg`;if(n.length===0&&S.length===0)throw Error(`gjsify ship: ${t.target} needs the app's icon and the project declares none. Add a scalable SVG at ${C} (or point \`gjsify.ship.icon\` at one) and \`gjsify ship\` renders every size from it. An app with no icon here ships with the generic one, and nothing on the target OS says so.`);let N=n.find(t=>/(?:^|[\\/])scalable[\\/]/.test(t))??n[0],F=new Map,I=new Map;for(let n of S){let S=new Uint8Array(readFileSync(n)),{width:C,height:N}=readPngSize(S,n);if(C!==N)throw Error(`gjsify ship: ${n} is ${C}×${N}, and an app icon is square on every platform that reads one — Windows and macOS both index icon images by one edge length.`);let H=iconThemeDir(n);if(H!==`${C}x${C}`)throw Error(`gjsify ship: ${n} is ${C}×${N} but its path says ${H}. The theme looks the file up by the path, so this icon would be served at the wrong size — move it or resize it.`);if(!t.sizes.includes(C))continue;let W=I.get(C);if(W!==void 0)throw Error(`gjsify ship: ${n} and ${W} are both ${C} px icons. Keep one.`);I.set(C,n),F.set(C,S)}let H=t.sizes.filter(t=>!F.has(t));if(H.length>0){if(N===void 0)throw Error(`gjsify ship: ${t.target} needs the app's icon at ${H.join(`, `)} px and the project ships PNGs only for ${[...F.keys()].sort((t,n)=>t-n).join(`, `)||`no size`}. Add a scalable SVG at ${C} and the rest is rendered from it, or add ${H.map(n=>`data/icons/hicolor/${n}x${n}/apps/${t.appId}.png`).join(`, `)}.`);let n=await(t.rasterize??rasterizeSvg)({svg:N,sizes:H});for(let t of H){let S=n.get(t);if(S===void 0)throw Error(`gjsify ship: ${N} rendered no ${t} px image.`);F.set(t,S)}}return{source:I.size===0?`rendered from ${N}`:H.length===0?`${I.size} sized PNG(s) the project ships`:`${I.size} sized PNG(s) the project ships, the rest rendered from ${N}`,png:F}}function iconSizes(t){return[...t.png.keys()].sort((t,n)=>t-n)}var aH,oH,sH,cH,lH=__esmMin(()=>{ef(),qn(),nL(),sv(),aH="Fedora: `sudo dnf install gjs librsvg2`, Debian/Ubuntu: `sudo apt install gjs gir1.2-rsvg-2.0`, macOS: `brew install gjs librsvg gobject-introspection`",oH=[137,80,78,71,13,10,26,10],sH=[0,0,0,0,73,69,78,68,174,66,96,130],cH=`imports.gi.versions.Rsvg = '2.0';
1127
+ `)}`}`)}let N;try{N=JSON.parse(C)}catch{throw Error(`${n}: gjs printed something other than the rendered icon while rendering ${t.svg}: ${C.slice(0,200)}`)}let F=new Map;for(let S of t.sizes){let C=N[String(S)];if(C===void 0)throw Error(`${n}: gjs rendered no ${S} px image of ${t.svg}.`);let I=new Uint8Array(Buffer.from(C,`base64`)),{width:H,height:W}=readPngSize(I,`the ${S} px render of ${t.svg}`);if(H!==S||W!==S)throw Error(`${n}: asked gjs for a ${S} px render of ${t.svg} and got ${H}×${W}.`);F.set(S,I)}return F}async function resolveAppIcon(t){let n=t.iconFiles.filter(t=>Vn(t).toLowerCase()===`.svg`&&!isSymbolicIcon(t)),S=t.iconFiles.filter(t=>Vn(t).toLowerCase()===`.png`&&!isSymbolicIcon(t)),C=`data/icons/hicolor/scalable/apps/${t.appId}.svg`;if(n.length===0&&S.length===0)throw Error(`gjsify ship: ${t.target} needs the app's icon and the project declares none. Add a scalable SVG at ${C} (or point \`gjsify.ship.icon\` at one) and \`gjsify ship\` renders every size from it. An app with no icon here ships with the generic one, and nothing on the target OS says so.`);let N=n.find(t=>/(?:^|[\\/])scalable[\\/]/.test(t))??n[0],F=new Map,I=new Map;for(let n of S){let S=new Uint8Array(readFileSync(n)),{width:C,height:N}=readPngSize(S,n);if(C!==N)throw Error(`gjsify ship: ${n} is ${C}×${N}, and an app icon is square on every platform that reads one — Windows and macOS both index icon images by one edge length.`);let H=iconThemeDir(n);if(H!==`${C}x${C}`)throw Error(`gjsify ship: ${n} is ${C}×${N} but its path says ${H}. The theme looks the file up by the path, so this icon would be served at the wrong size — move it or resize it.`);if(!t.sizes.includes(C))continue;let W=I.get(C);if(W!==void 0)throw Error(`gjsify ship: ${n} and ${W} are both ${C} px icons. Keep one.`);I.set(C,n),F.set(C,S)}let H=t.sizes.filter(t=>!F.has(t));if(H.length>0){if(N===void 0)throw Error(`gjsify ship: ${t.target} needs the app's icon at ${H.join(`, `)} px and the project ships PNGs only for ${[...F.keys()].sort((t,n)=>t-n).join(`, `)||`no size`}. Add a scalable SVG at ${C} and the rest is rendered from it, or add ${H.map(n=>`data/icons/hicolor/${n}x${n}/apps/${t.appId}.png`).join(`, `)}.`);let n=await(t.rasterize??rasterizeSvg)({svg:N,sizes:H});for(let t of H){let S=n.get(t);if(S===void 0)throw Error(`gjsify ship: ${N} rendered no ${t} px image.`);F.set(t,S)}}return{source:I.size===0?`rendered from ${N}`:H.length===0?`${I.size} sized PNG(s) the project ships`:`${I.size} sized PNG(s) the project ships, the rest rendered from ${N}`,png:F}}function iconSizes(t){return[...t.png.keys()].sort((t,n)=>t-n)}var oH,sH,cH,lH,uH=__esmMin(()=>{ef(),qn(),nL(),sv(),oH="Fedora: `sudo dnf install gjs librsvg2`, Debian/Ubuntu: `sudo apt install gjs gir1.2-rsvg-2.0`, macOS: `brew install gjs librsvg gobject-introspection`",sH=[137,80,78,71,13,10,26,10],cH=[0,0,0,0,73,69,78,68,174,66,96,130],lH=`imports.gi.versions.Rsvg = '2.0';
1128
1128
  const { Rsvg, GLib } = imports.gi;
1129
1129
  const Cairo = imports.cairo;
1130
1130
  const [svg, ...sizes] = ARGV;
@@ -1143,56 +1143,56 @@ for (const text of sizes) {
1143
1143
  GLib.unlink(path);
1144
1144
  out[size] = GLib.base64_encode(bytes);
1145
1145
  }
1146
- print(JSON.stringify(out));`});function head(t,n){let S=Buffer.alloc(8);return S.write(t,0,`latin1`),S.writeUInt32BE(n,4),new Uint8Array(S)}function buildIcns(t){let n=uH.map(n=>{let S=t.png.get(n.size);if(S===void 0)throw Error(`gjsify ship: the macOS icon needs a ${n.size} px image (${n.iconset}) and the raster set has none — \`resolveAppIcon\` was asked for the wrong sizes.`);let{width:C,height:N}=readPngSize(S,`the ${n.size} px icon image`);if(C!==n.size||N!==n.size)throw Error(`gjsify ship: the image keyed ${n.size} in the icon raster set is ${C}×${N}.`);return{...n,png:S}}),S=concatBytes([head(`TOC `,8+8*n.length),...n.map(t=>head(t.type,8+t.png.length))]),C=n.map(t=>concatBytes([head(t.type,8+t.png.length),t.png]));return concatBytes([head(`icns`,8+S.length+C.reduce((t,n)=>t+n.length,0)),S,...C])}var uH,dH,fH=__esmMin(()=>{HV(),lH(),uH=[{type:`icp4`,size:16,iconset:`icon_16x16.png`},{type:`ic11`,size:32,iconset:`icon_16x16@2x.png`},{type:`icp5`,size:32,iconset:`icon_32x32.png`},{type:`ic12`,size:64,iconset:`icon_32x32@2x.png`},{type:`ic07`,size:128,iconset:`icon_128x128.png`},{type:`ic13`,size:256,iconset:`icon_128x128@2x.png`},{type:`ic08`,size:256,iconset:`icon_256x256.png`},{type:`ic14`,size:512,iconset:`icon_256x256@2x.png`},{type:`ic09`,size:512,iconset:`icon_512x512.png`},{type:`ic10`,size:1024,iconset:`icon_512x512@2x.png`}],dH=[...new Set(uH.map(t=>t.size))].sort((t,n)=>t-n)});function entryHead(t){let n=Buffer.alloc(8);return n.writeUInt8(t>=256?0:t,0),n.writeUInt8(t>=256?0:t,1),n.writeUInt8(0,2),n.writeUInt8(0,3),n.writeUInt16LE(1,4),n.writeUInt16LE(32,6),new Uint8Array(n)}function entries(t){let n=[];for(let S of pH){let C=t.png.get(S);if(C===void 0)throw Error(`gjsify ship: the Windows icon needs a ${S} px image and the raster set has none — \`resolveAppIcon\` was asked for the wrong sizes (it has ${[...t.png.keys()].join(`, `)}).`);let{width:N,height:F}=readPngSize(C,`the ${S} px icon image`);if(N!==S||F!==S)throw Error(`gjsify ship: the image keyed ${S} in the icon raster set is ${N}×${F}.`);if(S>256)throw Error(`gjsify ship: a Windows icon image cannot be ${S} px — 256 is the format's ceiling.`);n.push({size:S,png:C})}return n}function iconResources(t){let n=entries(t),S=Buffer.alloc(6);S.writeUInt16LE(0,0),S.writeUInt16LE(1,2),S.writeUInt16LE(n.length,4);let C=[];return n.forEach(({size:t,png:n},S)=>{let N=Buffer.alloc(6);N.writeUInt32LE(n.length,0),N.writeUInt16LE(S+1,4),C.push(entryHead(t),new Uint8Array(N))}),{group:concatBytes([new Uint8Array(S),...C]),icons:n.map(t=>t.png)}}var pH,mH=__esmMin(()=>{HV(),lH(),pH=[16,24,32,48,64,256]});function movImm32(t,n,S){let C={eax:184,ecx:185,edx:186,r8d:184,r9d:185,r14d:190}[n];(n===`r8d`||n===`r9d`||n===`r14d`)&&t.push(65),t.push(C);let N=Buffer.alloc(4);N.writeInt32LE(S|0),t.push(...N)}function movStackDword(t,n,S){t.push(199,132,36);let C=Buffer.alloc(4);C.writeInt32LE(n),t.push(...C);let N=Buffer.alloc(4);N.writeInt32LE(S|0),t.push(...N)}function movStackFromReg(t,n,S){let C={rax:132,rbx:156,rsi:180,rdi:188}[n];t.push(72,137,C,36);let N=Buffer.alloc(4);N.writeInt32LE(S),t.push(...N)}function movRaxFromStack(t,n){t.push(72,139,132,36);let S=Buffer.alloc(4);S.writeInt32LE(n),t.push(...S)}function leaStack(t,n,S){let C={rax:132,rcx:140,rdx:148,rdi:188,r9:140}[n];t.push(n===`r9`?76:72,141,C,36);let N=Buffer.alloc(4);N.writeInt32LE(S),t.push(...N)}function buildResourceSection(t,n){let S=t.icons.length,iconLangAt=t=>48+S*8+t*24,C=iconLangAt(S),N=C+16+8,F=N+16+8,dataEntryAt=t=>F+t*16,I=align(dataEntryAt(S+1),8),H=[];for(let n of[...t.icons,t.group])H.push({at:I,bytes:n}),I=align(I+n.length,8);let W=Buffer.alloc(I),directory=(t,n)=>{W.writeUInt16LE(0,t+12),W.writeUInt16LE(n,t+14)},entry=(t,n,S,C)=>{W.writeUInt32LE(n,t),W.writeUInt32LE(C?(2147483648|S)>>>0:S,t+4)},dataEntry=(t,S)=>{W.writeUInt32LE(n+S.at,dataEntryAt(t)),W.writeUInt32LE(S.bytes.length,dataEntryAt(t)+4)};directory(0,2),entry(16,3,32,!0),entry(24,14,C,!0),directory(32,S);for(let t=0;t<S;t++)entry(48+t*8,t+1,iconLangAt(t),!0),directory(iconLangAt(t),1),entry(iconLangAt(t)+16,jH,dataEntryAt(t),!1),dataEntry(t,H[t]);directory(C,1),entry(C+16,1,N,!0),directory(N,1),entry(N+16,jH,dataEntryAt(S),!1),dataEntry(S,H[S]);for(let t of H)W.set(t.bytes,t.at);return new Uint8Array(W)}function emitStub(){let t=new Emitter;t.push(72,131,228,240),t.push(72,129,236,xH.size&255,xH.size>>8&255,0,0),leaStack(t,`rdi`,xH.args),t.push(49,192),movImm32(t,`ecx`,(xH.size-xH.args)/8),t.push(243,72,171),t.push(49,201),t.leaRip(`rdx`,`selfBuf`),movImm32(t,`r8d`,AH.selfBuf),t.callImport(`GetModuleFileNameW`),t.push(131,248,4),t.jcc(`b`,`fail`),t.leaRip(`rdx`,`selfBuf`),t.push(137,193),t.push(72,141,4,74),t.push(102,199,64,250,99,0),t.push(102,199,64,252,109,0),t.push(102,199,64,254,100,0),t.leaRip(`rcx`,`sysBuf`),movImm32(t,`edx`,AH.sysBuf),t.callImport(`GetSystemDirectoryW`),t.leaRip(`rcx`,`cmdBuf`),t.leaRip(`rdx`,`strQuote`),t.callImport(`lstrcpyW`);for(let n of[`sysBuf`,`strCmdExe`,`selfBuf`,`strQuoteSpace`])t.leaRip(`rcx`,`cmdBuf`),t.leaRip(`rdx`,n),t.callImport(`lstrcatW`);t.callImport(`GetCommandLineW`),t.push(72,137,194),t.push(102,131,58,34),t.jcc(`ne`,`skipPlain`),t.push(72,131,194,2),t.label(`skipQuoted`),t.push(102,139,2),t.push(102,133,192),t.jcc(`e`,`argsReady`),t.push(72,131,194,2),t.push(102,131,248,34),t.jcc(`ne`,`skipQuoted`),t.jmp(`skipSpace`),t.label(`skipPlain`),t.push(102,139,2),t.push(102,133,192),t.jcc(`e`,`argsReady`),t.push(102,131,248,32),t.jcc(`e`,`skipSpace`),t.push(102,131,248,9),t.jcc(`e`,`skipSpace`),t.push(72,131,194,2),t.jmp(`skipPlain`),t.label(`skipSpace`),t.push(102,139,2),t.push(102,131,248,32),t.jcc(`e`,`skipSpaceStep`),t.push(102,131,248,9),t.jcc(`ne`,`argsReady`),t.label(`skipSpaceStep`),t.push(72,131,194,2),t.jmp(`skipSpace`),t.label(`argsReady`),t.leaRip(`rcx`,`cmdBuf`),t.callImport(`lstrcatW`),t.leaRip(`rcx`,`cmdBuf`),t.leaRip(`rdx`,`strQuote`),t.callImport(`lstrcatW`),movImm32(t,`ecx`,-10),t.callImport(`GetStdHandle`),t.push(72,137,199),movImm32(t,`ecx`,-11),t.callImport(`GetStdHandle`),t.push(72,137,195),movImm32(t,`ecx`,-12),t.callImport(`GetStdHandle`),t.push(72,137,198),t.callImport(`GetConsoleCP`),t.push(133,192),t.jcc(`ne`,`haveConsole`),movImm32(t,`r14d`,TH),t.push(72,133,219),t.jcc(`e`,`needLog`),t.push(72,131,251,255),t.jcc(`e`,`needLog`),t.push(72,133,246),t.jcc(`e`,`needLog`),t.push(72,131,254,255),t.jcc(`ne`,`useStdHandles`),t.label(`needLog`),movImm32(t,`ecx`,AH.tmpBuf),t.leaRip(`rdx`,`tmpBuf`),t.callImport(`GetTempPathW`),t.leaRip(`rcx`,`logBuf`),t.leaRip(`rdx`,`tmpBuf`),t.callImport(`lstrcpyW`),t.leaRip(`rcx`,`logBuf`),t.leaRip(`rdx`,`strLogLeaf`),t.callImport(`lstrcatW`),t.leaRip(`rcx`,`logBuf`),movImm32(t,`edx`,EH),movImm32(t,`r8d`,DH),leaStack(t,`r9`,xH.securityAttributes),movStackDword(t,xH.securityAttributes,CH),movStackDword(t,xH.securityAttributes+16,1),movStackDword(t,xH.args,OH),movStackDword(t,xH.args+8,kH),movStackDword(t,xH.args+16,0),t.callImport(`CreateFileW`),t.push(72,131,248,255),t.jcc(`e`,`create`),t.push(72,133,219),t.jcc(`e`,`logIsStdout`),t.push(72,131,251,255),t.jcc(`ne`,`stdoutKept`),t.label(`logIsStdout`),t.push(72,137,195),t.label(`stdoutKept`),t.push(72,133,246),t.jcc(`e`,`logIsStderr`),t.push(72,131,254,255),t.jcc(`ne`,`useStdHandles`),t.label(`logIsStderr`),t.push(72,137,198),t.label(`useStdHandles`),movStackFromReg(t,`rdi`,xH.startupInfo+80),movStackFromReg(t,`rbx`,xH.startupInfo+88),movStackFromReg(t,`rsi`,xH.startupInfo+96),movStackDword(t,xH.startupInfo+60,wH),t.jmp(`create`),t.label(`haveConsole`),t.push(69,49,246),t.label(`create`),movStackDword(t,xH.startupInfo,SH),t.push(49,201),t.leaRip(`rdx`,`cmdBuf`),t.push(69,49,192),t.push(69,49,201),movStackDword(t,xH.args,1),t.push(68,137,180,36);{let n=Buffer.alloc(4);n.writeInt32LE(xH.args+8),t.push(...n)}movStackDword(t,xH.args+16,0),movStackDword(t,xH.args+24,0),leaStack(t,`rax`,xH.startupInfo),movStackFromReg(t,`rax`,xH.args+32),leaStack(t,`rax`,xH.processInformation),movStackFromReg(t,`rax`,xH.args+40),t.callImport(`CreateProcessW`),t.push(133,192),t.jcc(`e`,`fail`),movRaxFromStack(t,xH.processInformation),t.push(72,137,193),movImm32(t,`edx`,-1),t.callImport(`WaitForSingleObject`),movRaxFromStack(t,xH.processInformation),t.push(72,137,193),leaStack(t,`rdx`,xH.exitCode),t.callImport(`GetExitCodeProcess`),t.push(139,140,36);{let n=Buffer.alloc(4);n.writeInt32LE(xH.exitCode),t.push(...n)}return t.callImport(`ExitProcess`),t.label(`fail`),movImm32(t,`ecx`,1),t.callImport(`ExitProcess`),t.push(204),t}function wide(t){return new Uint8Array(Buffer.from(`${t}\0`,`utf16le`))}function dataItems(t){let n=[];for(let t of bH)n.push({symbol:`iat.${t}`,bytes:new Uint8Array(8)});n.push({symbol:`iat.null`,bytes:new Uint8Array(8)}),n.push({symbol:`importDescriptors`,bytes:new Uint8Array(40)});for(let t of bH)n.push({symbol:`ilt.${t}`,bytes:new Uint8Array(8)});n.push({symbol:`ilt.null`,bytes:new Uint8Array(8)});for(let t of bH){let S=Buffer.from(`\0\0${t}\0`,`latin1`);n.push({symbol:`hint.${t}`,bytes:new Uint8Array(S.length%2==0?S:Buffer.concat([S,Buffer.alloc(1)]))})}n.push({symbol:`dllName`,bytes:new Uint8Array(Buffer.from(`KERNEL32.dll\0\0`,`latin1`))}),n.push({symbol:`strQuote`,bytes:wide(`"`)}),n.push({symbol:`strCmdExe`,bytes:wide(`\\cmd.exe" /s /c ""`)}),n.push({symbol:`strQuoteSpace`,bytes:wide(`" `)}),n.push({symbol:`strLogLeaf`,bytes:wide(t.logLeaf)});for(let[t,S]of Object.entries(AH))n.push({symbol:t,bytes:new Uint8Array(S*2)});return n}function align(t,n){return Math.ceil(t/n)*n}function buildGuiLauncher(t){if(t.logLeaf===``||/[\\/:*?"<>|]/.test(t.logLeaf))throw Error(`gjsify ship: "${t.logLeaf}" cannot be the launcher's log file name — it is empty or holds a character Windows refuses in one. The stub writes it into \`%TEMP%\`, so the value is a leaf and never a path.`);let n=emitStub(),S=n.bytes.length,C=vH,N=C+align(S,vH),F=dataItems(t),I=new Map,H=0;for(let t of F)I.set(t.symbol,H),H+=t.bytes.length;let W=H,rvaOf=t=>{let n=I.get(t);if(n===void 0)throw Error(`gjsify ship: the launcher stub names no datum "${t}".`);return N+n},q=Buffer.alloc(W);for(let t of F)q.set(t.bytes,I.get(t.symbol)??0);q.writeUInt32LE(rvaOf(`ilt.GetModuleFileNameW`),I.get(`importDescriptors`)??0),q.writeUInt32LE(rvaOf(`dllName`),(I.get(`importDescriptors`)??0)+12),q.writeUInt32LE(rvaOf(`iat.GetModuleFileNameW`),(I.get(`importDescriptors`)??0)+16);for(let t of bH){let n=BigInt(rvaOf(`hint.${t}`));q.writeBigUInt64LE(n,I.get(`ilt.${t}`)??0),q.writeBigUInt64LE(n,I.get(`iat.${t}`)??0)}let Y=n.resolve(C,rvaOf),X=align(S,_H),Z=align(W,_H),te=_H,ne=te,re=ne+X,ie=N+align(W,vH),ae=t.icon===void 0?void 0:buildResourceSection(t.icon,ie),oe=ae===void 0?0:align(ae.length,_H),Q=re+Z,se=ae===void 0?2:3,ce=ae===void 0?N+align(W,vH):ie+align(ae.length,vH),le=Buffer.alloc(Q+oe);le.write(`MZ`,0,`ascii`),le.write(`This program cannot be run in DOS mode.\r\r
1147
- $`,64,`ascii`),le.writeUInt32LE(gH,60),le.write(`PE\0\0`,gH,`ascii`),le.writeUInt16LE(hH,132),le.writeUInt16LE(se,134),le.writeUInt32LE(0,136),le.writeUInt16LE(240,148),le.writeUInt16LE(35,150),le.writeUInt16LE(523,152),le.writeUInt8(14,154),le.writeUInt32LE(X,156),le.writeUInt32LE(Z+oe,160),le.writeUInt32LE(C,168),le.writeUInt32LE(C,172),le.writeBigUInt64LE(yH,176),le.writeUInt32LE(vH,184),le.writeUInt32LE(_H,188),le.writeUInt16LE(6,192),le.writeUInt16LE(6,200),le.writeUInt32LE(ce,208),le.writeUInt32LE(te,212),le.writeUInt16LE(2,220),le.writeUInt16LE(33024,222),le.writeBigUInt64LE(1048576n,224),le.writeBigUInt64LE(4096n,232),le.writeBigUInt64LE(1048576n,240),le.writeBigUInt64LE(4096n,248),le.writeUInt32LE(16,260),le.writeUInt32LE(rvaOf(`importDescriptors`),272),le.writeUInt32LE(40,276),le.writeUInt32LE(rvaOf(`iat.GetModuleFileNameW`),360),le.writeUInt32LE((bH.length+1)*8,364),ae!==void 0&&(le.writeUInt32LE(ie,280),le.writeUInt32LE(ae.length,284));let writeSection=(t,n,S,C,N,F,I)=>{let H=392+t*40;le.write(n.padEnd(8,`\0`),H,`latin1`),le.writeUInt32LE(C,H+8),le.writeUInt32LE(S,H+12),le.writeUInt32LE(F,H+16),le.writeUInt32LE(N,H+20),le.writeUInt32LE(I,H+36)};return writeSection(0,`.text`,C,S,ne,X,1610612768),writeSection(1,`.data`,N,W,re,Z,3221225536),ae!==void 0&&writeSection(2,`.rsrc`,ie,ae.length,Q,oe,1073741888),le.set(Y,ne),le.set(q,re),ae!==void 0&&le.set(ae,Q),new Uint8Array(le)}var hH,gH,_H,vH,yH,bH,Emitter,xH,SH,CH,wH,TH,EH,DH,OH,kH,AH,jH,MH=__esmMin(()=>{mH(),hH=34404,gH=128,_H=512,vH=4096,yH=5368709120n,bH=[`GetModuleFileNameW`,`GetSystemDirectoryW`,`GetCommandLineW`,`GetConsoleCP`,`GetStdHandle`,`GetTempPathW`,`CreateFileW`,`CreateProcessW`,`WaitForSingleObject`,`GetExitCodeProcess`,`ExitProcess`,`lstrcpyW`,`lstrcatW`],Emitter=class{bytes=[];labels=new Map;ripFixups=[];branchFixups=[];push(...t){for(let n of t)this.bytes.push(n&255)}label(t){this.labels.set(t,this.bytes.length)}ripSlot(t){this.ripFixups.push({at:this.bytes.length,symbol:t}),this.push(0,0,0,0)}branchSlot(t){this.branchFixups.push({at:this.bytes.length,label:t}),this.push(0,0,0,0)}leaRip(t,n){let S={rax:5,rcx:13,rdx:21,rdi:61,r8:5,r9:13}[t];this.push(t===`r8`||t===`r9`?76:72,141,S),this.ripSlot(n)}callImport(t){this.push(255,21),this.ripSlot(`iat.${t}`)}jmp(t){this.push(233),this.branchSlot(t)}jcc(t,n){this.push(15,{e:132,ne:133,b:130}[t]),this.branchSlot(n)}resolve(t,n){let S=Buffer.from(this.bytes);for(let{at:C,symbol:N}of this.ripFixups)S.writeInt32LE(n(N)-(t+C+4),C);for(let{at:t,label:n}of this.branchFixups){let C=this.labels.get(n);if(C===void 0)throw Error(`gjsify ship: the launcher stub jumps to no label "${n}".`);S.writeInt32LE(C-(t+4),t)}return new Uint8Array(S)}},xH={args:32,securityAttributes:80,startupInfo:112,processInformation:216,exitCode:240,size:272},SH=104,CH=24,wH=256,TH=134217728,EH=1073741824,DH=3,OH=2,kH=128,AH={sysBuf:264,selfBuf:520,tmpBuf:264,logBuf:600,cmdBuf:4096},jH=1033});function xmlText(t){return t.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`)}function assertPlistText(t,n,S){let C=-1;for(let n of t){let t=n.codePointAt(0)??0;if(t<32&&t!==9&&t!==10&&t!==13){C=t;break}}if(C!==-1)throw Error(`gjsify ship: ${n} would carry the control character U+${C.toString(16).padStart(4,`0`).toUpperCase()}, and XML has no escape for it — the Info.plist would be unparseable by every reader macOS has. Set \`${S}\` to a value without it.`);return t}function stringEntry(t,n){return`\t<key>${t}</key>\n\t<string>${xmlText(n)}</string>`}function arrayEntry(t,n){return`\t<key>${t}</key>\n\t<array>\n${n.map(t=>`\t\t<string>${xmlText(t)}</string>`).join(`
1148
- `)}\n\t</array>`}function renderInfoPlist(t,n,S){let C=assertPlistText(t.name,`CFBundleName`,`gjsify.ship.name`),N=assertPlistText(t.binaryName,`CFBundleExecutable`,`gjsify.ship.binaryName`),F=assertPlistText(t.appId,`CFBundleIdentifier`,`gjsify.ship.appId`);return[`<?xml version="1.0" encoding="UTF-8"?>`,`<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">`,`<plist version="1.0">`,`<dict>`,...n===void 0?[]:[stringEntry(`ATSApplicationFontsPath`,n)],stringEntry(`CFBundleDevelopmentRegion`,`en`),stringEntry(`CFBundleDisplayName`,C),stringEntry(`CFBundleExecutable`,N),...S===void 0?[]:[stringEntry(`CFBundleIconFile`,S)],stringEntry(`CFBundleIdentifier`,F),stringEntry(`CFBundleInfoDictionaryVersion`,`6.0`),stringEntry(`CFBundleName`,C),stringEntry(`CFBundlePackageType`,IH),stringEntry(`CFBundleShortVersionString`,t.version),stringEntry(`CFBundleSignature`,LH),arrayEntry(`CFBundleSupportedPlatforms`,[`MacOSX`]),stringEntry(`CFBundleVersion`,`${t.version}-${t.release}`),`</dict>`,`</plist>`,``].join(`
1149
- `)}function renderPkgInfo(){return`${IH}${LH}`}function renderEntitlements(t){return[`<?xml version="1.0" encoding="UTF-8"?>`,`<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">`,`<plist version="1.0">`,`<dict>`,t.map(t=>`\t<key>${xmlText(t)}</key>\n\t<true/>`).join(`
1146
+ print(JSON.stringify(out));`});function head(t,n){let S=Buffer.alloc(8);return S.write(t,0,`latin1`),S.writeUInt32BE(n,4),new Uint8Array(S)}function buildIcns(t){let n=dH.map(n=>{let S=t.png.get(n.size);if(S===void 0)throw Error(`gjsify ship: the macOS icon needs a ${n.size} px image (${n.iconset}) and the raster set has none — \`resolveAppIcon\` was asked for the wrong sizes.`);let{width:C,height:N}=readPngSize(S,`the ${n.size} px icon image`);if(C!==n.size||N!==n.size)throw Error(`gjsify ship: the image keyed ${n.size} in the icon raster set is ${C}×${N}.`);return{...n,png:S}}),S=concatBytes([head(`TOC `,8+8*n.length),...n.map(t=>head(t.type,8+t.png.length))]),C=n.map(t=>concatBytes([head(t.type,8+t.png.length),t.png]));return concatBytes([head(`icns`,8+S.length+C.reduce((t,n)=>t+n.length,0)),S,...C])}var dH,fH,pH=__esmMin(()=>{UV(),uH(),dH=[{type:`icp4`,size:16,iconset:`icon_16x16.png`},{type:`ic11`,size:32,iconset:`icon_16x16@2x.png`},{type:`icp5`,size:32,iconset:`icon_32x32.png`},{type:`ic12`,size:64,iconset:`icon_32x32@2x.png`},{type:`ic07`,size:128,iconset:`icon_128x128.png`},{type:`ic13`,size:256,iconset:`icon_128x128@2x.png`},{type:`ic08`,size:256,iconset:`icon_256x256.png`},{type:`ic14`,size:512,iconset:`icon_256x256@2x.png`},{type:`ic09`,size:512,iconset:`icon_512x512.png`},{type:`ic10`,size:1024,iconset:`icon_512x512@2x.png`}],fH=[...new Set(dH.map(t=>t.size))].sort((t,n)=>t-n)});function entryHead(t){let n=Buffer.alloc(8);return n.writeUInt8(t>=256?0:t,0),n.writeUInt8(t>=256?0:t,1),n.writeUInt8(0,2),n.writeUInt8(0,3),n.writeUInt16LE(1,4),n.writeUInt16LE(32,6),new Uint8Array(n)}function entries(t){let n=[];for(let S of mH){let C=t.png.get(S);if(C===void 0)throw Error(`gjsify ship: the Windows icon needs a ${S} px image and the raster set has none — \`resolveAppIcon\` was asked for the wrong sizes (it has ${[...t.png.keys()].join(`, `)}).`);let{width:N,height:F}=readPngSize(C,`the ${S} px icon image`);if(N!==S||F!==S)throw Error(`gjsify ship: the image keyed ${S} in the icon raster set is ${N}×${F}.`);if(S>256)throw Error(`gjsify ship: a Windows icon image cannot be ${S} px — 256 is the format's ceiling.`);n.push({size:S,png:C})}return n}function iconResources(t){let n=entries(t),S=Buffer.alloc(6);S.writeUInt16LE(0,0),S.writeUInt16LE(1,2),S.writeUInt16LE(n.length,4);let C=[];return n.forEach(({size:t,png:n},S)=>{let N=Buffer.alloc(6);N.writeUInt32LE(n.length,0),N.writeUInt16LE(S+1,4),C.push(entryHead(t),new Uint8Array(N))}),{group:concatBytes([new Uint8Array(S),...C]),icons:n.map(t=>t.png)}}var mH,hH=__esmMin(()=>{UV(),uH(),mH=[16,24,32,48,64,256]});function movImm32(t,n,S){let C={eax:184,ecx:185,edx:186,r8d:184,r9d:185,r14d:190}[n];(n===`r8d`||n===`r9d`||n===`r14d`)&&t.push(65),t.push(C);let N=Buffer.alloc(4);N.writeInt32LE(S|0),t.push(...N)}function movStackDword(t,n,S){t.push(199,132,36);let C=Buffer.alloc(4);C.writeInt32LE(n),t.push(...C);let N=Buffer.alloc(4);N.writeInt32LE(S|0),t.push(...N)}function movStackFromReg(t,n,S){let C={rax:132,rbx:156,rsi:180,rdi:188}[n];t.push(72,137,C,36);let N=Buffer.alloc(4);N.writeInt32LE(S),t.push(...N)}function movRaxFromStack(t,n){t.push(72,139,132,36);let S=Buffer.alloc(4);S.writeInt32LE(n),t.push(...S)}function leaStack(t,n,S){let C={rax:132,rcx:140,rdx:148,rdi:188,r9:140}[n];t.push(n===`r9`?76:72,141,C,36);let N=Buffer.alloc(4);N.writeInt32LE(S),t.push(...N)}function buildResourceSection(t,n){let S=t.icons.length,iconLangAt=t=>48+S*8+t*24,C=iconLangAt(S),N=C+16+8,F=N+16+8,dataEntryAt=t=>F+t*16,I=align(dataEntryAt(S+1),8),H=[];for(let n of[...t.icons,t.group])H.push({at:I,bytes:n}),I=align(I+n.length,8);let W=Buffer.alloc(I),directory=(t,n)=>{W.writeUInt16LE(0,t+12),W.writeUInt16LE(n,t+14)},entry=(t,n,S,C)=>{W.writeUInt32LE(n,t),W.writeUInt32LE(C?(2147483648|S)>>>0:S,t+4)},dataEntry=(t,S)=>{W.writeUInt32LE(n+S.at,dataEntryAt(t)),W.writeUInt32LE(S.bytes.length,dataEntryAt(t)+4)};directory(0,2),entry(16,3,32,!0),entry(24,14,C,!0),directory(32,S);for(let t=0;t<S;t++)entry(48+t*8,t+1,iconLangAt(t),!0),directory(iconLangAt(t),1),entry(iconLangAt(t)+16,MH,dataEntryAt(t),!1),dataEntry(t,H[t]);directory(C,1),entry(C+16,1,N,!0),directory(N,1),entry(N+16,MH,dataEntryAt(S),!1),dataEntry(S,H[S]);for(let t of H)W.set(t.bytes,t.at);return new Uint8Array(W)}function emitStub(){let t=new Emitter;t.push(72,131,228,240),t.push(72,129,236,SH.size&255,SH.size>>8&255,0,0),leaStack(t,`rdi`,SH.args),t.push(49,192),movImm32(t,`ecx`,(SH.size-SH.args)/8),t.push(243,72,171),t.push(49,201),t.leaRip(`rdx`,`selfBuf`),movImm32(t,`r8d`,jH.selfBuf),t.callImport(`GetModuleFileNameW`),t.push(131,248,4),t.jcc(`b`,`fail`),t.leaRip(`rdx`,`selfBuf`),t.push(137,193),t.push(72,141,4,74),t.push(102,199,64,250,99,0),t.push(102,199,64,252,109,0),t.push(102,199,64,254,100,0),t.leaRip(`rcx`,`sysBuf`),movImm32(t,`edx`,jH.sysBuf),t.callImport(`GetSystemDirectoryW`),t.leaRip(`rcx`,`cmdBuf`),t.leaRip(`rdx`,`strQuote`),t.callImport(`lstrcpyW`);for(let n of[`sysBuf`,`strCmdExe`,`selfBuf`,`strQuoteSpace`])t.leaRip(`rcx`,`cmdBuf`),t.leaRip(`rdx`,n),t.callImport(`lstrcatW`);t.callImport(`GetCommandLineW`),t.push(72,137,194),t.push(102,131,58,34),t.jcc(`ne`,`skipPlain`),t.push(72,131,194,2),t.label(`skipQuoted`),t.push(102,139,2),t.push(102,133,192),t.jcc(`e`,`argsReady`),t.push(72,131,194,2),t.push(102,131,248,34),t.jcc(`ne`,`skipQuoted`),t.jmp(`skipSpace`),t.label(`skipPlain`),t.push(102,139,2),t.push(102,133,192),t.jcc(`e`,`argsReady`),t.push(102,131,248,32),t.jcc(`e`,`skipSpace`),t.push(102,131,248,9),t.jcc(`e`,`skipSpace`),t.push(72,131,194,2),t.jmp(`skipPlain`),t.label(`skipSpace`),t.push(102,139,2),t.push(102,131,248,32),t.jcc(`e`,`skipSpaceStep`),t.push(102,131,248,9),t.jcc(`ne`,`argsReady`),t.label(`skipSpaceStep`),t.push(72,131,194,2),t.jmp(`skipSpace`),t.label(`argsReady`),t.leaRip(`rcx`,`cmdBuf`),t.callImport(`lstrcatW`),t.leaRip(`rcx`,`cmdBuf`),t.leaRip(`rdx`,`strQuote`),t.callImport(`lstrcatW`),movImm32(t,`ecx`,-10),t.callImport(`GetStdHandle`),t.push(72,137,199),movImm32(t,`ecx`,-11),t.callImport(`GetStdHandle`),t.push(72,137,195),movImm32(t,`ecx`,-12),t.callImport(`GetStdHandle`),t.push(72,137,198),t.callImport(`GetConsoleCP`),t.push(133,192),t.jcc(`ne`,`haveConsole`),movImm32(t,`r14d`,EH),t.push(72,133,219),t.jcc(`e`,`needLog`),t.push(72,131,251,255),t.jcc(`e`,`needLog`),t.push(72,133,246),t.jcc(`e`,`needLog`),t.push(72,131,254,255),t.jcc(`ne`,`useStdHandles`),t.label(`needLog`),movImm32(t,`ecx`,jH.tmpBuf),t.leaRip(`rdx`,`tmpBuf`),t.callImport(`GetTempPathW`),t.leaRip(`rcx`,`logBuf`),t.leaRip(`rdx`,`tmpBuf`),t.callImport(`lstrcpyW`),t.leaRip(`rcx`,`logBuf`),t.leaRip(`rdx`,`strLogLeaf`),t.callImport(`lstrcatW`),t.leaRip(`rcx`,`logBuf`),movImm32(t,`edx`,DH),movImm32(t,`r8d`,OH),leaStack(t,`r9`,SH.securityAttributes),movStackDword(t,SH.securityAttributes,wH),movStackDword(t,SH.securityAttributes+16,1),movStackDword(t,SH.args,kH),movStackDword(t,SH.args+8,AH),movStackDword(t,SH.args+16,0),t.callImport(`CreateFileW`),t.push(72,131,248,255),t.jcc(`e`,`create`),t.push(72,133,219),t.jcc(`e`,`logIsStdout`),t.push(72,131,251,255),t.jcc(`ne`,`stdoutKept`),t.label(`logIsStdout`),t.push(72,137,195),t.label(`stdoutKept`),t.push(72,133,246),t.jcc(`e`,`logIsStderr`),t.push(72,131,254,255),t.jcc(`ne`,`useStdHandles`),t.label(`logIsStderr`),t.push(72,137,198),t.label(`useStdHandles`),movStackFromReg(t,`rdi`,SH.startupInfo+80),movStackFromReg(t,`rbx`,SH.startupInfo+88),movStackFromReg(t,`rsi`,SH.startupInfo+96),movStackDword(t,SH.startupInfo+60,TH),t.jmp(`create`),t.label(`haveConsole`),t.push(69,49,246),t.label(`create`),movStackDword(t,SH.startupInfo,CH),t.push(49,201),t.leaRip(`rdx`,`cmdBuf`),t.push(69,49,192),t.push(69,49,201),movStackDword(t,SH.args,1),t.push(68,137,180,36);{let n=Buffer.alloc(4);n.writeInt32LE(SH.args+8),t.push(...n)}movStackDword(t,SH.args+16,0),movStackDword(t,SH.args+24,0),leaStack(t,`rax`,SH.startupInfo),movStackFromReg(t,`rax`,SH.args+32),leaStack(t,`rax`,SH.processInformation),movStackFromReg(t,`rax`,SH.args+40),t.callImport(`CreateProcessW`),t.push(133,192),t.jcc(`e`,`fail`),movRaxFromStack(t,SH.processInformation),t.push(72,137,193),movImm32(t,`edx`,-1),t.callImport(`WaitForSingleObject`),movRaxFromStack(t,SH.processInformation),t.push(72,137,193),leaStack(t,`rdx`,SH.exitCode),t.callImport(`GetExitCodeProcess`),t.push(139,140,36);{let n=Buffer.alloc(4);n.writeInt32LE(SH.exitCode),t.push(...n)}return t.callImport(`ExitProcess`),t.label(`fail`),movImm32(t,`ecx`,1),t.callImport(`ExitProcess`),t.push(204),t}function wide(t){return new Uint8Array(Buffer.from(`${t}\0`,`utf16le`))}function dataItems(t){let n=[];for(let t of xH)n.push({symbol:`iat.${t}`,bytes:new Uint8Array(8)});n.push({symbol:`iat.null`,bytes:new Uint8Array(8)}),n.push({symbol:`importDescriptors`,bytes:new Uint8Array(40)});for(let t of xH)n.push({symbol:`ilt.${t}`,bytes:new Uint8Array(8)});n.push({symbol:`ilt.null`,bytes:new Uint8Array(8)});for(let t of xH){let S=Buffer.from(`\0\0${t}\0`,`latin1`);n.push({symbol:`hint.${t}`,bytes:new Uint8Array(S.length%2==0?S:Buffer.concat([S,Buffer.alloc(1)]))})}n.push({symbol:`dllName`,bytes:new Uint8Array(Buffer.from(`KERNEL32.dll\0\0`,`latin1`))}),n.push({symbol:`strQuote`,bytes:wide(`"`)}),n.push({symbol:`strCmdExe`,bytes:wide(`\\cmd.exe" /s /c ""`)}),n.push({symbol:`strQuoteSpace`,bytes:wide(`" `)}),n.push({symbol:`strLogLeaf`,bytes:wide(t.logLeaf)});for(let[t,S]of Object.entries(jH))n.push({symbol:t,bytes:new Uint8Array(S*2)});return n}function align(t,n){return Math.ceil(t/n)*n}function buildGuiLauncher(t){if(t.logLeaf===``||/[\\/:*?"<>|]/.test(t.logLeaf))throw Error(`gjsify ship: "${t.logLeaf}" cannot be the launcher's log file name — it is empty or holds a character Windows refuses in one. The stub writes it into \`%TEMP%\`, so the value is a leaf and never a path.`);let n=emitStub(),S=n.bytes.length,C=yH,N=C+align(S,yH),F=dataItems(t),I=new Map,H=0;for(let t of F)I.set(t.symbol,H),H+=t.bytes.length;let W=H,rvaOf=t=>{let n=I.get(t);if(n===void 0)throw Error(`gjsify ship: the launcher stub names no datum "${t}".`);return N+n},q=Buffer.alloc(W);for(let t of F)q.set(t.bytes,I.get(t.symbol)??0);q.writeUInt32LE(rvaOf(`ilt.GetModuleFileNameW`),I.get(`importDescriptors`)??0),q.writeUInt32LE(rvaOf(`dllName`),(I.get(`importDescriptors`)??0)+12),q.writeUInt32LE(rvaOf(`iat.GetModuleFileNameW`),(I.get(`importDescriptors`)??0)+16);for(let t of xH){let n=BigInt(rvaOf(`hint.${t}`));q.writeBigUInt64LE(n,I.get(`ilt.${t}`)??0),q.writeBigUInt64LE(n,I.get(`iat.${t}`)??0)}let Y=n.resolve(C,rvaOf),X=align(S,vH),Z=align(W,vH),te=vH,ne=te,re=ne+X,ie=N+align(W,yH),ae=t.icon===void 0?void 0:buildResourceSection(t.icon,ie),oe=ae===void 0?0:align(ae.length,vH),Q=re+Z,se=ae===void 0?2:3,ce=ae===void 0?N+align(W,yH):ie+align(ae.length,yH),le=Buffer.alloc(Q+oe);le.write(`MZ`,0,`ascii`),le.write(`This program cannot be run in DOS mode.\r\r
1147
+ $`,64,`ascii`),le.writeUInt32LE(_H,60),le.write(`PE\0\0`,_H,`ascii`),le.writeUInt16LE(gH,132),le.writeUInt16LE(se,134),le.writeUInt32LE(0,136),le.writeUInt16LE(240,148),le.writeUInt16LE(35,150),le.writeUInt16LE(523,152),le.writeUInt8(14,154),le.writeUInt32LE(X,156),le.writeUInt32LE(Z+oe,160),le.writeUInt32LE(C,168),le.writeUInt32LE(C,172),le.writeBigUInt64LE(bH,176),le.writeUInt32LE(yH,184),le.writeUInt32LE(vH,188),le.writeUInt16LE(6,192),le.writeUInt16LE(6,200),le.writeUInt32LE(ce,208),le.writeUInt32LE(te,212),le.writeUInt16LE(2,220),le.writeUInt16LE(33024,222),le.writeBigUInt64LE(1048576n,224),le.writeBigUInt64LE(4096n,232),le.writeBigUInt64LE(1048576n,240),le.writeBigUInt64LE(4096n,248),le.writeUInt32LE(16,260),le.writeUInt32LE(rvaOf(`importDescriptors`),272),le.writeUInt32LE(40,276),le.writeUInt32LE(rvaOf(`iat.GetModuleFileNameW`),360),le.writeUInt32LE((xH.length+1)*8,364),ae!==void 0&&(le.writeUInt32LE(ie,280),le.writeUInt32LE(ae.length,284));let writeSection=(t,n,S,C,N,F,I)=>{let H=392+t*40;le.write(n.padEnd(8,`\0`),H,`latin1`),le.writeUInt32LE(C,H+8),le.writeUInt32LE(S,H+12),le.writeUInt32LE(F,H+16),le.writeUInt32LE(N,H+20),le.writeUInt32LE(I,H+36)};return writeSection(0,`.text`,C,S,ne,X,1610612768),writeSection(1,`.data`,N,W,re,Z,3221225536),ae!==void 0&&writeSection(2,`.rsrc`,ie,ae.length,Q,oe,1073741888),le.set(Y,ne),le.set(q,re),ae!==void 0&&le.set(ae,Q),new Uint8Array(le)}var gH,_H,vH,yH,bH,xH,Emitter,SH,CH,wH,TH,EH,DH,OH,kH,AH,jH,MH,NH=__esmMin(()=>{hH(),gH=34404,_H=128,vH=512,yH=4096,bH=5368709120n,xH=[`GetModuleFileNameW`,`GetSystemDirectoryW`,`GetCommandLineW`,`GetConsoleCP`,`GetStdHandle`,`GetTempPathW`,`CreateFileW`,`CreateProcessW`,`WaitForSingleObject`,`GetExitCodeProcess`,`ExitProcess`,`lstrcpyW`,`lstrcatW`],Emitter=class{bytes=[];labels=new Map;ripFixups=[];branchFixups=[];push(...t){for(let n of t)this.bytes.push(n&255)}label(t){this.labels.set(t,this.bytes.length)}ripSlot(t){this.ripFixups.push({at:this.bytes.length,symbol:t}),this.push(0,0,0,0)}branchSlot(t){this.branchFixups.push({at:this.bytes.length,label:t}),this.push(0,0,0,0)}leaRip(t,n){let S={rax:5,rcx:13,rdx:21,rdi:61,r8:5,r9:13}[t];this.push(t===`r8`||t===`r9`?76:72,141,S),this.ripSlot(n)}callImport(t){this.push(255,21),this.ripSlot(`iat.${t}`)}jmp(t){this.push(233),this.branchSlot(t)}jcc(t,n){this.push(15,{e:132,ne:133,b:130}[t]),this.branchSlot(n)}resolve(t,n){let S=Buffer.from(this.bytes);for(let{at:C,symbol:N}of this.ripFixups)S.writeInt32LE(n(N)-(t+C+4),C);for(let{at:t,label:n}of this.branchFixups){let C=this.labels.get(n);if(C===void 0)throw Error(`gjsify ship: the launcher stub jumps to no label "${n}".`);S.writeInt32LE(C-(t+4),t)}return new Uint8Array(S)}},SH={args:32,securityAttributes:80,startupInfo:112,processInformation:216,exitCode:240,size:272},CH=104,wH=24,TH=256,EH=134217728,DH=1073741824,OH=3,kH=2,AH=128,jH={sysBuf:264,selfBuf:520,tmpBuf:264,logBuf:600,cmdBuf:4096},MH=1033});function xmlText(t){return t.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`)}function assertPlistText(t,n,S){let C=-1;for(let n of t){let t=n.codePointAt(0)??0;if(t<32&&t!==9&&t!==10&&t!==13){C=t;break}}if(C!==-1)throw Error(`gjsify ship: ${n} would carry the control character U+${C.toString(16).padStart(4,`0`).toUpperCase()}, and XML has no escape for it — the Info.plist would be unparseable by every reader macOS has. Set \`${S}\` to a value without it.`);return t}function stringEntry(t,n){return`\t<key>${t}</key>\n\t<string>${xmlText(n)}</string>`}function arrayEntry(t,n){return`\t<key>${t}</key>\n\t<array>\n${n.map(t=>`\t\t<string>${xmlText(t)}</string>`).join(`
1148
+ `)}\n\t</array>`}function renderInfoPlist(t,n,S){let C=assertPlistText(t.name,`CFBundleName`,`gjsify.ship.name`),N=assertPlistText(t.binaryName,`CFBundleExecutable`,`gjsify.ship.binaryName`),F=assertPlistText(t.appId,`CFBundleIdentifier`,`gjsify.ship.appId`);return[`<?xml version="1.0" encoding="UTF-8"?>`,`<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">`,`<plist version="1.0">`,`<dict>`,...n===void 0?[]:[stringEntry(`ATSApplicationFontsPath`,n)],stringEntry(`CFBundleDevelopmentRegion`,`en`),stringEntry(`CFBundleDisplayName`,C),stringEntry(`CFBundleExecutable`,N),...S===void 0?[]:[stringEntry(`CFBundleIconFile`,S)],stringEntry(`CFBundleIdentifier`,F),stringEntry(`CFBundleInfoDictionaryVersion`,`6.0`),stringEntry(`CFBundleName`,C),stringEntry(`CFBundlePackageType`,LH),stringEntry(`CFBundleShortVersionString`,t.version),stringEntry(`CFBundleSignature`,RH),arrayEntry(`CFBundleSupportedPlatforms`,[`MacOSX`]),stringEntry(`CFBundleVersion`,`${t.version}-${t.release}`),`</dict>`,`</plist>`,``].join(`
1149
+ `)}function renderPkgInfo(){return`${LH}${RH}`}function renderEntitlements(t){return[`<?xml version="1.0" encoding="UTF-8"?>`,`<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">`,`<plist version="1.0">`,`<dict>`,t.map(t=>`\t<key>${xmlText(t)}</key>\n\t<true/>`).join(`
1150
1150
  `),`</dict>`,`</plist>`,``].join(`
1151
- `)}var NH,PH,FH,IH,LH,RH=__esmMin(()=>{NH=`Contents/Info.plist`,PH=`Contents/PkgInfo`,FH=`Contents/Resources`,IH=`APPL`,LH=`????`});function darwinFontsPath(t,n){let S=`${nH.fonts}/${t.appId}`,C=n.find(t=>t.path.startsWith(`${S}/`));if(C===void 0)return;let N=VH.darwin.dirs(t);return Tn.relative(N.other,Tn.dirname(place(VH.darwin,t,C.path)))}function appBundleDir(t){if(zH.test(t.name))throw Error(`gjsify ship: the macOS layout would put this app in "${t.name}.app", and a bundle directory may contain no "/", "\\" or ":" — HFS+ and the Finder swap the first two, so the bundle would not be the one its own metadata names. Set \`gjsify.ship.name\` to the display name you want on disk.`);return`${t.name}.app`}function assertUsableAsHelperName(t){if(t===``||t===`.`||t===`..`||zH.test(t)||t.includes(`\0`))throw Error(`gjsify ship: the macOS layout would name the carried interpreter "${t}" under \`Contents/Helpers\`, and that is not usable as a file name — empty, ".", ".." and anything containing "/", ":", "\\" or a NUL byte are refused. Set \`gjsify.ship.name\` to the display name you want.`);return t}function iconFor(t,n){if(t.kind===`app`){if(t.icon===void 0){if(VH[n].icon?.required!==!0)return;throw Error(`gjsify ship: the ${n} layout writes the application's icon and was given none. A \`kind: "app"\` stage is rendered its icon by \`resolveAppIcon\` before the layout runs; reaching this row without one is a caller that skipped that step.`)}return t.icon}}function launcherPath(t,n){return Tn.join(t.dirs(n).launcher,`${n.binaryName}${t.launcherExt}`)}function windowsGuiLauncherPath(t){let n=VH.windows;if(n.launcherExt.length!==4)throw Error(`gjsify ship: the windows launcher extension is "${n.launcherExt}" and the GUI stub can only reach a four-character one — it rewrites the last three characters of its own filename rather than searching for a path (\`utils/ship/pe-launcher.ts\`).`);return Tn.join(n.dirs(t).launcher,`${t.binaryName}.exe`)}function payloadArchExemptions(t,n){if(t===`win32`)return new Set([windowsGuiLauncherPath(n),...guiExecutables(n).map(t=>windowsGuiLauncherPath({...n,binaryName:t.name}))])}function guiExecutables(t){return(t.executables??[]).filter(t=>t.gui)}function windowsLaunchLogLeaf(t){return`${t.binaryName}.launch.log`}function layoutForOs(t){let n=UH.get(t);if(n===void 0)throw Error(`"${t}" is not a \`process.platform\` token this gjsify has a layout for. Known: ${HH.map(t=>VH[t].os).join(`, `)} — the \`\${process.platform}-\${process.arch}\` spelling, so \`win32\` and never \`windows\`.`);return n}function resolveLayout(t){let n=t.trim().toLowerCase();if(Object.hasOwn(VH,n))return VH[n];let S=UH.get(n);if(S!==void 0)return S;throw Error(`gjsify ship: "${t}" is not an operating system this command has a layout for. Known: ${HH.join(`, `)} (\`win32\` is accepted for \`windows\`, because that is the spelling \`--expect-target <os>-<arch>\` uses).`)}function hostLayout(t=process.platform){let n=UH.get(t);if(n===void 0)throw Error(`gjsify ship: this host is ${t}, which has no layout. Name the one you want — \`gjsify ship <${HH.join(`|`)}> --stage\` — assembly is not host-bound (ADR 0024 § A1).`);return n}function assertLayoutSupportsArch(t,n){let S=t.arches;if(!(S===null||S.only.includes(n)))throw Error(`gjsify ship: the ${t.name} layout is not assemblable for \`--arch ${n}\` — ${S.only.length===1?`the only architecture it has`:`the architectures it has`} ${S.only.length===1?`is`:`are`} ${S.only.join(`, `)}.\n ${S.why}.\n \`--arch\` names the architecture the PAYLOAD was built for and cross-compiles nothing, so there is no
1152
- flag that makes this work — the artifact would carry a runtime that does not exist.`)}function place(t,n,S){let C=t.dirs(n);if(S===`bin/${n.binaryName}`)return launcherPath(t,n);let N=n.executables?.find(t=>S===`bin/${t.name}`);if(N!==void 0)return launcherPath(t,{...n,binaryName:N.name});let F=`lib/${n.binaryName}/`,I=`${F}gi/`;return S.startsWith(I)?Tn.join(C.native,S.slice(I.length)):S.startsWith(F)?Tn.join(C.bundle,S.slice(F.length)):S.startsWith(`bin/`)?Tn.join(C.launcher,S.slice(4)):S.startsWith(`share/`)?Tn.join(C.data,S.slice(6)):Tn.join(C.other,S)}function nameFormBelowRoot(t,n){if(t.nameForm===void 0)return n;let S=t.nameForm,[C,...N]=n.split(Tn.sep);return N.length===0?n:[C,...N.map(t=>t.normalize(S))].join(Tn.sep)}function placeStage(t,n,S,C=[]){let N=new Map,F=[],claim=(n,S,C)=>{let I=nameFormBelowRoot(t,n),H=N.get(I);if(H!==void 0)throw Error(`gjsify ship: in the ${t.name} layout both ${H} and ${S} install as ${I}. Two payload files cannot share one destination — one would silently replace the other. Rename the \`gjsify.ship.extraFiles\` destination that collides.`);N.set(I,S),F.push({...C,path:I})};for(let C of S)claim(place(t,n,C.path),C.path,C);for(let C of t.metadata(n,S))claim(C.path,`the ${t.name} layout's own metadata`,C);for(let n of C)claim(n.path,`the runtime staged into the ${t.name} artifact`,n);return F.sort((t,n)=>t.path<n.path?-1:+(t.path>n.path))}var zH,BH,VH,HH,UH,WH=__esmMin(()=>{qn(),fH(),mH(),MH(),RH(),rH(),zH=/[/:\\]/,BH=[64,128,256],VH={linux:{name:`linux`,os:`linux`,shippedRuntime:`gjs`,launcherExt:``,root:()=>``,dirs:t=>({launcher:`bin`,bundle:`lib/${t.binaryName}`,native:`lib/${t.binaryName}/gi`,data:`share`,other:``,helpers:``,plugins:``}),icon:{sizes:BH,writes:"the hicolor theme's raster icons (`share/icons/hicolor/<n>x<n>/apps/<appId>.png`)",required:!1},metadata:(t,n)=>{let S=iconFor(t,`linux`);if(S===void 0)return[];let C=new Set(n.map(t=>t.path)),N=[];for(let n of[...S.png.keys()].sort((t,n)=>t-n)){let F=`${nH.icons}/${n}x${n}/apps/${t.appId}.png`,I=S.png.get(n);I===void 0||C.has(F)||N.push({path:place(VH.linux,t,F),mode:420,source:{kind:`bytes`,data:I}})}return N},arches:null},darwin:{name:`darwin`,os:`darwin`,shippedRuntime:`node`,runtimeGap:'the staged launcher execs an interpreter off `PATH`, which a downloaded `.app` cannot assume — macOS ships no Node, and there is no RELOCATABLE GJS (`build-gtk-runtime-darwin.mjs`: "GJS ships no relocation"), so ADR 0024 § 4 derives Node here. A self-contained bundle needs `@gjsify/node-runtime-darwin-<arch>` and a `--app node` payload (#1354 M0), or `@gjsify/gjs-runtime-darwin-<arch>` (ADR 0024 stage 7).',fontGap:"the faces are staged in `share/fonts/<appId>` and `Info.plist` carries `ATSApplicationFontsPath` at it, which is macOS's own per-app activation and the route that matters whenever Pango on macOS resolves CoreText by default — which it does on a Homebrew GTK, because that one is not built against fontconfig. A `.app` carrying the bundled GTK runtime reads the same faces through fontconfig instead: `@gjsify/node-gi`'s loader selects it with `PANGOCAIRO_BACKEND=fc` (ADR 0038 § Amendment 3), and `initFonts()` from `@gjsify/gtk-host/fonts` registers them as it does on Windows. Either way no branch is needed in your app: a CoreText map answers G_IO_ERROR_NOT_SUPPORTED and the call reports that as declined. Confirm in the shipped bundle with `PangoCairo.FontMap.get_default().list_families()`, and `PANGOCAIRO_BACKEND=bogus` to print which backends it was built with.",launcherExt:``,nameForm:`NFD`,root:appBundleDir,dirs:t=>{let n=appBundleDir(t);return{launcher:`${n}/Contents/MacOS`,bundle:`${n}/Contents/Resources/lib`,native:`${n}/Contents/Resources/native`,data:`${n}/Contents/Resources/share`,other:`${n}/Contents/Resources`,helpers:`${n}/Contents/Helpers`,plugins:`${n}/Contents/PlugIns`}},icon:{sizes:dH,writes:"the macOS bundle icon (`Contents/Resources/<binaryName>.icns`)",required:!0},metadata:(t,n)=>{let S=iconFor(t,`darwin`),C=S===void 0?void 0:`${t.binaryName}.icns`;return[{path:`${appBundleDir(t)}/${NH}`,mode:420,source:{kind:`text`,text:renderInfoPlist(t,darwinFontsPath(t,n),C)}},{path:`${appBundleDir(t)}/${PH}`,mode:420,source:{kind:`text`,text:renderPkgInfo()}},...S===void 0||C===void 0?[]:[{path:`${appBundleDir(t)}/${FH}/${C}`,mode:420,source:{kind:`bytes`,data:buildIcns(S)}}]]},arches:{only:[`x64`,`arm64`],why:"macOS runs on x86_64 and Apple silicon and nothing else, so those are the two `@gjsify/gtk-runtime-darwin-*` and `@gjsify/node-runtime-darwin-*` targets that exist"}},windows:{name:`windows`,os:`win32`,shippedRuntime:`node`,runtimeGap:"the staged launcher execs an interpreter off `PATH`, which a downloaded program directory cannot assume — Windows ships neither, and there is NO GJS host on Windows at all (ADR 0024 § 4), so § 4 derives Node here. A self-contained directory needs `@gjsify/node-runtime-win32-x64` and a `--app node` payload (#1354 M3).",fontGap:"the faces are staged in `share/fonts/<appId>` and the launcher exports GJSIFY_FONT_DIR at it, but WINDOWS HAS NO DECLARATIVE FONT ACTIVATION and nothing here reaches a bundled face on its own: GTK4 resolves pangowin32, whose font map is populated from DirectWrite and never from fontconfig or from GDI, unless something selects otherwise — which the bundled GTK runtime does (`PANGOCAIRO_BACKEND=fc`, ADR 0038 § Amendment 3), and an app may. MEASURED on the DirectWrite map, Windows 11 / GTK 4.22.4, rather than inferred (ADR 0038 W1-W5): a FONTCONFIG_FILE naming the staged directory moves the default font map by nothing even when it is the ONLY configuration present — that map does not read fontconfig, and exposes no config_changed or set_config with which to make it — while add_font_file on the same map a Gtk.Label renders through does register the family. So register them at startup, with one call from the GTK host layer: `import { initFonts } from '@gjsify/gtk-host/fonts'`, then `initFonts()` before the first window — it reads GJSIFY_FONT_DIR itself, registers every face it holds, and no-ops on the operating systems that already activated them. Without it the app renders in a substituted family with no error.",launcherExt:`.cmd`,root:()=>``,dirs:()=>({launcher:``,bundle:`app`,native:`lib`,data:`share`,other:``,helpers:``,plugins:``}),icon:{sizes:pH,writes:"the Windows launcher icon (`.rsrc` of `<binaryName>.exe`)",required:!0},metadata:t=>{let n=iconFor(t,`windows`);return[{path:windowsGuiLauncherPath(t),mode:493,source:{kind:`bytes`,data:buildGuiLauncher({logLeaf:windowsLaunchLogLeaf(t),...n===void 0?{}:{icon:iconResources(n)}})}},...guiExecutables(t).map(S=>({path:windowsGuiLauncherPath({...t,binaryName:S.name}),mode:493,source:{kind:`bytes`,data:buildGuiLauncher({logLeaf:windowsLaunchLogLeaf({...t,binaryName:S.name}),...n===void 0?{}:{icon:iconResources(n)}})}}))]},arches:{only:[`x64`,`arm64`],why:"win32 runs on x64 natively and on arm64 via the MSVC closure ADR 0089 builds — both have a `@gjsify/gtk-runtime-win32-*` and `@gjsify/node-runtime-win32-*` to stage"}}},HH=Object.keys(VH),UH=new Map(HH.map(t=>[VH[t].os,VH[t]]))});async function compileSchemasForStage(t){if(t.schemaFiles.length===0)return[];rmSync(t.workDir,{recursive:!0,force:!0,maxRetries:5}),mkdirSync(t.workDir,{recursive:!0});for(let n of t.schemaFiles)copyFileSync(n,In(t.workDir,Bn(n)));return await runSchemaCompiler(t.workDir),[{path:JH,mode:420,source:{kind:`file`,path:In(t.workDir,`gschemas.compiled`)}}]}async function compileSchemasForPayload(t){let n=t.payload.filter(t=>isSchemaSource(t.path));if(n.length!==0){rmSync(t.workDir,{recursive:!0,force:!0,maxRetries:5}),mkdirSync(t.workDir,{recursive:!0});for(let S of n)writeFileSync(In(t.workDir,Tn.basename(S.path)),S.data);return await runSchemaCompiler(t.workDir),{path:JH,mode:420,data:readFileSync(In(t.workDir,`gschemas.compiled`))}}}function isSchemaSource(t){return t.startsWith(`${nH.schemas}/`)&&t.endsWith(`.gschema.xml`)}async function runSchemaCompiler(t){try{await GH(KH,[`--strict`,`--targetdir=${t}`,t])}catch(t){let n=t;throw n.code===`ENOENT`?Error(`gjsify ship: this artifact has no install step, so \`${KH}\` has to run HERE to turn the payload's schemas into \`${JH}\` — and it is not on PATH. Install it (${qH}). Without the compiled cache the launcher points XDG_DATA_DIRS at a schema directory GSettings aborts on, so the bundle would build and then die at its first \`Gio.Settings.new()\`.`):Error(`gjsify ship: \`${KH} --strict\` refused this project's schemas.\n${(n.stderr??``).trimEnd()}\n \`--strict\` is deliberate: without it a malformed schema is SKIPPED at exit 0 and a cache
1151
+ `)}var PH,FH,IH,LH,RH,zH=__esmMin(()=>{PH=`Contents/Info.plist`,FH=`Contents/PkgInfo`,IH=`Contents/Resources`,LH=`APPL`,RH=`????`});function darwinFontsPath(t,n){let S=`${rH.fonts}/${t.appId}`,C=n.find(t=>t.path.startsWith(`${S}/`));if(C===void 0)return;let N=HH.darwin.dirs(t);return Tn.relative(N.other,Tn.dirname(place(HH.darwin,t,C.path)))}function appBundleDir(t){if(BH.test(t.name))throw Error(`gjsify ship: the macOS layout would put this app in "${t.name}.app", and a bundle directory may contain no "/", "\\" or ":" — HFS+ and the Finder swap the first two, so the bundle would not be the one its own metadata names. Set \`gjsify.ship.name\` to the display name you want on disk.`);return`${t.name}.app`}function assertUsableAsHelperName(t){if(t===``||t===`.`||t===`..`||BH.test(t)||t.includes(`\0`))throw Error(`gjsify ship: the macOS layout would name the carried interpreter "${t}" under \`Contents/Helpers\`, and that is not usable as a file name — empty, ".", ".." and anything containing "/", ":", "\\" or a NUL byte are refused. Set \`gjsify.ship.name\` to the display name you want.`);return t}function iconFor(t,n){if(t.kind===`app`){if(t.icon===void 0){if(HH[n].icon?.required!==!0)return;throw Error(`gjsify ship: the ${n} layout writes the application's icon and was given none. A \`kind: "app"\` stage is rendered its icon by \`resolveAppIcon\` before the layout runs; reaching this row without one is a caller that skipped that step.`)}return t.icon}}function launcherPath(t,n){return Tn.join(t.dirs(n).launcher,`${n.binaryName}${t.launcherExt}`)}function windowsGuiLauncherPath(t){let n=HH.windows;if(n.launcherExt.length!==4)throw Error(`gjsify ship: the windows launcher extension is "${n.launcherExt}" and the GUI stub can only reach a four-character one — it rewrites the last three characters of its own filename rather than searching for a path (\`utils/ship/pe-launcher.ts\`).`);return Tn.join(n.dirs(t).launcher,`${t.binaryName}.exe`)}function payloadArchExemptions(t,n){if(t===`win32`)return new Set([windowsGuiLauncherPath(n),...guiExecutables(n).map(t=>windowsGuiLauncherPath({...n,binaryName:t.name}))])}function guiExecutables(t){return(t.executables??[]).filter(t=>t.gui)}function windowsLaunchLogLeaf(t){return`${t.binaryName}.launch.log`}function layoutForOs(t){let n=WH.get(t);if(n===void 0)throw Error(`"${t}" is not a \`process.platform\` token this gjsify has a layout for. Known: ${UH.map(t=>HH[t].os).join(`, `)} — the \`\${process.platform}-\${process.arch}\` spelling, so \`win32\` and never \`windows\`.`);return n}function resolveLayout(t){let n=t.trim().toLowerCase();if(Object.hasOwn(HH,n))return HH[n];let S=WH.get(n);if(S!==void 0)return S;throw Error(`gjsify ship: "${t}" is not an operating system this command has a layout for. Known: ${UH.join(`, `)} (\`win32\` is accepted for \`windows\`, because that is the spelling \`--expect-target <os>-<arch>\` uses).`)}function hostLayout(t=process.platform){let n=WH.get(t);if(n===void 0)throw Error(`gjsify ship: this host is ${t}, which has no layout. Name the one you want — \`gjsify ship <${UH.join(`|`)}> --stage\` — assembly is not host-bound (ADR 0024 § A1).`);return n}function assertLayoutSupportsArch(t,n){let S=t.arches;if(!(S===null||S.only.includes(n)))throw Error(`gjsify ship: the ${t.name} layout is not assemblable for \`--arch ${n}\` — ${S.only.length===1?`the only architecture it has`:`the architectures it has`} ${S.only.length===1?`is`:`are`} ${S.only.join(`, `)}.\n ${S.why}.\n \`--arch\` names the architecture the PAYLOAD was built for and cross-compiles nothing, so there is no
1152
+ flag that makes this work — the artifact would carry a runtime that does not exist.`)}function place(t,n,S){let C=t.dirs(n);if(S===`bin/${n.binaryName}`)return launcherPath(t,n);let N=n.executables?.find(t=>S===`bin/${t.name}`);if(N!==void 0)return launcherPath(t,{...n,binaryName:N.name});let F=`lib/${n.binaryName}/`,I=`${F}gi/`;return S.startsWith(I)?Tn.join(C.native,S.slice(I.length)):S.startsWith(F)?Tn.join(C.bundle,S.slice(F.length)):S.startsWith(`bin/`)?Tn.join(C.launcher,S.slice(4)):S.startsWith(`share/`)?Tn.join(C.data,S.slice(6)):Tn.join(C.other,S)}function nameFormBelowRoot(t,n){if(t.nameForm===void 0)return n;let S=t.nameForm,[C,...N]=n.split(Tn.sep);return N.length===0?n:[C,...N.map(t=>t.normalize(S))].join(Tn.sep)}function placeStage(t,n,S,C=[]){let N=new Map,F=[],claim=(n,S,C)=>{let I=nameFormBelowRoot(t,n),H=N.get(I);if(H!==void 0)throw Error(`gjsify ship: in the ${t.name} layout both ${H} and ${S} install as ${I}. Two payload files cannot share one destination — one would silently replace the other. Rename the \`gjsify.ship.extraFiles\` destination that collides.`);N.set(I,S),F.push({...C,path:I})};for(let C of S)claim(place(t,n,C.path),C.path,C);for(let C of t.metadata(n,S))claim(C.path,`the ${t.name} layout's own metadata`,C);for(let n of C)claim(n.path,`the runtime staged into the ${t.name} artifact`,n);return F.sort((t,n)=>t.path<n.path?-1:+(t.path>n.path))}var BH,VH,HH,UH,WH,GH=__esmMin(()=>{qn(),pH(),hH(),NH(),zH(),iH(),BH=/[/:\\]/,VH=[64,128,256],HH={linux:{name:`linux`,os:`linux`,shippedRuntime:`gjs`,launcherExt:``,root:()=>``,dirs:t=>({launcher:`bin`,bundle:`lib/${t.binaryName}`,native:`lib/${t.binaryName}/gi`,data:`share`,other:``,helpers:``,plugins:``}),icon:{sizes:VH,writes:"the hicolor theme's raster icons (`share/icons/hicolor/<n>x<n>/apps/<appId>.png`)",required:!1},metadata:(t,n)=>{let S=iconFor(t,`linux`);if(S===void 0)return[];let C=new Set(n.map(t=>t.path)),N=[];for(let n of[...S.png.keys()].sort((t,n)=>t-n)){let F=`${rH.icons}/${n}x${n}/apps/${t.appId}.png`,I=S.png.get(n);I===void 0||C.has(F)||N.push({path:place(HH.linux,t,F),mode:420,source:{kind:`bytes`,data:I}})}return N},arches:null},darwin:{name:`darwin`,os:`darwin`,shippedRuntime:`node`,runtimeGap:'the staged launcher execs an interpreter off `PATH`, which a downloaded `.app` cannot assume — macOS ships no Node, and there is no RELOCATABLE GJS (`build-gtk-runtime-darwin.mjs`: "GJS ships no relocation"), so ADR 0024 § 4 derives Node here. A self-contained bundle needs `@gjsify/node-runtime-darwin-<arch>` and a `--app node` payload (#1354 M0), or `@gjsify/gjs-runtime-darwin-<arch>` (ADR 0024 stage 7).',fontGap:"the faces are staged in `share/fonts/<appId>` and `Info.plist` carries `ATSApplicationFontsPath` at it, which is macOS's own per-app activation and the route that matters whenever Pango on macOS resolves CoreText by default — which it does on a Homebrew GTK, because that one is not built against fontconfig. A `.app` carrying the bundled GTK runtime reads the same faces through fontconfig instead: `@gjsify/node-gi`'s loader selects it with `PANGOCAIRO_BACKEND=fc` (ADR 0038 § Amendment 3), and `initFonts()` from `@gjsify/gtk-host/fonts` registers them as it does on Windows. Either way no branch is needed in your app: a CoreText map answers G_IO_ERROR_NOT_SUPPORTED and the call reports that as declined. Confirm in the shipped bundle with `PangoCairo.FontMap.get_default().list_families()`, and `PANGOCAIRO_BACKEND=bogus` to print which backends it was built with.",launcherExt:``,nameForm:`NFD`,root:appBundleDir,dirs:t=>{let n=appBundleDir(t);return{launcher:`${n}/Contents/MacOS`,bundle:`${n}/Contents/Resources/lib`,native:`${n}/Contents/Resources/native`,data:`${n}/Contents/Resources/share`,other:`${n}/Contents/Resources`,helpers:`${n}/Contents/Helpers`,plugins:`${n}/Contents/PlugIns`}},icon:{sizes:fH,writes:"the macOS bundle icon (`Contents/Resources/<binaryName>.icns`)",required:!0},metadata:(t,n)=>{let S=iconFor(t,`darwin`),C=S===void 0?void 0:`${t.binaryName}.icns`;return[{path:`${appBundleDir(t)}/${PH}`,mode:420,source:{kind:`text`,text:renderInfoPlist(t,darwinFontsPath(t,n),C)}},{path:`${appBundleDir(t)}/${FH}`,mode:420,source:{kind:`text`,text:renderPkgInfo()}},...S===void 0||C===void 0?[]:[{path:`${appBundleDir(t)}/${IH}/${C}`,mode:420,source:{kind:`bytes`,data:buildIcns(S)}}]]},arches:{only:[`x64`,`arm64`],why:"macOS runs on x86_64 and Apple silicon and nothing else, so those are the two `@gjsify/gtk-runtime-darwin-*` and `@gjsify/node-runtime-darwin-*` targets that exist"}},windows:{name:`windows`,os:`win32`,shippedRuntime:`node`,runtimeGap:"the staged launcher execs an interpreter off `PATH`, which a downloaded program directory cannot assume — Windows ships neither, and there is NO GJS host on Windows at all (ADR 0024 § 4), so § 4 derives Node here. A self-contained directory needs `@gjsify/node-runtime-win32-x64` and a `--app node` payload (#1354 M3).",fontGap:"the faces are staged in `share/fonts/<appId>` and the launcher exports GJSIFY_FONT_DIR at it, but WINDOWS HAS NO DECLARATIVE FONT ACTIVATION and nothing here reaches a bundled face on its own: GTK4 resolves pangowin32, whose font map is populated from DirectWrite and never from fontconfig or from GDI, unless something selects otherwise — which the bundled GTK runtime does (`PANGOCAIRO_BACKEND=fc`, ADR 0038 § Amendment 3), and an app may. MEASURED on the DirectWrite map, Windows 11 / GTK 4.22.4, rather than inferred (ADR 0038 W1-W5): a FONTCONFIG_FILE naming the staged directory moves the default font map by nothing even when it is the ONLY configuration present — that map does not read fontconfig, and exposes no config_changed or set_config with which to make it — while add_font_file on the same map a Gtk.Label renders through does register the family. So register them at startup, with one call from the GTK host layer: `import { initFonts } from '@gjsify/gtk-host/fonts'`, then `initFonts()` before the first window — it reads GJSIFY_FONT_DIR itself, registers every face it holds, and no-ops on the operating systems that already activated them. Without it the app renders in a substituted family with no error.",launcherExt:`.cmd`,root:()=>``,dirs:()=>({launcher:``,bundle:`app`,native:`lib`,data:`share`,other:``,helpers:``,plugins:``}),icon:{sizes:mH,writes:"the Windows launcher icon (`.rsrc` of `<binaryName>.exe`)",required:!0},metadata:t=>{let n=iconFor(t,`windows`);return[{path:windowsGuiLauncherPath(t),mode:493,source:{kind:`bytes`,data:buildGuiLauncher({logLeaf:windowsLaunchLogLeaf(t),...n===void 0?{}:{icon:iconResources(n)}})}},...guiExecutables(t).map(S=>({path:windowsGuiLauncherPath({...t,binaryName:S.name}),mode:493,source:{kind:`bytes`,data:buildGuiLauncher({logLeaf:windowsLaunchLogLeaf({...t,binaryName:S.name}),...n===void 0?{}:{icon:iconResources(n)}})}}))]},arches:{only:[`x64`,`arm64`],why:"win32 runs on x64 natively and on arm64 via the MSVC closure ADR 0089 builds — both have a `@gjsify/gtk-runtime-win32-*` and `@gjsify/node-runtime-win32-*` to stage"}}},UH=Object.keys(HH),WH=new Map(UH.map(t=>[HH[t].os,HH[t]]))});async function compileSchemasForStage(t){if(t.schemaFiles.length===0)return[];rmSync(t.workDir,{recursive:!0,force:!0,maxRetries:5}),mkdirSync(t.workDir,{recursive:!0});for(let n of t.schemaFiles)copyFileSync(n,In(t.workDir,Bn(n)));return await runSchemaCompiler(t.workDir),[{path:YH,mode:420,source:{kind:`file`,path:In(t.workDir,`gschemas.compiled`)}}]}async function compileSchemasForPayload(t){let n=t.payload.filter(t=>isSchemaSource(t.path));if(n.length!==0){rmSync(t.workDir,{recursive:!0,force:!0,maxRetries:5}),mkdirSync(t.workDir,{recursive:!0});for(let S of n)writeFileSync(In(t.workDir,Tn.basename(S.path)),S.data);return await runSchemaCompiler(t.workDir),{path:YH,mode:420,data:readFileSync(In(t.workDir,`gschemas.compiled`))}}}function isSchemaSource(t){return t.startsWith(`${rH.schemas}/`)&&t.endsWith(`.gschema.xml`)}async function runSchemaCompiler(t){try{await KH(qH,[`--strict`,`--targetdir=${t}`,t])}catch(t){let n=t;throw n.code===`ENOENT`?Error(`gjsify ship: this artifact has no install step, so \`${qH}\` has to run HERE to turn the payload's schemas into \`${YH}\` — and it is not on PATH. Install it (${JH}). Without the compiled cache the launcher points XDG_DATA_DIRS at a schema directory GSettings aborts on, so the bundle would build and then die at its first \`Gio.Settings.new()\`.`):Error(`gjsify ship: \`${qH} --strict\` refused this project's schemas.\n${(n.stderr??``).trimEnd()}\n \`--strict\` is deliberate: without it a malformed schema is SKIPPED at exit 0 and a cache
1153
1153
  is written without it, so the app still aborts on the schema that was dropped. Fix the
1154
- file it names, or drop it from \`gjsify.ship.schemas\`.`)}}var GH,KH,qH,JH,YH=__esmMin(()=>{ev(),qn(),ef(),zu(),rH(),GH=promisify(execFile),KH=`glib-compile-schemas`,qH="Fedora: `sudo dnf install glib2`, Debian/Ubuntu: `sudo apt install libglib2.0-bin`",JH=`${nH.schemas}/gschemas.compiled`});function buildTimestamp(t,n=process.env){let S=n.SOURCE_DATE_EPOCH;if(S!==void 0){let t=Number(S);if(!Number.isInteger(t)||t<0)throw Error(`gjsify ship: SOURCE_DATE_EPOCH must be a non-negative integer, got "${S}".`);return t}return Math.floor(statSync(t).mtimeMs/1e3)}function readPayloadFacts(t){let n=t.map(t=>t.path);return{hasDesktopEntry:n.some(t=>isUnder(t,nH.applications)&&t.endsWith(`.desktop`)),hasIcons:n.some(t=>isUnder(t,nH.icons)),hasSchemas:n.some(t=>isUnder(t,nH.schemas)&&t.endsWith(`.gschema.xml`)),hasMimeTypes:n.some(t=>isUnder(t,nH.mime)&&t.endsWith(`.xml`)),bundledTypelibs:n.filter(t=>t.endsWith(`.typelib`))}}function readLauncherInterpreters(t,n,S){let C=t.find(t=>t.path===launcherPath(n,S));if(C===void 0)return[];let N=new TextDecoder().decode(C.data),F=n.name===`windows`?`cmd`:`sh`,I=[];for(let t of F===`cmd`?batchCommands(N):shellExecLines(N)){let n=interpreterOf(t,F);n!==null&&I.push(n)}return[...new Set(I)]}function shellExecLines(t){return[...`\n${t}`.matchAll(/\n[ \t]*exec\s+([^\n]*)/g)].map(t=>t[1].trim())}function cmdTokens(t){let n=[],S=0;for(;S<t.length;){if(/\s/.test(t[S])){S+=1;continue}let C=S,N=!1;for(;S<t.length&&(N||!/\s/.test(t[S]));)t[S]===`"`&&(N=!N),S+=1;n.push({text:t.slice(C,S),end:S})}return n}function splitBatchBlock(t){let n=0,S=!1;for(let C=0;C<t.length;C++){let N=t[C];if(N===`"`)S=!S;else if(!S&&N===`(`)n+=1;else if(!S&&N===`)`&&(--n,n===0))return[t.slice(1,C).trim(),t.slice(C+1).trim()]}return null}function batchPrefix(t){if(t.startsWith(`(`)){let n=splitBatchBlock(t);return n===null?null:[n[0],n[1]]}let n=cmdTokens(t),word=t=>(n[t]?.text??``).toLowerCase(),after=S=>[t.slice(n[S]?.end??t.length).trim()];if(word(0)===`else`)return after(0);if(word(0)===`for`){let t=n.findIndex(t=>t.text.toLowerCase()===`do`);return t===-1?null:after(t)}if(word(0)!==`if`)return;let S=1;for(;word(S)===`not`||word(S)===`/i`;)S+=1;return ZH.has(word(S))?after(S+1):word(S).includes(`==`)?after(S):QH.has(word(S+1))?after(S+2):null}function batchCommands(t){let n=[],S=t.split(/\r?\n/).map(t=>t.trim().replace(/^@+/,``).trim());for(let t=0;t<$H&&S.length>0;t++){let t=S.shift();if(t===``||t===`)`||t.startsWith(`::`))continue;let C=(cmdTokens(t)[0]?.text??``).toLowerCase();if(XH.has(C))continue;let N=batchPrefix(t);N===void 0?n.push(t):N!==null&&S.unshift(...N)}return n}function interpreterOf(t,n){if(n===`cmd`)return cmdProgramOf(t);let S=t.split(/\s+/).filter(t=>t.length>0);for(let t=0;t<2&&S.length>0;t++){let t=basenameOf(S[0]);if(t!==`env`)return t===``?null:t;S=S.slice(1).filter(t=>!t.startsWith(`-`)&&!/^[A-Za-z_][A-Za-z0-9_]*=/.test(t))}return null}function cmdProgramOf(t){let n=/^"([^"]*)"/.exec(t),S=((n===null?t.split(/\s+/)[0]??``:n[1]).replace(/^%[^%\s]*%/,``).split(/[/\\]/).pop()??``).replace(/\.exe$/i,``);return S===``?null:S}function basenameOf(t){let n=unquote(t).split(/[/\\]/);return n[n.length-1]??``}function unquote(t){let n=t[0];return(n===`"`||n===`'`)&&t.length>1&&t[t.length-1]===n?t.slice(1,-1):t}function assertLauncherMatchesInterpreter(t,n,S,C){let N=readLauncherInterpreters(t,n,S);if(N.length===0||N.includes(C))return;let F=C===`gjs`?`node`:`gjs`;if(N.includes(F))throw Error(`gjsify ship: the launcher ${launcherPath(n,S)} execs \`${F}\`, but this package would declare a dependency on \`${C}\`.\n An installed package that depends on one interpreter and runs another installs cleanly and fails
1154
+ file it names, or drop it from \`gjsify.ship.schemas\`.`)}}var KH,qH,JH,YH,XH=__esmMin(()=>{ev(),qn(),ef(),zu(),iH(),KH=promisify(execFile),qH=`glib-compile-schemas`,JH="Fedora: `sudo dnf install glib2`, Debian/Ubuntu: `sudo apt install libglib2.0-bin`",YH=`${rH.schemas}/gschemas.compiled`});function buildTimestamp(t,n=process.env){let S=n.SOURCE_DATE_EPOCH;if(S!==void 0){let t=Number(S);if(!Number.isInteger(t)||t<0)throw Error(`gjsify ship: SOURCE_DATE_EPOCH must be a non-negative integer, got "${S}".`);return t}return Math.floor(statSync(t).mtimeMs/1e3)}function readPayloadFacts(t){let n=t.map(t=>t.path);return{hasDesktopEntry:n.some(t=>isUnder(t,rH.applications)&&t.endsWith(`.desktop`)),hasIcons:n.some(t=>isUnder(t,rH.icons)),hasSchemas:n.some(t=>isUnder(t,rH.schemas)&&t.endsWith(`.gschema.xml`)),hasMimeTypes:n.some(t=>isUnder(t,rH.mime)&&t.endsWith(`.xml`)),bundledTypelibs:n.filter(t=>t.endsWith(`.typelib`))}}function readLauncherInterpreters(t,n,S){let C=t.find(t=>t.path===launcherPath(n,S));if(C===void 0)return[];let N=new TextDecoder().decode(C.data),F=n.name===`windows`?`cmd`:`sh`,I=[];for(let t of F===`cmd`?batchCommands(N):shellExecLines(N)){let n=interpreterOf(t,F);n!==null&&I.push(n)}return[...new Set(I)]}function shellExecLines(t){return[...`\n${t}`.matchAll(/\n[ \t]*exec\s+([^\n]*)/g)].map(t=>t[1].trim())}function cmdTokens(t){let n=[],S=0;for(;S<t.length;){if(/\s/.test(t[S])){S+=1;continue}let C=S,N=!1;for(;S<t.length&&(N||!/\s/.test(t[S]));)t[S]===`"`&&(N=!N),S+=1;n.push({text:t.slice(C,S),end:S})}return n}function splitBatchBlock(t){let n=0,S=!1;for(let C=0;C<t.length;C++){let N=t[C];if(N===`"`)S=!S;else if(!S&&N===`(`)n+=1;else if(!S&&N===`)`&&(--n,n===0))return[t.slice(1,C).trim(),t.slice(C+1).trim()]}return null}function batchPrefix(t){if(t.startsWith(`(`)){let n=splitBatchBlock(t);return n===null?null:[n[0],n[1]]}let n=cmdTokens(t),word=t=>(n[t]?.text??``).toLowerCase(),after=S=>[t.slice(n[S]?.end??t.length).trim()];if(word(0)===`else`)return after(0);if(word(0)===`for`){let t=n.findIndex(t=>t.text.toLowerCase()===`do`);return t===-1?null:after(t)}if(word(0)!==`if`)return;let S=1;for(;word(S)===`not`||word(S)===`/i`;)S+=1;return QH.has(word(S))?after(S+1):word(S).includes(`==`)?after(S):$H.has(word(S+1))?after(S+2):null}function batchCommands(t){let n=[],S=t.split(/\r?\n/).map(t=>t.trim().replace(/^@+/,``).trim());for(let t=0;t<eU&&S.length>0;t++){let t=S.shift();if(t===``||t===`)`||t.startsWith(`::`))continue;let C=(cmdTokens(t)[0]?.text??``).toLowerCase();if(ZH.has(C))continue;let N=batchPrefix(t);N===void 0?n.push(t):N!==null&&S.unshift(...N)}return n}function interpreterOf(t,n){if(n===`cmd`)return cmdProgramOf(t);let S=t.split(/\s+/).filter(t=>t.length>0);for(let t=0;t<2&&S.length>0;t++){let t=basenameOf(S[0]);if(t!==`env`)return t===``?null:t;S=S.slice(1).filter(t=>!t.startsWith(`-`)&&!/^[A-Za-z_][A-Za-z0-9_]*=/.test(t))}return null}function cmdProgramOf(t){let n=/^"([^"]*)"/.exec(t),S=((n===null?t.split(/\s+/)[0]??``:n[1]).replace(/^%[^%\s]*%/,``).split(/[/\\]/).pop()??``).replace(/\.exe$/i,``);return S===``?null:S}function basenameOf(t){let n=unquote(t).split(/[/\\]/);return n[n.length-1]??``}function unquote(t){let n=t[0];return(n===`"`||n===`'`)&&t.length>1&&t[t.length-1]===n?t.slice(1,-1):t}function assertLauncherMatchesInterpreter(t,n,S,C){let N=readLauncherInterpreters(t,n,S);if(N.length===0||N.includes(C))return;let F=C===`gjs`?`node`:`gjs`;if(N.includes(F))throw Error(`gjsify ship: the launcher ${launcherPath(n,S)} execs \`${F}\`, but this package would declare a dependency on \`${C}\`.\n An installed package that depends on one interpreter and runs another installs cleanly and fails
1155
1155
  at first launch, on the user's machine.
1156
1156
  Either set \`gjsify.ship.app.${n.os}\` to "${F}" in the project this was staged from — it overrides
1157
1157
  \`gjsify.app\` for that target alone — or fix the launcher: if it comes from \`gjsify.ship.extraFiles\`,
1158
- that override is what decides which interpreter runs and it must match the declaration.`)}function linuxInstallDependent(t){let n=[],S={hasCompiledSchemas:t.some(t=>t.path===JH)};for(let C of t){if(!isUnder(C.path,`share`)||tU.some(t=>C.path===t||isUnder(C.path,t)))continue;let t=eU.find(([t])=>isUnder(C.path,t));if(t===void 0){n.push({path:C.path,verdict:`unknown`,why:`nothing here classifies this directory — it may need an install step no non-Linux layout runs, or it may be inert; say which before shipping it`});continue}let[N,F]=t[1](S);n.push({path:C.path,verdict:N,why:F})}let C={aborts:0,unknown:1,inert:2};return n.sort((t,n)=>C[t.verdict]-C[n.verdict]||(t.path<n.path?-1:1))}function readShebangInterpreters(t){let n=new Set;for(let S of t){if(!(S.mode&73))continue;let t=readShebang(S.data);t!==null&&n.add(t)}return[...n].sort()}function readShebang(t){if(t[0]!==35||t[1]!==33)return null;let n=(new TextDecoder().decode(t.subarray(2,Math.min(t.byteLength,256))).split(`
1159
- `)[0]??``).trim().split(/\s+/)[0]??``;return n.startsWith(`/`)?n:null}function isArchIndependent(t){return!t.some(t=>isNativeBinary(t.data))}function readBinaryArch(t){if(t.byteLength<20)return null;let n=(t[0]<<24|t[1]<<16|t[2]<<8|t[3])>>>0;if(n===2135247942){let n=t[5]===1?t[18]|t[19]<<8:t[18]<<8|t[19];return nU[n]??null}if(n===4277009102||n===4277009103)return rU[(t[4]<<24|t[5]<<16|t[6]<<8|t[7])>>>0]??null;if(n===3472551422||n===3489328638)return rU[(t[7]<<24|t[6]<<16|t[5]<<8|t[4])>>>0]??null;if(t[0]===77&&t[1]===90&&t.byteLength>=64){let n=(t[60]|t[61]<<8|t[62]<<16|t[63]<<24)>>>0;return n+6>t.byteLength||(t[n]|t[n+1]<<8|t[n+2]<<16)>>>0!=17744||t[n+3]!==0?null:iU[t[n+4]|t[n+5]<<8]??null}return null}function assertPayloadMatchesArch(t,n,S={}){for(let C of t){let t=readBinaryArch(C.data);if(!(t===null||t===n)&&!S.exempt?.has(C.path))throw Error(`gjsify ship: the payload is ${t}, but the package would be labelled ${n} — ${C.path} is built for ${t}.\n \`--arch\` names the architecture the PAYLOAD was built for; it does not cross-compile anything.
1160
- A package labelled ${n} installs on ${n} and then fails to load. Build the payload for ${n}\n (its own prebuild), or assemble the stage without \`--arch\` and label the payload you actually have.`)}}function classifyBinary(t){if(t.byteLength<4)return null;switch((t[0]<<24|t[1]<<16|t[2]<<8|t[3])>>>0){case 2135247942:return`elf`;case 4277009102:case 4277009103:case 3472551422:case 3489328638:case 3405691582:return`macho`;default:return t[0]===77&&t[1]===90?`pe`:null}}function isNativeBinary(t){return classifyBinary(t)!==null}var XH,ZH,QH,$H,eU,tU,nU,rU,iU,aU=__esmMin(()=>{ef(),WH(),YH(),rH(),XH=new Set([`rem`,`set`,`setlocal`,`endlocal`,`echo`,`goto`,`exit`,`title`,`pause`,`shift`,`cd`,`chdir`,`pushd`,`popd`,`color`,`cls`,`verify`,`prompt`]),ZH=new Set([`exist`,`defined`,`errorlevel`]),QH=new Set([`equ`,`neq`,`lss`,`leq`,`gtr`,`geq`]),$H=32,eU=[[nH.schemas,({hasCompiledSchemas:t})=>t?[`inert`,"the schema SOURCE; `gschemas.compiled` is staged beside it and that is what GSettings reads, so this file is carried and never opened"]:[`aborts`,"needs `glib-compile-schemas`, and the launcher points XDG_DATA_DIRS here — GSettings ABORTS on a schema directory with no `gschemas.compiled`"]],[nH.mime,()=>[`inert`,"needs `update-mime-database`; detection runs off the compiled cache"]],[nH.icons,()=>[`inert`,"needs `gtk-update-icon-cache`; neither OS reads the hicolor theme"]],[nH.applications,()=>[`inert`,`a freedesktop desktop entry; neither OS reads one`]],[nH.metainfo,()=>[`inert`,`an AppStream component; neither OS reads one`]]],tU=[nH.locale,nH.fonts,JH],nU={3:`ia32`,21:`ppc64`,22:`s390x`,40:`arm`,62:`x64`,183:`arm64`,243:`riscv64`},rU={7:`ia32`,12:`arm`,16777223:`x64`,16777228:`arm64`},iU={332:`ia32`,34404:`x64`,43620:`arm64`}});async function buildDeb(t){let{payload:n,mtime:S}=t,C=t.prefix.replace(/^\/+/,``),N=n.map(t=>({...t,tarPath:`./${Tn.join(C,t.path)}`})),F=ancestorDirectories(N.map(t=>t.tarPath)),I=await gzipDeterministic(createTarball([...F.map(t=>({name:t,mode:493,mtime:S,directory:!0})),...N.map(t=>({name:t.tarPath,body:t.data,mode:t.mode,mtime:S}))])),H=renderControl(t,N.reduce((t,n)=>t+Math.ceil(n.data.byteLength/1024),0)+F.length),W=N.map(t=>`${createHash(`md5`).update(t.data).digest(`hex`)} ${t.tarPath.slice(2)}\n`).join(``),q=[{name:`./`,mode:493,mtime:S,directory:!0},{name:`./control`,body:H,mode:420,mtime:S},{name:`./md5sums`,body:W,mode:420,mtime:S}],Y=renderDebScripts(readPayloadFacts(n),t.prefix);for(let[t,n]of Object.entries(Y))q.push({name:`./${t}`,body:n,mode:493,mtime:S});let X=await gzipDeterministic(createTarball(q));return createArArchive([{name:`debian-binary`,data:new TextEncoder().encode(`2.0
1158
+ that override is what decides which interpreter runs and it must match the declaration.`)}function linuxInstallDependent(t){let n=[],S={hasCompiledSchemas:t.some(t=>t.path===YH)};for(let C of t){if(!isUnder(C.path,`share`)||nU.some(t=>C.path===t||isUnder(C.path,t)))continue;let t=tU.find(([t])=>isUnder(C.path,t));if(t===void 0){n.push({path:C.path,verdict:`unknown`,why:`nothing here classifies this directory — it may need an install step no non-Linux layout runs, or it may be inert; say which before shipping it`});continue}let[N,F]=t[1](S);n.push({path:C.path,verdict:N,why:F})}let C={aborts:0,unknown:1,inert:2};return n.sort((t,n)=>C[t.verdict]-C[n.verdict]||(t.path<n.path?-1:1))}function readShebangInterpreters(t){let n=new Set;for(let S of t){if(!(S.mode&73))continue;let t=readShebang(S.data);t!==null&&n.add(t)}return[...n].sort()}function readShebang(t){if(t[0]!==35||t[1]!==33)return null;let n=(new TextDecoder().decode(t.subarray(2,Math.min(t.byteLength,256))).split(`
1159
+ `)[0]??``).trim().split(/\s+/)[0]??``;return n.startsWith(`/`)?n:null}function isArchIndependent(t){return!t.some(t=>isNativeBinary(t.data))}function readBinaryArch(t){if(t.byteLength<20)return null;let n=(t[0]<<24|t[1]<<16|t[2]<<8|t[3])>>>0;if(n===2135247942){let n=t[5]===1?t[18]|t[19]<<8:t[18]<<8|t[19];return rU[n]??null}if(n===4277009102||n===4277009103)return iU[(t[4]<<24|t[5]<<16|t[6]<<8|t[7])>>>0]??null;if(n===3472551422||n===3489328638)return iU[(t[7]<<24|t[6]<<16|t[5]<<8|t[4])>>>0]??null;if(t[0]===77&&t[1]===90&&t.byteLength>=64){let n=(t[60]|t[61]<<8|t[62]<<16|t[63]<<24)>>>0;return n+6>t.byteLength||(t[n]|t[n+1]<<8|t[n+2]<<16)>>>0!=17744||t[n+3]!==0?null:aU[t[n+4]|t[n+5]<<8]??null}return null}function assertPayloadMatchesArch(t,n,S={}){for(let C of t){let t=readBinaryArch(C.data);if(!(t===null||t===n)&&!S.exempt?.has(C.path))throw Error(`gjsify ship: the payload is ${t}, but the package would be labelled ${n} — ${C.path} is built for ${t}.\n \`--arch\` names the architecture the PAYLOAD was built for; it does not cross-compile anything.
1160
+ A package labelled ${n} installs on ${n} and then fails to load. Build the payload for ${n}\n (its own prebuild), or assemble the stage without \`--arch\` and label the payload you actually have.`)}}function classifyBinary(t){if(t.byteLength<4)return null;switch((t[0]<<24|t[1]<<16|t[2]<<8|t[3])>>>0){case 2135247942:return`elf`;case 4277009102:case 4277009103:case 3472551422:case 3489328638:case 3405691582:return`macho`;default:return t[0]===77&&t[1]===90?`pe`:null}}function isNativeBinary(t){return classifyBinary(t)!==null}var ZH,QH,$H,eU,tU,nU,rU,iU,aU,oU=__esmMin(()=>{ef(),GH(),XH(),iH(),ZH=new Set([`rem`,`set`,`setlocal`,`endlocal`,`echo`,`goto`,`exit`,`title`,`pause`,`shift`,`cd`,`chdir`,`pushd`,`popd`,`color`,`cls`,`verify`,`prompt`]),QH=new Set([`exist`,`defined`,`errorlevel`]),$H=new Set([`equ`,`neq`,`lss`,`leq`,`gtr`,`geq`]),eU=32,tU=[[rH.schemas,({hasCompiledSchemas:t})=>t?[`inert`,"the schema SOURCE; `gschemas.compiled` is staged beside it and that is what GSettings reads, so this file is carried and never opened"]:[`aborts`,"needs `glib-compile-schemas`, and the launcher points XDG_DATA_DIRS here — GSettings ABORTS on a schema directory with no `gschemas.compiled`"]],[rH.mime,()=>[`inert`,"needs `update-mime-database`; detection runs off the compiled cache"]],[rH.icons,()=>[`inert`,"needs `gtk-update-icon-cache`; neither OS reads the hicolor theme"]],[rH.applications,()=>[`inert`,`a freedesktop desktop entry; neither OS reads one`]],[rH.metainfo,()=>[`inert`,`an AppStream component; neither OS reads one`]]],nU=[rH.locale,rH.fonts,YH],rU={3:`ia32`,21:`ppc64`,22:`s390x`,40:`arm`,62:`x64`,183:`arm64`,243:`riscv64`},iU={7:`ia32`,12:`arm`,16777223:`x64`,16777228:`arm64`},aU={332:`ia32`,34404:`x64`,43620:`arm64`}});async function buildDeb(t){let{payload:n,mtime:S}=t,C=t.prefix.replace(/^\/+/,``),N=n.map(t=>({...t,tarPath:`./${Tn.join(C,t.path)}`})),F=ancestorDirectories(N.map(t=>t.tarPath)),I=await gzipDeterministic(createTarball([...F.map(t=>({name:t,mode:493,mtime:S,directory:!0})),...N.map(t=>({name:t.tarPath,body:t.data,mode:t.mode,mtime:S}))])),H=renderControl(t,N.reduce((t,n)=>t+Math.ceil(n.data.byteLength/1024),0)+F.length),W=N.map(t=>`${createHash(`md5`).update(t.data).digest(`hex`)} ${t.tarPath.slice(2)}\n`).join(``),q=[{name:`./`,mode:493,mtime:S,directory:!0},{name:`./control`,body:H,mode:420,mtime:S},{name:`./md5sums`,body:W,mode:420,mtime:S}],Y=renderDebScripts(readPayloadFacts(n),t.prefix);for(let[t,n]of Object.entries(Y))q.push({name:`./${t}`,body:n,mode:493,mtime:S});let X=await gzipDeterministic(createTarball(q));return createArArchive([{name:`debian-binary`,data:new TextEncoder().encode(`2.0
1161
1161
  `),mtime:S},{name:`control.tar.gz`,data:X,mtime:S},{name:`data.tar.gz`,data:I,mtime:S}])}function singleLine(t){return t.replace(/[\r\n]+/g,` `).trim()}function ancestorDirectories(t){let n=new Set([`./`]);for(let S of t){let t=S.replace(/^\.\//,``).split(`/`);t.pop();let C=`.`;for(let S of t)C=`${C}/${S}`,n.add(`${C}/`)}return[...n].sort()}function renderControl(t,n){let{settings:S}=t,C=[[`Package`,S.binaryName],[`Version`,`${S.version}-${S.release}`],[`Architecture`,t.archLabel],[`Maintainer`,S.maintainer],[`Installed-Size`,String(n)]];t.depends.length>0&&C.push([`Depends`,t.depends.map(formatDebDepend).join(`, `)]),t.recommends!==void 0&&t.recommends.length>0&&C.push([`Recommends`,t.recommends.map(formatDebDepend).join(`, `)]),C.push([`Section`,S.section],[`Priority`,`optional`]),S.homepage&&C.push([`Homepage`,S.homepage]);let N=C.map(([t,n])=>`${t}: ${singleLine(n)}`);return N.push(`Description: ${singleLine(S.summary)}`),S.description.filter(t=>t!==S.summary).forEach((t,n)=>{n>0&&N.push(` .`),N.push(` ${t}`)}),`${N.join(`
1162
- `)}\n`}var oU=__esmMin(()=>{fl(),qn(),KR(),GV(),eH(),tH(),iH(),aU()});function xmlEscape(t){return t.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&apos;`)}var sU=__esmMin(()=>{});function validateMimeTypes(t){let n=new Set;for(let S of t){if(!cU.test(S.type))throw Error(`gjsify ship: \`gjsify.ship.mimeTypes\` has an invalid type "${S.type}". Expected \`<media>/<subtype>\`, e.g. \`application/x-bauplan\` — update-mime-database ignores a malformed name, so the type would install and never resolve.`);if(n.has(S.type))throw Error(`gjsify ship: \`gjsify.ship.mimeTypes\` defines ${S.type} twice. Which comment and glob set win would depend on document order.`);if(n.add(S.type),S.comment.trim()===``)throw Error(`gjsify ship: ${S.type} has an empty \`comment\`. A file manager then shows the user the raw type string instead of a name.`);for(let t of S.globs??[])if(!t.includes(`*`)&&!t.includes(`?`)&&!t.includes(`[`))throw Error(`gjsify ship: ${S.type} has the glob "${t}", which matches only a file named exactly that. A suffix pattern is written \`*.${t.replace(/^\.+/,``)}\`.`);if((S.globs??[]).length===0&&S.subClassOf===void 0)throw Error(`gjsify ship: ${S.type} declares neither \`globs\` nor \`subClassOf\`, so nothing can ever match it. The type would be registered and then never assigned to a file.`)}}function renderMimePackage(t){return`<?xml version="1.0" encoding="UTF-8"?>
1162
+ `)}\n`}var sU=__esmMin(()=>{fl(),qn(),KR(),KV(),tH(),nH(),aH(),oU()});function xmlEscape(t){return t.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&apos;`)}var cU=__esmMin(()=>{});function validateMimeTypes(t){let n=new Set;for(let S of t){if(!lU.test(S.type))throw Error(`gjsify ship: \`gjsify.ship.mimeTypes\` has an invalid type "${S.type}". Expected \`<media>/<subtype>\`, e.g. \`application/x-bauplan\` — update-mime-database ignores a malformed name, so the type would install and never resolve.`);if(n.has(S.type))throw Error(`gjsify ship: \`gjsify.ship.mimeTypes\` defines ${S.type} twice. Which comment and glob set win would depend on document order.`);if(n.add(S.type),S.comment.trim()===``)throw Error(`gjsify ship: ${S.type} has an empty \`comment\`. A file manager then shows the user the raw type string instead of a name.`);for(let t of S.globs??[])if(!t.includes(`*`)&&!t.includes(`?`)&&!t.includes(`[`))throw Error(`gjsify ship: ${S.type} has the glob "${t}", which matches only a file named exactly that. A suffix pattern is written \`*.${t.replace(/^\.+/,``)}\`.`);if((S.globs??[]).length===0&&S.subClassOf===void 0)throw Error(`gjsify ship: ${S.type} declares neither \`globs\` nor \`subClassOf\`, so nothing can ever match it. The type would be registered and then never assigned to a file.`)}}function renderMimePackage(t){return`<?xml version="1.0" encoding="UTF-8"?>
1163
1163
  <mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
1164
1164
  ${t.map(t=>{let n=[` <mime-type type="${xmlEscape(t.type)}">`,` <comment>${xmlEscape(t.comment)}</comment>`];t.subClassOf!==void 0&&n.push(` <sub-class-of type="${xmlEscape(t.subClassOf)}"/>`);for(let S of t.globs??[])n.push(` <glob pattern="${xmlEscape(S)}"/>`);return t.genericIcon!==void 0&&n.push(` <generic-icon name="${xmlEscape(t.genericIcon)}"/>`),n.push(` </mime-type>`),n.join(`
1165
1165
  `)}).join(`
1166
1166
  `)}
1167
1167
  </mime-info>
1168
- `}var cU,lU=__esmMin(()=>{sU(),cU=/^[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*$/});function normaliseVersion(t){let n=[],S=t.trim();S.startsWith(`v`)&&(S=S.slice(1));let C=S.indexOf(`+`);C!==-1&&(n.push(`gjsify ship: dropped the build metadata "${S.slice(C)}" from version ${t} — neither dpkg nor rpm has a field for it. Set \`gjsify.ship.version\` to pin an exact package version.`),S=S.slice(0,C));let N=S.indexOf(`-`);if(N!==-1){let t=S.slice(N+1).replace(/-/g,`.`);S=`${S.slice(0,N)}~${t}`}if(!uU.test(S))throw Error(`gjsify ship: "${t}" is not a usable package version (normalised to "${S}"). It must start with a digit and contain only letters, digits, \`.\`, \`+\` and \`~\`. Set \`gjsify.ship.version\` in package.json to override it.`);return{version:S,warnings:n}}function assertRelease(t){if(!dU.test(t))throw Error(`gjsify ship: "${t}" is not a usable package release. It must start with a letter or digit and contain only letters, digits, \`.\`, \`+\` and \`~\`. Set \`gjsify.ship.release\` in package.json.`);return t}var uU,dU,fU=__esmMin(()=>{uU=/^\d[A-Za-z0-9.+~]*$/,dU=/^[A-Za-z0-9][A-Za-z0-9.+~]*$/});function resolveShipApp(t){let n=t.perTarget??{};for(let t of Object.keys(n))if(!Object.hasOwn(pU,t))throw Error(`gjsify ship: \`gjsify.ship.app.${t}\` is not an OS this command assembles for. Known: ${Object.keys(pU).join(`, `)} — the \`process.platform\` spelling, not the \`gjsify ship <os>\` positional's. A runtime under a key nothing reads leaves that target on \`gjsify.app\` with nothing to say so.`);let S=n[t.layoutOs],C=S!==void 0,N=C?`gjsify.ship.app.${t.layoutOs}`:`gjsify.app`,F=C?S:t.project;if(F!==void 0&&F!==`gjs`&&F!==`node`)throw Error(`gjsify ship: \`${N}\` is "${F}", and only \`gjs\` and \`node\` can be packaged. A browser bundle has no process to launch, and a NativeScript app ships as an APK/IPA through a different pipeline. ADR 0024 § 4 has the runtime-per-OS table.`);return{app:F===`node`?`node`:`gjs`,key:N,overridden:C}}function resolveShipKind(t,n){return t.kind??n.kind??`app`}function resolveShipSettings(t){let n=[],{pkg:S,ship:C,flatpak:N,discovered:F}=t,I={...N,...definedOnly(C)},H=C.mimeTypes??[];if(H.length>0){validateMimeTypes(H);let t=new Set([...I.provides?.mimetypes??[],...H.map(t=>t.type)]);I.provides={...I.provides,mimetypes:[...t]}}let W=C.binaryName??deriveBinaryName(S.name),q=C.appId??N.appId??reverseDnsOrThrow(S.name,W),Y=I.name??titleCase(W),X=resolveShipKind(C,N),Z=t.app,te=C.version??S.version;if(!te)throw Error("gjsify ship: no version — set `version` in package.json or `gjsify.ship.version`.");let ne=normaliseVersion(te);n.push(...ne.warnings);let re=I.license?.project??S.license;if(!re)throw Error('gjsify ship: no licence — set `license` in package.json (an SPDX id, e.g. "MIT") or `gjsify.ship.license.project`. Both deb and rpm carry it as a required field.');I.license={...I.license,project:re};let ie=C.maintainer??formatAuthor(S.author)??formatDeveloper(I);if(!ie)throw Error('gjsify ship: no maintainer — set `author` in package.json ("Name <you@example.com>"), `gjsify.ship.maintainer`, or `gjsify.ship.developer`. dpkg refuses a package without one.');let ae=I.summary??S.description??Y,oe=descriptionParagraphs(I.description)??[ae],Q=sectionsFor(I.categories);X===`app`&&F.iconFiles.length===0&&n.push("gjsify ship: no icon found — the installed app will show a placeholder in menus on Linux, the Flatpak will carry no catalogue icon for an app store to show, and the darwin and windows layouts refuse to stage without one. Point `gjsify.ship.icon` at an SVG (or a directory of sized PNGs).");let se=resolveShipFlatpakSettings({ship:C,flatpak:N,kind:X});return n.push(...se.warnings),{settings:{projectDir:t.projectDir,appId:q,name:Y,binaryName:W,version:ne.version,release:assertRelease(C.release??`1`),maintainer:ie,summary:ae,description:oe,license:re,licenseFile:F.licenseFile,changelogFile:F.changelogFile,homepage:I.homepageUrl??S.homepage,section:C.section??Q.section,group:C.group??Q.group,kind:X,mimeTypes:H,extraDepends:{deb:C.depends?.deb??[],rpm:C.depends?.rpm??[]},typelibPackages:C.typelibPackages??{},bundlePath:F.bundlePath,bundleDir:F.bundleDir,iconFiles:F.iconFiles,schemaFiles:F.schemaFiles,typelibFiles:F.typelibFiles,formatFiles:F.formatFiles,localeFiles:F.localeFiles,fontFiles:F.fontFiles,extraFiles:C.extraFiles??{},execArgs:C.execArgs??[],executables:resolveShipExecutables({declared:C.executables,binaryName:W,projectDir:t.projectDir,bundleDir:F.bundleDir}),nestedBundles:resolveShipNestedBundles({declared:C.nestedBundles,projectDir:t.projectDir,layoutOs:t.cli.layoutOs}),helperExecutables:resolveShipHelperExecutables({declared:C.helperExecutables,projectDir:t.projectDir,layoutOs:t.cli.layoutOs}),outDir:t.cli.outDir??C.outDir??`ship`,arch:t.cli.arch??process.arch,app:Z,layoutOs:t.cli.layoutOs,minGjsVersion:C.minGjsVersion??`1.86`,minNodeVersion:C.minNodeVersion??`24`,flatpak:se.settings},metadata:I,warnings:n}}function resolveShipExecutables(t){let{declared:n}=t;if(n===void 0)return[];if(!Array.isArray(n))throw Error('gjsify ship: `gjsify.ship.executables` must be a list of `{ "name", "entry", "gui"? }` objects.');let S=new Set([t.binaryName]);return n.map((n,C)=>{let N=`gjsify.ship.executables[${C}]`;if(typeof n!=`object`||!n||Array.isArray(n))throw Error(`gjsify ship: \`${N}\` must be an object with \`name\` and \`entry\`.`);let{name:F,entry:I,gui:H,...W}=n,q=Object.keys(W);if(q.length>0)throw Error(`gjsify ship: \`${N}\` has unknown key(s) ${q.join(`, `)}; known: name, entry, gui.`);if(typeof F!=`string`||!hU.test(F))throw Error(`gjsify ship: \`${N}.name\` must match ${hU} — it becomes \`bin/<name>\`, \`Contents/MacOS/<name>\` and \`<name>.cmd\`, so it is lower-case with no path separator or space.`);if(S.has(F))throw Error(`gjsify ship: \`${N}.name\` "${F}" is already taken — by the package's own \`binaryName\` or by an earlier entry. Two launchers cannot share one file name.`);if(S.add(F),typeof I!=`string`||I===``)throw Error(`gjsify ship: \`${N}.entry\` must be the project-relative path of a built bundle.`);if(H!==void 0&&typeof H!=`boolean`)throw Error(`gjsify ship: \`${N}.gui\` must be a boolean.`);let Y=Fn(I)?I:Nn(t.projectDir,I),X=Ln(t.bundleDir,Y);if(X===``||X.startsWith(`..`)||Fn(X))throw Error(`gjsify ship: \`${N}.entry\` ${I} is outside ${t.bundleDir}, the directory \`gjsify.main\` lives in — only that directory is staged, so the launcher would point at a file the package does not carry. Build the entries into one directory.`);return{name:F,entry:X.split(Wn).join(Tn.sep),gui:H===!0}})}function assertUsableBundleLeaf(t,n,S){if(t===``||t===`.`||t===`..`||t.includes(`/`)||t.includes(`\\`)||t.includes(`\0`))throw Error(`gjsify ship: \`${n}.name\` "${t}" is not usable as a leaf under \`${S}\` — empty and ".", "..", and anything containing "/", "\\" or a NUL byte are refused.`);return t}function resolveShipNestedBundles(t){let{declared:n}=t;if(n===void 0)return[];if(!Array.isArray(n))throw Error('gjsify ship: `gjsify.ship.nestedBundles` must be a list of `{ "source", "name", "entitlements"? }` objects.');if(n.length>0&&t.layoutOs!==`darwin`)throw Error(`gjsify ship: \`gjsify.ship.nestedBundles\` is set and this run assembles the ${t.layoutOs} layout, which has no \`Contents/PlugIns\` or equivalent — a Flatpak sandbox has no App Extension model and a Windows program directory has nothing Apple's extension points name. Nested bundles are staged only for \`gjsify ship darwin\`.`);let S=new Set;return n.map((n,C)=>{let N=`gjsify.ship.nestedBundles[${C}]`;if(typeof n!=`object`||!n||Array.isArray(n))throw Error(`gjsify ship: \`${N}\` must be an object with \`source\` and \`name\`.`);let{source:F,name:I,entitlements:H,...W}=n,q=Object.keys(W);if(q.length>0)throw Error(`gjsify ship: \`${N}\` has unknown key(s) ${q.join(`, `)}; known: source, name, entitlements.`);if(typeof F!=`string`||F===``)throw Error(`gjsify ship: \`${N}.source\` must be the project-relative directory of a built bundle.`);if(typeof I!=`string`)throw Error(`gjsify ship: \`${N}.name\` must be a string — the leaf under \`Contents/PlugIns/\`.`);if(assertUsableBundleLeaf(I,N,`Contents/PlugIns`),S.has(I))throw Error(`gjsify ship: \`${N}.name\` "${I}" is already taken by an earlier nested bundle.`);S.add(I);let Y=Fn(F)?F:Nn(t.projectDir,F);if(!existsSync(Y))throw Error(`gjsify ship: \`${N}.source\` ${F} does not exist.`);if(H!==void 0&&!Array.isArray(H))throw Error(`gjsify ship: \`${N}.entitlements\` must be a list of strings.`);return{source:Y,name:I,entitlements:(H??[]).map((t,n)=>{if(typeof t!=`string`)throw Error(`gjsify ship: \`${N}.entitlements[${n}]\` must be a string.`);return t})}})}function resolveShipHelperExecutables(t){let{declared:n}=t;if(n===void 0)return[];if(!Array.isArray(n))throw Error('gjsify ship: `gjsify.ship.helperExecutables` must be a list of `{ "source", "name", "entitlements"? }` objects.');if(n.length>0&&t.layoutOs!==`darwin`)throw Error(`gjsify ship: \`gjsify.ship.helperExecutables\` is set and this run assembles the ${t.layoutOs} layout, which has no \`Contents/Helpers\` or equivalent. Helper executables are staged only for \`gjsify ship darwin\`.`);let S=new Set;return n.map((n,C)=>{let N=`gjsify.ship.helperExecutables[${C}]`;if(typeof n!=`object`||!n||Array.isArray(n))throw Error(`gjsify ship: \`${N}\` must be an object with \`source\` and \`name\`.`);let{source:F,name:I,entitlements:H,...W}=n,q=Object.keys(W);if(q.length>0)throw Error(`gjsify ship: \`${N}\` has unknown key(s) ${q.join(`, `)}; known: source, name, entitlements.`);if(typeof F!=`string`||F===``)throw Error(`gjsify ship: \`${N}.source\` must be the project-relative path of a prebuilt executable.`);if(typeof I!=`string`)throw Error(`gjsify ship: \`${N}.name\` must be a string — the leaf under \`Contents/Helpers/\`.`);if(assertUsableBundleLeaf(I,N,`Contents/Helpers`),S.has(I))throw Error(`gjsify ship: \`${N}.name\` "${I}" is already taken by an earlier helper executable.`);S.add(I);let Y=Fn(F)?F:Nn(t.projectDir,F);if(!existsSync(Y))throw Error(`gjsify ship: \`${N}.source\` ${F} does not exist.`);if(H!==void 0&&!Array.isArray(H))throw Error(`gjsify ship: \`${N}.entitlements\` must be a list of strings.`);return{source:Y,name:I,entitlements:(H??[]).map((t,n)=>{if(typeof t!=`string`)throw Error(`gjsify ship: \`${N}.entitlements[${n}]\` must be a string.`);return t})}})}function resolveShipBundle(t){let n=t.ship.bundle,S=typeof n==`object`&&n?n:{};for(let t of Object.keys(S))if(!Object.hasOwn(pU,t))throw Error(`gjsify ship: \`gjsify.ship.bundle.${t}\` is not an OS this command assembles for. Known: ${Object.keys(pU).join(`, `)} — the \`process.platform\` spelling, not the \`gjsify ship <os>\` positional's. An entry under a key nothing reads leaves that target on \`gjsify.main\` with nothing to say so.`);let C=typeof n==`string`?n:void 0,N=t.pkg.gjsify?.main??t.pkg.main,entryFor=t=>S[t]??C??N,F=S[t.layoutOs],I=entryFor(t.layoutOs),H=F===void 0?C===void 0?t.pkg.gjsify?.main===void 0?`main`:`gjsify.main`:`gjsify.ship.bundle`:`gjsify.ship.bundle.${t.layoutOs}`,W=[...new Set(Object.keys(pU).filter(n=>n!==t.layoutOs).map(entryFor).filter(t=>t!==void 0&&t!==I))];return{declared:I,key:H,overridden:F!==void 0,foreign:W}}function deriveBinaryName(t){if(!t)throw Error("gjsify ship: no package name — set `name` in package.json or `gjsify.ship.binaryName`.");let n=(t.includes(`/`)?t.split(`/`).pop():t).toLowerCase().replace(/[^a-z\d+.-]+/g,`-`).replace(/^-+|-+$/g,``);if(!/^[a-z\d][a-z\d+.-]+$/.test(n))throw Error(`gjsify ship: cannot derive a package name from "${t}" (got "${n}"). Set \`gjsify.ship.binaryName\` to something matching \`[a-z0-9][a-z0-9+.-]+\`.`);return n}function reverseDnsOrThrow(t,n){if(t&&/^[A-Za-z][\w-]*(\.[A-Za-z][\w-]*){2,}$/.test(t))return t;throw Error(`gjsify ship: no application id. Set \`gjsify.ship.appId\` (or \`gjsify.flatpak.appId\`) to a reverse-DNS id such as "io.github.you.${titleCase(n).replace(/\s+/g,``)}". It names the desktop entry, the AppStream component and the installed icon, so it cannot be guessed.`)}function definedOnly(t){return Object.fromEntries(Object.entries(t).filter(([,t])=>t!==void 0))}function titleCase(t){return t.split(/[-_.]+/).filter(t=>t.length>0).map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(` `)}function sectionsFor(t){for(let[n,S]of mU)if(t?.includes(n))return S;return{section:`misc`,group:`Applications/System`}}function formatAuthor(t){if(typeof t==`string`)return t.replace(/\s*\([^)]*\)\s*$/,``).trim()||void 0;if(t?.name)return t.email?`${t.name} <${t.email}>`:t.name}function formatDeveloper(t){let n=t.developer;if(n?.name)return n.email?`${n.name} <${n.email}>`:n.name}function descriptionParagraphs(t){if(t===void 0)return;if(typeof t==`string`){let n=t.trim().split(/\n\n+/).map(t=>t.trim().replace(/\s+/g,` `)).filter(t=>t.length>0);return n.length>0?n:void 0}let n=[];for(let S of t)if(typeof S==`string`){let t=S.trim().replace(/\s+/g,` `);t&&n.push(t)}else if(`p`in S)n.push(S.p.trim().replace(/\s+/g,` `));else for(let t of S.ul)n.push(`* ${(typeof t==`string`?t:t.item).trim().replace(/\s+/g,` `)}`);return n.length>0?n:void 0}var pU,mU,hU,gU,_U,vU=__esmMin(()=>{lU(),ef(),qn(),eH(),eV(),fU(),pU={linux:!0,darwin:!0,win32:!0},mU=[[`Development`,{section:`devel`,group:`Development/Tools`}],[`Education`,{section:`education`,group:`Applications/Education`}],[`Game`,{section:`games`,group:`Amusements/Games`}],[`Graphics`,{section:`graphics`,group:`Applications/Multimedia`}],[`AudioVideo`,{section:`sound`,group:`Applications/Multimedia`}],[`Network`,{section:`net`,group:`Applications/Internet`}],[`Office`,{section:`text`,group:`Applications/Productivity`}],[`Science`,{section:`science`,group:`Applications/Engineering`}],[`System`,{section:`admin`,group:`Applications/System`}],[`Utility`,{section:`utils`,group:`Applications/System`}]],hU=/^[a-z0-9][a-z0-9._+-]*$/,gU=[`LICENSE`,`LICENSE.md`,`LICENSE.txt`,`COPYING`,`COPYING.md`],_U=[`CHANGELOG.md`,`CHANGELOG`,`CHANGELOG.txt`,`NEWS.md`,`NEWS`]});function discoverPayload(t){let{projectDir:n,ship:S}=t,C=resolveBundle(t),N=Nn(C,`..`),F=discoverLocales(n,S.localeDir);return{bundlePath:C,bundleDir:N,bundleFiles:withoutForeignEntries(withoutLocaleTree(listFilesRecursive(N),N,n,S.localeDir),N,n,t.foreignBundles??[],C),iconFiles:discoverIcons(n,S.icon??t.flatpakIcon),schemaFiles:discoverSchemas(n,S.schemas),typelibFiles:discoverTypelibs(n,resolveBundledTypelibs(S.bundledTypelibs,t.layoutOs)),formatFiles:discoverFormatFiles(n,S,t.layoutOs),localeFiles:F,fontFiles:discoverFonts(n,S.fonts),licenseFile:discoverLicense(n,S.licenseFile),changelogFile:discoverChangelog(n,S.changelogFile)}}function discoverFormatFiles(t,n,S){let C={};if(S!==void 0&&S!==`linux`)return C;for(let[S,N]of Object.entries(n.formats??{})){if(S!==`deb`&&S!==`rpm`)throw Error(`gjsify ship: \`gjsify.ship.formats.${S}\` is not a format that carries its own files. Known: deb, rpm.`);C[S]={typelibFiles:discoverTypelibs(t,N?.bundledTypelibs),extraFiles:Object.fromEntries(Object.entries(N?.extraFiles??{}).map(([n,S])=>[n,Nn(t,S)]))}}return C}function resolveBundledTypelibs(t,n){if(t===void 0||Array.isArray(t))return t??[];let S=[`linux`,`darwin`,`win32`];for(let n of Object.keys(t))if(!S.includes(n))throw Error(`gjsify ship: \`gjsify.ship.bundledTypelibs.${n}\` is not an OS this command assembles for. Known: ${S.join(`, `)} — the \`process.platform\` spelling, not the \`gjsify ship <os>\` positional's.`);if(n===void 0)throw Error("gjsify ship: `gjsify.ship.bundledTypelibs` is a per-OS table but no layout OS was given.");return t[n]??[]}function discoverTypelibs(t,n){let S=[];for(let C of n??[]){let n=Nn(t,C);if(!existsSync(n))throw Error(`gjsify ship: \`gjsify.ship.bundledTypelibs\` names ${C}, which does not exist. A missing directory here means the package would install without the typelib it promises.`);for(let t of listFilesRecursive(n))(/\.(typelib|dylib|dll)$/i.test(t)||/\.so(\.\d+)*$/.test(t))&&S.push(In(n,t))}return S}function withoutLocaleTree(t,n,S,C){if(C===void 0)return t;let N=Ln(n,Nn(S,C));if(N===``||N.startsWith(`..`)||Fn(N))return t;let F=`${N.split(Wn).join(Tn.sep)}${Tn.sep}`;return t.filter(t=>!`${t}${Tn.sep}`.startsWith(F))}function discoverLocales(t,n){if(n===void 0)return[];let S=Nn(t,n);if(!existsSync(S))throw Error(`gjsify ship: \`gjsify.ship.localeDir\` names ${n}, which does not exist. Compile the catalogues first (msgfmt, or @gjsify/vite-plugin-gettext) — a missing directory here means the package would install without the translations it promises.`);let C=[],N=[];for(let t of listFilesRecursive(S)){if(t.endsWith(`.po`)||t.endsWith(`.pot`)){N.push(`${t} (a .po source; bindtextdomain reads .mo only)`);continue}if(!t.endsWith(`.mo`))continue;let n=t.split(Tn.sep);if(n.length!==3||n[1]!==`LC_MESSAGES`){N.push(`${t} (expected <lang>/LC_MESSAGES/<domain>.mo)`);continue}C.push({rel:n.join(`/`),abs:In(S,t)})}if(N.length>0)throw Error(`gjsify ship: \`gjsify.ship.localeDir\` (${n}) holds files no catalogue lookup will find:\n`+N.map(t=>` ${t}`).join(`
1168
+ `}var lU,uU=__esmMin(()=>{cU(),lU=/^[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*$/});function normaliseVersion(t){let n=[],S=t.trim();S.startsWith(`v`)&&(S=S.slice(1));let C=S.indexOf(`+`);C!==-1&&(n.push(`gjsify ship: dropped the build metadata "${S.slice(C)}" from version ${t} — neither dpkg nor rpm has a field for it. Set \`gjsify.ship.version\` to pin an exact package version.`),S=S.slice(0,C));let N=S.indexOf(`-`);if(N!==-1){let t=S.slice(N+1).replace(/-/g,`.`);S=`${S.slice(0,N)}~${t}`}if(!dU.test(S))throw Error(`gjsify ship: "${t}" is not a usable package version (normalised to "${S}"). It must start with a digit and contain only letters, digits, \`.\`, \`+\` and \`~\`. Set \`gjsify.ship.version\` in package.json to override it.`);return{version:S,warnings:n}}function assertRelease(t){if(!fU.test(t))throw Error(`gjsify ship: "${t}" is not a usable package release. It must start with a letter or digit and contain only letters, digits, \`.\`, \`+\` and \`~\`. Set \`gjsify.ship.release\` in package.json.`);return t}var dU,fU,pU=__esmMin(()=>{dU=/^\d[A-Za-z0-9.+~]*$/,fU=/^[A-Za-z0-9][A-Za-z0-9.+~]*$/});function resolveShipApp(t){let n=t.perTarget??{};for(let t of Object.keys(n))if(!Object.hasOwn(mU,t))throw Error(`gjsify ship: \`gjsify.ship.app.${t}\` is not an OS this command assembles for. Known: ${Object.keys(mU).join(`, `)} — the \`process.platform\` spelling, not the \`gjsify ship <os>\` positional's. A runtime under a key nothing reads leaves that target on \`gjsify.app\` with nothing to say so.`);let S=n[t.layoutOs],C=S!==void 0,N=C?`gjsify.ship.app.${t.layoutOs}`:`gjsify.app`,F=C?S:t.project;if(F!==void 0&&F!==`gjs`&&F!==`node`)throw Error(`gjsify ship: \`${N}\` is "${F}", and only \`gjs\` and \`node\` can be packaged. A browser bundle has no process to launch, and a NativeScript app ships as an APK/IPA through a different pipeline. ADR 0024 § 4 has the runtime-per-OS table.`);return{app:F===`node`?`node`:`gjs`,key:N,overridden:C}}function resolveShipKind(t,n){return t.kind??n.kind??`app`}function resolveShipSettings(t){let n=[],{pkg:S,ship:C,flatpak:N,discovered:F}=t,I={...N,...definedOnly(C)},H=C.mimeTypes??[];if(H.length>0){validateMimeTypes(H);let t=new Set([...I.provides?.mimetypes??[],...H.map(t=>t.type)]);I.provides={...I.provides,mimetypes:[...t]}}let W=C.binaryName??deriveBinaryName(S.name),q=C.appId??N.appId??reverseDnsOrThrow(S.name,W),Y=I.name??titleCase(W),X=resolveShipKind(C,N),Z=t.app,te=C.version??S.version;if(!te)throw Error("gjsify ship: no version — set `version` in package.json or `gjsify.ship.version`.");let ne=normaliseVersion(te);n.push(...ne.warnings);let re=I.license?.project??S.license;if(!re)throw Error('gjsify ship: no licence — set `license` in package.json (an SPDX id, e.g. "MIT") or `gjsify.ship.license.project`. Both deb and rpm carry it as a required field.');I.license={...I.license,project:re};let ie=C.maintainer??formatAuthor(S.author)??formatDeveloper(I);if(!ie)throw Error('gjsify ship: no maintainer — set `author` in package.json ("Name <you@example.com>"), `gjsify.ship.maintainer`, or `gjsify.ship.developer`. dpkg refuses a package without one.');let ae=I.summary??S.description??Y,oe=descriptionParagraphs(I.description)??[ae],Q=sectionsFor(I.categories);X===`app`&&F.iconFiles.length===0&&n.push("gjsify ship: no icon found — the installed app will show a placeholder in menus on Linux, the Flatpak will carry no catalogue icon for an app store to show, and the darwin and windows layouts refuse to stage without one. Point `gjsify.ship.icon` at an SVG (or a directory of sized PNGs).");let se=resolveShipFlatpakSettings({ship:C,flatpak:N,kind:X});n.push(...se.warnings);let ce=resolveShipNestedBundles({declared:C.nestedBundles,projectDir:t.projectDir,layoutOs:t.cli.layoutOs}),le=resolveShipHelperExecutables({declared:C.helperExecutables,projectDir:t.projectDir,layoutOs:t.cli.layoutOs});return t.cli.layoutOs!==`darwin`&&(Array.isArray(C.nestedBundles)&&C.nestedBundles.length>0||Array.isArray(C.helperExecutables)&&C.helperExecutables.length>0)&&n.push(`gjsify ship: nestedBundles/helperExecutables apply to darwin only — not staged for ${t.cli.layoutOs}`),{settings:{projectDir:t.projectDir,appId:q,name:Y,binaryName:W,version:ne.version,release:assertRelease(C.release??`1`),maintainer:ie,summary:ae,description:oe,license:re,licenseFile:F.licenseFile,changelogFile:F.changelogFile,homepage:I.homepageUrl??S.homepage,section:C.section??Q.section,group:C.group??Q.group,kind:X,mimeTypes:H,extraDepends:{deb:C.depends?.deb??[],rpm:C.depends?.rpm??[]},typelibPackages:C.typelibPackages??{},bundlePath:F.bundlePath,bundleDir:F.bundleDir,iconFiles:F.iconFiles,schemaFiles:F.schemaFiles,typelibFiles:F.typelibFiles,formatFiles:F.formatFiles,localeFiles:F.localeFiles,fontFiles:F.fontFiles,extraFiles:C.extraFiles??{},execArgs:C.execArgs??[],executables:resolveShipExecutables({declared:C.executables,binaryName:W,projectDir:t.projectDir,bundleDir:F.bundleDir}),nestedBundles:ce,helperExecutables:le,outDir:t.cli.outDir??C.outDir??`ship`,arch:t.cli.arch??process.arch,app:Z,layoutOs:t.cli.layoutOs,minGjsVersion:C.minGjsVersion??`1.86`,minNodeVersion:C.minNodeVersion??`24`,flatpak:se.settings},metadata:I,warnings:n}}function resolveShipExecutables(t){let{declared:n}=t;if(n===void 0)return[];if(!Array.isArray(n))throw Error('gjsify ship: `gjsify.ship.executables` must be a list of `{ "name", "entry", "gui"? }` objects.');let S=new Set([t.binaryName]);return n.map((n,C)=>{let N=`gjsify.ship.executables[${C}]`;if(typeof n!=`object`||!n||Array.isArray(n))throw Error(`gjsify ship: \`${N}\` must be an object with \`name\` and \`entry\`.`);let{name:F,entry:I,gui:H,...W}=n,q=Object.keys(W);if(q.length>0)throw Error(`gjsify ship: \`${N}\` has unknown key(s) ${q.join(`, `)}; known: name, entry, gui.`);if(typeof F!=`string`||!gU.test(F))throw Error(`gjsify ship: \`${N}.name\` must match ${gU} — it becomes \`bin/<name>\`, \`Contents/MacOS/<name>\` and \`<name>.cmd\`, so it is lower-case with no path separator or space.`);if(S.has(F))throw Error(`gjsify ship: \`${N}.name\` "${F}" is already taken — by the package's own \`binaryName\` or by an earlier entry. Two launchers cannot share one file name.`);if(S.add(F),typeof I!=`string`||I===``)throw Error(`gjsify ship: \`${N}.entry\` must be the project-relative path of a built bundle.`);if(H!==void 0&&typeof H!=`boolean`)throw Error(`gjsify ship: \`${N}.gui\` must be a boolean.`);let Y=Fn(I)?I:Nn(t.projectDir,I),X=Ln(t.bundleDir,Y);if(X===``||X.startsWith(`..`)||Fn(X))throw Error(`gjsify ship: \`${N}.entry\` ${I} is outside ${t.bundleDir}, the directory \`gjsify.main\` lives in — only that directory is staged, so the launcher would point at a file the package does not carry. Build the entries into one directory.`);return{name:F,entry:X.split(Wn).join(Tn.sep),gui:H===!0}})}function assertUsableBundleLeaf(t,n,S){if(t===``||t===`.`||t===`..`||t.includes(`/`)||t.includes(`\\`)||t.includes(`\0`))throw Error(`gjsify ship: \`${n}.name\` "${t}" is not usable as a leaf under \`${S}\` — empty and ".", "..", and anything containing "/", "\\" or a NUL byte are refused.`);return t}function resolveShipNestedBundles(t){let{declared:n}=t;if(n===void 0)return[];if(!Array.isArray(n))throw Error('gjsify ship: `gjsify.ship.nestedBundles` must be a list of `{ "source", "name", "entitlements"? }` objects.');let S=new Set,C=n.map((n,C)=>{let N=`gjsify.ship.nestedBundles[${C}]`;if(typeof n!=`object`||!n||Array.isArray(n))throw Error(`gjsify ship: \`${N}\` must be an object with \`source\` and \`name\`.`);let{source:F,name:I,entitlements:H,...W}=n,q=Object.keys(W);if(q.length>0)throw Error(`gjsify ship: \`${N}\` has unknown key(s) ${q.join(`, `)}; known: source, name, entitlements.`);if(typeof F!=`string`||F===``)throw Error(`gjsify ship: \`${N}.source\` must be the project-relative directory of a built bundle.`);if(typeof I!=`string`)throw Error(`gjsify ship: \`${N}.name\` must be a string — the leaf under \`Contents/PlugIns/\`.`);if(assertUsableBundleLeaf(I,N,`Contents/PlugIns`),S.has(I))throw Error(`gjsify ship: \`${N}.name\` "${I}" is already taken by an earlier nested bundle.`);S.add(I);let Y=Fn(F)?F:Nn(t.projectDir,F);if(t.layoutOs===`darwin`&&!existsSync(Y))throw Error(`gjsify ship: \`${N}.source\` ${F} does not exist.`);if(H!==void 0&&!Array.isArray(H))throw Error(`gjsify ship: \`${N}.entitlements\` must be a list of strings.`);return{source:Y,name:I,entitlements:(H??[]).map((t,n)=>{if(typeof t!=`string`)throw Error(`gjsify ship: \`${N}.entitlements[${n}]\` must be a string.`);return t})}});return t.layoutOs===`darwin`?C:[]}function resolveShipHelperExecutables(t){let{declared:n}=t;if(n===void 0)return[];if(!Array.isArray(n))throw Error('gjsify ship: `gjsify.ship.helperExecutables` must be a list of `{ "source", "name", "entitlements"? }` objects.');let S=new Set,C=n.map((n,C)=>{let N=`gjsify.ship.helperExecutables[${C}]`;if(typeof n!=`object`||!n||Array.isArray(n))throw Error(`gjsify ship: \`${N}\` must be an object with \`source\` and \`name\`.`);let{source:F,name:I,entitlements:H,...W}=n,q=Object.keys(W);if(q.length>0)throw Error(`gjsify ship: \`${N}\` has unknown key(s) ${q.join(`, `)}; known: source, name, entitlements.`);if(typeof F!=`string`||F===``)throw Error(`gjsify ship: \`${N}.source\` must be the project-relative path of a prebuilt executable.`);if(typeof I!=`string`)throw Error(`gjsify ship: \`${N}.name\` must be a string — the leaf under \`Contents/Helpers/\`.`);if(assertUsableBundleLeaf(I,N,`Contents/Helpers`),S.has(I))throw Error(`gjsify ship: \`${N}.name\` "${I}" is already taken by an earlier helper executable.`);S.add(I);let Y=Fn(F)?F:Nn(t.projectDir,F);if(t.layoutOs===`darwin`&&!existsSync(Y))throw Error(`gjsify ship: \`${N}.source\` ${F} does not exist.`);if(H!==void 0&&!Array.isArray(H))throw Error(`gjsify ship: \`${N}.entitlements\` must be a list of strings.`);return{source:Y,name:I,entitlements:(H??[]).map((t,n)=>{if(typeof t!=`string`)throw Error(`gjsify ship: \`${N}.entitlements[${n}]\` must be a string.`);return t})}});return t.layoutOs===`darwin`?C:[]}function resolveShipBundle(t){let n=t.ship.bundle,S=typeof n==`object`&&n?n:{};for(let t of Object.keys(S))if(!Object.hasOwn(mU,t))throw Error(`gjsify ship: \`gjsify.ship.bundle.${t}\` is not an OS this command assembles for. Known: ${Object.keys(mU).join(`, `)} — the \`process.platform\` spelling, not the \`gjsify ship <os>\` positional's. An entry under a key nothing reads leaves that target on \`gjsify.main\` with nothing to say so.`);let C=typeof n==`string`?n:void 0,N=t.pkg.gjsify?.main??t.pkg.main,entryFor=t=>S[t]??C??N,F=S[t.layoutOs],I=entryFor(t.layoutOs),H=F===void 0?C===void 0?t.pkg.gjsify?.main===void 0?`main`:`gjsify.main`:`gjsify.ship.bundle`:`gjsify.ship.bundle.${t.layoutOs}`,W=[...new Set(Object.keys(mU).filter(n=>n!==t.layoutOs).map(entryFor).filter(t=>t!==void 0&&t!==I))];return{declared:I,key:H,overridden:F!==void 0,foreign:W}}function deriveBinaryName(t){if(!t)throw Error("gjsify ship: no package name — set `name` in package.json or `gjsify.ship.binaryName`.");let n=(t.includes(`/`)?t.split(`/`).pop():t).toLowerCase().replace(/[^a-z\d+.-]+/g,`-`).replace(/^-+|-+$/g,``);if(!/^[a-z\d][a-z\d+.-]+$/.test(n))throw Error(`gjsify ship: cannot derive a package name from "${t}" (got "${n}"). Set \`gjsify.ship.binaryName\` to something matching \`[a-z0-9][a-z0-9+.-]+\`.`);return n}function reverseDnsOrThrow(t,n){if(t&&/^[A-Za-z][\w-]*(\.[A-Za-z][\w-]*){2,}$/.test(t))return t;throw Error(`gjsify ship: no application id. Set \`gjsify.ship.appId\` (or \`gjsify.flatpak.appId\`) to a reverse-DNS id such as "io.github.you.${titleCase(n).replace(/\s+/g,``)}". It names the desktop entry, the AppStream component and the installed icon, so it cannot be guessed.`)}function definedOnly(t){return Object.fromEntries(Object.entries(t).filter(([,t])=>t!==void 0))}function titleCase(t){return t.split(/[-_.]+/).filter(t=>t.length>0).map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(` `)}function sectionsFor(t){for(let[n,S]of hU)if(t?.includes(n))return S;return{section:`misc`,group:`Applications/System`}}function formatAuthor(t){if(typeof t==`string`)return t.replace(/\s*\([^)]*\)\s*$/,``).trim()||void 0;if(t?.name)return t.email?`${t.name} <${t.email}>`:t.name}function formatDeveloper(t){let n=t.developer;if(n?.name)return n.email?`${n.name} <${n.email}>`:n.name}function descriptionParagraphs(t){if(t===void 0)return;if(typeof t==`string`){let n=t.trim().split(/\n\n+/).map(t=>t.trim().replace(/\s+/g,` `)).filter(t=>t.length>0);return n.length>0?n:void 0}let n=[];for(let S of t)if(typeof S==`string`){let t=S.trim().replace(/\s+/g,` `);t&&n.push(t)}else if(`p`in S)n.push(S.p.trim().replace(/\s+/g,` `));else for(let t of S.ul)n.push(`* ${(typeof t==`string`?t:t.item).trim().replace(/\s+/g,` `)}`);return n.length>0?n:void 0}var mU,hU,gU,_U,vU,yU=__esmMin(()=>{uU(),ef(),qn(),tH(),eV(),pU(),mU={linux:!0,darwin:!0,win32:!0},hU=[[`Development`,{section:`devel`,group:`Development/Tools`}],[`Education`,{section:`education`,group:`Applications/Education`}],[`Game`,{section:`games`,group:`Amusements/Games`}],[`Graphics`,{section:`graphics`,group:`Applications/Multimedia`}],[`AudioVideo`,{section:`sound`,group:`Applications/Multimedia`}],[`Network`,{section:`net`,group:`Applications/Internet`}],[`Office`,{section:`text`,group:`Applications/Productivity`}],[`Science`,{section:`science`,group:`Applications/Engineering`}],[`System`,{section:`admin`,group:`Applications/System`}],[`Utility`,{section:`utils`,group:`Applications/System`}]],gU=/^[a-z0-9][a-z0-9._+-]*$/,_U=[`LICENSE`,`LICENSE.md`,`LICENSE.txt`,`COPYING`,`COPYING.md`],vU=[`CHANGELOG.md`,`CHANGELOG`,`CHANGELOG.txt`,`NEWS.md`,`NEWS`]});function discoverPayload(t){let{projectDir:n,ship:S}=t,C=resolveBundle(t),N=Nn(C,`..`),F=discoverLocales(n,S.localeDir);return{bundlePath:C,bundleDir:N,bundleFiles:withoutForeignEntries(withoutLocaleTree(listFilesRecursive(N),N,n,S.localeDir),N,n,t.foreignBundles??[],C),iconFiles:discoverIcons(n,S.icon??t.flatpakIcon),schemaFiles:discoverSchemas(n,S.schemas),typelibFiles:discoverTypelibs(n,resolveBundledTypelibs(S.bundledTypelibs,t.layoutOs)),formatFiles:discoverFormatFiles(n,S,t.layoutOs),localeFiles:F,fontFiles:discoverFonts(n,S.fonts),licenseFile:discoverLicense(n,S.licenseFile),changelogFile:discoverChangelog(n,S.changelogFile)}}function discoverFormatFiles(t,n,S){let C={};if(S!==void 0&&S!==`linux`)return C;for(let[S,N]of Object.entries(n.formats??{})){if(S!==`deb`&&S!==`rpm`)throw Error(`gjsify ship: \`gjsify.ship.formats.${S}\` is not a format that carries its own files. Known: deb, rpm.`);C[S]={typelibFiles:discoverTypelibs(t,N?.bundledTypelibs),extraFiles:Object.fromEntries(Object.entries(N?.extraFiles??{}).map(([n,S])=>[n,Nn(t,S)]))}}return C}function resolveBundledTypelibs(t,n){if(t===void 0||Array.isArray(t))return t??[];let S=[`linux`,`darwin`,`win32`];for(let n of Object.keys(t))if(!S.includes(n))throw Error(`gjsify ship: \`gjsify.ship.bundledTypelibs.${n}\` is not an OS this command assembles for. Known: ${S.join(`, `)} — the \`process.platform\` spelling, not the \`gjsify ship <os>\` positional's.`);if(n===void 0)throw Error("gjsify ship: `gjsify.ship.bundledTypelibs` is a per-OS table but no layout OS was given.");return t[n]??[]}function discoverTypelibs(t,n){let S=[];for(let C of n??[]){let n=Nn(t,C);if(!existsSync(n))throw Error(`gjsify ship: \`gjsify.ship.bundledTypelibs\` names ${C}, which does not exist. A missing directory here means the package would install without the typelib it promises.`);for(let t of listFilesRecursive(n))(/\.(typelib|dylib|dll)$/i.test(t)||/\.so(\.\d+)*$/.test(t))&&S.push(In(n,t))}return S}function withoutLocaleTree(t,n,S,C){if(C===void 0)return t;let N=Ln(n,Nn(S,C));if(N===``||N.startsWith(`..`)||Fn(N))return t;let F=`${N.split(Wn).join(Tn.sep)}${Tn.sep}`;return t.filter(t=>!`${t}${Tn.sep}`.startsWith(F))}function discoverLocales(t,n){if(n===void 0)return[];let S=Nn(t,n);if(!existsSync(S))throw Error(`gjsify ship: \`gjsify.ship.localeDir\` names ${n}, which does not exist. Compile the catalogues first (msgfmt, or @gjsify/vite-plugin-gettext) — a missing directory here means the package would install without the translations it promises.`);let C=[],N=[];for(let t of listFilesRecursive(S)){if(t.endsWith(`.po`)||t.endsWith(`.pot`)){N.push(`${t} (a .po source; bindtextdomain reads .mo only)`);continue}if(!t.endsWith(`.mo`))continue;let n=t.split(Tn.sep);if(n.length!==3||n[1]!==`LC_MESSAGES`){N.push(`${t} (expected <lang>/LC_MESSAGES/<domain>.mo)`);continue}C.push({rel:n.join(`/`),abs:In(S,t)})}if(N.length>0)throw Error(`gjsify ship: \`gjsify.ship.localeDir\` (${n}) holds files no catalogue lookup will find:\n`+N.map(t=>` ${t}`).join(`
1169
1169
  `)+`
1170
- A misplaced catalogue installs and then shows nothing, which reads exactly like having no translation at all. Lay them out as <lang>/LC_MESSAGES/<domain>.mo.`);if(C.length===0)throw Error(`gjsify ship: \`gjsify.ship.localeDir\` (${n}) contains no \`.mo\` catalogue. Declaring a locale directory that ships nothing is a promise the package does not keep.`);return C}function withoutForeignEntries(t,n,S,C,N){if(C.length===0)return t;let F=new Set;for(let t of C){let C=Fn(t)?t:Nn(S,t);if(C===N)continue;let I=Ln(n,C);I===``||I.startsWith(`..`)||Fn(I)||F.add(I.split(Wn).join(Tn.sep))}return t.filter(t=>!F.has(t))}function resolveBundle(t){let n=t.declaredBundle;if(n===void 0)throw Error("gjsify ship: no bundle to ship. Set `gjsify.main` (or `main`) in package.json to the built bundle, or `gjsify.ship.bundle` to override it.");let S=Fn(n)?n:Nn(t.projectDir,n);if(!existsSync(S))throw Error(`gjsify ship: the bundle ${n} does not exist. Build it first (\`gjsify run build\`), or drop \`--skip-build\`.`);return S}function discoverIcons(t,n){if(n!==void 0){let S=Nn(t,n);if(!existsSync(S))throw Error(`gjsify ship: the configured icon path ${n} does not exist.`);return statSync(S).isDirectory()?listIcons(S):[S]}for(let n of[`data/icons`,`data/icons/hicolor`]){let S=In(t,n);if(existsSync(S)&&statSync(S).isDirectory()){let t=listIcons(S);if(t.length>0)return t}}return[]}function listIcons(t){return listFilesRecursive(t).filter(t=>yU.some(n=>t.toLowerCase().endsWith(n))).map(n=>In(t,n.split(`/`).join(Wn))).sort()}function discoverFonts(t,n){let S=n??`data/fonts`,C=n===void 0?In(t,`data`,`fonts`):Nn(t,n);if(!existsSync(C)){if(n===void 0)return[];throw Error(`gjsify ship: the configured font path ${n} does not exist.`)}if(!statSync(C).isDirectory()){if(assertNotWebFont(C,S),!bU.some(t=>C.toLowerCase().endsWith(t)))throw Error(`gjsify ship: \`gjsify.ship.fonts\` names ${n}, which is not a font face fontconfig will open (${bU.join(`, `)}). A file it cannot read installs and is never found, and Pango substitutes a fallback family rather than reporting anything.`);return[C]}let N=[];for(let t of listFilesRecursive(C))assertNotWebFont(t,S),bU.some(n=>t.toLowerCase().endsWith(n))&&N.push(In(C,t.split(`/`).join(Wn)));if(N.length===0&&n!==void 0)throw Error(`gjsify ship: \`gjsify.ship.fonts\` (${n}) holds no font face (${bU.join(`, `)}). Declaring fonts that ship nothing is a promise the package does not keep — and its symptom is a substituted family, not an error.`);return N.sort()}function assertNotWebFont(t,n){let S=t.toLowerCase(),C=xU.find(t=>S.endsWith(t));if(C!==void 0)throw Error(`gjsify ship: \`gjsify.ship.fonts\` (${n}) carries ${t}, and \`${C}\` is a web-font wrapper whose support is a FreeType BUILD option — brotli for woff2, zlib for woff. Whether it opens is therefore a property of the FreeType the SHIPPED artifact loads (inside \`@gjsify/gtk-runtime-<target>\` for a \`.app\` or a Windows program directory), not of the machine that packaged it. Ship the desktop face instead (${bU.join(`, `)}); a font that fails to open is not an error, it is Pango quietly substituting a different typeface.`)}function discoverSchemas(t,n){let S=n===void 0?[In(t,`data`)]:[Nn(t,n)];for(let t of S){if(!existsSync(t)){if(n!==void 0)throw Error(`gjsify ship: the configured schema path ${n} does not exist.`);continue}if(!statSync(t).isDirectory())return[t];let S=listFilesRecursive(t).filter(t=>t.endsWith(`.gschema.xml`)).map(n=>In(t,n.split(`/`).join(Wn))).sort();if(S.length>0)return S}return[]}function discoverLicense(t,n){if(n!==void 0){let S=Nn(t,n);if(!existsSync(S))throw Error(`gjsify ship: the configured licence file ${n} does not exist.`);return S}for(let n of licenseSearchDirs(t))for(let t of gU){let S=In(n,t);if(existsSync(S))return S}}function discoverChangelog(t,n){if(n!==void 0){let S=Nn(t,n);if(!existsSync(S))throw Error(`gjsify ship: the configured changelog file ${n} does not exist.`);return S}for(let n of licenseSearchDirs(t))for(let t of _U){let S=In(n,t);if(existsSync(S))return S}}function licenseSearchDirs(t){let n=[];for(let S=t;;){if(n.push(S),isProjectRoot(S))return n;let C=zn(S);if(C===S)return[t];S=C}}function isProjectRoot(t){if(existsSync(In(t,`.git`)))return!0;let n=In(t,`package.json`);if(!existsSync(n))return!1;try{return JSON.parse(readFileSync(n,`utf-8`)).workspaces!==void 0}catch{return!1}}function listFilesRecursive(t){let n=[],walk=S=>{for(let C of readdirSync(S,{withFileTypes:!0}).sort((t,n)=>t.name<n.name?-1:1)){let N=In(S,C.name);if(C.isDirectory())walk(N);else if(C.isSymbolicLink())throw Error(`gjsify ship: ${N} is a symlink. The payload has to be self-contained — replace it with the file it points at, or exclude it from the bundle directory.`);else C.isFile()&&n.push(Tn.join(...Ln(t,N).split(Wn)))}};return walk(t),n.sort()}var yU,bU,xU,SU=__esmMin(()=>{ef(),qn(),vU(),yU=[`.svg`,`.png`],bU=[`.ttf`,`.otf`,`.ttc`,`.otc`],xU=[`.woff`,`.woff2`,`.eot`]});function isNodeRuntimeTarget(t){return CU.includes(t)}function nodeRuntimePackageName(t){return`@gjsify/node-runtime-${t}`}function nodeRuntimeBinaryName(t){return t.startsWith(`win32-`)?`node.exe`:`node`}function resolveNodeRuntime(t,n={}){let S=n.env??process.env,C=nodeRuntimeBinaryName(t),N=S.GJSIFY_NODE_RUNTIME;if(N){let t=complete(`GJSIFY_NODE_RUNTIME`,N,C);if(t)return t}let F=nodeRuntimePackageName(t),I=resolveInstalledPackage(F,{cwd:n.cwd,bundleUrl:import.meta.url});return I===null?null:complete(F,In(zn(I),`bin`),C)}function complete(t,n,S){let C=In(n,S),N=In(n,`LICENSE`);return!existsSync(C)||!existsSync(N)?null:{source:t,binDir:n,nodePath:C,licensePath:N}}var CU,wU=__esmMin(()=>{ef(),qn(),PI(),CU=[`darwin-arm64`,`darwin-x64`,`win32-x64`,`win32-arm64`]});function rfc822(t){let n=new Date(t*1e3),pad=t=>String(t).padStart(2,`0`);return`${TU[n.getUTCDay()]}, ${pad(n.getUTCDate())} ${EU[n.getUTCMonth()]} ${n.getUTCFullYear()} ${pad(n.getUTCHours())}:${pad(n.getUTCMinutes())}:${pad(n.getUTCSeconds())} +0000`}function changelogEntriesFor(t,n){let S=t.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`),C=RegExp(`^##+[ \\t]+\\[?${S}\\]?[^\\n]*$`,`m`).exec(n);if(C===null)return[];let N=n.slice(C.index+C[0].length),F=/^##[ \t]+\[?\d/m.exec(N),I=F===null?N:N.slice(0,F.index),H=[];for(let t of I.split(`
1171
- `)){let n=/^[*-][ \t]+(.*\S)\s*$/.exec(t);n!==null&&H.push(n[1].replace(/\[([^\]]*)\]\([^)]*\)/g,`$1`).replace(/\*\*([^*]+)\*\*/g,`$1`).replace(/\s+/g,` `).trim())}return H}function wrapEntry(t){let n=[],S=` *`;for(let C of t.split(/\s+/))C!==``&&(S.length+1+C.length>DU&&S!==` *`&&S!==` `&&(n.push(S),S=` `),S+=` ${C}`);return n.push(S),n}function renderDebianChangelog(t,n,S){let C=n===void 0?[]:changelogEntriesFor(t.version,n),N=t.homepage?`Release ${t.version}. See ${t.homepage} for the upstream changes.`:`Release ${t.version}.`,F=(C.length>0?C:[N]).flatMap(wrapEntry);return[`${t.binaryName} (${t.version}-${t.release}) unstable; urgency=medium`,``,...F,``,` -- ${t.maintainer} ${rfc822(S)}`,``].join(`
1172
- `)}var TU,EU,DU,OU=__esmMin(()=>{TU=[`Sun`,`Mon`,`Tue`,`Wed`,`Thu`,`Fri`,`Sat`],EU=[`Jan`,`Feb`,`Mar`,`Apr`,`May`,`Jun`,`Jul`,`Aug`,`Sep`,`Oct`,`Nov`,`Dec`],DU=80});function planStage(t,n){let S=[],C=`lib/${t.binaryName}`;S.push({path:`bin/${t.binaryName}`,mode:493,source:{kind:`text`,text:n.launcher}});for(let C of t.executables){let N=n.executableLaunchers?.[C.name];if(N===void 0||!n.bundleFiles.includes(C.entry))throw Error(`gjsify ship: \`gjsify.ship.executables\` "${C.name}" runs ${C.entry}, which is not in ${t.bundleDir} — build it before shipping, or the launcher would point at nothing.`);S.push({path:`bin/${C.name}`,mode:493,source:{kind:`text`,text:N}})}for(let N of n.bundleFiles)S.push({path:Tn.join(C,N),mode:isExecutableAsset(N)?493:420,source:{kind:`file`,path:Tn.join(t.bundleDir,N)}});if(S.push({path:`${nH.metainfo}/${t.appId}.metainfo.xml`,mode:420,source:{kind:`text`,text:n.metainfo}}),t.kind===`app`){if(n.desktopEntry===void 0)throw Error('gjsify ship: internal error — a desktop entry is required for `kind: "app"`.');S.push({path:`${nH.applications}/${t.appId}.desktop`,mode:420,source:{kind:`text`,text:n.desktopEntry}});for(let n of planIcons(t))S.push(n)}for(let n of t.schemaFiles){let C=Bn(n);if(!C.startsWith(t.appId))throw Error(`gjsify ship: the GSettings schema ${C} must be named \`${t.appId}[.…].gschema.xml\`. Every installed schema shares one system directory, so the app id is what keeps it unique.`);S.push({path:`${nH.schemas}/${C}`,mode:420,source:{kind:`file`,path:n}})}for(let n of t.typelibFiles)S.push({path:Tn.join(C,`gi`,Bn(n)),mode:493,source:{kind:`file`,path:n}});t.mimeTypes.length>0&&S.push({path:`${nH.mime}/${t.appId}.xml`,mode:420,source:{kind:`text`,text:renderMimePackage(t.mimeTypes)}});for(let n of t.localeFiles)S.push({path:Tn.join(nH.locale,n.rel),mode:420,source:{kind:`file`,path:n.abs}});for(let n of planFonts(t))S.push(n);for(let[n,C]of Object.entries(t.extraFiles))S.push({path:assertInsidePrefix(n),mode:420,source:{kind:`file`,path:C}});return normalise(S)}function planFonts(t){let n=[],S=new Map;for(let C of t.fontFiles){let N=`${nH.fonts}/${t.appId}/${Bn(C)}`,F=S.get(N);if(F!==void 0)throw Error(`gjsify ship: ${C} and ${F} both install as ${N}. Two faces cannot share one filename — one would silently not ship, and a missing face is a substituted typeface rather than an error. Rename one, or point \`gjsify.ship.fonts\` at a directory holding only the faces you mean to ship.`);S.set(N,C),n.push({path:N,mode:420,source:{kind:`file`,path:C}})}return n}async function planOverlay(t,n,S){if(S.licenseText===void 0)throw Error(`gjsify ship: no licence file found, so the ${n.id} package would ship no ${n.licenseDest(t.binaryName)}. Debian Policy § 12.5 requires it and lintian errors without it, and neither dpkg nor rpm will tell you it is missing. Add a LICENSE file to ${t.projectDir} or to the root of its repository, or point \`gjsify.ship.licenseFile\` at the one this package ships under.`);let C=n.licenseKind===`debian-copyright`?renderDebianCopyright(t,S.licenseText):S.licenseText,N=[{path:n.licenseDest(t.binaryName),mode:420,source:{kind:`text`,text:C}}];if(n.changelogDest!==void 0){let C=renderDebianChangelog(t,S.changelogText,S.mtime);N.push({path:n.changelogDest(t.binaryName),mode:420,source:{kind:`bytes`,data:await gzipDeterministic(new TextEncoder().encode(C),9)}})}let F=t.formatFiles[n.id];for(let n of F?.typelibFiles??[])N.push({path:Tn.join(`lib`,t.binaryName,`gi`,Bn(n)),mode:493,source:{kind:`bytes`,data:new Uint8Array(await readFile$1(n))}});for(let[t,n]of Object.entries(F?.extraFiles??{}))N.push({path:assertInsidePrefix(t),mode:t.endsWith(`.so`)?493:420,source:{kind:`bytes`,data:new Uint8Array(await readFile$1(n))}});return N}function assertOverlayIsLicensed(t,n,S){if(!(S.length>0))throw Error(`gjsify ship: this stage carries no ${t} licence overlay, so the package would ship no licence file for ${n} — Debian Policy § 12.5 requires one and lintian errors without it. The fix is on the assembling host, not this one: give that project a LICENSE (or set \`gjsify.ship.licenseFile\`) and re-run the \`--stage\` phase.`)}function renderDebianCopyright(t,n){let S=n.trimEnd().split(`
1170
+ A misplaced catalogue installs and then shows nothing, which reads exactly like having no translation at all. Lay them out as <lang>/LC_MESSAGES/<domain>.mo.`);if(C.length===0)throw Error(`gjsify ship: \`gjsify.ship.localeDir\` (${n}) contains no \`.mo\` catalogue. Declaring a locale directory that ships nothing is a promise the package does not keep.`);return C}function withoutForeignEntries(t,n,S,C,N){if(C.length===0)return t;let F=new Set;for(let t of C){let C=Fn(t)?t:Nn(S,t);if(C===N)continue;let I=Ln(n,C);I===``||I.startsWith(`..`)||Fn(I)||F.add(I.split(Wn).join(Tn.sep))}return t.filter(t=>!F.has(t))}function resolveBundle(t){let n=t.declaredBundle;if(n===void 0)throw Error("gjsify ship: no bundle to ship. Set `gjsify.main` (or `main`) in package.json to the built bundle, or `gjsify.ship.bundle` to override it.");let S=Fn(n)?n:Nn(t.projectDir,n);if(!existsSync(S))throw Error(`gjsify ship: the bundle ${n} does not exist. Build it first (\`gjsify run build\`), or drop \`--skip-build\`.`);return S}function discoverIcons(t,n){if(n!==void 0){let S=Nn(t,n);if(!existsSync(S))throw Error(`gjsify ship: the configured icon path ${n} does not exist.`);return statSync(S).isDirectory()?listIcons(S):[S]}for(let n of[`data/icons`,`data/icons/hicolor`]){let S=In(t,n);if(existsSync(S)&&statSync(S).isDirectory()){let t=listIcons(S);if(t.length>0)return t}}return[]}function listIcons(t){return listFilesRecursive(t).filter(t=>bU.some(n=>t.toLowerCase().endsWith(n))).map(n=>In(t,n.split(`/`).join(Wn))).sort()}function discoverFonts(t,n){let S=n??`data/fonts`,C=n===void 0?In(t,`data`,`fonts`):Nn(t,n);if(!existsSync(C)){if(n===void 0)return[];throw Error(`gjsify ship: the configured font path ${n} does not exist.`)}if(!statSync(C).isDirectory()){if(assertNotWebFont(C,S),!xU.some(t=>C.toLowerCase().endsWith(t)))throw Error(`gjsify ship: \`gjsify.ship.fonts\` names ${n}, which is not a font face fontconfig will open (${xU.join(`, `)}). A file it cannot read installs and is never found, and Pango substitutes a fallback family rather than reporting anything.`);return[C]}let N=[];for(let t of listFilesRecursive(C))assertNotWebFont(t,S),xU.some(n=>t.toLowerCase().endsWith(n))&&N.push(In(C,t.split(`/`).join(Wn)));if(N.length===0&&n!==void 0)throw Error(`gjsify ship: \`gjsify.ship.fonts\` (${n}) holds no font face (${xU.join(`, `)}). Declaring fonts that ship nothing is a promise the package does not keep — and its symptom is a substituted family, not an error.`);return N.sort()}function assertNotWebFont(t,n){let S=t.toLowerCase(),C=SU.find(t=>S.endsWith(t));if(C!==void 0)throw Error(`gjsify ship: \`gjsify.ship.fonts\` (${n}) carries ${t}, and \`${C}\` is a web-font wrapper whose support is a FreeType BUILD option — brotli for woff2, zlib for woff. Whether it opens is therefore a property of the FreeType the SHIPPED artifact loads (inside \`@gjsify/gtk-runtime-<target>\` for a \`.app\` or a Windows program directory), not of the machine that packaged it. Ship the desktop face instead (${xU.join(`, `)}); a font that fails to open is not an error, it is Pango quietly substituting a different typeface.`)}function discoverSchemas(t,n){let S=n===void 0?[In(t,`data`)]:[Nn(t,n)];for(let t of S){if(!existsSync(t)){if(n!==void 0)throw Error(`gjsify ship: the configured schema path ${n} does not exist.`);continue}if(!statSync(t).isDirectory())return[t];let S=listFilesRecursive(t).filter(t=>t.endsWith(`.gschema.xml`)).map(n=>In(t,n.split(`/`).join(Wn))).sort();if(S.length>0)return S}return[]}function discoverLicense(t,n){if(n!==void 0){let S=Nn(t,n);if(!existsSync(S))throw Error(`gjsify ship: the configured licence file ${n} does not exist.`);return S}for(let n of licenseSearchDirs(t))for(let t of _U){let S=In(n,t);if(existsSync(S))return S}}function discoverChangelog(t,n){if(n!==void 0){let S=Nn(t,n);if(!existsSync(S))throw Error(`gjsify ship: the configured changelog file ${n} does not exist.`);return S}for(let n of licenseSearchDirs(t))for(let t of vU){let S=In(n,t);if(existsSync(S))return S}}function licenseSearchDirs(t){let n=[];for(let S=t;;){if(n.push(S),isProjectRoot(S))return n;let C=zn(S);if(C===S)return[t];S=C}}function isProjectRoot(t){if(existsSync(In(t,`.git`)))return!0;let n=In(t,`package.json`);if(!existsSync(n))return!1;try{return JSON.parse(readFileSync(n,`utf-8`)).workspaces!==void 0}catch{return!1}}function listFilesRecursive(t){let n=[],walk=S=>{for(let C of readdirSync(S,{withFileTypes:!0}).sort((t,n)=>t.name<n.name?-1:1)){let N=In(S,C.name);if(C.isDirectory())walk(N);else if(C.isSymbolicLink())throw Error(`gjsify ship: ${N} is a symlink. The payload has to be self-contained — replace it with the file it points at, or exclude it from the bundle directory.`);else C.isFile()&&n.push(Tn.join(...Ln(t,N).split(Wn)))}};return walk(t),n.sort()}var bU,xU,SU,CU=__esmMin(()=>{ef(),qn(),yU(),bU=[`.svg`,`.png`],xU=[`.ttf`,`.otf`,`.ttc`,`.otc`],SU=[`.woff`,`.woff2`,`.eot`]});function isNodeRuntimeTarget(t){return wU.includes(t)}function nodeRuntimePackageName(t){return`@gjsify/node-runtime-${t}`}function nodeRuntimeBinaryName(t){return t.startsWith(`win32-`)?`node.exe`:`node`}function resolveNodeRuntime(t,n={}){let S=n.env??process.env,C=nodeRuntimeBinaryName(t),N=S.GJSIFY_NODE_RUNTIME;if(N){let t=complete(`GJSIFY_NODE_RUNTIME`,N,C);if(t)return t}let F=nodeRuntimePackageName(t),I=resolveInstalledPackage(F,{cwd:n.cwd,bundleUrl:import.meta.url});return I===null?null:complete(F,In(zn(I),`bin`),C)}function complete(t,n,S){let C=In(n,S),N=In(n,`LICENSE`);return!existsSync(C)||!existsSync(N)?null:{source:t,binDir:n,nodePath:C,licensePath:N}}var wU,TU=__esmMin(()=>{ef(),qn(),PI(),wU=[`darwin-arm64`,`darwin-x64`,`win32-x64`,`win32-arm64`]});function rfc822(t){let n=new Date(t*1e3),pad=t=>String(t).padStart(2,`0`);return`${EU[n.getUTCDay()]}, ${pad(n.getUTCDate())} ${DU[n.getUTCMonth()]} ${n.getUTCFullYear()} ${pad(n.getUTCHours())}:${pad(n.getUTCMinutes())}:${pad(n.getUTCSeconds())} +0000`}function changelogEntriesFor(t,n){let S=t.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`),C=RegExp(`^##+[ \\t]+\\[?${S}\\]?[^\\n]*$`,`m`).exec(n);if(C===null)return[];let N=n.slice(C.index+C[0].length),F=/^##[ \t]+\[?\d/m.exec(N),I=F===null?N:N.slice(0,F.index),H=[];for(let t of I.split(`
1171
+ `)){let n=/^[*-][ \t]+(.*\S)\s*$/.exec(t);n!==null&&H.push(n[1].replace(/\[([^\]]*)\]\([^)]*\)/g,`$1`).replace(/\*\*([^*]+)\*\*/g,`$1`).replace(/\s+/g,` `).trim())}return H}function wrapEntry(t){let n=[],S=` *`;for(let C of t.split(/\s+/))C!==``&&(S.length+1+C.length>OU&&S!==` *`&&S!==` `&&(n.push(S),S=` `),S+=` ${C}`);return n.push(S),n}function renderDebianChangelog(t,n,S){let C=n===void 0?[]:changelogEntriesFor(t.version,n),N=t.homepage?`Release ${t.version}. See ${t.homepage} for the upstream changes.`:`Release ${t.version}.`,F=(C.length>0?C:[N]).flatMap(wrapEntry);return[`${t.binaryName} (${t.version}-${t.release}) unstable; urgency=medium`,``,...F,``,` -- ${t.maintainer} ${rfc822(S)}`,``].join(`
1172
+ `)}var EU,DU,OU,kU=__esmMin(()=>{EU=[`Sun`,`Mon`,`Tue`,`Wed`,`Thu`,`Fri`,`Sat`],DU=[`Jan`,`Feb`,`Mar`,`Apr`,`May`,`Jun`,`Jul`,`Aug`,`Sep`,`Oct`,`Nov`,`Dec`],OU=80});function planStage(t,n){let S=[],C=`lib/${t.binaryName}`;S.push({path:`bin/${t.binaryName}`,mode:493,source:{kind:`text`,text:n.launcher}});for(let C of t.executables){let N=n.executableLaunchers?.[C.name];if(N===void 0||!n.bundleFiles.includes(C.entry))throw Error(`gjsify ship: \`gjsify.ship.executables\` "${C.name}" runs ${C.entry}, which is not in ${t.bundleDir} — build it before shipping, or the launcher would point at nothing.`);S.push({path:`bin/${C.name}`,mode:493,source:{kind:`text`,text:N}})}for(let N of n.bundleFiles)S.push({path:Tn.join(C,N),mode:isExecutableAsset(N)?493:420,source:{kind:`file`,path:Tn.join(t.bundleDir,N)}});if(S.push({path:`${rH.metainfo}/${t.appId}.metainfo.xml`,mode:420,source:{kind:`text`,text:n.metainfo}}),t.kind===`app`){if(n.desktopEntry===void 0)throw Error('gjsify ship: internal error — a desktop entry is required for `kind: "app"`.');S.push({path:`${rH.applications}/${t.appId}.desktop`,mode:420,source:{kind:`text`,text:n.desktopEntry}});for(let n of planIcons(t))S.push(n)}for(let n of t.schemaFiles){let C=Bn(n);if(!C.startsWith(t.appId))throw Error(`gjsify ship: the GSettings schema ${C} must be named \`${t.appId}[.…].gschema.xml\`. Every installed schema shares one system directory, so the app id is what keeps it unique.`);S.push({path:`${rH.schemas}/${C}`,mode:420,source:{kind:`file`,path:n}})}for(let n of t.typelibFiles)S.push({path:Tn.join(C,`gi`,Bn(n)),mode:493,source:{kind:`file`,path:n}});t.mimeTypes.length>0&&S.push({path:`${rH.mime}/${t.appId}.xml`,mode:420,source:{kind:`text`,text:renderMimePackage(t.mimeTypes)}});for(let n of t.localeFiles)S.push({path:Tn.join(rH.locale,n.rel),mode:420,source:{kind:`file`,path:n.abs}});for(let n of planFonts(t))S.push(n);for(let[n,C]of Object.entries(t.extraFiles))S.push({path:assertInsidePrefix(n),mode:420,source:{kind:`file`,path:C}});return normalise(S)}function planFonts(t){let n=[],S=new Map;for(let C of t.fontFiles){let N=`${rH.fonts}/${t.appId}/${Bn(C)}`,F=S.get(N);if(F!==void 0)throw Error(`gjsify ship: ${C} and ${F} both install as ${N}. Two faces cannot share one filename — one would silently not ship, and a missing face is a substituted typeface rather than an error. Rename one, or point \`gjsify.ship.fonts\` at a directory holding only the faces you mean to ship.`);S.set(N,C),n.push({path:N,mode:420,source:{kind:`file`,path:C}})}return n}async function planOverlay(t,n,S){if(S.licenseText===void 0)throw Error(`gjsify ship: no licence file found, so the ${n.id} package would ship no ${n.licenseDest(t.binaryName)}. Debian Policy § 12.5 requires it and lintian errors without it, and neither dpkg nor rpm will tell you it is missing. Add a LICENSE file to ${t.projectDir} or to the root of its repository, or point \`gjsify.ship.licenseFile\` at the one this package ships under.`);let C=n.licenseKind===`debian-copyright`?renderDebianCopyright(t,S.licenseText):S.licenseText,N=[{path:n.licenseDest(t.binaryName),mode:420,source:{kind:`text`,text:C}}];if(n.changelogDest!==void 0){let C=renderDebianChangelog(t,S.changelogText,S.mtime);N.push({path:n.changelogDest(t.binaryName),mode:420,source:{kind:`bytes`,data:await gzipDeterministic(new TextEncoder().encode(C),9)}})}let F=t.formatFiles[n.id];for(let n of F?.typelibFiles??[])N.push({path:Tn.join(`lib`,t.binaryName,`gi`,Bn(n)),mode:493,source:{kind:`bytes`,data:new Uint8Array(await readFile$1(n))}});for(let[t,n]of Object.entries(F?.extraFiles??{}))N.push({path:assertInsidePrefix(t),mode:t.endsWith(`.so`)?493:420,source:{kind:`bytes`,data:new Uint8Array(await readFile$1(n))}});return N}function assertOverlayIsLicensed(t,n,S){if(!(S.length>0))throw Error(`gjsify ship: this stage carries no ${t} licence overlay, so the package would ship no licence file for ${n} — Debian Policy § 12.5 requires one and lintian errors without it. The fix is on the assembling host, not this one: give that project a LICENSE (or set \`gjsify.ship.licenseFile\`) and re-run the \`--stage\` phase.`)}function renderDebianCopyright(t,n){let S=n.trimEnd().split(`
1173
1173
  `).map(t=>t.trim()===``?` .`:` ${t}`).join(`
1174
1174
  `);return[`Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/`,`Upstream-Name: ${t.name}`,...t.homepage?[`Source: ${t.homepage}`]:[],``,`Files: *`,`Copyright: ${t.maintainer}`,`License: ${t.license}`,S,``].join(`
1175
- `)}function planIcons(t){let n=[],S=new Map;for(let C of t.iconFiles){let N=Vn(C),F=iconThemeDir(C),I=isSymbolicIcon(C)?`${t.appId}-symbolic`:t.appId,H=`${nH.icons}/${F}/apps/${I}${N}`,W=S.get(H);if(W!==void 0)throw Error(`gjsify ship: ${C} and ${W} both install as ${H}. An icon is keyed on its context and its size: \`symbolic\` is read from a \`symbolic/\` path component or a \`-symbolic\` filename, the size from the path (\`.../128x128/...\`) or the filename (\`icon-128.png\`). Give them distinguishable sizes, or point \`gjsify.ship.icon\` at a single file.`);S.set(H,C),n.push({path:H,mode:420,source:{kind:`file`,path:C}})}return n}function assertInsidePrefix(t){let n=Tn.normalize(t);if(Tn.isAbsolute(n)||n===`..`||n.startsWith(`../`))throw Error(`gjsify ship: \`gjsify.ship.extraFiles\` destination "${t}" escapes the install prefix. Destinations are relative to the prefix, e.g. \`share/applications/extra.desktop\`.`);return n}function isExecutableAsset(t){return/\.(so|node|dylib)(\.\d+)*$/.test(t)}function normalise(t){let n=new Map;for(let S of t)n.set(S.path,S);return[...n.values()].sort((t,n)=>t.path<n.path?-1:+(t.path>n.path))}var kU=__esmMin(()=>{OU(),tH(),lH(),lU(),rH(),Ld(),qn()});function isGtkRuntimeTarget(t){return AU.includes(t)}function gtkRuntimePackageName(t){return`@gjsify/gtk-runtime-${t}`}function resolveGtkRuntime(t,n={}){let S=n.env??process.env,C=t.startsWith(`win32-`)?`bin`:`lib`,N=[],F=S.GJSIFY_GTK_RUNTIME;F&&N.push({source:`GJSIFY_GTK_RUNTIME`,dir:F});let I=resolveNodeGiRoot(n);I!==null&&(N.push({source:`${MU}/prebuilds/${t}`,dir:In(I,`prebuilds`,t,`gtk`)}),N.push({source:`${MU} sibling`,dir:In(I,`..`,`gtk-runtime-${t}`,`gtk`)}));let H=gtkRuntimePackageName(t),W=resolveStagedPackage(H,n);W!==null&&N.push({source:H,dir:In(zn(W),`gtk`)}),n.fetchedGtkRuntimeDir!==void 0&&N.push({source:`${H} (fetched for this ship run)`,dir:In(n.fetchedGtkRuntimeDir,`gtk`)});for(let t of N){let n=In(t.dir,C),S=In(t.dir,`girepository-1.0`);if(!(!existsSync(n)||!existsSync(S)))return{source:t.source,dir:t.dir,libDir:n,typelibDir:S}}return null}function resolveNodeGiAddon(t,n={}){let S=resolveNodeGiRoot(n);if(S===null)return null;let C=In(S,`prebuilds`,t,jU);return existsSync(C)?{source:MU,addonPath:C}:null}function resolveNodeGiRoot(t){let n=resolveStagedPackage(MU,t);return n===null?null:zn(n)}function resolveStagedPackage(t,n){let S={bundleUrl:import.meta.url};return n.cwd!==void 0&&(S.cwd=n.cwd),n.resolve!==void 0&&(S.resolve=n.resolve),resolveInstalledPackage(t,S)}function resolveNodeGiPackage(t={}){let n=resolveNodeGiRoot(t);if(n===null)return null;let S=[`package.json`];for(let t of readdirSync(n,{withFileTypes:!0}).sort((t,n)=>t.name<n.name?-1:1))t.isFile()&&t.name.endsWith(`.js`)&&S.push(t.name);let C=In(n,`overrides`);if(existsSync(C))for(let t of listFilesRecursive(C))S.push(Tn.join(`overrides`,t));return S.length>1?{source:MU,root:n,files:S.sort()}:null}function appRuntimePaths(t,n,S){let C=t.dirs(n),N=Tn.join(C.native,`node-gi`),F=Tn.join(N,`prebuilds`,S);return{nodeGiRoot:N,nodeGiPackageDir:Tn.join(C.bundle,`node_modules`,MU),prebuildDir:F,gtkDir:Tn.join(F,`gtk`),addonPath:Tn.join(F,jU),interpreterPath:C.helpers===``?Tn.join(C.launcher,nodeRuntimeBinaryName(S)):Tn.join(C.helpers,assertUsableAsHelperName(n.name)),interpreterLicensePath:Tn.join(C.data,`licenses`,`node`,`LICENSE`)}}function stageAppRuntime(t){let n=appRuntimePaths(t.layout,t.identity,t.target),S=[],C={},N=[],F=[];t.interpreter===null?F.push(`no bundled interpreter — install \`@gjsify/node-runtime-${t.target}\` (or point \`GJSIFY_NODE_RUNTIME\` at a \`bin/\` directory holding \`node\` and its \`LICENSE\`)`):(S.push({path:n.interpreterPath,mode:493,source:{kind:`file`,path:t.interpreter.nodePath}}),S.push({path:n.interpreterLicensePath,mode:420,source:{kind:`file`,path:t.interpreter.licensePath}}),C.interpreter=n.interpreterPath,N.push(`interpreter from ${t.interpreter.source}`));let I=resolveGtkRuntime(t.target,discoveryOptions(t));if(I!==null){for(let t of listFilesRecursive(I.dir)){let C=In(I.dir,t.split(`/`).join(Wn));S.push({path:Tn.join(n.gtkDir,t),mode:stagedMode(t,C),source:{kind:`file`,path:C}})}C.gtkRuntimeDir=n.gtkDir,N.push(`GTK closure from ${I.source}`)}else{let n=t.target.startsWith(`win32-`)?`bin`:`lib`,S=t.gtkFetchFailure===void 0?``:` — fetching it failed: ${t.gtkFetchFailure}`;F.push(`no GTK closure${S} — point \`GJSIFY_GTK_RUNTIME\` at a bundle directory holding \`${n}/\` and \`girepository-1.0/\`, or install \`${gtkRuntimePackageName(t.target)}\` where the build can reach it`)}let H=resolveNodeGiPackage(discoveryOptions(t));if(H!==null){for(let t of H.files)S.push({path:Tn.join(n.nodeGiPackageDir,t),mode:420,source:{kind:`file`,path:In(H.root,t.split(`/`).join(Wn))}});N.push(`node-gi runtime (${H.files.length} file(s)) from ${H.source}`)}else F.push(`no node-gi JavaScript — install \`${MU}\`; a \`--app node\` bundle keeps \`@gjsify/node-gi/*\` external, so the staged bundle would \`require\` a package the artifact does not carry`);let W=resolveNodeGiAddon(t.target,discoveryOptions(t));return W===null?F.push(`no node-gi addon — install \`${MU}\`, whose \`prebuilds/${t.target}/${jU}\` is the binary built against that closure`):(S.push({path:n.addonPath,mode:493,source:{kind:`file`,path:W.addonPath}}),C.nodeGiAddon=n.addonPath,N.push(`node-gi addon from ${W.source}`)),{files:S,launcher:C,found:N,missing:F}}function discoveryOptions(t){let n={};return t.cwd!==void 0&&(n.cwd=t.cwd),t.env!==void 0&&(n.env=t.env),t.resolve!==void 0&&(n.resolve=t.resolve),t.fetchedGtkRuntimeDir!==void 0&&(n.fetchedGtkRuntimeDir=t.fetchedGtkRuntimeDir),n}function stagedMode(t,n){if(isExecutableAsset(t)||t.startsWith(`libexec/`)||t.startsWith(`bin/`))return 493;try{if(statSync(n).mode&73)return 493}catch{}return 420}var AU,jU,MU,NU=__esmMin(()=>{ef(),qn(),SU(),WH(),wU(),kU(),PI(),AU=[`darwin-arm64`,`darwin-x64`,`win32-x64`,`win32-arm64`],jU=`node_gi.node`,MU=`@gjsify/node-gi`});function stageSubordinates(t){let n=t.layout.dirs(t.identity),S=[],C=[],N=[];for(let N of t.nestedBundles){if(n.plugins===``)throw Error(`gjsify ship: the ${t.layout.name} layout has no \`Contents/PlugIns\` equivalent, so the nested bundle "${N.name}" has nowhere to go. \`gjsify.ship.nestedBundles\` is darwin-only; \`resolveShipSettings\` should have refused this already — report this as a gjsify bug if it did not.`);let F=Tn.join(n.plugins,N.name);for(let t of listFilesRecursive(N.source)){let n=In(N.source,...t.split(Tn.sep));S.push({path:Tn.join(F,t),mode:stagedMode(t,n),source:{kind:`file`,path:n}})}C.push({path:F,entitlements:N.entitlements})}for(let C of t.helperExecutables){if(n.helpers===``)throw Error(`gjsify ship: the ${t.layout.name} layout has no \`Contents/Helpers\` equivalent, so the helper executable "${C.name}" has nowhere to go. \`gjsify.ship.helperExecutables\` is darwin-only; \`resolveShipSettings\` should have refused this already — report this as a gjsify bug if it did not.`);let F=Tn.join(n.helpers,C.name);S.push({path:F,mode:493,source:{kind:`file`,path:C.source}}),N.push({path:F,entitlements:C.entitlements})}return{files:S,nestedBundles:C,helperExecutables:N}}function signedSubordinatesFor(t,n,S){let C=t.dirs(n);return{nestedBundles:S.nestedBundles.map(t=>({path:Tn.join(C.plugins,t.name),entitlements:t.entitlements})),helperExecutables:S.helperExecutables.map(t=>({path:Tn.join(C.helpers,t.name),entitlements:t.entitlements}))}}function plistStringValue(t,n){return RegExp(`<key>${n}</key>\\s*<string>([^<]*)</string>`).exec(t)?.[1]}function nestedBundlePlist(t,n){let S=t.find(t=>t.path===Tn.join(n,`Contents`,`Info.plist`));return S===void 0?void 0:new TextDecoder().decode(S.data)}function recordedNestedBundles(t,n){return n.map(n=>{let S=Tn.basename(n.path),C=nestedBundlePlist(t,n.path);if(C===void 0)return{name:S};let N=plistStringValue(C,`CFBundleIdentifier`),F=plistStringValue(C,`NSExtensionPointIdentifier`);return{name:S,...N===void 0?{}:{bundleId:N},...F===void 0?{}:{extensionPoint:F}}})}var PU=__esmMin(()=>{qn(),SU(),NU()});function readManifest(t){try{return JSON.parse(readFileSync(In(t,`package.json`),`utf-8`))}catch{return null}}function findInstalled(t,n){let S=n;for(;;){let n=In(S,`node_modules`,...t.split(`/`));if(existsSync(In(n,`package.json`)))return n;let C=zn(S);if(C===S)return null;S=C}}function allows(t,n){let S=typeof t==`string`?[t]:t??[];if(S.includes(`!${n}`))return!1;let C=S.filter(t=>!t.startsWith(`!`));return C.length===0||C.includes(n)}function destinationOf(t){let n=t.split(Wn),S=n.indexOf(`node_modules`);return S===-1||S===n.length-1?null:n.slice(S+1).join(`/`)}function resolveNodeModulesClosure(t,n,S={}){let{target:C,exclude:N=[]}=S,F=new Map,I=[],H=[],W=[],visit=(t,n,S,q)=>{if(t===FU)return;if(S.length>0&&N.includes(t)){W.includes(t)||W.push(t);return}let Y=findInstalled(t,n);if(Y===null){if(q){I.includes(t)||I.push(t);return}throw Error(`gjsify ship: \`${t}\` is not installed${S.length>0?` (needed by ${S.join(` > `)})`:``}. `+(S.length===0?"`gjsify.ship.nodeModules` names it, so the artifact must carry it — install it, or remove the entry.":`A package without its required dependency is an artifact that fails at its first import.`))}let X=destinationOf(Y);if(X===null)throw Error(`gjsify ship: ${Y} is not inside a node_modules directory, so it has no place to be staged.`);let Z=realpathSync(Y),te=readManifest(Z);if(te===null)throw Error(`gjsify ship: ${In(Z,`package.json`)} is unreadable.`);if(S.length>0&&C!==void 0&&!(allows(te.os,C.os)&&allows(te.cpu,C.cpu))){H.includes(t)||H.push(t);return}let ne=F.get(X);if(ne!==void 0){if(ne.dir!==Z)throw Error(`gjsify ship: two installed copies of \`${t}\` would both be staged at node_modules/${X} (${ne.dir} and ${Z}).`);return}F.set(X,{name:t,version:te.version??`0.0.0`,dir:Z,dest:X});let re=[...S,t];for(let t of Object.keys(te.dependencies??{}))visit(t,Y,re,!1);for(let t of Object.keys(te.optionalDependencies??{}))visit(t,Y,re,!0)};for(let S of t)visit(S,n,[],!1);return{packages:[...F.values()].sort((t,n)=>t.dest<n.dest?-1:1),skippedOptional:I.sort(),skippedForTarget:H.sort(),excluded:W.sort()}}function listPackageFiles(t){let n=[],walk=S=>{for(let C of readdirSync(S,{withFileTypes:!0}).sort((t,n)=>t.name<n.name?-1:1)){let N=In(S,C.name);if(C.isDirectory())C.name!==`node_modules`&&walk(N);else if(C.isSymbolicLink())throw Error(`gjsify ship: ${N} is a symlink. The payload has to be self-contained — a package that links inside itself needs the link replaced by the file.`);else C.isFile()&&n.push(Tn.join(...Ln(t,N).split(Wn)))}};return walk(t),n}function modeOf(t,n){return isExecutableAsset(t)||statSync(n).mode&73?493:420}function stageNodeModules(t,n){let S=[];for(let C of t.packages)for(let t of listPackageFiles(C.dir)){let N=In(C.dir,...t.split(`/`));S.push({path:Tn.join(n,`node_modules`,C.dest,t),mode:modeOf(t,N),source:{kind:`file`,path:N}})}return S}var FU,IU=__esmMin(()=>{ef(),qn(),kU(),FU=`@gjsify/node-gi`});async function acquireGtkRuntime(t){let n=t.discovery??{};if(resolveGtkRuntime(t.target,n)!==null)return{kind:`present`};let S=gtkRuntimePackageName(t.target),C=`${S}@${t.version}`;if((n.env??process.env).GJSIFY_GTK_RUNTIME_FETCH===`0`)return{kind:`failed`,reason:`GJSIFY_GTK_RUNTIME_FETCH=0 turned off the fetch of ${C}`};t.log?.(`${S} is not installed here, and is not meant to be — fetching ${C} into the cache (about 100 MB, once)`);let N;try{N=await t.ensure(C)}catch(t){return{kind:`failed`,reason:t instanceof Error?t.message:String(t)}}return resolveGtkRuntime(t.target,{...n,fetchedGtkRuntimeDir:N})===null?{kind:`failed`,reason:`${C} was fetched to ${N} but holds no complete gtk/ closure`}:{kind:`fetched`,dir:N}}var LU=__esmMin(()=>{NU()});function appDirFor(t){return In(t,`appimage`,HU)}function appImageHostRequirements(t){let n=interpreterFloor(t),S=new Set(t.optionalNamespaces??[]);return[`${t.app} (>= ${n})`,...hostProvidedNamespaces(t.namespaces,t.bundledTypelibs).map(t=>S.has(t)?`the ${t} typelib (optional)`:`the ${t} typelib`)]}function interpreterFloor(t){return t.app===`node`?t.minNodeVersion??`24`:t.minGjsVersion??`1.86`}function renderAppRun(t,n){let S=VH.linux.dirs(t).launcher,C=interpreterFloor(t),[N=`0`,F=`0`]=C.split(`.`);return[`#!/bin/sh`,"# Generated by `gjsify ship` — do not edit.",`set -e`,`here=$(dirname "$(readlink -f "$0")")`,`if ! command -v ${t.app} >/dev/null 2>&1; then`,` echo "${shellSafe(t.name)} needs ${t.app}, and this system has none." >&2`,` echo "This AppImage carries the application, not its runtime. It needs:" >&2`,...n.map(t=>` echo " - ${shellSafe(t)}" >&2`),` exit 127`,`fi`,`found=$(${t.app} --version 2>/dev/null | sed -n 's/[^0-9]*\\([0-9][0-9]*\\)\\.\\([0-9][0-9]*\\).*/\\1 \\2/p' | head -n 1 || true)`,"major=${found% *}","minor=${found#* }",`if [ -n "$major" ]; then`,` if [ "$major" -lt ${N} ] || { [ "$major" -eq ${N} ] && [ "$minor" -lt ${F} ]; }; then`,` echo "${shellSafe(t.name)} needs ${t.app} ${C} or newer, and this system has $major.$minor." >&2`,` echo "This AppImage carries the application, not its runtime. It needs:" >&2`,...n.map(t=>` echo " - ${shellSafe(t)}" >&2`),` exit 126`,` fi`,`fi`,`exec "$here/usr/${S}/${t.binaryName}" "$@"`,``].join(`
1176
- `)}function shellSafe(t){return t.replace(/(["$`\\])/g,`\\$1`)}function findPinnedRuntime(t,n=process.env,S=existsSync){let C=n.GJSIFY_APPIMAGE_RUNTIME_DIR||`/usr/local/share/gjsify/appimage-runtime`,N=Tn.join(C,`runtime-${t}`);return S(N)?N:void 0}function appImageRuntimeNotice(t,n){return n===void 0?`NO pinned AppImage runtime for ${t}: appimagetool will fetch runtime-${t} from type2-runtime's rolling \`continuous\` tag, so this pack NEEDS A NETWORK and the ~940 KB of runtime it embeds carries no digest from this tree. Pin one at ${VU}/runtime-${t} (or point ${BU} at a directory holding it).`:`the AppImage runtime is pinned: ${n} — this pack needs no network`}function selectAppDirIcon(t,n){let S;for(let C of t){let t=rootIconRank(C.path,n);t!==void 0&&(S===void 0||t>S.rank)&&(S={entry:C,rank:t})}return S?.entry}function rootIconRank(t,n){if(GU.find(S=>t.endsWith(`${n}${S}`))===void 0||!t.startsWith(`${nH.icons}/`)||t.includes(`/symbolic/`))return;if(t.includes(`/scalable/`))return 2**53-1;let S=/\/(\d+)x\1\//.exec(t);return S===null?1:Number(S[1])}function assertAppImageIsPackable(t,n,S){let C=`${nH.applications}/${n.appId}.desktop`;if(!t.some(t=>t.path===C))throw Error(`gjsify ship: an AppImage needs a desktop entry and this payload has no ${C}. appimagetool refuses an AppDir without one, and the AppImage runtime has nothing to tell a desktop about the application it just mounted. A \`kind: "cli"\` project stages no entry by design — set \`gjsify.ship.kind\` to "app" if this is a GUI application, or ship it as a \`.deb\`, an \`.rpm\` or a Flatpak, none of which need one.`);if(selectAppDirIcon(t,n.appId)===void 0)throw Error(`gjsify ship: an AppImage needs an icon called ${n.appId} beside its desktop entry, and this payload stages none under ${nH.icons}/. The entry's \`Icon=\` names the app id, so a file keeping its own basename is an icon nothing looks up — point \`gjsify.ship.icon\` at a PNG or an SVG and it is renamed into the theme for you.`);if(S===void 0&&t.some(t=>isSchemaSource(t.path)))throw Error(`gjsify ship: this payload stages GSettings schema sources under ${nH.schemas}/ and no ${JH} was compiled for it. An AppImage has NO INSTALL STEP — that is the whole point of the format — so the \`.deb\`/\`.rpm\` postinst that compiles the system schema directory never runs, and GSettings aborts on a directory holding only sources. The AppDir must carry ${JH}; \`compileSchemasForPayload\` produces it from this payload.`)}function appDirPayload(t,n,S,C){assertAppImageIsPackable(n,t,C);let N=selectAppDirIcon(n,t.appId),F=`${nH.applications}/${t.appId}.desktop`,I=n.find(t=>t.path===F);return[...[...n,...C===void 0?[]:[C]].map(t=>({...t,path:`usr/${t.path}`})),{path:UU,mode:493,data:encodeUtf8(renderAppRun(t,S))},{path:`${t.appId}.desktop`,mode:420,data:I.data},{path:N.path.slice(N.path.lastIndexOf(`/`)+1),mode:420,data:N.data},{path:WU,mode:420,data:N.data}]}function appImageToolArgs(t){return[`--no-appstream`,`--comp`,`zstd`,...t.runtimeFile===void 0?[]:[`--runtime-file`,t.runtimeFile],t.appDir,t.target]}function appImageToolEnv(t){return{ARCH:t,[zU]:`1`}}function appImageToolFailureMessage(t,n){let S=n===void 0?`the AppImage RUNTIME could not be downloaded — ${RU} fetches it from github.com/AppImage/type2-runtime when no runtime is pinned, so this pack needs a network and an offline host fails here having written nothing; or `:`the pinned runtime at ${n} is not an AppImage runtime — it is passed through to \`--runtime-file\` unread, so a truncated or wrong-architecture file fails here; or `;return`gjsify ship: ${RU} failed with ${t}. Four causes, measured in this order: ${S}\`file\` is not installed — ${RU} requires file(1) and says so, even though this pack already tells it the architecture; or FUSE is unavailable and the tool on PATH is a wrapper that dropped ${zU}=1, which this pack sets so the extract path is taken instead of a mount; or the work directory is full — the AppDir is copied into a squashfs image beside it.`}async function buildAppImage(t){let n=appImageToolArgs(t),S=appImageToolEnv(t.archLabel);t.verbose&&ge.log(`[gjsify ship] ${Object.entries(S).map(([t,n])=>`${t}=${n}`).join(` `)} ${RU} ${n.join(` `)}`);let C=await spawnToCompletion(RU,n,{completion:`return`,cwd:t.workDir,stdio:`inherit`,env:{...process.env,...S},notFound:()=>Error(`gjsify ship: ${RU} is not on PATH. Unlike flatpak-builder and msitools it is not packaged by Fedora or Debian: take the release from https://github.com/AppImage/appimagetool/releases, \`chmod +x\` it and put it on PATH as \`${RU}\`. \`gjsify ship linux --stage\` needs none of this — the payload is assembled by this CLI and only the container needs the tool.`)});if(C.code!==0)throw Error(appImageToolFailureMessage(describeExit(C),t.runtimeFile));if(!existsSync(t.target))throw Error(`gjsify ship: ${RU} exited 0 and wrote no file at ${t.target}. An exit code is not an artifact — re-run with \`--verbose\` to see what it was told.`)}function appDirPaths(t){let n=new Set;for(let S of t){let t=S.path.split(`/`);for(let S=1;S<t.length;S++)n.add(t.slice(0,S).join(`/`))}return[...[...n].sort(),...t.map(t=>t.path)]}function stampAppDirTimes(t,n,S){for(let C of appDirPaths(n))utimesSync(In(t,C.split(`/`).join(Wn)),S,S);utimesSync(t,S,S)}var RU,zU,BU,VU,HU,UU,WU,GU,KU=__esmMin(()=>{_e(),ef(),qn(),sv(),HV(),eH(),WH(),YH(),rH(),RU=`appimagetool`,zU=`APPIMAGE_EXTRACT_AND_RUN`,BU=`GJSIFY_APPIMAGE_RUNTIME_DIR`,VU=`/usr/local/share/gjsify/appimage-runtime`,HU=`AppDir`,UU=`AppRun`,WU=`.DirIcon`,GU=[`.png`,`.svg`]});function dmgVolumeName(t){let n=t.name;if(n.trim()===``)throw Error("gjsify ship: the macOS image has no name to call its volume — `gjsify.ship.name` (or the package name it is derived from) is empty. `hdiutil` would accept that and mount the image as `untitled`, which is the name every nameless disk image on the machine has.");if(JU.test(n))throw Error(`gjsify ship: the macOS image would mount a volume called "${n}", and HFS+ cannot hold it: the Finder shows a stored ":" as a "/" and a stored "/" as a ":", so the volume would not be the one this project named. Set \`gjsify.ship.name\` to the display name you want.`);return n}function hdiutilCreateArgs(t){return[`create`,`-format`,`UDZO`,`-fs`,`HFS+J`,`-volname`,t.volumeName,`-srcfolder`,t.sourceDir,`-ov`,`-quiet`,t.target]}async function buildDmgImage(t){let n=hdiutilCreateArgs(t);t.verbose&&ge.log(`[gjsify ship] ${qU} ${n.join(` `)}`);let S=await spawnToCompletion(qU,n,{completion:`return`,cwd:t.workDir,stdio:`inherit`,notFound:()=>Error(`gjsify ship: ${qU} is not on PATH. It ships with macOS and cannot be installed anywhere else, so this is either a broken macOS installation or a host that is not macOS at all. A \`.dmg\` is packed on darwin (ADR 0024 § A1); from anywhere else the route is \`gjsify ship darwin --stage\` here and \`gjsify ship --from-stage <dir> --target macos-app-dmg\` there.`)});if(S.code!==0)throw Error(`gjsify ship: ${qU} failed with ${describeExit(S)}.`)}function dmgVolumeDir(t){return In(t,`dmg`,`volume`)}function addApplicationsLink(t){symlinkSync(YU.target,In(t,YU.name))}function codesignDmgArgs(t){return[`--force`,`--sign`,t.identity,...t.adhoc?[]:[`--timestamp`],t.file]}async function signDmgImage(t){let n=codesignDmgArgs(t);t.verbose&&ge.log(`[gjsify ship] ${XU} ${n.join(` `)}`);let S=await spawnToCompletion(XU,n,{completion:`return`,cwd:t.workDir,stdio:`inherit`,notFound:()=>Error(`gjsify ship: ${XU} is not on PATH, so the image cannot be signed. Install the Xcode Command Line Tools (\`xcode-select --install\`).`)});if(S.code!==0)throw Error(`gjsify ship: ${XU} failed on the image with ${describeExit(S)}.`)}async function stapleBundleBeforeImage(t){t.writeArchive(),await t.notarize(),await t.staple()}var qU,JU,YU,XU,ZU=__esmMin(()=>{_e(),ef(),qn(),sv(),qU=`hdiutil`,JU=/[/:]/,YU={name:`Applications`,target:`/Applications`},XU=`codesign`});function renderShipFlatpakManifest(t){let{settings:n,stageDir:S,overlayDir:C}=t,N=n.flatpak,F={id:n.appId,runtime:N.runtime,"runtime-version":N.runtimeVersion,sdk:N.sdk,branch:N.branch,command:n.binaryName,"finish-args":N.finishArgs};return N.sdkExtensions.length>0&&(F[`sdk-extensions`]=N.sdkExtensions),N.appendPath.length>0&&(F[`build-options`]={"append-path":N.appendPath.join(`:`)}),N.cleanup.length>0&&(F.cleanup=N.cleanup),F.modules=[{name:n.binaryName,buildsystem:`simple`,"build-commands":[`mkdir -p /app`,`cp -a stage/. /app/`,`cp -a overlay/. /app/`],sources:[{type:`dir`,path:S,dest:`stage`,skip:[t.stageManifestFile]},{type:`dir`,path:C,dest:`overlay`}]}],F}async function buildFlatpakBundle(t){let{settings:n,workDir:S,archLabel:C}=t,N=In(S,`${n.appId}.json`),F=In(S,`build`),I=In(S,`repo`),H=In(S,`state`);mkdirSync(S,{recursive:!0}),rmSync(I,{recursive:!0,force:!0,maxRetries:5}),writeFileSync(N,`${JSON.stringify(renderShipFlatpakManifest(t),null,2)}\n`),await run$1(`flatpak-builder`,[`--force-clean`,`--disable-rofiles-fuse`,`--delete-build-dirs`,`--state-dir=${H}`,`--arch=${C}`,`--repo=${I}`,F,N],t,"flatpak-builder not found. Install it (Fedora: `sudo dnf install flatpak-builder`)."),await run$1(`flatpak`,[`build-bundle`,`--arch=${C}`,I,t.target,n.appId,n.flatpak.branch],t,`flatpak not found. Install it via your distro: see https://flathub.org/setup.`)}async function run$1(t,n,S,C){S.verbose&&ge.log(`[gjsify ship] ${t} ${n.join(` `)}`);let N=await spawnToCompletion(t,n,{completion:`return`,cwd:S.workDir,stdio:`inherit`,notFound:()=>Error(`gjsify ship: ${C}`)});if(N.code!==0)throw Error(`gjsify ship: ${t} failed with ${describeExit(N)}.`)}var QU=__esmMin(()=>{_e(),ef(),qn(),sv(),__name$1(run$1,`run`)});function localeOf(t){return t.split(`/`)[0]??``}function fold(t,n,S,C,N){let F=In(N,`source${S}`);return writeFileSync(F,n),readFileSync(mergeCatalogues({mode:t,template:F,extension:S,catalogues:C,workDir:N}),`utf-8`)}function localizeMetadata(t,n){if(n.length===0)return t;let S=mkdtempSync(In(tmpdir(),`gjsify-ship-l10n-`));try{let C=[...n].sort((t,n)=>t.rel<n.rel?-1:+(t.rel>n.rel)),N=new Map;for(let[t,n]of C.entries()){let C=In(S,`${t}.po`);execFileSync(`msgunfmt`,[n.abs,`--output-file`,C],{stdio:`pipe`});let F=localeOf(n.rel);N.set(F,[...N.get(F)??[],C])}let F=[...N].map(([t,n])=>({locale:t,po:n.length===1?n[0]:msgcat(n,In(S,`${t}.merged.po`))}));return{metainfo:fold(`--xml`,t.metainfo,`.metainfo.xml`,F,S),desktopEntry:t.desktopEntry===void 0?void 0:fold(`--desktop`,t.desktopEntry,`.desktop`,F,S)}}catch(t){throw Error(describeFailure(t,n.length))}finally{rmSync(S,{recursive:!0,force:!0})}}function msgcat(t,n){return execFileSync(`msgcat`,[`--use-first`,`--output-file`,n,...t],{stdio:`pipe`}),n}function describeFailure(t,n){let S=t;return S?.code===`ENOENT`?`gjsify ship: \`msgfmt\`/\`msgunfmt\`/\`msgcat\` are not on PATH, but the package stages ${n} gettext catalogue(s). Install them (package: gettext) — shipping the metadata untranslated would install an English app menu entry for a translated app, which nothing downstream can detect.`:`gjsify ship: could not fold the gettext catalogues into the freedesktop metadata.${S?.stderr===void 0?``:`\n${String(S.stderr).trim()}`}`}var $U=__esmMin(()=>{ev(),ef(),$g(),qn(),zB()});function lookupArch(t,n,S){let C=t[n];if(!C)throw Error(`gjsify ship: no ${S} architecture is known for \`process.arch\` "${n}". Known: ${Object.keys(t).join(`, `)}.`);return C}function debArch(t,n){return n?`all`:lookupArch(eW,t,`Debian`)}function rpmArch(t,n){return n?`noarch`:lookupArch(tW,t,`RPM`)}function flatpakArch(t,n){return lookupArch(nW,t,`Flatpak`)}function appImageArch(t,n){return lookupArch(rW,t,`AppImage`)}function macosArch(t,n){return lookupArch(iW,t,`macOS`)}function windowsArch(t,n){return lookupArch(aW,t,`Windows`)}function windowsNameIsUnusable(t){return oW.test(t)||sW.test(t)||/[. ]$/.test(t)?!0:[...t].some(t=>(t.codePointAt(0)??0)<32)}function windowsProgramDirName(t){let n=t.name;if(n.trim()===``)throw Error("gjsify ship: the windows layout has no name to call the program directory — `gjsify.ship.name` (or the package name it is derived from) is empty. The artifact IS a directory and its zip expands into one, so an empty name would unpack `app\\`, `share\\` and the launcher loose into whatever folder the user was in.");if(windowsNameIsUnusable(n))throw Error(`gjsify ship: the windows layout would put this app in a directory called "${n}", and Windows cannot hold it: it reserves < > : " / \\ | ? * and the control characters, reserves CON, PRN, AUX, NUL, COM1-9 and LPT1-9 as device names at every path, and silently strips a trailing dot or space.
1175
+ `)}function planIcons(t){let n=[],S=new Map;for(let C of t.iconFiles){let N=Vn(C),F=iconThemeDir(C),I=isSymbolicIcon(C)?`${t.appId}-symbolic`:t.appId,H=`${rH.icons}/${F}/apps/${I}${N}`,W=S.get(H);if(W!==void 0)throw Error(`gjsify ship: ${C} and ${W} both install as ${H}. An icon is keyed on its context and its size: \`symbolic\` is read from a \`symbolic/\` path component or a \`-symbolic\` filename, the size from the path (\`.../128x128/...\`) or the filename (\`icon-128.png\`). Give them distinguishable sizes, or point \`gjsify.ship.icon\` at a single file.`);S.set(H,C),n.push({path:H,mode:420,source:{kind:`file`,path:C}})}return n}function assertInsidePrefix(t){let n=Tn.normalize(t);if(Tn.isAbsolute(n)||n===`..`||n.startsWith(`../`))throw Error(`gjsify ship: \`gjsify.ship.extraFiles\` destination "${t}" escapes the install prefix. Destinations are relative to the prefix, e.g. \`share/applications/extra.desktop\`.`);return n}function isExecutableAsset(t){return/\.(so|node|dylib)(\.\d+)*$/.test(t)}function normalise(t){let n=new Map;for(let S of t)n.set(S.path,S);return[...n.values()].sort((t,n)=>t.path<n.path?-1:+(t.path>n.path))}var AU=__esmMin(()=>{kU(),nH(),uH(),uU(),iH(),Ld(),qn()});function isGtkRuntimeTarget(t){return jU.includes(t)}function gtkRuntimePackageName(t){return`@gjsify/gtk-runtime-${t}`}function resolveGtkRuntime(t,n={}){let S=n.env??process.env,C=t.startsWith(`win32-`)?`bin`:`lib`,N=[],F=S.GJSIFY_GTK_RUNTIME;F&&N.push({source:`GJSIFY_GTK_RUNTIME`,dir:F});let I=resolveNodeGiRoot(n);I!==null&&(N.push({source:`${NU}/prebuilds/${t}`,dir:In(I,`prebuilds`,t,`gtk`)}),N.push({source:`${NU} sibling`,dir:In(I,`..`,`gtk-runtime-${t}`,`gtk`)}));let H=gtkRuntimePackageName(t),W=resolveStagedPackage(H,n);W!==null&&N.push({source:H,dir:In(zn(W),`gtk`)}),n.fetchedGtkRuntimeDir!==void 0&&N.push({source:`${H} (fetched for this ship run)`,dir:In(n.fetchedGtkRuntimeDir,`gtk`)});for(let t of N){let n=In(t.dir,C),S=In(t.dir,`girepository-1.0`);if(!(!existsSync(n)||!existsSync(S)))return{source:t.source,dir:t.dir,libDir:n,typelibDir:S}}return null}function resolveNodeGiAddon(t,n={}){let S=resolveNodeGiRoot(n);if(S===null)return null;let C=In(S,`prebuilds`,t,MU);return existsSync(C)?{source:NU,addonPath:C}:null}function resolveNodeGiRoot(t){let n=resolveStagedPackage(NU,t);return n===null?null:zn(n)}function resolveStagedPackage(t,n){let S={bundleUrl:import.meta.url};return n.cwd!==void 0&&(S.cwd=n.cwd),n.resolve!==void 0&&(S.resolve=n.resolve),resolveInstalledPackage(t,S)}function resolveNodeGiPackage(t={}){let n=resolveNodeGiRoot(t);if(n===null)return null;let S=[`package.json`];for(let t of readdirSync(n,{withFileTypes:!0}).sort((t,n)=>t.name<n.name?-1:1))t.isFile()&&t.name.endsWith(`.js`)&&S.push(t.name);let C=In(n,`overrides`);if(existsSync(C))for(let t of listFilesRecursive(C))S.push(Tn.join(`overrides`,t));return S.length>1?{source:NU,root:n,files:S.sort()}:null}function appRuntimePaths(t,n,S){let C=t.dirs(n),N=Tn.join(C.native,`node-gi`),F=Tn.join(N,`prebuilds`,S);return{nodeGiRoot:N,nodeGiPackageDir:Tn.join(C.bundle,`node_modules`,NU),prebuildDir:F,gtkDir:Tn.join(F,`gtk`),addonPath:Tn.join(F,MU),interpreterPath:C.helpers===``?Tn.join(C.launcher,nodeRuntimeBinaryName(S)):Tn.join(C.helpers,assertUsableAsHelperName(n.name)),interpreterLicensePath:Tn.join(C.data,`licenses`,`node`,`LICENSE`)}}function stageAppRuntime(t){let n=appRuntimePaths(t.layout,t.identity,t.target),S=[],C={},N=[],F=[];t.interpreter===null?F.push(`no bundled interpreter — install \`@gjsify/node-runtime-${t.target}\` (or point \`GJSIFY_NODE_RUNTIME\` at a \`bin/\` directory holding \`node\` and its \`LICENSE\`)`):(S.push({path:n.interpreterPath,mode:493,source:{kind:`file`,path:t.interpreter.nodePath}}),S.push({path:n.interpreterLicensePath,mode:420,source:{kind:`file`,path:t.interpreter.licensePath}}),C.interpreter=n.interpreterPath,N.push(`interpreter from ${t.interpreter.source}`));let I=resolveGtkRuntime(t.target,discoveryOptions(t));if(I!==null){for(let t of listFilesRecursive(I.dir)){let C=In(I.dir,t.split(`/`).join(Wn));S.push({path:Tn.join(n.gtkDir,t),mode:stagedMode(t,C),source:{kind:`file`,path:C}})}C.gtkRuntimeDir=n.gtkDir,N.push(`GTK closure from ${I.source}`)}else{let n=t.target.startsWith(`win32-`)?`bin`:`lib`,S=t.gtkFetchFailure===void 0?``:` — fetching it failed: ${t.gtkFetchFailure}`;F.push(`no GTK closure${S} — point \`GJSIFY_GTK_RUNTIME\` at a bundle directory holding \`${n}/\` and \`girepository-1.0/\`, or install \`${gtkRuntimePackageName(t.target)}\` where the build can reach it`)}let H=resolveNodeGiPackage(discoveryOptions(t));if(H!==null){for(let t of H.files)S.push({path:Tn.join(n.nodeGiPackageDir,t),mode:420,source:{kind:`file`,path:In(H.root,t.split(`/`).join(Wn))}});N.push(`node-gi runtime (${H.files.length} file(s)) from ${H.source}`)}else F.push(`no node-gi JavaScript — install \`${NU}\`; a \`--app node\` bundle keeps \`@gjsify/node-gi/*\` external, so the staged bundle would \`require\` a package the artifact does not carry`);let W=resolveNodeGiAddon(t.target,discoveryOptions(t));return W===null?F.push(`no node-gi addon — install \`${NU}\`, whose \`prebuilds/${t.target}/${MU}\` is the binary built against that closure`):(S.push({path:n.addonPath,mode:493,source:{kind:`file`,path:W.addonPath}}),C.nodeGiAddon=n.addonPath,N.push(`node-gi addon from ${W.source}`)),{files:S,launcher:C,found:N,missing:F}}function discoveryOptions(t){let n={};return t.cwd!==void 0&&(n.cwd=t.cwd),t.env!==void 0&&(n.env=t.env),t.resolve!==void 0&&(n.resolve=t.resolve),t.fetchedGtkRuntimeDir!==void 0&&(n.fetchedGtkRuntimeDir=t.fetchedGtkRuntimeDir),n}function stagedMode(t,n){if(isExecutableAsset(t)||t.startsWith(`libexec/`)||t.startsWith(`bin/`))return 493;try{if(statSync(n).mode&73)return 493}catch{}return 420}var jU,MU,NU,PU=__esmMin(()=>{ef(),qn(),CU(),GH(),TU(),AU(),PI(),jU=[`darwin-arm64`,`darwin-x64`,`win32-x64`,`win32-arm64`],MU=`node_gi.node`,NU=`@gjsify/node-gi`});function stageSubordinates(t){let n=t.layout.dirs(t.identity),S=[],C=[],N=[];for(let N of t.nestedBundles){if(n.plugins===``)throw Error(`gjsify ship: the ${t.layout.name} layout has no \`Contents/PlugIns\` equivalent, so the nested bundle "${N.name}" has nowhere to go. \`gjsify.ship.nestedBundles\` is darwin-only; \`resolveShipNestedBundles\` should have resolved this to \`[]\` already — report this as a gjsify bug if it did not.`);let F=Tn.join(n.plugins,N.name);for(let t of listFilesRecursive(N.source)){let n=In(N.source,...t.split(Tn.sep));S.push({path:Tn.join(F,t),mode:stagedMode(t,n),source:{kind:`file`,path:n}})}C.push({path:F,entitlements:N.entitlements})}for(let C of t.helperExecutables){if(n.helpers===``)throw Error(`gjsify ship: the ${t.layout.name} layout has no \`Contents/Helpers\` equivalent, so the helper executable "${C.name}" has nowhere to go. \`gjsify.ship.helperExecutables\` is darwin-only; \`resolveShipHelperExecutables\` should have resolved this to \`[]\` already — report this as a gjsify bug if it did not.`);let F=Tn.join(n.helpers,C.name);S.push({path:F,mode:493,source:{kind:`file`,path:C.source}}),N.push({path:F,entitlements:C.entitlements})}return{files:S,nestedBundles:C,helperExecutables:N}}function signedSubordinatesFor(t,n,S){let C=t.dirs(n);return{nestedBundles:S.nestedBundles.map(t=>({path:Tn.join(C.plugins,t.name),entitlements:t.entitlements})),helperExecutables:S.helperExecutables.map(t=>({path:Tn.join(C.helpers,t.name),entitlements:t.entitlements}))}}function plistStringValue(t,n){return RegExp(`<key>${n}</key>\\s*<string>([^<]*)</string>`).exec(t)?.[1]}function nestedBundlePlist(t,n){let S=t.find(t=>t.path===Tn.join(n,`Contents`,`Info.plist`));return S===void 0?void 0:new TextDecoder().decode(S.data)}function recordedNestedBundles(t,n){return n.map(n=>{let S=Tn.basename(n.path),C=nestedBundlePlist(t,n.path);if(C===void 0)return{name:S};let N=plistStringValue(C,`CFBundleIdentifier`),F=plistStringValue(C,`NSExtensionPointIdentifier`);return{name:S,...N===void 0?{}:{bundleId:N},...F===void 0?{}:{extensionPoint:F}}})}var FU=__esmMin(()=>{qn(),CU(),PU()});function readManifest(t){try{return JSON.parse(readFileSync(In(t,`package.json`),`utf-8`))}catch{return null}}function findInstalled(t,n){let S=n;for(;;){let n=In(S,`node_modules`,...t.split(`/`));if(existsSync(In(n,`package.json`)))return n;let C=zn(S);if(C===S)return null;S=C}}function allows(t,n){let S=typeof t==`string`?[t]:t??[];if(S.includes(`!${n}`))return!1;let C=S.filter(t=>!t.startsWith(`!`));return C.length===0||C.includes(n)}function destinationOf(t){let n=t.split(Wn),S=n.indexOf(`node_modules`);return S===-1||S===n.length-1?null:n.slice(S+1).join(`/`)}function resolveNodeModulesClosure(t,n,S={}){let{target:C,exclude:N=[]}=S,F=new Map,I=[],H=[],W=[],visit=(t,n,S,q)=>{if(t===IU)return;if(S.length>0&&N.includes(t)){W.includes(t)||W.push(t);return}let Y=findInstalled(t,n);if(Y===null){if(q){I.includes(t)||I.push(t);return}throw Error(`gjsify ship: \`${t}\` is not installed${S.length>0?` (needed by ${S.join(` > `)})`:``}. `+(S.length===0?"`gjsify.ship.nodeModules` names it, so the artifact must carry it — install it, or remove the entry.":`A package without its required dependency is an artifact that fails at its first import.`))}let X=destinationOf(Y);if(X===null)throw Error(`gjsify ship: ${Y} is not inside a node_modules directory, so it has no place to be staged.`);let Z=realpathSync(Y),te=readManifest(Z);if(te===null)throw Error(`gjsify ship: ${In(Z,`package.json`)} is unreadable.`);if(S.length>0&&C!==void 0&&!(allows(te.os,C.os)&&allows(te.cpu,C.cpu))){H.includes(t)||H.push(t);return}let ne=F.get(X);if(ne!==void 0){if(ne.dir!==Z)throw Error(`gjsify ship: two installed copies of \`${t}\` would both be staged at node_modules/${X} (${ne.dir} and ${Z}).`);return}F.set(X,{name:t,version:te.version??`0.0.0`,dir:Z,dest:X});let re=[...S,t];for(let t of Object.keys(te.dependencies??{}))visit(t,Y,re,!1);for(let t of Object.keys(te.optionalDependencies??{}))visit(t,Y,re,!0)};for(let S of t)visit(S,n,[],!1);return{packages:[...F.values()].sort((t,n)=>t.dest<n.dest?-1:1),skippedOptional:I.sort(),skippedForTarget:H.sort(),excluded:W.sort()}}function listPackageFiles(t){let n=[],walk=S=>{for(let C of readdirSync(S,{withFileTypes:!0}).sort((t,n)=>t.name<n.name?-1:1)){let N=In(S,C.name);if(C.isDirectory())C.name!==`node_modules`&&walk(N);else if(C.isSymbolicLink())throw Error(`gjsify ship: ${N} is a symlink. The payload has to be self-contained — a package that links inside itself needs the link replaced by the file.`);else C.isFile()&&n.push(Tn.join(...Ln(t,N).split(Wn)))}};return walk(t),n}function modeOf(t,n){return isExecutableAsset(t)||statSync(n).mode&73?493:420}function stageNodeModules(t,n){let S=[];for(let C of t.packages)for(let t of listPackageFiles(C.dir)){let N=In(C.dir,...t.split(`/`));S.push({path:Tn.join(n,`node_modules`,C.dest,t),mode:modeOf(t,N),source:{kind:`file`,path:N}})}return S}var IU,LU=__esmMin(()=>{ef(),qn(),AU(),IU=`@gjsify/node-gi`});async function acquireGtkRuntime(t){let n=t.discovery??{};if(resolveGtkRuntime(t.target,n)!==null)return{kind:`present`};let S=gtkRuntimePackageName(t.target),C=`${S}@${t.version}`;if((n.env??process.env).GJSIFY_GTK_RUNTIME_FETCH===`0`)return{kind:`failed`,reason:`GJSIFY_GTK_RUNTIME_FETCH=0 turned off the fetch of ${C}`};t.log?.(`${S} is not installed here, and is not meant to be — fetching ${C} into the cache (about 100 MB, once)`);let N;try{N=await t.ensure(C)}catch(t){return{kind:`failed`,reason:t instanceof Error?t.message:String(t)}}return resolveGtkRuntime(t.target,{...n,fetchedGtkRuntimeDir:N})===null?{kind:`failed`,reason:`${C} was fetched to ${N} but holds no complete gtk/ closure`}:{kind:`fetched`,dir:N}}var RU=__esmMin(()=>{PU()});function appDirFor(t){return In(t,`appimage`,UU)}function appImageHostRequirements(t){let n=interpreterFloor(t),S=new Set(t.optionalNamespaces??[]);return[`${t.app} (>= ${n})`,...hostProvidedNamespaces(t.namespaces,t.bundledTypelibs).map(t=>S.has(t)?`the ${t} typelib (optional)`:`the ${t} typelib`)]}function interpreterFloor(t){return t.app===`node`?t.minNodeVersion??`24`:t.minGjsVersion??`1.86`}function renderAppRun(t,n){let S=HH.linux.dirs(t).launcher,C=interpreterFloor(t),[N=`0`,F=`0`]=C.split(`.`);return[`#!/bin/sh`,"# Generated by `gjsify ship` — do not edit.",`set -e`,`here=$(dirname "$(readlink -f "$0")")`,`if ! command -v ${t.app} >/dev/null 2>&1; then`,` echo "${shellSafe(t.name)} needs ${t.app}, and this system has none." >&2`,` echo "This AppImage carries the application, not its runtime. It needs:" >&2`,...n.map(t=>` echo " - ${shellSafe(t)}" >&2`),` exit 127`,`fi`,`found=$(${t.app} --version 2>/dev/null | sed -n 's/[^0-9]*\\([0-9][0-9]*\\)\\.\\([0-9][0-9]*\\).*/\\1 \\2/p' | head -n 1 || true)`,"major=${found% *}","minor=${found#* }",`if [ -n "$major" ]; then`,` if [ "$major" -lt ${N} ] || { [ "$major" -eq ${N} ] && [ "$minor" -lt ${F} ]; }; then`,` echo "${shellSafe(t.name)} needs ${t.app} ${C} or newer, and this system has $major.$minor." >&2`,` echo "This AppImage carries the application, not its runtime. It needs:" >&2`,...n.map(t=>` echo " - ${shellSafe(t)}" >&2`),` exit 126`,` fi`,`fi`,`exec "$here/usr/${S}/${t.binaryName}" "$@"`,``].join(`
1176
+ `)}function shellSafe(t){return t.replace(/(["$`\\])/g,`\\$1`)}function findPinnedRuntime(t,n=process.env,S=existsSync){let C=n.GJSIFY_APPIMAGE_RUNTIME_DIR||`/usr/local/share/gjsify/appimage-runtime`,N=Tn.join(C,`runtime-${t}`);return S(N)?N:void 0}function appImageRuntimeNotice(t,n){return n===void 0?`NO pinned AppImage runtime for ${t}: appimagetool will fetch runtime-${t} from type2-runtime's rolling \`continuous\` tag, so this pack NEEDS A NETWORK and the ~940 KB of runtime it embeds carries no digest from this tree. Pin one at ${HU}/runtime-${t} (or point ${VU} at a directory holding it).`:`the AppImage runtime is pinned: ${n} — this pack needs no network`}function selectAppDirIcon(t,n){let S;for(let C of t){let t=rootIconRank(C.path,n);t!==void 0&&(S===void 0||t>S.rank)&&(S={entry:C,rank:t})}return S?.entry}function rootIconRank(t,n){if(KU.find(S=>t.endsWith(`${n}${S}`))===void 0||!t.startsWith(`${rH.icons}/`)||t.includes(`/symbolic/`))return;if(t.includes(`/scalable/`))return 2**53-1;let S=/\/(\d+)x\1\//.exec(t);return S===null?1:Number(S[1])}function assertAppImageIsPackable(t,n,S){let C=`${rH.applications}/${n.appId}.desktop`;if(!t.some(t=>t.path===C))throw Error(`gjsify ship: an AppImage needs a desktop entry and this payload has no ${C}. appimagetool refuses an AppDir without one, and the AppImage runtime has nothing to tell a desktop about the application it just mounted. A \`kind: "cli"\` project stages no entry by design — set \`gjsify.ship.kind\` to "app" if this is a GUI application, or ship it as a \`.deb\`, an \`.rpm\` or a Flatpak, none of which need one.`);if(selectAppDirIcon(t,n.appId)===void 0)throw Error(`gjsify ship: an AppImage needs an icon called ${n.appId} beside its desktop entry, and this payload stages none under ${rH.icons}/. The entry's \`Icon=\` names the app id, so a file keeping its own basename is an icon nothing looks up — point \`gjsify.ship.icon\` at a PNG or an SVG and it is renamed into the theme for you.`);if(S===void 0&&t.some(t=>isSchemaSource(t.path)))throw Error(`gjsify ship: this payload stages GSettings schema sources under ${rH.schemas}/ and no ${YH} was compiled for it. An AppImage has NO INSTALL STEP — that is the whole point of the format — so the \`.deb\`/\`.rpm\` postinst that compiles the system schema directory never runs, and GSettings aborts on a directory holding only sources. The AppDir must carry ${YH}; \`compileSchemasForPayload\` produces it from this payload.`)}function appDirPayload(t,n,S,C){assertAppImageIsPackable(n,t,C);let N=selectAppDirIcon(n,t.appId),F=`${rH.applications}/${t.appId}.desktop`,I=n.find(t=>t.path===F);return[...[...n,...C===void 0?[]:[C]].map(t=>({...t,path:`usr/${t.path}`})),{path:WU,mode:493,data:encodeUtf8(renderAppRun(t,S))},{path:`${t.appId}.desktop`,mode:420,data:I.data},{path:N.path.slice(N.path.lastIndexOf(`/`)+1),mode:420,data:N.data},{path:GU,mode:420,data:N.data}]}function appImageToolArgs(t){return[`--no-appstream`,`--comp`,`zstd`,...t.runtimeFile===void 0?[]:[`--runtime-file`,t.runtimeFile],t.appDir,t.target]}function appImageToolEnv(t){return{ARCH:t,[BU]:`1`}}function appImageToolFailureMessage(t,n){let S=n===void 0?`the AppImage RUNTIME could not be downloaded — ${zU} fetches it from github.com/AppImage/type2-runtime when no runtime is pinned, so this pack needs a network and an offline host fails here having written nothing; or `:`the pinned runtime at ${n} is not an AppImage runtime — it is passed through to \`--runtime-file\` unread, so a truncated or wrong-architecture file fails here; or `;return`gjsify ship: ${zU} failed with ${t}. Four causes, measured in this order: ${S}\`file\` is not installed — ${zU} requires file(1) and says so, even though this pack already tells it the architecture; or FUSE is unavailable and the tool on PATH is a wrapper that dropped ${BU}=1, which this pack sets so the extract path is taken instead of a mount; or the work directory is full — the AppDir is copied into a squashfs image beside it.`}async function buildAppImage(t){let n=appImageToolArgs(t),S=appImageToolEnv(t.archLabel);t.verbose&&ge.log(`[gjsify ship] ${Object.entries(S).map(([t,n])=>`${t}=${n}`).join(` `)} ${zU} ${n.join(` `)}`);let C=await spawnToCompletion(zU,n,{completion:`return`,cwd:t.workDir,stdio:`inherit`,env:{...process.env,...S},notFound:()=>Error(`gjsify ship: ${zU} is not on PATH. Unlike flatpak-builder and msitools it is not packaged by Fedora or Debian: take the release from https://github.com/AppImage/appimagetool/releases, \`chmod +x\` it and put it on PATH as \`${zU}\`. \`gjsify ship linux --stage\` needs none of this — the payload is assembled by this CLI and only the container needs the tool.`)});if(C.code!==0)throw Error(appImageToolFailureMessage(describeExit(C),t.runtimeFile));if(!existsSync(t.target))throw Error(`gjsify ship: ${zU} exited 0 and wrote no file at ${t.target}. An exit code is not an artifact — re-run with \`--verbose\` to see what it was told.`)}function appDirPaths(t){let n=new Set;for(let S of t){let t=S.path.split(`/`);for(let S=1;S<t.length;S++)n.add(t.slice(0,S).join(`/`))}return[...[...n].sort(),...t.map(t=>t.path)]}function stampAppDirTimes(t,n,S){for(let C of appDirPaths(n))utimesSync(In(t,C.split(`/`).join(Wn)),S,S);utimesSync(t,S,S)}var zU,BU,VU,HU,UU,WU,GU,KU,qU=__esmMin(()=>{_e(),ef(),qn(),sv(),UV(),tH(),GH(),XH(),iH(),zU=`appimagetool`,BU=`APPIMAGE_EXTRACT_AND_RUN`,VU=`GJSIFY_APPIMAGE_RUNTIME_DIR`,HU=`/usr/local/share/gjsify/appimage-runtime`,UU=`AppDir`,WU=`AppRun`,GU=`.DirIcon`,KU=[`.png`,`.svg`]});function dmgVolumeName(t){let n=t.name;if(n.trim()===``)throw Error("gjsify ship: the macOS image has no name to call its volume — `gjsify.ship.name` (or the package name it is derived from) is empty. `hdiutil` would accept that and mount the image as `untitled`, which is the name every nameless disk image on the machine has.");if(YU.test(n))throw Error(`gjsify ship: the macOS image would mount a volume called "${n}", and HFS+ cannot hold it: the Finder shows a stored ":" as a "/" and a stored "/" as a ":", so the volume would not be the one this project named. Set \`gjsify.ship.name\` to the display name you want.`);return n}function hdiutilCreateArgs(t){return[`create`,`-format`,`UDZO`,`-fs`,`HFS+J`,`-volname`,t.volumeName,`-srcfolder`,t.sourceDir,`-ov`,`-quiet`,t.target]}async function buildDmgImage(t){let n=hdiutilCreateArgs(t);t.verbose&&ge.log(`[gjsify ship] ${JU} ${n.join(` `)}`);let S=await spawnToCompletion(JU,n,{completion:`return`,cwd:t.workDir,stdio:`inherit`,notFound:()=>Error(`gjsify ship: ${JU} is not on PATH. It ships with macOS and cannot be installed anywhere else, so this is either a broken macOS installation or a host that is not macOS at all. A \`.dmg\` is packed on darwin (ADR 0024 § A1); from anywhere else the route is \`gjsify ship darwin --stage\` here and \`gjsify ship --from-stage <dir> --target macos-app-dmg\` there.`)});if(S.code!==0)throw Error(`gjsify ship: ${JU} failed with ${describeExit(S)}.`)}function dmgVolumeDir(t){return In(t,`dmg`,`volume`)}function addApplicationsLink(t){symlinkSync(XU.target,In(t,XU.name))}function codesignDmgArgs(t){return[`--force`,`--sign`,t.identity,...t.adhoc?[]:[`--timestamp`],t.file]}async function signDmgImage(t){let n=codesignDmgArgs(t);t.verbose&&ge.log(`[gjsify ship] ${ZU} ${n.join(` `)}`);let S=await spawnToCompletion(ZU,n,{completion:`return`,cwd:t.workDir,stdio:`inherit`,notFound:()=>Error(`gjsify ship: ${ZU} is not on PATH, so the image cannot be signed. Install the Xcode Command Line Tools (\`xcode-select --install\`).`)});if(S.code!==0)throw Error(`gjsify ship: ${ZU} failed on the image with ${describeExit(S)}.`)}async function stapleBundleBeforeImage(t){t.writeArchive(),await t.notarize(),await t.staple()}var JU,YU,XU,ZU,QU=__esmMin(()=>{_e(),ef(),qn(),sv(),JU=`hdiutil`,YU=/[/:]/,XU={name:`Applications`,target:`/Applications`},ZU=`codesign`});function renderShipFlatpakManifest(t){let{settings:n,stageDir:S,overlayDir:C}=t,N=n.flatpak,F={id:n.appId,runtime:N.runtime,"runtime-version":N.runtimeVersion,sdk:N.sdk,branch:N.branch,command:n.binaryName,"finish-args":N.finishArgs};return N.sdkExtensions.length>0&&(F[`sdk-extensions`]=N.sdkExtensions),N.appendPath.length>0&&(F[`build-options`]={"append-path":N.appendPath.join(`:`)}),N.cleanup.length>0&&(F.cleanup=N.cleanup),F.modules=[{name:n.binaryName,buildsystem:`simple`,"build-commands":[`mkdir -p /app`,`cp -a stage/. /app/`,`cp -a overlay/. /app/`],sources:[{type:`dir`,path:S,dest:`stage`,skip:[t.stageManifestFile]},{type:`dir`,path:C,dest:`overlay`}]}],F}async function buildFlatpakBundle(t){let{settings:n,workDir:S,archLabel:C}=t,N=In(S,`${n.appId}.json`),F=In(S,`build`),I=In(S,`repo`),H=In(S,`state`);mkdirSync(S,{recursive:!0}),rmSync(I,{recursive:!0,force:!0,maxRetries:5}),writeFileSync(N,`${JSON.stringify(renderShipFlatpakManifest(t),null,2)}\n`),await run$1(`flatpak-builder`,[`--force-clean`,`--disable-rofiles-fuse`,`--delete-build-dirs`,`--state-dir=${H}`,`--arch=${C}`,`--repo=${I}`,F,N],t,"flatpak-builder not found. Install it (Fedora: `sudo dnf install flatpak-builder`)."),await run$1(`flatpak`,[`build-bundle`,`--arch=${C}`,I,t.target,n.appId,n.flatpak.branch],t,`flatpak not found. Install it via your distro: see https://flathub.org/setup.`)}async function run$1(t,n,S,C){S.verbose&&ge.log(`[gjsify ship] ${t} ${n.join(` `)}`);let N=await spawnToCompletion(t,n,{completion:`return`,cwd:S.workDir,stdio:`inherit`,notFound:()=>Error(`gjsify ship: ${C}`)});if(N.code!==0)throw Error(`gjsify ship: ${t} failed with ${describeExit(N)}.`)}var $U=__esmMin(()=>{_e(),ef(),qn(),sv(),__name$1(run$1,`run`)});function localeOf(t){return t.split(`/`)[0]??``}function fold(t,n,S,C,N){let F=In(N,`source${S}`);return writeFileSync(F,n),readFileSync(mergeCatalogues({mode:t,template:F,extension:S,catalogues:C,workDir:N}),`utf-8`)}function localizeMetadata(t,n){if(n.length===0)return t;let S=mkdtempSync(In(tmpdir(),`gjsify-ship-l10n-`));try{let C=[...n].sort((t,n)=>t.rel<n.rel?-1:+(t.rel>n.rel)),N=new Map;for(let[t,n]of C.entries()){let C=In(S,`${t}.po`);execFileSync(`msgunfmt`,[n.abs,`--output-file`,C],{stdio:`pipe`});let F=localeOf(n.rel);N.set(F,[...N.get(F)??[],C])}let F=[...N].map(([t,n])=>({locale:t,po:n.length===1?n[0]:msgcat(n,In(S,`${t}.merged.po`))}));return{metainfo:fold(`--xml`,t.metainfo,`.metainfo.xml`,F,S),desktopEntry:t.desktopEntry===void 0?void 0:fold(`--desktop`,t.desktopEntry,`.desktop`,F,S)}}catch(t){throw Error(describeFailure(t,n.length))}finally{rmSync(S,{recursive:!0,force:!0})}}function msgcat(t,n){return execFileSync(`msgcat`,[`--use-first`,`--output-file`,n,...t],{stdio:`pipe`}),n}function describeFailure(t,n){let S=t;return S?.code===`ENOENT`?`gjsify ship: \`msgfmt\`/\`msgunfmt\`/\`msgcat\` are not on PATH, but the package stages ${n} gettext catalogue(s). Install them (package: gettext) — shipping the metadata untranslated would install an English app menu entry for a translated app, which nothing downstream can detect.`:`gjsify ship: could not fold the gettext catalogues into the freedesktop metadata.${S?.stderr===void 0?``:`\n${String(S.stderr).trim()}`}`}var eW=__esmMin(()=>{ev(),ef(),$g(),qn(),zB()});function lookupArch(t,n,S){let C=t[n];if(!C)throw Error(`gjsify ship: no ${S} architecture is known for \`process.arch\` "${n}". Known: ${Object.keys(t).join(`, `)}.`);return C}function debArch(t,n){return n?`all`:lookupArch(tW,t,`Debian`)}function rpmArch(t,n){return n?`noarch`:lookupArch(nW,t,`RPM`)}function flatpakArch(t,n){return lookupArch(rW,t,`Flatpak`)}function appImageArch(t,n){return lookupArch(iW,t,`AppImage`)}function macosArch(t,n){return lookupArch(aW,t,`macOS`)}function windowsArch(t,n){return lookupArch(oW,t,`Windows`)}function windowsNameIsUnusable(t){return sW.test(t)||cW.test(t)||/[. ]$/.test(t)?!0:[...t].some(t=>(t.codePointAt(0)??0)<32)}function windowsProgramDirName(t){let n=t.name;if(n.trim()===``)throw Error("gjsify ship: the windows layout has no name to call the program directory — `gjsify.ship.name` (or the package name it is derived from) is empty. The artifact IS a directory and its zip expands into one, so an empty name would unpack `app\\`, `share\\` and the launcher loose into whatever folder the user was in.");if(windowsNameIsUnusable(n))throw Error(`gjsify ship: the windows layout would put this app in a directory called "${n}", and Windows cannot hold it: it reserves < > : " / \\ | ? * and the control characters, reserves CON, PRN, AUX, NUL, COM1-9 and LPT1-9 as device names at every path, and silently strips a trailing dot or space.
1177
1177
  The artifact would assemble here and be unextractable — or extract under a different name than
1178
- the launcher resolves against. Set \`gjsify.ship.name\` to the display name you want on disk.`);return n}function requiredToolsOn(t,n){return Array.isArray(t)?t:t[n]??[]}function defaultFormatIds(t){return fW.filter(n=>dW[n].layoutOs===t&&dW[n].host.finishOn===`any`)}function formatIdsFor(t){return fW.filter(n=>dW[n].layoutOs===t)}function assertHostCanFinish(t,n=process.platform){let{finishOn:S}=t.host;if(!(S===`any`||S.includes(n)))throw Error(`gjsify ship: a ${t.id} artifact is packed on ${S.join(` or `)} and this host is ${n} (ADR 0024 § A1: a container is produced where its format's tool lives). Assembly is not host-bound, so the way across is the two-phase split: run \`gjsify ship --stage\` here, move \`ship/stage/\` to a ${S.join(`/`)} runner, and finish with \`gjsify ship --from-stage <dir> --target ${t.id}\`.`)}function assertToolsInstalled(t,n=isOnPath,S=process.platform){let C=requiredToolsOn(t.host.requiredTools,S),N=C.filter(t=>!n(t));if(N.length===0)return;let F=t.host.installHint;throw Error(`gjsify ship: packing a ${t.id} on ${S} needs ${C.join(` and `)}, and ${N.join(`, `)} ${N.length>1?`are`:`is`} not on PATH. ${F===void 0?`Install it`:`Install it (${F})`}, or drop this target — the other formats need no tools at all. \`gjsify ship --stage\` also works without ${N.join(`/`)}: the payload is assembled by this CLI and only the container needs them.`)}function parseFormatNames(t,n){let S=t.flatMap(t=>t.split(`,`)).map(t=>t.trim()).filter(t=>t.length>0),C=S.filter(t=>!Object.hasOwn(dW,t));if(C.length>0)throw Error(`gjsify ship: unknown target${C.length>1?`s`:``} ${C.join(`, `)} in ${n}. Known targets: ${fW.join(`, `)}.`);let N=[...new Set(S)].sort();if(N.length===0)throw Error(`gjsify ship: ${n} named no format. Known targets: ${fW.join(`, `)}.`);return N}function resolveFormats(t,n){let S=parseFormatNames(t,`--target`),C=S.filter(t=>dW[t].layoutOs!==n.os);if(C.length>0){let t=formatIdsFor(n.os),S=[...new Set(C.map(t=>dW[t].layoutOs))];throw Error(`gjsify ship: ${C.join(`, `)} ${C.length>1?`wrap`:`wraps`} the ${S.join(`/`)} layout and this run assembles the ${n.name} one. `+(t.length===0?`No format wraps the ${n.name} layout — \`gjsify ship ${n.name} --stage\` assembles it and stops.`:`Formats for this layout: ${t.join(`, `)}.`)+` To build ${C.join(`, `)}, name the layout each wraps: ${S.map(t=>`\`gjsify ship ${pW[t]??t} --target ${C.filter(n=>dW[n].layoutOs===t).join(`,`)}\``).join(`, `)}.`)}return S.map(t=>dW[t])}function configuredFormats(t,n){let S=parseFormatNames(t,"`gjsify.ship.targets`");return{formats:S.filter(t=>dW[t].layoutOs===n.os).map(t=>dW[t]),dropped:S.filter(t=>dW[t].layoutOs!==n.os)}}function assertKindCanPack(t,n){if(n===`app`)return;let S=t.filter(t=>t.requiresDesktopEntry);if(S.length!==0)throw Error(`gjsify ship: ${S.map(t=>t.id).join(`, `)} cannot package a \`kind: "cli"\` project — the container needs a desktop entry at its root and a CLI stages none by design. Set \`gjsify.ship.kind\` to "app" if this is a GUI application, or ship it as a \`.deb\`, an \`.rpm\` or a Flatpak, none of which need one.`)}function canCarryTicket(t){switch(t){case`macos-app`:case`macos-app-dmg`:return!0;case`macos-app-zip`:case`deb`:case`rpm`:case`flatpak`:case`appimage`:case`windows-dir`:case`windows-dir-zip`:case`msi`:return!1;default:throw Error(`gjsify ship: no ticket answer for format "${String(t)}".`)}}var eW,tW,nW,rW,iW,aW,oW,sW,cW,lW,uW,SHARE_LICENSE_DEST,WRITTEN_HERE,dW,fW,pW,mW=__esmMin(()=>{ZI(),KU(),ZU(),WH(),YH(),eW={x64:`amd64`,arm64:`arm64`,ia32:`i386`,arm:`armhf`,riscv64:`riscv64`,ppc64:`ppc64el`,s390x:`s390x`},tW={x64:`x86_64`,arm64:`aarch64`,ia32:`i686`,arm:`armv7hl`,riscv64:`riscv64`,ppc64:`ppc64le`,s390x:`s390x`},nW={x64:`x86_64`,arm64:`aarch64`,ia32:`i386`,arm:`arm`},rW={x64:`x86_64`,arm64:`aarch64`,ia32:`i686`,arm:`armhf`},iW={x64:`x86_64`,arm64:`arm64`},aW={x64:`x64`,arm64:`arm64`},oW=/[<>:"/\\|?*]/,sW=/^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|$)/i,cW=`a distro package declares its interpreter as a dependency instead of carrying one, and every distribution ships both`,lW='a `.app` a stranger downloads has to CARRY its interpreter, and there is no relocatable GJS to put in one — `packages/node-gi/scripts/build-gtk-runtime-darwin.mjs` records "GJS ships no relocation", which is why ADR 0024 § 4 derives Node on macOS and stage 7 is what would change it',uW="there is no GJS host on Windows at all (ADR 0024 § 4) — not a system one to depend on and not a relocatable one to carry — so a `--app gjs` payload cannot be shipped this way. That is why § 4 derives Node here, and why `@gjsify/node-runtime-win32-x64` exists",SHARE_LICENSE_DEST=t=>`share/licenses/${t}/LICENSE`,WRITTEN_HERE=t=>({finishOn:`any`,requiredTools:[],oracle:{readWith:t,readOn:[`linux`],selfReading:!1}}),dW={deb:{id:`deb`,layoutOs:`linux`,prefix:`/usr`,host:WRITTEN_HERE([`ar`,`tar`,`dpkg-deb`,`lintian`]),depends:`deb`,interpreters:[`gjs`,`node`],interpreterGap:cW,licenseDest:t=>`share/doc/${t}/copyright`,licenseKind:`debian-copyright`,changelogDest:t=>`share/doc/${t}/changelog.Debian.gz`,archName:debArch,fileName:(t,n)=>`${t.binaryName}_${t.version}-${t.release}_${n}.deb`,artifactKind:`file`},rpm:{id:`rpm`,layoutOs:`linux`,prefix:`/usr`,host:WRITTEN_HERE([`rpm`,`rpm2cpio`,`cpio`]),depends:`rpm`,interpreters:[`gjs`,`node`],interpreterGap:cW,licenseDest:SHARE_LICENSE_DEST,licenseKind:`plain`,archName:rpmArch,fileName:(t,n)=>`${t.binaryName}-${t.version}-${t.release}.${n}.rpm`,artifactKind:`file`},flatpak:{id:`flatpak`,layoutOs:`linux`,prefix:`/app`,host:{finishOn:[`linux`],requiredTools:[`flatpak-builder`,`flatpak`],installHint:"Fedora: `sudo dnf install flatpak flatpak-builder`, Debian/Ubuntu: `sudo apt install flatpak flatpak-builder`",oracle:{readWith:[`flatpak`,`ostree`],readOn:[`linux`],selfReading:!1}},depends:null,interpreters:[`gjs`],interpreterGap:"a Flatpak runs against `org.gnome.Platform`, which ships `gjs` and no `node`. Node exists only as `org.freedesktop.Sdk.Extension.node2x`, and that extension puts node on the BUILD path, not in the runtime — so the artifact would install and then fail at `exec node`",licenseDest:SHARE_LICENSE_DEST,licenseKind:`plain`,archName:flatpakArch,fileName:(t,n)=>`${t.appId}-${t.version}-${t.release}.${n}.flatpak`,artifactKind:`file`},appimage:{id:`appimage`,layoutOs:`linux`,prefix:`/usr`,host:{finishOn:[`linux`],requiredTools:[RU,KH],installHint:`no distribution packages appimagetool — take the release from https://github.com/AppImage/appimagetool/releases, \`chmod +x\` it and put it on PATH as \`appimagetool\`; or assemble here with \`gjsify ship linux --stage\` and pack where it is. The schema compiler is packaged: ${qH}`,oracle:{readWith:[`python3`,`unsquashfs`],readOn:[`linux`],selfReading:!1}},depends:null,interpreters:[`gjs`,`node`],interpreterGap:"an AppImage carries the application and takes its interpreter from the host, exactly as a distro package does — but with no dependency field to declare it in, so the requirement is printed at pack time and checked by `AppRun` at launch instead",licenseDest:SHARE_LICENSE_DEST,licenseKind:`plain`,archName:appImageArch,fileName:(t,n)=>`${t.binaryName}-${t.version}-${t.release}.${n}.AppImage`,artifactKind:`file`,requiresDesktopEntry:!0},"macos-app":{id:`macos-app`,layoutOs:`darwin`,prefix:``,host:{finishOn:`any`,requiredTools:[KH],installHint:qH,oracle:{readWith:[`python3`],readOn:[`linux`,`darwin`],selfReading:!1}},depends:null,interpreters:[`node`],interpreterGap:lW,licenseDest:SHARE_LICENSE_DEST,licenseKind:`plain`,archName:macosArch,fileName:t=>`${t.name}.app`,artifactKind:`directory`},"macos-app-zip":{id:`macos-app-zip`,layoutOs:`darwin`,prefix:``,host:{finishOn:`any`,requiredTools:[KH],installHint:qH,oracle:{readWith:[`zipinfo`],readOn:[`linux`,`darwin`],selfReading:!1}},depends:null,interpreters:[`node`],interpreterGap:lW,licenseDest:SHARE_LICENSE_DEST,licenseKind:`plain`,archName:macosArch,fileName:(t,n)=>`${t.binaryName}-${t.version}-${t.release}.macos.${n}.zip`,artifactKind:`file`},"macos-app-dmg":{id:`macos-app-dmg`,layoutOs:`darwin`,prefix:``,host:{finishOn:[`darwin`],requiredTools:[qU],installHint:"`hdiutil` is part of macOS and cannot be installed elsewhere — on a Mac it is /usr/bin/hdiutil, so an absent one means a broken installation rather than a missing package",oracle:{readWith:[`7z`,`dmg2img`,`fsck.hfsplus`],readOn:[`linux`],selfReading:!1}},depends:null,interpreters:[`node`],interpreterGap:lW,licenseDest:SHARE_LICENSE_DEST,licenseKind:`plain`,archName:macosArch,fileName:(t,n)=>`${t.binaryName}-${t.version}-${t.release}.${n}.dmg`,artifactKind:`file`},"windows-dir":{id:`windows-dir`,layoutOs:`win32`,prefix:``,host:{finishOn:`any`,requiredTools:[KH],installHint:qH,oracle:{readWith:[`cmd`,`python3`],readOn:[`linux`,`win32`],selfReading:!1}},depends:null,interpreters:[`node`],interpreterGap:uW,licenseDest:SHARE_LICENSE_DEST,licenseKind:`plain`,archName:windowsArch,fileName:t=>windowsProgramDirName(t),artifactKind:`directory`},"windows-dir-zip":{id:`windows-dir-zip`,layoutOs:`win32`,prefix:``,host:{finishOn:`any`,requiredTools:[KH],installHint:qH,oracle:{readWith:[`zipinfo`],readOn:[`linux`,`darwin`],selfReading:!1}},depends:null,interpreters:[`node`],interpreterGap:uW,licenseDest:SHARE_LICENSE_DEST,licenseKind:`plain`,archName:windowsArch,fileName:(t,n)=>`${t.binaryName}-${t.version}-${t.release}.windows.${n}.zip`,artifactKind:`file`},msi:{id:`msi`,layoutOs:`win32`,prefix:``,host:{finishOn:[`linux`,`win32`],requiredTools:{linux:[KH,`wixl`],win32:[KH,`candle.exe`,`light.exe`]},installHint:`${qH}; the MSI compiler is Fedora: \`sudo dnf install msitools\`, Debian/Ubuntu: \`sudo apt install msitools\`, Windows: WiX Toolset v3.14 (https://github.com/wixtoolset/wix3/releases) with its \`bin\` directory on PATH`,oracle:{readWith:[`msiexec`,`msiinfo`],readOn:[`win32`,`linux`],selfReading:!1}},depends:null,interpreters:[`node`],interpreterGap:uW,licenseDest:SHARE_LICENSE_DEST,licenseKind:`plain`,archName:windowsArch,fileName:(t,n)=>`${t.binaryName}-${t.version}-${t.release}.${n}.msi`,artifactKind:`file`}},fW=Object.keys(dW),pW=Object.fromEntries(HH.map(t=>[VH[t].os,t]))});function uuid5(t,n){let S=t.replace(/-/g,``),C=new Uint8Array(16);for(let t=0;t<16;t+=1)C[t]=Number.parseInt(S.slice(t*2,t*2+2),16);let N=createHash(`sha1`).update(C).update(new TextEncoder().encode(n)).digest(),F=Uint8Array.from(N.subarray(0,16));F[6]=(F[6]??0)&15|80,F[8]=(F[8]??0)&63|128;let I=[...F].map(t=>t.toString(16).padStart(2,`0`)).join(``);return[I.slice(0,8),I.slice(8,12),I.slice(12,16),I.slice(16,20),I.slice(20)].join(`-`)}function msiUpgradeCode(t){return uuid5(hW,`upgrade\n${t.appId}`).toUpperCase()}function msiProductCode(t,n){let S=`product\n${t.appId}\n${t.version}\n${t.release}\n${n}`;return uuid5(hW,S).toUpperCase()}function msiComponentGuid(t,n){return uuid5(hW,`component\n${t.appId}\n${n}`).toUpperCase()}function msiProductVersion(t){let n=/^(\d+)\.(\d+)(?:\.(\d+))?$/.exec(t);if(n===null)throw Error(`gjsify ship: "${t}" is not a version an \`.msi\` can carry. Windows Installer's \`ProductVersion\` is \`major.minor.build\` and nothing else — no prerelease suffix, no build metadata.
1178
+ the launcher resolves against. Set \`gjsify.ship.name\` to the display name you want on disk.`);return n}function requiredToolsOn(t,n){return Array.isArray(t)?t:t[n]??[]}function defaultFormatIds(t){return pW.filter(n=>fW[n].layoutOs===t&&fW[n].host.finishOn===`any`)}function formatIdsFor(t){return pW.filter(n=>fW[n].layoutOs===t)}function assertHostCanFinish(t,n=process.platform){let{finishOn:S}=t.host;if(!(S===`any`||S.includes(n)))throw Error(`gjsify ship: a ${t.id} artifact is packed on ${S.join(` or `)} and this host is ${n} (ADR 0024 § A1: a container is produced where its format's tool lives). Assembly is not host-bound, so the way across is the two-phase split: run \`gjsify ship --stage\` here, move \`ship/stage/\` to a ${S.join(`/`)} runner, and finish with \`gjsify ship --from-stage <dir> --target ${t.id}\`.`)}function assertToolsInstalled(t,n=isOnPath,S=process.platform){let C=requiredToolsOn(t.host.requiredTools,S),N=C.filter(t=>!n(t));if(N.length===0)return;let F=t.host.installHint;throw Error(`gjsify ship: packing a ${t.id} on ${S} needs ${C.join(` and `)}, and ${N.join(`, `)} ${N.length>1?`are`:`is`} not on PATH. ${F===void 0?`Install it`:`Install it (${F})`}, or drop this target — the other formats need no tools at all. \`gjsify ship --stage\` also works without ${N.join(`/`)}: the payload is assembled by this CLI and only the container needs them.`)}function parseFormatNames(t,n){let S=t.flatMap(t=>t.split(`,`)).map(t=>t.trim()).filter(t=>t.length>0),C=S.filter(t=>!Object.hasOwn(fW,t));if(C.length>0)throw Error(`gjsify ship: unknown target${C.length>1?`s`:``} ${C.join(`, `)} in ${n}. Known targets: ${pW.join(`, `)}.`);let N=[...new Set(S)].sort();if(N.length===0)throw Error(`gjsify ship: ${n} named no format. Known targets: ${pW.join(`, `)}.`);return N}function resolveFormats(t,n){let S=parseFormatNames(t,`--target`),C=S.filter(t=>fW[t].layoutOs!==n.os);if(C.length>0){let t=formatIdsFor(n.os),S=[...new Set(C.map(t=>fW[t].layoutOs))];throw Error(`gjsify ship: ${C.join(`, `)} ${C.length>1?`wrap`:`wraps`} the ${S.join(`/`)} layout and this run assembles the ${n.name} one. `+(t.length===0?`No format wraps the ${n.name} layout — \`gjsify ship ${n.name} --stage\` assembles it and stops.`:`Formats for this layout: ${t.join(`, `)}.`)+` To build ${C.join(`, `)}, name the layout each wraps: ${S.map(t=>`\`gjsify ship ${mW[t]??t} --target ${C.filter(n=>fW[n].layoutOs===t).join(`,`)}\``).join(`, `)}.`)}return S.map(t=>fW[t])}function configuredFormats(t,n){let S=parseFormatNames(t,"`gjsify.ship.targets`");return{formats:S.filter(t=>fW[t].layoutOs===n.os).map(t=>fW[t]),dropped:S.filter(t=>fW[t].layoutOs!==n.os)}}function assertKindCanPack(t,n){if(n===`app`)return;let S=t.filter(t=>t.requiresDesktopEntry);if(S.length!==0)throw Error(`gjsify ship: ${S.map(t=>t.id).join(`, `)} cannot package a \`kind: "cli"\` project — the container needs a desktop entry at its root and a CLI stages none by design. Set \`gjsify.ship.kind\` to "app" if this is a GUI application, or ship it as a \`.deb\`, an \`.rpm\` or a Flatpak, none of which need one.`)}function canCarryTicket(t){switch(t){case`macos-app`:case`macos-app-dmg`:return!0;case`macos-app-zip`:case`deb`:case`rpm`:case`flatpak`:case`appimage`:case`windows-dir`:case`windows-dir-zip`:case`msi`:return!1;default:throw Error(`gjsify ship: no ticket answer for format "${String(t)}".`)}}var tW,nW,rW,iW,aW,oW,sW,cW,lW,uW,dW,SHARE_LICENSE_DEST,WRITTEN_HERE,fW,pW,mW,hW=__esmMin(()=>{ZI(),qU(),QU(),GH(),XH(),tW={x64:`amd64`,arm64:`arm64`,ia32:`i386`,arm:`armhf`,riscv64:`riscv64`,ppc64:`ppc64el`,s390x:`s390x`},nW={x64:`x86_64`,arm64:`aarch64`,ia32:`i686`,arm:`armv7hl`,riscv64:`riscv64`,ppc64:`ppc64le`,s390x:`s390x`},rW={x64:`x86_64`,arm64:`aarch64`,ia32:`i386`,arm:`arm`},iW={x64:`x86_64`,arm64:`aarch64`,ia32:`i686`,arm:`armhf`},aW={x64:`x86_64`,arm64:`arm64`},oW={x64:`x64`,arm64:`arm64`},sW=/[<>:"/\\|?*]/,cW=/^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|$)/i,lW=`a distro package declares its interpreter as a dependency instead of carrying one, and every distribution ships both`,uW='a `.app` a stranger downloads has to CARRY its interpreter, and there is no relocatable GJS to put in one — `packages/node-gi/scripts/build-gtk-runtime-darwin.mjs` records "GJS ships no relocation", which is why ADR 0024 § 4 derives Node on macOS and stage 7 is what would change it',dW="there is no GJS host on Windows at all (ADR 0024 § 4) — not a system one to depend on and not a relocatable one to carry — so a `--app gjs` payload cannot be shipped this way. That is why § 4 derives Node here, and why `@gjsify/node-runtime-win32-x64` exists",SHARE_LICENSE_DEST=t=>`share/licenses/${t}/LICENSE`,WRITTEN_HERE=t=>({finishOn:`any`,requiredTools:[],oracle:{readWith:t,readOn:[`linux`],selfReading:!1}}),fW={deb:{id:`deb`,layoutOs:`linux`,prefix:`/usr`,host:WRITTEN_HERE([`ar`,`tar`,`dpkg-deb`,`lintian`]),depends:`deb`,interpreters:[`gjs`,`node`],interpreterGap:lW,licenseDest:t=>`share/doc/${t}/copyright`,licenseKind:`debian-copyright`,changelogDest:t=>`share/doc/${t}/changelog.Debian.gz`,archName:debArch,fileName:(t,n)=>`${t.binaryName}_${t.version}-${t.release}_${n}.deb`,artifactKind:`file`},rpm:{id:`rpm`,layoutOs:`linux`,prefix:`/usr`,host:WRITTEN_HERE([`rpm`,`rpm2cpio`,`cpio`]),depends:`rpm`,interpreters:[`gjs`,`node`],interpreterGap:lW,licenseDest:SHARE_LICENSE_DEST,licenseKind:`plain`,archName:rpmArch,fileName:(t,n)=>`${t.binaryName}-${t.version}-${t.release}.${n}.rpm`,artifactKind:`file`},flatpak:{id:`flatpak`,layoutOs:`linux`,prefix:`/app`,host:{finishOn:[`linux`],requiredTools:[`flatpak-builder`,`flatpak`],installHint:"Fedora: `sudo dnf install flatpak flatpak-builder`, Debian/Ubuntu: `sudo apt install flatpak flatpak-builder`",oracle:{readWith:[`flatpak`,`ostree`],readOn:[`linux`],selfReading:!1}},depends:null,interpreters:[`gjs`],interpreterGap:"a Flatpak runs against `org.gnome.Platform`, which ships `gjs` and no `node`. Node exists only as `org.freedesktop.Sdk.Extension.node2x`, and that extension puts node on the BUILD path, not in the runtime — so the artifact would install and then fail at `exec node`",licenseDest:SHARE_LICENSE_DEST,licenseKind:`plain`,archName:flatpakArch,fileName:(t,n)=>`${t.appId}-${t.version}-${t.release}.${n}.flatpak`,artifactKind:`file`},appimage:{id:`appimage`,layoutOs:`linux`,prefix:`/usr`,host:{finishOn:[`linux`],requiredTools:[zU,qH],installHint:`no distribution packages appimagetool — take the release from https://github.com/AppImage/appimagetool/releases, \`chmod +x\` it and put it on PATH as \`appimagetool\`; or assemble here with \`gjsify ship linux --stage\` and pack where it is. The schema compiler is packaged: ${JH}`,oracle:{readWith:[`python3`,`unsquashfs`],readOn:[`linux`],selfReading:!1}},depends:null,interpreters:[`gjs`,`node`],interpreterGap:"an AppImage carries the application and takes its interpreter from the host, exactly as a distro package does — but with no dependency field to declare it in, so the requirement is printed at pack time and checked by `AppRun` at launch instead",licenseDest:SHARE_LICENSE_DEST,licenseKind:`plain`,archName:appImageArch,fileName:(t,n)=>`${t.binaryName}-${t.version}-${t.release}.${n}.AppImage`,artifactKind:`file`,requiresDesktopEntry:!0},"macos-app":{id:`macos-app`,layoutOs:`darwin`,prefix:``,host:{finishOn:`any`,requiredTools:[qH],installHint:JH,oracle:{readWith:[`python3`],readOn:[`linux`,`darwin`],selfReading:!1}},depends:null,interpreters:[`node`],interpreterGap:uW,licenseDest:SHARE_LICENSE_DEST,licenseKind:`plain`,archName:macosArch,fileName:t=>`${t.name}.app`,artifactKind:`directory`},"macos-app-zip":{id:`macos-app-zip`,layoutOs:`darwin`,prefix:``,host:{finishOn:`any`,requiredTools:[qH],installHint:JH,oracle:{readWith:[`zipinfo`],readOn:[`linux`,`darwin`],selfReading:!1}},depends:null,interpreters:[`node`],interpreterGap:uW,licenseDest:SHARE_LICENSE_DEST,licenseKind:`plain`,archName:macosArch,fileName:(t,n)=>`${t.binaryName}-${t.version}-${t.release}.macos.${n}.zip`,artifactKind:`file`},"macos-app-dmg":{id:`macos-app-dmg`,layoutOs:`darwin`,prefix:``,host:{finishOn:[`darwin`],requiredTools:[JU],installHint:"`hdiutil` is part of macOS and cannot be installed elsewhere — on a Mac it is /usr/bin/hdiutil, so an absent one means a broken installation rather than a missing package",oracle:{readWith:[`7z`,`dmg2img`,`fsck.hfsplus`],readOn:[`linux`],selfReading:!1}},depends:null,interpreters:[`node`],interpreterGap:uW,licenseDest:SHARE_LICENSE_DEST,licenseKind:`plain`,archName:macosArch,fileName:(t,n)=>`${t.binaryName}-${t.version}-${t.release}.${n}.dmg`,artifactKind:`file`},"windows-dir":{id:`windows-dir`,layoutOs:`win32`,prefix:``,host:{finishOn:`any`,requiredTools:[qH],installHint:JH,oracle:{readWith:[`cmd`,`python3`],readOn:[`linux`,`win32`],selfReading:!1}},depends:null,interpreters:[`node`],interpreterGap:dW,licenseDest:SHARE_LICENSE_DEST,licenseKind:`plain`,archName:windowsArch,fileName:t=>windowsProgramDirName(t),artifactKind:`directory`},"windows-dir-zip":{id:`windows-dir-zip`,layoutOs:`win32`,prefix:``,host:{finishOn:`any`,requiredTools:[qH],installHint:JH,oracle:{readWith:[`zipinfo`],readOn:[`linux`,`darwin`],selfReading:!1}},depends:null,interpreters:[`node`],interpreterGap:dW,licenseDest:SHARE_LICENSE_DEST,licenseKind:`plain`,archName:windowsArch,fileName:(t,n)=>`${t.binaryName}-${t.version}-${t.release}.windows.${n}.zip`,artifactKind:`file`},msi:{id:`msi`,layoutOs:`win32`,prefix:``,host:{finishOn:[`linux`,`win32`],requiredTools:{linux:[qH,`wixl`],win32:[qH,`candle.exe`,`light.exe`]},installHint:`${JH}; the MSI compiler is Fedora: \`sudo dnf install msitools\`, Debian/Ubuntu: \`sudo apt install msitools\`, Windows: WiX Toolset v3.14 (https://github.com/wixtoolset/wix3/releases) with its \`bin\` directory on PATH`,oracle:{readWith:[`msiexec`,`msiinfo`],readOn:[`win32`,`linux`],selfReading:!1}},depends:null,interpreters:[`node`],interpreterGap:dW,licenseDest:SHARE_LICENSE_DEST,licenseKind:`plain`,archName:windowsArch,fileName:(t,n)=>`${t.binaryName}-${t.version}-${t.release}.${n}.msi`,artifactKind:`file`}},pW=Object.keys(fW),mW=Object.fromEntries(UH.map(t=>[HH[t].os,t]))});function uuid5(t,n){let S=t.replace(/-/g,``),C=new Uint8Array(16);for(let t=0;t<16;t+=1)C[t]=Number.parseInt(S.slice(t*2,t*2+2),16);let N=createHash(`sha1`).update(C).update(new TextEncoder().encode(n)).digest(),F=Uint8Array.from(N.subarray(0,16));F[6]=(F[6]??0)&15|80,F[8]=(F[8]??0)&63|128;let I=[...F].map(t=>t.toString(16).padStart(2,`0`)).join(``);return[I.slice(0,8),I.slice(8,12),I.slice(12,16),I.slice(16,20),I.slice(20)].join(`-`)}function msiUpgradeCode(t){return uuid5(gW,`upgrade\n${t.appId}`).toUpperCase()}function msiProductCode(t,n){let S=`product\n${t.appId}\n${t.version}\n${t.release}\n${n}`;return uuid5(gW,S).toUpperCase()}function msiComponentGuid(t,n){return uuid5(gW,`component\n${t.appId}\n${n}`).toUpperCase()}function msiProductVersion(t){let n=/^(\d+)\.(\d+)(?:\.(\d+))?$/.exec(t);if(n===null)throw Error(`gjsify ship: "${t}" is not a version an \`.msi\` can carry. Windows Installer's \`ProductVersion\` is \`major.minor.build\` and nothing else — no prerelease suffix, no build metadata.
1179
1179
  Dropping the suffix is not an option this command will take silently: \`1.2.0~rc.1\` and \`1.2.0\` would
1180
1180
  become the same version, \`MajorUpgrade\` could not tell them apart, and installing one over the other
1181
1181
  would leave both on the machine. Set \`gjsify.ship.version\` to a plain \`x.y.z\`, or drop \`msi\` from the targets.`);let[S,C,N]=[Number(n[1]),Number(n[2]),Number(n[3]??`0`)];if(S>255||C>255||N>65535)throw Error(`gjsify ship: version "${t}" is outside what Windows Installer compares — \`major\` and \`minor\` are at most 255 and \`build\` at most 65535. A field over the limit is not rejected by the installer, it is
1182
- TRUNCATED, so the artifact would carry a version that is not the one it was built from. Set \`gjsify.ship.version\`.`);return`${S}.${C}.${N}`}function msiIdentifier(t,n,S=``){let C=createHash(`sha1`).update(new TextEncoder().encode(n)).digest(`hex`).slice(0,12),N=n.replace(/[^A-Za-z0-9_.]/g,`_`),F=72-t.length-2-C.length-S.length;return`${t}_${N.length>F?N.slice(N.length-F):N}_${C}${S}`}function assertNameIsAddressable(t,n){if(t===`.`||t===`..`||t.length===0||gW.test(t))throw Error(`gjsify ship: the payload holds "${n}", and Windows Installer cannot address the path segment "${t}". A \`FileName\` or \`DefaultDir\` cell reserves < > : " / \\ | ? * and ; (its own list separator), and
1182
+ TRUNCATED, so the artifact would carry a version that is not the one it was built from. Set \`gjsify.ship.version\`.`);return`${S}.${C}.${N}`}function msiIdentifier(t,n,S=``){let C=createHash(`sha1`).update(new TextEncoder().encode(n)).digest(`hex`).slice(0,12),N=n.replace(/[^A-Za-z0-9_.]/g,`_`),F=72-t.length-2-C.length-S.length;return`${t}_${N.length>F?N.slice(N.length-F):N}_${C}${S}`}function assertNameIsAddressable(t,n){if(t===`.`||t===`..`||t.length===0||_W.test(t))throw Error(`gjsify ship: the payload holds "${n}", and Windows Installer cannot address the path segment "${t}". A \`FileName\` or \`DefaultDir\` cell reserves < > : " / \\ | ? * and ; (its own list separator), and
1183
1183
  \`.\` and \`..\` are not names. The \`.msi\` would build and install the file somewhere else, or not at all.`);if(t.length>255)throw Error(`gjsify ship: the payload holds "${n}", whose segment "${t.slice(0,40)}…" is ${t.length} characters. Windows Installer's \`FileName\` column is 255.`)}function directoryTree(t){let n={path:``,name:``,children:new Map,files:[]};for(let S of[...t].sort((t,n)=>t.path<n.path?-1:+(t.path>n.path))){let t=S.path.split(`/`),C=t.pop();if(C===void 0)throw Error(`gjsify ship: the payload holds an empty path.`);let N=n;for(let n of t){assertNameIsAddressable(n,S.path);let t=N.children.get(n)??{path:N.path===``?n:`${N.path}/${n}`,name:n,children:new Map,files:[]};N.children.set(n,t),N=t}assertNameIsAddressable(C,S.path),N.files.push(S)}return n}function renderWxs(t){let{settings:n,programDirName:S,archLabel:C}=t,N=C!==`x86`,F=msiProductVersion(n.version),I=n.maintainer.replace(/\s*<[^>]*>\s*$/,``).trim()||n.maintainer,H=windowsGuiLauncherPath(n),W=new Map,claim=(t,n)=>{let S=W.get(t);if(S!==void 0)throw Error(`gjsify ship: the MSI identifier "${t}" would be shared by ${S} and ${n}. Two rows cannot carry one id — one would silently replace the other.`);return W.set(t,n),t},q=claim(msiIdentifier(`i`,H,`.exe`),`the launcher icon`),Y=[],X=[],Z=!1,te,emitDir=(t,S)=>{for(let C of t.files){let t=claim(msiIdentifier(`c`,C.path),C.path),F=claim(msiIdentifier(`f`,C.path),C.path);X.push(t);let I=msiComponentGuid(n,C.path),W=xmlEscape(Tn.basename(C.path));Y.push(`${S}<Component Id="${t}" Guid="${I}" Win64="${N?`yes`:`no`}">`),C.path===H?(Z=!0,te=C.source,Y.push(`${S} <File Id="${F}" Name="${W}" Source="${xmlEscape(C.source)}" KeyPath="yes">`),Y.push(`${S} <Shortcut Id="${claim(`s_startmenu`,`the Start-Menu shortcut`)}" Directory="ProgramMenuFolder" Name="${xmlEscape(n.name)}" WorkingDirectory="INSTALLDIR" Description="${xmlEscape(n.summary)}" Icon="${q}" IconIndex="0" Advertise="yes" />`),Y.push(`${S} </File>`)):Y.push(`${S} <File Id="${F}" Name="${W}" Source="${xmlEscape(C.source)}" KeyPath="yes" />`),Y.push(`${S}</Component>`)}for(let n of[...t.children.values()].sort((t,n)=>t.name<n.name?-1:1)){let t=claim(msiIdentifier(`d`,n.path),`the directory ${n.path}`);Y.push(`${S}<Directory Id="${t}" Name="${xmlEscape(n.name)}">`),emitDir(n,`${S} `),Y.push(`${S}</Directory>`)}};if(emitDir(directoryTree(t.files),` `),X.length===0)throw Error("gjsify ship: the windows payload is empty, so there is nothing for an `.msi` to install.");if(!Z||te===void 0)throw Error(`gjsify ship: the windows payload carries no "${H}" at the root of the program directory, so the installer would have nothing to point a Start-Menu shortcut at — an application a user installs and
1184
1184
  cannot start. \`windows-dir\` puts the launcher there; a payload without one is a stage assembled for another layout.`);let ne=n.homepage===void 0?[]:[` <Property Id="ARPURLINFOABOUT" Value="${xmlEscape(n.homepage)}" />`];return[`<?xml version="1.0" encoding="utf-8"?>`,"<!-- Generated by `gjsify ship` (ADR 0024 stage 5). Do not edit; edit utils/ship/msi.ts. -->",`<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">`,` <Product Id="${msiProductCode(n,C)}" Name="${xmlEscape(n.name)}" Language="1033" Version="${F}" Manufacturer="${xmlEscape(I)}" UpgradeCode="${msiUpgradeCode(n)}">`,` <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" Manufacturer="${xmlEscape(I)}" Description="${xmlEscape(n.summary)}" />`,` <MajorUpgrade DowngradeErrorMessage="A newer version of ${xmlEscape(n.name)} is already installed." />`,` <Media Id="1" Cabinet="app.cab" EmbedCab="yes" />`,` <Icon Id="${q}" SourceFile="${xmlEscape(te)}" />`,` <Property Id="ARPPRODUCTICON" Value="${q}" />`,...ne,` <Directory Id="TARGETDIR" Name="SourceDir">`,` <Directory Id="ProgramFiles64Folder">`,` <Directory Id="INSTALLDIR" Name="${xmlEscape(S)}">`,...Y,` <Component Id="AddToPathComponent" Guid="${msiComponentGuid(n,`:path`)}" Win64="${N?`yes`:`no`}">`,` <CreateFolder />`,` <Environment Id="GjsifyPath" Name="PATH" Action="set" Part="last" System="yes" Permanent="no" Value="[INSTALLDIR]" />`,` </Component>`,` </Directory>`,` </Directory>`,` <Directory Id="ProgramMenuFolder" />`,` </Directory>`,` <Feature Id="Main" Title="${xmlEscape(n.name)}" Level="1">`,...X.map(t=>` <ComponentRef Id="${t}" />`),` </Feature>`,` <Feature Id="AddToPath" Title="Add ${xmlEscape(n.name)} to PATH" Level="2">`,` <ComponentRef Id="AddToPathComponent" />`,` <Condition Level="1">ADDTOPATH=1</Condition>`,` </Feature>`,` </Product>`,`</Wix>`,``].join(`
1185
- `)}function msiBackendFor(t){if(t===`linux`)return`wixl`;if(t===`win32`)return`wix3`;throw Error(`gjsify ship: no MSI compiler is wired for ${t}. \`wixl\` (msitools) is used on linux and WiX v3 on win32; assembly is not host-bound, so \`gjsify ship windows --stage\` here and \`gjsify ship --from-stage <dir> --target msi\` there is the way across.`)}async function buildMsi(t){let n=msiBackendFor(t.host??process.platform);mkdirSync(t.workDir,{recursive:!0});let S=In(t.workDir,`${t.settings.binaryName}.wxs`);if(writeFileSync(S,renderWxs(t)),n===`wixl`)return await run(`wixl`,[`-a`,t.archLabel,`-o`,t.target,S],t),S;let C=In(t.workDir,`obj`);return rmSync(C,{recursive:!0,force:!0,maxRetries:5}),mkdirSync(C,{recursive:!0}),await run(`candle.exe`,[`-nologo`,`-arch`,t.archLabel,`-out`,`${C}\\`,S],t),await run(`light.exe`,[`-nologo`,`-out`,t.target,In(C,`${t.settings.binaryName}.wixobj`)],t),S}async function run(t,n,S){S.verbose&&ge.log(`[gjsify ship] ${t} ${n.join(` `)}`);let C=await spawnToCompletion(t,[...n],{completion:`return`,cwd:S.workDir,stdio:`inherit`,notFound:()=>Error(`gjsify ship: ${t} not found. It is the MSI compiler for this host — Fedora: \`sudo dnf install msitools\`, Debian/Ubuntu: \`sudo apt install msitools\`, Windows: WiX Toolset v3.14 with its \`bin\` directory on PATH.`)});if(C.code!==0)throw Error(`gjsify ship: ${t} failed with ${describeExit(C)}.`)}var hW,gW,_W,vW=__esmMin(()=>{_e(),fl(),ef(),qn(),sv(),WH(),sU(),hW=`7b3a1f6e-0c4d-4a2b-9e51-3d8c6f2a0b14`,gW=/[<>:"/\\|?*;]/,_W=`root`});function getCrcTable(){if(TW!==null)return TW;let t=new Uint32Array(256);for(let n=0;n<256;n++){let S=n;for(let t=0;t<8;t++)S=S&1?3988292384^S>>>1:S>>>1;t[n]=S>>>0}return TW=t,t}function crc32(t){let n=getCrcTable(),S=4294967295;for(let C=0;C<t.length;C++)S=n[(S^t[C])&255]^S>>>8;return(S^4294967295)>>>0}function dosDateTime(t){let n=new Date(Math.max(t,315532800)*1e3);return{date:(n.getUTCFullYear()-1980&127)<<9|n.getUTCMonth()+1<<5|n.getUTCDate(),time:n.getUTCHours()<<11|n.getUTCMinutes()<<5|Math.floor(n.getUTCSeconds()/2)}}function buildZip(t,n){let S=[...t].sort((t,n)=>t.path<n.path?-1:+(t.path>n.path)),{date:C,time:N}=dosDateTime(n),F=new TextEncoder;if(S.length>65535)throw Error(`gjsify ship: this archive would hold ${S.length} entries and a non-ZIP64 central directory records the count in 16 bits, so it would silently wrap. Nothing here writes ZIP64 yet; the payload has to shrink, or this writer has to grow the ZIP64 records.`);let I=new Writer,H=new Writer,W=0;for(let t of S){let n=F.encode(t.path),S=crc32(t.data),q=t.data.byteLength,Y=I.offset;if(Y>4294967295||q>4294967295)throw Error(`gjsify ship: ${t.path} would push this archive past 4 GiB, which a non-ZIP64 header records in 32 bits and therefore truncates. Nothing here writes ZIP64 yet.`);I.u32(yW),I.u16(wW),I.u16(2048),I.u16(SW),I.u16(N),I.u16(C),I.u32(S),I.u32(q),I.u32(q),I.u16(n.byteLength),I.u16(0),I.bytes(n),I.bytes(t.data),H.u32(bW),H.u16(CW),H.u16(wW),H.u16(2048),H.u16(SW),H.u16(N),H.u16(C),H.u32(S),H.u32(q),H.u32(q),H.u16(n.byteLength),H.u16(0),H.u16(0),H.u16(0),H.u16(0),H.u32(((32768|t.mode&4095)>>>0)*65536),H.u32(Y),H.bytes(n),W+=1}let q=H.finish(),Y=new Writer;Y.bytes(I.finish());let X=Y.offset;return Y.bytes(q),Y.u32(xW),Y.u16(0),Y.u16(0),Y.u16(W),Y.u16(W),Y.u32(q.byteLength),Y.u32(X),Y.u16(0),Y.finish()}function zipEntriesFromPayload(t,n=``){let S=n===``?``:`${n}/`;return t.map(t=>({path:`${S}${t.path}`,mode:t.mode,data:t.data}))}var yW,bW,xW,SW,CW,wW,TW,Writer,EW=__esmMin(()=>{yW=67324752,bW=33639248,xW=101010256,SW=0,CW=788,wW=20,TW=null,Writer=class{parts=[];length=0;get offset(){return this.length}u16(t){this.push(new Uint8Array([t&255,t>>>8&255]))}u32(t){this.push(new Uint8Array([t&255,t>>>8&255,t>>>16&255,t>>>24&255]))}bytes(t){this.push(t)}push(t){this.parts.push(t),this.length+=t.byteLength}finish(){let t=new Uint8Array(this.length),n=0;for(let S of this.parts)t.set(S,n),n+=S.byteLength;return t}}});function entryEvidence(t){let n=new Set,S=new Set;return walkModuleAst(t,t=>{let C=importedSpecifier(t);C!==null&&(C.startsWith(`gi://`)||DW.has(C)?n.add(C):C.startsWith(`node:`)&&t.type!==`ImportExpression`&&S.add(C))}),{gi:[...n].sort(),node:[...S].sort()}}function assertEntryRunsUnder(t){let n=entryEvidence(t.source),S=t.interpreter===`node`?n.gi:n.node;if(S.length===0)return;let C=t.interpreter===`node`?`gjs`:`node`,N=t.interpreter===`gjs`?`GJS's loader refuses it: ImportError, "Unsupported URI scheme for importing: node"`:S.some(t=>t.startsWith(`gi://`))?`node's ESM loader refuses it: ERR_UNSUPPORTED_ESM_URL_SCHEME, "Only URLs with a scheme in: file, data, and node are supported by the default ESM loader"`:`node's ESM loader refuses it: ERR_MODULE_NOT_FOUND — a GJS built-in is not a package`,F=S.slice(0,3).join(`, `),I=S.length>3?`, and ${S.length-3} more`:``;throw Error(`gjsify ship: this target execs \`${t.interpreter}\` (\`${t.appKey}\`), and the entry it would ship — ${t.entry} (\`${t.bundleKey}\`) — imports ${F}${I}.\n ${N}, before a line of application code runs.\n The artifact would be built, reported as built, and fail at launch on every machine.
1186
- Either ship this target the \`--app ${t.interpreter}\` build of the app — \`gjsify.ship.bundle.${t.layoutOs}\` selects the entry per target, the way \`gjsify.ship.app.${t.layoutOs}\` selects the runtime —\n or set \`gjsify.ship.app.${t.layoutOs}\` to "${C}" if this bundle is the one that should ship.`)}var DW,OW=__esmMin(()=>{QN(),DW=new Set([`system`,`gettext`])});function releaseRecordPath(t){return`${t}${kW}`}function recordedSignature(t,n){return t===void 0?{kind:`none`}:t===n?{kind:`adhoc`}:{kind:`identity`,identity:t}}function buildReleaseRecord(t){let n=readFileSync(t.file);return{schema:1,artifact:Bn(t.file),sha256:createHash(`sha256`).update(n).digest(`hex`),size:n.length,format:t.format,os:t.os,arch:t.arch,signature:t.signature,notarized:t.notarized,stapled:t.stapled,nestedBundles:t.nestedBundles,generator:t.generator}}function writeReleaseRecord(t){let n=releaseRecordPath(t.file);return writeFileSync(n,`${JSON.stringify(buildReleaseRecord(t),null,4)}\n`),n}var kW,AW=__esmMin(()=>{fl(),ef(),qn(),kW=`.gjsify-release.json`});function base64Encode(t){let n=``,S=32768;for(let C=0;C<t.length;C+=S)n+=String.fromCharCode(...t.subarray(C,C+S));return btoa(n)}function base64Decode(t){let n=atob(t),S=new Uint8Array(n.length);for(let t=0;t<n.length;t++)S[t]=n.charCodeAt(t);return S}var jW=__esmMin(()=>{});function toPackSettings(t){return{binaryName:t.binaryName,appId:t.appId,name:t.name,version:t.version,release:t.release,maintainer:t.maintainer,summary:t.summary,description:t.description,license:t.license,...t.homepage===void 0?{}:{homepage:t.homepage},section:t.section,group:t.group,extraDepends:t.extraDepends,typelibPackages:t.typelibPackages,app:t.app,minGjsVersion:t.minGjsVersion,minNodeVersion:t.minNodeVersion,flatpak:t.flatpak,executables:t.executables.map(({name:t,gui:n})=>({name:t,gui:n})),nestedBundles:t.nestedBundles.map(({name:t,entitlements:n})=>({name:t,entitlements:n})),helperExecutables:t.helperExecutables.map(({name:t,entitlements:n})=>({name:t,entitlements:n}))}}function stageManifestPath(t){return In(t,MW)}function formatTarget(t){return`${t.os}-${t.arch}`}function writeStageManifest(t){let n={};for(let S of t.formats)n[S.id]=(t.overlay.get(S.id)??[]).map(t=>{if(t.source.kind===`text`)return{path:t.path,mode:t.mode,text:t.source.text};if(t.source.kind===`bytes`)return{path:t.path,mode:t.mode,base64:base64Encode(t.source.data)};throw Error(`gjsify ship: internal error — the ${S.id} overlay entry ${t.path} is a file reference, and a stage manifest may only carry rendered bytes. Render it in \`planOverlay\` instead.`)});let S={schema:6,tool:{name:`@gjsify/cli`,version:cliVersion()},target:{os:t.settings.layoutOs,arch:t.settings.arch},formats:t.formats.map(t=>t.id),mtime:t.mtime,namespaces:[...t.namespaces],optionalNamespaces:[...t.optionalNamespaces??[]],settings:toPackSettings(t.settings),staged:t.staged.map(n=>({path:n.path,mode:n.mode,bytes:statSync(In(t.stageDir,n.path.split(`/`).join(Wn))).size})),overlay:n};return writeFileSync(stageManifestPath(t.stageDir),`${JSON.stringify(S,null,2)}\n`),S}function readStageManifest(t){let n=stageManifestPath(t);if(!existsSync(n))throw Error(`gjsify ship: ${t} has no ${MW}, so it is not a stage this command can pack. A stage is produced by \`gjsify ship --stage\`, which writes that file at the stage root beside the payload. If you pointed --from-stage at a project's \`ship/\` directory, point it at \`ship/stage/\` instead.`);let S;try{S=JSON.parse(readFileSync(n,`utf-8`))}catch(t){throw Error(`gjsify ship: ${n} is not readable JSON (${t.message}). Re-run the \`--stage\` phase; a truncated manifest means the stage transfer was truncated too.`)}if(typeof S!=`object`||!S||Array.isArray(S))throw Error(`gjsify ship: ${n} is not a JSON object. Re-run the \`--stage\` phase.`);let C=S,N=C.schema;if(typeof N!=`number`||!Number.isInteger(N))throw Error(`gjsify ship: ${n} has no integer \`schema\` field, so it was not written by \`gjsify ship --stage\`. Re-run the \`--stage\` phase.`);if(N>6)throw Error(`gjsify ship: ${n} declares schema ${N} and this gjsify understands 6. The stage was assembled by a newer gjsify: upgrade this one (\`gjsify self-update\`), or re-run the \`--stage\` phase with this version. A manifest from the future is refused rather than partially read, because an unknown field could be the one that decides a file's mode.`);if(N<6)throw Error(`gjsify ship: ${n} declares schema ${N} and this gjsify understands 6. Re-run the \`--stage\` phase with this gjsify. A stage is a short-lived intermediate between two jobs of one run, not an archive, so no migration is kept for it.`);let at=t=>`${n} → ${t}`,F=record(C.tool,at(`tool`)),I=record(C.target,at(`target`)),H={schema:N,tool:{name:expectString(F.name,at(`tool.name`)),version:expectString(F.version,at(`tool.version`))},target:{os:expectLayoutOs(expectString(I.os,at(`target.os`)),at(`target.os`)),arch:expectString(I.arch,at(`target.arch`))},formats:expectArray(C.formats,at(`formats`)).map((t,n)=>{let S=expectString(t,at(`formats[${n}]`));if(!fW.includes(S))throw Error(`gjsify ship: ${at(`formats[${n}]`)} is "${S}", which this gjsify does not know. Known formats: ${fW.join(`, `)}.`);return S}),mtime:expectInteger(C.mtime,at(`mtime`)),namespaces:expectArray(C.namespaces,at(`namespaces`)).map((t,n)=>expectString(t,at(`namespaces[${n}]`))),...C.optionalNamespaces===void 0?{}:{optionalNamespaces:expectArray(C.optionalNamespaces,at(`optionalNamespaces`)).map((t,n)=>expectString(t,at(`optionalNamespaces[${n}]`)))},settings:readPackSettings(record(C.settings,at(`settings`)),at(`settings`)),staged:expectArray(C.staged,at(`staged`)).map((t,n)=>{let S=record(t,at(`staged[${n}]`));return{path:expectString(S.path,at(`staged[${n}].path`)),mode:expectInteger(S.mode,at(`staged[${n}].mode`)),bytes:expectInteger(S.bytes,at(`staged[${n}].bytes`))}}),overlay:{}};if(H.staged.length===0)throw Error(`gjsify ship: ${at(`staged`)} is empty, so this stage describes no payload. A stage always carries at least the launcher its plan named. Re-run the \`--stage\` phase; a stage that lost its plan cannot be packed into anything but an empty package.`);let W=record(C.overlay,at(`overlay`));for(let t of H.formats)H.overlay[t]=expectArray(W[t],at(`overlay.${t}`)).map((n,S)=>{let C=record(n,at(`overlay.${t}[${S}]`)),N=at(`overlay.${t}[${S}]`);if(C.text===void 0==(C.base64===void 0))throw Error(`gjsify ship: ${N} must carry exactly one of \`text\` and \`base64\`. An overlay entry is either rendered text or rendered bytes; an entry with neither would pack an empty file at a path the format requires content at.`);return{path:expectString(C.path,at(`overlay.${t}[${S}].path`)),mode:expectInteger(C.mode,at(`overlay.${t}[${S}].mode`)),...C.text===void 0?{base64:expectString(C.base64,at(`overlay.${t}[${S}].base64`))}:{text:expectString(C.text,at(`overlay.${t}[${S}].text`))}}});return H}function expectLayoutOs(t,n){try{return layoutForOs(t).os}catch{let S=HH.map(t=>VH[t].os).join(`, `);throw Error(`gjsify ship: ${n} is "${t}", which is not a layout this gjsify can pack. It carries the \`process.platform\` spelling and only that — ${S}, so \`win32\` and never \`windows\`. A stage holds exactly one OS's layout and every path in it has that OS's shape, so there is nothing to pack here. Re-run the \`--stage\` phase.`)}}function overlayFiles(t,n){return(t.overlay[n]??[]).map(t=>({path:t.path,mode:t.mode,source:t.base64===void 0?{kind:`text`,text:t.text??``}:{kind:`bytes`,data:base64Decode(t.base64)}}))}function assertExpectedTarget(t,n){if(n===void 0)return;let S=formatTarget(t.target);if(n!==S)throw Error(`gjsify ship: --expect-target ${n} but this stage was assembled for ${S}. The stage records the target its \`--arch\` resolved to at stage time, so this is a stage from another matrix leg: download the artifact belonging to ${n}, or drop --expect-target if packing this one is what you meant.`)}function assertFormatsStaged(t,n){let S=n.filter(n=>!t.formats.includes(n.id)).map(t=>t.id);if(S.length!==0)throw Error(`gjsify ship: this stage was assembled for ${t.formats.length===0?`no format at all`:t.formats.join(`, `)}, and --target names ${S.join(`, `)}. Phase one renders each format's overlay — rpm wants the licence at \`share/licenses/<pkg>/LICENSE\`, deb wants a machine-readable copyright at \`share/doc/<pkg>/copyright\` — so a format the stage never saw would pack without it, and Debian Policy § 12.5 makes that a broken package. Re-run \`gjsify ship --stage --target ${[...t.formats,...S].join(`,`)}\` on the assembling host.`)}function resolveStageMtime(t,n=process.env){let S=n.SOURCE_DATE_EPOCH;return S===void 0||Number(S)===t.mtime?{mtime:t.mtime,warnings:[]}:{mtime:t.mtime,warnings:[`SOURCE_DATE_EPOCH is ${S} here and this stage was stamped ${t.mtime}. The stage's stamp wins, because changing it would make this artifact differ from the same stage packed on the assembling host. Set the same value in both jobs, or set it in neither.`]}}function warnOnToolSkew(t){let n=cliVersion();return t.tool.version===n?[]:[`this stage was assembled by ${t.tool.name} ${t.tool.version} and is being packed by ${n}. Both phases run the same packer, so a version difference can change the artifact's bytes. Pin both jobs to one gjsify version.`]}function readPackSettings(t,n){let field=t=>`${n}.${t}`,S=record(t.extraDepends,field(`extraDepends`)),C=record(t.typelibPackages,field(`typelibPackages`));return{binaryName:expectString(t.binaryName,field(`binaryName`)),appId:expectString(t.appId,field(`appId`)),name:expectString(t.name,field(`name`)),version:expectString(t.version,field(`version`)),release:expectString(t.release,field(`release`)),maintainer:expectString(t.maintainer,field(`maintainer`)),summary:expectString(t.summary,field(`summary`)),description:expectArray(t.description,field(`description`)).map((t,n)=>expectString(t,field(`description[${n}]`))),license:expectString(t.license,field(`license`)),...t.homepage===void 0?{}:{homepage:expectString(t.homepage,field(`homepage`))},section:expectString(t.section,field(`section`)),group:expectString(t.group,field(`group`)),extraDepends:{deb:expectArray(S.deb??[],field(`extraDepends.deb`)).map((t,n)=>expectString(t,field(`extraDepends.deb[${n}]`))),rpm:expectArray(S.rpm??[],field(`extraDepends.rpm`)).map((t,n)=>expectString(t,field(`extraDepends.rpm[${n}]`)))},typelibPackages:Object.fromEntries(Object.entries(C).map(([t,n])=>{let S=record(n,field(`typelibPackages.${t}`));return[t,{deb:expectString(S.deb,field(`typelibPackages.${t}.deb`)),rpm:expectString(S.rpm,field(`typelibPackages.${t}.rpm`))}]})),app:expectApp(t.app,field(`app`)),minGjsVersion:expectString(t.minGjsVersion,field(`minGjsVersion`)),minNodeVersion:expectString(t.minNodeVersion,field(`minNodeVersion`)),flatpak:readFlatpakSettings(record(t.flatpak,field(`flatpak`)),field(`flatpak`)),executables:expectArray(t.executables??[],field(`executables`)).map((t,n)=>{let S=record(t,field(`executables[${n}]`));if(typeof S.gui!=`boolean`)throw Error(`gjsify ship: ${field(`executables[${n}].gui`)} must be a boolean.`);return{name:expectString(S.name,field(`executables[${n}].name`)),gui:S.gui}}),nestedBundles:expectArray(t.nestedBundles??[],field(`nestedBundles`)).map((t,n)=>{let S=record(t,field(`nestedBundles[${n}]`));return{name:expectString(S.name,field(`nestedBundles[${n}].name`)),entitlements:expectArray(S.entitlements,field(`nestedBundles[${n}].entitlements`)).map((t,S)=>expectString(t,field(`nestedBundles[${n}].entitlements[${S}]`)))}}),helperExecutables:expectArray(t.helperExecutables??[],field(`helperExecutables`)).map((t,n)=>{let S=record(t,field(`helperExecutables[${n}]`));return{name:expectString(S.name,field(`helperExecutables[${n}].name`)),entitlements:expectArray(S.entitlements,field(`helperExecutables[${n}].entitlements`)).map((t,S)=>expectString(t,field(`helperExecutables[${n}].entitlements[${S}]`)))}})}}function readFlatpakSettings(t,n){let field=t=>`${n}.${t}`,strings=(t,n)=>expectArray(t,field(n)).map((t,S)=>expectString(t,field(`${n}[${S}]`)));return{runtime:expectString(t.runtime,field(`runtime`)),runtimeVersion:expectString(t.runtimeVersion,field(`runtimeVersion`)),sdk:expectString(t.sdk,field(`sdk`)),branch:expectString(t.branch,field(`branch`)),sdkExtensions:strings(t.sdkExtensions,`sdkExtensions`),appendPath:strings(t.appendPath,`appendPath`),finishArgs:strings(t.finishArgs,`finishArgs`),cleanup:strings(t.cleanup,`cleanup`)}}function record(t,n){if(typeof t!=`object`||!t||Array.isArray(t))throw Error(`gjsify ship: ${n} must be an object. Re-run the \`--stage\` phase.`);return t}function expectArray(t,n){if(!Array.isArray(t))throw Error(`gjsify ship: ${n} must be an array. Re-run the \`--stage\` phase.`);return t}function expectApp(t,n){if(t===`gjs`||t===`node`)return t;throw Error(`gjsify ship: ${n} must be "gjs" or "node", got ${JSON.stringify(t)}.`)}function expectString(t,n){if(typeof t!=`string`)throw Error(`gjsify ship: ${n} must be a string. Re-run the \`--stage\` phase.`);return t}function expectInteger(t,n){if(typeof t!=`number`||!Number.isInteger(t)||t<0)throw Error(`gjsify ship: ${n} must be a non-negative integer. Re-run the \`--stage\` phase. (Modes are decimal here — JSON has no octal literal, so 0o755 is written 493.)`);return t}var MW,NW=__esmMin(()=>{ef(),qn(),jW(),yh(),mW(),WH(),MW=`.gjsify-ship-stage.json`});function writeStage(t,n){for(let t of n)if(t.path===`.gjsify-ship-stage.json`)throw Error(`gjsify ship: a payload file may not be called \`${MW}\` — that name belongs to the stage manifest, which sits at the stage root beside the payload and carries what the packing host needs (ADR 0024 § A2). Rename the \`gjsify.ship.extraFiles\` destination.`);rmSync(t,{recursive:!0,force:!0,maxRetries:5}),mkdirSync(t,{recursive:!0});for(let S of n){let n=In(t,S.path.split(`/`).join(Wn));mkdirSync(zn(n),{recursive:!0});let C;switch(S.source.kind){case`text`:C=new TextEncoder().encode(S.source.text);break;case`file`:C=new Uint8Array(readFileSync(S.source.path));break;case`bytes`:C=S.source.data;break;default:{let t=S.source;throw Error(`gjsify ship: no writer for the "${JSON.stringify(t)}" source kind.`)}}writeFileSync(n,C),chmodSync(n,S.mode)}}function readStage(t,n){let S=new Map(n.map(t=>[t.path,t])),C=new Map;for(let n of t)for(let t of listFilesRecursive(n)){if(t===`.gjsify-ship-stage.json`)continue;let N=S.get(t);if(N===void 0)throw Error(`gjsify ship: ${In(n,t.split(`/`).join(Wn))} is in the stage and not in its manifest, so nothing knows what mode to give it. Every payload file takes its mode from the plan, never from the filesystem, so a file that arrived some other way would be packed 0644 — unrunnable if it is a program. Remove it, or add it through \`gjsify.ship.extraFiles\` and re-run the \`--stage\` phase.`);let F=new Uint8Array(readFileSync(In(n,t.split(`/`).join(Wn))));if(N.bytes!==void 0&&N.bytes!==F.byteLength)throw Error(`gjsify ship: ${t} is ${F.byteLength} bytes in the stage and ${N.bytes} in its manifest. The stage arrived truncated or was edited after it was assembled. Re-upload it, or re-run the \`--stage\` phase.`);C.set(t,{path:t,mode:N.mode,data:F})}let N=n.filter(t=>!C.has(t.path)).map(t=>t.path);if(N.length>0)throw Error(`gjsify ship: the stage manifest lists ${N.length} file(s) the stage does not contain: ${N.slice(0,5).join(`, `)}${N.length>5?`, …`:``}. A payload has to be complete before it is packed — both formats would pack the rest without complaint and install a package that cannot start. Re-run the \`--stage\` phase, and check that whatever moved the stage between hosts copied every file (an artifact upload that drops empty files or dotfiles is the usual cause).`);return[...C.values()].sort((t,n)=>t.path<n.path?-1:+(t.path>n.path))}function writePayload(t,n,S){let C=S===``?``:`${S}/`;rmSync(t,{recursive:!0,force:!0,maxRetries:5}),mkdirSync(t,{recursive:!0});for(let N of n){if(!N.path.startsWith(C))throw Error(`gjsify ship: ${N.path} is outside ${S||`the artifact`}, which this artifact IS — so there is nowhere inside it for the file to go. A payload file that escaped the bundle would ship beside it, unsigned and unfound.`);let n=In(t,N.path.slice(C.length).split(`/`).join(Wn));mkdirSync(zn(n),{recursive:!0}),writeFileSync(n,N.data),chmodSync(n,N.mode)}}function directorySize(t){let n=0;for(let S of listFilesRecursive(t))n+=statSync(In(t,S.split(`/`).join(Wn))).size;return n}var PW=__esmMin(()=>{ef(),qn(),SU(),NW()});function asciiCodesignIdentifier(t){let n=Bn(t);if([...n].every(t=>(t.codePointAt(0)??0)<128))return;let S=n.normalize(`NFD`).replace(/\p{M}+/gu,``).replace(/[^A-Za-z0-9.-]+/g,`-`).replace(/^-+|-+$/g,``);return/[A-Za-z0-9]/.test(S)?S:`x-${[...new TextEncoder().encode(n)].map(t=>t.toString(16).padStart(2,`0`)).join(``)}`}function resolveSignPlan(t){let n=FW[t.layoutOs];if(n===void 0){if(t.flag!==void 0)throw Error(`gjsify ship: --sign has nothing to sign in the ${t.layoutOs} layout. A .deb and an .rpm carry no per-file signature — the artifact is signed as a whole by the repository that serves it (\`debsigs\`, \`rpmsign\`), with that repository's key and not with a build-time identity. Drop --sign, or assemble the darwin or windows layout.`);return{kind:`unsupported`}}let S=t.config?.[t.layoutOs]?.identity,[C,N]=t.flag===void 0?[S,`config`]:[t.flag,`flag`];return C===void 0||C===``?{kind:`skip`,message:`${C===``?`an empty identity was ${N===`flag`?`passed to --sign`:`set in \`${n.configKey}\``}`:`no identity was given`} — skipping ${n.tool}. An unsigned artifact is the default path and a legitimate deliverable (ADR 0024 § A13). Pass \`--sign <identity>\` or set \`${n.configKey}\` to sign; \`--sign -\` signs ad-hoc and needs no developer identity.`}:{kind:`sign`,identity:C,signer:n,source:N}}function assertHostCanSign(t){let n=process.platform;if(!t.signOn.includes(n))throw Error(`gjsify ship: signing the ${t.layoutOs} layout needs ${t.tool}, which runs on ${t.signOn.join(`, `)} and this host is ${n}. Assembly is not host-bound — \`gjsify ship <os> --stage\` here, then \`gjsify ship --from-stage <dir> --sign <identity>\` on a host that has both the tool and the identity (ADR 0024 § A1, § A14).`);if(!isOnPath(t.tool))throw Error(`gjsify ship: --sign was given and \`${t.tool}\` is not on PATH, so nothing can make the signature — ${t.installHint}. Dropping --sign produces an unsigned artifact, which is a legitimate output (ADR 0024 § A13); silently producing one while --sign was asked for is not.`)}function partitionSignedFileSet(t){let n=new Set(t.planned),S=new Set(t.arrived),C=[...S].filter(t=>!n.has(t)).sort(),N=t.sealPrefixes??[],underAnyPrefix=t=>N.some(n=>t.startsWith(n));return{sealed:N.length===0?[]:C.filter(underAnyPrefix),unexpected:N.length===0?C:C.filter(t=>!underAnyPrefix(t)),removed:[...n].filter(t=>!S.has(t)).sort()}}async function signPayload(t){let{payload:n,signer:S,workDir:C}=t,N=t.nestedBundles??[],F=t.helperExecutables??[];if((N.length>0||F.length>0)&&!S.sealsBundle)throw Error(`gjsify ship: this payload declares a nested bundle or helper executable, and the ${S.layoutOs} signer has no bundle to embed one in — \`signtool\` signs loose images, never a bundle tree. Nested bundles and helper executables are a darwin-only feature.`);writePayload(C,n,``);let I=t.identity===`-`,H=new Map,entitlementsFileFor=(n,S)=>{if(S.length===0)return;let C=H.get(n);if(C!==void 0)return C;let N=n===``?t.entitlementsPath:`${t.entitlementsPath}.${n}.plist`;return mkdirSync(zn(N),{recursive:!0}),writeFileSync(N,renderEntitlements(S)),H.set(n,N),N},run=async(n,N,F,H)=>{let W=S.args({identity:t.identity,file:n,adhoc:I,seal:F,...H?{entitlements:H}:{}});t.verbose&&t.log(`${S.tool} ${W.join(` `)}`);let q=await spawnToCompletion(S.tool,W,{completion:`return`,cwd:C,stdio:`inherit`,notFound:()=>Error(`gjsify ship: \`${S.tool}\` is not on PATH — ${S.installHint}.`)});if(q.code!==0)throw Error(`gjsify ship: ${S.tool} failed on ${N} with ${describeExit(q)}. Nothing is packed from a payload whose signature failed: an artifact that is half signed installs and is refused at first launch, which is worse than not shipping.`)},W=entitlementsFileFor(``,S.entitlements(I)),q=N.map(t=>`${t.path}/`),Y=new Set(F.map(t=>t.path)),underSubordinate=t=>q.some(n=>t.startsWith(n)),X=[],Z=0;for(let t of N){let N=entitlementsFileFor(t.path,t.entitlements),F=n.filter(n=>n.path.startsWith(`${t.path}/`)&&classifyBinary(n.data)===S.signs);for(let t of F)await run(In(C,t.path.split(`/`).join(Wn)),t.path,!1,N);Z+=F.length,await run(In(C,t.path.split(`/`).join(Wn)),`${t.path} (nested bundle seal)`,!0,N),X.push(S.sealAddPrefix(t.path))}for(let t of F){let n=entitlementsFileFor(t.path,t.entitlements);await run(In(C,t.path.split(`/`).join(Wn)),t.path,!1,n)}let te=n.filter(t=>classifyBinary(t.data)===S.signs&&!underSubordinate(t.path)&&!Y.has(t.path));if(te.length===0&&!S.sealsBundle)return t.log(`nothing in this payload is a ${S.signs===`macho`?`Mach-O`:`PE`} image, so ${S.tool} signed 0 file(s). The artifact carries no signature.`),[...n];for(let t of te)await run(In(C,t.path.split(`/`).join(Wn)),t.path,!1,W);let ne;if(S.sealsBundle){if(t.bundleRoot===``)throw Error(`gjsify ship: the ${S.layoutOs} signer seals a bundle and this layout has no root to seal. \`Layout.root\` is what names the artifact directory; a signer that sealed the whole stage would sign the payload of every other format beside it.`);ne=S.sealAddPrefix(t.bundleRoot),await run(In(C,t.bundleRoot.split(`/`).join(Wn)),`${t.bundleRoot} (bundle seal)`,!0,W)}let re=[...ne===void 0?[]:[ne],...X],ie=partitionSignedFileSet({arrived:listFilesRecursive(C),planned:n.map(t=>t.path),sealPrefixes:re});if(ie.unexpected.length>0||ie.removed.length>0)throw Error(`gjsify ship: ${S.tool} changed the payload's file set — ${ie.unexpected.length} added (${ie.unexpected.slice(0,3).join(`, `)||`—`}), ${ie.removed.length} removed (${ie.removed.slice(0,3).join(`, `)||`—`}). Signing is a mutation of the files that are already in the payload (ADR 0024 § A4), plus exactly each seal's own directory${re.length===0?``:` (${re.map(t=>`\`${t}\``).join(`, `)})`}.`);let ae=ie.sealed;t.log(`${S.tool} signed ${te.length+Z+F.length} of ${n.length} payload file(s) as ${I?"ad-hoc (`-`)":`\`${t.identity}\``}${ne===void 0?``:` and sealed ${t.bundleRoot} (${ae.length} seal file(s))`}${N.length===0?``:`, nested: ${N.map(t=>t.path).join(`, `)}`} — ${S.gap}.`);let read=t=>new Uint8Array(readFileSync(In(C,t.split(`/`).join(Wn))));return[...n.map(t=>({path:t.path,mode:t.mode,data:read(t.path)})),...ae.map(t=>({path:t,mode:420,data:read(t)}))].sort((t,n)=>t.path<n.path?-1:+(t.path>n.path))}function resolveNotaryPlan(t){let n=IW[t.layoutOs];if(n===void 0){if(t.flag!==void 0)throw Error(`gjsify ship: --notarize has no meaning in the ${t.layoutOs} layout. Notarisation is Apple's pre-clearance of a signed artifact and nothing else asks for it — Windows SmartScreen accrues reputation per file hash instead (ADR 0024 § A5).`);return{kind:`unsupported`}}if(t.flag===void 0||t.flag===``)return{kind:`skip`,message:`no notarisation credential was given — skipping ${n.tool} notarytool. Pass \`--notarize <keychain-profile>\`, naming a profile a prior \`notarytool store-credentials\` put in this host's keychain.`};if(t.sign.kind!==`sign`)throw Error("gjsify ship: --notarize was given without an identity to sign with. Notarisation is a check ON a signature, so submitting an unsigned artifact has nothing to clear. Pass `--sign <identity>` as well, or drop --notarize.");return{kind:`notarize`,credential:t.flag,notary:n}}async function notarizeArtifact(t){let{notary:n,credential:S}=t.plan,C=process.platform;if(!n.notarizeOn.includes(C))throw Error(`gjsify ship: notarising the ${n.layoutOs} layout needs ${n.tool}, which runs on ${n.notarizeOn.join(`, `)} and this host is ${C}.`);let N=n.args(S,t.artifact);t.verbose&&t.log(`${n.tool} ${N.join(` `)}`);let F=await spawnToCompletion(n.tool,N,{completion:`return`,stdio:`inherit`,notFound:()=>Error(`gjsify ship: \`${n.tool}\` is not on PATH — ${n.installHint}.`)});if(F.code!==0)throw Error(`gjsify ship: ${n.tool} notarytool failed with ${describeExit(F)}.`);t.log(`${n.tool} notarytool accepted ${t.artifact}.`)}async function stapleArtifact(t){let n=[`stapler`,`staple`,t.artifact];t.verbose&&t.log(`${t.notary.tool} ${n.join(` `)}`);let S=await spawnToCompletion(t.notary.tool,n,{completion:`return`,stdio:`inherit`,notFound:()=>Error(`gjsify ship: \`${t.notary.tool}\` is not on PATH — ${t.notary.installHint}.`)});if(S.code!==0)throw Error(`gjsify ship: ${t.notary.tool} stapler failed with ${describeExit(S)}. The artifact is notarised and NOT stapled, which means every launch asks Gatekeeper to check online — and fails closed on a machine with no network. Re-run the finish phase; \`stapler\` requires internet access and the ticket may not have propagated yet.`);t.log(`${t.notary.tool} stapler attached the ticket to ${t.artifact}.`)}var FW,IW,LW=__esmMin(()=>{ef(),qn(),ZI(),sv(),SU(),aU(),RH(),PW(),FW={darwin:{layoutOs:`darwin`,tool:`codesign`,signOn:[`darwin`],installHint:"install the Xcode Command Line Tools (`xcode-select --install`) on a macOS host",signs:`macho`,args:({identity:t,file:n,entitlements:S,adhoc:C,seal:N})=>{let F=N?void 0:asciiCodesignIdentifier(n);return[`--force`,`--sign`,t,`--options`,`runtime`,...S===void 0?[]:[`--entitlements`,S],...C?[]:[`--timestamp`],...F===void 0?[]:[`--identifier`,F],n]},entitlements:t=>[`com.apple.security.cs.allow-jit`,`com.apple.security.cs.allow-unsigned-executable-memory`,`com.apple.security.cs.disable-executable-page-protection`,`com.apple.security.cs.allow-dyld-environment-variables`,...t?[`com.apple.security.cs.disable-library-validation`]:[]],sealsBundle:!0,sealAddPrefix:t=>`${t}/Contents/_CodeSignature/`,configKey:`gjsify.ship.sign.darwin.identity`,gap:"the images are signed and the bundle is sealed, and the seal survives both the `.zip` and the `.dmg` round trip; § A16 stands measured in ONE direction only — library validation refuses an ad-hoc-signed dylib, so the ad-hoc identity grants `disable-library-validation` while a named one does not; a named Developer ID was signed and notarised on 2026-10-30 for an ASCII-named app, and a non-ASCII image name verifies only with the explicit ASCII `--identifier` this signer now passes"},win32:{layoutOs:`win32`,tool:`signtool`,signOn:[`win32`],installHint:"install the Windows SDK (signtool.exe ships in its `bin/<version>/x64` directory)",signs:`pe`,args:({identity:t,file:n})=>[`sign`,`/n`,t,`/fd`,`sha256`,n],entitlements:()=>[],sealsBundle:!1,sealAddPrefix:()=>``,configKey:`gjsify.ship.sign.win32.identity`,gap:`no timestamp countersignature is requested, so the signature expires with the certificate (UNVERIFIED: no run in this repository has ever invoked signtool)`}},IW={darwin:{layoutOs:`darwin`,tool:`xcrun`,notarizeOn:[`darwin`],installHint:"install the Xcode Command Line Tools (`xcode-select --install`) on a macOS host",args:(t,n)=>[`notarytool`,`submit`,`--keychain-profile`,t,`--wait`,n]}}});function stagedFontDir(t,n){return`${t}/${Tn.basename(nH.fonts)}/${n}`}function shellQuote(t){return`'${t.replace(/'/g,`'\\''`)}'`}function cmdQuote(t){let n=/["%!\r\n]/.exec(t);if(n!==null)throw Error(`gjsify ship: \`gjsify.ship.execArgs\` contains ${JSON.stringify(t)}, and cmd.exe has no way to pass ${JSON.stringify(n[0])} through a Windows launcher literally — \`%\` expands at parse time and \`"\` ends the quoted run. Move the value into the app (it can read it from its own config) or drop the character.`);return`"${t}"`}function renderLauncher(t,n,S,C={}){switch(S.name){case`linux`:return renderPrefixLauncher(t,n,S);case`darwin`:return renderAppBundleLauncher(t,n,S,C);case`windows`:return renderWindowsLauncher(t,n,S,C);default:{let t=S.name;throw Error(`gjsify ship: no launcher is wired for the "${String(t)}" layout.`)}}}function renderPrefixLauncher(t,n,S){let C=S.dirs(t),N=[`#!/bin/sh`,"# Generated by `gjsify ship` — do not edit.",`set -e`,`self=$(readlink -f "$0")`,`prefix=$(dirname "$(dirname "$self")")`,`XDG_DATA_DIRS="$prefix/${C.data}:\${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"`,`export XDG_DATA_DIRS`];if(t.typelibFiles.length>0){let t=`"$prefix"/${C.native}`;for(let n of[`GI_TYPELIB_PATH`,`LD_LIBRARY_PATH`])N.push(`${n}=${t}\${${n}:+:$${n}}`,`export ${n}`)}else if(Object.values(t.formatFiles).some(t=>t.typelibFiles.length>0)){let t=`"$prefix"/${C.native}`;N.push(`if [ -d ${t} ]; then`);for(let n of[`GI_TYPELIB_PATH`,`LD_LIBRARY_PATH`])N.push(` ${n}=${t}\${${n}:+:$${n}}`,` export ${n}`);N.push(`fi`)}return t.localeFiles.length>0&&N.push(`GJSIFY_LOCALE_DIR="$prefix"/${C.data}/locale`,`export GJSIFY_LOCALE_DIR`),t.fontFiles.length>0&&N.push(`GJSIFY_FONT_DIR="$prefix"/${stagedFontDir(C.data,t.appId)}`,`export GJSIFY_FONT_DIR`),N.push(`exec ${execLine(S,`"$prefix"/${C.bundle}/${n}`,t)} "$@"`,``),N.join(`
1185
+ `)}function msiBackendFor(t){if(t===`linux`)return`wixl`;if(t===`win32`)return`wix3`;throw Error(`gjsify ship: no MSI compiler is wired for ${t}. \`wixl\` (msitools) is used on linux and WiX v3 on win32; assembly is not host-bound, so \`gjsify ship windows --stage\` here and \`gjsify ship --from-stage <dir> --target msi\` there is the way across.`)}async function buildMsi(t){let n=msiBackendFor(t.host??process.platform);mkdirSync(t.workDir,{recursive:!0});let S=In(t.workDir,`${t.settings.binaryName}.wxs`);if(writeFileSync(S,renderWxs(t)),n===`wixl`)return await run(`wixl`,[`-a`,t.archLabel,`-o`,t.target,S],t),S;let C=In(t.workDir,`obj`);return rmSync(C,{recursive:!0,force:!0,maxRetries:5}),mkdirSync(C,{recursive:!0}),await run(`candle.exe`,[`-nologo`,`-arch`,t.archLabel,`-out`,`${C}\\`,S],t),await run(`light.exe`,[`-nologo`,`-out`,t.target,In(C,`${t.settings.binaryName}.wixobj`)],t),S}async function run(t,n,S){S.verbose&&ge.log(`[gjsify ship] ${t} ${n.join(` `)}`);let C=await spawnToCompletion(t,[...n],{completion:`return`,cwd:S.workDir,stdio:`inherit`,notFound:()=>Error(`gjsify ship: ${t} not found. It is the MSI compiler for this host — Fedora: \`sudo dnf install msitools\`, Debian/Ubuntu: \`sudo apt install msitools\`, Windows: WiX Toolset v3.14 with its \`bin\` directory on PATH.`)});if(C.code!==0)throw Error(`gjsify ship: ${t} failed with ${describeExit(C)}.`)}var gW,_W,vW,yW=__esmMin(()=>{_e(),fl(),ef(),qn(),sv(),GH(),cU(),gW=`7b3a1f6e-0c4d-4a2b-9e51-3d8c6f2a0b14`,_W=/[<>:"/\\|?*;]/,vW=`root`});function getCrcTable(){if(EW!==null)return EW;let t=new Uint32Array(256);for(let n=0;n<256;n++){let S=n;for(let t=0;t<8;t++)S=S&1?3988292384^S>>>1:S>>>1;t[n]=S>>>0}return EW=t,t}function crc32(t){let n=getCrcTable(),S=4294967295;for(let C=0;C<t.length;C++)S=n[(S^t[C])&255]^S>>>8;return(S^4294967295)>>>0}function dosDateTime(t){let n=new Date(Math.max(t,315532800)*1e3);return{date:(n.getUTCFullYear()-1980&127)<<9|n.getUTCMonth()+1<<5|n.getUTCDate(),time:n.getUTCHours()<<11|n.getUTCMinutes()<<5|Math.floor(n.getUTCSeconds()/2)}}function buildZip(t,n){let S=[...t].sort((t,n)=>t.path<n.path?-1:+(t.path>n.path)),{date:C,time:N}=dosDateTime(n),F=new TextEncoder;if(S.length>65535)throw Error(`gjsify ship: this archive would hold ${S.length} entries and a non-ZIP64 central directory records the count in 16 bits, so it would silently wrap. Nothing here writes ZIP64 yet; the payload has to shrink, or this writer has to grow the ZIP64 records.`);let I=new Writer,H=new Writer,W=0;for(let t of S){let n=F.encode(t.path),S=crc32(t.data),q=t.data.byteLength,Y=I.offset;if(Y>4294967295||q>4294967295)throw Error(`gjsify ship: ${t.path} would push this archive past 4 GiB, which a non-ZIP64 header records in 32 bits and therefore truncates. Nothing here writes ZIP64 yet.`);I.u32(bW),I.u16(TW),I.u16(2048),I.u16(CW),I.u16(N),I.u16(C),I.u32(S),I.u32(q),I.u32(q),I.u16(n.byteLength),I.u16(0),I.bytes(n),I.bytes(t.data),H.u32(xW),H.u16(wW),H.u16(TW),H.u16(2048),H.u16(CW),H.u16(N),H.u16(C),H.u32(S),H.u32(q),H.u32(q),H.u16(n.byteLength),H.u16(0),H.u16(0),H.u16(0),H.u16(0),H.u32(((32768|t.mode&4095)>>>0)*65536),H.u32(Y),H.bytes(n),W+=1}let q=H.finish(),Y=new Writer;Y.bytes(I.finish());let X=Y.offset;return Y.bytes(q),Y.u32(SW),Y.u16(0),Y.u16(0),Y.u16(W),Y.u16(W),Y.u32(q.byteLength),Y.u32(X),Y.u16(0),Y.finish()}function zipEntriesFromPayload(t,n=``){let S=n===``?``:`${n}/`;return t.map(t=>({path:`${S}${t.path}`,mode:t.mode,data:t.data}))}var bW,xW,SW,CW,wW,TW,EW,Writer,DW=__esmMin(()=>{bW=67324752,xW=33639248,SW=101010256,CW=0,wW=788,TW=20,EW=null,Writer=class{parts=[];length=0;get offset(){return this.length}u16(t){this.push(new Uint8Array([t&255,t>>>8&255]))}u32(t){this.push(new Uint8Array([t&255,t>>>8&255,t>>>16&255,t>>>24&255]))}bytes(t){this.push(t)}push(t){this.parts.push(t),this.length+=t.byteLength}finish(){let t=new Uint8Array(this.length),n=0;for(let S of this.parts)t.set(S,n),n+=S.byteLength;return t}}});function entryEvidence(t){let n=new Set,S=new Set;return walkModuleAst(t,t=>{let C=importedSpecifier(t);C!==null&&(C.startsWith(`gi://`)||OW.has(C)?n.add(C):C.startsWith(`node:`)&&t.type!==`ImportExpression`&&S.add(C))}),{gi:[...n].sort(),node:[...S].sort()}}function assertEntryRunsUnder(t){let n=entryEvidence(t.source),S=t.interpreter===`node`?n.gi:n.node;if(S.length===0)return;let C=t.interpreter===`node`?`gjs`:`node`,N=t.interpreter===`gjs`?`GJS's loader refuses it: ImportError, "Unsupported URI scheme for importing: node"`:S.some(t=>t.startsWith(`gi://`))?`node's ESM loader refuses it: ERR_UNSUPPORTED_ESM_URL_SCHEME, "Only URLs with a scheme in: file, data, and node are supported by the default ESM loader"`:`node's ESM loader refuses it: ERR_MODULE_NOT_FOUND — a GJS built-in is not a package`,F=S.slice(0,3).join(`, `),I=S.length>3?`, and ${S.length-3} more`:``;throw Error(`gjsify ship: this target execs \`${t.interpreter}\` (\`${t.appKey}\`), and the entry it would ship — ${t.entry} (\`${t.bundleKey}\`) — imports ${F}${I}.\n ${N}, before a line of application code runs.\n The artifact would be built, reported as built, and fail at launch on every machine.
1186
+ Either ship this target the \`--app ${t.interpreter}\` build of the app — \`gjsify.ship.bundle.${t.layoutOs}\` selects the entry per target, the way \`gjsify.ship.app.${t.layoutOs}\` selects the runtime —\n or set \`gjsify.ship.app.${t.layoutOs}\` to "${C}" if this bundle is the one that should ship.`)}var OW,kW=__esmMin(()=>{QN(),OW=new Set([`system`,`gettext`])});function releaseRecordPath(t){return`${t}${AW}`}function recordedSignature(t,n){return t===void 0?{kind:`none`}:t===n?{kind:`adhoc`}:{kind:`identity`,identity:t}}function buildReleaseRecord(t){let n=readFileSync(t.file);return{schema:1,artifact:Bn(t.file),sha256:createHash(`sha256`).update(n).digest(`hex`),size:n.length,format:t.format,os:t.os,arch:t.arch,signature:t.signature,notarized:t.notarized,stapled:t.stapled,nestedBundles:t.nestedBundles,generator:t.generator}}function writeReleaseRecord(t){let n=releaseRecordPath(t.file);return writeFileSync(n,`${JSON.stringify(buildReleaseRecord(t),null,4)}\n`),n}var AW,jW=__esmMin(()=>{fl(),ef(),qn(),AW=`.gjsify-release.json`});function base64Encode(t){let n=``,S=32768;for(let C=0;C<t.length;C+=S)n+=String.fromCharCode(...t.subarray(C,C+S));return btoa(n)}function base64Decode(t){let n=atob(t),S=new Uint8Array(n.length);for(let t=0;t<n.length;t++)S[t]=n.charCodeAt(t);return S}var MW=__esmMin(()=>{});function toPackSettings(t){return{binaryName:t.binaryName,appId:t.appId,name:t.name,version:t.version,release:t.release,maintainer:t.maintainer,summary:t.summary,description:t.description,license:t.license,...t.homepage===void 0?{}:{homepage:t.homepage},section:t.section,group:t.group,extraDepends:t.extraDepends,typelibPackages:t.typelibPackages,app:t.app,minGjsVersion:t.minGjsVersion,minNodeVersion:t.minNodeVersion,flatpak:t.flatpak,executables:t.executables.map(({name:t,gui:n})=>({name:t,gui:n})),nestedBundles:t.nestedBundles.map(({name:t,entitlements:n})=>({name:t,entitlements:n})),helperExecutables:t.helperExecutables.map(({name:t,entitlements:n})=>({name:t,entitlements:n}))}}function stageManifestPath(t){return In(t,NW)}function formatTarget(t){return`${t.os}-${t.arch}`}function writeStageManifest(t){let n={};for(let S of t.formats)n[S.id]=(t.overlay.get(S.id)??[]).map(t=>{if(t.source.kind===`text`)return{path:t.path,mode:t.mode,text:t.source.text};if(t.source.kind===`bytes`)return{path:t.path,mode:t.mode,base64:base64Encode(t.source.data)};throw Error(`gjsify ship: internal error — the ${S.id} overlay entry ${t.path} is a file reference, and a stage manifest may only carry rendered bytes. Render it in \`planOverlay\` instead.`)});let S={schema:6,tool:{name:`@gjsify/cli`,version:cliVersion()},target:{os:t.settings.layoutOs,arch:t.settings.arch},formats:t.formats.map(t=>t.id),mtime:t.mtime,namespaces:[...t.namespaces],optionalNamespaces:[...t.optionalNamespaces??[]],settings:toPackSettings(t.settings),staged:t.staged.map(n=>({path:n.path,mode:n.mode,bytes:statSync(In(t.stageDir,n.path.split(`/`).join(Wn))).size})),overlay:n};return writeFileSync(stageManifestPath(t.stageDir),`${JSON.stringify(S,null,2)}\n`),S}function readStageManifest(t){let n=stageManifestPath(t);if(!existsSync(n))throw Error(`gjsify ship: ${t} has no ${NW}, so it is not a stage this command can pack. A stage is produced by \`gjsify ship --stage\`, which writes that file at the stage root beside the payload. If you pointed --from-stage at a project's \`ship/\` directory, point it at \`ship/stage/\` instead.`);let S;try{S=JSON.parse(readFileSync(n,`utf-8`))}catch(t){throw Error(`gjsify ship: ${n} is not readable JSON (${t.message}). Re-run the \`--stage\` phase; a truncated manifest means the stage transfer was truncated too.`)}if(typeof S!=`object`||!S||Array.isArray(S))throw Error(`gjsify ship: ${n} is not a JSON object. Re-run the \`--stage\` phase.`);let C=S,N=C.schema;if(typeof N!=`number`||!Number.isInteger(N))throw Error(`gjsify ship: ${n} has no integer \`schema\` field, so it was not written by \`gjsify ship --stage\`. Re-run the \`--stage\` phase.`);if(N>6)throw Error(`gjsify ship: ${n} declares schema ${N} and this gjsify understands 6. The stage was assembled by a newer gjsify: upgrade this one (\`gjsify self-update\`), or re-run the \`--stage\` phase with this version. A manifest from the future is refused rather than partially read, because an unknown field could be the one that decides a file's mode.`);if(N<6)throw Error(`gjsify ship: ${n} declares schema ${N} and this gjsify understands 6. Re-run the \`--stage\` phase with this gjsify. A stage is a short-lived intermediate between two jobs of one run, not an archive, so no migration is kept for it.`);let at=t=>`${n} → ${t}`,F=record(C.tool,at(`tool`)),I=record(C.target,at(`target`)),H={schema:N,tool:{name:expectString(F.name,at(`tool.name`)),version:expectString(F.version,at(`tool.version`))},target:{os:expectLayoutOs(expectString(I.os,at(`target.os`)),at(`target.os`)),arch:expectString(I.arch,at(`target.arch`))},formats:expectArray(C.formats,at(`formats`)).map((t,n)=>{let S=expectString(t,at(`formats[${n}]`));if(!pW.includes(S))throw Error(`gjsify ship: ${at(`formats[${n}]`)} is "${S}", which this gjsify does not know. Known formats: ${pW.join(`, `)}.`);return S}),mtime:expectInteger(C.mtime,at(`mtime`)),namespaces:expectArray(C.namespaces,at(`namespaces`)).map((t,n)=>expectString(t,at(`namespaces[${n}]`))),...C.optionalNamespaces===void 0?{}:{optionalNamespaces:expectArray(C.optionalNamespaces,at(`optionalNamespaces`)).map((t,n)=>expectString(t,at(`optionalNamespaces[${n}]`)))},settings:readPackSettings(record(C.settings,at(`settings`)),at(`settings`)),staged:expectArray(C.staged,at(`staged`)).map((t,n)=>{let S=record(t,at(`staged[${n}]`));return{path:expectString(S.path,at(`staged[${n}].path`)),mode:expectInteger(S.mode,at(`staged[${n}].mode`)),bytes:expectInteger(S.bytes,at(`staged[${n}].bytes`))}}),overlay:{}};if(H.staged.length===0)throw Error(`gjsify ship: ${at(`staged`)} is empty, so this stage describes no payload. A stage always carries at least the launcher its plan named. Re-run the \`--stage\` phase; a stage that lost its plan cannot be packed into anything but an empty package.`);let W=record(C.overlay,at(`overlay`));for(let t of H.formats)H.overlay[t]=expectArray(W[t],at(`overlay.${t}`)).map((n,S)=>{let C=record(n,at(`overlay.${t}[${S}]`)),N=at(`overlay.${t}[${S}]`);if(C.text===void 0==(C.base64===void 0))throw Error(`gjsify ship: ${N} must carry exactly one of \`text\` and \`base64\`. An overlay entry is either rendered text or rendered bytes; an entry with neither would pack an empty file at a path the format requires content at.`);return{path:expectString(C.path,at(`overlay.${t}[${S}].path`)),mode:expectInteger(C.mode,at(`overlay.${t}[${S}].mode`)),...C.text===void 0?{base64:expectString(C.base64,at(`overlay.${t}[${S}].base64`))}:{text:expectString(C.text,at(`overlay.${t}[${S}].text`))}}});return H}function expectLayoutOs(t,n){try{return layoutForOs(t).os}catch{let S=UH.map(t=>HH[t].os).join(`, `);throw Error(`gjsify ship: ${n} is "${t}", which is not a layout this gjsify can pack. It carries the \`process.platform\` spelling and only that — ${S}, so \`win32\` and never \`windows\`. A stage holds exactly one OS's layout and every path in it has that OS's shape, so there is nothing to pack here. Re-run the \`--stage\` phase.`)}}function overlayFiles(t,n){return(t.overlay[n]??[]).map(t=>({path:t.path,mode:t.mode,source:t.base64===void 0?{kind:`text`,text:t.text??``}:{kind:`bytes`,data:base64Decode(t.base64)}}))}function assertExpectedTarget(t,n){if(n===void 0)return;let S=formatTarget(t.target);if(n!==S)throw Error(`gjsify ship: --expect-target ${n} but this stage was assembled for ${S}. The stage records the target its \`--arch\` resolved to at stage time, so this is a stage from another matrix leg: download the artifact belonging to ${n}, or drop --expect-target if packing this one is what you meant.`)}function assertFormatsStaged(t,n){let S=n.filter(n=>!t.formats.includes(n.id)).map(t=>t.id);if(S.length!==0)throw Error(`gjsify ship: this stage was assembled for ${t.formats.length===0?`no format at all`:t.formats.join(`, `)}, and --target names ${S.join(`, `)}. Phase one renders each format's overlay — rpm wants the licence at \`share/licenses/<pkg>/LICENSE\`, deb wants a machine-readable copyright at \`share/doc/<pkg>/copyright\` — so a format the stage never saw would pack without it, and Debian Policy § 12.5 makes that a broken package. Re-run \`gjsify ship --stage --target ${[...t.formats,...S].join(`,`)}\` on the assembling host.`)}function resolveStageMtime(t,n=process.env){let S=n.SOURCE_DATE_EPOCH;return S===void 0||Number(S)===t.mtime?{mtime:t.mtime,warnings:[]}:{mtime:t.mtime,warnings:[`SOURCE_DATE_EPOCH is ${S} here and this stage was stamped ${t.mtime}. The stage's stamp wins, because changing it would make this artifact differ from the same stage packed on the assembling host. Set the same value in both jobs, or set it in neither.`]}}function warnOnToolSkew(t){let n=cliVersion();return t.tool.version===n?[]:[`this stage was assembled by ${t.tool.name} ${t.tool.version} and is being packed by ${n}. Both phases run the same packer, so a version difference can change the artifact's bytes. Pin both jobs to one gjsify version.`]}function readPackSettings(t,n){let field=t=>`${n}.${t}`,S=record(t.extraDepends,field(`extraDepends`)),C=record(t.typelibPackages,field(`typelibPackages`));return{binaryName:expectString(t.binaryName,field(`binaryName`)),appId:expectString(t.appId,field(`appId`)),name:expectString(t.name,field(`name`)),version:expectString(t.version,field(`version`)),release:expectString(t.release,field(`release`)),maintainer:expectString(t.maintainer,field(`maintainer`)),summary:expectString(t.summary,field(`summary`)),description:expectArray(t.description,field(`description`)).map((t,n)=>expectString(t,field(`description[${n}]`))),license:expectString(t.license,field(`license`)),...t.homepage===void 0?{}:{homepage:expectString(t.homepage,field(`homepage`))},section:expectString(t.section,field(`section`)),group:expectString(t.group,field(`group`)),extraDepends:{deb:expectArray(S.deb??[],field(`extraDepends.deb`)).map((t,n)=>expectString(t,field(`extraDepends.deb[${n}]`))),rpm:expectArray(S.rpm??[],field(`extraDepends.rpm`)).map((t,n)=>expectString(t,field(`extraDepends.rpm[${n}]`)))},typelibPackages:Object.fromEntries(Object.entries(C).map(([t,n])=>{let S=record(n,field(`typelibPackages.${t}`));return[t,{deb:expectString(S.deb,field(`typelibPackages.${t}.deb`)),rpm:expectString(S.rpm,field(`typelibPackages.${t}.rpm`))}]})),app:expectApp(t.app,field(`app`)),minGjsVersion:expectString(t.minGjsVersion,field(`minGjsVersion`)),minNodeVersion:expectString(t.minNodeVersion,field(`minNodeVersion`)),flatpak:readFlatpakSettings(record(t.flatpak,field(`flatpak`)),field(`flatpak`)),executables:expectArray(t.executables??[],field(`executables`)).map((t,n)=>{let S=record(t,field(`executables[${n}]`));if(typeof S.gui!=`boolean`)throw Error(`gjsify ship: ${field(`executables[${n}].gui`)} must be a boolean.`);return{name:expectString(S.name,field(`executables[${n}].name`)),gui:S.gui}}),nestedBundles:expectArray(t.nestedBundles??[],field(`nestedBundles`)).map((t,n)=>{let S=record(t,field(`nestedBundles[${n}]`));return{name:expectString(S.name,field(`nestedBundles[${n}].name`)),entitlements:expectArray(S.entitlements,field(`nestedBundles[${n}].entitlements`)).map((t,S)=>expectString(t,field(`nestedBundles[${n}].entitlements[${S}]`)))}}),helperExecutables:expectArray(t.helperExecutables??[],field(`helperExecutables`)).map((t,n)=>{let S=record(t,field(`helperExecutables[${n}]`));return{name:expectString(S.name,field(`helperExecutables[${n}].name`)),entitlements:expectArray(S.entitlements,field(`helperExecutables[${n}].entitlements`)).map((t,S)=>expectString(t,field(`helperExecutables[${n}].entitlements[${S}]`)))}})}}function readFlatpakSettings(t,n){let field=t=>`${n}.${t}`,strings=(t,n)=>expectArray(t,field(n)).map((t,S)=>expectString(t,field(`${n}[${S}]`)));return{runtime:expectString(t.runtime,field(`runtime`)),runtimeVersion:expectString(t.runtimeVersion,field(`runtimeVersion`)),sdk:expectString(t.sdk,field(`sdk`)),branch:expectString(t.branch,field(`branch`)),sdkExtensions:strings(t.sdkExtensions,`sdkExtensions`),appendPath:strings(t.appendPath,`appendPath`),finishArgs:strings(t.finishArgs,`finishArgs`),cleanup:strings(t.cleanup,`cleanup`)}}function record(t,n){if(typeof t!=`object`||!t||Array.isArray(t))throw Error(`gjsify ship: ${n} must be an object. Re-run the \`--stage\` phase.`);return t}function expectArray(t,n){if(!Array.isArray(t))throw Error(`gjsify ship: ${n} must be an array. Re-run the \`--stage\` phase.`);return t}function expectApp(t,n){if(t===`gjs`||t===`node`)return t;throw Error(`gjsify ship: ${n} must be "gjs" or "node", got ${JSON.stringify(t)}.`)}function expectString(t,n){if(typeof t!=`string`)throw Error(`gjsify ship: ${n} must be a string. Re-run the \`--stage\` phase.`);return t}function expectInteger(t,n){if(typeof t!=`number`||!Number.isInteger(t)||t<0)throw Error(`gjsify ship: ${n} must be a non-negative integer. Re-run the \`--stage\` phase. (Modes are decimal here — JSON has no octal literal, so 0o755 is written 493.)`);return t}var NW,PW=__esmMin(()=>{ef(),qn(),MW(),yh(),hW(),GH(),NW=`.gjsify-ship-stage.json`});function writeStage(t,n){for(let t of n)if(t.path===`.gjsify-ship-stage.json`)throw Error(`gjsify ship: a payload file may not be called \`${NW}\` — that name belongs to the stage manifest, which sits at the stage root beside the payload and carries what the packing host needs (ADR 0024 § A2). Rename the \`gjsify.ship.extraFiles\` destination.`);rmSync(t,{recursive:!0,force:!0,maxRetries:5}),mkdirSync(t,{recursive:!0});for(let S of n){let n=In(t,S.path.split(`/`).join(Wn));mkdirSync(zn(n),{recursive:!0});let C;switch(S.source.kind){case`text`:C=new TextEncoder().encode(S.source.text);break;case`file`:C=new Uint8Array(readFileSync(S.source.path));break;case`bytes`:C=S.source.data;break;default:{let t=S.source;throw Error(`gjsify ship: no writer for the "${JSON.stringify(t)}" source kind.`)}}writeFileSync(n,C),chmodSync(n,S.mode)}}function readStage(t,n){let S=new Map(n.map(t=>[t.path,t])),C=new Map;for(let n of t)for(let t of listFilesRecursive(n)){if(t===`.gjsify-ship-stage.json`)continue;let N=S.get(t);if(N===void 0)throw Error(`gjsify ship: ${In(n,t.split(`/`).join(Wn))} is in the stage and not in its manifest, so nothing knows what mode to give it. Every payload file takes its mode from the plan, never from the filesystem, so a file that arrived some other way would be packed 0644 — unrunnable if it is a program. Remove it, or add it through \`gjsify.ship.extraFiles\` and re-run the \`--stage\` phase.`);let F=new Uint8Array(readFileSync(In(n,t.split(`/`).join(Wn))));if(N.bytes!==void 0&&N.bytes!==F.byteLength)throw Error(`gjsify ship: ${t} is ${F.byteLength} bytes in the stage and ${N.bytes} in its manifest. The stage arrived truncated or was edited after it was assembled. Re-upload it, or re-run the \`--stage\` phase.`);C.set(t,{path:t,mode:N.mode,data:F})}let N=n.filter(t=>!C.has(t.path)).map(t=>t.path);if(N.length>0)throw Error(`gjsify ship: the stage manifest lists ${N.length} file(s) the stage does not contain: ${N.slice(0,5).join(`, `)}${N.length>5?`, …`:``}. A payload has to be complete before it is packed — both formats would pack the rest without complaint and install a package that cannot start. Re-run the \`--stage\` phase, and check that whatever moved the stage between hosts copied every file (an artifact upload that drops empty files or dotfiles is the usual cause).`);return[...C.values()].sort((t,n)=>t.path<n.path?-1:+(t.path>n.path))}function writePayload(t,n,S){let C=S===``?``:`${S}/`;rmSync(t,{recursive:!0,force:!0,maxRetries:5}),mkdirSync(t,{recursive:!0});for(let N of n){if(!N.path.startsWith(C))throw Error(`gjsify ship: ${N.path} is outside ${S||`the artifact`}, which this artifact IS — so there is nowhere inside it for the file to go. A payload file that escaped the bundle would ship beside it, unsigned and unfound.`);let n=In(t,N.path.slice(C.length).split(`/`).join(Wn));mkdirSync(zn(n),{recursive:!0}),writeFileSync(n,N.data),chmodSync(n,N.mode)}}function directorySize(t){let n=0;for(let S of listFilesRecursive(t))n+=statSync(In(t,S.split(`/`).join(Wn))).size;return n}var FW=__esmMin(()=>{ef(),qn(),CU(),PW()});function asciiCodesignIdentifier(t){let n=Bn(t);if([...n].every(t=>(t.codePointAt(0)??0)<128))return;let S=n.normalize(`NFD`).replace(/\p{M}+/gu,``).replace(/[^A-Za-z0-9.-]+/g,`-`).replace(/^-+|-+$/g,``);return/[A-Za-z0-9]/.test(S)?S:`x-${[...new TextEncoder().encode(n)].map(t=>t.toString(16).padStart(2,`0`)).join(``)}`}function resolveSignPlan(t){let n=IW[t.layoutOs];if(n===void 0){if(t.flag!==void 0)throw Error(`gjsify ship: --sign has nothing to sign in the ${t.layoutOs} layout. A .deb and an .rpm carry no per-file signature — the artifact is signed as a whole by the repository that serves it (\`debsigs\`, \`rpmsign\`), with that repository's key and not with a build-time identity. Drop --sign, or assemble the darwin or windows layout.`);return{kind:`unsupported`}}let S=t.config?.[t.layoutOs]?.identity,[C,N]=t.flag===void 0?[S,`config`]:[t.flag,`flag`];return C===void 0||C===``?{kind:`skip`,message:`${C===``?`an empty identity was ${N===`flag`?`passed to --sign`:`set in \`${n.configKey}\``}`:`no identity was given`} — skipping ${n.tool}. An unsigned artifact is the default path and a legitimate deliverable (ADR 0024 § A13). Pass \`--sign <identity>\` or set \`${n.configKey}\` to sign; \`--sign -\` signs ad-hoc and needs no developer identity.`}:{kind:`sign`,identity:C,signer:n,source:N}}function assertHostCanSign(t){let n=process.platform;if(!t.signOn.includes(n))throw Error(`gjsify ship: signing the ${t.layoutOs} layout needs ${t.tool}, which runs on ${t.signOn.join(`, `)} and this host is ${n}. Assembly is not host-bound — \`gjsify ship <os> --stage\` here, then \`gjsify ship --from-stage <dir> --sign <identity>\` on a host that has both the tool and the identity (ADR 0024 § A1, § A14).`);if(!isOnPath(t.tool))throw Error(`gjsify ship: --sign was given and \`${t.tool}\` is not on PATH, so nothing can make the signature — ${t.installHint}. Dropping --sign produces an unsigned artifact, which is a legitimate output (ADR 0024 § A13); silently producing one while --sign was asked for is not.`)}function partitionSignedFileSet(t){let n=new Set(t.planned),S=new Set(t.arrived),C=[...S].filter(t=>!n.has(t)).sort(),N=t.sealPrefixes??[],underAnyPrefix=t=>N.some(n=>t.startsWith(n));return{sealed:N.length===0?[]:C.filter(underAnyPrefix),unexpected:N.length===0?C:C.filter(t=>!underAnyPrefix(t)),removed:[...n].filter(t=>!S.has(t)).sort()}}async function signPayload(t){let{payload:n,signer:S,workDir:C}=t,N=t.nestedBundles??[],F=t.helperExecutables??[];if((N.length>0||F.length>0)&&!S.sealsBundle)throw Error(`gjsify ship: this payload declares a nested bundle or helper executable, and the ${S.layoutOs} signer has no bundle to embed one in — \`signtool\` signs loose images, never a bundle tree. Nested bundles and helper executables are a darwin-only feature.`);writePayload(C,n,``);let I=t.identity===`-`,H=new Map,entitlementsFileFor=(n,S)=>{if(S.length===0)return;let C=H.get(n);if(C!==void 0)return C;let N=n===``?t.entitlementsPath:`${t.entitlementsPath}.${n}.plist`;return mkdirSync(zn(N),{recursive:!0}),writeFileSync(N,renderEntitlements(S)),H.set(n,N),N},run=async(n,N,F,H)=>{let W=S.args({identity:t.identity,file:n,adhoc:I,seal:F,...H?{entitlements:H}:{}});t.verbose&&t.log(`${S.tool} ${W.join(` `)}`);let q=await spawnToCompletion(S.tool,W,{completion:`return`,cwd:C,stdio:`inherit`,notFound:()=>Error(`gjsify ship: \`${S.tool}\` is not on PATH — ${S.installHint}.`)});if(q.code!==0)throw Error(`gjsify ship: ${S.tool} failed on ${N} with ${describeExit(q)}. Nothing is packed from a payload whose signature failed: an artifact that is half signed installs and is refused at first launch, which is worse than not shipping.`)},W=entitlementsFileFor(``,S.entitlements(I)),q=N.map(t=>`${t.path}/`),Y=new Set(F.map(t=>t.path)),underSubordinate=t=>q.some(n=>t.startsWith(n)),X=[],Z=0;for(let t of N){let N=entitlementsFileFor(t.path,t.entitlements),F=n.filter(n=>n.path.startsWith(`${t.path}/`)&&classifyBinary(n.data)===S.signs);for(let t of F)await run(In(C,t.path.split(`/`).join(Wn)),t.path,!1,N);Z+=F.length,await run(In(C,t.path.split(`/`).join(Wn)),`${t.path} (nested bundle seal)`,!0,N),X.push(S.sealAddPrefix(t.path))}for(let t of F){let n=entitlementsFileFor(t.path,t.entitlements);await run(In(C,t.path.split(`/`).join(Wn)),t.path,!1,n)}let te=n.filter(t=>classifyBinary(t.data)===S.signs&&!underSubordinate(t.path)&&!Y.has(t.path));if(te.length===0&&!S.sealsBundle)return t.log(`nothing in this payload is a ${S.signs===`macho`?`Mach-O`:`PE`} image, so ${S.tool} signed 0 file(s). The artifact carries no signature.`),[...n];for(let t of te)await run(In(C,t.path.split(`/`).join(Wn)),t.path,!1,W);let ne;if(S.sealsBundle){if(t.bundleRoot===``)throw Error(`gjsify ship: the ${S.layoutOs} signer seals a bundle and this layout has no root to seal. \`Layout.root\` is what names the artifact directory; a signer that sealed the whole stage would sign the payload of every other format beside it.`);ne=S.sealAddPrefix(t.bundleRoot),await run(In(C,t.bundleRoot.split(`/`).join(Wn)),`${t.bundleRoot} (bundle seal)`,!0,W)}let re=[...ne===void 0?[]:[ne],...X],ie=partitionSignedFileSet({arrived:listFilesRecursive(C),planned:n.map(t=>t.path),sealPrefixes:re});if(ie.unexpected.length>0||ie.removed.length>0)throw Error(`gjsify ship: ${S.tool} changed the payload's file set — ${ie.unexpected.length} added (${ie.unexpected.slice(0,3).join(`, `)||`—`}), ${ie.removed.length} removed (${ie.removed.slice(0,3).join(`, `)||`—`}). Signing is a mutation of the files that are already in the payload (ADR 0024 § A4), plus exactly each seal's own directory${re.length===0?``:` (${re.map(t=>`\`${t}\``).join(`, `)})`}.`);let ae=ie.sealed;t.log(`${S.tool} signed ${te.length+Z+F.length} of ${n.length} payload file(s) as ${I?"ad-hoc (`-`)":`\`${t.identity}\``}${ne===void 0?``:` and sealed ${t.bundleRoot} (${ae.length} seal file(s))`}${N.length===0?``:`, nested: ${N.map(t=>t.path).join(`, `)}`} — ${S.gap}.`);let read=t=>new Uint8Array(readFileSync(In(C,t.split(`/`).join(Wn))));return[...n.map(t=>({path:t.path,mode:t.mode,data:read(t.path)})),...ae.map(t=>({path:t,mode:420,data:read(t)}))].sort((t,n)=>t.path<n.path?-1:+(t.path>n.path))}function resolveNotaryPlan(t){let n=LW[t.layoutOs];if(n===void 0){if(t.flag!==void 0)throw Error(`gjsify ship: --notarize has no meaning in the ${t.layoutOs} layout. Notarisation is Apple's pre-clearance of a signed artifact and nothing else asks for it — Windows SmartScreen accrues reputation per file hash instead (ADR 0024 § A5).`);return{kind:`unsupported`}}if(t.flag===void 0||t.flag===``)return{kind:`skip`,message:`no notarisation credential was given — skipping ${n.tool} notarytool. Pass \`--notarize <keychain-profile>\`, naming a profile a prior \`notarytool store-credentials\` put in this host's keychain.`};if(t.sign.kind!==`sign`)throw Error("gjsify ship: --notarize was given without an identity to sign with. Notarisation is a check ON a signature, so submitting an unsigned artifact has nothing to clear. Pass `--sign <identity>` as well, or drop --notarize.");return{kind:`notarize`,credential:t.flag,notary:n}}async function notarizeArtifact(t){let{notary:n,credential:S}=t.plan,C=process.platform;if(!n.notarizeOn.includes(C))throw Error(`gjsify ship: notarising the ${n.layoutOs} layout needs ${n.tool}, which runs on ${n.notarizeOn.join(`, `)} and this host is ${C}.`);let N=n.args(S,t.artifact);t.verbose&&t.log(`${n.tool} ${N.join(` `)}`);let F=await spawnToCompletion(n.tool,N,{completion:`return`,stdio:`inherit`,notFound:()=>Error(`gjsify ship: \`${n.tool}\` is not on PATH — ${n.installHint}.`)});if(F.code!==0)throw Error(`gjsify ship: ${n.tool} notarytool failed with ${describeExit(F)}.`);t.log(`${n.tool} notarytool accepted ${t.artifact}.`)}async function stapleArtifact(t){let n=[`stapler`,`staple`,t.artifact];t.verbose&&t.log(`${t.notary.tool} ${n.join(` `)}`);let S=await spawnToCompletion(t.notary.tool,n,{completion:`return`,stdio:`inherit`,notFound:()=>Error(`gjsify ship: \`${t.notary.tool}\` is not on PATH — ${t.notary.installHint}.`)});if(S.code!==0)throw Error(`gjsify ship: ${t.notary.tool} stapler failed with ${describeExit(S)}. The artifact is notarised and NOT stapled, which means every launch asks Gatekeeper to check online — and fails closed on a machine with no network. Re-run the finish phase; \`stapler\` requires internet access and the ticket may not have propagated yet.`);t.log(`${t.notary.tool} stapler attached the ticket to ${t.artifact}.`)}var IW,LW,RW=__esmMin(()=>{ef(),qn(),ZI(),sv(),CU(),oU(),zH(),FW(),IW={darwin:{layoutOs:`darwin`,tool:`codesign`,signOn:[`darwin`],installHint:"install the Xcode Command Line Tools (`xcode-select --install`) on a macOS host",signs:`macho`,args:({identity:t,file:n,entitlements:S,adhoc:C,seal:N})=>{let F=N?void 0:asciiCodesignIdentifier(n);return[`--force`,`--sign`,t,`--options`,`runtime`,...S===void 0?[]:[`--entitlements`,S],...C?[]:[`--timestamp`],...F===void 0?[]:[`--identifier`,F],n]},entitlements:t=>[`com.apple.security.cs.allow-jit`,`com.apple.security.cs.allow-unsigned-executable-memory`,`com.apple.security.cs.disable-executable-page-protection`,`com.apple.security.cs.allow-dyld-environment-variables`,...t?[`com.apple.security.cs.disable-library-validation`]:[]],sealsBundle:!0,sealAddPrefix:t=>`${t}/Contents/_CodeSignature/`,configKey:`gjsify.ship.sign.darwin.identity`,gap:"the images are signed and the bundle is sealed, and the seal survives both the `.zip` and the `.dmg` round trip; § A16 stands measured in ONE direction only — library validation refuses an ad-hoc-signed dylib, so the ad-hoc identity grants `disable-library-validation` while a named one does not; a named Developer ID was signed and notarised on 2026-10-30 for an ASCII-named app, and a non-ASCII image name verifies only with the explicit ASCII `--identifier` this signer now passes"},win32:{layoutOs:`win32`,tool:`signtool`,signOn:[`win32`],installHint:"install the Windows SDK (signtool.exe ships in its `bin/<version>/x64` directory)",signs:`pe`,args:({identity:t,file:n})=>[`sign`,`/n`,t,`/fd`,`sha256`,n],entitlements:()=>[],sealsBundle:!1,sealAddPrefix:()=>``,configKey:`gjsify.ship.sign.win32.identity`,gap:`no timestamp countersignature is requested, so the signature expires with the certificate (UNVERIFIED: no run in this repository has ever invoked signtool)`}},LW={darwin:{layoutOs:`darwin`,tool:`xcrun`,notarizeOn:[`darwin`],installHint:"install the Xcode Command Line Tools (`xcode-select --install`) on a macOS host",args:(t,n)=>[`notarytool`,`submit`,`--keychain-profile`,t,`--wait`,n]}}});function stagedFontDir(t,n){return`${t}/${Tn.basename(rH.fonts)}/${n}`}function shellQuote(t){return`'${t.replace(/'/g,`'\\''`)}'`}function cmdQuote(t){let n=/["%!\r\n]/.exec(t);if(n!==null)throw Error(`gjsify ship: \`gjsify.ship.execArgs\` contains ${JSON.stringify(t)}, and cmd.exe has no way to pass ${JSON.stringify(n[0])} through a Windows launcher literally — \`%\` expands at parse time and \`"\` ends the quoted run. Move the value into the app (it can read it from its own config) or drop the character.`);return`"${t}"`}function renderLauncher(t,n,S,C={}){switch(S.name){case`linux`:return renderPrefixLauncher(t,n,S);case`darwin`:return renderAppBundleLauncher(t,n,S,C);case`windows`:return renderWindowsLauncher(t,n,S,C);default:{let t=S.name;throw Error(`gjsify ship: no launcher is wired for the "${String(t)}" layout.`)}}}function renderPrefixLauncher(t,n,S){let C=S.dirs(t),N=[`#!/bin/sh`,"# Generated by `gjsify ship` — do not edit.",`set -e`,`self=$(readlink -f "$0")`,`prefix=$(dirname "$(dirname "$self")")`,`XDG_DATA_DIRS="$prefix/${C.data}:\${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"`,`export XDG_DATA_DIRS`];if(t.typelibFiles.length>0){let t=`"$prefix"/${C.native}`;for(let n of[`GI_TYPELIB_PATH`,`LD_LIBRARY_PATH`])N.push(`${n}=${t}\${${n}:+:$${n}}`,`export ${n}`)}else if(Object.values(t.formatFiles).some(t=>t.typelibFiles.length>0)){let t=`"$prefix"/${C.native}`;N.push(`if [ -d ${t} ]; then`);for(let n of[`GI_TYPELIB_PATH`,`LD_LIBRARY_PATH`])N.push(` ${n}=${t}\${${n}:+:$${n}}`,` export ${n}`);N.push(`fi`)}return t.localeFiles.length>0&&N.push(`GJSIFY_LOCALE_DIR="$prefix"/${C.data}/locale`,`export GJSIFY_LOCALE_DIR`),t.fontFiles.length>0&&N.push(`GJSIFY_FONT_DIR="$prefix"/${stagedFontDir(C.data,t.appId)}`,`export GJSIFY_FONT_DIR`),N.push(`exec ${execLine(S,`"$prefix"/${C.bundle}/${n}`,t)} "$@"`,``),N.join(`
1187
1187
  `)}function renderAppBundleLauncher(t,n,S,C){let N=`${S.root(t)}/Contents`,F=S.dirs(t),under=t=>Tn.relative(N,t),beside=t=>Tn.relative(F.launcher,t),I=[`#!/bin/sh`,"# Generated by `gjsify ship` — do not edit.",`set -e`,`here=$(cd -- "$(dirname -- "$0")" && pwd)`,`contents=$(dirname -- "$here")`,`XDG_DATA_DIRS="$contents/${under(F.data)}"\${XDG_DATA_DIRS:+:$XDG_DATA_DIRS}`,`export XDG_DATA_DIRS`];C.gtkRuntimeDir!==void 0&&I.push(`GJSIFY_GTK_RUNTIME="$contents/${under(C.gtkRuntimeDir)}"`,`export GJSIFY_GTK_RUNTIME`),C.nodeGiAddon!==void 0&&I.push(`NODE_GI_NATIVE="$contents/${under(C.nodeGiAddon)}"`,`export NODE_GI_NATIVE`),t.typelibFiles.length>0&&(I.push(`GI_TYPELIB_PATH="$contents/${under(F.native)}"\${GI_TYPELIB_PATH:+:$GI_TYPELIB_PATH}`,`export GI_TYPELIB_PATH`),I.push(`GJSIFY_GI_LIBRARY_PATH="$contents/${under(F.native)}"\${GJSIFY_GI_LIBRARY_PATH:+:$GJSIFY_GI_LIBRARY_PATH}`,`export GJSIFY_GI_LIBRARY_PATH`)),t.localeFiles.length>0&&I.push(`GJSIFY_LOCALE_DIR="$contents/${under(F.data)}/locale"`,`export GJSIFY_LOCALE_DIR`),t.fontFiles.length>0&&I.push(`GJSIFY_FONT_DIR="$contents/${stagedFontDir(under(F.data),t.appId)}"`,`export GJSIFY_FONT_DIR`);let H=C.interpreter===void 0?void 0:`"$here/${beside(C.interpreter)}"`;return I.push(`exec ${execLine(S,`"$contents/${under(F.bundle)}/${n}"`,t,H)} "$@"`,``),I.join(`
1188
1188
  `)}function renderWindowsLauncher(t,n,S,C){let N=S.dirs(t),at=t=>`%HERE%${windowsPath(t)}`,F=[`@echo off`,`rem Generated by "gjsify ship" - do not edit.`,`setlocal`,`set "HERE=%~dp0"`,prependVar(`XDG_DATA_DIRS`,at(N.data))];C.gtkRuntimeDir!==void 0&&F.push(`set "GJSIFY_GTK_RUNTIME=${at(C.gtkRuntimeDir)}"`),C.nodeGiAddon!==void 0&&F.push(`set "NODE_GI_NATIVE=${at(C.nodeGiAddon)}"`),t.typelibFiles.length>0&&F.push(prependVar(`GI_TYPELIB_PATH`,at(N.native)),prependVar(`PATH`,at(N.native))),t.localeFiles.length>0&&F.push(`set "GJSIFY_LOCALE_DIR=${at(N.data)}\\locale"`),t.fontFiles.length>0&&F.push(`set "GJSIFY_FONT_DIR=${at(stagedFontDir(N.data,t.appId))}"`);let I=C.interpreter===void 0?void 0:`"${at(C.interpreter)}"`;return F.push(`${execLine(S,`"${at(N.bundle)}\\${windowsPath(n)}"`,t,I)} %*`,``),F.join(`\r
1189
- `)}function prependVar(t,n){return`if defined ${t} (set "${t}=${n};%${t}%") else (set "${t}=${n}")`}function windowsPath(t){return t.split(`/`).filter(t=>t.length>0).join(`\\`)}function execLine(t,n,S,C){let N=t.name===`windows`?cmdQuote:shellQuote,F=S.execArgs.map(N).join(` `),I=C??(S.app===`node`?`node`:`gjs`);return`${S.app===`node`?I:`${I} -m`} ${n}${F?` ${F}`:``}`}var RW=__esmMin(()=>{qn(),rH()});function createCpioArchive(t){let n=[],S=0;t.forEach((t,C)=>{let N=t.linkTarget===void 0?t.data??new Uint8Array:encodeUtf8(t.linkTarget),F=encodeUtf8(`${t.name}\0`),I=buildHeader({ino:t.ino??C+1,mode:t.mode,nlink:t.nlink??1,mtime:t.mtime??0,filesize:N.byteLength,namesize:F.byteLength});S=push(n,I,S),S=push(n,F,S),S=padTo4(n,S),S=push(n,N,S),S=padTo4(n,S)});let C=encodeUtf8(`TRAILER!!!\0`);return S=push(n,buildHeader({ino:0,mode:0,nlink:1,mtime:0,filesize:0,namesize:C.byteLength}),S),S=push(n,C,S),padTo4(n,S),concatBytes(n)}function buildHeader(t){let n=zW+hex8(t.ino)+hex8(t.mode)+hex8(0)+hex8(0)+hex8(t.nlink)+hex8(t.mtime)+hex8(t.filesize)+hex8(0)+hex8(0)+hex8(0)+hex8(0)+hex8(t.namesize)+hex8(0);if(n.length!==BW)throw Error(`gjsify ship: internal error — cpio header is ${n.length} bytes, expected ${BW}.`);return encodeUtf8(n)}function hex8(t){if(t<0||!Number.isInteger(t))throw Error(`gjsify ship: cpio header field must be a non-negative integer, got ${t}.`);let n=t.toString(16).toUpperCase();if(n.length>8)throw Error(`gjsify ship: cpio header field ${t} does not fit in 8 hex digits.`);return n.padStart(8,`0`)}function push(t,n,S){return n.byteLength>0&&t.push(n),S+n.byteLength}function padTo4(t,n){let S=n%4;if(S===0)return n;let C=4-S;return t.push(new Uint8Array(C)),n+C}var zW,BW,VW,HW,UW=__esmMin(()=>{HV(),zW=`070701`,BW=110,VW=32768,HW=16384});function buildRpmHeader(t,n){let S=[...t].sort((t,n)=>t.tag-n.tag),C=[],N=[],F=0;for(let t of S){if(t.tag<100)throw Error(`gjsify ship: rpm tag ${t.tag} is below 100 and would be rejected by hdrchkTag.`);let{data:n,count:S}=encodeValue(t.type,t.value,t.tag),I=qW[t.type],H=(I-F%I)%I;H>0&&(N.push(new Uint8Array(H)),F+=H),C.push({tag:t.tag,type:t.type,offset:F,count:S}),N.push(n),F+=n.byteLength}let I=F,H=C.length+1;N.push(indexEntry(n,7,-(GW*H),KW)),F+=GW;let W=new Uint8Array(WW.byteLength+8+H*GW+F),q=new DataView(W.buffer);W.set(WW,0),q.setUint32(8,H),q.setUint32(12,F);let Y=16;W.set(indexEntry(n,7,I,KW),Y),Y+=GW;for(let t of C)W.set(indexEntry(t.tag,t.type,t.offset,t.count),Y),Y+=GW;for(let t of N)W.set(t,Y),Y+=t.byteLength;return W}function indexEntry(t,n,S,C){let N=new Uint8Array(GW),F=new DataView(N.buffer);return F.setInt32(0,t),F.setInt32(4,n),F.setInt32(8,S),F.setInt32(12,C),N}function encodeValue(t,n,S){let C=new TextEncoder;switch(t){case 6:if(typeof n!=`string`)throw typeMismatch(S,`a string`);return{data:C.encode(`${n}\0`),count:1};case 8:case 9:{let t=typeof n==`string`?[n]:n;if(!Array.isArray(t))throw typeMismatch(S,`a string array`);if(t.length===0)throw Error(`gjsify ship: rpm tag ${S} has an empty array; omit it instead.`);return{data:C.encode(t.map(t=>`${t}\0`).join(``)),count:t.length}}case 7:if(!(n instanceof Uint8Array))throw typeMismatch(S,`binary data`);return{data:n,count:n.byteLength};case 3:case 4:{let C=typeof n==`number`?[n]:n;if(!Array.isArray(C))throw typeMismatch(S,`a number array`);if(C.length===0)throw Error(`gjsify ship: rpm tag ${S} has an empty array; omit it instead.`);let N=t===3?2:4,F=new Uint8Array(C.length*N),I=new DataView(F.buffer);return C.forEach((n,S)=>{t===3?I.setUint16(S*N,n&65535):I.setUint32(S*N,n>>>0)}),{data:F,count:C.length}}}}function typeMismatch(t,n){return Error(`gjsify ship: internal error — rpm tag ${t} expects ${n}.`)}function buildRpmLead(t){let n=new Uint8Array(96),S=new DataView(n.buffer);n.set([237,171,238,219],0),n[4]=3,n[5]=0,S.setInt16(6,0),S.setInt16(8,0);let C=new TextEncoder().encode(t).slice(0,65);return n.set(C,10),S.setInt16(76,0),S.setInt16(78,5),n}function padToEight(t){let n=(8-t.byteLength%8)%8;if(n===0)return t;let S=new Uint8Array(t.byteLength+n);return S.set(t,0),S}var WW,GW,KW,qW,JW=__esmMin(()=>{WW=Uint8Array.from([142,173,232,1,0,0,0,0]),GW=16,KW=16,qW={3:2,4:4,6:1,7:1,8:1,9:1}});async function buildRpm(t){let{settings:n,mtime:S}=t,C=collectFiles(t,`/${t.prefix.replace(/^\/+|\/+$/g,``)}`),N=createCpioArchive(C.map((t,n)=>({name:`.${t.path}`,mode:t.mode,data:t.data,mtime:S,ino:n+1}))),F=await gzipDeterministic(N),I=buildRpmHeader(mainHeaderEntries(t,C,N,F),63),H=concatBytes([I,F]),W=padToEight(buildRpmHeader([{tag:XW.SHA1HEADER,type:6,value:hashHex(`sha1`,I)},{tag:XW.SHA256HEADER,type:6,value:hashHex(`sha256`,I)},{tag:XW.SIZE,type:4,value:[H.byteLength]},{tag:XW.MD5,type:7,value:hashBytes(`md5`,H)},{tag:XW.PAYLOADSIZE,type:4,value:[N.byteLength]}],62));return concatBytes([buildRpmLead(`${n.binaryName}-${n.version}-${n.release}`),W,H])}function collectFiles(t,n){let S=t.payload.map(t=>{if(t.data.byteLength>4294967295)throw Error(`gjsify ship: ${t.path} is larger than 4 GiB, which needs rpm's LONGFILESIZES tag. That is not implemented — split the payload.`);return{path:`${n}/${t.path}`,mode:VW|t.mode&4095,data:t.data,isDirectory:!1}}),C=new Set;for(let t of S){let n=t.path.split(`/`).slice(1);n.pop();let S=``;for(let t of n)S=`${S}/${t}`,eG.has(S)||C.add(S)}for(let t of C)S.push({path:t,mode:HW|493,data:new Uint8Array,isDirectory:!0});return S.sort((t,n)=>t.path<n.path?-1:+(t.path>n.path))}function mainHeaderEntries(t,n,S,C){let{settings:N}=t,F=`${N.version}-${N.release}`,I=[],H=[],W=[];for(let t of n){let n=t.path.lastIndexOf(`/`),S=`${t.path.slice(0,n)}/`,C=I.indexOf(S);C===-1&&(C=I.push(S)-1),H.push(C),W.push(t.path.slice(n+1))}let q=renderRpmScriptlets(readPayloadFacts(t.payload),t.prefix),Y=buildRequires(t.depends,q,readShebangInterpreters(t.payload)),X=buildRecommends(t.recommends??[]),Z=[{tag:YW.HEADERI18NTABLE,type:8,value:[`C`]},{tag:YW.NAME,type:6,value:N.binaryName},{tag:YW.VERSION,type:6,value:N.version},{tag:YW.RELEASE,type:6,value:N.release},{tag:YW.SUMMARY,type:9,value:[N.summary]},{tag:YW.DESCRIPTION,type:9,value:[N.description.join(`
1189
+ `)}function prependVar(t,n){return`if defined ${t} (set "${t}=${n};%${t}%") else (set "${t}=${n}")`}function windowsPath(t){return t.split(`/`).filter(t=>t.length>0).join(`\\`)}function execLine(t,n,S,C){let N=t.name===`windows`?cmdQuote:shellQuote,F=S.execArgs.map(N).join(` `),I=C??(S.app===`node`?`node`:`gjs`);return`${S.app===`node`?I:`${I} -m`} ${n}${F?` ${F}`:``}`}var zW=__esmMin(()=>{qn(),iH()});function createCpioArchive(t){let n=[],S=0;t.forEach((t,C)=>{let N=t.linkTarget===void 0?t.data??new Uint8Array:encodeUtf8(t.linkTarget),F=encodeUtf8(`${t.name}\0`),I=buildHeader({ino:t.ino??C+1,mode:t.mode,nlink:t.nlink??1,mtime:t.mtime??0,filesize:N.byteLength,namesize:F.byteLength});S=push(n,I,S),S=push(n,F,S),S=padTo4(n,S),S=push(n,N,S),S=padTo4(n,S)});let C=encodeUtf8(`TRAILER!!!\0`);return S=push(n,buildHeader({ino:0,mode:0,nlink:1,mtime:0,filesize:0,namesize:C.byteLength}),S),S=push(n,C,S),padTo4(n,S),concatBytes(n)}function buildHeader(t){let n=BW+hex8(t.ino)+hex8(t.mode)+hex8(0)+hex8(0)+hex8(t.nlink)+hex8(t.mtime)+hex8(t.filesize)+hex8(0)+hex8(0)+hex8(0)+hex8(0)+hex8(t.namesize)+hex8(0);if(n.length!==VW)throw Error(`gjsify ship: internal error — cpio header is ${n.length} bytes, expected ${VW}.`);return encodeUtf8(n)}function hex8(t){if(t<0||!Number.isInteger(t))throw Error(`gjsify ship: cpio header field must be a non-negative integer, got ${t}.`);let n=t.toString(16).toUpperCase();if(n.length>8)throw Error(`gjsify ship: cpio header field ${t} does not fit in 8 hex digits.`);return n.padStart(8,`0`)}function push(t,n,S){return n.byteLength>0&&t.push(n),S+n.byteLength}function padTo4(t,n){let S=n%4;if(S===0)return n;let C=4-S;return t.push(new Uint8Array(C)),n+C}var BW,VW,HW,UW,WW=__esmMin(()=>{UV(),BW=`070701`,VW=110,HW=32768,UW=16384});function buildRpmHeader(t,n){let S=[...t].sort((t,n)=>t.tag-n.tag),C=[],N=[],F=0;for(let t of S){if(t.tag<100)throw Error(`gjsify ship: rpm tag ${t.tag} is below 100 and would be rejected by hdrchkTag.`);let{data:n,count:S}=encodeValue(t.type,t.value,t.tag),I=JW[t.type],H=(I-F%I)%I;H>0&&(N.push(new Uint8Array(H)),F+=H),C.push({tag:t.tag,type:t.type,offset:F,count:S}),N.push(n),F+=n.byteLength}let I=F,H=C.length+1;N.push(indexEntry(n,7,-(KW*H),qW)),F+=KW;let W=new Uint8Array(GW.byteLength+8+H*KW+F),q=new DataView(W.buffer);W.set(GW,0),q.setUint32(8,H),q.setUint32(12,F);let Y=16;W.set(indexEntry(n,7,I,qW),Y),Y+=KW;for(let t of C)W.set(indexEntry(t.tag,t.type,t.offset,t.count),Y),Y+=KW;for(let t of N)W.set(t,Y),Y+=t.byteLength;return W}function indexEntry(t,n,S,C){let N=new Uint8Array(KW),F=new DataView(N.buffer);return F.setInt32(0,t),F.setInt32(4,n),F.setInt32(8,S),F.setInt32(12,C),N}function encodeValue(t,n,S){let C=new TextEncoder;switch(t){case 6:if(typeof n!=`string`)throw typeMismatch(S,`a string`);return{data:C.encode(`${n}\0`),count:1};case 8:case 9:{let t=typeof n==`string`?[n]:n;if(!Array.isArray(t))throw typeMismatch(S,`a string array`);if(t.length===0)throw Error(`gjsify ship: rpm tag ${S} has an empty array; omit it instead.`);return{data:C.encode(t.map(t=>`${t}\0`).join(``)),count:t.length}}case 7:if(!(n instanceof Uint8Array))throw typeMismatch(S,`binary data`);return{data:n,count:n.byteLength};case 3:case 4:{let C=typeof n==`number`?[n]:n;if(!Array.isArray(C))throw typeMismatch(S,`a number array`);if(C.length===0)throw Error(`gjsify ship: rpm tag ${S} has an empty array; omit it instead.`);let N=t===3?2:4,F=new Uint8Array(C.length*N),I=new DataView(F.buffer);return C.forEach((n,S)=>{t===3?I.setUint16(S*N,n&65535):I.setUint32(S*N,n>>>0)}),{data:F,count:C.length}}}}function typeMismatch(t,n){return Error(`gjsify ship: internal error — rpm tag ${t} expects ${n}.`)}function buildRpmLead(t){let n=new Uint8Array(96),S=new DataView(n.buffer);n.set([237,171,238,219],0),n[4]=3,n[5]=0,S.setInt16(6,0),S.setInt16(8,0);let C=new TextEncoder().encode(t).slice(0,65);return n.set(C,10),S.setInt16(76,0),S.setInt16(78,5),n}function padToEight(t){let n=(8-t.byteLength%8)%8;if(n===0)return t;let S=new Uint8Array(t.byteLength+n);return S.set(t,0),S}var GW,KW,qW,JW,YW=__esmMin(()=>{GW=Uint8Array.from([142,173,232,1,0,0,0,0]),KW=16,qW=16,JW={3:2,4:4,6:1,7:1,8:1,9:1}});async function buildRpm(t){let{settings:n,mtime:S}=t,C=collectFiles(t,`/${t.prefix.replace(/^\/+|\/+$/g,``)}`),N=createCpioArchive(C.map((t,n)=>({name:`.${t.path}`,mode:t.mode,data:t.data,mtime:S,ino:n+1}))),F=await gzipDeterministic(N),I=buildRpmHeader(mainHeaderEntries(t,C,N,F),63),H=concatBytes([I,F]),W=padToEight(buildRpmHeader([{tag:ZW.SHA1HEADER,type:6,value:hashHex(`sha1`,I)},{tag:ZW.SHA256HEADER,type:6,value:hashHex(`sha256`,I)},{tag:ZW.SIZE,type:4,value:[H.byteLength]},{tag:ZW.MD5,type:7,value:hashBytes(`md5`,H)},{tag:ZW.PAYLOADSIZE,type:4,value:[N.byteLength]}],62));return concatBytes([buildRpmLead(`${n.binaryName}-${n.version}-${n.release}`),W,H])}function collectFiles(t,n){let S=t.payload.map(t=>{if(t.data.byteLength>4294967295)throw Error(`gjsify ship: ${t.path} is larger than 4 GiB, which needs rpm's LONGFILESIZES tag. That is not implemented — split the payload.`);return{path:`${n}/${t.path}`,mode:HW|t.mode&4095,data:t.data,isDirectory:!1}}),C=new Set;for(let t of S){let n=t.path.split(`/`).slice(1);n.pop();let S=``;for(let t of n)S=`${S}/${t}`,tG.has(S)||C.add(S)}for(let t of C)S.push({path:t,mode:UW|493,data:new Uint8Array,isDirectory:!0});return S.sort((t,n)=>t.path<n.path?-1:+(t.path>n.path))}function mainHeaderEntries(t,n,S,C){let{settings:N}=t,F=`${N.version}-${N.release}`,I=[],H=[],W=[];for(let t of n){let n=t.path.lastIndexOf(`/`),S=`${t.path.slice(0,n)}/`,C=I.indexOf(S);C===-1&&(C=I.push(S)-1),H.push(C),W.push(t.path.slice(n+1))}let q=renderRpmScriptlets(readPayloadFacts(t.payload),t.prefix),Y=buildRequires(t.depends,q,readShebangInterpreters(t.payload)),X=buildRecommends(t.recommends??[]),Z=[{tag:XW.HEADERI18NTABLE,type:8,value:[`C`]},{tag:XW.NAME,type:6,value:N.binaryName},{tag:XW.VERSION,type:6,value:N.version},{tag:XW.RELEASE,type:6,value:N.release},{tag:XW.SUMMARY,type:9,value:[N.summary]},{tag:XW.DESCRIPTION,type:9,value:[N.description.join(`
1190
1190
 
1191
- `)]},{tag:YW.BUILDTIME,type:4,value:[t.mtime]},{tag:YW.BUILDHOST,type:6,value:`localhost`},{tag:YW.SIZE,type:4,value:[n.reduce((t,n)=>t+n.data.byteLength,0)]},{tag:YW.LICENSE,type:6,value:N.license},{tag:YW.GROUP,type:9,value:[N.group]},{tag:YW.OS,type:6,value:`linux`},{tag:YW.ARCH,type:6,value:t.archLabel},{tag:YW.SOURCERPM,type:6,value:`${N.binaryName}-${F}.src.rpm`},{tag:YW.RPMVERSION,type:6,value:`4.20.0`},{tag:YW.ENCODING,type:6,value:`utf-8`},{tag:YW.FILESIZES,type:4,value:n.map(t=>t.data.byteLength)},{tag:YW.FILEMODES,type:3,value:n.map(t=>t.mode)},{tag:YW.FILERDEVS,type:3,value:n.map(()=>0)},{tag:YW.FILEMTIMES,type:4,value:n.map(()=>t.mtime)},{tag:YW.FILEDIGESTS,type:8,value:n.map(t=>t.isDirectory?``:hashHex(`sha256`,t.data))},{tag:YW.FILELINKTOS,type:8,value:n.map(()=>``)},{tag:YW.FILEFLAGS,type:4,value:n.map(()=>0)},{tag:YW.FILEUSERNAME,type:8,value:n.map(()=>`root`)},{tag:YW.FILEGROUPNAME,type:8,value:n.map(()=>`root`)},{tag:YW.FILEVERIFYFLAGS,type:4,value:n.map(()=>4294967295)},{tag:YW.FILEDEVICES,type:4,value:n.map(()=>1)},{tag:YW.FILEINODES,type:4,value:n.map((t,n)=>n+1)},{tag:YW.FILELANGS,type:8,value:n.map(()=>``)},{tag:YW.FILEDIGESTALGO,type:4,value:[QW]},{tag:YW.DIRINDEXES,type:4,value:H},{tag:YW.BASENAMES,type:8,value:W},{tag:YW.DIRNAMES,type:8,value:I},{tag:YW.PROVIDENAME,type:8,value:[N.binaryName]},{tag:YW.PROVIDEFLAGS,type:4,value:[ZW.EQUAL]},{tag:YW.PROVIDEVERSION,type:8,value:[F]},{tag:YW.REQUIRENAME,type:8,value:Y.names},{tag:YW.REQUIREFLAGS,type:4,value:Y.flags},{tag:YW.REQUIREVERSION,type:8,value:Y.versions},...X.names.length>0?[{tag:YW.RECOMMENDNAME,type:8,value:X.names},{tag:YW.RECOMMENDFLAGS,type:4,value:X.flags},{tag:YW.RECOMMENDVERSION,type:8,value:X.versions}]:[],{tag:YW.PAYLOADFORMAT,type:6,value:`cpio`},{tag:YW.PAYLOADCOMPRESSOR,type:6,value:`gzip`},{tag:YW.PAYLOADFLAGS,type:6,value:`9`},{tag:YW.PAYLOADDIGEST,type:8,value:[hashHex(`sha256`,C)]},{tag:YW.PAYLOADDIGESTALGO,type:4,value:[QW]},{tag:YW.PAYLOADDIGESTALT,type:8,value:[hashHex(`sha256`,S)]}];return assertParallelFileArrays(Z,n.length),N.homepage&&Z.push({tag:YW.URL,type:6,value:N.homepage}),q.post!==void 0&&(Z.push({tag:YW.POSTIN,type:6,value:q.post}),Z.push({tag:YW.POSTINPROG,type:6,value:`/bin/sh`})),q.postun!==void 0&&(Z.push({tag:YW.POSTUN,type:6,value:q.postun}),Z.push({tag:YW.POSTUNPROG,type:6,value:`/bin/sh`})),Z}function assertParallelFileArrays(t,n){let S=new Set([YW.FILESIZES,YW.FILEMODES,YW.FILERDEVS,YW.FILEMTIMES,YW.FILEDIGESTS,YW.FILELINKTOS,YW.FILEFLAGS,YW.FILEUSERNAME,YW.FILEGROUPNAME,YW.FILEVERIFYFLAGS,YW.FILEDEVICES,YW.FILEINODES,YW.FILELANGS,YW.DIRINDEXES,YW.BASENAMES]);for(let C of t){if(!S.has(C.tag))continue;let t=Array.isArray(C.value)?C.value.length:1;if(t!==n)throw Error(`gjsify ship: internal error — rpm tag ${C.tag} has ${t} values for ${n} files.`)}}function buildRequires(t,n,S){let C=[],N=[],F=[];for(let n of t){let t=parseDepend(n);C.push(t.name),N.push(senseFor(t.relation)),F.push(t.version??``)}n.post!==void 0&&(C.push(`/bin/sh`),N.push(ZW.INTERP|ZW.SCRIPT_POST),F.push(``)),n.postun!==void 0&&(C.push(`/bin/sh`),N.push(ZW.INTERP|ZW.SCRIPT_POSTUN),F.push(``));for(let t of S)C.push(t),N.push(ZW.FIND_REQUIRES),F.push(``);for(let[t,n]of $W)C.push(t),N.push(ZW.RPMLIB|ZW.LESS|ZW.EQUAL),F.push(n);return{names:C,flags:N,versions:F}}function buildRecommends(t){let n=[],S=[],C=[];for(let N of t){let t=parseDepend(N);n.push(t.name),S.push(senseFor(t.relation)),C.push(t.version??``)}return{names:n,flags:S,versions:C}}function senseFor(t){switch(t){case`>=`:return ZW.GREATER|ZW.EQUAL;case`>`:return ZW.GREATER;case`<=`:return ZW.LESS|ZW.EQUAL;case`<`:return ZW.LESS;case`=`:return ZW.EQUAL;default:return 0}}function hashHex(t,n){return createHash(t).update(n).digest(`hex`)}function hashBytes(t,n){return new Uint8Array(createHash(t).update(n).digest())}var YW,XW,ZW,QW,$W,eG,tG=__esmMin(()=>{fl(),HV(),UW(),eH(),aU(),JW(),tH(),iH(),rH(),YW={HEADERI18NTABLE:100,NAME:1e3,VERSION:1001,RELEASE:1002,SUMMARY:1004,DESCRIPTION:1005,BUILDTIME:1006,BUILDHOST:1007,SIZE:1009,LICENSE:1014,GROUP:1016,URL:1020,OS:1021,ARCH:1022,POSTIN:1024,POSTUN:1026,FILESIZES:1028,FILEMODES:1030,FILERDEVS:1033,FILEMTIMES:1034,FILEDIGESTS:1035,FILELINKTOS:1036,FILEFLAGS:1037,FILEUSERNAME:1039,FILEGROUPNAME:1040,SOURCERPM:1044,FILEVERIFYFLAGS:1045,PROVIDENAME:1047,REQUIREFLAGS:1048,REQUIRENAME:1049,REQUIREVERSION:1050,RECOMMENDNAME:5046,RECOMMENDVERSION:5047,RECOMMENDFLAGS:5048,RPMVERSION:1064,POSTINPROG:1086,POSTUNPROG:1088,FILEDEVICES:1095,FILEINODES:1096,FILELANGS:1097,PROVIDEFLAGS:1112,PROVIDEVERSION:1113,DIRINDEXES:1116,BASENAMES:1117,DIRNAMES:1118,PAYLOADFORMAT:1124,PAYLOADCOMPRESSOR:1125,PAYLOADFLAGS:1126,FILEDIGESTALGO:5011,ENCODING:5062,PAYLOADDIGEST:5092,PAYLOADDIGESTALGO:5093,PAYLOADDIGESTALT:5097},XW={SIZE:1e3,MD5:1004,PAYLOADSIZE:1007,SHA1HEADER:269,SHA256HEADER:273},ZW={LESS:2,GREATER:4,EQUAL:8,INTERP:256,SCRIPT_POST:1024,SCRIPT_POSTUN:4096,FIND_REQUIRES:16384,RPMLIB:1<<24},QW=8,$W=[[`rpmlib(CompressedFileNames)`,`3.0.4-1`],[`rpmlib(FileDigests)`,`4.6.0-1`],[`rpmlib(PayloadFilesHavePrefix)`,`4.0-1`]],eG=new Set([`/usr`,`/usr/bin`,`/usr/lib`,`/usr/lib64`,`/usr/libexec`,`/usr/sbin`,`/usr/share`,`/usr/${nH.applications}`,`/usr/share/doc`,`/usr/share/icons`,`/usr/share/licenses`,`/usr/share/man`,`/usr/${nH.metainfo}`,`/usr/share/glib-2.0`,`/usr/${nH.schemas}`,`/usr/${nH.fonts}`,`/etc`,`/opt`,`/var`])});async function assemble(t){let n=process.cwd(),S=t.os===void 0?hostLayout():resolveLayout(t.os),C=await new Config().forCommand(n),N=C.ship??{},F=C.flatpak??{},I=resolveShipApp({project:C.app,perTarget:N.app,layoutOs:S.os}),H=I.app;I.overridden&&ge.log(`${nG} runtime for ${S.name}: ${H} — \`${I.key}\` overrides \`gjsify.app${C.app===void 0?``:`: "${C.app}"`}\`.`);let W=readPackageJson$2(In(n,`package.json`))??{},q,Y=[];if(t.target!==void 0)q=resolveFormats(t.target,S);else if(N.targets!==void 0){let t=configuredFormats(N.targets,S);q=t.formats,t.dropped.length>0&&ge.log(`${nG} \`gjsify.ship.targets\` names ${t.dropped.join(`, `)}, which wrap another layout — not built for ${S.name}. Pass --target to ask for one explicitly.`)}else{let t=defaultFormatIds(S.os).map(t=>dW[t]);q=t.filter(t=>t.interpreters.includes(H)),Y=t.filter(t=>!t.interpreters.includes(H)),Y.length>0&&ge.log(`${nG} ${Y.map(t=>t.id).join(`, `)} wrap the ${S.name} layout but cannot run \`${H}\`, which \`${I.key}\` resolves to — ${Y[0]?.interpreterGap??``}. Set \`gjsify.ship.app.${S.os}\` to "${Y[0]?.interpreters.join(`" / "`)}" to ship this OS on that runtime; it leaves every other target on \`gjsify.app\`. Assembling the layout only; pass --target to be told the same thing as an error.`)}q.some(t=>t.id===`flatpak`)&&assertNoDroppedFlatpakModules(F),t.stage||assertPackable(q,S,t.os===void 0?`host`:`positional`,Y);let X=resolveSignPlan({flag:t.sign,config:N.sign,layoutOs:S.os}),Z=resolveNotaryPlan({flag:t.notarize,layoutOs:S.os,sign:X});if(t.stage&&assertNothingToSignYet(t),t.stage||(announceSigning(X,Z),X.kind===`sign`&&assertHostCanSign(X.signer)),t.stage||assertKindCanPack(q,resolveShipKind(N,F)),!t.stage)for(let t of q)assertCanPack(t);let te=parseDeclaredChannel(t.channel,`--channel`)??parseDeclaredChannel(N.channel,`gjsify.ship.channel`)??(q.some(t=>t.id===`flatpak`)?`flathub`:void 0);t[`skip-build`]||await runProjectBuild(n,te);let ne=resolveShipBundle({pkg:W,ship:N,layoutOs:S.os});ne.overridden&&ge.log(`${nG} entry for ${S.name}: ${ne.declared} — \`${ne.key}\` overrides \`gjsify.main\`.`);let re=discoverPayload({projectDir:n,pkg:W,ship:N,flatpakIcon:F.icon,declaredBundle:ne.declared,layoutOs:S.os,foreignBundles:ne.foreign}),{settings:ie,metadata:ae,warnings:oe}=resolveShipSettings({projectDir:n,pkg:W,ship:N,flatpak:F,cli:{outDir:t.out,arch:t.arch,layoutOs:S.os},discovered:re,app:H});for(let t of oe)ge.warn(`${nG} ${t}`);for(let t of q)assertFormatCanRunInterpreter(t,ie.app);let Q=readFileSync(ie.bundlePath,`utf-8`);assertEntryRunsUnder({interpreter:ie.app,source:Q,entry:Ln(n,ie.bundlePath)||ie.bundlePath,appKey:I.key,bundleKey:ne.key,layoutOs:S.os});let se=buildTimestamp(ie.bundlePath),ce={appId:ie.appId,name:ie.name,command:ie.binaryName,kind:ie.kind,metadata:ae,channel:te,configKey:`gjsify.ship`,copyrightYear:new Date(se*1e3).getUTCFullYear()};for(let t of validateAppMetadata(ce))ge.warn(`${nG} ${t.field} is not set — ${t.hint}`);ie.licenseFile!==void 0&&zn(ie.licenseFile)!==n&&ge.log(`${nG} licence text from ${Ln(n,ie.licenseFile)} (this package carries none of its own)`);let le=localizeMetadata({metainfo:ie.kind===`app`?renderMetainfoApp$1(ce):renderMetainfoCli$1(ce),desktopEntry:ie.kind===`app`?renderDesktopEntry(ce):void 0},ie.localeFiles),ue=await resolveCarriedRuntime(S,ie,n);carryNodeModules(ue,S,ie,n,N.nodeModules,N.nodeModulesExclude);let de=stageSubordinates({layout:S,identity:ie,nestedBundles:ie.nestedBundles,helperExecutables:ie.helperExecutables}),fe={bundleFiles:re.bundleFiles,launcher:renderLauncher(ie,Bn(ie.bundlePath),S,ue.launcher),executableLaunchers:Object.fromEntries(ie.executables.map(t=>[t.name,renderLauncher(ie,t.entry,S,ue.launcher)])),metainfo:le.metainfo,desktopEntry:le.desktopEntry,licenseText:ie.licenseFile===void 0?void 0:readFileSync(ie.licenseFile,`utf-8`),changelogText:ie.changelogFile===void 0?void 0:readFileSync(ie.changelogFile,`utf-8`),mtime:se},pe=Nn(n,ie.outDir),me=In(pe,`stage`),he=[...planStage(ie,fe),...S.os===`linux`?[]:await compileSchemasForStage({schemaFiles:ie.schemaFiles,workDir:In(pe,`schemas`)})],_e=ie.kind===`app`&&S.icon!==void 0&&(S.icon.required||ie.iconFiles.length>0)?await resolveAppIcon({iconFiles:ie.iconFiles,appId:ie.appId,sizes:S.icon.sizes,target:S.icon.writes}):void 0;_e!==void 0&&ge.log(`${nG} icon: ${iconSizes(_e).join(`/`)} px, ${_e.source}`);let ve=placeStage(S,{...ie,icon:_e},he,[...ue.files,...de.files]);if(writeStage(me,ve),ge.log(`${nG} staged ${ve.length} file(s) for ${S.name} in ${Ln(n,me)}/`),t.verbose)for(let t of ve)ge.log(`${nG} ${t.path}`);if(assertPayloadMatchesArch(readStage([me],ve),ie.arch,{exempt:payloadArchExemptions(S.os,ie)}),S.os!==`linux`){let t=linuxInstallDependent(he);if(t.length>0){ge.warn(`${nG} the ${S.name} layout carries ${t.length} file(s) whose Linux correctness comes from a package install step it has no equivalent for:`);let n={aborts:`ABORTS: `,unknown:`UNCLASSIFIED: `,inert:``};for(let{path:S,verdict:C,why:N}of t)ge.warn(`${nG} ${n[C]??``}${S} — ${N}`)}for(let t of ue.found)ge.log(`${nG} carries its own ${t}`);for(let t of ue.missing)ge.warn(`${nG} ${t}`);ue.launcher.interpreter===void 0&&S.runtimeGap!==void 0&&ge.warn(`${nG} ${S.runtimeGap}`),S.fontGap!==void 0&&he.some(t=>isUnder(t.path,nH.fonts))&&ge.warn(`${nG} ${S.fontGap}`),S.arches!==null&&!S.arches.only.includes(ie.arch)&&ge.warn(`${nG} this stage is labelled ${ie.arch} and the ${S.name} layout has no runtime for it — ${S.arches.why}. Nothing can pack this stage; \`--arch ${S.arches.only.join(`|`)}\` is what produces an artifact.`)}let ye=scanGiRequirements(Q),be=ye.namespaces,xe=ye.optional;if(t.verbose){let t=be.filter(t=>!xe.includes(t));ge.log(`${nG} gi namespaces: ${be.join(`, `)||`(none)`}`),xe.length>0&&(ge.log(`${nG} gi optional namespaces: ${xe.join(`, `)}`),ge.log(`${nG} gi required namespaces: ${t.join(`, `)||`(none)`}`))}let Se=new Map;for(let t of q)Se.set(t.id,(await planOverlay(ie,t,fe)).map(t=>({...t,path:place(S,ie,t.path)})));let Ce=readPayloadFacts(he);for(let t of q){if(t.depends===null)continue;let n=deriveDepends(t.depends,{namespaces:be,optionalNamespaces:xe,hasIcons:Ce.hasIcons,hasSchemas:Ce.hasSchemas,interpreter:ie.app,extra:ie.extraDepends[t.depends],typelibPackages:ie.typelibPackages,bundledTypelibs:Ce.bundledTypelibs,minGjsVersion:ie.minGjsVersion,minNodeVersion:ie.minNodeVersion});for(let S of n.unmappedOptional)ge.warn(`${nG} gi://${S} is imported optionally, but no ${t.depends} package is known to ship its typelib, so no Recommends entry names it. The package builds and runs without it. Add the row if the namespace should be recommended: \`gjsify.ship.typelibPackages.${S} = { "${t.depends}": "…" }\`.`);let S=ie.app===`node`?warnAboutNodeFloor(t.depends,ie.minNodeVersion):warnAboutGjsFloor(t.depends,ie.minGjsVersion);for(let t of S)ge.warn(`${nG} ${t}`)}let we=writeStageManifest({stageDir:me,settings:ie,formats:q,mtime:se,namespaces:be,optionalNamespaces:xe,staged:ve,overlay:Se});if(t.stage){let t=Y.length>0?`(none — ${Y.map(t=>t.id).join(` and `)} need \`gjsify.ship.app.${S.os}: "node"\`)`:formatIdsFor(S.os).length===0?`(none — no format wraps the ${S.name} layout)`:`(none asked for)`,n=we.formats.join(`, `)||t;ge.log(`${nG} stage manifest: ${formatTarget(we.target)}, formats ${n}`);return}let Te=[];for(let n of q)Te.push(await packOne({format:n,settings:ie,arch:ie.arch,staged:ve,overlay:Se.get(n.id)??[],stageDir:me,outRoot:pe,namespaces:be,optionalNamespaces:xe,mtime:se,sign:X,notarize:Z,verbose:t.verbose}));printArtifacts(n,Te)}function assertNothingToSignYet(t){let n=t.sign===void 0?t.notarize===void 0?void 0:`--notarize`:`--sign`;if(n!==void 0)throw Error(`gjsify ship: ${n} belongs to the finish phase, and --stage produces no artifact to sign — it writes the tree a packing host reads back. Assemble here, then run \`gjsify ship --from-stage <dir> --sign <identity>\` on the host that holds the identity (ADR 0024 § A2, § A14).`)}function announceSigning(t,n){t.kind===`skip`&&ge.warn(`${nG} ${t.message}`),n.kind===`skip`&&t.kind===`sign`&&ge.warn(`${nG} ${n.message}`)}async function resolveCarriedRuntime(t,n,S){let C={files:[],launcher:{},found:[],missing:[]};if(t.os===`linux`||n.app!==`node`)return C;let N=`${t.os}-${n.arch}`;if(!isGtkRuntimeTarget(N))return C;let F=await acquireGtkRuntime({target:N,version:cliVersion(),discovery:{cwd:S},ensure:async S=>(await ensurePkgDir(parseSpec(S),{verbose:!1,cacheMaxAge:iG,frozen:!1,platform:{os:t.os,cpu:n.arch}})).pkgDir,log:t=>ge.log(`${nG} ${t}`)});return stageAppRuntime({layout:t,identity:n,target:N,cwd:S,interpreter:isNodeRuntimeTarget(N)?resolveNodeRuntime(N,{cwd:S}):null,...F.kind===`fetched`?{fetchedGtkRuntimeDir:F.dir}:{},...F.kind===`failed`?{gtkFetchFailure:F.reason}:{}})}function carryNodeModules(t,n,S,C,N,F){if(N===void 0||N.length===0||S.app!==`node`)return;let I=resolveNodeModulesClosure(N,C,{target:{os:n.os,cpu:S.arch},exclude:F});t.files.push(...stageNodeModules(I,n.dirs(S).bundle)),t.found.push(`node_modules: ${I.packages.length} package(s) for ${N.join(`, `)}`),I.excluded.length>0&&ge.log(`${nG} node_modules: left out by gjsify.ship.nodeModulesExclude: ${I.excluded.join(`, `)}`),I.skippedForTarget.length>0&&ge.log(`${nG} node_modules: left out, installed but built for another platform than ${n.os}-${S.arch}: `+I.skippedForTarget.join(`, `)),I.skippedOptional.length>0&&ge.log(`${nG} node_modules: ${I.skippedOptional.length} optional dependenc(ies) not installed, so not carried (other platforms' builds): ${I.skippedOptional.join(`, `)}`)}async function finishFromStage(t,n){if(t.stage)throw Error("gjsify ship: --stage and --from-stage are the two halves of one split and cannot run together. `--stage` assembles a payload and stops; `--from-stage <dir>` packs one that is already assembled. Run them as two commands, on the host each belongs on (ADR 0024 § A2).");if(t[`skip-build`])throw Error(`gjsify ship: --from-stage never runs a build — the payload it packs was built and staged by an earlier run — so --skip-build has nothing to skip. Drop it.`);if(t.arch!==void 0)throw Error("gjsify ship: --arch is decided when the stage is assembled, not when it is packed: the launcher, the payload and the recorded target were all fixed then. Pass --arch to `gjsify ship --stage`, and use `--expect-target <os>-<arch>` here to assert which leg you are packing.");if(t.os!==void 0)throw Error(`gjsify ship: the layout is decided when the stage is assembled, so "${t.os}" has nothing to change here — the staged tree already IS one OS's layout. Use \`--expect-target <os>-<arch>\` to assert which one you are packing.`);let S=process.cwd(),C=Nn(S,n),N=readStageManifest(C);assertExpectedTarget(N,t[`expect-target`]);let F=layoutForOs(N.target.os);t.target===void 0&&assertPackable(N.formats.map(t=>dW[t]),F,`stage`,defaultFormatIds(F.os).map(t=>dW[t]).filter(t=>!t.interpreters.includes(N.settings.app)));let I=resolveFormats(t.target??N.formats,F);assertFormatsStaged(N,I);for(let t of I)assertCanPack(t);let H=resolveSignPlan({flag:t.sign,layoutOs:F.os}),W=resolveNotaryPlan({flag:t.notarize,layoutOs:F.os,sign:H});announceSigning(H,W),H.kind===`sign`&&assertHostCanSign(H.signer);for(let t of warnOnToolSkew(N))ge.warn(`${nG} ${t}`);let{mtime:q,warnings:Y}=resolveStageMtime(N);for(let t of Y)ge.warn(`${nG} ${t}`);if(ge.log(`${nG} packing ${N.settings.binaryName} ${N.settings.version}-${N.settings.release} for ${formatTarget(N.target)} from ${Ln(S,C)||`.`}/`),t.verbose){for(let t of N.staged)ge.log(`${nG} ${t.path}`);ge.log(`${nG} gi namespaces: ${N.namespaces.join(`, `)||`(none)`}`),(N.optionalNamespaces??[]).length>0&&ge.log(`${nG} gi optional namespaces: ${N.optionalNamespaces?.join(`, `)}`)}let X=t.out===void 0?zn(C):Nn(S,t.out),Z=[];for(let n of I){if(assertFormatCanRunInterpreter(n,N.settings.app),n.depends!==null){let t=N.settings.app===`node`?warnAboutNodeFloor(n.depends,N.settings.minNodeVersion):warnAboutGjsFloor(n.depends,N.settings.minGjsVersion);for(let n of t)ge.warn(`${nG} ${n}`)}Z.push(await packOne({format:n,settings:N.settings,arch:N.target.arch,staged:N.staged,overlay:overlayFiles(N,n.id),stageDir:C,outRoot:X,namespaces:N.namespaces,optionalNamespaces:N.optionalNamespaces??[],mtime:q,sign:H,notarize:W,verbose:t.verbose}))}printArtifacts(S,Z)}async function packOne(t){let{format:n,settings:S,stageDir:C,outRoot:N,mtime:F}=t;assertOverlayIsLicensed(n.id,S.binaryName,t.overlay);let I=In(N,`overlay`,n.id);writeStage(I,t.overlay);let H=readStage([C,I],[...t.staged,...t.overlay]),W=readPayloadFacts(H),q=n.depends===null?{requires:[],recommends:[],unmappedOptional:[]}:deriveDepends(n.depends,{namespaces:t.namespaces,optionalNamespaces:t.optionalNamespaces,hasIcons:W.hasIcons,hasSchemas:W.hasSchemas,interpreter:S.app,extra:S.extraDepends[n.depends],typelibPackages:S.typelibPackages,bundledTypelibs:W.bundledTypelibs,minGjsVersion:S.minGjsVersion,minNodeVersion:S.minNodeVersion}),Y=q.requires,X=q.recommends;assertPayloadMatchesArch(H,t.arch,{exempt:payloadArchExemptions(n.layoutOs,S)});let Z=layoutForOs(n.layoutOs);assertLauncherMatchesInterpreter(H,Z,S,S.app),assertLayoutSupportsArch(Z,t.arch);let te=signedSubordinatesFor(Z,S,S),ne=t.sign.kind===`sign`?await signPayload({payload:H,identity:t.sign.identity,signer:t.sign.signer,workDir:In(N,`signed`,n.id),bundleRoot:Z.root(S),entitlementsPath:In(N,`signed`,`${n.id}.entitlements.plist`),nestedBundles:te.nestedBundles,helperExecutables:te.helperExecutables,verbose:t.verbose,log:t=>ge.log(`${nG} ${t}`)}):H,re=n.archName(t.arch,isArchIndependent(ne)),ie={settings:S,payload:ne,prefix:n.prefix,depends:Y,recommends:X,archLabel:re,mtime:F},ae=In(N,`out`);mkdirSync(ae,{recursive:!0});let oe=In(ae,n.fileName(S,re));switch(n.id){case`deb`:writeFileSync(oe,await buildDeb(ie));break;case`rpm`:writeFileSync(oe,await buildRpm(ie));break;case`flatpak`:await buildFlatpakBundle({settings:S,stageDir:C,overlayDir:I,stageManifestFile:MW,workDir:In(N,`flatpak`),target:oe,archLabel:re,verbose:t.verbose});break;case`appimage`:{let n=appImageHostRequirements({app:S.app,minGjsVersion:S.minGjsVersion,minNodeVersion:S.minNodeVersion,namespaces:t.namespaces,optionalNamespaces:t.optionalNamespaces,bundledTypelibs:W.bundledTypelibs}),C=appDirFor(N),I=appDirPayload(S,ne,n,await compileSchemasForPayload({payload:ne,workDir:In(N,`appimage-schemas`)}));writePayload(C,I,``),stampAppDirTimes(C,I,F),ge.log(`${nG} the AppImage takes these from the host: ${n.join(`, `)}`);let H=findPinnedRuntime(re);ge.log(`${nG} ${appImageRuntimeNotice(re,H)}`),await buildAppImage({appDir:C,target:oe,archLabel:re,runtimeFile:H,workDir:zn(C),verbose:t.verbose});break}case`macos-app`:case`windows-dir`:writePayload(oe,ne,Z.root(S));break;case`macos-app-dmg`:{let n=dmgVolumeDir(N);if(writePayload(n,ne,``),t.notarize.kind===`notarize`){let C=t.notarize,N=In(n,`${S.name}.app`),I=In(zn(n),`bundle-notarize.zip`);await stapleBundleBeforeImage({writeArchive:()=>writeFileSync(I,buildZip(zipEntriesFromPayload(ne),F)),notarize:()=>notarizeArtifact({plan:C,artifact:I,verbose:t.verbose,log:t=>ge.log(`${nG} ${t}`)}),staple:()=>stapleArtifact({notary:C.notary,artifact:N,verbose:t.verbose,log:t=>ge.log(`${nG} ${t}`)})})}addApplicationsLink(n),await buildDmgImage({volumeName:dmgVolumeName(S),sourceDir:n,target:oe,workDir:zn(n),verbose:t.verbose}),t.sign.kind===`sign`&&await signDmgImage({identity:t.sign.identity,file:oe,adhoc:t.sign.identity===`-`,workDir:zn(n),verbose:t.verbose});break}case`macos-app-zip`:writeFileSync(oe,buildZip(zipEntriesFromPayload(ne),F));break;case`windows-dir-zip`:writeFileSync(oe,buildZip(zipEntriesFromPayload(ne,windowsProgramDirName(S)),F));break;case`msi`:{let n=In(N,`msi`);writePayload(In(n,_W),ne,Z.root(S)),await buildMsi({settings:S,files:ne.map(t=>({path:t.path,source:`${_W}/${t.path}`})),programDirName:windowsProgramDirName(S),archLabel:re,workDir:n,target:oe,verbose:t.verbose});break}default:{let t=n.id;throw Error(`gjsify ship: no packer is wired for format "${String(t)}".`)}}let Q=n.artifactKind===`directory`?directorySize(oe):statSync(oe).size,se=!1,ce=!1;if(t.notarize.kind===`notarize`&&(n.artifactKind===`directory`?ge.warn(`${nG} ${n.id} is a directory, and notarytool submits an archive or an installer — not notarised. The container format beside it is what carries the ticket.`):(await notarizeArtifact({plan:t.notarize,artifact:oe,verbose:t.verbose,log:t=>ge.log(`${nG} ${t}`)}),se=!0,canCarryTicket(n.id)?(await stapleArtifact({notary:t.notarize.notary,artifact:oe,verbose:t.verbose,log:t=>ge.log(`${nG} ${t}`)}),ce=!0):ge.warn(`${nG} ${n.id} is notarised and NOT stapled: \`stapler\` takes a UDIF image, a signed flat package or a code-signed bundle, and an archive is none of them. Apple's remedy is to staple each item that went INTO the archive and re-create it — for this artifact that is the \`.app\`, which \`--target macos-app\` writes beside it.`))),n.artifactKind===`file`){let S=writeReleaseRecord({file:oe,format:n.id,os:n.layoutOs,arch:isArchIndependent(ne)?`noarch`:t.arch,signature:recordedSignature(t.sign.kind===`sign`?t.sign.identity:void 0,`-`),notarized:se,stapled:ce,nestedBundles:recordedNestedBundles(ne,te.nestedBundles),generator:`@gjsify/cli ${cliVersion()}`});t.verbose&&ge.log(`${nG} release record: ${S}`)}return{format:n.id,path:oe,size:Q}}function printArtifacts(t,n){for(let S of n)ge.log(`${nG} ${S.format}: ${Ln(t,S.path)} (${S.size} bytes)`)}function assertCanPack(t){assertHostCanFinish(t),assertToolsInstalled(t)}function assertPackable(t,n,S,C=[]){if(t.length>0)return;if(C.length>0)throw Error(`gjsify ship: ${C.map(t=>t.id).join(` and `)} wrap the ${n.name} layout, and neither can run this project — ${C[0]?.interpreterGap??``}.\n Set \`gjsify.ship.app.${n.os}\` to "${C[0]?.interpreters.join(`" / "`)}" — it overrides \`gjsify.app\` for THIS target and\n leaves every other one alone, which is what lets one project be GJS on Linux and Node here.
1191
+ `)]},{tag:XW.BUILDTIME,type:4,value:[t.mtime]},{tag:XW.BUILDHOST,type:6,value:`localhost`},{tag:XW.SIZE,type:4,value:[n.reduce((t,n)=>t+n.data.byteLength,0)]},{tag:XW.LICENSE,type:6,value:N.license},{tag:XW.GROUP,type:9,value:[N.group]},{tag:XW.OS,type:6,value:`linux`},{tag:XW.ARCH,type:6,value:t.archLabel},{tag:XW.SOURCERPM,type:6,value:`${N.binaryName}-${F}.src.rpm`},{tag:XW.RPMVERSION,type:6,value:`4.20.0`},{tag:XW.ENCODING,type:6,value:`utf-8`},{tag:XW.FILESIZES,type:4,value:n.map(t=>t.data.byteLength)},{tag:XW.FILEMODES,type:3,value:n.map(t=>t.mode)},{tag:XW.FILERDEVS,type:3,value:n.map(()=>0)},{tag:XW.FILEMTIMES,type:4,value:n.map(()=>t.mtime)},{tag:XW.FILEDIGESTS,type:8,value:n.map(t=>t.isDirectory?``:hashHex(`sha256`,t.data))},{tag:XW.FILELINKTOS,type:8,value:n.map(()=>``)},{tag:XW.FILEFLAGS,type:4,value:n.map(()=>0)},{tag:XW.FILEUSERNAME,type:8,value:n.map(()=>`root`)},{tag:XW.FILEGROUPNAME,type:8,value:n.map(()=>`root`)},{tag:XW.FILEVERIFYFLAGS,type:4,value:n.map(()=>4294967295)},{tag:XW.FILEDEVICES,type:4,value:n.map(()=>1)},{tag:XW.FILEINODES,type:4,value:n.map((t,n)=>n+1)},{tag:XW.FILELANGS,type:8,value:n.map(()=>``)},{tag:XW.FILEDIGESTALGO,type:4,value:[$W]},{tag:XW.DIRINDEXES,type:4,value:H},{tag:XW.BASENAMES,type:8,value:W},{tag:XW.DIRNAMES,type:8,value:I},{tag:XW.PROVIDENAME,type:8,value:[N.binaryName]},{tag:XW.PROVIDEFLAGS,type:4,value:[QW.EQUAL]},{tag:XW.PROVIDEVERSION,type:8,value:[F]},{tag:XW.REQUIRENAME,type:8,value:Y.names},{tag:XW.REQUIREFLAGS,type:4,value:Y.flags},{tag:XW.REQUIREVERSION,type:8,value:Y.versions},...X.names.length>0?[{tag:XW.RECOMMENDNAME,type:8,value:X.names},{tag:XW.RECOMMENDFLAGS,type:4,value:X.flags},{tag:XW.RECOMMENDVERSION,type:8,value:X.versions}]:[],{tag:XW.PAYLOADFORMAT,type:6,value:`cpio`},{tag:XW.PAYLOADCOMPRESSOR,type:6,value:`gzip`},{tag:XW.PAYLOADFLAGS,type:6,value:`9`},{tag:XW.PAYLOADDIGEST,type:8,value:[hashHex(`sha256`,C)]},{tag:XW.PAYLOADDIGESTALGO,type:4,value:[$W]},{tag:XW.PAYLOADDIGESTALT,type:8,value:[hashHex(`sha256`,S)]}];return assertParallelFileArrays(Z,n.length),N.homepage&&Z.push({tag:XW.URL,type:6,value:N.homepage}),q.post!==void 0&&(Z.push({tag:XW.POSTIN,type:6,value:q.post}),Z.push({tag:XW.POSTINPROG,type:6,value:`/bin/sh`})),q.postun!==void 0&&(Z.push({tag:XW.POSTUN,type:6,value:q.postun}),Z.push({tag:XW.POSTUNPROG,type:6,value:`/bin/sh`})),Z}function assertParallelFileArrays(t,n){let S=new Set([XW.FILESIZES,XW.FILEMODES,XW.FILERDEVS,XW.FILEMTIMES,XW.FILEDIGESTS,XW.FILELINKTOS,XW.FILEFLAGS,XW.FILEUSERNAME,XW.FILEGROUPNAME,XW.FILEVERIFYFLAGS,XW.FILEDEVICES,XW.FILEINODES,XW.FILELANGS,XW.DIRINDEXES,XW.BASENAMES]);for(let C of t){if(!S.has(C.tag))continue;let t=Array.isArray(C.value)?C.value.length:1;if(t!==n)throw Error(`gjsify ship: internal error — rpm tag ${C.tag} has ${t} values for ${n} files.`)}}function buildRequires(t,n,S){let C=[],N=[],F=[];for(let n of t){let t=parseDepend(n);C.push(t.name),N.push(senseFor(t.relation)),F.push(t.version??``)}n.post!==void 0&&(C.push(`/bin/sh`),N.push(QW.INTERP|QW.SCRIPT_POST),F.push(``)),n.postun!==void 0&&(C.push(`/bin/sh`),N.push(QW.INTERP|QW.SCRIPT_POSTUN),F.push(``));for(let t of S)C.push(t),N.push(QW.FIND_REQUIRES),F.push(``);for(let[t,n]of eG)C.push(t),N.push(QW.RPMLIB|QW.LESS|QW.EQUAL),F.push(n);return{names:C,flags:N,versions:F}}function buildRecommends(t){let n=[],S=[],C=[];for(let N of t){let t=parseDepend(N);n.push(t.name),S.push(senseFor(t.relation)),C.push(t.version??``)}return{names:n,flags:S,versions:C}}function senseFor(t){switch(t){case`>=`:return QW.GREATER|QW.EQUAL;case`>`:return QW.GREATER;case`<=`:return QW.LESS|QW.EQUAL;case`<`:return QW.LESS;case`=`:return QW.EQUAL;default:return 0}}function hashHex(t,n){return createHash(t).update(n).digest(`hex`)}function hashBytes(t,n){return new Uint8Array(createHash(t).update(n).digest())}var XW,ZW,QW,$W,eG,tG,nG=__esmMin(()=>{fl(),UV(),WW(),tH(),oU(),YW(),nH(),aH(),iH(),XW={HEADERI18NTABLE:100,NAME:1e3,VERSION:1001,RELEASE:1002,SUMMARY:1004,DESCRIPTION:1005,BUILDTIME:1006,BUILDHOST:1007,SIZE:1009,LICENSE:1014,GROUP:1016,URL:1020,OS:1021,ARCH:1022,POSTIN:1024,POSTUN:1026,FILESIZES:1028,FILEMODES:1030,FILERDEVS:1033,FILEMTIMES:1034,FILEDIGESTS:1035,FILELINKTOS:1036,FILEFLAGS:1037,FILEUSERNAME:1039,FILEGROUPNAME:1040,SOURCERPM:1044,FILEVERIFYFLAGS:1045,PROVIDENAME:1047,REQUIREFLAGS:1048,REQUIRENAME:1049,REQUIREVERSION:1050,RECOMMENDNAME:5046,RECOMMENDVERSION:5047,RECOMMENDFLAGS:5048,RPMVERSION:1064,POSTINPROG:1086,POSTUNPROG:1088,FILEDEVICES:1095,FILEINODES:1096,FILELANGS:1097,PROVIDEFLAGS:1112,PROVIDEVERSION:1113,DIRINDEXES:1116,BASENAMES:1117,DIRNAMES:1118,PAYLOADFORMAT:1124,PAYLOADCOMPRESSOR:1125,PAYLOADFLAGS:1126,FILEDIGESTALGO:5011,ENCODING:5062,PAYLOADDIGEST:5092,PAYLOADDIGESTALGO:5093,PAYLOADDIGESTALT:5097},ZW={SIZE:1e3,MD5:1004,PAYLOADSIZE:1007,SHA1HEADER:269,SHA256HEADER:273},QW={LESS:2,GREATER:4,EQUAL:8,INTERP:256,SCRIPT_POST:1024,SCRIPT_POSTUN:4096,FIND_REQUIRES:16384,RPMLIB:1<<24},$W=8,eG=[[`rpmlib(CompressedFileNames)`,`3.0.4-1`],[`rpmlib(FileDigests)`,`4.6.0-1`],[`rpmlib(PayloadFilesHavePrefix)`,`4.0-1`]],tG=new Set([`/usr`,`/usr/bin`,`/usr/lib`,`/usr/lib64`,`/usr/libexec`,`/usr/sbin`,`/usr/share`,`/usr/${rH.applications}`,`/usr/share/doc`,`/usr/share/icons`,`/usr/share/licenses`,`/usr/share/man`,`/usr/${rH.metainfo}`,`/usr/share/glib-2.0`,`/usr/${rH.schemas}`,`/usr/${rH.fonts}`,`/etc`,`/opt`,`/var`])});async function assemble(t){let n=process.cwd(),S=t.os===void 0?hostLayout():resolveLayout(t.os),C=await new Config().forCommand(n),N=C.ship??{},F=C.flatpak??{},I=resolveShipApp({project:C.app,perTarget:N.app,layoutOs:S.os}),H=I.app;I.overridden&&ge.log(`${rG} runtime for ${S.name}: ${H} — \`${I.key}\` overrides \`gjsify.app${C.app===void 0?``:`: "${C.app}"`}\`.`);let W=readPackageJson$2(In(n,`package.json`))??{},q,Y=[];if(t.target!==void 0)q=resolveFormats(t.target,S);else if(N.targets!==void 0){let t=configuredFormats(N.targets,S);q=t.formats,t.dropped.length>0&&ge.log(`${rG} \`gjsify.ship.targets\` names ${t.dropped.join(`, `)}, which wrap another layout — not built for ${S.name}. Pass --target to ask for one explicitly.`)}else{let t=defaultFormatIds(S.os).map(t=>fW[t]);q=t.filter(t=>t.interpreters.includes(H)),Y=t.filter(t=>!t.interpreters.includes(H)),Y.length>0&&ge.log(`${rG} ${Y.map(t=>t.id).join(`, `)} wrap the ${S.name} layout but cannot run \`${H}\`, which \`${I.key}\` resolves to — ${Y[0]?.interpreterGap??``}. Set \`gjsify.ship.app.${S.os}\` to "${Y[0]?.interpreters.join(`" / "`)}" to ship this OS on that runtime; it leaves every other target on \`gjsify.app\`. Assembling the layout only; pass --target to be told the same thing as an error.`)}q.some(t=>t.id===`flatpak`)&&assertNoDroppedFlatpakModules(F),t.stage||assertPackable(q,S,t.os===void 0?`host`:`positional`,Y);let X=resolveSignPlan({flag:t.sign,config:N.sign,layoutOs:S.os}),Z=resolveNotaryPlan({flag:t.notarize,layoutOs:S.os,sign:X});if(t.stage&&assertNothingToSignYet(t),t.stage||(announceSigning(X,Z),X.kind===`sign`&&assertHostCanSign(X.signer)),t.stage||assertKindCanPack(q,resolveShipKind(N,F)),!t.stage)for(let t of q)assertCanPack(t);let te=parseDeclaredChannel(t.channel,`--channel`)??parseDeclaredChannel(N.channel,`gjsify.ship.channel`)??(q.some(t=>t.id===`flatpak`)?`flathub`:void 0);t[`skip-build`]||await runProjectBuild(n,te);let ne=resolveShipBundle({pkg:W,ship:N,layoutOs:S.os});ne.overridden&&ge.log(`${rG} entry for ${S.name}: ${ne.declared} — \`${ne.key}\` overrides \`gjsify.main\`.`);let re=discoverPayload({projectDir:n,pkg:W,ship:N,flatpakIcon:F.icon,declaredBundle:ne.declared,layoutOs:S.os,foreignBundles:ne.foreign}),{settings:ie,metadata:ae,warnings:oe}=resolveShipSettings({projectDir:n,pkg:W,ship:N,flatpak:F,cli:{outDir:t.out,arch:t.arch,layoutOs:S.os},discovered:re,app:H});for(let t of oe)ge.warn(`${rG} ${t}`);for(let t of q)assertFormatCanRunInterpreter(t,ie.app);let Q=readFileSync(ie.bundlePath,`utf-8`);assertEntryRunsUnder({interpreter:ie.app,source:Q,entry:Ln(n,ie.bundlePath)||ie.bundlePath,appKey:I.key,bundleKey:ne.key,layoutOs:S.os});let se=buildTimestamp(ie.bundlePath),ce={appId:ie.appId,name:ie.name,command:ie.binaryName,kind:ie.kind,metadata:ae,channel:te,configKey:`gjsify.ship`,copyrightYear:new Date(se*1e3).getUTCFullYear()};for(let t of validateAppMetadata(ce))ge.warn(`${rG} ${t.field} is not set — ${t.hint}`);ie.licenseFile!==void 0&&zn(ie.licenseFile)!==n&&ge.log(`${rG} licence text from ${Ln(n,ie.licenseFile)} (this package carries none of its own)`);let le=localizeMetadata({metainfo:ie.kind===`app`?renderMetainfoApp$1(ce):renderMetainfoCli$1(ce),desktopEntry:ie.kind===`app`?renderDesktopEntry(ce):void 0},ie.localeFiles),ue=await resolveCarriedRuntime(S,ie,n);carryNodeModules(ue,S,ie,n,N.nodeModules,N.nodeModulesExclude);let de=stageSubordinates({layout:S,identity:ie,nestedBundles:ie.nestedBundles,helperExecutables:ie.helperExecutables}),fe={bundleFiles:re.bundleFiles,launcher:renderLauncher(ie,Bn(ie.bundlePath),S,ue.launcher),executableLaunchers:Object.fromEntries(ie.executables.map(t=>[t.name,renderLauncher(ie,t.entry,S,ue.launcher)])),metainfo:le.metainfo,desktopEntry:le.desktopEntry,licenseText:ie.licenseFile===void 0?void 0:readFileSync(ie.licenseFile,`utf-8`),changelogText:ie.changelogFile===void 0?void 0:readFileSync(ie.changelogFile,`utf-8`),mtime:se},pe=Nn(n,ie.outDir),me=In(pe,`stage`),he=[...planStage(ie,fe),...S.os===`linux`?[]:await compileSchemasForStage({schemaFiles:ie.schemaFiles,workDir:In(pe,`schemas`)})],_e=ie.kind===`app`&&S.icon!==void 0&&(S.icon.required||ie.iconFiles.length>0)?await resolveAppIcon({iconFiles:ie.iconFiles,appId:ie.appId,sizes:S.icon.sizes,target:S.icon.writes}):void 0;_e!==void 0&&ge.log(`${rG} icon: ${iconSizes(_e).join(`/`)} px, ${_e.source}`);let ve=placeStage(S,{...ie,icon:_e},he,[...ue.files,...de.files]);if(writeStage(me,ve),ge.log(`${rG} staged ${ve.length} file(s) for ${S.name} in ${Ln(n,me)}/`),t.verbose)for(let t of ve)ge.log(`${rG} ${t.path}`);if(assertPayloadMatchesArch(readStage([me],ve),ie.arch,{exempt:payloadArchExemptions(S.os,ie)}),S.os!==`linux`){let t=linuxInstallDependent(he);if(t.length>0){ge.warn(`${rG} the ${S.name} layout carries ${t.length} file(s) whose Linux correctness comes from a package install step it has no equivalent for:`);let n={aborts:`ABORTS: `,unknown:`UNCLASSIFIED: `,inert:``};for(let{path:S,verdict:C,why:N}of t)ge.warn(`${rG} ${n[C]??``}${S} — ${N}`)}for(let t of ue.found)ge.log(`${rG} carries its own ${t}`);for(let t of ue.missing)ge.warn(`${rG} ${t}`);ue.launcher.interpreter===void 0&&S.runtimeGap!==void 0&&ge.warn(`${rG} ${S.runtimeGap}`),S.fontGap!==void 0&&he.some(t=>isUnder(t.path,rH.fonts))&&ge.warn(`${rG} ${S.fontGap}`),S.arches!==null&&!S.arches.only.includes(ie.arch)&&ge.warn(`${rG} this stage is labelled ${ie.arch} and the ${S.name} layout has no runtime for it — ${S.arches.why}. Nothing can pack this stage; \`--arch ${S.arches.only.join(`|`)}\` is what produces an artifact.`)}let ye=scanGiRequirements(Q),be=ye.namespaces,xe=ye.optional;if(t.verbose){let t=be.filter(t=>!xe.includes(t));ge.log(`${rG} gi namespaces: ${be.join(`, `)||`(none)`}`),xe.length>0&&(ge.log(`${rG} gi optional namespaces: ${xe.join(`, `)}`),ge.log(`${rG} gi required namespaces: ${t.join(`, `)||`(none)`}`))}let Se=new Map;for(let t of q)Se.set(t.id,(await planOverlay(ie,t,fe)).map(t=>({...t,path:place(S,ie,t.path)})));let Ce=readPayloadFacts(he);for(let t of q){if(t.depends===null)continue;let n=deriveDepends(t.depends,{namespaces:be,optionalNamespaces:xe,hasIcons:Ce.hasIcons,hasSchemas:Ce.hasSchemas,interpreter:ie.app,extra:ie.extraDepends[t.depends],typelibPackages:ie.typelibPackages,bundledTypelibs:Ce.bundledTypelibs,minGjsVersion:ie.minGjsVersion,minNodeVersion:ie.minNodeVersion});for(let S of n.unmappedOptional)ge.warn(`${rG} gi://${S} is imported optionally, but no ${t.depends} package is known to ship its typelib, so no Recommends entry names it. The package builds and runs without it. Add the row if the namespace should be recommended: \`gjsify.ship.typelibPackages.${S} = { "${t.depends}": "…" }\`.`);let S=ie.app===`node`?warnAboutNodeFloor(t.depends,ie.minNodeVersion):warnAboutGjsFloor(t.depends,ie.minGjsVersion);for(let t of S)ge.warn(`${rG} ${t}`)}let we=writeStageManifest({stageDir:me,settings:ie,formats:q,mtime:se,namespaces:be,optionalNamespaces:xe,staged:ve,overlay:Se});if(t.stage){let t=Y.length>0?`(none — ${Y.map(t=>t.id).join(` and `)} need \`gjsify.ship.app.${S.os}: "node"\`)`:formatIdsFor(S.os).length===0?`(none — no format wraps the ${S.name} layout)`:`(none asked for)`,n=we.formats.join(`, `)||t;ge.log(`${rG} stage manifest: ${formatTarget(we.target)}, formats ${n}`);return}let Te=[];for(let n of q)Te.push(await packOne({format:n,settings:ie,arch:ie.arch,staged:ve,overlay:Se.get(n.id)??[],stageDir:me,outRoot:pe,namespaces:be,optionalNamespaces:xe,mtime:se,sign:X,notarize:Z,verbose:t.verbose}));printArtifacts(n,Te)}function assertNothingToSignYet(t){let n=t.sign===void 0?t.notarize===void 0?void 0:`--notarize`:`--sign`;if(n!==void 0)throw Error(`gjsify ship: ${n} belongs to the finish phase, and --stage produces no artifact to sign — it writes the tree a packing host reads back. Assemble here, then run \`gjsify ship --from-stage <dir> --sign <identity>\` on the host that holds the identity (ADR 0024 § A2, § A14).`)}function announceSigning(t,n){t.kind===`skip`&&ge.warn(`${rG} ${t.message}`),n.kind===`skip`&&t.kind===`sign`&&ge.warn(`${rG} ${n.message}`)}async function resolveCarriedRuntime(t,n,S){let C={files:[],launcher:{},found:[],missing:[]};if(t.os===`linux`||n.app!==`node`)return C;let N=`${t.os}-${n.arch}`;if(!isGtkRuntimeTarget(N))return C;let F=await acquireGtkRuntime({target:N,version:cliVersion(),discovery:{cwd:S},ensure:async S=>(await ensurePkgDir(parseSpec(S),{verbose:!1,cacheMaxAge:aG,frozen:!1,platform:{os:t.os,cpu:n.arch}})).pkgDir,log:t=>ge.log(`${rG} ${t}`)});return stageAppRuntime({layout:t,identity:n,target:N,cwd:S,interpreter:isNodeRuntimeTarget(N)?resolveNodeRuntime(N,{cwd:S}):null,...F.kind===`fetched`?{fetchedGtkRuntimeDir:F.dir}:{},...F.kind===`failed`?{gtkFetchFailure:F.reason}:{}})}function carryNodeModules(t,n,S,C,N,F){if(N===void 0||N.length===0||S.app!==`node`)return;let I=resolveNodeModulesClosure(N,C,{target:{os:n.os,cpu:S.arch},exclude:F});t.files.push(...stageNodeModules(I,n.dirs(S).bundle)),t.found.push(`node_modules: ${I.packages.length} package(s) for ${N.join(`, `)}`),I.excluded.length>0&&ge.log(`${rG} node_modules: left out by gjsify.ship.nodeModulesExclude: ${I.excluded.join(`, `)}`),I.skippedForTarget.length>0&&ge.log(`${rG} node_modules: left out, installed but built for another platform than ${n.os}-${S.arch}: `+I.skippedForTarget.join(`, `)),I.skippedOptional.length>0&&ge.log(`${rG} node_modules: ${I.skippedOptional.length} optional dependenc(ies) not installed, so not carried (other platforms' builds): ${I.skippedOptional.join(`, `)}`)}async function finishFromStage(t,n){if(t.stage)throw Error("gjsify ship: --stage and --from-stage are the two halves of one split and cannot run together. `--stage` assembles a payload and stops; `--from-stage <dir>` packs one that is already assembled. Run them as two commands, on the host each belongs on (ADR 0024 § A2).");if(t[`skip-build`])throw Error(`gjsify ship: --from-stage never runs a build — the payload it packs was built and staged by an earlier run — so --skip-build has nothing to skip. Drop it.`);if(t.arch!==void 0)throw Error("gjsify ship: --arch is decided when the stage is assembled, not when it is packed: the launcher, the payload and the recorded target were all fixed then. Pass --arch to `gjsify ship --stage`, and use `--expect-target <os>-<arch>` here to assert which leg you are packing.");if(t.os!==void 0)throw Error(`gjsify ship: the layout is decided when the stage is assembled, so "${t.os}" has nothing to change here — the staged tree already IS one OS's layout. Use \`--expect-target <os>-<arch>\` to assert which one you are packing.`);let S=process.cwd(),C=Nn(S,n),N=readStageManifest(C);assertExpectedTarget(N,t[`expect-target`]);let F=layoutForOs(N.target.os);t.target===void 0&&assertPackable(N.formats.map(t=>fW[t]),F,`stage`,defaultFormatIds(F.os).map(t=>fW[t]).filter(t=>!t.interpreters.includes(N.settings.app)));let I=resolveFormats(t.target??N.formats,F);assertFormatsStaged(N,I);for(let t of I)assertCanPack(t);let H=resolveSignPlan({flag:t.sign,layoutOs:F.os}),W=resolveNotaryPlan({flag:t.notarize,layoutOs:F.os,sign:H});announceSigning(H,W),H.kind===`sign`&&assertHostCanSign(H.signer);for(let t of warnOnToolSkew(N))ge.warn(`${rG} ${t}`);let{mtime:q,warnings:Y}=resolveStageMtime(N);for(let t of Y)ge.warn(`${rG} ${t}`);if(ge.log(`${rG} packing ${N.settings.binaryName} ${N.settings.version}-${N.settings.release} for ${formatTarget(N.target)} from ${Ln(S,C)||`.`}/`),t.verbose){for(let t of N.staged)ge.log(`${rG} ${t.path}`);ge.log(`${rG} gi namespaces: ${N.namespaces.join(`, `)||`(none)`}`),(N.optionalNamespaces??[]).length>0&&ge.log(`${rG} gi optional namespaces: ${N.optionalNamespaces?.join(`, `)}`)}let X=t.out===void 0?zn(C):Nn(S,t.out),Z=[];for(let n of I){if(assertFormatCanRunInterpreter(n,N.settings.app),n.depends!==null){let t=N.settings.app===`node`?warnAboutNodeFloor(n.depends,N.settings.minNodeVersion):warnAboutGjsFloor(n.depends,N.settings.minGjsVersion);for(let n of t)ge.warn(`${rG} ${n}`)}Z.push(await packOne({format:n,settings:N.settings,arch:N.target.arch,staged:N.staged,overlay:overlayFiles(N,n.id),stageDir:C,outRoot:X,namespaces:N.namespaces,optionalNamespaces:N.optionalNamespaces??[],mtime:q,sign:H,notarize:W,verbose:t.verbose}))}printArtifacts(S,Z)}async function packOne(t){let{format:n,settings:S,stageDir:C,outRoot:N,mtime:F}=t;assertOverlayIsLicensed(n.id,S.binaryName,t.overlay);let I=In(N,`overlay`,n.id);writeStage(I,t.overlay);let H=readStage([C,I],[...t.staged,...t.overlay]),W=readPayloadFacts(H),q=n.depends===null?{requires:[],recommends:[],unmappedOptional:[]}:deriveDepends(n.depends,{namespaces:t.namespaces,optionalNamespaces:t.optionalNamespaces,hasIcons:W.hasIcons,hasSchemas:W.hasSchemas,interpreter:S.app,extra:S.extraDepends[n.depends],typelibPackages:S.typelibPackages,bundledTypelibs:W.bundledTypelibs,minGjsVersion:S.minGjsVersion,minNodeVersion:S.minNodeVersion}),Y=q.requires,X=q.recommends;assertPayloadMatchesArch(H,t.arch,{exempt:payloadArchExemptions(n.layoutOs,S)});let Z=layoutForOs(n.layoutOs);assertLauncherMatchesInterpreter(H,Z,S,S.app),assertLayoutSupportsArch(Z,t.arch);let te=signedSubordinatesFor(Z,S,S),ne=t.sign.kind===`sign`?await signPayload({payload:H,identity:t.sign.identity,signer:t.sign.signer,workDir:In(N,`signed`,n.id),bundleRoot:Z.root(S),entitlementsPath:In(N,`signed`,`${n.id}.entitlements.plist`),nestedBundles:te.nestedBundles,helperExecutables:te.helperExecutables,verbose:t.verbose,log:t=>ge.log(`${rG} ${t}`)}):H,re=n.archName(t.arch,isArchIndependent(ne)),ie={settings:S,payload:ne,prefix:n.prefix,depends:Y,recommends:X,archLabel:re,mtime:F},ae=In(N,`out`);mkdirSync(ae,{recursive:!0});let oe=In(ae,n.fileName(S,re));switch(n.id){case`deb`:writeFileSync(oe,await buildDeb(ie));break;case`rpm`:writeFileSync(oe,await buildRpm(ie));break;case`flatpak`:await buildFlatpakBundle({settings:S,stageDir:C,overlayDir:I,stageManifestFile:NW,workDir:In(N,`flatpak`),target:oe,archLabel:re,verbose:t.verbose});break;case`appimage`:{let n=appImageHostRequirements({app:S.app,minGjsVersion:S.minGjsVersion,minNodeVersion:S.minNodeVersion,namespaces:t.namespaces,optionalNamespaces:t.optionalNamespaces,bundledTypelibs:W.bundledTypelibs}),C=appDirFor(N),I=appDirPayload(S,ne,n,await compileSchemasForPayload({payload:ne,workDir:In(N,`appimage-schemas`)}));writePayload(C,I,``),stampAppDirTimes(C,I,F),ge.log(`${rG} the AppImage takes these from the host: ${n.join(`, `)}`);let H=findPinnedRuntime(re);ge.log(`${rG} ${appImageRuntimeNotice(re,H)}`),await buildAppImage({appDir:C,target:oe,archLabel:re,runtimeFile:H,workDir:zn(C),verbose:t.verbose});break}case`macos-app`:case`windows-dir`:writePayload(oe,ne,Z.root(S));break;case`macos-app-dmg`:{let n=dmgVolumeDir(N);if(writePayload(n,ne,``),t.notarize.kind===`notarize`){let C=t.notarize,N=In(n,`${S.name}.app`),I=In(zn(n),`bundle-notarize.zip`);await stapleBundleBeforeImage({writeArchive:()=>writeFileSync(I,buildZip(zipEntriesFromPayload(ne),F)),notarize:()=>notarizeArtifact({plan:C,artifact:I,verbose:t.verbose,log:t=>ge.log(`${rG} ${t}`)}),staple:()=>stapleArtifact({notary:C.notary,artifact:N,verbose:t.verbose,log:t=>ge.log(`${rG} ${t}`)})})}addApplicationsLink(n),await buildDmgImage({volumeName:dmgVolumeName(S),sourceDir:n,target:oe,workDir:zn(n),verbose:t.verbose}),t.sign.kind===`sign`&&await signDmgImage({identity:t.sign.identity,file:oe,adhoc:t.sign.identity===`-`,workDir:zn(n),verbose:t.verbose});break}case`macos-app-zip`:writeFileSync(oe,buildZip(zipEntriesFromPayload(ne),F));break;case`windows-dir-zip`:writeFileSync(oe,buildZip(zipEntriesFromPayload(ne,windowsProgramDirName(S)),F));break;case`msi`:{let n=In(N,`msi`);writePayload(In(n,vW),ne,Z.root(S)),await buildMsi({settings:S,files:ne.map(t=>({path:t.path,source:`${vW}/${t.path}`})),programDirName:windowsProgramDirName(S),archLabel:re,workDir:n,target:oe,verbose:t.verbose});break}default:{let t=n.id;throw Error(`gjsify ship: no packer is wired for format "${String(t)}".`)}}let Q=n.artifactKind===`directory`?directorySize(oe):statSync(oe).size,se=!1,ce=!1;if(t.notarize.kind===`notarize`&&(n.artifactKind===`directory`?ge.warn(`${rG} ${n.id} is a directory, and notarytool submits an archive or an installer — not notarised. The container format beside it is what carries the ticket.`):(await notarizeArtifact({plan:t.notarize,artifact:oe,verbose:t.verbose,log:t=>ge.log(`${rG} ${t}`)}),se=!0,canCarryTicket(n.id)?(await stapleArtifact({notary:t.notarize.notary,artifact:oe,verbose:t.verbose,log:t=>ge.log(`${rG} ${t}`)}),ce=!0):ge.warn(`${rG} ${n.id} is notarised and NOT stapled: \`stapler\` takes a UDIF image, a signed flat package or a code-signed bundle, and an archive is none of them. Apple's remedy is to staple each item that went INTO the archive and re-create it — for this artifact that is the \`.app\`, which \`--target macos-app\` writes beside it.`))),n.artifactKind===`file`){let S=writeReleaseRecord({file:oe,format:n.id,os:n.layoutOs,arch:isArchIndependent(ne)?`noarch`:t.arch,signature:recordedSignature(t.sign.kind===`sign`?t.sign.identity:void 0,`-`),notarized:se,stapled:ce,nestedBundles:recordedNestedBundles(ne,te.nestedBundles),generator:`@gjsify/cli ${cliVersion()}`});t.verbose&&ge.log(`${rG} release record: ${S}`)}return{format:n.id,path:oe,size:Q}}function printArtifacts(t,n){for(let S of n)ge.log(`${rG} ${S.format}: ${Ln(t,S.path)} (${S.size} bytes)`)}function assertCanPack(t){assertHostCanFinish(t),assertToolsInstalled(t)}function assertPackable(t,n,S,C=[]){if(t.length>0)return;if(C.length>0)throw Error(`gjsify ship: ${C.map(t=>t.id).join(` and `)} wrap the ${n.name} layout, and neither can run this project — ${C[0]?.interpreterGap??``}.\n Set \`gjsify.ship.app.${n.os}\` to "${C[0]?.interpreters.join(`" / "`)}" — it overrides \`gjsify.app\` for THIS target and\n leaves every other one alone, which is what lets one project be GJS on Linux and Node here.
1192
1192
  \`gjsify ship ${n.name} --stage\` assembles the tree either way.`);let N=formatIdsFor(n.os).sort();if(N.length>0){let t=S===`stage`?`${n.name} --stage --target`:`${n.name} --target`;throw Error(`gjsify ship: this run records no formats for the ${n.name} layout, so there is nothing to pack — and it is not that none exist: ${N.join(`, `)} wrap it.\n An empty list means none were SELECTED. \`gjsify.ship.targets\` is filtered to the layout being assembled,
1193
1193
  so a configured list naming only another OS's formats leaves this one empty and says so at stage time.
1194
- Name one where the payload is assembled: \`gjsify ship ${t} ${N[0]}\`.`)}let F=defaultFormatIds(`linux`).join(`,`),I={host:`This host is ${process.platform}, so \`gjsify ship\` assembled the ${n.name} layout. Assembly is not host-bound (ADR 0024 § A1), so the Linux packages are still one word away: \`gjsify ship linux\` builds ${F} from right here.`,positional:`\`gjsify ship ${n.name} --stage\` assembles the payload and stops, which is the whole of what this command does for that OS today.`,stage:`This stage carries the ${n.name} layout and nothing here can wrap it — a stage is a build intermediate, not an artifact. Keep it for the milestone that packs it, or re-assemble with \`gjsify ship linux --stage\` if a Linux package is what you wanted.`}[S];throw Error(`gjsify ship: no format wraps the ${n.name} layout, so there is nothing to pack. ${I} Every layout this gjsify knows has one (ADR 0024 stages 2-5), so this is a layout added without a \`FORMATS\` row.`)}function assertFormatCanRunInterpreter(t,n){if(!t.interpreters.includes(n))throw Error(`gjsify ship: this ${t.layoutOs} target runs \`${n}\`, and the ${t.id} runtime cannot run it — it provides ${t.interpreters.join(`, `)}.\n ${t.interpreterGap}.\n Build the formats that wrap this layout and can run it, or set \`gjsify.ship.app.${t.layoutOs}: "${t.interpreters.join(`" / "`)}"\` (which overrides \`gjsify.app\` for this target alone).`)}async function runProjectBuild(t,n){if(typeof readPackageJson$2(In(t,`package.json`))?.scripts?.build!=`string`)throw Error("gjsify ship: this project has no `build` script to run. Add one, or pass --skip-build to package what is already built.");ge.log(`${nG} running the project's build script`);let S=await spawnToCompletion(`gjsify`,[`run`,`build`],{completion:`return`,cwd:t,stdio:`inherit`,env:n===void 0?void 0:{...process.env,[wh]:n},notFound:()=>Error("gjsify ship: `gjsify` is not on PATH, so the project build cannot be run. Build the project yourself and pass --skip-build.")});if(S.code!==0)throw Error(`gjsify ship: the project's build script failed with ${describeExit(S)}.`)}var nG,rG,iG,aG=__esmMin(()=>{_e(),Th(),ef(),qn(),rR(),fB(),nV(),jI(),oB(),yh(),sv(),oU(),eH(),NU(),PU(),IU(),LU(),SU(),KU(),ZU(),eV(),QU(),lH(),$U(),mW(),WH(),wU(),rH(),YH(),vW(),EW(),OW(),QN(),aU(),kU(),AW(),LW(),RW(),tG(),vU(),NW(),PW(),nG=`[gjsify ship]`,rG={command:`ship [os]`,description:`Build installable artifacts (${fW.join(`, `)}) from the current project.`,builder:t=>t.positional(`os`,{type:`string`,description:`Operating system whose LAYOUT to assemble (${HH.join(`|`)}, ADR 0024 § A2). Default: this host. Assembly is not host-bound, so any of them can be staged anywhere.`}).option(`target`,{type:`string`,array:!0,description:`Formats to build, comma-separated or repeated. Default: every format wrapping the target OS's layout that needs no extra tooling — on linux, ${defaultFormatIds(`linux`).join(`,`)}. Also available for linux, and opt-in because it needs tooling this CLI does not carry: ${formatIdsFor(`linux`).filter(t=>!defaultFormatIds(`linux`).includes(t)).join(`, `)}.`}).option(`out`,{type:`string`,normalize:!0,description:"Output root, relative to the project. Default: `gjsify.ship.outDir`, else `ship`."}).option(`stage`,{type:`boolean`,default:!1,description:`Produce the staged payload and stop, without packing anything.`}).option(`from-stage`,{type:`string`,normalize:!0,description:"Pack a staged payload written by an earlier `--stage` run. Needs no project: the stage carries its own closure."}).option(`expect-target`,{type:`string`,description:"With --from-stage: refuse unless the stage was assembled for this `<os>-<arch>`, e.g. `linux-arm64`."}).option(`channel`,{type:`string`,choices:[...Sh],description:"Distribution channel (ADR 0113). Overrides gjsify.ship.channel; `--target flatpak` implies flathub. Passed to the project build, and gates the metainfo donation URL."}).option(`skip-build`,{type:`boolean`,default:!1,description:"Package what is already built instead of running the project's `build` script."}).option(`arch`,{type:`string`,description:"Target architecture in `process.arch` spelling. Default: this host."}).option(`sign`,{type:`string`,requiresArg:!0,description:"Sign the payload with this identity, e.g. a Developer ID name or SHA-1 fingerprint. `-` signs ad-hoc and needs no developer identity. Default: `gjsify.ship.sign.<darwin|win32>.identity`; absent means unsigned, which is a legitimate output."}).option(`notarize`,{type:`string`,requiresArg:!0,description:"Submit the signed artifact to Apple with this `notarytool` keychain profile. Needs --sign; darwin only."}).option(`verbose`,{type:`boolean`,default:!1,description:`Print each staged file, the GI namespaces the bundle imports, and every tool a host-bound packer invokes.`}),handler:async t=>{if(t[`from-stage`]!==void 0)return await finishFromStage(t,t[`from-stage`]);await assemble(t)}},iG=1440*7});function forceExit(t){if(process.exitCode=t,!gjsExit(t))return process.exit(t)}var oG=__esmMin(()=>{D_()});function workspaceLinkTarget(t,n){return sG===`junction`?Nn(n):Ln(zn(t),n)}function applyPlatformConfigFromFlags(t){for(let[n,S]of[[`os`,`npm_config_os`],[`cpu`,`npm_config_cpu`],[`libc`,`npm_config_libc`]]){let C=t[n];if(typeof C!=`string`)continue;let N=C.trim();N!==``&&(process.env[S]=N)}t.force&&(process.env.npm_config_force=`true`)}function isAbortedFromOverallTimeout(t){if(!t||typeof t!=`object`)return!1;let n=t.name;if(n===`AbortError`)return!0;let S=t.message;return!!(typeof S==`string`&&S.includes(`install-overall-timeout`)||n===`RegistryTimeoutError`)}function readCliVersionFrom(t){try{if(!existsSync(t))return null;let n=JSON.parse(readFileSync(t,`utf-8`));if(n.name===uG&&typeof n.version==`string`)return n.version}catch{}return null}function readRunningCliVersion(){try{let t=zn(Nn(fileURLToPath(import.meta.url)));for(let n=0;n<8&&t!==zn(t);n++){let n=readCliVersionFrom(In(t,`package.json`));if(n)return n;t=zn(t)}}catch{}return null}function readWorkspaceCliVersion(t){let n=readPackageJson$1(In(t,`package.json`)),S=!1;for(let t of[`dependencies`,`devDependencies`,`optionalDependencies`]){let C=n?.[t]?.[uG];typeof C==`string`&&(S=!0);let N=typeof C==`string`?/^[\^~=v]*(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)$/.exec(C.trim()):null;if(N)return N[1]}if(!S){let n=readCliVersionFrom(In(t,`node_modules`,uG,`package.json`));if(n)return n}return readCliVersionFrom(In(t,`packages`,`infra`,`cli`,`package.json`))}function warnOnCliVersionSkew(t){if(process.env.GJSIFY_NO_VERSION_SKEW_WARNING===`1`)return;let n=readRunningCliVersion(),S=readWorkspaceCliVersion(t);!n||!S||n===S||ge.warn(`gjsify install: version skew — you are running @gjsify/cli v${n}, but this workspace pins v${S}.\n A mismatched CLI can stall the install (lock discarded → full re-resolve) or silently produce a wrong build.\n Align them: run \`gjsify self-update\` (global CLI) or use the workspace-local \`node_modules/.bin/gjsify\`.\n Suppress this with GJSIFY_NO_VERSION_SKEW_WARNING=1.`)}function isWorkspaceRoot(t){let n=readPackageJson$1(In(t,`package.json`));return n?n.workspaces!==void 0:!1}function optionalDependencyNames(t){let n=new Set,S=new Set;for(let C of t){let t=new Set(Object.keys(C.optionalDependencies??{}));for(let S of t)n.add(S);for(let n of[`dependencies`,`devDependencies`])for(let N of Object.keys(C[n]??{}))t.has(N)||S.add(N)}for(let t of S)n.delete(t);return n}function depKindFromArgs(t){return t[`save-dev`]?`devDependencies`:t[`save-peer`]?`peerDependencies`:t[`save-optional`]?`optionalDependencies`:`dependencies`}function activateDevLinks(t,n){let S=prepareDevLinks(devLinkRoot(t));if(!S)return null;let C=applyDevLinks(S.links);if(!n)return S;ge.log(`gjsify install: development link ACTIVE (${S.overridePath}) — ${S.links.length} package(s) come from ${S.checkout}, linked rather than fetched (${C.length} (re)written, ${S.links.length-C.length} already current):`);let N=S.links.map(t=>t.name),F=N.slice(0,12);return ge.log(` ${F.join(`, `)}${N.length>F.length?`, +${N.length-F.length} more`:``}`),ge.log(" `gjsify unlink` restores the registry copies; `gjsify install --immutable` refuses while it exists."),S}function reportRewiredDevLinks(t){if(!t)return;let n=applyDevLinks(t.links);n.length!==0&&ge.log(`gjsify install: re-applied ${n.length} development link(s) the install had replaced: ${n.map(t=>t.name).join(`, `)}`)}async function projectInstallNative(t,n){let S=process.cwd(),C=In(S,`package.json`),N=[`.pnp.cjs`,`.pnp.loader.mjs`].filter(t=>existsSync(In(S,t)));if(N.length>0)throw Error(`gjsify install uses the node_modules linker and cannot run in a Yarn PnP project (found ${N.join(`, `)} in ${S}).\n\n• If this project uses \`gjsify install\` to manage dependencies, these PnP files are stale residue from an earlier \`yarn install\` — remove them and re-run:\n rm -f .pnp.cjs .pnp.loader.mjs && rm -rf .yarn/cache .yarn/unplugged\n gjsify install\n\n• If instead you want Yarn to manage dependencies, set \`nodeLinker: node-modules\` in .yarnrc.yml and run \`yarn install\` (not \`gjsify install\`).`);if(!t.packages||t.packages.length===0){let C=isWorkspaceRoot(S)?S:findWorkspaceRoot(S);if(C){C!==S&&ge.log(`gjsify install: resolved workspace root ${C} (from ${S}); installing the workspace.`),await workspaceInstall(C,t,n);return}}let F,I=readPackageJson$1(C),H=I?projectSpecsFromPackageJson(I):[];if(t.packages&&t.packages.length>0){let n=new Set(t.packages.map(t=>parseSpec$2(t).name));F=[...H.filter(t=>!n.has(parseSpec$2(t).name)),...t.packages]}else{if(!I)throw Error(`gjsify install: no package.json in ${S}`);if(F=H,F.length===0){ge.log(`gjsify install: no dependencies declared in package.json — nothing to do.`);return}}mkdirSync(S,{recursive:!0});let W=makeProgressReporter({enabled:!t.verbose&&!t.quiet&&t.progress!==!1}),q=await acquireInstallLock(S,{signal:n});try{let N=activateDevLinks(S,!0),H=await installPackages({prefix:S,specs:F,verbose:t.verbose,lockfile:!t.immutable,frozen:t.immutable,refreshLockfile:t[`refresh-lockfile`],signal:n,progress:W,optionalSpecs:new Set([...optionalDependencyNames(I?[I]:[]),...t[`save-optional`]?(t.packages??[]).map(t=>parseSpec$2(t).name):[]]),linkedNames:N?.names});if(reportRewiredDevLinks(N),t.packages&&t.packages.length>0&&I){let n=depKindFromArgs(t);for(let S of t.packages){let{name:t,range:C}=parseSpec$2(S),N=H.installed.find(n=>n.name===t);addDependencyEntry(I,t,C??(N?defaultRangeFromVersion(N.version):`latest`),n)}writePackageJson(C,I),t.immutable||syncLockfileRequested(S,projectSpecsFromPackageJson(I))}}finally{q.release()}}function syncLockfileRequested(t,n){let S=In(t,`gjsify-lock.json`);if(existsSync(S))try{let t=JSON.parse(readFileSync(S,`utf-8`)),C=[...n].sort(),N=[...t.requested??[]].sort();if(C.length===N.length&&C.every((t,n)=>t===N[n]))return;t.requested=n,atomicWriteStrict(S,JSON.stringify(t,null,2)+`
1195
- `)}catch{}}async function workspaceInstall(t,n,S){let C=await acquireInstallLock(t,{signal:S});try{await workspaceInstallLocked(t,n,S)}finally{C.release()}}async function workspaceInstallLocked(t,n,S){let C=discoverWorkspaces(t,{includeRoot:!0});if(C.length===0)throw Error(`gjsify install: ${t} has a "workspaces" field but no workspaces were discovered`);let N=new Map(C.map(t=>[t.name,t])),F=n.focus&&n.focus.length>0?planFocus(C,n.focus,`gjsify install`):void 0,I=F?new Set(F.workspaces):void 0,H=new Set,W=new Map,q=[];for(let t of C){let n=t.manifest;for(let S of[`dependencies`,`devDependencies`,`optionalDependencies`]){let C=n[S];if(C)for(let[n,S]of Object.entries(C)){if(typeof S!=`string`)continue;let C=N.get(n);if(C&&!/^(link|file|portal|git\+|https?):/.test(S)){if(I&&!I.has(t))continue;q.push({fromWorkspaceName:t.name,depName:n,targetLocation:C.location});continue}if(S.startsWith(`workspace:`))throw Error(`gjsify install: ${t.name} declares "${n}: ${S}" but no workspace with that name exists`);if(/^(link|file|portal|git\+|https?):/.test(S))continue;let F=`${n}@${S}`;H.add(F);let Y=W.get(F);Y||(Y=new Set,W.set(F,Y)),Y.add(t.name)}}}ge.log(`gjsify install: ${C.length} workspace(s), ${H.size} external dep spec(s), ${q.length} workspace symlink(s)`);let Y=activateDevLinks(t,!0);writeWorkspaceBinShims(t,F?.workspaces??C);let wireWorkspaceSymlinks=async()=>{if(q.length>0){let t=await Promise.resolve().then(()=>(Ld(),Pd)),n=new Set,S=[];for(let t of q){let C=N.get(t.fromWorkspaceName);if(!C)continue;let F=In(C.location,`node_modules`,t.depName);n.add(zn(F));let I=workspaceLinkTarget(F,t.targetLocation);S.push({linkPath:F,relTarget:I})}await Promise.all([...n].map(n=>t.mkdir(n,{recursive:!0})));let C=0,F=[],wireOne=async(n,S)=>{try{await t.rm(n,{recursive:!0,force:!0,maxRetries:10,retryDelay:100})}catch{}await t.symlink(S,n,sG)};for(let t=0;t<Math.min(32,S.length);t++)F.push((async()=>{for(;;){let t=C++;if(t>=S.length)return;let n=S[t];if(!n)return;await wireOne(n.linkPath,n.relTarget)}})());await Promise.all(F),ge.log(`gjsify install: wired ${q.length} workspace symlink(s)`)}let n=In(t,`node_modules`),S=0;for(let N of F?.workspaces??C){if(N.location===t||!N.name)continue;let C=In(n,N.name),F=!1;try{lstatSync(C),F=!0}catch{}F||(mkdirSync(zn(C),{recursive:!0}),symlinkSync(workspaceLinkTarget(C,N.location),C,sG),S++)}S>0&&ge.log(`gjsify install: hoisted ${S} workspace(s) to root node_modules/`)};await wireWorkspaceSymlinks();let X=C.find(n=>n.location===t)?.manifest,Z=extractOverrides(X),te=Z?.global,ne=new Map,re=new Set;if(Z&&Z.scoped.size>0){for(let t of F?.workspaces??C){let n=t.manifest;for(let S of[`dependencies`,`devDependencies`,`optionalDependencies`]){let C=n[S];if(C)for(let[n,S]of Object.entries(C)){let C=scopedOverrideFor(t,n,Z);if(!C)continue;let N=C,F=t.location,I=ne.get(F);I||(I=new Set,ne.set(F,I)),I.add(`${n}@${N}`),re.add(`${n}@${S}`)}}}let t=new Set;for(let n of C)for(let S of[`dependencies`,`devDependencies`,`optionalDependencies`]){let C=n.manifest[S];if(C)for(let[S,N]of Object.entries(C))scopedOverrideFor(n,S,Z)||t.add(`${S}@${N}`)}for(let n of re)t.has(n)||H.delete(n);ne.size>0&&ge.log(`gjsify install: ${ne.size} workspace(s) have scoped overrides — they will install their overridden deps locally after the root install`)}if(H.size>0){let I=makeProgressReporter({enabled:!n.verbose&&!n.quiet&&n.progress!==!1});await installPackages({prefix:t,specs:[...H],verbose:n.verbose,lockfile:!n.immutable,frozen:n.immutable,refreshLockfile:n[`refresh-lockfile`],overrides:te,signal:S,progress:I,workspaceNames:new Set(N.keys()),linkedNames:Y?.names,specOrigins:new Map([...W].map(([t,n])=>[t,[...n]])),optionalSpecs:optionalDependencyNames(C.map(t=>t.manifest)),focusSpecs:F?.specs})}else n.verbose&&ge.log(`gjsify install: no external deps to fetch`);for(let[t,F]of ne){if(F.size===0)continue;let I=C.find(n=>n.location===t)?.name??t;n.verbose&&ge.log(`gjsify install: ${I} — installing ${F.size} scoped-override spec(s) into ${t}/node_modules/`),await installPackages({prefix:t,specs:[...F],verbose:n.verbose,lockfile:!n.immutable,frozen:n.immutable,signal:S,workspaceNames:new Set(N.keys()),linkedNames:Y?.names,optionalSpecs:optionalDependencyNames(C.map(t=>t.manifest))})}await wireWorkspaceSymlinks(),reportRewiredDevLinks(Y);let ie=writeWorkspaceBinShims(t,F?.workspaces??C);ie>0&&ge.log(`gjsify install: linked ${ie} workspace bin(s) into node_modules/.bin/`)}function writeWorkspaceBinShims(t,n){let S=In(t,`node_modules`,`.bin`),C=detectNativePackages(t).map(t=>t.prebuildsDir),N=0;for(let F of n){let n=F.manifest,I=n.gjsify?.bin,H=n.bin,W=mergeWorkspaceBins(F.name,I,H);if(W.size!==0){mkdirSync(S,{recursive:!0});for(let[n,{nodeTarget:I,gjsTarget:H}]of W){let W=In(S,n);for(let t of[W,`${W}.cmd`,`${W}.ps1`])try{rmSync(t,{force:!0,maxRetries:10,retryDelay:100})}catch{}if(writeFileSync(W,buildBinShim(F.location,I,H,C,process.platform,t),{mode:493}),chmodSync(W,493),process.platform===`win32`)for(let[t,n]of Object.entries(buildWorkspaceBinShimsForWindows(F.location,I,H,C)))writeFileSync(`${W}.${t}`,n,{mode:493});N++}}}return N}function extractOverrides(t){if(!t)return;let n={},S=new Map,merge=(t,C)=>{if(t){for(let[N,F]of Object.entries(t))if(!N.startsWith(`_`)){if(typeof F==`string`){let t=N,S=N.startsWith(`@`)?N.indexOf(`@`,1):N.indexOf(`@`);S>0&&(t=N.slice(0,S)),n[t]=F;continue}if(F&&typeof F==`object`&&!Array.isArray(F)){let t={};for(let[n,S]of Object.entries(F)){if(n.startsWith(`_`))continue;if(typeof S!=`string`){ge.warn(`gjsify install: ${C}["${N}"]["${n}"] is not a string — only one level of nesting is supported, skipping`);continue}let F=n,I=n.startsWith(`@`)?n.indexOf(`@`,1):n.indexOf(`@`);I>0&&(F=n.slice(0,I)),t[F]=S}if(Object.keys(t).length>0){let n=S.get(N)??{};S.set(N,{...n,...t})}continue}ge.warn(`gjsify install: ${C}["${N}"] is not a string or object — skipping`)}}};if(merge(t.overrides,`overrides`),merge(t.resolutions,`resolutions`),!(Object.keys(n).length===0&&S.size===0))return{global:n,scoped:S}}function scopedOverrideFor(t,n,S){if(!S||S.scoped.size===0)return;let C=[t.name,t.relativeLocation];for(let t of C){let C=S.scoped.get(t);if(C?.[n])return C[n]}}function buildBinShim(t,n,S,C=[],N=process.platform,F=t){let I=n?In(t,n):null,H=S?In(t,S):null,W=buildNativeEnvPreamble(F,C,{platform:N});if(I&&H){let t=N===`darwin`||N===`win32`,n=`if command -v gjs >/dev/null 2>&1 && [ -f "${H}" ]; then\n${W}exec gjs -m "${H}" "$@"\nfi\nexec node "${I}" "$@"\n`,S=`if command -v node >/dev/null 2>&1 && [ -f "${I}" ]; then\nexec node "${I}" "$@"\nfi\n${W}exec gjs -m "${H}" "$@"\n`;return`#!/bin/sh
1194
+ Name one where the payload is assembled: \`gjsify ship ${t} ${N[0]}\`.`)}let F=defaultFormatIds(`linux`).join(`,`),I={host:`This host is ${process.platform}, so \`gjsify ship\` assembled the ${n.name} layout. Assembly is not host-bound (ADR 0024 § A1), so the Linux packages are still one word away: \`gjsify ship linux\` builds ${F} from right here.`,positional:`\`gjsify ship ${n.name} --stage\` assembles the payload and stops, which is the whole of what this command does for that OS today.`,stage:`This stage carries the ${n.name} layout and nothing here can wrap it — a stage is a build intermediate, not an artifact. Keep it for the milestone that packs it, or re-assemble with \`gjsify ship linux --stage\` if a Linux package is what you wanted.`}[S];throw Error(`gjsify ship: no format wraps the ${n.name} layout, so there is nothing to pack. ${I} Every layout this gjsify knows has one (ADR 0024 stages 2-5), so this is a layout added without a \`FORMATS\` row.`)}function assertFormatCanRunInterpreter(t,n){if(!t.interpreters.includes(n))throw Error(`gjsify ship: this ${t.layoutOs} target runs \`${n}\`, and the ${t.id} runtime cannot run it — it provides ${t.interpreters.join(`, `)}.\n ${t.interpreterGap}.\n Build the formats that wrap this layout and can run it, or set \`gjsify.ship.app.${t.layoutOs}: "${t.interpreters.join(`" / "`)}"\` (which overrides \`gjsify.app\` for this target alone).`)}async function runProjectBuild(t,n){if(typeof readPackageJson$2(In(t,`package.json`))?.scripts?.build!=`string`)throw Error("gjsify ship: this project has no `build` script to run. Add one, or pass --skip-build to package what is already built.");ge.log(`${rG} running the project's build script`);let S=await spawnToCompletion(`gjsify`,[`run`,`build`],{completion:`return`,cwd:t,stdio:`inherit`,env:n===void 0?void 0:{...process.env,[wh]:n},notFound:()=>Error("gjsify ship: `gjsify` is not on PATH, so the project build cannot be run. Build the project yourself and pass --skip-build.")});if(S.code!==0)throw Error(`gjsify ship: the project's build script failed with ${describeExit(S)}.`)}var rG,iG,aG,oG=__esmMin(()=>{_e(),Th(),ef(),qn(),rR(),fB(),nV(),jI(),oB(),yh(),sv(),sU(),tH(),PU(),FU(),LU(),RU(),CU(),qU(),QU(),eV(),$U(),uH(),eW(),hW(),GH(),TU(),iH(),XH(),yW(),DW(),kW(),QN(),oU(),AU(),jW(),RW(),zW(),nG(),yU(),PW(),FW(),rG=`[gjsify ship]`,iG={command:`ship [os]`,description:`Build installable artifacts (${pW.join(`, `)}) from the current project.`,builder:t=>t.positional(`os`,{type:`string`,description:`Operating system whose LAYOUT to assemble (${UH.join(`|`)}, ADR 0024 § A2). Default: this host. Assembly is not host-bound, so any of them can be staged anywhere.`}).option(`target`,{type:`string`,array:!0,description:`Formats to build, comma-separated or repeated. Default: every format wrapping the target OS's layout that needs no extra tooling — on linux, ${defaultFormatIds(`linux`).join(`,`)}. Also available for linux, and opt-in because it needs tooling this CLI does not carry: ${formatIdsFor(`linux`).filter(t=>!defaultFormatIds(`linux`).includes(t)).join(`, `)}.`}).option(`out`,{type:`string`,normalize:!0,description:"Output root, relative to the project. Default: `gjsify.ship.outDir`, else `ship`."}).option(`stage`,{type:`boolean`,default:!1,description:`Produce the staged payload and stop, without packing anything.`}).option(`from-stage`,{type:`string`,normalize:!0,description:"Pack a staged payload written by an earlier `--stage` run. Needs no project: the stage carries its own closure."}).option(`expect-target`,{type:`string`,description:"With --from-stage: refuse unless the stage was assembled for this `<os>-<arch>`, e.g. `linux-arm64`."}).option(`channel`,{type:`string`,choices:[...Sh],description:"Distribution channel (ADR 0113). Overrides gjsify.ship.channel; `--target flatpak` implies flathub. Passed to the project build, and gates the metainfo donation URL."}).option(`skip-build`,{type:`boolean`,default:!1,description:"Package what is already built instead of running the project's `build` script."}).option(`arch`,{type:`string`,description:"Target architecture in `process.arch` spelling. Default: this host."}).option(`sign`,{type:`string`,requiresArg:!0,description:"Sign the payload with this identity, e.g. a Developer ID name or SHA-1 fingerprint. `-` signs ad-hoc and needs no developer identity. Default: `gjsify.ship.sign.<darwin|win32>.identity`; absent means unsigned, which is a legitimate output."}).option(`notarize`,{type:`string`,requiresArg:!0,description:"Submit the signed artifact to Apple with this `notarytool` keychain profile. Needs --sign; darwin only."}).option(`verbose`,{type:`boolean`,default:!1,description:`Print each staged file, the GI namespaces the bundle imports, and every tool a host-bound packer invokes.`}),handler:async t=>{if(t[`from-stage`]!==void 0)return await finishFromStage(t,t[`from-stage`]);await assemble(t)}},aG=1440*7});function forceExit(t){if(process.exitCode=t,!gjsExit(t))return process.exit(t)}var sG=__esmMin(()=>{D_()});function workspaceLinkTarget(t,n){return cG===`junction`?Nn(n):Ln(zn(t),n)}function applyPlatformConfigFromFlags(t){for(let[n,S]of[[`os`,`npm_config_os`],[`cpu`,`npm_config_cpu`],[`libc`,`npm_config_libc`]]){let C=t[n];if(typeof C!=`string`)continue;let N=C.trim();N!==``&&(process.env[S]=N)}t.force&&(process.env.npm_config_force=`true`)}function isAbortedFromOverallTimeout(t){if(!t||typeof t!=`object`)return!1;let n=t.name;if(n===`AbortError`)return!0;let S=t.message;return!!(typeof S==`string`&&S.includes(`install-overall-timeout`)||n===`RegistryTimeoutError`)}function readCliVersionFrom(t){try{if(!existsSync(t))return null;let n=JSON.parse(readFileSync(t,`utf-8`));if(n.name===dG&&typeof n.version==`string`)return n.version}catch{}return null}function readRunningCliVersion(){try{let t=zn(Nn(fileURLToPath(import.meta.url)));for(let n=0;n<8&&t!==zn(t);n++){let n=readCliVersionFrom(In(t,`package.json`));if(n)return n;t=zn(t)}}catch{}return null}function readWorkspaceCliVersion(t){let n=readPackageJson$1(In(t,`package.json`)),S=!1;for(let t of[`dependencies`,`devDependencies`,`optionalDependencies`]){let C=n?.[t]?.[dG];typeof C==`string`&&(S=!0);let N=typeof C==`string`?/^[\^~=v]*(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)$/.exec(C.trim()):null;if(N)return N[1]}if(!S){let n=readCliVersionFrom(In(t,`node_modules`,dG,`package.json`));if(n)return n}return readCliVersionFrom(In(t,`packages`,`infra`,`cli`,`package.json`))}function warnOnCliVersionSkew(t){if(process.env.GJSIFY_NO_VERSION_SKEW_WARNING===`1`)return;let n=readRunningCliVersion(),S=readWorkspaceCliVersion(t);!n||!S||n===S||ge.warn(`gjsify install: version skew — you are running @gjsify/cli v${n}, but this workspace pins v${S}.\n A mismatched CLI can stall the install (lock discarded → full re-resolve) or silently produce a wrong build.\n Align them: run \`gjsify self-update\` (global CLI) or use the workspace-local \`node_modules/.bin/gjsify\`.\n Suppress this with GJSIFY_NO_VERSION_SKEW_WARNING=1.`)}function isWorkspaceRoot(t){let n=readPackageJson$1(In(t,`package.json`));return n?n.workspaces!==void 0:!1}function optionalDependencyNames(t){let n=new Set,S=new Set;for(let C of t){let t=new Set(Object.keys(C.optionalDependencies??{}));for(let S of t)n.add(S);for(let n of[`dependencies`,`devDependencies`])for(let N of Object.keys(C[n]??{}))t.has(N)||S.add(N)}for(let t of S)n.delete(t);return n}function depKindFromArgs(t){return t[`save-dev`]?`devDependencies`:t[`save-peer`]?`peerDependencies`:t[`save-optional`]?`optionalDependencies`:`dependencies`}function activateDevLinks(t,n){let S=prepareDevLinks(devLinkRoot(t));if(!S)return null;let C=applyDevLinks(S.links);if(!n)return S;ge.log(`gjsify install: development link ACTIVE (${S.overridePath}) — ${S.links.length} package(s) come from ${S.checkout}, linked rather than fetched (${C.length} (re)written, ${S.links.length-C.length} already current):`);let N=S.links.map(t=>t.name),F=N.slice(0,12);return ge.log(` ${F.join(`, `)}${N.length>F.length?`, +${N.length-F.length} more`:``}`),ge.log(" `gjsify unlink` restores the registry copies; `gjsify install --immutable` refuses while it exists."),S}function reportRewiredDevLinks(t){if(!t)return;let n=applyDevLinks(t.links);n.length!==0&&ge.log(`gjsify install: re-applied ${n.length} development link(s) the install had replaced: ${n.map(t=>t.name).join(`, `)}`)}async function projectInstallNative(t,n){let S=process.cwd(),C=In(S,`package.json`),N=[`.pnp.cjs`,`.pnp.loader.mjs`].filter(t=>existsSync(In(S,t)));if(N.length>0)throw Error(`gjsify install uses the node_modules linker and cannot run in a Yarn PnP project (found ${N.join(`, `)} in ${S}).\n\n• If this project uses \`gjsify install\` to manage dependencies, these PnP files are stale residue from an earlier \`yarn install\` — remove them and re-run:\n rm -f .pnp.cjs .pnp.loader.mjs && rm -rf .yarn/cache .yarn/unplugged\n gjsify install\n\n• If instead you want Yarn to manage dependencies, set \`nodeLinker: node-modules\` in .yarnrc.yml and run \`yarn install\` (not \`gjsify install\`).`);if(!t.packages||t.packages.length===0){let C=isWorkspaceRoot(S)?S:findWorkspaceRoot(S);if(C){C!==S&&ge.log(`gjsify install: resolved workspace root ${C} (from ${S}); installing the workspace.`),await workspaceInstall(C,t,n);return}}let F,I=readPackageJson$1(C),H=I?projectSpecsFromPackageJson(I):[];if(t.packages&&t.packages.length>0){let n=new Set(t.packages.map(t=>parseSpec$2(t).name));F=[...H.filter(t=>!n.has(parseSpec$2(t).name)),...t.packages]}else{if(!I)throw Error(`gjsify install: no package.json in ${S}`);if(F=H,F.length===0){ge.log(`gjsify install: no dependencies declared in package.json — nothing to do.`);return}}mkdirSync(S,{recursive:!0});let W=makeProgressReporter({enabled:!t.verbose&&!t.quiet&&t.progress!==!1}),q=await acquireInstallLock(S,{signal:n});try{let N=activateDevLinks(S,!0),H=await installPackages({prefix:S,specs:F,verbose:t.verbose,lockfile:!t.immutable,frozen:t.immutable,refreshLockfile:t[`refresh-lockfile`],signal:n,progress:W,optionalSpecs:new Set([...optionalDependencyNames(I?[I]:[]),...t[`save-optional`]?(t.packages??[]).map(t=>parseSpec$2(t).name):[]]),linkedNames:N?.names});if(reportRewiredDevLinks(N),t.packages&&t.packages.length>0&&I){let n=depKindFromArgs(t);for(let S of t.packages){let{name:t,range:C}=parseSpec$2(S),N=H.installed.find(n=>n.name===t);addDependencyEntry(I,t,C??(N?defaultRangeFromVersion(N.version):`latest`),n)}writePackageJson(C,I),t.immutable||syncLockfileRequested(S,projectSpecsFromPackageJson(I))}}finally{q.release()}}function syncLockfileRequested(t,n){let S=In(t,`gjsify-lock.json`);if(existsSync(S))try{let t=JSON.parse(readFileSync(S,`utf-8`)),C=[...n].sort(),N=[...t.requested??[]].sort();if(C.length===N.length&&C.every((t,n)=>t===N[n]))return;t.requested=n,atomicWriteStrict(S,JSON.stringify(t,null,2)+`
1195
+ `)}catch{}}async function workspaceInstall(t,n,S){let C=await acquireInstallLock(t,{signal:S});try{await workspaceInstallLocked(t,n,S)}finally{C.release()}}async function workspaceInstallLocked(t,n,S){let C=discoverWorkspaces(t,{includeRoot:!0});if(C.length===0)throw Error(`gjsify install: ${t} has a "workspaces" field but no workspaces were discovered`);let N=new Map(C.map(t=>[t.name,t])),F=n.focus&&n.focus.length>0?planFocus(C,n.focus,`gjsify install`):void 0,I=F?new Set(F.workspaces):void 0,H=new Set,W=new Map,q=[];for(let t of C){let n=t.manifest;for(let S of[`dependencies`,`devDependencies`,`optionalDependencies`]){let C=n[S];if(C)for(let[n,S]of Object.entries(C)){if(typeof S!=`string`)continue;let C=N.get(n);if(C&&!/^(link|file|portal|git\+|https?):/.test(S)){if(I&&!I.has(t))continue;q.push({fromWorkspaceName:t.name,depName:n,targetLocation:C.location});continue}if(S.startsWith(`workspace:`))throw Error(`gjsify install: ${t.name} declares "${n}: ${S}" but no workspace with that name exists`);if(/^(link|file|portal|git\+|https?):/.test(S))continue;let F=`${n}@${S}`;H.add(F);let Y=W.get(F);Y||(Y=new Set,W.set(F,Y)),Y.add(t.name)}}}ge.log(`gjsify install: ${C.length} workspace(s), ${H.size} external dep spec(s), ${q.length} workspace symlink(s)`);let Y=activateDevLinks(t,!0);writeWorkspaceBinShims(t,F?.workspaces??C);let wireWorkspaceSymlinks=async()=>{if(q.length>0){let t=await Promise.resolve().then(()=>(Ld(),Pd)),n=new Set,S=[];for(let t of q){let C=N.get(t.fromWorkspaceName);if(!C)continue;let F=In(C.location,`node_modules`,t.depName);n.add(zn(F));let I=workspaceLinkTarget(F,t.targetLocation);S.push({linkPath:F,relTarget:I})}await Promise.all([...n].map(n=>t.mkdir(n,{recursive:!0})));let C=0,F=[],wireOne=async(n,S)=>{try{await t.rm(n,{recursive:!0,force:!0,maxRetries:10,retryDelay:100})}catch{}await t.symlink(S,n,cG)};for(let t=0;t<Math.min(32,S.length);t++)F.push((async()=>{for(;;){let t=C++;if(t>=S.length)return;let n=S[t];if(!n)return;await wireOne(n.linkPath,n.relTarget)}})());await Promise.all(F),ge.log(`gjsify install: wired ${q.length} workspace symlink(s)`)}let n=In(t,`node_modules`),S=0;for(let N of F?.workspaces??C){if(N.location===t||!N.name)continue;let C=In(n,N.name),F=!1;try{lstatSync(C),F=!0}catch{}F||(mkdirSync(zn(C),{recursive:!0}),symlinkSync(workspaceLinkTarget(C,N.location),C,cG),S++)}S>0&&ge.log(`gjsify install: hoisted ${S} workspace(s) to root node_modules/`)};await wireWorkspaceSymlinks();let X=C.find(n=>n.location===t)?.manifest,Z=extractOverrides(X),te=Z?.global,ne=new Map,re=new Set;if(Z&&Z.scoped.size>0){for(let t of F?.workspaces??C){let n=t.manifest;for(let S of[`dependencies`,`devDependencies`,`optionalDependencies`]){let C=n[S];if(C)for(let[n,S]of Object.entries(C)){let C=scopedOverrideFor(t,n,Z);if(!C)continue;let N=C,F=t.location,I=ne.get(F);I||(I=new Set,ne.set(F,I)),I.add(`${n}@${N}`),re.add(`${n}@${S}`)}}}let t=new Set;for(let n of C)for(let S of[`dependencies`,`devDependencies`,`optionalDependencies`]){let C=n.manifest[S];if(C)for(let[S,N]of Object.entries(C))scopedOverrideFor(n,S,Z)||t.add(`${S}@${N}`)}for(let n of re)t.has(n)||H.delete(n);ne.size>0&&ge.log(`gjsify install: ${ne.size} workspace(s) have scoped overrides — they will install their overridden deps locally after the root install`)}if(H.size>0){let I=makeProgressReporter({enabled:!n.verbose&&!n.quiet&&n.progress!==!1});await installPackages({prefix:t,specs:[...H],verbose:n.verbose,lockfile:!n.immutable,frozen:n.immutable,refreshLockfile:n[`refresh-lockfile`],overrides:te,signal:S,progress:I,workspaceNames:new Set(N.keys()),linkedNames:Y?.names,specOrigins:new Map([...W].map(([t,n])=>[t,[...n]])),optionalSpecs:optionalDependencyNames(C.map(t=>t.manifest)),focusSpecs:F?.specs})}else n.verbose&&ge.log(`gjsify install: no external deps to fetch`);for(let[t,F]of ne){if(F.size===0)continue;let I=C.find(n=>n.location===t)?.name??t;n.verbose&&ge.log(`gjsify install: ${I} — installing ${F.size} scoped-override spec(s) into ${t}/node_modules/`),await installPackages({prefix:t,specs:[...F],verbose:n.verbose,lockfile:!n.immutable,frozen:n.immutable,signal:S,workspaceNames:new Set(N.keys()),linkedNames:Y?.names,optionalSpecs:optionalDependencyNames(C.map(t=>t.manifest))})}await wireWorkspaceSymlinks(),reportRewiredDevLinks(Y);let ie=writeWorkspaceBinShims(t,F?.workspaces??C);ie>0&&ge.log(`gjsify install: linked ${ie} workspace bin(s) into node_modules/.bin/`)}function writeWorkspaceBinShims(t,n){let S=In(t,`node_modules`,`.bin`),C=detectNativePackages(t).map(t=>t.prebuildsDir),N=0;for(let F of n){let n=F.manifest,I=n.gjsify?.bin,H=n.bin,W=mergeWorkspaceBins(F.name,I,H);if(W.size!==0){mkdirSync(S,{recursive:!0});for(let[n,{nodeTarget:I,gjsTarget:H}]of W){let W=In(S,n);for(let t of[W,`${W}.cmd`,`${W}.ps1`])try{rmSync(t,{force:!0,maxRetries:10,retryDelay:100})}catch{}if(writeFileSync(W,buildBinShim(F.location,I,H,C,process.platform,t),{mode:493}),chmodSync(W,493),process.platform===`win32`)for(let[t,n]of Object.entries(buildWorkspaceBinShimsForWindows(F.location,I,H,C)))writeFileSync(`${W}.${t}`,n,{mode:493});N++}}}return N}function extractOverrides(t){if(!t)return;let n={},S=new Map,merge=(t,C)=>{if(t){for(let[N,F]of Object.entries(t))if(!N.startsWith(`_`)){if(typeof F==`string`){let t=N,S=N.startsWith(`@`)?N.indexOf(`@`,1):N.indexOf(`@`);S>0&&(t=N.slice(0,S)),n[t]=F;continue}if(F&&typeof F==`object`&&!Array.isArray(F)){let t={};for(let[n,S]of Object.entries(F)){if(n.startsWith(`_`))continue;if(typeof S!=`string`){ge.warn(`gjsify install: ${C}["${N}"]["${n}"] is not a string — only one level of nesting is supported, skipping`);continue}let F=n,I=n.startsWith(`@`)?n.indexOf(`@`,1):n.indexOf(`@`);I>0&&(F=n.slice(0,I)),t[F]=S}if(Object.keys(t).length>0){let n=S.get(N)??{};S.set(N,{...n,...t})}continue}ge.warn(`gjsify install: ${C}["${N}"] is not a string or object — skipping`)}}};if(merge(t.overrides,`overrides`),merge(t.resolutions,`resolutions`),!(Object.keys(n).length===0&&S.size===0))return{global:n,scoped:S}}function scopedOverrideFor(t,n,S){if(!S||S.scoped.size===0)return;let C=[t.name,t.relativeLocation];for(let t of C){let C=S.scoped.get(t);if(C?.[n])return C[n]}}function buildBinShim(t,n,S,C=[],N=process.platform,F=t){let I=n?In(t,n):null,H=S?In(t,S):null,W=buildNativeEnvPreamble(F,C,{platform:N});if(I&&H){let t=N===`darwin`||N===`win32`,n=`if command -v gjs >/dev/null 2>&1 && [ -f "${H}" ]; then\n${W}exec gjs -m "${H}" "$@"\nfi\nexec node "${I}" "$@"\n`,S=`if command -v node >/dev/null 2>&1 && [ -f "${I}" ]; then\nexec node "${I}" "$@"\nfi\n${W}exec gjs -m "${H}" "$@"\n`;return`#!/bin/sh
1196
1196
  `+(t?S:n)}if(I)return`#!/bin/sh\nexec node "${I}" "$@"\n`;if(H)return`#!/bin/sh\n${W}exec gjs -m "${H}" "$@"\n`;throw Error(`buildBinShim: either nodeTarget or gjsTarget must be provided`)}function buildWorkspaceBinShimsForWindows(t,n,S,C=[]){let N=n?In(t,n):null,F=S?In(t,S):null;if(N)return buildLauncherShims({interpreter:`node`,target:N});if(F){let t=C.join(`;`);return buildLauncherShims({interpreter:`gjs`,interpreterArgs:[`-m`],target:F,prependEnv:C.length===0?{}:{GI_TYPELIB_PATH:t,PATH:t}})}throw Error(`buildWorkspaceBinShimsForWindows: either nodeTarget or gjsTarget must be provided`)}function mergeWorkspaceBins(t,n,S){let C=new Map,N=t.startsWith(`@`)?t.slice(t.indexOf(`/`)+1):t,get=t=>{let n=C.get(t);return n||(n={},C.set(t,n)),n};if(typeof S==`string`)get(N).nodeTarget=S;else if(S&&typeof S==`object`)for(let[t,n]of Object.entries(S))typeof n==`string`&&n.length>0&&(get(t).nodeTarget=n);if(typeof n==`string`)get(N).gjsTarget=n;else if(n&&typeof n==`object`)for(let[t,S]of Object.entries(n))typeof S==`string`&&S.length>0&&(get(t).gjsTarget=S);return C}async function projectInstallViaNpm(t){let n=[`install`];t[`save-dev`]&&n.push(`--save-dev`),t[`save-peer`]&&n.push(`--save-peer`),t[`save-optional`]&&n.push(`--save-optional`),t.verbose&&n.push(`--loglevel`,`verbose`),t.packages&&t.packages.length>0&&n.push(...t.packages),await spawnNpm(n)}async function spawnNpm(t){return spawnToCompletion(`npm`,t,{completion:`return`,notFound:()=>Error(`npm not found on PATH — install Node.js first.`)}).then(({code:t})=>{if(t!==0)throw Error(`npm install exited with code ${t}`)}).catch(t=>{let n=t.code;ge.error(n===void 0?t.message:`npm install failed: ${t.message}`),process.exit(1)})}async function installGlobalAndLink(t,n){let S=defaultGlobalLayout();mkdirSync(S.prefix,{recursive:!0}),ge.log(`gjsify install --global → ${S.prefix}`),ge.log(` bins → ${S.binDir}`);let C=await acquireInstallLock(S.prefix,{});try{let C=await installPackages({prefix:S.prefix,specs:t,verbose:n.verbose}),N=t.map(specToPackageName);if(N.includes(`@gjsify/cli`)){let t=C.installed.find(t=>t.name===`@gjsify/cli`)?.version??`latest`;await installGjsEnginePackages(S.prefix,t,{verbose:n.verbose})}n.prune!==!1&&pruneAfterInstall(S.prefix,resolveHostPlatform({env:{}}),{hint:`gjsify prune -g --dry-run`}),reportLinkedBins(linkGlobalBins(N,S),S.binDir)}finally{C.release()}}function pruneProjectPrefix(t){t.prune!==!1&&pruneAfterInstall(process.cwd(),resolveHostPlatform({env:{}}),{immutable:t.immutable===!0,hint:`gjsify prune --dry-run`})}function reportLinkedBins(t,n){if(t.length===0)ge.warn("\nNo bins declared (neither `gjsify.bin` nor `bin` in package.json) — nothing was symlinked.");else{ge.log(`\nLinked ${t.length} bin(s):`);for(let n of t)ge.log(` • ${n.link} → ${n.target}`)}t.length>0&&!binDirOnPath(n)&&ge.warn(`\nNote: ${n} is not on your PATH.\nAdd it to your shell rc file:\n export PATH="${n}:$PATH"`)}async function ensureProjectGjsEngine(t,n,S={}){let C=S.cwd??process.cwd(),N=S.hasEngineFn??hasBundlerEngineInstalled;if(!existsSync(In(C,`node_modules`,`@gjsify`,`cli`,`package.json`))||!n||N(C))return;if(t.immutable){ge.warn(`\nWarning: \`gjsify build\` will fail under GJS — ${Nz} is not installed, and\n --immutable cannot add it (the lockfile does not name it). Declare it so the lockfile carries it:
1197
1197
  gjsify install ${Nz}\n Under Node the npm \`rolldown\` engine is used instead and this does not apply.`);return}let F=readCliVersionFrom(In(C,`node_modules`,`@gjsify`,`cli`,`package.json`))??`latest`;ge.log(`\n${Nz} is missing and this host can run gjs, so \`gjsify build\` would have no\n bundler engine (there is no npm \`rolldown\` fallback under GJS). Installing the GJS engine set at\n ${F}, in lockstep with the CLI.`),await(S.installFn??installGjsEnginePackages)(C,F,{verbose:t.verbose})}async function runPostInstallChecks(t){ge.log(`
1198
1198
  --- gjsify post-install checks ---`);let n=runMinimalChecks(),S=n.filter(t=>!t.found&&t.severity===`required`);if(S.length>0){ge.warn(`Missing required system dependencies:
@@ -1204,27 +1204,27 @@ A misplaced catalogue installs and then shows nothing, which reads exactly like
1204
1204
  A bridge lost that way is silently absent from the next build rather than
1205
1205
  reported, so the first symptom can be an unrelated-looking bundler error
1206
1206
  (\`Could not load <file>\` from rolldown, for the CSS bridge). Nothing to
1207
- install: no \`-musl\` package is published for any target yet.`)}}maybeInstallGitHooks()}function maybeInstallGitHooks(){let t=process.cwd(),n=In(t,`scripts`,`install-git-hooks.mjs`);if(existsSync(n)&&existsSync(In(t,`.git`)))try{let S=spawnSync(nodeBinary(),[n,`--quiet`],{cwd:t,stdio:`inherit`,env:process.env});S.status!==0&&ge.warn(`[gjsify install] scripts/install-git-hooks.mjs exited ${S.status} — git hooks may not be active.`)}catch(t){ge.warn(`[gjsify install] git hook installation skipped: ${t instanceof Error?t.message:String(t)}`)}}var sG,cG,lG,uG,dG=__esmMin(()=>{_e(),ef(),qn(),ir(),ev(),oG(),AI(),ZI(),nL(),yR(),jz(),LR(),nz(),kR(),sv(),MI(),gV(),Fz(),gz(),vz(),FR(),xz(),sG=process.platform===`win32`?`junction`:void 0,cG=18e5,lG={command:`install [packages..]`,description:`Install npm dependencies in the current project (or globally with -g), then run gjsify-aware post-checks.`,builder:t=>t.positional(`packages`,{description:`Optional package specs. With none, runs a full project install.`,type:`string`,array:!0}).option(`global`,{description:`Install into the user-global XDG location and symlink bins into ~/.local/bin.`,type:`boolean`,alias:`g`,default:!1}).option(`save-dev`,{type:`boolean`,alias:`D`}).option(`save-peer`,{type:`boolean`}).option(`save-optional`,{type:`boolean`,alias:`O`}).option(`immutable`,{description:`CI mode: install strictly from gjsify-lock.json, fail if the lockfile is missing or stale. Equivalent to yarn --immutable / npm ci --frozen-lockfile.`,type:`boolean`,default:!1}).option(`refresh-lockfile`,{description:`Re-resolve every dependency to the newest version satisfying its range and rewrite the lockfile (bumps in-range transitive deps). Without it, a resolve preserves versions already pinned in the lockfile and only resolves new/changed deps — the npm/yarn/pnpm default. Mirrors yarn install --mode=update-lockfile.`,type:`boolean`,default:!1}).option(`focus`,{description:`Install only the named workspaces (package names), the workspaces they depend on, and their external dependencies, as if they were the only members of the monorepo (yarn workspaces focus). Reads gjsify-lock.json and never rewrites it; fails if it is missing or stale. Workspace projects only.`,type:`string`,array:!0}).option(`verbose`,{description:`Verbose install logging.`,type:`boolean`,default:!1}).option(`quiet`,{description:`Silence the progress bar.`,type:`boolean`,default:!1}).option(`progress`,{description:`Show a TTY-aware progress bar for resolve / download / extract phases. Auto-enabled when stderr is a TTY (override with --no-progress). Implicitly off under --verbose (per-package log lines replace the bar) or --quiet.`,type:`boolean`,default:!0}).option(`backend`,{description:"Install backend. `native` (default) routes through `@gjsify/{semver,npm-registry,tar}` — no Node/npm at runtime. `npm` shells out to `npm install` as an escape hatch for cases the native backend does not yet model (Yarn PnP repos, lifecycle scripts). Overrides `GJSIFY_INSTALL_BACKEND` if both are set.",type:`string`,choices:[`native`,`npm`]}).option(`timeout`,{description:`Overall install wall-clock timeout in ms (default 1800000 = 30 min). On timeout, all in-flight registry fetches are aborted and the install exits non-zero with a clear "install timed out — likely a registry slowdown" message. Per-request timeouts in @gjsify/npm-registry (default 30s) still apply within this budget. Set to 0 to disable the overall budget.`,type:`number`,default:cG}).option(`os`,{description:"Resolve/install for this OS instead of the running one (npm config key `os`, e.g. darwin, win32, linux). Affects which packages pass the os/cpu/libc compatibility check; the lockfile stays platform-independent either way.",type:`string`}).option(`cpu`,{description:"Resolve/install for this CPU architecture instead of the running one (npm config key `cpu`, e.g. x64, arm64).",type:`string`}).option(`libc`,{description:"Resolve/install for this libc family instead of probing the host (npm config key `libc`: glibc or musl). Only meaningful with --os=linux. A package declaring a libc is incompatible when the target libc is unknown.",type:`string`}).option(`force`,{description:"Install a REQUIRED dependency even when its os/cpu/libc excludes the target, instead of failing with EBADPLATFORM (npm config key `force`). Incompatible OPTIONAL dependencies stay skipped — npm ignores --force for those too, and a binary that cannot load is not worth downloading.",type:`boolean`,default:!1}).option(`prune`,{description:`After installing, remove packages an earlier install left behind that this host cannot use (foreign os/cpu/libc). Use --no-prune to disable. Skipped automatically under --immutable, and whenever --os/--cpu/--libc is given: an install must never delete against a target the user typed.`,type:`boolean`,default:!0}),handler:async t=>{if(applyPlatformConfigFromFlags(t),t.immutable){if(t.packages&&t.packages.length>0)return ge.error(`gjsify install --immutable does not accept package arguments. Remove the package names or drop --immutable.`),process.exit(1);if(t.global)return ge.error(`gjsify install --immutable is incompatible with --global.`),process.exit(1);if(t[`refresh-lockfile`])return ge.error(`gjsify install --immutable is incompatible with --refresh-lockfile (--immutable forbids rewriting the lockfile). Drop one.`),process.exit(1);assertNoDevLinkUnderImmutable(process.cwd())}if(t.global){if(!t.packages||t.packages.length===0)return ge.error(`gjsify install --global requires at least one <pkg> argument.`),process.exit(1);for(let n of[`save-dev`,`save-peer`,`save-optional`])t[n]&&ge.warn(`gjsify install --global ignores --${n}: global installs do not modify a project package.json.`);await installGlobalAndLink(t.packages,{verbose:t.verbose,prune:t.prune});return}if(warnOnCliVersionSkew(process.cwd()),(t.backend??process.env.GJSIFY_INSTALL_BACKEND??`native`)===`npm`){await projectInstallViaNpm(t),pruneProjectPrefix(t),await runPostInstallChecks(t);return}let n=t.timeout>0?t.timeout:0,S=n>0?new AbortController:null,C=S===null?null:setTimeout(()=>S.abort(Error(`install-overall-timeout`)),n),N=n>0?setTimeout(()=>{let t=Math.round(n/100)/10;ge.error(`gjsify install: the ${t}s budget elapsed and the abort did not unwind within 10s — forcing exit. That means one of two things, and this timer cannot distinguish them: the install was still WORKING (a cold tree here extracts several GB, and extraction blocks the loop in multi-second synchronous stretches), or a step genuinely wedged. Re-running tells you which, and is safe: extraction is idempotent, every package already on disk is skipped, so a second run finishes the remainder in a fraction of the time. A re-run that makes NO further progress is a real wedge — file an issue.`),forceExit(1)},n+1e4):null;N?.unref?.();try{await projectInstallNative(t,S?.signal),pruneProjectPrefix(t),await runPostInstallChecks(t)}catch(t){if(S!==null&&S.signal.aborted&&isAbortedFromOverallTimeout(t)){let t=Math.round(n/100)/10;return ge.error(`gjsify install: timed out after ${t}s — likely a registry slowdown or a wedged extract.\nRe-run, or override with --timeout <ms> (set --timeout 0 to disable the overall budget).`),process.exit(1)}throw t}finally{C!==null&&clearTimeout(C),N!==null&&clearTimeout(N)}}},uG=`@gjsify/cli`});function sweepCheckouts(t,n){let S=null;try{S=readDevLinkOverride(t)?.checkout??null}catch{S=null}return S&&S!==n?[S,n]:[n]}var fG,pG,mG=__esmMin(()=>{_e(),ef(),qn(),xz(),fG={command:`link <checkout>`,description:"Link this project against a local gjsify checkout for development: its workspace packages replace the installed registry copies, recorded in a git-ignored .gjsify-link.json that every later `gjsify install` re-applies. Undo with `gjsify unlink`.",builder:t=>t.positional(`checkout`,{description:`Path to the gjsify checkout to link from (a repo whose package.json declares "workspaces").`,type:`string`,demandOption:!0}).option(`packages`,{description:"Name glob selecting which of the checkout's workspace packages take part (repeatable; default: all of them). Matched against the package NAME with the same single-segment dialect as `gjsify foreach --include`, so a whole scope is `@gjsify/*` — a bare `*` matches no scoped name. Only packages this project actually uses are linked: declared dependencies plus everything in its lockfile or installed node_modules, transitive and nested copies included.",type:`string`,array:!0}).option(`dry-run`,{description:`Print the links that would be made and write nothing.`,type:`boolean`,default:!1}),handler:t=>{let n=process.cwd(),S=t[`dry-run`]??!1,C=Nn(n,t.checkout),N=devLinkPath(n),F=resolveCheckoutWorkspaces(C,N),I=t.packages??[],H=planDevLinks({consumerRoot:n,workspaces:F,patterns:I,knownNames:consumerKnownNames(n),nested:consumerNestedPlacements(n)});if(H.length===0)return ge.error(`gjsify link: nothing to link — ${C} has ${F.length} workspace package(s), none of which ${n} uses (declared, locked or installed)${I.length===0?``:` and matches ${I.join(`, `)}`}.\nA link that links nothing is a silent no-op, so this is an error. Check the --packages pattern, or run \`gjsify install\` first so the dependency tree exists.`),process.exit(1);let W=`gjsify link${S?` (dry-run)`:``}`;ge.log(`${W} → ${C}`),ge.log(`${` `.repeat(W.length)} in ${n}`);for(let t of H)ge.log(` ${t.name} → ${Ln(C,t.target)||`.`}`);let q=unbuiltDevLinks(H);if(q.length>0)return ge.error(`\n${formatUnbuiltDevLinks(q)}`),process.exit(1);let Y=sweepCheckouts(n,C),X=new Set(H.map(t=>t.name)),Z=scanDevLinks(n,Y).filter(t=>!X.has(t.name));for(let t of Z)ge.log(` retire ${t.name} (no longer selected)`);if(S){ge.log(`\n${W}: nothing written. Drop --dry-run to apply.`);return}let te=retireDevLinks(n,Y,X),ne=applyDevLinks(H);writeDevLinkOverride(n,{version:1,checkout:C,packages:I});let re=ensureLocallyIgnored(n);ge.log(`\n ${ne.length} link(s) written, ${H.length-ne.length} already current.`),Z.length>0&&ge.log(` ${te.length} of ${Z.length} retired link(s) removed.`),ge.log(` override: ${N}`),re===`added`&&ge.log(` git: ${yz} added to .git/info/exclude (local, never committed)`),re===`no-git`&&ge.log(` git: ${n} is not a git repository — nothing to ignore`),re===`unreadable-git`&&ge.warn(` ! git: ${n} has a .git POINTER that does not parse, so ${yz} is NOT ignored. Add it to .gitignore by hand, or the next \`git add -A\` commits your local override.`),ge.log("\nEvery `gjsify install` here now re-applies these links and says so.\n`gjsify install --immutable` refuses while the override exists. Undo: `gjsify unlink`.")}},pG={command:`unlink`,description:"Undo `gjsify link`: remove the development links and the .gjsify-link.json override, then reinstall the registry copies.",builder:t=>t.option(`dry-run`,{description:`Print what would be removed and change nothing.`,type:`boolean`,default:!1}).option(`install`,{description:"Reinstall after unlinking, to put the registry copies back where the links were. On by default; --no-install leaves the holes for a later `gjsify install`.",type:`boolean`,default:!0}),handler:async t=>{let n=process.cwd(),S=t[`dry-run`]??!1,C=devLinkPath(n);if(!existsSync(C)){ge.log(`gjsify unlink: no development link in ${n} (no ${yz}).`);return}let N=[];try{let t=readDevLinkOverride(n)?.checkout;t&&N.push(t)}catch{}let F=[];try{F=prepareDevLinks(n)?.links??[]}catch(t){ge.warn(`gjsify unlink: ${t instanceof Error?t.message:String(t)}\n Removing the override anyway; any dangling links are cleaned by the reinstall.`)}let I=`gjsify unlink${S?` (dry-run)`:``}`;if(ge.log(`${I} in ${n}`),S){let t=new Set(F.map(t=>t.name));for(let S of scanDevLinks(n,N))t.add(S.name);for(let n of[...t].sort())ge.log(` would remove link ${n}`);ge.log(` would remove ${C}`),ge.log(` would remove ${yz} entry from .git/info/exclude (if this module wrote it)`),ge.log(`\n${I}: nothing changed. Drop --dry-run to apply.`);return}let H=removeDevLinks(F),W=new Set(H.map(t=>t.name));for(let t of retireDevLinks(n,N,new Set))W.has(t.name)||H.push(t);for(let t of H)ge.log(` unlinked ${t.name}`);let q=scanDevLinks(n,N);if(q.length>0)return ge.error(`gjsify unlink: ${q.length} link(s) still point into a checkout and could not be removed:\n`+q.map(t=>` ${t.name} ${t.linkPath} → ${t.target}`).join(`
1208
- `)+`\n ${C} is kept so this stays undoable. Remove the paths above and re-run.`),process.exit(1);if(removeDevLinkOverride(n),ge.log(` removed ${C}`),removeLocalIgnore(n)===`removed`&&ge.log(` removed ${yz} entry from .git/info/exclude`),t.install===!1){ge.log(`\n ${H.length} link(s) removed. Run \`gjsify install\` to restore the registry copies.`);return}ge.log(`\n ${H.length} link(s) removed — reinstalling to restore the registry copies.\n`);let{runCli:Y}=await Promise.resolve().then(()=>(iY(),rY));await Y([`install`])}}});function splitWorkspaceSpecifier(t,n){if(t.startsWith(`.`)||t.startsWith(`/`)||t.includes(`:`))return null;let S=t.split(`/`),C=t.startsWith(`@`)?[2]:[1];for(let t of C){let C=S.slice(0,t).join(`/`);if(!n.has(C))continue;let N=S.slice(t).join(`/`);return{name:C,subpath:N?`./${N}`:`.`}}return null}function resolveRelative(t,n){let S=Nn(zn(t),n);for(let t of[S,`${S}.js`,`${S}.mjs`,In(S,`index.js`)])try{if(statSync(t).isFile())return t}catch{}return null}function workspaceEntry(t,n){let S=t.manifest,pick=t=>{if(typeof t==`string`)return t;if(!t||typeof t!=`object`||Array.isArray(t))return null;let n=t;for(let t of[`node`,`import`,`default`,`gjs`])if(t in n){let S=pick(n[t]);if(S)return S}return null},C=null;if(typeof S.exports==`string`?C=n===`.`?S.exports:null:S.exports&&typeof S.exports==`object`&&(C=pick(S.exports[n])),!C&&n===`.`&&(C=typeof S.module==`string`?S.module:null,C??=typeof S.main==`string`?S.main:null),!C)return null;let N=Nn(t.location,C);return existsSync(N)?N:null}function workspacePeers(t,n){return Object.keys(t.peerDependencies??{}).filter(t=>n.has(t))}function cliRuntimeClosure(t,n={}){let S=new Map(t.map(t=>[t.name,t])),C=new Set,N=n.entry,F=n.cliManifest;if(N===void 0||F===void 0){let t=cliPackageDir(),n=null;if(t)try{n=JSON.parse(readFileSync(In(t,`package.json`),`utf8`))}catch{}if(F??=n,N===void 0){let S=n?.bin,C=typeof S==`string`?S:S?.gjsify??n?.main;N=t&&C?Nn(t,C):null}}for(let t of workspacePeers(F??{},S))C.add(t);if(!N||!existsSync(N))return C;let I=new Set,H=[N];for(;H.length>0;){let t=H.shift();if(I.has(t))continue;I.add(t);let n;try{n=readFileSync(t,`utf8`)}catch{continue}for(let N of moduleSpecifiers$1(n)){if(N.startsWith(`.`)){let n=resolveRelative(t,N);n&&H.push(n);continue}let n=splitWorkspaceSpecifier(N,S),F=n?S.get(n.name):void 0;if(!n||!F)continue;C.add(n.name);for(let t of workspacePeers(F.manifest,S))C.add(t);let I=workspaceEntry(F,n.subpath);I&&H.push(I)}}return C}var hG=__esmMin(()=>{ef(),qn(),QN(),yh()});function signalTree(t,n,S){for(let t=n.length-1;t>=0;t--)try{process.kill(n[t],S)}catch{}try{t.kill(S)}catch{}}function killActiveChildren(){let t=new Map;for(let n of gG){let S=n.pid?collectDescendants(n.pid):[];t.set(n,S),signalTree(n,S,`SIGTERM`)}setTimeout(()=>{for(let n of gG){let S=new Set(n.pid?collectDescendants(n.pid):[]);for(let C of t.get(n)??[])S.add(C);signalTree(n,[...S],`SIGKILL`)}},_G).unref?.()}function assertEveryIncludeMatches(t,n){if(!n||n.length===0)return;let S=n.filter(n=>filterWorkspaces(t,{include:[n]}).length===0);if(S.length===0)return;let C=[`gjsify foreach: --include matched no workspace (${S.length} of ${n.length} pattern(s)):`];for(let n of S){C.push(` ${JSON.stringify(n)}`);let S=stripSurroundingQuotes(n);if(S!==n&&filterWorkspaces(t,{include:[S]}).length>0){C.push(` → matches as ${JSON.stringify(S)}: the QUOTES are part of the value. A shell expansion`," is not re-scanned for quoting, so a pre-quoted filter spliced through `sh -c` arrives with",` the quotes attached. Pass the bare name and let word splitting do the work.`);continue}let N=t.map(t=>t.name).filter(t=>t.toLowerCase().includes(S.replace(/\*/g,``).toLowerCase())).slice(0,3);N.length>0&&C.push(` → did you mean: ${N.join(`, `)}?`)}throw C.push(` ${t.length} workspace(s) discovered. Refusing to run: a filter that selects nothing would`,` otherwise exit 0 and look exactly like a successful run over the whole set.`),ge.error(C.join(`
1209
- `)),process.exit(1),Error(`gjsify foreach: --include matched no workspace`)}function stripSurroundingQuotes(t){return t.length>=2&&(t[0]===`'`||t[0]===`"`)&&t[t.length-1]===t[0]?t.slice(1,-1):t}async function runSequential(t,n,S,C,N,F){for(let I of t)await runOne(I,n,S,!1,C,N,F)}async function runParallel(t,n,S,C,N,F,I){let H=0,W=[];for(let q=0;q<C;q++)W.push((async()=>{for(;H<t.length;)await runOne(t[H++],n,S,!0,N,F,I)})());await Promise.all(W)}async function runTopologicalParallel(t,n,S,C,N,F,I,H){let W=new Map([...buildDependencyGraph(t,{includeDev:F}).edges].map(([t,n])=>[t,new Set(n)])),q=new Map(t.map(t=>[t.name,t])),Y=t.length,X=new Set,Z=0,te=!process.stdout.isTTY||N,ne=new Map,re=Number(process.env.GJSIFY_FOREACH_STALL_MINUTES??`20`),ie=(Number.isFinite(re)&&re>0?re:20)*6e4;return new Promise((t,F)=>{let re=null,ae=Date.now(),describeInflight=()=>[...ne.entries()].map(([t,n])=>`${t} (${Math.round((Date.now()-n)/1e3)}s)`).join(`, `),failFast=t=>{re||(re=t,killActiveChildren(),setTimeout(()=>settle(),vG).unref?.())},oe=setInterval(()=>{let t=Date.now()-ae;t<3e5||ne.size===0||(ge.error(`[gjsify foreach] WARNING: no workspace completed for ${Math.round(t/6e4)}min — in-flight: ${describeInflight()}`),t>=ie&&failFast(Error(`gjsify foreach: stalled — no workspace completed for ${Math.round(t/6e4)}min (override via GJSIFY_FOREACH_STALL_MINUTES); killed in-flight: ${describeInflight()}`)))},6e4);oe.unref?.();let settle=()=>{clearInterval(oe),re?F(re):t()},pump=()=>{if(!re){for(;Z<C;){let t=[...W.entries()].filter(([,t])=>[...t].every(t=>X.has(t))).map(([t])=>t);if(t.length===0)break;let C=t.sort()[0];W.delete(C),Z++,ne.set(C,Date.now()),te&&ge.error(`[gjsify foreach] start ${C} (${X.size}/${Y} done, ${Z} in flight)`),runOne(q.get(C),n,S,!0,N,I,H).then(()=>{X.add(C)}).catch(t=>{failFast(t instanceof Error?t:Error(String(t)))}).finally(()=>{Z--,ne.delete(C),ae=Date.now(),re?Z===0&&settle():W.size===0&&Z===0?settle():pump()})}W.size>0&&Z===0&&!re&&(clearInterval(oe),F(Error(`gjsify foreach --topological: stuck — workspaces ${[...W.keys()].join(`, `)} have unsatisfied deps in the selected set`)))}};pump()})}async function runOne(t,n,S,C,N,F,I){if(F){N&&ge.error(`[${t.name}] $ ${n} ${S.join(` `)}`),await spawnPrefixed(n,S,t.location,C?`[${t.name}] `:null);return}if(I&&I.tryRestore(t))return;let H=I?.snapshotOutputs(t),W=detectPackageManager(),q=W===`gjsify`?[`run`,n,...S]:[`run`,n,...S.length>0?[`--`,...S]:[]];N&&ge.error(`[${t.name}] $ ${W} ${q.join(` `)}`),await spawnPrefixed(W,q,t.location,C?`[${t.name}] `:null),I&&H&&I.storeAfterSuccess(t,H)}async function spawnPrefixed(t,n,S,C){let N=null,F=[];try{let I=await spawnToCompletion(t,n,{completion:`exit`,cwd:S,stdio:C?`pipe`:`inherit`,color:!0,onSpawn:t=>{N=t,gG.add(t);let n=!process.stdout.isTTY;C&&t.stdout&&t.stderr&&(F.push(prefixLines(t.stdout,process.stdout,C,n)),F.push(prefixLines(t.stderr,process.stderr,C,n)))}});for(let t of F)t();if(I.code!==0)throw Error(`${t} ${n.join(` `)} exited with code ${I.code}`)}finally{N&&gG.delete(N)}}var gG,_G,vG,yG,bG=__esmMin(()=>{_e(),sv(),qR(),$g(),AI(),MI(),hG(),Jz(),dR(),Qz(),tB(),gG=new Set,_G=5e3,vG=15e3,yG={command:`foreach [script] [args..]`,description:"Run a workspace script across all (or filtered) workspaces. Drop-in for `yarn workspaces foreach`: -A/--all, -p/--parallel, -t/--topological, --include, --exclude, --no-private. Pass --exec to run an arbitrary command instead of a script.",builder:t=>t.positional(`script`,{description:"Script name to run in each workspace (`run <name>`-equivalent). With --exec, the command to run instead.",type:`string`}).positional(`args`,{description:`Extra arguments forwarded to each child invocation.`,type:`string`,array:!0}).option(`all`,{description:"Include workspaces declared as `private: true`.",type:`boolean`,alias:`A`,default:!1}).option(`parallel`,{description:`Run workspaces in parallel (capped by --jobs).`,type:`boolean`,alias:`p`,default:!1}).option(`topological`,{description:`Wait for each workspace's deps to finish before starting it (production deps only).`,type:`boolean`,alias:`t`,default:!1}).option(`topological-dev`,{description:`Like --topological but also respects devDependencies (often cyclic — use sparingly).`,type:`boolean`,default:!1}).option(`include`,{description:`Glob pattern to include workspaces by name (repeatable). A pattern that matches NO discovered workspace is a hard error — a filter selecting nothing is a typo or a caller-side quoting bug, never an intent.`,type:`string`,array:!0}).option(`exclude`,{description:`Glob pattern to exclude workspaces by name (repeatable).`,type:`string`,array:!0}).option(`with-dependencies`,{description:`Also select everything the filtered set DEPENDS ON (production deps; add --topological-dev for devDependencies). --include only filters and --topological only orders, so neither can say 'and the packages these need'. Excludes are re-applied afterwards.`,type:`boolean`,alias:`d`,default:!1}).option(`private`,{description:`Include private workspaces (default true). Pass --no-private to skip them.`,type:`boolean`,default:!0}).option(`verbose`,{description:`Echo every spawned command before running it.`,type:`boolean`,alias:`v`,default:!1}).option(`jobs`,{description:`Maximum concurrent workspaces in --parallel mode (default: cpu count).`,type:`number`,alias:`j`}).option(`exec`,{description:"Treat <script> [args..] as an arbitrary command (yarn `workspaces foreach exec`-equivalent) instead of a package.json script lookup. Workspace filtering by script presence is skipped. Use `-- <cmd> <args...>` to pass flags to the command without yargs intercepting them.",type:`boolean`,default:!1}).option(`cached`,{description:`Content-hash build cache (ADR 0006): skip a workspace whose inputs (src/**, package.json, tsconfig*.json, transitive workspace deps, toolchain versions) are unchanged and restore its stored outputs instead; on miss run the script and store the output dirs it modified. Script mode only. Default from GJSIFY_BUILD_CACHE=1.`,type:`boolean`}).option(`shard`,{description:`Run only a deterministic slice "<index>/<total>" (1-based) of the matched workspaces, e.g. --shard 2/4. For fanning a long run across parallel CI jobs. Partitions by sorted name (round-robin) so the shards are disjoint and their union is the full set; order-independent, so safe for tests but NOT for ordered builds.`,type:`string`}).parserConfiguration({"populate--":!0,"parse-positional-numbers":!1}),handler:async t=>{let n=findWorkspaceRoot(process.cwd())??process.cwd(),S=discoverWorkspaces(n),C=t.exec===!0,N=t.script,F=t.args??[];if(!C){let n=doubleDashArgs(t);n.length>0&&(F=[...F,...n])}if(C){let n=doubleDashArgs(t);if(n.length>0&&(N?F=[...F,...n]:(N=n[0],F=[...F,...n.slice(1)])),!N)return ge.error("gjsify foreach --exec: missing command. Pass it after `--`, e.g. `gjsify foreach --exec -- npm publish --tag latest`."),process.exit(1)}assertEveryIncludeMatches(S,t.include);let I=filterWorkspaces(S,{include:t.include,exclude:t.exclude,noPrivate:t.private===!1});if(t[`with-dependencies`]===!0){let n=affectedClosure(buildDependencyGraph(S,{includeDev:t[`topological-dev`]===!0}),I.map(t=>t.name));I=filterWorkspaces(S.filter(t=>n.has(t.name)),{exclude:t.exclude,noPrivate:t.private===!1})}if(!C){if(!N)return ge.error(`gjsify foreach: missing <script> positional. Pass --exec to run an arbitrary command instead.`),process.exit(1);let t=N;I=I.filter(n=>typeof(n.manifest.scripts??{})[t]==`string`)}if(typeof t.shard==`string`&&t.shard.length>0){let n=/^\s*(\d+)\s*\/\s*(\d+)\s*$/.exec(t.shard);if(!n)return ge.error(`gjsify foreach: invalid --shard "${t.shard}" — expected "<index>/<total>" (1-based), e.g. 2/4.`),process.exit(1);let S=Number(n[1]),C=Number(n[2]);if(C<1||S<1||S>C)return ge.error(`gjsify foreach: invalid --shard "${t.shard}" — need 1 <= index <= total and total >= 1.`),process.exit(1);if(C>1){let t=[...I].sort((t,n)=>t.name<n.name?-1:+(t.name>n.name));I=t.filter((t,n)=>n%C===S-1),ge.log(`gjsify foreach: shard ${S}/${C} → ${I.length} of ${t.length} workspace(s)`)}}if(I.length===0){ge.log(`gjsify foreach: no workspaces match (${C?`exec`:`script`}="${N}", include=${JSON.stringify(t.include??[])}, exclude=${JSON.stringify(t.exclude??[])})`);return}(t.topological||t[`topological-dev`])&&(I=topologicalSort(buildDependencyGraph(I,{includeDev:t[`topological-dev`]===!0})));let H=t.verbose===!0,W=N,q=t.cached??buildCacheEnabledByEnv();if(t.cached===!0&&C)return ge.error(`gjsify foreach: --cached only applies to script mode, not --exec.`),process.exit(1);let Y=q&&!C?new BuildCacheRunner({root:n,workspaces:S,script:W,args:F,targets:I.map(t=>t.name)}):void 0,X=t.parallel===!0?cliRuntimeClosure(S):new Set,Z=X.size>0?I.filter(t=>X.has(t.name)):[],te=Z.length>0?I.filter(t=>!X.has(t.name)):I;try{if(Z.length>0){ge.error(`[gjsify foreach] serial prefix: ${Z.length} package(s) the running CLI imports — ${Z.map(t=>t.name).join(`, `)}`);for(let t of Z)ge.error(`[gjsify foreach] start ${t.name} (serial prefix)`),await runOne(t,W,F,!0,H,C,Y)}if(t.parallel&&!t.topological&&!t[`topological-dev`]){let n=t.jobs&&t.jobs>0?t.jobs:cpus().length;await runParallel(te,W,F,n,H,C,Y)}else if(t.parallel){let n=t.jobs&&t.jobs>0?t.jobs:cpus().length;await runTopologicalParallel(te,W,F,n,H,t[`topological-dev`]===!0,C,Y)}else await runSequential(te,W,F,H,C,Y)}catch(t){return killActiveChildren(),ge.error(t.message),process.exit(1)}process.exit(0)}}});async function runLifecycleScript(t,n,S,C={}){let N=(n.scripts??{})[S];if(typeof N!=`string`){if(C.optional!==!1)return!1;throw Error(`gjsify lifecycle-script: no "${S}" in ${t}/package.json`)}let F=findWorkspaceRoot(t),I=[In(t,`node_modules`,`.bin`)];F&&F!==t&&I.push(In(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(Gn),npm_lifecycle_event:S,npm_package_name:n.name??``,npm_package_version:n.version??``,...C.env};if(C.stdio===`ignore`)throw Error(`gjsify lifecycle-script: stdio "ignore" is not supported — see utils/spawn.ts`);let q=await spawnToCompletion(N,[],{completion:`return`,cwd:t,env:W,shell:!0,stdio:C.stdio===`inherit-stderr`?`inherit-stderr`:C.stdio===`pipe`?`pipe`:`inherit`});if(q.code!==0)throw Error(`gjsify lifecycle-script: "${S}" in ${t} exited with ${describeExit(q)}`);return!0}var xG=__esmMin(()=>{qn(),sv(),MI()});async function packWorkspace(t,n={}){let S=In(t,`package.json`);if(!existsSync(S))throw Error(`gjsify pack: no package.json at ${t}`);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 ${t} has no "name"`);let H=n.lifecycleScripts??[`prepack`];for(let S of H)await runLifecycleScript(t,N,S,{optional:!0,stdio:n.lifecycleStdio});let W=readFileSync(S,`utf-8`),q=W===C?N:JSON.parse(W),Y=n.skipWorkspaceRewrite?q:rewriteWorkspaceDeps(q,t),X=JSON.stringify(Y,null,indentOf(W))+`
1207
+ install: no \`-musl\` package is published for any target yet.`)}}maybeInstallGitHooks()}function maybeInstallGitHooks(){let t=process.cwd(),n=In(t,`scripts`,`install-git-hooks.mjs`);if(existsSync(n)&&existsSync(In(t,`.git`)))try{let S=spawnSync(nodeBinary(),[n,`--quiet`],{cwd:t,stdio:`inherit`,env:process.env});S.status!==0&&ge.warn(`[gjsify install] scripts/install-git-hooks.mjs exited ${S.status} — git hooks may not be active.`)}catch(t){ge.warn(`[gjsify install] git hook installation skipped: ${t instanceof Error?t.message:String(t)}`)}}var cG,lG,uG,dG,fG=__esmMin(()=>{_e(),ef(),qn(),ir(),ev(),sG(),AI(),ZI(),nL(),yR(),jz(),LR(),nz(),kR(),sv(),MI(),_V(),Fz(),gz(),vz(),FR(),xz(),cG=process.platform===`win32`?`junction`:void 0,lG=18e5,uG={command:`install [packages..]`,description:`Install npm dependencies in the current project (or globally with -g), then run gjsify-aware post-checks.`,builder:t=>t.positional(`packages`,{description:`Optional package specs. With none, runs a full project install.`,type:`string`,array:!0}).option(`global`,{description:`Install into the user-global XDG location and symlink bins into ~/.local/bin.`,type:`boolean`,alias:`g`,default:!1}).option(`save-dev`,{type:`boolean`,alias:`D`}).option(`save-peer`,{type:`boolean`}).option(`save-optional`,{type:`boolean`,alias:`O`}).option(`immutable`,{description:`CI mode: install strictly from gjsify-lock.json, fail if the lockfile is missing or stale. Equivalent to yarn --immutable / npm ci --frozen-lockfile.`,type:`boolean`,default:!1}).option(`refresh-lockfile`,{description:`Re-resolve every dependency to the newest version satisfying its range and rewrite the lockfile (bumps in-range transitive deps). Without it, a resolve preserves versions already pinned in the lockfile and only resolves new/changed deps — the npm/yarn/pnpm default. Mirrors yarn install --mode=update-lockfile.`,type:`boolean`,default:!1}).option(`focus`,{description:`Install only the named workspaces (package names), the workspaces they depend on, and their external dependencies, as if they were the only members of the monorepo (yarn workspaces focus). Reads gjsify-lock.json and never rewrites it; fails if it is missing or stale. Workspace projects only.`,type:`string`,array:!0}).option(`verbose`,{description:`Verbose install logging.`,type:`boolean`,default:!1}).option(`quiet`,{description:`Silence the progress bar.`,type:`boolean`,default:!1}).option(`progress`,{description:`Show a TTY-aware progress bar for resolve / download / extract phases. Auto-enabled when stderr is a TTY (override with --no-progress). Implicitly off under --verbose (per-package log lines replace the bar) or --quiet.`,type:`boolean`,default:!0}).option(`backend`,{description:"Install backend. `native` (default) routes through `@gjsify/{semver,npm-registry,tar}` — no Node/npm at runtime. `npm` shells out to `npm install` as an escape hatch for cases the native backend does not yet model (Yarn PnP repos, lifecycle scripts). Overrides `GJSIFY_INSTALL_BACKEND` if both are set.",type:`string`,choices:[`native`,`npm`]}).option(`timeout`,{description:`Overall install wall-clock timeout in ms (default 1800000 = 30 min). On timeout, all in-flight registry fetches are aborted and the install exits non-zero with a clear "install timed out — likely a registry slowdown" message. Per-request timeouts in @gjsify/npm-registry (default 30s) still apply within this budget. Set to 0 to disable the overall budget.`,type:`number`,default:lG}).option(`os`,{description:"Resolve/install for this OS instead of the running one (npm config key `os`, e.g. darwin, win32, linux). Affects which packages pass the os/cpu/libc compatibility check; the lockfile stays platform-independent either way.",type:`string`}).option(`cpu`,{description:"Resolve/install for this CPU architecture instead of the running one (npm config key `cpu`, e.g. x64, arm64).",type:`string`}).option(`libc`,{description:"Resolve/install for this libc family instead of probing the host (npm config key `libc`: glibc or musl). Only meaningful with --os=linux. A package declaring a libc is incompatible when the target libc is unknown.",type:`string`}).option(`force`,{description:"Install a REQUIRED dependency even when its os/cpu/libc excludes the target, instead of failing with EBADPLATFORM (npm config key `force`). Incompatible OPTIONAL dependencies stay skipped — npm ignores --force for those too, and a binary that cannot load is not worth downloading.",type:`boolean`,default:!1}).option(`prune`,{description:`After installing, remove packages an earlier install left behind that this host cannot use (foreign os/cpu/libc). Use --no-prune to disable. Skipped automatically under --immutable, and whenever --os/--cpu/--libc is given: an install must never delete against a target the user typed.`,type:`boolean`,default:!0}),handler:async t=>{if(applyPlatformConfigFromFlags(t),t.immutable){if(t.packages&&t.packages.length>0)return ge.error(`gjsify install --immutable does not accept package arguments. Remove the package names or drop --immutable.`),process.exit(1);if(t.global)return ge.error(`gjsify install --immutable is incompatible with --global.`),process.exit(1);if(t[`refresh-lockfile`])return ge.error(`gjsify install --immutable is incompatible with --refresh-lockfile (--immutable forbids rewriting the lockfile). Drop one.`),process.exit(1);assertNoDevLinkUnderImmutable(process.cwd())}if(t.global){if(!t.packages||t.packages.length===0)return ge.error(`gjsify install --global requires at least one <pkg> argument.`),process.exit(1);for(let n of[`save-dev`,`save-peer`,`save-optional`])t[n]&&ge.warn(`gjsify install --global ignores --${n}: global installs do not modify a project package.json.`);await installGlobalAndLink(t.packages,{verbose:t.verbose,prune:t.prune});return}if(warnOnCliVersionSkew(process.cwd()),(t.backend??process.env.GJSIFY_INSTALL_BACKEND??`native`)===`npm`){await projectInstallViaNpm(t),pruneProjectPrefix(t),await runPostInstallChecks(t);return}let n=t.timeout>0?t.timeout:0,S=n>0?new AbortController:null,C=S===null?null:setTimeout(()=>S.abort(Error(`install-overall-timeout`)),n),N=n>0?setTimeout(()=>{let t=Math.round(n/100)/10;ge.error(`gjsify install: the ${t}s budget elapsed and the abort did not unwind within 10s — forcing exit. That means one of two things, and this timer cannot distinguish them: the install was still WORKING (a cold tree here extracts several GB, and extraction blocks the loop in multi-second synchronous stretches), or a step genuinely wedged. Re-running tells you which, and is safe: extraction is idempotent, every package already on disk is skipped, so a second run finishes the remainder in a fraction of the time. A re-run that makes NO further progress is a real wedge — file an issue.`),forceExit(1)},n+1e4):null;N?.unref?.();try{await projectInstallNative(t,S?.signal),pruneProjectPrefix(t),await runPostInstallChecks(t)}catch(t){if(S!==null&&S.signal.aborted&&isAbortedFromOverallTimeout(t)){let t=Math.round(n/100)/10;return ge.error(`gjsify install: timed out after ${t}s — likely a registry slowdown or a wedged extract.\nRe-run, or override with --timeout <ms> (set --timeout 0 to disable the overall budget).`),process.exit(1)}throw t}finally{C!==null&&clearTimeout(C),N!==null&&clearTimeout(N)}}},dG=`@gjsify/cli`});function sweepCheckouts(t,n){let S=null;try{S=readDevLinkOverride(t)?.checkout??null}catch{S=null}return S&&S!==n?[S,n]:[n]}var pG,mG,hG=__esmMin(()=>{_e(),ef(),qn(),xz(),pG={command:`link <checkout>`,description:"Link this project against a local gjsify checkout for development: its workspace packages replace the installed registry copies, recorded in a git-ignored .gjsify-link.json that every later `gjsify install` re-applies. Undo with `gjsify unlink`.",builder:t=>t.positional(`checkout`,{description:`Path to the gjsify checkout to link from (a repo whose package.json declares "workspaces").`,type:`string`,demandOption:!0}).option(`packages`,{description:"Name glob selecting which of the checkout's workspace packages take part (repeatable; default: all of them). Matched against the package NAME with the same single-segment dialect as `gjsify foreach --include`, so a whole scope is `@gjsify/*` — a bare `*` matches no scoped name. Only packages this project actually uses are linked: declared dependencies plus everything in its lockfile or installed node_modules, transitive and nested copies included.",type:`string`,array:!0}).option(`dry-run`,{description:`Print the links that would be made and write nothing.`,type:`boolean`,default:!1}),handler:t=>{let n=process.cwd(),S=t[`dry-run`]??!1,C=Nn(n,t.checkout),N=devLinkPath(n),F=resolveCheckoutWorkspaces(C,N),I=t.packages??[],H=planDevLinks({consumerRoot:n,workspaces:F,patterns:I,knownNames:consumerKnownNames(n),nested:consumerNestedPlacements(n)});if(H.length===0)return ge.error(`gjsify link: nothing to link — ${C} has ${F.length} workspace package(s), none of which ${n} uses (declared, locked or installed)${I.length===0?``:` and matches ${I.join(`, `)}`}.\nA link that links nothing is a silent no-op, so this is an error. Check the --packages pattern, or run \`gjsify install\` first so the dependency tree exists.`),process.exit(1);let W=`gjsify link${S?` (dry-run)`:``}`;ge.log(`${W} → ${C}`),ge.log(`${` `.repeat(W.length)} in ${n}`);for(let t of H)ge.log(` ${t.name} → ${Ln(C,t.target)||`.`}`);let q=unbuiltDevLinks(H);if(q.length>0)return ge.error(`\n${formatUnbuiltDevLinks(q)}`),process.exit(1);let Y=sweepCheckouts(n,C),X=new Set(H.map(t=>t.name)),Z=scanDevLinks(n,Y).filter(t=>!X.has(t.name));for(let t of Z)ge.log(` retire ${t.name} (no longer selected)`);if(S){ge.log(`\n${W}: nothing written. Drop --dry-run to apply.`);return}let te=retireDevLinks(n,Y,X),ne=applyDevLinks(H);writeDevLinkOverride(n,{version:1,checkout:C,packages:I});let re=ensureLocallyIgnored(n);ge.log(`\n ${ne.length} link(s) written, ${H.length-ne.length} already current.`),Z.length>0&&ge.log(` ${te.length} of ${Z.length} retired link(s) removed.`),ge.log(` override: ${N}`),re===`added`&&ge.log(` git: ${yz} added to .git/info/exclude (local, never committed)`),re===`no-git`&&ge.log(` git: ${n} is not a git repository — nothing to ignore`),re===`unreadable-git`&&ge.warn(` ! git: ${n} has a .git POINTER that does not parse, so ${yz} is NOT ignored. Add it to .gitignore by hand, or the next \`git add -A\` commits your local override.`),ge.log("\nEvery `gjsify install` here now re-applies these links and says so.\n`gjsify install --immutable` refuses while the override exists. Undo: `gjsify unlink`.")}},mG={command:`unlink`,description:"Undo `gjsify link`: remove the development links and the .gjsify-link.json override, then reinstall the registry copies.",builder:t=>t.option(`dry-run`,{description:`Print what would be removed and change nothing.`,type:`boolean`,default:!1}).option(`install`,{description:"Reinstall after unlinking, to put the registry copies back where the links were. On by default; --no-install leaves the holes for a later `gjsify install`.",type:`boolean`,default:!0}),handler:async t=>{let n=process.cwd(),S=t[`dry-run`]??!1,C=devLinkPath(n);if(!existsSync(C)){ge.log(`gjsify unlink: no development link in ${n} (no ${yz}).`);return}let N=[];try{let t=readDevLinkOverride(n)?.checkout;t&&N.push(t)}catch{}let F=[];try{F=prepareDevLinks(n)?.links??[]}catch(t){ge.warn(`gjsify unlink: ${t instanceof Error?t.message:String(t)}\n Removing the override anyway; any dangling links are cleaned by the reinstall.`)}let I=`gjsify unlink${S?` (dry-run)`:``}`;if(ge.log(`${I} in ${n}`),S){let t=new Set(F.map(t=>t.name));for(let S of scanDevLinks(n,N))t.add(S.name);for(let n of[...t].sort())ge.log(` would remove link ${n}`);ge.log(` would remove ${C}`),ge.log(` would remove ${yz} entry from .git/info/exclude (if this module wrote it)`),ge.log(`\n${I}: nothing changed. Drop --dry-run to apply.`);return}let H=removeDevLinks(F),W=new Set(H.map(t=>t.name));for(let t of retireDevLinks(n,N,new Set))W.has(t.name)||H.push(t);for(let t of H)ge.log(` unlinked ${t.name}`);let q=scanDevLinks(n,N);if(q.length>0)return ge.error(`gjsify unlink: ${q.length} link(s) still point into a checkout and could not be removed:\n`+q.map(t=>` ${t.name} ${t.linkPath} → ${t.target}`).join(`
1208
+ `)+`\n ${C} is kept so this stays undoable. Remove the paths above and re-run.`),process.exit(1);if(removeDevLinkOverride(n),ge.log(` removed ${C}`),removeLocalIgnore(n)===`removed`&&ge.log(` removed ${yz} entry from .git/info/exclude`),t.install===!1){ge.log(`\n ${H.length} link(s) removed. Run \`gjsify install\` to restore the registry copies.`);return}ge.log(`\n ${H.length} link(s) removed — reinstalling to restore the registry copies.\n`);let{runCli:Y}=await Promise.resolve().then(()=>(aY(),iY));await Y([`install`])}}});function splitWorkspaceSpecifier(t,n){if(t.startsWith(`.`)||t.startsWith(`/`)||t.includes(`:`))return null;let S=t.split(`/`),C=t.startsWith(`@`)?[2]:[1];for(let t of C){let C=S.slice(0,t).join(`/`);if(!n.has(C))continue;let N=S.slice(t).join(`/`);return{name:C,subpath:N?`./${N}`:`.`}}return null}function resolveRelative(t,n){let S=Nn(zn(t),n);for(let t of[S,`${S}.js`,`${S}.mjs`,In(S,`index.js`)])try{if(statSync(t).isFile())return t}catch{}return null}function workspaceEntry(t,n){let S=t.manifest,pick=t=>{if(typeof t==`string`)return t;if(!t||typeof t!=`object`||Array.isArray(t))return null;let n=t;for(let t of[`node`,`import`,`default`,`gjs`])if(t in n){let S=pick(n[t]);if(S)return S}return null},C=null;if(typeof S.exports==`string`?C=n===`.`?S.exports:null:S.exports&&typeof S.exports==`object`&&(C=pick(S.exports[n])),!C&&n===`.`&&(C=typeof S.module==`string`?S.module:null,C??=typeof S.main==`string`?S.main:null),!C)return null;let N=Nn(t.location,C);return existsSync(N)?N:null}function workspacePeers(t,n){return Object.keys(t.peerDependencies??{}).filter(t=>n.has(t))}function cliRuntimeClosure(t,n={}){let S=new Map(t.map(t=>[t.name,t])),C=new Set,N=n.entry,F=n.cliManifest;if(N===void 0||F===void 0){let t=cliPackageDir(),n=null;if(t)try{n=JSON.parse(readFileSync(In(t,`package.json`),`utf8`))}catch{}if(F??=n,N===void 0){let S=n?.bin,C=typeof S==`string`?S:S?.gjsify??n?.main;N=t&&C?Nn(t,C):null}}for(let t of workspacePeers(F??{},S))C.add(t);if(!N||!existsSync(N))return C;let I=new Set,H=[N];for(;H.length>0;){let t=H.shift();if(I.has(t))continue;I.add(t);let n;try{n=readFileSync(t,`utf8`)}catch{continue}for(let N of moduleSpecifiers$1(n)){if(N.startsWith(`.`)){let n=resolveRelative(t,N);n&&H.push(n);continue}let n=splitWorkspaceSpecifier(N,S),F=n?S.get(n.name):void 0;if(!n||!F)continue;C.add(n.name);for(let t of workspacePeers(F.manifest,S))C.add(t);let I=workspaceEntry(F,n.subpath);I&&H.push(I)}}return C}var gG=__esmMin(()=>{ef(),qn(),QN(),yh()});function signalTree(t,n,S){for(let t=n.length-1;t>=0;t--)try{process.kill(n[t],S)}catch{}try{t.kill(S)}catch{}}function killActiveChildren(){let t=new Map;for(let n of _G){let S=n.pid?collectDescendants(n.pid):[];t.set(n,S),signalTree(n,S,`SIGTERM`)}setTimeout(()=>{for(let n of _G){let S=new Set(n.pid?collectDescendants(n.pid):[]);for(let C of t.get(n)??[])S.add(C);signalTree(n,[...S],`SIGKILL`)}},vG).unref?.()}function assertEveryIncludeMatches(t,n){if(!n||n.length===0)return;let S=n.filter(n=>filterWorkspaces(t,{include:[n]}).length===0);if(S.length===0)return;let C=[`gjsify foreach: --include matched no workspace (${S.length} of ${n.length} pattern(s)):`];for(let n of S){C.push(` ${JSON.stringify(n)}`);let S=stripSurroundingQuotes(n);if(S!==n&&filterWorkspaces(t,{include:[S]}).length>0){C.push(` → matches as ${JSON.stringify(S)}: the QUOTES are part of the value. A shell expansion`," is not re-scanned for quoting, so a pre-quoted filter spliced through `sh -c` arrives with",` the quotes attached. Pass the bare name and let word splitting do the work.`);continue}let N=t.map(t=>t.name).filter(t=>t.toLowerCase().includes(S.replace(/\*/g,``).toLowerCase())).slice(0,3);N.length>0&&C.push(` → did you mean: ${N.join(`, `)}?`)}throw C.push(` ${t.length} workspace(s) discovered. Refusing to run: a filter that selects nothing would`,` otherwise exit 0 and look exactly like a successful run over the whole set.`),ge.error(C.join(`
1209
+ `)),process.exit(1),Error(`gjsify foreach: --include matched no workspace`)}function stripSurroundingQuotes(t){return t.length>=2&&(t[0]===`'`||t[0]===`"`)&&t[t.length-1]===t[0]?t.slice(1,-1):t}async function runSequential(t,n,S,C,N,F){for(let I of t)await runOne(I,n,S,!1,C,N,F)}async function runParallel(t,n,S,C,N,F,I){let H=0,W=[];for(let q=0;q<C;q++)W.push((async()=>{for(;H<t.length;)await runOne(t[H++],n,S,!0,N,F,I)})());await Promise.all(W)}async function runTopologicalParallel(t,n,S,C,N,F,I,H){let W=new Map([...buildDependencyGraph(t,{includeDev:F}).edges].map(([t,n])=>[t,new Set(n)])),q=new Map(t.map(t=>[t.name,t])),Y=t.length,X=new Set,Z=0,te=!process.stdout.isTTY||N,ne=new Map,re=Number(process.env.GJSIFY_FOREACH_STALL_MINUTES??`20`),ie=(Number.isFinite(re)&&re>0?re:20)*6e4;return new Promise((t,F)=>{let re=null,ae=Date.now(),describeInflight=()=>[...ne.entries()].map(([t,n])=>`${t} (${Math.round((Date.now()-n)/1e3)}s)`).join(`, `),failFast=t=>{re||(re=t,killActiveChildren(),setTimeout(()=>settle(),yG).unref?.())},oe=setInterval(()=>{let t=Date.now()-ae;t<3e5||ne.size===0||(ge.error(`[gjsify foreach] WARNING: no workspace completed for ${Math.round(t/6e4)}min — in-flight: ${describeInflight()}`),t>=ie&&failFast(Error(`gjsify foreach: stalled — no workspace completed for ${Math.round(t/6e4)}min (override via GJSIFY_FOREACH_STALL_MINUTES); killed in-flight: ${describeInflight()}`)))},6e4);oe.unref?.();let settle=()=>{clearInterval(oe),re?F(re):t()},pump=()=>{if(!re){for(;Z<C;){let t=[...W.entries()].filter(([,t])=>[...t].every(t=>X.has(t))).map(([t])=>t);if(t.length===0)break;let C=t.sort()[0];W.delete(C),Z++,ne.set(C,Date.now()),te&&ge.error(`[gjsify foreach] start ${C} (${X.size}/${Y} done, ${Z} in flight)`),runOne(q.get(C),n,S,!0,N,I,H).then(()=>{X.add(C)}).catch(t=>{failFast(t instanceof Error?t:Error(String(t)))}).finally(()=>{Z--,ne.delete(C),ae=Date.now(),re?Z===0&&settle():W.size===0&&Z===0?settle():pump()})}W.size>0&&Z===0&&!re&&(clearInterval(oe),F(Error(`gjsify foreach --topological: stuck — workspaces ${[...W.keys()].join(`, `)} have unsatisfied deps in the selected set`)))}};pump()})}async function runOne(t,n,S,C,N,F,I){if(F){N&&ge.error(`[${t.name}] $ ${n} ${S.join(` `)}`),await spawnPrefixed(n,S,t.location,C?`[${t.name}] `:null);return}if(I&&I.tryRestore(t))return;let H=I?.snapshotOutputs(t),W=detectPackageManager(),q=W===`gjsify`?[`run`,n,...S]:[`run`,n,...S.length>0?[`--`,...S]:[]];N&&ge.error(`[${t.name}] $ ${W} ${q.join(` `)}`),await spawnPrefixed(W,q,t.location,C?`[${t.name}] `:null),I&&H&&I.storeAfterSuccess(t,H)}async function spawnPrefixed(t,n,S,C){let N=null,F=[];try{let I=await spawnToCompletion(t,n,{completion:`exit`,cwd:S,stdio:C?`pipe`:`inherit`,color:!0,onSpawn:t=>{N=t,_G.add(t);let n=!process.stdout.isTTY;C&&t.stdout&&t.stderr&&(F.push(prefixLines(t.stdout,process.stdout,C,n)),F.push(prefixLines(t.stderr,process.stderr,C,n)))}});for(let t of F)t();if(I.code!==0)throw Error(`${t} ${n.join(` `)} exited with code ${I.code}`)}finally{N&&_G.delete(N)}}var _G,vG,yG,bG,xG=__esmMin(()=>{_e(),sv(),qR(),$g(),AI(),MI(),gG(),Jz(),dR(),Qz(),tB(),_G=new Set,vG=5e3,yG=15e3,bG={command:`foreach [script] [args..]`,description:"Run a workspace script across all (or filtered) workspaces. Drop-in for `yarn workspaces foreach`: -A/--all, -p/--parallel, -t/--topological, --include, --exclude, --no-private. Pass --exec to run an arbitrary command instead of a script.",builder:t=>t.positional(`script`,{description:"Script name to run in each workspace (`run <name>`-equivalent). With --exec, the command to run instead.",type:`string`}).positional(`args`,{description:`Extra arguments forwarded to each child invocation.`,type:`string`,array:!0}).option(`all`,{description:"Include workspaces declared as `private: true`.",type:`boolean`,alias:`A`,default:!1}).option(`parallel`,{description:`Run workspaces in parallel (capped by --jobs).`,type:`boolean`,alias:`p`,default:!1}).option(`topological`,{description:`Wait for each workspace's deps to finish before starting it (production deps only).`,type:`boolean`,alias:`t`,default:!1}).option(`topological-dev`,{description:`Like --topological but also respects devDependencies (often cyclic — use sparingly).`,type:`boolean`,default:!1}).option(`include`,{description:`Glob pattern to include workspaces by name (repeatable). A pattern that matches NO discovered workspace is a hard error — a filter selecting nothing is a typo or a caller-side quoting bug, never an intent.`,type:`string`,array:!0}).option(`exclude`,{description:`Glob pattern to exclude workspaces by name (repeatable).`,type:`string`,array:!0}).option(`with-dependencies`,{description:`Also select everything the filtered set DEPENDS ON (production deps; add --topological-dev for devDependencies). --include only filters and --topological only orders, so neither can say 'and the packages these need'. Excludes are re-applied afterwards.`,type:`boolean`,alias:`d`,default:!1}).option(`private`,{description:`Include private workspaces (default true). Pass --no-private to skip them.`,type:`boolean`,default:!0}).option(`verbose`,{description:`Echo every spawned command before running it.`,type:`boolean`,alias:`v`,default:!1}).option(`jobs`,{description:`Maximum concurrent workspaces in --parallel mode (default: cpu count).`,type:`number`,alias:`j`}).option(`exec`,{description:"Treat <script> [args..] as an arbitrary command (yarn `workspaces foreach exec`-equivalent) instead of a package.json script lookup. Workspace filtering by script presence is skipped. Use `-- <cmd> <args...>` to pass flags to the command without yargs intercepting them.",type:`boolean`,default:!1}).option(`cached`,{description:`Content-hash build cache (ADR 0006): skip a workspace whose inputs (src/**, package.json, tsconfig*.json, transitive workspace deps, toolchain versions) are unchanged and restore its stored outputs instead; on miss run the script and store the output dirs it modified. Script mode only. Default from GJSIFY_BUILD_CACHE=1.`,type:`boolean`}).option(`shard`,{description:`Run only a deterministic slice "<index>/<total>" (1-based) of the matched workspaces, e.g. --shard 2/4. For fanning a long run across parallel CI jobs. Partitions by sorted name (round-robin) so the shards are disjoint and their union is the full set; order-independent, so safe for tests but NOT for ordered builds.`,type:`string`}).parserConfiguration({"populate--":!0,"parse-positional-numbers":!1}),handler:async t=>{let n=findWorkspaceRoot(process.cwd())??process.cwd(),S=discoverWorkspaces(n),C=t.exec===!0,N=t.script,F=t.args??[];if(!C){let n=doubleDashArgs(t);n.length>0&&(F=[...F,...n])}if(C){let n=doubleDashArgs(t);if(n.length>0&&(N?F=[...F,...n]:(N=n[0],F=[...F,...n.slice(1)])),!N)return ge.error("gjsify foreach --exec: missing command. Pass it after `--`, e.g. `gjsify foreach --exec -- npm publish --tag latest`."),process.exit(1)}assertEveryIncludeMatches(S,t.include);let I=filterWorkspaces(S,{include:t.include,exclude:t.exclude,noPrivate:t.private===!1});if(t[`with-dependencies`]===!0){let n=affectedClosure(buildDependencyGraph(S,{includeDev:t[`topological-dev`]===!0}),I.map(t=>t.name));I=filterWorkspaces(S.filter(t=>n.has(t.name)),{exclude:t.exclude,noPrivate:t.private===!1})}if(!C){if(!N)return ge.error(`gjsify foreach: missing <script> positional. Pass --exec to run an arbitrary command instead.`),process.exit(1);let t=N;I=I.filter(n=>typeof(n.manifest.scripts??{})[t]==`string`)}if(typeof t.shard==`string`&&t.shard.length>0){let n=/^\s*(\d+)\s*\/\s*(\d+)\s*$/.exec(t.shard);if(!n)return ge.error(`gjsify foreach: invalid --shard "${t.shard}" — expected "<index>/<total>" (1-based), e.g. 2/4.`),process.exit(1);let S=Number(n[1]),C=Number(n[2]);if(C<1||S<1||S>C)return ge.error(`gjsify foreach: invalid --shard "${t.shard}" — need 1 <= index <= total and total >= 1.`),process.exit(1);if(C>1){let t=[...I].sort((t,n)=>t.name<n.name?-1:+(t.name>n.name));I=t.filter((t,n)=>n%C===S-1),ge.log(`gjsify foreach: shard ${S}/${C} → ${I.length} of ${t.length} workspace(s)`)}}if(I.length===0){ge.log(`gjsify foreach: no workspaces match (${C?`exec`:`script`}="${N}", include=${JSON.stringify(t.include??[])}, exclude=${JSON.stringify(t.exclude??[])})`);return}(t.topological||t[`topological-dev`])&&(I=topologicalSort(buildDependencyGraph(I,{includeDev:t[`topological-dev`]===!0})));let H=t.verbose===!0,W=N,q=t.cached??buildCacheEnabledByEnv();if(t.cached===!0&&C)return ge.error(`gjsify foreach: --cached only applies to script mode, not --exec.`),process.exit(1);let Y=q&&!C?new BuildCacheRunner({root:n,workspaces:S,script:W,args:F,targets:I.map(t=>t.name)}):void 0,X=t.parallel===!0?cliRuntimeClosure(S):new Set,Z=X.size>0?I.filter(t=>X.has(t.name)):[],te=Z.length>0?I.filter(t=>!X.has(t.name)):I;try{if(Z.length>0){ge.error(`[gjsify foreach] serial prefix: ${Z.length} package(s) the running CLI imports — ${Z.map(t=>t.name).join(`, `)}`);for(let t of Z)ge.error(`[gjsify foreach] start ${t.name} (serial prefix)`),await runOne(t,W,F,!0,H,C,Y)}if(t.parallel&&!t.topological&&!t[`topological-dev`]){let n=t.jobs&&t.jobs>0?t.jobs:cpus().length;await runParallel(te,W,F,n,H,C,Y)}else if(t.parallel){let n=t.jobs&&t.jobs>0?t.jobs:cpus().length;await runTopologicalParallel(te,W,F,n,H,t[`topological-dev`]===!0,C,Y)}else await runSequential(te,W,F,H,C,Y)}catch(t){return killActiveChildren(),ge.error(t.message),process.exit(1)}process.exit(0)}}});async function runLifecycleScript(t,n,S,C={}){let N=(n.scripts??{})[S];if(typeof N!=`string`){if(C.optional!==!1)return!1;throw Error(`gjsify lifecycle-script: no "${S}" in ${t}/package.json`)}let F=findWorkspaceRoot(t),I=[In(t,`node_modules`,`.bin`)];F&&F!==t&&I.push(In(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(Gn),npm_lifecycle_event:S,npm_package_name:n.name??``,npm_package_version:n.version??``,...C.env};if(C.stdio===`ignore`)throw Error(`gjsify lifecycle-script: stdio "ignore" is not supported — see utils/spawn.ts`);let q=await spawnToCompletion(N,[],{completion:`return`,cwd:t,env:W,shell:!0,stdio:C.stdio===`inherit-stderr`?`inherit-stderr`:C.stdio===`pipe`?`pipe`:`inherit`});if(q.code!==0)throw Error(`gjsify lifecycle-script: "${S}" in ${t} exited with ${describeExit(q)}`);return!0}var SG=__esmMin(()=>{qn(),sv(),MI()});async function packWorkspace(t,n={}){let S=In(t,`package.json`);if(!existsSync(S))throw Error(`gjsify pack: no package.json at ${t}`);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 ${t} has no "name"`);let H=n.lifecycleScripts??[`prepack`];for(let S of H)await runLifecycleScript(t,N,S,{optional:!0,stdio:n.lifecycleStdio});let W=readFileSync(S,`utf-8`),q=W===C?N:JSON.parse(W),Y=n.skipWorkspaceRewrite?q:rewriteWorkspaceDeps(q,t),X=JSON.stringify(Y,null,indentOf(W))+`
1210
1210
  `,Z=collectPackedFiles(t,q);assertTypeDeclarationsShipped(t,q,Z);let te=[{name:`package/`,directory:!0,mode:493}],ne=[],re=0;for(let n of Z){let S;S=n===`package.json`?new TextEncoder().encode(X):new Uint8Array(readFileSync(In(t,n)));let C=statSync(In(t,n)).mode&511;te.push({name:`package/${n}`,body:S,mode:C,mtime:0}),ne.push({path:n,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`),Q=`sha512-${createHash(`sha512`).update(ie).digest(`base64`)}`,se=n.destination?Nn(n.destination):t,ce=In(se,ae);return n.dryRun||(mkdirSync(se,{recursive:!0}),writeFileSync(ce,ie)),{filename:ae,name:F,version:I,size:ie.byteLength,unpackedSize:re,shasum:oe,integrity:Q,entryCount:ne.length,files:ne,absolutePath:n.dryRun?null:ce}}function collectPackedFiles(t,n){let S=forceIncluded(n),C=Array.isArray(n.files)?n.files.filter(t=>typeof t==`string`):null,N=new Set;if(C)for(let n of expandFilesPatterns(t,C))N.add(n);else{let n=loadIgnore(t);for(let S of walkAll(t))n(S)||N.add(S)}for(let n of S)existsSync(In(t,n))&&N.add(n);return[...N].sort()}function collectTypeDeclarationRefs(t){let n=new Set,add=t=>{if(typeof t!=`string`)return;let S=t.replace(/^\.\//,``);S.includes(`*`)||n.add(S)};for(let n of[`types`,`typings`])add(t[n]);let walk=t=>{if(!(!t||typeof t!=`object`)){if(Array.isArray(t)){for(let n of t)walk(n);return}for(let[n,S]of Object.entries(t))n===`types`||n===`typings`?add(S):walk(S)}};return walk(t.exports),[...n]}function assertTypeDeclarationsShipped(t,n,S){let C=new Set(S),N=collectTypeDeclarationRefs(n).filter(n=>{let S=In(t,n);return existsSync(S)&&statSync(S).isFile()&&!C.has(n)});if(N.length===0)return;let F=typeof n.name==`string`?n.name:`(unnamed)`,I=Array.isArray(n.files)?JSON.stringify(n.files):`(none)`;throw Error(`gjsify pack: ${F} references TypeScript declaration file(s) via "exports"/"types" that exist on disk but are excluded from the tarball by the "files" allowlist (${I}):\n`+N.map(t=>` - ${t}`).join(`
1211
1211
  `)+`
1212
- Add the missing path(s) to package.json "files" so type resolution isn't silently broken for consumers.`)}function forceIncluded(t){let n=new Set;n.add(`package.json`);for(let t of[`README`,`README.md`,`LICENSE`,`LICENSE.md`,`NOTICE`,`NOTICE.md`])n.add(t);let S=typeof t.main==`string`?t.main:null;S&&n.add(S.replace(/^\.\//,``));let C=t.bin;if(typeof C==`string`)n.add(C.replace(/^\.\//,``));else if(C&&typeof C==`object`)for(let t of Object.values(C))typeof t==`string`&&n.add(t.replace(/^\.\//,``));return[...n]}function walkAll(t,n=``){let S=[],C=n?In(t,n):t,N;try{N=readdirSync(C,{withFileTypes:!0})}catch{return S}for(let C of N){if(CG.has(C.name)||C.name.startsWith(`.tsbuildinfo`))continue;let N=n?`${n}/${C.name}`:C.name;C.isDirectory()?S.push(...walkAll(t,N)):C.isFile()&&S.push(N)}return S}function expandFilesPatterns(t,n){let S=new Set,C=null;for(let N of n){let n=N.replace(/^\.\//,``).replace(/\/$/,``);if(!n)continue;if(!/[*?[\]]/.test(n)){let C=In(t,n);if(!existsSync(C))continue;let N=statSync(C);if(N.isDirectory())for(let C of walkAll(t,n))S.add(C);else N.isFile()&&S.add(n);continue}C??=walkAll(t);let F=filesGlobToRegExp(n),I=filesGlobToRegExp(`${n}/**`);for(let t of C)(F.test(t)||I.test(t))&&S.add(t)}return[...S]}function filesGlobToRegExp(t){let n=`^`;for(let S=0;S<t.length;S++){let C=t[S];if(C===`*`)t[S+1]===`*`?(n+=`.*`,S++,t[S+1]===`/`&&S++):n+=`[^/]*`;else if(C===`?`)n+=`[^/]`;else if(C===`[`){let C=S+1,N=`[`;for(t[C]===`!`&&(N+=`^`,C++);C<t.length&&t[C]!==`]`;C++)N+=t[C];C<t.length?(n+=`${N}]`,S=C):n+=`\\[`}else".+^${}()|\\]".includes(C)?n+=`\\${C}`:n+=C}return RegExp(`${n}$`)}function loadIgnore(t){let n=In(t,`.npmignore`),S=In(t,`.gitignore`),C=[],N=existsSync(n)?n:existsSync(S)?S:null;if(N){let t=readFileSync(N,`utf-8`).split(`
1213
- `);for(let n of t){let t=n.trim();!t||t.startsWith(`#`)||t.startsWith(`!`)||C.push(globToRegex(t))}}return t=>{for(let n of C)if(n.test(t))return!0;return!1}}function globToRegex(t){let n=t.replace(/^\//,``);return n=n.replace(/[.+^${}()|[\]\\]/g,`\\$&`),n=n.replace(/\*\*/g,`__DOUBLESTAR__`).replace(/\*/g,`[^/]*`).replace(/__DOUBLESTAR__/g,`.*`),n=n.replace(/\?/g,`[^/]`),RegExp(`^${n}($|/)`)}function collectWorkspaceProtocolDeps(t){let n=[];for(let S of wG){let C=t[S];if(C)for(let[t,N]of Object.entries(C))typeof N==`string`&&N.startsWith(`workspace:`)&&n.push(`${S}.${t}`)}return n}function findPackWorkspaceRoot(t){let n=findWorkspaceRoot(t);if(n)return n;let S=t;for(let t=0;t<12;t++){let t=In(S,`package.json`);if(existsSync(t)&&readPackageJson$2(t)?.workspaces!==void 0)return S;let n=Nn(S,`..`);if(n===S)break;S=n}return null}function rewriteWorkspaceDeps(t,n){let S=findPackWorkspaceRoot(n);if(!S){let S=collectWorkspaceProtocolDeps(t);if(S.length>0)throw Error(`gjsify pack: ${String(t.name)} declares workspace: ranges (${S.join(`, `)}) but ${n} is not inside a monorepo (no ancestor package.json declares "workspaces"). A workspace: range cannot be published — replace it with a real npm range, or pack from within the monorepo.`);return t}let C=new Map;for(let t of discoverWorkspaces(S))t.name&&t.version&&C.set(t.name,t.version);let N=JSON.parse(JSON.stringify(t));for(let t of wG){let n=N[t];if(n)for(let[F,I]of Object.entries(n)){if(typeof I!=`string`||!I.startsWith(`workspace:`))continue;let H=C.get(F);if(!H)throw Error(`gjsify pack: ${N.name} declares ${I} on ${F} (${t}) but no sibling workspace with that name exists in the monorepo at ${S}`);let W=I.slice(10);W===`*`||W===``?n[F]=H:W===`^`||W===`~`?n[F]=`${W}${H}`:n[F]=W}}return N}function indentOf(t){let n=t.match(/\n([ \t]+)"/);return n?n[1]:` `}var SG,CG,wG,TG=__esmMin(()=>{ef(),fl(),qn(),KR(),AI(),MI(),jI(),xG(),SG={command:`pack [path]`,description:`Produce an npm-compatible .tgz tarball for the workspace at <path> (default: cwd). Rewrites workspace:^/~/* deps to resolved versions.`,builder:t=>t.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 t=>{let n=await packWorkspace(Nn(t.path??process.cwd()),{destination:t[`pack-destination`],dryRun:t[`dry-run`]===!0,lifecycleScripts:t[`ignore-scripts`]?[]:[`prepack`],lifecycleStdio:t.json?`inherit-stderr`:`inherit`});t.json?process.stdout.write(`${JSON.stringify([n],null,2)}\n`):process.stdout.write(`${n.filename}\n`)}},CG=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`]),wG=[`dependencies`,`devDependencies`,`peerDependencies`,`optionalDependencies`]});function parseRetryAfter(t,n=Date.now()){if(!t)return;let S=t.trim();if(/^\d+(?:\.\d+)?$/.test(S))return Math.round(Number(S)*1e3);let C=Date.parse(S);return Number.isNaN(C)?void 0:Math.max(0,C-n)}function retryDelayMs(t,n,S){let C=parseRetryAfter(S);return Math.min(C??n*2**t,DG)}async function fetchWithTransientRetry(t,n={}){let S=n.retries??5,C=n.baseMs??2e3,N=n.sleep??(t=>new Promise(n=>setTimeout(n,t)));for(let F=0;;F++){let I,H;try{I=await t()}catch(t){H=t}if(I&&!isTransientStatus(I.status))return{response:I,retried:F};if(F>=S){if(I)return{response:I,retried:F};throw H}let W=retryDelayMs(F,C,I?.headers.get(`retry-after`)),q=I?`${I.status} ${I.statusText}`:`network error: ${H instanceof Error?H.message:String(H)}`;n.log?.(`transient ${q} (attempt ${F+1}/${S+1}), retrying in ${W}ms`),await N(W)}}var EG,isTransientStatus,DG,OG=__esmMin(()=>{EG=new Set([408,425,429,500,502,503,504]),isTransientStatus=t=>EG.has(t),DG=3e4});function decodeJwtPayload(t){let n=t.split(`.`);if(n.length!==3)return null;try{let t=n[1].replace(/-/g,`+`).replace(/_/g,`/`),S=typeof atob==`function`?atob(t):Buffer.from(t,`base64`).toString(`binary`);return JSON.parse(S)}catch{return null}}function hasGithubOidcEnv(){return!!(process.env.ACTIONS_ID_TOKEN_REQUEST_URL&&process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN)}async function fetchGithubOidcToken(t,n){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=`${S}${S.includes(`?`)?`&`:`?`}audience=${encodeURIComponent(t)}`;n?.(`gjsify oidc: GET ${N.replace(C,`<bearer>`)}`);let F=await fetch(N,{method:`GET`,headers:{Accept:`application/json`,Authorization:`Bearer ${C}`}});if(!F.ok){let t=await F.text().catch(()=>`<no body>`);throw new OidcUnavailableError(`Failed to fetch GitHub OIDC id_token: ${F.status} ${F.statusText} — ${t.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(t){let{packageName:n,registry:S,idToken:C,log:N}=t,F=`${S.endsWith(`/`)?S.slice(0,-1):S}/-/npm/v1/oidc/token/exchange/package/${n.startsWith(`@`)?(()=>{let t=n.indexOf(`/`),S=n.slice(1,t),C=n.slice(t+1);return`@${encodeURIComponent(S)}%2f${encodeURIComponent(C)}`})():encodeURIComponent(n)}`;N?.(`gjsify oidc: POST ${F}`);let I=t.maxRetries??3,H=t.retryBaseMs??1e3;for(let t=0;;t++){let S;try{S=await fetch(F,{method:`POST`,headers:{Authorization:`Bearer ${C}`,"Content-Type":`application/json`,Accept:`application/json`},body:`{}`})}catch(S){if(t<I){let S=retryDelayMs(t,H);N?.(`gjsify oidc: network error for ${n} (attempt ${t+1}/${I+1}), retrying in ${S}ms`),await sleep(S);continue}throw new OidcExchangeError(`npm OIDC token exchange network error for ${n} after ${t+1} attempt(s): ${S instanceof Error?S.message:String(S)}`,0,``,n,decodeJwtPayload(C)??void 0)}let W=await S.text().catch(()=>``);if(!S.ok){if(isTransientStatus(S.status)&&t<I){let C=retryDelayMs(t,H,S.headers.get(`retry-after`));N?.(`gjsify oidc: transient ${S.status} ${S.statusText} for ${n} (attempt ${t+1}/${I+1}), retrying in ${C}ms`),await sleep(C);continue}throw new OidcExchangeError(`npm OIDC token exchange failed for ${n}: ${S.status} ${S.statusText} — ${W.slice(0,300)}`,S.status,W,n,decodeJwtPayload(C)??void 0)}let q;try{q=JSON.parse(W)}catch{throw new OidcExchangeError(`npm OIDC token exchange returned non-JSON body for ${n}: ${W.slice(0,200)}`,S.status,W,n)}if(!q.token)throw new OidcExchangeError(`npm OIDC token exchange returned no \`token\` field for ${n}`,S.status,W,n);return q.token}}async function getNpmTrustedToken(t){let n=`npm:${new URL(t.registry).hostname}`,S=await fetchGithubOidcToken(n,t.log);return{token:await exchangeOidcForNpmToken({...t,idToken:S}),audience:n}}var sleep,OidcUnavailableError,OidcExchangeError,kG=__esmMin(()=>{OG(),sleep=t=>new Promise(n=>setTimeout(n,t)),OidcUnavailableError=class extends Error{reason;constructor(t,n){super(t),this.reason=n,this.name=`OidcUnavailableError`}},OidcExchangeError=class extends Error{status;body;packageName;claims;constructor(t,n,S,C,N){super(t),this.status=n,this.body=S,this.packageName=C,this.claims=N,this.name=`OidcExchangeError`}}});async function diagnose404(t){let{packageName:n,version:S,registry:C,npmrc:N}=t,F={};try{F=await whoami(C,N)}catch{return{reason:`unknown`,message:formatUnknown(n,S)}}return F.username&&F.username.length>0?{reason:`live-token-404`,username:F.username,message:formatLiveToken404(n,S,F.username)}:{reason:`dead-token`,message:formatDeadToken(n,S)}}function formatDeadToken(t,n){return[`gjsify publish: ${t}@${n} — 404 Not Found`,``,`The npm token in ~/.npmrc appears to be revoked or expired (the /-/whoami probe`,`returned {} instead of {"username": "..."}). The 404 is npm's response to a PUT`,`authenticated with an invalid bearer token.`,``,`To refresh:`,` npm login`,` # or, future: gjsify login (tracked as project_gjsify_login_goal)`,``,`Then verify before publishing:`,` curl -s -H "Authorization: Bearer $(grep registry.npmjs.org ~/.npmrc | sed 's|.*=||')" \\`,` https://registry.npmjs.org/-/whoami`,` # Healthy: {"username":"<you>"}`,` # Dead: {}`].join(`
1212
+ Add the missing path(s) to package.json "files" so type resolution isn't silently broken for consumers.`)}function forceIncluded(t){let n=new Set;n.add(`package.json`);for(let t of[`README`,`README.md`,`LICENSE`,`LICENSE.md`,`NOTICE`,`NOTICE.md`])n.add(t);let S=typeof t.main==`string`?t.main:null;S&&n.add(S.replace(/^\.\//,``));let C=t.bin;if(typeof C==`string`)n.add(C.replace(/^\.\//,``));else if(C&&typeof C==`object`)for(let t of Object.values(C))typeof t==`string`&&n.add(t.replace(/^\.\//,``));return[...n]}function walkAll(t,n=``){let S=[],C=n?In(t,n):t,N;try{N=readdirSync(C,{withFileTypes:!0})}catch{return S}for(let C of N){if(wG.has(C.name)||C.name.startsWith(`.tsbuildinfo`))continue;let N=n?`${n}/${C.name}`:C.name;C.isDirectory()?S.push(...walkAll(t,N)):C.isFile()&&S.push(N)}return S}function expandFilesPatterns(t,n){let S=new Set,C=null;for(let N of n){let n=N.replace(/^\.\//,``).replace(/\/$/,``);if(!n)continue;if(!/[*?[\]]/.test(n)){let C=In(t,n);if(!existsSync(C))continue;let N=statSync(C);if(N.isDirectory())for(let C of walkAll(t,n))S.add(C);else N.isFile()&&S.add(n);continue}C??=walkAll(t);let F=filesGlobToRegExp(n),I=filesGlobToRegExp(`${n}/**`);for(let t of C)(F.test(t)||I.test(t))&&S.add(t)}return[...S]}function filesGlobToRegExp(t){let n=`^`;for(let S=0;S<t.length;S++){let C=t[S];if(C===`*`)t[S+1]===`*`?(n+=`.*`,S++,t[S+1]===`/`&&S++):n+=`[^/]*`;else if(C===`?`)n+=`[^/]`;else if(C===`[`){let C=S+1,N=`[`;for(t[C]===`!`&&(N+=`^`,C++);C<t.length&&t[C]!==`]`;C++)N+=t[C];C<t.length?(n+=`${N}]`,S=C):n+=`\\[`}else".+^${}()|\\]".includes(C)?n+=`\\${C}`:n+=C}return RegExp(`${n}$`)}function loadIgnore(t){let n=In(t,`.npmignore`),S=In(t,`.gitignore`),C=[],N=existsSync(n)?n:existsSync(S)?S:null;if(N){let t=readFileSync(N,`utf-8`).split(`
1213
+ `);for(let n of t){let t=n.trim();!t||t.startsWith(`#`)||t.startsWith(`!`)||C.push(globToRegex(t))}}return t=>{for(let n of C)if(n.test(t))return!0;return!1}}function globToRegex(t){let n=t.replace(/^\//,``);return n=n.replace(/[.+^${}()|[\]\\]/g,`\\$&`),n=n.replace(/\*\*/g,`__DOUBLESTAR__`).replace(/\*/g,`[^/]*`).replace(/__DOUBLESTAR__/g,`.*`),n=n.replace(/\?/g,`[^/]`),RegExp(`^${n}($|/)`)}function collectWorkspaceProtocolDeps(t){let n=[];for(let S of TG){let C=t[S];if(C)for(let[t,N]of Object.entries(C))typeof N==`string`&&N.startsWith(`workspace:`)&&n.push(`${S}.${t}`)}return n}function findPackWorkspaceRoot(t){let n=findWorkspaceRoot(t);if(n)return n;let S=t;for(let t=0;t<12;t++){let t=In(S,`package.json`);if(existsSync(t)&&readPackageJson$2(t)?.workspaces!==void 0)return S;let n=Nn(S,`..`);if(n===S)break;S=n}return null}function rewriteWorkspaceDeps(t,n){let S=findPackWorkspaceRoot(n);if(!S){let S=collectWorkspaceProtocolDeps(t);if(S.length>0)throw Error(`gjsify pack: ${String(t.name)} declares workspace: ranges (${S.join(`, `)}) but ${n} is not inside a monorepo (no ancestor package.json declares "workspaces"). A workspace: range cannot be published — replace it with a real npm range, or pack from within the monorepo.`);return t}let C=new Map;for(let t of discoverWorkspaces(S))t.name&&t.version&&C.set(t.name,t.version);let N=JSON.parse(JSON.stringify(t));for(let t of TG){let n=N[t];if(n)for(let[F,I]of Object.entries(n)){if(typeof I!=`string`||!I.startsWith(`workspace:`))continue;let H=C.get(F);if(!H)throw Error(`gjsify pack: ${N.name} declares ${I} on ${F} (${t}) but no sibling workspace with that name exists in the monorepo at ${S}`);let W=I.slice(10);W===`*`||W===``?n[F]=H:W===`^`||W===`~`?n[F]=`${W}${H}`:n[F]=W}}return N}function indentOf(t){let n=t.match(/\n([ \t]+)"/);return n?n[1]:` `}var CG,wG,TG,EG=__esmMin(()=>{ef(),fl(),qn(),KR(),AI(),MI(),jI(),SG(),CG={command:`pack [path]`,description:`Produce an npm-compatible .tgz tarball for the workspace at <path> (default: cwd). Rewrites workspace:^/~/* deps to resolved versions.`,builder:t=>t.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 t=>{let n=await packWorkspace(Nn(t.path??process.cwd()),{destination:t[`pack-destination`],dryRun:t[`dry-run`]===!0,lifecycleScripts:t[`ignore-scripts`]?[]:[`prepack`],lifecycleStdio:t.json?`inherit-stderr`:`inherit`});t.json?process.stdout.write(`${JSON.stringify([n],null,2)}\n`):process.stdout.write(`${n.filename}\n`)}},wG=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`]),TG=[`dependencies`,`devDependencies`,`peerDependencies`,`optionalDependencies`]});function parseRetryAfter(t,n=Date.now()){if(!t)return;let S=t.trim();if(/^\d+(?:\.\d+)?$/.test(S))return Math.round(Number(S)*1e3);let C=Date.parse(S);return Number.isNaN(C)?void 0:Math.max(0,C-n)}function retryDelayMs(t,n,S){let C=parseRetryAfter(S);return Math.min(C??n*2**t,OG)}async function fetchWithTransientRetry(t,n={}){let S=n.retries??5,C=n.baseMs??2e3,N=n.sleep??(t=>new Promise(n=>setTimeout(n,t)));for(let F=0;;F++){let I,H;try{I=await t()}catch(t){H=t}if(I&&!isTransientStatus(I.status))return{response:I,retried:F};if(F>=S){if(I)return{response:I,retried:F};throw H}let W=retryDelayMs(F,C,I?.headers.get(`retry-after`)),q=I?`${I.status} ${I.statusText}`:`network error: ${H instanceof Error?H.message:String(H)}`;n.log?.(`transient ${q} (attempt ${F+1}/${S+1}), retrying in ${W}ms`),await N(W)}}var DG,isTransientStatus,OG,kG=__esmMin(()=>{DG=new Set([408,425,429,500,502,503,504]),isTransientStatus=t=>DG.has(t),OG=3e4});function decodeJwtPayload(t){let n=t.split(`.`);if(n.length!==3)return null;try{let t=n[1].replace(/-/g,`+`).replace(/_/g,`/`),S=typeof atob==`function`?atob(t):Buffer.from(t,`base64`).toString(`binary`);return JSON.parse(S)}catch{return null}}function hasGithubOidcEnv(){return!!(process.env.ACTIONS_ID_TOKEN_REQUEST_URL&&process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN)}async function fetchGithubOidcToken(t,n){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=`${S}${S.includes(`?`)?`&`:`?`}audience=${encodeURIComponent(t)}`;n?.(`gjsify oidc: GET ${N.replace(C,`<bearer>`)}`);let F=await fetch(N,{method:`GET`,headers:{Accept:`application/json`,Authorization:`Bearer ${C}`}});if(!F.ok){let t=await F.text().catch(()=>`<no body>`);throw new OidcUnavailableError(`Failed to fetch GitHub OIDC id_token: ${F.status} ${F.statusText} — ${t.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(t){let{packageName:n,registry:S,idToken:C,log:N}=t,F=`${S.endsWith(`/`)?S.slice(0,-1):S}/-/npm/v1/oidc/token/exchange/package/${n.startsWith(`@`)?(()=>{let t=n.indexOf(`/`),S=n.slice(1,t),C=n.slice(t+1);return`@${encodeURIComponent(S)}%2f${encodeURIComponent(C)}`})():encodeURIComponent(n)}`;N?.(`gjsify oidc: POST ${F}`);let I=t.maxRetries??3,H=t.retryBaseMs??1e3;for(let t=0;;t++){let S;try{S=await fetch(F,{method:`POST`,headers:{Authorization:`Bearer ${C}`,"Content-Type":`application/json`,Accept:`application/json`},body:`{}`})}catch(S){if(t<I){let S=retryDelayMs(t,H);N?.(`gjsify oidc: network error for ${n} (attempt ${t+1}/${I+1}), retrying in ${S}ms`),await sleep(S);continue}throw new OidcExchangeError(`npm OIDC token exchange network error for ${n} after ${t+1} attempt(s): ${S instanceof Error?S.message:String(S)}`,0,``,n,decodeJwtPayload(C)??void 0)}let W=await S.text().catch(()=>``);if(!S.ok){if(isTransientStatus(S.status)&&t<I){let C=retryDelayMs(t,H,S.headers.get(`retry-after`));N?.(`gjsify oidc: transient ${S.status} ${S.statusText} for ${n} (attempt ${t+1}/${I+1}), retrying in ${C}ms`),await sleep(C);continue}throw new OidcExchangeError(`npm OIDC token exchange failed for ${n}: ${S.status} ${S.statusText} — ${W.slice(0,300)}`,S.status,W,n,decodeJwtPayload(C)??void 0)}let q;try{q=JSON.parse(W)}catch{throw new OidcExchangeError(`npm OIDC token exchange returned non-JSON body for ${n}: ${W.slice(0,200)}`,S.status,W,n)}if(!q.token)throw new OidcExchangeError(`npm OIDC token exchange returned no \`token\` field for ${n}`,S.status,W,n);return q.token}}async function getNpmTrustedToken(t){let n=`npm:${new URL(t.registry).hostname}`,S=await fetchGithubOidcToken(n,t.log);return{token:await exchangeOidcForNpmToken({...t,idToken:S}),audience:n}}var sleep,OidcUnavailableError,OidcExchangeError,AG=__esmMin(()=>{kG(),sleep=t=>new Promise(n=>setTimeout(n,t)),OidcUnavailableError=class extends Error{reason;constructor(t,n){super(t),this.reason=n,this.name=`OidcUnavailableError`}},OidcExchangeError=class extends Error{status;body;packageName;claims;constructor(t,n,S,C,N){super(t),this.status=n,this.body=S,this.packageName=C,this.claims=N,this.name=`OidcExchangeError`}}});async function diagnose404(t){let{packageName:n,version:S,registry:C,npmrc:N}=t,F={};try{F=await whoami(C,N)}catch{return{reason:`unknown`,message:formatUnknown(n,S)}}return F.username&&F.username.length>0?{reason:`live-token-404`,username:F.username,message:formatLiveToken404(n,S,F.username)}:{reason:`dead-token`,message:formatDeadToken(n,S)}}function formatDeadToken(t,n){return[`gjsify publish: ${t}@${n} — 404 Not Found`,``,`The npm token in ~/.npmrc appears to be revoked or expired (the /-/whoami probe`,`returned {} instead of {"username": "..."}). The 404 is npm's response to a PUT`,`authenticated with an invalid bearer token.`,``,`To refresh:`,` npm login`,` # or, future: gjsify login (tracked as project_gjsify_login_goal)`,``,`Then verify before publishing:`,` curl -s -H "Authorization: Bearer $(grep registry.npmjs.org ~/.npmrc | sed 's|.*=||')" \\`,` https://registry.npmjs.org/-/whoami`,` # Healthy: {"username":"<you>"}`,` # Dead: {}`].join(`
1214
1214
  `)}function formatLiveToken404(t,n,S){return[`gjsify publish: ${t}@${n} — 404 Not Found`,``,`Authenticated as: ${S}`,``,`Your token authenticates, so this is NOT a dead-token problem. The package`,`${t} is not (yet) on npmjs.com. Two cases:`,``,` 1. First publish of a brand-new scoped package — do the one-time bootstrap`,` (see AGENTS.md > "New @gjsify/* package: first-publish + Trusted`,` Publisher bootstrap"). The npm registry can also 404 *transiently*`,` while provisioning a brand-new package: simply re-run, or do the very`," first publish with `npm publish` (then configure the Trusted Publisher)."," 2. You lack publish access to the scope — verify with `npm access ls-packages`."].join(`
1215
- `)}function formatUnknown(t,n){return`gjsify publish: ${t}@${n} — 404 Not Found`}function is404DiagnosticCandidate(t){let n=t.trim();return!!(n.length===0||/^not found$/i.test(n)||/"error"\s*:\s*"Not Found"/i.test(n))}var AG=__esmMin(()=>{gh()});function backoffFor(t){return jG[Math.min(Math.max(t,0),jG.length-1)]??3e4}function probeTimeoutFor(t,n){return Math.min(t,Math.max(n,MG))}function budgetForPayload(t,n){if(t<6e5||n<=PG)return t;let S=(n-PG)/(1024*1024);return t+Math.ceil(S)*FG}function cacheBustedUrl(t,n){return`${t}${t.includes(`?`)?`&`:`?`}__gjsify_readback=${encodeURIComponent(n)}`}async function verifyPublishedVersion(t){let{registry:n,name:S,version:C,budgetMs:N}=t,F=t.fetchImpl??((...t)=>globalThis.fetch(...t)),I=t.sleep??(t=>new Promise(n=>setTimeout(n,t))),H=t.now??(()=>Date.now()),W=t.probeTimeoutMs??3e4,q=`${n.endsWith(`/`)?n.slice(0,-1):n}/${escapePackageName(S)}`,Y=H(),X=0,Z={state:`error`,detail:`no probe was sent`};for(let n=0;X++,Z=await probeOnce({url:q,version:C,doFetch:F,probeTimeoutMs:probeTimeoutFor(W,N-(H()-Y)),authorization:t.authorization,nonce:`${Y}-${X}`}),t.log?.(`gjsify publish: read-back probe ${X} of ${S}@${C} → ${Z.state}`+(Z.state===`present`?``:` (${Z.detail})`)),Z.state!==`present`;n++){let t=N-(H()-Y);if(t<=0)break;await I(Math.min(backoffFor(n),t))}let te={attempts:X,elapsedMs:H()-Y,url:q,last:Z};if(Z.state===`present`)return{...te,confirmed:!0,verdict:`confirmed`,verdictDetail:`${q} serves ${C} with a tarball`};if(Z.state===`error`)return{...te,confirmed:!1,verdict:`unknown`,verdictDetail:`the read-back could not reach a verdict — ${Z.detail}`};let ne=await probeRegistryRecord({url:q,version:C,doFetch:F,probeTimeoutMs:W,authorization:t.authorization,nonce:`${Y}-record`});return t.log?.(`gjsify publish: read-back record probe of ${S}@${C} → ${ne.state} (${ne.detail})`),ne.state===`recorded`?{...te,confirmed:!1,verdict:`recorded-not-served`,verdictDetail:ne.detail,recordedAt:ne.recordedAt}:ne.state===`no-record`?{...te,confirmed:!1,verdict:`not-published`,verdictDetail:ne.detail}:{...te,confirmed:!1,verdict:`unknown`,verdictDetail:ne.detail}}async function probeRegistryRecord(t){let{url:n,version:S,doFetch:C,probeTimeoutMs:N}=t,F=new AbortController,I=setTimeout(()=>F.abort(),N),H;try{H=await C(cacheBustedUrl(n,t.nonce),{headers:{"cache-control":`no-cache`,...t.authorization?{authorization:t.authorization}:{}},signal:F.signal})}catch(t){return{state:`unknown`,detail:`the registry serves no ${S} and its own record was unreadable (${t instanceof Error?t.message:String(t)})`}}finally{clearTimeout(I)}if(H.status===404)return{state:`no-record`,detail:`the registry has no packument for this name at all (404)`};if(!H.ok)return{state:`unknown`,detail:`the registry serves no ${S} and its own record answered ${H.status} ${H.statusText}`};let W;try{W=await H.json()}catch(t){return{state:`unknown`,detail:`the registry serves no ${S} and its own record is not JSON (${t instanceof Error?t.message:String(t)})`}}let q=W?.time,Y=q&&typeof q==`object`?q[S]:void 0;return typeof Y==`string`&&Y.length>0?{state:`recorded`,recordedAt:Y,detail:`the registry RECORDS ${S} at ${Y} and its install document does not serve it`}:{state:`no-record`,detail:`the registry has no record of ${S} — neither in its install document nor in its own \`time\` map`}}async function sendPackumentRequest(t){let{url:n,doFetch:S,probeTimeoutMs:C}=t,N={accept:`application/vnd.npm.install-v1+json`,"cache-control":`no-cache`,...t.authorization?{authorization:t.authorization}:{}},send=async t=>{let n=new AbortController,F=setTimeout(()=>n.abort(),C);try{return await S(t,{headers:N,signal:n.signal})}finally{clearTimeout(F)}},F;try{F=await send(cacheBustedUrl(n,t.nonce)),!F.ok&&F.status!==404&&F.status>=400&&F.status<500&&(F=await send(n))}catch(t){return{error:`request failed (${t instanceof Error?t.message:String(t)})`}}return F}async function probeOnce(t){let{version:n}=t,S=await sendPackumentRequest(t);if(`error`in S)return{state:`error`,detail:S.error};let C=S;if(C.status===404)return{state:`absent`,status:404,detail:`404 — the registry serves no packument for this name`};if(!C.ok)return{state:`error`,status:C.status,detail:`${C.status} ${C.statusText}`};let N;try{N=await C.json()}catch(t){let n=t instanceof Error?t.message:String(t);return{state:`error`,status:C.status,detail:`packument is not JSON (${n})`}}let F=N?.versions,I=F&&typeof F==`object`?Object.keys(F):[],H=F&&typeof F==`object`&&Object.hasOwn(F,n)?F[n]:void 0;if(!H){let t=I.length>0?I[I.length-1]:`(none)`;return{state:`absent`,status:C.status,detail:`packument carries ${I.length} version(s), newest ${t} — ${n} is not among them`}}let W=H.dist?.tarball;return typeof W!=`string`||W.length===0?{state:`absent`,status:C.status,detail:`packument has ${n} but its \`dist.tarball\` is missing`}:{state:`present`,status:C.status,tarball:W}}function formatUnconfirmedPublish(t){let{name:n,version:S,putUrl:C,putStatus:N,putStatusText:F,payloadBytes:I,readback:H}=t,W=t.claim??`accepted`,q=(H.elapsedMs/1e3).toFixed(1),Y=H.last.state===`present`?`served`:H.last.detail,X=W===`already-published`?`npm says ${S} is ALREADY PUBLISHED`:`npm ACCEPTED the upload`,Z=H.verdict===`unknown`?H.last.state===`absent`?`${X}; its install document does not serve ${S} and the registry's own record could NOT be read.`:`${X} and the read-back could NOT establish whether the registry serves it.`:H.verdict===`recorded-not-served`?`${X}; the registry RECORDS ${S} and its install document does not serve it.`:`${X} and the registry has no record of ${S}.`,te=H.verdict===`unknown`?[` This is NOT a report that the publish failed, and it is not one that it worked. The read-back`,` reached no answer it could act on, so the version may or may not be installable — confirm it`," before releasing anything that depends on it (`npm view <name>@<version> dist.tarball`)."]:H.verdict===`recorded-not-served`?[` Do NOT re-publish: the registry holds the write, so a re-run is answered 409 and changes`,` nothing. The document npm installs from is behind the registry's own record — measured on`,` the ts-for-gir v5.1.0 release, @ts-for-gir/reporter was recorded at 21:43:00.983Z and a`,` cache-busted read of its install document still did not carry 5.1.0 ~40 min later. Wait and`,` re-read; if it persists, check https://status.npmjs.org/.`]:W===`already-published`?[` A 409 is npm refusing to overwrite a version it holds, which is not the same as serving it:`,` in the v0.46.0 recovery @gjsify/node-runtime-darwin-arm64 was answered 409 at 09:48:49 and`,` the registry recorded 0.46.0 at 09:49:07, 18s later. Re-running answers the same 409, so it`," cannot fix this — wait and re-read (`npm view <name>@<version>`), or check",` https://status.npmjs.org/.`]:[` A 2xx from npm is an ACCEPTED write, not a durable one. In the v0.46.0 release 19 of 199`,` packages were recorded by the registry 56-252s after their 2xx, and ONE was never recorded`,` at all while its job stayed green — that is the failure this check exists to name.`," Re-run this publish (`--tolerate-republish` no-ops if it landed meanwhile). If it keeps",` failing, the write was rejected downstream of the 2xx: check https://status.npmjs.org/.`];return[`gjsify publish: ${n}@${S} — ${Z}`,` PUT ${C} (${I} bytes) → ${N} ${F}`,` read-back GET ${H.url} (accept: application/vnd.npm.install-v1+json, per-probe cache buster)`,` answered ${H.last.state}: ${Y}`,` after ${H.attempts} probe(s) over ${q}s`,` verdict ${H.verdict} — ${H.verdictDetail}`,...te].join(`
1216
- `)}async function probePackageName(t){let n=t.fetchImpl??((...t)=>globalThis.fetch(...t)),S=await sendPackumentRequest({url:`${t.registry.endsWith(`/`)?t.registry.slice(0,-1):t.registry}/${escapePackageName(t.name)}`,doFetch:n,probeTimeoutMs:t.probeTimeoutMs??3e4,authorization:t.authorization,nonce:`name-${Date.now()}-${++IG}`});if(`error`in S)return{state:`unknown`,detail:S.error};if(S.status===404)return{state:`absent`,status:404,detail:`404 — the registry serves no packument for this name`};if(!S.ok)return{state:`unknown`,status:S.status,detail:`${S.status} ${S.statusText}`};let C;try{C=await S.json()}catch(t){let n=t instanceof Error?t.message:String(t);return{state:`unknown`,status:S.status,detail:`packument is not JSON (${n})`}}let N=C?.versions,F=N&&typeof N==`object`?Object.keys(N).length:0;return F===0?{state:`unknown`,status:S.status,detail:`a 200 carrying no versions establishes nothing`}:{state:`present`,status:S.status,versions:F}}var jG,MG,NG,PG,FG,IG,LG=__esmMin(()=>{yh(),jG=[2e3,4e3,8e3,15e3,3e4],MG=2e3,NG=6e5,PG=32*1024*1024,FG=1e4,IG=0});function collectWorkspacePins(t,n){let S=[];for(let C of RG){let N=depsOf(t,C),F=depsOf(n,C);for(let[t,n]of Object.entries(N))typeof n!=`string`||!n.startsWith(`workspace:`)||S.push({name:t,spec:F[t]??n,block:C})}return S}var RG,zG,depsOf,BG=__esmMin(()=>{RG=[`dependencies`,`optionalDependencies`,`peerDependencies`],zG=`dependencies`,depsOf=(t,n)=>{let S=t[n];return S&&typeof S==`object`?S:{}}});function statusTokenFromEnv(t){for(let n of[t.NPM_STATUS_TOKEN,t.NODE_AUTH_TOKEN]){let t=n?.trim();if(t&&!/^X+(-X+)+$/.test(t))return t}}async function fetchVersionStatus(t){if(!t.token)return{state:`unavailable`,reason:`no-credential`,detail:`the status endpoint needs an npm access token (set NPM_STATUS_TOKEN); OIDC publish tokens are not accepted`};let n=t.fetchImpl??((...t)=>globalThis.fetch(...t)),S=`${t.registry.endsWith(`/`)?t.registry.slice(0,-1):t.registry}/-/package/${escapePackageName(t.name)}/version/${encodeURIComponent(t.version)}/status`,C;try{C=await n(S,{headers:{accept:`application/json`,authorization:`Bearer ${t.token}`},signal:AbortSignal.timeout(t.probeTimeoutMs??3e4)})}catch(t){return{state:`unavailable`,reason:`error`,detail:t instanceof Error?t.message:String(t)}}if(C.status===401)return{state:`unavailable`,reason:`rejected`,detail:`401 — the token is missing, invalid or expired`};if(C.status===403)return{state:`unavailable`,reason:`not-enabled`,detail:`403 — package version status is not enabled for this package`};if(C.status===404)return{state:`unavailable`,reason:`not-found`,detail:`404 — no such version, or the token cannot see this package`};if(!C.ok)return{state:`unavailable`,reason:`error`,detail:`${C.status} ${C.statusText}`};let N;try{N=await C.json()}catch(t){return{state:`unavailable`,reason:`error`,detail:`status body is not JSON (${t instanceof Error?t.message:String(t)})`}}let F=N?.status;return typeof F!=`string`||!VG.includes(F)?{state:`unavailable`,reason:`error`,detail:`unrecognised status ${JSON.stringify(F)}`}:{state:`known`,status:F}}function isTerminalClass(t){return t!==`validating`&&t!==`published-lagging`&&t!==`unchecked`}function whyUnchecked(t){return t.reason===`no-credential`?`status endpoint not asked: no NPM_STATUS_TOKEN`:t.detail}function classifyUnserved(t,n){if(n.state===`known`)switch(n.status){case`validating`:return{cls:`validating`,detail:`npm accepted the upload and its automated review has not finished`,terminal:!1};case`staged`:return{cls:`staged`,detail:`awaiting maintainer approval on npm`,terminal:!0};case`blocked`:return{cls:`blocked`,detail:`failed npm automated validation`,terminal:!0};case`deleted`:return{cls:`deleted`,detail:`deleted on npm`,terminal:!0};case`published`:return{cls:`published-lagging`,detail:`npm reports it published; the install document does not serve it yet`,terminal:!1}}return n.reason===`not-found`?{cls:`missing`,detail:`the registry has no such version (${n.detail}); the PUT did not land`,terminal:!0}:{cls:`unchecked`,detail:`not served (read-back: ${t}); ${whyUnchecked(n)}`,terminal:!1}}function describeClass(t){switch(t){case`validating`:return`validating (npm automated review pending)`;case`staged`:return`staged (needs maintainer approval)`;case`blocked`:return`blocked (failed automated validation)`;case`deleted`:return`deleted`;case`published-lagging`:return`published, not yet served`;case`missing`:return`missing (never recorded)`;case`unchecked`:return`not served (status not checked)`}}var VG,HG=__esmMin(()=>{yh(),VG=[`published`,`validating`,`staged`,`blocked`,`deleted`]});function appendLedger(t,n){t&&appendFileSync(t,`${JSON.stringify(n)}\n`)}function readLedger(t){if(!t||!existsSync(t))return[];let n=[];for(let S of readFileSync(t,`utf-8`).split(`
1217
- `))if(S.trim())try{let t=JSON.parse(S);(t.ev===`unserved`||t.ev===`held`||t.ev===`served`)&&n.push(t)}catch{}return n}function pinVersion(t){return/^[\^~]?(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?)$/.exec(t.trim())?.[1]}async function findUnavailablePins(t){let n=[],S=new Map;for(let C of t.pins){let N=pinVersion(C.spec);if(!N){t.log?.(`gjsify publish: ${C.name}@${C.spec} names no single version — not checked for hold`);continue}let F=`${C.name}@${N}`,I=C.block===`dependencies`?F:`${F}#nowait`;if(!S.has(I)){let n=C.block===`dependencies`?t:{...t,waitBudgetMs:0};S.set(I,await judgePin(n,C.name,N))}let H=S.get(I);H&&n.push({...H,block:C.block})}return n}async function judgePin(t,n,S){let C={name:n,version:S,block:`dependencies`},N=[...t.ledger].reverse().find(t=>t.name===n&&t.version===S);if(N?.ev===`served`)return null;if(N?.ev===`unserved`&&isTerminalClass(N.cls))return{...C,cls:N.cls,detail:N.detail};if(N?.ev===`held`)return{...C,cls:`held`,detail:`was itself held — ${summariseReasons(N.reasons)}`};let F={registry:t.registry,name:n,version:S,authorization:t.authorization,fetchImpl:t.fetchImpl,sleep:t.sleep,now:t.now,log:t.log},I=await verifyPublishedVersion({...F,budgetMs:WG});if(I.confirmed)return confirmedServed(t,N,n,S);let ask=()=>fetchVersionStatus({registry:t.registry,name:n,version:S,token:t.statusToken,fetchImpl:t.fetchImpl}),H=classifyUnserved(I.verdict,await ask());if(!H.terminal&&t.waitBudgetMs>0){if(I=await verifyPublishedVersion({...F,budgetMs:t.waitBudgetMs}),I.confirmed)return confirmedServed(t,N,n,S);H=classifyUnserved(I.verdict,await ask())}return{...C,cls:H.cls,detail:H.detail}}function confirmedServed(t,n,S,C){return n?.ev===`unserved`&&appendLedger(t.ledgerPath,{ev:`served`,name:S,version:C}),null}function summariseReasons(t){return t.map(t=>`${t.name}@${t.version} is ${t.cls===`held`?`held`:describeClass(t.cls)}`).join(`; `)}async function recordUnserved(t){let n=await fetchVersionStatus({registry:t.registry,name:t.name,version:t.version,token:t.statusToken,fetchImpl:t.fetchImpl}),S=classifyUnserved(t.verdict,n);return appendLedger(t.ledgerPath,{ev:`unserved`,name:t.name,version:t.version,cls:S.cls,detail:S.detail}),S}function pendingEntries(t){let n=new Map;for(let S of t)n.set(`${S.name}@${S.version}`,S);let S=[...n.values()];return{unserved:S.filter(t=>t.ev===`unserved`),held:S.filter(t=>t.ev===`held`)}}function markHeldPublished(t,n,S){[...readLedger(t)].reverse().find(t=>t.name===n&&t.version===S)?.ev===`held`&&appendLedger(t,{ev:`served`,name:n,version:S})}async function settleUnserved(t){let n=pendingEntries(t.entries).unserved.filter(t=>!isTerminalClass(t.cls));return(await Promise.all(n.map(async n=>{if((await verifyPublishedVersion({registry:t.registryFor(n.name),name:n.name,version:n.version,budgetMs:t.budgetMs,authorization:t.authorization,fetchImpl:t.fetchImpl,sleep:t.sleep,now:t.now,log:t.log})).confirmed)return appendLedger(t.ledgerPath,{ev:`served`,name:n.name,version:n.version}),`${n.name}@${n.version}`}))).filter(t=>t!==void 0)}function renderLedgerSummary(t,n){let{unserved:S,held:C}=pendingEntries(t);if(S.length===0&&C.length===0)return;let N=[`### npm versions that were accepted but are not installable`,``];if(S.length>0){N.push(`| Package | Version | State | Detail |`,`| --- | --- | --- | --- |`);for(let t of S)N.push(`| \`${t.name}\` | ${t.version} | ${describeClass(t.cls)} | ${t.detail} |`);N.push(``)}if(C.length>0){N.push(`### Held — NOT published in this run`,``,`Each package below depends on a version npm does not serve, so publishing it would have shipped a package that cannot be installed.`,``,`| Package | Version | Because |`,`| --- | --- | --- |`);for(let t of C)N.push(`| \`${t.name}\` | ${t.version} | ${summariseReasons(t.reasons)} |`);N.push(``,"Once the dependencies above are served by npm (a `validating` version appears on its own, or is approved/released by a maintainer), publish the held set with:",``,"```sh",`gh workflow run release.yml --ref ${n} -f skip_publish=false -f only='${[...new Set(C.map(t=>t.name))].join(` `)}'`,"```"),S.some(t=>t.cls===`blocked`||t.cls===`deleted`)&&N.push(``,"A `blocked` or `deleted` version is a spent number: re-running the release cannot serve it, the package needs a version bump.")}return N.join(`
1218
- `)}var UG,WG,holdsPublish,GG=__esmMin(()=>{ef(),BG(),LG(),HG(),UG=3e5,WG=1,holdsPublish=t=>t.block===zG});function beginPrompt(){KG++}function endPrompt(t=defaultWrite){if(KG=Math.max(0,KG-1),KG>0||qG.length===0)return;let n=qG.splice(0,qG.length);for(let S of n)t(S)}function writeAroundPrompt(t,n=defaultWrite){if(KG>0){qG.push(t);return}n(t)}function defaultWrite(t){process.stdout.write(t)}var KG,qG,JG=__esmMin(()=>{KG=0,qG=[]});function isTtyStdin(){let t=process.stdin;return!!t.isTTY&&typeof t.setRawMode==`function`}function applyKey(t,n,S){return n===`\r`||n===`
1215
+ `)}function formatUnknown(t,n){return`gjsify publish: ${t}@${n} — 404 Not Found`}function is404DiagnosticCandidate(t){let n=t.trim();return!!(n.length===0||/^not found$/i.test(n)||/"error"\s*:\s*"Not Found"/i.test(n))}var jG=__esmMin(()=>{gh()});function backoffFor(t){return MG[Math.min(Math.max(t,0),MG.length-1)]??3e4}function probeTimeoutFor(t,n){return Math.min(t,Math.max(n,NG))}function budgetForPayload(t,n){if(t<6e5||n<=FG)return t;let S=(n-FG)/(1024*1024);return t+Math.ceil(S)*IG}function cacheBustedUrl(t,n){return`${t}${t.includes(`?`)?`&`:`?`}__gjsify_readback=${encodeURIComponent(n)}`}async function verifyPublishedVersion(t){let{registry:n,name:S,version:C,budgetMs:N}=t,F=t.fetchImpl??((...t)=>globalThis.fetch(...t)),I=t.sleep??(t=>new Promise(n=>setTimeout(n,t))),H=t.now??(()=>Date.now()),W=t.probeTimeoutMs??3e4,q=`${n.endsWith(`/`)?n.slice(0,-1):n}/${escapePackageName(S)}`,Y=H(),X=0,Z={state:`error`,detail:`no probe was sent`};for(let n=0;X++,Z=await probeOnce({url:q,version:C,doFetch:F,probeTimeoutMs:probeTimeoutFor(W,N-(H()-Y)),authorization:t.authorization,nonce:`${Y}-${X}`}),t.log?.(`gjsify publish: read-back probe ${X} of ${S}@${C} → ${Z.state}`+(Z.state===`present`?``:` (${Z.detail})`)),Z.state!==`present`;n++){let t=N-(H()-Y);if(t<=0)break;await I(Math.min(backoffFor(n),t))}let te={attempts:X,elapsedMs:H()-Y,url:q,last:Z};if(Z.state===`present`)return{...te,confirmed:!0,verdict:`confirmed`,verdictDetail:`${q} serves ${C} with a tarball`};if(Z.state===`error`)return{...te,confirmed:!1,verdict:`unknown`,verdictDetail:`the read-back could not reach a verdict — ${Z.detail}`};let ne=await probeRegistryRecord({url:q,version:C,doFetch:F,probeTimeoutMs:W,authorization:t.authorization,nonce:`${Y}-record`});return t.log?.(`gjsify publish: read-back record probe of ${S}@${C} → ${ne.state} (${ne.detail})`),ne.state===`recorded`?{...te,confirmed:!1,verdict:`recorded-not-served`,verdictDetail:ne.detail,recordedAt:ne.recordedAt}:ne.state===`no-record`?{...te,confirmed:!1,verdict:`not-published`,verdictDetail:ne.detail}:{...te,confirmed:!1,verdict:`unknown`,verdictDetail:ne.detail}}async function probeRegistryRecord(t){let{url:n,version:S,doFetch:C,probeTimeoutMs:N}=t,F=new AbortController,I=setTimeout(()=>F.abort(),N),H;try{H=await C(cacheBustedUrl(n,t.nonce),{headers:{"cache-control":`no-cache`,...t.authorization?{authorization:t.authorization}:{}},signal:F.signal})}catch(t){return{state:`unknown`,detail:`the registry serves no ${S} and its own record was unreadable (${t instanceof Error?t.message:String(t)})`}}finally{clearTimeout(I)}if(H.status===404)return{state:`no-record`,detail:`the registry has no packument for this name at all (404)`};if(!H.ok)return{state:`unknown`,detail:`the registry serves no ${S} and its own record answered ${H.status} ${H.statusText}`};let W;try{W=await H.json()}catch(t){return{state:`unknown`,detail:`the registry serves no ${S} and its own record is not JSON (${t instanceof Error?t.message:String(t)})`}}let q=W?.time,Y=q&&typeof q==`object`?q[S]:void 0;return typeof Y==`string`&&Y.length>0?{state:`recorded`,recordedAt:Y,detail:`the registry RECORDS ${S} at ${Y} and its install document does not serve it`}:{state:`no-record`,detail:`the registry has no record of ${S} — neither in its install document nor in its own \`time\` map`}}async function sendPackumentRequest(t){let{url:n,doFetch:S,probeTimeoutMs:C}=t,N={accept:`application/vnd.npm.install-v1+json`,"cache-control":`no-cache`,...t.authorization?{authorization:t.authorization}:{}},send=async t=>{let n=new AbortController,F=setTimeout(()=>n.abort(),C);try{return await S(t,{headers:N,signal:n.signal})}finally{clearTimeout(F)}},F;try{F=await send(cacheBustedUrl(n,t.nonce)),!F.ok&&F.status!==404&&F.status>=400&&F.status<500&&(F=await send(n))}catch(t){return{error:`request failed (${t instanceof Error?t.message:String(t)})`}}return F}async function probeOnce(t){let{version:n}=t,S=await sendPackumentRequest(t);if(`error`in S)return{state:`error`,detail:S.error};let C=S;if(C.status===404)return{state:`absent`,status:404,detail:`404 — the registry serves no packument for this name`};if(!C.ok)return{state:`error`,status:C.status,detail:`${C.status} ${C.statusText}`};let N;try{N=await C.json()}catch(t){let n=t instanceof Error?t.message:String(t);return{state:`error`,status:C.status,detail:`packument is not JSON (${n})`}}let F=N?.versions,I=F&&typeof F==`object`?Object.keys(F):[],H=F&&typeof F==`object`&&Object.hasOwn(F,n)?F[n]:void 0;if(!H){let t=I.length>0?I[I.length-1]:`(none)`;return{state:`absent`,status:C.status,detail:`packument carries ${I.length} version(s), newest ${t} — ${n} is not among them`}}let W=H.dist?.tarball;return typeof W!=`string`||W.length===0?{state:`absent`,status:C.status,detail:`packument has ${n} but its \`dist.tarball\` is missing`}:{state:`present`,status:C.status,tarball:W}}function formatUnconfirmedPublish(t){let{name:n,version:S,putUrl:C,putStatus:N,putStatusText:F,payloadBytes:I,readback:H}=t,W=t.claim??`accepted`,q=(H.elapsedMs/1e3).toFixed(1),Y=H.last.state===`present`?`served`:H.last.detail,X=W===`already-published`?`npm says ${S} is ALREADY PUBLISHED`:`npm ACCEPTED the upload`,Z=H.verdict===`unknown`?H.last.state===`absent`?`${X}; its install document does not serve ${S} and the registry's own record could NOT be read.`:`${X} and the read-back could NOT establish whether the registry serves it.`:H.verdict===`recorded-not-served`?`${X}; the registry RECORDS ${S} and its install document does not serve it.`:`${X} and the registry has no record of ${S}.`,te=H.verdict===`unknown`?[` This is NOT a report that the publish failed, and it is not one that it worked. The read-back`,` reached no answer it could act on, so the version may or may not be installable — confirm it`," before releasing anything that depends on it (`npm view <name>@<version> dist.tarball`)."]:H.verdict===`recorded-not-served`?[` Do NOT re-publish: the registry holds the write, so a re-run is answered 409 and changes`,` nothing. The document npm installs from is behind the registry's own record — measured on`,` the ts-for-gir v5.1.0 release, @ts-for-gir/reporter was recorded at 21:43:00.983Z and a`,` cache-busted read of its install document still did not carry 5.1.0 ~40 min later. Wait and`,` re-read; if it persists, check https://status.npmjs.org/.`]:W===`already-published`?[` A 409 is npm refusing to overwrite a version it holds, which is not the same as serving it:`,` in the v0.46.0 recovery @gjsify/node-runtime-darwin-arm64 was answered 409 at 09:48:49 and`,` the registry recorded 0.46.0 at 09:49:07, 18s later. Re-running answers the same 409, so it`," cannot fix this — wait and re-read (`npm view <name>@<version>`), or check",` https://status.npmjs.org/.`]:[` A 2xx from npm is an ACCEPTED write, not a durable one. In the v0.46.0 release 19 of 199`,` packages were recorded by the registry 56-252s after their 2xx, and ONE was never recorded`,` at all while its job stayed green — that is the failure this check exists to name.`," Re-run this publish (`--tolerate-republish` no-ops if it landed meanwhile). If it keeps",` failing, the write was rejected downstream of the 2xx: check https://status.npmjs.org/.`];return[`gjsify publish: ${n}@${S} — ${Z}`,` PUT ${C} (${I} bytes) → ${N} ${F}`,` read-back GET ${H.url} (accept: application/vnd.npm.install-v1+json, per-probe cache buster)`,` answered ${H.last.state}: ${Y}`,` after ${H.attempts} probe(s) over ${q}s`,` verdict ${H.verdict} — ${H.verdictDetail}`,...te].join(`
1216
+ `)}async function probePackageName(t){let n=t.fetchImpl??((...t)=>globalThis.fetch(...t)),S=await sendPackumentRequest({url:`${t.registry.endsWith(`/`)?t.registry.slice(0,-1):t.registry}/${escapePackageName(t.name)}`,doFetch:n,probeTimeoutMs:t.probeTimeoutMs??3e4,authorization:t.authorization,nonce:`name-${Date.now()}-${++LG}`});if(`error`in S)return{state:`unknown`,detail:S.error};if(S.status===404)return{state:`absent`,status:404,detail:`404 — the registry serves no packument for this name`};if(!S.ok)return{state:`unknown`,status:S.status,detail:`${S.status} ${S.statusText}`};let C;try{C=await S.json()}catch(t){let n=t instanceof Error?t.message:String(t);return{state:`unknown`,status:S.status,detail:`packument is not JSON (${n})`}}let N=C?.versions,F=N&&typeof N==`object`?Object.keys(N).length:0;return F===0?{state:`unknown`,status:S.status,detail:`a 200 carrying no versions establishes nothing`}:{state:`present`,status:S.status,versions:F}}var MG,NG,PG,FG,IG,LG,RG=__esmMin(()=>{yh(),MG=[2e3,4e3,8e3,15e3,3e4],NG=2e3,PG=6e5,FG=32*1024*1024,IG=1e4,LG=0});function collectWorkspacePins(t,n){let S=[];for(let C of zG){let N=depsOf(t,C),F=depsOf(n,C);for(let[t,n]of Object.entries(N))typeof n!=`string`||!n.startsWith(`workspace:`)||S.push({name:t,spec:F[t]??n,block:C})}return S}var zG,BG,depsOf,VG=__esmMin(()=>{zG=[`dependencies`,`optionalDependencies`,`peerDependencies`],BG=`dependencies`,depsOf=(t,n)=>{let S=t[n];return S&&typeof S==`object`?S:{}}});function statusTokenFromEnv(t){for(let n of[t.NPM_STATUS_TOKEN,t.NODE_AUTH_TOKEN]){let t=n?.trim();if(t&&!/^X+(-X+)+$/.test(t))return t}}async function fetchVersionStatus(t){if(!t.token)return{state:`unavailable`,reason:`no-credential`,detail:`the status endpoint needs an npm access token (set NPM_STATUS_TOKEN); OIDC publish tokens are not accepted`};let n=t.fetchImpl??((...t)=>globalThis.fetch(...t)),S=`${t.registry.endsWith(`/`)?t.registry.slice(0,-1):t.registry}/-/package/${escapePackageName(t.name)}/version/${encodeURIComponent(t.version)}/status`,C;try{C=await n(S,{headers:{accept:`application/json`,authorization:`Bearer ${t.token}`},signal:AbortSignal.timeout(t.probeTimeoutMs??3e4)})}catch(t){return{state:`unavailable`,reason:`error`,detail:t instanceof Error?t.message:String(t)}}if(C.status===401)return{state:`unavailable`,reason:`rejected`,detail:`401 — the token is missing, invalid or expired`};if(C.status===403)return{state:`unavailable`,reason:`not-enabled`,detail:`403 — package version status is not enabled for this package`};if(C.status===404)return{state:`unavailable`,reason:`not-found`,detail:`404 — no such version, or the token cannot see this package`};if(!C.ok)return{state:`unavailable`,reason:`error`,detail:`${C.status} ${C.statusText}`};let N;try{N=await C.json()}catch(t){return{state:`unavailable`,reason:`error`,detail:`status body is not JSON (${t instanceof Error?t.message:String(t)})`}}let F=N?.status;return typeof F!=`string`||!HG.includes(F)?{state:`unavailable`,reason:`error`,detail:`unrecognised status ${JSON.stringify(F)}`}:{state:`known`,status:F}}function isTerminalClass(t){return t!==`validating`&&t!==`published-lagging`&&t!==`unchecked`}function whyUnchecked(t){return t.reason===`no-credential`?`status endpoint not asked: no NPM_STATUS_TOKEN`:t.detail}function classifyUnserved(t,n){if(n.state===`known`)switch(n.status){case`validating`:return{cls:`validating`,detail:`npm accepted the upload and its automated review has not finished`,terminal:!1};case`staged`:return{cls:`staged`,detail:`awaiting maintainer approval on npm`,terminal:!0};case`blocked`:return{cls:`blocked`,detail:`failed npm automated validation`,terminal:!0};case`deleted`:return{cls:`deleted`,detail:`deleted on npm`,terminal:!0};case`published`:return{cls:`published-lagging`,detail:`npm reports it published; the install document does not serve it yet`,terminal:!1}}return n.reason===`not-found`?{cls:`missing`,detail:`the registry has no such version (${n.detail}); the PUT did not land`,terminal:!0}:{cls:`unchecked`,detail:`not served (read-back: ${t}); ${whyUnchecked(n)}`,terminal:!1}}function describeClass(t){switch(t){case`validating`:return`validating (npm automated review pending)`;case`staged`:return`staged (needs maintainer approval)`;case`blocked`:return`blocked (failed automated validation)`;case`deleted`:return`deleted`;case`published-lagging`:return`published, not yet served`;case`missing`:return`missing (never recorded)`;case`unchecked`:return`not served (status not checked)`}}var HG,UG=__esmMin(()=>{yh(),HG=[`published`,`validating`,`staged`,`blocked`,`deleted`]});function appendLedger(t,n){t&&appendFileSync(t,`${JSON.stringify(n)}\n`)}function readLedger(t){if(!t||!existsSync(t))return[];let n=[];for(let S of readFileSync(t,`utf-8`).split(`
1217
+ `))if(S.trim())try{let t=JSON.parse(S);(t.ev===`unserved`||t.ev===`held`||t.ev===`served`)&&n.push(t)}catch{}return n}function pinVersion(t){return/^[\^~]?(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?)$/.exec(t.trim())?.[1]}async function findUnavailablePins(t){let n=[],S=new Map;for(let C of t.pins){let N=pinVersion(C.spec);if(!N){t.log?.(`gjsify publish: ${C.name}@${C.spec} names no single version — not checked for hold`);continue}let F=`${C.name}@${N}`,I=C.block===`dependencies`?F:`${F}#nowait`;if(!S.has(I)){let n=C.block===`dependencies`?t:{...t,waitBudgetMs:0};S.set(I,await judgePin(n,C.name,N))}let H=S.get(I);H&&n.push({...H,block:C.block})}return n}async function judgePin(t,n,S){let C={name:n,version:S,block:`dependencies`},N=[...t.ledger].reverse().find(t=>t.name===n&&t.version===S);if(N?.ev===`served`)return null;if(N?.ev===`unserved`&&isTerminalClass(N.cls))return{...C,cls:N.cls,detail:N.detail};if(N?.ev===`held`)return{...C,cls:`held`,detail:`was itself held — ${summariseReasons(N.reasons)}`};let F={registry:t.registry,name:n,version:S,authorization:t.authorization,fetchImpl:t.fetchImpl,sleep:t.sleep,now:t.now,log:t.log},I=await verifyPublishedVersion({...F,budgetMs:GG});if(I.confirmed)return confirmedServed(t,N,n,S);let ask=()=>fetchVersionStatus({registry:t.registry,name:n,version:S,token:t.statusToken,fetchImpl:t.fetchImpl}),H=classifyUnserved(I.verdict,await ask());if(!H.terminal&&t.waitBudgetMs>0){if(I=await verifyPublishedVersion({...F,budgetMs:t.waitBudgetMs}),I.confirmed)return confirmedServed(t,N,n,S);H=classifyUnserved(I.verdict,await ask())}return{...C,cls:H.cls,detail:H.detail}}function confirmedServed(t,n,S,C){return n?.ev===`unserved`&&appendLedger(t.ledgerPath,{ev:`served`,name:S,version:C}),null}function summariseReasons(t){return t.map(t=>`${t.name}@${t.version} is ${t.cls===`held`?`held`:describeClass(t.cls)}`).join(`; `)}async function recordUnserved(t){let n=await fetchVersionStatus({registry:t.registry,name:t.name,version:t.version,token:t.statusToken,fetchImpl:t.fetchImpl}),S=classifyUnserved(t.verdict,n);return appendLedger(t.ledgerPath,{ev:`unserved`,name:t.name,version:t.version,cls:S.cls,detail:S.detail}),S}function pendingEntries(t){let n=new Map;for(let S of t)n.set(`${S.name}@${S.version}`,S);let S=[...n.values()];return{unserved:S.filter(t=>t.ev===`unserved`),held:S.filter(t=>t.ev===`held`)}}function markHeldPublished(t,n,S){[...readLedger(t)].reverse().find(t=>t.name===n&&t.version===S)?.ev===`held`&&appendLedger(t,{ev:`served`,name:n,version:S})}async function settleUnserved(t){let n=pendingEntries(t.entries).unserved.filter(t=>!isTerminalClass(t.cls));return(await Promise.all(n.map(async n=>{if((await verifyPublishedVersion({registry:t.registryFor(n.name),name:n.name,version:n.version,budgetMs:t.budgetMs,authorization:t.authorization,fetchImpl:t.fetchImpl,sleep:t.sleep,now:t.now,log:t.log})).confirmed)return appendLedger(t.ledgerPath,{ev:`served`,name:n.name,version:n.version}),`${n.name}@${n.version}`}))).filter(t=>t!==void 0)}function renderLedgerSummary(t,n){let{unserved:S,held:C}=pendingEntries(t);if(S.length===0&&C.length===0)return;let N=[`### npm versions that were accepted but are not installable`,``];if(S.length>0){N.push(`| Package | Version | State | Detail |`,`| --- | --- | --- | --- |`);for(let t of S)N.push(`| \`${t.name}\` | ${t.version} | ${describeClass(t.cls)} | ${t.detail} |`);N.push(``)}if(C.length>0){N.push(`### Held — NOT published in this run`,``,`Each package below depends on a version npm does not serve, so publishing it would have shipped a package that cannot be installed.`,``,`| Package | Version | Because |`,`| --- | --- | --- |`);for(let t of C)N.push(`| \`${t.name}\` | ${t.version} | ${summariseReasons(t.reasons)} |`);N.push(``,"Once the dependencies above are served by npm (a `validating` version appears on its own, or is approved/released by a maintainer), publish the held set with:",``,"```sh",`gh workflow run release.yml --ref ${n} -f skip_publish=false -f only='${[...new Set(C.map(t=>t.name))].join(` `)}'`,"```"),S.some(t=>t.cls===`blocked`||t.cls===`deleted`)&&N.push(``,"A `blocked` or `deleted` version is a spent number: re-running the release cannot serve it, the package needs a version bump.")}return N.join(`
1218
+ `)}var WG,GG,holdsPublish,KG=__esmMin(()=>{ef(),VG(),RG(),UG(),WG=3e5,GG=1,holdsPublish=t=>t.block===BG});function beginPrompt(){qG++}function endPrompt(t=defaultWrite){if(qG=Math.max(0,qG-1),qG>0||JG.length===0)return;let n=JG.splice(0,JG.length);for(let S of n)t(S)}function writeAroundPrompt(t,n=defaultWrite){if(qG>0){JG.push(t);return}n(t)}function defaultWrite(t){process.stdout.write(t)}var qG,JG,YG=__esmMin(()=>{qG=0,JG=[]});function isTtyStdin(){let t=process.stdin;return!!t.isTTY&&typeof t.setRawMode==`function`}function applyKey(t,n,S){return n===`\r`||n===`
1219
1219
  `?{buf:t,echo:`
1220
- `,done:!0,interrupt:!1}:n===YG?{buf:t,echo:`
1221
- `,done:!1,interrupt:!0}:n===XG||n===ZG?t.length>0?{buf:t.slice(0,-1),echo:`\b \b`,done:!1,interrupt:!1}:{buf:t,echo:``,done:!1,interrupt:!1}:n>=` `?{buf:t+n,echo:S?`*`:n,done:!1,interrupt:!1}:{buf:t,echo:``,done:!1,interrupt:!1}}async function runRawSession(t){let n=process.stdin,S=process.stdout,C=null,cleanup=()=>{n.removeListener(`data`,onData);try{n.setRawMode(!1)}catch{}typeof n.pause==`function`&&n.pause()},onData=t=>{let n=typeof t==`string`?t:t.toString(`utf-8`);for(let t of n){if(!C)continue;let n=applyKey(C.buf,t,C.mask);if(C.buf=n.buf,n.echo&&S.write(n.echo),n.interrupt)return cleanup(),process.exit(130);if(n.done){let{resolve:t}=C;C=null,t(n.buf)}}};n.setRawMode(!0),typeof n.resume==`function`&&n.resume(),n.setEncoding(`utf-8`),n.on(`data`,onData);let read=(t,n)=>new Promise(N=>{beginPrompt(),S.write(t),C={mask:n,buf:``,resolve:t=>{endPrompt(),N(t)}}});try{return await t(read)}finally{cleanup()}}function readLine(){return new Promise(t=>{let n=``,onData=S=>{n+=typeof S==`string`?S:S.toString(`utf-8`);let C=n.search(/[\r\n]/);C>=0&&(cleanup(),t(n.slice(0,C)))},onEnd=()=>{cleanup(),t(n.replace(/\r$/,``).trim())},cleanup=()=>{process.stdin.removeListener(`data`,onData),process.stdin.removeListener(`end`,onEnd)};process.stdin.setEncoding(`utf-8`),typeof process.stdin.isPaused==`function`&&process.stdin.isPaused()&&process.stdin.resume(),process.stdin.on(`data`,onData),process.stdin.once(`end`,onEnd)})}async function promptLine(t){if(!isTtyStdin()){beginPrompt(),process.stdout.write(t);try{return await readLine()}finally{endPrompt()}}return runRawSession(n=>n(t,!1))}async function promptCredentials(t){if(!isTtyStdin()){let n=t;n||=(process.stdout.write(`Username: `),await readLine()),process.stdout.write(`Password: `);let S=await readLine();return{username:n,password:S}}return runRawSession(async n=>({username:t??await n(`Username: `,!1),password:await n(`Password: `,!0)}))}var YG,XG,ZG,QG=__esmMin(()=>{JG(),YG=``,XG=``,ZG=`\b`});function isOtpCacheEnabled(){let t=process.env[$G];return!(t===`1`||t===`true`||t===`yes`)}function normalizeRegistry(t){return t.endsWith(`/`)?t.slice(0,-1):t}function cacheBaseDir(t){if(t?.dir)return t.dir;let n=process.env.XDG_RUNTIME_DIR;return In(n&&n.length>0?n:tmpdir(),eK)}function cacheFileFor(t,n){let S=normalizeRegistry(t).replace(/[^a-zA-Z0-9]+/g,`-`).replace(/^-+|-+$/g,``).slice(0,120);return In(cacheBaseDir(n),`otp-${S||`default`}.json`)}function readCachedOtp(t,n){if(!isOtpCacheEnabled())return;let S=n?.now??Date.now(),C=cacheFileFor(t,n);try{if(!existsSync(C))return;let n=JSON.parse(readFileSync(C,`utf8`));if(!n||typeof n.otp!=`string`||typeof n.expiresAt!=`number`){deleteCacheFile(C);return}if(n.registry!==normalizeRegistry(t))return;if(S>=n.expiresAt){deleteCacheFile(C);return}return n.otp.length>0?n.otp:void 0}catch{deleteCacheFile(C);return}}function writeCachedOtp(t,n,S){if(!isOtpCacheEnabled()||!n||n.length===0)return;let C=S?.now??Date.now(),N=S?.ttlMs??3e4;try{mkdirSync(cacheBaseDir(S),{recursive:!0,mode:448});let F=cacheFileFor(t,S),I={otp:n,expiresAt:C+N,registry:normalizeRegistry(t)};writeFileSync(F,JSON.stringify(I),{mode:384}),chmodSync(F,384)}catch{}}function clearCachedOtp(t,n){deleteCacheFile(cacheFileFor(t,n))}function deleteCacheFile(t){try{existsSync(t)&&rmSync(t,{force:!0})}catch{}}var $G,eK,tK=__esmMin(()=>{ef(),$g(),qn(),$G=`GJSIFY_NO_OTP_CACHE`,eK=`gjsify-otp`});async function isOtpChallenge(t){if(t.status!==401)return!1;if((t.headers.get(`www-authenticate`)??``).toLowerCase().includes(`otp`))return!0;let n=await t.clone().text().catch(()=>``);return/one-time pass/i.test(n)||/\bEOTP\b/.test(n)}async function withOtpRetry(t,n,S={}){let C=S.maxPrompts??2,N=S.question,F=n.current(),I=S.seedFirstAttempt===!0&&F!==void 0,H=n.epoch(),W=await t(I?F:void 0);if(!await isOtpChallenge(W))return W;if(I&&n.invalidate(H),!I&&n.current()!==void 0){if(H=n.epoch(),W=await t(n.current()),!await isOtpChallenge(W))return W;n.invalidate(H)}for(let S=0;S<C;S++){let S=await n.refresh(N,H);if(!S||(H=n.epoch(),W=await t(S),!await isOtpChallenge(W)))return W;n.invalidate(H)}return W}var nK,rK,OtpProvider,iK=__esmMin(()=>{QG(),tK(),nK=`This operation requires a one-time password.
1222
- Enter OTP: `,rK=`The previous one-time password is no longer valid (npm codes last about 30 seconds).
1223
- Enter a NEW OTP: `,OtpProvider=class{cached;promptFn;registry;generation=0;pending;constructor(t,n=promptLine,S={}){this.promptFn=n,this.registry=S.registry;let C=t&&t.length>0?t:void 0;C?(this.cached=C,this.registry&&writeCachedOtp(this.registry,C)):this.cached=this.registry?readCachedOtp(this.registry):void 0}current(){return this.cached}epoch(){return this.generation}async refresh(t,n){if(n!==void 0&&this.generation>n&&this.cached)return this.cached;if(this.pending)return this.pending;this.pending=this.promptOnce(t??(this.generation>0?rK:nK));try{return await this.pending}finally{this.pending=void 0}}async promptOnce(t){let n=(await this.promptFn(t)).trim();return n&&(this.cached=n,this.generation++,this.registry&&writeCachedOtp(this.registry,n)),n}invalidate(t){t!==void 0&&this.generation!==t||(this.cached=void 0,this.registry&&clearCachedOtp(this.registry))}}});function remainingHoldDeadlineMs(){let t=Number(process.env.GJSIFY_HOLD_DEADLINE);return Number.isFinite(t)&&t>0?Math.max(0,t-Date.now()):1/0}function acceptsRepublish(t,n,S,C){return(t===409||t===403&&/previously published/i.test(n))&&(S||C)}async function publishWorkspace(t){let{wsDir:n,tag:S,access:C,provenance:N,tolerate:F,tolerateUntrustedNew:I,trustedFlag:H,verbose:W,json:q,otpProvider:Y}=t,X=await packWorkspace(n,{dryRun:!0,lifecycleScripts:[`prepublishOnly`,`prepack`],lifecycleStdio:q?`inherit-stderr`:`inherit`}),Z=await packWorkspaceToBytes(n),te=readFileSync(In(n,`package.json`),`utf-8`),ne=JSON.parse(te),re=await loadRewrittenManifest(n,ne),ie=await loadNpmrc(n),ae=t.registry??process.env.npm_config_registry??registryFor(X.name,ie)??lh,oe=ae.endsWith(`/`)?ae.slice(0,-1):ae,Q=`${oe}/${escapePackageName(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:Z,tarballUrl:`${oe}/${X.name}/-/${se}`,packed:{...X,wireFilename:se},provenance:N}),le=buildPublishHeaders(Q,{npmrc:ie}),ue=new Set(t.assumePresent??[]),de=collectWorkspacePins(ne,re).filter(t=>!ue.has(t.name));if(de.length>0){let t=await Promise.all(de.map(async t=>({pin:t,presence:await probePackageName({registry:ae,name:t.name,authorization:le.authorization})}))),n=[];for(let{pin:S,presence:C}of t){if(C.state===`present`)continue;let t=`${S.block}.${S.name}@${S.spec}`;if(C.state===`unknown`){ge.error(`gjsify publish: could not establish whether ${S.name} exists (${C.detail}) — not blocking on ${t}`);continue}if(S.block!==`dependencies`){ge.error(`gjsify publish: ${t} names a package ${ae} does not have — npm installs around it, Yarn (\`YN0035\`) does not`);continue}n.push(S)}if(n.length>0)return{ok:I,action:`blocked-missing-dependency`,name:X.name,version:X.version,registry:ae,tolerated:I,missing:n}}let fe=process.env.GJSIFY_PUBLISH_LEDGER;if(de.length>0){let n=await findUnavailablePins({registry:oe,pins:de,ledger:readLedger(fe),ledgerPath:fe,authorization:le.authorization,statusToken:statusTokenFromEnv(process.env),waitBudgetMs:t.holdWaitMs??3e5,log:W?t=>ge.error(t):void 0});for(let t of n.filter(t=>!holdsPublish(t)))ge.error(`gjsify publish: ${t.block}.${t.name}@${t.version} is not served (${t.detail}) — optional edge, publishing anyway`);let S=n.filter(holdsPublish);if(S.length>0)return appendLedger(fe,{ev:`held`,name:X.name,version:X.version,reasons:S}),{ok:!1,action:`held-unpublished-dependency`,name:X.name,version:X.version,registry:oe,reasons:S}}let pe=H===!0||H===void 0&&hasGithubOidcEnv()&&!process.env.NODE_AUTH_TOKEN,me=`token`;if(pe)try{let{token:t,audience:n}=await getNpmTrustedToken({packageName:X.name,registry:ae,log:W?t=>ge.error(t):void 0});le.authorization=`Bearer ${t}`,me=`oidc`,W&&ge.error(`gjsify publish: OIDC token obtained (audience=${n})`)}catch(t){if(t instanceof OidcExchangeError&&t.status===404&&/package not found/i.test(t.body)&&I)return{ok:!0,action:`skipped-untrusted-new`,name:X.name,version:X.version};if(H===!0)return{ok:!1,action:`oidc-failed`,name:X.name,version:X.version,error:t};if(!le.authorization)return{ok:!1,action:`oidc-no-token`,name:X.name,version:X.version,error:t};if(W){let n=t instanceof Error?t.message:String(t);ge.error(`gjsify publish: OIDC auto-detect failed (${n}) — falling back to token auth`)}}W&&(ge.error(`gjsify publish: PUT ${Q} (${X.name}@${X.version})`),ge.error(` auth-mode: ${me}`),ge.error(` authorization: ${le.authorization?`(set)`:`(none)`}`),ge.error(` payload size: ${JSON.stringify(ce).length} bytes`));let he=JSON.stringify(ce),_e=!1,doPut=async n=>{let S={...le};n&&(S[`npm-otp`]=n,S[`npm-auth-type`]=`legacy`);let{response:C,retried:N}=await fetchWithTransientRetry(()=>fetch(Q,{method:`PUT`,headers:S,body:he}),{log:t=>ge.error(`gjsify publish: PUT ${X.name}@${X.version}: ${t}`),...t.putRetry});return N>0&&(_e=!0),C},ve=await withOtpRetry(doPut,Y,{seedFirstAttempt:t.seedOtpFirst});if(W){ge.error(` response: ${ve.status} ${ve.statusText}`);let t=await ve.clone().text().catch(()=>``);t&&ge.error(` body: ${t.slice(0,300)}`)}let readBack=async()=>{let n=t.verifyBudgetMs??6e5;if(n<=0)return;let S=budgetForPayload(n,he.length);return verifyPublishedVersion({registry:oe,name:X.name,version:X.version,budgetMs:S,authorization:le.authorization,log:W?t=>ge.error(t):void 0})};if(await isOtpChallenge(ve))return{ok:!1,action:`otp-required`,name:X.name,version:X.version,status:ve.status};if(ve.ok){let t=await readBack();return t?.confirmed&&W&&ge.error(` read-back: confirmed after ${t.attempts} probe(s) in ${t.elapsedMs} ms`),t&&!t.confirmed?{ok:!1,action:`publish-unconfirmed`,claim:`accepted`,name:X.name,version:X.version,registry:oe,putStatus:ve.status,putStatusText:ve.statusText,putUrl:Q,payloadBytes:he.length,readback:t,classification:await recordUnserved({ledgerPath:fe,registry:oe,name:X.name,version:X.version,verdict:t.verdict,statusToken:statusTokenFromEnv(process.env)})}:(markHeldPublished(fe,X.name,X.version),{ok:!0,action:`published`,name:X.name,version:X.version,filename:X.filename,size:X.size,integrity:X.integrity,tag:S,registry:oe,readback:t})}let ye=await ve.text().catch(()=>`<no body>`);if(acceptsRepublish(ve.status,ye,F,_e)){let t=await readBack();return t&&!t.confirmed?{ok:!1,action:`publish-unconfirmed`,claim:`already-published`,name:X.name,version:X.version,registry:oe,putStatus:ve.status,putStatusText:ve.statusText,putUrl:Q,payloadBytes:he.length,readback:t,classification:await recordUnserved({ledgerPath:fe,registry:oe,name:X.name,version:X.version,verdict:t.verdict,statusToken:statusTokenFromEnv(process.env)})}:(markHeldPublished(fe,X.name,X.version),{ok:!0,action:`republish-tolerated`,name:X.name,version:X.version,status:ve.status,registry:oe,readback:t})}if(ve.status===404&&me===`token`&&is404DiagnosticCandidate(ye)){let t=await diagnose404({packageName:X.name,version:X.version,registry:oe,npmrc:ie});if(t.reason!==`unknown`)return{ok:!1,action:`diagnostic`,name:X.name,version:X.version,status:404,diag:t}}return{ok:!1,action:`error`,name:X.name,version:X.version,status:ve.status,statusText:ve.statusText,text:ye}}function describeVerification(t,n){if(!t?.confirmed)return{verified:!1,clause:`(UNVERIFIED — read-back disabled by --verify-timeout 0)`,json:null};let S=(t.elapsedMs/1e3).toFixed(1);return{verified:!0,clause:`(verified on ${n} — ${t.attempts} probe(s), ${S}s)`,json:{registry:n,verdict:t.verdict,probes:t.attempts,elapsedMs:t.elapsedMs,tarball:t.last.state===`present`?t.last.tarball:null}}}function warnUnverified(t,n,S){process.env.GITHUB_ACTIONS&&process.stderr.write(`::warning title=Publish unverified::${t}@${n} was published with the read-back disabled (--verify-timeout 0) — nothing confirmed that ${S} serves it\n`)}function reportPublishOutcome(t,n,S=!1){switch(t.action){case`published`:{let S=describeVerification(t.readback,t.registry),C={ok:!0,name:t.name,version:t.version,filename:t.filename,size:t.size,integrity:t.integrity,tag:t.tag,registry:t.registry,verified:S.verified,verification:S.json};n?process.stdout.write(`${JSON.stringify(C,null,2)}\n`):process.stdout.write(`+ ${t.name}@${t.version} ${S.clause}\n`),S.verified||warnUnverified(t.name,t.version,t.registry);return}case`held-unpublished-dependency`:{let C=summariseReasons(t.reasons);return n?process.stdout.write(`${JSON.stringify({ok:!1,action:`held-unpublished-dependency`,name:t.name,version:t.version,registry:t.registry,reasons:t.reasons,deferred:S},null,2)}\n`):process.stderr.write(`~ ${t.name}@${t.version} (HELD — not published: ${C})\n`),process.env.GITHUB_ACTIONS&&process.stderr.write(`::warning title=Package held::${t.name}@${t.version} was NOT published: ${C}\n`),S?void 0:process.exit(1)}case`publish-unconfirmed`:{let C=`${formatUnconfirmedPublish(t)}\n state: ${describeClass(t.classification.cls)} — ${t.classification.detail}`;if(n?process.stdout.write(`${JSON.stringify({ok:!1,action:`publish-unconfirmed`,name:t.name,version:t.version,registry:t.registry,claim:t.claim,putStatus:t.putStatus,probes:t.readback.attempts,elapsedMs:t.readback.elapsedMs,readbackUrl:t.readback.url,readbackState:t.readback.last.state,verdict:t.readback.verdict,verdictDetail:t.readback.verdictDetail,recordedAt:t.readback.recordedAt??null,deferred:S,class:t.classification.cls,classDetail:t.classification.detail},null,2)}\n`):process.stderr.write(`${C}\n`),S){if(process.env.GITHUB_ACTIONS){let n=t.claim===`already-published`?`was reported already published`:`was accepted`;process.stderr.write(`::warning title=Publish unconfirmed::${t.name}@${t.version} ${n} (HTTP ${t.putStatus}) but did not resolve on ${t.registry} within ${(t.readback.elapsedMs/1e3).toFixed(1)}s [${t.readback.verdict}; ${describeClass(t.classification.cls)}] — the release-closure job must confirm it
1224
- `)}return}return process.exit(1)}case`republish-tolerated`:{let S=describeVerification(t.readback,t.registry),C={ok:!0,action:`republish-tolerated`,name:t.name,version:t.version,status:t.status,registry:t.registry,verified:S.verified,verification:S.json};n?process.stdout.write(`${JSON.stringify(C,null,2)}\n`):process.stdout.write(`= ${t.name}@${t.version} (already published, tolerated) ${S.clause}\n`),S.verified||warnUnverified(t.name,t.version,t.registry);return}case`skipped-untrusted-new`:n?process.stdout.write(`${JSON.stringify({ok:!0,action:`skipped-untrusted-new`,name:t.name,version:t.version,reason:`no-trusted-publisher`},null,2)}\n`):process.stdout.write(`~ ${t.name}@${t.version} (skipped — no Trusted Publisher on npm, see AGENTS.md "New @gjsify/* package: first-publish + Trusted Publisher bootstrap")\n`);return;case`blocked-missing-dependency`:{let S=t.missing.map(t=>`${t.block}.${t.name}@${t.spec}`).join(`, `);return n?process.stdout.write(`${JSON.stringify({ok:t.ok,action:`blocked-missing-dependency`,name:t.name,version:t.version,registry:t.registry,tolerated:t.tolerated,missing:t.missing},null,2)}\n`):process.stdout.write(`~ ${t.name}@${t.version} (NOT published — ${t.missing.length} required pin(s) name a package ${t.registry} does not have: ${S})\n`),ge.error(`gjsify publish: every consumer install of ${t.name} would fail with \`npm error 404\`, on every package manager — a required edge is not skippable. Bootstrap the target first (docs/publishing.md § New \`@gjsify/*\` package), then re-run. See #1713.`),t.tolerated?void 0:process.exit(1)}case`otp-required`:return ge.error("gjsify publish: npm requires a 2FA one-time code — re-run with `--otp <code>`"),process.exit(1);case`oidc-failed`:return handleOidcFailure(t.error,t.name,n),process.exit(1);case`oidc-no-token`:{let S=t.error instanceof Error?t.error.message:String(t.error);return ge.error(`gjsify publish: OIDC token exchange failed for ${t.name} (${S}) and no fallback npm token is configured — refusing to publish without credentials.`),n&&process.stdout.write(`${JSON.stringify({ok:!1,name:t.name,version:t.version,error:`oidc-failed-no-token`},null,2)}\n`),process.exit(1)}case`diagnostic`:return n?process.stdout.write(`${JSON.stringify({ok:!1,name:t.name,version:t.version,status:404,diagnostic:t.diag.reason,username:t.diag.username},null,2)}\n`):process.stderr.write(`${t.diag.message}\n`),process.exit(1);case`error`:return ge.error(`gjsify publish: ${t.name}@${t.version} — ${t.status} ${t.statusText}`),ge.error(t.text),process.exit(1)}}async function packWorkspaceToBytes(t){let n=In(tmpdir(),`gjsify-publish-${process.pid}-${Date.now()}`),S=await packWorkspace(t,{destination:n,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(()=>(ef(),Qd))).rmSync(S.absolutePath)}catch{}try{(await Promise.resolve().then(()=>(ef(),Qd))).rmdirSync(n)}catch{}return C}async function loadRewrittenManifest(t,n){let S=In(tmpdir(),`gjsify-publish-manifest-${process.pid}-${Date.now()}`),C=await packWorkspace(t,{destination:S,dryRun:!1}),{rmSync:N}=await Promise.resolve().then(()=>(ef(),Qd));if(!C.absolutePath)throw Error(`gjsify publish: pack did not produce a file`);let{gunzip:F,parseTar:I}=await Promise.resolve().then(()=>(KR(),GR)),H=new Uint8Array(readFileSync(C.absolutePath));N(S,{recursive:!0,force:!0,maxRetries:3,retryDelay:100});let W=await F(H);for(let t of I(W))if(t.name===`package/package.json`&&t.body)return JSON.parse(new TextDecoder().decode(t.body));return n}function buildPublishPayload(t){let{pkg:n,tag:S,access:C,tarballBytes:N,tarballUrl:F,packed:I,provenance:H}=t,W={...n,_id:`${I.name}@${I.version}`,dist:{integrity:I.integrity,shasum:I.shasum,tarball:F}};H&&(W._hasShrinkwrap=!1);let q={_id:I.name,name:I.name,description:typeof n.description==`string`?n.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&&(q.access=C),q}function handleOidcFailure(t,n,S){if(t instanceof OidcUnavailableError){let C=`gjsify publish: OIDC not available — ${t.message}`;S?process.stdout.write(`${JSON.stringify({ok:!1,name:n,error:`oidc-unavailable`,reason:t.reason,message:t.message})}\n`):process.stderr.write(`${C}\n`);return}if(t instanceof OidcExchangeError){let C=t.status===401||t.status===403?`npm rejected the OIDC exchange (${t.status}) — check that ${n} has a Trusted Publisher configured at https://www.npmjs.com/package/${encodeURIComponent(n)}/access pointing at this workflow.`:t.message;if(S)process.stdout.write(`${JSON.stringify({ok:!1,name:n,error:`oidc-exchange`,status:t.status,body:t.body,claims:t.claims,message:t.message})}\n`);else if(process.stderr.write(`✗ ${n}: ${C}\n`),t.body&&process.stderr.write(` ↳ npm said: ${t.body.slice(0,300)}\n`),t.claims){let n=t.claims,S=[`aud`,`iss`,`repository`,`repository_owner`,`workflow_ref`,`job_workflow_ref`,`ref`,`environment`,`sub`].filter(t=>n[t]!==void 0).map(t=>`${t}=${JSON.stringify(n[t])}`).join(`, `);S&&process.stderr.write(` ↳ JWT claims npm received: ${S}\n`)}return}let C=t instanceof Error?t.message:String(t);S?process.stdout.write(`${JSON.stringify({ok:!1,name:n,error:`unknown`,message:C})}\n`):process.stderr.write(`✗ ${n}: ${C}\n`)}var aK,oK=__esmMin(()=>{_e(),ef(),$g(),qn(),jW(),gh(),yh(),TG(),kG(),AG(),LG(),BG(),GG(),HG(),pB(),iK(),QG(),OG(),aK={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:t=>t.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(`verify-timeout`,{description:"Seconds to keep asking the registry for the just-published version before giving up. npm answers 2xx to a write it has only ACCEPTED: in the v0.46.0 release 19 of 199 packages were recorded 56-252s after their 2xx and one was never recorded at all, so a shorter window turns normal queueing into a false red. `0` disables the read-back — for a registry with no packument read path; the success line then reads `UNVERIFIED` and says so, because a publish nothing checked must never look like one that was checked.",type:`number`,default:NG/1e3}).option(`verify-defer`,{description:"Report an unconfirmed read-back and exit 0 instead of 1. ONLY for a caller that re-checks the same set afterwards — `gjsify run npm:publish` passes it because `scripts/verify-published-closure.mjs` sweeps the whole roster at the end of release.yml. Everywhere else an unconfirmed publish must fail the job that made it.",type:`boolean`,default:!1}).option(`hold-timeout`,{description:'Seconds to wait for an intra-repo dependency pin whose exact version the registry does not serve (yet) before HOLDING this package instead of publishing it. A version npm accepted but never serves (status "validating") would make every dependent uninstallable; the write lag measured on v0.46.0 reaches 252s, hence the default. `0` probes once and holds without waiting. A hold exits 1, or 0 under `--verify-defer`.',type:`number`,default:UG/1e3}).option(`report-ledger`,{description:"Print the job-summary markdown for the publish ledger named by $GJSIFY_PUBLISH_LEDGER (versions npm accepted but does not serve, packages held because of them, the recovery command) and exit. Pair with `--ref <tag>`.",type:`boolean`,default:!1}).option(`fail-on-unsettled`,{description:`With --report-ledger: exit 1 when any package is still HELD or any accepted version is still unserved, naming them and the recovery command. The end-of-sweep gate: a sweep that left something behind must be red, not a warning.`,type:`boolean`,default:!1}).option(`held-names`,{description:`Print, one per line, the packages the ledger shows HELD and not yet published, and exit. Feeds the held-package second pass (.github/scripts/retry-held-publish.sh).`,type:`boolean`,default:!1}).option(`settle-ledger`,{description:`Wait up to --settle-timeout for every version the ledger records as accepted-but-unserved to be served (the longer read-back the sweep defers), record each as served, and exit.`,type:`boolean`,default:!1}).option(`settle-timeout`,{description:`With --settle-ledger: seconds to wait. Versions poll concurrently, so this is the longest lag tolerated, not a sum. Default 600 (the fatal read-back default; measured lags reach 368 s).`,type:`number`,default:NG/1e3}).option(`ref`,{description:`With --report-ledger: the git ref to put in the printed recovery command.`,type:`string`}).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 t=>{let n=Nn(t.path??process.cwd()),S=t.tag??`latest`,C=t.access,N=t.otp,F=t[`tolerate-republish`]===!0,I=t[`tolerate-untrusted-new`]===!0,H=t[`verify-timeout`]??6e5/1e3;if(!Number.isFinite(H)||H<0)return ge.error(`gjsify publish: --verify-timeout must be a non-negative number of seconds, got ${JSON.stringify(t[`verify-timeout`])}`),process.exit(2);let W=Math.round(H*1e3),q=t[`verify-defer`]===!0,Y=t.provenance===!0,X=t[`dry-run`]===!0,Z=t[`check-trusted`]===!0,te=t.trusted,ne=!!process.env.GJSIFY_PUBLISH_DEBUG,re=process.env.GJSIFY_PUBLISH_LEDGER;if(t[`held-names`]===!0){for(let t of pendingEntries(readLedger(re)).held)process.stdout.write(`${t.name}\n`);return}if(t[`settle-ledger`]===!0){let n=t[`settle-timeout`]??6e5/1e3;if(!Number.isFinite(n)||n<0)return ge.error(`gjsify publish: --settle-timeout must be a non-negative number of seconds, got ${JSON.stringify(t[`settle-timeout`])}`),process.exit(2);let S=await loadNpmrc(process.cwd()),C=await settleUnserved({entries:readLedger(re),ledgerPath:re,registryFor:t=>(process.env.npm_config_registry??registryFor(t,S)??lh).replace(/\/$/,``),budgetMs:Math.max(1,Math.round(n*1e3)),log:ne?t=>ge.error(t):void 0});for(let t of C)process.stdout.write(`served after settling: ${t}\n`);return}if(t[`report-ledger`]===!0){let n=readLedger(re),S=renderLedgerSummary(n,t.ref??`<tag>`);if(S&&process.stdout.write(`${S}\n`),t[`fail-on-unsettled`]===!0){let{unserved:S,held:C}=pendingEntries(n),N=[...new Set([...C,...S].map(t=>t.name))];if(N.length>0){let n=t.ref??`<tag>`;return ge.error(`gjsify publish: ${C.length} package(s) still HELD and ${S.length} version(s) still unserved after the second pass: ${N.join(` `)}\n recover: re-run THIS run (\`gh run rerun <run-id>\` — keeps the version; never a new dispatch on the next channel, which mints a new one), or for a release: gh workflow run release.yml --ref ${n} -f skip_publish=false -f only='${N.join(` `)}'`),process.exit(1)}}return}let ie=t[`hold-timeout`]??3e5/1e3;if(!Number.isFinite(ie)||ie<0)return ge.error(`gjsify publish: --hold-timeout must be a non-negative number of seconds, got ${JSON.stringify(t[`hold-timeout`])}`),process.exit(2);if(Y&&ge.warn(`gjsify publish: --provenance recorded but not signed (no sigstore integration yet).`),Z){let S=In(n,`package.json`),C=JSON.parse(readFileSync(S,`utf-8`));if(typeof C.name!=`string`)return process.stderr.write(`gjsify publish --check-trusted: ${S} has no \`name\` field\n`),process.exit(2);if(C.private===!0){let n={ok:!0,action:`check-trusted`,name:C.name,skipped:`private`};t.json?process.stdout.write(`${JSON.stringify(n)}\n`):process.stdout.write(`- ${C.name}: skipped (private package)\n`);return}let N=await loadNpmrc(n),F=process.env.npm_config_registry??registryFor(C.name,N)??lh;try{await getNpmTrustedToken({packageName:C.name,registry:F,log:ne?t=>ge.error(t):void 0});let n={ok:!0,action:`check-trusted`,name:C.name,registry:F};t.json?process.stdout.write(`${JSON.stringify(n)}\n`):process.stdout.write(`✓ ${C.name}: trusted publisher OK\n`);return}catch(n){handleOidcFailure(n,C.name,t.json===!0);return}}if(X){let S=await packWorkspace(n,{dryRun:!0,lifecycleScripts:[`prepublishOnly`,`prepack`],lifecycleStdio:t.json?`inherit-stderr`:`inherit`}),C={ok:!0,action:`dry-run`,name:S.name,version:S.version,filename:S.filename,size:S.size,shasum:S.shasum,integrity:S.integrity};t.json?process.stdout.write(`${JSON.stringify(C,null,2)}\n`):process.stdout.write(`+ ${S.name}@${S.version} (dry-run, ${S.size} bytes, ${S.entryCount} files)\n`);return}let ae=!!(process.stdin.isTTY&&process.stdout.isTTY),oe=await loadNpmrc(n),Q;try{Q=JSON.parse(readFileSync(In(n,`package.json`),`utf-8`)).name}catch{}let se=process.env.npm_config_registry??(Q?registryFor(Q,oe):void 0)??oe.registry??lh,ce=new OtpProvider(N,ae?promptLine:async()=>``,{registry:se});reportPublishOutcome(await publishWorkspace({wsDir:n,tag:S,access:C,provenance:Y,tolerate:F,tolerateUntrustedNew:I,trustedFlag:te,verbose:ne,json:t.json===!0,otpProvider:ce,seedOtpFirst:N!==void 0,verifyBudgetMs:W,holdWaitMs:Math.min(Math.round(ie*1e3),remainingHoldDeadlineMs())}),t.json===!0,q)}}});function buildTree(t){let n={name:`#root`,attrs:{},nodes:[]},S=[n];for(let n of scanXml(t)){let t=S[S.length-1];if(n.kind===`text`)t.nodes.push(n.text);else if(n.kind===`open`){let C={name:normName(n.name),attrs:n.attributes,nodes:[]};t.nodes.push(C),n.selfClosing||S.push(C)}else S.length>1&&S.pop()}return n}function inlineMarkdown(t){let n=``;for(let S of t.nodes){if(typeof S==`string`){n+=S;continue}if(isTranslation(S))continue;let t=inlineMarkdown(S),C=sK[S.name];C===void 0?S.name===`a`&&S.attrs.href?n+=`[${t}](${S.attrs.href})`:n+=t:n+=t.trim()===``?t:`${C}${t.trim()}${C}`}return n}function parseBlocks(t){let n=[];for(let S of elements(t))if(!isTranslation(S)){if(S.name===`p`){let t=clean(inlineMarkdown(S));t&&n.push({p:t})}else if(S.name===`ul`||S.name===`ol`){let t=elements(S,`li`).filter(t=>!isTranslation(t)).map(t=>clean(inlineMarkdown(t))).filter(Boolean);t.length&&n.push({ul:t})}}return n}function parseMetainfoReleases(t){let n=elements(buildTree(t),`component`)[0];if(!n)throw Error(`metainfo root must be <component>`);let S=elements(n,`releases`)[0];return S?elements(S,`release`).map(t=>{let n=t.attrs.timestamp,S=t.attrs.date??(n?new Date(Number(n)*1e3).toISOString().slice(0,10):``),C=elements(t,`description`).find(t=>!isTranslation(t)),N=C?parseBlocks(C):[];return{version:t.attrs.version??``,date:S,...N.length?{description:N}:{}}}):[]}var normName,elements,isTranslation,sK,clean,cK=__esmMin(()=>{Ye(),normName=t=>t.startsWith(`_`)?t.slice(1):t,elements=(t,n)=>t.nodes.filter(t=>typeof t!=`string`&&(n===void 0||t.name===n)),isTranslation=t=>t.attrs[`xml:lang`]!==void 0,sK={em:`*`,i:`*`,strong:`**`,b:`**`,code:"`",tt:"`"},clean=t=>t.replace(/\s+/g,` `).trim()});function descriptionToMarkdown(t){let n=typeof t==`string`?stringToBlocks(t):t,S=[];for(let t of n)if(`p`in t){let n=t.p.trim().replace(/\s+/g,` `);n&&S.push(n)}else{let n=t.ul.map(t=>(typeof t==`string`?t:t.item).trim()).filter(Boolean);n.length&&S.push(n.map(t=>`- ${t}`).join(`
1220
+ `,done:!0,interrupt:!1}:n===XG?{buf:t,echo:`
1221
+ `,done:!1,interrupt:!0}:n===ZG||n===QG?t.length>0?{buf:t.slice(0,-1),echo:`\b \b`,done:!1,interrupt:!1}:{buf:t,echo:``,done:!1,interrupt:!1}:n>=` `?{buf:t+n,echo:S?`*`:n,done:!1,interrupt:!1}:{buf:t,echo:``,done:!1,interrupt:!1}}async function runRawSession(t){let n=process.stdin,S=process.stdout,C=null,cleanup=()=>{n.removeListener(`data`,onData);try{n.setRawMode(!1)}catch{}typeof n.pause==`function`&&n.pause()},onData=t=>{let n=typeof t==`string`?t:t.toString(`utf-8`);for(let t of n){if(!C)continue;let n=applyKey(C.buf,t,C.mask);if(C.buf=n.buf,n.echo&&S.write(n.echo),n.interrupt)return cleanup(),process.exit(130);if(n.done){let{resolve:t}=C;C=null,t(n.buf)}}};n.setRawMode(!0),typeof n.resume==`function`&&n.resume(),n.setEncoding(`utf-8`),n.on(`data`,onData);let read=(t,n)=>new Promise(N=>{beginPrompt(),S.write(t),C={mask:n,buf:``,resolve:t=>{endPrompt(),N(t)}}});try{return await t(read)}finally{cleanup()}}function readLine(){return new Promise(t=>{let n=``,onData=S=>{n+=typeof S==`string`?S:S.toString(`utf-8`);let C=n.search(/[\r\n]/);C>=0&&(cleanup(),t(n.slice(0,C)))},onEnd=()=>{cleanup(),t(n.replace(/\r$/,``).trim())},cleanup=()=>{process.stdin.removeListener(`data`,onData),process.stdin.removeListener(`end`,onEnd)};process.stdin.setEncoding(`utf-8`),typeof process.stdin.isPaused==`function`&&process.stdin.isPaused()&&process.stdin.resume(),process.stdin.on(`data`,onData),process.stdin.once(`end`,onEnd)})}async function promptLine(t){if(!isTtyStdin()){beginPrompt(),process.stdout.write(t);try{return await readLine()}finally{endPrompt()}}return runRawSession(n=>n(t,!1))}async function promptCredentials(t){if(!isTtyStdin()){let n=t;n||=(process.stdout.write(`Username: `),await readLine()),process.stdout.write(`Password: `);let S=await readLine();return{username:n,password:S}}return runRawSession(async n=>({username:t??await n(`Username: `,!1),password:await n(`Password: `,!0)}))}var XG,ZG,QG,$G=__esmMin(()=>{YG(),XG=``,ZG=``,QG=`\b`});function isOtpCacheEnabled(){let t=process.env[eK];return!(t===`1`||t===`true`||t===`yes`)}function normalizeRegistry(t){return t.endsWith(`/`)?t.slice(0,-1):t}function cacheBaseDir(t){if(t?.dir)return t.dir;let n=process.env.XDG_RUNTIME_DIR;return In(n&&n.length>0?n:tmpdir(),tK)}function cacheFileFor(t,n){let S=normalizeRegistry(t).replace(/[^a-zA-Z0-9]+/g,`-`).replace(/^-+|-+$/g,``).slice(0,120);return In(cacheBaseDir(n),`otp-${S||`default`}.json`)}function readCachedOtp(t,n){if(!isOtpCacheEnabled())return;let S=n?.now??Date.now(),C=cacheFileFor(t,n);try{if(!existsSync(C))return;let n=JSON.parse(readFileSync(C,`utf8`));if(!n||typeof n.otp!=`string`||typeof n.expiresAt!=`number`){deleteCacheFile(C);return}if(n.registry!==normalizeRegistry(t))return;if(S>=n.expiresAt){deleteCacheFile(C);return}return n.otp.length>0?n.otp:void 0}catch{deleteCacheFile(C);return}}function writeCachedOtp(t,n,S){if(!isOtpCacheEnabled()||!n||n.length===0)return;let C=S?.now??Date.now(),N=S?.ttlMs??3e4;try{mkdirSync(cacheBaseDir(S),{recursive:!0,mode:448});let F=cacheFileFor(t,S),I={otp:n,expiresAt:C+N,registry:normalizeRegistry(t)};writeFileSync(F,JSON.stringify(I),{mode:384}),chmodSync(F,384)}catch{}}function clearCachedOtp(t,n){deleteCacheFile(cacheFileFor(t,n))}function deleteCacheFile(t){try{existsSync(t)&&rmSync(t,{force:!0})}catch{}}var eK,tK,nK=__esmMin(()=>{ef(),$g(),qn(),eK=`GJSIFY_NO_OTP_CACHE`,tK=`gjsify-otp`});async function isOtpChallenge(t){if(t.status!==401)return!1;if((t.headers.get(`www-authenticate`)??``).toLowerCase().includes(`otp`))return!0;let n=await t.clone().text().catch(()=>``);return/one-time pass/i.test(n)||/\bEOTP\b/.test(n)}async function withOtpRetry(t,n,S={}){let C=S.maxPrompts??2,N=S.question,F=n.current(),I=S.seedFirstAttempt===!0&&F!==void 0,H=n.epoch(),W=await t(I?F:void 0);if(!await isOtpChallenge(W))return W;if(I&&n.invalidate(H),!I&&n.current()!==void 0){if(H=n.epoch(),W=await t(n.current()),!await isOtpChallenge(W))return W;n.invalidate(H)}for(let S=0;S<C;S++){let S=await n.refresh(N,H);if(!S||(H=n.epoch(),W=await t(S),!await isOtpChallenge(W)))return W;n.invalidate(H)}return W}var rK,iK,OtpProvider,aK=__esmMin(()=>{$G(),nK(),rK=`This operation requires a one-time password.
1222
+ Enter OTP: `,iK=`The previous one-time password is no longer valid (npm codes last about 30 seconds).
1223
+ Enter a NEW OTP: `,OtpProvider=class{cached;promptFn;registry;generation=0;pending;constructor(t,n=promptLine,S={}){this.promptFn=n,this.registry=S.registry;let C=t&&t.length>0?t:void 0;C?(this.cached=C,this.registry&&writeCachedOtp(this.registry,C)):this.cached=this.registry?readCachedOtp(this.registry):void 0}current(){return this.cached}epoch(){return this.generation}async refresh(t,n){if(n!==void 0&&this.generation>n&&this.cached)return this.cached;if(this.pending)return this.pending;this.pending=this.promptOnce(t??(this.generation>0?iK:rK));try{return await this.pending}finally{this.pending=void 0}}async promptOnce(t){let n=(await this.promptFn(t)).trim();return n&&(this.cached=n,this.generation++,this.registry&&writeCachedOtp(this.registry,n)),n}invalidate(t){t!==void 0&&this.generation!==t||(this.cached=void 0,this.registry&&clearCachedOtp(this.registry))}}});function remainingHoldDeadlineMs(){let t=Number(process.env.GJSIFY_HOLD_DEADLINE);return Number.isFinite(t)&&t>0?Math.max(0,t-Date.now()):1/0}function acceptsRepublish(t,n,S,C){return(t===409||t===403&&/previously published/i.test(n))&&(S||C)}async function publishWorkspace(t){let{wsDir:n,tag:S,access:C,provenance:N,tolerate:F,tolerateUntrustedNew:I,trustedFlag:H,verbose:W,json:q,otpProvider:Y}=t,X=await packWorkspace(n,{dryRun:!0,lifecycleScripts:[`prepublishOnly`,`prepack`],lifecycleStdio:q?`inherit-stderr`:`inherit`}),Z=await packWorkspaceToBytes(n),te=readFileSync(In(n,`package.json`),`utf-8`),ne=JSON.parse(te),re=await loadRewrittenManifest(n,ne),ie=await loadNpmrc(n),ae=t.registry??process.env.npm_config_registry??registryFor(X.name,ie)??lh,oe=ae.endsWith(`/`)?ae.slice(0,-1):ae,Q=`${oe}/${escapePackageName(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:Z,tarballUrl:`${oe}/${X.name}/-/${se}`,packed:{...X,wireFilename:se},provenance:N}),le=buildPublishHeaders(Q,{npmrc:ie}),ue=new Set(t.assumePresent??[]),de=collectWorkspacePins(ne,re).filter(t=>!ue.has(t.name));if(de.length>0){let t=await Promise.all(de.map(async t=>({pin:t,presence:await probePackageName({registry:ae,name:t.name,authorization:le.authorization})}))),n=[];for(let{pin:S,presence:C}of t){if(C.state===`present`)continue;let t=`${S.block}.${S.name}@${S.spec}`;if(C.state===`unknown`){ge.error(`gjsify publish: could not establish whether ${S.name} exists (${C.detail}) — not blocking on ${t}`);continue}if(S.block!==`dependencies`){ge.error(`gjsify publish: ${t} names a package ${ae} does not have — npm installs around it, Yarn (\`YN0035\`) does not`);continue}n.push(S)}if(n.length>0)return{ok:I,action:`blocked-missing-dependency`,name:X.name,version:X.version,registry:ae,tolerated:I,missing:n}}let fe=process.env.GJSIFY_PUBLISH_LEDGER;if(de.length>0){let n=await findUnavailablePins({registry:oe,pins:de,ledger:readLedger(fe),ledgerPath:fe,authorization:le.authorization,statusToken:statusTokenFromEnv(process.env),waitBudgetMs:t.holdWaitMs??3e5,log:W?t=>ge.error(t):void 0});for(let t of n.filter(t=>!holdsPublish(t)))ge.error(`gjsify publish: ${t.block}.${t.name}@${t.version} is not served (${t.detail}) — optional edge, publishing anyway`);let S=n.filter(holdsPublish);if(S.length>0)return appendLedger(fe,{ev:`held`,name:X.name,version:X.version,reasons:S}),{ok:!1,action:`held-unpublished-dependency`,name:X.name,version:X.version,registry:oe,reasons:S}}let pe=H===!0||H===void 0&&hasGithubOidcEnv()&&!process.env.NODE_AUTH_TOKEN,me=`token`;if(pe)try{let{token:t,audience:n}=await getNpmTrustedToken({packageName:X.name,registry:ae,log:W?t=>ge.error(t):void 0});le.authorization=`Bearer ${t}`,me=`oidc`,W&&ge.error(`gjsify publish: OIDC token obtained (audience=${n})`)}catch(t){if(t instanceof OidcExchangeError&&t.status===404&&/package not found/i.test(t.body)&&I)return{ok:!0,action:`skipped-untrusted-new`,name:X.name,version:X.version};if(H===!0)return{ok:!1,action:`oidc-failed`,name:X.name,version:X.version,error:t};if(!le.authorization)return{ok:!1,action:`oidc-no-token`,name:X.name,version:X.version,error:t};if(W){let n=t instanceof Error?t.message:String(t);ge.error(`gjsify publish: OIDC auto-detect failed (${n}) — falling back to token auth`)}}W&&(ge.error(`gjsify publish: PUT ${Q} (${X.name}@${X.version})`),ge.error(` auth-mode: ${me}`),ge.error(` authorization: ${le.authorization?`(set)`:`(none)`}`),ge.error(` payload size: ${JSON.stringify(ce).length} bytes`));let he=JSON.stringify(ce),_e=!1,doPut=async n=>{let S={...le};n&&(S[`npm-otp`]=n,S[`npm-auth-type`]=`legacy`);let{response:C,retried:N}=await fetchWithTransientRetry(()=>fetch(Q,{method:`PUT`,headers:S,body:he}),{log:t=>ge.error(`gjsify publish: PUT ${X.name}@${X.version}: ${t}`),...t.putRetry});return N>0&&(_e=!0),C},ve=await withOtpRetry(doPut,Y,{seedFirstAttempt:t.seedOtpFirst});if(W){ge.error(` response: ${ve.status} ${ve.statusText}`);let t=await ve.clone().text().catch(()=>``);t&&ge.error(` body: ${t.slice(0,300)}`)}let readBack=async()=>{let n=t.verifyBudgetMs??6e5;if(n<=0)return;let S=budgetForPayload(n,he.length);return verifyPublishedVersion({registry:oe,name:X.name,version:X.version,budgetMs:S,authorization:le.authorization,log:W?t=>ge.error(t):void 0})};if(await isOtpChallenge(ve))return{ok:!1,action:`otp-required`,name:X.name,version:X.version,status:ve.status};if(ve.ok){let t=await readBack();return t?.confirmed&&W&&ge.error(` read-back: confirmed after ${t.attempts} probe(s) in ${t.elapsedMs} ms`),t&&!t.confirmed?{ok:!1,action:`publish-unconfirmed`,claim:`accepted`,name:X.name,version:X.version,registry:oe,putStatus:ve.status,putStatusText:ve.statusText,putUrl:Q,payloadBytes:he.length,readback:t,classification:await recordUnserved({ledgerPath:fe,registry:oe,name:X.name,version:X.version,verdict:t.verdict,statusToken:statusTokenFromEnv(process.env)})}:(markHeldPublished(fe,X.name,X.version),{ok:!0,action:`published`,name:X.name,version:X.version,filename:X.filename,size:X.size,integrity:X.integrity,tag:S,registry:oe,readback:t})}let ye=await ve.text().catch(()=>`<no body>`);if(acceptsRepublish(ve.status,ye,F,_e)){let t=await readBack();return t&&!t.confirmed?{ok:!1,action:`publish-unconfirmed`,claim:`already-published`,name:X.name,version:X.version,registry:oe,putStatus:ve.status,putStatusText:ve.statusText,putUrl:Q,payloadBytes:he.length,readback:t,classification:await recordUnserved({ledgerPath:fe,registry:oe,name:X.name,version:X.version,verdict:t.verdict,statusToken:statusTokenFromEnv(process.env)})}:(markHeldPublished(fe,X.name,X.version),{ok:!0,action:`republish-tolerated`,name:X.name,version:X.version,status:ve.status,registry:oe,readback:t})}if(ve.status===404&&me===`token`&&is404DiagnosticCandidate(ye)){let t=await diagnose404({packageName:X.name,version:X.version,registry:oe,npmrc:ie});if(t.reason!==`unknown`)return{ok:!1,action:`diagnostic`,name:X.name,version:X.version,status:404,diag:t}}return{ok:!1,action:`error`,name:X.name,version:X.version,status:ve.status,statusText:ve.statusText,text:ye}}function describeVerification(t,n){if(!t?.confirmed)return{verified:!1,clause:`(UNVERIFIED — read-back disabled by --verify-timeout 0)`,json:null};let S=(t.elapsedMs/1e3).toFixed(1);return{verified:!0,clause:`(verified on ${n} — ${t.attempts} probe(s), ${S}s)`,json:{registry:n,verdict:t.verdict,probes:t.attempts,elapsedMs:t.elapsedMs,tarball:t.last.state===`present`?t.last.tarball:null}}}function warnUnverified(t,n,S){process.env.GITHUB_ACTIONS&&process.stderr.write(`::warning title=Publish unverified::${t}@${n} was published with the read-back disabled (--verify-timeout 0) — nothing confirmed that ${S} serves it\n`)}function reportPublishOutcome(t,n,S=!1){switch(t.action){case`published`:{let S=describeVerification(t.readback,t.registry),C={ok:!0,name:t.name,version:t.version,filename:t.filename,size:t.size,integrity:t.integrity,tag:t.tag,registry:t.registry,verified:S.verified,verification:S.json};n?process.stdout.write(`${JSON.stringify(C,null,2)}\n`):process.stdout.write(`+ ${t.name}@${t.version} ${S.clause}\n`),S.verified||warnUnverified(t.name,t.version,t.registry);return}case`held-unpublished-dependency`:{let C=summariseReasons(t.reasons);return n?process.stdout.write(`${JSON.stringify({ok:!1,action:`held-unpublished-dependency`,name:t.name,version:t.version,registry:t.registry,reasons:t.reasons,deferred:S},null,2)}\n`):process.stderr.write(`~ ${t.name}@${t.version} (HELD — not published: ${C})\n`),process.env.GITHUB_ACTIONS&&process.stderr.write(`::warning title=Package held::${t.name}@${t.version} was NOT published: ${C}\n`),S?void 0:process.exit(1)}case`publish-unconfirmed`:{let C=`${formatUnconfirmedPublish(t)}\n state: ${describeClass(t.classification.cls)} — ${t.classification.detail}`;if(n?process.stdout.write(`${JSON.stringify({ok:!1,action:`publish-unconfirmed`,name:t.name,version:t.version,registry:t.registry,claim:t.claim,putStatus:t.putStatus,probes:t.readback.attempts,elapsedMs:t.readback.elapsedMs,readbackUrl:t.readback.url,readbackState:t.readback.last.state,verdict:t.readback.verdict,verdictDetail:t.readback.verdictDetail,recordedAt:t.readback.recordedAt??null,deferred:S,class:t.classification.cls,classDetail:t.classification.detail},null,2)}\n`):process.stderr.write(`${C}\n`),S){if(process.env.GITHUB_ACTIONS){let n=t.claim===`already-published`?`was reported already published`:`was accepted`;process.stderr.write(`::warning title=Publish unconfirmed::${t.name}@${t.version} ${n} (HTTP ${t.putStatus}) but did not resolve on ${t.registry} within ${(t.readback.elapsedMs/1e3).toFixed(1)}s [${t.readback.verdict}; ${describeClass(t.classification.cls)}] — the release-closure job must confirm it
1224
+ `)}return}return process.exit(1)}case`republish-tolerated`:{let S=describeVerification(t.readback,t.registry),C={ok:!0,action:`republish-tolerated`,name:t.name,version:t.version,status:t.status,registry:t.registry,verified:S.verified,verification:S.json};n?process.stdout.write(`${JSON.stringify(C,null,2)}\n`):process.stdout.write(`= ${t.name}@${t.version} (already published, tolerated) ${S.clause}\n`),S.verified||warnUnverified(t.name,t.version,t.registry);return}case`skipped-untrusted-new`:n?process.stdout.write(`${JSON.stringify({ok:!0,action:`skipped-untrusted-new`,name:t.name,version:t.version,reason:`no-trusted-publisher`},null,2)}\n`):process.stdout.write(`~ ${t.name}@${t.version} (skipped — no Trusted Publisher on npm, see AGENTS.md "New @gjsify/* package: first-publish + Trusted Publisher bootstrap")\n`);return;case`blocked-missing-dependency`:{let S=t.missing.map(t=>`${t.block}.${t.name}@${t.spec}`).join(`, `);return n?process.stdout.write(`${JSON.stringify({ok:t.ok,action:`blocked-missing-dependency`,name:t.name,version:t.version,registry:t.registry,tolerated:t.tolerated,missing:t.missing},null,2)}\n`):process.stdout.write(`~ ${t.name}@${t.version} (NOT published — ${t.missing.length} required pin(s) name a package ${t.registry} does not have: ${S})\n`),ge.error(`gjsify publish: every consumer install of ${t.name} would fail with \`npm error 404\`, on every package manager — a required edge is not skippable. Bootstrap the target first (docs/publishing.md § New \`@gjsify/*\` package), then re-run. See #1713.`),t.tolerated?void 0:process.exit(1)}case`otp-required`:return ge.error("gjsify publish: npm requires a 2FA one-time code — re-run with `--otp <code>`"),process.exit(1);case`oidc-failed`:return handleOidcFailure(t.error,t.name,n),process.exit(1);case`oidc-no-token`:{let S=t.error instanceof Error?t.error.message:String(t.error);return ge.error(`gjsify publish: OIDC token exchange failed for ${t.name} (${S}) and no fallback npm token is configured — refusing to publish without credentials.`),n&&process.stdout.write(`${JSON.stringify({ok:!1,name:t.name,version:t.version,error:`oidc-failed-no-token`},null,2)}\n`),process.exit(1)}case`diagnostic`:return n?process.stdout.write(`${JSON.stringify({ok:!1,name:t.name,version:t.version,status:404,diagnostic:t.diag.reason,username:t.diag.username},null,2)}\n`):process.stderr.write(`${t.diag.message}\n`),process.exit(1);case`error`:return ge.error(`gjsify publish: ${t.name}@${t.version} — ${t.status} ${t.statusText}`),ge.error(t.text),process.exit(1)}}async function packWorkspaceToBytes(t){let n=In(tmpdir(),`gjsify-publish-${process.pid}-${Date.now()}`),S=await packWorkspace(t,{destination:n,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(()=>(ef(),Qd))).rmSync(S.absolutePath)}catch{}try{(await Promise.resolve().then(()=>(ef(),Qd))).rmdirSync(n)}catch{}return C}async function loadRewrittenManifest(t,n){let S=In(tmpdir(),`gjsify-publish-manifest-${process.pid}-${Date.now()}`),C=await packWorkspace(t,{destination:S,dryRun:!1}),{rmSync:N}=await Promise.resolve().then(()=>(ef(),Qd));if(!C.absolutePath)throw Error(`gjsify publish: pack did not produce a file`);let{gunzip:F,parseTar:I}=await Promise.resolve().then(()=>(KR(),GR)),H=new Uint8Array(readFileSync(C.absolutePath));N(S,{recursive:!0,force:!0,maxRetries:3,retryDelay:100});let W=await F(H);for(let t of I(W))if(t.name===`package/package.json`&&t.body)return JSON.parse(new TextDecoder().decode(t.body));return n}function buildPublishPayload(t){let{pkg:n,tag:S,access:C,tarballBytes:N,tarballUrl:F,packed:I,provenance:H}=t,W={...n,_id:`${I.name}@${I.version}`,dist:{integrity:I.integrity,shasum:I.shasum,tarball:F}};H&&(W._hasShrinkwrap=!1);let q={_id:I.name,name:I.name,description:typeof n.description==`string`?n.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&&(q.access=C),q}function handleOidcFailure(t,n,S){if(t instanceof OidcUnavailableError){let C=`gjsify publish: OIDC not available — ${t.message}`;S?process.stdout.write(`${JSON.stringify({ok:!1,name:n,error:`oidc-unavailable`,reason:t.reason,message:t.message})}\n`):process.stderr.write(`${C}\n`);return}if(t instanceof OidcExchangeError){let C=t.status===401||t.status===403?`npm rejected the OIDC exchange (${t.status}) — check that ${n} has a Trusted Publisher configured at https://www.npmjs.com/package/${encodeURIComponent(n)}/access pointing at this workflow.`:t.message;if(S)process.stdout.write(`${JSON.stringify({ok:!1,name:n,error:`oidc-exchange`,status:t.status,body:t.body,claims:t.claims,message:t.message})}\n`);else if(process.stderr.write(`✗ ${n}: ${C}\n`),t.body&&process.stderr.write(` ↳ npm said: ${t.body.slice(0,300)}\n`),t.claims){let n=t.claims,S=[`aud`,`iss`,`repository`,`repository_owner`,`workflow_ref`,`job_workflow_ref`,`ref`,`environment`,`sub`].filter(t=>n[t]!==void 0).map(t=>`${t}=${JSON.stringify(n[t])}`).join(`, `);S&&process.stderr.write(` ↳ JWT claims npm received: ${S}\n`)}return}let C=t instanceof Error?t.message:String(t);S?process.stdout.write(`${JSON.stringify({ok:!1,name:n,error:`unknown`,message:C})}\n`):process.stderr.write(`✗ ${n}: ${C}\n`)}var oK,sK=__esmMin(()=>{_e(),ef(),$g(),qn(),MW(),gh(),yh(),EG(),AG(),jG(),RG(),VG(),KG(),UG(),pB(),aK(),$G(),kG(),oK={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:t=>t.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(`verify-timeout`,{description:"Seconds to keep asking the registry for the just-published version before giving up. npm answers 2xx to a write it has only ACCEPTED: in the v0.46.0 release 19 of 199 packages were recorded 56-252s after their 2xx and one was never recorded at all, so a shorter window turns normal queueing into a false red. `0` disables the read-back — for a registry with no packument read path; the success line then reads `UNVERIFIED` and says so, because a publish nothing checked must never look like one that was checked.",type:`number`,default:PG/1e3}).option(`verify-defer`,{description:"Report an unconfirmed read-back and exit 0 instead of 1. ONLY for a caller that re-checks the same set afterwards — `gjsify run npm:publish` passes it because `scripts/verify-published-closure.mjs` sweeps the whole roster at the end of release.yml. Everywhere else an unconfirmed publish must fail the job that made it.",type:`boolean`,default:!1}).option(`hold-timeout`,{description:'Seconds to wait for an intra-repo dependency pin whose exact version the registry does not serve (yet) before HOLDING this package instead of publishing it. A version npm accepted but never serves (status "validating") would make every dependent uninstallable; the write lag measured on v0.46.0 reaches 252s, hence the default. `0` probes once and holds without waiting. A hold exits 1, or 0 under `--verify-defer`.',type:`number`,default:WG/1e3}).option(`report-ledger`,{description:"Print the job-summary markdown for the publish ledger named by $GJSIFY_PUBLISH_LEDGER (versions npm accepted but does not serve, packages held because of them, the recovery command) and exit. Pair with `--ref <tag>`.",type:`boolean`,default:!1}).option(`fail-on-unsettled`,{description:`With --report-ledger: exit 1 when any package is still HELD or any accepted version is still unserved, naming them and the recovery command. The end-of-sweep gate: a sweep that left something behind must be red, not a warning.`,type:`boolean`,default:!1}).option(`held-names`,{description:`Print, one per line, the packages the ledger shows HELD and not yet published, and exit. Feeds the held-package second pass (.github/scripts/retry-held-publish.sh).`,type:`boolean`,default:!1}).option(`settle-ledger`,{description:`Wait up to --settle-timeout for every version the ledger records as accepted-but-unserved to be served (the longer read-back the sweep defers), record each as served, and exit.`,type:`boolean`,default:!1}).option(`settle-timeout`,{description:`With --settle-ledger: seconds to wait. Versions poll concurrently, so this is the longest lag tolerated, not a sum. Default 600 (the fatal read-back default; measured lags reach 368 s).`,type:`number`,default:PG/1e3}).option(`ref`,{description:`With --report-ledger: the git ref to put in the printed recovery command.`,type:`string`}).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 t=>{let n=Nn(t.path??process.cwd()),S=t.tag??`latest`,C=t.access,N=t.otp,F=t[`tolerate-republish`]===!0,I=t[`tolerate-untrusted-new`]===!0,H=t[`verify-timeout`]??6e5/1e3;if(!Number.isFinite(H)||H<0)return ge.error(`gjsify publish: --verify-timeout must be a non-negative number of seconds, got ${JSON.stringify(t[`verify-timeout`])}`),process.exit(2);let W=Math.round(H*1e3),q=t[`verify-defer`]===!0,Y=t.provenance===!0,X=t[`dry-run`]===!0,Z=t[`check-trusted`]===!0,te=t.trusted,ne=!!process.env.GJSIFY_PUBLISH_DEBUG,re=process.env.GJSIFY_PUBLISH_LEDGER;if(t[`held-names`]===!0){for(let t of pendingEntries(readLedger(re)).held)process.stdout.write(`${t.name}\n`);return}if(t[`settle-ledger`]===!0){let n=t[`settle-timeout`]??6e5/1e3;if(!Number.isFinite(n)||n<0)return ge.error(`gjsify publish: --settle-timeout must be a non-negative number of seconds, got ${JSON.stringify(t[`settle-timeout`])}`),process.exit(2);let S=await loadNpmrc(process.cwd()),C=await settleUnserved({entries:readLedger(re),ledgerPath:re,registryFor:t=>(process.env.npm_config_registry??registryFor(t,S)??lh).replace(/\/$/,``),budgetMs:Math.max(1,Math.round(n*1e3)),log:ne?t=>ge.error(t):void 0});for(let t of C)process.stdout.write(`served after settling: ${t}\n`);return}if(t[`report-ledger`]===!0){let n=readLedger(re),S=renderLedgerSummary(n,t.ref??`<tag>`);if(S&&process.stdout.write(`${S}\n`),t[`fail-on-unsettled`]===!0){let{unserved:S,held:C}=pendingEntries(n),N=[...new Set([...C,...S].map(t=>t.name))];if(N.length>0){let n=t.ref??`<tag>`;return ge.error(`gjsify publish: ${C.length} package(s) still HELD and ${S.length} version(s) still unserved after the second pass: ${N.join(` `)}\n recover: re-run THIS run (\`gh run rerun <run-id>\` — keeps the version; never a new dispatch on the next channel, which mints a new one), or for a release: gh workflow run release.yml --ref ${n} -f skip_publish=false -f only='${N.join(` `)}'`),process.exit(1)}}return}let ie=t[`hold-timeout`]??3e5/1e3;if(!Number.isFinite(ie)||ie<0)return ge.error(`gjsify publish: --hold-timeout must be a non-negative number of seconds, got ${JSON.stringify(t[`hold-timeout`])}`),process.exit(2);if(Y&&ge.warn(`gjsify publish: --provenance recorded but not signed (no sigstore integration yet).`),Z){let S=In(n,`package.json`),C=JSON.parse(readFileSync(S,`utf-8`));if(typeof C.name!=`string`)return process.stderr.write(`gjsify publish --check-trusted: ${S} has no \`name\` field\n`),process.exit(2);if(C.private===!0){let n={ok:!0,action:`check-trusted`,name:C.name,skipped:`private`};t.json?process.stdout.write(`${JSON.stringify(n)}\n`):process.stdout.write(`- ${C.name}: skipped (private package)\n`);return}let N=await loadNpmrc(n),F=process.env.npm_config_registry??registryFor(C.name,N)??lh;try{await getNpmTrustedToken({packageName:C.name,registry:F,log:ne?t=>ge.error(t):void 0});let n={ok:!0,action:`check-trusted`,name:C.name,registry:F};t.json?process.stdout.write(`${JSON.stringify(n)}\n`):process.stdout.write(`✓ ${C.name}: trusted publisher OK\n`);return}catch(n){handleOidcFailure(n,C.name,t.json===!0);return}}if(X){let S=await packWorkspace(n,{dryRun:!0,lifecycleScripts:[`prepublishOnly`,`prepack`],lifecycleStdio:t.json?`inherit-stderr`:`inherit`}),C={ok:!0,action:`dry-run`,name:S.name,version:S.version,filename:S.filename,size:S.size,shasum:S.shasum,integrity:S.integrity};t.json?process.stdout.write(`${JSON.stringify(C,null,2)}\n`):process.stdout.write(`+ ${S.name}@${S.version} (dry-run, ${S.size} bytes, ${S.entryCount} files)\n`);return}let ae=!!(process.stdin.isTTY&&process.stdout.isTTY),oe=await loadNpmrc(n),Q;try{Q=JSON.parse(readFileSync(In(n,`package.json`),`utf-8`)).name}catch{}let se=process.env.npm_config_registry??(Q?registryFor(Q,oe):void 0)??oe.registry??lh,ce=new OtpProvider(N,ae?promptLine:async()=>``,{registry:se});reportPublishOutcome(await publishWorkspace({wsDir:n,tag:S,access:C,provenance:Y,tolerate:F,tolerateUntrustedNew:I,trustedFlag:te,verbose:ne,json:t.json===!0,otpProvider:ce,seedOtpFirst:N!==void 0,verifyBudgetMs:W,holdWaitMs:Math.min(Math.round(ie*1e3),remainingHoldDeadlineMs())}),t.json===!0,q)}}});function buildTree(t){let n={name:`#root`,attrs:{},nodes:[]},S=[n];for(let n of scanXml(t)){let t=S[S.length-1];if(n.kind===`text`)t.nodes.push(n.text);else if(n.kind===`open`){let C={name:normName(n.name),attrs:n.attributes,nodes:[]};t.nodes.push(C),n.selfClosing||S.push(C)}else S.length>1&&S.pop()}return n}function inlineMarkdown(t){let n=``;for(let S of t.nodes){if(typeof S==`string`){n+=S;continue}if(isTranslation(S))continue;let t=inlineMarkdown(S),C=cK[S.name];C===void 0?S.name===`a`&&S.attrs.href?n+=`[${t}](${S.attrs.href})`:n+=t:n+=t.trim()===``?t:`${C}${t.trim()}${C}`}return n}function parseBlocks(t){let n=[];for(let S of elements(t))if(!isTranslation(S)){if(S.name===`p`){let t=clean(inlineMarkdown(S));t&&n.push({p:t})}else if(S.name===`ul`||S.name===`ol`){let t=elements(S,`li`).filter(t=>!isTranslation(t)).map(t=>clean(inlineMarkdown(t))).filter(Boolean);t.length&&n.push({ul:t})}}return n}function parseMetainfoReleases(t){let n=elements(buildTree(t),`component`)[0];if(!n)throw Error(`metainfo root must be <component>`);let S=elements(n,`releases`)[0];return S?elements(S,`release`).map(t=>{let n=t.attrs.timestamp,S=t.attrs.date??(n?new Date(Number(n)*1e3).toISOString().slice(0,10):``),C=elements(t,`description`).find(t=>!isTranslation(t)),N=C?parseBlocks(C):[];return{version:t.attrs.version??``,date:S,...N.length?{description:N}:{}}}):[]}var normName,elements,isTranslation,cK,clean,lK=__esmMin(()=>{Ye(),normName=t=>t.startsWith(`_`)?t.slice(1):t,elements=(t,n)=>t.nodes.filter(t=>typeof t!=`string`&&(n===void 0||t.name===n)),isTranslation=t=>t.attrs[`xml:lang`]!==void 0,cK={em:`*`,i:`*`,strong:`**`,b:`**`,code:"`",tt:"`"},clean=t=>t.replace(/\s+/g,` `).trim()});function descriptionToMarkdown(t){let n=typeof t==`string`?stringToBlocks(t):t,S=[];for(let t of n)if(`p`in t){let n=t.p.trim().replace(/\s+/g,` `);n&&S.push(n)}else{let n=t.ul.map(t=>(typeof t==`string`?t:t.item).trim()).filter(Boolean);n.length&&S.push(n.map(t=>`- ${t}`).join(`
1225
1225
  `))}return S.join(`
1226
1226
 
1227
- `)}function stripVersionPrefix(t){return t.trim().replace(/^v/i,``)}function resolveReleases(t){let n=t.metainfo??(t.configReleases?void 0:t.siteMetainfo);return n===void 0?{releases:t.configReleases}:{releases:parseMetainfoReleases(t.readMetainfo(n)),source:n}}function renderReleaseNotes({releases:t,source:n,version:S,repoUrl:C}){let N=stripVersionPrefix(S),F=t??[],I=F.findIndex(t=>stripVersionPrefix(t.version)===N);if(I<0){let t=n===void 0?"no `releases` configured":"no `<release>` entries";throw Error(`no \`releases\` entry for version ${N} in ${n??`the gjsify config`}`+(F.length?` (found: ${F.map(t=>t.version).join(`, `)})`:` (${t})`))}let H=F[I],W=H.description===void 0?``:descriptionToMarkdown(H.description);if(!W)throw Error(`the \`releases\` entry for version ${N} has no description`);let q=F[I+1];return!C||!q?`${W}\n`:`${W}\n\n**Full changelog:** ${`${C.replace(/\/+$/,``)}/compare/v${stripVersionPrefix(q.version)}...v${N}`}\n`}var lK=__esmMin(()=>{nV(),cK()}),uK,dK=__esmMin(()=>{rR(),jI(),lK(),ef(),qn(),uK={command:`release-notes [release]`,description:"Print the `releases` entry for a version as GitHub Markdown (from the config or a metainfo file). Fails when there is no entry or no description.",builder:t=>t.positional(`release`,{description:"Version or tag (a leading `v` is accepted). Default: the version in package.json.",type:`string`}).option(`compare`,{description:"Append a `**Full changelog:**` compare link to the previous entry (needs `vcsBrowserUrl`).",type:`boolean`,default:!1}).option(`metainfo`,{description:"Read the `<release>` entries from this AppStream metainfo file instead of the config. Default without `releases` in the config: the file named by `gjsify.site.metainfo`.",type:`string`}),handler:async t=>{let n=process.cwd();try{let S=await new Config().forCommand(n),C=S.ship??{},N=S.flatpak??{},F=t.release??readPackageJson$2(In(n,`package.json`))?.version;if(!F)throw Error(`no version given and package.json has none`);let{releases:I,source:H}=resolveReleases({metainfo:t.metainfo,configReleases:C.releases??N.releases,siteMetainfo:S.site?.metainfo,readMetainfo:t=>{try{return readFileSync(Nn(n,t),`utf8`)}catch{throw Error(`cannot read the metainfo file ${t}`)}}}),W=t.compare===!0?C.vcsBrowserUrl??N.vcsBrowserUrl:void 0;process.stdout.write(renderReleaseNotes({releases:I,source:H,version:stripVersionPrefix(F),repoUrl:W}))}catch(t){return process.stderr.write(`gjsify release-notes: ${t instanceof Error?t.message:String(t)}\n`),process.exit(1)}}}});function px(t,n){return Math.round(t*n)}function planAndroidIcons(t){let n=[];for(let{name:S,scale:C}of pK){let N=`mipmap-${S}`;n.push({path:`${N}/ic_launcher.png`,kind:`legacy`,size:px(48,C)}),n.push({path:`${N}/ic_launcher_round.png`,kind:`round`,size:px(48,C)}),n.push({path:`${N}/ic_launcher_foreground.png`,kind:`foreground`,size:px(108,C)}),t.monochrome&&n.push({path:`${N}/ic_launcher_monochrome.png`,kind:`monochrome`,size:px(108,C)})}for(let{name:t,scale:S}of mK)n.push({path:`drawable-${t}/logo.png`,kind:`splash`,size:px(96,S)});let S=adaptiveIconXml(t.monochrome);return{png:n,text:[{path:`values/ic_launcher_background.xml`,content:backgroundXml(t.background)},{path:`mipmap-anydpi-v26/ic_launcher.xml`,content:S},{path:`mipmap-anydpi-v26/ic_launcher_round.xml`,content:S}]}}function backgroundXml(t){return`<?xml version="1.0" encoding="utf-8"?>
1227
+ `)}function stripVersionPrefix(t){return t.trim().replace(/^v/i,``)}function resolveReleases(t){let n=t.metainfo??(t.configReleases?void 0:t.siteMetainfo);return n===void 0?{releases:t.configReleases}:{releases:parseMetainfoReleases(t.readMetainfo(n)),source:n}}function renderReleaseNotes({releases:t,source:n,version:S,repoUrl:C}){let N=stripVersionPrefix(S),F=t??[],I=F.findIndex(t=>stripVersionPrefix(t.version)===N);if(I<0){let t=n===void 0?"no `releases` configured":"no `<release>` entries";throw Error(`no \`releases\` entry for version ${N} in ${n??`the gjsify config`}`+(F.length?` (found: ${F.map(t=>t.version).join(`, `)})`:` (${t})`))}let H=F[I],W=H.description===void 0?``:descriptionToMarkdown(H.description);if(!W)throw Error(`the \`releases\` entry for version ${N} has no description`);let q=F[I+1];return!C||!q?`${W}\n`:`${W}\n\n**Full changelog:** ${`${C.replace(/\/+$/,``)}/compare/v${stripVersionPrefix(q.version)}...v${N}`}\n`}var uK=__esmMin(()=>{nV(),lK()}),dK,fK=__esmMin(()=>{rR(),jI(),uK(),ef(),qn(),dK={command:`release-notes [release]`,description:"Print the `releases` entry for a version as GitHub Markdown (from the config or a metainfo file). Fails when there is no entry or no description.",builder:t=>t.positional(`release`,{description:"Version or tag (a leading `v` is accepted). Default: the version in package.json.",type:`string`}).option(`compare`,{description:"Append a `**Full changelog:**` compare link to the previous entry (needs `vcsBrowserUrl`).",type:`boolean`,default:!1}).option(`metainfo`,{description:"Read the `<release>` entries from this AppStream metainfo file instead of the config. Default without `releases` in the config: the file named by `gjsify.site.metainfo`.",type:`string`}),handler:async t=>{let n=process.cwd();try{let S=await new Config().forCommand(n),C=S.ship??{},N=S.flatpak??{},F=t.release??readPackageJson$2(In(n,`package.json`))?.version;if(!F)throw Error(`no version given and package.json has none`);let{releases:I,source:H}=resolveReleases({metainfo:t.metainfo,configReleases:C.releases??N.releases,siteMetainfo:S.site?.metainfo,readMetainfo:t=>{try{return readFileSync(Nn(n,t),`utf8`)}catch{throw Error(`cannot read the metainfo file ${t}`)}}}),W=t.compare===!0?C.vcsBrowserUrl??N.vcsBrowserUrl:void 0;process.stdout.write(renderReleaseNotes({releases:I,source:H,version:stripVersionPrefix(F),repoUrl:W}))}catch(t){return process.stderr.write(`gjsify release-notes: ${t instanceof Error?t.message:String(t)}\n`),process.exit(1)}}}});function px(t,n){return Math.round(t*n)}function planAndroidIcons(t){let n=[];for(let{name:S,scale:C}of mK){let N=`mipmap-${S}`;n.push({path:`${N}/ic_launcher.png`,kind:`legacy`,size:px(48,C)}),n.push({path:`${N}/ic_launcher_round.png`,kind:`round`,size:px(48,C)}),n.push({path:`${N}/ic_launcher_foreground.png`,kind:`foreground`,size:px(108,C)}),t.monochrome&&n.push({path:`${N}/ic_launcher_monochrome.png`,kind:`monochrome`,size:px(108,C)})}for(let{name:t,scale:S}of hK)n.push({path:`drawable-${t}/logo.png`,kind:`splash`,size:px(96,S)});let S=adaptiveIconXml(t.monochrome);return{png:n,text:[{path:`values/ic_launcher_background.xml`,content:backgroundXml(t.background)},{path:`mipmap-anydpi-v26/ic_launcher.xml`,content:S},{path:`mipmap-anydpi-v26/ic_launcher_round.xml`,content:S}]}}function backgroundXml(t){return`<?xml version="1.0" encoding="utf-8"?>
1228
1228
  <resources>
1229
1229
  <color name="ic_launcher_background">${t}</color>
1230
1230
  </resources>
@@ -1234,12 +1234,12 @@ Enter a NEW OTP: `,OtpProvider=class{cached;promptFn;registry;generation=0;pendi
1234
1234
  <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
1235
1235
  ${t?` <monochrome android:drawable="@mipmap/ic_launcher_monochrome"/>
1236
1236
  `:``}</adaptive-icon>
1237
- `}function normalizeColor(t){let n=/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(t.trim());if(n===null)return null;let S=n[1];return`#${(S.length===3?[...S].map(t=>t+t).join(``):S).toUpperCase()}`}function parseMetainfoBranding(t){let n=null;for(let S of t.matchAll(/<color\b([^>]*)>\s*([^<\s]+)\s*<\/color>/g)){let t=S[1]??``;if(!/type\s*=\s*["']primary["']/.test(t))continue;let C=normalizeColor(S[2]??``);if(C===null)continue;let N=/scheme_preference\s*=\s*["']([^"']+)["']/.exec(t)?.[1];if(N===`light`)return C;N===void 0&&n===null&&(n=C)}return n}function parseAppResourcesPath(t){return/\bappResourcesPath\s*:\s*["'`]([^"'`]+)["'`]/.exec(t)?.[1]??null}function resolveResourcesName(t){return t.flag??t.configured??(t.nativescriptConfig===null?null:parseAppResourcesPath(t.nativescriptConfig))??`App_Resources`}function resolveBackground(t){let n=t.flag??t.configured;if(n!==void 0){let t=normalizeColor(n);if(t===null)throw Error(`gjsify android-icons: \`${n}\` is not a colour — write it as #rrggbb.`);return t}return t.fromMetainfo??`#FFFFFF`}function pickIconSources(t){let n=t.filter(t=>Vn(t).toLowerCase()===`.svg`),S=n.filter(t=>!isSymbolicIcon(t)),C=S.find(t=>/(?:^|[\\/])scalable[\\/]/.test(t))??S[0]??null,N=n.filter(isSymbolicIcon),F=C===null?null:`${Bn(C,`.svg`)}-symbolic`;return{icon:C,symbolic:N.find(t=>Bn(t,`.svg`)===F)??N[0]??null}}function symbolicSibling(t){return In(zn(zn(zn(t))),`symbolic`,`apps`,`${Bn(t,`.svg`)}-symbolic.svg`)}function dataUri(t){return`data:image/svg+xml;base64,${Buffer.from(t).toString(`base64`)}`}function wrapperSvg(t,n,S){let C=`xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"`;if(t===`round`){let t=100*hK,N=(100-t)/2;return`<svg ${C} width="100" height="100" viewBox="0 0 100 100"><circle cx="50" cy="50" r="50" fill="${S}"/><image x="${N}" y="${N}" width="${t}" height="${t}" xlink:href="${dataUri(n)}"/></svg>`}return`<svg ${C} width="108" height="108" viewBox="0 0 108 108"><image x="21" y="21" width="66" height="66" xlink:href="${dataUri(n)}"/></svg>`}function sha256(t){return createHash(`sha256`).update(t).digest(`hex`)}function hashInputs(t){return sha256(JSON.stringify({generator:1,icon:sha256(t.icon),symbolic:t.symbolic===null?null:sha256(t.symbolic),background:t.background}))}function buildStamp(t,n,S){return{generator:1,inputs:t,files:[...n.png.map(t=>t.path),...n.text.map(t=>t.path)].map(t=>Tn.join(S,t)).sort()}}function checkStamp(t,n,S){if(t===null)return{current:!1,reason:`was never generated`};let C;try{C=JSON.parse(t)}catch{return{current:!1,reason:`has an unreadable stamp`}}if(C.generator!==1||C.inputs!==n)return{current:!1,reason:`is out of date with the icon, colour or generator`};let N=(C.files??[]).find(t=>!S(t));return N===void 0?{current:!0}:{current:!1,reason:`lacks ${N}`}}var fK,pK,mK,hK,gK=__esmMin(()=>{fl(),qn(),lH(),fK=`.gjsify-android-icons.json`,pK=[{name:`mdpi`,scale:1},{name:`hdpi`,scale:1.5},{name:`xhdpi`,scale:2},{name:`xxhdpi`,scale:3},{name:`xxxhdpi`,scale:4}],mK=[{name:`ldpi`,scale:.75},...pK],hK=.72});function walk(t,n=[]){if(!existsSync(t))return n;for(let S of readdirSync(t,{withFileTypes:!0})){let C=In(t,S.name);S.isDirectory()?walk(C,n):n.push(C)}return n}function discoverIcon(t,n){if(n!==void 0){let S=Nn(t,n);if(!existsSync(S))throw Error(`the icon ${n} does not exist`);let C=symbolicSibling(S);return{icon:S,symbolic:existsSync(C)?C:null}}let S=[In(t,`data`,`icons`),...siblingIconRoots(t)];for(let t of S){let n=pickIconSources(walk(t).filter(t=>t.toLowerCase().endsWith(`.svg`)).sort());if(n.icon!==null)return{icon:n.icon,symbolic:n.symbolic}}throw Error("no app icon found; pass --icon <svg> or set `gjsify.androidIcons.icon`")}function siblingIconRoots(t){let n=zn(t);return existsSync(n)?readdirSync(n).sort().map(t=>In(n,t,`data`,`icons`)).filter(n=>n!==In(t,`data`,`icons`)&&existsSync(n)&&statSync(n).isDirectory()):[]}function findMetainfoColor(t,n){let S=new Set([In(n,`data`)]);S.add(Nn(zn(t),`..`,`..`,`..`,`..`));for(let t of S){let n=walk(In(t,`metainfo`)).filter(t=>/\.metainfo\.xml(\.in)?$/.test(t)).sort();for(let t of n){let n=parseMetainfoBranding(readFileSync(t,`utf8`));if(n!==null)return n}}return null}var _K,vK,yK=__esmMin(()=>{ef(),$g(),qn(),rR(),gK(),lH(),_K=`Android/src/main/res`,vK={command:`android-icons`,description:`Generate the Android launcher icon and splash logo of a NativeScript app from its one app icon.`,builder:t=>t.option(`resources`,{description:"The App_Resources directory. Default: `gjsify.androidIcons.resources`, else `appResourcesPath` of nativescript.config.ts, else App_Resources.",type:`string`}).option(`icon`,{description:"The scalable app icon SVG. Default: `gjsify.androidIcons.icon`, else the hicolor icon under data/icons (here or in a sibling package).",type:`string`}).option(`background`,{description:"Adaptive-icon background colour. Default: `gjsify.androidIcons.background`, else the metainfo light `<branding>` colour, else white.",type:`string`}).option(`check`,{description:`Write nothing; exit 1 when the generated files are missing or the inputs changed.`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd();try{let S=(await new Config().forCommand(n)).androidIcons??{},C=[`nativescript.config.ts`,`nativescript.config.js`].map(t=>In(n,t)).find(t=>existsSync(t)),N=resolveResourcesName({flag:t.resources,configured:S.resources,nativescriptConfig:C===void 0?null:readFileSync(C,`utf8`)}),F=Nn(n,N),{icon:I,symbolic:H}=discoverIcon(n,t.icon??S.icon),W=resolveBackground({flag:t.background,configured:S.background,fromMetainfo:findMetainfoColor(I,n)}),q=new Uint8Array(readFileSync(I)),Y=H===null?null:new Uint8Array(readFileSync(H)),X=hashInputs({icon:q,symbolic:Y,background:W}),Z=planAndroidIcons({background:W,monochrome:Y!==null}),te=In(F,fK);if(t.check===!0){let t=checkStamp(existsSync(te)?readFileSync(te,`utf8`):null,X,t=>existsSync(In(F,...t.split(`/`))));return t.current?void 0:(process.stderr.write(`gjsify android-icons: ${N} ${t.reason}; run \`gjsify android-icons\` and commit it\n`),process.exit(1))}let ne=In(F,..._K.split(`/`)),re=mkdtempSync(In(tmpdir(),`gjsify-android-icons-`));try{let t=new Map([[`plain`,I]]);for(let n of[`round`,`foreground`]){let S=In(re,`${n}.svg`);writeFileSync(S,wrapperSvg(n,q,W)),t.set(n,S)}if(Y!==null){let n=In(re,`monochrome.svg`);writeFileSync(n,wrapperSvg(`monochrome`,Y,W)),t.set(`monochrome`,n)}for(let[n,S]of t){let t=Z.png.filter(t=>n===`plain`?t.kind===`legacy`||t.kind===`splash`:t.kind===n),C=await rasterizeSvg({svg:S,sizes:[...new Set(t.map(t=>t.size))],command:`gjsify android-icons`});for(let n of t){let t=In(ne,n.path);mkdirSync(zn(t),{recursive:!0}),writeFileSync(t,C.get(n.size))}}}finally{rmSync(re,{recursive:!0,force:!0})}for(let t of Z.text){let n=In(ne,t.path);mkdirSync(zn(n),{recursive:!0}),writeFileSync(n,t.content)}rmSync(In(ne,`drawable`,`ic_launcher_foreground.xml`),{force:!0}),writeFileSync(te,`${JSON.stringify(buildStamp(X,Z,_K),null,2)}\n`),process.stdout.write(`gjsify android-icons: wrote ${Z.png.length+Z.text.length} files under ${Ln(n,ne).split(Wn).join(`/`)} from ${Ln(n,I)}\n`)}catch(t){return process.stderr.write(`gjsify android-icons: ${t instanceof Error?t.message:String(t)}\n`),process.exit(1)}}}});function globToRegExp(t){let n=t.split(`*`).map(t=>t.replace(/[.+?^${}()|[\]\\]/g,`\\$&`)).join(`.*`);return RegExp(`^${n}$`,`i`)}function isIgnored(t,n){return n.some(n=>{let S=globToRegExp(n);return S.test(t.name)||t.email!==``&&S.test(t.email)})}function parsePerson(t){let n=/^(.*?)\s*<([^>]*)>\s*$/.exec(t.trim());return n?{name:n[1].trim(),email:n[2].trim()}:{name:t.trim(),email:``}}function poLanguage(t){let n=Tn.basename(t);return/\.po$/i.test(n)?n.slice(0,-3):void 0}function bump(t,n){t.set(n,(t.get(n)??0)+1)}function rank(t){return[...t.entries()].sort(([t,n],[S,C])=>C-n||(t<S?-1:+(t>S))).map(([t])=>t)}function appendUnseen(t,n,S){let C=new Set(t);for(let N of n??[]){let n=N.trim();n&&!C.has(n)&&!S(n)&&(C.add(n),t.push(n))}}function buildCredits(t,n={}){let S=n.ignore??bK,C=n.overrides??{},N=C.exclude??[],excluded=t=>isIgnored({name:t,email:``},N),F=new Map,I=new Map,H=t.map(t=>{let n=new Set;for(let C of[t.author,...t.coAuthors])C.name&&!isIgnored(C,S)&&!excluded(C.name)&&n.add(C.name);let C=new Set,N=!1;for(let n of t.files){isTranslationFile(n)||(N=!0);let t=poLanguage(n);t&&C.add(t)}return{names:n,languages:C,touchesCode:N}}),W=new Map;for(let{names:t,languages:n}of H){if(t.size!==1||n.size!==1)continue;let[S]=t,[C]=n,N=W.get(S);N||W.set(S,N=new Set),N.add(C)}for(let{names:t,languages:n,touchesCode:S}of H){let C=t.size>1||n.size>1;for(let N of t){S&&bump(F,N);let t=W.get(N);for(let S of n){if(C&&t&&!t.has(S))continue;let n=I.get(S);n||I.set(S,n=new Map),bump(n,N)}}}let q={developers:rank(F),translators:{},supporters:[]},Y=C.excludeTranslators??{};for(let t of[...I.keys()].sort()){let n=[...Y[`*`]??[],...Y[t]??[]],S=rank(I.get(t)).filter(t=>!isIgnored({name:t,email:``},n));S.length&&(q.translators[t]=S)}appendUnseen(q.developers,C.developers,excluded);for(let t of Object.keys(C.translators??{}).sort()){let n=q.translators[t]??[];appendUnseen(n,C.translators[t],excluded),n.length&&(q.translators[t]=n)}return q.translators=Object.fromEntries(Object.entries(q.translators).sort(([t],[n])=>t<n?-1:1)),appendUnseen(q.supporters,C.supporters,excluded),q}function parseGitLog(t){let n=[];for(let S of t.split(SK)){if(!S.trim())continue;let[t=``,C=``,N=``,F=``]=S.split(xK);n.push({author:{name:t.trim(),email:C.trim()},coAuthors:N.split(CK).map(t=>t.trim()).filter(Boolean).map(parsePerson),files:F.split(`
1237
+ `}function normalizeColor(t){let n=/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(t.trim());if(n===null)return null;let S=n[1];return`#${(S.length===3?[...S].map(t=>t+t).join(``):S).toUpperCase()}`}function parseMetainfoBranding(t){let n=null;for(let S of t.matchAll(/<color\b([^>]*)>\s*([^<\s]+)\s*<\/color>/g)){let t=S[1]??``;if(!/type\s*=\s*["']primary["']/.test(t))continue;let C=normalizeColor(S[2]??``);if(C===null)continue;let N=/scheme_preference\s*=\s*["']([^"']+)["']/.exec(t)?.[1];if(N===`light`)return C;N===void 0&&n===null&&(n=C)}return n}function parseAppResourcesPath(t){return/\bappResourcesPath\s*:\s*["'`]([^"'`]+)["'`]/.exec(t)?.[1]??null}function resolveResourcesName(t){return t.flag??t.configured??(t.nativescriptConfig===null?null:parseAppResourcesPath(t.nativescriptConfig))??`App_Resources`}function resolveBackground(t){let n=t.flag??t.configured;if(n!==void 0){let t=normalizeColor(n);if(t===null)throw Error(`gjsify android-icons: \`${n}\` is not a colour — write it as #rrggbb.`);return t}return t.fromMetainfo??`#FFFFFF`}function pickIconSources(t){let n=t.filter(t=>Vn(t).toLowerCase()===`.svg`),S=n.filter(t=>!isSymbolicIcon(t)),C=S.find(t=>/(?:^|[\\/])scalable[\\/]/.test(t))??S[0]??null,N=n.filter(isSymbolicIcon),F=C===null?null:`${Bn(C,`.svg`)}-symbolic`;return{icon:C,symbolic:N.find(t=>Bn(t,`.svg`)===F)??N[0]??null}}function symbolicSibling(t){return In(zn(zn(zn(t))),`symbolic`,`apps`,`${Bn(t,`.svg`)}-symbolic.svg`)}function dataUri(t){return`data:image/svg+xml;base64,${Buffer.from(t).toString(`base64`)}`}function wrapperSvg(t,n,S){let C=`xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"`;if(t===`round`){let t=100*gK,N=(100-t)/2;return`<svg ${C} width="100" height="100" viewBox="0 0 100 100"><circle cx="50" cy="50" r="50" fill="${S}"/><image x="${N}" y="${N}" width="${t}" height="${t}" xlink:href="${dataUri(n)}"/></svg>`}return`<svg ${C} width="108" height="108" viewBox="0 0 108 108"><image x="21" y="21" width="66" height="66" xlink:href="${dataUri(n)}"/></svg>`}function sha256(t){return createHash(`sha256`).update(t).digest(`hex`)}function hashInputs(t){return sha256(JSON.stringify({generator:1,icon:sha256(t.icon),symbolic:t.symbolic===null?null:sha256(t.symbolic),background:t.background}))}function buildStamp(t,n,S){return{generator:1,inputs:t,files:[...n.png.map(t=>t.path),...n.text.map(t=>t.path)].map(t=>Tn.join(S,t)).sort()}}function checkStamp(t,n,S){if(t===null)return{current:!1,reason:`was never generated`};let C;try{C=JSON.parse(t)}catch{return{current:!1,reason:`has an unreadable stamp`}}if(C.generator!==1||C.inputs!==n)return{current:!1,reason:`is out of date with the icon, colour or generator`};let N=(C.files??[]).find(t=>!S(t));return N===void 0?{current:!0}:{current:!1,reason:`lacks ${N}`}}var pK,mK,hK,gK,_K=__esmMin(()=>{fl(),qn(),uH(),pK=`.gjsify-android-icons.json`,mK=[{name:`mdpi`,scale:1},{name:`hdpi`,scale:1.5},{name:`xhdpi`,scale:2},{name:`xxhdpi`,scale:3},{name:`xxxhdpi`,scale:4}],hK=[{name:`ldpi`,scale:.75},...mK],gK=.72});function walk(t,n=[]){if(!existsSync(t))return n;for(let S of readdirSync(t,{withFileTypes:!0})){let C=In(t,S.name);S.isDirectory()?walk(C,n):n.push(C)}return n}function discoverIcon(t,n){if(n!==void 0){let S=Nn(t,n);if(!existsSync(S))throw Error(`the icon ${n} does not exist`);let C=symbolicSibling(S);return{icon:S,symbolic:existsSync(C)?C:null}}let S=[In(t,`data`,`icons`),...siblingIconRoots(t)];for(let t of S){let n=pickIconSources(walk(t).filter(t=>t.toLowerCase().endsWith(`.svg`)).sort());if(n.icon!==null)return{icon:n.icon,symbolic:n.symbolic}}throw Error("no app icon found; pass --icon <svg> or set `gjsify.androidIcons.icon`")}function siblingIconRoots(t){let n=zn(t);return existsSync(n)?readdirSync(n).sort().map(t=>In(n,t,`data`,`icons`)).filter(n=>n!==In(t,`data`,`icons`)&&existsSync(n)&&statSync(n).isDirectory()):[]}function findMetainfoColor(t,n){let S=new Set([In(n,`data`)]);S.add(Nn(zn(t),`..`,`..`,`..`,`..`));for(let t of S){let n=walk(In(t,`metainfo`)).filter(t=>/\.metainfo\.xml(\.in)?$/.test(t)).sort();for(let t of n){let n=parseMetainfoBranding(readFileSync(t,`utf8`));if(n!==null)return n}}return null}var vK,yK,bK=__esmMin(()=>{ef(),$g(),qn(),rR(),_K(),uH(),vK=`Android/src/main/res`,yK={command:`android-icons`,description:`Generate the Android launcher icon and splash logo of a NativeScript app from its one app icon.`,builder:t=>t.option(`resources`,{description:"The App_Resources directory. Default: `gjsify.androidIcons.resources`, else `appResourcesPath` of nativescript.config.ts, else App_Resources.",type:`string`}).option(`icon`,{description:"The scalable app icon SVG. Default: `gjsify.androidIcons.icon`, else the hicolor icon under data/icons (here or in a sibling package).",type:`string`}).option(`background`,{description:"Adaptive-icon background colour. Default: `gjsify.androidIcons.background`, else the metainfo light `<branding>` colour, else white.",type:`string`}).option(`check`,{description:`Write nothing; exit 1 when the generated files are missing or the inputs changed.`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd();try{let S=(await new Config().forCommand(n)).androidIcons??{},C=[`nativescript.config.ts`,`nativescript.config.js`].map(t=>In(n,t)).find(t=>existsSync(t)),N=resolveResourcesName({flag:t.resources,configured:S.resources,nativescriptConfig:C===void 0?null:readFileSync(C,`utf8`)}),F=Nn(n,N),{icon:I,symbolic:H}=discoverIcon(n,t.icon??S.icon),W=resolveBackground({flag:t.background,configured:S.background,fromMetainfo:findMetainfoColor(I,n)}),q=new Uint8Array(readFileSync(I)),Y=H===null?null:new Uint8Array(readFileSync(H)),X=hashInputs({icon:q,symbolic:Y,background:W}),Z=planAndroidIcons({background:W,monochrome:Y!==null}),te=In(F,pK);if(t.check===!0){let t=checkStamp(existsSync(te)?readFileSync(te,`utf8`):null,X,t=>existsSync(In(F,...t.split(`/`))));return t.current?void 0:(process.stderr.write(`gjsify android-icons: ${N} ${t.reason}; run \`gjsify android-icons\` and commit it\n`),process.exit(1))}let ne=In(F,...vK.split(`/`)),re=mkdtempSync(In(tmpdir(),`gjsify-android-icons-`));try{let t=new Map([[`plain`,I]]);for(let n of[`round`,`foreground`]){let S=In(re,`${n}.svg`);writeFileSync(S,wrapperSvg(n,q,W)),t.set(n,S)}if(Y!==null){let n=In(re,`monochrome.svg`);writeFileSync(n,wrapperSvg(`monochrome`,Y,W)),t.set(`monochrome`,n)}for(let[n,S]of t){let t=Z.png.filter(t=>n===`plain`?t.kind===`legacy`||t.kind===`splash`:t.kind===n),C=await rasterizeSvg({svg:S,sizes:[...new Set(t.map(t=>t.size))],command:`gjsify android-icons`});for(let n of t){let t=In(ne,n.path);mkdirSync(zn(t),{recursive:!0}),writeFileSync(t,C.get(n.size))}}}finally{rmSync(re,{recursive:!0,force:!0})}for(let t of Z.text){let n=In(ne,t.path);mkdirSync(zn(n),{recursive:!0}),writeFileSync(n,t.content)}rmSync(In(ne,`drawable`,`ic_launcher_foreground.xml`),{force:!0}),writeFileSync(te,`${JSON.stringify(buildStamp(X,Z,vK),null,2)}\n`),process.stdout.write(`gjsify android-icons: wrote ${Z.png.length+Z.text.length} files under ${Ln(n,ne).split(Wn).join(`/`)} from ${Ln(n,I)}\n`)}catch(t){return process.stderr.write(`gjsify android-icons: ${t instanceof Error?t.message:String(t)}\n`),process.exit(1)}}}});function globToRegExp(t){let n=t.split(`*`).map(t=>t.replace(/[.+?^${}()|[\]\\]/g,`\\$&`)).join(`.*`);return RegExp(`^${n}$`,`i`)}function isIgnored(t,n){return n.some(n=>{let S=globToRegExp(n);return S.test(t.name)||t.email!==``&&S.test(t.email)})}function parsePerson(t){let n=/^(.*?)\s*<([^>]*)>\s*$/.exec(t.trim());return n?{name:n[1].trim(),email:n[2].trim()}:{name:t.trim(),email:``}}function poLanguage(t){let n=Tn.basename(t);return/\.po$/i.test(n)?n.slice(0,-3):void 0}function bump(t,n){t.set(n,(t.get(n)??0)+1)}function rank(t){return[...t.entries()].sort(([t,n],[S,C])=>C-n||(t<S?-1:+(t>S))).map(([t])=>t)}function appendUnseen(t,n,S){let C=new Set(t);for(let N of n??[]){let n=N.trim();n&&!C.has(n)&&!S(n)&&(C.add(n),t.push(n))}}function buildCredits(t,n={}){let S=n.ignore??xK,C=n.overrides??{},N=C.exclude??[],excluded=t=>isIgnored({name:t,email:``},N),F=new Map,I=new Map,H=t.map(t=>{let n=new Set;for(let C of[t.author,...t.coAuthors])C.name&&!isIgnored(C,S)&&!excluded(C.name)&&n.add(C.name);let C=new Set,N=!1;for(let n of t.files){isTranslationFile(n)||(N=!0);let t=poLanguage(n);t&&C.add(t)}return{names:n,languages:C,touchesCode:N}}),W=new Map;for(let{names:t,languages:n}of H){if(t.size!==1||n.size!==1)continue;let[S]=t,[C]=n,N=W.get(S);N||W.set(S,N=new Set),N.add(C)}for(let{names:t,languages:n,touchesCode:S}of H){let C=t.size>1||n.size>1;for(let N of t){S&&bump(F,N);let t=W.get(N);for(let S of n){if(C&&t&&!t.has(S))continue;let n=I.get(S);n||I.set(S,n=new Map),bump(n,N)}}}let q={developers:rank(F),translators:{},supporters:[]},Y=C.excludeTranslators??{};for(let t of[...I.keys()].sort()){let n=[...Y[`*`]??[],...Y[t]??[]],S=rank(I.get(t)).filter(t=>!isIgnored({name:t,email:``},n));S.length&&(q.translators[t]=S)}appendUnseen(q.developers,C.developers,excluded);for(let t of Object.keys(C.translators??{}).sort()){let n=q.translators[t]??[];appendUnseen(n,C.translators[t],excluded),n.length&&(q.translators[t]=n)}return q.translators=Object.fromEntries(Object.entries(q.translators).sort(([t],[n])=>t<n?-1:1)),appendUnseen(q.supporters,C.supporters,excluded),q}function parseGitLog(t){let n=[];for(let S of t.split(CK)){if(!S.trim())continue;let[t=``,C=``,N=``,F=``]=S.split(SK);n.push({author:{name:t.trim(),email:C.trim()},coAuthors:N.split(wK).map(t=>t.trim()).filter(Boolean).map(parsePerson),files:F.split(`
1238
1238
  `).map(t=>t.trim()).filter(Boolean)})}return n}function git(t,n,S){let C=spawnSync(`git`,[...n],{cwd:t,encoding:`utf8`,input:S,maxBuffer:1<<30});if(C.error)throw Error(`cannot run git: ${C.error.message}`);if(C.status!==0)throw Error(`git ${n.join(` `)} failed: ${String(C.stderr).trim()}`);return String(C.stdout)}function mapTrailers(t,n){let S=new Set;for(let t of n)for(let n of t.coAuthors)n.email&&S.add(`${n.name} <${n.email}>`);if(S.size===0)return;let C=[...S],N=git(t,[`check-mailmap`,`--stdin`],C.join(`
1239
1239
  `)+`
1240
1240
  `).split(`
1241
- `).filter(Boolean);if(N.length!==C.length)throw Error(`git check-mailmap answered a different number of lines`);let F=new Map(C.map((t,n)=>[t,parsePerson(N[n])]));for(let t of n)t.coAuthors=t.coAuthors.map(t=>t.email?F.get(`${t.name} <${t.email}>`):t)}function readCommits(t){if(git(t,[`rev-parse`,`--is-shallow-repository`]).trim()===`true`)throw Error(`the repository is a shallow clone; fetch the full history first (git fetch --unshallow)`);let n=parseGitLog(git(t,wK));return mapTrailers(t,n),n}function asStringList(t,n){if(!Array.isArray(t)||t.some(t=>typeof t!=`string`))throw Error(`${n} must be an array of strings`);return t}function parseOverrides(t,n=`overrides`){let S;try{S=JSON.parse(t)}catch(t){throw Error(`${n} is not valid JSON: ${t instanceof Error?t.message:String(t)}`)}if(typeof S!=`object`||!S||Array.isArray(S))throw Error(`${n} must be a JSON object`);let C=S,N=new Set([...TK,...EK]);for(let t of Object.keys(C))if(!N.has(t))throw Error(`${n} has an unknown key "${t}" (known: ${[...N].join(`, `)})`);let F={};for(let t of TK)C[t]!==void 0&&(F[t]=asStringList(C[t],`${n}.${t}`));for(let t of EK){let S=C[t];if(S===void 0)continue;if(typeof S!=`object`||!S||Array.isArray(S))throw Error(`${n}.${t} must map a language to an array of names`);let N={};for(let[C,F]of Object.entries(S))N[C]=asStringList(F,`${n}.${t}.${C}`);F[t]=N}return F}function serializeCredits(t){return JSON.stringify(t,null,2)+`
1242
- `}function isStale(t,n){if(t===null)return!0;try{return JSON.stringify(JSON.parse(t))!==JSON.stringify(n)}catch{return!0}}var bK,xK,SK,CK,isTranslationFile,wK,TK,EK,DK=__esmMin(()=>{ev(),qn(),bK=[`*[bot]`,`github-actions`,`Weblate`,`Weblate (bot)`,`Hosted Weblate`,`Weblate Translation Memory`,`LibreTranslate`,`Claude`,`*@anthropic.com`,`noreply-mt-*@weblate.org`,`hosted@weblate.org`,`*[bot]@users.noreply.github.com`],xK=``,SK=``,CK=``,isTranslationFile=t=>/\.pot?$/i.test(t),wK=[`-c`,`core.quotepath=off`,`log`,`--no-merges`,`--use-mailmap`,`--name-only`,`--format=${SK}%aN${xK}%aE${xK}%(trailers:key=Co-authored-by,valueonly,unfold,separator=%x1d)${xK}`],TK=[`developers`,`supporters`,`exclude`],EK=[`translators`,`excludeTranslators`]}),OK,kK,AK,jK=__esmMin(()=>{rR(),DK(),ef(),qn(),OK=`credits.json`,kK=`credits.overrides.json`,AK={command:`credits`,description:`Write the project’s contributors (developers, translators per language) from the git history as JSON, names only.`,builder:t=>t.option(`output`,{alias:`o`,description:`File to write. Default: \`gjsify.credits.output\`, else ${OK}.`,type:`string`}).option(`overrides`,{description:`Hand-kept additions and exclusions. Default: \`gjsify.credits.overrides\`, else ${kK} when it exists.`,type:`string`}).option(`check`,{description:`Write nothing; exit 1 when the file on disk differs from what the history gives.`,type:`boolean`,default:!1}).option(`stdout`,{description:`Print the JSON instead of writing it.`,type:`boolean`,default:!1}).conflicts(`check`,`stdout`),handler:async t=>{let n=process.cwd();try{let S=(await new Config().forCommand(n)).credits??{},C=Nn(n,t.output??S.output??OK),N=t.overrides??S.overrides,F=Nn(n,N??kK),I;if(existsSync(F))I=parseOverrides(readFileSync(F,`utf8`),N??kK);else if(N!==void 0)throw Error(`cannot read the overrides file ${N}`);let H=buildCredits(readCommits(n),{ignore:S.ignore??bK,overrides:I}),W=serializeCredits(H);if(t.stdout===!0)process.stdout.write(W);else if(t.check===!0){let n=existsSync(C)?readFileSync(C,`utf8`):null;if(isStale(n,H))return process.stderr.write(`gjsify credits: ${t.output??S.output??OK} is ${n===null?`missing`:`stale`}; run \`gjsify credits\` and commit it\n`),process.exit(1)}else writeFileSync(C,W)}catch(t){return process.stderr.write(`gjsify credits: ${t instanceof Error?t.message:String(t)}\n`),process.exit(1)}}}}),MK,NK=__esmMin(()=>{gh(),pB(),MK={command:`whoami`,description:`Print the npm-registry username for the current ~/.npmrc token. Clear failure message when the token is dead, missing, or the registry is unreachable.`,builder:t=>t.option(`registry`,{description:`Registry URL to probe. Default: scope-aware lookup from .npmrc (falls back to ${lh}).`,type:`string`}).option(`json`,{description:"Emit `{username, registry}` (or `{error, registry}`) as a single-line JSON object.",type:`boolean`,default:!1}),handler:async t=>{let n=await loadNpmrc(process.cwd()),S=t.registry??process.env.npm_config_registry??n.registry??lh,C=S.endsWith(`/`)?S.slice(0,-1):S,N=t.json===!0;if(!hasAnyCredential(n))return N?process.stdout.write(`${JSON.stringify({error:`no-token-configured`,registry:C})}\n`):process.stderr.write([`gjsify whoami: no npm token configured.`,``,`No \`_authToken\` found in ~/.npmrc / $NPM_CONFIG_USERCONFIG / .npmrc for ${C}.`,``,`Add one via: npm login`,`Then verify: gjsify whoami`].join(`
1241
+ `).filter(Boolean);if(N.length!==C.length)throw Error(`git check-mailmap answered a different number of lines`);let F=new Map(C.map((t,n)=>[t,parsePerson(N[n])]));for(let t of n)t.coAuthors=t.coAuthors.map(t=>t.email?F.get(`${t.name} <${t.email}>`):t)}function readCommits(t){if(git(t,[`rev-parse`,`--is-shallow-repository`]).trim()===`true`)throw Error(`the repository is a shallow clone; fetch the full history first (git fetch --unshallow)`);let n=parseGitLog(git(t,TK));return mapTrailers(t,n),n}function asStringList(t,n){if(!Array.isArray(t)||t.some(t=>typeof t!=`string`))throw Error(`${n} must be an array of strings`);return t}function parseOverrides(t,n=`overrides`){let S;try{S=JSON.parse(t)}catch(t){throw Error(`${n} is not valid JSON: ${t instanceof Error?t.message:String(t)}`)}if(typeof S!=`object`||!S||Array.isArray(S))throw Error(`${n} must be a JSON object`);let C=S,N=new Set([...EK,...DK]);for(let t of Object.keys(C))if(!N.has(t))throw Error(`${n} has an unknown key "${t}" (known: ${[...N].join(`, `)})`);let F={};for(let t of EK)C[t]!==void 0&&(F[t]=asStringList(C[t],`${n}.${t}`));for(let t of DK){let S=C[t];if(S===void 0)continue;if(typeof S!=`object`||!S||Array.isArray(S))throw Error(`${n}.${t} must map a language to an array of names`);let N={};for(let[C,F]of Object.entries(S))N[C]=asStringList(F,`${n}.${t}.${C}`);F[t]=N}return F}function serializeCredits(t){return JSON.stringify(t,null,2)+`
1242
+ `}function isStale(t,n){if(t===null)return!0;try{return JSON.stringify(JSON.parse(t))!==JSON.stringify(n)}catch{return!0}}var xK,SK,CK,wK,isTranslationFile,TK,EK,DK,OK=__esmMin(()=>{ev(),qn(),xK=[`*[bot]`,`github-actions`,`Weblate`,`Weblate (bot)`,`Hosted Weblate`,`Weblate Translation Memory`,`LibreTranslate`,`Claude`,`*@anthropic.com`,`noreply-mt-*@weblate.org`,`hosted@weblate.org`,`*[bot]@users.noreply.github.com`],SK=``,CK=``,wK=``,isTranslationFile=t=>/\.pot?$/i.test(t),TK=[`-c`,`core.quotepath=off`,`log`,`--no-merges`,`--use-mailmap`,`--name-only`,`--format=${CK}%aN${SK}%aE${SK}%(trailers:key=Co-authored-by,valueonly,unfold,separator=%x1d)${SK}`],EK=[`developers`,`supporters`,`exclude`],DK=[`translators`,`excludeTranslators`]}),kK,AK,jK,MK=__esmMin(()=>{rR(),OK(),ef(),qn(),kK=`credits.json`,AK=`credits.overrides.json`,jK={command:`credits`,description:`Write the project’s contributors (developers, translators per language) from the git history as JSON, names only.`,builder:t=>t.option(`output`,{alias:`o`,description:`File to write. Default: \`gjsify.credits.output\`, else ${kK}.`,type:`string`}).option(`overrides`,{description:`Hand-kept additions and exclusions. Default: \`gjsify.credits.overrides\`, else ${AK} when it exists.`,type:`string`}).option(`check`,{description:`Write nothing; exit 1 when the file on disk differs from what the history gives.`,type:`boolean`,default:!1}).option(`stdout`,{description:`Print the JSON instead of writing it.`,type:`boolean`,default:!1}).conflicts(`check`,`stdout`),handler:async t=>{let n=process.cwd();try{let S=(await new Config().forCommand(n)).credits??{},C=Nn(n,t.output??S.output??kK),N=t.overrides??S.overrides,F=Nn(n,N??AK),I;if(existsSync(F))I=parseOverrides(readFileSync(F,`utf8`),N??AK);else if(N!==void 0)throw Error(`cannot read the overrides file ${N}`);let H=buildCredits(readCommits(n),{ignore:S.ignore??xK,overrides:I}),W=serializeCredits(H);if(t.stdout===!0)process.stdout.write(W);else if(t.check===!0){let n=existsSync(C)?readFileSync(C,`utf8`):null;if(isStale(n,H))return process.stderr.write(`gjsify credits: ${t.output??S.output??kK} is ${n===null?`missing`:`stale`}; run \`gjsify credits\` and commit it\n`),process.exit(1)}else writeFileSync(C,W)}catch(t){return process.stderr.write(`gjsify credits: ${t instanceof Error?t.message:String(t)}\n`),process.exit(1)}}}}),NK,PK=__esmMin(()=>{gh(),pB(),NK={command:`whoami`,description:`Print the npm-registry username for the current ~/.npmrc token. Clear failure message when the token is dead, missing, or the registry is unreachable.`,builder:t=>t.option(`registry`,{description:`Registry URL to probe. Default: scope-aware lookup from .npmrc (falls back to ${lh}).`,type:`string`}).option(`json`,{description:"Emit `{username, registry}` (or `{error, registry}`) as a single-line JSON object.",type:`boolean`,default:!1}),handler:async t=>{let n=await loadNpmrc(process.cwd()),S=t.registry??process.env.npm_config_registry??n.registry??lh,C=S.endsWith(`/`)?S.slice(0,-1):S,N=t.json===!0;if(!hasAnyCredential(n))return N?process.stdout.write(`${JSON.stringify({error:`no-token-configured`,registry:C})}\n`):process.stderr.write([`gjsify whoami: no npm token configured.`,``,`No \`_authToken\` found in ~/.npmrc / $NPM_CONFIG_USERCONFIG / .npmrc for ${C}.`,``,`Add one via: npm login`,`Then verify: gjsify whoami`].join(`
1243
1243
  `)+`
1244
1244
  `),process.exit(1);let F;try{F=await whoami(S,n)}catch(t){let n=t instanceof Error?t.message:String(t);return N?process.stdout.write(`${JSON.stringify({error:n,registry:C})}\n`):(process.stderr.write(`gjsify whoami: ${n}\n`),process.stderr.write(`Registry: ${C}\n`)),process.exit(1)}if(F.username&&F.username.length>0){N?process.stdout.write(`${JSON.stringify({username:F.username,registry:C})}\n`):(process.stdout.write(`Logged in as: ${F.username}\n`),process.stdout.write(`Registry: ${C}\n`));return}N?process.stdout.write(`${JSON.stringify({error:`dead-token`,registry:C})}\n`):process.stderr.write([`gjsify whoami: token appears dead or revoked (registry returned an empty whoami response).`,``,`Refresh via: npm login`,`Then verify: gjsify whoami`,``,`For the @gjsify scope, see AGENTS.md > "New @gjsify/* package: first-publish + Trusted Publisher bootstrap".`].join(`
1245
1245
  `)+`
@@ -1248,12 +1248,12 @@ ${t?` <monochrome android:drawable="@mipmap/ic_launcher_monochrome"/>
1248
1248
  `)+`
1249
1249
  `),S}function removeAuthToken(t){let n=userconfigNpmrcPath(),S=authTokenKey(t),C=readUserconfig(n);if(!C)return{path:n,removed:!1};let N=C.split(`
1250
1250
  `),F=N.filter(t=>!t.replace(/\s+/g,``).startsWith(`${S}=`)),I=F.length!==N.length;return I&&writeUserconfig(n,F.join(`
1251
- `)),{path:n,removed:I}}var PK=__esmMin(()=>{ef(),$g(),qn()});async function runLogin(t){let n=await loadNpmrc(t.cwd??process.cwd()),S=t.registry??process.env.npm_config_registry??(t.scope?registryFor(t.scope.startsWith(`@`)?`${t.scope}/_`:`@${t.scope}/_`,n):void 0)??lh,C=S.endsWith(`/`)?S:`${S}/`,{username:N,password:F}=await promptCredentials(t.username);if(!N)throw new LoginError(`gjsify login: a username is required.`);if(!F)throw new LoginError(`gjsify login: a password is required.`);let I=`Basic ${btoa(`${N}:${F}`)}`,H=`${C}-/user/org.couchdb.user:${encodeURIComponent(N)}`,W={_id:`org.couchdb.user:${N}`,name:N,password:F,type:`user`,roles:[],date:void 0};function authHeaders(t){let n={authorization:I,"content-type":`application/json`,accept:`*/*`};return t&&(n[`npm-otp`]=t),n}async function putUser(t,n){return fetch(`${H}${t}`,{method:`PUT`,headers:authHeaders(n),body:JSON.stringify(W)})}let q=typeof t.otp==`string`&&t.otp.length>0,Y=t.otp??readCachedOtp(C),X=await putUser(``,Y);if(X.status===401&&!q){let t=(X.headers.get(`www-authenticate`)??``).toLowerCase(),n=await X.clone().text().catch(()=>``);if(t.includes(`otp`)||/one-time pass/i.test(n)){if(clearCachedOtp(C),Y=await promptLine(`This operation requires a one-time password.
1252
- Enter OTP: `),!Y)throw new LoginError(`gjsify login: no OTP entered.`);writeCachedOtp(C,Y),X=await putUser(``,Y)}}if(X.status===409){let t=await fetch(`${H}?write=true`,{headers:authHeaders(Y)});if(t.ok){let n=await t.json().catch(()=>({}));for(let t of Object.keys(n))(!W[t]||t===`roles`)&&(W[t]=n[t]);W._rev&&(X=await putUser(`/-rev/${W._rev}`,Y))}}if(X.status===400)throw new LoginError(`gjsify login: there is no user with the username "${N}" on ${C}.`);if(!X.ok){let t=await X.text().catch(()=>`<no body>`);throw new LoginError(`gjsify login: ${X.status} ${X.statusText} from ${C}\n${t.slice(0,400)}`)}let Z=await X.json().catch(()=>({}));if(!Z.token)throw new LoginError("gjsify login: the registry accepted the login but returned no token (unexpected response shape). Your registry may require the web-OAuth flow — use `npm login`.");let te=writeAuthToken(C,Z.token);return Y&&writeCachedOtp(C,Y),{username:(await whoami(C,await loadNpmrc(t.cwd??process.cwd()))).username??N,registry:C,npmrcPath:te}}var LoginError,FK,IK=__esmMin(()=>{_e(),gh(),pB(),PK(),QG(),tK(),LoginError=class extends Error{constructor(t){super(t),this.name=`LoginError`}},FK={command:`login`,description:"Log in to an npm registry (Node-free `npm login`). Prompts for username + password (hidden) and writes the token to ~/.npmrc. Use --otp for 2FA. Web-OAuth flow is not supported — this is npm's legacy credentials flow.",builder:t=>t.option(`registry`,{description:`Registry URL to log in to. Default: ${lh} (or a --scope's registry).`,type:`string`}).option(`scope`,{description:`Associate the login with a scope (e.g. @gjsify) — resolves that scope's registry from .npmrc.`,type:`string`}).option(`username`,{description:`Username (prompted if omitted).`,type:`string`}).option(`otp`,{description:`npm 2FA one-time code (prompted on demand if omitted).`,type:`string`}).option(`json`,{description:"Emit `{username, registry}` JSON on success.",type:`boolean`}),handler:async t=>{try{let{username:n,registry:S,npmrcPath:C}=await runLogin({registry:t.registry,scope:t.scope,username:t.username,otp:t.otp});t.json?process.stdout.write(`${JSON.stringify({username:n,registry:S})}\n`):process.stdout.write(`Logged in as ${n} on ${S}\n(token written to ${C})\n`)}catch(t){if(t instanceof LoginError)return ge.error(t.message),process.exit(1);throw t}}}}),LK,RK=__esmMin(()=>{gh(),pB(),PK(),tK(),LK={command:`logout`,description:"Log out of an npm registry (Node-free `npm logout`). Revokes the token on the registry (best-effort) and removes it from ~/.npmrc.",builder:t=>t.option(`registry`,{description:`Registry URL to log out of. Default: ${lh} (or a --scope's registry).`,type:`string`}).option(`scope`,{description:`Log out of a scope's registry (e.g. @gjsify) — resolved from .npmrc.`,type:`string`}).option(`json`,{description:"Emit `{registry, revoked, removed}` JSON.",type:`boolean`}),handler:async t=>{let n=await loadNpmrc(process.cwd()),S=t.registry??process.env.npm_config_registry??(t.scope?registryFor(t.scope.startsWith(`@`)?`${t.scope}/_`:`@${t.scope}/_`,n):void 0)??lh,C=S.endsWith(`/`)?S:`${S}/`,N=resolveAuthForUrl(`${C}-/whoami`,n),F=!1;if(N?.startsWith(`Bearer `)){let t=N.slice(7);try{F=(await fetch(`${C}-/user/token/${encodeURIComponent(t)}`,{method:`DELETE`,headers:{authorization:N,accept:`*/*`}})).ok}catch{}}clearCachedOtp(C);let{path:I,removed:H}=removeAuthToken(C);t.json?process.stdout.write(`${JSON.stringify({registry:C,revoked:F,removed:H})}\n`):H?process.stdout.write(`Logged out of ${C}${F?` (token revoked)`:``}\n(removed from ${I})\n`):process.stdout.write(`No token for ${C} found in ${I} — nothing to remove.\n`)}}});function discoverNonWorkspacePublishables(t){let n=t,S=zK[0];for(let t=0;t<8&&!existsSync(In(n,...S));t++){let t=zn(n);if(t===n)return[];n=t}let C=[];for(let t of zK){let S=In(n,...t);if(!existsSync(S))continue;let N;try{N=readdirSync(S,{withFileTypes:!0})}catch{continue}for(let n of N){if(!n.isDirectory())continue;let N=In(S,n.name),F=In(N,`package.json`);if(existsSync(F))try{let S=JSON.parse(readFileSync(F,`utf8`));if(!S||typeof S.name!=`string`||S.name.length===0)continue;C.push({location:N,relativeLocation:In(...t,n.name),name:S.name,version:typeof S.version==`string`?S.version:`0.0.0`,manifest:S,private:S.private===!0})}catch{}}}return C}function mergePublishables(t,n){let S=new Set(t.map(t=>t.name));return[...t,...discoverNonWorkspacePublishables(n).filter(t=>!S.has(t.name))]}var zK,BK=__esmMin(()=>{ef(),qn(),zK=[[`packages`,`node-gi`],[`packages`,`napi`],[`packages`,`node-runtime`]]});function trustUrl(t,n){return`${t.endsWith(`/`)?t.slice(0,-1):t}/-/package/${escapePackageName(n)}/trust`}function githubTrustBody(t){let n={repository:t.repository,workflow_ref:{file:normalizeWorkflowFile(t.workflow)}};return t.environment&&(n.environment=t.environment),[{type:`github`,claims:n,permissions:t.permissions&&t.permissions.length>0?t.permissions:[VK]}]}function normalizeWorkflowFile(t){return t.split(`/`).pop()??t}function validateRepository(t){let n=t.split(`/`);return n.length===2&&n[0].length>0&&n[1].length>0}function matchesGithubTrust(t,n){if(t.type!==`github`)return!1;let S=t.claims?.repository,C=t.claims?.workflow_ref?.file;return S===n.repository&&C===normalizeWorkflowFile(n.workflow)}function classifyTrustList(t,n,S){return t===404?`unpublished`:t===401?`auth-required`:t>=200&&t<300?(Array.isArray(n)?n:[]).some(t=>matchesGithubTrust(t,S))?`trusted`:`untrusted`:`error`}function parseRepoFromGitRemote(t){let n=t.trim();if(!n)return null;n=n.replace(/^git\+/,``),n=n.replace(/\.git$/,``);let S=n.match(/^[^/@]+@[^:]+:(.+)$/);if(S)return twoSegments(S[1]);let C=n.match(/^[a-z]+:\/\/[^/]+\/(.+)$/i);return C?twoSegments(C[1]):null}function twoSegments(t){let n=t.split(`/`).filter(t=>t.length>0);return n.length<2?null:`${n[n.length-2]}/${n[n.length-1]}`}var VK,HK=__esmMin(()=>{yh(),VK=`createPackage`});function createTrustRequester(t){return async(n,S,C)=>{let doFetch=N=>{let F=buildHeaders(S,{npmrc:t.npmrc});F.accept=`application/json`,C!==void 0&&(F[`content-type`]=`application/json`),N&&(F[`npm-otp`]=N);let I={method:n,headers:F};return C!==void 0&&(I.body=JSON.stringify(C)),fetch(S,I)},N=await withOtpRetry(doFetch,t.otpProvider),F=await N.text().catch(()=>``),I;try{I=F?JSON.parse(F):void 0}catch{}return{status:N.status,json:I,text:F,headers:N.headers}}}function firstLine(t){return t.split(`
1253
- `)[0].slice(0,200)}var UK,WK=__esmMin(()=>{_e(),ev(),ef(),qn(),gh(),AI(),BK(),pB(),iK(),HK(),UK={command:`trust [packages..]`,description:"Configure npm Trusted Publishers (OIDC/GitHub Actions) for publishable workspace packages so release.yml can publish without a token. Native — no `npm` needed. Incremental: skips already-configured packages.",builder:t=>t.positional(`packages`,{description:`Optional package-name globs to limit the sweep (default: all publishable workspaces).`,type:`string`,array:!0}).option(`repository`,{description:"GitHub repo as `owner/repo`. Default: inferred from the `origin` git remote.",type:`string`}).option(`workflow`,{description:`Workflow filename allowed to publish (basename only).`,type:`string`,default:`release.yml`}).option(`environment`,{description:`Optional GitHub Actions environment the workflow must run in.`,type:`string`}).option(`registry`,{description:`Registry override. Default: scope-aware lookup from .npmrc (falls back to ${lh}).`,type:`string`}).option(`otp`,{description:"npm 2FA one-time code; sent as `npm-otp`. Prompted on demand if omitted.",type:`string`}).option(`dry-run`,{description:`List what would be configured without writing anything.`,type:`boolean`,default:!1}).option(`force`,{description:`Re-POST the config even for packages already trusted for this repo+workflow.`,type:`boolean`,default:!1}).option(`list`,{description:`Only report each package’s current trust state; configure nothing.`,type:`boolean`,default:!1}).option(`private`,{description:`Include private workspaces (default false — private packages are not publishable).`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=await loadNpmrc(n);if(!hasAnyCredential(S))return ge.error("gjsify trust: no npm token configured. Run `gjsify login` first."),process.exit(1);let C=t.registry??process.env.npm_config_registry??S.registry??lh;if(t[`dry-run`]!==!0){let t;try{t=await whoami(C,S)}catch(t){let n=t instanceof Error?t.message:String(t);return ge.error(`gjsify trust: npm auth check failed (${n}).\nYour ~/.npmrc token is dead or revoked — refresh it with \`npm login\`, then re-run.
1251
+ `)),{path:n,removed:I}}var FK=__esmMin(()=>{ef(),$g(),qn()});async function runLogin(t){let n=await loadNpmrc(t.cwd??process.cwd()),S=t.registry??process.env.npm_config_registry??(t.scope?registryFor(t.scope.startsWith(`@`)?`${t.scope}/_`:`@${t.scope}/_`,n):void 0)??lh,C=S.endsWith(`/`)?S:`${S}/`,{username:N,password:F}=await promptCredentials(t.username);if(!N)throw new LoginError(`gjsify login: a username is required.`);if(!F)throw new LoginError(`gjsify login: a password is required.`);let I=`Basic ${btoa(`${N}:${F}`)}`,H=`${C}-/user/org.couchdb.user:${encodeURIComponent(N)}`,W={_id:`org.couchdb.user:${N}`,name:N,password:F,type:`user`,roles:[],date:void 0};function authHeaders(t){let n={authorization:I,"content-type":`application/json`,accept:`*/*`};return t&&(n[`npm-otp`]=t),n}async function putUser(t,n){return fetch(`${H}${t}`,{method:`PUT`,headers:authHeaders(n),body:JSON.stringify(W)})}let q=typeof t.otp==`string`&&t.otp.length>0,Y=t.otp??readCachedOtp(C),X=await putUser(``,Y);if(X.status===401&&!q){let t=(X.headers.get(`www-authenticate`)??``).toLowerCase(),n=await X.clone().text().catch(()=>``);if(t.includes(`otp`)||/one-time pass/i.test(n)){if(clearCachedOtp(C),Y=await promptLine(`This operation requires a one-time password.
1252
+ Enter OTP: `),!Y)throw new LoginError(`gjsify login: no OTP entered.`);writeCachedOtp(C,Y),X=await putUser(``,Y)}}if(X.status===409){let t=await fetch(`${H}?write=true`,{headers:authHeaders(Y)});if(t.ok){let n=await t.json().catch(()=>({}));for(let t of Object.keys(n))(!W[t]||t===`roles`)&&(W[t]=n[t]);W._rev&&(X=await putUser(`/-rev/${W._rev}`,Y))}}if(X.status===400)throw new LoginError(`gjsify login: there is no user with the username "${N}" on ${C}.`);if(!X.ok){let t=await X.text().catch(()=>`<no body>`);throw new LoginError(`gjsify login: ${X.status} ${X.statusText} from ${C}\n${t.slice(0,400)}`)}let Z=await X.json().catch(()=>({}));if(!Z.token)throw new LoginError("gjsify login: the registry accepted the login but returned no token (unexpected response shape). Your registry may require the web-OAuth flow — use `npm login`.");let te=writeAuthToken(C,Z.token);return Y&&writeCachedOtp(C,Y),{username:(await whoami(C,await loadNpmrc(t.cwd??process.cwd()))).username??N,registry:C,npmrcPath:te}}var LoginError,IK,LK=__esmMin(()=>{_e(),gh(),pB(),FK(),$G(),nK(),LoginError=class extends Error{constructor(t){super(t),this.name=`LoginError`}},IK={command:`login`,description:"Log in to an npm registry (Node-free `npm login`). Prompts for username + password (hidden) and writes the token to ~/.npmrc. Use --otp for 2FA. Web-OAuth flow is not supported — this is npm's legacy credentials flow.",builder:t=>t.option(`registry`,{description:`Registry URL to log in to. Default: ${lh} (or a --scope's registry).`,type:`string`}).option(`scope`,{description:`Associate the login with a scope (e.g. @gjsify) — resolves that scope's registry from .npmrc.`,type:`string`}).option(`username`,{description:`Username (prompted if omitted).`,type:`string`}).option(`otp`,{description:`npm 2FA one-time code (prompted on demand if omitted).`,type:`string`}).option(`json`,{description:"Emit `{username, registry}` JSON on success.",type:`boolean`}),handler:async t=>{try{let{username:n,registry:S,npmrcPath:C}=await runLogin({registry:t.registry,scope:t.scope,username:t.username,otp:t.otp});t.json?process.stdout.write(`${JSON.stringify({username:n,registry:S})}\n`):process.stdout.write(`Logged in as ${n} on ${S}\n(token written to ${C})\n`)}catch(t){if(t instanceof LoginError)return ge.error(t.message),process.exit(1);throw t}}}}),RK,zK=__esmMin(()=>{gh(),pB(),FK(),nK(),RK={command:`logout`,description:"Log out of an npm registry (Node-free `npm logout`). Revokes the token on the registry (best-effort) and removes it from ~/.npmrc.",builder:t=>t.option(`registry`,{description:`Registry URL to log out of. Default: ${lh} (or a --scope's registry).`,type:`string`}).option(`scope`,{description:`Log out of a scope's registry (e.g. @gjsify) — resolved from .npmrc.`,type:`string`}).option(`json`,{description:"Emit `{registry, revoked, removed}` JSON.",type:`boolean`}),handler:async t=>{let n=await loadNpmrc(process.cwd()),S=t.registry??process.env.npm_config_registry??(t.scope?registryFor(t.scope.startsWith(`@`)?`${t.scope}/_`:`@${t.scope}/_`,n):void 0)??lh,C=S.endsWith(`/`)?S:`${S}/`,N=resolveAuthForUrl(`${C}-/whoami`,n),F=!1;if(N?.startsWith(`Bearer `)){let t=N.slice(7);try{F=(await fetch(`${C}-/user/token/${encodeURIComponent(t)}`,{method:`DELETE`,headers:{authorization:N,accept:`*/*`}})).ok}catch{}}clearCachedOtp(C);let{path:I,removed:H}=removeAuthToken(C);t.json?process.stdout.write(`${JSON.stringify({registry:C,revoked:F,removed:H})}\n`):H?process.stdout.write(`Logged out of ${C}${F?` (token revoked)`:``}\n(removed from ${I})\n`):process.stdout.write(`No token for ${C} found in ${I} — nothing to remove.\n`)}}});function discoverNonWorkspacePublishables(t){let n=t,S=BK[0];for(let t=0;t<8&&!existsSync(In(n,...S));t++){let t=zn(n);if(t===n)return[];n=t}let C=[];for(let t of BK){let S=In(n,...t);if(!existsSync(S))continue;let N;try{N=readdirSync(S,{withFileTypes:!0})}catch{continue}for(let n of N){if(!n.isDirectory())continue;let N=In(S,n.name),F=In(N,`package.json`);if(existsSync(F))try{let S=JSON.parse(readFileSync(F,`utf8`));if(!S||typeof S.name!=`string`||S.name.length===0)continue;C.push({location:N,relativeLocation:In(...t,n.name),name:S.name,version:typeof S.version==`string`?S.version:`0.0.0`,manifest:S,private:S.private===!0})}catch{}}}return C}function mergePublishables(t,n){let S=new Set(t.map(t=>t.name));return[...t,...discoverNonWorkspacePublishables(n).filter(t=>!S.has(t.name))]}var BK,VK=__esmMin(()=>{ef(),qn(),BK=[[`packages`,`node-gi`],[`packages`,`napi`],[`packages`,`node-runtime`]]});function trustUrl(t,n){return`${t.endsWith(`/`)?t.slice(0,-1):t}/-/package/${escapePackageName(n)}/trust`}function githubTrustBody(t){let n={repository:t.repository,workflow_ref:{file:normalizeWorkflowFile(t.workflow)}};return t.environment&&(n.environment=t.environment),[{type:`github`,claims:n,permissions:t.permissions&&t.permissions.length>0?t.permissions:[HK]}]}function normalizeWorkflowFile(t){return t.split(`/`).pop()??t}function validateRepository(t){let n=t.split(`/`);return n.length===2&&n[0].length>0&&n[1].length>0}function matchesGithubTrust(t,n){if(t.type!==`github`)return!1;let S=t.claims?.repository,C=t.claims?.workflow_ref?.file;return S===n.repository&&C===normalizeWorkflowFile(n.workflow)}function classifyTrustList(t,n,S){return t===404?`unpublished`:t===401?`auth-required`:t>=200&&t<300?(Array.isArray(n)?n:[]).some(t=>matchesGithubTrust(t,S))?`trusted`:`untrusted`:`error`}function parseRepoFromGitRemote(t){let n=t.trim();if(!n)return null;n=n.replace(/^git\+/,``),n=n.replace(/\.git$/,``);let S=n.match(/^[^/@]+@[^:]+:(.+)$/);if(S)return twoSegments(S[1]);let C=n.match(/^[a-z]+:\/\/[^/]+\/(.+)$/i);return C?twoSegments(C[1]):null}function twoSegments(t){let n=t.split(`/`).filter(t=>t.length>0);return n.length<2?null:`${n[n.length-2]}/${n[n.length-1]}`}var HK,UK=__esmMin(()=>{yh(),HK=`createPackage`});function createTrustRequester(t){return async(n,S,C)=>{let doFetch=N=>{let F=buildHeaders(S,{npmrc:t.npmrc});F.accept=`application/json`,C!==void 0&&(F[`content-type`]=`application/json`),N&&(F[`npm-otp`]=N);let I={method:n,headers:F};return C!==void 0&&(I.body=JSON.stringify(C)),fetch(S,I)},N=await withOtpRetry(doFetch,t.otpProvider),F=await N.text().catch(()=>``),I;try{I=F?JSON.parse(F):void 0}catch{}return{status:N.status,json:I,text:F,headers:N.headers}}}function firstLine(t){return t.split(`
1253
+ `)[0].slice(0,200)}var WK,GK=__esmMin(()=>{_e(),ev(),ef(),qn(),gh(),AI(),VK(),pB(),aK(),UK(),WK={command:`trust [packages..]`,description:"Configure npm Trusted Publishers (OIDC/GitHub Actions) for publishable workspace packages so release.yml can publish without a token. Native — no `npm` needed. Incremental: skips already-configured packages.",builder:t=>t.positional(`packages`,{description:`Optional package-name globs to limit the sweep (default: all publishable workspaces).`,type:`string`,array:!0}).option(`repository`,{description:"GitHub repo as `owner/repo`. Default: inferred from the `origin` git remote.",type:`string`}).option(`workflow`,{description:`Workflow filename allowed to publish (basename only).`,type:`string`,default:`release.yml`}).option(`environment`,{description:`Optional GitHub Actions environment the workflow must run in.`,type:`string`}).option(`registry`,{description:`Registry override. Default: scope-aware lookup from .npmrc (falls back to ${lh}).`,type:`string`}).option(`otp`,{description:"npm 2FA one-time code; sent as `npm-otp`. Prompted on demand if omitted.",type:`string`}).option(`dry-run`,{description:`List what would be configured without writing anything.`,type:`boolean`,default:!1}).option(`force`,{description:`Re-POST the config even for packages already trusted for this repo+workflow.`,type:`boolean`,default:!1}).option(`list`,{description:`Only report each package’s current trust state; configure nothing.`,type:`boolean`,default:!1}).option(`private`,{description:`Include private workspaces (default false — private packages are not publishable).`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=await loadNpmrc(n);if(!hasAnyCredential(S))return ge.error("gjsify trust: no npm token configured. Run `gjsify login` first."),process.exit(1);let C=t.registry??process.env.npm_config_registry??S.registry??lh;if(t[`dry-run`]!==!0){let t;try{t=await whoami(C,S)}catch(t){let n=t instanceof Error?t.message:String(t);return ge.error(`gjsify trust: npm auth check failed (${n}).\nYour ~/.npmrc token is dead or revoked — refresh it with \`npm login\`, then re-run.
1254
1254
  (\`gjsify trust\` uses the ~/.npmrc bearer token directly — unlike \`npm trust\`, which logs in via the browser.)`),process.exit(1)}if(!t.username)return ge.error("gjsify trust: your npm token appears dead or revoked (registry returned an empty whoami).\nRefresh it with `npm login`, then re-run."),process.exit(1);ge.log(`gjsify trust: authenticated as ${t.username}`)}let N=t.repository;if(!N){let t=spawnSync(`git`,[`remote`,`get-url`,`origin`],{cwd:n,encoding:`utf8`});t.status===0&&(N=parseRepoFromGitRemote(t.stdout)??void 0)}if(!N)return ge.error("gjsify trust: could not determine the GitHub repository.\nPass --repository owner/repo (no `origin` remote to infer from)."),process.exit(1);if(!validateRepository(N))return ge.error(`gjsify trust: --repository must be "owner/repo", got "${N}".`),process.exit(1);let F=normalizeWorkflowFile(t.workflow),I=t.environment,H=t.list===!0,W=t[`dry-run`]===!0,q=t.force===!0,Y=In(n,`.github`,`workflows`,F);existsSync(Y)||ge.warn(`gjsify trust: note — ${Y} not found; configuring trust for "${F}" anyway.`);let X=filterWorkspaces(mergePublishables(discoverWorkspaces(n,{includeRoot:!0}),n),{noPrivate:t.private!==!0,include:t.packages&&t.packages.length>0?t.packages:void 0}).filter(t=>t.name);if(X.length===0)return ge.error(`gjsify trust: no publishable packages matched.`),process.exit(1);ge.log(`gjsify trust: ${X.length} package(s) | repo=${N} workflow=${F}`),W&&ge.log(`(dry-run — nothing will be written)`),ge.log();let Z=createTrustRequester({npmrc:S,otpProvider:new OtpProvider(t.otp)}),te=0,ne=0,re=0,ie=0,ae=[],oe=[];for(let n of X){let C=n.name,Y=trustUrl(t.registry??registryFor(C,S)??lh,C);process.stdout.write(`→ ${C.padEnd(42)} `);let X=await Z(`GET`,Y),Q=classifyTrustList(X.status,X.json,{repository:N,workflow:F});if(H){Q===`trusted`?ge.log(`trusted`):Q===`unpublished`?ge.log(`unpublished`):Q===`auth-required`?ge.log(`auth-required (could not read)`):Q===`untrusted`?ge.log(`not trusted`):ge.log(`error (HTTP ${X.status})`);continue}if(Q===`trusted`&&!q){ge.log(`already configured — skip`),ne++;continue}if(Q===`unpublished`){ge.log(`not on npm yet — needs first-publish, skip`),re++,ae.push(C);continue}if(W){ge.log(`would configure`),te++;continue}let se=await Z(`POST`,Y,githubTrustBody({repository:N,workflow:F,environment:I}));se.status>=200&&se.status<300?(ge.log(`configured`),te++):se.status===409?(ge.log(`already configured (409) — done`),ne++):se.status===404?(ge.log(`not on npm yet — needs first-publish, skip`),re++,ae.push(C)):(ge.log(`FAILED (HTTP ${se.status})`),ie++,oe.push(`${C} — HTTP ${se.status}${se.text?`: ${firstLine(se.text)}`:``}`))}if(!H){if(ge.log(),ge.log(`Done: ${te} ${W?`would-configure`:`configured`}, ${ne} already-configured, ${re} unpublished, ${ie} failed.`),ae.length>0){ge.log("Need a first publish before they can be trust-configured (then re-run `gjsify trust`):");for(let t of ae)ge.log(` ${t}`)}if(oe.length>0){ge.log("Failed (re-run `gjsify trust` — it is incremental; usually a lapsed 2FA window or rate-limit):");for(let t of oe)ge.log(` ${t}`);process.exit(1)}}}}});function resolveRepoRoot(t){let n=findWorkspaceRoot(t);if(n)return n;let S=spawnSync(`git`,[`rev-parse`,`--show-toplevel`],{cwd:t,encoding:`utf8`});if(S.status===0){let t=S.stdout.trim();if(t&&existsSync(t))return t}return t}function assertEveryPatternMatches(t,n){let S=n.filter(n=>{try{return discoverWorkspaces(t,{patterns:[n]}).length===0}catch{return!0}});if(S.length===0)return;let C=[`gjsify onboard: --packages matched no package directory (${S.length} of ${n.length} pattern(s)) under ${t}:`];for(let t of S)C.push(` ${JSON.stringify(t)}`);throw C.push(" Patterns are DIRECTORY globs resolved against the repo root, and only `*` is supported",` (one path segment). A matched directory needs a package.json with a "name".`),Error(C.join(`
1255
1255
  `))}function collectOnboardPackages(t,n,S={}){let C=[],N=[],F=new Set,take=(t,n,S)=>{let I=0;for(let t of n)!t.name||F.has(t.name)||(F.add(t.name),N.push(t),I++);C.push({kind:t,patterns:S,count:I})};if(existsSync(In(t,`package.json`)))try{take(`workspaces`,discoverWorkspaces(t,{includeRoot:!0}))}catch{}return S.patterns&&S.patterns.length>0&&take(`packages`,discoverWorkspaces(t,{patterns:[...S.patterns]}),S.patterns),take(`scanned-dirs`,mergePublishables([],n)),{packages:N,sources:C}}function describeSources(t){return t.filter(t=>t.count>0).map(t=>t.patterns?`${t.kind}(${t.patterns.join(`,`)})=${t.count}`:`${t.kind}=${t.count}`).join(` + `)}function declaredRepository(t){let n=t.manifest.repository,S=typeof n==`string`?n:n?.url;return typeof S!=`string`||S.length===0?null:parseRepoFromGitRemote(S)}function assertRepositoryAgreement(t,n){let S=n.toLowerCase(),C=t.map(t=>({ws:t,declared:declaredRepository(t)})).filter(t=>t.declared!==null&&t.declared.toLowerCase()!==S);if(C.length===0)return;let N=new Map;for(let{ws:t,declared:n}of C){let S=N.get(n)??[];S.push(t.name),N.set(n,S)}let F=[`gjsify onboard: ${C.length} selected package(s) declare a DIFFERENT repository than ${n}:`];for(let[t,n]of N){let S=n.slice(0,5).join(`, `),C=n.length>5?`, … (+${n.length-5} more)`:``;F.push(` ${t}: ${n.length} package(s) — ${S}${C}`)}throw F.push(` A Trusted Publisher scoped to the wrong repository points that package's OIDC exchange`,` at a workflow that does not publish it, which breaks the release this sweep protects.`,` Either exclude them (--exclude), select only what belongs here (--include), or point`,` --repository at the repo that actually publishes them.`),Error(F.join(`
1256
- `))}var GK=__esmMin(()=>{ef(),ev(),AI(),qn(),BK(),HK(),MI()});function describeRateLimitHeaders(t){if(!t)return`no headers captured`;let n=[];return t.forEach((t,S)=>{(/^retry-after$/i.test(S)||/ratelimit/i.test(S))&&n.push(`${S}: ${t}`)}),n.length>0?n.join(`, `):`npm sent no Retry-After and no rate-limit headers`}function retryAfterMs(t){let n=t?.get(`retry-after`);if(!n)return null;let S=Number.parseInt(n.trim(),10);return!Number.isFinite(S)||S<0?null:S*1e3}async function packumentExists(t,n){let S=t.endsWith(`/`)?t.slice(0,-1):t;try{let t=await fetch(`${S}/${n.replace(`/`,`%2f`)}`,{method:`GET`,headers:{accept:`application/vnd.npm.install-v1+json`}});return t.status===404?!1:t.ok?!0:null}catch{return null}}function actionForState(t){switch(t){case`trusted`:return`skip`;case`untrusted`:return`trust`;case`unpublished`:return`publish-and-trust`;default:return`blocked`}}function defaultSleep(t){return new Promise(n=>setTimeout(n,t))}async function requestWaitingOutRateLimit(t,n,S,C,N={}){let F=N.sleep??defaultSleep,I=N.maxRateLimitWaitMs??3e5,H=N.rateLimitBaseDelayMs??2e3,W=N.gate;W&&await W.wait();let q=await t(n,S,C),Y=0;for(let X=0;q.status===429&&Y<I;X++){let Z=retryAfterMs(q.headers),te=Math.min(Z??H*2**X,KK),ne=Math.min(te,I-Y);N.onRateLimit?.({url:S,headers:describeRateLimitHeaders(q.headers),waitMs:ne,fromRetryAfter:Z!==null}),W?.penalize(ne),await(W?W.wait():F(ne)),Y+=ne,q=await t(n,S,C)}return q}async function probeTrustState(t,n,S,C={}){let N=S.registryOverride??registryFor(n.name,S.npmrc)??lh,F=trustUrl(N,n.name),I={repository:S.repository,workflow:S.workflow},H=C.sleep??defaultSleep,W=await requestWaitingOutRateLimit(t,`GET`,F,void 0,C),q=classifyTrustList(W.status,W.json,I);return q===`auth-required`&&C.retryOn401!==!1&&(await H(C.retryDelayMs??400),W=await t(`GET`,F),q=classifyTrustList(W.status,W.json,I)),(q===`untrusted`||q===`auth-required`)&&await(C.exists??packumentExists)(N,n.name)===!1&&(q=`unpublished`),{ws:n,registry:N,url:F,state:q,httpStatus:W.status,action:actionForState(q)}}async function probeAllTrustStates(t,n,S,C,N={}){if(n.length===0)return[];let F=n.length,I=0,report=t=>(I++,N.onProgress?.(I,F,t),t);return[report(await probeTrustState(t,n[0],C,N)),...await mapWithConcurrency(n.slice(1),Math.max(1,S),async n=>report(await probeTrustState(t,n,C,N)))]}async function mapWithConcurrency(t,n,S){let C=Array.from({length:t.length}),N=0,F=Array.from({length:Math.min(Math.max(1,n),t.length)},async()=>{for(;;){let n=N++;if(n>=t.length)return;C[n]=await S(t[n])}});return await Promise.all(F),C}var KK,RateLimitGate,qK=__esmMin(()=>{gh(),HK(),KK=6e4,RateLimitGate=class{until=0;now;sleeper;constructor(t={}){this.now=t.now??(()=>Date.now()),this.sleeper=t.sleep??defaultSleep}async wait(){let t=this.until-this.now();t>0&&await this.sleeper(t)}penalize(t){this.until=Math.max(this.until,this.now()+t)}remainingMs(){return Math.max(0,this.until-this.now())}}});function finish(t,n,S){let C=S.failed??0;if(S.asJson)process.stdout.write(`${JSON.stringify({ok:C===0,dryRun:S.dryRun,root:S.root,sources:S.sources,discovered:S.discovered,total:n.length,published:t.filter(t=>t.result===`published`||t.result===`published+trusted`).length,trusted:t.filter(t=>t.result===`trusted`||t.result===`published+trusted`).length,alreadyDone:t.filter(t=>t.result===`already-done`).length,failed:C,results:t},null,2)}\n`);else{let n=S.dryRun?C>0?`Dry-run INCOMPLETE — nothing changed, but ${C} package(s) had an unreadable state, so the plan above does not cover them. Authenticate (\`gjsify login\`) and re-run.`:`Dry-run complete — nothing changed.`:`Done: ${t.filter(t=>t.result.includes(`published`)).length} published, ${t.filter(t=>t.result===`trusted`||t.result===`published+trusted`).length} trusted, ${t.filter(t=>t.result===`already-done`).length} already done, ${C} failed.`;process.stdout.write(`\n${n}\n`)}process.exit(+(C>0))}function statusCell(t){switch(t.action){case`skip`:return`published✓ trusted✓`;case`trust`:return`published✓ trust… `;case`publish-and-trust`:return`publish… trust… `;case`blocked`:return`unreadable (${t.httpStatus})`}}async function ensureAuthenticated(t){let{npmrc:n,registry:S,cwd:C,nonInteractive:N,dryRun:F,otp:I,log:H}=t;if(hasAnyCredential(n))try{let t=await whoami(S,n);if(t.username)return t.username}catch{}if(F){H(`gjsify onboard: no live npm token — dry-run continues (state reads may be limited).`);return}if(N)throw Error("gjsify onboard: not authenticated and --yes was passed — run `gjsify login` first (or omit --yes to log in interactively).");H(`gjsify onboard: no live npm token — logging in…`);try{return(await runLogin({registry:S,otp:I,cwd:C})).username}catch(t){throw t instanceof LoginError?Error(t.message):t}}async function buildIfPresent(t,n){if(typeof(t.manifest.scripts??{}).build!=`string`)return;let S=detectPackageManager(),C=[`run`,`build`];n(` $ ${S} ${C.join(` `)}`);let{code:N}=await spawnToCompletion(S,C,{completion:`return`,cwd:t.location,env:{...process.env}});if(N!==0)throw Error(`build exited with code ${N}`)}function describePublishFailure(t){switch(t.action){case`otp-required`:return`npm required a 2FA code (re-run with --otp, or on a TTY)`;case`oidc-failed`:case`oidc-no-token`:return`OIDC/token auth failed`;case`diagnostic`:return`HTTP 404 (${t.diag.reason})`;case`publish-unconfirmed`:return`npm ${t.claim===`already-published`?`reported it already published`:`accepted the upload`} (HTTP ${t.putStatus}) but ${t.name}@${t.version} did not resolve on ${t.registry} after ${t.readback.attempts} probe(s) over ${(t.readback.elapsedMs/1e3).toFixed(1)}s [${t.readback.verdict}: ${t.readback.verdictDetail}]`;case`blocked-missing-dependency`:return`not published — ${t.missing.length} required pin(s) name a package ${t.registry} does not have: ${t.missing.map(t=>`${t.block}.${t.name}@${t.spec}`).join(`, `)}. Bootstrap the target BEFORE its dependent; that order is a correctness property`;case`error`:return`HTTP ${t.status} ${t.statusText}`;default:return`unknown`}}var JK,YK,XK=__esmMin(()=>{_e(),ev(),gh(),AI(),pB(),iK(),JG(),oK(),WK(),IK(),tB(),sv(),GK(),HK(),qK(),JK=4,YK={command:`onboard`,description:`Ensure every publishable package in a monorepo is both published on npm and has a Trusted Publisher configured for its release workflow — publishing/trusting only what is missing, one shared OTP across the whole sweep. Works on npm/yarn workspaces and, via --packages, on a monorepo with no workspace manifest at all. Idempotent.`,builder:t=>t.option(`repository`,{description:"GitHub repo as `owner/repo`. Default: inferred from the `origin` git remote.",type:`string`}).option(`workflow`,{description:`Workflow filename allowed to publish via OIDC (basename only).`,type:`string`,default:`release.yml`}).option(`environment`,{description:`Optional GitHub Actions environment the workflow must run in.`,type:`string`}).option(`registry`,{description:`Registry override. Default: scope-aware lookup from .npmrc (falls back to ${lh}).`,type:`string`}).option(`otp`,{description:`npm 2FA one-time code, used as the initial shared code. Prompted on demand (once) if omitted and a challenge occurs.`,type:`string`}).option(`packages`,{description:'Directory glob naming package folders, resolved against the repo root (repeatable). For a monorepo that is not an npm/yarn workspace — `--packages "*"` in a repo whose 703 package directories sit at the top level. Merged with the root manifest\'s own `workspaces` globs when it has any. A pattern matching NO directory is a hard error.',type:`string`,array:!0}).option(`include`,{description:`Glob pattern to include packages by NAME (repeatable). Applied after discovery.`,type:`string`,array:!0}).option(`exclude`,{description:`Glob pattern to exclude packages by NAME (repeatable). Applied after discovery.`,type:`string`,array:!0}).option(`access`,{description:"npm access for a FIRST publish — `public` or `restricted`. Only ever applied to a package this sweep publishes; an already-published package keeps whatever access it has.",type:`string`,choices:[`public`,`restricted`],default:`public`}).option(`build`,{description:"Run each to-be-published package's `build` script first. `--no-build` skips it, for a repo whose packages are generated artifacts with nothing to build.",type:`boolean`,default:!0}).option(`verbose`,{description:`List every package in the plan table, including the ones already published + trusted (by default only the rows needing work are listed; the counts always cover all of them).`,type:`boolean`,alias:`v`,default:!1}).option(`concurrency`,{description:`How many packages to probe (read state) in parallel (kept small so a single token does not burst npm; the first read is always serial to prompt for the shared OTP once).`,type:`number`,default:4}).option(`write-concurrency`,{description:`How many Trusted-Publisher writes to issue in parallel. It buys FEWER 2FA PROMPTS more than it buys speed: an npm code lives about 30 seconds, so a serial sweep crosses a code boundary every ~38 packages. Raising it does not beat npm's rate limit — a 429 anywhere now pauses the whole sweep, so it self-paces down to whatever the registry will serve. Publishes are unaffected: they stay serial, because publish ORDER is a correctness property.`,type:`number`,default:JK}).option(`dry-run`,{description:`Report the plan (what would be published / trusted) without changing anything.`,type:`boolean`,default:!1}).option(`json`,{description:`Emit a machine-readable summary object as the final line of stdout.`,type:`boolean`,default:!1}).option(`yes`,{description:`Non-interactive: never prompt. Fail clearly if a login or an OTP is required and not supplied via flags.`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=t[`dry-run`]===!0,C=t.json===!0,N=t.yes===!0,log=(t=``)=>{C?process.stderr.write(`${t}\n`):writeAroundPrompt(`${t}\n`)},F=await loadNpmrc(n),I=t.registry??process.env.npm_config_registry??F.registry??lh,H;try{H=await ensureAuthenticated({npmrc:F,registry:I,cwd:n,nonInteractive:N,dryRun:S,otp:t.otp,log})}catch(t){let n=t instanceof Error?t.message:String(t);return C?process.stdout.write(`${JSON.stringify({ok:!1,error:`auth`,message:n})}\n`):ge.error(n),process.exit(1)}F=await loadNpmrc(n),H&&log(`gjsify onboard: authenticated as ${H}`);let W=t.repository;if(!W){let t=spawnSync(`git`,[`remote`,`get-url`,`origin`],{cwd:n,encoding:`utf8`});t.status===0&&(W=parseRepoFromGitRemote(t.stdout)??void 0)}if(!W||!validateRepository(W)){let t=`gjsify onboard: could not determine the GitHub repository — pass --repository owner/repo.`;return C?process.stdout.write(`${JSON.stringify({ok:!1,error:`repository`,message:t})}\n`):ge.error(t),process.exit(1)}let q=normalizeWorkflowFile(t.workflow),Y=t.environment,X=resolveRepoRoot(n),Z,te;try{t.packages&&t.packages.length>0&&assertEveryPatternMatches(X,t.packages);let S=collectOnboardPackages(X,n,{patterns:t.packages});Z=S.packages,te=describeSources(S.sources)}catch(t){let n=t instanceof Error?t.message:String(t);return C?process.stdout.write(`${JSON.stringify({ok:!1,error:`discovery`,message:n})}\n`):ge.error(n),process.exit(1)}let ne=filterWorkspaces(Z,{noPrivate:!0,include:t.include,exclude:t.exclude}).filter(t=>t.name);if(ne.length===0){let t=`gjsify onboard: no publishable packages found under ${X} (discovered ${Z.length}${te?` — ${te}`:``}). `+(Z.length>0?`Every discovered package is private or was filtered out by --include/--exclude.`:`Pass --packages with a directory glob if this repo has no workspace manifest.`);return C?process.stdout.write(`${JSON.stringify({ok:!1,error:`no-packages`,message:t})}\n`):ge.error(t),process.exit(1)}try{assertRepositoryAgreement(ne,W)}catch(t){let n=t instanceof Error?t.message:String(t);return C?process.stdout.write(`${JSON.stringify({ok:!1,error:`foreign-repository`,message:n})}\n`):ge.error(n),process.exit(1)}log(`gjsify onboard: root=${X} | ${te}`),log(`gjsify onboard: ${ne.length} of ${Z.length} package(s) selected | repo=${W} workflow=${q}`),S&&log(`(dry-run — nothing will be published or configured)`),log();let re=new OtpProvider(t.otp,N?async()=>``:void 0,{registry:I}),ie=createTrustRequester({npmrc:F,otpProvider:re}),ae=new RateLimitGate,oe=!1,onRateLimit=t=>{oe||(oe=!0,log(` npm rate limit hit. ${t.headers}. Waiting ${Math.round(t.waitMs/1e3)}s (${t.fromRetryAfter?`npm's Retry-After`:`our backoff — npm advised nothing`}), and holding the whole sweep back while it lasts.`))},Q={gate:ae,onRateLimit},se=Math.max(1,Math.min(50,Math.ceil(ne.length/10))),ce=0,le=0,ue=0;ne.length>se&&log(`Reading trust state for ${ne.length} package(s)…`);let de=await probeAllTrustStates(ie,ne,Math.max(1,t.concurrency),{registryOverride:t.registry,npmrc:F,repository:W,workflow:q},{...Q,onProgress:(t,n,S)=>{if(S.action===`trust`||S.action===`publish-and-trust`?ce++:S.action===`skip`?le++:ue++,t%se!==0&&t!==n||n<=se)return;let C=[`${ce} to do`,`${le} already done`];ue>0&&C.push(`${ue} unreadable`),log(` read ${t}/${n} — ${C.join(`, `)}`)}}),fe=de.filter(t=>t.action===`publish-and-trust`),pe=de.filter(t=>t.action===`trust`),me=de.filter(t=>t.action===`skip`),he=de.filter(t=>t.action===`blocked`);for(let n of de)n.action===`skip`&&t.verbose!==!0||log(` ${statusCell(n)} ${n.ws.name}`);!t.verbose&&me.length>0&&log(` (${me.length} already published + trusted — pass -v to list)`),log(),log(`Plan: ${me.length} already done, ${fe.length} to publish+trust, ${pe.length} to trust, ${he.length} unreadable.`);let _e=he.filter(t=>t.httpStatus===429).length;_e>0&&log(` ${_e} of those are npm rate limits (HTTP 429) that outlasted the backoff — lower --concurrency and re-run; the sweep is idempotent and picks up where it left off.`);let ve=[];if(S){for(let t of de)ve.push({name:t.ws.name,result:t.action===`skip`?`already-done`:t.action===`blocked`?`failed`:`skipped-dry-run`,detail:t.action===`publish-and-trust`?`would publish + trust`:t.action===`trust`?`would trust`:t.action===`blocked`?`state HTTP ${t.httpStatus}`:void 0});finish(ve,de,{asJson:C,dryRun:S,failed:he.length,root:X,sources:te,discovered:Z.length});return}let ye=githubTrustBody({repository:W,workflow:q,environment:Y}),be=Math.max(1,t[`write-concurrency`]),xe=fe.length+pe.length,Se=Array.from({length:de.length}),Ce=0,we=0,Te=0,configureTrust=async(t,n,S)=>{let C=await requestWaitingOutRateLimit(ie,`POST`,t.url,ye,Q),N=`${++we}/${xe}`;C.status>=200&&C.status<300?(log(` [${N}] trusted ${t.ws.name}`),Se[n]={name:t.ws.name,result:S?`published+trusted`:`trusted`}):C.status===409?Se[n]={name:t.ws.name,result:S?`published+trusted`:`trusted`}:C.status===404?(log(` [${N}] ${t.ws.name}: published but not yet trust-configurable (re-run onboard)`),Se[n]={name:t.ws.name,result:S?`published`:`failed`,detail:`trust config deferred (404)`},S||Ce++):(log(` [${N}] trust failed (HTTP ${C.status}) — ${t.ws.name}`),Se[n]={name:t.ws.name,result:`failed`,detail:`trust HTTP ${C.status}`},C.status===429&&Te++,Ce++)},Ee=[],De=new Set;for(let n=0;n<de.length;n++){let S=de[n];if(S.action===`skip`){Se[n]={name:S.ws.name,result:`already-done`};continue}if(S.action===`blocked`){log(`→ ${S.ws.name}: cannot read trust state (HTTP ${S.httpStatus}) — skipped`),Se[n]={name:S.ws.name,result:`failed`,detail:`state HTTP ${S.httpStatus}`},Ce++;continue}if(S.action===`trust`){Ee.push({p:S,i:n});continue}log(`→ ${S.ws.name}: building + publishing…`);try{t.build!==!1&&await buildIfPresent(S.ws,log)}catch(t){let C=t instanceof Error?t.message:String(t);log(` build failed: ${C}`),Se[n]={name:S.ws.name,result:`failed`,detail:`build: ${C}`},Ce++;continue}let C=await publishWorkspace({assumePresent:[...De],wsDir:S.ws.location,tag:`latest`,access:t.access,provenance:!1,tolerate:!0,tolerateUntrustedNew:!1,trustedFlag:void 0,registry:S.registry,verbose:!1,json:!1,otpProvider:re,seedOtpFirst:!1});if(!C.ok){let t=describePublishFailure(C);log(` publish failed: ${t}`),Se[n]={name:S.ws.name,result:`failed`,detail:`publish: ${t}`},Ce++;continue}log(` published ${C.name}@${`version`in C?C.version:``}`+(`readback`in C&&C.readback?.confirmed?` (verified on ${C.registry} — ${C.readback.attempts} probe(s))`:C.action===`skipped-untrusted-new`?``:` (UNVERIFIED)`)),De.add(C.name),await configureTrust(S,n,C.action!==`skipped-untrusted-new`)}Ee.length>0&&(Ee.length>1&&log(`→ configuring ${Ee.length} Trusted Publisher(s), ${be} at a time…`),await mapWithConcurrency(Ee,be,async({p:t,i:n})=>configureTrust(t,n,!1)));for(let t of Se)t&&ve.push(t);Te>0&&(log(),log(`${Te} of the failures are npm rate limits (HTTP 429) that outlasted the wait, not a problem with those packages.`),log(` Re-run to pick them up — the sweep is idempotent and skips everything already configured. A lower --write-concurrency (currently ${be}) provokes the limit less.`)),finish(ve,de,{asJson:C,dryRun:S,failed:Ce,root:X,sources:te,discovered:Z.length})}}});function pathFor(t){return t===`win32`?Dn:Tn}function isInside$1(t,n,S){let C=pathFor(S);if(!C.isAbsolute(t)||!C.isAbsolute(n))return!1;let N=n.endsWith(C.sep)?n:n+C.sep;return t===n||t.startsWith(N)}function classifyInstall(t){let n=t.env??process.env,S=t.platform??process.platform,C=pathFor(S),N=C.resolve(t.selfDir);if(n.FLATPAK_ID||isInside$1(N,QK,S)){let t=n.FLATPAK_ID??`io.github.gjsify.Cli`;return{kind:`flatpak`,evidence:n.FLATPAK_ID?`FLATPAK_ID=${n.FLATPAK_ID}`:`running from ${QK}`,updateWith:`flatpak update ${t}`,managedElsewhere:!0}}return isInside$1(N,C.resolve(t.xdgPrefix),S)?{kind:`xdg-global`,evidence:`running from the user-global prefix ${t.xdgPrefix}`,managedElsewhere:!1}:S!==`win32`&&ZK.some(t=>isInside$1(N,t,S))?{kind:`system-package`,evidence:`running from the system prefix ${N}`,updateWith:"your distribution package manager (`apt upgrade` / `dnf upgrade` / …), or install the newer package from https://github.com/gjsify/gjsify/releases/latest",managedElsewhere:!0}:N.split(C.sep).includes(`node_modules`)?{kind:`npm-global`,evidence:`running from a node_modules tree at ${N}`,updateWith:`npm install -g @gjsify/cli@latest (or switch to the Node-free bootstrap)`,managedElsewhere:!0}:{kind:`unknown`,evidence:`running from ${N}, which matches no known install layout`,managedElsewhere:!1}}var ZK,QK,$K=__esmMin(()=>{qn(),ZK=[`/usr/`,`/opt/`,`/snap/`],QK=`/app/`,__name$1(isInside$1,`isInside`)});function verifyPathResolution(t){let n=t.platform??process.platform,S=n===`win32`?Dn:Tn,norm=t=>n===`win32`?S.resolve(t).toLowerCase():S.resolve(t);if(t.resolvedBin===null)return{ok:!1,message:`BUT nothing named \`${t.binName}\` is on PATH, so the update cannot take effect.\n\n Add the bin dir to PATH:\n ${t.binDir}`};if(norm(S.dirname(t.resolvedBin))===norm(t.binDir))return{ok:!0};let C=t.runningVersion?` (v${t.runningVersion})`:``;return{ok:!1,message:`BUT \`${t.binName}\` on PATH resolves to\n ${t.resolvedBin}${C}\nwhich is NOT the install that was just updated, so the next \`${t.binName}\`\nyou run will not be v${t.targetVersion}.\n\n If that is another install, remove it (e.g. \`npm uninstall -g ${eq}\`)\n or put ${t.binDir} ahead of it on PATH.\n If you ran this through npx/dlx, that temporary copy owns the name only for\n this run — open a new shell and check \`${t.binName} --version\`.`}}function isNextChannelVersion(t){return t?(parse(t)?.prerelease??[]).some(t=>t===`next`):!1}function nextChannelNotice(t){return t.requestedTag!==void 0||!isNextChannelVersion(t.currentVersion)?null:`Note: v${t.currentVersion} is a \`next\` prerelease; updating without --tag moves you to \`${tq}\`. Use \`--tag next\` to stay on the next channel.`}function readSelfDir(){let t=process.env.GJSIFY_CLI_PACKAGE_JSON;if(t)return zn(Nn(t));let n=fileURLToPath(import.meta.url),S=zn(Nn(n));for(let t=0;t<8&&S!==zn(S);t++){if(existsSync(In(S,`package.json`)))return S;S=zn(S)}return zn(Nn(n))}function readCurrentVersion(){try{let t=process.env.GJSIFY_CLI_PACKAGE_JSON;if(t){let n=JSON.parse(readFileSync(t,`utf-8`));return n.name===eq&&typeof n.version==`string`?n.version:null}let n=zn(Nn(fileURLToPath(import.meta.url)));for(let t=0;t<8&&n!==zn(n);t++){let t=In(n,`package.json`);if(existsSync(t)){let n=JSON.parse(readFileSync(t,`utf-8`));if(n.name===eq&&typeof n.version==`string`)return n.version}n=zn(n)}}catch{}return null}function resolveTag(t,n){let S=t[`dist-tags`]??{};return S[n]?S[n]:t.versions&&typeof t.versions==`object`&&t.versions[n]?n:null}var eq,tq,nq,rq,iq=__esmMin(()=>{_e(),ef(),qn(),ir(),gh(),OI(),jz(),$K(),Fz(),zz(),gz(),vz(),eq=`@gjsify/cli`,tq=`latest`,nq={command:`self-update`,description:`Update the installed ${eq} to the latest release (or pinned --tag).`,builder:t=>t.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`}).option(`prune`,{description:`After updating, remove packages an earlier install left behind that this host cannot use (foreign os/cpu/libc). Use --no-prune to disable.`,type:`boolean`,default:!0}).option(`skip-deps`,{description:`Update only the @gjsify/cli bundle itself; do not pull its runtime dependencies (rolldown, lightningcss, @gjsify/tsc, the native gi:// bridges, …). Faster, but can leave the on-disk runtime deps stale relative to the new bundle.`,type:`boolean`,default:!1}),handler:async t=>{let n=defaultGlobalLayout(),S=In(In(n.prefix,`node_modules`,eq),`package.json`),C=readCurrentVersion(),N=existsSync(S);ge.log(`Current ${eq}: v${C??`(unknown)`}`);let F=classifyInstall({selfDir:readSelfDir(),xdgPrefix:n.prefix});if(F.managedElsewhere)return ge.error(`\ngjsify self-update: this gjsify is managed by something else — ${F.evidence}.\nUpdating it from here would write ${n.prefix} and leave you running two installs.\n\nUpdate with: ${F.updateWith}\n`),process.exit(1);N||ge.warn(`\nWarning: no @gjsify/cli install found under ${n.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`);let I=t.tag??tq,H=nextChannelNotice({currentVersion:C,requestedTag:t.tag});H&&ge.log(H),ge.log(`Fetching dist-tags for ${eq}@${I} ...`);let W;try{W=await fetchPackument(eq)}catch(t){let n=t instanceof Error?t.message:String(t);return ge.error(`Failed to fetch packument: ${n}`),process.exit(1)}let q=resolveTag(W,I);if(!q)return ge.error(`Unknown dist-tag '${I}' on ${eq}. Known tags: ${Object.keys(W[`dist-tags`]??{}).join(`, `)||`(none)`}`),process.exit(1);ge.log(`Latest matching --tag ${I}: v${q}`);let Y=N&&!hasBundlerEngineInstalled(n.prefix),X=Y&&!t.skipDeps&&!t.check;if(C===q&&!t.force&&!X){ge.log(`Already up to date (v${q}).`),Y&&t.skipDeps&&ge.log("Note: the GJS bundler engine @gjsify/rolldown-native is not installed — re-run without --skip-deps to repair it (`gjsify build` needs it under GJS)."),t.check||ge.log(`Run with --force to reinstall anyway.`);return}if(X&&C===q&&!t.force&&ge.log(`@gjsify/cli is at v${q} but the GJS bundler engine @gjsify/rolldown-native is missing — repairing.`),t.check)return ge.log(C?`Update available: v${C} → v${q}`:`Install required: → v${q}`),process.exit(1);let Z=!t.skipDeps,te=Z?` + runtime dependencies`:` (bundle only)`;ge.log(`Installing ${eq}@${q}${te} ...`);let ne=makeProgressReporter();try{await installPackages({prefix:n.prefix,specs:[`${eq}@${q}`],verbose:!1,skipDeps:!Z,progress:ne})}catch(t){let n=t instanceof Error?t.message:String(t);return ge.error(`self-update: install failed — ${n}`),ge.error("Re-run `gjsify self-update` to retry."),process.exit(1)}Z&&await installGjsEnginePackages(n.prefix,q,{verbose:!1}),t.prune!==!1&&pruneAfterInstall(n.prefix,resolveHostPlatform({env:{}}),{hint:`gjsify prune -g --dry-run`});let re=linkGlobalBins([eq],n);if(re.length===0)ge.warn("self-update: install completed but no bins were linked — package.json may be missing a `bin` field.");else for(let t of re)ge.log(` • ${t.link} → ${t.target}`);if(globalLayoutIsDefault()){let t=verifyPathResolution({binName:rq,binDir:n.binDir,resolvedBin:resolveBinOnPath(rq,{pathValue:pathWithoutSelfShim()}),runningVersion:C,targetVersion:q});if(!t.ok)return ge.error(`\nInstalled ${eq} v${q} at ${n.prefix}`),ge.error(t.message),process.exit(1)}ge.log(`\nUpdated ${eq} to v${q}.`),Z?ge.log(`Runtime dependencies were resolved alongside the bundle.`):ge.log(`Bundle-only update (--skip-deps): on-disk runtime dependencies were left unchanged.`)}},rq=`gjsify`});function loadInstallerTemplate(){return`#!/usr/bin/env -S gjs -m
1256
+ `))}var KK=__esmMin(()=>{ef(),ev(),AI(),qn(),VK(),UK(),MI()});function describeRateLimitHeaders(t){if(!t)return`no headers captured`;let n=[];return t.forEach((t,S)=>{(/^retry-after$/i.test(S)||/ratelimit/i.test(S))&&n.push(`${S}: ${t}`)}),n.length>0?n.join(`, `):`npm sent no Retry-After and no rate-limit headers`}function retryAfterMs(t){let n=t?.get(`retry-after`);if(!n)return null;let S=Number.parseInt(n.trim(),10);return!Number.isFinite(S)||S<0?null:S*1e3}async function packumentExists(t,n){let S=t.endsWith(`/`)?t.slice(0,-1):t;try{let t=await fetch(`${S}/${n.replace(`/`,`%2f`)}`,{method:`GET`,headers:{accept:`application/vnd.npm.install-v1+json`}});return t.status===404?!1:t.ok?!0:null}catch{return null}}function actionForState(t){switch(t){case`trusted`:return`skip`;case`untrusted`:return`trust`;case`unpublished`:return`publish-and-trust`;default:return`blocked`}}function defaultSleep(t){return new Promise(n=>setTimeout(n,t))}async function requestWaitingOutRateLimit(t,n,S,C,N={}){let F=N.sleep??defaultSleep,I=N.maxRateLimitWaitMs??3e5,H=N.rateLimitBaseDelayMs??2e3,W=N.gate;W&&await W.wait();let q=await t(n,S,C),Y=0;for(let X=0;q.status===429&&Y<I;X++){let Z=retryAfterMs(q.headers),te=Math.min(Z??H*2**X,qK),ne=Math.min(te,I-Y);N.onRateLimit?.({url:S,headers:describeRateLimitHeaders(q.headers),waitMs:ne,fromRetryAfter:Z!==null}),W?.penalize(ne),await(W?W.wait():F(ne)),Y+=ne,q=await t(n,S,C)}return q}async function probeTrustState(t,n,S,C={}){let N=S.registryOverride??registryFor(n.name,S.npmrc)??lh,F=trustUrl(N,n.name),I={repository:S.repository,workflow:S.workflow},H=C.sleep??defaultSleep,W=await requestWaitingOutRateLimit(t,`GET`,F,void 0,C),q=classifyTrustList(W.status,W.json,I);return q===`auth-required`&&C.retryOn401!==!1&&(await H(C.retryDelayMs??400),W=await t(`GET`,F),q=classifyTrustList(W.status,W.json,I)),(q===`untrusted`||q===`auth-required`)&&await(C.exists??packumentExists)(N,n.name)===!1&&(q=`unpublished`),{ws:n,registry:N,url:F,state:q,httpStatus:W.status,action:actionForState(q)}}async function probeAllTrustStates(t,n,S,C,N={}){if(n.length===0)return[];let F=n.length,I=0,report=t=>(I++,N.onProgress?.(I,F,t),t);return[report(await probeTrustState(t,n[0],C,N)),...await mapWithConcurrency(n.slice(1),Math.max(1,S),async n=>report(await probeTrustState(t,n,C,N)))]}async function mapWithConcurrency(t,n,S){let C=Array.from({length:t.length}),N=0,F=Array.from({length:Math.min(Math.max(1,n),t.length)},async()=>{for(;;){let n=N++;if(n>=t.length)return;C[n]=await S(t[n])}});return await Promise.all(F),C}var qK,RateLimitGate,JK=__esmMin(()=>{gh(),UK(),qK=6e4,RateLimitGate=class{until=0;now;sleeper;constructor(t={}){this.now=t.now??(()=>Date.now()),this.sleeper=t.sleep??defaultSleep}async wait(){let t=this.until-this.now();t>0&&await this.sleeper(t)}penalize(t){this.until=Math.max(this.until,this.now()+t)}remainingMs(){return Math.max(0,this.until-this.now())}}});function finish(t,n,S){let C=S.failed??0;if(S.asJson)process.stdout.write(`${JSON.stringify({ok:C===0,dryRun:S.dryRun,root:S.root,sources:S.sources,discovered:S.discovered,total:n.length,published:t.filter(t=>t.result===`published`||t.result===`published+trusted`).length,trusted:t.filter(t=>t.result===`trusted`||t.result===`published+trusted`).length,alreadyDone:t.filter(t=>t.result===`already-done`).length,failed:C,results:t},null,2)}\n`);else{let n=S.dryRun?C>0?`Dry-run INCOMPLETE — nothing changed, but ${C} package(s) had an unreadable state, so the plan above does not cover them. Authenticate (\`gjsify login\`) and re-run.`:`Dry-run complete — nothing changed.`:`Done: ${t.filter(t=>t.result.includes(`published`)).length} published, ${t.filter(t=>t.result===`trusted`||t.result===`published+trusted`).length} trusted, ${t.filter(t=>t.result===`already-done`).length} already done, ${C} failed.`;process.stdout.write(`\n${n}\n`)}process.exit(+(C>0))}function statusCell(t){switch(t.action){case`skip`:return`published✓ trusted✓`;case`trust`:return`published✓ trust… `;case`publish-and-trust`:return`publish… trust… `;case`blocked`:return`unreadable (${t.httpStatus})`}}async function ensureAuthenticated(t){let{npmrc:n,registry:S,cwd:C,nonInteractive:N,dryRun:F,otp:I,log:H}=t;if(hasAnyCredential(n))try{let t=await whoami(S,n);if(t.username)return t.username}catch{}if(F){H(`gjsify onboard: no live npm token — dry-run continues (state reads may be limited).`);return}if(N)throw Error("gjsify onboard: not authenticated and --yes was passed — run `gjsify login` first (or omit --yes to log in interactively).");H(`gjsify onboard: no live npm token — logging in…`);try{return(await runLogin({registry:S,otp:I,cwd:C})).username}catch(t){throw t instanceof LoginError?Error(t.message):t}}async function buildIfPresent(t,n){if(typeof(t.manifest.scripts??{}).build!=`string`)return;let S=detectPackageManager(),C=[`run`,`build`];n(` $ ${S} ${C.join(` `)}`);let{code:N}=await spawnToCompletion(S,C,{completion:`return`,cwd:t.location,env:{...process.env}});if(N!==0)throw Error(`build exited with code ${N}`)}function describePublishFailure(t){switch(t.action){case`otp-required`:return`npm required a 2FA code (re-run with --otp, or on a TTY)`;case`oidc-failed`:case`oidc-no-token`:return`OIDC/token auth failed`;case`diagnostic`:return`HTTP 404 (${t.diag.reason})`;case`publish-unconfirmed`:return`npm ${t.claim===`already-published`?`reported it already published`:`accepted the upload`} (HTTP ${t.putStatus}) but ${t.name}@${t.version} did not resolve on ${t.registry} after ${t.readback.attempts} probe(s) over ${(t.readback.elapsedMs/1e3).toFixed(1)}s [${t.readback.verdict}: ${t.readback.verdictDetail}]`;case`blocked-missing-dependency`:return`not published — ${t.missing.length} required pin(s) name a package ${t.registry} does not have: ${t.missing.map(t=>`${t.block}.${t.name}@${t.spec}`).join(`, `)}. Bootstrap the target BEFORE its dependent; that order is a correctness property`;case`error`:return`HTTP ${t.status} ${t.statusText}`;default:return`unknown`}}var YK,XK,ZK=__esmMin(()=>{_e(),ev(),gh(),AI(),pB(),aK(),YG(),sK(),GK(),LK(),tB(),sv(),KK(),UK(),JK(),YK=4,XK={command:`onboard`,description:`Ensure every publishable package in a monorepo is both published on npm and has a Trusted Publisher configured for its release workflow — publishing/trusting only what is missing, one shared OTP across the whole sweep. Works on npm/yarn workspaces and, via --packages, on a monorepo with no workspace manifest at all. Idempotent.`,builder:t=>t.option(`repository`,{description:"GitHub repo as `owner/repo`. Default: inferred from the `origin` git remote.",type:`string`}).option(`workflow`,{description:`Workflow filename allowed to publish via OIDC (basename only).`,type:`string`,default:`release.yml`}).option(`environment`,{description:`Optional GitHub Actions environment the workflow must run in.`,type:`string`}).option(`registry`,{description:`Registry override. Default: scope-aware lookup from .npmrc (falls back to ${lh}).`,type:`string`}).option(`otp`,{description:`npm 2FA one-time code, used as the initial shared code. Prompted on demand (once) if omitted and a challenge occurs.`,type:`string`}).option(`packages`,{description:'Directory glob naming package folders, resolved against the repo root (repeatable). For a monorepo that is not an npm/yarn workspace — `--packages "*"` in a repo whose 703 package directories sit at the top level. Merged with the root manifest\'s own `workspaces` globs when it has any. A pattern matching NO directory is a hard error.',type:`string`,array:!0}).option(`include`,{description:`Glob pattern to include packages by NAME (repeatable). Applied after discovery.`,type:`string`,array:!0}).option(`exclude`,{description:`Glob pattern to exclude packages by NAME (repeatable). Applied after discovery.`,type:`string`,array:!0}).option(`access`,{description:"npm access for a FIRST publish — `public` or `restricted`. Only ever applied to a package this sweep publishes; an already-published package keeps whatever access it has.",type:`string`,choices:[`public`,`restricted`],default:`public`}).option(`build`,{description:"Run each to-be-published package's `build` script first. `--no-build` skips it, for a repo whose packages are generated artifacts with nothing to build.",type:`boolean`,default:!0}).option(`verbose`,{description:`List every package in the plan table, including the ones already published + trusted (by default only the rows needing work are listed; the counts always cover all of them).`,type:`boolean`,alias:`v`,default:!1}).option(`concurrency`,{description:`How many packages to probe (read state) in parallel (kept small so a single token does not burst npm; the first read is always serial to prompt for the shared OTP once).`,type:`number`,default:4}).option(`write-concurrency`,{description:`How many Trusted-Publisher writes to issue in parallel. It buys FEWER 2FA PROMPTS more than it buys speed: an npm code lives about 30 seconds, so a serial sweep crosses a code boundary every ~38 packages. Raising it does not beat npm's rate limit — a 429 anywhere now pauses the whole sweep, so it self-paces down to whatever the registry will serve. Publishes are unaffected: they stay serial, because publish ORDER is a correctness property.`,type:`number`,default:YK}).option(`dry-run`,{description:`Report the plan (what would be published / trusted) without changing anything.`,type:`boolean`,default:!1}).option(`json`,{description:`Emit a machine-readable summary object as the final line of stdout.`,type:`boolean`,default:!1}).option(`yes`,{description:`Non-interactive: never prompt. Fail clearly if a login or an OTP is required and not supplied via flags.`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=t[`dry-run`]===!0,C=t.json===!0,N=t.yes===!0,log=(t=``)=>{C?process.stderr.write(`${t}\n`):writeAroundPrompt(`${t}\n`)},F=await loadNpmrc(n),I=t.registry??process.env.npm_config_registry??F.registry??lh,H;try{H=await ensureAuthenticated({npmrc:F,registry:I,cwd:n,nonInteractive:N,dryRun:S,otp:t.otp,log})}catch(t){let n=t instanceof Error?t.message:String(t);return C?process.stdout.write(`${JSON.stringify({ok:!1,error:`auth`,message:n})}\n`):ge.error(n),process.exit(1)}F=await loadNpmrc(n),H&&log(`gjsify onboard: authenticated as ${H}`);let W=t.repository;if(!W){let t=spawnSync(`git`,[`remote`,`get-url`,`origin`],{cwd:n,encoding:`utf8`});t.status===0&&(W=parseRepoFromGitRemote(t.stdout)??void 0)}if(!W||!validateRepository(W)){let t=`gjsify onboard: could not determine the GitHub repository — pass --repository owner/repo.`;return C?process.stdout.write(`${JSON.stringify({ok:!1,error:`repository`,message:t})}\n`):ge.error(t),process.exit(1)}let q=normalizeWorkflowFile(t.workflow),Y=t.environment,X=resolveRepoRoot(n),Z,te;try{t.packages&&t.packages.length>0&&assertEveryPatternMatches(X,t.packages);let S=collectOnboardPackages(X,n,{patterns:t.packages});Z=S.packages,te=describeSources(S.sources)}catch(t){let n=t instanceof Error?t.message:String(t);return C?process.stdout.write(`${JSON.stringify({ok:!1,error:`discovery`,message:n})}\n`):ge.error(n),process.exit(1)}let ne=filterWorkspaces(Z,{noPrivate:!0,include:t.include,exclude:t.exclude}).filter(t=>t.name);if(ne.length===0){let t=`gjsify onboard: no publishable packages found under ${X} (discovered ${Z.length}${te?` — ${te}`:``}). `+(Z.length>0?`Every discovered package is private or was filtered out by --include/--exclude.`:`Pass --packages with a directory glob if this repo has no workspace manifest.`);return C?process.stdout.write(`${JSON.stringify({ok:!1,error:`no-packages`,message:t})}\n`):ge.error(t),process.exit(1)}try{assertRepositoryAgreement(ne,W)}catch(t){let n=t instanceof Error?t.message:String(t);return C?process.stdout.write(`${JSON.stringify({ok:!1,error:`foreign-repository`,message:n})}\n`):ge.error(n),process.exit(1)}log(`gjsify onboard: root=${X} | ${te}`),log(`gjsify onboard: ${ne.length} of ${Z.length} package(s) selected | repo=${W} workflow=${q}`),S&&log(`(dry-run — nothing will be published or configured)`),log();let re=new OtpProvider(t.otp,N?async()=>``:void 0,{registry:I}),ie=createTrustRequester({npmrc:F,otpProvider:re}),ae=new RateLimitGate,oe=!1,onRateLimit=t=>{oe||(oe=!0,log(` npm rate limit hit. ${t.headers}. Waiting ${Math.round(t.waitMs/1e3)}s (${t.fromRetryAfter?`npm's Retry-After`:`our backoff — npm advised nothing`}), and holding the whole sweep back while it lasts.`))},Q={gate:ae,onRateLimit},se=Math.max(1,Math.min(50,Math.ceil(ne.length/10))),ce=0,le=0,ue=0;ne.length>se&&log(`Reading trust state for ${ne.length} package(s)…`);let de=await probeAllTrustStates(ie,ne,Math.max(1,t.concurrency),{registryOverride:t.registry,npmrc:F,repository:W,workflow:q},{...Q,onProgress:(t,n,S)=>{if(S.action===`trust`||S.action===`publish-and-trust`?ce++:S.action===`skip`?le++:ue++,t%se!==0&&t!==n||n<=se)return;let C=[`${ce} to do`,`${le} already done`];ue>0&&C.push(`${ue} unreadable`),log(` read ${t}/${n} — ${C.join(`, `)}`)}}),fe=de.filter(t=>t.action===`publish-and-trust`),pe=de.filter(t=>t.action===`trust`),me=de.filter(t=>t.action===`skip`),he=de.filter(t=>t.action===`blocked`);for(let n of de)n.action===`skip`&&t.verbose!==!0||log(` ${statusCell(n)} ${n.ws.name}`);!t.verbose&&me.length>0&&log(` (${me.length} already published + trusted — pass -v to list)`),log(),log(`Plan: ${me.length} already done, ${fe.length} to publish+trust, ${pe.length} to trust, ${he.length} unreadable.`);let _e=he.filter(t=>t.httpStatus===429).length;_e>0&&log(` ${_e} of those are npm rate limits (HTTP 429) that outlasted the backoff — lower --concurrency and re-run; the sweep is idempotent and picks up where it left off.`);let ve=[];if(S){for(let t of de)ve.push({name:t.ws.name,result:t.action===`skip`?`already-done`:t.action===`blocked`?`failed`:`skipped-dry-run`,detail:t.action===`publish-and-trust`?`would publish + trust`:t.action===`trust`?`would trust`:t.action===`blocked`?`state HTTP ${t.httpStatus}`:void 0});finish(ve,de,{asJson:C,dryRun:S,failed:he.length,root:X,sources:te,discovered:Z.length});return}let ye=githubTrustBody({repository:W,workflow:q,environment:Y}),be=Math.max(1,t[`write-concurrency`]),xe=fe.length+pe.length,Se=Array.from({length:de.length}),Ce=0,we=0,Te=0,configureTrust=async(t,n,S)=>{let C=await requestWaitingOutRateLimit(ie,`POST`,t.url,ye,Q),N=`${++we}/${xe}`;C.status>=200&&C.status<300?(log(` [${N}] trusted ${t.ws.name}`),Se[n]={name:t.ws.name,result:S?`published+trusted`:`trusted`}):C.status===409?Se[n]={name:t.ws.name,result:S?`published+trusted`:`trusted`}:C.status===404?(log(` [${N}] ${t.ws.name}: published but not yet trust-configurable (re-run onboard)`),Se[n]={name:t.ws.name,result:S?`published`:`failed`,detail:`trust config deferred (404)`},S||Ce++):(log(` [${N}] trust failed (HTTP ${C.status}) — ${t.ws.name}`),Se[n]={name:t.ws.name,result:`failed`,detail:`trust HTTP ${C.status}`},C.status===429&&Te++,Ce++)},Ee=[],De=new Set;for(let n=0;n<de.length;n++){let S=de[n];if(S.action===`skip`){Se[n]={name:S.ws.name,result:`already-done`};continue}if(S.action===`blocked`){log(`→ ${S.ws.name}: cannot read trust state (HTTP ${S.httpStatus}) — skipped`),Se[n]={name:S.ws.name,result:`failed`,detail:`state HTTP ${S.httpStatus}`},Ce++;continue}if(S.action===`trust`){Ee.push({p:S,i:n});continue}log(`→ ${S.ws.name}: building + publishing…`);try{t.build!==!1&&await buildIfPresent(S.ws,log)}catch(t){let C=t instanceof Error?t.message:String(t);log(` build failed: ${C}`),Se[n]={name:S.ws.name,result:`failed`,detail:`build: ${C}`},Ce++;continue}let C=await publishWorkspace({assumePresent:[...De],wsDir:S.ws.location,tag:`latest`,access:t.access,provenance:!1,tolerate:!0,tolerateUntrustedNew:!1,trustedFlag:void 0,registry:S.registry,verbose:!1,json:!1,otpProvider:re,seedOtpFirst:!1});if(!C.ok){let t=describePublishFailure(C);log(` publish failed: ${t}`),Se[n]={name:S.ws.name,result:`failed`,detail:`publish: ${t}`},Ce++;continue}log(` published ${C.name}@${`version`in C?C.version:``}`+(`readback`in C&&C.readback?.confirmed?` (verified on ${C.registry} — ${C.readback.attempts} probe(s))`:C.action===`skipped-untrusted-new`?``:` (UNVERIFIED)`)),De.add(C.name),await configureTrust(S,n,C.action!==`skipped-untrusted-new`)}Ee.length>0&&(Ee.length>1&&log(`→ configuring ${Ee.length} Trusted Publisher(s), ${be} at a time…`),await mapWithConcurrency(Ee,be,async({p:t,i:n})=>configureTrust(t,n,!1)));for(let t of Se)t&&ve.push(t);Te>0&&(log(),log(`${Te} of the failures are npm rate limits (HTTP 429) that outlasted the wait, not a problem with those packages.`),log(` Re-run to pick them up — the sweep is idempotent and skips everything already configured. A lower --write-concurrency (currently ${be}) provokes the limit less.`)),finish(ve,de,{asJson:C,dryRun:S,failed:Ce,root:X,sources:te,discovered:Z.length})}}});function pathFor(t){return t===`win32`?Dn:Tn}function isInside$1(t,n,S){let C=pathFor(S);if(!C.isAbsolute(t)||!C.isAbsolute(n))return!1;let N=n.endsWith(C.sep)?n:n+C.sep;return t===n||t.startsWith(N)}function classifyInstall(t){let n=t.env??process.env,S=t.platform??process.platform,C=pathFor(S),N=C.resolve(t.selfDir);if(n.FLATPAK_ID||isInside$1(N,$K,S)){let t=n.FLATPAK_ID??`io.github.gjsify.Cli`;return{kind:`flatpak`,evidence:n.FLATPAK_ID?`FLATPAK_ID=${n.FLATPAK_ID}`:`running from ${$K}`,updateWith:`flatpak update ${t}`,managedElsewhere:!0}}return isInside$1(N,C.resolve(t.xdgPrefix),S)?{kind:`xdg-global`,evidence:`running from the user-global prefix ${t.xdgPrefix}`,managedElsewhere:!1}:S!==`win32`&&QK.some(t=>isInside$1(N,t,S))?{kind:`system-package`,evidence:`running from the system prefix ${N}`,updateWith:"your distribution package manager (`apt upgrade` / `dnf upgrade` / …), or install the newer package from https://github.com/gjsify/gjsify/releases/latest",managedElsewhere:!0}:N.split(C.sep).includes(`node_modules`)?{kind:`npm-global`,evidence:`running from a node_modules tree at ${N}`,updateWith:`npm install -g @gjsify/cli@latest (or switch to the Node-free bootstrap)`,managedElsewhere:!0}:{kind:`unknown`,evidence:`running from ${N}, which matches no known install layout`,managedElsewhere:!1}}var QK,$K,eq=__esmMin(()=>{qn(),QK=[`/usr/`,`/opt/`,`/snap/`],$K=`/app/`,__name$1(isInside$1,`isInside`)});function verifyPathResolution(t){let n=t.platform??process.platform,S=n===`win32`?Dn:Tn,norm=t=>n===`win32`?S.resolve(t).toLowerCase():S.resolve(t);if(t.resolvedBin===null)return{ok:!1,message:`BUT nothing named \`${t.binName}\` is on PATH, so the update cannot take effect.\n\n Add the bin dir to PATH:\n ${t.binDir}`};if(norm(S.dirname(t.resolvedBin))===norm(t.binDir))return{ok:!0};let C=t.runningVersion?` (v${t.runningVersion})`:``;return{ok:!1,message:`BUT \`${t.binName}\` on PATH resolves to\n ${t.resolvedBin}${C}\nwhich is NOT the install that was just updated, so the next \`${t.binName}\`\nyou run will not be v${t.targetVersion}.\n\n If that is another install, remove it (e.g. \`npm uninstall -g ${tq}\`)\n or put ${t.binDir} ahead of it on PATH.\n If you ran this through npx/dlx, that temporary copy owns the name only for\n this run — open a new shell and check \`${t.binName} --version\`.`}}function isNextChannelVersion(t){return t?(parse(t)?.prerelease??[]).some(t=>t===`next`):!1}function nextChannelNotice(t){return t.requestedTag!==void 0||!isNextChannelVersion(t.currentVersion)?null:`Note: v${t.currentVersion} is a \`next\` prerelease; updating without --tag moves you to \`${nq}\`. Use \`--tag next\` to stay on the next channel.`}function readSelfDir(){let t=process.env.GJSIFY_CLI_PACKAGE_JSON;if(t)return zn(Nn(t));let n=fileURLToPath(import.meta.url),S=zn(Nn(n));for(let t=0;t<8&&S!==zn(S);t++){if(existsSync(In(S,`package.json`)))return S;S=zn(S)}return zn(Nn(n))}function readCurrentVersion(){try{let t=process.env.GJSIFY_CLI_PACKAGE_JSON;if(t){let n=JSON.parse(readFileSync(t,`utf-8`));return n.name===tq&&typeof n.version==`string`?n.version:null}let n=zn(Nn(fileURLToPath(import.meta.url)));for(let t=0;t<8&&n!==zn(n);t++){let t=In(n,`package.json`);if(existsSync(t)){let n=JSON.parse(readFileSync(t,`utf-8`));if(n.name===tq&&typeof n.version==`string`)return n.version}n=zn(n)}}catch{}return null}function resolveTag(t,n){let S=t[`dist-tags`]??{};return S[n]?S[n]:t.versions&&typeof t.versions==`object`&&t.versions[n]?n:null}var tq,nq,rq,iq,aq=__esmMin(()=>{_e(),ef(),qn(),ir(),gh(),OI(),jz(),eq(),Fz(),zz(),gz(),vz(),tq=`@gjsify/cli`,nq=`latest`,rq={command:`self-update`,description:`Update the installed ${tq} to the latest release (or pinned --tag).`,builder:t=>t.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`}).option(`prune`,{description:`After updating, remove packages an earlier install left behind that this host cannot use (foreign os/cpu/libc). Use --no-prune to disable.`,type:`boolean`,default:!0}).option(`skip-deps`,{description:`Update only the @gjsify/cli bundle itself; do not pull its runtime dependencies (rolldown, lightningcss, @gjsify/tsc, the native gi:// bridges, …). Faster, but can leave the on-disk runtime deps stale relative to the new bundle.`,type:`boolean`,default:!1}),handler:async t=>{let n=defaultGlobalLayout(),S=In(In(n.prefix,`node_modules`,tq),`package.json`),C=readCurrentVersion(),N=existsSync(S);ge.log(`Current ${tq}: v${C??`(unknown)`}`);let F=classifyInstall({selfDir:readSelfDir(),xdgPrefix:n.prefix});if(F.managedElsewhere)return ge.error(`\ngjsify self-update: this gjsify is managed by something else — ${F.evidence}.\nUpdating it from here would write ${n.prefix} and leave you running two installs.\n\nUpdate with: ${F.updateWith}\n`),process.exit(1);N||ge.warn(`\nWarning: no @gjsify/cli install found under ${n.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`);let I=t.tag??nq,H=nextChannelNotice({currentVersion:C,requestedTag:t.tag});H&&ge.log(H),ge.log(`Fetching dist-tags for ${tq}@${I} ...`);let W;try{W=await fetchPackument(tq)}catch(t){let n=t instanceof Error?t.message:String(t);return ge.error(`Failed to fetch packument: ${n}`),process.exit(1)}let q=resolveTag(W,I);if(!q)return ge.error(`Unknown dist-tag '${I}' on ${tq}. Known tags: ${Object.keys(W[`dist-tags`]??{}).join(`, `)||`(none)`}`),process.exit(1);ge.log(`Latest matching --tag ${I}: v${q}`);let Y=N&&!hasBundlerEngineInstalled(n.prefix),X=Y&&!t.skipDeps&&!t.check;if(C===q&&!t.force&&!X){ge.log(`Already up to date (v${q}).`),Y&&t.skipDeps&&ge.log("Note: the GJS bundler engine @gjsify/rolldown-native is not installed — re-run without --skip-deps to repair it (`gjsify build` needs it under GJS)."),t.check||ge.log(`Run with --force to reinstall anyway.`);return}if(X&&C===q&&!t.force&&ge.log(`@gjsify/cli is at v${q} but the GJS bundler engine @gjsify/rolldown-native is missing — repairing.`),t.check)return ge.log(C?`Update available: v${C} → v${q}`:`Install required: → v${q}`),process.exit(1);let Z=!t.skipDeps,te=Z?` + runtime dependencies`:` (bundle only)`;ge.log(`Installing ${tq}@${q}${te} ...`);let ne=makeProgressReporter();try{await installPackages({prefix:n.prefix,specs:[`${tq}@${q}`],verbose:!1,skipDeps:!Z,progress:ne})}catch(t){let n=t instanceof Error?t.message:String(t);return ge.error(`self-update: install failed — ${n}`),ge.error("Re-run `gjsify self-update` to retry."),process.exit(1)}Z&&await installGjsEnginePackages(n.prefix,q,{verbose:!1}),t.prune!==!1&&pruneAfterInstall(n.prefix,resolveHostPlatform({env:{}}),{hint:`gjsify prune -g --dry-run`});let re=linkGlobalBins([tq],n);if(re.length===0)ge.warn("self-update: install completed but no bins were linked — package.json may be missing a `bin` field.");else for(let t of re)ge.log(` • ${t.link} → ${t.target}`);if(globalLayoutIsDefault()){let t=verifyPathResolution({binName:iq,binDir:n.binDir,resolvedBin:resolveBinOnPath(iq,{pathValue:pathWithoutSelfShim()}),runningVersion:C,targetVersion:q});if(!t.ok)return ge.error(`\nInstalled ${tq} v${q} at ${n.prefix}`),ge.error(t.message),process.exit(1)}ge.log(`\nUpdated ${tq} to v${q}.`),Z?ge.log(`Runtime dependencies were resolved alongside the bundle.`):ge.log(`Bundle-only update (--skip-deps): on-disk runtime dependencies were left unchanged.`)}},iq=`gjsify`});function loadInstallerTemplate(){return`#!/usr/bin/env -S gjs -m
1257
1257
  /**
1258
1258
  * gjsify universal installer — bootstraps \`@gjsify/cli\` (or any GJS app on npm)
1259
1259
  * on a system that has only \`gjs\` and libsoup: no Node, no npm. Decision and
@@ -1778,28 +1778,28 @@ async function main() {
1778
1778
  }
1779
1779
 
1780
1780
  await main();
1781
- `}function pickDefaultBinName(t,n){let S=t?.gjsify?.bin;if(S&&typeof S==`object`){let t=Object.keys(S)[0];if(t)return t}let C=t?.bin;if(C&&typeof C==`object`){let t=Object.keys(C)[0];if(t)return t}return n.startsWith(`@`)?n.slice(n.indexOf(`/`)+1):n}var aq,oq,sq=__esmMin(()=>{_e(),ef(),qn(),aq=`https://github.com/gjsify/gjsify/releases/latest/download/cli.gjs.mjs`,oq={command:`generate-installer [target]`,description:`Scaffold an install.mjs in the current directory for a GJS-runnable npm package.`,builder:t=>t.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:t=>{let n=Nn(process.cwd(),t.output);if(existsSync(n)&&!t.force)return ge.error(`${t.output} already exists. Re-run with --force to overwrite.`),process.exit(1);let S=Nn(process.cwd(),`package.json`),C=null;if(existsSync(S))try{C=JSON.parse(readFileSync(S,`utf-8`))}catch{}let N=t.target??C?.name;if(!N)return ge.error("No target package: pass `gjsify generate-installer <pkg>` or run inside a directory with a package.json."),process.exit(1);let F=t[`bin-name`]??pickDefaultBinName(C,N),I=t[`bootstrap-url`]??aq;writeFileSync(n,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}),ge.log(`Wrote ${t.output} (target=${N}, bin=${F}).`),ge.log(``),ge.log(`Install one-liner for your README:`),ge.log(` curl -fsSL https://github.com/<you>/<repo>/raw/main/${t.output} -o /tmp/i.mjs \\`),ge.log(` && gjs -m /tmp/i.mjs && rm /tmp/i.mjs`)}}}),cq,lq=__esmMin(()=>{_e(),ef(),nz(),Fz(),gz(),vz(),cq={command:`prune`,description:`Remove installed packages this host cannot use (foreign os/cpu/libc). Reads each package manifest — a package that declares no platform is never touched.`,builder:t=>t.option(`global`,{description:"Prune the user-global XDG prefix (the `install -g` target) instead of the project.",type:`boolean`,alias:`g`,default:!1}).option(`dry-run`,{description:`Report what would be removed without touching the filesystem.`,type:`boolean`,default:!1}).option(`verbose`,{description:`List every package rather than the first few.`,type:`boolean`,default:!1}).option(`os`,{description:`Prune AS IF the host were this OS (linux, darwin, win32). Defaults to this host.`,type:`string`}).option(`cpu`,{description:`Prune AS IF the host were this architecture (x64, arm64, …). Defaults to this host.`,type:`string`}).option(`libc`,{description:`Prune AS IF the host used this libc (glibc, musl). Defaults to this host.`,type:`string`}),handler:async t=>{let n=t.global?defaultGlobalLayout():null,S=n?n.prefix:process.cwd();if(!existsSync(`${S}/node_modules`)){ge.log(`gjsify prune: nothing installed at ${S}`);return}let C=resolveHostPlatform({env:{...t.os?{npm_config_os:t.os}:{},...t.cpu?{npm_config_cpu:t.cpu}:{},...t.libc?{npm_config_libc:t.libc}:{}}}),N=await acquireInstallLock(S,{}),F;try{F=executePrune(planPrune({prefix:S,target:C}),{dryRun:t.dryRun})}finally{N.release()}if(ge.log(formatPruneReport(F,{dryRun:t.dryRun,verbose:t.verbose})),F.failed.length>0)return process.exit(1)}}});function isInside(t,n){let S=Ln(t,n);return S===``?!0:S!==`..`&&!S.startsWith(`..${Wn}`)&&!Fn(S)}function findBinShimsForPackage(t,n,S){if(!existsSync(t))return[];let C=[],N;try{N=readdirSync(t)}catch{return[]}for(let F of N){let N=In(t,F);try{if(!statSync(N).isFile())continue;let t=readFileSync(N,`utf-8`);if(!t.startsWith(`#!/bin/sh`))continue;let S=t.split(`
1782
- `).find(t=>/^exec (?:gjs -m )?'/.test(t));if(!S)continue;let F=S.match(/'([^']+)'/);if(!F)continue;let I=F[1];if(isInside(n,I)){C.push(N);for(let t of[`.cmd`,`.ps1`])existsSync(N+t)&&C.push(N+t)}}catch(t){S&&ge.warn(` ? could not inspect ${N}: ${t.message}`)}}return C}var uq,dq=__esmMin(()=>{_e(),ef(),qn(),Fz(),uq={command:`uninstall <packages..>`,description:"Uninstall a previously installed package. Currently only `--global` mode is supported.",builder:t=>t.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:t=>{if(!t.global)return ge.error("gjsify uninstall currently only supports --global. For project-local removal, edit package.json + re-run `gjsify install`."),process.exit(1);let n=defaultGlobalLayout(),S=t[`dry-run`]??!1,C=t.verbose??!1,N=`gjsify uninstall${S?` (dry-run)`:``} --global`;ge.log(`${N} ← ${n.prefix}`),ge.log(`${` `.repeat(N.length)} bins ← ${n.binDir}`);let F=!1;for(let N of t.packages){let t=specToPackageName(N),I=In(n.prefix,`node_modules`,t);if(!existsSync(I)){ge.warn(` ✗ ${t} — not installed at ${I}`);continue}let H=findBinShimsForPackage(n.binDir,I,C);if(S){ge.log(` • would remove ${I}`);for(let t of H)ge.log(` • would remove ${t}`)}else{rmSync(I,{recursive:!0,force:!0}),ge.log(` • removed ${I}`);for(let t of H)unlinkSync(t),ge.log(` • removed ${t}`)}F=!0}F||(ge.error(`
1781
+ `}function pickDefaultBinName(t,n){let S=t?.gjsify?.bin;if(S&&typeof S==`object`){let t=Object.keys(S)[0];if(t)return t}let C=t?.bin;if(C&&typeof C==`object`){let t=Object.keys(C)[0];if(t)return t}return n.startsWith(`@`)?n.slice(n.indexOf(`/`)+1):n}var oq,sq,cq=__esmMin(()=>{_e(),ef(),qn(),oq=`https://github.com/gjsify/gjsify/releases/latest/download/cli.gjs.mjs`,sq={command:`generate-installer [target]`,description:`Scaffold an install.mjs in the current directory for a GJS-runnable npm package.`,builder:t=>t.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:t=>{let n=Nn(process.cwd(),t.output);if(existsSync(n)&&!t.force)return ge.error(`${t.output} already exists. Re-run with --force to overwrite.`),process.exit(1);let S=Nn(process.cwd(),`package.json`),C=null;if(existsSync(S))try{C=JSON.parse(readFileSync(S,`utf-8`))}catch{}let N=t.target??C?.name;if(!N)return ge.error("No target package: pass `gjsify generate-installer <pkg>` or run inside a directory with a package.json."),process.exit(1);let F=t[`bin-name`]??pickDefaultBinName(C,N),I=t[`bootstrap-url`]??oq;writeFileSync(n,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}),ge.log(`Wrote ${t.output} (target=${N}, bin=${F}).`),ge.log(``),ge.log(`Install one-liner for your README:`),ge.log(` curl -fsSL https://github.com/<you>/<repo>/raw/main/${t.output} -o /tmp/i.mjs \\`),ge.log(` && gjs -m /tmp/i.mjs && rm /tmp/i.mjs`)}}}),lq,uq=__esmMin(()=>{_e(),ef(),nz(),Fz(),gz(),vz(),lq={command:`prune`,description:`Remove installed packages this host cannot use (foreign os/cpu/libc). Reads each package manifest — a package that declares no platform is never touched.`,builder:t=>t.option(`global`,{description:"Prune the user-global XDG prefix (the `install -g` target) instead of the project.",type:`boolean`,alias:`g`,default:!1}).option(`dry-run`,{description:`Report what would be removed without touching the filesystem.`,type:`boolean`,default:!1}).option(`verbose`,{description:`List every package rather than the first few.`,type:`boolean`,default:!1}).option(`os`,{description:`Prune AS IF the host were this OS (linux, darwin, win32). Defaults to this host.`,type:`string`}).option(`cpu`,{description:`Prune AS IF the host were this architecture (x64, arm64, …). Defaults to this host.`,type:`string`}).option(`libc`,{description:`Prune AS IF the host used this libc (glibc, musl). Defaults to this host.`,type:`string`}),handler:async t=>{let n=t.global?defaultGlobalLayout():null,S=n?n.prefix:process.cwd();if(!existsSync(`${S}/node_modules`)){ge.log(`gjsify prune: nothing installed at ${S}`);return}let C=resolveHostPlatform({env:{...t.os?{npm_config_os:t.os}:{},...t.cpu?{npm_config_cpu:t.cpu}:{},...t.libc?{npm_config_libc:t.libc}:{}}}),N=await acquireInstallLock(S,{}),F;try{F=executePrune(planPrune({prefix:S,target:C}),{dryRun:t.dryRun})}finally{N.release()}if(ge.log(formatPruneReport(F,{dryRun:t.dryRun,verbose:t.verbose})),F.failed.length>0)return process.exit(1)}}});function isInside(t,n){let S=Ln(t,n);return S===``?!0:S!==`..`&&!S.startsWith(`..${Wn}`)&&!Fn(S)}function findBinShimsForPackage(t,n,S){if(!existsSync(t))return[];let C=[],N;try{N=readdirSync(t)}catch{return[]}for(let F of N){let N=In(t,F);try{if(!statSync(N).isFile())continue;let t=readFileSync(N,`utf-8`);if(!t.startsWith(`#!/bin/sh`))continue;let S=t.split(`
1782
+ `).find(t=>/^exec (?:gjs -m )?'/.test(t));if(!S)continue;let F=S.match(/'([^']+)'/);if(!F)continue;let I=F[1];if(isInside(n,I)){C.push(N);for(let t of[`.cmd`,`.ps1`])existsSync(N+t)&&C.push(N+t)}}catch(t){S&&ge.warn(` ? could not inspect ${N}: ${t.message}`)}}return C}var dq,fq=__esmMin(()=>{_e(),ef(),qn(),Fz(),dq={command:`uninstall <packages..>`,description:"Uninstall a previously installed package. Currently only `--global` mode is supported.",builder:t=>t.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:t=>{if(!t.global)return ge.error("gjsify uninstall currently only supports --global. For project-local removal, edit package.json + re-run `gjsify install`."),process.exit(1);let n=defaultGlobalLayout(),S=t[`dry-run`]??!1,C=t.verbose??!1,N=`gjsify uninstall${S?` (dry-run)`:``} --global`;ge.log(`${N} ← ${n.prefix}`),ge.log(`${` `.repeat(N.length)} bins ← ${n.binDir}`);let F=!1;for(let N of t.packages){let t=specToPackageName(N),I=In(n.prefix,`node_modules`,t);if(!existsSync(I)){ge.warn(` ✗ ${t} — not installed at ${I}`);continue}let H=findBinShimsForPackage(n.binDir,I,C);if(S){ge.log(` • would remove ${I}`);for(let t of H)ge.log(` • would remove ${t}`)}else{rmSync(I,{recursive:!0,force:!0}),ge.log(` • removed ${I}`);for(let t of H)unlinkSync(t),ge.log(` • removed ${t}`)}F=!0}F||(ge.error(`
1783
1783
  No packages removed.`),process.exit(1))}}});function globToRegexSource(t){let n=``,S=0;for(;S<t.length;){let C=t[S];if(C===`*`&&t[S+1]===`*`&&(S===0||t[S-1]===`/`)){if(S+2===t.length){n+=`.*`,S+=2;continue}if(t[S+2]===`/`){n+=`(?:.*/)?`,S+=3;continue}}if(C===`*`)for(n+=`[^/]*`;t[S+1]===`*`;)S++;else if(C===`?`)n+=`[^/]`;else if(C===`[`){let C=findClassEnd(t,S);if(C===-1)n+=`\\[`;else{let N=t.slice(S+1,C),F=!1;(N.startsWith(`!`)||N.startsWith(`^`))&&(F=!0,N=N.slice(1)),N=N.replace(/\]/g,`\\]`),n+=`[${F?`^/`:``}${N}]`,S=C}}else C===`\\`&&S+1<t.length?(S++,n+=escapeRegex(t[S])):n+=escapeRegex(C);S++}return n}function findClassEnd(t,n){let S=n+1;for((t[S]===`!`||t[S]===`^`)&&S++,t[S]===`]`&&S++;S<t.length;S++)if(t[S]===`]`)return S;return-1}function escapeRegex(t){return/[.+^${}()|[\]\\*?]/.test(t)?`\\${t}`:t}function parseLine(t){let n=t.replace(/\r$/,``);if(n=n.replace(/(?<!\\)\s+$/,``),n===``||n.startsWith(`#`))return null;let S=!1;n.startsWith(`!`)?(S=!0,n=n.slice(1)):(n.startsWith(`\\!`)||n.startsWith(`\\#`))&&(n=n.slice(1));let C=!1;if(n.endsWith(`/`)&&!n.endsWith(`\\/`)&&(C=!0,n=n.slice(0,-1)),n===``)return null;let N=n.includes(`/`);n.startsWith(`/`)&&(n=n.slice(1));let F=globToRegexSource(n);return{re:RegExp(`^${N?``:`(?:.*/)?`}${F}$`),negate:S,dirOnly:C}}function compileGitignore(t,n){let S=[];for(let n of t){let t=parseLine(n);t&&S.push(t)}let relOf=t=>{let S=Ln(n,t);return S===``||S===`..`||S.startsWith(`..${Wn}`)||Fn(S)?null:Wn===`/`?S:S.split(Wn).join(`/`)},decide=(t,n)=>{for(let C=S.length-1;C>=0;C--){let N=S[C];if(!(N.dirOnly&&!n)&&N.re.test(t))return N.negate?`whitelist`:`ignore`}return null};return{base:n,matched(t,n){if(S.length===0)return null;let C=relOf(t);return C===null?null:decide(C,n)},matchedPathOrAnyParents(t,n){if(S.length===0)return null;let C=relOf(t);if(C===null)return null;let N=n;for(;;){let t=decide(C,N);if(t!==null)return t;let n=C.lastIndexOf(`/`);if(n===-1)return null;C=C.slice(0,n),N=!0}}}}function readGitignoreFile(t,n=zn(t)){let S;try{S=readFileSync(t,`utf-8`)}catch{return null}return compileGitignore(S.split(`
1784
- `),n)}var fq=__esmMin(()=>{ef(),qn()});function externalParserFor(t,n=!1){if(hq.has(t))return null;let S=Vn(t).slice(1),C=mq[t]??(S?pq[S]:void 0)??null;return C===`svelte`&&!n?null:C}function scanForNativeSkips(t,n=process.cwd(),S={}){let C=[],N=0,F=t.filter(t=>t.startsWith(`!`)).map(t=>t.slice(1)),I=[],H=readGitignoreFile(In(n,`.prettierignore`));H&&I.push(H),F.length&&I.push(compileGitignore(F,n));let globallyIgnored=(t,n,S)=>I.some(C=>(S?C.matchedPathOrAnyParents(t,n):C.matched(t,n))===`ignore`),W=S.configPath?Nn(n,S.configPath):null,q=loadScope(W??discoverConfig(n)),Y=W===null,scopeFor=t=>Y?nearestScope(t,q):q,expandBraces=t=>{let n=/\{([^{}]*)\}/.exec(t);return n?n[1].split(`,`).flatMap(S=>expandBraces(t.slice(0,n.index)+S+t.slice(n.index+n[0].length))):[t]},X=[],Z=new Set;for(let S of t){if(S.startsWith(`!`))continue;let t=Nn(n,S);if(/[*?[{]/.test(S)&&!existsSync(t))for(let t of expandBraces(S))X.push(RegExp(`^${globToRegexSource(t.includes(`/`)?t:`**/${t}`)}$`));else Z.add(t)}(X.length||Z.size===0)&&Z.add(Nn(n));let record=(t,n)=>{n?.ignore?.matchedPathOrAnyParents(t,!1)!==`ignore`&&(N++,externalParserFor(Bn(t),n?.svelte)&&C.push(t))},te=[];for(let t of Z){let n;try{n=statSync(t)}catch{continue}globallyIgnored(t,n.isDirectory(),!0)||(n.isDirectory()?te.push(t):n.isFile()&&record(t,scopeFor(zn(t))))}let matchesGlob=t=>{if(!X.length||Z.has(t))return!0;let S=Ln(n,t).split(Wn).join(`/`);return X.some(t=>t.test(S))},ne=new Set,walk=(t,n,S)=>{if(ne.has(t))return;ne.add(t);let C=readGitignoreFile(In(t,`.gitignore`)),N=C?[C,...n]:n;Y&&t!==S?.dir&&(S=scopeAt(t)??S);let F;try{F=readdirSync(t,{withFileTypes:!0})}catch{return}for(let n of F){let C=In(t,n.name),F=n.isDirectory();!F&&!n.isFile()||F&&(gq.has(n.name)||n.name===`node_modules`)||globallyIgnored(C,F,!1)||gitIgnored(N,C,F)||(F?walk(C,N,S):matchesGlob(C)&&record(C,S))}},re=te.every(t=>repoRootOf(t)!==null);for(let t of te)walk(t,parentGitignores(t,re?repoRootOf(t):null,re),scopeFor(t));return{skipped:C,total:N}}function gitIgnored(t,n,S){for(let C of t){let t=C.matched(n,S);if(t!==null)return t===`ignore`}return!1}function parentGitignores(t,n,S){if(S&&n===null)return[];let C=[];for(let S=t;S!==n;){let t=zn(S);if(t===S)break;S=t;let n=readGitignoreFile(In(S,`.gitignore`));n&&C.push(n)}let N=n?readGitignoreFile(In(n,`.git`,`info`,`exclude`),n):null;return N&&C.push(N),C}function repoRootOf(t){for(let n=t;;n=zn(n)){if(existsSync(In(n,`.git`))||existsSync(In(n,`.jj`)))return n;if(zn(n)===n)return null}}function configIn(t){for(let n of _q){let S=In(t,n);if(existsSync(S))return S}return null}function discoverConfig(t){for(let n=Nn(t);;n=zn(n)){let t=configIn(n);if(t)return t;if(zn(n)===n)return null}}function scopeAt(t){let n=configIn(t);return n?loadScope(n):null}function nearestScope(t,n){for(;;t=zn(t)){if(n&&t===n.dir)return n;let S=scopeAt(t);if(S)return S;if(zn(t)===t)return n}}function loadScope(t){if(!t)return null;let n=zn(t),S={};try{S=parseJsonc(readFileSync(t,`utf-8`))}catch{S={}}let C=Array.isArray(S.ignorePatterns)?S.ignorePatterns.filter(t=>typeof t==`string`):[];return{dir:n,ignore:C.length?compileGitignore(C,n):null,svelte:S.svelte!==void 0&&S.svelte!==null&&S.svelte!==!1}}function parseJsonc(t){let pass=(t,n)=>{let S=``;for(let C=0;C<t.length;){if(t[C]===`"`){let n=C+1;for(;n<t.length&&t[n]!==`"`;)n+=t[n]===`\\`?2:1;S+=t.slice(C,n+1),C=n+1;continue}let N=n(t,C);N>0?C+=N:S+=t[C++]}return S},n=pass(t,(t,n)=>{if(t.startsWith(`//`,n)){let S=t.indexOf(`
1785
- `,n);return(S===-1?t.length:S)-n}if(t.startsWith(`/*`,n)){let S=t.indexOf(`*/`,n+2);return(S===-1?t.length:S+2)-n}return 0});return JSON.parse(pass(n,(t,n)=>t[n]===`,`&&/^\s*[}\]]/.test(t.slice(n+1))?1:0))}var parsers,pq,mq,hq,gq,_q,vq=__esmMin(()=>{ef(),qn(),fq(),parsers=(t,n)=>Object.fromEntries(n.map(n=>[n,t])),pq={...parsers(`yaml`,[`yml`,`mir`,`reek`,`rviz`,`sublime-syntax`,`syntax`,`yaml`,`yaml-tmlanguage`]),...parsers(`markdown`,[`md`,`livemd`,`markdown`,`mdown`,`mdwn`,`mkd`,`mkdn`,`mkdown`,`ronn`,`scd`,`workbook`]),...parsers(`html`,[`html`,`hta`,`htm`,`inc`,`xht`,`xhtml`]),...parsers(`glimmer`,[`handlebars`,`hbs`]),mdx:`mdx`,vue:`vue`,svelte:`svelte`,mjml:`mjml`},mq={...parsers(`yaml`,[`.clang-format`,`.clang-tidy`,`.clangd`,`.gemrc`,`CITATION.cff`,`glide.lock`]),...parsers(`yaml`,[`pixi.lock`,`.prettierrc`,`.stylelintrc`,`.lintstagedrc`]),...parsers(`markdown`,[`contents.lr`,`README`])},hq=new Set([`package-lock.json`,`pnpm-lock.yaml`,`yarn.lock`,`MODULE.bazel.lock`,`bun.lock`,`deno.lock`,`composer.lock`,`Package.resolved`,`Pipfile.lock`,`flake.lock`,`mcmod.info`,`Cargo.lock`,`Gopkg.lock`,`pdm.lock`,`poetry.lock`,`uv.lock`]),gq=new Set([`.git`,`.jj`,`.sl`,`.svn`,`.hg`]),_q=[`.oxfmtrc.json`,`.oxfmtrc.jsonc`]});function handleInit({cwd:t,force:n}){let writeOne=(S,C)=>{let N=Nn(t,S);if(existsSync(N)&&!n){ge.log(`[gjsify format] ${S} exists at ${N} — pass --force to overwrite.`);return}writeFileSync(N,C,`utf-8`),ge.log(`[gjsify format] wrote ${N}`)};writeOne(`.oxlintrc.json`,loadOxlintTemplate()),writeOne(`.oxfmtrc.json`,loadOxfmtTemplate()),ge.log("[gjsify format] Run `gjsify format` to apply the formatter to the project.")}var yq,bq=__esmMin(()=>{_e(),ef(),qn(),oV(),vq(),yq={command:`format [paths..]`,description:`Format source files via oxfmt (Markdown/YAML/HTML/Vue need the napi build).`,builder:t=>t.positional(`paths`,{description:"Files or directories to format. Default: `.`",type:`string`,array:!0}).option(`write`,{description:`Modify files in place (default: true). Pass --no-write to report drift instead.`,type:`boolean`,default:!0}).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 an .oxfmtrc.json. Default: walks up from cwd to find one.`,type:`string`,normalize:!0}).option(`init`,{description:`Write recommended .oxlintrc.json + .oxfmtrc.json into cwd (skips existing files unless --force).`,type:`boolean`,default:!1}).option(`force`,{description:`Overwrite existing .oxlintrc.json / .oxfmtrc.json with --init.`,type:`boolean`,default:!1}).option(`verbose`,{description:`Echo the resolved oxfmt launcher + args before spawning.`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd();if(t.init){handleInit({cwd:n,force:t.force??!1});return}let S=t.paths?.length?t.paths:[`.`],C=[];t.check?C.push(`--check`):t.write===!1?C.push(`--list-different`):C.push(`--write`);let N=t.configPath??findOxfmtConfig(n)??void 0;if(N&&C.push(`--config`,Nn(N)),C.push(...S),t.check&&await shouldUseNativeOxfmt()){let t=scanForNativeSkips(S,n,{configPath:N});if(t.skipped.length>0){let S=t.skipped.map(t=>` ${Ln(n,t)||t}`).join(`
1786
- `);ge.error(`[gjsify format] ERROR: ${t.skipped.length} file(s) skipped — the native oxfmt (GJS) has no Prettier host for them (Markdown/HTML/Vue/YAML/…):\n${S}\n The format check is INCOMPLETE. Run \`gjsify format --check\` under Node to check these files, or add them to \`ignorePatterns\`.`),setOxcExitCode(1);return}}try{setOxcExitCode(await runOxfmt(C,{cwd:n,verbose:t.verbose}))}catch(t){if(t instanceof OxcNotFoundError){printOxcNotFound(t),setOxcExitCode(1);return}throw t}}}}),xq,Sq=__esmMin(()=>{qn(),oV(),xq={command:`lint [paths..]`,description:`Run oxlint diagnostics (spawned via its Node launcher to support JS plugins).`,builder:t=>t.positional(`paths`,{description:"Files or directories to lint. Default: `.`",type:`string`,array:!0}).option(`fix`,{description:`Apply safe lint fixes in place.`,type:`boolean`,default:!1}).option(`config-path`,{description:`Path to an .oxlintrc.json. Default: walks up from cwd to find one.`,type:`string`,normalize:!0}).option(`verbose`,{description:`Echo the resolved oxlint launcher + args before spawning.`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=t.paths?.length?t.paths:[`.`],C=[];t.fix&&C.push(`--fix`);let N=t.configPath??findOxlintConfig(n)??void 0;N&&C.push(`--config`,Nn(N)),C.push(...S);try{setOxcExitCode(await runOxlint(C,{cwd:n,verbose:t.verbose}))}catch(t){if(t instanceof OxcNotFoundError){printOxcNotFound(t),setOxcExitCode(1);return}throw t}}}}),Cq,wq=__esmMin(()=>{qn(),oV(),Cq={command:`fix [paths..]`,description:`Run oxfmt --write then oxlint --fix — format + safe lint fixes in one pass.`,builder:t=>t.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 an .oxlintrc.json. Default: walks up from cwd to find one.`,type:`string`,normalize:!0}).option(`verbose`,{description:`Echo the resolved oxc launchers + args before spawning.`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=t.paths?.length?t.paths:[`.`],C=t.verbose??!1,N=t.write!==!1;try{let F=[N?`--write`:`--list-different`],I=t.configPath??findOxfmtConfig(n)??void 0;I&&F.push(`--config`,Nn(I)),F.push(...S);let H=await runOxfmt(F,{cwd:n,verbose:C}),W=[];N&&W.push(`--fix`);let q=t.configPath??findOxlintConfig(n)??void 0;q&&W.push(`--config`,Nn(q)),W.push(...S);let Y=await runOxlint(W,{cwd:n,verbose:C});setOxcExitCode(H||Y)}catch(t){if(t instanceof OxcNotFoundError){printOxcNotFound(t),setOxcExitCode(1);return}throw t}}}});function createInterface(t,n){return typeof t==`object`&&t&&!(`read`in t&&typeof t.read==`function`)?new Interface(t):new Interface({input:t,output:n})}var Interface,Tq=__esmMin(()=>{Kd(),Interface=class extends Interface$1{question(t,n){return new Promise(n=>{super.question(t,n)})}}});function semverGt(t,n){try{return compare(t,n)===1}catch{return!1}}function groupByDependency(t){let n=new Map;for(let S of t){let t=n.get(S.name);t||(t={name:S.name,occurrences:[],declaredRanges:new Set,dominantRange:S.currentRange,highestVersion:S.currentVersion},n.set(S.name,t)),t.occurrences.push(S),t.declaredRanges.add(S.currentRange),S.currentVersion&&(!t.highestVersion||semverGt(S.currentVersion,t.highestVersion))&&(t.highestVersion=S.currentVersion)}for(let t of n.values()){let n=new Map;for(let S of t.occurrences)n.set(S.currentRange,(n.get(S.currentRange)??0)+1);let S=t.occurrences[0].currentRange,C=-1,N=null;for(let[t,F]of n.entries()){let n=parse(t.replace(/^[\^~>=<]+/,``))?.version??null;(F>C||F===C&&n&&N&&semverGt(n,N)||F===C&&t<S)&&(S=t,C=F,N=n)}t.dominantRange=S}return[...n.values()].sort((t,n)=>t.name.localeCompare(n.name))}function isInconsistent(t){return t.declaredRanges.size>1}function findInconsistencies(t){return t.filter(isInconsistent)}var Eq=__esmMin(()=>{OI()});function discoverContext(t){let n=findWorkspaceRoot(t);if(n)return{root:n,workspaces:discoverWorkspaces(n,{includeRoot:!0}),isMonorepo:!0};let S=In(t,`package.json`);if(!existsSync(S))throw Error(`[gjsify upgrade] no package.json at ${S}`);let C=JSON.parse(readFileSync(S,`utf-8`));return{root:t,workspaces:[{name:C.name??`<root>`,location:t,relativeLocation:`.`,version:C.version??`0.0.0`,manifest:C,private:C.private===!0}],isMonorepo:!1}}function applyWorkspaceFilter(t,n,S){let C=n?.split(`,`).map(t=>t.trim()).filter(Boolean),N=S?.split(`,`).map(t=>t.trim()).filter(Boolean);return(!C||C.length===0)&&(!N||N.length===0)?t:filterWorkspaces(t,{include:C,exclude:N})}function parseFilterList(t){return t?t.split(`,`).map(t=>t.trim().toLowerCase()).filter(Boolean):[]}function collectAllDeclarations(t,n){let S=[];for(let C of t)for(let t of collectFromWorkspace(C,n))S.push(t);return S}function collectFromWorkspace(t,n){let S=[],C=t.manifest;for(let N of Oq){let F=C[N];if(!(!F||typeof F!=`object`))for(let[C,I]of Object.entries(F)){if(typeof I!=`string`||n.length&&!n.some(t=>C.toLowerCase().includes(t))||isDistTagSpec(I)||I.startsWith(`workspace:`)||I.startsWith(`file:`)||I.startsWith(`link:`)||I.startsWith(`git+`)||I.startsWith(`git:`)||I.startsWith(`http:`)||I.startsWith(`https:`)||I.startsWith(`npm:`)||I.startsWith(`portal:`))continue;let{prefix:F,version:H}=splitRange(I);S.push({workspace:t.name,workspaceLocation:t.location,name:C,field:N,currentRange:I,currentVersion:H,prefix:F})}}return S}function isDistTagSpec(t){let n=t.trim();return kq.has(n)||!/^[A-Za-z]/.test(n)||/^v\d/.test(n)||/^v[xX*]/.test(n)?!1:/^[A-Za-z][\w.-]*$/.test(n)}function splitRange(t){let n=t.match(/^(\^|~|>=|<=|>|<|=)?\s*([0-9].*)$/);if(!n)return{prefix:``,version:null};let S=n[1]??``,C=n[2]?.split(/\s|[|&,]/)[0]??null;return{prefix:S,version:(C?parse(C):null)?.version??null}}function reportInexactRanges(t){let n=t.map(t=>({name:t.name,loose:t.occurrences.filter(t=>t.prefix!==``)})).filter(t=>t.loose.length>0);if(n.length===0)return 0;let S=n.reduce((t,n)=>t+n.loose.length,0);ge.error(`gjsify upgrade --check --exact: FAIL. ${S} declaration(s) across ${n.length} dep(s) carry a range operator:\n`);for(let t of n){let n=new Map;for(let S of t.loose){let t=n.get(S.currentRange)??[];t.push(S.workspace),n.set(S.currentRange,t)}ge.error(` ${Aq.bold}${t.name}${Aq.reset}`);for(let[t,S]of n.entries()){let n=S.length>6?`${S.slice(0,6).join(`, `)} … +${S.length-6}`:S.join(`, `);ge.error(` ${t.padEnd(16)} — ${n}`)}}return S}function checkLockfileRangeViolations(t,n){let S=In(n,`gjsify-lock.json`);if(!existsSync(S))return 0;let C;try{C=JSON.parse(readFileSync(S,`utf-8`))}catch{return 0}if(!C.packages)return 0;let N=new Map;for(let n of t){let t=N.get(n.name)??new Set;for(let S of n.occurrences)t.add(S.currentRange);N.set(n.name,t)}let F=0;for(let[t,n]of Object.entries(C.packages)){if(!n.version)continue;let S=t.split(`node_modules/`);if(S.length!==2)continue;let C=S[1],I=N.get(C);if(!I||I.size===0)continue;let H=!1;for(let t of I)try{if(n.version&&satisfies(n.version,t)){H=!0;break}}catch{}H||(ge.error(` ${C}: lockfile has ${n.version}, but declared ranges are ${[...I].join(`, `)}`),F++)}return F>0&&ge.error(`gjsify upgrade --check: FAIL. ${F} lockfile entr${F===1?`y`:`ies`} violate declared ranges:\n`),F}function runCheckMode(t,n=!1,S=process.cwd()){checkLockfileRangeViolations(t,S);let C=n?reportInexactRanges(t):0,N=findInconsistencies(t);if(N.length===0&&C>0)return ge.error("\nFix: run `gjsify upgrade --align --exact` (offline; drops the operator and keeps the version)."),process.exit(1);if(N.length===0){ge.log(`gjsify upgrade --check: OK. ${t.length} dep(s) consistently declared across workspaces`+(n?`, every declaration pinned exactly.`:`.`));return}ge.error(`gjsify upgrade --check: FAIL. ${N.length} dep(s) declared at inconsistent ranges:\n`);for(let t of N){let n=new Map;for(let S of t.occurrences){let t=n.get(S.currentRange)??[];t.push(S.workspace),n.set(S.currentRange,t)}ge.error(` ${Aq.bold}${t.name}${Aq.reset}`);for(let[t,S]of n.entries())ge.error(` ${t.padEnd(16)} — ${S.join(`, `)}`)}ge.error(n?"\nFix: run `gjsify upgrade --align --exact` (offline; aligns each dep to its highest declared version and drops the operator).":"\nFix: run `gjsify upgrade --align` (offline; aligns each dep to its highest declared range)."),process.exit(1)}function alignTargets(t,n){return n?t.filter(t=>isInconsistent(t)||t.occurrences.some(t=>t.prefix!==``)):findInconsistencies(t)}function reportUnrepairable(t){ge.error(`\ngjsify upgrade --align: ${t.length} dep(s) left unrepaired — no version to align on:\n`);for(let n of t)ge.error(` ${Aq.bold}${n.name}${Aq.reset} ${[...n.declaredRanges].join(`, `)}`);return ge.error("\nThose ranges name no single version. Edit them by hand, or resolve one with `--latest`."),process.exit(1)}function runAlignMode(t,n){let S=n.exact??!1,C=alignTargets(t,S);if(C.length===0){ge.log(`gjsify upgrade --align: nothing to do. ${t.length} dep(s) already consistent`+(S?`, every declaration pinned exactly.`:`.`));return}let N=[],F=[];for(let t of C){if(!t.highestVersion){F.push(t);continue}let n=t.occurrences.find(n=>n.currentRange===t.dominantRange)?.prefix||`^`;N.push({...t,latestVersion:t.highestVersion,diff:`none`,occurrences:t.occurrences.map(t=>({...t,prefix:n}))})}if(N.length>0){ge.log(S?`gjsify upgrade --align --exact: pinning ${N.length} dep(s) to their highest declared version, without a range operator:\n`:`gjsify upgrade --align: aligning ${N.length} inconsistent dep(s) to their highest declared version:\n`);for(let t of N){let n=t.occurrences[0]?.prefix??`^`;ge.log(` ${t.name.padEnd(28)} ranges: ${[...t.declaredRanges].join(`, `)} → ${targetRange(n,t.latestVersion,S)}`)}if(n.dryRun)ge.log(`
1787
- [gjsify upgrade --align] --dry-run: no files changed.`);else{let t=applyToFiles(N,S);ge.log(`\n✏️ updated ${N.length} dep(s) across ${t} package.json file(s).`)}}if(F.length>0)return reportUnrepairable(F)}async function resolveCandidateGroups(t,n,S,C){let N=[],F=0;async function worker(){for(;;){let I=F++;if(I>=t.length)return;let H=t[I];try{let t=(await fetchPackument(H.name,{npmrc:n}))[`dist-tags`]?.latest;if(!t){S&&ge.warn(` ${H.name}: no dist-tags.latest, skipping`);continue}let F=H.highestVersion;if(!F){S&&ge.warn(` ${H.name}: unable to parse any current range`);continue}let I=classifyDiff(F,t);if(I===`none`||C===`minor`&&I===`major`||C===`patch`&&(I===`major`||I===`minor`))continue;N.push({...H,latestVersion:t,diff:I})}catch(t){S&&ge.warn(` ${H.name}: fetch failed (${t.message})`)}}}return await Promise.all(Array.from({length:8},()=>worker())),N.sort((t,n)=>t.name.localeCompare(n.name)),N}function classifyDiff(t,n){let S=parse(t),C=parse(n);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`}function colorForDiff(t){switch(t){case`major`:return Aq.red;case`minor`:return Aq.yellow;case`patch`:return Aq.green;case`prerelease`:return Aq.cyan;default:return``}}function printTable(t){let n=Math.max(...t.map(t=>t.name.length),4),S=Math.max(...t.map(t=>`${t.occurrences.length}`.length+2),3),C=Math.max(...t.map(t=>declaredCellWidth(t)),7),N=Math.max(...t.map(t=>t.latestVersion.length),6),F=String(t.length).length+2,I=` `.repeat(F+2)+Aq.bold+`name`.padEnd(n)+` `+`fan`.padEnd(S)+` `+`declared`.padEnd(C)+` `+`latest`.padEnd(N)+` kind`+Aq.reset;ge.log(I),ge.log(` `.repeat(F+2)+Aq.dim+`─`.repeat(n+S+C+N+16)+Aq.reset);for(let I=0;I<t.length;I++){let H=t[I],W=`${I+1}.`.padEnd(F),q=H.declaredRanges.size>1?`${Aq.magenta}⚠ ${Aq.reset}`:` `,Y=colorForDiff(H.diff);ge.log(W+q+H.name.padEnd(n)+` `+Aq.dim+`${H.occurrences.length}`.padEnd(S)+Aq.reset+` `+Aq.dim+renderDeclaredCell(H).padEnd(C)+Aq.reset+` `+Y+H.latestVersion.padEnd(N)+Aq.reset+` `+Y+H.diff+Aq.reset)}let H=t.filter(t=>t.declaredRanges.size>1).length;H>0&&ge.log(`\n${Aq.magenta}⚠${Aq.reset} ${H} dep(s) declared at inconsistent ranges across workspaces.`)}function declaredCellWidth(t){return renderDeclaredCell(t).length}function renderDeclaredCell(t){if(t.declaredRanges.size===1)return[...t.declaredRanges][0];let n=[...t.declaredRanges].sort().join(`, `);return n.length<=32?n:n.slice(0,29)+`…`}function printChangePlan(t,n=!1){for(let S of t)for(let t of S.occurrences)ge.log(` ${t.workspace.padEnd(38)} ${S.name.padEnd(28)} ${t.currentRange.padEnd(12)} → ${targetRange(t.prefix,S.latestVersion,n)}`)}async function promptSelection(t){if(!process.stdin.isTTY)return ge.log(`[gjsify upgrade] non-TTY stdin: pass --latest / --minor / --patch (or --yes for interactive-all) to upgrade non-interactively.`),[];let n=createInterface({input:process.stdin,output:process.stdout});try{ge.log(`
1788
- Select upgrades: comma- or space-separated indices, `+Aq.bold+`a`+Aq.reset+` for all, ranges like `+Aq.bold+`1-3`+Aq.reset+`, or `+Aq.bold+`ENTER`+Aq.reset+` to skip:`);let S=(await n.question(`> `)).trim();if(!S)return[];if(S.toLowerCase()===`a`||S.toLowerCase()===`all`)return[...t];let C=new Set;for(let t of S.split(/[\s,]+/).filter(Boolean)){let n=t.match(/^(\d+)-(\d+)$/);if(n){let t=Number(n[1]),S=Number(n[2]);for(let n=Math.min(t,S);n<=Math.max(t,S);n++)C.add(n-1)}else/^\d+$/.test(t)&&C.add(Number(t)-1)}return[...C].filter(n=>n>=0&&n<t.length).map(n=>t[n])}finally{n.close()}}function targetRange(t,n,S){return S?n:`${t}${n}`}function applyToFiles(t,n=!1){let S=new Map;for(let n of t)for(let t of n.occurrences){let C=S.get(t.workspaceLocation)??[];C.push({...n,occurrences:[t]}),S.set(t.workspaceLocation,C)}let C=0;for(let[t,N]of S.entries()){let S=In(t,`package.json`),F=readFileSync(S,`utf-8`),I=JSON.parse(F),H=!1,W=[];for(let t of N){let S=t.occurrences[0],C=I[S.field];if(!C)continue;let N=targetRange(S.prefix,t.latestVersion,n);C[t.name]!==N&&(C[t.name]=N,H=!0,W.push(t.name))}if(H){let t=detectIndent(F);writeFileSync(S,keepUntouchedLines(F,JSON.stringify(I,null,t)+(F.endsWith(`
1784
+ `),n)}var pq=__esmMin(()=>{ef(),qn()});function externalParserFor(t,n=!1){if(gq.has(t))return null;let S=Vn(t).slice(1),C=hq[t]??(S?mq[S]:void 0)??null;return C===`svelte`&&!n?null:C}function scanForNativeSkips(t,n=process.cwd(),S={}){let C=[],N=0,F=t.filter(t=>t.startsWith(`!`)).map(t=>t.slice(1)),I=[],H=readGitignoreFile(In(n,`.prettierignore`));H&&I.push(H),F.length&&I.push(compileGitignore(F,n));let globallyIgnored=(t,n,S)=>I.some(C=>(S?C.matchedPathOrAnyParents(t,n):C.matched(t,n))===`ignore`),W=S.configPath?Nn(n,S.configPath):null,q=loadScope(W??discoverConfig(n)),Y=W===null,scopeFor=t=>Y?nearestScope(t,q):q,expandBraces=t=>{let n=/\{([^{}]*)\}/.exec(t);return n?n[1].split(`,`).flatMap(S=>expandBraces(t.slice(0,n.index)+S+t.slice(n.index+n[0].length))):[t]},X=[],Z=new Set;for(let S of t){if(S.startsWith(`!`))continue;let t=Nn(n,S);if(/[*?[{]/.test(S)&&!existsSync(t))for(let t of expandBraces(S))X.push(RegExp(`^${globToRegexSource(t.includes(`/`)?t:`**/${t}`)}$`));else Z.add(t)}(X.length||Z.size===0)&&Z.add(Nn(n));let record=(t,n)=>{n?.ignore?.matchedPathOrAnyParents(t,!1)!==`ignore`&&(N++,externalParserFor(Bn(t),n?.svelte)&&C.push(t))},te=[];for(let t of Z){let n;try{n=statSync(t)}catch{continue}globallyIgnored(t,n.isDirectory(),!0)||(n.isDirectory()?te.push(t):n.isFile()&&record(t,scopeFor(zn(t))))}let matchesGlob=t=>{if(!X.length||Z.has(t))return!0;let S=Ln(n,t).split(Wn).join(`/`);return X.some(t=>t.test(S))},ne=new Set,walk=(t,n,S)=>{if(ne.has(t))return;ne.add(t);let C=readGitignoreFile(In(t,`.gitignore`)),N=C?[C,...n]:n;Y&&t!==S?.dir&&(S=scopeAt(t)??S);let F;try{F=readdirSync(t,{withFileTypes:!0})}catch{return}for(let n of F){let C=In(t,n.name),F=n.isDirectory();!F&&!n.isFile()||F&&(_q.has(n.name)||n.name===`node_modules`)||globallyIgnored(C,F,!1)||gitIgnored(N,C,F)||(F?walk(C,N,S):matchesGlob(C)&&record(C,S))}},re=te.every(t=>repoRootOf(t)!==null);for(let t of te)walk(t,parentGitignores(t,re?repoRootOf(t):null,re),scopeFor(t));return{skipped:C,total:N}}function gitIgnored(t,n,S){for(let C of t){let t=C.matched(n,S);if(t!==null)return t===`ignore`}return!1}function parentGitignores(t,n,S){if(S&&n===null)return[];let C=[];for(let S=t;S!==n;){let t=zn(S);if(t===S)break;S=t;let n=readGitignoreFile(In(S,`.gitignore`));n&&C.push(n)}let N=n?readGitignoreFile(In(n,`.git`,`info`,`exclude`),n):null;return N&&C.push(N),C}function repoRootOf(t){for(let n=t;;n=zn(n)){if(existsSync(In(n,`.git`))||existsSync(In(n,`.jj`)))return n;if(zn(n)===n)return null}}function configIn(t){for(let n of vq){let S=In(t,n);if(existsSync(S))return S}return null}function discoverConfig(t){for(let n=Nn(t);;n=zn(n)){let t=configIn(n);if(t)return t;if(zn(n)===n)return null}}function scopeAt(t){let n=configIn(t);return n?loadScope(n):null}function nearestScope(t,n){for(;;t=zn(t)){if(n&&t===n.dir)return n;let S=scopeAt(t);if(S)return S;if(zn(t)===t)return n}}function loadScope(t){if(!t)return null;let n=zn(t),S={};try{S=parseJsonc(readFileSync(t,`utf-8`))}catch{S={}}let C=Array.isArray(S.ignorePatterns)?S.ignorePatterns.filter(t=>typeof t==`string`):[];return{dir:n,ignore:C.length?compileGitignore(C,n):null,svelte:S.svelte!==void 0&&S.svelte!==null&&S.svelte!==!1}}function parseJsonc(t){let pass=(t,n)=>{let S=``;for(let C=0;C<t.length;){if(t[C]===`"`){let n=C+1;for(;n<t.length&&t[n]!==`"`;)n+=t[n]===`\\`?2:1;S+=t.slice(C,n+1),C=n+1;continue}let N=n(t,C);N>0?C+=N:S+=t[C++]}return S},n=pass(t,(t,n)=>{if(t.startsWith(`//`,n)){let S=t.indexOf(`
1785
+ `,n);return(S===-1?t.length:S)-n}if(t.startsWith(`/*`,n)){let S=t.indexOf(`*/`,n+2);return(S===-1?t.length:S+2)-n}return 0});return JSON.parse(pass(n,(t,n)=>t[n]===`,`&&/^\s*[}\]]/.test(t.slice(n+1))?1:0))}var parsers,mq,hq,gq,_q,vq,yq=__esmMin(()=>{ef(),qn(),pq(),parsers=(t,n)=>Object.fromEntries(n.map(n=>[n,t])),mq={...parsers(`yaml`,[`yml`,`mir`,`reek`,`rviz`,`sublime-syntax`,`syntax`,`yaml`,`yaml-tmlanguage`]),...parsers(`markdown`,[`md`,`livemd`,`markdown`,`mdown`,`mdwn`,`mkd`,`mkdn`,`mkdown`,`ronn`,`scd`,`workbook`]),...parsers(`html`,[`html`,`hta`,`htm`,`inc`,`xht`,`xhtml`]),...parsers(`glimmer`,[`handlebars`,`hbs`]),mdx:`mdx`,vue:`vue`,svelte:`svelte`,mjml:`mjml`},hq={...parsers(`yaml`,[`.clang-format`,`.clang-tidy`,`.clangd`,`.gemrc`,`CITATION.cff`,`glide.lock`]),...parsers(`yaml`,[`pixi.lock`,`.prettierrc`,`.stylelintrc`,`.lintstagedrc`]),...parsers(`markdown`,[`contents.lr`,`README`])},gq=new Set([`package-lock.json`,`pnpm-lock.yaml`,`yarn.lock`,`MODULE.bazel.lock`,`bun.lock`,`deno.lock`,`composer.lock`,`Package.resolved`,`Pipfile.lock`,`flake.lock`,`mcmod.info`,`Cargo.lock`,`Gopkg.lock`,`pdm.lock`,`poetry.lock`,`uv.lock`]),_q=new Set([`.git`,`.jj`,`.sl`,`.svn`,`.hg`]),vq=[`.oxfmtrc.json`,`.oxfmtrc.jsonc`]});function handleInit({cwd:t,force:n}){let writeOne=(S,C)=>{let N=Nn(t,S);if(existsSync(N)&&!n){ge.log(`[gjsify format] ${S} exists at ${N} — pass --force to overwrite.`);return}writeFileSync(N,C,`utf-8`),ge.log(`[gjsify format] wrote ${N}`)};writeOne(`.oxlintrc.json`,loadOxlintTemplate()),writeOne(`.oxfmtrc.json`,loadOxfmtTemplate()),ge.log("[gjsify format] Run `gjsify format` to apply the formatter to the project.")}var bq,xq=__esmMin(()=>{_e(),ef(),qn(),sV(),yq(),bq={command:`format [paths..]`,description:`Format source files via oxfmt (Markdown/YAML/HTML/Vue need the napi build).`,builder:t=>t.positional(`paths`,{description:"Files or directories to format. Default: `.`",type:`string`,array:!0}).option(`write`,{description:`Modify files in place (default: true). Pass --no-write to report drift instead.`,type:`boolean`,default:!0}).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 an .oxfmtrc.json. Default: walks up from cwd to find one.`,type:`string`,normalize:!0}).option(`init`,{description:`Write recommended .oxlintrc.json + .oxfmtrc.json into cwd (skips existing files unless --force).`,type:`boolean`,default:!1}).option(`force`,{description:`Overwrite existing .oxlintrc.json / .oxfmtrc.json with --init.`,type:`boolean`,default:!1}).option(`verbose`,{description:`Echo the resolved oxfmt launcher + args before spawning.`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd();if(t.init){handleInit({cwd:n,force:t.force??!1});return}let S=t.paths?.length?t.paths:[`.`],C=[];t.check?C.push(`--check`):t.write===!1?C.push(`--list-different`):C.push(`--write`);let N=t.configPath??findOxfmtConfig(n)??void 0;if(N&&C.push(`--config`,Nn(N)),C.push(...S),t.check&&await shouldUseNativeOxfmt()){let t=scanForNativeSkips(S,n,{configPath:N});if(t.skipped.length>0){let S=t.skipped.map(t=>` ${Ln(n,t)||t}`).join(`
1786
+ `);ge.error(`[gjsify format] ERROR: ${t.skipped.length} file(s) skipped — the native oxfmt (GJS) has no Prettier host for them (Markdown/HTML/Vue/YAML/…):\n${S}\n The format check is INCOMPLETE. Run \`gjsify format --check\` under Node to check these files, or add them to \`ignorePatterns\`.`),setOxcExitCode(1);return}}try{setOxcExitCode(await runOxfmt(C,{cwd:n,verbose:t.verbose}))}catch(t){if(t instanceof OxcNotFoundError){printOxcNotFound(t),setOxcExitCode(1);return}throw t}}}}),Sq,Cq=__esmMin(()=>{qn(),sV(),Sq={command:`lint [paths..]`,description:`Run oxlint diagnostics (spawned via its Node launcher to support JS plugins).`,builder:t=>t.positional(`paths`,{description:"Files or directories to lint. Default: `.`",type:`string`,array:!0}).option(`fix`,{description:`Apply safe lint fixes in place.`,type:`boolean`,default:!1}).option(`config-path`,{description:`Path to an .oxlintrc.json. Default: walks up from cwd to find one.`,type:`string`,normalize:!0}).option(`verbose`,{description:`Echo the resolved oxlint launcher + args before spawning.`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=t.paths?.length?t.paths:[`.`],C=[];t.fix&&C.push(`--fix`);let N=t.configPath??findOxlintConfig(n)??void 0;N&&C.push(`--config`,Nn(N)),C.push(...S);try{setOxcExitCode(await runOxlint(C,{cwd:n,verbose:t.verbose}))}catch(t){if(t instanceof OxcNotFoundError){printOxcNotFound(t),setOxcExitCode(1);return}throw t}}}}),wq,Tq=__esmMin(()=>{qn(),sV(),wq={command:`fix [paths..]`,description:`Run oxfmt --write then oxlint --fix — format + safe lint fixes in one pass.`,builder:t=>t.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 an .oxlintrc.json. Default: walks up from cwd to find one.`,type:`string`,normalize:!0}).option(`verbose`,{description:`Echo the resolved oxc launchers + args before spawning.`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=t.paths?.length?t.paths:[`.`],C=t.verbose??!1,N=t.write!==!1;try{let F=[N?`--write`:`--list-different`],I=t.configPath??findOxfmtConfig(n)??void 0;I&&F.push(`--config`,Nn(I)),F.push(...S);let H=await runOxfmt(F,{cwd:n,verbose:C}),W=[];N&&W.push(`--fix`);let q=t.configPath??findOxlintConfig(n)??void 0;q&&W.push(`--config`,Nn(q)),W.push(...S);let Y=await runOxlint(W,{cwd:n,verbose:C});setOxcExitCode(H||Y)}catch(t){if(t instanceof OxcNotFoundError){printOxcNotFound(t),setOxcExitCode(1);return}throw t}}}});function createInterface(t,n){return typeof t==`object`&&t&&!(`read`in t&&typeof t.read==`function`)?new Interface(t):new Interface({input:t,output:n})}var Interface,Eq=__esmMin(()=>{Kd(),Interface=class extends Interface$1{question(t,n){return new Promise(n=>{super.question(t,n)})}}});function semverGt(t,n){try{return compare(t,n)===1}catch{return!1}}function groupByDependency(t){let n=new Map;for(let S of t){let t=n.get(S.name);t||(t={name:S.name,occurrences:[],declaredRanges:new Set,dominantRange:S.currentRange,highestVersion:S.currentVersion},n.set(S.name,t)),t.occurrences.push(S),t.declaredRanges.add(S.currentRange),S.currentVersion&&(!t.highestVersion||semverGt(S.currentVersion,t.highestVersion))&&(t.highestVersion=S.currentVersion)}for(let t of n.values()){let n=new Map;for(let S of t.occurrences)n.set(S.currentRange,(n.get(S.currentRange)??0)+1);let S=t.occurrences[0].currentRange,C=-1,N=null;for(let[t,F]of n.entries()){let n=parse(t.replace(/^[\^~>=<]+/,``))?.version??null;(F>C||F===C&&n&&N&&semverGt(n,N)||F===C&&t<S)&&(S=t,C=F,N=n)}t.dominantRange=S}return[...n.values()].sort((t,n)=>t.name.localeCompare(n.name))}function isInconsistent(t){return t.declaredRanges.size>1}function findInconsistencies(t){return t.filter(isInconsistent)}var Dq=__esmMin(()=>{OI()});function discoverContext(t){let n=findWorkspaceRoot(t);if(n)return{root:n,workspaces:discoverWorkspaces(n,{includeRoot:!0}),isMonorepo:!0};let S=In(t,`package.json`);if(!existsSync(S))throw Error(`[gjsify upgrade] no package.json at ${S}`);let C=JSON.parse(readFileSync(S,`utf-8`));return{root:t,workspaces:[{name:C.name??`<root>`,location:t,relativeLocation:`.`,version:C.version??`0.0.0`,manifest:C,private:C.private===!0}],isMonorepo:!1}}function applyWorkspaceFilter(t,n,S){let C=n?.split(`,`).map(t=>t.trim()).filter(Boolean),N=S?.split(`,`).map(t=>t.trim()).filter(Boolean);return(!C||C.length===0)&&(!N||N.length===0)?t:filterWorkspaces(t,{include:C,exclude:N})}function parseFilterList(t){return t?t.split(`,`).map(t=>t.trim().toLowerCase()).filter(Boolean):[]}function collectAllDeclarations(t,n){let S=[];for(let C of t)for(let t of collectFromWorkspace(C,n))S.push(t);return S}function collectFromWorkspace(t,n){let S=[],C=t.manifest;for(let N of kq){let F=C[N];if(!(!F||typeof F!=`object`))for(let[C,I]of Object.entries(F)){if(typeof I!=`string`||n.length&&!n.some(t=>C.toLowerCase().includes(t))||isDistTagSpec(I)||I.startsWith(`workspace:`)||I.startsWith(`file:`)||I.startsWith(`link:`)||I.startsWith(`git+`)||I.startsWith(`git:`)||I.startsWith(`http:`)||I.startsWith(`https:`)||I.startsWith(`npm:`)||I.startsWith(`portal:`))continue;let{prefix:F,version:H}=splitRange(I);S.push({workspace:t.name,workspaceLocation:t.location,name:C,field:N,currentRange:I,currentVersion:H,prefix:F})}}return S}function isDistTagSpec(t){let n=t.trim();return Aq.has(n)||!/^[A-Za-z]/.test(n)||/^v\d/.test(n)||/^v[xX*]/.test(n)?!1:/^[A-Za-z][\w.-]*$/.test(n)}function splitRange(t){let n=t.match(/^(\^|~|>=|<=|>|<|=)?\s*([0-9].*)$/);if(!n)return{prefix:``,version:null};let S=n[1]??``,C=n[2]?.split(/\s|[|&,]/)[0]??null;return{prefix:S,version:(C?parse(C):null)?.version??null}}function reportInexactRanges(t){let n=t.map(t=>({name:t.name,loose:t.occurrences.filter(t=>t.prefix!==``)})).filter(t=>t.loose.length>0);if(n.length===0)return 0;let S=n.reduce((t,n)=>t+n.loose.length,0);ge.error(`gjsify upgrade --check --exact: FAIL. ${S} declaration(s) across ${n.length} dep(s) carry a range operator:\n`);for(let t of n){let n=new Map;for(let S of t.loose){let t=n.get(S.currentRange)??[];t.push(S.workspace),n.set(S.currentRange,t)}ge.error(` ${jq.bold}${t.name}${jq.reset}`);for(let[t,S]of n.entries()){let n=S.length>6?`${S.slice(0,6).join(`, `)} … +${S.length-6}`:S.join(`, `);ge.error(` ${t.padEnd(16)} — ${n}`)}}return S}function checkLockfileRangeViolations(t,n){let S=In(n,`gjsify-lock.json`);if(!existsSync(S))return 0;let C;try{C=JSON.parse(readFileSync(S,`utf-8`))}catch{return 0}if(!C.packages)return 0;let N=new Map;for(let n of t){let t=N.get(n.name)??new Set;for(let S of n.occurrences)t.add(S.currentRange);N.set(n.name,t)}let F=0;for(let[t,n]of Object.entries(C.packages)){if(!n.version)continue;let S=t.split(`node_modules/`);if(S.length!==2)continue;let C=S[1],I=N.get(C);if(!I||I.size===0)continue;let H=!1;for(let t of I)try{if(n.version&&satisfies(n.version,t)){H=!0;break}}catch{}H||(ge.error(` ${C}: lockfile has ${n.version}, but declared ranges are ${[...I].join(`, `)}`),F++)}return F>0&&ge.error(`gjsify upgrade --check: FAIL. ${F} lockfile entr${F===1?`y`:`ies`} violate declared ranges:\n`),F}function runCheckMode(t,n=!1,S=process.cwd()){checkLockfileRangeViolations(t,S);let C=n?reportInexactRanges(t):0,N=findInconsistencies(t);if(N.length===0&&C>0)return ge.error("\nFix: run `gjsify upgrade --align --exact` (offline; drops the operator and keeps the version)."),process.exit(1);if(N.length===0){ge.log(`gjsify upgrade --check: OK. ${t.length} dep(s) consistently declared across workspaces`+(n?`, every declaration pinned exactly.`:`.`));return}ge.error(`gjsify upgrade --check: FAIL. ${N.length} dep(s) declared at inconsistent ranges:\n`);for(let t of N){let n=new Map;for(let S of t.occurrences){let t=n.get(S.currentRange)??[];t.push(S.workspace),n.set(S.currentRange,t)}ge.error(` ${jq.bold}${t.name}${jq.reset}`);for(let[t,S]of n.entries())ge.error(` ${t.padEnd(16)} — ${S.join(`, `)}`)}ge.error(n?"\nFix: run `gjsify upgrade --align --exact` (offline; aligns each dep to its highest declared version and drops the operator).":"\nFix: run `gjsify upgrade --align` (offline; aligns each dep to its highest declared range)."),process.exit(1)}function alignTargets(t,n){return n?t.filter(t=>isInconsistent(t)||t.occurrences.some(t=>t.prefix!==``)):findInconsistencies(t)}function reportUnrepairable(t){ge.error(`\ngjsify upgrade --align: ${t.length} dep(s) left unrepaired — no version to align on:\n`);for(let n of t)ge.error(` ${jq.bold}${n.name}${jq.reset} ${[...n.declaredRanges].join(`, `)}`);return ge.error("\nThose ranges name no single version. Edit them by hand, or resolve one with `--latest`."),process.exit(1)}function runAlignMode(t,n){let S=n.exact??!1,C=alignTargets(t,S);if(C.length===0){ge.log(`gjsify upgrade --align: nothing to do. ${t.length} dep(s) already consistent`+(S?`, every declaration pinned exactly.`:`.`));return}let N=[],F=[];for(let t of C){if(!t.highestVersion){F.push(t);continue}let n=t.occurrences.find(n=>n.currentRange===t.dominantRange)?.prefix||`^`;N.push({...t,latestVersion:t.highestVersion,diff:`none`,occurrences:t.occurrences.map(t=>({...t,prefix:n}))})}if(N.length>0){ge.log(S?`gjsify upgrade --align --exact: pinning ${N.length} dep(s) to their highest declared version, without a range operator:\n`:`gjsify upgrade --align: aligning ${N.length} inconsistent dep(s) to their highest declared version:\n`);for(let t of N){let n=t.occurrences[0]?.prefix??`^`;ge.log(` ${t.name.padEnd(28)} ranges: ${[...t.declaredRanges].join(`, `)} → ${targetRange(n,t.latestVersion,S)}`)}if(n.dryRun)ge.log(`
1787
+ [gjsify upgrade --align] --dry-run: no files changed.`);else{let t=applyToFiles(N,S);ge.log(`\n✏️ updated ${N.length} dep(s) across ${t} package.json file(s).`)}}if(F.length>0)return reportUnrepairable(F)}async function resolveCandidateGroups(t,n,S,C){let N=[],F=0;async function worker(){for(;;){let I=F++;if(I>=t.length)return;let H=t[I];try{let t=(await fetchPackument(H.name,{npmrc:n}))[`dist-tags`]?.latest;if(!t){S&&ge.warn(` ${H.name}: no dist-tags.latest, skipping`);continue}let F=H.highestVersion;if(!F){S&&ge.warn(` ${H.name}: unable to parse any current range`);continue}let I=classifyDiff(F,t);if(I===`none`||C===`minor`&&I===`major`||C===`patch`&&(I===`major`||I===`minor`))continue;N.push({...H,latestVersion:t,diff:I})}catch(t){S&&ge.warn(` ${H.name}: fetch failed (${t.message})`)}}}return await Promise.all(Array.from({length:8},()=>worker())),N.sort((t,n)=>t.name.localeCompare(n.name)),N}function classifyDiff(t,n){let S=parse(t),C=parse(n);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`}function colorForDiff(t){switch(t){case`major`:return jq.red;case`minor`:return jq.yellow;case`patch`:return jq.green;case`prerelease`:return jq.cyan;default:return``}}function printTable(t){let n=Math.max(...t.map(t=>t.name.length),4),S=Math.max(...t.map(t=>`${t.occurrences.length}`.length+2),3),C=Math.max(...t.map(t=>declaredCellWidth(t)),7),N=Math.max(...t.map(t=>t.latestVersion.length),6),F=String(t.length).length+2,I=` `.repeat(F+2)+jq.bold+`name`.padEnd(n)+` `+`fan`.padEnd(S)+` `+`declared`.padEnd(C)+` `+`latest`.padEnd(N)+` kind`+jq.reset;ge.log(I),ge.log(` `.repeat(F+2)+jq.dim+`─`.repeat(n+S+C+N+16)+jq.reset);for(let I=0;I<t.length;I++){let H=t[I],W=`${I+1}.`.padEnd(F),q=H.declaredRanges.size>1?`${jq.magenta}⚠ ${jq.reset}`:` `,Y=colorForDiff(H.diff);ge.log(W+q+H.name.padEnd(n)+` `+jq.dim+`${H.occurrences.length}`.padEnd(S)+jq.reset+` `+jq.dim+renderDeclaredCell(H).padEnd(C)+jq.reset+` `+Y+H.latestVersion.padEnd(N)+jq.reset+` `+Y+H.diff+jq.reset)}let H=t.filter(t=>t.declaredRanges.size>1).length;H>0&&ge.log(`\n${jq.magenta}⚠${jq.reset} ${H} dep(s) declared at inconsistent ranges across workspaces.`)}function declaredCellWidth(t){return renderDeclaredCell(t).length}function renderDeclaredCell(t){if(t.declaredRanges.size===1)return[...t.declaredRanges][0];let n=[...t.declaredRanges].sort().join(`, `);return n.length<=32?n:n.slice(0,29)+`…`}function printChangePlan(t,n=!1){for(let S of t)for(let t of S.occurrences)ge.log(` ${t.workspace.padEnd(38)} ${S.name.padEnd(28)} ${t.currentRange.padEnd(12)} → ${targetRange(t.prefix,S.latestVersion,n)}`)}async function promptSelection(t){if(!process.stdin.isTTY)return ge.log(`[gjsify upgrade] non-TTY stdin: pass --latest / --minor / --patch (or --yes for interactive-all) to upgrade non-interactively.`),[];let n=createInterface({input:process.stdin,output:process.stdout});try{ge.log(`
1788
+ Select upgrades: comma- or space-separated indices, `+jq.bold+`a`+jq.reset+` for all, ranges like `+jq.bold+`1-3`+jq.reset+`, or `+jq.bold+`ENTER`+jq.reset+` to skip:`);let S=(await n.question(`> `)).trim();if(!S)return[];if(S.toLowerCase()===`a`||S.toLowerCase()===`all`)return[...t];let C=new Set;for(let t of S.split(/[\s,]+/).filter(Boolean)){let n=t.match(/^(\d+)-(\d+)$/);if(n){let t=Number(n[1]),S=Number(n[2]);for(let n=Math.min(t,S);n<=Math.max(t,S);n++)C.add(n-1)}else/^\d+$/.test(t)&&C.add(Number(t)-1)}return[...C].filter(n=>n>=0&&n<t.length).map(n=>t[n])}finally{n.close()}}function targetRange(t,n,S){return S?n:`${t}${n}`}function applyToFiles(t,n=!1){let S=new Map;for(let n of t)for(let t of n.occurrences){let C=S.get(t.workspaceLocation)??[];C.push({...n,occurrences:[t]}),S.set(t.workspaceLocation,C)}let C=0;for(let[t,N]of S.entries()){let S=In(t,`package.json`),F=readFileSync(S,`utf-8`),I=JSON.parse(F),H=!1,W=[];for(let t of N){let S=t.occurrences[0],C=I[S.field];if(!C)continue;let N=targetRange(S.prefix,t.latestVersion,n);C[t.name]!==N&&(C[t.name]=N,H=!0,W.push(t.name))}if(H){let t=detectIndent(F);writeFileSync(S,keepUntouchedLines(F,JSON.stringify(I,null,t)+(F.endsWith(`
1789
1789
  `)?`
1790
1790
  `:``),W),`utf-8`),C++}}return C}function keepUntouchedLines(t,n,S){let C=t.split(`
1791
1791
  `),N=n.split(`
1792
1792
  `);return C.length===N.length?N.map((t,n)=>S.some(n=>t.includes(`"${n}"`))?t:C[n]).join(`
1793
- `):n}function uniqueLocations(t){let n=new Set;for(let S of t)for(let t of S.occurrences)n.add(t.workspaceLocation);return[...n]}function detectIndent(t){let n=t.match(/^\{\n( +)/);return n?n[1].length:2}async function loadNpmrcLight(t){let n={registry:lh,scopes:{},authTokens:{},basicAuth:{}};for(let S of[In(homedir(),`.npmrc`),In(t,`.npmrc`)])if(existsSync(S))try{let t=parseNpmrc(readFileSync(S,`utf-8`));n={...n,...t,scopes:{...n.scopes,...t.scopes}}}catch{}return process.env.npm_config_registry&&(n.registry=process.env.npm_config_registry),n}var Dq,Oq,kq,Aq,jq=__esmMin(()=>{_e(),ef(),qn(),$g(),Tq(),OI(),gh(),AI(),MI(),Eq(),Dq={command:`upgrade`,description:"Workspace-aware dependency upgrades. Walks every package.json in the monorepo, groups by dep, flags inconsistencies. `--latest` / `--minor` / `--patch` for bulk-mode, `--align` for offline consistency-only mode, `--check` for CI drift detection.",builder:t=>t.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 deps whose name matches this substring (case-insensitive). Repeatable; comma-separated values are split.`,type:`string`}).option(`workspace`,{alias:`p`,description:`Restrict to a subset of workspaces. Patterns are matched against the workspace package name AND its directory path (substring + glob). Repeatable; comma-separated values are split.`,type:`string`}).option(`exclude-workspace`,{description:`Skip workspaces matching this pattern (glob-shaped; matched against workspace package name AND directory path). Repeatable; comma-separated values are split. Use for workspaces with intentional dependency drift — e.g. integration tests pinned to specific upstream versions.`,type:`string`}).option(`align`,{description:"Offline repair mode: find deps declared at multiple ranges across the workspace and align them to the highest. With `--exact`, also drop the range operator from declarations that already agree. No registry calls.",type:`boolean`,default:!1}).option(`check`,{description:"CI gate: exit non-zero when any dep is declared inconsistently across workspaces. Implies offline (no registry calls). Pairs with `--align` as the fix.",type:`boolean`,default:!1}).option(`exact`,{description:"Pin without a range operator. When writing, emits `1.2.3` instead of `^1.2.3`; with `--check`, fails on any matched dep that carries one; with `--align`, repairs exactly that. Pair with `--filter` — a repository-wide exactness run touches every ordinary caret dep by design.",type:`boolean`,default:!1}).option(`dry-run`,{description:`Print the upgrade plan without writing package.json files.`,type:`boolean`,default:!1}).option(`cwd`,{description:`Project directory. Default: process.cwd(). When inside a workspace, walks up to the monorepo root.`,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 t=>{let n=discoverContext(Nn(t.cwd??process.cwd())),S=applyWorkspaceFilter(n.workspaces,t.workspace,t.excludeWorkspace);if(S.length===0){ge.log(`[gjsify upgrade] no matching workspaces.`);return}let C=collectAllDeclarations(S,parseFilterList(t.filter));if(C.length===0){ge.log(`[gjsify upgrade] no external npm dependencies to check.`);return}let N=groupByDependency(C);if(t.check)return runCheckMode(N,t.exact);if(t.align)return runAlignMode(N,t);let F=await loadNpmrcLight(n.root),I=t.latest?`latest`:t.minor?`minor`:t.patch?`patch`:`interactive`;ge.log(`[gjsify upgrade] checking ${N.length} unique deps across ${S.length} workspace(s) against ${F.registry}…`);let H=await resolveCandidateGroups(N,F,t.verbose??!1,I);if(H.length===0){ge.log(`✅ all dependencies are up to date`);let t=findInconsistencies(N);t.length>0&&ge.log(`\n⚠ ${t.length} dep(s) declared at inconsistent ranges across workspaces. Run \`gjsify upgrade --align\` to fix.`);return}printTable(H);let W;if(I===`interactive`&&!t.yes?W=await promptSelection(H):(t.yes&&I===`interactive`&&ge.log(`[gjsify upgrade] -y / --yes: selecting all`),W=H),W.length===0){ge.log(`[gjsify upgrade] nothing selected; no files changed.`);return}if(t.dryRun){let n=uniqueLocations(W).length;ge.log(`[gjsify upgrade] --dry-run: would update ${W.length} deps across ${n} package.json file(s).`),printChangePlan(W,t.exact);return}let q=applyToFiles(W,t.exact);ge.log(`✏️ updated ${W.length} dep(s) across ${q} package.json file(s). Run \`gjsify install\` to apply.`)}},Oq=[`dependencies`,`devDependencies`,`optionalDependencies`,`peerDependencies`],kq=new Set([`x`,`X`,`*`,``]),Aq={reset:`\x1B[0m`,bold:`\x1B[1m`,dim:`\x1B[2m`,red:`\x1B[31m`,yellow:`\x1B[33m`,green:`\x1B[32m`,cyan:`\x1B[36m`,magenta:`\x1B[35m`}});async function unscannableBarrelPaths(t,n){let S=[];for(let C of n){let n=Nn(t,C);try{(await stat$1(n)).isDirectory()||S.push(`${n} is not a directory`)}catch(t){S.push(`${n}: ${t.message}`)}}return S}async function generateBarrels(t){let n=t.singleQuotes?`'`:`"`,S=t.noSemicolon?``:`;`,C=t.extension===`none`?``:`.${t.extension}`,N=0;for(let F of t.paths){let I=Nn(t.baseDir,F),H=Bn(I)===`types`,W;try{W=(await readdir$1(I,{withFileTypes:!0})).filter(t=>t.isFile()).filter(t=>Nq.test(t.name)).filter(t=>t.name!==`index.ts`).filter(n=>!t.exclude.some(t=>t.test(n.name))).sort((t,n)=>t.name.localeCompare(n.name))}catch(n){t.verbose&&ge.error(`[gjsify barrels] skip ${I}: ${n.message}`);continue}let q=W.map(t=>{let N=Bn(t.name,Vn(t.name));return`${H?`export type *`:`export *`} from ${n}./${N}${C}${n}${S}`}),Y=q.length?`${q.join(`
1793
+ `):n}function uniqueLocations(t){let n=new Set;for(let S of t)for(let t of S.occurrences)n.add(t.workspaceLocation);return[...n]}function detectIndent(t){let n=t.match(/^\{\n( +)/);return n?n[1].length:2}async function loadNpmrcLight(t){let n={registry:lh,scopes:{},authTokens:{},basicAuth:{}};for(let S of[In(homedir(),`.npmrc`),In(t,`.npmrc`)])if(existsSync(S))try{let t=parseNpmrc(readFileSync(S,`utf-8`));n={...n,...t,scopes:{...n.scopes,...t.scopes}}}catch{}return process.env.npm_config_registry&&(n.registry=process.env.npm_config_registry),n}var Oq,kq,Aq,jq,Mq=__esmMin(()=>{_e(),ef(),qn(),$g(),Eq(),OI(),gh(),AI(),MI(),Dq(),Oq={command:`upgrade`,description:"Workspace-aware dependency upgrades. Walks every package.json in the monorepo, groups by dep, flags inconsistencies. `--latest` / `--minor` / `--patch` for bulk-mode, `--align` for offline consistency-only mode, `--check` for CI drift detection.",builder:t=>t.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 deps whose name matches this substring (case-insensitive). Repeatable; comma-separated values are split.`,type:`string`}).option(`workspace`,{alias:`p`,description:`Restrict to a subset of workspaces. Patterns are matched against the workspace package name AND its directory path (substring + glob). Repeatable; comma-separated values are split.`,type:`string`}).option(`exclude-workspace`,{description:`Skip workspaces matching this pattern (glob-shaped; matched against workspace package name AND directory path). Repeatable; comma-separated values are split. Use for workspaces with intentional dependency drift — e.g. integration tests pinned to specific upstream versions.`,type:`string`}).option(`align`,{description:"Offline repair mode: find deps declared at multiple ranges across the workspace and align them to the highest. With `--exact`, also drop the range operator from declarations that already agree. No registry calls.",type:`boolean`,default:!1}).option(`check`,{description:"CI gate: exit non-zero when any dep is declared inconsistently across workspaces. Implies offline (no registry calls). Pairs with `--align` as the fix.",type:`boolean`,default:!1}).option(`exact`,{description:"Pin without a range operator. When writing, emits `1.2.3` instead of `^1.2.3`; with `--check`, fails on any matched dep that carries one; with `--align`, repairs exactly that. Pair with `--filter` — a repository-wide exactness run touches every ordinary caret dep by design.",type:`boolean`,default:!1}).option(`dry-run`,{description:`Print the upgrade plan without writing package.json files.`,type:`boolean`,default:!1}).option(`cwd`,{description:`Project directory. Default: process.cwd(). When inside a workspace, walks up to the monorepo root.`,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 t=>{let n=discoverContext(Nn(t.cwd??process.cwd())),S=applyWorkspaceFilter(n.workspaces,t.workspace,t.excludeWorkspace);if(S.length===0){ge.log(`[gjsify upgrade] no matching workspaces.`);return}let C=collectAllDeclarations(S,parseFilterList(t.filter));if(C.length===0){ge.log(`[gjsify upgrade] no external npm dependencies to check.`);return}let N=groupByDependency(C);if(t.check)return runCheckMode(N,t.exact);if(t.align)return runAlignMode(N,t);let F=await loadNpmrcLight(n.root),I=t.latest?`latest`:t.minor?`minor`:t.patch?`patch`:`interactive`;ge.log(`[gjsify upgrade] checking ${N.length} unique deps across ${S.length} workspace(s) against ${F.registry}…`);let H=await resolveCandidateGroups(N,F,t.verbose??!1,I);if(H.length===0){ge.log(`✅ all dependencies are up to date`);let t=findInconsistencies(N);t.length>0&&ge.log(`\n⚠ ${t.length} dep(s) declared at inconsistent ranges across workspaces. Run \`gjsify upgrade --align\` to fix.`);return}printTable(H);let W;if(I===`interactive`&&!t.yes?W=await promptSelection(H):(t.yes&&I===`interactive`&&ge.log(`[gjsify upgrade] -y / --yes: selecting all`),W=H),W.length===0){ge.log(`[gjsify upgrade] nothing selected; no files changed.`);return}if(t.dryRun){let n=uniqueLocations(W).length;ge.log(`[gjsify upgrade] --dry-run: would update ${W.length} deps across ${n} package.json file(s).`),printChangePlan(W,t.exact);return}let q=applyToFiles(W,t.exact);ge.log(`✏️ updated ${W.length} dep(s) across ${q} package.json file(s). Run \`gjsify install\` to apply.`)}},kq=[`dependencies`,`devDependencies`,`optionalDependencies`,`peerDependencies`],Aq=new Set([`x`,`X`,`*`,``]),jq={reset:`\x1B[0m`,bold:`\x1B[1m`,dim:`\x1B[2m`,red:`\x1B[31m`,yellow:`\x1B[33m`,green:`\x1B[32m`,cyan:`\x1B[36m`,magenta:`\x1B[35m`}});async function unscannableBarrelPaths(t,n){let S=[];for(let C of n){let n=Nn(t,C);try{(await stat$1(n)).isDirectory()||S.push(`${n} is not a directory`)}catch(t){S.push(`${n}: ${t.message}`)}}return S}async function generateBarrels(t){let n=t.singleQuotes?`'`:`"`,S=t.noSemicolon?``:`;`,C=t.extension===`none`?``:`.${t.extension}`,N=0;for(let F of t.paths){let I=Nn(t.baseDir,F),H=Bn(I)===`types`,W;try{W=(await readdir$1(I,{withFileTypes:!0})).filter(t=>t.isFile()).filter(t=>Pq.test(t.name)).filter(t=>t.name!==`index.ts`).filter(n=>!t.exclude.some(t=>t.test(n.name))).sort((t,n)=>t.name.localeCompare(n.name))}catch(n){t.verbose&&ge.error(`[gjsify barrels] skip ${I}: ${n.message}`);continue}let q=W.map(t=>{let N=Bn(t.name,Vn(t.name));return`${H?`export type *`:`export *`} from ${n}./${N}${C}${n}${S}`}),Y=q.length?`${q.join(`
1794
1794
  `)}\n`:`export {};
1795
- `,X=`${t.header}\n\n${Y}`,Z=In(I,`index.ts`);if(await readFile$1(Z,`utf-8`).catch(()=>``)===X){t.verbose&&ge.log(`[gjsify barrels] up-to-date: ${Z}`);continue}t.check?(ge.error(`[gjsify barrels] drift: ${Z}`),N++):(await writeFile$1(Z,X,`utf-8`),t.verbose&&ge.log(`[gjsify barrels] wrote: ${Z}`))}return N}var Mq,Nq,Pq=__esmMin(()=>{_e(),Ld(),qn(),Mq=[`\\.test\\.`,`\\.spec\\.`,`\\.test-data\\.`],Nq=/\.(ts|tsx|mts|cts)$/}),Fq,Iq=__esmMin(()=>{_e(),Pq(),Fq={command:`barrels [paths..]`,description:"Regenerate `index.ts` barrel files for the given directories. Drop-in replacement for `barrelsby`.",builder:t=>t.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 t=>{let n=Array.from(new Set((t.paths??[]).filter(Boolean)));if(n.length===0){ge.error(`[gjsify barrels] no paths provided. Pass directories as positional arguments or via --paths.`),process.exitCode=1;return}let S=t.baseDir??process.cwd(),C=await unscannableBarrelPaths(S,n);if(C.length>0){for(let t of C)ge.error(`[gjsify barrels] cannot scan ${t}`);ge.error(`[gjsify barrels] ${C.length} of ${n.length} path(s) could not be scanned — refusing to report on the rest as if that were the whole set.`),process.exitCode=1;return}let N=t.exclude?.length?t.exclude:[...Mq],F=await generateBarrels({paths:n,extension:t.ext??`none`,baseDir:S,exclude:N.map(t=>new RegExp(t)),header:t.header??"// Auto-generated by `gjsify barrels` — do not edit by hand.",noSemicolon:t.semicolon===!1||t.semicolon===void 0,singleQuotes:t.singleQuotes!==!1,check:t.check??!1,verbose:t.verbose??!1});t.check&&F>0&&(ge.error(`[gjsify barrels] ${F} barrel file(s) drifted. Run without --check to fix.`),process.exitCode=1)}}}),Lq,Rq=__esmMin(()=>{_e(),Xl(),qn(),ir(),nL(),ZI(),ef(),oG(),kR(),MI(),sv(),Lq={command:`tsc [tscArgs..]`,description:"Run TypeScript compiler (tsc) under GJS via the @gjsify/tsc bundle. All arguments are passed through to tsc. Equivalent to `gjsify-tsc <args>` from the @gjsify/tsc bin.",builder:t=>t.parserConfiguration({"unknown-options-as-args":!0}).version(!1).help(!1).positional(`tscArgs`,{description:"Arguments forwarded verbatim to tsc (e.g. `--version`, `-p tsconfig.json`).",type:`string`,array:!0,default:[]}),handler:async t=>{let n=(t._??[]).slice(1).map(String),S=t.tscArgs??[],C=n.length>0?n:S,N=process.cwd(),F=[pathToFileURL(`${findWorkspaceRoot(N)??N}/__gjsify_tsc__.js`).href,import.meta.url],I;for(let t of F)try{I=createRequire(t).resolve(`@gjsify/tsc/bundle`);break}catch{}let H;for(let t of F)try{H=In(zn(createRequire(t).resolve(`typescript/package.json`)),`lib`,`tsc.js`);break}catch{}if(!I&&!H)return ge.error("gjsify tsc: neither @gjsify/tsc (GJS bundle) nor npm `typescript` (Node) is installed."),ge.error(" Install with: gjsify install --save-dev @gjsify/tsc (or add `typescript`)."),forceExit(1);let W=buildNativeEnv(detectNativePackages(N)),q={...process.env,...W},runNodeTsc=async()=>{let t=nodeBinary();if(!(t.includes(`/`)||t.includes(`\\`)?existsSync(t):isOnPath(t)))return ge.error(`gjsify tsc: the @gjsify/tsc GJS bundle is unavailable and \`${t}\` cannot be run, so upstream \`typescript\` cannot run either.`),ge.error(` Build the bundle with: gjsify workspace @gjsify/tsc build`),ge.error(" …or install Node.js so the upstream `typescript` fallback can be spawned."),forceExit(1);try{await new Promise((n,S)=>{spawnToCompletion(t,[H,...C],{completion:`exit`,env:q,onSpawn:t=>{let n=!1;t.on(`error`,()=>{n=!0}),t.on(`close`,t=>{n||forceExit(t??1)})}}).catch(S)})}catch(t){let n=t;return n.code===`ENOENT`?(ge.error("gjsify tsc: the @gjsify/tsc GJS bundle is unavailable and `node` is not on PATH, so upstream `typescript` cannot run either."),ge.error(` Build the bundle with: gjsify workspace @gjsify/tsc build`)):ge.error(`gjsify tsc (node typescript): ${n.message}`),forceExit(1)}};if(I)try{await new Promise((t,n)=>{spawnToCompletion(`gjs`,[`-m`,I,...C],{completion:`exit`,env:q,onSpawn:t=>{let n=!1;t.on(`error`,()=>{n=!0}),t.on(`close`,t=>{n||forceExit(t??1)})}}).catch(n)})}catch(t){let n=t;return n.code===`ENOENT`&&H?await runNodeTsc():(n.code===`ENOENT`?(ge.error("gjsify tsc: `gjs` not found on PATH and no npm `typescript` fallback."),ge.error(" Install GJS (e.g. `dnf install gjs`), or add `typescript` to the project.")):ge.error(`gjsify tsc: ${n.message}`),forceExit(1))}else await runNodeTsc()}}});function readStdinText(){return readFileSync(0,`utf-8`)}function readStdinLines(){return splitStdinLines(readStdinText())}function splitStdinLines(t){return t.split(`
1796
- `).map(t=>t.trim()).filter(Boolean)}var zq=__esmMin(()=>{ef()});function isResolvableScript(t){return Wq.test(t)&&!Bq.some(n=>n.test(t))&&!Uq.some(n=>n.match.test(t))}function resolveRootScripts(t,n){let S=new Set,C=[];for(let n of t)isResolvableScript(n)?C.push(n):S.add(n);let N=new Set;for(;C.length>0;){let t=C.shift();if(!N.has(t)){N.add(t);for(let N of n(t))Vq.some(t=>t.test(N))||(isResolvableScript(N)?C.push(N):S.add(N))}}return{files:[...S],scripts:N.size}}function classifyAndExpand(t,n,S){let C=n.map(t=>t.replace(/\\/g,`/`)).filter(t=>t.length>0);if(C.length===0)return{global:!1,reason:`empty-diff`,workspaces:[],runE2E:!1,runIntegration:!1,skipAll:!0};let N=[];for(let t of C)Vq.some(n=>n.test(t))||N.push(t);let F=``;if(S){let t=resolveRootScripts(N,S);t.scripts>0&&(N=t.files,F=`; ${t.scripts} root script(s) resolved to their readers`)}if(N.length===0)return{global:!1,reason:`ignored-only`+F,workspaces:[],runE2E:!1,runIntegration:!1,skipAll:!0};for(let n of N)for(let S of Bq)if(S.test(n))return{global:!0,reason:`global-trigger ${S.source} matched ${n}${F}`,workspaces:t.map(t=>t.name),runE2E:!0,runIntegration:!0,skipAll:!1};let{matched:I,unmatched:H}=workspacesForChangedFiles(t,N),W=new Set(t.map(t=>t.name)),q=new Set,Y=new Set,X=!1;for(let n of Uq){let S=N.filter(t=>n.match.test(t));if(S.length!==0){for(let t of S)Y.add(t);for(let S of n.seeds){if(!W.has(S))return{global:!0,reason:`script-coupling seed ${S} is not a workspace (${n.match.source} → ${n.why}); SCRIPT_COUPLINGS in commands/affected.ts is stale`,workspaces:t.map(t=>t.name),runE2E:!0,runIntegration:!0,skipAll:!1};q.add(S)}n.runE2E&&(X=!0)}}let Z=H.filter(t=>!Y.has(t));if(Z.length>0)return{global:!0,reason:`unmatched files (${Z.length}): ${Z.slice(0,3).join(`, `)}${Z.length>3?`…`:``}${F}`,workspaces:t.map(t=>t.name),runE2E:!0,runIntegration:!0,skipAll:!1};for(let t of q)I.add(t);if(q.size===0&&N.every(t=>Hq.some(n=>n.test(t)))&&I.size===1){let t=[...I][0],n=N.some(t=>t.startsWith(`tests/e2e/`)),S=N.some(t=>t.startsWith(`tests/integration/`));return{global:!1,reason:`test-only (${N.length} file(s) in ${t})${F}`,workspaces:[t],runE2E:n||X,runIntegration:S||isIntegrationWorkspace(t),skipAll:!1}}let te=affectedClosure(buildReverseDependencyGraph(t,{includeDev:!1}),[...I]),ne=buildDependencyGraph(t,{includeDev:!0}),re=!1;for(let[t,n]of ne.edges)if(isIntegrationWorkspace(t)){for(let S of n)if(te.has(S)){te.add(t),re=!0;break}}let ie=N.some(t=>t.startsWith(`tests/e2e/`))||X;return{global:!1,reason:`closure (${te.size} ws from ${I.size} seed(s))`+(q.size>0?`, ${q.size} via script-coupling`:``)+F,workspaces:[...te].sort(),runE2E:ie,runIntegration:re,skipAll:!1}}function isIntegrationWorkspace(t){return t.startsWith(`@gjsify/integration-`)}var Bq,Vq,Hq,Uq,Wq,Gq=__esmMin(()=>{AI(),Bq=[/^packages\/infra\/workspace\//,/^packages\/infra\/cli\//,/^packages\/infra\/rolldown-plugin-gjsify\//,/^packages\/infra\/resolve-npm\//,/^packages\/gjs\/unit\//,/^\.github\/actions\//,/^gjsify-lock\.json$/,/^package\.json$/,/^tsconfig[^/]*\.json$/,/^\.github\/workflows\/main\.yml$/,/^scripts\/audit-runtimes\.mjs$/],Vq=[/\.md$/i,/^refs\//,/^website\//,/^docs\//,/^\.github\/workflows\/(deploy-docs|commitlint|release|release-cut|audit-runtimes|prebuilds|node-gi|napi|cli-cross-platform|build-ci-image|cancel-pr-runs|macos-suites|windows-suites|gtk-os-suites)\.yml$/,/^\.github\/prebuild-toolchain\//,/^scripts\/manifest-conformance\//,/^status\//,/^scripts\/generate-status\.mjs$/,/^packages\/node-gi\//,/^packages\/napi\//,/^flatpak\//,/^LICENSE/,/^\.gitignore$/,/^\.gjsify-[^/]*\.md$/,/^STATUS\.md$/,/^CHANGELOG\.md$/,/^AGENTS\.md$/,/^CLAUDE\.md$/,/^README\.md$/],Hq=[/\.spec\.[mc]?[tj]sx?$/,/^tests\/(e2e|integration)\//],Uq=[{match:/^\.githooks\//,seeds:[],runE2E:!0,why:`tests/e2e/git-hooks-cli-bundle-staleness drives .githooks/pre-commit`},{match:/^templates\//,seeds:[`@gjsify/create-app`],runE2E:!0,why:`@gjsify/create-app build → node scripts/process-template.mjs reads templates/`},{match:/^packages\/framework\/react-native\//,seeds:[],runE2E:!0,why:`tests/e2e/react-native-devtools is the only external observer of AppRegistry.runApplication`}],Wq=/^scripts\/[^/]+$/});function stripCommentLines(t,n){let S=/\.(ya?ml|sh|bash|py|toml)$|(^|\/)\.git[a-z]*$|Dockerfile$/.test(t)?/^\s*#/:/^\s*(\/\/|\/\*|\*)/;return n.split(`
1795
+ `,X=`${t.header}\n\n${Y}`,Z=In(I,`index.ts`);if(await readFile$1(Z,`utf-8`).catch(()=>``)===X){t.verbose&&ge.log(`[gjsify barrels] up-to-date: ${Z}`);continue}t.check?(ge.error(`[gjsify barrels] drift: ${Z}`),N++):(await writeFile$1(Z,X,`utf-8`),t.verbose&&ge.log(`[gjsify barrels] wrote: ${Z}`))}return N}var Nq,Pq,Fq=__esmMin(()=>{_e(),Ld(),qn(),Nq=[`\\.test\\.`,`\\.spec\\.`,`\\.test-data\\.`],Pq=/\.(ts|tsx|mts|cts)$/}),Iq,Lq=__esmMin(()=>{_e(),Fq(),Iq={command:`barrels [paths..]`,description:"Regenerate `index.ts` barrel files for the given directories. Drop-in replacement for `barrelsby`.",builder:t=>t.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 t=>{let n=Array.from(new Set((t.paths??[]).filter(Boolean)));if(n.length===0){ge.error(`[gjsify barrels] no paths provided. Pass directories as positional arguments or via --paths.`),process.exitCode=1;return}let S=t.baseDir??process.cwd(),C=await unscannableBarrelPaths(S,n);if(C.length>0){for(let t of C)ge.error(`[gjsify barrels] cannot scan ${t}`);ge.error(`[gjsify barrels] ${C.length} of ${n.length} path(s) could not be scanned — refusing to report on the rest as if that were the whole set.`),process.exitCode=1;return}let N=t.exclude?.length?t.exclude:[...Nq],F=await generateBarrels({paths:n,extension:t.ext??`none`,baseDir:S,exclude:N.map(t=>new RegExp(t)),header:t.header??"// Auto-generated by `gjsify barrels` — do not edit by hand.",noSemicolon:t.semicolon===!1||t.semicolon===void 0,singleQuotes:t.singleQuotes!==!1,check:t.check??!1,verbose:t.verbose??!1});t.check&&F>0&&(ge.error(`[gjsify barrels] ${F} barrel file(s) drifted. Run without --check to fix.`),process.exitCode=1)}}}),Rq,zq=__esmMin(()=>{_e(),Xl(),qn(),ir(),nL(),ZI(),ef(),sG(),kR(),MI(),sv(),Rq={command:`tsc [tscArgs..]`,description:"Run TypeScript compiler (tsc) under GJS via the @gjsify/tsc bundle. All arguments are passed through to tsc. Equivalent to `gjsify-tsc <args>` from the @gjsify/tsc bin.",builder:t=>t.parserConfiguration({"unknown-options-as-args":!0}).version(!1).help(!1).positional(`tscArgs`,{description:"Arguments forwarded verbatim to tsc (e.g. `--version`, `-p tsconfig.json`).",type:`string`,array:!0,default:[]}),handler:async t=>{let n=(t._??[]).slice(1).map(String),S=t.tscArgs??[],C=n.length>0?n:S,N=process.cwd(),F=[pathToFileURL(`${findWorkspaceRoot(N)??N}/__gjsify_tsc__.js`).href,import.meta.url],I;for(let t of F)try{I=createRequire(t).resolve(`@gjsify/tsc/bundle`);break}catch{}let H;for(let t of F)try{H=In(zn(createRequire(t).resolve(`typescript/package.json`)),`lib`,`tsc.js`);break}catch{}if(!I&&!H)return ge.error("gjsify tsc: neither @gjsify/tsc (GJS bundle) nor npm `typescript` (Node) is installed."),ge.error(" Install with: gjsify install --save-dev @gjsify/tsc (or add `typescript`)."),forceExit(1);let W=buildNativeEnv(detectNativePackages(N)),q={...process.env,...W},runNodeTsc=async()=>{let t=nodeBinary();if(!(t.includes(`/`)||t.includes(`\\`)?existsSync(t):isOnPath(t)))return ge.error(`gjsify tsc: the @gjsify/tsc GJS bundle is unavailable and \`${t}\` cannot be run, so upstream \`typescript\` cannot run either.`),ge.error(` Build the bundle with: gjsify workspace @gjsify/tsc build`),ge.error(" …or install Node.js so the upstream `typescript` fallback can be spawned."),forceExit(1);try{await new Promise((n,S)=>{spawnToCompletion(t,[H,...C],{completion:`exit`,env:q,onSpawn:t=>{let n=!1;t.on(`error`,()=>{n=!0}),t.on(`close`,t=>{n||forceExit(t??1)})}}).catch(S)})}catch(t){let n=t;return n.code===`ENOENT`?(ge.error("gjsify tsc: the @gjsify/tsc GJS bundle is unavailable and `node` is not on PATH, so upstream `typescript` cannot run either."),ge.error(` Build the bundle with: gjsify workspace @gjsify/tsc build`)):ge.error(`gjsify tsc (node typescript): ${n.message}`),forceExit(1)}};if(I)try{await new Promise((t,n)=>{spawnToCompletion(`gjs`,[`-m`,I,...C],{completion:`exit`,env:q,onSpawn:t=>{let n=!1;t.on(`error`,()=>{n=!0}),t.on(`close`,t=>{n||forceExit(t??1)})}}).catch(n)})}catch(t){let n=t;return n.code===`ENOENT`&&H?await runNodeTsc():(n.code===`ENOENT`?(ge.error("gjsify tsc: `gjs` not found on PATH and no npm `typescript` fallback."),ge.error(" Install GJS (e.g. `dnf install gjs`), or add `typescript` to the project.")):ge.error(`gjsify tsc: ${n.message}`),forceExit(1))}else await runNodeTsc()}}});function readStdinText(){return readFileSync(0,`utf-8`)}function readStdinLines(){return splitStdinLines(readStdinText())}function splitStdinLines(t){return t.split(`
1796
+ `).map(t=>t.trim()).filter(Boolean)}var Bq=__esmMin(()=>{ef()});function isResolvableScript(t){return Gq.test(t)&&!Vq.some(n=>n.test(t))&&!Wq.some(n=>n.match.test(t))}function resolveRootScripts(t,n){let S=new Set,C=[];for(let n of t)isResolvableScript(n)?C.push(n):S.add(n);let N=new Set;for(;C.length>0;){let t=C.shift();if(!N.has(t)){N.add(t);for(let N of n(t))Hq.some(t=>t.test(N))||(isResolvableScript(N)?C.push(N):S.add(N))}}return{files:[...S],scripts:N.size}}function classifyAndExpand(t,n,S){let C=n.map(t=>t.replace(/\\/g,`/`)).filter(t=>t.length>0);if(C.length===0)return{global:!1,reason:`empty-diff`,workspaces:[],runE2E:!1,runIntegration:!1,skipAll:!0};let N=[];for(let t of C)Hq.some(n=>n.test(t))||N.push(t);let F=``;if(S){let t=resolveRootScripts(N,S);t.scripts>0&&(N=t.files,F=`; ${t.scripts} root script(s) resolved to their readers`)}if(N.length===0)return{global:!1,reason:`ignored-only`+F,workspaces:[],runE2E:!1,runIntegration:!1,skipAll:!0};for(let n of N)for(let S of Vq)if(S.test(n))return{global:!0,reason:`global-trigger ${S.source} matched ${n}${F}`,workspaces:t.map(t=>t.name),runE2E:!0,runIntegration:!0,skipAll:!1};let{matched:I,unmatched:H}=workspacesForChangedFiles(t,N),W=new Set(t.map(t=>t.name)),q=new Set,Y=new Set,X=!1;for(let n of Wq){let S=N.filter(t=>n.match.test(t));if(S.length!==0){for(let t of S)Y.add(t);for(let S of n.seeds){if(!W.has(S))return{global:!0,reason:`script-coupling seed ${S} is not a workspace (${n.match.source} → ${n.why}); SCRIPT_COUPLINGS in commands/affected.ts is stale`,workspaces:t.map(t=>t.name),runE2E:!0,runIntegration:!0,skipAll:!1};q.add(S)}n.runE2E&&(X=!0)}}let Z=H.filter(t=>!Y.has(t));if(Z.length>0)return{global:!0,reason:`unmatched files (${Z.length}): ${Z.slice(0,3).join(`, `)}${Z.length>3?`…`:``}${F}`,workspaces:t.map(t=>t.name),runE2E:!0,runIntegration:!0,skipAll:!1};for(let t of q)I.add(t);if(q.size===0&&N.every(t=>Uq.some(n=>n.test(t)))&&I.size===1){let t=[...I][0],n=N.some(t=>t.startsWith(`tests/e2e/`)),S=N.some(t=>t.startsWith(`tests/integration/`));return{global:!1,reason:`test-only (${N.length} file(s) in ${t})${F}`,workspaces:[t],runE2E:n||X,runIntegration:S||isIntegrationWorkspace(t),skipAll:!1}}let te=affectedClosure(buildReverseDependencyGraph(t,{includeDev:!1}),[...I]),ne=buildDependencyGraph(t,{includeDev:!0}),re=!1;for(let[t,n]of ne.edges)if(isIntegrationWorkspace(t)){for(let S of n)if(te.has(S)){te.add(t),re=!0;break}}let ie=N.some(t=>t.startsWith(`tests/e2e/`))||X;return{global:!1,reason:`closure (${te.size} ws from ${I.size} seed(s))`+(q.size>0?`, ${q.size} via script-coupling`:``)+F,workspaces:[...te].sort(),runE2E:ie,runIntegration:re,skipAll:!1}}function isIntegrationWorkspace(t){return t.startsWith(`@gjsify/integration-`)}var Vq,Hq,Uq,Wq,Gq,Kq=__esmMin(()=>{AI(),Vq=[/^packages\/infra\/workspace\//,/^packages\/infra\/cli\//,/^packages\/infra\/rolldown-plugin-gjsify\//,/^packages\/infra\/resolve-npm\//,/^packages\/gjs\/unit\//,/^\.github\/actions\//,/^gjsify-lock\.json$/,/^package\.json$/,/^tsconfig[^/]*\.json$/,/^\.github\/workflows\/main\.yml$/,/^scripts\/audit-runtimes\.mjs$/],Hq=[/\.md$/i,/^refs\//,/^website\//,/^docs\//,/^\.github\/workflows\/(deploy-docs|commitlint|release|release-cut|audit-runtimes|prebuilds|node-gi|napi|cli-cross-platform|build-ci-image|cancel-pr-runs|macos-suites|windows-suites|gtk-os-suites)\.yml$/,/^\.github\/prebuild-toolchain\//,/^scripts\/manifest-conformance\//,/^status\//,/^scripts\/generate-status\.mjs$/,/^packages\/node-gi\//,/^packages\/napi\//,/^flatpak\//,/^LICENSE/,/^\.gitignore$/,/^\.gjsify-[^/]*\.md$/,/^STATUS\.md$/,/^CHANGELOG\.md$/,/^AGENTS\.md$/,/^CLAUDE\.md$/,/^README\.md$/],Uq=[/\.spec\.[mc]?[tj]sx?$/,/^tests\/(e2e|integration)\//],Wq=[{match:/^\.githooks\//,seeds:[],runE2E:!0,why:`tests/e2e/git-hooks-cli-bundle-staleness drives .githooks/pre-commit`},{match:/^templates\//,seeds:[`@gjsify/create-app`],runE2E:!0,why:`@gjsify/create-app build → node scripts/process-template.mjs reads templates/`},{match:/^packages\/framework\/react-native\//,seeds:[],runE2E:!0,why:`tests/e2e/react-native-devtools is the only external observer of AppRegistry.runApplication`}],Gq=/^scripts\/[^/]+$/});function stripCommentLines(t,n){let S=/\.(ya?ml|sh|bash|py|toml)$|(^|\/)\.git[a-z]*$|Dockerfile$/.test(t)?/^\s*#/:/^\s*(\/\/|\/\*|\*)/;return n.split(`
1797
1797
  `).filter(t=>!S.test(t)).join(`
1798
1798
  `)}function scriptNamePattern(t){let n=Tn.basename(t),S=/^(.*?)(\.d)?\.[mc]?[jt]sx?$/.exec(n),C=S?`${escapeRe(S[1])}(\\.d)?\\.[mc]?[jt]sx?\\b`:`${escapeRe(n)}\\b`;return RegExp(`(^|[^\\w.-])${C}`)}function gatedJobs(t){let n=new Map,S=new Set;for(let{job:C,text:N}of t){if(!C)continue;n.has(C)||n.set(C,[]);let t=/^ {4}needs:\s*\[(.*)\]/.exec(N)??/^ {4}needs:\s*([A-Za-z0-9_-]+)\s*$/.exec(N);t&&n.set(C,t[1].split(`,`).map(t=>t.trim()).filter(Boolean)),(/needs\.changes\b/.test(N)||/^ {4}needs:\s*$/.test(N))&&S.add(C)}let C=new Set([`changes`,...S]),N=!0;for(;N;){N=!1;for(let[t,S]of n)!C.has(t)&&S.some(t=>C.has(t))&&(C.add(t),N=!0)}return C.delete(`changes`),C}function workflowLines(t){let n=t.split(`
1799
- `),S=[],C,N=!1;for(let t of n){/^jobs:\s*$/.test(t)?N=!0:/^\S/.test(t)&&(N=!1);let n=N?/^ {2}([A-Za-z0-9_-]+):\s*$/.exec(t):null;n&&(C=n[1]),!/^\s*#/.test(t)&&S.push({job:N?C:void 0,text:t})}return S}function buildScriptReferrers(t){let n=new Map;for(let[S,C]of t)S===Kq||S===qq||n.set(S,stripCommentLines(S,C));let S=t.get(Kq),C=S===void 0?[]:workflowLines(S),N=gatedJobs(C),gatedWorkflowNames=t=>C.some(n=>t.test(n.text)&&(n.job===void 0||N.has(n.job))),F,I=t.get(qq);I!==void 0&&(F=JSON.parse(I));let manifestReads=t=>{if(!F)return!1;for(let[n,S]of Object.entries(F))if(n!==`scripts`&&t.test(JSON.stringify(S)))return!0;let n=F.scripts??{};for(let[S,C]of Object.entries(n)){if(!t.test(C))continue;if(Yq.test(S))return!0;let N=RegExp(`(^|[\\s"'])${escapeRe(S)}($|[\\s"'&;|])`);if(Object.entries(n).some(([t,n])=>t!==S&&N.test(n))||gatedWorkflowNames(N))return!0}return!1};return t=>{let S=scriptNamePattern(t),C=[];for(let[N,F]of n)N!==t&&S.test(F)&&C.push(N);return gatedWorkflowNames(S)&&C.push(Kq),manifestReads(S)&&C.push(qq),C.sort()}}function readTrackedTexts(t){let n=spawnSync(`git`,[`ls-files`,`-z`],{cwd:t,encoding:`utf8`});if(n.status!==0)throw Error(`git ls-files failed (${n.status}): ${String(n.stderr).trim()}`);let S=new Map;for(let C of n.stdout.split(`\0`)){if(!C||C.startsWith(`refs/`))continue;let n=In(t,C),N=statSync(n,{throwIfNoEntry:!1});if(!N?.isFile()||N.size>Jq)continue;let F=readFileSync(n,`utf8`);F.includes(`\0`)||S.set(C,F)}return S}var Kq,qq,Jq,Yq,escapeRe,Xq=__esmMin(()=>{ev(),ef(),qn(),Kq=`.github/workflows/main.yml`,qq=`package.json`,Jq=2*1024*1024,Yq=/^(pre|post)?(install|prepare|build|test)(:|$)/,escapeRe=t=>t.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)});function scriptReadersFor(t,n){if(n.some(t=>/^scripts\/[^/]+$/.test(t.replace(/\\/g,`/`))))try{return buildScriptReferrers(readTrackedTexts(t))}catch(t){process.stderr.write(`gjsify affected: cannot index the tree for script readers (${String(t)}); root scripts stay unmatched\n`);return}}function runGitDiff(t,n,S){let C=spawnSync(`git`,[`diff`,`--no-renames`,`--name-only`,`${n}...${S}`],{cwd:t,encoding:`utf8`});if(C.status!==0)throw process.stderr.write(`gjsify affected: git diff failed (${C.status}): ${C.stderr.trim()}\n`),process.exit(2),Error(`gjsify affected: git diff failed (${C.status})`);return C.stdout.split(`
1799
+ `),S=[],C,N=!1;for(let t of n){/^jobs:\s*$/.test(t)?N=!0:/^\S/.test(t)&&(N=!1);let n=N?/^ {2}([A-Za-z0-9_-]+):\s*$/.exec(t):null;n&&(C=n[1]),!/^\s*#/.test(t)&&S.push({job:N?C:void 0,text:t})}return S}function buildScriptReferrers(t){let n=new Map;for(let[S,C]of t)S===qq||S===Jq||n.set(S,stripCommentLines(S,C));let S=t.get(qq),C=S===void 0?[]:workflowLines(S),N=gatedJobs(C),gatedWorkflowNames=t=>C.some(n=>t.test(n.text)&&(n.job===void 0||N.has(n.job))),F,I=t.get(Jq);I!==void 0&&(F=JSON.parse(I));let manifestReads=t=>{if(!F)return!1;for(let[n,S]of Object.entries(F))if(n!==`scripts`&&t.test(JSON.stringify(S)))return!0;let n=F.scripts??{};for(let[S,C]of Object.entries(n)){if(!t.test(C))continue;if(Xq.test(S))return!0;let N=RegExp(`(^|[\\s"'])${escapeRe(S)}($|[\\s"'&;|])`);if(Object.entries(n).some(([t,n])=>t!==S&&N.test(n))||gatedWorkflowNames(N))return!0}return!1};return t=>{let S=scriptNamePattern(t),C=[];for(let[N,F]of n)N!==t&&S.test(F)&&C.push(N);return gatedWorkflowNames(S)&&C.push(qq),manifestReads(S)&&C.push(Jq),C.sort()}}function readTrackedTexts(t){let n=spawnSync(`git`,[`ls-files`,`-z`],{cwd:t,encoding:`utf8`});if(n.status!==0)throw Error(`git ls-files failed (${n.status}): ${String(n.stderr).trim()}`);let S=new Map;for(let C of n.stdout.split(`\0`)){if(!C||C.startsWith(`refs/`))continue;let n=In(t,C),N=statSync(n,{throwIfNoEntry:!1});if(!N?.isFile()||N.size>Yq)continue;let F=readFileSync(n,`utf8`);F.includes(`\0`)||S.set(C,F)}return S}var qq,Jq,Yq,Xq,escapeRe,Zq=__esmMin(()=>{ev(),ef(),qn(),qq=`.github/workflows/main.yml`,Jq=`package.json`,Yq=2*1024*1024,Xq=/^(pre|post)?(install|prepare|build|test)(:|$)/,escapeRe=t=>t.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)});function scriptReadersFor(t,n){if(n.some(t=>/^scripts\/[^/]+$/.test(t.replace(/\\/g,`/`))))try{return buildScriptReferrers(readTrackedTexts(t))}catch(t){process.stderr.write(`gjsify affected: cannot index the tree for script readers (${String(t)}); root scripts stay unmatched\n`);return}}function runGitDiff(t,n,S){let C=spawnSync(`git`,[`diff`,`--no-renames`,`--name-only`,`${n}...${S}`],{cwd:t,encoding:`utf8`});if(C.status!==0)throw process.stderr.write(`gjsify affected: git diff failed (${C.status}): ${C.stderr.trim()}\n`),process.exit(2),Error(`gjsify affected: git diff failed (${C.status})`);return C.stdout.split(`
1800
1800
  `).filter(Boolean)}function emit(t,n){if(t===`json`){process.stdout.write(JSON.stringify(n)+`
1801
1801
  `);return}if(t===`globs`){for(let t of n.workspaces)process.stdout.write(`${t}\n`);return}if(t===`github-actions`){let t=n.global?``:n.workspaces.map(t=>`--include ${assertShellSafeWorkspaceName(t)}`).join(` `),S=process.env.GITHUB_OUTPUT,C=[`skip-all=${n.skipAll}`,`global=${n.global}`,`include-args=${t}`,`run-integration=${n.runIntegration}`,`run-e2e=${n.runE2E}`,`reason=${n.reason}`];if(S)for(let t of C)appendFileSync(S,`${t}\n`);else for(let t of C)process.stdout.write(`${t}\n`);return}process.stdout.write(`affected:
1802
- `),process.stdout.write(` reason: ${n.reason}\n`),process.stdout.write(` global: ${n.global}\n`),process.stdout.write(` skip-all: ${n.skipAll}\n`),process.stdout.write(` run-integration: ${n.runIntegration}\n`),process.stdout.write(` run-e2e: ${n.runE2E}\n`),process.stdout.write(` workspaces (${n.workspaces.length}):\n`);for(let t of n.workspaces)process.stdout.write(` - ${t}\n`)}function assertShellSafeWorkspaceName(t){if(Qq.test(t))return t;throw process.stderr.write(`gjsify affected: workspace name ${JSON.stringify(t)} is not shell-safe, so it cannot be emitted as an\n \`include-args\` token (the value is consumed by an UNQUOTED $INCLUDE_ARGS expansion — see the\n contract at the top of commands/affected.ts). Rename the workspace, or teach this command a\n transport the consumers can unquote. Refusing to emit a filter that would silently mis-match.\n`),process.exit(2),Error(`gjsify affected: unsafe workspace name ${t}`)}var Zq,Qq,$q=__esmMin(()=>{ev(),ef(),zq(),AI(),Gq(),Xq(),MI(),Zq={command:`affected`,description:"Classify changed files against the workspace tree and print the set of workspaces affected (seeds + transitive dependents). Designed for CI to gate `gjsify foreach test --include …` so unrelated workspaces are not re-tested on every PR.",builder:t=>t.option(`base`,{description:"Diff base. Default: `origin/main`. Resolved via `git rev-parse`. On a PR set this to `${{ github.event.pull_request.base.sha }}`.",type:`string`}).option(`head`,{description:"Diff head. Default: `HEAD`.",type:`string`,default:`HEAD`}).option(`format`,{description:`Output shape.`,choices:[`text`,`json`,`globs`,`github-actions`],default:`text`}).option(`changed-from-stdin`,{description:"Skip `git diff`. Read a newline-separated list of repo-relative paths from stdin instead. Lets callers — tests, ad-hoc scripts — control the input exactly.",type:`boolean`,default:!1}).option(`cwd`,{description:"Workspace root. Default: discovered from `process.cwd()`.",type:`string`}),handler:async t=>{let n=t.cwd??findWorkspaceRoot(process.cwd())??process.cwd(),S=discoverWorkspaces(n,{includeRoot:!0}),C=t[`changed-from-stdin`]?readStdinLines():runGitDiff(n,t.base??`origin/main`,t.head??`HEAD`),N=classifyAndExpand(S,C,scriptReadersFor(n,C));emit(t.format,N)}},Qq=/^[A-Za-z0-9@][A-Za-z0-9@._/-]*$/}),eJ=__exportAll$5({isSelfWrite:()=>isSelfWrite,runWatchLoop:()=>runWatchLoop,spawnBundleSupervised:()=>spawnBundleSupervised,spawnSupervised:()=>spawnSupervised});function spawnSupervised(t,n,S){return new Promise((C,N)=>{spawnToCompletion(t,n,{completion:`daemon`,env:S,onSpawn:C}).catch(N)})}async function spawnBundleSupervised(t,n,S,C){if(t!==`gjs`){let{bundleRequiresNodeGi:N,resolveNodeGiForBundle:F}=await Promise.resolve().then(()=>(kR(),OR));if(N(n)&&!F(n,S))throw Error(`Cannot run ${C} on ${t}: \`@gjsify/node-gi\` is not installed. Add @gjsify/node-gi as a dependency to run ${C} on ${t}.`)}let{computeNativeEnvForBundle:N}=await Promise.resolve().then(()=>(DR(),ER)),{env:F}=N(n,S),I={...process.env,...F};if(t===`gjs`)return spawnSupervised(`gjs`,[`-m`,n],I);if(t===`node`){let{nodeBinary:t}=await Promise.resolve().then(()=>(kR(),OR));return spawnSupervised(t(),[n],I)}let[H,W]=lv[t].launch(n);return spawnSupervised(H,W,I)}function isSelfWrite(t,n,S){if(n===void 0||S===null)return!1;let C=Nn(t,S),N=Nn(t,n);if(C===N||C.startsWith(`${N}.`))return!0;let F=zn(N);return F===Nn(t)?!1:C===F||C.startsWith(`${F}${Wn}`)}async function runWatchLoop(t){let{dir:n,label:S,prepare:C,build:N,spawnChild:F,output:I,ignore:H,debounceMs:W=200}=t;markDaemonCommand();let q=null,Y=!1,X=!1,rebuild=async()=>{if(Y){X=!0;return}Y=!0;try{C&&await C(),q&&=(q.kill(),null),await N(),F&&(q=await F())}catch(t){ge.error(`[${S}] rebuild failed: ${t.message}`)}finally{Y=!1,X&&(X=!1,rebuild())}};await rebuild();let Z=null,te=(t.watch??[{path:n,recursive:!0}]).map(t=>watch(t.path,{recursive:t.recursive},(n,S)=>{let C=typeof S==`string`?S:null;isSelfWrite(t.path,I,C)||H&&C!==null&&H(Nn(t.path,C))||(Z&&clearTimeout(Z),Z=setTimeout(()=>void rebuild(),W))}));holdMainLoop();let ne=!1,shutdown=()=>{if(!ne){ne=!0,Z&&clearTimeout(Z),q?.kill();for(let t of te)t.close();process.exit(0)}};process.on(`SIGINT`,shutdown),process.on(`SIGTERM`,shutdown),ge.log(`[${S}] watching ${t.dirLabel??n} — press Ctrl+C to stop`)}var tJ=__esmMin(()=>{_e(),ef(),qn(),Ue(),Vz(),sv(),uv()});function readPackage$4(t){try{return JSON.parse(readFileSync(In(t,`package.json`),`utf8`))}catch{return{}}}function deriveAppId(t){return t?`org.gjsify.storybook.${t.replace(/^@/,``).replace(/[^a-zA-Z0-9]+/g,`.`).replace(/^\.+|\.+$/g,``)}`:`org.gjsify.Storybook`}function findStoryFiles(t){let n=[];if(!existsSync(t))return n;for(let S of readdirSync(t,{withFileTypes:!0})){if(S.name===`node_modules`||S.name.startsWith(`.`))continue;let C=In(t,S.name);S.isDirectory()?n.push(...findStoryFiles(C)):/\.story\.(ts|js|mts|mjs)$/.test(S.name)&&n.push(C)}return n}function generateEntry$4(t,n,S){let C=t.map((t,n)=>`import * as m${n} from ${JSON.stringify(t)};`).join(`
1802
+ `),process.stdout.write(` reason: ${n.reason}\n`),process.stdout.write(` global: ${n.global}\n`),process.stdout.write(` skip-all: ${n.skipAll}\n`),process.stdout.write(` run-integration: ${n.runIntegration}\n`),process.stdout.write(` run-e2e: ${n.runE2E}\n`),process.stdout.write(` workspaces (${n.workspaces.length}):\n`);for(let t of n.workspaces)process.stdout.write(` - ${t}\n`)}function assertShellSafeWorkspaceName(t){if($q.test(t))return t;throw process.stderr.write(`gjsify affected: workspace name ${JSON.stringify(t)} is not shell-safe, so it cannot be emitted as an\n \`include-args\` token (the value is consumed by an UNQUOTED $INCLUDE_ARGS expansion — see the\n contract at the top of commands/affected.ts). Rename the workspace, or teach this command a\n transport the consumers can unquote. Refusing to emit a filter that would silently mis-match.\n`),process.exit(2),Error(`gjsify affected: unsafe workspace name ${t}`)}var Qq,$q,eJ=__esmMin(()=>{ev(),ef(),Bq(),AI(),Kq(),Zq(),MI(),Qq={command:`affected`,description:"Classify changed files against the workspace tree and print the set of workspaces affected (seeds + transitive dependents). Designed for CI to gate `gjsify foreach test --include …` so unrelated workspaces are not re-tested on every PR.",builder:t=>t.option(`base`,{description:"Diff base. Default: `origin/main`. Resolved via `git rev-parse`. On a PR set this to `${{ github.event.pull_request.base.sha }}`.",type:`string`}).option(`head`,{description:"Diff head. Default: `HEAD`.",type:`string`,default:`HEAD`}).option(`format`,{description:`Output shape.`,choices:[`text`,`json`,`globs`,`github-actions`],default:`text`}).option(`changed-from-stdin`,{description:"Skip `git diff`. Read a newline-separated list of repo-relative paths from stdin instead. Lets callers — tests, ad-hoc scripts — control the input exactly.",type:`boolean`,default:!1}).option(`cwd`,{description:"Workspace root. Default: discovered from `process.cwd()`.",type:`string`}),handler:async t=>{let n=t.cwd??findWorkspaceRoot(process.cwd())??process.cwd(),S=discoverWorkspaces(n,{includeRoot:!0}),C=t[`changed-from-stdin`]?readStdinLines():runGitDiff(n,t.base??`origin/main`,t.head??`HEAD`),N=classifyAndExpand(S,C,scriptReadersFor(n,C));emit(t.format,N)}},$q=/^[A-Za-z0-9@][A-Za-z0-9@._/-]*$/}),tJ=__exportAll$5({isSelfWrite:()=>isSelfWrite,runWatchLoop:()=>runWatchLoop,spawnBundleSupervised:()=>spawnBundleSupervised,spawnSupervised:()=>spawnSupervised});function spawnSupervised(t,n,S){return new Promise((C,N)=>{spawnToCompletion(t,n,{completion:`daemon`,env:S,onSpawn:C}).catch(N)})}async function spawnBundleSupervised(t,n,S,C){if(t!==`gjs`){let{bundleRequiresNodeGi:N,resolveNodeGiForBundle:F}=await Promise.resolve().then(()=>(kR(),OR));if(N(n)&&!F(n,S))throw Error(`Cannot run ${C} on ${t}: \`@gjsify/node-gi\` is not installed. Add @gjsify/node-gi as a dependency to run ${C} on ${t}.`)}let{computeNativeEnvForBundle:N}=await Promise.resolve().then(()=>(DR(),ER)),{env:F}=N(n,S),I={...process.env,...F};if(t===`gjs`)return spawnSupervised(`gjs`,[`-m`,n],I);if(t===`node`){let{nodeBinary:t}=await Promise.resolve().then(()=>(kR(),OR));return spawnSupervised(t(),[n],I)}let[H,W]=lv[t].launch(n);return spawnSupervised(H,W,I)}function isSelfWrite(t,n,S){if(n===void 0||S===null)return!1;let C=Nn(t,S),N=Nn(t,n);if(C===N||C.startsWith(`${N}.`))return!0;let F=zn(N);return F===Nn(t)?!1:C===F||C.startsWith(`${F}${Wn}`)}async function runWatchLoop(t){let{dir:n,label:S,prepare:C,build:N,spawnChild:F,output:I,ignore:H,debounceMs:W=200}=t;markDaemonCommand();let q=null,Y=!1,X=!1,rebuild=async()=>{if(Y){X=!0;return}Y=!0;try{C&&await C(),q&&=(q.kill(),null),await N(),F&&(q=await F())}catch(t){ge.error(`[${S}] rebuild failed: ${t.message}`)}finally{Y=!1,X&&(X=!1,rebuild())}};await rebuild();let Z=null,te=(t.watch??[{path:n,recursive:!0}]).map(t=>watch(t.path,{recursive:t.recursive},(n,S)=>{let C=typeof S==`string`?S:null;isSelfWrite(t.path,I,C)||H&&C!==null&&H(Nn(t.path,C))||(Z&&clearTimeout(Z),Z=setTimeout(()=>void rebuild(),W))}));holdMainLoop();let ne=!1,shutdown=()=>{if(!ne){ne=!0,Z&&clearTimeout(Z),q?.kill();for(let t of te)t.close();process.exit(0)}};process.on(`SIGINT`,shutdown),process.on(`SIGTERM`,shutdown),ge.log(`[${S}] watching ${t.dirLabel??n} — press Ctrl+C to stop`)}var nJ=__esmMin(()=>{_e(),ef(),qn(),Ue(),Vz(),sv(),uv()});function readPackage$4(t){try{return JSON.parse(readFileSync(In(t,`package.json`),`utf8`))}catch{return{}}}function deriveAppId(t){return t?`org.gjsify.storybook.${t.replace(/^@/,``).replace(/[^a-zA-Z0-9]+/g,`.`).replace(/^\.+|\.+$/g,``)}`:`org.gjsify.Storybook`}function findStoryFiles(t){let n=[];if(!existsSync(t))return n;for(let S of readdirSync(t,{withFileTypes:!0})){if(S.name===`node_modules`||S.name.startsWith(`.`))continue;let C=In(t,S.name);S.isDirectory()?n.push(...findStoryFiles(C)):/\.story\.(ts|js|mts|mjs)$/.test(S.name)&&n.push(C)}return n}function generateEntry$4(t,n,S){let C=t.map((t,n)=>`import * as m${n} from ${JSON.stringify(t)};`).join(`
1803
1803
  `),N=t.map((t,n)=>`m${n}`).join(`, `),F=S?`\n title: ${JSON.stringify(S)},`:``;return`// Auto-generated by \`gjsify storybook\` — do not edit by hand.
1804
1804
  import { collectStoryModules, runStorybook } from '@gjsify/storybook';
1805
1805
  ${C}
@@ -1808,10 +1808,10 @@ await runStorybook({
1808
1808
  applicationId: ${JSON.stringify(n)},${F}
1809
1809
  stories: collectStoryModules([${N}]),
1810
1810
  });
1811
- `}var nJ,rJ=__esmMin(()=>{_e(),ef(),qn(),D_(),__name$1(readPackage$4,`readPackage`),__name$1(generateEntry$4,`generateEntry`),nJ={command:`storybook`,description:`Discover *.story.ts in this project and launch the GTK storybook browser.`,builder:t=>t.option(`stories`,{description:`Directory scanned recursively for *.story.ts (default: src, or gjsify.storybook.stories)`,type:`string`}).option(`app-id`,{description:`GApplication id (default: gjsify.storybook.applicationId or derived from the package name)`,type:`string`}).option(`title`,{description:`Window title`,type:`string`}).option(`globals`,{description:"Value for `gjsify build --globals` (default: auto; use auto,dom for canvas/DOM stories)",type:`string`}).option(`out`,{description:`Output bundle path (default: node_modules/.cache/gjsify-storybook)`,type:`string`}).option(`runtime`,{description:"Runtime to build for and launch on: gjs | node | bun | deno (default: the host runtime). node/bun/deno build the same `--app node` bundle (gi:// → @gjsify/node-gi) and require @gjsify/node-gi installed in the project.",type:`string`,choices:[`gjs`,`node`,`bun`,`deno`],defaultDescription:`host runtime (gjs on gjs, else node/bun/deno)`}).option(`watch`,{description:`Rebuild and relaunch when a story file changes`,type:`boolean`,default:!1}).option(`build-only`,{description:`Build the bundle but do not launch it`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=readPackage$4(n),C=S.gjsify?.storybook??{},N=Nn(n,t.stories??C.stories??`src`),F=t.appId??C.applicationId??deriveAppId(S.name),I=t.title??C.title,H=t.globals??C.globals??`auto`,W=t.runtime??C.runtime??hostRuntime$1(),q=W===`gjs`?`gjs`:`node`,Y=In(n,`node_modules`,`.cache`,`gjsify-storybook`);mkdirSync(Y,{recursive:!0});let X=In(Y,`entry.ts`),Z=t.out?Nn(n,t.out):In(Y,`storybook.${q}.mjs`),writeEntry=()=>{let t=findStoryFiles(N).sort();return writeFileSync(X,generateEntry$4(t,F,I)),t.length},te=writeEntry();if(te===0)return ge.error(`No *.story.ts files found under ${Ln(n,N)||N}\n\n \`gjsify storybook\` renders the stories of the CURRENT project: it discovers\n \`*.story.ts\` files and launches a component browser over them. Point it at a\n different directory with --stories <dir> (or \`gjsify.storybook.stories\` in\n package.json) if yours live elsewhere.\n\n To SEE a storybook without authoring one first, run the curated Libadwaita\n component browser — it is a showcase, so it needs no project at all:\n\n gjsify showcase adwaita-storybook`),process.exit(1);ge.log(`Found ${te} story file(s) under ${Ln(n,N)||`.`} (runtime: ${W})`);let{runCli:ne}=await Promise.resolve().then(()=>(iY(),rY)),buildBundle=()=>ne([`build`,X,`--app`,q,`--globals`,H,`--outfile`,Z]),launch=async()=>{if(W===`gjs`){let{runGjsBundle:t}=await Promise.resolve().then(()=>(DR(),ER));await t(Z,[],{completion:`exit`,exitOnSuccess:!0})}else if(W===`node`){let{runNodeBundle:t}=await Promise.resolve().then(()=>(kR(),OR));await t(Z,[],{completion:`exit`,exitOnSuccess:!0})}else{let{runRuntimeBundle:t}=await Promise.resolve().then(()=>(kR(),OR));await t(W,Z,[],{completion:`exit`,exitOnSuccess:!0})}};if(!t.watch){if(await buildBundle(),t.buildOnly)return;await launch();return}let{runWatchLoop:re,spawnBundleSupervised:ie}=await Promise.resolve().then(()=>(tJ(),eJ));await re({dir:N,dirLabel:Ln(n,N)||`.`,label:`storybook`,prepare:()=>{writeEntry()},build:buildBundle,spawnChild:t.buildOnly?null:()=>ie(W,Z,n,`the storybook`),output:Z})}}});function resolveSitePackage(t){let n=Nn(t);for(;;){let t=In(n,`node_modules`,`@gjsify`,`site`);if(existsSync(In(t,`package.json`)))return t;let S=zn(n);if(S===n)return;n=S}}function gjsOnPath(){return spawnSync(`gjs`,[`--version`],{stdio:`ignore`}).status===0}function pickRuntime(t,n){if(t)return t;let S=hostRuntime$1();return S===`gjs`||resolveNodeGi(n)?S:gjsOnPath()?`gjs`:S}function generateEntry$3(t,n=`gjsify site`){let S=`// Auto-generated by \`${n}\` — do not edit by hand.\nimport { runSiteCli } from '@gjsify/site';\n`;return t===`gjs`?`${S}import system from 'system';\n\nsystem.exit(await runSiteCli(system.programArgs));\n`:`${S}\nprocess.exit(await runSiteCli(process.argv.slice(2)));\n`}async function dispatchSite(t){let n=process.cwd(),S=resolveSitePackage(n);if(!S)return ge.error(`${t.invokedAs}: @gjsify/site is not installed in this project.\n\n The generator ships as its own package so a project only pays for it when it
1811
+ `}var rJ,iJ=__esmMin(()=>{_e(),ef(),qn(),D_(),__name$1(readPackage$4,`readPackage`),__name$1(generateEntry$4,`generateEntry`),rJ={command:`storybook`,description:`Discover *.story.ts in this project and launch the GTK storybook browser.`,builder:t=>t.option(`stories`,{description:`Directory scanned recursively for *.story.ts (default: src, or gjsify.storybook.stories)`,type:`string`}).option(`app-id`,{description:`GApplication id (default: gjsify.storybook.applicationId or derived from the package name)`,type:`string`}).option(`title`,{description:`Window title`,type:`string`}).option(`globals`,{description:"Value for `gjsify build --globals` (default: auto; use auto,dom for canvas/DOM stories)",type:`string`}).option(`out`,{description:`Output bundle path (default: node_modules/.cache/gjsify-storybook)`,type:`string`}).option(`runtime`,{description:"Runtime to build for and launch on: gjs | node | bun | deno (default: the host runtime). node/bun/deno build the same `--app node` bundle (gi:// → @gjsify/node-gi) and require @gjsify/node-gi installed in the project.",type:`string`,choices:[`gjs`,`node`,`bun`,`deno`],defaultDescription:`host runtime (gjs on gjs, else node/bun/deno)`}).option(`watch`,{description:`Rebuild and relaunch when a story file changes`,type:`boolean`,default:!1}).option(`build-only`,{description:`Build the bundle but do not launch it`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=readPackage$4(n),C=S.gjsify?.storybook??{},N=Nn(n,t.stories??C.stories??`src`),F=t.appId??C.applicationId??deriveAppId(S.name),I=t.title??C.title,H=t.globals??C.globals??`auto`,W=t.runtime??C.runtime??hostRuntime$1(),q=W===`gjs`?`gjs`:`node`,Y=In(n,`node_modules`,`.cache`,`gjsify-storybook`);mkdirSync(Y,{recursive:!0});let X=In(Y,`entry.ts`),Z=t.out?Nn(n,t.out):In(Y,`storybook.${q}.mjs`),writeEntry=()=>{let t=findStoryFiles(N).sort();return writeFileSync(X,generateEntry$4(t,F,I)),t.length},te=writeEntry();if(te===0)return ge.error(`No *.story.ts files found under ${Ln(n,N)||N}\n\n \`gjsify storybook\` renders the stories of the CURRENT project: it discovers\n \`*.story.ts\` files and launches a component browser over them. Point it at a\n different directory with --stories <dir> (or \`gjsify.storybook.stories\` in\n package.json) if yours live elsewhere.\n\n To SEE a storybook without authoring one first, run the curated Libadwaita\n component browser — it is a showcase, so it needs no project at all:\n\n gjsify showcase adwaita-storybook`),process.exit(1);ge.log(`Found ${te} story file(s) under ${Ln(n,N)||`.`} (runtime: ${W})`);let{runCli:ne}=await Promise.resolve().then(()=>(aY(),iY)),buildBundle=()=>ne([`build`,X,`--app`,q,`--globals`,H,`--outfile`,Z]),launch=async()=>{if(W===`gjs`){let{runGjsBundle:t}=await Promise.resolve().then(()=>(DR(),ER));await t(Z,[],{completion:`exit`,exitOnSuccess:!0})}else if(W===`node`){let{runNodeBundle:t}=await Promise.resolve().then(()=>(kR(),OR));await t(Z,[],{completion:`exit`,exitOnSuccess:!0})}else{let{runRuntimeBundle:t}=await Promise.resolve().then(()=>(kR(),OR));await t(W,Z,[],{completion:`exit`,exitOnSuccess:!0})}};if(!t.watch){if(await buildBundle(),t.buildOnly)return;await launch();return}let{runWatchLoop:re,spawnBundleSupervised:ie}=await Promise.resolve().then(()=>(nJ(),tJ));await re({dir:N,dirLabel:Ln(n,N)||`.`,label:`storybook`,prepare:()=>{writeEntry()},build:buildBundle,spawnChild:t.buildOnly?null:()=>ie(W,Z,n,`the storybook`),output:Z})}}});function resolveSitePackage(t){let n=Nn(t);for(;;){let t=In(n,`node_modules`,`@gjsify`,`site`);if(existsSync(In(t,`package.json`)))return t;let S=zn(n);if(S===n)return;n=S}}function gjsOnPath(){return spawnSync(`gjs`,[`--version`],{stdio:`ignore`}).status===0}function pickRuntime(t,n){if(t)return t;let S=hostRuntime$1();return S===`gjs`||resolveNodeGi(n)?S:gjsOnPath()?`gjs`:S}function generateEntry$3(t,n=`gjsify site`){let S=`// Auto-generated by \`${n}\` — do not edit by hand.\nimport { runSiteCli } from '@gjsify/site';\n`;return t===`gjs`?`${S}import system from 'system';\n\nsystem.exit(await runSiteCli(system.programArgs));\n`:`${S}\nprocess.exit(await runSiteCli(process.argv.slice(2)));\n`}async function dispatchSite(t){let n=process.cwd(),S=resolveSitePackage(n);if(!S)return ge.error(`${t.invokedAs}: @gjsify/site is not installed in this project.\n\n The generator ships as its own package so a project only pays for it when it
1812
1812
  publishes a page or a store listing. Add it, then run this again:
1813
1813
 
1814
- npm install --save-dev @gjsify/site`),process.exit(1);if(t.needsClient&&!existsSync(In(S,`lib`,`client`,`site.js`)))return ge.error(`${t.invokedAs}: ${S} has no built client bundle (lib/client/site.js).\n In a source checkout, build the package first: \`gjsify workspace site build\`.`),process.exit(1);let C=pickRuntime(t.runtime,n),N=C===`gjs`?`gjs`:`node`,F=In(n,`node_modules`,`.cache`,`gjsify-site`);mkdirSync(F,{recursive:!0});let I=In(F,`entry.${N}.ts`),H=In(F,`site.${N}.mjs`);writeFileSync(I,generateEntry$3(N,t.invokedAs));let W=t.globals??`auto`;if(N===`gjs`){let{BuildAction:t}=await Promise.resolve().then(()=>(eR(),ZL));await t.bundleFileForGjs(I,H,{globals:W,preserveDefaultExport:!1,toolchainAnchor:t.runningCliFile(),logLevel:`silent`})}else{let{runCli:t}=await Promise.resolve().then(()=>(iY(),rY));await t([`build`,I,`--app`,N,`--globals`,W,`--outfile`,H])}let q=[...t.argv.slice(0,1),`--package-dir`,S,...t.argv.slice(1)];if(C===`gjs`){let{runGjsBundle:t}=await Promise.resolve().then(()=>(DR(),ER));await t(H,q,{completion:`exit`,exitOnSuccess:!0});return}if(C===`node`){let{runNodeBundle:t}=await Promise.resolve().then(()=>(kR(),OR));await t(H,q,{completion:`exit`,exitOnSuccess:!0});return}let{runRuntimeBundle:Y}=await Promise.resolve().then(()=>(kR(),OR));await Y(C,H,q,{completion:`exit`,exitOnSuccess:!0})}var iJ=__esmMin(()=>{_e(),ev(),ef(),qn(),D_(),kR(),__name$1(generateEntry$3,`generateEntry`)}),aJ,oJ=__esmMin(()=>{qn(),iJ(),aJ={command:`site <operation>`,description:`Render this project's static landing page from its AppStream metainfo (downloads, screenshots, release notes, support links), or sync the page catalogues.`,builder:t=>t.positional(`operation`,{description:`build — render the pages; i18n — update the page catalogues`,type:`string`,choices:[`build`,`i18n`],demandOption:!0}).option(`root`,{description:`Repository to read from (default: the working directory)`,type:`string`}).option(`out`,{description:`Output directory, emptied first (default: <root>/dist)`,type:`string`}).option(`offline`,{description:`Skip every network call`,type:`boolean`,default:!1}).option(`drafts`,{description:"build: include blog posts marked `draft: true`",type:`boolean`,default:!1}).option(`cache`,{description:`Use the one-hour HTTP response cache (--no-cache to ignore it)`,type:`boolean`,default:!0}).option(`cache-dir`,{description:`Where the response cache and the image renditions live`,defaultDescription:`<root>/node_modules/.cache/gjsify-site`,type:`string`}).option(`check`,{description:`i18n: report what is out of date instead of writing it`,type:`boolean`,default:!1}).option(`package`,{description:`i18n: sync @gjsify/site's own catalogues instead of this project's`,type:`boolean`,default:!1}).option(`runtime`,{description:"Runtime to build for and run on: gjs | node | bun | deno (default: the host runtime). node/bun/deno build the same `--app node` bundle and require @gjsify/node-gi in the project; without it the default falls back to gjs.",type:`string`,choices:[`gjs`,`node`,`bun`,`deno`],defaultDescription:`host runtime (gjs on gjs, else node/bun/deno)`}).option(`globals`,{description:"Value for `gjsify build --globals` (default: auto)",type:`string`}),handler:async t=>{let n=process.cwd(),S=[t.operation];t.root&&S.push(`--root`,Nn(n,t.root)),t.out&&S.push(`--out`,Nn(n,t.out)),t.offline&&S.push(`--offline`),t.drafts&&S.push(`--drafts`),t.cache?t.cacheDir&&S.push(`--cache-dir`,Nn(n,t.cacheDir)):S.push(`--no-cache`),t.check&&S.push(`--check`),t.package&&S.push(`--package`),await dispatchSite({invokedAs:`gjsify site`,argv:S,runtime:t.runtime,globals:t.globals,needsClient:t.operation===`build`})}}});function readFlag(t,n){let S=`--${n}`;for(let n=0;n<t.length;n++){let C=t[n];if(C===S)return t[n+1];if(C.startsWith(`${S}=`))return C.slice(S.length+1)}}function withFlag(t,n,S){let C=`--${n}`,N=[...t];for(let t=0;t<N.length;t++){let n=N[t];if(n===C)return N[t+1]=S,N;if(n.startsWith(`${C}=`))return N[t]=`${C}=${S}`,N}return N.push(C,S),N}function buildEntryPoint(t){let n=t[1];if(!(n===void 0||n.startsWith(`-`)))return n}function noEntryError(t,n){let S=n?`\`${t}\` is not a plain \`gjsify build <entry> …\` command, so its entry point cannot be read`:`this package declares no \`${t}\` script`;return Error(`gjsify dev: nothing to build — ${S}.\n Name the entry point directly: gjsify dev src/index.ts\n or point at another script: gjsify dev --script <name>`)}function planDev(t){let n=t.scripts[t.scriptName],S=typeof n==`string`?gjsifyCommandArgv(n):null,C=S&&S[0]===`build`?S:null,N=t.entry??(C?buildEntryPoint(C):void 0);if(N===void 0)throw noEntryError(t.scriptName,typeof n==`string`);let F;return C?(F=[...C],buildEntryPoint(C)===void 0?F.splice(1,0,N):F[1]=N):F=[`build`,N],F=withFlag(F,`app`,t.app),t.globals!==void 0&&(F=withFlag(F,`globals`,t.globals)),t.outfile!==void 0&&(F=withFlag(F,`outfile`,t.outfile)),{buildArgv:F,bundle:readFlag(F,`outfile`)??t.declaredBundle,watchDir:t.watchDir??zn(N)}}function noBundleError(t,n){return Error(`gjsify dev: nothing to launch — neither \`${t}\` nor --outfile names an output file, and this package declares no ${n===`gjs`?"`gjsify.main`":"`gjsify.example.node`"}.\n Pass one: gjsify dev --outfile dist/index.${n}.mjs\n or rebuild without launching: gjsify dev --build-only`)}var sJ=__esmMin(()=>{qn(),qL()});function readPackage$3(t){try{return JSON.parse(readFileSync(In(t,`package.json`),`utf8`))}catch{return{}}}var cJ,lJ=__esmMin(()=>{_e(),ef(),qn(),sJ(),uv(),D_(),__name$1(readPackage$3,`readPackage`),cJ={command:`dev [entry]`,description:`Watch this project, rebuild on change and relaunch the app.`,builder:t=>t.positional(`entry`,{description:"Entry point to build (default: the one the build script names, e.g. src/index.ts from `build:gjs`).",type:`string`}).option(`runtime`,{description:"Runtime to build for and launch on: gjs | node | bun | deno (default: the host runtime). node/bun/deno build the same `--app node` bundle.",type:`string`,choices:cv,defaultDescription:`host runtime (gjs on gjs, else node/bun/deno)`}).option(`script`,{description:`package.json script the build flags are read from (default: build:gjs, or build:node for node/bun/deno).`,type:`string`}).option(`globals`,{description:"Override the build script `--globals` value.",type:`string`}).option(`outfile`,{description:"Override the build script `--outfile` path.",type:`string`}).option(`watch-dir`,{description:`Directory watched recursively (default: the directory of the entry point).`,type:`string`}).option(`debounce`,{description:`Quiet window in ms after a change before rebuilding.`,type:`number`,default:200}).option(`build-only`,{description:`Rebuild on every change but never launch the app.`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=readPackage$3(n),C=t.runtime??hostRuntime$1(),N=buildAppForRuntime(C),F=t.script??(N===`gjs`?`build:gjs`:`build:node`),I;try{I=planDev({scripts:S.scripts??{},scriptName:F,app:N,declaredBundle:N===`gjs`?S.gjsify?.main:S.gjsify?.example?.node,entry:t.entry,globals:t.globals,outfile:t.outfile,watchDir:t.watchDir})}catch(t){return ge.error(t.message),process.exit(1)}let H=I.bundle===void 0?void 0:Nn(n,I.bundle);if(H===void 0&&!t.buildOnly)return ge.error(noBundleError(F,N).message),process.exit(1);let W=Nn(n,I.watchDir);if(!existsSync(W))return ge.error(`gjsify dev: nothing to watch — ${Ln(n,W)||W} does not exist.\n Point the loop at your sources: gjsify dev --watch-dir <dir>`),process.exit(1);let q=H===void 0?`\`${F}\` output`:Ln(n,H);ge.log(`Watching ${Ln(n,W)||`.`} → ${q} (runtime: ${C})`);let{runCli:Y}=await Promise.resolve().then(()=>(iY(),rY)),{runWatchLoop:X,spawnBundleSupervised:Z}=await Promise.resolve().then(()=>(tJ(),eJ));await X({dir:W,dirLabel:Ln(n,W)||`.`,label:`dev`,build:()=>Y(I.buildArgv),spawnChild:t.buildOnly||H===void 0?null:()=>Z(C,H,n,`this project`),output:H,debounceMs:t.debounce})}}});function readPackage$2(t){try{return JSON.parse(readFileSync(In(t,`package.json`),`utf8`))}catch{return{}}}function deriveStorybookAppId(t){return t?`org.gjsify.storybook.${t.replace(/^@/,``).replace(/[^a-zA-Z0-9]+/g,`.`).replace(/^\.+|\.+$/g,``)}`:`org.gjsify.Storybook`}function deriveBrowserAppId$1(t){return t?`org.gjsify.browser.${t.replace(/^@/,``).replace(/[^a-zA-Z0-9]+/g,`.`).replace(/^\.+|\.+$/g,``)}`:`org.gjsify.Browser`}function hasDep(t,n){return!!(t.dependencies?.[n]||t.devDependencies?.[n])}function generateEntry$2(t,n,S,C,N){let F=JSON.stringify(n),I=N?`, { address: ${JSON.stringify(N)} }`:``;return t===`storybook`?`// Auto-generated by \`gjsify debug\` — do not edit by hand.
1814
+ npm install --save-dev @gjsify/site`),process.exit(1);if(t.needsClient&&!existsSync(In(S,`lib`,`client`,`site.js`)))return ge.error(`${t.invokedAs}: ${S} has no built client bundle (lib/client/site.js).\n In a source checkout, build the package first: \`gjsify workspace site build\`.`),process.exit(1);let C=pickRuntime(t.runtime,n),N=C===`gjs`?`gjs`:`node`,F=In(n,`node_modules`,`.cache`,`gjsify-site`);mkdirSync(F,{recursive:!0});let I=In(F,`entry.${N}.ts`),H=In(F,`site.${N}.mjs`);writeFileSync(I,generateEntry$3(N,t.invokedAs));let W=t.globals??`auto`;if(N===`gjs`){let{BuildAction:t}=await Promise.resolve().then(()=>(eR(),ZL));await t.bundleFileForGjs(I,H,{globals:W,preserveDefaultExport:!1,toolchainAnchor:t.runningCliFile(),logLevel:`silent`})}else{let{runCli:t}=await Promise.resolve().then(()=>(aY(),iY));await t([`build`,I,`--app`,N,`--globals`,W,`--outfile`,H])}let q=[...t.argv.slice(0,1),`--package-dir`,S,...t.argv.slice(1)];if(C===`gjs`){let{runGjsBundle:t}=await Promise.resolve().then(()=>(DR(),ER));await t(H,q,{completion:`exit`,exitOnSuccess:!0});return}if(C===`node`){let{runNodeBundle:t}=await Promise.resolve().then(()=>(kR(),OR));await t(H,q,{completion:`exit`,exitOnSuccess:!0});return}let{runRuntimeBundle:Y}=await Promise.resolve().then(()=>(kR(),OR));await Y(C,H,q,{completion:`exit`,exitOnSuccess:!0})}var aJ=__esmMin(()=>{_e(),ev(),ef(),qn(),D_(),kR(),__name$1(generateEntry$3,`generateEntry`)}),oJ,sJ=__esmMin(()=>{qn(),aJ(),oJ={command:`site <operation>`,description:`Render this project's static landing page from its AppStream metainfo (downloads, screenshots, release notes, support links), or sync the page catalogues.`,builder:t=>t.positional(`operation`,{description:`build — render the pages; i18n — update the page catalogues`,type:`string`,choices:[`build`,`i18n`],demandOption:!0}).option(`root`,{description:`Repository to read from (default: the working directory)`,type:`string`}).option(`out`,{description:`Output directory, emptied first (default: <root>/dist)`,type:`string`}).option(`offline`,{description:`Skip every network call`,type:`boolean`,default:!1}).option(`drafts`,{description:"build: include blog posts marked `draft: true`",type:`boolean`,default:!1}).option(`cache`,{description:`Use the one-hour HTTP response cache (--no-cache to ignore it)`,type:`boolean`,default:!0}).option(`cache-dir`,{description:`Where the response cache and the image renditions live`,defaultDescription:`<root>/node_modules/.cache/gjsify-site`,type:`string`}).option(`check`,{description:`i18n: report what is out of date instead of writing it`,type:`boolean`,default:!1}).option(`package`,{description:`i18n: sync @gjsify/site's own catalogues instead of this project's`,type:`boolean`,default:!1}).option(`runtime`,{description:"Runtime to build for and run on: gjs | node | bun | deno (default: the host runtime). node/bun/deno build the same `--app node` bundle and require @gjsify/node-gi in the project; without it the default falls back to gjs.",type:`string`,choices:[`gjs`,`node`,`bun`,`deno`],defaultDescription:`host runtime (gjs on gjs, else node/bun/deno)`}).option(`globals`,{description:"Value for `gjsify build --globals` (default: auto)",type:`string`}),handler:async t=>{let n=process.cwd(),S=[t.operation];t.root&&S.push(`--root`,Nn(n,t.root)),t.out&&S.push(`--out`,Nn(n,t.out)),t.offline&&S.push(`--offline`),t.drafts&&S.push(`--drafts`),t.cache?t.cacheDir&&S.push(`--cache-dir`,Nn(n,t.cacheDir)):S.push(`--no-cache`),t.check&&S.push(`--check`),t.package&&S.push(`--package`),await dispatchSite({invokedAs:`gjsify site`,argv:S,runtime:t.runtime,globals:t.globals,needsClient:t.operation===`build`})}}});function readFlag(t,n){let S=`--${n}`;for(let n=0;n<t.length;n++){let C=t[n];if(C===S)return t[n+1];if(C.startsWith(`${S}=`))return C.slice(S.length+1)}}function withFlag(t,n,S){let C=`--${n}`,N=[...t];for(let t=0;t<N.length;t++){let n=N[t];if(n===C)return N[t+1]=S,N;if(n.startsWith(`${C}=`))return N[t]=`${C}=${S}`,N}return N.push(C,S),N}function buildEntryPoint(t){let n=t[1];if(!(n===void 0||n.startsWith(`-`)))return n}function noEntryError(t,n){let S=n?`\`${t}\` is not a plain \`gjsify build <entry> …\` command, so its entry point cannot be read`:`this package declares no \`${t}\` script`;return Error(`gjsify dev: nothing to build — ${S}.\n Name the entry point directly: gjsify dev src/index.ts\n or point at another script: gjsify dev --script <name>`)}function planDev(t){let n=t.scripts[t.scriptName],S=typeof n==`string`?gjsifyCommandArgv(n):null,C=S&&S[0]===`build`?S:null,N=t.entry??(C?buildEntryPoint(C):void 0);if(N===void 0)throw noEntryError(t.scriptName,typeof n==`string`);let F;return C?(F=[...C],buildEntryPoint(C)===void 0?F.splice(1,0,N):F[1]=N):F=[`build`,N],F=withFlag(F,`app`,t.app),t.globals!==void 0&&(F=withFlag(F,`globals`,t.globals)),t.outfile!==void 0&&(F=withFlag(F,`outfile`,t.outfile)),{buildArgv:F,bundle:readFlag(F,`outfile`)??t.declaredBundle,watchDir:t.watchDir??zn(N)}}function noBundleError(t,n){return Error(`gjsify dev: nothing to launch — neither \`${t}\` nor --outfile names an output file, and this package declares no ${n===`gjs`?"`gjsify.main`":"`gjsify.example.node`"}.\n Pass one: gjsify dev --outfile dist/index.${n}.mjs\n or rebuild without launching: gjsify dev --build-only`)}var cJ=__esmMin(()=>{qn(),qL()});function readPackage$3(t){try{return JSON.parse(readFileSync(In(t,`package.json`),`utf8`))}catch{return{}}}var lJ,uJ=__esmMin(()=>{_e(),ef(),qn(),cJ(),uv(),D_(),__name$1(readPackage$3,`readPackage`),lJ={command:`dev [entry]`,description:`Watch this project, rebuild on change and relaunch the app.`,builder:t=>t.positional(`entry`,{description:"Entry point to build (default: the one the build script names, e.g. src/index.ts from `build:gjs`).",type:`string`}).option(`runtime`,{description:"Runtime to build for and launch on: gjs | node | bun | deno (default: the host runtime). node/bun/deno build the same `--app node` bundle.",type:`string`,choices:cv,defaultDescription:`host runtime (gjs on gjs, else node/bun/deno)`}).option(`script`,{description:`package.json script the build flags are read from (default: build:gjs, or build:node for node/bun/deno).`,type:`string`}).option(`globals`,{description:"Override the build script `--globals` value.",type:`string`}).option(`outfile`,{description:"Override the build script `--outfile` path.",type:`string`}).option(`watch-dir`,{description:`Directory watched recursively (default: the directory of the entry point).`,type:`string`}).option(`debounce`,{description:`Quiet window in ms after a change before rebuilding.`,type:`number`,default:200}).option(`build-only`,{description:`Rebuild on every change but never launch the app.`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=readPackage$3(n),C=t.runtime??hostRuntime$1(),N=buildAppForRuntime(C),F=t.script??(N===`gjs`?`build:gjs`:`build:node`),I;try{I=planDev({scripts:S.scripts??{},scriptName:F,app:N,declaredBundle:N===`gjs`?S.gjsify?.main:S.gjsify?.example?.node,entry:t.entry,globals:t.globals,outfile:t.outfile,watchDir:t.watchDir})}catch(t){return ge.error(t.message),process.exit(1)}let H=I.bundle===void 0?void 0:Nn(n,I.bundle);if(H===void 0&&!t.buildOnly)return ge.error(noBundleError(F,N).message),process.exit(1);let W=Nn(n,I.watchDir);if(!existsSync(W))return ge.error(`gjsify dev: nothing to watch — ${Ln(n,W)||W} does not exist.\n Point the loop at your sources: gjsify dev --watch-dir <dir>`),process.exit(1);let q=H===void 0?`\`${F}\` output`:Ln(n,H);ge.log(`Watching ${Ln(n,W)||`.`} → ${q} (runtime: ${C})`);let{runCli:Y}=await Promise.resolve().then(()=>(aY(),iY)),{runWatchLoop:X,spawnBundleSupervised:Z}=await Promise.resolve().then(()=>(nJ(),tJ));await X({dir:W,dirLabel:Ln(n,W)||`.`,label:`dev`,build:()=>Y(I.buildArgv),spawnChild:t.buildOnly||H===void 0?null:()=>Z(C,H,n,`this project`),output:H,debounceMs:t.debounce})}}});function readPackage$2(t){try{return JSON.parse(readFileSync(In(t,`package.json`),`utf8`))}catch{return{}}}function deriveStorybookAppId(t){return t?`org.gjsify.storybook.${t.replace(/^@/,``).replace(/[^a-zA-Z0-9]+/g,`.`).replace(/^\.+|\.+$/g,``)}`:`org.gjsify.Storybook`}function deriveBrowserAppId$1(t){return t?`org.gjsify.browser.${t.replace(/^@/,``).replace(/[^a-zA-Z0-9]+/g,`.`).replace(/^\.+|\.+$/g,``)}`:`org.gjsify.Browser`}function hasDep(t,n){return!!(t.dependencies?.[n]||t.devDependencies?.[n])}function generateEntry$2(t,n,S,C,N){let F=JSON.stringify(n),I=N?`, { address: ${JSON.stringify(N)} }`:``;return t===`storybook`?`// Auto-generated by \`gjsify debug\` — do not edit by hand.
1815
1815
  import { runDevtoolsMcp, storybookProfile } from '@gjsify/devtools-mcp';
1816
1816
 
1817
1817
  await runDevtoolsMcp(storybookProfile(${F}${I}));
@@ -1831,18 +1831,18 @@ await runDevtoolsMcp({
1831
1831
  version: ${JSON.stringify(C)},
1832
1832
  busNameBase: ${F},${N?`\n address: ${JSON.stringify(N)},`:``}
1833
1833
  });
1834
- `}var uJ,dJ=__esmMin(()=>{_e(),ef(),qn(),__name$1(readPackage$2,`readPackage`),__name$1(deriveBrowserAppId$1,`deriveBrowserAppId`),__name$1(generateEntry$2,`generateEntry`),uJ={command:`debug`,description:`Launch an MCP bridge for a devtools-enabled gjsify app (org.gjsify.Devtools).`,builder:t=>t.option(`bus-name`,{description:`App DBus base name (default: gjsify.devtools.busNameBase, or the storybook app-id)`,type:`string`}).option(`address`,{description:`Peer D-Bus address of the app (unix:path=… / nonce-tcp:…) instead of the session bus — for macOS/Windows, which have no session bus. Default: GJSIFY_DEVTOOLS_ADDRESS, then the address file the app publishes, then the session bus`,type:`string`}).option(`profile`,{description:`Tool profile: generic | storybook | browser | cdp (default: auto — storybook if @gjsify/storybook is a dep, browser if @gjsify/devtools-browser is, cdp if @gjsify/devtools-cdp is, else generic)`,type:`string`}).option(`globals`,{description:"Value for `gjsify build --globals` (default: auto)",type:`string`}).option(`out`,{description:`Output bundle path (default: node_modules/.cache/gjsify-debug)`,type:`string`}).option(`build-only`,{description:`Build the bridge bundle but do not launch it (for a .mcp.json command pointing at the bundle)`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=readPackage$2(n),C=S.gjsify?.devtools??{},N=t.profile??C.profile??(hasDep(S,`@gjsify/storybook`)?`storybook`:hasDep(S,`@gjsify/devtools-browser`)?`browser`:hasDep(S,`@gjsify/devtools-cdp`)?`cdp`:`generic`),F=t.busName??C.busNameBase??(N===`storybook`?S.gjsify?.storybook?.applicationId??deriveStorybookAppId(S.name):N===`browser`||N===`cdp`?S.gjsify?.browse?.applicationId??deriveBrowserAppId$1(S.name):void 0);if(!F)return ge.error(`gjsify debug: no bus name — set package.json#gjsify.devtools.busNameBase or pass --bus-name <org.example.App>`),process.exit(1);let I=t.globals??C.globals??`auto`,H=S.name?`${S.name}-devtools`:`gjsify-devtools`,W=In(n,`node_modules`,`.cache`,`gjsify-debug`);mkdirSync(W,{recursive:!0});let q=In(W,`entry.ts`),Y=t.out?Nn(n,t.out):In(W,`bridge.gjs.mjs`),X=t.address??C.address;writeFileSync(q,generateEntry$2(N,F,H,`0.8.0`,X)),ge.error(`[gjsify debug] profile=${N} bus=${F}${X?` address=${X}`:``}`);let{runCli:Z}=await Promise.resolve().then(()=>(iY(),rY));if(await Z([`build`,q,`--app`,`gjs`,`--shebang`,`--globals`,I,`--outfile`,Y]),t.buildOnly){ge.error(`[gjsify debug] built ${Y}`);return}let{runGjsBundle:te}=await Promise.resolve().then(()=>(DR(),ER));await te(Y,[],{completion:`exit`,exitOnSuccess:!0})}}});function readPackage$1(t){try{return JSON.parse(readFileSync(In(t,`package.json`),`utf8`))}catch{return{}}}function generateEntry$1(){return`// Auto-generated by \`gjsify devtools\` — do not edit by hand.
1834
+ `}var dJ,fJ=__esmMin(()=>{_e(),ef(),qn(),__name$1(readPackage$2,`readPackage`),__name$1(deriveBrowserAppId$1,`deriveBrowserAppId`),__name$1(generateEntry$2,`generateEntry`),dJ={command:`debug`,description:`Launch an MCP bridge for a devtools-enabled gjsify app (org.gjsify.Devtools).`,builder:t=>t.option(`bus-name`,{description:`App DBus base name (default: gjsify.devtools.busNameBase, or the storybook app-id)`,type:`string`}).option(`address`,{description:`Peer D-Bus address of the app (unix:path=… / nonce-tcp:…) instead of the session bus — for macOS/Windows, which have no session bus. Default: GJSIFY_DEVTOOLS_ADDRESS, then the address file the app publishes, then the session bus`,type:`string`}).option(`profile`,{description:`Tool profile: generic | storybook | browser | cdp (default: auto — storybook if @gjsify/storybook is a dep, browser if @gjsify/devtools-browser is, cdp if @gjsify/devtools-cdp is, else generic)`,type:`string`}).option(`globals`,{description:"Value for `gjsify build --globals` (default: auto)",type:`string`}).option(`out`,{description:`Output bundle path (default: node_modules/.cache/gjsify-debug)`,type:`string`}).option(`build-only`,{description:`Build the bridge bundle but do not launch it (for a .mcp.json command pointing at the bundle)`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=readPackage$2(n),C=S.gjsify?.devtools??{},N=t.profile??C.profile??(hasDep(S,`@gjsify/storybook`)?`storybook`:hasDep(S,`@gjsify/devtools-browser`)?`browser`:hasDep(S,`@gjsify/devtools-cdp`)?`cdp`:`generic`),F=t.busName??C.busNameBase??(N===`storybook`?S.gjsify?.storybook?.applicationId??deriveStorybookAppId(S.name):N===`browser`||N===`cdp`?S.gjsify?.browse?.applicationId??deriveBrowserAppId$1(S.name):void 0);if(!F)return ge.error(`gjsify debug: no bus name — set package.json#gjsify.devtools.busNameBase or pass --bus-name <org.example.App>`),process.exit(1);let I=t.globals??C.globals??`auto`,H=S.name?`${S.name}-devtools`:`gjsify-devtools`,W=In(n,`node_modules`,`.cache`,`gjsify-debug`);mkdirSync(W,{recursive:!0});let q=In(W,`entry.ts`),Y=t.out?Nn(n,t.out):In(W,`bridge.gjs.mjs`),X=t.address??C.address;writeFileSync(q,generateEntry$2(N,F,H,`0.8.0`,X)),ge.error(`[gjsify debug] profile=${N} bus=${F}${X?` address=${X}`:``}`);let{runCli:Z}=await Promise.resolve().then(()=>(aY(),iY));if(await Z([`build`,q,`--app`,`gjs`,`--shebang`,`--globals`,I,`--outfile`,Y]),t.buildOnly){ge.error(`[gjsify debug] built ${Y}`);return}let{runGjsBundle:te}=await Promise.resolve().then(()=>(DR(),ER));await te(Y,[],{completion:`exit`,exitOnSuccess:!0})}}});function readPackage$1(t){try{return JSON.parse(readFileSync(In(t,`package.json`),`utf8`))}catch{return{}}}function generateEntry$1(){return`// Auto-generated by \`gjsify devtools\` — do not edit by hand.
1835
1835
  import system from 'system';
1836
1836
 
1837
1837
  import { runDevtoolsCli } from '@gjsify/devtools-mcp';
1838
1838
 
1839
1839
  system.exit(await runDevtoolsCli(system.programArgs));
1840
- `}var fJ,pJ=__esmMin(()=>{_e(),ef(),qn(),__name$1(readPackage$1,`readPackage`),__name$1(generateEntry$1,`generateEntry`),fJ={command:`devtools <operation> [operands..]`,description:"Drive a running devtools-enabled app from a script: capture a screenshot to a file, find a widget, activate it, send a key. Peer of `gjsify debug`, which speaks MCP for an AI agent.",builder:t=>t.positional(`operation`,{description:`Control-plane operation: shot | find | activate | key | tree | property | …`,type:`string`,demandOption:!0}).positional(`operands`,{description:"Subcommand arguments — e.g. the output path for `shot`, the selector for `find`.",type:`string`,array:!0}).option(`bus-name`,{description:"App DBus base name — the app's Gtk application id (default: gjsify.devtools.busNameBase, then the storybook app-id). Unlike `gjsify debug` there is no derived fallback: the bus name IS the application id, and guessing it produces a name nothing answers to",type:`string`}).option(`address`,{description:`Peer D-Bus address of the app (unix:path=… / nonce-tcp:…) instead of the session bus — for macOS/Windows, which have no session bus. Default: GJSIFY_DEVTOOLS_ADDRESS, then the address file the app publishes, then the session bus`,type:`string`}).option(`instance`,{description:`App instance label for a multi-instance app (default: GJSIFY_DEVTOOLS_INSTANCE)`,type:`string`}).option(`globals`,{description:"Value for `gjsify build --globals` (default: auto)",type:`string`}).option(`out`,{description:`Output bundle path (default: node_modules/.cache/gjsify-devtools)`,type:`string`}).option(`timeout`,{description:`Seconds to keep polling GetStatus for the control plane to answer (default: 30). 0 = do not wait`,type:`number`,default:30}),handler:async t=>{let n=process.cwd(),S=readPackage$1(n),C=S.gjsify?.devtools??{},N=t.busName??C.busNameBase??S.gjsify?.storybook?.applicationId??S.gjsify?.browse?.applicationId;if(!N)return ge.error(`gjsify devtools: no bus name — the bus name IS the app's Gtk application id, so it cannot be derived from the package name. Pass --bus-name <org.example.App> (the app prints it when it exports the control plane) or set package.json#gjsify.devtools.busNameBase.`),process.exit(1);let F=In(n,`node_modules`,`.cache`,`gjsify-devtools`);mkdirSync(F,{recursive:!0});let I=In(F,`entry.ts`),H=t.out?Nn(n,t.out):In(F,`cli.gjs.mjs`),W=t.globals??`auto`;writeFileSync(I,generateEntry$1()),ge.error(`[gjsify devtools] bus=${N}${t.address?` address=${t.address}`:``}${t.instance?` instance=${t.instance}`:``}`);let{runCli:q}=await Promise.resolve().then(()=>(iY(),rY));await q([`build`,I,`--app`,`gjs`,`--globals`,W,`--outfile`,H]);let Y=[t.operation,...t.operands??[],`--bus-name`,N];t.address&&Y.push(`--address`,t.address),t.instance&&Y.push(`--instance`,t.instance),Y.push(`--timeout`,String(t.timeout));let{runGjsBundle:X}=await Promise.resolve().then(()=>(DR(),ER));await X(H,Y,{completion:`exit`,exitOnSuccess:!0})}}});function readPackage(t){try{return JSON.parse(readFileSync(In(t,`package.json`),`utf8`))}catch{return{}}}function deriveBrowserAppId(t){return t?`org.gjsify.browser.${t.replace(/^@/,``).replace(/[^a-zA-Z0-9]+/g,`.`).replace(/^\.+|\.+$/g,``)}`:`org.gjsify.Browser`}function generateEntry(t,n,S,C,N){let F=S?`\n title: ${JSON.stringify(S)},`:``,I=n?`\n homeUrl: ${JSON.stringify(n)},`:``,H=C===void 0?``:`\n inspectorPort: ${C},`,W=N?`\n screenshot: ${JSON.stringify(N)},`:``;return`// Auto-generated by \`gjsify browse\` — do not edit by hand.
1840
+ `}var pJ,mJ=__esmMin(()=>{_e(),ef(),qn(),__name$1(readPackage$1,`readPackage`),__name$1(generateEntry$1,`generateEntry`),pJ={command:`devtools <operation> [operands..]`,description:"Drive a running devtools-enabled app from a script: capture a screenshot to a file, find a widget, activate it, send a key. Peer of `gjsify debug`, which speaks MCP for an AI agent.",builder:t=>t.positional(`operation`,{description:`Control-plane operation: shot | find | activate | key | tree | property | …`,type:`string`,demandOption:!0}).positional(`operands`,{description:"Subcommand arguments — e.g. the output path for `shot`, the selector for `find`.",type:`string`,array:!0}).option(`bus-name`,{description:"App DBus base name — the app's Gtk application id (default: gjsify.devtools.busNameBase, then the storybook app-id). Unlike `gjsify debug` there is no derived fallback: the bus name IS the application id, and guessing it produces a name nothing answers to",type:`string`}).option(`address`,{description:`Peer D-Bus address of the app (unix:path=… / nonce-tcp:…) instead of the session bus — for macOS/Windows, which have no session bus. Default: GJSIFY_DEVTOOLS_ADDRESS, then the address file the app publishes, then the session bus`,type:`string`}).option(`instance`,{description:`App instance label for a multi-instance app (default: GJSIFY_DEVTOOLS_INSTANCE)`,type:`string`}).option(`globals`,{description:"Value for `gjsify build --globals` (default: auto)",type:`string`}).option(`out`,{description:`Output bundle path (default: node_modules/.cache/gjsify-devtools)`,type:`string`}).option(`timeout`,{description:`Seconds to keep polling GetStatus for the control plane to answer (default: 30). 0 = do not wait`,type:`number`,default:30}),handler:async t=>{let n=process.cwd(),S=readPackage$1(n),C=S.gjsify?.devtools??{},N=t.busName??C.busNameBase??S.gjsify?.storybook?.applicationId??S.gjsify?.browse?.applicationId;if(!N)return ge.error(`gjsify devtools: no bus name — the bus name IS the app's Gtk application id, so it cannot be derived from the package name. Pass --bus-name <org.example.App> (the app prints it when it exports the control plane) or set package.json#gjsify.devtools.busNameBase.`),process.exit(1);let F=In(n,`node_modules`,`.cache`,`gjsify-devtools`);mkdirSync(F,{recursive:!0});let I=In(F,`entry.ts`),H=t.out?Nn(n,t.out):In(F,`cli.gjs.mjs`),W=t.globals??`auto`;writeFileSync(I,generateEntry$1()),ge.error(`[gjsify devtools] bus=${N}${t.address?` address=${t.address}`:``}${t.instance?` instance=${t.instance}`:``}`);let{runCli:q}=await Promise.resolve().then(()=>(aY(),iY));await q([`build`,I,`--app`,`gjs`,`--globals`,W,`--outfile`,H]);let Y=[t.operation,...t.operands??[],`--bus-name`,N];t.address&&Y.push(`--address`,t.address),t.instance&&Y.push(`--instance`,t.instance),Y.push(`--timeout`,String(t.timeout));let{runGjsBundle:X}=await Promise.resolve().then(()=>(DR(),ER));await X(H,Y,{completion:`exit`,exitOnSuccess:!0})}}});function readPackage(t){try{return JSON.parse(readFileSync(In(t,`package.json`),`utf8`))}catch{return{}}}function deriveBrowserAppId(t){return t?`org.gjsify.browser.${t.replace(/^@/,``).replace(/[^a-zA-Z0-9]+/g,`.`).replace(/^\.+|\.+$/g,``)}`:`org.gjsify.Browser`}function generateEntry(t,n,S,C,N){let F=S?`\n title: ${JSON.stringify(S)},`:``,I=n?`\n homeUrl: ${JSON.stringify(n)},`:``,H=C===void 0?``:`\n inspectorPort: ${C},`,W=N?`\n screenshot: ${JSON.stringify(N)},`:``;return`// Auto-generated by \`gjsify browse\` — do not edit by hand.
1841
1841
  import { runBrowserDevtools } from '@gjsify/devtools-browser';
1842
1842
 
1843
1843
  await runBrowserDevtools({
1844
1844
  applicationId: ${JSON.stringify(t)},${F}${I}${H}${W}
1845
1845
  });
1846
- `}var mJ,hJ=__esmMin(()=>{_e(),ef(),qn(),mJ={command:`browse [url]`,description:`Launch the Adwaita web browser, optionally pointed at a URL.`,builder:t=>t.positional(`url`,{description:`Initial URL to load (default: page:welcome)`,type:`string`}).option(`app-id`,{description:`GApplication id (default: gjsify.browse.applicationId or derived from the package name)`,type:`string`}).option(`title`,{description:`Window title`,type:`string`}).option(`globals`,{description:"Value for `gjsify build --globals` (default: auto,dom — WebKit/iframe need DOM globals)",type:`string`}).option(`out`,{description:`Output bundle path (default: node_modules/.cache/gjsify-browse)`,type:`string`}).option(`devtools`,{description:`Enable the MCP devtools control plane (sets GJSIFY_DEVTOOLS=1)`,type:`boolean`,default:!1}).option(`inspector-port`,{description:`Enable WebKit's remote inspector protocol on this port + the Cdp* methods (implies --devtools)`,type:`number`}).option(`screenshot`,{description:`One-shot: load the URL, capture a WebKit screenshot to this path, and exit (CI / quick captures).`,type:`string`}).option(`build-only`,{description:`Build the bundle but do not launch it`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=readPackage(n),C=S.gjsify?.browse??{},N=t.appId??C.applicationId??deriveBrowserAppId(S.name),F=t.title??C.title,I=t.globals??C.globals??`auto,dom`,H=t.url,W=t.inspectorPort??C.inspectorPort,q=t.devtools||W!==void 0,Y=In(n,`node_modules`,`.cache`,`gjsify-browse`);mkdirSync(Y,{recursive:!0});let X=In(Y,`entry.ts`),Z=t.out?Nn(n,t.out):In(Y,`browse.gjs.mjs`);writeFileSync(X,generateEntry(N,H,F,W,t.screenshot?Nn(n,t.screenshot):void 0)),ge.log(`[gjsify browse] app=${N}${H?` url=${H}`:``}${q?` devtools=1`:``}${W===void 0?``:` inspector-port=${W}`}`);let{runCli:te}=await Promise.resolve().then(()=>(iY(),rY));if(await te([`build`,X,`--app`,`gjs`,`--globals`,I,`--outfile`,Z]),t.buildOnly){ge.log(`[gjsify browse] built ${Z}`);return}q&&(process.env.GJSIFY_DEVTOOLS=`1`),W!==void 0&&(process.env.WEBKIT_INSPECTOR_HTTP_SERVER=`127.0.0.1:${W}`);let{runGjsBundle:ne}=await Promise.resolve().then(()=>(DR(),ER));await ne(Z,[],{completion:`exit`,exitOnSuccess:!0})}}});function webextIconPaths(t,n,S){let C=t.sources.get(n);if(C===void 0)throw Error(`gjsify webext: the manifest asks for icon "${n}", and \`gjsify.webext.icons.sources\` declares ${[...t.sources.keys()].map(t=>`"${t}"`).join(`, `)||`none`}.`);let N=t.svgTargets.has(S.id),F={};for(let S of t.sizes)F[String(S)]=N?`icons/${Bn(C.get(S))}`:`icons/${n}-${S}.png`;return F}function svgIconFiles(t){let n=new Map;for(let[S,C]of t.sources)for(let t of C.values()){let C=`icons/${Bn(t)}`,N=n.get(C);if(N!==void 0&&N!==t)throw Error(`gjsify webext: icon "${S}" uses ${t}, and ${N} has the same file name; an SVG target would receive only one of them as `+C+`. Rename one.`);n.set(C,t)}return n}async function renderWebextIcons(t,n,S=rasterizeSvg){let C=n.some(n=>!t.svgTargets.has(n.id)),N=n.some(n=>t.svgTargets.has(n.id)),F=new Map;if(C){let n=new Map;for(let[S,C]of t.sources)for(let[t,N]of C)n.set(N,[...n.get(N)??[],{size:t,name:S}]);for(let[t,C]of n){let n=await S({svg:t,sizes:[...new Set(C.map(t=>t.size))],command:`gjsify webext`});for(let{size:t,name:S}of C)F.set(`icons/${S}-${t}.png`,n.get(t))}}return{png:F,svg:N?svgIconFiles(t):new Map}}function writeWebextIcons(t,n,S,C){if(mkdirSync(In(C,`icons`),{recursive:!0}),n.svgTargets.has(S.id))for(let[n,S]of t.svg)copyFileSync(S,In(C,n));else for(let[n,S]of t.png)writeFileSync(In(C,n),S)}var gJ=__esmMin(()=>{ef(),qn(),lH()});function isRecord$1(t){return typeof t==`object`&&!!t&&!Array.isArray(t)}function mergeManifest(t,n){let S={...t};for(let[t,C]of Object.entries(n))C===null?delete S[t]:isRecord$1(C)&&isRecord$1(S[t])?S[t]=mergeManifest(S[t],C):S[t]=C;return S}function applyTargetOverrides(t,n){let{$targets:S,...C}=t;if(S===void 0)return C;if(!isRecord$1(S))throw Error("gjsify webext: the manifest's `$targets` must be an object.");let N=S[n];if(N===void 0)return C;if(!isRecord$1(N))throw Error(`gjsify webext: \`$targets["${n}"]\` in the manifest must be an object.`);return mergeManifest(C,N)}async function composeManifest(t,n){let S=typeof t==`function`?await t(n):applyTargetOverrides(t,n.target);if(!isRecord$1(S))throw Error(`gjsify webext: the manifest for ${n.target} is not an object (got ${typeof S}).`);if(S.version!==void 0)return S;let C={};for(let[t,N]of Object.entries(S))C[t]=N,t===`name`&&(C.version=n.version);return C.version===void 0&&(C.version=n.version),C}async function loadManifestTemplate(t){if(/\.json$/i.test(t))try{return JSON.parse(readFileSync(t,`utf8`))}catch(n){throw Error(`gjsify webext: ${t} is not valid JSON: ${n.message}`)}let n,cleanup=null;if(isGjs()){let{BuildAction:S}=await Promise.resolve().then(()=>(eR(),ZL)),C=await S.bundleFileForGjsCached(t,{cacheSubdir:`webext`,label:Bn(t),cache:!1,define:{"import.meta.url":JSON.stringify(pathToFileURL(t).href)}}),N=In(zn(C),`manifest-${process.pid}-${++_J}.mjs`);copyFileSync(C,N),n=pathToFileURL(N).href,cleanup=()=>rmSync(N,{force:!0})}else n=`${pathToFileURL(t).href}?t=${statSync(t).mtimeMs}-${++_J}`;try{let S=(await import(n)).default;if(typeof S!=`function`&&!isRecord$1(S))throw Error(`gjsify webext: ${t} has no default export. Export the manifest object, or a function \`(ctx) => manifest\` that receives the target.`);return S}finally{cleanup?.()}}function addPath(t,n){typeof n!=`string`||n===``||/^[a-z][a-z0-9+.-]*:/i.test(n)||n.includes(`*`)||t.add(n.replace(/^\//,``).replace(/[?#].*$/,``))}function addIconValue(t,n){if(typeof n==`string`)addPath(t,n);else if(isRecord$1(n))for(let S of Object.values(n))addPath(t,S)}function manifestFileReferences(t){let n=new Set,S=t.background;if(isRecord$1(S)&&(addPath(n,S.service_worker),addPath(n,S.page),Array.isArray(S.scripts)))for(let t of S.scripts)addPath(n,t);if(Array.isArray(t.content_scripts)){for(let S of t.content_scripts)if(isRecord$1(S)){for(let t of[`js`,`css`])if(Array.isArray(S[t]))for(let C of S[t])addPath(n,C)}}for(let S of[`action`,`browser_action`,`page_action`,`sidebar_action`]){let C=t[S];isRecord$1(C)&&(addPath(n,C.default_popup),addPath(n,C.default_panel),addIconValue(n,C.default_icon))}if(isRecord$1(t.options_ui)&&addPath(n,t.options_ui.page),addPath(n,t.options_page),addPath(n,t.devtools_page),isRecord$1(t.side_panel)&&addPath(n,t.side_panel.default_path),addIconValue(n,t.icons),isRecord$1(t.chrome_url_overrides))for(let S of Object.values(t.chrome_url_overrides))addPath(n,S);if(Array.isArray(t.web_accessible_resources)){for(let S of t.web_accessible_resources)if(typeof S==`string`)addPath(n,S);else if(isRecord$1(S)&&Array.isArray(S.resources))for(let t of S.resources)addPath(n,t)}return[...n].sort()}function checkManifest(t,n,S){let C=[];t.manifest_version!==n.manifestVersion&&C.push(`manifest_version is ${JSON.stringify(t.manifest_version)}, and target ${n.id} is Manifest V${n.manifestVersion}. gjsify does not convert keys between versions — branch on \`ctx.manifestVersion\` in the manifest.`);for(let N of manifestFileReferences(t))existsSync(In(S,N))||C.push(`the manifest names "${N}", which the build did not write into ${n.id}/.`);let N=existsSync(In(S,`_locales`)),F=t.default_locale;return N&&typeof F!=`string`?C.push(`_locales/ exists but the manifest sets no default_locale; the browser refuses to load it.`):!N&&F!==void 0?C.push(`the manifest sets default_locale "${String(F)}" but there is no _locales/ directory.`):typeof F==`string`&&!existsSync(In(S,`_locales`,F,`messages.json`))&&C.push(`default_locale is "${F}" but _locales/${F}/messages.json does not exist.`),C}var _J,vJ=__esmMin(()=>{ef(),qn(),ir(),D_(),__name$1(isRecord$1,`isRecord`),_J=0});function planPage(t,n,S){let C=zn(n),N=[],F=[],local=t=>{if(TJ.test(t)||t.startsWith(`/`))return null;let n=t.replace(/[?#].*$/,``);return Fn(n)?n:Nn(C,n)},I=S.replace(yJ,n=>{let S=xJ.exec(n);if(!S)return n;let C=local(S[2]);if(C===null||!EJ.test(C))return n;let F=N.length===0?`${t}.js`:`${t}-${N.length+1}.js`;return N.push({entry:C,format:CJ.test(n)?`esm`:`iife`,output:F}),n.replace(xJ,(t,n)=>`src=${n}${F}${n}`)});return I=I.replace(bJ,t=>{if(!wJ.test(t))return t;let n=SJ.exec(t);if(!n)return t;let S=local(n[2]);if(S===null)return t;let C=Bn(S);return F.push({source:S,output:C}),t.replace(SJ,(t,n)=>`href=${n}${C}${n}`)}),{html:I,scripts:N,stylesheets:F}}var yJ,bJ,xJ,SJ,CJ,wJ,TJ,EJ,DJ=__esmMin(()=>{qn(),yJ=/<script\b[^>]*\bsrc\s*=\s*["'][^"']+["'][^>]*>/gi,bJ=/<link\b[^>]*>/gi,xJ=/\bsrc\s*=\s*(["'])([^"']+)\1/i,SJ=/\bhref\s*=\s*(["'])([^"']+)\1/i,CJ=/\btype\s*=\s*["']module["']/i,wJ=/\brel\s*=\s*["'][^"']*\bstylesheet\b[^"']*["']/i,TJ=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,EJ=/\.(?:[cm]?[jt]sx?)$/i});function zipTimestamp(t=process.env){let n=Number(t.SOURCE_DATE_EPOCH);return Number.isFinite(n)&&n>=OJ?n:OJ}function zipEntriesOf(t){let n=[],walk=S=>{for(let C of readdirSync(S,{withFileTypes:!0})){let N=In(S,C.name);C.isDirectory()?walk(N):n.push({path:Ln(t,N).split(/[\\/]/).join(`/`),mode:420,data:readFileSync(N)})}};return walk(t),n}async function buildWebext(t){let{config:n,targets:S,outDir:C,define:N}=t,F=t.log??(t=>ge.log(t)),I=t.mode===`production`&&n.minify,H=In(C,`.stage`);rmSync(H,{recursive:!0,force:!0}),mkdirSync(H,{recursive:!0});try{for(let[S,C]of n.scripts)await t.bundle({entry:C,outfile:In(H,`${S}.js`),format:`iife`,define:N,minify:I});let W=new Map;for(let[S,C]of n.pages){let n=planPage(S,C,readFileSync(C,`utf8`));for(let S of n.scripts)await t.bundle({entry:S.entry,outfile:In(H,S.output),format:S.format,define:N,minify:I});for(let t of n.stylesheets){let n=W.get(t.output);if(n!==void 0&&n!==t.source)throw Error(`gjsify webext: pages link ${n} and ${t.source}, which would both be written as ${t.output}. Rename one.`);W.set(t.output,t.source),cpSync(t.source,In(H,t.output))}writeFileSync(In(H,`${S}.html`),n.html)}let q=n.icons,Y=q?await renderWebextIcons(q,S,t.rasterize):null,X=await loadManifestTemplate(n.manifest),Z={folders:new Map,zips:new Map};for(let I of S){let S=In(C,I.id);t.inPlace||rmSync(S,{recursive:!0,force:!0}),mkdirSync(S,{recursive:!0}),n.publicDir&&cpSync(n.publicDir,S,{recursive:!0}),n.localesDir&&cpSync(n.localesDir,In(S,`_locales`),{recursive:!0}),cpSync(H,S,{recursive:!0}),q&&Y&&writeWebextIcons(Y,q,I,S);let W=await composeManifest(X,{target:I.id,browser:I.browser,manifestVersion:I.manifestVersion,mode:t.mode,version:n.version,define:N,icons:t=>{if(!q)throw Error(`gjsify webext: the manifest asks for icon "${t}" and \`gjsify.webext.icons\` is not declared.`);return webextIconPaths(q,t,I)}});writeFileSync(In(S,`manifest.json`),`${JSON.stringify(W,null,2)}\n`);let te=checkManifest(W,I,S);if(te.length>0)throw Error(`gjsify webext: ${I.id} would not load:\n - ${te.join(`
1847
- - `)}`);if(Z.folders.set(I.id,S),F(`built ${Ln(process.cwd(),S)||S}`),t.zip){let t=In(C,`${n.name}-${n.version}-${I.id}.zip`);writeFileSync(t,buildZip(zipEntriesOf(S),zipTimestamp())),Z.zips.set(I.id,t),F(`zipped ${Ln(process.cwd(),t)||t} (${Math.round(statSync(t).size/1024)} KiB)`)}}return Z}finally{rmSync(H,{recursive:!0,force:!0})}}var OJ,kJ=__esmMin(()=>{_e(),ef(),qn(),EW(),gJ(),vJ(),DJ(),OJ=315532800});function parseWebextTarget(t){let n=/^([a-z]+)-mv([23])$/.exec(t),S=n?.[1];if(!n||S===void 0||!AJ.includes(S))throw Error(`gjsify webext: unknown target "${t}". A target is <browser>-mv<2|3> with browser one of ${AJ.join(`, `)} (e.g. chrome-mv3, firefox-mv2).`);let C=n[2]===`2`?2:3,N=C===2?MJ.get(S):void 0;if(N!==void 0)throw Error(`gjsify webext: target "${t}" does not exist any more: ${N}. Use ${S}-mv3.`);return{id:t,browser:S,manifestVersion:C}}function webExtRunTarget(t){return t.browser===`firefox`?`firefox-desktop`:t.browser===`chrome`||t.browser===`edge`||t.browser===`opera`?`chromium`:null}var AJ,jJ,MJ,NJ=__esmMin(()=>{AJ=[`chrome`,`edge`,`firefox`,`opera`,`safari`],jJ=[`chrome-mv3`,`firefox-mv3`],MJ=new Map([[`chrome`,`chrome has removed Manifest V2`],[`edge`,`edge has removed Manifest V2`],[`opera`,`opera's extension store accepts Manifest V3 only`]])});function isRecord(t){return typeof t==`object`&&!!t&&!Array.isArray(t)}function defaultArtifactName(t){let n=(t??`extension`).replace(/^@[^/]+\//,``);return n===``?`extension`:n}function iconSourceForSize(t,n){if(typeof t==`string`)return t;let S=Object.keys(t).filter(t=>/^\d+$/.test(t)).map(Number).sort((t,n)=>t-n).find(t=>n<=t);return S===void 0?t.default:t[String(S)]}function resolveWebextConfig(t,n,S=defaultExists){let C=[],N=t.gjsify?.webext;if(N===void 0)throw Error("gjsify webext: this package declares no `gjsify.webext` block in package.json. Add one naming at least the manifest and one script or page — see `gjsify webext build --help`.");if(!isRecord(N))throw Error("gjsify webext: `gjsify.webext` must be an object.");let F=N,abs=t=>Fn(t)?t:Nn(n,t),need=(t,n,N)=>{let F=abs(n);return S(F,N)||C.push(`${t} "${n}" is not a ${N===`dir`?`directory`:`file`}.`),F},I=[],H=F.targets??[...jJ];if(!Array.isArray(H)||H.length===0)C.push("`targets` must be a non-empty array of target names.");else for(let t of H)try{I.some(n=>n.id===t)?C.push(`target "${t}" is listed twice.`):I.push(parseWebextTarget(String(t)))}catch(t){C.push(t.message.replace(/^gjsify webext: /,``))}let W=``;if(F.manifest!==void 0)W=need("`manifest`",F.manifest,`file`);else{let t=FJ.find(t=>S(In(n,t),`file`));t===void 0?C.push(`no \`manifest\` declared and none of ${FJ.join(`, `)} exists.`):W=In(n,t)}let q=new Map,claim=(t,n)=>{let S=q.get(t);S===void 0?q.set(t,n):C.push(`${n} and ${S} both write ${t}.`)},readEntries=t=>{let n=new Map,S=F[t];if(S===void 0)return n;if(!isRecord(S))return C.push(`\`${t}\` must map an output name to a source file.`),n;for(let[N,F]of Object.entries(S)){if(!IJ.test(N)){C.push(`\`${t}.${N}\`: an output name is a plain file name (letters, digits, . _ -).`);continue}if(typeof F!=`string`){C.push(`\`${t}.${N}\` must be a path.`);continue}n.set(N,need(`\`${t}.${N}\``,F,`file`)),t===`scripts`?claim(`${N}.js`,`\`scripts.${N}\``):claim(`${N}.html`,`\`pages.${N}\``)}return n},Y=readEntries(`scripts`),X=readEntries(`pages`);Y.size===0&&X.size===0&&C.push("declare at least one entry under `scripts` or `pages`; there is nothing to build.");for(let t of X.keys())Y.has(t)&&C.push(`\`scripts.${t}\` and the script of \`pages.${t}\` both write ${t}.js.`);let Z=null;if(F.icons!==void 0)if(!isRecord(F.icons)||!isRecord(F.icons.sources))C.push("`icons` must be an object with a `sources` map (icon name → SVG).");else{let t=F.icons.sizes??PJ;(!Array.isArray(t)||t.length===0||t.some(t=>!Number.isInteger(t)||t<=0))&&C.push("`icons.sizes` must be a non-empty list of positive integers.");let n=new Set(F.icons.svg??[]);for(let t of n)I.some(n=>n.id===t)||C.push(`\`icons.svg\` names "${t}", which is not one of this package's targets.`);let N=new Map;for(let[n,I]of Object.entries(F.icons.sources)){if(!IJ.test(n)){C.push(`\`icons.sources.${n}\`: an icon name is a plain file name.`);continue}if(typeof I!=`string`&&!isRecord(I)){C.push(`\`icons.sources.${n}\` must be an SVG path or a map of size ceilings to SVGs.`);continue}let F=new Map;for(let S of t){let t=iconSourceForSize(I,S);if(t===void 0){C.push(`\`icons.sources.${n}\` has no SVG for ${S} px — add a "default".`);continue}/\.svg$/i.test(t)||C.push(`\`icons.sources.${n}\`: "${t}" is not an .svg file.`),F.set(S,abs(t))}for(let t of new Set(F.values()))S(t,`file`)||C.push(`\`icons.sources.${n}\`: "${t}" does not exist.`);N.set(n,F)}Z={sizes:t,sources:N,svgTargets:n}}let optionalDir=(t,C)=>{let N=F[t];if(N!==void 0)return need(`\`${t}\``,N,`dir`);let I=In(n,C);return S(I,`dir`)?I:null},te=optionalDir(`public`,`public`),ne=optionalDir(`locales`,`_locales`),re=F.define??{};(!isRecord(re)||Object.values(re).some(t=>typeof t!=`string`))&&C.push("`define` must map identifiers to JS expressions given as strings.");let ie=F.watch??[];if((!Array.isArray(ie)||ie.some(t=>typeof t!=`string`))&&C.push("`watch` must be a list of directories."),C.length>0)throw Error(`gjsify webext: \`gjsify.webext\` in ${In(n,`package.json`)}:\n - ${C.join(`
1848
- - `)}`);return{root:n,name:F.name??defaultArtifactName(t.name),version:t.version??`0.0.0`,targets:I,manifest:W,scripts:Y,pages:X,icons:Z,publicDir:te,localesDir:ne,outDir:abs(F.outDir??`.output`),define:re,watch:ie.map(abs),minify:F.minify??!0}}function defaultExists(t,n){if(!existsSync(t))return!1;let S=statSync(t);return n===`dir`?S.isDirectory():S.isFile()}function selectTargets(t,n){return n===void 0||n.length===0?t.targets:n.map(n=>{let S=t.targets.find(t=>t.id===n);if(S)return S;throw parseWebextTarget(n),Error(`gjsify webext: target "${n}" is not in \`gjsify.webext.targets\` (${t.targets.map(t=>t.id).join(`, `)}).`)})}var PJ,FJ,IJ,LJ=__esmMin(()=>{ef(),qn(),NJ(),PJ=[16,32,48,128],FJ=[`manifest.ts`,`manifest.mts`,`manifest.js`,`manifest.mjs`,`manifest.json`],IJ=/^[A-Za-z0-9][A-Za-z0-9._-]*$/});function webExtRunArgs(t){let n=webExtRunTarget(t.target);if(n===null)throw Error(`gjsify webext dev: web-ext cannot launch ${t.target.browser}. Build with \`gjsify webext build --target ${t.target.id}\` and load the folder by hand, or pass \`--no-launch\`.`);let S=[`run`,`--source-dir`,t.sourceDir,`--target`,n,`--no-input`,`--profile-create-if-missing`];return n===`firefox-desktop`?(S.push(`--firefox-profile`,t.profile,`--keep-profile-changes`),t.browserBinary&&S.push(`--firefox`,t.browserBinary),t.headless&&S.push(`--arg=-headless`)):(S.push(`--chromium-profile`,t.profile),t.browserBinary&&S.push(`--chromium-binary`,t.browserBinary),t.headless&&S.push(`--arg=--headless=new`)),S}function defaultDevProfile(t,n,S=process.env){return In(S.XDG_CACHE_HOME||In(homedir(),`.cache`),`gjsify`,`webext`,t,n.id)}function resolveWebExt(t,n=process.platform,S=process.env){let C=n===`win32`?`web-ext.cmd`:`web-ext`;for(let n=t;;n=zn(n)){let t=In(n,`node_modules`,`.bin`);if(existsSync(In(t,C)))return{cmd:`web-ext`,env:{...S,PATH:[t,S.PATH].filter(Boolean).join(Gn)}};if(zn(n)===n)break}return isOnPath(`web-ext`)?{cmd:`web-ext`,env:S}:null}var RJ,zJ=__esmMin(()=>{ef(),$g(),qn(),ZI(),NJ(),RJ="gjsify webext dev: `web-ext` is not installed. Add it to the project (`gjsify install --save-dev web-ext`) or install it globally, or pass `--no-launch` to rebuild without a browser."});function loadConfig(t){let n=In(t,`package.json`);if(!existsSync(n))throw Error(`gjsify webext: no package.json in ${t}.`);return resolveWebextConfig(JSON.parse(readFileSync(n,`utf8`)),t)}function effectiveDefines(t,n){let S={...t.define};for(let t of n){let n=t.indexOf(`=`);if(n<=0)throw Error(`gjsify webext: --define "${t}" is not KEY=VALUE.`);S[t.slice(0,n)]=t.slice(n+1)}return S}async function bundleInProcess(t){let{runCli:n}=await Promise.resolve().then(()=>(iY(),rY)),S=[`build`,t.entry,`--app`,`browser`,`--format`,t.format,`--outfile`,t.outfile];for(let[n,C]of Object.entries(t.define))S.push(`--define`,`${n}=${C}`);t.minify||S.push(`--no-minify`),await n(S)}async function runBuild(t,n){let S=process.cwd(),C=loadConfig(S),N=t.mode===`development`?`development`:`production`;await buildWebext({config:C,targets:selectTargets(C,t.target),outDir:t.outDir?Nn(S,t.outDir):C.outDir,mode:N,define:effectiveDefines(C,t.define),inPlace:!1,zip:n,bundle:bundleInProcess})}function devTarget(t,n){if(n&&n.length>1)throw Error(`gjsify webext dev: pass one --target.`);let[S]=selectTargets(t,n);return n&&n.length===1?S:t.targets.find(t=>t.browser===`firefox`)??S}function devWatchTargets(t,n){let skip=t=>t===`node_modules`||t.startsWith(`.`),S=[{path:t.root,recursive:!1}];for(let C of readdirSync(t.root,{withFileTypes:!0})){let N=In(t.root,C.name);!C.isDirectory()||skip(C.name)||N===n||n.startsWith(N+Wn)||S.push({path:N,recursive:!0})}for(let n of t.watch)S.push({path:n,recursive:!0});return S}var BJ,VJ,HJ,UJ,WJ,GJ,KJ,qJ=__esmMin(()=>{_e(),ef(),qn(),iJ(),kJ(),LJ(),zJ(),BJ={description:`Build only these targets (default: every target in gjsify.webext.targets).`,type:`string`,array:!0},VJ={description:`Output directory (default: gjsify.webext.outDir, else .output).`,type:`string`},HJ={description:`Compile-time constant for every bundle, KEY=VALUE (repeatable); wins over gjsify.webext.define.`,type:`string`,array:!0,default:[]},UJ={command:`build`,description:`Build one extension folder per target: bundles, pages, icons, locales and the manifest.`,builder:t=>t.option(`target`,BJ).option(`out-dir`,VJ).option(`define`,HJ).option(`mode`,{description:`Passed to the manifest as ctx.mode; development also skips minification.`,type:`string`,choices:[`production`,`development`],default:`production`}),handler:t=>runBuild(t,!1)},WJ={command:`zip`,description:`Production build, then one store-ready <name>-<version>-<target>.zip per target.`,builder:t=>t.option(`target`,BJ).option(`out-dir`,VJ).option(`define`,HJ),handler:t=>runBuild(t,!0)},GJ={command:`dev`,description:`Build one target in development mode, launch it in a browser via web-ext, and rebuild in place on change.`,builder:t=>t.option(`target`,{...BJ,description:`The target to run (default: the first Firefox target).`}).option(`out-dir`,{description:`Output directory (default: <outDir>-dev).`,type:`string`}).option(`define`,HJ).option(`launch`,{description:`Start a browser with the extension (--no-launch only rebuilds).`,type:`boolean`,default:!0}).option(`browser-binary`,{description:`Browser executable web-ext should start.`,type:`string`}).option(`profile`,{description:`Browser profile directory (default: $XDG_CACHE_HOME/gjsify/webext/<name>/<target>).`,type:`string`}).option(`headless`,{description:`Start the browser without a window.`,type:`boolean`,default:!1}).option(`debounce`,{description:`Quiet window in ms before a rebuild.`,type:`number`,default:200}),handler:async t=>{let n=process.cwd(),S=loadConfig(n),C=devTarget(S,t.target),N=t.outDir?Nn(n,t.outDir):`${S.outDir}-dev`,F=effectiveDefines(S,t.define),I=In(N,C.id),H=null;if(t.launch&&(H=resolveWebExt(n),H===null))throw Error(RJ);let W=null,stopBrowser=()=>{W?.kill()};process.on(`SIGINT`,stopBrowser),process.on(`SIGTERM`,stopBrowser);let launch=async()=>{if(H===null||W!==null)return;let N=t.profile?Nn(n,t.profile):defaultDevProfile(S.name,C);mkdirSync(zn(N),{recursive:!0});let F=webExtRunArgs({sourceDir:I,target:C,profile:N,browserBinary:t.browserBinary,headless:t.headless});ge.log(`[webext] launching ${C.id} with profile ${N}`);let{spawnSupervised:q}=await Promise.resolve().then(()=>(tJ(),eJ));W=await q(H.cmd,F,H.env),W.on(`exit`,t=>{ge.log(`[webext] browser closed (${t??0}) — stopping`),process.exit(0)})},{runWatchLoop:q}=await Promise.resolve().then(()=>(tJ(),eJ));await q({dir:n,dirLabel:`.`,label:`webext`,watch:devWatchTargets(S,N),ignore:t=>t===N||t.startsWith(N+Wn),build:async()=>{await buildWebext({config:S,targets:[C],outDir:N,mode:`development`,define:F,inPlace:!0,zip:!1,bundle:bundleInProcess}),await launch()},spawnChild:null,debounceMs:t.debounce})}},KJ={command:`listing`,description:`Derive the store listings (Chrome Web Store, Edge Add-ons, Firefox AMO) from the AppStream metainfo, the gettext catalogues and the screenshots: texts, permission justifications and exact-size images.`,builder:t=>t.option(`store`,{description:`Which store to write (default: all).`,type:`string`,choices:[`cws`,`edge`,`amo`,`all`],default:`all`}).option(`out`,{description:`Output directory, emptied first (default: dist/listing).`,type:`string`}).option(`check`,{description:`Validate against the store limits; write nothing.`,type:`boolean`,default:!1}).option(`metainfo`,{description:`AppStream metainfo (default: gjsify.webext.listing.metainfo, else gjsify.site.metainfo).`,type:`string`}).option(`config`,{description:`JSON file that overrides the gjsify.webext.listing block of package.json.`,type:`string`}).option(`pot`,{description:`Also write the config strings as a gettext template.`,type:`string`}).option(`root`,{description:`Project root (default: the working directory).`,type:`string`}).option(`offline`,{description:`Skip downloading screenshots hosted elsewhere.`,type:`boolean`,default:!1}).option(`runtime`,{description:`Runtime to run on: gjs | node | bun | deno (default: the host runtime).`,type:`string`,choices:[`gjs`,`node`,`bun`,`deno`]}).option(`globals`,{description:"Value for `gjsify build --globals` (default: auto).",type:`string`}),handler:async t=>{let n=process.cwd(),S=[`listing`,`--store`,t.store];t.root&&S.push(`--root`,Nn(n,t.root)),t.out&&S.push(`--out`,Nn(n,t.out)),t.check&&S.push(`--check`),t.metainfo&&S.push(`--metainfo`,t.metainfo),t.config&&S.push(`--config`,Nn(n,t.config)),t.pot&&S.push(`--pot`,Nn(n,t.pot)),t.offline&&S.push(`--offline`),await dispatchSite({invokedAs:`gjsify webext listing`,argv:S,runtime:t.runtime,globals:t.globals,needsClient:!1})}}}),JJ,YJ=__esmMin(()=>{qJ(),JJ={command:`webext <subcommand>`,description:`Browser extensions: build, zip and develop one WebExtension for Chrome, Edge, Firefox, Opera and Safari.`,builder:t=>t.command(UJ.command,UJ.description,UJ.builder,UJ.handler).command(WJ.command,WJ.description,WJ.builder,WJ.handler).command(GJ.command,GJ.description,GJ.builder,GJ.handler).command(KJ.command,KJ.description,KJ.builder,KJ.handler).demandCommand(1).strict()}});function blueprintsUnder(t,n){let S;try{S=statSync(t)}catch{return n}if(!S.isDirectory())return t.endsWith(`.blp`)&&n.push(t),n;for(let S of readdirSync(t).sort())XJ.has(S)||S.startsWith(`.`)||blueprintsUnder(In(t,S),n);return n}var XJ,ZJ,formatFor,QJ,$J=__esmMin(()=>{_e(),ef(),qn(),sA(),mA(),XJ=new Set([`node_modules`,`dist`,`lib`,`.git`]),ZJ=new Map,formatFor=t=>{let n=ZJ.get(t);if(n!==void 0)return n;let S=emitFormatForTree(t);return ZJ.set(t,S),S},QJ={command:`types [paths..]`,description:"Generate the `<name>.d.blp.ts` type sidecar for each .blp (ADR 0088), so `import { build }` / `import { GTypeName }` type-check before anything is built. Defaults to the current directory.",builder:t=>t.positional(`paths`,{description:`Files or directories to scan for .blp (default: the current directory)`,type:`string`,array:!0,normalize:!0,default:[]}).option(`check`,{description:`Write nothing; exit non-zero when a sidecar is missing or stale`,type:`boolean`,default:!1}).option(`verbose`,{description:`Print every file considered, not only the ones that changed`,type:`boolean`,default:!1}),handler:async t=>{let n=t.paths??[],S=(n.length>0?n:[`.`]).map(t=>Fn(t)?t:Nn(process.cwd(),t)),C=[];for(let t of S)blueprintsUnder(t,C);let N=[],F=0;for(let n of C){let S=sidecarPathFor(n),C=emitTypedSidecar(parseBlueprint(readFileSync(n,`utf8`),n),Bn(n),formatFor(zn(n))),I;try{I=readFileSync(S,`utf8`)}catch{I=void 0}if(I===C){t.verbose&&ge.log(`[gjsify blueprint types] current: ${S}`);continue}if(t.check){N.push(S);continue}writeFileSync(S,C,`utf8`),F+=1,ge.log(`[gjsify blueprint types] wrote ${S}`)}if(t.check){if(N.length===0){ge.log(`[gjsify blueprint types] ${C.length} .blp checked, every sidecar current.`);return}for(let t of N)ge.error(`[gjsify blueprint types] missing or stale: ${t}`);ge.error(`[gjsify blueprint types] run without --check to regenerate.`),process.exitCode=1;return}ge.log(`[gjsify blueprint types] ${C.length} .blp scanned, ${F} sidecar(s) written, ${C.length-F} already current.`)}}}),eY,tY=__esmMin(()=>{$J(),eY={command:`blueprint <subcommand>`,description:`Blueprint (.blp) tooling: generate the TypeScript type sidecars a .blp exports (ADR 0088).`,builder:t=>t.command(QJ.command,QJ.description,QJ.builder,QJ.handler).demandCommand(1).strict()}}),nY=__esmMin(()=>{aR(),sR(),uR(),mR(),jR(),PR(),Uz(),Gz(),qz(),rB(),gB(),FB(),RB(),HB(),GB(),VV(),aG(),fB(),dG(),mG(),bG(),tB(),TG(),oK(),dK(),yK(),jK(),NK(),IK(),RK(),WK(),XK(),iq(),sq(),lq(),dq(),bq(),Sq(),wq(),jq(),Iq(),Rq(),$q(),rJ(),oJ(),lJ(),dJ(),pJ(),hJ(),YJ(),tY()}),rY=__exportAll$5({runCli:()=>runCli});function runtimeLabel(){let t=gjsSystemVersion();if(t!==void 0){let n=Number(t);return`GJS ${Math.floor(n/1e4)}.${Math.floor(n%1e4/100)}.${n%100} (SpiderMonkey)`}return isBun()?`Bun ${globalThis.Bun?.version??process.versions.bun??``}`.trim():isDeno()?`Deno ${globalThis.Deno?.version?.deno??``}`.trim():isNode()?`Node.js ${process.version}`:`unknown runtime`}async function runCli(t){ensureGjsifyShimOnPath();let n=ih(t);await n.scriptName(bh).version(cliVersion()).strict().fail((t,S)=>{let C=classifyCliFailure(t,S);if(C.kind===`usage`)throw n.showHelp(`error`),Error(C.message,{cause:S})}).wrap(n.terminalWidth()).command(PB.command,PB.description,PB.builder,PB.handler).command(lG.command,lG.description,lG.builder,lG.handler).command(fG.command,fG.description,fG.builder,fG.handler).command(pG.command,pG.description,pG.builder,pG.handler).command(iR.command,iR.description,iR.builder,iR.handler).command(oR.command,oR.description,oR.builder,oR.handler).command(lR.command,lR.description,lR.builder,lR.handler).command(pR.command,pR.description,pR.builder,pR.handler).command(AR.command,AR.description,AR.builder,AR.handler).command(NR.command,NR.description,NR.builder,NR.handler).command(Hz.command,Hz.description,Hz.builder,Hz.handler).command(dB.command,dB.description,dB.builder,dB.handler).command(Wz.command,Wz.description,Wz.builder,Wz.handler).command(Kz.command,Kz.description,Kz.builder,Kz.handler).command(nB.command,nB.description,nB.builder,nB.handler).command(hB.command,hB.description,hB.builder,hB.handler).command(LB.command,LB.description,LB.builder,LB.handler).command(VB.command,VB.description,VB.builder,VB.handler).command(WB.command,WB.description,WB.builder,WB.handler).command(BV.command,BV.description,BV.builder,BV.handler).command(rG.command,rG.description,rG.builder,rG.handler).command(yG.command,yG.description,yG.builder,yG.handler).command(eB.command,eB.description,eB.builder,eB.handler).command(SG.command,SG.description,SG.builder,SG.handler).command(aK.command,aK.description,aK.builder,aK.handler).command(MK.command,MK.description,MK.builder,MK.handler).command(uK.command,uK.description,uK.builder,uK.handler).command(vK.command,vK.description,vK.builder,vK.handler).command(AK.command,AK.description,AK.builder,AK.handler).command(FK.command,FK.description,FK.builder,FK.handler).command(LK.command,LK.description,LK.builder,LK.handler).command(UK.command,UK.description,UK.builder,UK.handler).command(YK.command,YK.description,YK.builder,YK.handler).command(nq.command,nq.description,nq.builder,nq.handler).command(oq.command,oq.description,oq.builder,oq.handler).command(uq.command,uq.description,uq.builder,uq.handler).command(cq.command,cq.description,cq.builder,cq.handler).command(Dq.command,Dq.description,Dq.builder,Dq.handler).command(yq.command,yq.description,yq.builder,yq.handler).command(xq.command,xq.description,xq.builder,xq.handler).command(Cq.command,Cq.description,Cq.builder,Cq.handler).command(Fq.command,Fq.description,Fq.builder,Fq.handler).command(Lq.command,Lq.description,Lq.builder,Lq.handler).command(Zq.command,Zq.description,Zq.builder,Zq.handler).command(nJ.command,nJ.description,nJ.builder,nJ.handler).command(aJ.command,aJ.description,aJ.builder,aJ.handler).command(cJ.command,cJ.description,cJ.builder,cJ.handler).command(uJ.command,uJ.description,uJ.builder,uJ.handler).command(fJ.command,fJ.description,fJ.builder,fJ.handler).command(mJ.command,mJ.description,mJ.builder,mJ.handler).command(JJ.command,JJ.description,JJ.builder,JJ.handler).command(eY.command,eY.description,eY.builder,eY.handler).demandCommand(1).epilogue(`Running on ${runtimeLabel()}`).help().parseAsync()}var iY=__esmMin(()=>{ah(),oh(),yh(),nY(),xh(),D_(),zz()});iY(),D_(),Vz();function pendingFailureCode(t,n){if(n||t==null)return null;let S=Number(t);return Number.isFinite(S)&&S!==0?S:null}function exitOnReportedFailure(){let t=pendingFailureCode(process.exitCode,isDaemonCommand());t!==null&&gjsExit(t)}_e(),D_();try{await runCli(hideBin(process.argv))}catch(t){let n=typeof t==`object`&&t&&typeof t.code==`string`?t.code:``,S=t instanceof Error?t.message:String(t);ge.error(n&&!S.includes(n)?`${n}: ${S}`:S),process.env.GJSIFY_DEBUG&&t instanceof Error&&t.stack&&ge.error(t.stack),process.exitCode=1,gjsExit(1)}exitOnReportedFailure();const aY=globalThis.process,oY=Number(aY?.exitCode);Number.isInteger(oY)&&oY!==0&&aY.exit(oY);
1846
+ `}var hJ,gJ=__esmMin(()=>{_e(),ef(),qn(),hJ={command:`browse [url]`,description:`Launch the Adwaita web browser, optionally pointed at a URL.`,builder:t=>t.positional(`url`,{description:`Initial URL to load (default: page:welcome)`,type:`string`}).option(`app-id`,{description:`GApplication id (default: gjsify.browse.applicationId or derived from the package name)`,type:`string`}).option(`title`,{description:`Window title`,type:`string`}).option(`globals`,{description:"Value for `gjsify build --globals` (default: auto,dom — WebKit/iframe need DOM globals)",type:`string`}).option(`out`,{description:`Output bundle path (default: node_modules/.cache/gjsify-browse)`,type:`string`}).option(`devtools`,{description:`Enable the MCP devtools control plane (sets GJSIFY_DEVTOOLS=1)`,type:`boolean`,default:!1}).option(`inspector-port`,{description:`Enable WebKit's remote inspector protocol on this port + the Cdp* methods (implies --devtools)`,type:`number`}).option(`screenshot`,{description:`One-shot: load the URL, capture a WebKit screenshot to this path, and exit (CI / quick captures).`,type:`string`}).option(`build-only`,{description:`Build the bundle but do not launch it`,type:`boolean`,default:!1}),handler:async t=>{let n=process.cwd(),S=readPackage(n),C=S.gjsify?.browse??{},N=t.appId??C.applicationId??deriveBrowserAppId(S.name),F=t.title??C.title,I=t.globals??C.globals??`auto,dom`,H=t.url,W=t.inspectorPort??C.inspectorPort,q=t.devtools||W!==void 0,Y=In(n,`node_modules`,`.cache`,`gjsify-browse`);mkdirSync(Y,{recursive:!0});let X=In(Y,`entry.ts`),Z=t.out?Nn(n,t.out):In(Y,`browse.gjs.mjs`);writeFileSync(X,generateEntry(N,H,F,W,t.screenshot?Nn(n,t.screenshot):void 0)),ge.log(`[gjsify browse] app=${N}${H?` url=${H}`:``}${q?` devtools=1`:``}${W===void 0?``:` inspector-port=${W}`}`);let{runCli:te}=await Promise.resolve().then(()=>(aY(),iY));if(await te([`build`,X,`--app`,`gjs`,`--globals`,I,`--outfile`,Z]),t.buildOnly){ge.log(`[gjsify browse] built ${Z}`);return}q&&(process.env.GJSIFY_DEVTOOLS=`1`),W!==void 0&&(process.env.WEBKIT_INSPECTOR_HTTP_SERVER=`127.0.0.1:${W}`);let{runGjsBundle:ne}=await Promise.resolve().then(()=>(DR(),ER));await ne(Z,[],{completion:`exit`,exitOnSuccess:!0})}}});function webextIconPaths(t,n,S){let C=t.sources.get(n);if(C===void 0)throw Error(`gjsify webext: the manifest asks for icon "${n}", and \`gjsify.webext.icons.sources\` declares ${[...t.sources.keys()].map(t=>`"${t}"`).join(`, `)||`none`}.`);let N=t.svgTargets.has(S.id),F={};for(let S of t.sizes)F[String(S)]=N?`icons/${Bn(C.get(S))}`:`icons/${n}-${S}.png`;return F}function svgIconFiles(t){let n=new Map;for(let[S,C]of t.sources)for(let t of C.values()){let C=`icons/${Bn(t)}`,N=n.get(C);if(N!==void 0&&N!==t)throw Error(`gjsify webext: icon "${S}" uses ${t}, and ${N} has the same file name; an SVG target would receive only one of them as `+C+`. Rename one.`);n.set(C,t)}return n}async function renderWebextIcons(t,n,S=rasterizeSvg){let C=n.some(n=>!t.svgTargets.has(n.id)),N=n.some(n=>t.svgTargets.has(n.id)),F=new Map;if(C){let n=new Map;for(let[S,C]of t.sources)for(let[t,N]of C)n.set(N,[...n.get(N)??[],{size:t,name:S}]);for(let[t,C]of n){let n=await S({svg:t,sizes:[...new Set(C.map(t=>t.size))],command:`gjsify webext`});for(let{size:t,name:S}of C)F.set(`icons/${S}-${t}.png`,n.get(t))}}return{png:F,svg:N?svgIconFiles(t):new Map}}function writeWebextIcons(t,n,S,C){if(mkdirSync(In(C,`icons`),{recursive:!0}),n.svgTargets.has(S.id))for(let[n,S]of t.svg)copyFileSync(S,In(C,n));else for(let[n,S]of t.png)writeFileSync(In(C,n),S)}var _J=__esmMin(()=>{ef(),qn(),uH()});function isRecord$1(t){return typeof t==`object`&&!!t&&!Array.isArray(t)}function mergeManifest(t,n){let S={...t};for(let[t,C]of Object.entries(n))C===null?delete S[t]:isRecord$1(C)&&isRecord$1(S[t])?S[t]=mergeManifest(S[t],C):S[t]=C;return S}function applyTargetOverrides(t,n){let{$targets:S,...C}=t;if(S===void 0)return C;if(!isRecord$1(S))throw Error("gjsify webext: the manifest's `$targets` must be an object.");let N=S[n];if(N===void 0)return C;if(!isRecord$1(N))throw Error(`gjsify webext: \`$targets["${n}"]\` in the manifest must be an object.`);return mergeManifest(C,N)}async function composeManifest(t,n){let S=typeof t==`function`?await t(n):applyTargetOverrides(t,n.target);if(!isRecord$1(S))throw Error(`gjsify webext: the manifest for ${n.target} is not an object (got ${typeof S}).`);if(S.version!==void 0)return S;let C={};for(let[t,N]of Object.entries(S))C[t]=N,t===`name`&&(C.version=n.version);return C.version===void 0&&(C.version=n.version),C}async function loadManifestTemplate(t){if(/\.json$/i.test(t))try{return JSON.parse(readFileSync(t,`utf8`))}catch(n){throw Error(`gjsify webext: ${t} is not valid JSON: ${n.message}`)}let n,cleanup=null;if(isGjs()){let{BuildAction:S}=await Promise.resolve().then(()=>(eR(),ZL)),C=await S.bundleFileForGjsCached(t,{cacheSubdir:`webext`,label:Bn(t),cache:!1,define:{"import.meta.url":JSON.stringify(pathToFileURL(t).href)}}),N=In(zn(C),`manifest-${process.pid}-${++vJ}.mjs`);copyFileSync(C,N),n=pathToFileURL(N).href,cleanup=()=>rmSync(N,{force:!0})}else n=`${pathToFileURL(t).href}?t=${statSync(t).mtimeMs}-${++vJ}`;try{let S=(await import(n)).default;if(typeof S!=`function`&&!isRecord$1(S))throw Error(`gjsify webext: ${t} has no default export. Export the manifest object, or a function \`(ctx) => manifest\` that receives the target.`);return S}finally{cleanup?.()}}function addPath(t,n){typeof n!=`string`||n===``||/^[a-z][a-z0-9+.-]*:/i.test(n)||n.includes(`*`)||t.add(n.replace(/^\//,``).replace(/[?#].*$/,``))}function addIconValue(t,n){if(typeof n==`string`)addPath(t,n);else if(isRecord$1(n))for(let S of Object.values(n))addPath(t,S)}function manifestFileReferences(t){let n=new Set,S=t.background;if(isRecord$1(S)&&(addPath(n,S.service_worker),addPath(n,S.page),Array.isArray(S.scripts)))for(let t of S.scripts)addPath(n,t);if(Array.isArray(t.content_scripts)){for(let S of t.content_scripts)if(isRecord$1(S)){for(let t of[`js`,`css`])if(Array.isArray(S[t]))for(let C of S[t])addPath(n,C)}}for(let S of[`action`,`browser_action`,`page_action`,`sidebar_action`]){let C=t[S];isRecord$1(C)&&(addPath(n,C.default_popup),addPath(n,C.default_panel),addIconValue(n,C.default_icon))}if(isRecord$1(t.options_ui)&&addPath(n,t.options_ui.page),addPath(n,t.options_page),addPath(n,t.devtools_page),isRecord$1(t.side_panel)&&addPath(n,t.side_panel.default_path),addIconValue(n,t.icons),isRecord$1(t.chrome_url_overrides))for(let S of Object.values(t.chrome_url_overrides))addPath(n,S);if(Array.isArray(t.web_accessible_resources)){for(let S of t.web_accessible_resources)if(typeof S==`string`)addPath(n,S);else if(isRecord$1(S)&&Array.isArray(S.resources))for(let t of S.resources)addPath(n,t)}return[...n].sort()}function checkManifest(t,n,S){let C=[];t.manifest_version!==n.manifestVersion&&C.push(`manifest_version is ${JSON.stringify(t.manifest_version)}, and target ${n.id} is Manifest V${n.manifestVersion}. gjsify does not convert keys between versions — branch on \`ctx.manifestVersion\` in the manifest.`);for(let N of manifestFileReferences(t))existsSync(In(S,N))||C.push(`the manifest names "${N}", which the build did not write into ${n.id}/.`);let N=existsSync(In(S,`_locales`)),F=t.default_locale;return N&&typeof F!=`string`?C.push(`_locales/ exists but the manifest sets no default_locale; the browser refuses to load it.`):!N&&F!==void 0?C.push(`the manifest sets default_locale "${String(F)}" but there is no _locales/ directory.`):typeof F==`string`&&!existsSync(In(S,`_locales`,F,`messages.json`))&&C.push(`default_locale is "${F}" but _locales/${F}/messages.json does not exist.`),C}var vJ,yJ=__esmMin(()=>{ef(),qn(),ir(),D_(),__name$1(isRecord$1,`isRecord`),vJ=0});function planPage(t,n,S){let C=zn(n),N=[],F=[],local=t=>{if(EJ.test(t)||t.startsWith(`/`))return null;let n=t.replace(/[?#].*$/,``);return Fn(n)?n:Nn(C,n)},I=S.replace(bJ,n=>{let S=SJ.exec(n);if(!S)return n;let C=local(S[2]);if(C===null||!DJ.test(C))return n;let F=N.length===0?`${t}.js`:`${t}-${N.length+1}.js`;return N.push({entry:C,format:wJ.test(n)?`esm`:`iife`,output:F}),n.replace(SJ,(t,n)=>`src=${n}${F}${n}`)});return I=I.replace(xJ,t=>{if(!TJ.test(t))return t;let n=CJ.exec(t);if(!n)return t;let S=local(n[2]);if(S===null)return t;let C=Bn(S);return F.push({source:S,output:C}),t.replace(CJ,(t,n)=>`href=${n}${C}${n}`)}),{html:I,scripts:N,stylesheets:F}}var bJ,xJ,SJ,CJ,wJ,TJ,EJ,DJ,OJ=__esmMin(()=>{qn(),bJ=/<script\b[^>]*\bsrc\s*=\s*["'][^"']+["'][^>]*>/gi,xJ=/<link\b[^>]*>/gi,SJ=/\bsrc\s*=\s*(["'])([^"']+)\1/i,CJ=/\bhref\s*=\s*(["'])([^"']+)\1/i,wJ=/\btype\s*=\s*["']module["']/i,TJ=/\brel\s*=\s*["'][^"']*\bstylesheet\b[^"']*["']/i,EJ=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,DJ=/\.(?:[cm]?[jt]sx?)$/i});function zipTimestamp(t=process.env){let n=Number(t.SOURCE_DATE_EPOCH);return Number.isFinite(n)&&n>=kJ?n:kJ}function zipEntriesOf(t){let n=[],walk=S=>{for(let C of readdirSync(S,{withFileTypes:!0})){let N=In(S,C.name);C.isDirectory()?walk(N):n.push({path:Ln(t,N).split(/[\\/]/).join(`/`),mode:420,data:readFileSync(N)})}};return walk(t),n}async function buildWebext(t){let{config:n,targets:S,outDir:C,define:N}=t,F=t.log??(t=>ge.log(t)),I=t.mode===`production`&&n.minify,H=In(C,`.stage`);rmSync(H,{recursive:!0,force:!0}),mkdirSync(H,{recursive:!0});try{for(let[S,C]of n.scripts)await t.bundle({entry:C,outfile:In(H,`${S}.js`),format:`iife`,define:N,minify:I});let W=new Map;for(let[S,C]of n.pages){let n=planPage(S,C,readFileSync(C,`utf8`));for(let S of n.scripts)await t.bundle({entry:S.entry,outfile:In(H,S.output),format:S.format,define:N,minify:I});for(let t of n.stylesheets){let n=W.get(t.output);if(n!==void 0&&n!==t.source)throw Error(`gjsify webext: pages link ${n} and ${t.source}, which would both be written as ${t.output}. Rename one.`);W.set(t.output,t.source),cpSync(t.source,In(H,t.output))}writeFileSync(In(H,`${S}.html`),n.html)}let q=n.icons,Y=q?await renderWebextIcons(q,S,t.rasterize):null,X=await loadManifestTemplate(n.manifest),Z={folders:new Map,zips:new Map};for(let I of S){let S=In(C,I.id);t.inPlace||rmSync(S,{recursive:!0,force:!0}),mkdirSync(S,{recursive:!0}),n.publicDir&&cpSync(n.publicDir,S,{recursive:!0}),n.localesDir&&cpSync(n.localesDir,In(S,`_locales`),{recursive:!0}),cpSync(H,S,{recursive:!0}),q&&Y&&writeWebextIcons(Y,q,I,S);let W=await composeManifest(X,{target:I.id,browser:I.browser,manifestVersion:I.manifestVersion,mode:t.mode,version:n.version,define:N,icons:t=>{if(!q)throw Error(`gjsify webext: the manifest asks for icon "${t}" and \`gjsify.webext.icons\` is not declared.`);return webextIconPaths(q,t,I)}});writeFileSync(In(S,`manifest.json`),`${JSON.stringify(W,null,2)}\n`);let te=checkManifest(W,I,S);if(te.length>0)throw Error(`gjsify webext: ${I.id} would not load:\n - ${te.join(`
1847
+ - `)}`);if(Z.folders.set(I.id,S),F(`built ${Ln(process.cwd(),S)||S}`),t.zip){let t=In(C,`${n.name}-${n.version}-${I.id}.zip`);writeFileSync(t,buildZip(zipEntriesOf(S),zipTimestamp())),Z.zips.set(I.id,t),F(`zipped ${Ln(process.cwd(),t)||t} (${Math.round(statSync(t).size/1024)} KiB)`)}}return Z}finally{rmSync(H,{recursive:!0,force:!0})}}var kJ,AJ=__esmMin(()=>{_e(),ef(),qn(),DW(),_J(),yJ(),OJ(),kJ=315532800});function parseWebextTarget(t){let n=/^([a-z]+)-mv([23])$/.exec(t),S=n?.[1];if(!n||S===void 0||!jJ.includes(S))throw Error(`gjsify webext: unknown target "${t}". A target is <browser>-mv<2|3> with browser one of ${jJ.join(`, `)} (e.g. chrome-mv3, firefox-mv2).`);let C=n[2]===`2`?2:3,N=C===2?NJ.get(S):void 0;if(N!==void 0)throw Error(`gjsify webext: target "${t}" does not exist any more: ${N}. Use ${S}-mv3.`);return{id:t,browser:S,manifestVersion:C}}function webExtRunTarget(t){return t.browser===`firefox`?`firefox-desktop`:t.browser===`chrome`||t.browser===`edge`||t.browser===`opera`?`chromium`:null}var jJ,MJ,NJ,PJ=__esmMin(()=>{jJ=[`chrome`,`edge`,`firefox`,`opera`,`safari`],MJ=[`chrome-mv3`,`firefox-mv3`],NJ=new Map([[`chrome`,`chrome has removed Manifest V2`],[`edge`,`edge has removed Manifest V2`],[`opera`,`opera's extension store accepts Manifest V3 only`]])});function isRecord(t){return typeof t==`object`&&!!t&&!Array.isArray(t)}function defaultArtifactName(t){let n=(t??`extension`).replace(/^@[^/]+\//,``);return n===``?`extension`:n}function iconSourceForSize(t,n){if(typeof t==`string`)return t;let S=Object.keys(t).filter(t=>/^\d+$/.test(t)).map(Number).sort((t,n)=>t-n).find(t=>n<=t);return S===void 0?t.default:t[String(S)]}function resolveWebextConfig(t,n,S=defaultExists){let C=[],N=t.gjsify?.webext;if(N===void 0)throw Error("gjsify webext: this package declares no `gjsify.webext` block in package.json. Add one naming at least the manifest and one script or page — see `gjsify webext build --help`.");if(!isRecord(N))throw Error("gjsify webext: `gjsify.webext` must be an object.");let F=N,abs=t=>Fn(t)?t:Nn(n,t),need=(t,n,N)=>{let F=abs(n);return S(F,N)||C.push(`${t} "${n}" is not a ${N===`dir`?`directory`:`file`}.`),F},I=[],H=F.targets??[...MJ];if(!Array.isArray(H)||H.length===0)C.push("`targets` must be a non-empty array of target names.");else for(let t of H)try{I.some(n=>n.id===t)?C.push(`target "${t}" is listed twice.`):I.push(parseWebextTarget(String(t)))}catch(t){C.push(t.message.replace(/^gjsify webext: /,``))}let W=``;if(F.manifest!==void 0)W=need("`manifest`",F.manifest,`file`);else{let t=IJ.find(t=>S(In(n,t),`file`));t===void 0?C.push(`no \`manifest\` declared and none of ${IJ.join(`, `)} exists.`):W=In(n,t)}let q=new Map,claim=(t,n)=>{let S=q.get(t);S===void 0?q.set(t,n):C.push(`${n} and ${S} both write ${t}.`)},readEntries=t=>{let n=new Map,S=F[t];if(S===void 0)return n;if(!isRecord(S))return C.push(`\`${t}\` must map an output name to a source file.`),n;for(let[N,F]of Object.entries(S)){if(!LJ.test(N)){C.push(`\`${t}.${N}\`: an output name is a plain file name (letters, digits, . _ -).`);continue}if(typeof F!=`string`){C.push(`\`${t}.${N}\` must be a path.`);continue}n.set(N,need(`\`${t}.${N}\``,F,`file`)),t===`scripts`?claim(`${N}.js`,`\`scripts.${N}\``):claim(`${N}.html`,`\`pages.${N}\``)}return n},Y=readEntries(`scripts`),X=readEntries(`pages`);Y.size===0&&X.size===0&&C.push("declare at least one entry under `scripts` or `pages`; there is nothing to build.");for(let t of X.keys())Y.has(t)&&C.push(`\`scripts.${t}\` and the script of \`pages.${t}\` both write ${t}.js.`);let Z=null;if(F.icons!==void 0)if(!isRecord(F.icons)||!isRecord(F.icons.sources))C.push("`icons` must be an object with a `sources` map (icon name → SVG).");else{let t=F.icons.sizes??FJ;(!Array.isArray(t)||t.length===0||t.some(t=>!Number.isInteger(t)||t<=0))&&C.push("`icons.sizes` must be a non-empty list of positive integers.");let n=new Set(F.icons.svg??[]);for(let t of n)I.some(n=>n.id===t)||C.push(`\`icons.svg\` names "${t}", which is not one of this package's targets.`);let N=new Map;for(let[n,I]of Object.entries(F.icons.sources)){if(!LJ.test(n)){C.push(`\`icons.sources.${n}\`: an icon name is a plain file name.`);continue}if(typeof I!=`string`&&!isRecord(I)){C.push(`\`icons.sources.${n}\` must be an SVG path or a map of size ceilings to SVGs.`);continue}let F=new Map;for(let S of t){let t=iconSourceForSize(I,S);if(t===void 0){C.push(`\`icons.sources.${n}\` has no SVG for ${S} px — add a "default".`);continue}/\.svg$/i.test(t)||C.push(`\`icons.sources.${n}\`: "${t}" is not an .svg file.`),F.set(S,abs(t))}for(let t of new Set(F.values()))S(t,`file`)||C.push(`\`icons.sources.${n}\`: "${t}" does not exist.`);N.set(n,F)}Z={sizes:t,sources:N,svgTargets:n}}let optionalDir=(t,C)=>{let N=F[t];if(N!==void 0)return need(`\`${t}\``,N,`dir`);let I=In(n,C);return S(I,`dir`)?I:null},te=optionalDir(`public`,`public`),ne=optionalDir(`locales`,`_locales`),re=F.define??{};(!isRecord(re)||Object.values(re).some(t=>typeof t!=`string`))&&C.push("`define` must map identifiers to JS expressions given as strings.");let ie=F.watch??[];if((!Array.isArray(ie)||ie.some(t=>typeof t!=`string`))&&C.push("`watch` must be a list of directories."),C.length>0)throw Error(`gjsify webext: \`gjsify.webext\` in ${In(n,`package.json`)}:\n - ${C.join(`
1848
+ - `)}`);return{root:n,name:F.name??defaultArtifactName(t.name),version:t.version??`0.0.0`,targets:I,manifest:W,scripts:Y,pages:X,icons:Z,publicDir:te,localesDir:ne,outDir:abs(F.outDir??`.output`),define:re,watch:ie.map(abs),minify:F.minify??!0}}function defaultExists(t,n){if(!existsSync(t))return!1;let S=statSync(t);return n===`dir`?S.isDirectory():S.isFile()}function selectTargets(t,n){return n===void 0||n.length===0?t.targets:n.map(n=>{let S=t.targets.find(t=>t.id===n);if(S)return S;throw parseWebextTarget(n),Error(`gjsify webext: target "${n}" is not in \`gjsify.webext.targets\` (${t.targets.map(t=>t.id).join(`, `)}).`)})}var FJ,IJ,LJ,RJ=__esmMin(()=>{ef(),qn(),PJ(),FJ=[16,32,48,128],IJ=[`manifest.ts`,`manifest.mts`,`manifest.js`,`manifest.mjs`,`manifest.json`],LJ=/^[A-Za-z0-9][A-Za-z0-9._-]*$/});function webExtRunArgs(t){let n=webExtRunTarget(t.target);if(n===null)throw Error(`gjsify webext dev: web-ext cannot launch ${t.target.browser}. Build with \`gjsify webext build --target ${t.target.id}\` and load the folder by hand, or pass \`--no-launch\`.`);let S=[`run`,`--source-dir`,t.sourceDir,`--target`,n,`--no-input`,`--profile-create-if-missing`];return n===`firefox-desktop`?(S.push(`--firefox-profile`,t.profile,`--keep-profile-changes`),t.browserBinary&&S.push(`--firefox`,t.browserBinary),t.headless&&S.push(`--arg=-headless`)):(S.push(`--chromium-profile`,t.profile),t.browserBinary&&S.push(`--chromium-binary`,t.browserBinary),t.headless&&S.push(`--arg=--headless=new`)),S}function defaultDevProfile(t,n,S=process.env){return In(S.XDG_CACHE_HOME||In(homedir(),`.cache`),`gjsify`,`webext`,t,n.id)}function resolveWebExt(t,n=process.platform,S=process.env){let C=n===`win32`?`web-ext.cmd`:`web-ext`;for(let n=t;;n=zn(n)){let t=In(n,`node_modules`,`.bin`);if(existsSync(In(t,C)))return{cmd:`web-ext`,env:{...S,PATH:[t,S.PATH].filter(Boolean).join(Gn)}};if(zn(n)===n)break}return isOnPath(`web-ext`)?{cmd:`web-ext`,env:S}:null}var zJ,BJ=__esmMin(()=>{ef(),$g(),qn(),ZI(),PJ(),zJ="gjsify webext dev: `web-ext` is not installed. Add it to the project (`gjsify install --save-dev web-ext`) or install it globally, or pass `--no-launch` to rebuild without a browser."});function loadConfig(t){let n=In(t,`package.json`);if(!existsSync(n))throw Error(`gjsify webext: no package.json in ${t}.`);return resolveWebextConfig(JSON.parse(readFileSync(n,`utf8`)),t)}function effectiveDefines(t,n){let S={...t.define};for(let t of n){let n=t.indexOf(`=`);if(n<=0)throw Error(`gjsify webext: --define "${t}" is not KEY=VALUE.`);S[t.slice(0,n)]=t.slice(n+1)}return S}async function bundleInProcess(t){let{runCli:n}=await Promise.resolve().then(()=>(aY(),iY)),S=[`build`,t.entry,`--app`,`browser`,`--format`,t.format,`--outfile`,t.outfile];for(let[n,C]of Object.entries(t.define))S.push(`--define`,`${n}=${C}`);t.minify||S.push(`--no-minify`),await n(S)}async function runBuild(t,n){let S=process.cwd(),C=loadConfig(S),N=t.mode===`development`?`development`:`production`;await buildWebext({config:C,targets:selectTargets(C,t.target),outDir:t.outDir?Nn(S,t.outDir):C.outDir,mode:N,define:effectiveDefines(C,t.define),inPlace:!1,zip:n,bundle:bundleInProcess})}function devTarget(t,n){if(n&&n.length>1)throw Error(`gjsify webext dev: pass one --target.`);let[S]=selectTargets(t,n);return n&&n.length===1?S:t.targets.find(t=>t.browser===`firefox`)??S}function devWatchTargets(t,n){let skip=t=>t===`node_modules`||t.startsWith(`.`),S=[{path:t.root,recursive:!1}];for(let C of readdirSync(t.root,{withFileTypes:!0})){let N=In(t.root,C.name);!C.isDirectory()||skip(C.name)||N===n||n.startsWith(N+Wn)||S.push({path:N,recursive:!0})}for(let n of t.watch)S.push({path:n,recursive:!0});return S}var VJ,HJ,UJ,WJ,GJ,KJ,qJ,JJ=__esmMin(()=>{_e(),ef(),qn(),aJ(),AJ(),RJ(),BJ(),VJ={description:`Build only these targets (default: every target in gjsify.webext.targets).`,type:`string`,array:!0},HJ={description:`Output directory (default: gjsify.webext.outDir, else .output).`,type:`string`},UJ={description:`Compile-time constant for every bundle, KEY=VALUE (repeatable); wins over gjsify.webext.define.`,type:`string`,array:!0,default:[]},WJ={command:`build`,description:`Build one extension folder per target: bundles, pages, icons, locales and the manifest.`,builder:t=>t.option(`target`,VJ).option(`out-dir`,HJ).option(`define`,UJ).option(`mode`,{description:`Passed to the manifest as ctx.mode; development also skips minification.`,type:`string`,choices:[`production`,`development`],default:`production`}),handler:t=>runBuild(t,!1)},GJ={command:`zip`,description:`Production build, then one store-ready <name>-<version>-<target>.zip per target.`,builder:t=>t.option(`target`,VJ).option(`out-dir`,HJ).option(`define`,UJ),handler:t=>runBuild(t,!0)},KJ={command:`dev`,description:`Build one target in development mode, launch it in a browser via web-ext, and rebuild in place on change.`,builder:t=>t.option(`target`,{...VJ,description:`The target to run (default: the first Firefox target).`}).option(`out-dir`,{description:`Output directory (default: <outDir>-dev).`,type:`string`}).option(`define`,UJ).option(`launch`,{description:`Start a browser with the extension (--no-launch only rebuilds).`,type:`boolean`,default:!0}).option(`browser-binary`,{description:`Browser executable web-ext should start.`,type:`string`}).option(`profile`,{description:`Browser profile directory (default: $XDG_CACHE_HOME/gjsify/webext/<name>/<target>).`,type:`string`}).option(`headless`,{description:`Start the browser without a window.`,type:`boolean`,default:!1}).option(`debounce`,{description:`Quiet window in ms before a rebuild.`,type:`number`,default:200}),handler:async t=>{let n=process.cwd(),S=loadConfig(n),C=devTarget(S,t.target),N=t.outDir?Nn(n,t.outDir):`${S.outDir}-dev`,F=effectiveDefines(S,t.define),I=In(N,C.id),H=null;if(t.launch&&(H=resolveWebExt(n),H===null))throw Error(zJ);let W=null,stopBrowser=()=>{W?.kill()};process.on(`SIGINT`,stopBrowser),process.on(`SIGTERM`,stopBrowser);let launch=async()=>{if(H===null||W!==null)return;let N=t.profile?Nn(n,t.profile):defaultDevProfile(S.name,C);mkdirSync(zn(N),{recursive:!0});let F=webExtRunArgs({sourceDir:I,target:C,profile:N,browserBinary:t.browserBinary,headless:t.headless});ge.log(`[webext] launching ${C.id} with profile ${N}`);let{spawnSupervised:q}=await Promise.resolve().then(()=>(nJ(),tJ));W=await q(H.cmd,F,H.env),W.on(`exit`,t=>{ge.log(`[webext] browser closed (${t??0}) — stopping`),process.exit(0)})},{runWatchLoop:q}=await Promise.resolve().then(()=>(nJ(),tJ));await q({dir:n,dirLabel:`.`,label:`webext`,watch:devWatchTargets(S,N),ignore:t=>t===N||t.startsWith(N+Wn),build:async()=>{await buildWebext({config:S,targets:[C],outDir:N,mode:`development`,define:F,inPlace:!0,zip:!1,bundle:bundleInProcess}),await launch()},spawnChild:null,debounceMs:t.debounce})}},qJ={command:`listing`,description:`Derive the store listings (Chrome Web Store, Edge Add-ons, Firefox AMO) from the AppStream metainfo, the gettext catalogues and the screenshots: texts, permission justifications and exact-size images.`,builder:t=>t.option(`store`,{description:`Which store to write (default: all).`,type:`string`,choices:[`cws`,`edge`,`amo`,`all`],default:`all`}).option(`out`,{description:`Output directory, emptied first (default: dist/listing).`,type:`string`}).option(`check`,{description:`Validate against the store limits; write nothing.`,type:`boolean`,default:!1}).option(`metainfo`,{description:`AppStream metainfo (default: gjsify.webext.listing.metainfo, else gjsify.site.metainfo).`,type:`string`}).option(`config`,{description:`JSON file that overrides the gjsify.webext.listing block of package.json.`,type:`string`}).option(`pot`,{description:`Also write the config strings as a gettext template.`,type:`string`}).option(`root`,{description:`Project root (default: the working directory).`,type:`string`}).option(`offline`,{description:`Skip downloading screenshots hosted elsewhere.`,type:`boolean`,default:!1}).option(`runtime`,{description:`Runtime to run on: gjs | node | bun | deno (default: the host runtime).`,type:`string`,choices:[`gjs`,`node`,`bun`,`deno`]}).option(`globals`,{description:"Value for `gjsify build --globals` (default: auto).",type:`string`}),handler:async t=>{let n=process.cwd(),S=[`listing`,`--store`,t.store];t.root&&S.push(`--root`,Nn(n,t.root)),t.out&&S.push(`--out`,Nn(n,t.out)),t.check&&S.push(`--check`),t.metainfo&&S.push(`--metainfo`,t.metainfo),t.config&&S.push(`--config`,Nn(n,t.config)),t.pot&&S.push(`--pot`,Nn(n,t.pot)),t.offline&&S.push(`--offline`),await dispatchSite({invokedAs:`gjsify webext listing`,argv:S,runtime:t.runtime,globals:t.globals,needsClient:!1})}}}),YJ,XJ=__esmMin(()=>{JJ(),YJ={command:`webext <subcommand>`,description:`Browser extensions: build, zip and develop one WebExtension for Chrome, Edge, Firefox, Opera and Safari.`,builder:t=>t.command(WJ.command,WJ.description,WJ.builder,WJ.handler).command(GJ.command,GJ.description,GJ.builder,GJ.handler).command(KJ.command,KJ.description,KJ.builder,KJ.handler).command(qJ.command,qJ.description,qJ.builder,qJ.handler).demandCommand(1).strict()}});function blueprintsUnder(t,n){let S;try{S=statSync(t)}catch{return n}if(!S.isDirectory())return t.endsWith(`.blp`)&&n.push(t),n;for(let S of readdirSync(t).sort())ZJ.has(S)||S.startsWith(`.`)||blueprintsUnder(In(t,S),n);return n}var ZJ,QJ,formatFor,$J,eY=__esmMin(()=>{_e(),ef(),qn(),sA(),mA(),ZJ=new Set([`node_modules`,`dist`,`lib`,`.git`]),QJ=new Map,formatFor=t=>{let n=QJ.get(t);if(n!==void 0)return n;let S=emitFormatForTree(t);return QJ.set(t,S),S},$J={command:`types [paths..]`,description:"Generate the `<name>.d.blp.ts` type sidecar for each .blp (ADR 0088), so `import { build }` / `import { GTypeName }` type-check before anything is built. Defaults to the current directory.",builder:t=>t.positional(`paths`,{description:`Files or directories to scan for .blp (default: the current directory)`,type:`string`,array:!0,normalize:!0,default:[]}).option(`check`,{description:`Write nothing; exit non-zero when a sidecar is missing or stale`,type:`boolean`,default:!1}).option(`verbose`,{description:`Print every file considered, not only the ones that changed`,type:`boolean`,default:!1}),handler:async t=>{let n=t.paths??[],S=(n.length>0?n:[`.`]).map(t=>Fn(t)?t:Nn(process.cwd(),t)),C=[];for(let t of S)blueprintsUnder(t,C);let N=[],F=0;for(let n of C){let S=sidecarPathFor(n),C=emitTypedSidecar(parseBlueprint(readFileSync(n,`utf8`),n),Bn(n),formatFor(zn(n))),I;try{I=readFileSync(S,`utf8`)}catch{I=void 0}if(I===C){t.verbose&&ge.log(`[gjsify blueprint types] current: ${S}`);continue}if(t.check){N.push(S);continue}writeFileSync(S,C,`utf8`),F+=1,ge.log(`[gjsify blueprint types] wrote ${S}`)}if(t.check){if(N.length===0){ge.log(`[gjsify blueprint types] ${C.length} .blp checked, every sidecar current.`);return}for(let t of N)ge.error(`[gjsify blueprint types] missing or stale: ${t}`);ge.error(`[gjsify blueprint types] run without --check to regenerate.`),process.exitCode=1;return}ge.log(`[gjsify blueprint types] ${C.length} .blp scanned, ${F} sidecar(s) written, ${C.length-F} already current.`)}}}),tY,nY=__esmMin(()=>{eY(),tY={command:`blueprint <subcommand>`,description:`Blueprint (.blp) tooling: generate the TypeScript type sidecars a .blp exports (ADR 0088).`,builder:t=>t.command($J.command,$J.description,$J.builder,$J.handler).demandCommand(1).strict()}}),rY=__esmMin(()=>{aR(),sR(),uR(),mR(),jR(),PR(),Uz(),Gz(),qz(),rB(),gB(),FB(),RB(),HB(),GB(),HV(),oG(),fB(),fG(),hG(),xG(),tB(),EG(),sK(),fK(),bK(),MK(),PK(),LK(),zK(),GK(),ZK(),aq(),cq(),uq(),fq(),xq(),Cq(),Tq(),Mq(),Lq(),zq(),eJ(),iJ(),sJ(),uJ(),fJ(),mJ(),gJ(),XJ(),nY()}),iY=__exportAll$5({runCli:()=>runCli});function runtimeLabel(){let t=gjsSystemVersion();if(t!==void 0){let n=Number(t);return`GJS ${Math.floor(n/1e4)}.${Math.floor(n%1e4/100)}.${n%100} (SpiderMonkey)`}return isBun()?`Bun ${globalThis.Bun?.version??process.versions.bun??``}`.trim():isDeno()?`Deno ${globalThis.Deno?.version?.deno??``}`.trim():isNode()?`Node.js ${process.version}`:`unknown runtime`}async function runCli(t){ensureGjsifyShimOnPath();let n=ih(t);await n.scriptName(bh).version(cliVersion()).strict().fail((t,S)=>{let C=classifyCliFailure(t,S);if(C.kind===`usage`)throw n.showHelp(`error`),Error(C.message,{cause:S})}).wrap(n.terminalWidth()).command(PB.command,PB.description,PB.builder,PB.handler).command(uG.command,uG.description,uG.builder,uG.handler).command(pG.command,pG.description,pG.builder,pG.handler).command(mG.command,mG.description,mG.builder,mG.handler).command(iR.command,iR.description,iR.builder,iR.handler).command(oR.command,oR.description,oR.builder,oR.handler).command(lR.command,lR.description,lR.builder,lR.handler).command(pR.command,pR.description,pR.builder,pR.handler).command(AR.command,AR.description,AR.builder,AR.handler).command(NR.command,NR.description,NR.builder,NR.handler).command(Hz.command,Hz.description,Hz.builder,Hz.handler).command(dB.command,dB.description,dB.builder,dB.handler).command(Wz.command,Wz.description,Wz.builder,Wz.handler).command(Kz.command,Kz.description,Kz.builder,Kz.handler).command(nB.command,nB.description,nB.builder,nB.handler).command(hB.command,hB.description,hB.builder,hB.handler).command(LB.command,LB.description,LB.builder,LB.handler).command(VB.command,VB.description,VB.builder,VB.handler).command(WB.command,WB.description,WB.builder,WB.handler).command(VV.command,VV.description,VV.builder,VV.handler).command(iG.command,iG.description,iG.builder,iG.handler).command(bG.command,bG.description,bG.builder,bG.handler).command(eB.command,eB.description,eB.builder,eB.handler).command(CG.command,CG.description,CG.builder,CG.handler).command(oK.command,oK.description,oK.builder,oK.handler).command(NK.command,NK.description,NK.builder,NK.handler).command(dK.command,dK.description,dK.builder,dK.handler).command(yK.command,yK.description,yK.builder,yK.handler).command(jK.command,jK.description,jK.builder,jK.handler).command(IK.command,IK.description,IK.builder,IK.handler).command(RK.command,RK.description,RK.builder,RK.handler).command(WK.command,WK.description,WK.builder,WK.handler).command(XK.command,XK.description,XK.builder,XK.handler).command(rq.command,rq.description,rq.builder,rq.handler).command(sq.command,sq.description,sq.builder,sq.handler).command(dq.command,dq.description,dq.builder,dq.handler).command(lq.command,lq.description,lq.builder,lq.handler).command(Oq.command,Oq.description,Oq.builder,Oq.handler).command(bq.command,bq.description,bq.builder,bq.handler).command(Sq.command,Sq.description,Sq.builder,Sq.handler).command(wq.command,wq.description,wq.builder,wq.handler).command(Iq.command,Iq.description,Iq.builder,Iq.handler).command(Rq.command,Rq.description,Rq.builder,Rq.handler).command(Qq.command,Qq.description,Qq.builder,Qq.handler).command(rJ.command,rJ.description,rJ.builder,rJ.handler).command(oJ.command,oJ.description,oJ.builder,oJ.handler).command(lJ.command,lJ.description,lJ.builder,lJ.handler).command(dJ.command,dJ.description,dJ.builder,dJ.handler).command(pJ.command,pJ.description,pJ.builder,pJ.handler).command(hJ.command,hJ.description,hJ.builder,hJ.handler).command(YJ.command,YJ.description,YJ.builder,YJ.handler).command(tY.command,tY.description,tY.builder,tY.handler).demandCommand(1).epilogue(`Running on ${runtimeLabel()}`).help().parseAsync()}var aY=__esmMin(()=>{ah(),oh(),yh(),rY(),xh(),D_(),zz()});aY(),D_(),Vz();function pendingFailureCode(t,n){if(n||t==null)return null;let S=Number(t);return Number.isFinite(S)&&S!==0?S:null}function exitOnReportedFailure(){let t=pendingFailureCode(process.exitCode,isDaemonCommand());t!==null&&gjsExit(t)}_e(),D_();try{await runCli(hideBin(process.argv))}catch(t){let n=typeof t==`object`&&t&&typeof t.code==`string`?t.code:``,S=t instanceof Error?t.message:String(t);ge.error(n&&!S.includes(n)?`${n}: ${S}`:S),process.env.GJSIFY_DEBUG&&t instanceof Error&&t.stack&&ge.error(t.stack),process.exitCode=1,gjsExit(1)}exitOnReportedFailure();const oY=globalThis.process,sY=Number(oY?.exitCode);Number.isInteger(sY)&&sY!==0&&oY.exit(sY);