hugoblox 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,30 +1,28 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from 'commander';
3
- import g from 'node:fs/promises';
4
- import u from 'node:path';
3
+ import P from 'node:fs/promises';
4
+ import E from 'node:path';
5
+ import Te from 'ora';
6
+ import Ze from 'yaml';
5
7
  import { execa } from 'execa';
6
- import $t from 'yaml';
7
- import ue from 'node:os';
8
- import k from 'semver';
9
- import yt from 'ora';
10
- import K, { randomUUID } from 'node:crypto';
8
+ import ve from 'node:os';
9
+ import Ke from 'node:dns/promises';
10
+ import Pe from 'prompts';
11
+ import oe, { randomUUID } from 'node:crypto';
11
12
  import { createRequire } from 'node:module';
12
13
  import { promisify } from 'node:util';
13
- import be from 'prompts';
14
- import Tt from 'node:fs';
15
14
  import { fileURLToPath } from 'node:url';
16
- import Y from 'chalk';
15
+ import L from 'semver';
16
+ import Wt from 'node:fs';
17
+ import ne from 'chalk';
17
18
  import { Buffer as Buffer$1 } from 'node:buffer';
18
19
 
19
- var S=class extends Error{constructor(e,o="HBX_ERROR",r){super(e),this.name="HbxError",this.code=o,this.details=r;}},d=class extends S{constructor(e,o){super(e,"HBX_INPUT_ERROR",o);}},U=class extends S{constructor(e="Operation cancelled by user"){super(e,"HBX_ABORTED");}},Z=class extends S{constructor(e,o){super(e,"HBX_CONFIG_ERROR",o);}};function Se(t){return !!(t&&typeof t=="object"&&"code"in t)}async function v(t){try{return await g.access(t),!0}catch{return false}}async function C(t){await g.mkdir(t,{recursive:true});}async function Ie(t){if(!await v(t)){await C(t);return}if((await g.readdir(t)).length>0)throw new Error(`Directory ${t} is not empty`)}async function T(t,e){await C(u.dirname(t)),await g.writeFile(t,e);}function _e(t,e){t.command("block").description("Manage HugoBlox blocks").command("add").argument("<id>","Block identifier").description("Add a HugoBlox block to the current project").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((r,n,i)=>{let{logger:s}=e,a=!!i.optsWithGlobals().json,c="Block management is coming soon. Follow https://hugoblox.com/changelog for updates or join Discord to preview it early.";if(a){s.json({status:"pending",message:c});return}s.info(c);});}var oe="hbx",J="HBX_DEBUG",F="HBX_LICENSE_TOKEN",Be="HBX_TELEMETRY_DISABLED",ge=u.join(ue.homedir(),".hbx"),re=u.join(ge,"config.json"),Bt=u.join(ue.homedir(),".cache","hbx"),V=u.join(Bt,"templates"),je="HBX_UPDATE_CHECK_DISABLED",W="https://api.github.com",$e=`${W}/repos/HugoBlox/hugo-blox-builder/contents/templates`,De="https://github.com/HugoBlox/hugo-blox-builder.git",Ae="HBX_TEMPLATES_DIR",$="https://cli-api.hugoblox.com",Ne=`${$}/api/usage-insights`,ne="hugoblox",Re=1e3*60*60*24,Le=1e3*60*60*12;var he=[{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 ie="hbx.blocks.json";async function _(t=process.cwd()){let e=t,{root:o}=u.parse(t);for(;;){if((await Promise.all([v(u.join(e,"config","_default")),v(u.join(e,"hugoblox.yaml"))])).some(Boolean))return {root:e,manifestPath:u.join(e,ie)};if(e===o)return;e=u.dirname(e);}}async function Oe(t){let e=u.join(t,"hugoblox.yaml");if(await v(e))try{let o=await g.readFile(e,"utf8"),r=$t.parse(o);if(!r)return;let n=r.template??{},i=r.build??{};return {templateId:n.id,templateName:n.name,requiredHugoVersion:i.hugo_version}}catch(o){throw new d("Failed to parse hugoblox.yaml",{error:o})}}function Ue(t,e){At(t,e),Nt(t,e);}function At(t,e){t.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(o,r,n)=>{let{logger:i,telemetry:s}=e,c=!!n.optsWithGlobals().json,l=await Fe(r.path),p=["server"];r.defaultFlags!==false&&p.push("--disableFastRender"),p.push(...o),await Ve(p,l,i,{allowSignalExit:true,label:"dev server"}),await s.track({name:"dev",payload:{customPath:!!r.path,defaultFlags:r.defaultFlags!==false,args:o}}),c&&i.json({status:"success"});});}function Nt(t,e){t.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(o,r,n)=>{let{logger:i,telemetry:s}=e,c=!!n.optsWithGlobals().json,l=await Fe(r.path),p=[];r.defaultFlags!==false&&p.push("--gc","--minify"),p.push(...o),await Ve(p,l,i,{allowSignalExit:false,label:"build"}),await s.track({name:"build",payload:{customPath:!!r.path,defaultFlags:r.defaultFlags!==false,args:o}}),c&&i.json({status:"success"});});}async function Fe(t){let e=t?u.resolve(t):u.resolve(process.cwd()),o=await _(e);if(!o)throw new d("Unable to locate a HugoBlox project. Run this inside a project or pass --path.");return o.root}async function Ve(t,e,o,r){o.info(`Running: hugo ${t.join(" ")}`);try{await execa("hugo",t,{cwd:e,stdio:"inherit"}),o.success(`Hugo ${r.label} finished`);}catch(n){let i=n;if(r.allowSignalExit&&(i.signal==="SIGINT"||i.signal==="SIGTERM")){o.info("Hugo process stopped");return}throw new d(`Hugo ${r.label} failed: ${i.shortMessage??i.message}`,{error:i})}}var Ot=["github.com/HugoBlox/hugo-blox-builder","github.com/wowchemy/wowchemy-hugo-themes"];async function ae(t){let e=u.join(t,"go.mod");try{let o=await g.readFile(e,"utf8"),n=Ft(o).filter(s=>Ot.some(a=>s.path.startsWith(a)));return await Promise.all(n.map(async s=>{let a=await Mt(s.path);return {path:s.path,current:s.version,latest:a}}))}catch{return []}}async function Mt(t){if(t.includes("github.com/HugoBlox/hugo-blox-builder"))return Ut(t)}async function Ut(t){try{let e=await fetch(`${W}/repos/HugoBlox/hugo-blox-builder/tags?per_page=100`);if(!e.ok)return;let o=await e.json(),r=t.split("github.com/HugoBlox/hugo-blox-builder/");if(r.length<2)return;let n=r[1],i=o.filter(s=>s.name.startsWith(`${n}/`)&&/v\d+\.\d+\.\d+/.test(s.name)).map(s=>s.name);return i.length===0?void 0:(i.sort((s,a)=>{let c=s.split("/").pop()||"0.0.0",l=a.split("/").pop()||"0.0.0";return k.rcompare(c,l)}),i[0].split("/").pop())}catch{return}}function Ft(t){let e=[],o=t.split(/\r?\n/),r=false;for(let n of o){let i=n.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 ce(t,e){if(!t||!e)return {updateAvailable:false,diff:""};let o=k.coerce(t),r=k.coerce(e);return !o||!r?{updateAvailable:false,diff:""}:k.lt(o,r)?{updateAvailable:true,diff:`${X(t)} -> ${X(e)}`}:{updateAvailable:false,diff:""}}function X(t){let e=/v\d+\.\d+\.\d+-(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})-([a-f0-9]{12})/,o=t.match(e);if(o){let[r,n,i,s,a,c,l,p]=o;return `commit ${p.substring(0,7)} (released ${n}-${i}-${s})`}return t}function Xe(t){let e=process.env.HOME||process.env.USERPROFILE;if(!e)return t;let o=u.resolve(e),r=u.resolve(t);return r.startsWith(o)?r.replace(o,"~"):t}async function ze(t,e){try{let o=await execa(t,e,{reject:!1});return o.exitCode===0?o.stdout.trim():`Failed (${o.stderr.trim()})`}catch(o){return `Not available (${o.message})`}}function Je(t,e){t.command("doctor").description("Check local environment for common issues").action(async(o,r)=>{let{logger:n,config:i}=e,a=!!r.optsWithGlobals().json,c=[];c.push({name:"Node.js",ok:true,details:process.version});let l=await ze("hugo",["version"]);c.push({name:"Hugo",ok:!l.startsWith("Not"),details:l});let p=Gt(l),m=await ze("pnpm",["--version"]);c.push({name:"pnpm",ok:!m.startsWith("Not"),details:m});let h=i.getToken();c.push({name:"Pro license",ok:!!h,details:h?"Configured":"Missing"});let x=await _();if(x){let f=await Oe(x.root);if(f){let w=f.templateName??f.templateId??"Unknown";c.push({name:"Template",ok:true,details:`${w} (${Xe(x.root)})`});let E=Xt(f.requiredHugoVersion,p);E&&c.push(E);}let y=await ae(x.root);for(let w of y){let E=w.path.split("/").pop()||w.path,R=w.current;if(w.latest){let Q=k.coerce(w.current),O=k.coerce(w.latest);Q&&O&&k.eq(Q,O)&&(R=`${R} (latest)`);}c.push({name:`Module: ${E}`,ok:true,details:R});let{updateAvailable:L}=ce(w.current,w.latest);L&&w.latest&&c.push({name:`${E} update`,ok:false,details:`Current ${w.current}, latest ${w.latest}. Run 'hbx upgrade' to update.`,level:"warn"});}}let N={status:c.some(f=>(f.level??(f.ok?"info":"error"))==="error")?"error":"success",checks:c};if(a){n.json(N);return}for(let f of N.checks){let y=f.level??(f.ok?"info":"error");y==="info"?n.success(`${f.name}: ${f.details}`):y==="warn"?n.warn(`${f.name}: ${f.details}`):n.error(`${f.name}: ${f.details}`);}});}function Gt(t){let e=t.match(/v(\d+\.\d+\.\d+)/i);return e?e[1]:t.match(/(\d+\.\d+\.\d+)/)?.[1]}function Xt(t,e){if(!t||!e)return;let o=k.coerce(t),r=k.coerce(e);if(!(!o||!r))return k.lt(r,o)?{name:"Hugo version compatibility",ok:false,details:`Template requires Hugo ${o.version}, but ${r.version} is installed`,level:"error"}:k.major(r)>k.major(o)||k.minor(r)>k.minor(o)?{name:"Hugo version compatibility",ok:true,details:`Using Hugo ${r.version}; template tested with ${o.version}`,level:"warn"}:{name:"Hugo version compatibility",ok:true,details:`Template requires Hugo ${o.version} and you're running ${r.version}`,level:"info"}}function We(t,e){t.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(o,r)=>{let{logger:n,config:i,telemetry:s}=e,c=!!r.optsWithGlobals().json,l=o.path?{root:u.resolve(o.path),manifestPath:u.join(u.resolve(o.path),"hbx.blocks.json")}:await _();if(!l)throw new d("Unable to locate a HugoBlox project - pass --path if needed");let p=i.getToken();if(!p){if(o.ci)throw new d(`Missing license key. Set ${F} or run hbx login before using --ci.`);n.warn("No Pro license detected, proceeding with OSS assets only");}let m=yt("Hydrating Pro assets...").start();try{let x=u.join(l.root,"config","_default","module.hbx.toml"),b=u.join(l.root,"node_modules","@hugoblox-pro","sample");await C(b),await T(u.join(b,"README.md"),`# HugoBlox Pro assets placeholder
20
- `),await T(x,`# Generated by hbx install
21
- [[module.imports]]
22
- path = "github.com/HugoBlox/hugo-blox-builder"
23
- [[module.imports]]
24
- path = "node_modules/@hugoblox-pro/sample"
25
- `),m.succeed("Assets hydrated");}catch(x){throw m.fail("Failed to hydrate assets"),x}await s.track({name:"install",payload:{ci:!!o.ci,force:!!o.force,tokenPresent:!!p,customPath:!!o.path}});let h={status:"success",path:l.root,forced:!!o.force,token:!!p};c?n.json(h):(n.success("Install complete"),p||n.info("Tip: run hbx login to unlock Pro downloads"));});}var ye="com.hugoblox.cli",Kt=1,qt=createRequire(import.meta.url),Yt=promisify(K.scrypt),I=null;try{I=qt("keytar");}catch{I=null;}async function Ke(t,e,o,r,n){let i=`device:${o}`,s,a;if(I)await I.setPassword(ye,i,r);else {let c=await eo(r,e);s=c.payload,a=c.salt;}t.setDeviceInfo({id:o,label:n,secretAlias:I?i:void 0,secretFallback:s,secretFallbackSalt:a,secretFallbackVersion:s?Kt:void 0}),await t.save();}async function qe(t,e){let o=t.getDeviceInfo();if(!o?.id)return;let r;if(o.secretAlias&&I&&(r=await I.getPassword(ye,o.secretAlias)),!r&&o.secretFallback&&o.secretFallbackSalt)try{let{key:n}=await Ye(e,o.secretFallbackSalt);r=Zt(o.secretFallback,n);}catch{r=void 0;}if(r)return {id:o.id,secret:r,label:o.label}}async function we(t){let e=t.getDeviceInfo();e?.secretAlias&&I&&await I.deletePassword(ye,e.secretAlias),t.setDeviceInfo(void 0),await t.save();}function Qt(t,e){let o=K.randomBytes(12),r=K.createCipheriv("aes-256-gcm",e.subarray(0,32),o),n=Buffer.concat([r.update(t,"utf8"),r.final()]),i=r.getAuthTag();return Buffer.concat([o,i,n]).toString("base64")}function Zt(t,e){let o=Buffer.from(t,"base64"),r=o.subarray(0,12),n=o.subarray(12,28),i=o.subarray(28),s=K.createDecipheriv("aes-256-gcm",e.subarray(0,32),r);return s.setAuthTag(n),Buffer.concat([s.update(i),s.final()]).toString("utf8")}async function Ye(t,e){let o=Buffer.from(e,"base64");return {key:await Yt(t,o,32,{N:32768,r:8,p:1,maxmem:64*1024*1024}),salt:e}}async function eo(t,e){let o=K.randomBytes(16).toString("base64"),{key:r}=await Ye(e,o);return {payload:Qt(t,r),salt:o}}async function P(t,e={}){let o=t.config.getToken();if(!o)throw new d("Set HBX_LICENSE_TOKEN or run 'hbx login' to access Pro content.");let r=await t.config.ensureTelemetryId();if(e.force)await we(t.config);else {let s=await qe(t.config,r);if(s)return {id:s.id,secret:s.secret}}let n=e.label??ue.hostname(),i=await oo(t.config,o,r,n);return await Ke(t.config,r,i.deviceId,i.deviceSecret,n),t.logger.debug(`Registered device ${i.deviceId}`),{id:i.deviceId,secret:i.deviceSecret}}async function Qe(t){await we(t);}async function oo(t,e,o,r){let n=await fetch(`${$}/api/license/devices/register`,{method:"POST",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json","x-telemetry-id":o},body:JSON.stringify({deviceLabel:r})}),i=await ro(n);if(!n.ok)throw i?.code==="license_device_limit"?new d("This license has reached the maximum number of devices. Revoke an existing device and try again."):n.status===401||n.status===403?new d(i?.error??"Unable to register device"):new d(i?.error??`Device registration failed (status ${n.status})`);if(!i?.deviceId||!i?.deviceSecret)throw new d("Device registration response was missing credentials");return i}async function ro(t){try{return await t.json()}catch{return}}async function q(t,e={}){if(e.ci){if(typeof e.initial=="string")return e.initial;throw new d(`Option required in CI mode: ${t}`)}return (await be({type:"text",name:"value",message:t,initial:e.initial},{onCancel:()=>{throw new U}})).value}async function Ze(t,e,o={}){if(o.ci){if(typeof o.initial=="string")return o.initial;throw new d(`Option required in CI mode: ${t}`)}return (await be({type:"select",name:"value",message:t,choices:e,initial:0},{onCancel:()=>{throw new U}})).value}async function H(t,e={}){if(e.ci){if(typeof e.initial=="boolean")return e.initial;throw new d(`Confirmation required in CI mode: ${t}`)}return (await be({type:"confirm",name:"value",message:t,initial:e.initial??true},{onCancel:()=>{throw new U}})).value}function ve(t){return t?t.length<=6?"***":`${t.slice(0,3)}***${t.slice(-2)}`:"(none)"}function et(t,e){let o=t??e;return u.resolve(process.cwd(),o)}function tt(t,e){t.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(o,r)=>{let{config:n,logger:i}=e,a=!!r.optsWithGlobals().json,c=o.token;if(!c){if(o.ci)throw new d("License key is required when using --ci");c=await q("Enter your HugoBlox Pro license key");}let l=false;try{n.setToken(c),await n.save(),l=!0,await P(e,{force:!0});let p={status:"success",token:ve(c)};a?i.json(p):i.success(`License key saved (${ve(c)})`);}catch(p){throw l&&(n.clearToken(),await n.save()),io(p)}});}function ot(t,e){t.command("logout").description("Remove stored HugoBlox credentials and device secrets").action(async(o,r)=>{let{config:n,logger:i}=e,s=!!r.optsWithGlobals().json;await Qe(n),n.clearToken(),await n.save();let a={status:"success"};s?i.json(a):i.success("License key removed");});}function io(t){let e=t instanceof Error?t.message:"Device registration failed",o="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 t instanceof S?new d(`${e}. ${o}`,t.details):new d(`${e}. ${o}`)}function so(t){return t.split("-").map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}async function rt(t){let{logger:e}=t,o=await ao(e),r=await co(t);return o.length||r.length?[...r,...o]:he}async function ao(t){try{let e=await fetch($e,{headers:{"User-Agent":"hbx-cli"}});if(!e.ok)throw new Error(`GitHub responded with status ${e.status}`);return (await e.json()).filter(n=>n.type==="dir").map(n=>({id:n.name,name:so(n.name),description:`Starter template ${n.name}`,repoPath:n.path,slug:n.name,source:"oss"}))}catch(e){return t?.debug?.(`Falling back to offline starter metadata: ${String(e)}`),he}}async function co(t){let{logger:e,config:o}=t,r=new Headers({"User-Agent":"hbx-cli"});try{let i=await o.ensureTelemetryId();r.set("x-telemetry-id",i);}catch{}let n=o.getToken();if(n)try{let i=await P(t);r.set("Authorization",`Bearer ${n}`),r.set("X-HBX-Device-Id",i.id),r.set("X-HBX-Device-Secret",i.secret);}catch(i){e?.debug?.(`Skipping device-auth headers for Pro templates: ${String(i)}`);}try{let i=await fetch(`${$}/api/pro-templates`,{headers:r});if(!i.ok)throw new Error(`catalog responded with status ${i.status}`);return (await i.json()).templates.map(a=>({id:a.id,name:`${a.name} (Pro)`,description:a.description??void 0,repoPath:void 0,slug:a.slug??a.id,source:"pro",version:a.version,sizeBytes:a.sizeBytes,updatedAt:a.updatedAt,commitHash:a.commitHash,downloadEndpoint:a.downloadUrl}))}catch(i){return e.debug(`Unable to fetch Pro template catalog: ${String(i)}`),[]}}async function nt(t,e){try{await execa("git",["init"],{cwd:t}),await execa("git",["add","."],{cwd:t}),await execa("git",["commit","-m","chore: initialize site"],{cwd:t,reject:!1}),e.success(`Initialized git repository in ${u.relative(process.cwd(),t)||"."}`);}catch(o){e.warn(`Git initialization skipped: ${String(o)}`);}}async function Ee(t,e,o={},r=0){let n=t.config.getToken();if(!n)throw new d("A HugoBlox Pro license key is required before accessing Pro templates.");let i=await t.config.ensureTelemetryId(),s=await P(t,{force:r>0}),a=new Headers(o.headers??{});a.set("Authorization",`Bearer ${n}`),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(`${$}${e}`,{...o,headers:a});if((c.status===401||c.status===403)&&r===0)return await P(t,{force:true}),Ee(t,e,o,r+1);if(!c.ok){let l=await mo(c);throw l?.code==="license_device_limit"?new d("This license has reached the maximum number of devices. Revoke an existing device and try again."):c.status===401||c.status===403?new d(l?.error??"Device authentication failed."):new d(l?.error??`Request failed (${c.status})`)}return c}async function mo(t){try{return await t.json()}catch{return}}var po=3;async function at(t,e,o,r){if(e.source==="pro"){await ho(t,e,o,r);return}let n=process.env[Ae];if(n){await uo(e,n,o),r.debug(`Hydrated template ${e.id} from local override`);return}let i=await go(e,r),s=i!==void 0?u.join(V,e.id,i):void 0;if(s&&await v(s)){await D(s,o),r.debug(`Hydrated template ${e.id} from cache (${i})`);return}let a=await g.mkdtemp(u.join(ue.tmpdir(),"hbx-template-")),c=u.join(a,"repo");try{await execa("git",["clone","--depth","1",De,c],{stdio:"ignore"});let l=await fo(c,e);s?(await C(u.dirname(s)),await g.rm(s,{recursive:!0,force:!0}),await g.cp(l,s,{recursive:!0}),await ct(u.join(V,e.id)),await D(s,o),r.debug(`Hydrated template ${e.id} from fresh cache (${i})`)):(await D(l,o),r.debug(`Hydrated template ${e.id} from repository`));}catch(l){throw new d("Failed to clone HugoBlox templates. Ensure git is installed and accessible.",{error:l})}finally{await g.rm(a,{recursive:true,force:true});}}async function uo(t,e,o){let r=u.join(e,t.id);try{await g.access(r);}catch(n){throw new d(`Local template not found at ${r}`,{error:n})}await D(r,o);}async function fo(t,e){let o=e.repoPath??"",r=u.join(t,o);return await g.access(r),r}async function D(t,e){await g.rm(e,{recursive:true,force:true}),await C(u.dirname(e)),await g.cp(t,e,{recursive:true}),await g.rm(u.join(e,".git"),{recursive:true,force:true});}async function ct(t){if(!await v(t))return;let e=await g.readdir(t,{withFileTypes:true}),o=await Promise.all(e.filter(r=>r.isDirectory()).map(async r=>{let n=u.join(t,r.name),i=await g.stat(n);return {path:n,mtimeMs:i.mtimeMs}}));o.sort((r,n)=>n.mtimeMs-r.mtimeMs);for(let r of o.slice(po))await g.rm(r.path,{recursive:true,force:true});}async function go(t,e){let o=encodeURIComponent(t.repoPath??""),r=`${W}/repos/HugoBlox/hugo-blox-builder/commits?path=${o}&per_page=1`;try{let n=await fetch(r,{headers:{"User-Agent":"hbx-cli"}});if(!n.ok)throw new Error(`GitHub responded with status ${n.status}`);return (await n.json())[0]?.sha}catch(n){e.debug(`Unable to determine latest template commit for ${t.id}: ${String(n)}`);return}}async function ho(t,e,o,r){let n=e.version?u.join(V,e.id,e.version):void 0;if(n&&await v(n)){await D(n,o),r.debug(`Hydrated Pro template ${e.id} from cache (${e.version})`);return}let i=await g.mkdtemp(u.join(ue.tmpdir(),"hbx-pro-template-")),s=u.join(i,"template.tgz"),a=u.join(i,"extract");await C(a);try{let c=await yo(t,e,s);await execa("tar",["-xzf",s,"-C",a]);let l=await wo(a,e.slug),p=e.version??c.version??void 0,m=p!==void 0?u.join(V,e.id,p):void 0;m?(await C(u.dirname(m)),await g.rm(m,{recursive:!0,force:!0}),await g.cp(l,m,{recursive:!0}),await ct(u.join(V,e.id)),await D(m,o),r.debug(`Hydrated Pro template ${e.id} from fresh cache (${p})`)):(await D(l,o),r.debug(`Hydrated Pro template ${e.id} from archive`));}catch(c){throw new d(`Failed to download Pro template ${e.name}. Ensure your license is valid and try again.`,{error:c})}finally{await g.rm(i,{recursive:true,force:true});}}async function yo(t,e,o){let r=e.downloadEndpoint??`/api/pro-templates/${encodeURIComponent(e.id)}/download`,n=await Ee(t,r),i=await bo(n);if(!i?.url)throw new d("Pro template download URL was missing");let s=await fetch(i.url);if(!s.ok)throw new d(`Pro template archive download failed (${s.status})`);let a=Buffer.from(await s.arrayBuffer());return await g.writeFile(o,a),{version:i.version}}async function wo(t,e){let o=await g.readdir(t,{withFileTypes:true}),r=o.find(i=>i.isDirectory()&&i.name===e);if(r)return u.join(t,r.name);let n=o.filter(i=>i.isDirectory());return n.length===1?u.join(t,n[0].name):t}async function bo(t){try{return await t.json()}catch{return}}var lt="https://hugoblox.com/discord",dt="https://docs.hugoblox.com",mt="https://hugoblox.com/pro";function Ce(t){return t.trim().toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-{2,}/g,"-").replace(/^-+|-+$/g,"").slice(0,64)}async function ft(t,e,o,r){let{logger:n}=t;await at(t,o,e,n),await xo(e,o),r.sampleContent||await Co(e,o);}async function gt(t,e,o){o.info(`\u{1F4E6} Installing dependencies with ${e}...`);let r={...process.env},n=["install"],i=!o.isJsonMode();e==="pnpm"&&(r.PNPM_WORKSPACE_DIR=t,r.PNPM_IGNORE_WORKSPACE_ROOT_CHECK="1",await vo(t),n.push("--no-link-workspace-packages"));try{return await execa(e,n,{cwd:t,stdio:i?"ignore":"inherit",env:r}),o.success("\u2705 Dependencies installed"),!0}catch(s){return i?o.warn(`\u26A0\uFE0F Failed to install dependencies automatically. Run ${e} install inside ${t}`):o.warn(`\u26A0\uFE0F Failed to install dependencies automatically: ${String(s)}`),false}}async function vo(t){let e=u.join(t,"pnpm-workspace.yaml");if(await v(e))return;await T(e,`packages:
20
+ var R=class extends Error{constructor(e,o="HBX_ERROR",r){super(e),this.name="HbxError",this.code=o,this.details=r;}},d=class extends R{constructor(e,o){super(e,"HBX_INPUT_ERROR",o);}},G=class extends R{constructor(e="Operation cancelled by user"){super(e,"HBX_ABORTED");}},ie=class extends R{constructor(e,o){super(e,"HBX_CONFIG_ERROR",o);}};function De(t){return !!(t&&typeof t=="object"&&"code"in t)}async function v(t){try{return await P.access(t),!0}catch{return false}}async function H(t){await P.mkdir(t,{recursive:true});}async function Ne(t){if(!await v(t)){await H(t);return}if((await P.readdir(t)).length>0)throw new Error(`Directory ${t} is not empty`)}async function $(t,e){await H(E.dirname(t)),await P.writeFile(t,e);}var ce="hbx",ee="HBX_DEBUG",X="HBX_LICENSE_TOKEN",Me="HBX_TELEMETRY_DISABLED",Ce=E.join(ve.homedir(),".hbx"),le=E.join(Ce,"config.json"),Qt=E.join(ve.homedir(),".cache","hbx"),W=E.join(Qt,"templates"),Fe="HBX_UPDATE_CHECK_DISABLED",z="https://api.github.com",Ue=`${z}/repos/HugoBlox/hugo-blox-builder/contents/templates`,Ve="https://github.com/HugoBlox/hugo-blox-builder.git",Ge="HBX_TEMPLATES_DIR",M="https://cli-api.hugoblox.com",Xe=`${M}/api/usage-insights`,me="hugoblox",We=1e3*60*60*24,ze=1e3*60*60*12;var Ee=[{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 de="hbx.blocks.json";async function A(t=process.cwd()){let e=t,{root:o}=E.parse(t);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,de)};if(e===o)return;e=E.dirname(e);}}async function Je(t){let e=E.join(t,"hugoblox.yaml");if(await v(e))try{let o=await P.readFile(e,"utf8"),r=Ze.parse(o);if(!r)return;let i=r.template??{},n=r.build??{};return {templateId:i.id,templateName:i.name,requiredHugoVersion:n.hugo_version}}catch(o){throw new d("Failed to parse hugoblox.yaml",{error:o})}}async function qe(){try{let{stdout:t}=await execa("hugo",["version"]);return oo(t)}catch{return}}function oo(t){let e=t.match(/v(\d+\.\d+\.\d+)/i);return e?e[1]:t.match(/(\d+\.\d+\.\d+)/)?.[1]}var F=class extends Error{constructor(o,r){super(o);this.cause=r;this.name="NetworkError";}};async function q(t,e={}){let{timeout:o=15e3,retries:r=3,backoff:i=500,...n}=e,s=0;for(;s<=r;){let a=new AbortController,c=setTimeout(()=>a.abort(),o);try{let l=await fetch(t,{...n,signal:a.signal});if(clearTimeout(c),l.status===429||l.status>=500&&l.status<600)throw new F(`Server error: ${l.status}`);return l}catch(l){clearTimeout(c),s++;let u=l.name==="AbortError";if(s>r)throw u?new F(`Request timed out after ${o}ms`,l):l instanceof F?l:new F("Network request failed",l);let T=i*2**(s-1);await new Promise(m=>setTimeout(m,T));}}throw new F("Unreachable")}async function Ye(){try{return await Ke.lookup("google.com"),!0}catch{try{return await Ke.lookup("1.1.1.1"),!0}catch{return false}}}async function j(t,e={}){if(e.ci){if(typeof e.initial=="string")return e.initial;throw new d(`Option required in CI mode: ${t}`)}return (await Pe({type:"text",name:"value",message:t,initial:e.initial},{onCancel:()=>{throw new G}})).value}async function te(t,e,o={}){if(o.ci){if(typeof o.initial=="string")return o.initial;throw new d(`Option required in CI mode: ${t}`)}return (await Pe({type:"select",name:"value",message:t,choices:e,initial:0},{onCancel:()=>{throw new G}})).value}async function _(t,e={}){if(e.ci){if(typeof e.initial=="boolean")return e.initial;throw new d(`Confirmation required in CI mode: ${t}`)}return (await Pe({type:"confirm",name:"value",message:t,initial:e.initial??true},{onCancel:()=>{throw new G}})).value}function et(t){let e=t.match(/github\.com[/:]([\w-]+)\/([\w-]+?)(?:\.git)?$/i);return e?{owner:e[1],repo:e[2]}:null}function ro(t){return et(t)!==null}async function no(t,e){let o=`https://api.github.com/repos/${t}/${e}/contents/hugoblox/themes`;try{let r=await q(o,{headers:{"User-Agent":"hbx-cli",Accept:"application/vnd.github.v3+json"}});if(!r.ok)throw r.status===404?new d(`Repository does not contain a 'hugoblox/themes' directory. Please check the repository structure at https://github.com/${t}/${e}`):new d(`Failed to fetch themes from GitHub (status ${r.status})`);let n=(await r.json()).filter(s=>s.type==="file"&&s.name.toLowerCase().endsWith(".yaml"));if(n.length===0)throw new d(`No theme files found in hugoblox/themes directory at https://github.com/${t}/${e}`);return n.map(s=>({name:s.name,downloadUrl:s.download_url}))}catch(r){throw r instanceof d?r:new d(`Failed to access GitHub repository: ${r instanceof Error?r.message:String(r)}`)}}async function io(t,e){let o=await q(t,{headers:{"User-Agent":"hbx-cli"}});if(!o.ok)throw new d(`Failed to download theme file (status ${o.status})`);let r=await o.text();await $(e,r);}async function so(t,e){let o=E.join(t,"config","_default","params.yaml");if(!await v(o))throw new d(`params.yaml not found at ${o}. Please ensure you're in a HugoBlox site.`);let r=await P.readFile(o,"utf8"),i=Ze.parse(r),n=typeof i=="object"&&i!==null?i:{};(typeof n.hugoblox!="object"||n.hugoblox===null)&&(n.hugoblox={});let s=n.hugoblox;(typeof s.theme!="object"||s.theme===null)&&(s.theme={}),s.theme.pack=e;let a=Ze.stringify(n);await P.writeFile(o,a,"utf8");}function N(t){return t.toLowerCase().replace(/\.yaml$/i,"")}function tt(t,e){t.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(o,r)=>{let{logger:i,telemetry:n}=e,s=!!r.optsWithGlobals().json;try{let a=await A();if(!a)throw new d("Not in a HugoBlox site. Please run this command from within a HugoBlox site directory (must contain hugoblox.yaml)");let c=a.root,l=o.repo;if(!l){if(o.ci)throw new d("--repo is required when running with --ci");l=await j("Enter the GitHub repository URL containing themes (e.g., https://github.com/username/themes-repo):");}if(l=l.trim(),!ro(l))throw new d("Invalid GitHub repository URL. Please provide a valid GitHub URL (e.g., https://github.com/owner/repo)");let u=et(l);if(!u)throw new d("Failed to parse GitHub URL");let{owner:g,repo:T}=u,m=g,f=Te("Fetching available themes...").start(),y;try{y=await no(g,T),f.succeed(`Found ${y.length} theme(s)`);}catch(w){throw f.fail("Failed to fetch themes"),w}let p,h=o.theme;if(!h)if(o.ci)h="all";else {let w=[{title:"All themes",value:"all"},...y.map(C=>({title:N(C.name),value:C.name}))];h=await te("Which theme(s) do you want to download?",w);}if(h.toLowerCase()==="all")p=y;else {let w=N(h),b=y.find(C=>N(C.name)===w);if(!b)throw new d(`Theme '${h}' not found. Available themes: ${y.map(C=>C.name).join(", ")}`);p=[b];}let I=E.join(c,"data","themes",m);await H(I);let x=Te(`Downloading ${p.length} theme(s)...`).start();try{for(let w of p){let b=E.join(I,w.name);await io(w.downloadUrl,b);}x.succeed(`\u2705 Downloaded ${p.length} theme(s) to data/themes/${m}/`);}catch(w){throw x.fail("Failed to download themes"),w}let k=!1,S=null;if((o.setActive||o.setActive!==!1&&!o.noSetActive)&&(o.ci?p.length===1&&(k=!0,S=N(p[0].name)):(k=await _("Do you want to set one of these themes as active?",{initial:p.length===1}),k&&(p.length===1?S=N(p[0].name):S=await te("Which theme do you want to activate?",p.map(b=>({title:N(b.name),value:N(b.name)})))))),k&&S){let w=`${m}/${S}`,b=Te("Updating params.yaml...").start();try{await so(c,w),b.succeed(`\u2705 Set active theme to: ${w}`);}catch(C){throw b.fail("Failed to update params.yaml"),C}}if(await n.track({name:"add-theme",payload:{vendor:m,themesCount:p.length,activated:k,ci:!!o.ci}}),s){i.json({status:"success",vendor:m,themes:p.map(w=>w.name),activated:S?`${m}/${S}`:null});return}i.success(`
21
+ \u{1F3A8} Themes installed successfully!`),(!k||!S)&&(i.info(`
22
+ \u{1F4DD} To use a theme, update your config/_default/params.yaml:`),i.info(`
23
+ hugoblox:`),i.info(" theme:"),i.info(` pack: "${m}/${N(p[0].name)}"`));}catch(a){if(s){i.json({status:"error",message:a instanceof Error?a.message:String(a)});return}throw a}});}function ot(t,e){let o=t.command("add").description("Add resources (themes)");tt(o,e);}function rt(t,e){t.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((o,r,i)=>{let{logger:n}=e,s=!!i.optsWithGlobals().json,a="Block creation is coming soon. Follow Discord for updates or to preview it early.";if(s){n.json({status:"pending",message:a});return}n.info(a);});}var He="com.hugoblox.cli",lo=1,mo=createRequire(import.meta.url),uo=promisify(oe.scrypt),D=null;try{D=mo("keytar");}catch{D=null;}async function nt(t,e,o,r,i){let n=`device:${o}`,s,a;if(D)await D.setPassword(He,n,r);else {let c=await go(r,e);s=c.payload,a=c.salt;}t.setDeviceInfo({id:o,label:i,secretAlias:D?n:void 0,secretFallback:s,secretFallbackSalt:a,secretFallbackVersion:s?lo:void 0}),await t.save();}async function it(t,e){let o=t.getDeviceInfo();if(!o?.id)return;let r;if(o.secretAlias&&D&&(r=await D.getPassword(He,o.secretAlias)),!r&&o.secretFallback&&o.secretFallbackSalt)try{let{key:i}=await st(e,o.secretFallbackSalt);r=fo(o.secretFallback,i);}catch{r=void 0;}if(r)return {id:o.id,secret:r,label:o.label}}async function Se(t){let e=t.getDeviceInfo();e?.secretAlias&&D&&await D.deletePassword(He,e.secretAlias),t.setDeviceInfo(void 0),await t.save();}function po(t,e){let o=oe.randomBytes(12),r=oe.createCipheriv("aes-256-gcm",e.subarray(0,32),o),i=Buffer.concat([r.update(t,"utf8"),r.final()]),n=r.getAuthTag();return Buffer.concat([o,n,i]).toString("base64")}function fo(t,e){let o=Buffer.from(t,"base64"),r=o.subarray(0,12),i=o.subarray(12,28),n=o.subarray(28),s=oe.createDecipheriv("aes-256-gcm",e.subarray(0,32),r);return s.setAuthTag(i),Buffer.concat([s.update(n),s.final()]).toString("utf8")}async function st(t,e){let o=Buffer.from(e,"base64");return {key:await uo(t,o,32,{N:32768,r:8,p:1,maxmem:64*1024*1024}),salt:e}}async function go(t,e){let o=oe.randomBytes(16).toString("base64"),{key:r}=await st(e,o);return {payload:po(t,r),salt:o}}async function B(t,e={}){let o=t.config.getLicense();if(!o)throw new d("Set HBX_LICENSE_TOKEN or run 'hbx login' to access Pro content.");let r=await t.config.ensureTelemetryId();if(e.force)await Se(t.config);else {let s=await it(t.config,r);if(s)return {id:s.id,secret:s.secret}}let i=e.label??ve.hostname(),n=await yo(t.config,o,r,i);return await nt(t.config,r,n.deviceId,n.deviceSecret,i),t.logger.debug(`Registered device ${n.deviceId}`),{id:n.deviceId,secret:n.deviceSecret}}async function at(t){await Se(t);}async function yo(t,e,o,r){let i=await fetch(`${M}/api/license/devices/register`,{method:"POST",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json","x-telemetry-id":o},body:JSON.stringify({deviceLabel:r})}),n=await wo(i);if(!i.ok)throw n?.code==="license_device_limit"?new d("This license has reached the maximum number of devices. Revoke an existing device and try again."):i.status===401||i.status===403?new d(n?.error??"Unable to register device"):new d(n?.error??`Device registration failed (status ${i.status})`);if(!n?.deviceId||!n?.deviceSecret)throw new d("Device registration response was missing credentials");return n}async function wo(t){try{return await t.json()}catch{return}}function bo(t){return t.split("-").map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}async function ct(t){let{logger:e}=t,o=await vo(e),r=await xo(t);return o.length||r.length?[...r,...o]:Ee}async function vo(t){try{let e=await fetch(Ue,{headers:{"User-Agent":"hbx-cli"}});if(!e.ok)throw new Error(`GitHub responded with status ${e.status}`);return (await e.json()).filter(i=>i.type==="dir").map(i=>({id:i.name,name:bo(i.name),description:`Starter template ${i.name}`,repoPath:i.path,slug:i.name,source:"oss"}))}catch(e){return t?.debug?.(`Falling back to offline starter metadata: ${String(e)}`),Ee}}async function xo(t){let{logger:e,config:o}=t,r=new Headers({"User-Agent":"hbx-cli"});try{let n=await o.ensureTelemetryId();r.set("x-telemetry-id",n);}catch{}let i=o.getLicense();if(i)try{let n=await B(t);r.set("Authorization",`Bearer ${i}`),r.set("X-HBX-Device-Id",n.id),r.set("X-HBX-Device-Secret",n.secret);}catch(n){e?.debug?.(`Skipping device-auth headers for Pro templates: ${String(n)}`);}try{let n=await fetch(`${M}/api/pro-templates`,{headers:r});if(!n.ok)throw new Error(`catalog responded with status ${n.status}`);return (await n.json()).templates.map(a=>({id:a.id,name:`${a.name} (Pro)`,description:a.description??void 0,repoPath:void 0,slug:a.slug??a.id,source:"pro",version:a.version,sizeBytes:a.sizeBytes,updatedAt:a.updatedAt,commitHash:a.commitHash,downloadEndpoint:a.downloadUrl}))}catch(n){return e.debug(`Unable to fetch Pro template catalog: ${String(n)}`),[]}}async function lt(t,e){try{await execa("git",["init"],{cwd:t}),await execa("git",["add","."],{cwd:t}),await execa("git",["commit","-m","chore: initialize site"],{cwd:t,reject:!1}),e.success(`Initialized git repository in ${E.relative(process.cwd(),t)||"."}`);}catch(o){e.warn(`Git initialization skipped: ${String(o)}`);}}async function Ie(t,e,o={},r=0){let i=t.config.getLicense();if(!i)throw new d("A HugoBlox Pro license key is required before accessing Pro templates.");let n=await t.config.ensureTelemetryId(),s=await B(t,{force:r>0}),a=new Headers(o.headers??{});a.set("Authorization",`Bearer ${i}`),a.set("X-HBX-Device-Id",s.id),a.set("X-HBX-Device-Secret",s.secret),a.set("X-Telemetry-Id",n);let c=await fetch(`${M}${e}`,{...o,headers:a});if((c.status===401||c.status===403)&&r===0)return await B(t,{force:true}),Ie(t,e,o,r+1);if(!c.ok){let l=await Eo(c);throw l?.code==="license_device_limit"?new d("This license has reached the maximum number of devices. Revoke an existing device and try again."):c.status===401||c.status===403?new d(l?.error??"Device authentication failed."):new d(l?.error??`Request failed (${c.status})`)}return c}async function Eo(t){try{return await t.json()}catch{return}}var Po=3;async function ut(t,e,o,r){if(e.source==="pro"){await So(t,e,o,r);return}let i=process.env[Ge];if(i){await To(e,i,o),r.debug(`Hydrated template ${e.id} from local override`);return}let n=await Ho(e,r),s=n!==void 0?E.join(W,e.id,n):void 0;if(s&&await v(s)){await U(s,o),r.debug(`Hydrated template ${e.id} from cache (${n})`);return}let a=await P.mkdtemp(E.join(ve.tmpdir(),"hbx-template-")),c=E.join(a,"repo");try{await execa("git",["clone","--depth","1",Ve,c],{stdio:"ignore"});let l=await ko(c,e);s?(await H(E.dirname(s)),await P.rm(s,{recursive:!0,force:!0}),await P.cp(l,s,{recursive:!0}),await pt(E.join(W,e.id)),await U(s,o),r.debug(`Hydrated template ${e.id} from fresh cache (${n})`)):(await U(l,o),r.debug(`Hydrated template ${e.id} from repository`));}catch(l){throw new d("Failed to clone HugoBlox templates. Ensure git is installed and accessible.",{error:l})}finally{await P.rm(a,{recursive:true,force:true});}}async function To(t,e,o){let r=E.join(e,t.id);try{await P.access(r);}catch(i){throw new d(`Local template not found at ${r}`,{error:i})}await U(r,o);}async function ko(t,e){let o=e.repoPath??"",r=E.join(t,o);return await P.access(r),r}async function U(t,e){await P.rm(e,{recursive:true,force:true}),await H(E.dirname(e)),await P.cp(t,e,{recursive:true}),await P.rm(E.join(e,".git"),{recursive:true,force:true});}async function pt(t){if(!await v(t))return;let e=await P.readdir(t,{withFileTypes:true}),o=await Promise.all(e.filter(r=>r.isDirectory()).map(async r=>{let i=E.join(t,r.name),n=await P.stat(i);return {path:i,mtimeMs:n.mtimeMs}}));o.sort((r,i)=>i.mtimeMs-r.mtimeMs);for(let r of o.slice(Po))await P.rm(r.path,{recursive:true,force:true});}async function Ho(t,e){let o=encodeURIComponent(t.repoPath??""),r=`${z}/repos/HugoBlox/hugo-blox-builder/commits?path=${o}&per_page=1`;try{let i=await fetch(r,{headers:{"User-Agent":"hbx-cli"}});if(!i.ok)throw new Error(`GitHub responded with status ${i.status}`);return (await i.json())[0]?.sha}catch(i){e.debug(`Unable to determine latest template commit for ${t.id}: ${String(i)}`);return}}async function So(t,e,o,r){let i=e.version?E.join(W,e.id,e.version):void 0;if(i&&await v(i)){await U(i,o),r.debug(`Hydrated Pro template ${e.id} from cache (${e.version})`);return}let n=await P.mkdtemp(E.join(ve.tmpdir(),"hbx-pro-template-")),s=E.join(n,"template.tgz"),a=E.join(n,"extract");await H(a);try{let c=await $o(t,e,s);await execa("tar",["-xzf",s,"-C",a]);let l=await Io(a,e.slug),u=e.version??c.version??void 0,g=u!==void 0?E.join(W,e.id,u):void 0;g?(await H(E.dirname(g)),await P.rm(g,{recursive:!0,force:!0}),await P.cp(l,g,{recursive:!0}),await pt(E.join(W,e.id)),await U(g,o),r.debug(`Hydrated Pro template ${e.id} from fresh cache (${u})`)):(await U(l,o),r.debug(`Hydrated Pro template ${e.id} from archive`));}catch(c){throw new d(`Failed to download Pro template ${e.name}. Ensure your license is valid and try again.`,{error:c})}finally{await P.rm(n,{recursive:true,force:true});}}async function $o(t,e,o){let r=e.downloadEndpoint??`/api/pro-templates/${encodeURIComponent(e.id)}/download`,i=await Ie(t,r),n=await _o(i);if(!n?.url)throw new d("Pro template download URL was missing");let s=await fetch(n.url);if(!s.ok)throw new d(`Pro template archive download failed (${s.status})`);let a=Buffer.from(await s.arrayBuffer());return await P.writeFile(o,a),{version:n.version}}async function Io(t,e){let o=await P.readdir(t,{withFileTypes:true}),r=o.find(n=>n.isDirectory()&&n.name===e);if(r)return E.join(t,r.name);let i=o.filter(n=>n.isDirectory());return i.length===1?E.join(t,i[0].name):t}async function _o(t){try{return await t.json()}catch{return}}var ft="https://hugoblox.com/discord",gt="https://docs.hugoblox.com",ht="https://hugoblox.com/pro";function re(t){return t.trim().toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-{2,}/g,"-").replace(/^-+|-+$/g,"").slice(0,64)}async function bt(t,e,o,r){let{logger:i}=t;await ut(t,o,e,i),await Bo(e,o),r.sampleContent||await Lo(e,o);}async function vt(t,e,o){o.info(`\u{1F4E6} Installing dependencies with ${e}...`);let r={...process.env},i=["install"],n=!o.isJsonMode();e==="pnpm"&&(r.PNPM_WORKSPACE_DIR=t,r.PNPM_IGNORE_WORKSPACE_ROOT_CHECK="1",await jo(t),i.push("--no-link-workspace-packages"));try{return await execa(e,i,{cwd:t,stdio:n?"ignore":"inherit",env:r}),o.success("\u2705 Dependencies installed"),!0}catch(s){return n?o.warn(`\u26A0\uFE0F Failed to install dependencies automatically. Run ${e} install inside ${t}`):o.warn(`\u26A0\uFE0F Failed to install dependencies automatically: ${String(s)}`),false}}async function jo(t){let e=E.join(t,"pnpm-workspace.yaml");if(await v(e))return;await $(e,`packages:
26
24
  - './*'
27
- `);}async function ht(t,e,o){o.info("\u{1F525} Starting dev server with Hugo (press Ctrl+C to exit)...");let r={...process.env};e==="pnpm"&&(r.PNPM_WORKSPACE_DIR=t);try{await execa(e,["dev"],{cwd:t,stdio:"inherit",env:r}),o.success("\u2705 Dev server stopped");}catch(n){let i=n;if(i.signal==="SIGINT"||i.signal==="SIGTERM"){o.info("\u2705 Dev server stopped");return}if(n?.code==="ENOENT"||/[hH]ugo/.test(String(i.stderr))){o.error("Hugo executable not found. Install Hugo (https://gohugo.io/getting-started/installing/) or deploy with the Copilot at https://hugoblox.com/templates/");return}throw o.error(`Dev server exited with an error: ${String(n)}`),n}}async function xo(t,e,o){let r=Ce(u.basename(t))||e.slug;await Eo(t,r);let n={"README.md":`# ${e.name}
25
+ `);}async function xt(t,e,o){o.info("\u{1F525} Starting dev server with Hugo (press Ctrl+C to exit)...");let r={...process.env};e==="pnpm"&&(r.PNPM_WORKSPACE_DIR=t);try{await execa(e,["dev"],{cwd:t,stdio:"inherit",env:r}),o.success("\u2705 Dev server stopped");}catch(i){let n=i;if(n.signal==="SIGINT"||n.signal==="SIGTERM"){o.info("\u2705 Dev server stopped");return}if(i?.code==="ENOENT"||/[hH]ugo/.test(String(n.stderr))){o.error("Hugo executable not found. Install Hugo (https://gohugo.io/getting-started/installing/) or deploy with the Copilot at https://hugoblox.com/templates/");return}throw o.error(`Dev server exited with an error: ${String(i)}`),i}}async function Bo(t,e,o){let r=re(E.basename(t))||e.slug;await Ao(t,r);let i={"README.md":`# ${e.name}
28
26
 
29
27
  This site was created with the HugoBlox CLI.
30
28
  `,".gitignore":`node_modules
@@ -33,9 +31,9 @@ This site was created with the HugoBlox CLI.
33
31
  public
34
32
  .DS_Store
35
33
  modules/_vendor
36
- `};(n[".env"]=`# HBX environment variables
34
+ `};(i[".env"]=`# HBX environment variables
37
35
  HBX_LICENSE_TOKEN=
38
- `);for(let[i,s]of Object.entries(n)){let a=u.join(t,i);await v(a)||await T(a,s);}}async function Eo(t,e){let o=u.join(t,"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(o)){await T(o,JSON.stringify(r,null,2));return}try{let n=await g.readFile(o,"utf8"),i=JSON.parse(n),s={...r,...i,name:e,scripts:{...r.scripts,...i.scripts},dependencies:{...r.dependencies,...i.dependencies}};await T(o,JSON.stringify(s,null,2));}catch{await T(o,JSON.stringify(r,null,2));}}async function Co(t,e){let o=u.join(t,"content");await g.rm(o,{recursive:true,force:true}),await C(u.dirname(u.join(o,"_index.md"))),await T(u.join(o,"_index.md"),Po(e));}function Po(t){return `---
36
+ `);for(let[n,s]of Object.entries(i)){let a=E.join(t,n);await v(a)||await $(a,s);}}async function Ao(t,e){let o=E.join(t,"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(o)){await $(o,JSON.stringify(r,null,2));return}try{let i=await P.readFile(o,"utf8"),n=JSON.parse(i),s={...r,...n,name:e,scripts:{...r.scripts,...n.scripts},dependencies:{...r.dependencies,...n.dependencies}};await $(o,JSON.stringify(s,null,2));}catch{await $(o,JSON.stringify(r,null,2));}}async function Lo(t,e){let o=E.join(t,"content");await P.rm(o,{recursive:true,force:true}),await H(E.dirname(E.join(o,"_index.md"))),await $(E.join(o,"_index.md"),Ro(e));}function Ro(t){return `---
39
37
  title: "${t.name}"
40
38
  type: landing
41
39
  design:
@@ -49,14 +47,14 @@ sections:
49
47
  text: "Start customizing blocks to launch your next experience."
50
48
  primary_action:
51
49
  text: "Join our Discord"
52
- url: "${lt}"
50
+ url: "${ft}"
53
51
  icon: "chat-bubble-left-right"
54
52
  secondary_action:
55
53
  text: "Upgrade to Pro"
56
- url: "${mt}"
54
+ url: "${ht}"
57
55
  tertiary_action:
58
56
  text: "View Docs"
59
- url: "${dt}"
57
+ url: "${gt}"
60
58
  design:
61
59
  css_class: "bg-gradient-to-r from-blue-600 to-indigo-600 text-white"
62
60
  spacing:
@@ -65,17 +63,34 @@ sections:
65
63
  content:
66
64
  title: "Your next steps"
67
65
  text: |
68
- 1. Join the community on [Discord](${lt}) for support and inspiration.
69
- 2. Explore the [documentation](${dt}) to learn how to add blocks, deploy, and automate.
70
- 3. [Upgrade to Pro](${mt}) to unlock premium blocks, design systems, and automation-ready packages.
66
+ 1. Join the community on [Discord](${ft}) for support and inspiration.
67
+ 2. Explore the [documentation](${gt}) to learn how to add blocks, deploy, and automate.
68
+ 3. [Upgrade to Pro](${ht}) to unlock premium blocks, design systems, and automation-ready packages.
71
69
  4. Share feedback and showcase your build to help the ecosystem grow.
72
- `}function To(t,e){if(!e)return;let o=e.toLowerCase(),r=t.find(n=>{let i=n.id.toLowerCase(),s=n.slug?.toLowerCase();return i===o||s===o});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 bt(t,e){t.command("create").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(r,n,i)=>{let{logger:s,config:a,telemetry:c}=e,p=!!i.optsWithGlobals().json,m=yt({text:"Fetching templates...",spinner:"dots"}).start(),h=await rt(e).finally(()=>{m.succeed("\u2728 Templates ready");}),b=To(h,n.template);if(!b){if(n.ci)throw new d("Template must be specified when running with --ci");let M=await Ze("Select a starter",h.map(j=>({title:j.name,description:j.description,value:j.id})));b=h.find(j=>j.id===M);}if(!b)throw new d("Unable to determine template");let N=b.source==="pro",f=await So(n,r,b),y=et(f,b.slug);await Ie(y);let w=typeof n.sampleContent=="boolean"?n.sampleContent:typeof n.noSampleContent=="boolean"?!n.noSampleContent:n.ci?false:await H("Include sample content? (recommended)",{initial:true}),E=N;if(!N)E=typeof n.pro=="boolean"?n.pro:n.ci?false:await H("Do you have a HugoBlox Pro license?",{initial:!!a.getToken()});else if(!a.getToken()){if(n.ci)throw new d(`"${b.name}" is a HugoBlox Pro template. Set HBX_LICENSE_TOKEN with your license key before running in CI.`);if(s.info(`"${b.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 d("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 j=await wt(a.getToken());a.setToken(j),await a.save();}if(!N&&E&&!a.getToken()){if(n.ci)throw new d("Set HBX_LICENSE_TOKEN before running --ci when enabling Pro features.");let M=await wt(a.getToken());a.setToken(M),await a.save();}E&&await P(e);let R=yt(`Creating site in ${u.relative(process.cwd(),y)||"."}...`).start();try{await ft(e,y,b,{sampleContent:w,includeEnv:!0,packageManager:n.packageManager??"pnpm"}),R.succeed("Files generated");}catch(M){throw R.fail("Failed to scaffold site"),M}let L=false;n.install!==false?L=await gt(y,n.packageManager??"pnpm",s):s.info("Skipping dependency installation"),n.git&&await nt(y,s);let Q={status:"success",template:b.id,path:y,pro:E,manifest:u.join(y,ie)};!L&&n.preview?s.warn("\u26A0\uFE0F Cannot start the dev server because dependencies failed to install."):n.install===false&&n.preview&&s.warn("\u26A0\uFE0F Install dependencies first (skip --no-install) to start the dev server automatically.");let O=false;if(L&&(O=await ko(n,p)),await c.track({name:"new-site",payload:{template:b.id,sample:w,pro:E,ci:!!n.ci,packageManager:n.packageManager??"pnpm",install:n.install!==false,dependenciesReady:L,preview:O}}),O){await ht(y,n.packageManager??"pnpm",s);return}if(p){s.json(Q);return}s.success(`\u2705 Site created at ${y}`),s.info("\u{1F680} Next steps:"),s.info(` \u{1F449} cd ${u.relative(process.cwd(),y)||y}`),n.install===false&&s.info(` \u{1F449} ${n.packageManager??"pnpm"} install`),s.info(" \u{1F449} pnpm dev");});}async function ko(t,e){return e||t.ci?false:typeof t.preview=="boolean"?t.preview:t.noPreview?false:H("Start the dev server now?",{initial:true})}async function So(t,e,o){if(t.dir)return t.dir;if(e)return e;if(t.ci)return o.slug;let n=(await q("Project folder name",{initial:o.slug})).trim();return n?Io(n)?n:Ce(n)||o.slug:o.slug}function Io(t){return /[\\/]/.test(t)||t.includes(":")}async function wt(t){let o=(await q("Enter your HugoBlox Pro license key (from your purchase confirmation email)",{initial:t??""})).trim();if(!o)throw new d("A HugoBlox Pro license key is required to continue. Check your purchase email or visit https://hugoblox.com/pro.");return o}function vt(t,e){let o=t.command("telemetry").description("Manage HugoBlox telemetry preferences");o.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!");}),o.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.");}),o.command("status").description("Show whether telemetry is enabled").action(()=>{let r=e.config.isTelemetryEnabled();e.logger.info(`Telemetry is ${r?"enabled":"disabled"}.`);}),o.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.");});}function Pt(t,e){t.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("--canary","Upgrade to the latest development commit (main branch) instead of stable release").action(async(o,r)=>{let {logger:n}=e;r.optsWithGlobals();let s=await _();if(!s)throw new d("No Hugo project found in the current directory.");let a=yt("Checking for updates...").start(),c=await ae(s.root);if(a.stop(),c.length===0){n.info("\u2139\uFE0F No official HugoBlox modules found in go.mod");return}if(o.canary){n.warn("\u26A0\uFE0F Upgrading modules to latest canary (development) version.");for(let h of c)n.info(` ${h.path}: ${X(h.current)} -> @main`);if(!o.yes&&!o.ci&&!await H("Are you sure you want to upgrade to the bleeding edge?",{initial:true})){n.info("Upgrade cancelled");return}let m=c.map(h=>`${h.path}@main`);await Et(s.root,m,n);return}let l=c.map(m=>{let{updateAvailable:h,diff:x}=ce(m.current,m.latest);return {...m,updateAvailable:h,diff:x}}).filter(m=>m.updateAvailable&&m.latest);if(l.length===0){n.success("\u2705 All HugoBlox modules are up to date");return}n.info(`\u{1F4E6} Updates available for ${l.length} module(s):`);for(let m of l){let h=m.path.split("/").pop();n.info(` ${h}`),n.info(` Current: ${X(m.current)}`),n.info(` Latest: ${X(m.latest||"")}`);}if(!o.yes&&!o.ci&&!await H("Do you want to upgrade now?",{initial:true})){n.info("Upgrade cancelled");return}let p=l.map(m=>`${m.path}@${m.latest}`);await Et(s.root,p,n);});}async function Et(t,e,o){let r=yt("Upgrading modules...").start();try{await execa("hugo",["mod","get",...e],{cwd:t}),r.text="Tidying go.mod...",await execa("hugo",["mod","tidy"],{cwd:t}),r.succeed(`\u2705 Upgraded ${e.length} module(s)`);}catch(n){r.fail("Failed to upgrade modules"),o.error(String(n)),process.exit(1);}}var A;function le(){if(A)return A;let t=process.env.HBX_CLI_VERSION??process.env.npm_package_version;if(t)return A=t,A;let e=Ho(import.meta.url);try{let o=Tt.readFileSync(e,"utf8");A=JSON.parse(o).version??"0.0.0";}catch{A="0.0.0";}return A}function Ho(t){let e=u.dirname(fileURLToPath(t)),o=u.resolve(e,"../package.json");return Tt.existsSync(o)?o:u.resolve(e,"../../package.json")}function kt(t,e){t.command("version").description("Print CLI version").action((o,r)=>{let{logger:n}=e,i=!!r.optsWithGlobals().json,s=le(),a={status:"success",version:s};i?n.json(a):n.info(`hbx ${s}`);});}var me=class t{#e;constructor(e){this.#e=e;}static async load(){try{let e=await g.readFile(re,"utf8"),o=JSON.parse(e);return new t(o)}catch(e){if(e.code==="ENOENT")return new t({});throw new Z("Failed to read configuration",{error:e})}}toJSON(){return this.#e}getToken(){return process.env[F]??this.#e.token}setToken(e){this.#e={...this.#e,token:e};}clearToken(){let e={...this.#e};e.token=void 0,e.device=void 0,this.#e=e;}isTelemetryEnabled(){return process.env[Be]==="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 o=K.randomUUID();return this.#e={...this.#e,telemetry:{...this.#e.telemetry,id:o}},await this.save(),o}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 g.mkdir(ge,{recursive:true});let e=JSON.stringify(this.#e,null,2);await g.writeFile(re,e,{mode:384}),await g.chmod(re,384);}};var pe=class{#e;#t;constructor(e={}){this.#e=e.json??false,this.#t=e.debug??process.env[J]==="1";}isJsonMode(){return this.#e}setJsonMode(e){this.#e=e;}setDebug(e){this.#t=e;}info(e){this.#e||process.stdout.write(`${Y.blue("i")} ${e}
73
- `);}success(e){this.#e||process.stdout.write(`${Y.green("\u2714")} ${e}
74
- `);}warn(e){this.#e||process.stdout.write(`${Y.yellow("!")} ${e}
75
- `);}error(e){this.#e||process.stderr.write(`${Y.red("\u2716")} ${e}
76
- `);}debug(e){!this.#t||this.#e||process.stdout.write(`${Y.gray("debug")} ${e}
70
+ `}function _e(t){return t?t.length<=6?"***":`${t.slice(0,3)}***${t.slice(-2)}`:"(none)"}function Ct(t,e){let o=t??e;return E.resolve(process.cwd(),o)}function No(t,e){if(!e)return;let o=e.toLowerCase(),r=t.find(i=>{let n=i.id.toLowerCase(),s=i.slug?.toLowerCase();return n===o||s===o});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 Tt(t,e){t.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(o,r,i)=>{let{logger:n,config:s,telemetry:a}=e,l=!!i.optsWithGlobals().json,u=Te({text:"Fetching templates...",spinner:"dots"}).start(),g=await ct(e).finally(()=>{u.succeed("\u2728 Templates ready");}),m=No(g,r.template);if(!m){if(r.ci)throw new d("Template must be specified when running with --ci");let b=await te("Select a starter",g.map(C=>({title:C.name,description:C.description,value:C.id})));m=g.find(C=>C.id===b);}if(!m)throw new d("Unable to determine template");let f=m.source==="pro",y=await Mo(r,o,m),p=Ct(y,m.slug);await Ne(p);let h=typeof r.sampleContent=="boolean"?r.sampleContent:typeof r.noSampleContent=="boolean"?!r.noSampleContent:r.ci?false:await _("Include sample content? (recommended)",{initial:true}),I=f;if(!f)I=typeof r.pro=="boolean"?r.pro:r.ci?false:await _("Do you have a HugoBlox Pro license?",{initial:!!s.getLicense()});else if(!s.getLicense()){if(r.ci)throw new d(`"${m.name}" is a HugoBlox Pro template. Set HBX_LICENSE_TOKEN with your license key before running in CI.`);if(n.info(`"${m.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 _("Do you have a HugoBlox Pro license key to enter now?",{initial:true}))throw new d("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 C=await Pt(s.getLicense());s.setLicense(C),await s.save();}if(!f&&I&&!s.getLicense()){if(r.ci)throw new d("Set HBX_LICENSE_TOKEN before running --ci when enabling Pro features.");let b=await Pt(s.getLicense());s.setLicense(b),await s.save();}I&&await B(e);let x=Te(`Creating site in ${E.relative(process.cwd(),p)||"."}...`).start();try{await bt(e,p,m,{sampleContent:h,includeEnv:!0,packageManager:r.packageManager??"pnpm"}),x.succeed("Files generated");}catch(b){throw x.fail("Failed to scaffold site"),b}let k=false;r.install!==false?k=await vt(p,r.packageManager??"pnpm",n):n.info("Skipping dependency installation"),r.git&&await lt(p,n);let S={status:"success",template:m.id,path:p,pro:I,manifest:E.join(p,de)};!k&&r.preview?n.warn("\u26A0\uFE0F Cannot start the dev server because dependencies failed to install."):r.install===false&&r.preview&&n.warn("\u26A0\uFE0F Install dependencies first (skip --no-install) to start the dev server automatically.");let w=false;if(k&&(w=await Oo(r,l)),await a.track({name:"new-site",payload:{template:m.id,sample:h,pro:I,ci:!!r.ci,packageManager:r.packageManager??"pnpm",install:r.install!==false,dependenciesReady:k,preview:w}}),w){await xt(p,r.packageManager??"pnpm",n);return}if(l){n.json(S);return}n.success(`\u2705 Site created at ${p}`),n.info("\u{1F680} Next steps:"),n.info(` \u{1F449} cd ${E.relative(process.cwd(),p)||p}`),r.install===false&&n.info(` \u{1F449} ${r.packageManager??"pnpm"} install`),n.info(" \u{1F449} pnpm dev");});}async function Oo(t,e){return e||t.ci?false:typeof t.preview=="boolean"?t.preview:t.noPreview?false:_("Start the dev server now?",{initial:true})}async function Mo(t,e,o){if(t.dir)return t.dir;if(e)return e;if(t.ci)return o.slug;let i=(await j("Project folder name",{initial:o.slug})).trim();return i?Fo(i)?i:re(i)||o.slug:o.slug}function Fo(t){return /[\\/]/.test(t)||t.includes(":")}async function Pt(t){let o=(await j("Enter your HugoBlox Pro license key (from your purchase confirmation email)",{initial:t??""})).trim();if(!o)throw new d("A HugoBlox Pro license key is required to continue. Check your purchase email or visit https://hugoblox.com/pro.");return o}var Xo=fileURLToPath(import.meta.url),Be=E.dirname(Xo);function Wo(){return Be.endsWith("dist")?E.join(Be,"lib","templates","minimal-theme.yaml"):E.resolve(Be,"..","lib","templates","minimal-theme.yaml")}var kt=Wo();function zo(t){return /^[a-zA-Z0-9_-]+$/.test(t)}async function Jo(){try{return await P.readFile(kt,"utf8")}catch(t){throw new d(`Failed to load theme template: ${kt}`,{error:t})}}function qo(t,e,o,r){let i=t.split(`
71
+ `),n=[],s=false,a=0;for(let c of i){if(c.trim()==="meta:"){s=true,a=c.indexOf("meta:"),n.push(c),n.push(' format: "hugoblox-theme@1"'),n.push(` name: "${o}"`),n.push(` vendor: "${e}"`),n.push(' version: "0.0.1"'),n.push(' license: "MIT"'),n.push(' description: "Created via HugoBlox CLI"');continue}if(s){c.trim()&&!c.startsWith(" ".repeat(a+2))&&c.indexOf(":")>0&&(s=false,n.push(c));continue}n.push(c);}return n.join(`
72
+ `)}function Ht(t,e){t.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(o,r,i)=>{let{logger:n,telemetry:s}=e,a=!!i.optsWithGlobals().json;try{let c=r.vendor;if(!c){if(r.ci)throw new d("--vendor is required when running with --ci");c=await j("What is your GitHub username? (This will be your vendor namespace)");}if(c=c.trim(),!c)throw new d("Vendor namespace is required");if(!zo(c))throw new d("Vendor namespace must contain only alphanumeric characters, hyphens, and underscores");let l=o;if(!l){if(r.ci)throw new d("Theme slug is required when running with --ci");l=await j("What do you want to name your theme? (e.g., cyberpunk-neon)",{initial:"my-theme"});}if(l=l.trim(),!l)throw new d("Theme slug is required");let u=re(l),g=r.themeName;g||(r.ci?g=l:g=await j("Human-readable theme name?",{initial:l})),g=g.trim()||l;let T=E.join(process.cwd(),"data","themes",c),m=E.join(T,`${u}.yaml`);if(await v(m)){if(r.ci)throw new d(`Theme file already exists: ${m}`);if(!await _(`Theme file ${u}.yaml already exists. Overwrite?`,{initial:!1})){n.info("Theme creation cancelled");return}}let f=Te("Creating theme...").start();try{await H(T);let p=await Jo(),h=qo(p,c,g,u);await $(m,h),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:u,ci:!!r.ci}});let y=E.relative(process.cwd(),m);if(a){n.json({status:"success",path:m,vendor:c,themeFilename:u,themeName:g});return}n.success(`
73
+ Theme created at: ${y}`),n.info(`
74
+ \u{1F4DD} To use this theme, update your params.yaml:`),n.info(`
75
+ hugoblox:`),n.info(" theme:"),n.info(` pack: "${c}/${u}"`),r.ci||await _(`
76
+ \u{1F30D} Would you like to share this theme with the community?`,{initial:!1})&&(n.info(`
77
+ \u2728 Great! Here's how to publish your theme:`),n.info(`
78
+ 1\uFE0F\u20E3 Create a new GitHub repository`),n.info("2\uFE0F\u20E3 In your repo, create a folder structure: hugoblox/themes/"),n.info(`3\uFE0F\u20E3 Copy your theme file to: hugoblox/themes/${u}.yaml`),n.info("4\uFE0F\u20E3 Commit and push to GitHub"),n.info(`
79
+ \u{1F4E2} Once published, others can install it with:
80
+ hbx add theme --repo https://github.com/${c}/your-repo-name
81
+ `),n.info("\u{1F4A1} Tip: You can add multiple themes to the same repository!"));}catch(c){if(a){n.json({status:"error",message:c instanceof Error?c.message:String(c)});return}throw c}});}function St(t,e){let o=t.command("create").description("Create resources (site, theme, block)");Tt(o,e),Ht(o,e),rt(o,e);}function It(t,e){Yo(t,e),Qo(t,e);}function Yo(t,e){t.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(o,r,i)=>{let{logger:n,telemetry:s}=e,c=!!i.optsWithGlobals().json,l=await _t(r.path),u=["server"];r.defaultFlags!==false&&u.push("--disableFastRender"),u.push(...o),await jt(u,l,n,{allowSignalExit:true,label:"dev server"}),await s.track({name:"dev",payload:{customPath:!!r.path,defaultFlags:r.defaultFlags!==false,args:o}}),c&&n.json({status:"success"});});}function Qo(t,e){t.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(o,r,i)=>{let{logger:n,telemetry:s}=e,c=!!i.optsWithGlobals().json,l=await _t(r.path),u=[];r.defaultFlags!==false&&u.push("--gc","--minify"),u.push(...o),await jt(u,l,n,{allowSignalExit:false,label:"build"}),await s.track({name:"build",payload:{customPath:!!r.path,defaultFlags:r.defaultFlags!==false,args:o}}),c&&n.json({status:"success"});});}async function _t(t){let e=t?E.resolve(t):E.resolve(process.cwd()),o=await A(e);if(!o)throw new d("Unable to locate a HugoBlox project. Run this inside a project or pass --path.");return o.root}async function jt(t,e,o,r){o.info(`Running: hugo ${t.join(" ")}`);try{await execa("hugo",t,{cwd:e,stdio:"inherit"}),o.success(`Hugo ${r.label} finished`);}catch(i){let n=i;if(r.allowSignalExit&&(n.signal==="SIGINT"||n.signal==="SIGTERM")){o.info("Hugo process stopped");return}throw new d(`Hugo ${r.label} failed: ${n.shortMessage??n.message}`,{error:n})}}var or=["github.com/HugoBlox/hugo-blox-builder","github.com/wowchemy/wowchemy-hugo-themes"];async function pe(t){let e=E.join(t,"go.mod"),o;try{o=await P.readFile(e,"utf8");}catch{return []}let i=ir(o).filter(s=>or.some(a=>s.path.startsWith(a)));return await Promise.all(i.map(async s=>{try{let a=await rr(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 rr(t){if(t.includes("github.com/HugoBlox/hugo-blox-builder"))return nr(t)}async function nr(t){let e=await q(`${z}/repos/HugoBlox/hugo-blox-builder/tags?per_page=100`);if(!e.ok)throw new Error(`GitHub API error: ${e.status}`);let o=await e.json(),r=t.split("github.com/HugoBlox/hugo-blox-builder/");if(r.length<2)return;let i=r[1],n=o.filter(s=>s.name.startsWith(`${i}/`)&&/v\d+\.\d+\.\d+/.test(s.name)).map(s=>s.name);if(n.length!==0)return n.sort((s,a)=>{let c=s.split("/").pop()||"0.0.0",l=a.split("/").pop()||"0.0.0";return L.rcompare(c,l)}),n[0].split("/").pop()}async function Bt(t,e){if(!t.includes("github.com/HugoBlox/hugo-blox-builder"))return;let o=t.split("github.com/HugoBlox/hugo-blox-builder/");if(o.length<2)return;let r=o[1],i=e==="main"||e.startsWith("v")?e:`v${e}`,n=e==="main"?"main":`${r}/${i.replace(/^v/,"v")}`,s=`${r}/hugo.yaml`,a=await q(`${z}/repos/HugoBlox/hugo-blox-builder/contents/${s}?ref=${n}`,{headers:{Accept:"application/vnd.github.v3.raw"}});if(!a.ok)return;let c=await a.text();return Ze.parse(c)?.module?.hugoVersion?.min}function ir(t){let e=[],o=t.split(/\r?\n/),r=false;for(let i of o){let n=i.trim();if(n.startsWith("require (")){r=true;continue}if(r&&n===")"){r=false;continue}let s="";if(!r&&n.startsWith("require ")?s=n.replace("require","").trim():r&&(s=n),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 fe(t,e){if(!t||!e)return {updateAvailable:false,diff:""};let o=L.coerce(t),r=L.coerce(e);return !o||!r?{updateAvailable:false,diff:""}:L.lt(o,r)?{updateAvailable:true,diff:`${Y(t)} -> ${Y(e)}`}:{updateAvailable:false,diff:""}}function Y(t){let e=/v\d+\.\d+\.\d+-(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})-([a-f0-9]{12})/,o=t.match(e);if(o){let[r,i,n,s,a,c,l,u]=o;return `commit ${u.substring(0,7)} (released ${i}-${n}-${s})`}return t}function Lt(t){let e=process.env.HOME||process.env.USERPROFILE;if(!e)return t;let o=E.resolve(e),r=E.resolve(t);return r.startsWith(o)?r.replace(o,"~"):t}async function Ae(t,e){try{let o=await execa(t,e,{reject:!1});return o.exitCode===0?o.stdout.trim():`Failed (${o.stderr.trim()})`}catch(o){return `Not available (${o.message})`}}function Rt(t,e){t.command("doctor").description("Check local environment for common issues").action(async(o,r)=>{let{logger:i,config:n}=e,a=!!r.optsWithGlobals().json,c=[];c.push({name:"Node.js",ok:true,details:process.version});let l=await Ae("git",["--version"]);c.push({name:"Git",ok:!l.startsWith("Not"),details:l});let u=await Ae("hugo",["version"]);c.push({name:"Hugo",ok:!u.startsWith("Not"),details:u});let g=ar(u),T=await Ae("pnpm",["--version"]);c.push({name:"pnpm",ok:!T.startsWith("Not"),details:T});let m=n.getLicense();c.push({name:"Pro license",ok:!!m,details:m?"Configured":"Missing"});let f=await A();if(f){let h=await Je(f.root);if(h){let x=h.templateName??h.templateId??"Unknown";c.push({name:"Template",ok:true,details:`${x} (${Lt(f.root)})`});let k=cr(h.requiredHugoVersion,g);k&&c.push(k);}let I=await pe(f.root);for(let x of I){let k=x.path.split("/").pop()||x.path,S=x.current;if(x.latest){let b=L.coerce(x.current),C=L.coerce(x.latest);b&&C&&L.eq(b,C)&&(S=`${S} (latest)`);}c.push({name:`Module: ${k}`,ok:true,details:S});let{updateAvailable:w}=fe(x.current,x.latest);w&&x.latest&&c.push({name:`${k} update`,ok:false,details:`Current ${x.current}, latest ${x.latest}. Run 'hbx upgrade' to update.`,level:"warn"});}}let p={status:c.some(h=>(h.level??(h.ok?"info":"error"))==="error")?"error":"success",checks:c};if(a){i.json(p);return}for(let h of p.checks){let I=h.level??(h.ok?"info":"error");I==="info"?i.success(`${h.name}: ${h.details}`):I==="warn"?i.warn(`${h.name}: ${h.details}`):i.error(`${h.name}: ${h.details}`);}});}function ar(t){let e=t.match(/v(\d+\.\d+\.\d+)/i);return e?e[1]:t.match(/(\d+\.\d+\.\d+)/)?.[1]}function cr(t,e){if(!t||!e)return;let o=L.coerce(t),r=L.coerce(e);if(!(!o||!r))return L.lt(r,o)?{name:"Hugo version compatibility",ok:false,details:`Template requires Hugo ${o.version}, but ${r.version} is installed`,level:"error"}:L.major(r)>L.major(o)||L.minor(r)>L.minor(o)?{name:"Hugo version compatibility",ok:true,details:`Using Hugo ${r.version}; template tested with ${o.version}`,level:"warn"}:{name:"Hugo version compatibility",ok:true,details:`Template requires Hugo ${o.version} and you're running ${r.version}`,level:"info"}}function Dt(t,e){t.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(o,r)=>{let{logger:i,config:n,telemetry:s}=e,c=!!r.optsWithGlobals().json,l=o.path?{root:E.resolve(o.path),manifestPath:E.join(E.resolve(o.path),"hbx.blocks.json")}:await A();if(!l)throw new d("Unable to locate a HugoBlox project - pass --path if needed");let u=n.getLicense();if(!u){if(o.ci)throw new d(`Missing license key. Set ${X} or run hbx login before using --ci.`);i.warn("No Pro license detected, proceeding with OSS assets only");}let g=Te("Hydrating Pro assets...").start();try{let m=E.join(l.root,"config","_default","module.hbx.toml"),f=E.join(l.root,"node_modules","@hugoblox-pro","sample");await H(f),await $(E.join(f,"README.md"),`# HugoBlox Pro assets placeholder
82
+ `),await $(m,`# Generated by hbx install
83
+ [[module.imports]]
84
+ path = "github.com/HugoBlox/hugo-blox-builder"
85
+ [[module.imports]]
86
+ path = "node_modules/@hugoblox-pro/sample"
87
+ `),g.succeed("Assets hydrated");}catch(m){throw g.fail("Failed to hydrate assets"),m}await s.track({name:"install",payload:{ci:!!o.ci,force:!!o.force,tokenPresent:!!u,customPath:!!o.path}});let T={status:"success",path:l.root,forced:!!o.force,token:!!u};c?i.json(T):(i.success("Install complete"),u||i.info("Tip: run hbx login to unlock Pro downloads"));});}function Nt(t,e){t.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(o,r)=>{let{config:i,logger:n}=e,a=!!r.optsWithGlobals().json,c=o.token;if(!c){if(o.ci)throw new d("License key is required when using --ci");c=await j("Enter your HugoBlox Pro license key");}let l=false;try{i.setLicense(c),await i.save(),l=!0,await B(e,{force:!0});let u={status:"success",token:_e(c)};a?n.json(u):n.success(`License key saved (${_e(c)})`);}catch(u){throw l&&(i.clearLicense(),await i.save()),mr(u)}});}function Ot(t,e){t.command("logout").description("Remove stored HugoBlox credentials and device secrets").action(async(o,r)=>{let{config:i,logger:n}=e,s=!!r.optsWithGlobals().json;await at(i),i.clearLicense(),await i.save();let a={status:"success"};s?n.json(a):n.success("License key removed");});}function mr(t){let e=t instanceof Error?t.message:"Device registration failed",o="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 t instanceof R?new d(`${e}. ${o}`,t.details):new d(`${e}. ${o}`)}function Mt(t,e){let o=t.command("telemetry").description("Manage HugoBlox telemetry preferences");o.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!");}),o.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.");}),o.command("status").description("Show whether telemetry is enabled").action(()=>{let r=e.config.isTelemetryEnabled();e.logger.info(`Telemetry is ${r?"enabled":"disabled"}.`);}),o.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 Ut(t,e,o){let r=L.coerce(e)?.version;if(!r)return;let i=[{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 n of i){let s=E.join(t,n.path);if(await v(s))try{let a=await P.readFile(s,"utf8"),c=a.match(n.regex);if(c){let l=c[2],u=L.coerce(l),g=L.coerce(r);if(u&&g&&L.lt(u,g)){let T=a.replace(n.regex,`$1${r}$3`);await P.writeFile(s,T,"utf8"),o.success(`Updated ${n.name} Hugo version to ${r}`);}}}catch{}}}function Xt(t,e){t.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(o,r)=>{let{logger:i}=e;await Ye()||(i.error("\u274C You appear to be offline. Please check your internet connection."),process.exit(1));let n=await A();if(!n)throw new d("No Hugo project found in the current directory.");let s=Te("Checking for updates...").start(),a=await pe(n.root);if(a.length===0){s.stop(),i.info("\u2139\uFE0F No official HugoBlox modules found in go.mod");return}let c=a.filter(m=>m.error);if(c.length>0){s.stop(),i.error("\u274C Failed to check for updates for some modules:");for(let m of c)i.error(` ${m.path}: ${m.error}`);process.exit(1);}let l=[];if(o.canary)s.text="Checking canary versions...",l.push(...a.map(m=>({path:m.path,version:"main"})));else {let m=a.map(f=>{let{updateAvailable:y,diff:p}=fe(f.current,f.latest);return {...f,updateAvailable:y,diff:p}}).filter(f=>f.updateAvailable&&f.latest);if(m.length===0){s.stop(),i.success("\u2705 All HugoBlox modules are up to date");return}l.push(...m.map(f=>({path:f.path,version:f.latest||""})));}s.text="Checking version requirements...";let u=await Promise.all(l.map(async m=>{try{let f=await Bt(m.path,m.version);return {...m,min:f}}catch{return {...m,min:void 0}}}));if(s.stop(),!o.force){let m=await qe();if(m){let f=u.filter(y=>{if(!y.min)return false;let p=L.coerce(y.min),h=L.coerce(m);return p&&h&&L.lt(h,p)});if(f.length>0){i.error("\u274C Hugo version incompatible with upgrade targets:");for(let y of f)i.error(` ${y.path.split("/").pop()} requires Hugo >= ${y.min} (you have ${m})`);i.info("\u{1F449} Please upgrade Hugo first: https://gohugo.io/installation/"),i.info(" Or run with --force to ignore this check."),process.exit(1);}}else i.warn("\u26A0\uFE0F Could not detect local Hugo version. Skipping compatibility check.");}if(o.canary){i.warn("\u26A0\uFE0F Upgrading modules to latest canary (development) version.");for(let m of a)i.info(` ${m.path.split("/").pop()}: ${Y(m.current)} -> @main`);}else {i.info(`\u{1F4E6} Updates available for ${l.length} module(s):`);for(let m of l){let f=a.find(y=>y.path===m.path)?.current||"?";i.info(` ${m.path.split("/").pop()}`),i.info(` Current: ${Y(f)}`),i.info(` Latest: ${Y(m.version)}`);}}if(!o.yes&&!o.ci&&!await _(o.canary?"Are you sure you want to upgrade to the bleeding edge?":"Do you want to upgrade now?",{initial:true})){i.info("Upgrade cancelled");return}let g=l.map(m=>`${m.path}@${m.version}`);await ur(n.root,g,i);let T=u.reduce((m,f)=>{if(!f.min)return m;let y=L.coerce(f.min),p=L.coerce(m);return y&&(!p||L.gt(y,p))?f.min:m},void 0);T&&await Ut(n.root,T,i),i.info(""),i.warn("\u26A0\uFE0F Important: Please review the release notes for any breaking changes."),i.info("\u{1F449} https://github.com/HugoBlox/hugo-blox-builder/releases");});}async function ur(t,e,o){let r=Te("Upgrading modules...").start();try{await execa("hugo",["mod","get",...e],{cwd:t}),r.text="Tidying go.mod...",await execa("hugo",["mod","tidy"],{cwd:t}),r.succeed(`\u2705 Upgraded ${e.length} module(s)`);}catch(i){r.fail("Failed to upgrade modules"),o.error(String(i)),process.exit(1);}}var V;function he(){if(V)return V;let t=process.env.HBX_CLI_VERSION??process.env.npm_package_version;if(t)return V=t,V;let e=fr(import.meta.url);try{let o=Wt.readFileSync(e,"utf8");V=JSON.parse(o).version??"0.0.0";}catch{V="0.0.0";}return V}function fr(t){let e=E.dirname(fileURLToPath(t)),o=E.resolve(e,"../package.json");return Wt.existsSync(o)?o:E.resolve(e,"../../package.json")}function zt(t,e){t.command("version").description("Print CLI version").action((o,r)=>{let{logger:i}=e,n=!!r.optsWithGlobals().json,s=he(),a={status:"success",version:s};n?i.json(a):i.info(`hbx ${s}`);});}var we=class t{#e;constructor(e){this.#e=e;}static async load(){try{let e=await P.readFile(le,"utf8"),o=JSON.parse(e);return new t(o)}catch(e){if(e.code==="ENOENT")return new t({});throw new ie("Failed to read configuration",{error:e})}}toJSON(){return this.#e}getLicense(){return process.env[X]??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[Me]==="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 o=oe.randomUUID();return this.#e={...this.#e,telemetry:{...this.#e.telemetry,id:o}},await this.save(),o}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 P.mkdir(Ce,{recursive:true});let e=JSON.stringify(this.#e,null,2);await P.writeFile(le,e,{mode:384}),await P.chmod(le,384);}};var be=class{#e;#t;constructor(e={}){this.#e=e.json??false,this.#t=e.debug??process.env[ee]==="1";}isJsonMode(){return this.#e}setJsonMode(e){this.#e=e;}setDebug(e){this.#t=e;}info(e){this.#e||process.stdout.write(`${ne.blue("i")} ${e}
88
+ `);}success(e){this.#e||process.stdout.write(`${ne.green("\u2714")} ${e}
89
+ `);}warn(e){this.#e||process.stdout.write(`${ne.yellow("!")} ${e}
90
+ `);}error(e){this.#e||process.stderr.write(`${ne.red("\u2716")} ${e}
91
+ `);}debug(e){!this.#t||this.#e||process.stdout.write(`${ne.gray("debug")} ${e}
77
92
  `);}json(e){let o=JSON.stringify(e,null,2);process.stdout.write(`${o}
78
- `);}};var $o=new Set(["command","project","duration","status","errorCode","errorMessage","metadata"]),Do=50,Ao=6144,St=25e3,fe=class{#e;#t;#r;#n=[];#o;#i=false;#s;#a;#c;constructor(e,o,r){this.#e=e,this.#t=o,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.#n.push({...e,timestamp:new Date().toISOString(),payload:e.payload??{}}),await this.flush());}async flush(){if(!this.#n.length)return;if(this.#o){await this.#o;return}let e=this.#n.splice(0);this.#o=this.#d(e).finally(()=>{this.#o=void 0;}),await this.#o;}#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#d(e){if(!e.length)return;let o=this.#e.getTelemetryId(),n=[...e.map(i=>Lo(i))];for(;n.length;){let i=[],s;for(;n.length&&i.length<Do;){let a=n[0];if(!a)break;let c=[...i,a],l=this.#m(c,o),p=JSON.stringify(l);if(Buffer$1.byteLength(p,"utf8")>St){if(!i.length){n.shift(),this.#t.warn("Dropped telemetry event because payload exceeded max size");continue}break}let m=n.shift();if(!m)break;i.push(m),s=p;}!i.length||!s||await this.#p(s,o);}}#m(e,o){return {clientId:o&&o.length>=8?o:"anonymous",os:ue.platform(),osVersion:Ro(),arch:process.arch,nodeVersion:process.version,ci:No(),command:this.#s,releaseChannel:this.#a,sessionId:this.#c,cliVersion:this.#r,version:this.#r,hasLicense:!!this.#e.getToken(),events:e}}async#p(e,o){let r=Buffer$1.byteLength(e,"utf8");if(r>St){this.#t.warn("Telemetry payload skipped because it exceeded the maximum request size");return}try{let n=new AbortController,i=setTimeout(()=>n.abort(),5e3),s=await fetch(Ne,{method:"POST",headers:{"Content-Type":"application/json","Content-Length":String(r),"User-Agent":`hbx-cli/${this.#r}`,...o?{"x-telemetry-id":o}:void 0},body:e,signal:n.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(n){this.#t.debug(`telemetry send failed: ${String(n)}`);}}};function No(){return process.env.CI==="1"||process.env.CONTINUOUS_INTEGRATION==="1"||!!process.env.BUILD_NUMBER||!!process.env.RUN_ID}function Ro(){let t=ue.version;if(typeof t=="function")try{return t()}catch{return ue.release()}return ue.release()}function Lo(t){let e=Oo(t.payload);if(!e){let{payload:o,...r}=t;return r}try{let o=JSON.stringify(e);return Buffer$1.byteLength(o,"utf8")>Ao?{...t,payload:{truncated:!0}}:{...t,payload:e}}catch{return {...t,payload:{truncated:true}}}}function Oo(t){if(!t||typeof t!="object")return;let e={};for(let o of $o)if(Object.hasOwn(t,o)){let r=t[o];if(o==="metadata"&&(r==null||typeof r!="object"))continue;e[o]=r;}return Object.keys(e).length?e:void 0}async function _t(t,e,o){if(process.env[je]==="1")return;let r=e.getUpdateMetadata()??{},n=Date.now(),i=r.latestVersion,s=r.lastChecked??0;if(!i||n-s>Re){let l=await Uo(t,o);l.latestVersion&&(i=l.latestVersion),l.checkedAt>0&&(s=l.checkedAt,e.setUpdateMetadata({lastChecked:s,latestVersion:i}),await e.save());}if(!i||!k.valid(i)||!k.gt(i,t)||!Mo(r,n,i))return;let c=`npm install -g ${ne}`;o.warn(`A new version of hbx is available: ${i} (current ${t}).
79
- Update with: ${c} (or pnpm add -g ${ne}).`),e.setUpdateMetadata({lastNotifiedAt:n,latestVersion:i}),await e.save();}function Mo(t,e,o){return !t||t.lastNotifiedAt===void 0||t.latestVersion!==o?true:e-t.lastNotifiedAt>Le}async function Uo(t,e){try{let o=await fetch(`https://registry.npmjs.org/${encodeURIComponent(ne)}/latest`,{headers:{"User-Agent":`hbx-cli/${t}`}});if(!o.ok)throw new Error(`npm registry responded with status ${o.status}`);return {latestVersion:(await o.json()).version,checkedAt:Date.now()}}catch(o){return e.debug(`update check failed: ${String(o)}`),{checkedAt:Date.now()}}}async function Vo(t=process.argv){let e=le(),o=await me.load(),r=new pe({debug:process.env[J]==="1"});await o.ensureTelemetryId();let n=new fe(o,r,e),i={config:o,logger:r,telemetry:n};await _t(e,o,r),await Jo(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[J]==="1"),n.setCommand(zo(c));}),bt(s,i),_e(s,i),We(s,i),Ue(s,i),Je(s,i),tt(s,i),ot(s,i),Pt(s,i),vt(s,i),kt(s,i);try{await s.parseAsync(t);}catch(a){Go(a,r);}}function Go(t,e){if(Se(t)){let o={status:"error",code:t.code,message:t.message,details:t.details};e.isJsonMode()?e.json(o):e.error(`${t.code}: ${t.message}`);}else t instanceof S?e.error(`${t.code}: ${t.message}`):t instanceof Error?e.error(t.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"))&&Vo();function zo(t){if(!t)return oe;let e=[],o=t;for(;o?.parent;){let r=o.name?.();r&&e.unshift(r),o=o.parent;}return e.length?`${oe} ${e.join(" ")}`.trim():oe}async function Jo(t){if(process.env[F]&&t.config.getToken()&&!t.config.getDeviceInfo())try{await P(t);}catch(e){t.logger.debug(`Skipping device registration warm-up: ${String(e)}`);}}
93
+ `);}};var yr=new Set(["command","project","duration","status","errorCode","errorMessage","metadata"]),wr=50,br=6144,Jt=25e3,xe=class{#e;#t;#r;#n=[];#o;#i=false;#s;#a;#c;constructor(e,o,r){this.#e=e,this.#t=o,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.#n.push({...e,timestamp:new Date().toISOString(),payload:e.payload??{}}),await this.flush());}async flush(){if(!this.#n.length)return;if(this.#o){await this.#o;return}let e=this.#n.splice(0);this.#o=this.#m(e).finally(()=>{this.#o=void 0;}),await this.#o;}#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 o=this.#e.getTelemetryId(),i=[...e.map(n=>Cr(n))];for(;i.length;){let n=[],s;for(;i.length&&n.length<wr;){let a=i[0];if(!a)break;let c=[...n,a],l=this.#d(c,o),u=JSON.stringify(l);if(Buffer$1.byteLength(u,"utf8")>Jt){if(!n.length){i.shift(),this.#t.warn("Dropped telemetry event because payload exceeded max size");continue}break}let g=i.shift();if(!g)break;n.push(g),s=u;}!n.length||!s||await this.#u(s,o);}}#d(e,o){return {clientId:o&&o.length>=8?o:"anonymous",os:ve.platform(),osVersion:xr(),arch:process.arch,nodeVersion:process.version,ci:vr(),command:this.#s,releaseChannel:this.#a,sessionId:this.#c,cliVersion:this.#r,version:this.#r,hasLicense:!!this.#e.getLicense(),events:e}}async#u(e,o){let r=Buffer$1.byteLength(e,"utf8");if(r>Jt){this.#t.warn("Telemetry payload skipped because it exceeded the maximum request size");return}try{let i=new AbortController,n=setTimeout(()=>i.abort(),5e3),s=await fetch(Xe,{method:"POST",headers:{"Content-Type":"application/json","Content-Length":String(r),"User-Agent":`hbx-cli/${this.#r}`,...o?{"x-telemetry-id":o}:void 0},body:e,signal:i.signal});if(clearTimeout(n),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(i){this.#t.debug(`telemetry send failed: ${String(i)}`);}}};function vr(){return process.env.CI==="1"||process.env.CONTINUOUS_INTEGRATION==="1"||!!process.env.BUILD_NUMBER||!!process.env.RUN_ID}function xr(){let t=ve.version;if(typeof t=="function")try{return t()}catch{return ve.release()}return ve.release()}function Cr(t){let e=Er(t.payload);if(!e){let{payload:o,...r}=t;return r}try{let o=JSON.stringify(e);return Buffer$1.byteLength(o,"utf8")>br?{...t,payload:{truncated:!0}}:{...t,payload:e}}catch{return {...t,payload:{truncated:true}}}}function Er(t){if(!t||typeof t!="object")return;let e={};for(let o of yr)if(Object.hasOwn(t,o)){let r=t[o];if(o==="metadata"&&(r==null||typeof r!="object"))continue;e[o]=r;}return Object.keys(e).length?e:void 0}async function Kt(t,e,o){if(process.env[Fe]==="1")return;let r=e.getUpdateMetadata()??{},i=Date.now(),n=r.latestVersion,s=r.lastChecked??0;if(!n||i-s>We){let l=await Tr(t,o);l.latestVersion&&(n=l.latestVersion),l.checkedAt>0&&(s=l.checkedAt,e.setUpdateMetadata({lastChecked:s,latestVersion:n}),await e.save());}if(!n||!L.valid(n)||!L.gt(n,t)||!Pr(r,i,n))return;let c=`npm install -g ${me}`;o.warn(`A new version of hbx is available: ${n} (current ${t}).
94
+ Update with: ${c} (or pnpm add -g ${me}).`),e.setUpdateMetadata({lastNotifiedAt:i,latestVersion:n}),await e.save();}function Pr(t,e,o){return !t||t.lastNotifiedAt===void 0||t.latestVersion!==o?true:e-t.lastNotifiedAt>ze}async function Tr(t,e){try{let o=await fetch(`https://registry.npmjs.org/${encodeURIComponent(me)}/latest`,{headers:{"User-Agent":`hbx-cli/${t}`}});if(!o.ok)throw new Error(`npm registry responded with status ${o.status}`);return {latestVersion:(await o.json()).version,checkedAt:Date.now()}}catch(o){return e.debug(`update check failed: ${String(o)}`),{checkedAt:Date.now()}}}async function Hr(t=process.argv){let e=he(),o=await we.load(),r=new be({debug:process.env[ee]==="1"});await o.ensureTelemetryId();let i=new xe(o,r,e),n={config:o,logger:r,telemetry:i};await Kt(e,o,r),await _r(n);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[ee]==="1"),i.setCommand(Ir(c));}),St(s,n),ot(s,n),Dt(s,n),It(s,n),Rt(s,n),Nt(s,n),Ot(s,n),Xt(s,n),Mt(s,n),zt(s,n);try{await s.parseAsync(t);}catch(a){Sr(a,r);}}function Sr(t,e){if(De(t)){let o={status:"error",code:t.code,message:t.message,details:t.details};e.isJsonMode()?e.json(o):e.error(`${t.code}: ${t.message}`);}else t instanceof R?e.error(`${t.code}: ${t.message}`):t instanceof Error?e.error(t.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"))&&Hr();function Ir(t){if(!t)return ce;let e=[],o=t;for(;o?.parent;){let r=o.name?.();r&&e.unshift(r),o=o.parent;}return e.length?`${ce} ${e.join(" ")}`.trim():ce}async function _r(t){if(process.env[X]&&t.config.getLicense()&&!t.config.getDeviceInfo())try{await B(t);}catch(e){t.logger.debug(`Skipping device registration warm-up: ${String(e)}`);}}
80
95
 
81
- export { Vo as bootstrap };
96
+ export { Hr as bootstrap };
@@ -0,0 +1,46 @@
1
+ # HugoBlox Theme Pack
2
+ # https://docs.hugoblox.com
3
+
4
+ hugoblox:
5
+ meta:
6
+ format: "hugoblox-theme@1"
7
+ name: "Minimal"
8
+ vendor: "hugoblox"
9
+ version: "1.0.0"
10
+ license: "MIT"
11
+ description: "Clean, GitHub-inspired design"
12
+
13
+ type: "dual"
14
+
15
+ light:
16
+ # Inspired by GitHub Light
17
+ colors:
18
+ primary: "#0969da" # GitHub Blue
19
+ secondary: "#1f883d" # GitHub Green
20
+ neutral: "#24292f" # GitHub Dark Gray (Text)
21
+ ui:
22
+ background: "#ffffff"
23
+ foreground: "#24292f"
24
+ header:
25
+ background: "#f6f8fa" # GitHub Header Gray
26
+ foreground: "#24292f"
27
+ footer:
28
+ background: "#ffffff" # Clean
29
+ foreground: "#57606a" # Muted text
30
+
31
+ dark:
32
+ # Inspired by GitHub Dark
33
+ colors:
34
+ primary: "#58a6ff" # GitHub Blue (Dark Mode)
35
+ secondary: "#238636" # GitHub Green (Dark Mode)
36
+ neutral: "#c9d1d9" # GitHub Light Gray (Text)
37
+ ui:
38
+ background: "#0d1117" # GitHub Dimmed BG
39
+ foreground: "#c9d1d9"
40
+ header:
41
+ background: "#161b22" # GitHub Dark Header
42
+ foreground: "#f0f6fc"
43
+ footer:
44
+ background: "#0d1117"
45
+ foreground: "#8b949e" # Muted text
46
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hugoblox",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "The official CLI for creating and managing HugoBlox sites.",
5
5
  "type": "module",
6
6
  "bin": {