@stacksjs/buddy 0.75.108 → 0.75.110

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.
@@ -1,2 +1,2 @@
1
- import{existsSync,readFileSync}from"node:fs";const API="https://api.appstoreconnect.apple.com";export function appStoreConnectCredentials(env=process.env){const keyId=env.APP_STORE_CONNECT_KEY_ID?.trim(),issuerId=env.APP_STORE_CONNECT_ISSUER_ID?.trim();let privateKey=env.APP_STORE_CONNECT_PRIVATE_KEY?.trim();const keyPath=env.APP_STORE_CONNECT_PRIVATE_KEY_PATH?.trim();if(!privateKey&&keyPath&&existsSync(keyPath))privateKey=readFileSync(keyPath,"utf8").trim();if(!keyId||!issuerId||!privateKey)return null;return{keyId,issuerId,privateKey:privateKey.replace(/\\n/g,`
2
- `)}}function base64url(bytes){return(typeof bytes==="string"?Buffer.from(bytes):Buffer.from(bytes)).toString("base64").replace(/=+$/,"").replace(/\+/g,"-").replace(/\//g,"_")}export async function appStoreConnectToken(credentials,now=Date.now()){const pem=credentials.privateKey.replace(/-----(BEGIN|END) PRIVATE KEY-----/g,"").replace(/\s+/g,""),key=await crypto.subtle.importKey("pkcs8",Buffer.from(pem,"base64"),{name:"ECDSA",namedCurve:"P-256"},!1,["sign"]),iat=Math.floor(now/1000),header=base64url(JSON.stringify({alg:"ES256",kid:credentials.keyId,typ:"JWT"})),payload=base64url(JSON.stringify({iss:credentials.issuerId,iat,exp:iat+1200,aud:"appstoreconnect-v1"})),signature=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},key,Buffer.from(`${header}.${payload}`));return`${header}.${payload}.${base64url(new Uint8Array(signature))}`}export class AppStoreConnect{token;fetchImpl;constructor(token,fetchImpl=fetch){this.token=token;this.fetchImpl=fetchImpl}static async connect(credentials,fetchImpl){return new AppStoreConnect(await appStoreConnectToken(credentials),fetchImpl)}async request(path,init={}){const response=await this.fetchImpl(`${API}${path}`,{...init,headers:{Authorization:`Bearer ${this.token}`,"Content-Type":"application/json",...init.headers}});if(!response.ok){const body=await response.text().catch(()=>"");throw Error(`App Store Connect ${init.method??"GET"} ${path} answered ${response.status}${body?`: ${body.slice(0,300)}`:""}`)}return response.status===204?null:await response.json()}async appId(bundleId){const id=(await this.request(`/v1/apps?filter[bundleId]=${encodeURIComponent(bundleId)}&limit=1`))?.data?.[0]?.id;if(!id)throw Error(`App Store Connect has no app with the bundle id ${bundleId}`);return id}async latestXcodeCloudRun(appId){const productId=(await this.request(`/v1/ciProducts?filter[app]=${appId}&limit=1`))?.data?.[0]?.id;if(!productId)return null;const runs=await this.request(`/v1/ciProducts/${productId}/buildRuns?sort=-number&limit=1&fields[ciBuildRuns]=number`),number=Number(runs?.data?.[0]?.attributes?.number);return Number.isInteger(number)?number:null}async builds(appId){return((await this.request(`/v1/builds?filter[app]=${appId}&sort=-uploadedDate&limit=50&fields[builds]=version,uploadedDate,processingState,expired`))?.data??[]).map((build)=>({id:build.id,number:Number(build.attributes?.version),uploadedDate:String(build.attributes?.uploadedDate??""),processingState:String(build.attributes?.processingState??""),expired:Boolean(build.attributes?.expired)}))}async expire(buildId){await this.request(`/v1/builds/${buildId}`,{method:"PATCH",body:JSON.stringify({data:{type:"builds",id:buildId,attributes:{expired:!0}}})})}}export function buildsToExpire(builds,keep=1){return builds.filter((build)=>!build.expired&&build.processingState==="VALID").sort((a,b)=>b.number-a.number).slice(Math.max(0,keep))}export function tagForXcodeCloudRun(version,latestRun){return`v${version}-build.${latestRun+1}`}
1
+ import{existsSync,readFileSync}from"node:fs";import{nextBuildNumber}from"@stacksjs/bumpx";const API="https://api.appstoreconnect.apple.com";export function appStoreConnectCredentials(env=process.env){const keyId=env.APP_STORE_CONNECT_KEY_ID?.trim(),issuerId=env.APP_STORE_CONNECT_ISSUER_ID?.trim();let privateKey=env.APP_STORE_CONNECT_PRIVATE_KEY?.trim();const keyPath=env.APP_STORE_CONNECT_PRIVATE_KEY_PATH?.trim();if(!privateKey&&keyPath&&existsSync(keyPath))privateKey=readFileSync(keyPath,"utf8").trim();if(!keyId||!issuerId||!privateKey)return null;return{keyId,issuerId,privateKey:privateKey.replace(/\\n/g,`
2
+ `)}}function base64url(bytes){return(typeof bytes==="string"?Buffer.from(bytes):Buffer.from(bytes)).toString("base64").replace(/=+$/,"").replace(/\+/g,"-").replace(/\//g,"_")}export async function appStoreConnectToken(credentials,now=Date.now()){const pem=credentials.privateKey.replace(/-----(BEGIN|END) PRIVATE KEY-----/g,"").replace(/\s+/g,""),key=await crypto.subtle.importKey("pkcs8",Buffer.from(pem,"base64"),{name:"ECDSA",namedCurve:"P-256"},!1,["sign"]),iat=Math.floor(now/1000),header=base64url(JSON.stringify({alg:"ES256",kid:credentials.keyId,typ:"JWT"})),payload=base64url(JSON.stringify({iss:credentials.issuerId,iat,exp:iat+1200,aud:"appstoreconnect-v1"})),signature=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},key,Buffer.from(`${header}.${payload}`));return`${header}.${payload}.${base64url(new Uint8Array(signature))}`}export class AppStoreConnect{token;fetchImpl;constructor(token,fetchImpl=fetch){this.token=token;this.fetchImpl=fetchImpl}static async connect(credentials,fetchImpl){return new AppStoreConnect(await appStoreConnectToken(credentials),fetchImpl)}async request(path,init={}){const response=await this.fetchImpl(`${API}${path}`,{...init,headers:{Authorization:`Bearer ${this.token}`,"Content-Type":"application/json",...init.headers}});if(!response.ok){const body=await response.text().catch(()=>"");throw Error(`App Store Connect ${init.method??"GET"} ${path} answered ${response.status}${body?`: ${body.slice(0,300)}`:""}`)}return response.status===204?null:await response.json()}async appId(bundleId){const id=(await this.request(`/v1/apps?filter[bundleId]=${encodeURIComponent(bundleId)}&limit=1`))?.data?.[0]?.id;if(!id)throw Error(`App Store Connect has no app with the bundle id ${bundleId}`);return id}async latestXcodeCloudRun(appId){const productId=(await this.request(`/v1/ciProducts?filter[app]=${appId}&limit=1`))?.data?.[0]?.id;if(!productId)return null;const runs=await this.request(`/v1/ciProducts/${productId}/buildRuns?sort=-number&limit=1&fields[ciBuildRuns]=number`),number=Number(runs?.data?.[0]?.attributes?.number);return Number.isSafeInteger(number)&&number>=0?number:null}async builds(appId){return((await this.request(`/v1/builds?filter[app]=${appId}&sort=-uploadedDate&limit=50&fields[builds]=version,uploadedDate,processingState,expired`))?.data??[]).map((build)=>({id:build.id,number:Number(build.attributes?.version),uploadedDate:String(build.attributes?.uploadedDate??""),processingState:String(build.attributes?.processingState??""),expired:Boolean(build.attributes?.expired)}))}async expire(buildId){await this.request(`/v1/builds/${buildId}`,{method:"PATCH",body:JSON.stringify({data:{type:"builds",id:buildId,attributes:{expired:!0}}})})}}export function buildsToExpire(builds,keep=1){return builds.filter((build)=>!build.expired&&build.processingState==="VALID").sort((a,b)=>b.number-a.number).slice(Math.max(0,keep))}export function tagForXcodeCloudRun(version,latestRun){return`v${version}-build.${nextBuildNumber(latestRun)}`}
@@ -1,4 +1,4 @@
1
1
  import{execFileSync}from"node:child_process";import{readdirSync,readFileSync,statSync,writeFileSync}from"node:fs";import{join}from"node:path";import process from"node:process";import{assertFrameworkRepo}from"./framework-repo";const root=new URL("../../../../../../../",import.meta.url).pathname;function abs(relative){return join(root,relative)}function ignoredPaths(paths){if(!paths.length)return new Set;try{const output=execFileSync("git",["check-ignore","--stdin"],{cwd:root,input:paths.join(`
2
2
  `),encoding:"utf8",stdio:["pipe","pipe","ignore"]});return new Set(output.split(`
3
- `).map((line)=>line.trim()).filter(Boolean))}catch{return new Set}}function walkFiles(dir,extension){let entries;try{entries=readdirSync(abs(dir))}catch{return[]}return entries.flatMap((entry)=>{const full=join(abs(dir),entry);if(statSync(full).isDirectory())return walkFiles(join(dir,entry),extension);if(!entry.endsWith(extension)||entry==="index.ts")return[];return[join(dir,entry)]})}export function countFiles(dir,extension){const files=walkFiles(dir,extension),ignored=ignoredPaths(files);return files.filter((file)=>!ignored.has(file)).length}function countDirs(dir){return readdirSync(abs(dir)).filter((entry)=>statSync(join(abs(dir),entry)).isDirectory()).length}const SKILLS="storage/framework/defaults/ai/skills",AGENTS="AGENTS.md",CLAIMS=[{what:"built-in models",measure:()=>countFiles("storage/framework/defaults/app/Models",".ts"),sites:[{file:AGENTS,pattern:/(\d+) built-in models you can use or override/},{file:AGENTS,pattern:/All (\d+) models \(`User`/},{file:`${SKILLS}/stacks-orm/SKILL.md`,pattern:/(\d+) models/},{file:`${SKILLS}/stacks-auto-imports/SKILL.md`,pattern:/\((\d+) models\)/},{file:AGENTS,pattern:/including the (\d+) built-in `Models\/`/},{file:AGENTS,pattern:/\((\d+) built-ins, grouped into/},{file:`${SKILLS}/stacks-models/SKILL.md`,pattern:/holds (\d+), and that/},{file:`${SKILLS}/stacks-models/SKILL.md`,pattern:/the (\d+) built-in framework models/},{file:`${SKILLS}/stacks-orm/SKILL.md`,pattern:/(\d+) built-in models/}]},{what:"commerce models",measure:()=>countFiles("storage/framework/defaults/app/Models/commerce",".ts"),sites:[{file:`${SKILLS}/stacks-commerce/SKILL.md`,pattern:/and (\d+) models/},{file:`${SKILLS}/stacks-types/SKILL.md`,pattern:/Commerce \((\d+) models\)/}]},{what:"components",measure:()=>countFiles("storage/framework/defaults/resources/components",".stx"),sites:[{file:AGENTS,pattern:/widgets \((\d+) components\)/},{file:`${SKILLS}/stacks-dashboard/SKILL.md`,pattern:/(\d+) built-in dashboard components/},{file:`${SKILLS}/stacks-dashboard/SKILL.md`,pattern:/route views, (\d+) components,/}]},{what:"default actions",measure:()=>readFileSync(abs("storage/framework/auto-imports/actions.ts"),"utf-8").split(`
4
- `).filter((line)=>/^\s+'/.test(line)).length,sites:[{file:AGENTS,pattern:/(\d+) default actions/},{file:`${SKILLS}/stacks-actions/SKILL.md`,pattern:/(\d+) default framework actions/}]},{what:"migrations",measure:()=>countFiles("database/migrations",".sql"),sites:[{file:AGENTS,pattern:/(\d+) migrations ship for/},{file:`${SKILLS}/stacks-migrations/SKILL.md`,pattern:/(\d+) built-in migration files/},{file:`${SKILLS}/stacks-migrations/SKILL.md`,pattern:/(\d+) migration files exist by default/},{file:`${SKILLS}/stacks-database/SKILL.md`,pattern:/\((\d+) migration files/}]},{what:"composables",measure:()=>new Set(readFileSync(abs("storage/framework/core/composables/src/index.ts"),"utf-8").match(/\buse[A-Z][A-Za-z0-9]*/g)??[]).size,sites:[{file:`${SKILLS}/stacks-composables/SKILL.md`,pattern:/(\d+) composables/},{file:`${SKILLS}/stacks-composables/SKILL.md`,pattern:/(\d+) reactive composables for STX/}]},{what:"config files",measure:()=>countFiles("config",".ts"),sites:[{file:AGENTS,pattern:/~(\d+) typed config files/}]},{what:"skills",measure:()=>countDirs(SKILLS),sites:[{file:`${SKILLS}/stacks-writing-for-agents/SKILL.md`,pattern:/ships (\d+) skills/}]}];function inspect(){const drift=[];let checked=0;for(const claim of CLAIMS){const actual=claim.measure();for(const site of claim.sites){checked++;const match=readFileSync(abs(site.file),"utf-8").match(site.pattern),stated=match?Number(match[1]):null;if(stated!==actual)drift.push({what:claim.what,file:site.file,stated,actual})}}return{drift,checked}}function write(){let rewritten=0;for(const claim of CLAIMS){const actual=claim.measure();for(const site of claim.sites){const source=readFileSync(abs(site.file),"utf-8"),match=source.match(site.pattern);if(!match||Number(match[1])===actual)continue;const updated=match[0].replace(String(match[1]),String(actual));writeFileSync(abs(site.file),source.replace(match[0],updated),"utf-8");rewritten++}}return rewritten}export async function run(){assertFrameworkRepo(root,"docs:agent-counts");if(process.argv.includes("--write")){const rewritten=write();console.log(rewritten===0?"\u2713 agent-facing counts were already current":`\u2713 updated ${rewritten} count(s); run \`buddy setup:ai\` to refresh the installed copies`);return}const{drift,checked}=inspect();if(drift.length===0){console.log(`\u2713 agent-facing counts are current (${checked} checked)`);return}console.error(`\u2717 ${drift.length} of ${checked} agent-facing count(s) no longer match the tree:`);for(const entry of drift)console.error(entry.stated===null?` ${entry.file}: the ${entry.what} claim is gone - reword the check, or restore the sentence`:` ${entry.file}: says ${entry.stated} ${entry.what}, tree has ${entry.actual}`);console.error("\nRun `buddy docs:agent-counts` to rewrite them from the tree.");if(process.argv.includes("--check"))process.exit(1)}if(import.meta.main)await run();
3
+ `).map((line)=>line.trim()).filter(Boolean))}catch{return new Set}}function walkFiles(dir,extension){let entries;try{entries=readdirSync(abs(dir))}catch{return[]}return entries.flatMap((entry)=>{const full=join(abs(dir),entry);if(statSync(full).isDirectory())return walkFiles(join(dir,entry),extension);if(!entry.endsWith(extension)||entry==="index.ts")return[];return[join(dir,entry)]})}export function countFiles(dir,extension){const files=walkFiles(dir,extension),ignored=ignoredPaths(files);return files.filter((file)=>!ignored.has(file)).length}function countDirs(dir){return readdirSync(abs(dir)).filter((entry)=>statSync(join(abs(dir),entry)).isDirectory()).length}const SKILLS="storage/framework/defaults/ai/skills",AGENTS="AGENTS.md",CLAIMS=[{what:"built-in models",measure:()=>countFiles("storage/framework/defaults/app/Models",".ts"),sites:[{file:AGENTS,pattern:/(\d+) built-in models you can use or override/},{file:AGENTS,pattern:/All (\d+) models \(`User`/},{file:`${SKILLS}/stacks-orm/SKILL.md`,pattern:/(\d+) models/},{file:`${SKILLS}/stacks-auto-imports/SKILL.md`,pattern:/\((\d+) models\)/},{file:AGENTS,pattern:/including the (\d+) built-in `Models\/`/},{file:AGENTS,pattern:/\((\d+) built-ins, grouped into/},{file:`${SKILLS}/stacks-models/SKILL.md`,pattern:/holds (\d+), and that/},{file:`${SKILLS}/stacks-models/SKILL.md`,pattern:/the (\d+) built-in framework models/},{file:`${SKILLS}/stacks-orm/SKILL.md`,pattern:/(\d+) built-in models/}]},{what:"commerce models",measure:()=>countFiles("storage/framework/defaults/app/Models/commerce",".ts"),sites:[{file:`${SKILLS}/stacks-commerce/SKILL.md`,pattern:/and (\d+) models/}]},{what:"components",measure:()=>countFiles("storage/framework/defaults/resources/components",".stx"),sites:[{file:AGENTS,pattern:/widgets \((\d+) components\)/},{file:`${SKILLS}/stacks-dashboard/SKILL.md`,pattern:/(\d+) built-in dashboard components/},{file:`${SKILLS}/stacks-dashboard/SKILL.md`,pattern:/route views, (\d+) components,/}]},{what:"default actions",measure:()=>readFileSync(abs("storage/framework/auto-imports/actions.ts"),"utf-8").split(`
4
+ `).filter((line)=>/^\s+'/.test(line)).length,sites:[{file:AGENTS,pattern:/(\d+) default actions/},{file:`${SKILLS}/stacks-actions/SKILL.md`,pattern:/(\d+) default framework actions/}]},{what:"migrations",measure:()=>countFiles("database/migrations",".sql"),sites:[{file:AGENTS,pattern:/(\d+) migrations ship for/},{file:`${SKILLS}/stacks-migrations/SKILL.md`,pattern:/(\d+) built-in migration files/},{file:`${SKILLS}/stacks-migrations/SKILL.md`,pattern:/(\d+) migration files exist by default/},{file:`${SKILLS}/stacks-database/SKILL.md`,pattern:/\((\d+) migration files/}]},{what:"config files",measure:()=>countFiles("config",".ts"),sites:[{file:AGENTS,pattern:/~(\d+) typed config files/}]},{what:"skills",measure:()=>countDirs(SKILLS),sites:[{file:`${SKILLS}/stacks-writing-for-agents/SKILL.md`,pattern:/ships (\d+) skills/}]}];function inspect(){const drift=[];let checked=0;for(const claim of CLAIMS){const actual=claim.measure();for(const site of claim.sites){checked++;const match=readFileSync(abs(site.file),"utf-8").match(site.pattern),stated=match?Number(match[1]):null;if(stated!==actual)drift.push({what:claim.what,file:site.file,stated,actual})}}return{drift,checked}}function write(){let rewritten=0;for(const claim of CLAIMS){const actual=claim.measure();for(const site of claim.sites){const source=readFileSync(abs(site.file),"utf-8"),match=source.match(site.pattern);if(!match||Number(match[1])===actual)continue;const updated=match[0].replace(String(match[1]),String(actual));writeFileSync(abs(site.file),source.replace(match[0],updated),"utf-8");rewritten++}}return rewritten}export async function run(){assertFrameworkRepo(root,"docs:agent-counts");if(process.argv.includes("--write")){const rewritten=write();console.log(rewritten===0?"\u2713 agent-facing counts were already current":`\u2713 updated ${rewritten} count(s); run \`buddy setup:ai\` to refresh the installed copies`);return}const{drift,checked}=inspect();if(drift.length===0){console.log(`\u2713 agent-facing counts are current (${checked} checked)`);return}console.error(`\u2717 ${drift.length} of ${checked} agent-facing count(s) no longer match the tree:`);for(const entry of drift)console.error(entry.stated===null?` ${entry.file}: the ${entry.what} claim is gone - reword the check, or restore the sentence`:` ${entry.file}: says ${entry.stated} ${entry.what}, tree has ${entry.actual}`);console.error("\nRun `buddy docs:agent-counts` to rewrite them from the tree.");if(process.argv.includes("--check"))process.exit(1)}if(import.meta.main)await run();
@@ -0,0 +1,13 @@
1
+ export declare function nativePackageCatalog(projectRoot?: unknown): PackageEntry[];
2
+ export declare function renderNativeCatalog(projectRoot?: unknown): string;
3
+ export declare function renderDriverCapabilities(): string;
4
+ export declare function run(): Promise<void>;
5
+ declare interface PackageEntry {
6
+ name: string
7
+ directory: string
8
+ skill: string
9
+ entry: string
10
+ exports: string[]
11
+ dependencies: string[]
12
+ tests: string[]
13
+ }
@@ -0,0 +1,3 @@
1
+ import{existsSync,readFileSync,readdirSync,statSync,writeFileSync}from"node:fs";import{dirname,join,relative}from"node:path";import process from"node:process";import{capabilityRegistry}from"../../../../config/src/capabilities";import{FEATURE_NAMES}from"../../../../features/src/names";import{assertFrameworkRepo}from"./framework-repo";const root=new URL("../../../../../../../",import.meta.url).pathname,core="storage/framework/core",destination="storage/framework/defaults/ai/skills/stacks-native",PACKAGE_SKILLS={"action-runner":"stacks-actions","calendar-api":"stacks-calendar",defaults:"stacks-build",github:"stacks-git","model-meta":"stacks-models",tinker:"stacks-repl"};function localSource(projectRoot,entry,specifier){const path=join(dirname(entry),specifier),stem=path.replace(/\.js$/,""),resolved=[path,`${stem}.ts`,`${stem}.tsx`,join(path,"index.ts")].find((candidate)=>existsSync(join(projectRoot,candidate))&&statSync(join(projectRoot,candidate)).isFile());if(!resolved)throw Error(`Native catalog cannot resolve ${specifier} from ${entry}`);return resolved}export function nativePackageCatalog(projectRoot=root){const scanner=new Bun.Transpiler({loader:"ts"});return readdirSync(join(projectRoot,core)).filter((slug)=>existsSync(join(projectRoot,core,slug,"package.json"))).sort().map((slug)=>{const directory=join(core,slug),manifest=JSON.parse(readFileSync(join(projectRoot,directory,"package.json"),"utf8")),skill=PACKAGE_SKILLS[slug]??`stacks-${slug}`;if(!existsSync(join(projectRoot,"storage/framework/defaults/ai/skills",skill,"SKILL.md")))throw Error(`Native package ${manifest.name} needs a skill or an explicit package-to-skill mapping`);const source=join(directory,"src/index.ts"),entry=existsSync(join(projectRoot,source))?source:join(directory,"package.json"),scan=entry.endsWith(".ts")?scanner.scan(readFileSync(join(projectRoot,entry),"utf8")):void 0,tests=existsSync(join(projectRoot,directory,"tests"))?[...new Bun.Glob("**/*.{test,spec}.{ts,tsx,js}").scanSync({cwd:join(projectRoot,directory,"tests"),onlyFiles:!0})].sort().map((file)=>join(directory,"tests",file)):[];return{name:manifest.name,directory,skill,entry,exports:scan?.exports.sort()??[],dependencies:[...new Set(scan?.imports.map((item)=>item.path).filter((path)=>path.startsWith("."))??[])].map((path)=>localSource(projectRoot,entry,path)).sort(),tests}})}function sourceLink(path,label=path){return`[${label}](https://github.com/stacksjs/stacks/blob/main/${path})`}export function renderNativeCatalog(projectRoot=root){const packages=nativePackageCatalog(projectRoot);return["# Native Stacks package catalog","","<!-- Generated by buddy docs:native-skills. Edit source packages or the mapping, then regenerate. -->","","This indexes every current core package. It describes source surfaces and","retained tests, not a promise that every export or remote provider is fully","supported. Read the selected skill and implementation before choosing an API.","Wildcard re-exports and type-only exports are not expanded by the source scan.","Browser runtime bindings are documented separately in `stacks-auto-imports`.","","| Package | Task guidance | Source entry | Retained tests |","|---|---|---|---|",...packages.map((entry)=>`| \`${entry.name}\` | [\`${entry.skill}\`](../${entry.skill}/SKILL.md) | ${sourceLink(entry.entry,"entrypoint")} | ${entry.tests.length} |`),"","## Source surfaces","","Use these pointers to discover the current implementation and exact signatures.","An exported name is not evidence that an operation supports every driver.","",...packages.flatMap((entry)=>[`### ${entry.name}`,"",`Guidance: [\`${entry.skill}\`](../${entry.skill}/SKILL.md). Source: ${sourceLink(entry.entry)}.`,"",entry.exports.length?`Declared runtime exports: ${entry.exports.map((name)=>`\`${name}\``).join(", ")}.`:"Read the entrypoint and package export map for re-exported or type-only surfaces.","",...entry.dependencies.length?[`Local source modules: ${entry.dependencies.map((path)=>sourceLink(path,relative(entry.directory,path))).join(", ")}.`,""]:[],...entry.tests.length?[`Evidence directory: ${sourceLink(`${entry.directory}/tests`,`${entry.tests.length} retained tests`)}. These files are evidence pointers, not a claim that all tests were run for this catalog.`,""]:[]])].join(`
2
+ `)}export function renderDriverCapabilities(){return["# Driver evidence and limitations","","<!-- Generated by buddy docs:native-skills from capabilityRegistry. -->","","The registry distinguishes supported, partial, experimental, and unsupported","drivers. Unknown and unsupported selections fail. Partial and experimental","drivers remain subject to the limitations below. Read prerequisites before","deploying; a configuration type does not establish an implemented transport.","",...capabilityRegistry.flatMap((driver)=>[`## ${driver.category}: ${driver.name}`,"",`Status: **${driver.status}**. Topology: ${driver.topology}.`,"",...driver.implementation?[`Implementation: ${sourceLink(driver.implementation)}.`,""]:[],...driver.prerequisites.length?["Prerequisites:","",...driver.prerequisites.map((value)=>`- ${value}`),""]:[],...driver.limitations.length?["Limitations:","",...driver.limitations.map((value)=>`- ${value}`),""]:[],...driver.testEvidence.length?["Retained evidence:","",...driver.testEvidence.map((path)=>`- ${sourceLink(path)}`),""]:[]]),"## Optional application bundles","",`Installable bundle names: ${FEATURE_NAMES.map((name)=>`\`${name}\``).join(", ")}.`,"","Read `stacks-features` for installation, config gates, route bundles, and","migration selection. These are distinct from user-targeted feature flags.",""].join(`
3
+ `).replace(/[\u2014\u2013]/g,"-")}export async function run(){assertFrameworkRepo(root,"docs:native-skills");const stale=[{path:join(root,destination,"CATALOG.md"),body:renderNativeCatalog()},{path:join(root,destination,"CAPABILITIES.md"),body:renderDriverCapabilities()}].filter((file)=>!existsSync(file.path)||readFileSync(file.path,"utf8")!==file.body);if(process.argv.includes("--write")){for(const file of stale)writeFileSync(file.path,file.body,"utf8");console.log(`Native skill references refreshed: ${stale.length} file(s).`)}else if(stale.length){console.error(`Native skill references are stale: ${stale.map((file)=>relative(root,file.path)).join(", ")}. Run ./buddy docs:native-skills.`);process.exitCode=1}else console.log("Native skill package coverage and driver evidence are current.")}if(import.meta.main)await run();
@@ -1 +1 @@
1
- import{run as runAgentCounts}from"./docs/agent-counts";import{run as runArtifacts}from"./docs/generated-artifacts";import{run as runBuddyDocs}from"./docs/buddy-commands";import{run as runCapabilities}from"./docs/capabilities";import{run as runSnippets}from"./docs/snippets";import{run as runDesktopMatrix}from"./docs/desktop-matrix";import{run as runLinks}from"./docs/links";import{runTool}from"./run-tool";export function docs(buddy){buddy.command("docs:buddy","Regenerate the buddy command reference doc").action(async()=>{await runTool(runBuddyDocs,"--write")});buddy.command("docs:buddy:check","Verify the buddy command reference doc is current").action(async()=>{await runTool(runBuddyDocs,"--check")});buddy.command("docs:artifacts","Regenerate the generated API artifacts (OpenAPI + types)").action(async()=>{await runTool(runArtifacts,"--write")});buddy.command("docs:artifacts:check","Verify the generated API artifacts are current").action(async()=>{await runTool(runArtifacts,"--check")});buddy.command("docs:agent-counts","Rewrite the counts AGENTS.md and the skills state, from the tree").action(async()=>{await runTool(runAgentCounts,"--write")});buddy.command("docs:agent-counts:check","Verify the counts AGENTS.md and the skills state are current").action(async()=>{await runTool(runAgentCounts,"--check")});buddy.command("docs:capabilities","Regenerate the driver capability matrix in docs/features/capabilities.md").action(async()=>{await runTool(runCapabilities,"--write")});buddy.command("docs:capabilities:check","Verify the published capability matrix matches its registry").action(async()=>{await runTool(runCapabilities,"--check")});buddy.command("docs:desktop-matrix","Regenerate the desktop support matrix in docs/packages/desktop.md").action(async()=>{await runTool(runDesktopMatrix,"--write")});buddy.command("docs:desktop-matrix:check","Verify the published desktop support matrix matches its source").action(async()=>{await runTool(runDesktopMatrix,"--check")});buddy.command("docs:snippets","Record the documented imports that do not compile, as the baseline").action(async()=>{await runTool(runSnippets,"--write")});buddy.command("docs:snippets:check","Verify no NEW documented import fails to compile").action(async()=>{await runTool(runSnippets,"--check")});buddy.command("docs:links","Report internal documentation links").action(async()=>{await runTool(runLinks)});buddy.command("docs:links:check","Verify internal documentation links resolve").action(async()=>{await runTool(runLinks,"--check")})}
1
+ import{run as runAgentCounts}from"./docs/agent-counts";import{run as runArtifacts}from"./docs/generated-artifacts";import{run as runBuddyDocs}from"./docs/buddy-commands";import{run as runCapabilities}from"./docs/capabilities";import{run as runSnippets}from"./docs/snippets";import{run as runDesktopMatrix}from"./docs/desktop-matrix";import{run as runLinks}from"./docs/links";import{run as runNativeSkills}from"./docs/native-skills";import{runTool}from"./run-tool";export function docs(buddy){buddy.command("docs:native-skills","Regenerate native skill package coverage and driver evidence").action(async()=>{await runTool(runNativeSkills,"--write")});buddy.command("docs:native-skills:check","Verify native skills cover current packages and driver capabilities").action(async()=>{await runTool(runNativeSkills,"--check")});buddy.command("docs:buddy","Regenerate the buddy command reference doc").action(async()=>{await runTool(runBuddyDocs,"--write")});buddy.command("docs:buddy:check","Verify the buddy command reference doc is current").action(async()=>{await runTool(runBuddyDocs,"--check")});buddy.command("docs:artifacts","Regenerate the generated API artifacts (OpenAPI + types)").action(async()=>{await runTool(runArtifacts,"--write")});buddy.command("docs:artifacts:check","Verify the generated API artifacts are current").action(async()=>{await runTool(runArtifacts,"--check")});buddy.command("docs:agent-counts","Rewrite the counts AGENTS.md and the skills state, from the tree").action(async()=>{await runTool(runAgentCounts,"--write")});buddy.command("docs:agent-counts:check","Verify the counts AGENTS.md and the skills state are current").action(async()=>{await runTool(runAgentCounts,"--check")});buddy.command("docs:capabilities","Regenerate the driver capability matrix in docs/features/capabilities.md").action(async()=>{await runTool(runCapabilities,"--write")});buddy.command("docs:capabilities:check","Verify the published capability matrix matches its registry").action(async()=>{await runTool(runCapabilities,"--check")});buddy.command("docs:desktop-matrix","Regenerate the desktop support matrix in docs/packages/desktop.md").action(async()=>{await runTool(runDesktopMatrix,"--write")});buddy.command("docs:desktop-matrix:check","Verify the published desktop support matrix matches its source").action(async()=>{await runTool(runDesktopMatrix,"--check")});buddy.command("docs:snippets","Record the documented imports that do not compile, as the baseline").action(async()=>{await runTool(runSnippets,"--write")});buddy.command("docs:snippets:check","Verify no NEW documented import fails to compile").action(async()=>{await runTool(runSnippets,"--check")});buddy.command("docs:links","Report internal documentation links").action(async()=>{await runTool(runLinks)});buddy.command("docs:links:check","Verify internal documentation links resolve").action(async()=>{await runTool(runLinks,"--check")})}
@@ -1,2 +1,2 @@
1
- import{execFileSync}from"node:child_process";import{existsSync,readFileSync,writeFileSync}from"node:fs";import{join}from"node:path";import{pathToFileURL}from"node:url";import process from"node:process";import{runAction}from"@stacksjs/actions";import{intro,italic,log,onUnknownSubcommand,outro}from"@stacksjs/cli";import{Action}from"@stacksjs/enums";import{ExitCode}from"@stacksjs/types";import{AppStoreConnect,appStoreConnectCredentials,buildsToExpire,tagForXcodeCloudRun}from"../app-store-connect";import{bumpedVersion,iosVersionIn,nextBuildTag,withIosVersion}from"../release-ios";import{resultFailed}from"../result";const descriptions={release:"Release a new version of your libraries/packages",project:"Target a specific project",dryRun:"Run the release without actually releasing",bump:"Non-interactive bump: patch | minor | major | prepatch | preminor | premajor | prerelease | calendar | x.y.z",verbose:"Enable verbose output"};export function release(buddy){buddy.command("release",descriptions.release).option("--dry-run",descriptions.dryRun,{default:!1}).option("-p, --project [project]",descriptions.project,{default:!1}).option("--bump <type>",descriptions.bump).option("--verbose",descriptions.verbose,{default:!1}).action(async(options)=>{log.debug("Running `buddy release` ...",options);if(options.dryRun)log.warn("Dry run enabled. No changes will be made or committed.");const startTime=await intro("buddy release"),result=await runAction(Action.Release,options);if(resultFailed(result)){await log.error("Failed to release",result.error);process.exit(ExitCode.FatalError)}await outro(options.dryRun?"Dry run complete. Nothing was committed, tagged or pushed.":"Triggered CI/CD Release via GitHub Actions",{startTime,useSeconds:!0});if(!options.dryRun)log.info(`Follow along: ${italic(resolveGitHubActionsUrl(readOriginRemote()))}`)});buddy.command("release:ios","Ship the iOS app: regenerate its project for production, commit, tag and push").option("--bump <type>","Raise the app version first: patch | minor | major | x.y.z (default: a new build of the current version)").option("--keep-builds <n>","TestFlight builds to keep besides the new one; older ones are expired (needs an App Store Connect API key)",{default:1}).option("--dry-run",descriptions.dryRun,{default:!1}).action(async(options)=>{const startTime=await intro("buddy release:ios");try{const tag=await releaseIos(options);await outro(options.dryRun?`Dry run complete: would release ${tag}`:`Released ${tag}`,{startTime,useSeconds:!0});if(!options.dryRun)log.info('A CI that builds tags (Xcode Cloud: Tag Changes, prefix "v") turns it into a TestFlight build now.')}catch(error){await log.error("Failed to release the iOS app",error);process.exit(ExitCode.FatalError)}});onUnknownSubcommand(buddy,"release")}function git(...args){return execFileSync("git",args,{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).trim()}async function releaseIos(options){const root=process.cwd(),configPath=join(root,"config/mobile.ts");if(!existsSync(configPath))throw Error("config/mobile.ts not found: run this in a Stacks app with a mobile config");const branch=git("rev-parse","--abbrev-ref","HEAD");if(branch!=="main")throw Error(`releases are cut from main; this is ${branch}`);if(git("status","--porcelain","--untracked-files=no"))throw Error("commit or stash your changes first, so the release is exactly what is on main");git("pull","--quiet","--rebase","origin","main");git("fetch","--quiet","--tags","origin");const source=readFileSync(configPath,"utf8"),current=iosVersionIn(source);if(!current)throw Error("config/mobile.ts declares no iOS `version`");const version=options.bump?bumpedVersion(current,options.bump):current,existingTags=git("tag","--list",`v${version}-build.*`).split(`
2
- `).filter(Boolean);let tag=nextBuildTag(version,existingTags);const credentials=appStoreConnectCredentials();let store=null;if(credentials){const bundleId=(await import(pathToFileURL(configPath).href)).default.ios?.bundleId;if(!bundleId)throw Error("config/mobile.ts declares no ios.bundleId");const api=await AppStoreConnect.connect(credentials);store={api,appId:await api.appId(bundleId)};const latestRun=await api.latestXcodeCloudRun(store.appId);if(latestRun!==null){const fromStore=tagForXcodeCloudRun(version,latestRun);if(!existingTags.includes(fromStore))tag=fromStore}}else log.warn("No App Store Connect API key (APP_STORE_CONNECT_KEY_ID, _ISSUER_ID, _PRIVATE_KEY_PATH): the tag counts releases, not the build number TestFlight will show, and older builds stay listed.");log.info(`Releasing ${tag}${version===current?"":` (version ${current} \u2192 ${version})`}`);const keep=Math.max(0,Number(options.keepBuilds??1)||0);if(options.dryRun){if(store){const retiring=buildsToExpire(await store.api.builds(store.appId),keep);log.info(retiring.length?`Would expire TestFlight builds ${retiring.map((b)=>b.number).join(", ")}`:"No TestFlight builds to expire")}return tag}const paths=["config/mobile.ts","storage/framework/mobile/ios"];if(version!==current){writeFileSync(configPath,withIosVersion(source,version));const pkgPath=join(root,"package.json");if(existsSync(pkgPath)){const pkg=readFileSync(pkgPath,"utf8");writeFileSync(pkgPath,pkg.replace(/("version"\s*:\s*)"[^"]*"/,`$1"${version}"`));paths.push("package.json")}}for(const key of["MOBILE_URL","IOS_APP_VERSION","IOS_BUILD_NUMBER"])delete process.env[key];const result=await runAction(Action.BuildIos,{});if(resultFailed(result))throw result.error??Error("the iOS build failed");git("add","--",...paths);if(git("diff","--cached","--name-only"))git("commit","--quiet","-m",`chore(release): ${tag}`);git("tag","-a",tag,"-m",tag);git("push","--quiet","--atomic","origin","main",tag);if(store)try{const retiring=buildsToExpire(await store.api.builds(store.appId),keep);for(const build of retiring)await store.api.expire(build.id);if(retiring.length)log.info(`Expired TestFlight builds ${retiring.map((b)=>b.number).join(", ")}`)}catch(error){log.warn(`Could not expire older TestFlight builds: ${error instanceof Error?error.message:String(error)}`)}return tag}export function resolveGitHubActionsUrl(remoteUrl,repository=process.env.GITHUB_REPOSITORY,serverUrl=process.env.GITHUB_SERVER_URL??"https://github.com"){const repo=repository?.trim()||remoteUrl?.trim().match(/github\.com[/:]([^/\s]+\/[^/\s]+?)(?:\.git)?$/)?.[1];return repo?`${serverUrl.replace(/\/$/,"")}/${repo}/actions`:"https://github.com/stacksjs/stacks/actions"}function readOriginRemote(){try{return execFileSync("git",["config","--get","remote.origin.url"],{encoding:"utf8"}).trim()}catch{return}}
1
+ import{execFileSync}from"node:child_process";import{existsSync,readFileSync,writeFileSync}from"node:fs";import{join}from"node:path";import{pathToFileURL}from"node:url";import process from"node:process";import{runAction}from"@stacksjs/actions";import{intro,italic,log,onUnknownSubcommand,outro}from"@stacksjs/cli";import{Action}from"@stacksjs/enums";import{ExitCode}from"@stacksjs/types";import{AppStoreConnect,appStoreConnectCredentials,buildsToExpire}from"../app-store-connect";import{bumpedVersion,iosVersionIn,nextBuildTag,withIosVersion}from"../release-ios";import{resultFailed}from"../result";const descriptions={release:"Release a new version of your libraries/packages",project:"Target a specific project",dryRun:"Run the release without actually releasing",bump:"Non-interactive bump: patch | minor | major | prepatch | preminor | premajor | prerelease | pre | release | build | calendar | x.y.z",verbose:"Enable verbose output"};export function release(buddy){buddy.command("release",descriptions.release).option("--dry-run",descriptions.dryRun,{default:!1}).option("-p, --project [project]",descriptions.project,{default:!1}).option("--bump <type>",descriptions.bump).option("--preid <identifier>","Prerelease channel, for example beta or rc").option("--verbose",descriptions.verbose,{default:!1}).action(async(options)=>{log.debug("Running `buddy release` ...",options);if(options.dryRun)log.warn("Dry run enabled. No changes will be made or committed.");const startTime=await intro("buddy release"),result=await runAction(Action.Release,options);if(resultFailed(result)){await log.error("Failed to release",result.error);process.exit(ExitCode.FatalError)}await outro(options.dryRun?"Dry run complete. Nothing was committed, tagged or pushed.":"Triggered CI/CD Release via GitHub Actions",{startTime,useSeconds:!0});if(!options.dryRun)log.info(`Follow along: ${italic(resolveGitHubActionsUrl(readOriginRemote()))}`)});buddy.command("release:ios","Ship the iOS app: regenerate its project for production, commit, tag and push").option("--bump <type>","build | patch | minor | major | x.y.z (default: a new build of the current marketing version)").option("--keep-builds <n>","TestFlight builds to keep besides the new one; older ones are expired (needs an App Store Connect API key)",{default:1}).option("--dry-run",descriptions.dryRun,{default:!1}).action(async(options)=>{const startTime=await intro("buddy release:ios");try{const tag=await releaseIos(options);await outro(options.dryRun?`Dry run complete: would release ${tag}`:`Released ${tag}`,{startTime,useSeconds:!0});if(!options.dryRun)log.info('A CI that builds tags (Xcode Cloud: Tag Changes, prefix "v") turns it into a TestFlight build now.')}catch(error){await log.error("Failed to release the iOS app",error);process.exit(ExitCode.FatalError)}});onUnknownSubcommand(buddy,"release")}function git(...args){return execFileSync("git",args,{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).trim()}async function releaseIos(options){const root=process.cwd(),configPath=join(root,"config/mobile.ts");if(!existsSync(configPath))throw Error("config/mobile.ts not found: run this in a Stacks app with a mobile config");const branch=git("rev-parse","--abbrev-ref","HEAD");if(branch!=="main")throw Error(`releases are cut from main; this is ${branch}`);if(git("status","--porcelain","--untracked-files=no"))throw Error("commit or stash your changes first, so the release is exactly what is on main");git("pull","--quiet","--rebase","origin","main");git("fetch","--quiet","--tags","origin");const source=readFileSync(configPath,"utf8"),current=iosVersionIn(source);if(!current)throw Error("config/mobile.ts declares no iOS `version`");const version=options.bump?bumpedVersion(current,options.bump):current,existingTags=git("tag","--list",`v${version}-build.*`).split(`
2
+ `).filter(Boolean);let tag=nextBuildTag(version,existingTags);const credentials=appStoreConnectCredentials();let store=null;if(credentials){const bundleId=(await import(pathToFileURL(configPath).href)).default.ios?.bundleId;if(!bundleId)throw Error("config/mobile.ts declares no ios.bundleId");const api=await AppStoreConnect.connect(credentials);store={api,appId:await api.appId(bundleId)};const latestRun=await api.latestXcodeCloudRun(store.appId);if(latestRun!==null)tag=nextBuildTag(version,existingTags,latestRun)}else log.warn("No App Store Connect API key (APP_STORE_CONNECT_KEY_ID, _ISSUER_ID, _PRIVATE_KEY_PATH): the tag counts releases, not the build number TestFlight will show, and older builds stay listed.");log.info(`Releasing ${tag}${version===current?"":` (version ${current} \u2192 ${version})`}`);const keep=Math.max(0,Number(options.keepBuilds??1)||0);if(options.dryRun){if(store){const retiring=buildsToExpire(await store.api.builds(store.appId),keep);log.info(retiring.length?`Would expire TestFlight builds ${retiring.map((b)=>b.number).join(", ")}`:"No TestFlight builds to expire")}return tag}const paths=["config/mobile.ts","storage/framework/mobile/ios"];if(version!==current){writeFileSync(configPath,withIosVersion(source,version));const pkgPath=join(root,"package.json");if(existsSync(pkgPath)){const pkg=readFileSync(pkgPath,"utf8");writeFileSync(pkgPath,pkg.replace(/("version"\s*:\s*)"[^"]*"/,`$1"${version}"`));paths.push("package.json")}}for(const key of["MOBILE_URL","IOS_APP_VERSION","IOS_BUILD_NUMBER"])delete process.env[key];const result=await runAction(Action.BuildIos,{});if(resultFailed(result))throw result.error??Error("the iOS build failed");git("add","--",...paths);if(git("diff","--cached","--name-only"))git("commit","--quiet","-m",`chore(release): ${tag}`);git("tag","-a",tag,"-m",tag);git("push","--quiet","--atomic","origin","main",tag);if(store)try{const retiring=buildsToExpire(await store.api.builds(store.appId),keep);for(const build of retiring)await store.api.expire(build.id);if(retiring.length)log.info(`Expired TestFlight builds ${retiring.map((b)=>b.number).join(", ")}`)}catch(error){log.warn(`Could not expire older TestFlight builds: ${error instanceof Error?error.message:String(error)}`)}return tag}export function resolveGitHubActionsUrl(remoteUrl,repository=process.env.GITHUB_REPOSITORY,serverUrl=process.env.GITHUB_SERVER_URL??"https://github.com"){const repo=repository?.trim()||remoteUrl?.trim().match(/github\.com[/:]([^/\s]+\/[^/\s]+?)(?:\.git)?$/)?.[1];return repo?`${serverUrl.replace(/\/$/,"")}/${repo}/actions`:"https://github.com/stacksjs/stacks/actions"}function readOriginRemote(){try{return execFileSync("git",["config","--get","remote.origin.url"],{encoding:"utf8"}).trim()}catch{return}}
@@ -1 +1 @@
1
- export async function withTimeout(work,ms){let timeoutId;const deadline=new Promise((_,reject)=>{timeoutId=setTimeout(()=>reject(Error("timeout")),ms)});try{return await Promise.race([work,deadline])}finally{if(timeoutId!==void 0)clearTimeout(timeoutId)}}const commandRegistry={about:{path:"./commands/about.js",exportName:"about"},add:{path:"./commands/add.js",exportName:"add"},"ai:access":{path:"./commands/ai-access.js",exportName:"aiAccess"},"ai:context":{path:"./commands/ai-context.js",exportName:"aiContext"},auth:{path:"./commands/auth.js",exportName:"auth"},build:{path:"./commands/build.js",exportName:"build"},cd:{path:"./commands/cd.js",exportName:"cd"},changelog:{path:"./commands/changelog.js",exportName:"changelog"},clean:{path:"./commands/clean.js",exportName:"clean"},cloud:{path:"./commands/cloud.js",exportName:"cloud"},commit:{path:"./commands/commit.js",exportName:"commit"},completion:{path:"./commands/completion.js",exportName:"completion"},"config:migrate":{path:"./commands/config-migrate.js",exportName:"configMigrate"},configure:{path:"./commands/configure.js",exportName:"configure"},create:{path:"./commands/create.js",exportName:"create"},new:{path:"./commands/create.js",exportName:"create"},deploy:{path:"./commands/deploy.js",exportName:"deploy"},"deploy:rollback":{path:"./commands/deploy.js",exportName:"deploy"},dev:{path:"./commands/dev.js",exportName:"dev"},"desktop:apple:doctor":{path:"./commands/desktop-apple.js",exportName:"desktopApple"},"desktop:apple:csr":{path:"./commands/desktop-apple.js",exportName:"desktopApple"},"desktop:apple:init":{path:"./commands/desktop-apple.js",exportName:"desktopApple"},"desktop:apple:package":{path:"./commands/desktop-apple.js",exportName:"desktopApple"},"desktop:apple:provision":{path:"./commands/desktop-apple.js",exportName:"desktopApple"},"desktop:apple:publish":{path:"./commands/desktop-apple.js",exportName:"desktopApple"},"desktop:probe":{path:"./commands/desktop-probe.js",exportName:"desktopProbe"},dns:{path:"./commands/dns.js",exportName:"dns"},"dns:pull":{path:"./commands/dns.js",exportName:"dns"},"dns:diff":{path:"./commands/dns.js",exportName:"dns"},"dns:sync":{path:"./commands/dns.js",exportName:"dns"},doctor:{path:"./commands/doctor.js",exportName:"doctor"},domains:{path:"./commands/domains.js",exportName:"domains"},email:{path:"./commands/email.js",exportName:"email"},env:{path:"./commands/env.js",exportName:"env"},"extension:init":{path:"./commands/extension.js",exportName:"extension"},"extension:build":{path:"./commands/extension.js",exportName:"extension"},"extension:package":{path:"./commands/extension.js",exportName:"extension"},"extension:chrome:publish":{path:"./commands/extension.js",exportName:"extension"},"extension:chrome:status":{path:"./commands/extension.js",exportName:"extension"},"extension:firefox:publish":{path:"./commands/extension.js",exportName:"extension"},"extension:safari:init":{path:"./commands/extension.js",exportName:"extension"},"extension:safari:provision":{path:"./commands/extension.js",exportName:"extension"},"extension:safari:app":{path:"./commands/extension.js",exportName:"extension"},"extension:safari:publish":{path:"./commands/extension.js",exportName:"extension"},"dashboard:install":{path:"./commands/features.js",exportName:"features"},"dashboard:uninstall":{path:"./commands/features.js",exportName:"features"},"commerce:install":{path:"./commands/features.js",exportName:"features"},"commerce:uninstall":{path:"./commands/features.js",exportName:"features"},"commerce:import":{path:"./commands/commerce-import.js",exportName:"commerceImport"},"cms:install":{path:"./commands/features.js",exportName:"features"},"cms:uninstall":{path:"./commands/features.js",exportName:"features"},"marketing:install":{path:"./commands/features.js",exportName:"features"},"marketing:uninstall":{path:"./commands/features.js",exportName:"features"},"monitoring:install":{path:"./commands/features.js",exportName:"features"},"monitoring:uninstall":{path:"./commands/features.js",exportName:"features"},"realtime:install":{path:"./commands/features.js",exportName:"features"},"realtime:uninstall":{path:"./commands/features.js",exportName:"features"},"queue:install":{path:"./commands/features.js",exportName:"features"},"queue:uninstall":{path:"./commands/features.js",exportName:"features"},"db:backup":{path:"./commands/db.js",exportName:"db"},"db:backups":{path:"./commands/db.js",exportName:"db"},"db:restore":{path:"./commands/db.js",exportName:"db"},"storage:backup":{path:"./commands/storage-backup.js",exportName:"storageBackup"},"storage:backups":{path:"./commands/storage-backup.js",exportName:"storageBackup"},"storage:restore":{path:"./commands/storage-backup.js",exportName:"storageBackup"},"feedback:invite":{path:"./commands/feedback.js",exportName:"feedback"},"feedback:tokens":{path:"./commands/feedback.js",exportName:"feedback"},"feedback:revoke":{path:"./commands/feedback.js",exportName:"feedback"},"socials:identities":{path:"./commands/socials.js",exportName:"socials"},"socials:authorize":{path:"./commands/socials.js",exportName:"socials"},fresh:{path:"./commands/fresh.js",exportName:"fresh"},generate:{path:"./commands/generate.js",exportName:"generate"},"gdpr:export":{path:"./commands/gdpr.js",exportName:"gdpr"},"gdpr:erase":{path:"./commands/gdpr.js",exportName:"gdpr"},"gdpr:prune":{path:"./commands/gdpr.js",exportName:"gdpr"},"gdpr:register":{path:"./commands/gdpr.js",exportName:"gdpr"},"gdpr:register:check":{path:"./commands/gdpr.js",exportName:"gdpr"},http:{path:"./commands/http.js",exportName:"http"},install:{path:"./commands/install.js",exportName:"install"},key:{path:"./commands/key.js",exportName:"key"},lint:{path:"./commands/lint.js",exportName:"lint"},format:{path:"./commands/lint.js",exportName:"lint"},"format:check":{path:"./commands/lint.js",exportName:"lint"},libs:{path:"./commands/libs.js",exportName:"libs"},libraries:{path:"./commands/libs.js",exportName:"libs"},list:{path:"./commands/list.js",exportName:"list"},mail:{path:"./commands/mail.js",exportName:"mailCommands"},"mail:preview":{path:"./commands/mail.js",exportName:"mailCommands"},maintenance:{path:"./commands/maintenance.js",exportName:"maintenance"},down:{path:"./commands/maintenance.js",exportName:"maintenance"},up:{path:"./commands/maintenance.js",exportName:"maintenance"},status:{path:"./commands/maintenance.js",exportName:"maintenance"},"coming-soon":{path:"./commands/maintenance.js",exportName:"maintenance"},"coming-soon:status":{path:"./commands/maintenance.js",exportName:"maintenance"},launch:{path:"./commands/maintenance.js",exportName:"maintenance"},make:{path:"./commands/make.js",exportName:"make"},"scaffold:crud":{path:"./commands/make.js",exportName:"make"},migrate:{path:"./commands/migrate.js",exportName:"migrate"},"migrate:fresh":{path:"./commands/migrate.js",exportName:"migrate"},"migrate:switch":{path:"./commands/migrate.js",exportName:"migrate"},"migrate:project":{path:"./commands/migrate-project.js",exportName:"migrateProject"},outdated:{path:"./commands/outdated.js",exportName:"outdated"},package:{path:"./commands/package.js",exportName:"packageCommands"},phone:{path:"./commands/phone.js",exportName:"phone"},ports:{path:"./commands/ports.js",exportName:"ports"},"server:flash":{path:"./commands/server.js",exportName:"server"},"server:first-boot":{path:"./commands/server.js",exportName:"server"},"server:doctor":{path:"./commands/server.js",exportName:"server"},"server:setup":{path:"./commands/server.js",exportName:"server"},"server:trust":{path:"./commands/server.js",exportName:"server"},"link:core":{path:"./commands/link.js",exportName:"link"},"comments:list":{path:"./commands/comments.js",exportName:"commentsCommands"},"comments:approve":{path:"./commands/comments.js",exportName:"commentsCommands"},"comments:reject":{path:"./commands/comments.js",exportName:"commentsCommands"},"comments:delete":{path:"./commands/comments.js",exportName:"commentsCommands"},"user:add":{path:"./commands/user.js",exportName:"user"},"user:list":{path:"./commands/user.js",exportName:"user"},"unlink:core":{path:"./commands/link.js",exportName:"link"},prepublish:{path:"./commands/prepublish.js",exportName:"prepublish"},projects:{path:"./commands/projects.js",exportName:"projects"},publish:{path:"./commands/publish.js",exportName:"publish"},"publish:model":{path:"./commands/publish.js",exportName:"publish"},"publish:controller":{path:"./commands/publish.js",exportName:"publish"},"publish:middleware":{path:"./commands/publish.js",exportName:"publish"},"publish:action":{path:"./commands/publish.js",exportName:"publish"},"publish:core":{path:"./commands/publish.js",exportName:"publish"},"core:status":{path:"./commands/publish.js",exportName:"publish"},queue:{path:"./commands/queue.js",exportName:"queue"},release:{path:"./commands/release.js",exportName:"release"},route:{path:"./commands/route.js",exportName:"route"},saas:{path:"./commands/saas.js",exportName:"saas"},"stripe:setup":{path:"./commands/saas.js",exportName:"saas"},schedule:{path:"./commands/schedule.js",exportName:"schedule"},search:{path:"./commands/search.js",exportName:"search"},"search-engine:update":{path:"./commands/search.js",exportName:"search"},"search-engine:settings":{path:"./commands/search.js",exportName:"search"},seed:{path:"./commands/seed.js",exportName:"seed"},"seed:roles":{path:"./commands/seed.js",exportName:"seed"},"roles:seed":{path:"./commands/seed.js",exportName:"seed"},preview:{path:"./commands/serve.js",exportName:"preview"},serve:{path:"./commands/serve.js",exportName:"serve"},"serve:api":{path:"./commands/serve.js",exportName:"serveApi"},setup:{path:"./commands/setup.js",exportName:"setup"},"setup:ai":{path:"./commands/setup.js",exportName:"setup"},"setup:ssl":{path:"./commands/setup.js",exportName:"setup"},"setup:oh-my-zsh":{path:"./commands/setup.js",exportName:"setup"},"ai:setup":{path:"./commands/setup.js",exportName:"setup"},share:{path:"./commands/share.js",exportName:"share"},"simulator:doctor":{path:"./commands/simulator.js",exportName:"simulator"},"simulator:open":{path:"./commands/simulator.js",exportName:"simulator"},stack:{path:"./commands/stacks.js",exportName:"stacks"},sms:{path:"./commands/sms.js",exportName:"sms"},telemetry:{path:"./commands/telemetry.js",exportName:"telemetryCommand"},test:{path:"./commands/test.js",exportName:"test"},tinker:{path:"./commands/tinker.js",exportName:"tinker"},types:{path:"./commands/types.js",exportName:"types"},undeploy:{path:"./commands/cloud.js",exportName:"cloud"},upgrade:{path:"./commands/upgrade.js",exportName:"upgrade"},version:{path:"./commands/version.js",exportName:"version"},"docs:buddy":{path:"./commands/docs.js",exportName:"docs"},"docs:buddy:check":{path:"./commands/docs.js",exportName:"docs"},"docs:artifacts":{path:"./commands/docs.js",exportName:"docs"},"docs:artifacts:check":{path:"./commands/docs.js",exportName:"docs"},"docs:links":{path:"./commands/docs.js",exportName:"docs"},"docs:links:check":{path:"./commands/docs.js",exportName:"docs"}},commandGroups={minimal:["version","help"],development:["dev","build","test","lint"],database:["migrate","seed","fresh"],scaffolding:["make","generate"],deployment:["deploy","release","cloud","server"],info:["about","doctor","list"]},loadedRegistrars=new WeakMap;function loaderKey(loader){return`${loader.path}#${loader.exportName}`}export function markLoaded(buddy,commandName){const loader=commandRegistry[commandName];if(!loader)return;let set=loadedRegistrars.get(buddy);if(!set){set=new Set;loadedRegistrars.set(buddy,set)}set.add(loaderKey(loader))}export async function loadCommand(commandName,buddy){const loader=commandRegistry[commandName];if(!loader)return!1;let set=loadedRegistrars.get(buddy);if(!set){set=new Set;loadedRegistrars.set(buddy,set)}const key=loaderKey(loader);if(set.has(key))return!0;set.add(key);try{const commandFunction=(await import(loader.path))[loader.exportName];if(typeof commandFunction==="function"){commandFunction(buddy);return!0}else return!1}catch{return!1}}export async function loadCommands(commandNames,buddy){const seen=new Set,unique=[];for(const name of commandNames){const loader=commandRegistry[name],key=loader?`${loader.path}#${loader.exportName}`:`name:${name}`;if(seen.has(key))continue;seen.add(key);unique.push(name)}await Promise.all(unique.map(async(name)=>{try{await withTimeout(loadCommand(name,buddy),5000)}catch{}}))}export async function loadCommandGroup(groupName,buddy){const commands=commandGroups[groupName];if(commands)await loadCommands(commands,buddy)}export async function loadAllCommands(buddy){const allCommands=Object.keys(commandRegistry);await loadCommands(allCommands,buddy)}export function getCommandNames(){return Object.keys(commandRegistry)}export function getCommandsToLoad(args){const requestedCommand=args[0],isVersionFlag=requestedCommand==="--version"||requestedCommand==="-v",isHelpFlag=requestedCommand==="--help"||requestedCommand==="-h",isHelpWord=requestedCommand==="help";if(isVersionFlag)return["version"];if(!requestedCommand||isHelpFlag||isHelpWord)return Object.keys(commandRegistry);const baseCommand=requestedCommand.split(":")[0];if(baseCommand==="list")return["list",...Object.keys(commandRegistry).filter((k)=>k!=="list")];if(commandRegistry[requestedCommand])return[requestedCommand];if(commandRegistry[baseCommand])return[baseCommand];return Object.keys(commandRegistry)}
1
+ export async function withTimeout(work,ms){let timeoutId;const deadline=new Promise((_,reject)=>{timeoutId=setTimeout(()=>reject(Error("timeout")),ms)});try{return await Promise.race([work,deadline])}finally{if(timeoutId!==void 0)clearTimeout(timeoutId)}}const commandRegistry={about:{path:"./commands/about.js",exportName:"about"},add:{path:"./commands/add.js",exportName:"add"},"ai:access":{path:"./commands/ai-access.js",exportName:"aiAccess"},"ai:context":{path:"./commands/ai-context.js",exportName:"aiContext"},auth:{path:"./commands/auth.js",exportName:"auth"},build:{path:"./commands/build.js",exportName:"build"},cd:{path:"./commands/cd.js",exportName:"cd"},changelog:{path:"./commands/changelog.js",exportName:"changelog"},clean:{path:"./commands/clean.js",exportName:"clean"},cloud:{path:"./commands/cloud.js",exportName:"cloud"},commit:{path:"./commands/commit.js",exportName:"commit"},completion:{path:"./commands/completion.js",exportName:"completion"},"config:migrate":{path:"./commands/config-migrate.js",exportName:"configMigrate"},configure:{path:"./commands/configure.js",exportName:"configure"},create:{path:"./commands/create.js",exportName:"create"},new:{path:"./commands/create.js",exportName:"create"},deploy:{path:"./commands/deploy.js",exportName:"deploy"},"deploy:rollback":{path:"./commands/deploy.js",exportName:"deploy"},dev:{path:"./commands/dev.js",exportName:"dev"},"desktop:apple:doctor":{path:"./commands/desktop-apple.js",exportName:"desktopApple"},"desktop:apple:csr":{path:"./commands/desktop-apple.js",exportName:"desktopApple"},"desktop:apple:init":{path:"./commands/desktop-apple.js",exportName:"desktopApple"},"desktop:apple:package":{path:"./commands/desktop-apple.js",exportName:"desktopApple"},"desktop:apple:provision":{path:"./commands/desktop-apple.js",exportName:"desktopApple"},"desktop:apple:publish":{path:"./commands/desktop-apple.js",exportName:"desktopApple"},"desktop:probe":{path:"./commands/desktop-probe.js",exportName:"desktopProbe"},dns:{path:"./commands/dns.js",exportName:"dns"},"dns:pull":{path:"./commands/dns.js",exportName:"dns"},"dns:diff":{path:"./commands/dns.js",exportName:"dns"},"dns:sync":{path:"./commands/dns.js",exportName:"dns"},doctor:{path:"./commands/doctor.js",exportName:"doctor"},domains:{path:"./commands/domains.js",exportName:"domains"},email:{path:"./commands/email.js",exportName:"email"},env:{path:"./commands/env.js",exportName:"env"},"extension:init":{path:"./commands/extension.js",exportName:"extension"},"extension:build":{path:"./commands/extension.js",exportName:"extension"},"extension:package":{path:"./commands/extension.js",exportName:"extension"},"extension:chrome:publish":{path:"./commands/extension.js",exportName:"extension"},"extension:chrome:status":{path:"./commands/extension.js",exportName:"extension"},"extension:firefox:publish":{path:"./commands/extension.js",exportName:"extension"},"extension:safari:init":{path:"./commands/extension.js",exportName:"extension"},"extension:safari:provision":{path:"./commands/extension.js",exportName:"extension"},"extension:safari:app":{path:"./commands/extension.js",exportName:"extension"},"extension:safari:publish":{path:"./commands/extension.js",exportName:"extension"},"dashboard:install":{path:"./commands/features.js",exportName:"features"},"dashboard:uninstall":{path:"./commands/features.js",exportName:"features"},"commerce:install":{path:"./commands/features.js",exportName:"features"},"commerce:uninstall":{path:"./commands/features.js",exportName:"features"},"commerce:import":{path:"./commands/commerce-import.js",exportName:"commerceImport"},"cms:install":{path:"./commands/features.js",exportName:"features"},"cms:uninstall":{path:"./commands/features.js",exportName:"features"},"marketing:install":{path:"./commands/features.js",exportName:"features"},"marketing:uninstall":{path:"./commands/features.js",exportName:"features"},"monitoring:install":{path:"./commands/features.js",exportName:"features"},"monitoring:uninstall":{path:"./commands/features.js",exportName:"features"},"realtime:install":{path:"./commands/features.js",exportName:"features"},"realtime:uninstall":{path:"./commands/features.js",exportName:"features"},"queue:install":{path:"./commands/features.js",exportName:"features"},"queue:uninstall":{path:"./commands/features.js",exportName:"features"},"db:backup":{path:"./commands/db.js",exportName:"db"},"db:backups":{path:"./commands/db.js",exportName:"db"},"db:restore":{path:"./commands/db.js",exportName:"db"},"storage:backup":{path:"./commands/storage-backup.js",exportName:"storageBackup"},"storage:backups":{path:"./commands/storage-backup.js",exportName:"storageBackup"},"storage:restore":{path:"./commands/storage-backup.js",exportName:"storageBackup"},"feedback:invite":{path:"./commands/feedback.js",exportName:"feedback"},"feedback:tokens":{path:"./commands/feedback.js",exportName:"feedback"},"feedback:revoke":{path:"./commands/feedback.js",exportName:"feedback"},"socials:identities":{path:"./commands/socials.js",exportName:"socials"},"socials:authorize":{path:"./commands/socials.js",exportName:"socials"},fresh:{path:"./commands/fresh.js",exportName:"fresh"},generate:{path:"./commands/generate.js",exportName:"generate"},"gdpr:export":{path:"./commands/gdpr.js",exportName:"gdpr"},"gdpr:erase":{path:"./commands/gdpr.js",exportName:"gdpr"},"gdpr:prune":{path:"./commands/gdpr.js",exportName:"gdpr"},"gdpr:register":{path:"./commands/gdpr.js",exportName:"gdpr"},"gdpr:register:check":{path:"./commands/gdpr.js",exportName:"gdpr"},http:{path:"./commands/http.js",exportName:"http"},install:{path:"./commands/install.js",exportName:"install"},key:{path:"./commands/key.js",exportName:"key"},lint:{path:"./commands/lint.js",exportName:"lint"},format:{path:"./commands/lint.js",exportName:"lint"},"format:check":{path:"./commands/lint.js",exportName:"lint"},libs:{path:"./commands/libs.js",exportName:"libs"},libraries:{path:"./commands/libs.js",exportName:"libs"},list:{path:"./commands/list.js",exportName:"list"},mail:{path:"./commands/mail.js",exportName:"mailCommands"},"mail:preview":{path:"./commands/mail.js",exportName:"mailCommands"},maintenance:{path:"./commands/maintenance.js",exportName:"maintenance"},down:{path:"./commands/maintenance.js",exportName:"maintenance"},up:{path:"./commands/maintenance.js",exportName:"maintenance"},status:{path:"./commands/maintenance.js",exportName:"maintenance"},"coming-soon":{path:"./commands/maintenance.js",exportName:"maintenance"},"coming-soon:status":{path:"./commands/maintenance.js",exportName:"maintenance"},launch:{path:"./commands/maintenance.js",exportName:"maintenance"},make:{path:"./commands/make.js",exportName:"make"},"scaffold:crud":{path:"./commands/make.js",exportName:"make"},migrate:{path:"./commands/migrate.js",exportName:"migrate"},"migrate:fresh":{path:"./commands/migrate.js",exportName:"migrate"},"migrate:switch":{path:"./commands/migrate.js",exportName:"migrate"},"migrate:project":{path:"./commands/migrate-project.js",exportName:"migrateProject"},outdated:{path:"./commands/outdated.js",exportName:"outdated"},package:{path:"./commands/package.js",exportName:"packageCommands"},phone:{path:"./commands/phone.js",exportName:"phone"},ports:{path:"./commands/ports.js",exportName:"ports"},"server:flash":{path:"./commands/server.js",exportName:"server"},"server:first-boot":{path:"./commands/server.js",exportName:"server"},"server:doctor":{path:"./commands/server.js",exportName:"server"},"server:setup":{path:"./commands/server.js",exportName:"server"},"server:trust":{path:"./commands/server.js",exportName:"server"},"link:core":{path:"./commands/link.js",exportName:"link"},"comments:list":{path:"./commands/comments.js",exportName:"commentsCommands"},"comments:approve":{path:"./commands/comments.js",exportName:"commentsCommands"},"comments:reject":{path:"./commands/comments.js",exportName:"commentsCommands"},"comments:delete":{path:"./commands/comments.js",exportName:"commentsCommands"},"user:add":{path:"./commands/user.js",exportName:"user"},"user:list":{path:"./commands/user.js",exportName:"user"},"unlink:core":{path:"./commands/link.js",exportName:"link"},prepublish:{path:"./commands/prepublish.js",exportName:"prepublish"},projects:{path:"./commands/projects.js",exportName:"projects"},publish:{path:"./commands/publish.js",exportName:"publish"},"publish:model":{path:"./commands/publish.js",exportName:"publish"},"publish:controller":{path:"./commands/publish.js",exportName:"publish"},"publish:middleware":{path:"./commands/publish.js",exportName:"publish"},"publish:action":{path:"./commands/publish.js",exportName:"publish"},"publish:core":{path:"./commands/publish.js",exportName:"publish"},"core:status":{path:"./commands/publish.js",exportName:"publish"},queue:{path:"./commands/queue.js",exportName:"queue"},release:{path:"./commands/release.js",exportName:"release"},route:{path:"./commands/route.js",exportName:"route"},saas:{path:"./commands/saas.js",exportName:"saas"},"stripe:setup":{path:"./commands/saas.js",exportName:"saas"},schedule:{path:"./commands/schedule.js",exportName:"schedule"},search:{path:"./commands/search.js",exportName:"search"},"search-engine:update":{path:"./commands/search.js",exportName:"search"},"search-engine:settings":{path:"./commands/search.js",exportName:"search"},seed:{path:"./commands/seed.js",exportName:"seed"},"seed:roles":{path:"./commands/seed.js",exportName:"seed"},"roles:seed":{path:"./commands/seed.js",exportName:"seed"},preview:{path:"./commands/serve.js",exportName:"preview"},serve:{path:"./commands/serve.js",exportName:"serve"},"serve:api":{path:"./commands/serve.js",exportName:"serveApi"},setup:{path:"./commands/setup.js",exportName:"setup"},"setup:ai":{path:"./commands/setup.js",exportName:"setup"},"setup:ssl":{path:"./commands/setup.js",exportName:"setup"},"setup:oh-my-zsh":{path:"./commands/setup.js",exportName:"setup"},"ai:setup":{path:"./commands/setup.js",exportName:"setup"},share:{path:"./commands/share.js",exportName:"share"},"simulator:doctor":{path:"./commands/simulator.js",exportName:"simulator"},"simulator:open":{path:"./commands/simulator.js",exportName:"simulator"},stack:{path:"./commands/stacks.js",exportName:"stacks"},sms:{path:"./commands/sms.js",exportName:"sms"},telemetry:{path:"./commands/telemetry.js",exportName:"telemetryCommand"},test:{path:"./commands/test.js",exportName:"test"},tinker:{path:"./commands/tinker.js",exportName:"tinker"},types:{path:"./commands/types.js",exportName:"types"},undeploy:{path:"./commands/cloud.js",exportName:"cloud"},upgrade:{path:"./commands/upgrade.js",exportName:"upgrade"},version:{path:"./commands/version.js",exportName:"version"},"docs:buddy":{path:"./commands/docs.js",exportName:"docs"},"docs:native-skills":{path:"./commands/docs.js",exportName:"docs"},"docs:native-skills:check":{path:"./commands/docs.js",exportName:"docs"},"docs:buddy:check":{path:"./commands/docs.js",exportName:"docs"},"docs:artifacts":{path:"./commands/docs.js",exportName:"docs"},"docs:artifacts:check":{path:"./commands/docs.js",exportName:"docs"},"docs:links":{path:"./commands/docs.js",exportName:"docs"},"docs:links:check":{path:"./commands/docs.js",exportName:"docs"}},commandGroups={minimal:["version","help"],development:["dev","build","test","lint"],database:["migrate","seed","fresh"],scaffolding:["make","generate"],deployment:["deploy","release","cloud","server"],info:["about","doctor","list"]},loadedRegistrars=new WeakMap;function loaderKey(loader){return`${loader.path}#${loader.exportName}`}export function markLoaded(buddy,commandName){const loader=commandRegistry[commandName];if(!loader)return;let set=loadedRegistrars.get(buddy);if(!set){set=new Set;loadedRegistrars.set(buddy,set)}set.add(loaderKey(loader))}export async function loadCommand(commandName,buddy){const loader=commandRegistry[commandName];if(!loader)return!1;let set=loadedRegistrars.get(buddy);if(!set){set=new Set;loadedRegistrars.set(buddy,set)}const key=loaderKey(loader);if(set.has(key))return!0;set.add(key);try{const commandFunction=(await import(loader.path))[loader.exportName];if(typeof commandFunction==="function"){commandFunction(buddy);return!0}else return!1}catch{return!1}}export async function loadCommands(commandNames,buddy){const seen=new Set,unique=[];for(const name of commandNames){const loader=commandRegistry[name],key=loader?`${loader.path}#${loader.exportName}`:`name:${name}`;if(seen.has(key))continue;seen.add(key);unique.push(name)}await Promise.all(unique.map(async(name)=>{try{await withTimeout(loadCommand(name,buddy),5000)}catch{}}))}export async function loadCommandGroup(groupName,buddy){const commands=commandGroups[groupName];if(commands)await loadCommands(commands,buddy)}export async function loadAllCommands(buddy){const allCommands=Object.keys(commandRegistry);await loadCommands(allCommands,buddy)}export function getCommandNames(){return Object.keys(commandRegistry)}export function getCommandsToLoad(args){const requestedCommand=args[0],isVersionFlag=requestedCommand==="--version"||requestedCommand==="-v",isHelpFlag=requestedCommand==="--help"||requestedCommand==="-h",isHelpWord=requestedCommand==="help";if(isVersionFlag)return["version"];if(!requestedCommand||isHelpFlag||isHelpWord)return Object.keys(commandRegistry);const baseCommand=requestedCommand.split(":")[0];if(baseCommand==="list")return["list",...Object.keys(commandRegistry).filter((k)=>k!=="list")];if(commandRegistry[requestedCommand])return[requestedCommand];if(commandRegistry[baseCommand])return[baseCommand];return Object.keys(commandRegistry)}
@@ -5,4 +5,4 @@ export declare function withIosVersion(source: string, version: string): string;
5
5
  /** The version a bump leads to, or the one given outright. */
6
6
  export declare function bumpedVersion(current: string, bump: string): string;
7
7
  /** The next build's tag for `version`, after the tags that already exist. */
8
- export declare function nextBuildTag(version: string, tags: string[]): string;
8
+ export declare function nextBuildTag(version: string, tags: string[], latestRun?: number): string;
@@ -1 +1 @@
1
- const SEMVER=/^\d+\.\d+\.\d+$/;function iosBlock(source){const start=source.search(/\bios\s*:\s*\{/);if(start===-1)return null;const after=source.slice(start+1).search(/\n\s*(?:android|desktop|watch|web)\s*:\s*\{/);return{start,end:after===-1?source.length:start+1+after}}const VERSION_ENTRY=/(\bversion\s*:\s*(?:[^,\n]*?\?\?\s*)?)(['"])(\d+\.\d+\.\d+)\2/;export function iosVersionIn(source){const block=iosBlock(source);if(!block)return null;return VERSION_ENTRY.exec(source.slice(block.start,block.end))?.[3]??null}export function withIosVersion(source,version){const block=iosBlock(source);if(!block||!VERSION_ENTRY.test(source.slice(block.start,block.end)))throw Error("config/mobile.ts declares no iOS `version`");const ios=source.slice(block.start,block.end).replace(VERSION_ENTRY,(_,lead,quote)=>`${lead}${quote}${version}${quote}`);return source.slice(0,block.start)+ios+source.slice(block.end)}export function bumpedVersion(current,bump){if(SEMVER.test(bump))return bump;const[major=0,minor=0,patch=0]=current.split(".").map(Number);if(bump==="major")return`${major+1}.0.0`;if(bump==="minor")return`${major}.${minor+1}.0`;if(bump==="patch")return`${major}.${minor}.${patch+1}`;throw Error(`"${bump}" is not patch, minor, major or a version like 1.2.0`)}export function nextBuildTag(version,tags){const prefix=`v${version}-build.`,builds=tags.filter((tag)=>tag.startsWith(prefix)).map((tag)=>Number(tag.slice(prefix.length))).filter((n)=>Number.isInteger(n)&&n>0);return`${prefix}${Math.max(0,...builds)+1}`}
1
+ import{incrementVersion,nextBuildNumber,SemVer}from"@stacksjs/bumpx";function marketingVersion(version){const parsed=new SemVer(version);if(parsed.prerelease.length||parsed.build.length||parsed.toString()!==version)throw Error("An iOS marketing version must be a stable version such as 1.0.0");return parsed.toString()}function iosBlock(source){const start=source.search(/\bios\s*:\s*\{/);if(start===-1)return null;const after=source.slice(start+1).search(/\n\s*(?:android|desktop|watch|web)\s*:\s*\{/);return{start,end:after===-1?source.length:start+1+after}}const VERSION_ENTRY=/(\bversion\s*:\s*(?:[^,\n]*?\?\?\s*)?)(['"])(\d+\.\d+\.\d+)\2/;export function iosVersionIn(source){const block=iosBlock(source);if(!block)return null;return VERSION_ENTRY.exec(source.slice(block.start,block.end))?.[3]??null}export function withIosVersion(source,version){marketingVersion(version);const block=iosBlock(source);if(!block||!VERSION_ENTRY.test(source.slice(block.start,block.end)))throw Error("config/mobile.ts declares no iOS `version`");const ios=source.slice(block.start,block.end).replace(VERSION_ENTRY,(_,lead,quote)=>`${lead}${quote}${version}${quote}`);return source.slice(0,block.start)+ios+source.slice(block.end)}export function bumpedVersion(current,bump){marketingVersion(current);if(bump==="build")return current;if(["patch","minor","major"].includes(bump))return marketingVersion(incrementVersion(current,bump));return marketingVersion(bump)}export function nextBuildTag(version,tags,latestRun=0){marketingVersion(version);const prefix=`v${version}-build.`,builds=tags.filter((tag)=>tag.startsWith(prefix)).map((tag)=>tag.slice(prefix.length)).filter((number)=>/^[1-9]\d*$/.test(number)).map(Number).filter(Number.isSafeInteger);return`${prefix}${nextBuildNumber(latestRun,builds)}`}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/buddy",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.75.108",
5
+ "version": "0.75.110",
6
6
  "description": "Meet Buddy. The Stacks runtime.",
7
7
  "author": "Chris Breuer",
8
8
  "contributors": [
@@ -95,68 +95,69 @@
95
95
  "prepublishOnly": "bun run build"
96
96
  },
97
97
  "dependencies": {
98
- "@stacksjs/actions": "^0.75.108",
99
- "@stacksjs/ai": "^0.75.108",
100
- "@stacksjs/alias": "^0.75.108",
101
- "@stacksjs/analytics": "^0.75.108",
102
- "@stacksjs/api": "^0.75.108",
103
- "@stacksjs/arrays": "^0.75.108",
104
- "@stacksjs/auth": "^0.75.108",
105
- "@stacksjs/browser-extension": "^0.75.108",
106
- "@stacksjs/build": "^0.75.108",
107
- "@stacksjs/cache": "^0.75.108",
108
- "@stacksjs/chat": "^0.75.108",
98
+ "@stacksjs/bumpx": "^0.2.20",
99
+ "@stacksjs/actions": "^0.75.110",
100
+ "@stacksjs/ai": "^0.75.110",
101
+ "@stacksjs/alias": "^0.75.110",
102
+ "@stacksjs/analytics": "^0.75.110",
103
+ "@stacksjs/api": "^0.75.110",
104
+ "@stacksjs/arrays": "^0.75.110",
105
+ "@stacksjs/auth": "^0.75.110",
106
+ "@stacksjs/browser-extension": "^0.75.110",
107
+ "@stacksjs/build": "^0.75.110",
108
+ "@stacksjs/cache": "^0.75.110",
109
+ "@stacksjs/chat": "^0.75.110",
109
110
  "@stacksjs/clapp": "^0.2.16",
110
- "@stacksjs/cli": "^0.75.108",
111
- "@stacksjs/cloud": "^0.75.108",
112
- "@stacksjs/cms": "^0.75.108",
113
- "@stacksjs/collections": "^0.75.108",
114
- "@stacksjs/commerce": "^0.75.108",
115
- "@stacksjs/config": "^0.75.108",
116
- "@stacksjs/database": "^0.75.108",
117
- "@stacksjs/desktop-build": "^0.75.108",
118
- "@stacksjs/dns": "^0.75.108",
111
+ "@stacksjs/cli": "^0.75.110",
112
+ "@stacksjs/cloud": "^0.75.110",
113
+ "@stacksjs/cms": "^0.75.110",
114
+ "@stacksjs/collections": "^0.75.110",
115
+ "@stacksjs/commerce": "^0.75.110",
116
+ "@stacksjs/config": "^0.75.110",
117
+ "@stacksjs/database": "^0.75.110",
118
+ "@stacksjs/desktop-build": "^0.75.110",
119
+ "@stacksjs/dns": "^0.75.110",
119
120
  "@stacksjs/dnsx": "^0.2.3",
120
- "@stacksjs/email": "^0.75.108",
121
- "@stacksjs/enums": "^0.75.108",
122
- "@stacksjs/env": "^0.75.108",
123
- "@stacksjs/error-handling": "^0.75.108",
124
- "@stacksjs/events": "^0.75.108",
125
- "@stacksjs/features": "^0.75.108",
126
- "@stacksjs/git": "^0.75.108",
121
+ "@stacksjs/email": "^0.75.110",
122
+ "@stacksjs/enums": "^0.75.110",
123
+ "@stacksjs/env": "^0.75.110",
124
+ "@stacksjs/error-handling": "^0.75.110",
125
+ "@stacksjs/events": "^0.75.110",
126
+ "@stacksjs/features": "^0.75.110",
127
+ "@stacksjs/git": "^0.75.110",
127
128
  "@stacksjs/gitit": "^0.2.5",
128
- "@stacksjs/health": "^0.75.108",
129
+ "@stacksjs/health": "^0.75.110",
129
130
  "@stacksjs/httx": "^0.1.10",
130
- "@stacksjs/image": "^0.75.108",
131
- "@stacksjs/lint": "^0.75.108",
132
- "@stacksjs/logging": "^0.75.108",
133
- "@stacksjs/notifications": "^0.75.108",
134
- "@stacksjs/objects": "^0.75.108",
135
- "@stacksjs/orm": "^0.75.108",
136
- "@stacksjs/path": "^0.75.108",
137
- "@stacksjs/payments": "^0.75.108",
138
- "@stacksjs/realtime": "^0.75.108",
139
- "@stacksjs/router": "^0.75.108",
131
+ "@stacksjs/image": "^0.75.110",
132
+ "@stacksjs/lint": "^0.75.110",
133
+ "@stacksjs/logging": "^0.75.110",
134
+ "@stacksjs/notifications": "^0.75.110",
135
+ "@stacksjs/objects": "^0.75.110",
136
+ "@stacksjs/orm": "^0.75.110",
137
+ "@stacksjs/path": "^0.75.110",
138
+ "@stacksjs/payments": "^0.75.110",
139
+ "@stacksjs/realtime": "^0.75.110",
140
+ "@stacksjs/router": "^0.75.110",
140
141
  "@stacksjs/rpx": "^0.11.54",
141
- "@stacksjs/scheduler": "^0.75.108",
142
- "@stacksjs/search-engine": "^0.75.108",
143
- "@stacksjs/security": "^0.75.108",
144
- "@stacksjs/server": "^0.75.108",
145
- "@stacksjs/sites": "^0.75.108",
146
- "@stacksjs/skills": "^0.75.108",
147
- "@stacksjs/socials": "^0.75.108",
148
- "@stacksjs/storage": "^0.75.108",
149
- "@stacksjs/strings": "^0.75.108",
142
+ "@stacksjs/scheduler": "^0.75.110",
143
+ "@stacksjs/search-engine": "^0.75.110",
144
+ "@stacksjs/security": "^0.75.110",
145
+ "@stacksjs/server": "^0.75.110",
146
+ "@stacksjs/sites": "^0.75.110",
147
+ "@stacksjs/skills": "^0.75.110",
148
+ "@stacksjs/socials": "^0.75.110",
149
+ "@stacksjs/storage": "^0.75.110",
150
+ "@stacksjs/strings": "^0.75.110",
150
151
  "@stacksjs/stx": "^0.2.422",
151
- "@stacksjs/testing": "^0.75.108",
152
- "@stacksjs/tinker": "^0.75.108",
152
+ "@stacksjs/testing": "^0.75.110",
153
+ "@stacksjs/tinker": "^0.75.110",
153
154
  "@stacksjs/tlsx": "^0.13.19",
154
155
  "@stacksjs/ts-cloud": "^0.16.47",
155
- "@stacksjs/tunnel": "^0.75.108",
156
- "@stacksjs/types": "^0.75.108",
157
- "@stacksjs/ui": "^0.75.108",
158
- "@stacksjs/utils": "^0.75.108",
159
- "@stacksjs/validation": "^0.75.108",
156
+ "@stacksjs/tunnel": "^0.75.110",
157
+ "@stacksjs/types": "^0.75.110",
158
+ "@stacksjs/ui": "^0.75.110",
159
+ "@stacksjs/utils": "^0.75.110",
160
+ "@stacksjs/validation": "^0.75.110",
160
161
  "ajv": "^8.20.0",
161
162
  "ajv-formats": "^3.0.1",
162
163
  "bun-plugin-stx": "^0.2.422",