@stacksjs/buddy 0.74.26 → 0.74.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- import{existsSync}from"node:fs";import{join}from"node:path";import process from"node:process";import{installRequestContext,parseCookieHeader}from"@stacksjs/config";import{log}from"@stacksjs/logging";import{siteConfigPath}from"@stacksjs/path";import{ExitCode}from"@stacksjs/types";import{resolveStxSource}from"./stx-source";function productionRequestSnapshot(){const{__stxServeContext:snapshot,__stxServeCookies:legacyCookies,__stxServeSearch:legacySearch,__stxServeSite:site}=globalThis;if(!snapshot&&!legacyCookies&&legacySearch===void 0)return;return{...snapshot,cookies:snapshot?.cookies??legacyCookies??{},url:snapshot?.url||snapshot?.search||legacySearch||"",search:snapshot?.search??legacySearch??"",site:snapshot?.site??site??null}}installRequestContext(productionRequestSnapshot);function parseCookies(req){return parseCookieHeader(req.headers.get("cookie"))}export function resolveUserPartialsPath(cwd=process.cwd(),configuredDir){if(configuredDir){const configured=[join(cwd,"resources",configuredDir),join(cwd,configuredDir)].find((candidate)=>existsSync(candidate));if(configured)return configured}const existing=["resources/partials","resources/views/partials","partials","resources/components"].filter((candidate)=>existsSync(join(cwd,candidate)));if(existing.length===0)return;const populated=existing.find((candidate)=>containsTemplates(join(cwd,candidate)));return join(cwd,populated??existing[0])}function containsTemplates(dir){try{return[...new Bun.Glob("**/*.stx").scanSync({cwd:dir,onlyFiles:!0})].length>0}catch{return!1}}export async function loadStxPartialsDir(cwd=process.cwd()){const configPath=join(cwd,"config/stx.ts");if(!existsSync(configPath))return;try{const dir=(await import(configPath)).default?.partialsDir;return typeof dir==="string"&&dir.length>0?dir:void 0}catch{return}}function resolveCsrfMiddlewarePath(){const rel="app/Middleware/Csrf.ts",vendored=join(process.cwd(),"storage/framework/defaults",rel);if(existsSync(vendored))return vendored;try{const pkgJson=Bun.resolveSync("@stacksjs/defaults/package.json",process.cwd());return`${pkgJson.slice(0,pkgJson.lastIndexOf("/"))}/${rel}`}catch{return vendored}}export async function startProductionServer(options){if(options?.port)process.env.PORT=String(options.port);process.env.APP_ENV=process.env.APP_ENV||"production";const port=Number(process.env.PORT)||3000,{config,overridesReady,resolveViewPatterns}=await import("@stacksjs/config");await overridesReady;const{applyViewSecurityHeaders,describeApiProxyRules,describeRedirectRules,injectGlobalAutoImports,resolveApiBase,resolveApiProxyRules,resolveEmbeddableRules,resolveRedirectRules}=await import("@stacksjs/server"),{resolveDefaultsResources}=await import("@stacksjs/actions/dev/defaults-resources"),{stxPageAuthMiddleware}=await import("@stacksjs/auth");await injectGlobalAutoImports();let stxServe;const serveSource=resolveStxSource({value:process.env.BUN_PLUGIN_STX_SRC});if(serveSource.kind==="missing")await log.exit(`BUN_PLUGIN_STX_SRC points at ${serveSource.path}, which does not exist. Unset it to use the installed bun-plugin-stx.`,ExitCode.FatalError);if(serveSource.kind==="override"){({serve:stxServe}=await import(serveSource.path));log.warn(`Serving views through ${serveSource.path} instead of the installed bun-plugin-stx.`)}else({serve:stxServe}=await import("bun-plugin-stx/serve"));log.debug(`stx serve implementation: ${serveSource.kind==="override"?serveSource.path:"bun-plugin-stx/serve"}`);const stxModule=await resolveVendoredStxModule(),{site:siteConfig,i18n:i18nConfig}=await loadStxSiteConfig(),userViewsPath="resources/views",defaultsResources=resolveDefaultsResources(),defaultViewsPath=join(defaultsResources,"views"),userLayoutsPath=existsSync("resources/views/layouts")?"resources/views/layouts":"resources/layouts",userComponentsPath=existsSync("resources/views/components")?"resources/views/components":"resources/components",userPartialsPath=resolveUserPartialsPath(process.cwd(),await loadStxPartialsDir()),apiBase=resolveApiBase(config.ports?.api),viewPatterns=resolveViewPatterns(userViewsPath,defaultViewsPath,config?.ui?.defaultViews);for(const name of viewPatterns.missing)log.warn(`ui.defaultViews lists "${name}", which does not exist under ${defaultViewsPath} - ignoring.`);const apiProxyRules=resolveApiProxyRules(config.server?.proxy);if(apiProxyRules.paths.length>0||apiProxyRules.prefixes.length>1)log.info(`API proxy: ${describeApiProxyRules(apiProxyRules)}`);const redirectRules=resolveRedirectRules(config.server?.redirects);if(redirectRules.size>0)log.info(`Redirects: ${describeRedirectRules(redirectRules)}`);const embeddableRules=resolveEmbeddableRules(config.server?.security?.embeddable);if(embeddableRules.paths.length>0||embeddableRules.prefixes.length>0)log.info(`Frameable by other origins: ${[...embeddableRules.paths,...embeddableRules.prefixes].join(" ")}`);log.info(`Starting production server on port ${port}...`);await stxServe({patterns:viewPatterns.patterns,port,autoIncrementPort:!1,reusePort:["production","staging","development"].includes((process.env.APP_ENV||"").toLowerCase()),componentsDir:userComponentsPath,fallbackComponentsDir:join(defaultsResources,"components"),layoutsDir:userLayoutsPath,...userPartialsPath&&{partialsDir:userPartialsPath},fallbackLayoutsDir:join(defaultsResources,"layouts"),fallbackPartialsDir:defaultViewsPath,quiet:options?.verbose!==!0,...stxModule&&{stxModule},...i18nConfig&&{i18n:i18nConfig},...siteConfig?.url&&{site:siteConfig},middleware:stxPageAuthMiddleware(),onRequest:async(req)=>{const{maintenanceGate,isApiBoundRequest:isApiBound,proxyToBackend,resolveRedirect}=await import("@stacksjs/server"),gated=await maintenanceGate(req);if(gated)return gated;const url=new URL(req.url),redirected=resolveRedirect(url,redirectRules);if(redirected)return redirected;if(isApiBound(req,url.pathname,apiProxyRules)){if(!apiBase){log.error(`No API target configured for ${url.pathname}. This app shares its host with other deployments, so there is no safe default port to guess - refusing to proxy. Set PORT_API (or API_URL) for this site, and deploy an \`api\` site on its own port.`);return new Response("Bad Gateway",{status:502})}try{return await proxyToBackend(req,apiBase)}catch(error){log.error(`API proxy to ${apiBase} failed: ${error.message}`);return new Response("Bad Gateway",{status:502})}}if(existsSync(join(process.cwd(),"resources/views/blog.stx"))){const{renderBlogFeed}=await import("@stacksjs/actions/blog"),feed=await renderBlogFeed(req);if(feed)return feed}globalThis.__stxServeSearch=url.search;globalThis.__stxServeCookies=parseCookies(req);if(config.analytics?.capturePageviews)import("@stacksjs/analytics").then(({recordPageview})=>recordPageview(req)).catch(()=>{});if(config.sites?.enabled){const sites=await import("@stacksjs/sites"),resolved=await sites.resolveSiteByHost(sites.requestHost(req.headers,sites.sitesOptions()));sites.setCurrentSite(resolved);globalThis.__stxServeSite=sites.toSiteSnapshot(resolved)}else globalThis.__stxServeSite=null;return},onResponse:async(req,response)=>{const secured=applyViewSecurityHeaders(req,response,embeddableRules),method=req.method.toUpperCase();if(method!=="GET"&&method!=="HEAD")return secured;const baseline=secured??response;let current=baseline;if(current.status===404&&config.sites?.enabled)try{const{cmsNotFoundFallback}=await import("@stacksjs/cms"),cmsResponse=await cmsNotFoundFallback(req);if(cmsResponse)current=cmsResponse}catch(error){log.debug(`CMS fallback skipped: ${error.message}`)}try{const{seedCsrfCookieIfMissing}=await import(resolveCsrfMiddlewarePath());return await seedCsrfCookieIfMissing(req,current)??(current===baseline?secured:current)}catch(error){log.debug(`CSRF cookie seeding skipped: ${error.message}`);return current===baseline?secured:current}}});log.success(`Production server listening on http://0.0.0.0:${port}`)}async function resolveVendoredStxModule(){const source=resolveStxSource({value:process.env.STACKS_STX_SRC});if(source.kind==="missing")await log.exit(`STACKS_STX_SRC points at ${source.path}, which does not exist. Unset it to use the installed @stacksjs/stx.`,ExitCode.FatalError);if(source.kind==="override"){log.warn(`Rendering through ${source.path} instead of the installed @stacksjs/stx.`);return await import(source.path)}try{return await import("@stacksjs/stx")}catch{}return}function fallbackI18nFromSite(site){const locales=site.i18n.locales,defaultLocale=site.i18n.defaultLocale??locales[0];return{locales,defaultLocale,labels:site.i18n.labels??Object.fromEntries(locales.map((c)=>[c,c.toUpperCase()])),translations:{},pickerSelector:site.i18n.pickerSelector??"#lang-picker"}}async function resolveSiteI18n(site){try{const resolved=await resolveVendoredStxModule();if(typeof resolved?.resolveI18n==="function"){const i18n=resolved.resolveI18n(site,process.cwd());if(i18n)return i18n}}catch{}return fallbackI18nFromSite(site)}async function loadStxSiteConfig(){const sitePath=siteConfigPath();if(!existsSync(sitePath))return{};try{const mod=await import(sitePath),site=mod.default??mod.site??mod.config;if(!site)return{};if(!site.i18n)return{site};const i18n=await resolveSiteI18n(site);return{site,i18n}}catch{}return{}}
1
+ import{existsSync}from"node:fs";import{join}from"node:path";import process from"node:process";import{installRequestContext,parseCookieHeader}from"@stacksjs/config";import{log}from"@stacksjs/logging";import{siteConfigPath}from"@stacksjs/path";import{ExitCode}from"@stacksjs/types";import{resolveStxSource}from"./stx-source";function productionRequestSnapshot(){const{__stxServeContext:snapshot,__stxServeCookies:legacyCookies,__stxServeSearch:legacySearch,__stxServeSite:site}=globalThis;if(!snapshot&&!legacyCookies&&legacySearch===void 0)return;return{...snapshot,cookies:snapshot?.cookies??legacyCookies??{},url:snapshot?.url||snapshot?.search||legacySearch||"",search:snapshot?.search??legacySearch??"",site:snapshot?.site??site??null}}installRequestContext(productionRequestSnapshot);function parseCookies(req){return parseCookieHeader(req.headers.get("cookie"))}export function resolveUserPartialsPath(cwd=process.cwd(),configuredDir){if(configuredDir){const configured=[join(cwd,"resources",configuredDir),join(cwd,configuredDir)].find((candidate)=>existsSync(candidate));if(configured)return configured}const existing=["resources/partials","resources/views/partials","partials","resources/components"].filter((candidate)=>existsSync(join(cwd,candidate)));if(existing.length===0)return;const populated=existing.find((candidate)=>containsTemplates(join(cwd,candidate)));return join(cwd,populated??existing[0])}function containsTemplates(dir){try{return[...new Bun.Glob("**/*.stx").scanSync({cwd:dir,onlyFiles:!0})].length>0}catch{return!1}}export async function loadStxPartialsDir(cwd=process.cwd()){const configPath=join(cwd,"config/stx.ts");if(!existsSync(configPath))return;try{const dir=(await import(configPath)).default?.partialsDir;return typeof dir==="string"&&dir.length>0?dir:void 0}catch{return}}function resolveCsrfMiddlewarePath(){const rel="app/Middleware/Csrf.ts",vendored=join(process.cwd(),"storage/framework/defaults",rel);if(existsSync(vendored))return vendored;try{const pkgJson=Bun.resolveSync("@stacksjs/defaults/package.json",process.cwd());return`${pkgJson.slice(0,pkgJson.lastIndexOf("/"))}/${rel}`}catch{return vendored}}export async function startProductionServer(options){if(options?.port)process.env.PORT=String(options.port);process.env.APP_ENV=process.env.APP_ENV||"production";const port=Number(process.env.PORT)||3000,{config,overridesReady,resolveViewPatterns}=await import("@stacksjs/config");await overridesReady;const{applyViewSecurityHeaders,describeApiProxyRules,describeRedirectRules,injectGlobalAutoImports,resolveApiBase,resolveApiProxyRules,resolveEmbeddableRules,resolveRedirectRules}=await import("@stacksjs/server"),{resolveDefaultsResources}=await import("@stacksjs/actions/dev/defaults-resources"),{stxPageAuthMiddleware}=await import("@stacksjs/auth"),{enhanceRequest,loadMiddlewareHandlers}=await import("@stacksjs/router"),pageMiddleware=await loadMiddlewareHandlers();await injectGlobalAutoImports();let stxServe;const serveSource=resolveStxSource({value:process.env.BUN_PLUGIN_STX_SRC});if(serveSource.kind==="missing")await log.exit(`BUN_PLUGIN_STX_SRC points at ${serveSource.path}, which does not exist. Unset it to use the installed bun-plugin-stx.`,ExitCode.FatalError);if(serveSource.kind==="override"){({serve:stxServe}=await import(serveSource.path));log.warn(`Serving views through ${serveSource.path} instead of the installed bun-plugin-stx.`)}else({serve:stxServe}=await import("bun-plugin-stx/serve"));log.debug(`stx serve implementation: ${serveSource.kind==="override"?serveSource.path:"bun-plugin-stx/serve"}`);const stxModule=await resolveVendoredStxModule(),{site:siteConfig,i18n:i18nConfig}=await loadStxSiteConfig(),userViewsPath="resources/views",defaultsResources=resolveDefaultsResources(),defaultViewsPath=join(defaultsResources,"views"),userLayoutsPath=existsSync("resources/views/layouts")?"resources/views/layouts":"resources/layouts",userComponentsPath=existsSync("resources/views/components")?"resources/views/components":"resources/components",userPartialsPath=resolveUserPartialsPath(process.cwd(),await loadStxPartialsDir()),apiBase=resolveApiBase(config.ports?.api),viewPatterns=resolveViewPatterns(userViewsPath,defaultViewsPath,config?.ui?.defaultViews);for(const name of viewPatterns.missing)log.warn(`ui.defaultViews lists "${name}", which does not exist under ${defaultViewsPath} - ignoring.`);const apiProxyRules=resolveApiProxyRules(config.server?.proxy);if(apiProxyRules.paths.length>0||apiProxyRules.prefixes.length>1)log.info(`API proxy: ${describeApiProxyRules(apiProxyRules)}`);const redirectRules=resolveRedirectRules(config.server?.redirects);if(redirectRules.size>0)log.info(`Redirects: ${describeRedirectRules(redirectRules)}`);const embeddableRules=resolveEmbeddableRules(config.server?.security?.embeddable);if(embeddableRules.paths.length>0||embeddableRules.prefixes.length>0)log.info(`Frameable by other origins: ${[...embeddableRules.paths,...embeddableRules.prefixes].join(" ")}`);log.info(`Starting production server on port ${port}...`);await stxServe({patterns:viewPatterns.patterns,port,autoIncrementPort:!1,reusePort:["production","staging","development"].includes((process.env.APP_ENV||"").toLowerCase()),componentsDir:userComponentsPath,fallbackComponentsDir:join(defaultsResources,"components"),layoutsDir:userLayoutsPath,...userPartialsPath&&{partialsDir:userPartialsPath},fallbackLayoutsDir:join(defaultsResources,"layouts"),fallbackPartialsDir:defaultViewsPath,quiet:options?.verbose!==!0,...stxModule&&{stxModule},...i18nConfig&&{i18n:i18nConfig},...siteConfig?.url&&{site:siteConfig},middleware:{...pageMiddleware,...stxPageAuthMiddleware()},prepareMiddlewareRequest:(request)=>enhanceRequest(request),onRequest:async(req)=>{const{maintenanceGate,isApiBoundRequest:isApiBound,proxyToBackend,resolveRedirect}=await import("@stacksjs/server"),gated=await maintenanceGate(req);if(gated)return gated;const url=new URL(req.url),redirected=resolveRedirect(url,redirectRules);if(redirected)return redirected;if(isApiBound(req,url.pathname,apiProxyRules)){if(!apiBase){log.error(`No API target configured for ${url.pathname}. This app shares its host with other deployments, so there is no safe default port to guess - refusing to proxy. Set PORT_API (or API_URL) for this site, and deploy an \`api\` site on its own port.`);return new Response("Bad Gateway",{status:502})}try{return await proxyToBackend(req,apiBase)}catch(error){log.error(`API proxy to ${apiBase} failed: ${error.message}`);return new Response("Bad Gateway",{status:502})}}if(existsSync(join(process.cwd(),"resources/views/blog.stx"))){const{renderBlogFeed}=await import("@stacksjs/actions/blog"),feed=await renderBlogFeed(req);if(feed)return feed}globalThis.__stxServeSearch=url.search;globalThis.__stxServeCookies=parseCookies(req);if(config.analytics?.capturePageviews)import("@stacksjs/analytics").then(({recordPageview})=>recordPageview(req)).catch(()=>{});if(config.sites?.enabled){const sites=await import("@stacksjs/sites"),resolved=await sites.resolveSiteByHost(sites.requestHost(req.headers,sites.sitesOptions()));sites.setCurrentSite(resolved);globalThis.__stxServeSite=sites.toSiteSnapshot(resolved)}else globalThis.__stxServeSite=null;return},onResponse:async(req,response)=>{const secured=applyViewSecurityHeaders(req,response,embeddableRules),method=req.method.toUpperCase();if(method!=="GET"&&method!=="HEAD")return secured;const baseline=secured??response;let current=baseline;if(current.status===404&&config.sites?.enabled)try{const{cmsNotFoundFallback}=await import("@stacksjs/cms"),cmsResponse=await cmsNotFoundFallback(req);if(cmsResponse)current=cmsResponse}catch(error){log.debug(`CMS fallback skipped: ${error.message}`)}try{const{seedCsrfCookieIfMissing}=await import(resolveCsrfMiddlewarePath());return await seedCsrfCookieIfMissing(req,current)??(current===baseline?secured:current)}catch(error){log.debug(`CSRF cookie seeding skipped: ${error.message}`);return current===baseline?secured:current}}});log.success(`Production server listening on http://0.0.0.0:${port}`)}async function resolveVendoredStxModule(){const source=resolveStxSource({value:process.env.STACKS_STX_SRC});if(source.kind==="missing")await log.exit(`STACKS_STX_SRC points at ${source.path}, which does not exist. Unset it to use the installed @stacksjs/stx.`,ExitCode.FatalError);if(source.kind==="override"){log.warn(`Rendering through ${source.path} instead of the installed @stacksjs/stx.`);return await import(source.path)}try{return await import("@stacksjs/stx")}catch{}return}function fallbackI18nFromSite(site){const locales=site.i18n.locales,defaultLocale=site.i18n.defaultLocale??locales[0];return{locales,defaultLocale,labels:site.i18n.labels??Object.fromEntries(locales.map((c)=>[c,c.toUpperCase()])),translations:{},pickerSelector:site.i18n.pickerSelector??"#lang-picker"}}async function resolveSiteI18n(site){try{const resolved=await resolveVendoredStxModule();if(typeof resolved?.resolveI18n==="function"){const i18n=resolved.resolveI18n(site,process.cwd());if(i18n)return i18n}}catch{}return fallbackI18nFromSite(site)}async function loadStxSiteConfig(){const sitePath=siteConfigPath();if(!existsSync(sitePath))return{};try{const mod=await import(sitePath),site=mod.default??mod.site??mod.config;if(!site)return{};if(!site.i18n)return{site};const i18n=await resolveSiteI18n(site);return{site,i18n}}catch{}return{}}
@@ -5,14 +5,6 @@
5
5
  * a dangling one; only the second is ours to clean up.
6
6
  */
7
7
  export declare function isDanglingLink(target: string): boolean;
8
- /**
9
- * The package manager this project actually installs with.
10
- *
11
- * An app installed with pantry has no node_modules at all, so running `bun
12
- * install` at the end of an unvendor writes a second, competing dependency
13
- * tree that the `./buddy` shim does not read — the install "succeeds" and the
14
- * project still cannot resolve a single @stacksjs package.
15
- */
16
8
  export declare function detectInstaller(cwd: string): string[];
17
9
  /**
18
10
  * Repoint package manifests that remain under `storage/framework` after core
@@ -1,3 +1,3 @@
1
- import{existsSync,lstatSync}from"node:fs";import{readdir}from"node:fs/promises";import{join,resolve}from"node:path";import{log}from"@stacksjs/cli";import{fs}from"@stacksjs/storage";export function isDanglingLink(target){try{return lstatSync(target).isSymbolicLink()&&!existsSync(target)}catch{return!1}}export function detectInstaller(cwd){const has=(rel)=>existsSync(resolve(cwd,rel)),usesPantry=has("pantry")||has("pantry.lock")&&!has("node_modules");if(usesPantry&&Bun.which("pantry"))return["pantry","install"];if(usesPantry)log.warn("This project installs with pantry, but no `pantry` binary is on PATH \u2014 falling back to `bun install`.");return["bun","install"]}export async function rewriteSurvivingFrameworkManifests(cwd,provided,range){const framework=resolve(cwd,"storage/framework"),files=[];let ranges=0;const walk=async(dir)=>{let entries;try{entries=await readdir(dir,{withFileTypes:!0})}catch{return}for(const entry of entries){if(entry.name==="core"||entry.name==="node_modules"||entry.name==="dist")continue;const full=join(dir,entry.name);if(entry.isDirectory()){await walk(full);continue}if(!entry.isFile()||entry.name!=="package.json")continue;const raw=await fs.promises.readFile(full,"utf-8"),pkg=JSON.parse(raw);let touched=!1;for(const field of["dependencies","devDependencies","peerDependencies"]){const dependencies=pkg[field];if(!dependencies)continue;for(const[name,spec]of Object.entries(dependencies)){if(!spec.startsWith("workspace:")||!provided.has(name))continue;dependencies[name]=range;ranges++;touched=!0}}if(!touched)continue;await fs.promises.writeFile(full,`${JSON.stringify(pkg,null,2)}
1
+ import{existsSync,lstatSync,readFileSync}from"node:fs";import{readdir}from"node:fs/promises";import{join,resolve}from"node:path";import{log}from"@stacksjs/cli";import{fs}from"@stacksjs/storage";export function isDanglingLink(target){try{return lstatSync(target).isSymbolicLink()&&!existsSync(target)}catch{return!1}}function hoistedLinker(cwd){try{const bunfig=readFileSync(resolve(cwd,"bunfig.toml"),"utf-8");return/^\s*linker\s*=\s*["']hoisted["']/m.test(bunfig)}catch{return!1}}export function detectInstaller(cwd){const has=(rel)=>existsSync(resolve(cwd,rel)),usesPantry=has("pantry")||has("pantry.lock")&&!has("node_modules");if(usesPantry&&Bun.which("pantry")){if(hoistedLinker(cwd))return["pantry","install","--linker","hoisted"];return["pantry","install"]}if(usesPantry)log.warn("This project installs with pantry, but no `pantry` binary is on PATH \u2014 falling back to `bun install`.");return["bun","install"]}export async function rewriteSurvivingFrameworkManifests(cwd,provided,range){const framework=resolve(cwd,"storage/framework"),files=[];let ranges=0;const walk=async(dir)=>{let entries;try{entries=await readdir(dir,{withFileTypes:!0})}catch{return}for(const entry of entries){if(entry.name==="core"||entry.name==="node_modules"||entry.name==="dist")continue;const full=join(dir,entry.name);if(entry.isDirectory()){await walk(full);continue}if(!entry.isFile()||entry.name!=="package.json")continue;const raw=await fs.promises.readFile(full,"utf-8"),pkg=JSON.parse(raw);let touched=!1;for(const field of["dependencies","devDependencies","peerDependencies"]){const dependencies=pkg[field];if(!dependencies)continue;for(const[name,spec]of Object.entries(dependencies)){if(!spec.startsWith("workspace:")||!provided.has(name))continue;dependencies[name]=range;ranges++;touched=!0}}if(!touched)continue;await fs.promises.writeFile(full,`${JSON.stringify(pkg,null,2)}
2
2
  `);files.push(full.replace(`${cwd}/`,""))}};await walk(framework);return{files,ranges}}const SCANNED_EXTENSIONS=new Set([".ts",".tsx",".js",".mjs",".cjs",".json",".sh",".yml",".yaml",".toml"]),SKIPPED_DIRECTORIES=new Set(["node_modules","pantry","dist","storage","public","coverage","temp","tmp",".git",".cache",".claude",".idea",".stx",".vscode"]);async function*projectFiles(cwd){const walk=async function*(dir){let entries;try{entries=await readdir(dir,{withFileTypes:!0})}catch{return}for(const entry of entries){const full=join(dir,entry.name);if(entry.isDirectory()){if(SKIPPED_DIRECTORIES.has(entry.name))continue;yield*walk(full);continue}if(!entry.isFile())continue;const dot=entry.name.lastIndexOf("."),ext=dot===-1?"":entry.name.slice(dot);if(SCANNED_EXTENSIONS.has(ext)||entry.name==="Dockerfile"||entry.name.startsWith("Dockerfile."))yield full}};yield*walk(cwd)}const CORE_SOURCE_IMPORT=/(\bfrom\s+|\bimport\s*\(\s*|\brequire\s*\(\s*)(['"])(?:\.{1,2}\/)*storage\/framework\/core\/([\w.-]+)\/src\/([^'"]+?)(?:\.ts)?\2/g;function toPackageSpecifier(pkg,rest){const subpath=rest.replace(/\/index$/,"");return subpath==="index"?`@stacksjs/${pkg}`:`@stacksjs/${pkg}/${subpath}`}const CORE_ACTION_COMMANDS={"actions/src/migrate/database":"migrate","actions/src/migrate/fresh":"migrate:fresh","actions/src/database/seed":"seed","actions/src/auth/setup":"auth:setup","actions/src/dev/api":"dev:api","actions/src/key-generate":"key:generate"},CORE_COMMAND_PATH=/\bbunx?\s+(?:-{1,2}[\w=.-]+\s+)*(?:\.\/)?storage\/framework\/core\/([\w/.-]+?)\.ts\b/g;export async function rewriteCoreCommandPaths(cwd){const touched=[];for await(const file of projectFiles(cwd)){const raw=await fs.promises.readFile(file,"utf-8");if(!raw.includes("storage/framework/core/"))continue;const next=raw.replace(CORE_COMMAND_PATH,(match,entry)=>{if(entry==="buddy/src/cli")return"./buddy";const command=CORE_ACTION_COMMANDS[entry];return command?`./buddy ${command}`:match});if(next!==raw){await fs.promises.writeFile(file,next);touched.push(file.replace(`${cwd}/`,""))}}return touched}export async function rewriteCoreSourceImports(cwd){const touched=[];for await(const file of projectFiles(cwd)){const raw=await fs.promises.readFile(file,"utf-8");if(!raw.includes("storage/framework/core/"))continue;const next=raw.replace(CORE_SOURCE_IMPORT,(_match,lead,quote,pkg,rest)=>`${lead}${quote}${toPackageSpecifier(pkg,rest)}${quote}`);if(next!==raw){await fs.promises.writeFile(file,next);touched.push(file.replace(`${cwd}/`,""))}}return touched}export async function findCoreReferences(cwd){const hits=[];for await(const file of projectFiles(cwd)){const raw=await fs.promises.readFile(file,"utf-8");if(!raw.includes("storage/framework/core"))continue;raw.split(`
3
3
  `).forEach((text,index)=>{if(!text.includes("storage/framework/core"))return;const trimmed=text.trim();if(/^(?:\/\/|\*|#|<!--)/.test(trimmed))return;hits.push({file:file.replace(`${cwd}/`,""),line:index+1,text:trimmed.slice(0,120)})})}return hits}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/buddy",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.74.26",
5
+ "version": "0.74.28",
6
6
  "description": "Meet Buddy. The Stacks runtime.",
7
7
  "author": "Chris Breuer",
8
8
  "contributors": [
@@ -95,69 +95,69 @@
95
95
  "prepublishOnly": "bun run build"
96
96
  },
97
97
  "dependencies": {
98
- "@stacksjs/actions": "^0.74.26",
99
- "@stacksjs/ai": "^0.74.26",
100
- "@stacksjs/alias": "^0.74.26",
101
- "@stacksjs/analytics": "^0.74.26",
102
- "@stacksjs/api": "^0.74.26",
103
- "@stacksjs/arrays": "^0.74.26",
104
- "@stacksjs/auth": "^0.74.26",
105
- "@stacksjs/browser-extension": "^0.74.26",
106
- "@stacksjs/build": "^0.74.26",
107
- "@stacksjs/cache": "^0.74.26",
108
- "@stacksjs/chat": "^0.74.26",
98
+ "@stacksjs/actions": "^0.74.28",
99
+ "@stacksjs/ai": "^0.74.28",
100
+ "@stacksjs/alias": "^0.74.28",
101
+ "@stacksjs/analytics": "^0.74.28",
102
+ "@stacksjs/api": "^0.74.28",
103
+ "@stacksjs/arrays": "^0.74.28",
104
+ "@stacksjs/auth": "^0.74.28",
105
+ "@stacksjs/browser-extension": "^0.74.28",
106
+ "@stacksjs/build": "^0.74.28",
107
+ "@stacksjs/cache": "^0.74.28",
108
+ "@stacksjs/chat": "^0.74.28",
109
109
  "@stacksjs/clapp": "^0.2.12",
110
- "@stacksjs/cli": "^0.74.26",
111
- "@stacksjs/cloud": "^0.74.26",
112
- "@stacksjs/cms": "^0.74.26",
113
- "@stacksjs/collections": "^0.74.26",
114
- "@stacksjs/config": "^0.74.26",
115
- "@stacksjs/database": "^0.74.26",
116
- "@stacksjs/desktop-build": "^0.74.26",
117
- "@stacksjs/dns": "^0.74.26",
110
+ "@stacksjs/cli": "^0.74.28",
111
+ "@stacksjs/cloud": "^0.74.28",
112
+ "@stacksjs/cms": "^0.74.28",
113
+ "@stacksjs/collections": "^0.74.28",
114
+ "@stacksjs/config": "^0.74.28",
115
+ "@stacksjs/database": "^0.74.28",
116
+ "@stacksjs/desktop-build": "^0.74.28",
117
+ "@stacksjs/dns": "^0.74.28",
118
118
  "@stacksjs/dnsx": "^0.2.3",
119
- "@stacksjs/email": "^0.74.26",
120
- "@stacksjs/enums": "^0.74.26",
121
- "@stacksjs/env": "^0.74.26",
122
- "@stacksjs/error-handling": "^0.74.26",
123
- "@stacksjs/events": "^0.74.26",
124
- "@stacksjs/features": "^0.74.26",
125
- "@stacksjs/git": "^0.74.26",
119
+ "@stacksjs/email": "^0.74.28",
120
+ "@stacksjs/enums": "^0.74.28",
121
+ "@stacksjs/env": "^0.74.28",
122
+ "@stacksjs/error-handling": "^0.74.28",
123
+ "@stacksjs/events": "^0.74.28",
124
+ "@stacksjs/features": "^0.74.28",
125
+ "@stacksjs/git": "^0.74.28",
126
126
  "@stacksjs/gitit": "^0.2.5",
127
- "@stacksjs/health": "^0.74.26",
127
+ "@stacksjs/health": "^0.74.28",
128
128
  "@stacksjs/httx": "^0.1.10",
129
- "@stacksjs/image": "^0.74.26",
130
- "@stacksjs/lint": "^0.74.26",
131
- "@stacksjs/logging": "^0.74.26",
132
- "@stacksjs/notifications": "^0.74.26",
133
- "@stacksjs/objects": "^0.74.26",
134
- "@stacksjs/orm": "^0.74.26",
135
- "@stacksjs/path": "^0.74.26",
136
- "@stacksjs/payments": "^0.74.26",
137
- "@stacksjs/realtime": "^0.74.26",
138
- "@stacksjs/router": "^0.74.26",
129
+ "@stacksjs/image": "^0.74.28",
130
+ "@stacksjs/lint": "^0.74.28",
131
+ "@stacksjs/logging": "^0.74.28",
132
+ "@stacksjs/notifications": "^0.74.28",
133
+ "@stacksjs/objects": "^0.74.28",
134
+ "@stacksjs/orm": "^0.74.28",
135
+ "@stacksjs/path": "^0.74.28",
136
+ "@stacksjs/payments": "^0.74.28",
137
+ "@stacksjs/realtime": "^0.74.28",
138
+ "@stacksjs/router": "^0.74.28",
139
139
  "@stacksjs/rpx": "^0.11.42",
140
- "@stacksjs/scheduler": "^0.74.26",
141
- "@stacksjs/search-engine": "^0.74.26",
142
- "@stacksjs/security": "^0.74.26",
143
- "@stacksjs/server": "^0.74.26",
144
- "@stacksjs/sites": "^0.74.26",
145
- "@stacksjs/skills": "^0.74.26",
146
- "@stacksjs/storage": "^0.74.26",
147
- "@stacksjs/strings": "^0.74.26",
140
+ "@stacksjs/scheduler": "^0.74.28",
141
+ "@stacksjs/search-engine": "^0.74.28",
142
+ "@stacksjs/security": "^0.74.28",
143
+ "@stacksjs/server": "^0.74.28",
144
+ "@stacksjs/sites": "^0.74.28",
145
+ "@stacksjs/skills": "^0.74.28",
146
+ "@stacksjs/storage": "^0.74.28",
147
+ "@stacksjs/strings": "^0.74.28",
148
148
  "@stacksjs/stx": "^0.2.274",
149
- "@stacksjs/testing": "^0.74.26",
150
- "@stacksjs/tinker": "^0.74.26",
149
+ "@stacksjs/testing": "^0.74.28",
150
+ "@stacksjs/tinker": "^0.74.28",
151
151
  "@stacksjs/tlsx": "^0.13.19",
152
- "@stacksjs/ts-cloud": "^0.12.10",
153
- "@stacksjs/tunnel": "^0.74.26",
154
- "@stacksjs/types": "^0.74.26",
155
- "@stacksjs/ui": "^0.74.26",
156
- "@stacksjs/utils": "^0.74.26",
157
- "@stacksjs/validation": "^0.74.26",
152
+ "@stacksjs/ts-cloud": "^0.12.15",
153
+ "@stacksjs/tunnel": "^0.74.28",
154
+ "@stacksjs/types": "^0.74.28",
155
+ "@stacksjs/ui": "^0.74.28",
156
+ "@stacksjs/utils": "^0.74.28",
157
+ "@stacksjs/validation": "^0.74.28",
158
158
  "ajv": "^8.20.0",
159
159
  "ajv-formats": "^3.0.1",
160
- "bun-plugin-stx": "^0.2.274",
160
+ "bun-plugin-stx": "^0.2.279",
161
161
  "ts-pantry": "^0.11.35"
162
162
  },
163
163
  "devDependencies": {