hugoblox 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +50 -50
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -1,28 +1,28 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from 'commander';
3
- import _ from 'node:fs/promises';
3
+ import $ from 'node:fs/promises';
4
4
  import E from 'node:path';
5
- import Ve from 'ora';
6
- import Ze from 'yaml';
5
+ import Ge from 'ora';
6
+ import rt from 'yaml';
7
7
  import { execa } from 'execa';
8
- import Le from 'node:os';
9
- import vt from 'node:dns/promises';
10
- import Ue from 'prompts';
11
- import ge, { randomUUID } from 'node:crypto';
8
+ import Ne from 'node:os';
9
+ import St from 'node:dns/promises';
10
+ import ze from 'prompts';
11
+ import ye, { randomUUID } from 'node:crypto';
12
12
  import { createRequire } from 'node:module';
13
13
  import { promisify } from 'node:util';
14
14
  import F from 'node:fs';
15
15
  import { fileURLToPath } from 'node:url';
16
- import N from 'semver';
17
- import ye from 'chalk';
16
+ import M from 'semver';
17
+ import ve from 'chalk';
18
18
  import { Buffer as Buffer$1 } from 'node:buffer';
19
19
 
20
- var M=class extends Error{constructor(e,t="HBX_ERROR",r){super(e),this.name="HbxError",this.code=t,this.details=r;}},u=class extends M{constructor(e,t){super(e,"HBX_INPUT_ERROR",t);}},Z=class extends M{constructor(e="Operation cancelled by user"){super(e,"HBX_ABORTED");}},we=class extends M{constructor(e,t){super(e,"HBX_CONFIG_ERROR",t);}};function ct(n){return !!(n&&typeof n=="object"&&"code"in n)}async function v(n){try{return await _.access(n),!0}catch{return false}}async function $(n){await _.mkdir(n,{recursive:true});}async function ve(n){if(!await v(n)){await $(n);return}if((await _.readdir(n)).length>0)throw new Error(`Directory ${n} is not empty`)}async function j(n,e){await $(E.dirname(n)),await _.writeFile(n,e);}var Ce="hbx",G="HBX_DEBUG",ee="HBX_LICENSE_TOKEN",mt="HBX_TELEMETRY_DISABLED",Oe=E.join(Le.homedir(),".hbx"),Pe=E.join(Oe,"config.json"),_n=E.join(Le.homedir(),".cache","hbx"),te=E.join(_n,"templates"),dt="HBX_UPDATE_CHECK_DISABLED",ne="https://api.github.com",ut=`${ne}/repos/HugoBlox/hugo-blox-builder/contents/templates`,pt="https://github.com/HugoBlox/hugo-blox-builder.git",ft="HBX_TEMPLATES_DIR",X="https://cli-api.hugoblox.com",gt=`${X}/api/usage-insights`,Se="hugoblox",ht=1e3*60*60*24,yt=1e3*60*60*12;var Fe=[{id:"academic-cv",name:"Academic CV",description:"Publish your academic CV and showcase your research.",repoPath:"templates/academic-cv",slug:"academic-cv",tags:["academic","cv"],source:"oss"},{id:"startup",name:"Startup",description:"Marketing site for SaaS and startups.",repoPath:"templates/startup",slug:"startup",tags:["business"],source:"oss"},{id:"folio",name:"Portfolio",description:"Minimal portfolio for creatives.",repoPath:"templates/folio",slug:"folio",tags:["portfolio"],source:"oss"}];var ke="hbx.blocks.json";async function D(n=process.cwd()){let e=n,{root:t}=E.parse(n);for(;;){if((await Promise.all([v(E.join(e,"config","_default")),v(E.join(e,"hugoblox.yaml"))])).some(Boolean))return {root:e,manifestPath:E.join(e,ke)};if(e===t)return;e=E.dirname(e);}}async function wt(n){let e=E.join(n,"hugoblox.yaml");if(await v(e))try{let t=await _.readFile(e,"utf8"),r=Ze.parse(t);if(!r)return;let o=r.template??{},i=r.build??{};return {templateId:o.id,templateName:o.name,requiredHugoVersion:i.hugo_version}}catch(t){throw new u("Failed to parse hugoblox.yaml",{error:t})}}async function bt(){try{let{stdout:n}=await execa("hugo",["version"]);return jn(n)}catch{return}}function jn(n){let e=n.match(/v(\d+\.\d+\.\d+)/i);return e?e[1]:n.match(/(\d+\.\d+\.\d+)/)?.[1]}var q=class extends Error{constructor(t,r){super(t);this.cause=r;this.name="NetworkError";}};async function oe(n,e={}){let{timeout:t=15e3,retries:r=3,backoff:o=500,...i}=e,s=0;for(;s<=r;){let a=new AbortController,c=setTimeout(()=>a.abort(),t);try{let l=await fetch(n,{...i,signal:a.signal});if(clearTimeout(c),l.status===429||l.status>=500&&l.status<600)throw new q(`Server error: ${l.status}`);return l}catch(l){clearTimeout(c),s++;let m=l.name==="AbortError";if(s>r)throw m?new q(`Request timed out after ${t}ms`,l):l instanceof q?l:new q("Network request failed",l);let w=o*2**(s-1);await new Promise(d=>setTimeout(d,w));}}throw new q("Unreachable")}async function xt(){try{return await vt.lookup("google.com"),!0}catch{try{return await vt.lookup("1.1.1.1"),!0}catch{return false}}}async function L(n,e={}){if(e.ci){if(typeof e.initial=="string")return e.initial;throw new u(`Option required in CI mode: ${n}`)}return (await Ue({type:"text",name:"value",message:n,initial:e.initial},{onCancel:()=>{throw new Z}})).value}async function fe(n,e,t={}){if(t.ci){if(typeof t.initial=="string")return t.initial;throw new u(`Option required in CI mode: ${n}`)}return (await Ue({type:"select",name:"value",message:n,choices:e,initial:0},{onCancel:()=>{throw new Z}})).value}async function R(n,e={}){if(e.ci){if(typeof e.initial=="boolean")return e.initial;throw new u(`Confirmation required in CI mode: ${n}`)}return (await Ue({type:"confirm",name:"value",message:n,initial:e.initial??true},{onCancel:()=>{throw new Z}})).value}function St(n){let e=n.match(/github\.com[/:]([\w-]+)\/([\w-]+?)(?:\.git)?$/i);return e?{owner:e[1],repo:e[2]}:null}function Dn(n){return St(n)!==null}async function Ln(n,e){let t=`https://api.github.com/repos/${n}/${e}/contents/hugoblox/themes`;try{let r=await oe(t,{headers:{"User-Agent":"hbx-cli",Accept:"application/vnd.github.v3+json"}});if(!r.ok)throw r.status===404?new u(`Repository does not contain a 'hugoblox/themes' directory. Please check the repository structure at https://github.com/${n}/${e}`):new u(`Failed to fetch themes from GitHub (status ${r.status})`);let i=(await r.json()).filter(s=>s.type==="file"&&s.name.toLowerCase().endsWith(".yaml"));if(i.length===0)throw new u(`No theme files found in hugoblox/themes directory at https://github.com/${n}/${e}`);return i.map(s=>({name:s.name,downloadUrl:s.download_url}))}catch(r){throw r instanceof u?r:new u(`Failed to access GitHub repository: ${r instanceof Error?r.message:String(r)}`)}}async function Bn(n,e){let t=await oe(n,{headers:{"User-Agent":"hbx-cli"}});if(!t.ok)throw new u(`Failed to download theme file (status ${t.status})`);let r=await t.text();await j(e,r);}async function Nn(n,e){let t=E.join(n,"config","_default","params.yaml");if(!await v(t))throw new u(`params.yaml not found at ${t}. Please ensure you're in a HugoBlox site.`);let r=await _.readFile(t,"utf8"),o=Ze.parse(r),i=typeof o=="object"&&o!==null?o:{};(typeof i.hugoblox!="object"||i.hugoblox===null)&&(i.hugoblox={});let s=i.hugoblox;(typeof s.theme!="object"||s.theme===null)&&(s.theme={}),s.theme.pack=e;let a=Ze.stringify(i);await _.writeFile(t,a,"utf8");}function U(n){return n.toLowerCase().replace(/\.yaml$/i,"")}function kt(n,e){n.command("theme").description("Add theme pack(s) from a GitHub repository").option("--repo <url>","GitHub repository URL containing themes").option("--theme <name>","Specific theme filename to download (without .yaml), or 'all' for all themes").option("--set-active","Set the downloaded theme as active in params.yaml").option("--no-set-active","Skip setting theme as active").option("--ci","Run in non-interactive mode").action(async(t,r)=>{let{logger:o,telemetry:i}=e,s=!!r.optsWithGlobals().json;try{let a=await D();if(!a)throw new u("Not in a HugoBlox site. Please run this command from within a HugoBlox site directory (must contain hugoblox.yaml)");let c=a.root,l=t.repo;if(!l){if(t.ci)throw new u("--repo is required when running with --ci");l=await L("Enter the GitHub repository URL containing themes (e.g., https://github.com/username/themes-repo):");}if(l=l.trim(),!Dn(l))throw new u("Invalid GitHub repository URL. Please provide a valid GitHub URL (e.g., https://github.com/owner/repo)");let m=St(l);if(!m)throw new u("Failed to parse GitHub URL");let{owner:g,repo:w}=m,d=g,f=Ve("Fetching available themes...").start(),h;try{h=await Ln(g,w),f.succeed(`Found ${h.length} theme(s)`);}catch(S){throw f.fail("Failed to fetch themes"),S}let p,b=t.theme;if(!b)if(t.ci)b="all";else {let S=[{title:"All themes",value:"all"},...h.map(T=>({title:U(T.name),value:T.name}))];b=await fe("Which theme(s) do you want to download?",S);}if(b.toLowerCase()==="all")p=h;else {let S=U(b),k=h.find(T=>U(T.name)===S);if(!k)throw new u(`Theme '${b}' not found. Available themes: ${h.map(T=>T.name).join(", ")}`);p=[k];}let P=E.join(c,"data","themes",d);await $(P);let x=Ve(`Downloading ${p.length} theme(s)...`).start();try{for(let S of p){let k=E.join(P,S.name);await Bn(S.downloadUrl,k);}x.succeed(`\u2705 Downloaded ${p.length} theme(s) to data/themes/${d}/`);}catch(S){throw x.fail("Failed to download themes"),S}let C=!1,H=null;if((t.setActive||t.setActive!==!1&&!t.noSetActive)&&(t.ci?p.length===1&&(C=!0,H=U(p[0].name)):(C=await R("Do you want to set one of these themes as active?",{initial:p.length===1}),C&&(p.length===1?H=U(p[0].name):H=await fe("Which theme do you want to activate?",p.map(k=>({title:U(k.name),value:U(k.name)})))))),C&&H){let S=`${d}/${H}`,k=Ve("Updating params.yaml...").start();try{await Nn(c,S),k.succeed(`\u2705 Set active theme to: ${S}`);}catch(T){throw k.fail("Failed to update params.yaml"),T}}if(await i.track({name:"add-theme",payload:{vendor:d,themesCount:p.length,activated:C,ci:!!t.ci}}),s){o.json({status:"success",vendor:d,themes:p.map(S=>S.name),activated:H?`${d}/${H}`:null});return}o.success(`
21
- \u{1F3A8} Themes installed successfully!`),(!C||!H)&&(o.info(`
20
+ var N=class extends Error{constructor(e,t="HBX_ERROR",r){super(e),this.name="HbxError",this.code=t,this.details=r;}},u=class extends N{constructor(e,t){super(e,"HBX_INPUT_ERROR",t);}},ee=class extends N{constructor(e="Operation cancelled by user"){super(e,"HBX_ABORTED");}},xe=class extends N{constructor(e,t){super(e,"HBX_CONFIG_ERROR",t);}};function ut(n){return !!(n&&typeof n=="object"&&"code"in n)}async function v(n){try{return await $.access(n),!0}catch{return false}}async function _(n){await $.mkdir(n,{recursive:true});}async function Pe(n){if(!await v(n)){await _(n);return}if((await $.readdir(n)).length>0)throw new Error(`Directory ${n} is not empty`)}async function R(n,e){await _(E.dirname(n)),await $.writeFile(n,e);}var ke="hbx",G="HBX_DEBUG",te="HBX_LICENSE_TOKEN",ft="HBX_TELEMETRY_DISABLED",Ve=E.join(Ne.homedir(),".hbx"),Ee=E.join(Ve,"config.json"),Nn=E.join(Ne.homedir(),".cache","hbx"),ne=E.join(Nn,"templates"),gt="HBX_UPDATE_CHECK_DISABLED",re="https://api.github.com",ht=`${re}/repos/HugoBlox/hugo-blox-builder/contents/templates`,yt="https://github.com/HugoBlox/hugo-blox-builder.git",wt="HBX_TEMPLATES_DIR",X="https://cli-api.hugoblox.com",bt=`${X}/api/usage-insights`,Te="hugoblox",vt=1e3*60*60*24,xt=1e3*60*60*12;var We=[{id:"academic-cv",name:"Academic CV",description:"Publish your academic CV and showcase your research.",repoPath:"templates/academic-cv",slug:"academic-cv",tags:["academic","cv"],source:"oss"},{id:"startup",name:"Startup",description:"Marketing site for SaaS and startups.",repoPath:"templates/startup",slug:"startup",tags:["business"],source:"oss"},{id:"folio",name:"Portfolio",description:"Minimal portfolio for creatives.",repoPath:"templates/folio",slug:"folio",tags:["portfolio"],source:"oss"}];var Ae="hbx.blocks.json";async function D(n=process.cwd()){let e=n,{root:t}=E.parse(n);for(;;){if((await Promise.all([v(E.join(e,"config","_default")),v(E.join(e,"hugoblox.yaml"))])).some(Boolean))return {root:e,manifestPath:E.join(e,Ae)};if(e===t)return;e=E.dirname(e);}}async function Ct(n){let e=E.join(n,"hugoblox.yaml");if(await v(e))try{let t=await $.readFile(e,"utf8"),r=rt.parse(t);if(!r)return;let o=r.template??{},i=r.build??{};return {templateId:o.id,templateName:o.name,requiredHugoVersion:i.hugo_version}}catch(t){throw new u("Failed to parse hugoblox.yaml",{error:t})}}async function Pt(){try{let{stdout:n}=await execa("hugo",["version"]);return Vn(n)}catch{return}}function Vn(n){let e=n.match(/v(\d+\.\d+\.\d+)/i);return e?e[1]:n.match(/(\d+\.\d+\.\d+)/)?.[1]}var q=class extends Error{constructor(t,r){super(t);this.cause=r;this.name="NetworkError";}};async function ie(n,e={}){let{timeout:t=15e3,retries:r=3,backoff:o=500,...i}=e,s=0;for(;s<=r;){let c=new AbortController,a=setTimeout(()=>c.abort(),t);try{let l=await fetch(n,{...i,signal:c.signal});if(clearTimeout(a),l.status===429||l.status>=500&&l.status<600)throw new q(`Server error: ${l.status}`);return l}catch(l){clearTimeout(a),s++;let m=l.name==="AbortError";if(s>r)throw m?new q(`Request timed out after ${t}ms`,l):l instanceof q?l:new q("Network request failed",l);let w=o*2**(s-1);await new Promise(d=>setTimeout(d,w));}}throw new q("Unreachable")}async function kt(){try{return await St.lookup("google.com"),!0}catch{try{return await St.lookup("1.1.1.1"),!0}catch{return false}}}async function B(n,e={}){if(e.ci){if(typeof e.initial=="string")return e.initial;throw new u(`Option required in CI mode: ${n}`)}return (await ze({type:"text",name:"value",message:n,initial:e.initial},{onCancel:()=>{throw new ee}})).value}async function he(n,e,t={}){if(t.ci){if(typeof t.initial=="string")return t.initial;throw new u(`Option required in CI mode: ${n}`)}return (await ze({type:"select",name:"value",message:n,choices:e,initial:0},{onCancel:()=>{throw new ee}})).value}async function H(n,e={}){if(e.ci){if(typeof e.initial=="boolean")return e.initial;throw new u(`Confirmation required in CI mode: ${n}`)}return (await ze({type:"confirm",name:"value",message:n,initial:e.initial??true},{onCancel:()=>{throw new ee}})).value}function At(n){let e=n.match(/github\.com[/:]([\w-]+)\/([\w-]+?)(?:\.git)?$/i);return e?{owner:e[1],repo:e[2]}:null}function Wn(n){return At(n)!==null}async function zn(n,e){let t=`https://api.github.com/repos/${n}/${e}/contents/hugoblox/themes`;try{let r=await ie(t,{headers:{"User-Agent":"hbx-cli",Accept:"application/vnd.github.v3+json"}});if(!r.ok)throw r.status===404?new u(`Repository does not contain a 'hugoblox/themes' directory. Please check the repository structure at https://github.com/${n}/${e}`):new u(`Failed to fetch themes from GitHub (status ${r.status})`);let i=(await r.json()).filter(s=>s.type==="file"&&s.name.toLowerCase().endsWith(".yaml"));if(i.length===0)throw new u(`No theme files found in hugoblox/themes directory at https://github.com/${n}/${e}`);return i.map(s=>({name:s.name,downloadUrl:s.download_url}))}catch(r){throw r instanceof u?r:new u(`Failed to access GitHub repository: ${r instanceof Error?r.message:String(r)}`)}}async function Gn(n,e){let t=await ie(n,{headers:{"User-Agent":"hbx-cli"}});if(!t.ok)throw new u(`Failed to download theme file (status ${t.status})`);let r=await t.text();await R(e,r);}async function Xn(n,e){let t=E.join(n,"config","_default","params.yaml");if(!await v(t))throw new u(`params.yaml not found at ${t}. Please ensure you're in a HugoBlox site.`);let r=await $.readFile(t,"utf8"),o=rt.parse(r),i=typeof o=="object"&&o!==null?o:{};(typeof i.hugoblox!="object"||i.hugoblox===null)&&(i.hugoblox={});let s=i.hugoblox;(typeof s.theme!="object"||s.theme===null)&&(s.theme={}),s.theme.pack=e;let c=rt.stringify(i);await $.writeFile(t,c,"utf8");}function U(n){return n.toLowerCase().replace(/\.yaml$/i,"")}function _t(n,e){n.command("theme").description("Add theme pack(s) from a GitHub repository").option("--repo <url>","GitHub repository URL containing themes").option("--theme <name>","Specific theme filename to download (without .yaml), or 'all' for all themes").option("--set-active","Set the downloaded theme as active in params.yaml").option("--no-set-active","Skip setting theme as active").option("--ci","Run in non-interactive mode").action(async(t,r)=>{let{logger:o,telemetry:i}=e,s=!!r.optsWithGlobals().json;try{let c=await D();if(!c)throw new u("Not in a HugoBlox site. Please run this command from within a HugoBlox site directory (must contain hugoblox.yaml)");let a=c.root,l=t.repo;if(!l){if(t.ci)throw new u("--repo is required when running with --ci");l=await B("Enter the GitHub repository URL containing themes (e.g., https://github.com/username/themes-repo):");}if(l=l.trim(),!Wn(l))throw new u("Invalid GitHub repository URL. Please provide a valid GitHub URL (e.g., https://github.com/owner/repo)");let m=At(l);if(!m)throw new u("Failed to parse GitHub URL");let{owner:p,repo:w}=m,d=p,g=Ge("Fetching available themes...").start(),h;try{h=await zn(p,w),g.succeed(`Found ${h.length} theme(s)`);}catch(S){throw g.fail("Failed to fetch themes"),S}let f,b=t.theme;if(!b)if(t.ci)b="all";else {let S=[{title:"All themes",value:"all"},...h.map(T=>({title:U(T.name),value:T.name}))];b=await he("Which theme(s) do you want to download?",S);}if(b.toLowerCase()==="all")f=h;else {let S=U(b),k=h.find(T=>U(T.name)===S);if(!k)throw new u(`Theme '${b}' not found. Available themes: ${h.map(T=>T.name).join(", ")}`);f=[k];}let P=E.join(a,"data","themes",d);await _(P);let x=Ge(`Downloading ${f.length} theme(s)...`).start();try{for(let S of f){let k=E.join(P,S.name);await Gn(S.downloadUrl,k);}x.succeed(`\u2705 Downloaded ${f.length} theme(s) to data/themes/${d}/`);}catch(S){throw x.fail("Failed to download themes"),S}let C=!1,j=null;if((t.setActive||t.setActive!==!1&&!t.noSetActive)&&(t.ci?f.length===1&&(C=!0,j=U(f[0].name)):(C=await H("Do you want to set one of these themes as active?",{initial:f.length===1}),C&&(f.length===1?j=U(f[0].name):j=await he("Which theme do you want to activate?",f.map(k=>({title:U(k.name),value:U(k.name)})))))),C&&j){let S=`${d}/${j}`,k=Ge("Updating params.yaml...").start();try{await Xn(a,S),k.succeed(`\u2705 Set active theme to: ${S}`);}catch(T){throw k.fail("Failed to update params.yaml"),T}}if(await i.track({name:"add-theme",payload:{vendor:d,themesCount:f.length,activated:C,ci:!!t.ci}}),s){o.json({status:"success",vendor:d,themes:f.map(S=>S.name),activated:j?`${d}/${j}`:null});return}o.success(`
21
+ \u{1F3A8} Themes installed successfully!`),(!C||!j)&&(o.info(`
22
22
  \u{1F4DD} To use a theme, update your config/_default/params.yaml:`),o.info(`
23
- hugoblox:`),o.info(" theme:"),o.info(` pack: "${d}/${U(p[0].name)}"`));}catch(a){if(s){o.json({status:"error",message:a instanceof Error?a.message:String(a)});return}throw a}});}function Et(n,e){let t=n.command("add").description("Add resources (themes)");kt(t,e);}function Tt(n,e){n.command("block").argument("<id>","Block identifier").description("Create a new HugoBlox block").option("--example <slug>","Include sample content for the block").option("--dry-run","Print the actions without writing files").option("--yes","Overwrite files when they already exist").action((t,r,o)=>{let{logger:i}=e,s=!!o.optsWithGlobals().json,a="Block creation is coming soon. Follow Discord for updates or to preview it early.";if(s){i.json({status:"pending",message:a});return}i.info(a);});}var ze="com.hugoblox.cli",Fn=1,Un=createRequire(import.meta.url),Vn=promisify(ge.scrypt),O=null;try{O=Un("keytar");}catch{O=null;}async function At(n,e,t,r,o){let i=`device:${t}`,s,a;if(O)await O.setPassword(ze,i,r);else {let c=await Gn(r,e);s=c.payload,a=c.salt;}n.setDeviceInfo({id:t,label:o,secretAlias:O?i:void 0,secretFallback:s,secretFallbackSalt:a,secretFallbackVersion:s?Fn:void 0}),await n.save();}async function $t(n,e){let t=n.getDeviceInfo();if(!t?.id)return;let r;if(t.secretAlias&&O&&(r=await O.getPassword(ze,t.secretAlias)),!r&&t.secretFallback&&t.secretFallbackSalt)try{let{key:o}=await _t(e,t.secretFallbackSalt);r=zn(t.secretFallback,o);}catch{r=void 0;}if(r)return {id:t.id,secret:r,label:t.label}}async function Ge(n){let e=n.getDeviceInfo();e?.secretAlias&&O&&await O.deletePassword(ze,e.secretAlias),n.setDeviceInfo(void 0),await n.save();}function Wn(n,e){let t=ge.randomBytes(12),r=ge.createCipheriv("aes-256-gcm",e.subarray(0,32),t),o=Buffer.concat([r.update(n,"utf8"),r.final()]),i=r.getAuthTag();return Buffer.concat([t,i,o]).toString("base64")}function zn(n,e){let t=Buffer.from(n,"base64"),r=t.subarray(0,12),o=t.subarray(12,28),i=t.subarray(28),s=ge.createDecipheriv("aes-256-gcm",e.subarray(0,32),r);return s.setAuthTag(o),Buffer.concat([s.update(i),s.final()]).toString("utf8")}async function _t(n,e){let t=Buffer.from(e,"base64");return {key:await Vn(n,t,32,{N:32768,r:8,p:1,maxmem:64*1024*1024}),salt:e}}async function Gn(n,e){let t=ge.randomBytes(16).toString("base64"),{key:r}=await _t(e,t);return {payload:Wn(n,r),salt:t}}async function B(n,e={}){let t=n.config.getLicense();if(!t)throw new u("Set HBX_LICENSE_TOKEN or run 'hbx login' to access Pro content.");let r=await n.config.ensureTelemetryId();if(e.force)await Ge(n.config);else {let s=await $t(n.config,r);if(s)return {id:s.id,secret:s.secret}}let o=e.label??Le.hostname(),i=await qn(n.config,t,r,o);return await At(n.config,r,i.deviceId,i.deviceSecret,o),n.logger.debug(`Registered device ${i.deviceId}`),{id:i.deviceId,secret:i.deviceSecret}}async function It(n){await Ge(n);}async function qn(n,e,t,r){let o=await fetch(`${X}/api/license/devices/register`,{method:"POST",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json","x-telemetry-id":t},body:JSON.stringify({deviceLabel:r})}),i=await Jn(o);if(!o.ok)throw i?.code==="license_device_limit"?new u("This license has reached the maximum number of devices. Revoke an existing device and try again."):o.status===401||o.status===403?new u(i?.error??"Unable to register device"):new u(i?.error??`Device registration failed (status ${o.status})`);if(!i?.deviceId||!i?.deviceSecret)throw new u("Device registration response was missing credentials");return i}async function Jn(n){try{return await n.json()}catch{return}}function Kn(n){return n.split("-").map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}async function V(n){let{logger:e}=n,t=await Yn(e),r=await Qn(n);return t.length||r.length?[...r,...t]:Fe}async function Yn(n){try{let e=await fetch(ut,{headers:{"User-Agent":"hbx-cli"}});if(!e.ok)throw new Error(`GitHub responded with status ${e.status}`);return (await e.json()).filter(o=>o.type==="dir").map(o=>({id:o.name,name:Kn(o.name),description:`Starter template ${o.name}`,repoPath:o.path,slug:o.name,source:"oss"}))}catch(e){return n?.debug?.(`Falling back to offline starter metadata: ${String(e)}`),Fe}}async function Qn(n){let{logger:e,config:t}=n,r=new Headers({"User-Agent":"hbx-cli"});try{let a=await t.ensureTelemetryId();r.set("x-telemetry-id",a);}catch{}let o,i=t.getLicense();if(i)try{let a=await B(n);o=new Headers(r),o.set("Authorization",`Bearer ${i}`),o.set("X-HBX-Device-Id",a.id),o.set("X-HBX-Device-Secret",a.secret);}catch(a){e?.debug?.(`Skipping device-auth headers for Pro templates: ${String(a)}`);}let s=[];o&&s.push({label:"with auth",headers:o}),s.push({label:o?"without auth":"anonymous",headers:r});for(let a of s)try{let c=await fetch(`${X}/api/pro-templates`,{headers:a.headers});if(!c.ok)throw new Error(`catalog responded with status ${c.status}`);return (await c.json()).templates.map(m=>({id:m.id,name:`${m.name} (Pro)`,description:m.description??void 0,repoPath:void 0,slug:m.slug??m.id,source:"pro",version:m.version,sizeBytes:m.sizeBytes,updatedAt:m.updatedAt,commitHash:m.commitHash,downloadEndpoint:m.downloadUrl}))}catch(c){e.debug(`Unable to fetch Pro template catalog (${a.label}): ${String(c)}`);}return []}async function Ee(n,e){try{await execa("git",["init"],{cwd:n}),await execa("git",["add","."],{cwd:n}),await execa("git",["commit","-m","chore: initialize site"],{cwd:n,reject:!1}),e.success(`Initialized git repository in ${E.relative(process.cwd(),n)||"."}`);}catch(t){e.warn(`Git initialization skipped: ${String(t)}`);}}async function qe(n,e,t={},r=0){let o=n.config.getLicense();if(!o)throw new u("A HugoBlox Pro license key is required before accessing Pro templates.");let i=await n.config.ensureTelemetryId(),s=await B(n,{force:r>0}),a=new Headers(t.headers??{});a.set("Authorization",`Bearer ${o}`),a.set("X-HBX-Device-Id",s.id),a.set("X-HBX-Device-Secret",s.secret),a.set("X-Telemetry-Id",i);let c=await fetch(`${X}${e}`,{...t,headers:a});if((c.status===401||c.status===403)&&r===0)return await B(n,{force:true}),qe(n,e,t,r+1);if(!c.ok){let l=await er(c);throw l?.code==="license_device_limit"?new u("This license has reached the maximum number of devices. Revoke an existing device and try again."):c.status===401||c.status===403?new u(l?.error??"Device authentication failed."):new u(l?.error??`Request failed (${c.status})`)}return c}async function er(n){try{return await n.json()}catch{return}}var tr=3;async function jt(n,e,t,r){if(e.source==="pro"){await ir(n,e,t,r);return}let o=process.env[ft];if(o){await nr(e,o,t),r.debug(`Hydrated template ${e.id} from local override`);return}let i=await or(e,r),s=i!==void 0?E.join(te,e.id,i):void 0;if(s&&await v(s)){await J(s,t),r.debug(`Hydrated template ${e.id} from cache (${i})`);return}let a=await _.mkdtemp(E.join(Le.tmpdir(),"hbx-template-")),c=E.join(a,"repo");try{await execa("git",["clone","--depth","1",pt,c],{stdio:"ignore"});let l=await rr(c,e);s?(await $(E.dirname(s)),await _.rm(s,{recursive:!0,force:!0}),await _.cp(l,s,{recursive:!0}),await Dt(E.join(te,e.id)),await J(s,t),r.debug(`Hydrated template ${e.id} from fresh cache (${i})`)):(await J(l,t),r.debug(`Hydrated template ${e.id} from repository`));}catch(l){throw new u("Failed to clone HugoBlox templates. Ensure git is installed and accessible.",{error:l})}finally{await _.rm(a,{recursive:true,force:true});}}async function nr(n,e,t){let r=E.join(e,n.id);try{await _.access(r);}catch(o){throw new u(`Local template not found at ${r}`,{error:o})}await J(r,t);}async function rr(n,e){let t=e.repoPath??"",r=E.join(n,t);return await _.access(r),r}async function J(n,e){await _.rm(e,{recursive:true,force:true}),await $(E.dirname(e)),await _.cp(n,e,{recursive:true}),await _.rm(E.join(e,".git"),{recursive:true,force:true});}async function Dt(n){if(!await v(n))return;let e=await _.readdir(n,{withFileTypes:true}),t=await Promise.all(e.filter(r=>r.isDirectory()).map(async r=>{let o=E.join(n,r.name),i=await _.stat(o);return {path:o,mtimeMs:i.mtimeMs}}));t.sort((r,o)=>o.mtimeMs-r.mtimeMs);for(let r of t.slice(tr))await _.rm(r.path,{recursive:true,force:true});}async function or(n,e){let t=encodeURIComponent(n.repoPath??""),r=`${ne}/repos/HugoBlox/hugo-blox-builder/commits?path=${t}&per_page=1`;try{let o=await fetch(r,{headers:{"User-Agent":"hbx-cli"}});if(!o.ok)throw new Error(`GitHub responded with status ${o.status}`);return (await o.json())[0]?.sha}catch(o){e.debug(`Unable to determine latest template commit for ${n.id}: ${String(o)}`);return}}async function ir(n,e,t,r){let o=e.version?E.join(te,e.id,e.version):void 0;if(o&&await v(o)){await J(o,t),r.debug(`Hydrated Pro template ${e.id} from cache (${e.version})`);return}let i=await _.mkdtemp(E.join(Le.tmpdir(),"hbx-pro-template-")),s=E.join(i,"template.tgz"),a=E.join(i,"extract");await $(a);try{let c=await sr(n,e,s);await execa("tar",["-xzf",s,"-C",a]);let l=await ar(a,e.slug),m=e.version??c.version??void 0,g=m!==void 0?E.join(te,e.id,m):void 0;g?(await $(E.dirname(g)),await _.rm(g,{recursive:!0,force:!0}),await _.cp(l,g,{recursive:!0}),await Dt(E.join(te,e.id)),await J(g,t),r.debug(`Hydrated Pro template ${e.id} from fresh cache (${m})`)):(await J(l,t),r.debug(`Hydrated Pro template ${e.id} from archive`));}catch(c){throw new u(`Failed to download Pro template ${e.name}. Ensure your license is valid and try again.`,{error:c})}finally{await _.rm(i,{recursive:true,force:true});}}async function sr(n,e,t){let r=e.downloadEndpoint??`/api/pro-templates/${encodeURIComponent(e.id)}/download`,o=await qe(n,r),i=await cr(o);if(!i?.url)throw new u("Pro template download URL was missing");let s=await fetch(i.url);if(!s.ok)throw new u(`Pro template archive download failed (${s.status})`);let a=Buffer.from(await s.arrayBuffer());return await _.writeFile(t,a),{version:i.version}}async function ar(n,e){let t=await _.readdir(n,{withFileTypes:true}),r=t.find(i=>i.isDirectory()&&i.name===e);if(r)return E.join(n,r.name);let o=t.filter(i=>i.isDirectory());return o.length===1?E.join(n,o[0].name):n}async function cr(n){try{return await n.json()}catch{return}}var Lt="https://hugoblox.com/discord",Bt="https://docs.hugoblox.com",Nt="https://hugoblox.com/pro";function z(n){return n.trim().toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-{2,}/g,"-").replace(/^-+|-+$/g,"").slice(0,64)}async function Te(n,e,t,r){let{logger:o}=n;await jt(n,t,e,o),await mr(e,t,r),r.sampleContent||await ur(e,t);}async function Ae(n,e,t){t.info(`\u{1F4E6} Installing dependencies with ${e}...`);let r={...process.env},o=["install"],i=!t.isJsonMode();e==="pnpm"&&(r.PNPM_WORKSPACE_DIR=n,r.PNPM_IGNORE_WORKSPACE_ROOT_CHECK="1",await lr(n),o.push("--no-link-workspace-packages"));try{return await execa(e,o,{cwd:n,stdio:i?"ignore":"inherit",env:r}),t.success("\u2705 Dependencies installed"),!0}catch(s){return i?t.warn(`\u26A0\uFE0F Failed to install dependencies automatically. Run ${e} install inside ${n}`):t.warn(`\u26A0\uFE0F Failed to install dependencies automatically: ${String(s)}`),false}}async function lr(n){let e=E.join(n,"pnpm-workspace.yaml");if(await v(e))return;await j(e,`packages:
23
+ hugoblox:`),o.info(" theme:"),o.info(` pack: "${d}/${U(f[0].name)}"`));}catch(c){if(s){o.json({status:"error",message:c instanceof Error?c.message:String(c)});return}throw c}});}function $t(n,e){let t=n.command("add").description("Add resources (themes)");_t(t,e);}function It(n,e){n.command("block").argument("<id>","Block identifier").description("Create a new HugoBlox block").option("--example <slug>","Include sample content for the block").option("--dry-run","Print the actions without writing files").option("--yes","Overwrite files when they already exist").action((t,r,o)=>{let{logger:i}=e,s=!!o.optsWithGlobals().json,c="Block creation is coming soon. Follow Discord for updates or to preview it early.";if(s){i.json({status:"pending",message:c});return}i.info(c);});}var qe="com.hugoblox.cli",Kn=1,Yn=createRequire(import.meta.url),Qn=promisify(ye.scrypt),O=null;try{O=Yn("keytar");}catch{O=null;}async function Ht(n,e,t,r,o){let i=`device:${t}`,s,c;if(O)await O.setPassword(qe,i,r);else {let a=await tr(r,e);s=a.payload,c=a.salt;}n.setDeviceInfo({id:t,label:o,secretAlias:O?i:void 0,secretFallback:s,secretFallbackSalt:c,secretFallbackVersion:s?Kn:void 0}),await n.save();}async function jt(n,e){let t=n.getDeviceInfo();if(!t?.id)return;let r;if(t.secretAlias&&O&&(r=await O.getPassword(qe,t.secretAlias)),!r&&t.secretFallback&&t.secretFallbackSalt)try{let{key:o}=await Rt(e,t.secretFallbackSalt);r=er(t.secretFallback,o);}catch{r=void 0;}if(r)return {id:t.id,secret:r,label:t.label}}async function Je(n){let e=n.getDeviceInfo();e?.secretAlias&&O&&await O.deletePassword(qe,e.secretAlias),n.setDeviceInfo(void 0),await n.save();}function Zn(n,e){let t=ye.randomBytes(12),r=ye.createCipheriv("aes-256-gcm",e.subarray(0,32),t),o=Buffer.concat([r.update(n,"utf8"),r.final()]),i=r.getAuthTag();return Buffer.concat([t,i,o]).toString("base64")}function er(n,e){let t=Buffer.from(n,"base64"),r=t.subarray(0,12),o=t.subarray(12,28),i=t.subarray(28),s=ye.createDecipheriv("aes-256-gcm",e.subarray(0,32),r);return s.setAuthTag(o),Buffer.concat([s.update(i),s.final()]).toString("utf8")}async function Rt(n,e){let t=Buffer.from(e,"base64");return {key:await Qn(n,t,32,{N:32768,r:8,p:1,maxmem:64*1024*1024}),salt:e}}async function tr(n,e){let t=ye.randomBytes(16).toString("base64"),{key:r}=await Rt(e,t);return {payload:Zn(n,r),salt:t}}async function L(n,e={}){let t=n.config.getLicense();if(!t)throw new u("Set HBX_LICENSE_TOKEN or run 'hbx login' to access Pro content.");let r=await n.config.ensureTelemetryId();if(e.force)await Je(n.config);else {let s=await jt(n.config,r);if(s)return {id:s.id,secret:s.secret}}let o=e.label??Ne.hostname(),i=await rr(n.config,t,r,o);return await Ht(n.config,r,i.deviceId,i.deviceSecret,o),n.logger.debug(`Registered device ${i.deviceId}`),{id:i.deviceId,secret:i.deviceSecret}}async function Dt(n){await Je(n);}async function rr(n,e,t,r){let o=await fetch(`${X}/api/license/devices/register`,{method:"POST",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json","x-telemetry-id":t},body:JSON.stringify({deviceLabel:r})}),i=await or(o);if(!o.ok)throw i?.code==="license_device_limit"?new u("This license has reached the maximum number of devices. Revoke an existing device and try again."):o.status===401||o.status===403?new u(i?.error??"Unable to register device"):new u(i?.error??`Device registration failed (status ${o.status})`);if(!i?.deviceId||!i?.deviceSecret)throw new u("Device registration response was missing credentials");return i}async function or(n){try{return await n.json()}catch{return}}function ir(n){return n.split("-").map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}async function V(n){let{logger:e}=n,t=await sr(e),r=await ar(n);return t.length||r.length?[...r,...t]:We}async function sr(n){try{let e=await fetch(ht,{headers:{"User-Agent":"hbx-cli"}});if(!e.ok)throw new Error(`GitHub responded with status ${e.status}`);return (await e.json()).filter(o=>o.type==="dir").map(o=>({id:o.name,name:ir(o.name),description:`Starter template ${o.name}`,repoPath:o.path,slug:o.name,source:"oss"}))}catch(e){return n?.debug?.(`Falling back to offline starter metadata: ${String(e)}`),We}}async function ar(n){let{logger:e,config:t}=n,r=new Headers({"User-Agent":"hbx-cli"});try{let c=await t.ensureTelemetryId();r.set("x-telemetry-id",c);}catch{}let o,i=t.getLicense();if(i)try{let c=await L(n);o=new Headers(r),o.set("Authorization",`Bearer ${i}`),o.set("X-HBX-Device-Id",c.id),o.set("X-HBX-Device-Secret",c.secret);}catch(c){e?.debug?.(`Skipping device-auth headers for Pro templates: ${String(c)}`);}let s=[];o&&s.push({label:"with auth",headers:o}),s.push({label:o?"without auth":"anonymous",headers:r});for(let c of s)try{let a=await fetch(`${X}/api/pro-templates`,{headers:c.headers});if(!a.ok)throw new Error(`catalog responded with status ${a.status}`);return (await a.json()).templates.map(m=>({id:m.id,name:`${m.name} (Pro)`,description:m.description??void 0,repoPath:void 0,slug:m.slug??m.id,source:"pro",version:m.version,sizeBytes:m.sizeBytes,updatedAt:m.updatedAt,commitHash:m.commitHash,downloadEndpoint:m.downloadUrl}))}catch(a){e.debug(`Unable to fetch Pro template catalog (${c.label}): ${String(a)}`);}return []}async function _e(n,e){try{await execa("git",["init"],{cwd:n}),await execa("git",["add","."],{cwd:n}),await execa("git",["commit","-m","chore: initialize site"],{cwd:n,reject:!1}),e.success(`Initialized git repository in ${E.relative(process.cwd(),n)||"."}`);}catch(t){e.warn(`Git initialization skipped: ${String(t)}`);}}async function Ye(n,e,t={},r=0){let o=n.config.getLicense();if(!o)throw new u("A HugoBlox Pro license key is required before accessing Pro templates.");let i=await n.config.ensureTelemetryId(),s=await L(n,{force:r>0}),c=new Headers(t.headers??{});c.set("Authorization",`Bearer ${o}`),c.set("X-HBX-Device-Id",s.id),c.set("X-HBX-Device-Secret",s.secret),c.set("X-Telemetry-Id",i);let a=await fetch(`${X}${e}`,{...t,headers:c});if((a.status===401||a.status===403)&&r===0)return await L(n,{force:true}),Ye(n,e,t,r+1);if(!a.ok){let l=await lr(a);throw l?.code==="license_device_limit"?new u("This license has reached the maximum number of devices. Revoke an existing device and try again."):a.status===401||a.status===403?new u(l?.error??"Device authentication failed."):new u(l?.error??`Request failed (${a.status})`)}return a}async function lr(n){try{return await n.json()}catch{return}}var mr=3;async function Mt(n,e,t,r){if(e.source==="pro"){await fr(n,e,t,r);return}let o=process.env[wt];if(o){await dr(e,o,t),r.debug(`Hydrated template ${e.id} from local override`);return}let i=await pr(e,r),s=i!==void 0?E.join(ne,e.id,i):void 0;if(s&&await v(s)){await J(s,t),r.debug(`Hydrated template ${e.id} from cache (${i})`);return}let c=await $.mkdtemp(E.join(Ne.tmpdir(),"hbx-template-")),a=E.join(c,"repo");try{await execa("git",["clone","--depth","1",yt,a],{stdio:"ignore"});let l=await ur(a,e);s?(await _(E.dirname(s)),await $.rm(s,{recursive:!0,force:!0}),await $.cp(l,s,{recursive:!0}),await Nt(E.join(ne,e.id)),await J(s,t),r.debug(`Hydrated template ${e.id} from fresh cache (${i})`)):(await J(l,t),r.debug(`Hydrated template ${e.id} from repository`));}catch(l){throw new u("Failed to clone HugoBlox templates. Ensure git is installed and accessible.",{error:l})}finally{await $.rm(c,{recursive:true,force:true});}}async function dr(n,e,t){let r=E.join(e,n.id);try{await $.access(r);}catch(o){throw new u(`Local template not found at ${r}`,{error:o})}await J(r,t);}async function ur(n,e){let t=e.repoPath??"",r=E.join(n,t);return await $.access(r),r}async function J(n,e){await $.rm(e,{recursive:true,force:true}),await _(E.dirname(e)),await $.cp(n,e,{recursive:true}),await $.rm(E.join(e,".git"),{recursive:true,force:true});}async function Nt(n){if(!await v(n))return;let e=await $.readdir(n,{withFileTypes:true}),t=await Promise.all(e.filter(r=>r.isDirectory()).map(async r=>{let o=E.join(n,r.name),i=await $.stat(o);return {path:o,mtimeMs:i.mtimeMs}}));t.sort((r,o)=>o.mtimeMs-r.mtimeMs);for(let r of t.slice(mr))await $.rm(r.path,{recursive:true,force:true});}async function pr(n,e){let t=encodeURIComponent(n.repoPath??""),r=`${re}/repos/HugoBlox/hugo-blox-builder/commits?path=${t}&per_page=1`;try{let o=await fetch(r,{headers:{"User-Agent":"hbx-cli"}});if(!o.ok)throw new Error(`GitHub responded with status ${o.status}`);return (await o.json())[0]?.sha}catch(o){e.debug(`Unable to determine latest template commit for ${n.id}: ${String(o)}`);return}}async function fr(n,e,t,r){let o=e.version?E.join(ne,e.id,e.version):void 0;if(o&&await v(o)){await J(o,t),r.debug(`Hydrated Pro template ${e.id} from cache (${e.version})`);return}let i=await $.mkdtemp(E.join(Ne.tmpdir(),"hbx-pro-template-")),s=E.join(i,"template.tgz"),c=E.join(i,"extract");await _(c);try{let a=await gr(n,e,s);await execa("tar",["-xzf",s,"-C",c]);let l=await hr(c,e.slug),m=e.version??a.version??void 0,p=m!==void 0?E.join(ne,e.id,m):void 0;p?(await _(E.dirname(p)),await $.rm(p,{recursive:!0,force:!0}),await $.cp(l,p,{recursive:!0}),await Nt(E.join(ne,e.id)),await J(p,t),r.debug(`Hydrated Pro template ${e.id} from fresh cache (${m})`)):(await J(l,t),r.debug(`Hydrated Pro template ${e.id} from archive`));}catch(a){throw new u(`Failed to download Pro template ${e.name}. Ensure your license is valid and try again.`,{error:a})}finally{await $.rm(i,{recursive:true,force:true});}}async function gr(n,e,t){let r=e.downloadEndpoint??`/api/pro-templates/${encodeURIComponent(e.id)}/download`,o=await Ye(n,r),i=await yr(o);if(!i?.url)throw new u("Pro template download URL was missing");let s=await fetch(i.url);if(!s.ok)throw new u(`Pro template archive download failed (${s.status})`);let c=Buffer.from(await s.arrayBuffer());return await $.writeFile(t,c),{version:i.version}}async function hr(n,e){let t=await $.readdir(n,{withFileTypes:true}),r=t.find(i=>i.isDirectory()&&i.name===e);if(r)return E.join(n,r.name);let o=t.filter(i=>i.isDirectory());return o.length===1?E.join(n,o[0].name):n}async function yr(n){try{return await n.json()}catch{return}}var Ot="https://hugoblox.com/discord",Ft="https://docs.hugoblox.com",Ut="https://hugoblox.com/pro";function z(n){return n.trim().toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-{2,}/g,"-").replace(/^-+|-+$/g,"").slice(0,64)}async function $e(n,e,t,r){let{logger:o}=n;await Mt(n,t,e,o),await br(e,t,r),r.sampleContent||await xr(e,t);}async function Ie(n,e,t){t.info(`\u{1F4E6} Installing dependencies with ${e}...`);let r={...process.env},o=["install"],i=!t.isJsonMode();e==="pnpm"&&(r.PNPM_WORKSPACE_DIR=n,r.PNPM_IGNORE_WORKSPACE_ROOT_CHECK="1",await wr(n),o.push("--no-link-workspace-packages"));try{return await execa(e,o,{cwd:n,stdio:i?"ignore":"inherit",env:r}),t.success("\u2705 Dependencies installed"),!0}catch(s){return i?t.warn(`\u26A0\uFE0F Failed to install dependencies automatically. Run ${e} install inside ${n}`):t.warn(`\u26A0\uFE0F Failed to install dependencies automatically: ${String(s)}`),false}}async function wr(n){let e=E.join(n,"pnpm-workspace.yaml");if(await v(e))return;await R(e,`packages:
24
24
  - './*'
25
- `);}async function Ft(n,e,t){t.info("\u{1F525} Starting dev server with Hugo (press Ctrl+C to exit)...");let r={...process.env};e==="pnpm"&&(r.PNPM_WORKSPACE_DIR=n);try{await execa(e,["dev"],{cwd:n,stdio:"inherit",env:r}),t.success("\u2705 Dev server stopped");}catch(o){let i=o;if(i.signal==="SIGINT"||i.signal==="SIGTERM"){t.info("\u2705 Dev server stopped");return}if(o?.code==="ENOENT"||/[hH]ugo/.test(String(i.stderr))){t.error("Hugo executable not found. Install Hugo (https://docs.hugoblox.com/start/cli) or deploy with the Copilot at https://hugoblox.com/templates/");return}throw t.error(`Dev server exited with an error: ${String(o)}`),o}}async function mr(n,e,t){let r=z(E.basename(n))||e.slug;await dr(n,r);let o={"README.md":`# ${e.name}
25
+ `);}async function zt(n,e,t){t.info("\u{1F525} Starting dev server with Hugo (press Ctrl+C to exit)...");let r={...process.env};e==="pnpm"&&(r.PNPM_WORKSPACE_DIR=n);try{await execa(e,["dev"],{cwd:n,stdio:"inherit",env:r}),t.success("\u2705 Dev server stopped");}catch(o){let i=o;if(i.signal==="SIGINT"||i.signal==="SIGTERM"){t.info("\u2705 Dev server stopped");return}if(o?.code==="ENOENT"||/[hH]ugo/.test(String(i.stderr))){t.error("Hugo executable not found. Install Hugo (https://docs.hugoblox.com/start/cli) or deploy with the Copilot at https://hugoblox.com/templates/");return}throw t.error(`Dev server exited with an error: ${String(o)}`),o}}async function br(n,e,t){let r=z(E.basename(n))||e.slug;await vr(n,r);let o={"README.md":`# ${e.name}
26
26
 
27
27
  This site was created with the HugoBlox CLI.
28
28
  `,".gitignore":`node_modules
@@ -33,7 +33,7 @@ public
33
33
  modules/_vendor
34
34
  `};t.includeEnv&&(o[".env"]=`# HBX environment variables
35
35
  HBX_LICENSE_TOKEN=
36
- `);for(let[i,s]of Object.entries(o)){let a=E.join(n,i);await v(a)||await j(a,s);}}async function dr(n,e){let t=E.join(n,"package.json"),r={name:e,private:true,scripts:{dev:"hugo server -D",build:"hugo --gc --minify",lint:"echo 'TODO: add lint script'"},dependencies:{}};if(!await v(t)){await j(t,JSON.stringify(r,null,2));return}try{let o=await _.readFile(t,"utf8"),i=JSON.parse(o),s={...r,...i,name:e,scripts:{...r.scripts,...i.scripts},dependencies:{...r.dependencies,...i.dependencies}};await j(t,JSON.stringify(s,null,2));}catch{await j(t,JSON.stringify(r,null,2));}}async function ur(n,e){let t=E.join(n,"content");await _.rm(t,{recursive:true,force:true}),await $(E.dirname(E.join(t,"_index.md"))),await j(E.join(t,"_index.md"),pr(e));}function pr(n){return `---
36
+ `);for(let[i,s]of Object.entries(o)){let c=E.join(n,i);await v(c)||await R(c,s);}}async function vr(n,e){let t=E.join(n,"package.json"),r={name:e,private:true,scripts:{dev:"hugo server -D",build:"hugo --gc --minify",lint:"echo 'TODO: add lint script'"},dependencies:{}};if(!await v(t)){await R(t,JSON.stringify(r,null,2));return}try{let o=await $.readFile(t,"utf8"),i=JSON.parse(o),s={...r,...i,name:e,scripts:{...r.scripts,...i.scripts},dependencies:{...r.dependencies,...i.dependencies}};await R(t,JSON.stringify(s,null,2));}catch{await R(t,JSON.stringify(r,null,2));}}async function xr(n,e){let t=E.join(n,"content");await $.rm(t,{recursive:true,force:true}),await _(E.dirname(E.join(t,"_index.md"))),await R(E.join(t,"_index.md"),Cr(e));}function Cr(n){return `---
37
37
  title: "${n.name}"
38
38
  type: landing
39
39
  design:
@@ -47,14 +47,14 @@ sections:
47
47
  text: "Start customizing blocks to launch your next experience."
48
48
  primary_action:
49
49
  text: "Join our Discord"
50
- url: "${Lt}"
50
+ url: "${Ot}"
51
51
  icon: "chat-bubble-left-right"
52
52
  secondary_action:
53
53
  text: "Upgrade to Pro"
54
- url: "${Nt}"
54
+ url: "${Ut}"
55
55
  tertiary_action:
56
56
  text: "View Docs"
57
- url: "${Bt}"
57
+ url: "${Ft}"
58
58
  design:
59
59
  css_class: "bg-gradient-to-r from-blue-600 to-indigo-600 text-white"
60
60
  spacing:
@@ -63,55 +63,55 @@ sections:
63
63
  content:
64
64
  title: "Your next steps"
65
65
  text: |
66
- 1. Join the community on [Discord](${Lt}) for support and inspiration.
67
- 2. Explore the [documentation](${Bt}) to learn how to add blocks, deploy, and automate.
68
- 3. [Upgrade to Pro](${Nt}) to unlock premium blocks, design systems, and automation-ready packages.
66
+ 1. Join the community on [Discord](${Ot}) for support and inspiration.
67
+ 2. Explore the [documentation](${Ft}) to learn how to add blocks, deploy, and automate.
68
+ 3. [Upgrade to Pro](${Ut}) to unlock premium blocks, design systems, and automation-ready packages.
69
69
  4. Share feedback and showcase your build to help the ecosystem grow.
70
- `}function Je(n){return n?n.length<=6?"***":`${n.slice(0,3)}***${n.slice(-2)}`:"(none)"}function $e(n,e){let t=n??e;return E.resolve(process.cwd(),t)}async function Ut(n=process.cwd()){let e=E.join(n,"pnpm-lock.yaml"),t=E.join(n,"yarn.lock"),r=E.join(n,"package-lock.json");return F.existsSync(e)?"pnpm":F.existsSync(t)?"yarn":F.existsSync(r)?"npm":"pnpm"}async function _e(n){try{let e=E.resolve(n);if(n.includes("\0")||/[<>:"|?*]/.test(n))return {valid:!1,exists:!1,isEmpty:!1,writable:!1,error:"Path contains invalid characters"};let t=!1,r=!1,o=!1;try{let i=F.statSync(e);if(t=!0,i.isDirectory()){r=F.readdirSync(e).length===0;try{F.accessSync(e,F.constants.W_OK),o=!0;}catch{o=!1;}}else return {valid:!1,exists:!0,isEmpty:!1,writable:!1,error:"Path exists but is not a directory"}}catch{let s=E.dirname(e);try{F.accessSync(s,F.constants.W_OK),o=!0;}catch{return {valid:!1,exists:!1,isEmpty:!1,writable:!1,error:"Parent directory is not writable"}}}return {valid:!0,exists:t,isEmpty:r,writable:o}}catch(e){return {valid:false,exists:false,isEmpty:false,writable:false,error:e instanceof Error?e.message:"Unknown error"}}}function fr(n,e){if(!e)return;let t=e.toLowerCase(),r=n.find(o=>{let i=o.id.toLowerCase(),s=o.slug?.toLowerCase();return i===t||s===t});if(r)return r;if(e.startsWith("http")||e.startsWith("git@"))return {id:e,name:"Custom template",description:`External template: ${e}`,repoPath:e,slug:"custom",source:"custom"}}function zt(n,e){n.command("site").description("Create a new HugoBlox site").argument("[dir]","Target directory (defaults to template slug, e.g., new-site)").option("--template <id>","Starter template ID").option("--dir <path>","Target directory").option("--package-manager <name>","Package manager","pnpm").option("--no-install","Skip dependency installation").option("--git","Initialize a git repository").option("--ci","Run in non-interactive mode").option("--sample-content","Force include sample content").option("--no-sample-content","Skip sample content").option("--pro","Mark the project as Pro ready").option("--preview","Automatically start the dev server after setup").option("--no-preview","Skip the dev server prompt").action(async(t,r,o)=>{let{logger:i,config:s,telemetry:a}=e,l=!!o.optsWithGlobals().json,m=Ve({text:"Fetching templates...",spinner:"dots"}).start(),g=await V(e).finally(()=>{m.succeed("\u2728 Templates ready");}),d=fr(g,r.template);if(!d){if(r.ci)throw new u("Template must be specified when running with --ci");let k=await fe("Select a starter",g.map(T=>({title:T.name,description:T.description,value:T.id})));d=g.find(T=>T.id===k);}if(!d)throw new u("Unable to determine template");let f=d.source==="pro",h=await hr(r,t,d),p=$e(h,d.slug);await ve(p);let b=typeof r.sampleContent=="boolean"?r.sampleContent:typeof r.noSampleContent=="boolean"?!r.noSampleContent:r.ci?false:await R("Include sample content? (recommended)",{initial:true}),P=f;if(!f)P=typeof r.pro=="boolean"?r.pro:r.ci?false:await R("Do you have a HugoBlox Pro license?",{initial:!!s.getLicense()});else if(!s.getLicense()){if(r.ci)throw new u(`"${d.name}" is a HugoBlox Pro template. Set HBX_LICENSE_TOKEN with your license key before running in CI.`);if(i.info(`"${d.name}" is part of HugoBlox Pro. Purchase a license at https://hugoblox.com/pro to receive your key via email (powered by Lemon Squeezy).`),!await R("Do you have a HugoBlox Pro license key to enter now?",{initial:true}))throw new u("Pro templates require an active license. Purchase at https://hugoblox.com/pro and rerun this command after running 'hbx login' or setting HBX_LICENSE_TOKEN.");let T=await Wt(s.getLicense());s.setLicense(T),await s.save();}if(!f&&P&&!s.getLicense()){if(r.ci)throw new u("Set HBX_LICENSE_TOKEN before running --ci when enabling Pro features.");let k=await Wt(s.getLicense());s.setLicense(k),await s.save();}P&&await B(e);let x=Ve(`Creating site in ${E.relative(process.cwd(),p)||"."}...`).start();try{await Te(e,p,d,{sampleContent:b,includeEnv:!0,packageManager:r.packageManager??"pnpm"}),x.succeed("Files generated");}catch(k){throw x.fail("Failed to scaffold site"),k}let C=false;r.install!==false?C=await Ae(p,r.packageManager??"pnpm",i):i.info("Skipping dependency installation"),r.git&&await Ee(p,i);let H={status:"success",template:d.id,path:p,pro:P,manifest:E.join(p,ke)};!C&&r.preview?i.warn("\u26A0\uFE0F Cannot start the dev server because dependencies failed to install."):r.install===false&&r.preview&&i.warn("\u26A0\uFE0F Install dependencies first (skip --no-install) to start the dev server automatically.");let S=false;if(C&&(S=await gr(r,l)),await a.track({name:"new-site",payload:{template:d.id,sample:b,pro:P,ci:!!r.ci,packageManager:r.packageManager??"pnpm",install:r.install!==false,dependenciesReady:C,preview:S}}),S){await Ft(p,r.packageManager??"pnpm",i);return}if(l){i.json(H);return}i.success(`\u2705 Site created at ${p}`),i.info("\u{1F680} Next steps:"),i.info(` \u{1F449} cd ${E.relative(process.cwd(),p)||p}`),r.install===false&&i.info(` \u{1F449} ${r.packageManager??"pnpm"} install`),i.info(" \u{1F449} pnpm dev");});}async function gr(n,e){return e||n.ci?false:typeof n.preview=="boolean"?n.preview:n.noPreview?false:R("Start the dev server now?",{initial:true})}async function hr(n,e,t){if(n.dir)return n.dir;if(e)return e;if(n.ci)return t.slug;let o=(await L("Project folder name",{initial:t.slug})).trim();return o?yr(o)?o:z(o)||t.slug:t.slug}function yr(n){return /[\\/]/.test(n)||n.includes(":")}async function Wt(n){let t=(await L("Enter your HugoBlox Pro license key (from your purchase confirmation email)",{initial:n??""})).trim();if(!t)throw new u("A HugoBlox Pro license key is required to continue. Check your purchase email or visit https://hugoblox.com/pro.");return t}var xr=fileURLToPath(import.meta.url),Ye=E.dirname(xr);function Cr(){return Ye.endsWith("dist")?E.join(Ye,"lib","templates","minimal-theme.yaml"):E.resolve(Ye,"..","lib","templates","minimal-theme.yaml")}var Gt=Cr();function Pr(n){return /^[a-zA-Z0-9_-]+$/.test(n)}async function Sr(){try{return await _.readFile(Gt,"utf8")}catch(n){throw new u(`Failed to load theme template: ${Gt}`,{error:n})}}function kr(n,e,t,r){let o=n.split(`
71
- `),i=[],s=false,a=0;for(let c of o){if(c.trim()==="meta:"){s=true,a=c.indexOf("meta:"),i.push(c),i.push(' format: "hugoblox-theme@1"'),i.push(` name: "${t}"`),i.push(` vendor: "${e}"`),i.push(' version: "0.0.1"'),i.push(' license: "MIT"'),i.push(' description: "Created via HugoBlox CLI"');continue}if(s){c.trim()&&!c.startsWith(" ".repeat(a+2))&&c.indexOf(":")>0&&(s=false,i.push(c));continue}i.push(c);}return i.join(`
72
- `)}function Xt(n,e){n.command("theme").description("Scaffold a new theme pack").argument("[name]","Theme slug/filename (will be converted to kebab-case)").option("--vendor <namespace>","Vendor namespace (e.g., GitHub username)").option("--theme-name <name>","Human-readable theme name (defaults to slug)").option("--git","Initialize a git repository").option("--ci","Run in non-interactive mode").action(async(t,r,o)=>{let{logger:i,telemetry:s}=e,a=!!o.optsWithGlobals().json;try{let c=r.vendor;if(!c){if(r.ci)throw new u("--vendor is required when running with --ci");c=await L("What is your GitHub username? (This will be your vendor namespace)");}if(c=c.trim(),!c)throw new u("Vendor namespace is required");if(!Pr(c))throw new u("Vendor namespace must contain only alphanumeric characters, hyphens, and underscores");let l=t;if(!l){if(r.ci)throw new u("Theme slug is required when running with --ci");l=await L("What do you want to name your theme? (e.g., cyberpunk-neon)",{initial:"my-theme"});}if(l=l.trim(),!l)throw new u("Theme slug is required");let m=z(l),g=r.themeName;g||(r.ci?g=l:g=await L("Human-readable theme name?",{initial:l})),g=g.trim()||l;let w=E.join(process.cwd(),"data","themes",c),d=E.join(w,`${m}.yaml`);if(await v(d)){if(r.ci)throw new u(`Theme file already exists: ${d}`);if(!await R(`Theme file ${m}.yaml already exists. Overwrite?`,{initial:!1})){i.info("Theme creation cancelled");return}}let f=Ve("Creating theme...").start();try{await $(w);let p=await Sr(),b=kr(p,c,g,m);await j(d,b),f.succeed("\u2705 Theme created successfully!");}catch(p){throw f.fail("Failed to create theme"),p}await s.track({name:"create-theme",payload:{vendor:c,themeFilename:m,ci:!!r.ci}});let h=E.relative(process.cwd(),d);if(a){i.json({status:"success",path:d,vendor:c,themeFilename:m,themeName:g});return}i.success(`
70
+ `}function Qe(n){return n?n.length<=6?"***":`${n.slice(0,3)}***${n.slice(-2)}`:"(none)"}function He(n,e){let t=n??e;return E.resolve(process.cwd(),t)}async function Gt(n=process.cwd()){let e=E.join(n,"pnpm-lock.yaml"),t=E.join(n,"yarn.lock"),r=E.join(n,"package-lock.json");return F.existsSync(e)?"pnpm":F.existsSync(t)?"yarn":F.existsSync(r)?"npm":"pnpm"}async function je(n){try{let e=E.resolve(n);if(n.includes("\0")||/[<>:"|?*]/.test(n))return {valid:!1,exists:!1,isEmpty:!1,writable:!1,error:"Path contains invalid characters"};let t=!1,r=!1,o=!1;try{let i=F.statSync(e);if(t=!0,i.isDirectory()){r=F.readdirSync(e).length===0;try{F.accessSync(e,F.constants.W_OK),o=!0;}catch{o=!1;}}else return {valid:!1,exists:!0,isEmpty:!1,writable:!1,error:"Path exists but is not a directory"}}catch{let s=E.dirname(e);try{F.accessSync(s,F.constants.W_OK),o=!0;}catch{return {valid:!1,exists:!1,isEmpty:!1,writable:!1,error:"Parent directory is not writable"}}}return {valid:!0,exists:t,isEmpty:r,writable:o}}catch(e){return {valid:false,exists:false,isEmpty:false,writable:false,error:e instanceof Error?e.message:"Unknown error"}}}function Pr(n,e){if(!e)return;let t=e.toLowerCase(),r=n.find(o=>{let i=o.id.toLowerCase(),s=o.slug?.toLowerCase();return i===t||s===t});if(r)return r;if(e.startsWith("http")||e.startsWith("git@"))return {id:e,name:"Custom template",description:`External template: ${e}`,repoPath:e,slug:"custom",source:"custom"}}function Jt(n,e){n.command("site").description("Create a new HugoBlox site").argument("[dir]","Target directory (defaults to template slug, e.g., new-site)").option("--template <id>","Starter template ID").option("--dir <path>","Target directory").option("--package-manager <name>","Package manager","pnpm").option("--no-install","Skip dependency installation").option("--git","Initialize a git repository").option("--ci","Run in non-interactive mode").option("--sample-content","Force include sample content").option("--no-sample-content","Skip sample content").option("--pro","Mark the project as Pro ready").option("--preview","Automatically start the dev server after setup").option("--no-preview","Skip the dev server prompt").action(async(t,r,o)=>{let{logger:i,config:s,telemetry:c}=e,l=!!o.optsWithGlobals().json,m=Ge({text:"Fetching templates...",spinner:"dots"}).start(),p=await V(e).finally(()=>{m.succeed("\u2728 Templates ready");}),d=Pr(p,r.template);if(!d){if(r.ci)throw new u("Template must be specified when running with --ci");let k=await he("Select a starter",p.map(T=>({title:T.name,description:T.description,value:T.id})));d=p.find(T=>T.id===k);}if(!d)throw new u("Unable to determine template");let g=d.source==="pro",h=await kr(r,t,d),f=He(h,d.slug);await Pe(f);let b=typeof r.sampleContent=="boolean"?r.sampleContent:typeof r.noSampleContent=="boolean"?!r.noSampleContent:r.ci?false:await H("Include sample content? (recommended)",{initial:true}),P=g;if(!g)P=typeof r.pro=="boolean"?r.pro:r.ci?false:await H("Do you have a HugoBlox Pro license?",{initial:!!s.getLicense()});else if(!s.getLicense()){if(r.ci)throw new u(`"${d.name}" is a HugoBlox Pro template. Set HBX_LICENSE_TOKEN with your license key before running in CI.`);if(i.info(`"${d.name}" is part of HugoBlox Pro. Purchase a license at https://hugoblox.com/pro to receive your key via email (powered by Lemon Squeezy).`),!await H("Do you have a HugoBlox Pro license key to enter now?",{initial:true}))throw new u("Pro templates require an active license. Purchase at https://hugoblox.com/pro and rerun this command after running 'hbx login' or setting HBX_LICENSE_TOKEN.");let T=await qt(s.getLicense());s.setLicense(T),await s.save();}if(!g&&P&&!s.getLicense()){if(r.ci)throw new u("Set HBX_LICENSE_TOKEN before running --ci when enabling Pro features.");let k=await qt(s.getLicense());s.setLicense(k),await s.save();}P&&await L(e);let x=Ge(`Creating site in ${E.relative(process.cwd(),f)||"."}...`).start();try{await $e(e,f,d,{sampleContent:b,includeEnv:!0,packageManager:r.packageManager??"pnpm"}),x.succeed("Files generated");}catch(k){throw x.fail("Failed to scaffold site"),k}let C=false;r.install!==false?C=await Ie(f,r.packageManager??"pnpm",i):i.info("Skipping dependency installation"),r.git&&await _e(f,i);let j={status:"success",template:d.id,path:f,pro:P,manifest:E.join(f,Ae)};!C&&r.preview?i.warn("\u26A0\uFE0F Cannot start the dev server because dependencies failed to install."):r.install===false&&r.preview&&i.warn("\u26A0\uFE0F Install dependencies first (skip --no-install) to start the dev server automatically.");let S=false;if(C&&(S=await Sr(r,l)),await c.track({name:"new-site",payload:{template:d.id,sample:b,pro:P,ci:!!r.ci,packageManager:r.packageManager??"pnpm",install:r.install!==false,dependenciesReady:C,preview:S}}),S){await zt(f,r.packageManager??"pnpm",i);return}if(l){i.json(j);return}i.success(`\u2705 Site created at ${f}`),i.info("\u{1F680} Next steps:"),i.info(` \u{1F449} cd ${E.relative(process.cwd(),f)||f}`),r.install===false&&i.info(` \u{1F449} ${r.packageManager??"pnpm"} install`),i.info(" \u{1F449} pnpm dev");});}async function Sr(n,e){return e||n.ci?false:typeof n.preview=="boolean"?n.preview:n.noPreview?false:H("Start the dev server now?",{initial:true})}async function kr(n,e,t){if(n.dir)return n.dir;if(e)return e;if(n.ci)return t.slug;let o=(await B("Project folder name",{initial:t.slug})).trim();return o?Er(o)?o:z(o)||t.slug:t.slug}function Er(n){return /[\\/]/.test(n)||n.includes(":")}async function qt(n){let t=(await B("Enter your HugoBlox Pro license key (from your purchase confirmation email)",{initial:n??""})).trim();if(!t)throw new u("A HugoBlox Pro license key is required to continue. Check your purchase email or visit https://hugoblox.com/pro.");return t}var $r=fileURLToPath(import.meta.url),et=E.dirname($r);function Ir(){return et.endsWith("dist")?E.join(et,"lib","templates","minimal-theme.yaml"):E.resolve(et,"..","lib","templates","minimal-theme.yaml")}var Kt=Ir();function Hr(n){return /^[a-zA-Z0-9_-]+$/.test(n)}async function jr(){try{return await $.readFile(Kt,"utf8")}catch(n){throw new u(`Failed to load theme template: ${Kt}`,{error:n})}}function Rr(n,e,t,r){let o=n.split(`
71
+ `),i=[],s=false,c=0;for(let a of o){if(a.trim()==="meta:"){s=true,c=a.indexOf("meta:"),i.push(a),i.push(' format: "hugoblox-theme@1"'),i.push(` name: "${t}"`),i.push(` vendor: "${e}"`),i.push(' version: "0.0.1"'),i.push(' license: "MIT"'),i.push(' description: "Created via HugoBlox CLI"');continue}if(s){a.trim()&&!a.startsWith(" ".repeat(c+2))&&a.indexOf(":")>0&&(s=false,i.push(a));continue}i.push(a);}return i.join(`
72
+ `)}function Yt(n,e){n.command("theme").description("Scaffold a new theme pack").argument("[name]","Theme slug/filename (will be converted to kebab-case)").option("--vendor <namespace>","Vendor namespace (e.g., GitHub username)").option("--theme-name <name>","Human-readable theme name (defaults to slug)").option("--git","Initialize a git repository").option("--ci","Run in non-interactive mode").action(async(t,r,o)=>{let{logger:i,telemetry:s}=e,c=!!o.optsWithGlobals().json;try{let a=r.vendor;if(!a){if(r.ci)throw new u("--vendor is required when running with --ci");a=await B("What is your GitHub username? (This will be your vendor namespace)");}if(a=a.trim(),!a)throw new u("Vendor namespace is required");if(!Hr(a))throw new u("Vendor namespace must contain only alphanumeric characters, hyphens, and underscores");let l=t;if(!l){if(r.ci)throw new u("Theme slug is required when running with --ci");l=await B("What do you want to name your theme? (e.g., cyberpunk-neon)",{initial:"my-theme"});}if(l=l.trim(),!l)throw new u("Theme slug is required");let m=z(l),p=r.themeName;p||(r.ci?p=l:p=await B("Human-readable theme name?",{initial:l})),p=p.trim()||l;let w=E.join(process.cwd(),"data","themes",a),d=E.join(w,`${m}.yaml`);if(await v(d)){if(r.ci)throw new u(`Theme file already exists: ${d}`);if(!await H(`Theme file ${m}.yaml already exists. Overwrite?`,{initial:!1})){i.info("Theme creation cancelled");return}}let g=Ge("Creating theme...").start();try{await _(w);let f=await jr(),b=Rr(f,a,p,m);await R(d,b),g.succeed("\u2705 Theme created successfully!");}catch(f){throw g.fail("Failed to create theme"),f}await s.track({name:"create-theme",payload:{vendor:a,themeFilename:m,ci:!!r.ci}});let h=E.relative(process.cwd(),d);if(c){i.json({status:"success",path:d,vendor:a,themeFilename:m,themeName:p});return}i.success(`
73
73
  Theme created at: ${h}`),i.info(`
74
74
  \u{1F4DD} To use this theme, update your params.yaml:`),i.info(`
75
- hugoblox:`),i.info(" theme:"),i.info(` pack: "${c}/${m}"`),r.ci||await R(`
75
+ hugoblox:`),i.info(" theme:"),i.info(` pack: "${a}/${m}"`),r.ci||await H(`
76
76
  \u{1F30D} Would you like to share this theme with the community?`,{initial:!1})&&(i.info(`
77
77
  \u2728 Great! Here's how to publish your theme:`),i.info(`
78
78
  1\uFE0F\u20E3 Create a new GitHub repository`),i.info("2\uFE0F\u20E3 In your repo, create a folder structure: hugoblox/themes/"),i.info(`3\uFE0F\u20E3 Copy your theme file to: hugoblox/themes/${m}.yaml`),i.info("4\uFE0F\u20E3 Commit and push to GitHub"),i.info(`
79
79
  \u{1F4E2} Once published, others can install it with:
80
- hbx add theme --repo https://github.com/${c}/your-repo-name
81
- `),i.info("\u{1F4A1} Tip: You can add multiple themes to the same repository!"));}catch(c){if(a){i.json({status:"error",message:c instanceof Error?c.message:String(c)});return}throw c}});}function qt(n,e){let t=n.command("create").description("Create resources (site, theme, block)");zt(t,e),Xt(t,e),Tt(t,e);}function Kt(n,e){Tr(n,e),Ar(n,e);}function Tr(n,e){n.command("dev [hugoArgs...]").description("Start the Hugo development server (hugo server)").option("--path <dir>","Project directory (defaults to cwd)").option("--no-default-flags","Disable automatic --disableFastRender flag").action(async(t,r,o)=>{let{logger:i,telemetry:s}=e,c=!!o.optsWithGlobals().json,l=await Yt(r.path),m=["server"];r.defaultFlags!==false&&m.push("--disableFastRender"),m.push(...t),await Qt(m,l,i,{allowSignalExit:true,label:"dev server"}),await s.track({name:"dev",payload:{customPath:!!r.path,defaultFlags:r.defaultFlags!==false,args:t}}),c&&i.json({status:"success"});});}function Ar(n,e){n.command("build [hugoArgs...]").description("Run a production Hugo build (hugo --gc --minify)").option("--path <dir>","Project directory (defaults to cwd)").option("--no-default-flags","Disable automatic --gc/--minify flags").action(async(t,r,o)=>{let{logger:i,telemetry:s}=e,c=!!o.optsWithGlobals().json,l=await Yt(r.path),m=[];r.defaultFlags!==false&&m.push("--gc","--minify"),m.push(...t),await Qt(m,l,i,{allowSignalExit:false,label:"build"}),await s.track({name:"build",payload:{customPath:!!r.path,defaultFlags:r.defaultFlags!==false,args:t}}),c&&i.json({status:"success"});});}async function Yt(n){let e=n?E.resolve(n):E.resolve(process.cwd()),t=await D(e);if(!t)throw new u("Unable to locate a HugoBlox project. Run this inside a project or pass --path.");return t.root}async function Qt(n,e,t,r){t.info(`Running: hugo ${n.join(" ")}`);try{await execa("hugo",n,{cwd:e,stdio:"inherit"}),t.success(`Hugo ${r.label} finished`);}catch(o){let i=o;if(r.allowSignalExit&&(i.signal==="SIGINT"||i.signal==="SIGTERM")){t.info("Hugo process stopped");return}throw new u(`Hugo ${r.label} failed: ${i.shortMessage??i.message}`,{error:i})}}var Rr=["github.com/HugoBlox/hugo-blox-builder","github.com/wowchemy/wowchemy-hugo-themes"];async function Re(n){let e=E.join(n,"go.mod"),t;try{t=await _.readFile(e,"utf8");}catch{return []}let o=Dr(t).filter(s=>Rr.some(a=>s.path.startsWith(a)));return await Promise.all(o.map(async s=>{try{let a=await Hr(s.path);return {path:s.path,current:s.version,latest:a}}catch(a){return {path:s.path,current:s.version,latest:void 0,error:a.message}}}))}async function Hr(n){if(n.includes("github.com/HugoBlox/hugo-blox-builder"))return jr(n)}async function jr(n){let e=await oe(`${ne}/repos/HugoBlox/hugo-blox-builder/tags?per_page=100`);if(!e.ok)throw new Error(`GitHub API error: ${e.status}`);let t=await e.json(),r=n.split("github.com/HugoBlox/hugo-blox-builder/");if(r.length<2)return;let o=r[1],i=t.filter(s=>s.name.startsWith(`${o}/`)&&/v\d+\.\d+\.\d+/.test(s.name)).map(s=>s.name);if(i.length!==0)return i.sort((s,a)=>{let c=s.split("/").pop()||"0.0.0",l=a.split("/").pop()||"0.0.0";return N.rcompare(c,l)}),i[0].split("/").pop()}async function Zt(n,e){if(!n.includes("github.com/HugoBlox/hugo-blox-builder"))return;let t=n.split("github.com/HugoBlox/hugo-blox-builder/");if(t.length<2)return;let r=t[1],o=e==="main"||e.startsWith("v")?e:`v${e}`,i=e==="main"?"main":`${r}/${o.replace(/^v/,"v")}`,s=`${r}/hugo.yaml`,a=await oe(`${ne}/repos/HugoBlox/hugo-blox-builder/contents/${s}?ref=${i}`,{headers:{Accept:"application/vnd.github.v3.raw"}});if(!a.ok)return;let c=await a.text();return Ze.parse(c)?.module?.hugoVersion?.min}function Dr(n){let e=[],t=n.split(/\r?\n/),r=false;for(let o of t){let i=o.trim();if(i.startsWith("require (")){r=true;continue}if(r&&i===")"){r=false;continue}let s="";if(!r&&i.startsWith("require ")?s=i.replace("require","").trim():r&&(s=i),s){s=s.split("//")[0].trim();let a=s.split(/\s+/);a.length>=2&&e.push({path:a[0],version:a[1]});}}return e}function He(n,e){if(!n||!e)return {updateAvailable:false,diff:""};let t=N.coerce(n),r=N.coerce(e);return !t||!r?{updateAvailable:false,diff:""}:N.lt(t,r)?{updateAvailable:true,diff:`${ae(n)} -> ${ae(e)}`}:{updateAvailable:false,diff:""}}function ae(n){let e=/v\d+\.\d+\.\d+-(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})-([a-f0-9]{12})/,t=n.match(e);if(t){let[r,o,i,s,a,c,l,m]=t;return `commit ${m.substring(0,7)} (released ${o}-${i}-${s})`}return n}function tn(n){let e=process.env.HOME||process.env.USERPROFILE;if(!e)return n;let t=E.resolve(e),r=E.resolve(n);return r.startsWith(t)?r.replace(t,"~"):n}async function Qe(n,e){try{let t=await execa(n,e,{reject:!1});return t.exitCode===0?t.stdout.trim():`Failed (${t.stderr.trim()})`}catch(t){return `Not available (${t.message})`}}function nn(n,e){n.command("doctor").description("Check local environment for common issues").action(async(t,r)=>{let{logger:o,config:i}=e,a=!!r.optsWithGlobals().json,c=[];c.push({name:"Node.js",ok:true,details:process.version});let l=await Qe("git",["--version"]);c.push({name:"Git",ok:!l.startsWith("Not"),details:l});let m=await Qe("hugo",["version"]);c.push({name:"Hugo",ok:!m.startsWith("Not"),details:m});let g=Br(m),w=await Qe("pnpm",["--version"]);c.push({name:"pnpm",ok:!w.startsWith("Not"),details:w});let d=i.getLicense();c.push({name:"Pro license",ok:!!d,details:d?"Configured":"Missing"});let f=await D();if(f){let b=await wt(f.root);if(b){let x=b.templateName??b.templateId??"Unknown";c.push({name:"Template",ok:true,details:`${x} (${tn(f.root)})`});let C=Nr(b.requiredHugoVersion,g);C&&c.push(C);}let P=await Re(f.root);for(let x of P){let C=x.path.split("/").pop()||x.path,H=x.current;if(x.latest){let k=N.coerce(x.current),T=N.coerce(x.latest);k&&T&&N.eq(k,T)&&(H=`${H} (latest)`);}c.push({name:`Module: ${C}`,ok:true,details:H});let{updateAvailable:S}=He(x.current,x.latest);S&&x.latest&&c.push({name:`${C} update`,ok:false,details:`Current ${x.current}, latest ${x.latest}. Run 'hbx upgrade' to update.`,level:"warn"});}}let p={status:c.some(b=>(b.level??(b.ok?"info":"error"))==="error")?"error":"success",checks:c};if(a){o.json(p);return}for(let b of p.checks){let P=b.level??(b.ok?"info":"error");P==="info"?o.success(`${b.name}: ${b.details}`):P==="warn"?o.warn(`${b.name}: ${b.details}`):o.error(`${b.name}: ${b.details}`);}});}function Br(n){let e=n.match(/v(\d+\.\d+\.\d+)/i);return e?e[1]:n.match(/(\d+\.\d+\.\d+)/)?.[1]}function Nr(n,e){if(!n||!e)return;let t=N.coerce(n),r=N.coerce(e);if(!(!t||!r))return N.lt(r,t)?{name:"Hugo version compatibility",ok:false,details:`Template requires Hugo ${t.version}, but ${r.version} is installed`,level:"error"}:N.major(r)>N.major(t)||N.minor(r)>N.minor(t)?{name:"Hugo version compatibility",ok:true,details:`Using Hugo ${r.version}; template tested with ${t.version}`,level:"warn"}:{name:"Hugo version compatibility",ok:true,details:`Template requires Hugo ${t.version} and you're running ${r.version}`,level:"info"}}function rn(n,e){n.command("install").description("Hydrate HugoBlox Pro assets").option("--ci","Fail when prompts would appear").option("--force","Force re-download of assets").option("--path <dir>","Project directory (defaults to cwd)").action(async(t,r)=>{let{logger:o,config:i,telemetry:s}=e,c=!!r.optsWithGlobals().json,l=t.path?{root:E.resolve(t.path),manifestPath:E.join(E.resolve(t.path),"hbx.blocks.json")}:await D();if(!l)throw new u("Unable to locate a HugoBlox project - pass --path if needed");let m=i.getLicense();if(!m){if(t.ci)throw new u(`Missing license key. Set ${ee} or run hbx login before using --ci.`);o.warn("No Pro license detected, proceeding with OSS assets only");}let g=Ve("Hydrating Pro assets...").start();try{let d=E.join(l.root,"config","_default","module.hbx.toml"),f=E.join(l.root,"node_modules","@hugoblox-pro","sample");await $(f),await j(E.join(f,"README.md"),`# HugoBlox Pro assets placeholder
82
- `),await j(d,`# Generated by hbx install
80
+ hbx add theme --repo https://github.com/${a}/your-repo-name
81
+ `),i.info("\u{1F4A1} Tip: You can add multiple themes to the same repository!"));}catch(a){if(c){i.json({status:"error",message:a instanceof Error?a.message:String(a)});return}throw a}});}function Qt(n,e){let t=n.command("create").description("Create resources (site, theme, block)");Jt(t,e),Yt(t,e),It(t,e);}function en(n,e){Br(n,e),Lr(n,e);}function Br(n,e){n.command("dev [hugoArgs...]").description("Start the Hugo development server (hugo server)").option("--path <dir>","Project directory (defaults to cwd)").option("--no-default-flags","Disable automatic --disableFastRender flag").action(async(t,r,o)=>{let{logger:i,telemetry:s}=e,a=!!o.optsWithGlobals().json,l=await tn(r.path),m=["server"];r.defaultFlags!==false&&m.push("--disableFastRender"),m.push(...t),await nn(m,l,i,{allowSignalExit:true,label:"dev server"}),await s.track({name:"dev",payload:{customPath:!!r.path,defaultFlags:r.defaultFlags!==false,args:t}}),a&&i.json({status:"success"});});}function Lr(n,e){n.command("build [hugoArgs...]").description("Run a production Hugo build (hugo --gc --minify)").option("--path <dir>","Project directory (defaults to cwd)").option("--no-default-flags","Disable automatic --gc/--minify flags").action(async(t,r,o)=>{let{logger:i,telemetry:s}=e,a=!!o.optsWithGlobals().json,l=await tn(r.path),m=[];r.defaultFlags!==false&&m.push("--gc","--minify"),m.push(...t),await nn(m,l,i,{allowSignalExit:false,label:"build"}),await s.track({name:"build",payload:{customPath:!!r.path,defaultFlags:r.defaultFlags!==false,args:t}}),a&&i.json({status:"success"});});}async function tn(n){let e=n?E.resolve(n):E.resolve(process.cwd()),t=await D(e);if(!t)throw new u("Unable to locate a HugoBlox project. Run this inside a project or pass --path.");return t.root}async function nn(n,e,t,r){t.info(`Running: hugo ${n.join(" ")}`);try{await execa("hugo",n,{cwd:e,stdio:"inherit"}),t.success(`Hugo ${r.label} finished`);}catch(o){let i=o;if(r.allowSignalExit&&(i.signal==="SIGINT"||i.signal==="SIGTERM")){t.info("Hugo process stopped");return}throw new u(`Hugo ${r.label} failed: ${i.shortMessage??i.message}`,{error:i})}}var Nr=["github.com/HugoBlox/kit/modules","github.com/HugoBlox/hugo-blox-builder","github.com/wowchemy/wowchemy-hugo-themes"],sn=[{from:"github.com/HugoBlox/hugo-blox-builder/modules/blox-tailwind",to:"github.com/HugoBlox/kit/modules/blox"},{from:"github.com/HugoBlox/hugo-blox-builder/modules/blox-analytics",to:"github.com/HugoBlox/kit/modules/analytics"},{from:"github.com/HugoBlox/hugo-blox-builder/modules/blox-plugin-netlify",to:"github.com/HugoBlox/kit/modules/integrations/netlify"},{from:"github.com/HugoBlox/hugo-blox-builder/modules/blox-plugin-reveal",to:"github.com/HugoBlox/kit/modules/slides"}],K="github.com/HugoBlox/hugo-blox-builder/",an="github.com/HugoBlox/kit/";async function De(n){let e=E.join(n,"go.mod"),t;try{t=await $.readFile(e,"utf8");}catch{return []}let o=Fr(t).map(s=>({...s,path:tt(s.path)})).filter(s=>Nr.some(c=>s.path.startsWith(c)));return await Promise.all(o.map(async s=>{try{let c=await Or(s.path);return {path:s.path,current:s.version,latest:c}}catch(c){return {path:s.path,current:s.version,latest:void 0,error:c.message}}}))}async function Or(n){let e=tt(n);if(e.includes("github.com/HugoBlox/kit/modules"))return rn(e,"HugoBlox/kit");if(e.includes("github.com/HugoBlox/hugo-blox-builder"))return rn(e,"HugoBlox/hugo-blox-builder")}async function rn(n,e){let t=await ie(`${re}/repos/${e}/tags?per_page=100`);if(!t.ok)throw new Error(`GitHub API error: ${t.status}`);let r=await t.json(),o=e==="HugoBlox/kit"?"github.com/HugoBlox/kit/":K,i=n.split(o);if(i.length<2)return;let s=i[1],c=r.filter(a=>a.name.startsWith(`${s}/`)&&/v\d+\.\d+\.\d+/.test(a.name)).map(a=>a.name);if(c.length!==0)return c.sort((a,l)=>{let m=a.split("/").pop()||"0.0.0",p=l.split("/").pop()||"0.0.0";return M.rcompare(m,p)}),c[0].split("/").pop()}async function cn(n,e){let t=tt(n),r="HugoBlox/hugo-blox-builder",o="";if(t.includes("github.com/HugoBlox/kit/")){r="HugoBlox/kit";let p=t.split("github.com/HugoBlox/kit/");if(p.length<2)return;o=p[1];}else if(t.includes(K)){let p=t.split(K);if(p.length<2)return;o=p[1];}else return;let i=e==="main"||e.startsWith("v")?e:`v${e}`,s=e==="main"?"main":`${o}/${i.replace(/^v/,"v")}`,c=`${o}/hugo.yaml`,a=await ie(`${re}/repos/${r}/contents/${c}?ref=${s}`,{headers:{Accept:"application/vnd.github.v3.raw"}});if(!a.ok)return;let l=await a.text();return rt.parse(l)?.module?.hugoVersion?.min}async function ln(n){let e=E.join(n,"go.mod"),t=[E.join(n,"config","_default","module.yaml"),E.join(n,"config","_default","modules.yaml"),E.join(n,"config","_default","module.toml"),E.join(n,"config","_default","modules.toml")];try{let r=await $.readFile(e,"utf8"),o=on(r);o!==r&&await $.writeFile(e,o,"utf8");}catch{}for(let r of t)try{let o=await $.readFile(r,"utf8"),i=on(o);i!==o&&await $.writeFile(r,i,"utf8");}catch{}}function tt(n){let e=sn.find(t=>t.from===n);return e?e.to:n.startsWith(K)?n.replace(K,an):n}function on(n){let e=n;for(let t of sn)e=e.replaceAll(t.from,t.to);return e.includes(K)&&(e=e.replaceAll(K,an)),e}function Fr(n){let e=[],t=n.split(/\r?\n/),r=false;for(let o of t){let i=o.trim();if(i.startsWith("require (")){r=true;continue}if(r&&i===")"){r=false;continue}let s="";if(!r&&i.startsWith("require ")?s=i.replace("require","").trim():r&&(s=i),s){s=s.split("//")[0].trim();let c=s.split(/\s+/);c.length>=2&&e.push({path:c[0],version:c[1]});}}return e}function Be(n,e){if(!n||!e)return {updateAvailable:false,diff:""};let t=M.coerce(n),r=M.coerce(e);return !t||!r?{updateAvailable:false,diff:""}:M.lt(t,r)?{updateAvailable:true,diff:`${le(n)} -> ${le(e)}`}:{updateAvailable:false,diff:""}}function le(n){let e=/v\d+\.\d+\.\d+-(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})-([a-f0-9]{12})/,t=n.match(e);if(t){let[r,o,i,s,c,a,l,m]=t;return `commit ${m.substring(0,7)} (released ${o}-${i}-${s})`}return n}function dn(n){let e=process.env.HOME||process.env.USERPROFILE;if(!e)return n;let t=E.resolve(e),r=E.resolve(n);return r.startsWith(t)?r.replace(t,"~"):n}async function nt(n,e){try{let t=await execa(n,e,{reject:!1});return t.exitCode===0?t.stdout.trim():`Failed (${t.stderr.trim()})`}catch(t){return `Not available (${t.message})`}}function un(n,e){n.command("doctor").description("Check local environment for common issues").action(async(t,r)=>{let{logger:o,config:i}=e,c=!!r.optsWithGlobals().json,a=[];a.push({name:"Node.js",ok:true,details:process.version});let l=await nt("git",["--version"]);a.push({name:"Git",ok:!l.startsWith("Not"),details:l});let m=await nt("hugo",["version"]);a.push({name:"Hugo",ok:!m.startsWith("Not"),details:m});let p=Vr(m),w=await nt("pnpm",["--version"]);a.push({name:"pnpm",ok:!w.startsWith("Not"),details:w});let d=i.getLicense();a.push({name:"Pro license",ok:!!d,details:d?"Configured":"Missing"});let g=await D();if(g){let b=await Ct(g.root);if(b){let x=b.templateName??b.templateId??"Unknown";a.push({name:"Template",ok:true,details:`${x} (${dn(g.root)})`});let C=Wr(b.requiredHugoVersion,p);C&&a.push(C);}let P=await De(g.root);for(let x of P){let C=x.path.split("/").pop()||x.path,j=x.current;if(x.latest){let k=M.coerce(x.current),T=M.coerce(x.latest);k&&T&&M.eq(k,T)&&(j=`${j} (latest)`);}a.push({name:`Module: ${C}`,ok:true,details:j});let{updateAvailable:S}=Be(x.current,x.latest);S&&x.latest&&a.push({name:`${C} update`,ok:false,details:`Current ${x.current}, latest ${x.latest}. Run 'hbx upgrade' to update.`,level:"warn"});}}let f={status:a.some(b=>(b.level??(b.ok?"info":"error"))==="error")?"error":"success",checks:a};if(c){o.json(f);return}for(let b of f.checks){let P=b.level??(b.ok?"info":"error");P==="info"?o.success(`${b.name}: ${b.details}`):P==="warn"?o.warn(`${b.name}: ${b.details}`):o.error(`${b.name}: ${b.details}`);}});}function Vr(n){let e=n.match(/v(\d+\.\d+\.\d+)/i);return e?e[1]:n.match(/(\d+\.\d+\.\d+)/)?.[1]}function Wr(n,e){if(!n||!e)return;let t=M.coerce(n),r=M.coerce(e);if(!(!t||!r))return M.lt(r,t)?{name:"Hugo version compatibility",ok:false,details:`Template requires Hugo ${t.version}, but ${r.version} is installed`,level:"error"}:M.major(r)>M.major(t)||M.minor(r)>M.minor(t)?{name:"Hugo version compatibility",ok:true,details:`Using Hugo ${r.version}; template tested with ${t.version}`,level:"warn"}:{name:"Hugo version compatibility",ok:true,details:`Template requires Hugo ${t.version} and you're running ${r.version}`,level:"info"}}function pn(n,e){n.command("install").description("Hydrate HugoBlox Pro assets").option("--ci","Fail when prompts would appear").option("--force","Force re-download of assets").option("--path <dir>","Project directory (defaults to cwd)").action(async(t,r)=>{let{logger:o,config:i,telemetry:s}=e,a=!!r.optsWithGlobals().json,l=t.path?{root:E.resolve(t.path),manifestPath:E.join(E.resolve(t.path),"hbx.blocks.json")}:await D();if(!l)throw new u("Unable to locate a HugoBlox project - pass --path if needed");let m=i.getLicense();if(!m){if(t.ci)throw new u(`Missing license key. Set ${te} or run hbx login before using --ci.`);o.warn("No Pro license detected, proceeding with OSS assets only");}let p=Ge("Hydrating Pro assets...").start();try{let d=E.join(l.root,"config","_default","module.hbx.toml"),g=E.join(l.root,"node_modules","@hugoblox-pro","sample");await _(g),await R(E.join(g,"README.md"),`# HugoBlox Pro assets placeholder
82
+ `),await R(d,`# Generated by hbx install
83
83
  [[module.imports]]
84
84
  path = "github.com/HugoBlox/hugo-blox-builder"
85
85
  [[module.imports]]
86
86
  path = "node_modules/@hugoblox-pro/sample"
87
- `),g.succeed("Assets hydrated");}catch(d){throw g.fail("Failed to hydrate assets"),d}await s.track({name:"install",payload:{ci:!!t.ci,force:!!t.force,tokenPresent:!!m,customPath:!!t.path}});let w={status:"success",path:l.root,forced:!!t.force,token:!!m};c?o.json(w):(o.success("Install complete"),m||o.info("Tip: run hbx login to unlock Pro downloads"));});}function on(n,e){n.command("login").description("Authenticate with HugoBlox Pro and register this device for template access").option("--token <value>","License key").option("--ci","Fail when license key is missing").action(async(t,r)=>{let{config:o,logger:i}=e,a=!!r.optsWithGlobals().json,c=t.token;if(!c){if(t.ci)throw new u("License key is required when using --ci");c=await L("Enter your HugoBlox Pro license key");}let l=false;try{o.setLicense(c),await o.save(),l=!0,await B(e,{force:!0});let m={status:"success",token:Je(c)};a?i.json(m):i.success(`License key saved (${Je(c)})`);}catch(m){throw l&&(o.clearLicense(),await o.save()),Or(m)}});}function sn(n,e){n.command("logout").description("Remove stored HugoBlox credentials and device secrets").action(async(t,r)=>{let{config:o,logger:i}=e,s=!!r.optsWithGlobals().json;await It(o),o.clearLicense(),await o.save();let a={status:"success"};s?i.json(a):i.success("License key removed");});}function Or(n){let e=n instanceof Error?n.message:"Device registration failed",t="HBX must register this machine before downloading Pro templates. Check your internet connection, ensure your license has a free device slot, or revoke an old device and rerun 'hbx login'.";return n instanceof M?new u(`${e}. ${t}`,n.details):new u(`${e}. ${t}`)}function le(n){let e=n.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);if(!e)return {frontMatter:{},body:n};try{let t=Ze.parse(e[1]);return typeof t!="object"||t===null||Array.isArray(t)?{frontMatter:{},body:n}:{frontMatter:t,body:e[2]??""}}catch{return {frontMatter:{},body:n}}}async function*me(n){let e;try{e=await _.readdir(n,{withFileTypes:!0});}catch{return}for(let t of e){let r=E.join(n,t.name);if(t.isDirectory()){try{if((await _.lstat(r)).isSymbolicLink())continue}catch{continue}yield*me(r);}else t.name.endsWith(".md")&&(yield r);}}function ln(n,e){n.command("v0.11.0-authors").description("Migrate author profiles from content/authors/ to data/authors/ (v0.11.0+)").option("-y, --yes","Skip confirmation prompts").option("--dry-run","Preview changes without modifying files").action(async t=>{let{logger:r}=e,o=await D();if(!o)throw new u("No Hugo project found in the current directory.");let i=Ve("Analyzing author profiles...").start();try{let s=E.join(o.root,"content","authors");if(!await v(s)){i.stop(),r.info("\u2139\uFE0F No authors directory found. Nothing to migrate.");return}let a=await mn(s);if(a.length===0){i.stop(),r.info("\u2139\uFE0F No author profiles found to migrate.");return}i.stop(),r.info(`
87
+ `),p.succeed("Assets hydrated");}catch(d){throw p.fail("Failed to hydrate assets"),d}await s.track({name:"install",payload:{ci:!!t.ci,force:!!t.force,tokenPresent:!!m,customPath:!!t.path}});let w={status:"success",path:l.root,forced:!!t.force,token:!!m};a?o.json(w):(o.success("Install complete"),m||o.info("Tip: run hbx login to unlock Pro downloads"));});}function fn(n,e){n.command("login").description("Authenticate with HugoBlox Pro and register this device for template access").option("--token <value>","License key").option("--ci","Fail when license key is missing").action(async(t,r)=>{let{config:o,logger:i}=e,c=!!r.optsWithGlobals().json,a=t.token;if(!a){if(t.ci)throw new u("License key is required when using --ci");a=await B("Enter your HugoBlox Pro license key");}let l=false;try{o.setLicense(a),await o.save(),l=!0,await L(e,{force:!0});let m={status:"success",token:Qe(a)};c?i.json(m):i.success(`License key saved (${Qe(a)})`);}catch(m){throw l&&(o.clearLicense(),await o.save()),Gr(m)}});}function gn(n,e){n.command("logout").description("Remove stored HugoBlox credentials and device secrets").action(async(t,r)=>{let{config:o,logger:i}=e,s=!!r.optsWithGlobals().json;await Dt(o),o.clearLicense(),await o.save();let c={status:"success"};s?i.json(c):i.success("License key removed");});}function Gr(n){let e=n instanceof Error?n.message:"Device registration failed",t="HBX must register this machine before downloading Pro templates. Check your internet connection, ensure your license has a free device slot, or revoke an old device and rerun 'hbx login'.";return n instanceof N?new u(`${e}. ${t}`,n.details):new u(`${e}. ${t}`)}function de(n){let e=n.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);if(!e)return {frontMatter:{},body:n};try{let t=rt.parse(e[1]);return typeof t!="object"||t===null||Array.isArray(t)?{frontMatter:{},body:n}:{frontMatter:t,body:e[2]??""}}catch{return {frontMatter:{},body:n}}}async function*ue(n){let e;try{e=await $.readdir(n,{withFileTypes:!0});}catch{return}for(let t of e){let r=E.join(n,t.name);if(t.isDirectory()){try{if((await $.lstat(r)).isSymbolicLink())continue}catch{continue}yield*ue(r);}else t.name.endsWith(".md")&&(yield r);}}function wn(n,e){n.command("v0.11.0-authors").description("Migrate author profiles from content/authors/ to data/authors/ (v0.11.0+)").option("-y, --yes","Skip confirmation prompts").option("--dry-run","Preview changes without modifying files").action(async t=>{let{logger:r}=e,o=await D();if(!o)throw new u("No Hugo project found in the current directory.");let i=Ge("Analyzing author profiles...").start();try{let s=E.join(o.root,"content","authors");if(!await v(s)){i.stop(),r.info("\u2139\uFE0F No authors directory found. Nothing to migrate.");return}let c=await bn(s);if(c.length===0){i.stop(),r.info("\u2139\uFE0F No author profiles found to migrate.");return}i.stop(),r.info(`
88
88
  \u{1F4CB} Migration Plan (v0.11.0 Author System):
89
- `),r.info(` Found ${a.length} author profile(s):`);for(let l of a){let m=l.slug==="admin"?"me":l.slug;r.info(` \u2022 ${l.slug} \u2192 data/authors/${m}.yaml`),l.avatarPath&&r.info(` Avatar: ${E.basename(l.avatarPath)} \u2192 assets/media/authors/${m}${E.extname(l.avatarPath)}`);}if(r.info(`
89
+ `),r.info(` Found ${c.length} author profile(s):`);for(let l of c){let m=l.slug==="admin"?"me":l.slug;r.info(` \u2022 ${l.slug} \u2192 data/authors/${m}.yaml`),l.avatarPath&&r.info(` Avatar: ${E.basename(l.avatarPath)} \u2192 assets/media/authors/${m}${E.extname(l.avatarPath)}`);}if(r.info(`
90
90
  Changes:`),r.info(" \u2713 Create data/authors/ directory"),r.info(" \u2713 Generate YAML files with new schema (hugoblox/author/v1)"),r.info(" \u2713 Migrate avatar images to assets/media/authors/"),r.info(" \u2713 Update author references in content files"),r.info(" \u2713 Archive original content/authors/ directory"),t.dryRun){r.info(`
91
- \u{1F50D} Dry run mode - no files will be modified.`);return}if(!t.yes&&!await R(`
92
- This will restructure your author data. We recommend backing up first. Continue?`,{initial:!1})){r.info("Migration cancelled.");return}let c=await oo(o.root,a,r);if(r.info(""),c.success)r.success("\u2705 Migration complete!"),r.info(` \u2022 Migrated ${c.authorsMigrated} author profile(s)`),r.info(` \u2022 Updated ${c.contentFilesMigrated} content file(s)`),r.info(`
93
- \u{1F4DA} Next steps:`),r.info(" 1. Review generated files in data/authors/"),r.info(" 2. Test your site: pnpm dev"),r.info(" 3. Remove backup: rm -rf content/authors.backup");else {r.error("\u274C Migration completed with errors:");for(let l of c.errors)r.error(` \u2022 ${l}`);r.info(`
94
- Original files preserved in content/authors/`);}}catch(s){throw i.stop(),s}});}async function mn(n){let e=[],t=await _.readdir(n,{withFileTypes:true});for(let o of t){if(!o.isDirectory()||o.name.startsWith("_"))continue;let i=E.join(n,o.name),s=E.join(i,"_index.md");if(!await v(s))continue;let a=et(o.name);if(a)try{let c=await _.readFile(s,"utf8"),{frontMatter:l,body:m}=le(c),g,d=(await _.readdir(i)).find(f=>/^avatar\.(png|jpg|jpeg|webp)$/i.test(f));d&&(g=E.join(i,d)),e.push({slug:o.name,targetSlug:a,originalPath:i,frontMatter:l,content:m.trim(),avatarPath:g});}catch{}}let r=E.join(n,"_index.md");if(await v(r))try{let o=await _.readFile(r,"utf8"),{frontMatter:i,body:s}=le(o);if(Vr(i,s)){let a=y(i.slug)??"admin",c=a?et(a):void 0;if(c&&!e.some(l=>l.targetSlug===c)){let l,g=(await _.readdir(n)).find(w=>/^avatar\.(png|jpg|jpeg|webp)$/i.test(w));g&&(l=E.join(n,g)),e.push({slug:a,targetSlug:c,originalPath:n,frontMatter:i,content:s.trim(),avatarPath:l});}}}catch{}return e}function Vr(n,e){return e.trim()?true:["title","name","first_name","last_name","bio","profiles","organizations","affiliations","interests","education","work","skills","languages","role","status","pronouns","name_pronunciation"].some(r=>n[r]!==void 0)}function et(n){let e=z(n);if(e)return e==="admin"?"me":e}function y(n){if(typeof n!="string")return;let e=n.trim();return e===""?void 0:e}function he(n){return typeof n=="number"&&Number.isFinite(n)?n:y(n)}function Wr(n){return Array.isArray(n)?n.map(e=>y(e)).filter(e=>!!e):[]}function zr(n){let e={},t=y(n.title??n.name);t&&(e.display=t);let r=y(n.first_name??n.given_name??n.given);r&&(e.given=r);let o=y(n.last_name??n.family_name??n.family);o&&(e.family=o);let i=y(n.middle_name??n.middle);i&&(e.middle=i);let s=y(n.nickname??n.alternate_name??n.alt_name);s&&(e.alternate=s);let a=y(n.name_pronunciation??n.pronunciation);a&&(e.pronunciation=a);let c=y(n.pronouns);return c&&(e.pronouns=c),e}function Gr(n){if(n.status&&typeof n.status=="object"&&!Array.isArray(n.status)){let t=y(n.status.icon);if(t)return {icon:t}}let e=y(n.status_icon??n.status_emoji??n.status);if(e)return {icon:e}}function Xr(n){return Array.isArray(n)?n.map(e=>{if(typeof e!="object"||e===null)return;let t=e,r=y(t.name);if(!r)return;let o=y(t.url);return o?{name:r,url:o}:{name:r}}).filter(e=>!!e):[]}function qr(n){let e={},t=["orcid","google_scholar","openalex","semantic_scholar","research_gate","scopus","arxiv"];for(let i of t){let s=y(n[i]);s&&(e[i]=s);}let r=[];Array.isArray(n.profiles)&&r.push(...n.profiles);let o=n.links;Array.isArray(o)&&r.push(...o);for(let i of r){if(typeof i!="object"||i===null)continue;let s=y(i.url);s&&Jr(s,e);}return Object.keys(e).length===0?void 0:e}function Jr(n,e){if(/^https?:\/\//i.test(n))try{let t=new URL(n),r=t.hostname.toLowerCase(),o=t.pathname.split("/").filter(Boolean);if(r.includes("scholar.google.")){let i=t.searchParams.get("user");i&&!e.google_scholar&&(e.google_scholar=i);return}if(r.includes("orcid.org")){let i=t.pathname.match(/(\d{4}-\d{4}-\d{4}-\d{3}[0-9X])/i);i&&!e.orcid&&(e.orcid=i[1]);return}if(r.includes("openalex.org")){let i=o[o.length-1];i&&!e.openalex&&(e.openalex=i);return}if(r.includes("semanticscholar.org")){let i=o[o.length-1];i&&!e.semantic_scholar&&(e.semantic_scholar=i);return}if(r.includes("researchgate.net")){let i=o[o.length-1];i&&!e.research_gate&&(e.research_gate=i);return}if(r.includes("scopus.com")){let i=t.searchParams.get("authorId")??t.searchParams.get("scopusId")??o[o.length-1];i&&!e.scopus&&(e.scopus=i);return}if(r.includes("arxiv.org")){let i=o[o.length-1];i&&!e.arxiv&&(e.arxiv=i);}}catch{}}function Kr(n,e,t){let r=[];if(Array.isArray(n))for(let s of n){if(typeof s!="object"||s===null)continue;let a=s,c=y(a.icon),l=y(a.url),m=y(a.label);if(c&&l){let g={icon:c,url:l};m&&(g.label=m),r.push(g);}}let o=y(t);if(o){let s=o.startsWith("mailto:")?o:`mailto:${o}`;r.some(a=>a.url===s)||r.push({icon:"at-symbol",url:s,label:"Email"});}let i=y(e);return i&&!r.some(s=>s.url===i)&&r.push({icon:"link",url:i,label:"Website"}),r}function Yr(n){if(typeof n=="string"){let e=n.trim();return e||void 0}if(Array.isArray(n)){let e=n.map(t=>y(t)).filter(t=>!!t);if(e.length>0)return e}}function Qr(n){return Array.isArray(n)?n.map(e=>{if(typeof e!="object"||e===null)return;let t=e,r=y(t.institution??t.organization??t.school);if(!r)return;let o={institution:r},i=y(t.degree??t.area??t.qualification);i&&(o.degree=i);let s=he(t.year);s!==void 0&&(o.year=s);let a=he(t.start??t.date_start);a!==void 0&&(o.start=a);let c=he(t.end??t.date_end);c!==void 0&&(o.end=c);let l=y(t.summary);l&&(o.summary=l);let m=dn(t.button);return m&&(o.button=m),o}).filter(e=>!!e):[]}function Zr(n){return Array.isArray(n)?n.map(e=>{if(typeof e!="object"||e===null)return;let t=e,r=y(t.role??t.position),o=y(t.org??t.company_name??t.company);if(!r||!o)return;let i={role:r,org:o},s=he(t.start??t.date_start);s!==void 0&&(i.start=s);let a=he(t.end??t.date_end);a!==void 0&&(i.end=a);let c=y(t.summary);c&&(i.summary=c);let l=dn(t.button);return l&&(i.button=l),i}).filter(e=>!!e):[]}function dn(n){if(typeof n!="object"||n===null)return;let e=n,t=y(e.url);if(!t)return;let r={url:t},o=y(e.text);o&&(r.text=o);let i=y(e.icon);return i&&(r.icon=i),r}function eo(n){return Array.isArray(n)?n.map(e=>{if(typeof e!="object"||e===null)return;let t=e,o=(Array.isArray(t.items)?t.items:[]).map(a=>{if(typeof a!="object"||a===null)return;let c=a,l=y(c.label??c.name);if(!l)return;let m={label:l},g=un(c.level)??tt(typeof c.percent=="number"?c.percent:void 0);g!==void 0&&(m.level=g);let w=y(c.icon);return w&&(m.icon=w),m}).filter(a=>!!a);if(o.length===0)return;let i={items:o},s=y(t.name);return s&&(i.name=s),i}).filter(e=>!!e):[]}function tt(n){if(typeof n!="number"||Number.isNaN(n)||n<=0)return;let e=Math.min(100,n);return Math.max(1,Math.min(5,Math.ceil(e/20)))}function un(n){if(!(typeof n!="number"||Number.isNaN(n)))return n>=1&&n<=5?Math.round(n):tt(n)}function to(n){return Array.isArray(n)?n.map(e=>{if(typeof e=="string"){let c=y(e);return c?{name:c}:void 0}if(typeof e!="object"||e===null)return;let t=e,r=y(t.name??t.label);if(!r)return;let o=typeof t.percent=="number"?Math.max(0,Math.min(100,t.percent)):void 0,i=un(t.level)??tt(o),s={name:r};i!==void 0&&(s.level=i),o!==void 0&&(s.percent=o);let a=y(t.label)??no(o,i);return a&&(s.label=a),s}).filter(e=>!!e):[]}function no(n,e){let t=n??(typeof e=="number"?e*20:void 0);if(t!==void 0){if(t>=99)return "Native";if(t>=90)return "C2";if(t>=75)return "C1";if(t>=60)return "B2";if(t>=45)return "B1";if(t>=30)return "A2"}}function ro(n){return Array.isArray(n)?n.map(e=>{if(typeof e=="string"){let l=y(e);return l?{title:l}:void 0}if(typeof e!="object"||e===null)return;let t=e,r=y(t.title);if(!r)return;let o={title:r},i=y(t.awarder);i&&(o.awarder=i);let s=y(t.date);s&&(o.date=s);let a=y(t.summary);a&&(o.summary=a);let c=y(t.icon);return c&&(o.icon=c),o}).filter(e=>!!e):[]}function pn(n,e){let{frontMatter:t,content:r}=n,o={schema:"hugoblox/author/v1",slug:e},i=zr(t);Object.keys(i).length>0&&(o.name=i),t.superuser===true&&(o.is_owner=true);let s=Gr(t);s&&(o.status=s);let a=y(t.role);a&&(o.role=a);let c=y(t.bio)??r.trim();c&&(o.bio=c);let l=Xr(t.organizations??t.affiliations);l.length>0&&(o.affiliations=l);let m=qr(t);m&&(o.ids=m);let g=[];Array.isArray(t.profiles)&&g.push(...t.profiles);let w=t.links;Array.isArray(w)&&g.push(...w);let d=Kr(g,t.website,t.email);d.length>0&&(o.links=d);let f=Wr(t.interests);f.length>0&&(o.interests=f);let h=Yr(t.postnominals??t.credentials);h&&(o.postnominals=h);let p=Qr(t.education);p.length>0&&(o.education=p);let b=Zr(t.work??t.experience);b.length>0&&(o.experience=b);let P=eo(t.skills);P.length>0&&(o.skills=P);let x=to(t.languages);x.length>0&&(o.languages=x);let C=ro(t.awards);return C.length>0&&(o.awards=C),typeof t.weight=="number"&&Number.isFinite(t.weight)&&(o.weight=Math.trunc(t.weight)),o}async function fn(n,e,t){let r=E.extname(n)||".png",o=E.join(e,`${t}${r}`);return await _.copyFile(n,o),o}async function oo(n,e,t){let r={success:true,authorsMigrated:0,contentFilesMigrated:0,errors:[]},o=Ve("Creating backup...").start(),i=E.join(n,"content","authors"),s=E.join(n,"content","authors.backup");try{if(await v(s)){let f=new Date().toISOString().replace(/[:.]/g,"-").split(".")[0],h=`${s}.${f}`;o.text=`Existing backup found, creating timestamped backup: ${E.basename(h)}`,await _.cp(i,h,{recursive:!0}),t.info(` Previous backup preserved as: ${E.basename(h)}`);}else await _.cp(i,s,{recursive:!0});o.text="Backup created, migrating author profiles...";let a=E.join(n,"data","authors"),c=E.join(n,"assets","media","authors");if(await v(a)){let h=(await _.readdir(a)).filter(p=>p.endsWith(".yaml")||p.endsWith(".yml"));if(h.length>0)throw o.stop(),new u(`data/authors/ already contains ${h.length} YAML file(s).
95
- Please remove or back them up manually before running migration.`)}await $(a),await $(c);let l=new Map,m=new Set,g=[],w=[];for(let f of e){let h=f.targetSlug??et(f.slug);if(!h){w.push(f.slug);continue}m.has(h)&&g.push(h),m.add(h);let p=new Set([f.slug]),b=f.slug.toLowerCase();b!==f.slug&&p.add(b);let P=z(f.slug);P&&P!==f.slug&&p.add(P);for(let x of p)l.has(x)||l.set(x,h);}if(w.length>0)throw o.stop(),new u(`Unable to normalize the following author slug(s): ${w.join(", ")}
96
- Please rename them to use lowercase letters, numbers, or hyphens.`);if(g.length>0)throw o.stop(),new u(`Slug collision detected: Multiple profiles would map to: ${g.join(", ")}
97
- Please manually rename one of the conflicting profiles before migration.`);for(let f=0;f<e.length;f++){let h=e[f];o.text=`Migrating profiles... (${f+1}/${e.length})`;try{let p=l.get(h.slug);if(!p)throw new u(`Unable to determine target slug for '${h.slug}'`);let b=pn(h,p),P=E.join(a,`${p}.yaml`),x=Ze.stringify(b,{defaultStringType:"QUOTE_DOUBLE",lineWidth:0});try{let C=Ze.parse(x);if(!C.schema||!C.slug)throw new Error("Generated YAML missing required fields")}catch(C){throw new Error(`Invalid YAML generated: ${String(C)}`)}if(await _.writeFile(P,x,"utf8"),h.avatarPath)try{await fn(h.avatarPath,c,p);}catch(C){r.errors.push(`\u2713 Profile '${h.slug}' migrated, but avatar copy failed: ${String(C)}`);}r.authorsMigrated++;}catch(p){r.errors.push(`Failed to migrate ${h.slug}: ${String(p)}`),r.success=!1;}}o.text="Updating content references...";let d=E.join(n,"content");if(await v(d)){let f=await gn(d,l);r.contentFilesMigrated=f;}o.text="Finalizing migration...",await _.rm(i,{recursive:!0,force:!0}),o.succeed("Migration complete");}catch(a){o.fail("Migration failed"),r.success=false,r.errors.push(String(a));try{t.warn("\u26A0\uFE0F Attempting to rollback changes..."),!await v(i)&&await v(s)&&(await _.cp(s,i,{recursive:!0}),t.info(" \u2713 Original authors directory restored from backup"));let c=E.join(n,"data","authors");await v(c)&&(await _.readdir(c)).filter(w=>w.endsWith(".yaml")).length===r.authorsMigrated&&(await _.rm(c,{recursive:!0,force:!0}),t.info(" \u2713 Partial data/authors/ files removed"));let l=E.join(n,"assets","media","authors");await v(l)&&(await _.readdir(l)).length<=r.authorsMigrated&&(await _.rm(l,{recursive:!0,force:!0}),t.info(" \u2713 Partial avatar files removed")),t.info("\u2713 Rollback complete. Your original files are safe.");}catch(c){r.errors.push(`Rollback failed: ${String(c)}`),t.error("\u274C Rollback failed. Please manually check:"),t.error(" - content/authors.backup/ contains your original files"),t.error(" - You may need to manually restore them");}}return r}async function gn(n,e){let t=0;for await(let r of me(n))try{let o=await _.readFile(r,"utf8"),{frontMatter:i,body:s}=le(o),a=!1;if(Array.isArray(i.authors)){let c=i.authors.map(l=>{if(typeof l=="string"){let m=l.trim(),g=m.toLowerCase(),w=e.get(m)??e.get(l)??e.get(g);if(w)return a=!0,w}return l});i.authors=c;}if(a){let c=`---
98
- ${Ze.stringify(i)}---
91
+ \u{1F50D} Dry run mode - no files will be modified.`);return}if(!t.yes&&!await H(`
92
+ This will restructure your author data. We recommend backing up first. Continue?`,{initial:!1})){r.info("Migration cancelled.");return}let a=await mo(o.root,c,r);if(r.info(""),a.success)r.success("\u2705 Migration complete!"),r.info(` \u2022 Migrated ${a.authorsMigrated} author profile(s)`),r.info(` \u2022 Updated ${a.contentFilesMigrated} content file(s)`),r.info(`
93
+ \u{1F4DA} Next steps:`),r.info(" 1. Review generated files in data/authors/"),r.info(" 2. Test your site: pnpm dev"),r.info(" 3. Remove backup: rm -rf content/authors.backup");else {r.error("\u274C Migration completed with errors:");for(let l of a.errors)r.error(` \u2022 ${l}`);r.info(`
94
+ Original files preserved in content/authors/`);}}catch(s){throw i.stop(),s}});}async function bn(n){let e=[],t=await $.readdir(n,{withFileTypes:true});for(let o of t){if(!o.isDirectory()||o.name.startsWith("_"))continue;let i=E.join(n,o.name),s=E.join(i,"_index.md");if(!await v(s))continue;let c=ot(o.name);if(c)try{let a=await $.readFile(s,"utf8"),{frontMatter:l,body:m}=de(a),p,d=(await $.readdir(i)).find(g=>/^avatar\.(png|jpg|jpeg|webp)$/i.test(g));d&&(p=E.join(i,d)),e.push({slug:o.name,targetSlug:c,originalPath:i,frontMatter:l,content:m.trim(),avatarPath:p});}catch{}}let r=E.join(n,"_index.md");if(await v(r))try{let o=await $.readFile(r,"utf8"),{frontMatter:i,body:s}=de(o);if(Jr(i,s)){let c=y(i.slug)??"admin",a=c?ot(c):void 0;if(a&&!e.some(l=>l.targetSlug===a)){let l,p=(await $.readdir(n)).find(w=>/^avatar\.(png|jpg|jpeg|webp)$/i.test(w));p&&(l=E.join(n,p)),e.push({slug:c,targetSlug:a,originalPath:n,frontMatter:i,content:s.trim(),avatarPath:l});}}}catch{}return e}function Jr(n,e){return e.trim()?true:["title","name","first_name","last_name","bio","profiles","organizations","affiliations","interests","education","work","skills","languages","role","status","pronouns","name_pronunciation"].some(r=>n[r]!==void 0)}function ot(n){let e=z(n);if(e)return e==="admin"?"me":e}function y(n){if(typeof n!="string")return;let e=n.trim();return e===""?void 0:e}function be(n){return typeof n=="number"&&Number.isFinite(n)?n:y(n)}function Kr(n){return Array.isArray(n)?n.map(e=>y(e)).filter(e=>!!e):[]}function Yr(n){let e={},t=y(n.title??n.name);t&&(e.display=t);let r=y(n.first_name??n.given_name??n.given);r&&(e.given=r);let o=y(n.last_name??n.family_name??n.family);o&&(e.family=o);let i=y(n.middle_name??n.middle);i&&(e.middle=i);let s=y(n.nickname??n.alternate_name??n.alt_name);s&&(e.alternate=s);let c=y(n.name_pronunciation??n.pronunciation);c&&(e.pronunciation=c);let a=y(n.pronouns);return a&&(e.pronouns=a),e}function Qr(n){if(n.status&&typeof n.status=="object"&&!Array.isArray(n.status)){let t=y(n.status.icon);if(t)return {icon:t}}let e=y(n.status_icon??n.status_emoji??n.status);if(e)return {icon:e}}function Zr(n){return Array.isArray(n)?n.map(e=>{if(typeof e!="object"||e===null)return;let t=e,r=y(t.name);if(!r)return;let o=y(t.url);return o?{name:r,url:o}:{name:r}}).filter(e=>!!e):[]}function eo(n){let e={},t=["orcid","google_scholar","openalex","semantic_scholar","research_gate","scopus","arxiv"];for(let i of t){let s=y(n[i]);s&&(e[i]=s);}let r=[];Array.isArray(n.profiles)&&r.push(...n.profiles);let o=n.links;Array.isArray(o)&&r.push(...o);for(let i of r){if(typeof i!="object"||i===null)continue;let s=y(i.url);s&&to(s,e);}return Object.keys(e).length===0?void 0:e}function to(n,e){if(/^https?:\/\//i.test(n))try{let t=new URL(n),r=t.hostname.toLowerCase(),o=t.pathname.split("/").filter(Boolean);if(r.includes("scholar.google.")){let i=t.searchParams.get("user");i&&!e.google_scholar&&(e.google_scholar=i);return}if(r.includes("orcid.org")){let i=t.pathname.match(/(\d{4}-\d{4}-\d{4}-\d{3}[0-9X])/i);i&&!e.orcid&&(e.orcid=i[1]);return}if(r.includes("openalex.org")){let i=o[o.length-1];i&&!e.openalex&&(e.openalex=i);return}if(r.includes("semanticscholar.org")){let i=o[o.length-1];i&&!e.semantic_scholar&&(e.semantic_scholar=i);return}if(r.includes("researchgate.net")){let i=o[o.length-1];i&&!e.research_gate&&(e.research_gate=i);return}if(r.includes("scopus.com")){let i=t.searchParams.get("authorId")??t.searchParams.get("scopusId")??o[o.length-1];i&&!e.scopus&&(e.scopus=i);return}if(r.includes("arxiv.org")){let i=o[o.length-1];i&&!e.arxiv&&(e.arxiv=i);}}catch{}}function no(n,e,t){let r=[];if(Array.isArray(n))for(let s of n){if(typeof s!="object"||s===null)continue;let c=s,a=y(c.icon),l=y(c.url),m=y(c.label);if(a&&l){let p={icon:a,url:l};m&&(p.label=m),r.push(p);}}let o=y(t);if(o){let s=o.startsWith("mailto:")?o:`mailto:${o}`;r.some(c=>c.url===s)||r.push({icon:"at-symbol",url:s,label:"Email"});}let i=y(e);return i&&!r.some(s=>s.url===i)&&r.push({icon:"link",url:i,label:"Website"}),r}function ro(n){if(typeof n=="string"){let e=n.trim();return e||void 0}if(Array.isArray(n)){let e=n.map(t=>y(t)).filter(t=>!!t);if(e.length>0)return e}}function oo(n){return Array.isArray(n)?n.map(e=>{if(typeof e!="object"||e===null)return;let t=e,r=y(t.institution??t.organization??t.school);if(!r)return;let o={institution:r},i=y(t.degree??t.area??t.qualification);i&&(o.degree=i);let s=be(t.year);s!==void 0&&(o.year=s);let c=be(t.start??t.date_start);c!==void 0&&(o.start=c);let a=be(t.end??t.date_end);a!==void 0&&(o.end=a);let l=y(t.summary);l&&(o.summary=l);let m=vn(t.button);return m&&(o.button=m),o}).filter(e=>!!e):[]}function io(n){return Array.isArray(n)?n.map(e=>{if(typeof e!="object"||e===null)return;let t=e,r=y(t.role??t.position),o=y(t.org??t.company_name??t.company);if(!r||!o)return;let i={role:r,org:o},s=be(t.start??t.date_start);s!==void 0&&(i.start=s);let c=be(t.end??t.date_end);c!==void 0&&(i.end=c);let a=y(t.summary);a&&(i.summary=a);let l=vn(t.button);return l&&(i.button=l),i}).filter(e=>!!e):[]}function vn(n){if(typeof n!="object"||n===null)return;let e=n,t=y(e.url);if(!t)return;let r={url:t},o=y(e.text);o&&(r.text=o);let i=y(e.icon);return i&&(r.icon=i),r}function so(n){return Array.isArray(n)?n.map(e=>{if(typeof e!="object"||e===null)return;let t=e,o=(Array.isArray(t.items)?t.items:[]).map(c=>{if(typeof c!="object"||c===null)return;let a=c,l=y(a.label??a.name);if(!l)return;let m={label:l},p=xn(a.level)??it(typeof a.percent=="number"?a.percent:void 0);p!==void 0&&(m.level=p);let w=y(a.icon);return w&&(m.icon=w),m}).filter(c=>!!c);if(o.length===0)return;let i={items:o},s=y(t.name);return s&&(i.name=s),i}).filter(e=>!!e):[]}function it(n){if(typeof n!="number"||Number.isNaN(n)||n<=0)return;let e=Math.min(100,n);return Math.max(1,Math.min(5,Math.ceil(e/20)))}function xn(n){if(!(typeof n!="number"||Number.isNaN(n)))return n>=1&&n<=5?Math.round(n):it(n)}function ao(n){return Array.isArray(n)?n.map(e=>{if(typeof e=="string"){let a=y(e);return a?{name:a}:void 0}if(typeof e!="object"||e===null)return;let t=e,r=y(t.name??t.label);if(!r)return;let o=typeof t.percent=="number"?Math.max(0,Math.min(100,t.percent)):void 0,i=xn(t.level)??it(o),s={name:r};i!==void 0&&(s.level=i),o!==void 0&&(s.percent=o);let c=y(t.label)??co(o,i);return c&&(s.label=c),s}).filter(e=>!!e):[]}function co(n,e){let t=n??(typeof e=="number"?e*20:void 0);if(t!==void 0){if(t>=99)return "Native";if(t>=90)return "C2";if(t>=75)return "C1";if(t>=60)return "B2";if(t>=45)return "B1";if(t>=30)return "A2"}}function lo(n){return Array.isArray(n)?n.map(e=>{if(typeof e=="string"){let l=y(e);return l?{title:l}:void 0}if(typeof e!="object"||e===null)return;let t=e,r=y(t.title);if(!r)return;let o={title:r},i=y(t.awarder);i&&(o.awarder=i);let s=y(t.date);s&&(o.date=s);let c=y(t.summary);c&&(o.summary=c);let a=y(t.icon);return a&&(o.icon=a),o}).filter(e=>!!e):[]}function Cn(n,e){let{frontMatter:t,content:r}=n,o={schema:"hugoblox/author/v1",slug:e},i=Yr(t);Object.keys(i).length>0&&(o.name=i),t.superuser===true&&(o.is_owner=true);let s=Qr(t);s&&(o.status=s);let c=y(t.role);c&&(o.role=c);let a=y(t.bio)??r.trim();a&&(o.bio=a);let l=Zr(t.organizations??t.affiliations);l.length>0&&(o.affiliations=l);let m=eo(t);m&&(o.ids=m);let p=[];Array.isArray(t.profiles)&&p.push(...t.profiles);let w=t.links;Array.isArray(w)&&p.push(...w);let d=no(p,t.website,t.email);d.length>0&&(o.links=d);let g=Kr(t.interests);g.length>0&&(o.interests=g);let h=ro(t.postnominals??t.credentials);h&&(o.postnominals=h);let f=oo(t.education);f.length>0&&(o.education=f);let b=io(t.work??t.experience);b.length>0&&(o.experience=b);let P=so(t.skills);P.length>0&&(o.skills=P);let x=ao(t.languages);x.length>0&&(o.languages=x);let C=lo(t.awards);return C.length>0&&(o.awards=C),typeof t.weight=="number"&&Number.isFinite(t.weight)&&(o.weight=Math.trunc(t.weight)),o}async function Pn(n,e,t){let r=E.extname(n)||".png",o=E.join(e,`${t}${r}`);return await $.copyFile(n,o),o}async function mo(n,e,t){let r={success:true,authorsMigrated:0,contentFilesMigrated:0,errors:[]},o=Ge("Creating backup...").start(),i=E.join(n,"content","authors"),s=E.join(n,"content","authors.backup");try{if(await v(s)){let g=new Date().toISOString().replace(/[:.]/g,"-").split(".")[0],h=`${s}.${g}`;o.text=`Existing backup found, creating timestamped backup: ${E.basename(h)}`,await $.cp(i,h,{recursive:!0}),t.info(` Previous backup preserved as: ${E.basename(h)}`);}else await $.cp(i,s,{recursive:!0});o.text="Backup created, migrating author profiles...";let c=E.join(n,"data","authors"),a=E.join(n,"assets","media","authors");if(await v(c)){let h=(await $.readdir(c)).filter(f=>f.endsWith(".yaml")||f.endsWith(".yml"));if(h.length>0)throw o.stop(),new u(`data/authors/ already contains ${h.length} YAML file(s).
95
+ Please remove or back them up manually before running migration.`)}await _(c),await _(a);let l=new Map,m=new Set,p=[],w=[];for(let g of e){let h=g.targetSlug??ot(g.slug);if(!h){w.push(g.slug);continue}m.has(h)&&p.push(h),m.add(h);let f=new Set([g.slug]),b=g.slug.toLowerCase();b!==g.slug&&f.add(b);let P=z(g.slug);P&&P!==g.slug&&f.add(P);for(let x of f)l.has(x)||l.set(x,h);}if(w.length>0)throw o.stop(),new u(`Unable to normalize the following author slug(s): ${w.join(", ")}
96
+ Please rename them to use lowercase letters, numbers, or hyphens.`);if(p.length>0)throw o.stop(),new u(`Slug collision detected: Multiple profiles would map to: ${p.join(", ")}
97
+ Please manually rename one of the conflicting profiles before migration.`);for(let g=0;g<e.length;g++){let h=e[g];o.text=`Migrating profiles... (${g+1}/${e.length})`;try{let f=l.get(h.slug);if(!f)throw new u(`Unable to determine target slug for '${h.slug}'`);let b=Cn(h,f),P=E.join(c,`${f}.yaml`),x=rt.stringify(b,{defaultStringType:"QUOTE_DOUBLE",lineWidth:0});try{let C=rt.parse(x);if(!C.schema||!C.slug)throw new Error("Generated YAML missing required fields")}catch(C){throw new Error(`Invalid YAML generated: ${String(C)}`)}if(await $.writeFile(P,x,"utf8"),h.avatarPath)try{await Pn(h.avatarPath,a,f);}catch(C){r.errors.push(`\u2713 Profile '${h.slug}' migrated, but avatar copy failed: ${String(C)}`);}r.authorsMigrated++;}catch(f){r.errors.push(`Failed to migrate ${h.slug}: ${String(f)}`),r.success=!1;}}o.text="Updating content references...";let d=E.join(n,"content");if(await v(d)){let g=await Sn(d,l);r.contentFilesMigrated=g;}o.text="Finalizing migration...",await $.rm(i,{recursive:!0,force:!0}),o.succeed("Migration complete");}catch(c){o.fail("Migration failed"),r.success=false,r.errors.push(String(c));try{t.warn("\u26A0\uFE0F Attempting to rollback changes..."),!await v(i)&&await v(s)&&(await $.cp(s,i,{recursive:!0}),t.info(" \u2713 Original authors directory restored from backup"));let a=E.join(n,"data","authors");await v(a)&&(await $.readdir(a)).filter(w=>w.endsWith(".yaml")).length===r.authorsMigrated&&(await $.rm(a,{recursive:!0,force:!0}),t.info(" \u2713 Partial data/authors/ files removed"));let l=E.join(n,"assets","media","authors");await v(l)&&(await $.readdir(l)).length<=r.authorsMigrated&&(await $.rm(l,{recursive:!0,force:!0}),t.info(" \u2713 Partial avatar files removed")),t.info("\u2713 Rollback complete. Your original files are safe.");}catch(a){r.errors.push(`Rollback failed: ${String(a)}`),t.error("\u274C Rollback failed. Please manually check:"),t.error(" - content/authors.backup/ contains your original files"),t.error(" - You may need to manually restore them");}}return r}async function Sn(n,e){let t=0;for await(let r of ue(n))try{let o=await $.readFile(r,"utf8"),{frontMatter:i,body:s}=de(o),c=!1;if(Array.isArray(i.authors)){let a=i.authors.map(l=>{if(typeof l=="string"){let m=l.trim(),p=m.toLowerCase(),w=e.get(m)??e.get(l)??e.get(p);if(w)return c=!0,w}return l});i.authors=a;}if(c){let a=`---
98
+ ${rt.stringify(i)}---
99
99
 
100
- ${s}`;await _.writeFile(r,c,"utf8"),t++;}}catch{}return t}function hn(n,e){n.command("v0.11.0-events").description("Migrate legacy events content to HugoBlox v0.11.0 conventions").option("-y, --yes","Skip confirmation prompts").option("--dry-run","Preview changes without modifying files").action(async t=>{let{logger:r}=e,o=await D();if(!o)throw new u("No Hugo project found in the current directory.");let i=Ve("Analyzing event content...").start();try{let s=E.join(o.root,"content","event"),a=E.join(o.root,"content","events"),c=await v(s),l=await v(a),m;if(l?m=a:c&&(m=s),!m){i.stop(),r.info("\u2139\uFE0F No legacy event content found under content/event/ or content/events/.");return}let g=await co(m),w=c&&!l;if(i.stop(),r.info(`
100
+ ${s}`;await $.writeFile(r,a,"utf8"),t++;}}catch{}return t}function kn(n,e){n.command("v0.11.0-events").description("Migrate legacy events content to HugoBlox v0.11.0 conventions").option("-y, --yes","Skip confirmation prompts").option("--dry-run","Preview changes without modifying files").action(async t=>{let{logger:r}=e,o=await D();if(!o)throw new u("No Hugo project found in the current directory.");let i=Ge("Analyzing event content...").start();try{let s=E.join(o.root,"content","event"),c=E.join(o.root,"content","events"),a=await v(s),l=await v(c),m;if(l?m=c:a&&(m=s),!m){i.stop(),r.info("\u2139\uFE0F No legacy event content found under content/event/ or content/events/.");return}let p=await go(m),w=a&&!l;if(i.stop(),r.info(`
101
101
  \u{1F4CB} Migration Plan (v0.11.0 Events):
102
- `),w?r.info(" \u2713 Rename content/event/ \u2192 content/events/"):c&&l?r.info(" \u2713 content/events/ already exists (no rename needed)"):c?r.info(" \u2713 Legacy content/event/ directory detected (will be renamed)."):r.info(" \u2713 No legacy directory rename required"),r.info(` \u2713 Update front matter for ${g} event file(s)`),g===0&&!w){r.info(`
102
+ `),w?r.info(" \u2713 Rename content/event/ \u2192 content/events/"):a&&l?r.info(" \u2713 content/events/ already exists (no rename needed)"):a?r.info(" \u2713 Legacy content/event/ directory detected (will be renamed)."):r.info(" \u2713 No legacy directory rename required"),r.info(` \u2713 Update front matter for ${p} event file(s)`),p===0&&!w){r.info(`
103
103
  \u2139\uFE0F No event markdown files were found to migrate.`);return}if(t.dryRun){r.info(`
104
- \u{1F50D} Dry run mode - no files will be modified.`);return}if(!t.yes&&!await R(`
105
- This will rename event directories (if needed) and adjust front matter. Continue?`,{initial:!1})){r.info("Migration cancelled.");return}if(w){let p=Ve("Renaming content/event/ to content/events/...").start();await _.rename(s,a),p.succeed("Renamed legacy event directory.");}let d=await v(a)?a:m;if(!d)throw new u("No event directory found to migrate after analysis.");let f=Ve("Updating event front matter...").start(),h=await so(d);if(f.stop(),r.info(""),h.errors.length>0){r.error("\u274C Front matter migration completed with errors:");for(let p of h.errors)r.error(` \u2022 ${E.relative(o.root,p.file)}: ${p.message}`);throw new u("Event front matter migration encountered errors. Please resolve them and rerun the command.")}r.success("\u2705 Event migration complete!"),r.info(` \u2022 Processed ${h.processed} file(s)`),r.info(` \u2022 Updated ${h.updated} file(s)`);}catch(s){throw i.fail("Event migration failed"),s instanceof u?s:new u(`Event migration failed: ${String(s)}`)}});}async function so(n){let e={processed:0,updated:0,errors:[]};for await(let t of me(n))try{let r=await _.readFile(t,"utf8"),{frontMatter:o,body:i}=le(r),{migrated:s,changed:a}=ao(o);if(!a){e.processed+=1;continue}let l=`---
106
- ${Ze.stringify(s,{lineWidth:0})}---
104
+ \u{1F50D} Dry run mode - no files will be modified.`);return}if(!t.yes&&!await H(`
105
+ This will rename event directories (if needed) and adjust front matter. Continue?`,{initial:!1})){r.info("Migration cancelled.");return}if(w){let f=Ge("Renaming content/event/ to content/events/...").start();await $.rename(s,c),f.succeed("Renamed legacy event directory.");}let d=await v(c)?c:m;if(!d)throw new u("No event directory found to migrate after analysis.");let g=Ge("Updating event front matter...").start(),h=await po(d);if(g.stop(),r.info(""),h.errors.length>0){r.error("\u274C Front matter migration completed with errors:");for(let f of h.errors)r.error(` \u2022 ${E.relative(o.root,f.file)}: ${f.message}`);throw new u("Event front matter migration encountered errors. Please resolve them and rerun the command.")}r.success("\u2705 Event migration complete!"),r.info(` \u2022 Processed ${h.processed} file(s)`),r.info(` \u2022 Updated ${h.updated} file(s)`);}catch(s){throw i.fail("Event migration failed"),s instanceof u?s:new u(`Event migration failed: ${String(s)}`)}});}async function po(n){let e={processed:0,updated:0,errors:[]};for await(let t of ue(n))try{let r=await $.readFile(t,"utf8"),{frontMatter:o,body:i}=de(r),{migrated:s,changed:c}=fo(o);if(!c){e.processed+=1;continue}let l=`---
106
+ ${rt.stringify(s,{lineWidth:0})}---
107
107
 
108
- ${i}`;await _.writeFile(t,l,"utf8"),e.processed+=1,e.updated+=1;}catch(r){e.errors.push({file:t,message:String(r)}),e.processed+=1;}return e}function ao(n){let e={...n},t=false,r=(i,s)=>{e[i]===void 0&&n[s]!==void 0&&(e[i]=n[s],t=true);};r("event_start","date"),r("event_end","date_end"),r("event_all_day","all_day"),r("event_name","event"),n.publishDate!==void 0&&e.date!==n.publishDate?(e.date=n.publishDate,t=true):n.publishDate===void 0&&n.date!==void 0&&e.date!==n.date&&(e.date=n.date,t=true);let o=i=>{i in e&&(delete e[i],t=true);};return o("publishDate"),o("date_end"),o("all_day"),o("event"),{migrated:e,changed:t}}async function co(n){let e=0;for await(let t of me(n))e+=1;return e}function yn(n,e){let t=n.command("migrate").description("Migrate HugoBlox project to newer versions");ln(t,e),hn(t,e);}function wn(n,e){let t=n.command("telemetry").description("Manage HugoBlox telemetry preferences");t.command("enable").description("Enable anonymous telemetry").action(async()=>{e.config.setTelemetryEnabled(true),await e.config.save(),e.logger.success("Telemetry enabled. Thanks for helping improve HugoBlox!");}),t.command("disable").description("Disable telemetry collection").action(async()=>{e.config.setTelemetryEnabled(false),await e.config.save(),e.logger.success("Telemetry disabled. You can re-enable it anytime.");}),t.command("status").description("Show whether telemetry is enabled").action(()=>{let r=e.config.isTelemetryEnabled();e.logger.info(`Telemetry is ${r?"enabled":"disabled"}.`);}),t.action(()=>{let r=e.config.isTelemetryEnabled();e.logger.info(`Telemetry is ${r?"enabled":"disabled"}.`),e.logger.info("Use 'hbx telemetry enable|disable' to change the setting.");});}async function vn(n,e,t){let r=N.coerce(e)?.version;if(!r)return;let o=[{path:"hugoblox.yaml",regex:/(hugo_version:\s*['"]?)([\d.]+)(['"]?)/,name:"hugoblox.yaml"},{path:"netlify.toml",regex:/(HUGO_VERSION\s*=\s*['"])([\d.]+)(['"])/,name:"netlify.toml"},{path:".github/workflows/deploy.yml",regex:/(WC_HUGO_VERSION:\s*['"]?)([\d.]+)(['"]?)/,name:"GitHub Actions"}];for(let i of o){let s=E.join(n,i.path);if(await v(s))try{let a=await _.readFile(s,"utf8"),c=a.match(i.regex);if(c){let l=c[2],m=N.coerce(l),g=N.coerce(r);if(m&&g&&N.lt(m,g)){let w=a.replace(i.regex,`$1${r}$3`);await _.writeFile(s,w,"utf8"),t.success(`Updated ${i.name} Hugo version to ${r}`);}}}catch{}}}function Pn(n,e){n.command("upgrade").alias("update").description("Upgrade HugoBlox modules to the latest version").option("-y, --yes","Skip confirmation").option("--ci","Run in non-interactive mode").option("--force","Force upgrade even if Hugo version is incompatible").option("--canary","Upgrade to the latest development commit (main branch) instead of stable release").action(async(t,r)=>{let{logger:o}=e;await xt()||(o.error("\u274C You appear to be offline. Please check your internet connection."),process.exit(1));let i=await D();if(!i)throw new u("No Hugo project found in the current directory.");let s=Ve("Checking for updates...").start(),a=await Re(i.root);if(a.length===0){s.stop(),o.info("\u2139\uFE0F No official HugoBlox modules found in go.mod");return}let c=a.filter(d=>d.error);if(c.length>0){s.stop(),o.error("\u274C Failed to check for updates for some modules:");for(let d of c)o.error(` ${d.path}: ${d.error}`);process.exit(1);}let l=[];if(t.canary)s.text="Checking canary versions...",l.push(...a.map(d=>({path:d.path,version:"main"})));else {let d=a.map(f=>{let{updateAvailable:h,diff:p}=He(f.current,f.latest);return {...f,updateAvailable:h,diff:p}}).filter(f=>f.updateAvailable&&f.latest);if(d.length===0){s.stop(),o.success("\u2705 All HugoBlox modules are up to date");return}l.push(...d.map(f=>({path:f.path,version:f.latest||""})));}s.text="Checking version requirements...";let m=await Promise.all(l.map(async d=>{try{let f=await Zt(d.path,d.version);return {...d,min:f}}catch{return {...d,min:void 0}}}));if(s.stop(),!t.force){let d=await bt();if(d){let f=m.filter(h=>{if(!h.min)return false;let p=N.coerce(h.min),b=N.coerce(d);return p&&b&&N.lt(b,p)});if(f.length>0){o.error("\u274C Hugo version incompatible with upgrade targets:");for(let h of f)o.error(` ${h.path.split("/").pop()} requires Hugo >= ${h.min} (you have ${d})`);o.info("\u{1F449} Please upgrade Hugo first: https://docs.hugoblox.com/start/cli"),o.info(" Or run with --force to ignore this check."),process.exit(1);}}else o.warn("\u26A0\uFE0F Could not detect local Hugo version. Skipping compatibility check.");}if(t.canary){o.warn("\u26A0\uFE0F Upgrading modules to latest canary (development) version.");for(let d of a)o.info(` ${d.path.split("/").pop()}: ${ae(d.current)} -> @main`);}else {o.info(`\u{1F4E6} Updates available for ${l.length} module(s):`);for(let d of l){let f=a.find(h=>h.path===d.path)?.current||"?";o.info(` ${d.path.split("/").pop()}`),o.info(` Current: ${ae(f)}`),o.info(` Latest: ${ae(d.version)}`);}}if(!t.yes&&!t.ci&&!await R(t.canary?"Are you sure you want to upgrade to the bleeding edge?":"Do you want to upgrade now?",{initial:true})){o.info("Upgrade cancelled");return}let g=l.map(d=>`${d.path}@${d.version}`);await mo(i.root,g,o);let w=m.reduce((d,f)=>{if(!f.min)return d;let h=N.coerce(f.min),p=N.coerce(d);return h&&(!p||N.gt(h,p))?f.min:d},void 0);w&&await vn(i.root,w,o),o.info(""),o.warn("\u26A0\uFE0F Important: Please review the release notes for any breaking changes."),o.info("\u{1F449} https://github.com/HugoBlox/hugo-blox-builder/releases");});}async function mo(n,e,t){let r=Ve("Upgrading modules...").start();try{await execa("hugo",["mod","get",...e],{cwd:n}),r.text="Tidying go.mod...",await execa("hugo",["mod","tidy"],{cwd:n}),r.succeed(`\u2705 Upgraded ${e.length} module(s)`);}catch(o){r.fail("Failed to upgrade modules"),t.error(String(o)),process.exit(1);}}var K;function Y(){if(K)return K;let n=process.env.HBX_CLI_VERSION??process.env.npm_package_version;if(n)return K=n,K;let e=po(import.meta.url);try{let t=F.readFileSync(e,"utf8");K=JSON.parse(t).version??"0.0.0";}catch{K="0.0.0";}return K}function po(n){let e=E.dirname(fileURLToPath(n)),t=E.resolve(e,"../package.json");return F.existsSync(t)?t:E.resolve(e,"../../package.json")}function kn(n,e){n.command("version").description("Print CLI version").action((t,r)=>{let{logger:o}=e,i=!!r.optsWithGlobals().json,s=Y(),a={status:"success",version:s};i?o.json(a):o.info(`hbx ${s}`);});}var ue=class n{#e;constructor(e){this.#e=e;}static async load(){try{let e=await _.readFile(Pe,"utf8"),t=JSON.parse(e);return new n(t)}catch(e){if(e.code==="ENOENT")return new n({});throw new we("Failed to read configuration",{error:e})}}toJSON(){return this.#e}getLicense(){return process.env[ee]??this.#e.token}setLicense(e){this.#e={...this.#e,token:e};}clearLicense(){let e={...this.#e};e.token=void 0,e.device=void 0,this.#e=e;}isTelemetryEnabled(){return process.env[mt]==="1"?false:typeof this.#e.telemetry?.enabled=="boolean"?this.#e.telemetry.enabled:true}setTelemetryEnabled(e){this.#e={...this.#e,telemetry:{...this.#e.telemetry,enabled:e,lastPrompted:Date.now()}};}getTelemetryId(){return this.#e.telemetry?.id}async ensureTelemetryId(){let e=this.getTelemetryId();if(e)return e;let t=ge.randomUUID();return this.#e={...this.#e,telemetry:{...this.#e.telemetry,id:t}},await this.save(),t}getDefaultTemplate(){return this.#e.defaults?.template}getUpdateMetadata(){return this.#e.updates}setUpdateMetadata(e){this.#e={...this.#e,updates:{...this.#e.updates,...e}};}getDeviceInfo(){return this.#e.device}setDeviceInfo(e){this.#e={...this.#e,device:e};}async save(){await _.mkdir(Oe,{recursive:true});let e=JSON.stringify(this.#e,null,2);await _.writeFile(Pe,e,{mode:384}),await _.chmod(Pe,384);}};var pe=class{#e;#t;constructor(e={}){this.#e=e.json??false,this.#t=e.debug??process.env[G]==="1";}isJsonMode(){return this.#e}setJsonMode(e){this.#e=e;}setDebug(e){this.#t=e;}info(e){this.#e||process.stdout.write(`${ye.blue("i")} ${e}
109
- `);}success(e){this.#e||process.stdout.write(`${ye.green("\u2714")} ${e}
110
- `);}warn(e){this.#e||process.stdout.write(`${ye.yellow("!")} ${e}
111
- `);}error(e){this.#e||process.stderr.write(`${ye.red("\u2716")} ${e}
112
- `);}debug(e){!this.#t||this.#e||process.stdout.write(`${ye.gray("debug")} ${e}
108
+ ${i}`;await $.writeFile(t,l,"utf8"),e.processed+=1,e.updated+=1;}catch(r){e.errors.push({file:t,message:String(r)}),e.processed+=1;}return e}function fo(n){let e={...n},t=false,r=(i,s)=>{e[i]===void 0&&n[s]!==void 0&&(e[i]=n[s],t=true);};r("event_start","date"),r("event_end","date_end"),r("event_all_day","all_day"),r("event_name","event"),n.publishDate!==void 0&&e.date!==n.publishDate?(e.date=n.publishDate,t=true):n.publishDate===void 0&&n.date!==void 0&&e.date!==n.date&&(e.date=n.date,t=true);let o=i=>{i in e&&(delete e[i],t=true);};return o("publishDate"),o("date_end"),o("all_day"),o("event"),{migrated:e,changed:t}}async function go(n){let e=0;for await(let t of ue(n))e+=1;return e}function En(n,e){let t=n.command("migrate").description("Migrate HugoBlox project to newer versions");wn(t,e),kn(t,e);}function Tn(n,e){let t=n.command("telemetry").description("Manage HugoBlox telemetry preferences");t.command("enable").description("Enable anonymous telemetry").action(async()=>{e.config.setTelemetryEnabled(true),await e.config.save(),e.logger.success("Telemetry enabled. Thanks for helping improve HugoBlox!");}),t.command("disable").description("Disable telemetry collection").action(async()=>{e.config.setTelemetryEnabled(false),await e.config.save(),e.logger.success("Telemetry disabled. You can re-enable it anytime.");}),t.command("status").description("Show whether telemetry is enabled").action(()=>{let r=e.config.isTelemetryEnabled();e.logger.info(`Telemetry is ${r?"enabled":"disabled"}.`);}),t.action(()=>{let r=e.config.isTelemetryEnabled();e.logger.info(`Telemetry is ${r?"enabled":"disabled"}.`),e.logger.info("Use 'hbx telemetry enable|disable' to change the setting.");});}async function _n(n,e,t){let r=M.coerce(e)?.version;if(!r)return;let o=[{path:"hugoblox.yaml",regex:/(hugo_version:\s*['"]?)([\d.]+)(['"]?)/,name:"hugoblox.yaml"},{path:"netlify.toml",regex:/(HUGO_VERSION\s*=\s*['"])([\d.]+)(['"])/,name:"netlify.toml"},{path:".github/workflows/deploy.yml",regex:/(WC_HUGO_VERSION:\s*['"]?)([\d.]+)(['"]?)/,name:"GitHub Actions"}];for(let i of o){let s=E.join(n,i.path);if(await v(s))try{let c=await $.readFile(s,"utf8"),a=c.match(i.regex);if(a){let l=a[2],m=M.coerce(l),p=M.coerce(r);if(m&&p&&M.lt(m,p)){let w=c.replace(i.regex,`$1${r}$3`);await $.writeFile(s,w,"utf8"),t.success(`Updated ${i.name} Hugo version to ${r}`);}}}catch{}}}function Hn(n,e){n.command("upgrade").alias("update").description("Upgrade HugoBlox modules to the latest version").option("-y, --yes","Skip confirmation").option("--ci","Run in non-interactive mode").option("--force","Force upgrade even if Hugo version is incompatible").option("--canary","Upgrade to the latest development commit (main branch) instead of stable release").action(async(t,r)=>{let{logger:o}=e;await kt()||(o.error("\u274C You appear to be offline. Please check your internet connection."),process.exit(1));let i=await D();if(!i)throw new u("No Hugo project found in the current directory.");await ln(i.root);let s=Ge("Checking for updates...").start(),c=await De(i.root);if(c.length===0){s.stop(),o.info("\u2139\uFE0F No official HugoBlox modules found in go.mod");return}let a=c.filter(d=>d.error);if(a.length>0){s.stop(),o.error("\u274C Failed to check for updates for some modules:");for(let d of a)o.error(` ${d.path}: ${d.error}`);process.exit(1);}let l=[];if(t.canary)s.text="Checking canary versions...",l.push(...c.map(d=>({path:d.path,version:"main"})));else {let d=c.map(g=>{let{updateAvailable:h,diff:f}=Be(g.current,g.latest);return {...g,updateAvailable:h,diff:f}}).filter(g=>g.updateAvailable&&g.latest);if(d.length===0){s.stop(),o.success("\u2705 All HugoBlox modules are up to date");return}l.push(...d.map(g=>({path:g.path,version:g.latest||""})));}s.text="Checking version requirements...";let m=await Promise.all(l.map(async d=>{try{let g=await cn(d.path,d.version);return {...d,min:g}}catch{return {...d,min:void 0}}}));if(s.stop(),!t.force){let d=await Pt();if(d){let g=m.filter(h=>{if(!h.min)return false;let f=M.coerce(h.min),b=M.coerce(d);return f&&b&&M.lt(b,f)});if(g.length>0){o.error("\u274C Hugo version incompatible with upgrade targets:");for(let h of g)o.error(` ${h.path.split("/").pop()} requires Hugo >= ${h.min} (you have ${d})`);o.info("\u{1F449} Please upgrade Hugo first: https://docs.hugoblox.com/start/cli"),o.info(" Or run with --force to ignore this check."),process.exit(1);}}else o.warn("\u26A0\uFE0F Could not detect local Hugo version. Skipping compatibility check.");}if(t.canary){o.warn("\u26A0\uFE0F Upgrading modules to latest canary (development) version.");for(let d of c)o.info(` ${d.path.split("/").pop()}: ${le(d.current)} -> @main`);}else {o.info(`\u{1F4E6} Updates available for ${l.length} module(s):`);for(let d of l){let g=c.find(h=>h.path===d.path)?.current||"?";o.info(` ${d.path.split("/").pop()}`),o.info(` Current: ${le(g)}`),o.info(` Latest: ${le(d.version)}`);}}if(!t.yes&&!t.ci&&!await H(t.canary?"Are you sure you want to upgrade to the bleeding edge?":"Do you want to upgrade now?",{initial:true})){o.info("Upgrade cancelled");return}let p=l.map(d=>`${d.path}@${d.version}`);await yo(i.root,p,o);let w=m.reduce((d,g)=>{if(!g.min)return d;let h=M.coerce(g.min),f=M.coerce(d);return h&&(!f||M.gt(h,f))?g.min:d},void 0);w&&await _n(i.root,w,o),o.info(""),o.warn("\u26A0\uFE0F Important: Please review the release notes for any breaking changes."),o.info("\u{1F449} https://github.com/HugoBlox/hugo-blox-builder/releases");});}async function yo(n,e,t){let r=Ge("Upgrading modules...").start();try{await execa("hugo",["mod","get",...e],{cwd:n}),r.text="Tidying go.mod...",await execa("hugo",["mod","tidy"],{cwd:n}),r.succeed(`\u2705 Upgraded ${e.length} module(s)`);}catch(o){r.fail("Failed to upgrade modules"),t.error(String(o)),process.exit(1);}}var Y;function Q(){if(Y)return Y;let n=process.env.HBX_CLI_VERSION??process.env.npm_package_version;if(n)return Y=n,Y;let e=bo(import.meta.url);try{let t=F.readFileSync(e,"utf8");Y=JSON.parse(t).version??"0.0.0";}catch{Y="0.0.0";}return Y}function bo(n){let e=E.dirname(fileURLToPath(n)),t=E.resolve(e,"../package.json");return F.existsSync(t)?t:E.resolve(e,"../../package.json")}function Rn(n,e){n.command("version").description("Print CLI version").action((t,r)=>{let{logger:o}=e,i=!!r.optsWithGlobals().json,s=Q(),c={status:"success",version:s};i?o.json(c):o.info(`hbx ${s}`);});}var fe=class n{#e;constructor(e){this.#e=e;}static async load(){try{let e=await $.readFile(Ee,"utf8"),t=JSON.parse(e);return new n(t)}catch(e){if(e.code==="ENOENT")return new n({});throw new xe("Failed to read configuration",{error:e})}}toJSON(){return this.#e}getLicense(){return process.env[te]??this.#e.token}setLicense(e){this.#e={...this.#e,token:e};}clearLicense(){let e={...this.#e};e.token=void 0,e.device=void 0,this.#e=e;}isTelemetryEnabled(){return process.env[ft]==="1"?false:typeof this.#e.telemetry?.enabled=="boolean"?this.#e.telemetry.enabled:true}setTelemetryEnabled(e){this.#e={...this.#e,telemetry:{...this.#e.telemetry,enabled:e,lastPrompted:Date.now()}};}getTelemetryId(){return this.#e.telemetry?.id}async ensureTelemetryId(){let e=this.getTelemetryId();if(e)return e;let t=ye.randomUUID();return this.#e={...this.#e,telemetry:{...this.#e.telemetry,id:t}},await this.save(),t}getDefaultTemplate(){return this.#e.defaults?.template}getUpdateMetadata(){return this.#e.updates}setUpdateMetadata(e){this.#e={...this.#e,updates:{...this.#e.updates,...e}};}getDeviceInfo(){return this.#e.device}setDeviceInfo(e){this.#e={...this.#e,device:e};}async save(){await $.mkdir(Ve,{recursive:true});let e=JSON.stringify(this.#e,null,2);await $.writeFile(Ee,e,{mode:384}),await $.chmod(Ee,384);}};var ge=class{#e;#t;constructor(e={}){this.#e=e.json??false,this.#t=e.debug??process.env[G]==="1";}isJsonMode(){return this.#e}setJsonMode(e){this.#e=e;}setDebug(e){this.#t=e;}info(e){this.#e||process.stdout.write(`${ve.blue("i")} ${e}
109
+ `);}success(e){this.#e||process.stdout.write(`${ve.green("\u2714")} ${e}
110
+ `);}warn(e){this.#e||process.stdout.write(`${ve.yellow("!")} ${e}
111
+ `);}error(e){this.#e||process.stderr.write(`${ve.red("\u2716")} ${e}
112
+ `);}debug(e){!this.#t||this.#e||process.stdout.write(`${ve.gray("debug")} ${e}
113
113
  `);}json(e){let t=JSON.stringify(e,null,2);process.stdout.write(`${t}
114
- `);}};var ho=new Set(["command","project","duration","status","errorCode","errorMessage","metadata"]),yo=50,wo=6144,En=25e3,Q=class{#e;#t;#r;#o=[];#n;#i=false;#s;#a;#c;constructor(e,t,r){this.#e=e,this.#t=t,this.#r=r,this.#a=process.env.HBX_RELEASE_CHANNEL??process.env.RELEASE_CHANNEL??"stable",this.#c=randomUUID(),this.#l();}isEnabled(){return this.#e.isTelemetryEnabled()}setCommand(e){this.#s=e;}async track(e){this.isEnabled()&&(this.#o.push({...e,timestamp:new Date().toISOString(),payload:e.payload??{}}),await this.flush());}async flush(){if(!this.#o.length)return;if(this.#n){await this.#n;return}let e=this.#o.splice(0);this.#n=this.#m(e).finally(()=>{this.#n=void 0;}),await this.#n;}#l(){if(this.#i)return;let e=()=>{this.flush();};process.once("beforeExit",e),process.once("exit",e),process.once("SIGINT",e),process.once("SIGTERM",e),this.#i=true;}async#m(e){if(!e.length)return;let t=this.#e.getTelemetryId(),o=[...e.map(i=>xo(i))];for(;o.length;){let i=[],s;for(;o.length&&i.length<yo;){let a=o[0];if(!a)break;let c=[...i,a],l=this.#d(c,t),m=JSON.stringify(l);if(Buffer$1.byteLength(m,"utf8")>En){if(!i.length){o.shift(),this.#t.warn("Dropped telemetry event because payload exceeded max size");continue}break}let g=o.shift();if(!g)break;i.push(g),s=m;}!i.length||!s||await this.#u(s,t);}}#d(e,t){return {clientId:t&&t.length>=8?t:"anonymous",os:Le.platform(),osVersion:vo(),arch:process.arch,nodeVersion:process.version,ci:bo(),command:this.#s,releaseChannel:this.#a,sessionId:this.#c,cliVersion:this.#r,version:this.#r,hasLicense:!!this.#e.getLicense(),events:e}}async#u(e,t){let r=Buffer$1.byteLength(e,"utf8");if(r>En){this.#t.warn("Telemetry payload skipped because it exceeded the maximum request size");return}try{let o=new AbortController,i=setTimeout(()=>o.abort(),5e3),s=await fetch(gt,{method:"POST",headers:{"Content-Type":"application/json","Content-Length":String(r),"User-Agent":`hbx-cli/${this.#r}`,...t?{"x-telemetry-id":t}:void 0},body:e,signal:o.signal});if(clearTimeout(i),s.status===413){this.#t.warn("Telemetry payload rejected (too large)");return}if(!s.ok)throw new Error(`telemetry responded with status ${s.status}`)}catch(o){this.#t.debug(`telemetry send failed: ${String(o)}`);}}};function bo(){return process.env.CI==="1"||process.env.CONTINUOUS_INTEGRATION==="1"||!!process.env.BUILD_NUMBER||!!process.env.RUN_ID}function vo(){let n=Le.version;if(typeof n=="function")try{return n()}catch{return Le.release()}return Le.release()}function xo(n){let e=Co(n.payload);if(!e){let{payload:t,...r}=n;return r}try{let t=JSON.stringify(e);return Buffer$1.byteLength(t,"utf8")>wo?{...n,payload:{truncated:!0}}:{...n,payload:e}}catch{return {...n,payload:{truncated:true}}}}function Co(n){if(!n||typeof n!="object")return;let e={};for(let t of ho)if(Object.hasOwn(n,t)){let r=n[t];if(t==="metadata"&&(r==null||typeof r!="object"))continue;e[t]=r;}return Object.keys(e).length?e:void 0}async function An(n,e,t){if(process.env[dt]==="1")return;let r=e.getUpdateMetadata()??{},o=Date.now(),i=r.latestVersion,s=r.lastChecked??0;if(!i||o-s>ht){let l=await So(n,t);l.latestVersion&&(i=l.latestVersion),l.checkedAt>0&&(s=l.checkedAt,e.setUpdateMetadata({lastChecked:s,latestVersion:i}),await e.save());}if(!i||!N.valid(i)||!N.gt(i,n)||!Po(r,o,i))return;let c=`npm install -g ${Se}`;t.warn(`A new version of hbx is available: ${i} (current ${n}).
115
- Update with: ${c} (or pnpm add -g ${Se}).`),e.setUpdateMetadata({lastNotifiedAt:o,latestVersion:i}),await e.save();}function Po(n,e,t){return !n||n.lastNotifiedAt===void 0||n.latestVersion!==t?true:e-n.lastNotifiedAt>yt}async function So(n,e){try{let t=await fetch(`https://registry.npmjs.org/${encodeURIComponent(Se)}/latest`,{headers:{"User-Agent":`hbx-cli/${n}`}});if(!t.ok)throw new Error(`npm registry responded with status ${t.status}`);return {latestVersion:(await t.json()).version,checkedAt:Date.now()}}catch(t){return e.debug(`update check failed: ${String(t)}`),{checkedAt:Date.now()}}}var Be=class{constructor(e){this.context=e;this.cancelled=false;}async*create(e){this.cancelled=false;try{if(yield*this.validateConfiguration(e),this.cancelled||(yield*this.fetchTemplate(e.templateId),this.cancelled)||(yield*this.scaffoldSite(e),this.cancelled)||e.options?.autoInstall!==!1&&(yield*this.installDependencies(e),this.cancelled)||e.options?.initGit!==!1&&(yield*this.initializeGit(e),this.cancelled))return;yield*this.completeCreation(e);}catch(t){yield {id:"error",type:"error",title:"Creation Failed",message:t instanceof Error?t.message:String(t),timestamp:new Date,data:{error:t,config:e}};}}async*validateConfiguration(e){yield this.createProgressStep("validate",0,"Starting validation..."),yield this.createProgressStep("validate",25,"Checking template availability...");let t=await this.validate(e);if(yield this.createProgressStep("validate",75,"Validating target path..."),!t.valid)throw new Error(`Validation failed: ${t.errors[0]?.message}`);for(let r of t.warnings)yield {id:"validate",type:"warning",title:"Configuration Warning",message:r.message,timestamp:new Date,data:{field:r.field,suggestion:r.suggestion}};yield this.createSuccessStep("validate","Configuration validated");}async*fetchTemplate(e){yield this.createProgressStep("fetch_template",0,"Fetching available templates...");let t=await V(this.context);yield this.createProgressStep("fetch_template",50,"Locating template...");let r=t.find(o=>o.id===e);if(!r)throw new Error(`Template "${e}" not found`);yield this.createProgressStep("fetch_template",75,`Found template: ${r.name}`),await this.delay(500),yield this.createSuccessStep("fetch_template",`Template "${r.name}" ready`,{template:r});}async*scaffoldSite(e){let r=(await V(this.context)).find(s=>s.id===e.templateId);if(!r)throw new Error(`Template "${e.templateId}" not found`);yield this.createProgressStep("scaffold_site",0,"Preparing target directory...");let o=$e(e.targetPath,r.slug);await ve(o),yield this.createProgressStep("scaffold_site",25,"Copying template files...");let i={sampleContent:e.options?.includeSampleContent??true,includeEnv:true,packageManager:e.packageManager||"pnpm"};await Te(this.context,o,r,i),yield this.createProgressStep("scaffold_site",75,"Customizing site configuration..."),await this.customizeSiteConfig(o,e),yield this.createSuccessStep("scaffold_site","Site structure created",{targetDir:o,templateId:e.templateId});}async*installDependencies(e){let t=e.packageManager||"pnpm",r=e.targetPath;yield this.createProgressStep("install_deps",0,`Starting ${t} install...`);try{await Ae(r,t,this.context.logger)?yield this.createSuccessStep("install_deps","Dependencies installed successfully"):yield {id:"install_deps",type:"warning",title:"Dependencies installation skipped",message:"Some dependencies failed to install, but site creation can continue",timestamp:new Date};}catch(o){throw new Error(`Failed to install dependencies: ${String(o)}`)}}async*initializeGit(e){yield this.createProgressStep("init_git",0,"Initializing git repository..."),await Ee(e.targetPath,this.context.logger),yield this.createProgressStep("init_git",75,"Creating initial commit..."),await this.delay(1e3),yield this.createSuccessStep("init_git","Git repository initialized");}async*completeCreation(e){yield this.createProgressStep("complete",50,"Finalizing setup..."),await this.generateSummaryReport(e),yield {id:"complete",type:"success",title:`Site "${e.siteName}" created successfully! \u{1F389}`,progress:100,timestamp:new Date,data:{siteName:e.siteName,targetPath:e.targetPath,templateId:e.templateId,packageManager:e.packageManager,nextSteps:this.generateNextSteps(e)}};}async validate(e){let t=[],r=[];(await V(this.context)).find(s=>s.id===e.templateId)||t.push({field:"templateId",message:`Template "${e.templateId}" not found`,code:"TEMPLATE_NOT_FOUND"}),(!e.siteName||e.siteName.trim().length===0)&&t.push({field:"siteName",message:"Site name is required",code:"SITE_NAME_REQUIRED"});let i=await _e(e.targetPath);return i.valid||t.push({field:"targetPath",message:i.error||"Invalid target path",code:"INVALID_PATH"}),i.exists&&!i.isEmpty&&r.push({field:"targetPath",message:"Directory is not empty",suggestion:"Files may be overwritten during site creation"}),{valid:t.length===0,errors:t,warnings:r}}async cancel(){this.cancelled=true;}createProgressStep(e,t,r,o){return {id:e,type:"progress",title:this.getStepTitle(e),message:r,progress:t,timestamp:new Date,data:o}}createSuccessStep(e,t,r){return {id:e,type:"success",title:this.getStepTitle(e),message:t,progress:100,timestamp:new Date,data:r}}getStepTitle(e){return {validate:"Validating configuration",fetch_template:"Fetching template",scaffold_site:"Creating site structure",install_deps:"Installing dependencies",init_git:"Initializing git repository",start_server:"Starting development server",complete:"Finalizing setup"}[e]||e}async delay(e){return new Promise(t=>setTimeout(t,e))}async customizeSiteConfig(e,t){this.context.logger.debug(`Customizing site config for ${t.siteName}`);}async generateSummaryReport(e){this.context.logger.debug(`Site creation completed: ${JSON.stringify({template:e.templateId,path:e.targetPath,options:e.options})}`);}generateNextSteps(e){let t=[`cd ${e.targetPath}`];return e.options?.autoInstall===false&&t.push(`${e.packageManager||"pnpm"} install`),e.options?.autoPreview!==false&&t.push(`${e.packageManager||"pnpm"} dev`),t}};var Ne=class n{constructor(e){this.context=e;}static{this.PREVIEW_DATA={"academic-cv":{thumbnailUrl:"https://hugoblox.com/previews/academic-cv-thumb.jpg",category:"academic",difficulty:"beginner",estimatedTime:3,features:["Publication lists","Research sections","Academic timeline","Contact forms"],useCases:["Professors","Researchers","PhD students","Academic professionals"]},startup:{thumbnailUrl:"https://hugoblox.com/previews/startup-thumb.jpg",category:"business",difficulty:"intermediate",estimatedTime:5,features:["Landing pages","Pricing tables","Team sections","Newsletter signup"],useCases:["SaaS companies","Startups","Product launches","Marketing sites"]},folio:{thumbnailUrl:"https://hugoblox.com/previews/folio-thumb.jpg",category:"portfolio",difficulty:"beginner",estimatedTime:2,features:["Project galleries","About sections","Contact forms","Responsive design"],useCases:["Designers","Developers","Freelancers","Creative professionals"]}};}async enrichWithPreviews(e,t){let r=e.map(o=>this.enrichTemplate(o));return t?this.applyQueryOptions(r,t):r}enrichTemplate(e){let t=n.PREVIEW_DATA[e.id];return t?{...e,preview:t,stats:this.calculateStats(e)}:{...e,preview:{thumbnailUrl:this.generateFallbackThumbnail(e),category:this.inferCategory(e),difficulty:"intermediate",estimatedTime:4,features:this.inferFeatures(e),useCases:["General purpose"]},stats:this.calculateStats(e)}}generateFallbackThumbnail(e){return `https://hugoblox.com/api/placeholder-thumb/${encodeURIComponent(e.id)}`}inferCategory(e){let t=e.name.toLowerCase(),r=(e.description||"").toLowerCase();return t.includes("academic")||t.includes("cv")||t.includes("research")?"academic":t.includes("startup")||t.includes("business")||r.includes("saas")?"business":t.includes("portfolio")||t.includes("folio")?"portfolio":t.includes("blog")||r.includes("blog")?"blog":t.includes("docs")||t.includes("documentation")?"documentation":"other"}inferFeatures(e){let t=[],r=(e.description||"").toLowerCase();return r.includes("responsive")&&t.push("Mobile responsive"),r.includes("dark")&&t.push("Dark mode support"),r.includes("seo")&&t.push("SEO optimized"),r.includes("multilingual")&&t.push("Multi-language support"),t.length>0?t:["Modern design","Responsive layout"]}calculateStats(e){let t=e.source==="pro"?80:60;return {popularity:["academic-cv","startup","folio"].includes(e.id)?t+20:t,lastUpdated:new Date().toISOString().split("T")[0]}}applyQueryOptions(e,t){let r=[...e];switch(t.category&&(r=r.filter(o=>o.preview.category===t.category)),t.difficulty&&(r=r.filter(o=>o.preview.difficulty===t.difficulty)),t.source&&(r=r.filter(o=>o.source===t.source)),t.sortBy){case "popularity":r.sort((o,i)=>(i.stats?.popularity||0)-(o.stats?.popularity||0));break;case "name":r.sort((o,i)=>o.name.localeCompare(i.name));break;case "difficulty":{let o={beginner:1,intermediate:2,advanced:3};r.sort((i,s)=>o[i.preview.difficulty]-o[s.preview.difficulty]);break}default:r.sort((o,i)=>o.source==="pro"&&i.source!=="pro"?-1:i.source==="pro"&&o.source!=="pro"?1:o.name.localeCompare(i.name));}return t.limit&&t.limit>0&&(r=r.slice(0,t.limit)),r}async getPreview(e){let t=n.PREVIEW_DATA[e];return t?{templateId:e,thumbnailUrl:t.thumbnailUrl,screenshots:await this.getScreenshots(e),demoUrl:await this.getDemoUrl(e),features:t.features,useCases:t.useCases}:null}async getScreenshots(e){let t="https://hugoblox.com/previews/";return [`${t}${e}-1.jpg`,`${t}${e}-2.jpg`,`${t}${e}-3.jpg`]}async getDemoUrl(e){return {"academic-cv":"https://hugoblox.com/templates/academic-cv/",startup:"https://hugoblox.com/templates/startup/",folio:"https://hugoblox.com/templates/portfolio/"}[e]}};var Me=class{constructor(e){this.context=e;this.templates={fetchAll:async e=>{let t=await V(this.context);return this.previewService.enrichWithPreviews(t,e)},getById:async e=>(await this.templates.fetchAll()).find(r=>r.id===e)||null,getPreview:async e=>this.previewService.getPreview(e)};this.creation={create:e=>this.creationService.create(e),validate:async e=>this.creationService.validate(e),cancel:async()=>this.creationService.cancel()};this.system={detectPackageManager:async e=>Ut(e||process.cwd()),validatePath:async e=>_e(e),getDefaultConfig:()=>({templateId:"startup",siteName:"my-hugoblox-site",targetPath:"./my-hugoblox-site",packageManager:"pnpm",options:{includeSampleContent:true,initGit:true,autoInstall:true,autoPreview:true},showAdvanced:false,rememberedChoices:{}})};this.previewService=new Ne(e),this.creationService=new Be(e);}};async function ko(n={}){let e=await Eo(n);return new Me(e)}async function Eo(n){let e=Y(),t=await ue.load(),r=new pe({debug:n.debug??process.env[G]==="1",json:true});await t.ensureTelemetryId();let o=n.telemetryEnabled!==false?new Q(t,r,e):new at(t,r,e);return n.progressCallback&&(o.progressCallback=n.progressCallback),{config:t,logger:r,telemetry:o}}var at=class extends Q{async track(){}setCommand(){}};async function Ao(n=process.argv){let e=Y(),t=await ue.load(),r=new pe({debug:process.env[G]==="1"});await t.ensureTelemetryId();let o=new Q(t,r,e),i={config:t,logger:r,telemetry:o};await An(e,t,r),await Ro(i);let s=new Command;s.name("hbx").description("HugoBlox Experience CLI").version(e,"-v, --version","Show CLI version").option("--json","Output machine-readable JSON").option("--debug","Enable verbose logging"),s.hook("preAction",(a,c)=>{let l=c?.optsWithGlobals?.()??a.optsWithGlobals();r.setJsonMode(!!l.json),r.setDebug(!!l.debug||process.env[G]==="1"),o.setCommand(Io(c));}),qt(s,i),Et(s,i),rn(s,i),Kt(s,i),nn(s,i),on(s,i),sn(s,i),yn(s,i),Pn(s,i),wn(s,i),kn(s,i);try{await s.parseAsync(n);}catch(a){$o(a,r);}}function $o(n,e){if(ct(n)){let t={status:"error",code:n.code,message:n.message,details:n.details};e.isJsonMode()?e.json(t):e.error(`${n.code}: ${n.message}`);}else n instanceof M?e.error(`${n.code}: ${n.message}`):n instanceof Error?e.error(n.message):e.error("Unknown error");process.exit(1);}(process.argv[1]===fileURLToPath(import.meta.url)||process.argv[1].endsWith("/bin/hbx")||process.argv[1].endsWith("/bin/hugoblox"))&&Ao();function Io(n){if(!n)return Ce;let e=[],t=n;for(;t?.parent;){let r=t.name?.();r&&e.unshift(r),t=t.parent;}return e.length?`${Ce} ${e.join(" ")}`.trim():Ce}async function Ro(n){if(process.env[ee]&&n.config.getLicense()&&!n.config.getDeviceInfo())try{await B(n);}catch(e){n.logger.debug(`Skipping device registration warm-up: ${String(e)}`);}}
114
+ `);}};var Co=new Set(["command","project","duration","status","errorCode","errorMessage","metadata"]),Po=50,So=6144,Dn=25e3,Z=class{#e;#t;#r;#o=[];#n;#i=false;#s;#a;#c;constructor(e,t,r){this.#e=e,this.#t=t,this.#r=r,this.#a=process.env.HBX_RELEASE_CHANNEL??process.env.RELEASE_CHANNEL??"stable",this.#c=randomUUID(),this.#l();}isEnabled(){return this.#e.isTelemetryEnabled()}setCommand(e){this.#s=e;}async track(e){this.isEnabled()&&(this.#o.push({...e,timestamp:new Date().toISOString(),payload:e.payload??{}}),await this.flush());}async flush(){if(!this.#o.length)return;if(this.#n){await this.#n;return}let e=this.#o.splice(0);this.#n=this.#m(e).finally(()=>{this.#n=void 0;}),await this.#n;}#l(){if(this.#i)return;let e=()=>{this.flush();};process.once("beforeExit",e),process.once("exit",e),process.once("SIGINT",e),process.once("SIGTERM",e),this.#i=true;}async#m(e){if(!e.length)return;let t=this.#e.getTelemetryId(),o=[...e.map(i=>To(i))];for(;o.length;){let i=[],s;for(;o.length&&i.length<Po;){let c=o[0];if(!c)break;let a=[...i,c],l=this.#d(a,t),m=JSON.stringify(l);if(Buffer$1.byteLength(m,"utf8")>Dn){if(!i.length){o.shift(),this.#t.warn("Dropped telemetry event because payload exceeded max size");continue}break}let p=o.shift();if(!p)break;i.push(p),s=m;}!i.length||!s||await this.#u(s,t);}}#d(e,t){return {clientId:t&&t.length>=8?t:"anonymous",os:Ne.platform(),osVersion:Eo(),arch:process.arch,nodeVersion:process.version,ci:ko(),command:this.#s,releaseChannel:this.#a,sessionId:this.#c,cliVersion:this.#r,version:this.#r,hasLicense:!!this.#e.getLicense(),events:e}}async#u(e,t){let r=Buffer$1.byteLength(e,"utf8");if(r>Dn){this.#t.warn("Telemetry payload skipped because it exceeded the maximum request size");return}try{let o=new AbortController,i=setTimeout(()=>o.abort(),5e3),s=await fetch(bt,{method:"POST",headers:{"Content-Type":"application/json","Content-Length":String(r),"User-Agent":`hbx-cli/${this.#r}`,...t?{"x-telemetry-id":t}:void 0},body:e,signal:o.signal});if(clearTimeout(i),s.status===413){this.#t.warn("Telemetry payload rejected (too large)");return}if(!s.ok)throw new Error(`telemetry responded with status ${s.status}`)}catch(o){this.#t.debug(`telemetry send failed: ${String(o)}`);}}};function ko(){return process.env.CI==="1"||process.env.CONTINUOUS_INTEGRATION==="1"||!!process.env.BUILD_NUMBER||!!process.env.RUN_ID}function Eo(){let n=Ne.version;if(typeof n=="function")try{return n()}catch{return Ne.release()}return Ne.release()}function To(n){let e=Ao(n.payload);if(!e){let{payload:t,...r}=n;return r}try{let t=JSON.stringify(e);return Buffer$1.byteLength(t,"utf8")>So?{...n,payload:{truncated:!0}}:{...n,payload:e}}catch{return {...n,payload:{truncated:true}}}}function Ao(n){if(!n||typeof n!="object")return;let e={};for(let t of Co)if(Object.hasOwn(n,t)){let r=n[t];if(t==="metadata"&&(r==null||typeof r!="object"))continue;e[t]=r;}return Object.keys(e).length?e:void 0}async function Ln(n,e,t){if(process.env[gt]==="1")return;let r=e.getUpdateMetadata()??{},o=Date.now(),i=r.latestVersion,s=r.lastChecked??0;if(!i||o-s>vt){let l=await $o(n,t);l.latestVersion&&(i=l.latestVersion),l.checkedAt>0&&(s=l.checkedAt,e.setUpdateMetadata({lastChecked:s,latestVersion:i}),await e.save());}if(!i||!M.valid(i)||!M.gt(i,n)||!_o(r,o,i))return;let a=`npm install -g ${Te}`;t.warn(`A new version of hbx is available: ${i} (current ${n}).
115
+ Update with: ${a} (or pnpm add -g ${Te}).`),e.setUpdateMetadata({lastNotifiedAt:o,latestVersion:i}),await e.save();}function _o(n,e,t){return !n||n.lastNotifiedAt===void 0||n.latestVersion!==t?true:e-n.lastNotifiedAt>xt}async function $o(n,e){try{let t=await fetch(`https://registry.npmjs.org/${encodeURIComponent(Te)}/latest`,{headers:{"User-Agent":`hbx-cli/${n}`}});if(!t.ok)throw new Error(`npm registry responded with status ${t.status}`);return {latestVersion:(await t.json()).version,checkedAt:Date.now()}}catch(t){return e.debug(`update check failed: ${String(t)}`),{checkedAt:Date.now()}}}var Oe=class{constructor(e){this.context=e;this.cancelled=false;}async*create(e){this.cancelled=false;try{if(yield*this.validateConfiguration(e),this.cancelled||(yield*this.fetchTemplate(e.templateId),this.cancelled)||(yield*this.scaffoldSite(e),this.cancelled)||e.options?.autoInstall!==!1&&(yield*this.installDependencies(e),this.cancelled)||e.options?.initGit!==!1&&(yield*this.initializeGit(e),this.cancelled))return;yield*this.completeCreation(e);}catch(t){yield {id:"error",type:"error",title:"Creation Failed",message:t instanceof Error?t.message:String(t),timestamp:new Date,data:{error:t,config:e}};}}async*validateConfiguration(e){yield this.createProgressStep("validate",0,"Starting validation..."),yield this.createProgressStep("validate",25,"Checking template availability...");let t=await this.validate(e);if(yield this.createProgressStep("validate",75,"Validating target path..."),!t.valid)throw new Error(`Validation failed: ${t.errors[0]?.message}`);for(let r of t.warnings)yield {id:"validate",type:"warning",title:"Configuration Warning",message:r.message,timestamp:new Date,data:{field:r.field,suggestion:r.suggestion}};yield this.createSuccessStep("validate","Configuration validated");}async*fetchTemplate(e){yield this.createProgressStep("fetch_template",0,"Fetching available templates...");let t=await V(this.context);yield this.createProgressStep("fetch_template",50,"Locating template...");let r=t.find(o=>o.id===e);if(!r)throw new Error(`Template "${e}" not found`);yield this.createProgressStep("fetch_template",75,`Found template: ${r.name}`),await this.delay(500),yield this.createSuccessStep("fetch_template",`Template "${r.name}" ready`,{template:r});}async*scaffoldSite(e){let r=(await V(this.context)).find(s=>s.id===e.templateId);if(!r)throw new Error(`Template "${e.templateId}" not found`);yield this.createProgressStep("scaffold_site",0,"Preparing target directory...");let o=He(e.targetPath,r.slug);await Pe(o),yield this.createProgressStep("scaffold_site",25,"Copying template files...");let i={sampleContent:e.options?.includeSampleContent??true,includeEnv:true,packageManager:e.packageManager||"pnpm"};await $e(this.context,o,r,i),yield this.createProgressStep("scaffold_site",75,"Customizing site configuration..."),await this.customizeSiteConfig(o,e),yield this.createSuccessStep("scaffold_site","Site structure created",{targetDir:o,templateId:e.templateId});}async*installDependencies(e){let t=e.packageManager||"pnpm",r=e.targetPath;yield this.createProgressStep("install_deps",0,`Starting ${t} install...`);try{await Ie(r,t,this.context.logger)?yield this.createSuccessStep("install_deps","Dependencies installed successfully"):yield {id:"install_deps",type:"warning",title:"Dependencies installation skipped",message:"Some dependencies failed to install, but site creation can continue",timestamp:new Date};}catch(o){throw new Error(`Failed to install dependencies: ${String(o)}`)}}async*initializeGit(e){yield this.createProgressStep("init_git",0,"Initializing git repository..."),await _e(e.targetPath,this.context.logger),yield this.createProgressStep("init_git",75,"Creating initial commit..."),await this.delay(1e3),yield this.createSuccessStep("init_git","Git repository initialized");}async*completeCreation(e){yield this.createProgressStep("complete",50,"Finalizing setup..."),await this.generateSummaryReport(e),yield {id:"complete",type:"success",title:`Site "${e.siteName}" created successfully! \u{1F389}`,progress:100,timestamp:new Date,data:{siteName:e.siteName,targetPath:e.targetPath,templateId:e.templateId,packageManager:e.packageManager,nextSteps:this.generateNextSteps(e)}};}async validate(e){let t=[],r=[];(await V(this.context)).find(s=>s.id===e.templateId)||t.push({field:"templateId",message:`Template "${e.templateId}" not found`,code:"TEMPLATE_NOT_FOUND"}),(!e.siteName||e.siteName.trim().length===0)&&t.push({field:"siteName",message:"Site name is required",code:"SITE_NAME_REQUIRED"});let i=await je(e.targetPath);return i.valid||t.push({field:"targetPath",message:i.error||"Invalid target path",code:"INVALID_PATH"}),i.exists&&!i.isEmpty&&r.push({field:"targetPath",message:"Directory is not empty",suggestion:"Files may be overwritten during site creation"}),{valid:t.length===0,errors:t,warnings:r}}async cancel(){this.cancelled=true;}createProgressStep(e,t,r,o){return {id:e,type:"progress",title:this.getStepTitle(e),message:r,progress:t,timestamp:new Date,data:o}}createSuccessStep(e,t,r){return {id:e,type:"success",title:this.getStepTitle(e),message:t,progress:100,timestamp:new Date,data:r}}getStepTitle(e){return {validate:"Validating configuration",fetch_template:"Fetching template",scaffold_site:"Creating site structure",install_deps:"Installing dependencies",init_git:"Initializing git repository",start_server:"Starting development server",complete:"Finalizing setup"}[e]||e}async delay(e){return new Promise(t=>setTimeout(t,e))}async customizeSiteConfig(e,t){this.context.logger.debug(`Customizing site config for ${t.siteName}`);}async generateSummaryReport(e){this.context.logger.debug(`Site creation completed: ${JSON.stringify({template:e.templateId,path:e.targetPath,options:e.options})}`);}generateNextSteps(e){let t=[`cd ${e.targetPath}`];return e.options?.autoInstall===false&&t.push(`${e.packageManager||"pnpm"} install`),e.options?.autoPreview!==false&&t.push(`${e.packageManager||"pnpm"} dev`),t}};var Fe=class n{constructor(e){this.context=e;}static{this.PREVIEW_DATA={"academic-cv":{thumbnailUrl:"https://hugoblox.com/previews/academic-cv-thumb.jpg",category:"academic",difficulty:"beginner",estimatedTime:3,features:["Publication lists","Research sections","Academic timeline","Contact forms"],useCases:["Professors","Researchers","PhD students","Academic professionals"]},startup:{thumbnailUrl:"https://hugoblox.com/previews/startup-thumb.jpg",category:"business",difficulty:"intermediate",estimatedTime:5,features:["Landing pages","Pricing tables","Team sections","Newsletter signup"],useCases:["SaaS companies","Startups","Product launches","Marketing sites"]},folio:{thumbnailUrl:"https://hugoblox.com/previews/folio-thumb.jpg",category:"portfolio",difficulty:"beginner",estimatedTime:2,features:["Project galleries","About sections","Contact forms","Responsive design"],useCases:["Designers","Developers","Freelancers","Creative professionals"]}};}async enrichWithPreviews(e,t){let r=e.map(o=>this.enrichTemplate(o));return t?this.applyQueryOptions(r,t):r}enrichTemplate(e){let t=n.PREVIEW_DATA[e.id];return t?{...e,preview:t,stats:this.calculateStats(e)}:{...e,preview:{thumbnailUrl:this.generateFallbackThumbnail(e),category:this.inferCategory(e),difficulty:"intermediate",estimatedTime:4,features:this.inferFeatures(e),useCases:["General purpose"]},stats:this.calculateStats(e)}}generateFallbackThumbnail(e){return `https://hugoblox.com/api/placeholder-thumb/${encodeURIComponent(e.id)}`}inferCategory(e){let t=e.name.toLowerCase(),r=(e.description||"").toLowerCase();return t.includes("academic")||t.includes("cv")||t.includes("research")?"academic":t.includes("startup")||t.includes("business")||r.includes("saas")?"business":t.includes("portfolio")||t.includes("folio")?"portfolio":t.includes("blog")||r.includes("blog")?"blog":t.includes("docs")||t.includes("documentation")?"documentation":"other"}inferFeatures(e){let t=[],r=(e.description||"").toLowerCase();return r.includes("responsive")&&t.push("Mobile responsive"),r.includes("dark")&&t.push("Dark mode support"),r.includes("seo")&&t.push("SEO optimized"),r.includes("multilingual")&&t.push("Multi-language support"),t.length>0?t:["Modern design","Responsive layout"]}calculateStats(e){let t=e.source==="pro"?80:60;return {popularity:["academic-cv","startup","folio"].includes(e.id)?t+20:t,lastUpdated:new Date().toISOString().split("T")[0]}}applyQueryOptions(e,t){let r=[...e];switch(t.category&&(r=r.filter(o=>o.preview.category===t.category)),t.difficulty&&(r=r.filter(o=>o.preview.difficulty===t.difficulty)),t.source&&(r=r.filter(o=>o.source===t.source)),t.sortBy){case "popularity":r.sort((o,i)=>(i.stats?.popularity||0)-(o.stats?.popularity||0));break;case "name":r.sort((o,i)=>o.name.localeCompare(i.name));break;case "difficulty":{let o={beginner:1,intermediate:2,advanced:3};r.sort((i,s)=>o[i.preview.difficulty]-o[s.preview.difficulty]);break}default:r.sort((o,i)=>o.source==="pro"&&i.source!=="pro"?-1:i.source==="pro"&&o.source!=="pro"?1:o.name.localeCompare(i.name));}return t.limit&&t.limit>0&&(r=r.slice(0,t.limit)),r}async getPreview(e){let t=n.PREVIEW_DATA[e];return t?{templateId:e,thumbnailUrl:t.thumbnailUrl,screenshots:await this.getScreenshots(e),demoUrl:await this.getDemoUrl(e),features:t.features,useCases:t.useCases}:null}async getScreenshots(e){let t="https://hugoblox.com/previews/";return [`${t}${e}-1.jpg`,`${t}${e}-2.jpg`,`${t}${e}-3.jpg`]}async getDemoUrl(e){return {"academic-cv":"https://hugoblox.com/templates/academic-cv/",startup:"https://hugoblox.com/templates/startup/",folio:"https://hugoblox.com/templates/portfolio/"}[e]}};var Ue=class{constructor(e){this.context=e;this.templates={fetchAll:async e=>{let t=await V(this.context);return this.previewService.enrichWithPreviews(t,e)},getById:async e=>(await this.templates.fetchAll()).find(r=>r.id===e)||null,getPreview:async e=>this.previewService.getPreview(e)};this.creation={create:e=>this.creationService.create(e),validate:async e=>this.creationService.validate(e),cancel:async()=>this.creationService.cancel()};this.system={detectPackageManager:async e=>Gt(e||process.cwd()),validatePath:async e=>je(e),getDefaultConfig:()=>({templateId:"startup",siteName:"my-hugoblox-site",targetPath:"./my-hugoblox-site",packageManager:"pnpm",options:{includeSampleContent:true,initGit:true,autoInstall:true,autoPreview:true},showAdvanced:false,rememberedChoices:{}})};this.previewService=new Fe(e),this.creationService=new Oe(e);}};async function Io(n={}){let e=await Ho(n);return new Ue(e)}async function Ho(n){let e=Q(),t=await fe.load(),r=new ge({debug:n.debug??process.env[G]==="1",json:true});await t.ensureTelemetryId();let o=n.telemetryEnabled!==false?new Z(t,r,e):new dt(t,r,e);return n.progressCallback&&(o.progressCallback=n.progressCallback),{config:t,logger:r,telemetry:o}}var dt=class extends Z{async track(){}setCommand(){}};async function Ro(n=process.argv){let e=Q(),t=await fe.load(),r=new ge({debug:process.env[G]==="1"});await t.ensureTelemetryId();let o=new Z(t,r,e),i={config:t,logger:r,telemetry:o};await Ln(e,t,r),await Mo(i);let s=new Command;s.name("hbx").description("HugoBlox Experience CLI").version(e,"-v, --version","Show CLI version").option("--json","Output machine-readable JSON").option("--debug","Enable verbose logging"),s.hook("preAction",(c,a)=>{let l=a?.optsWithGlobals?.()??c.optsWithGlobals();r.setJsonMode(!!l.json),r.setDebug(!!l.debug||process.env[G]==="1"),o.setCommand(Lo(a));}),Qt(s,i),$t(s,i),pn(s,i),en(s,i),un(s,i),fn(s,i),gn(s,i),En(s,i),Hn(s,i),Tn(s,i),Rn(s,i);try{await s.parseAsync(n);}catch(c){Do(c,r);}}function Do(n,e){if(ut(n)){let t={status:"error",code:n.code,message:n.message,details:n.details};e.isJsonMode()?e.json(t):e.error(`${n.code}: ${n.message}`);}else n instanceof N?e.error(`${n.code}: ${n.message}`):n instanceof Error?e.error(n.message):e.error("Unknown error");process.exit(1);}(process.argv[1]===fileURLToPath(import.meta.url)||process.argv[1].endsWith("/bin/hbx")||process.argv[1].endsWith("/bin/hugoblox"))&&Ro();function Lo(n){if(!n)return ke;let e=[],t=n;for(;t?.parent;){let r=t.name?.();r&&e.unshift(r),t=t.parent;}return e.length?`${ke} ${e.join(" ")}`.trim():ke}async function Mo(n){if(process.env[te]&&n.config.getLicense()&&!n.config.getDeviceInfo())try{await L(n);}catch(e){n.logger.debug(`Skipping device registration warm-up: ${String(e)}`);}}
116
116
 
117
- export { Ao as bootstrap, ko as createWelcomeScreenAPI, Y as getCliVersion };
117
+ export { Ro as bootstrap, Io as createWelcomeScreenAPI, Q as getCliVersion };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hugoblox",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "The official CLI for creating and managing HugoBlox sites.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -55,8 +55,8 @@
55
55
  "vitest": "1.4.0"
56
56
  },
57
57
  "scripts": {
58
- "build": "tsup",
59
- "build:publish": "cross-env HBX_PUBLISH_BUILD=1 tsup",
58
+ "build": "cross-env HBX_PUBLISH_BUILD=1 tsup",
59
+ "build:dev": "tsup",
60
60
  "dev": "tsx watch src/index.ts",
61
61
  "lint": "biome check .",
62
62
  "lint:fix": "biome check --apply .",