@stacksjs/desktop-build 0.75.399 → 0.75.401
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/agent-launcher.d.ts
CHANGED
|
@@ -39,6 +39,11 @@ export declare function renderAgentEntry(options?: { agentEntry?: string, launch
|
|
|
39
39
|
export declare function runDesktopAgentApp(options: RunDesktopAgentAppOptions): Promise<number>;
|
|
40
40
|
export declare const AGENT_MANIFEST: 'desktop-agent.json';
|
|
41
41
|
export declare const AGENT_MANIFEST_ENV: 'STACKS_DESKTOP_AGENT_MANIFEST';
|
|
42
|
+
/**
|
|
43
|
+
* Set for the agent's routes before they load: the app's folder in Application
|
|
44
|
+
* Support (`desktopAgentPaths().dataDir`), where a route keeps its own database.
|
|
45
|
+
*/
|
|
46
|
+
export declare const AGENT_DATA_DIR_ENV: 'STACKS_DESKTOP_DATA_DIR';
|
|
42
47
|
/**
|
|
43
48
|
* The executable of a desktop app that runs its own API (`macos.agent`). It
|
|
44
49
|
* holds the single-instance lock, starts the agent, and spawns Craft's AppKit
|
package/dist/agent-launcher.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{appendFileSync,existsSync,mkdirSync,readFileSync,rmSync,writeFileSync}from"node:fs";import{homedir}from"node:os";import{dirname,isAbsolute,join,resolve}from"node:path";import process from"node:process";import{fileURLToPath}from"node:url";import{format}from"node:util";import{startDesktopAgent}from"./agent";export const AGENT_MANIFEST="desktop-agent.json",AGENT_MANIFEST_ENV="STACKS_DESKTOP_AGENT_MANIFEST";export function desktopAgentPaths(appName,home=homedir()){const dataDir=join(home,"Library","Application Support",appName);return{dataDir,portFile:join(dataDir,"agent.port"),lockFile:join(dataDir,"agent.pid"),logFile:join(home,"Library","Logs",`${appName}.log`)}}export function acquireInstanceLock(lockFile,pid=process.pid){mkdirSync(dirname(lockFile),{recursive:!0});if(existsSync(lockFile)){const holder=Number(readFileSync(lockFile,"utf8").trim());if(holder&&holder!==pid)try{process.kill(holder,0);return!1}catch(error){if(error.code==="EPERM")return!1}}writeFileSync(lockFile,String(pid));return!0}export function releaseInstanceLock(lockFile,pid=process.pid){try{if(readFileSync(lockFile,"utf8").trim()===String(pid))rmSync(lockFile)}catch{}}export function logToFileWhenDetached(logFile,isTTY=Boolean(process.stdout.isTTY)){if(isTTY)return!1;mkdirSync(dirname(logFile),{recursive:!0});for(const level of["log","info","warn","error","debug"])console[level]=(...args)=>{try{appendFileSync(logFile,`${new Date().toISOString()} ${level==="log"?"":`[${level}] `}${format(...args)}
|
|
1
|
+
import{appendFileSync,existsSync,mkdirSync,readFileSync,rmSync,writeFileSync}from"node:fs";import{homedir}from"node:os";import{dirname,isAbsolute,join,resolve}from"node:path";import process from"node:process";import{fileURLToPath}from"node:url";import{format}from"node:util";import{startDesktopAgent}from"./agent";export const AGENT_MANIFEST="desktop-agent.json",AGENT_MANIFEST_ENV="STACKS_DESKTOP_AGENT_MANIFEST",AGENT_DATA_DIR_ENV="STACKS_DESKTOP_DATA_DIR";export function desktopAgentPaths(appName,home=homedir()){const dataDir=join(home,"Library","Application Support",appName);return{dataDir,portFile:join(dataDir,"agent.port"),lockFile:join(dataDir,"agent.pid"),logFile:join(home,"Library","Logs",`${appName}.log`)}}export function acquireInstanceLock(lockFile,pid=process.pid){mkdirSync(dirname(lockFile),{recursive:!0});if(existsSync(lockFile)){const holder=Number(readFileSync(lockFile,"utf8").trim());if(holder&&holder!==pid)try{process.kill(holder,0);return!1}catch(error){if(error.code==="EPERM")return!1}}writeFileSync(lockFile,String(pid));return!0}export function releaseInstanceLock(lockFile,pid=process.pid){try{if(readFileSync(lockFile,"utf8").trim()===String(pid))rmSync(lockFile)}catch{}}export function logToFileWhenDetached(logFile,isTTY=Boolean(process.stdout.isTTY)){if(isTTY)return!1;mkdirSync(dirname(logFile),{recursive:!0});for(const level of["log","info","warn","error","debug"])console[level]=(...args)=>{try{appendFileSync(logFile,`${new Date().toISOString()} ${level==="log"?"":`[${level}] `}${format(...args)}
|
|
2
2
|
`)}catch{}};return!0}export function findAgentManifest(execPath=process.execPath,env=process.env){if(env[AGENT_MANIFEST_ENV])return resolve(env[AGENT_MANIFEST_ENV]);const bundled=join(dirname(execPath),"..","Resources",AGENT_MANIFEST);return existsSync(bundled)?bundled:null}export function readAgentManifest(file){const manifest=JSON.parse(readFileSync(file,"utf8")),base=dirname(file),at=(path)=>isAbsolute(path)?path:resolve(base,path);return{...manifest,host:at(manifest.host),nativeBundle:at(manifest.nativeBundle),...manifest.staticDir?{staticDir:at(manifest.staticDir)}:{}}}export function agentHostCommand(manifest,agentUrl){return[manifest.host,"--api-url",agentUrl,"--native-bundle",manifest.nativeBundle,...manifest.hostArguments]}export async function stacksAgentHandler(options){try{const{overridesReady}=await import("@stacksjs/config");await overridesReady}catch(error){console.warn(`[agent] config not loaded: ${error instanceof Error?error.message:String(error)}`)}if(options.appRoutes)try{const{injectGlobalAutoImports}=await import("@stacksjs/server");await injectGlobalAutoImports()}catch(error){console.warn(`[agent] models and framework globals not injected: ${error instanceof Error?error.message:String(error)}`)}const{provideActions,route,serverResponse}=await import("@stacksjs/router");if(options.actions)provideActions(options.actions);const module=options.entry?await options.entry():void 0;if(typeof module?.default==="function")return module.default;if(options.appRoutes)return(request)=>serverResponse(request);for(const file of options.routes??[])if(file.prefix||file.middleware?.length)await route.group({prefix:file.prefix,middleware:file.middleware?.length?file.middleware:void 0},async()=>{await file.load()});else await file.load();return(request)=>route.handleRequest(request)}export function renderAgentEntry(options={}){const launcher=options.launcherModule??fileURLToPath(import.meta.url),entry=options.agentEntry?`() => import(${JSON.stringify(options.agentEntry)})`:"undefined",routes=options.routes?.length?`[
|
|
3
3
|
${options.routes.map((file)=>` { load: () => import(${JSON.stringify(file.file)})${file.prefix?`, prefix: ${JSON.stringify(file.prefix)}`:""}${file.middleware?.length?`, middleware: ${JSON.stringify(file.middleware)}`:""} },`).join(`
|
|
4
4
|
`)}
|
|
@@ -19,6 +19,6 @@ process.exit(await runDesktopAgentApp({
|
|
|
19
19
|
manifest,
|
|
20
20
|
handler: () => stacksAgentHandler({ entry: ${entry}, appRoutes: manifest.appRoutes, routes: ${routes}, actions: ${actions} }),
|
|
21
21
|
}))
|
|
22
|
-
`}export async function runDesktopAgentApp(options){const{manifest}=options,paths=options.paths??desktopAgentPaths(manifest.appName),tag=`[${manifest.appName}]`;if(options.logWhenDetached!==!1)logToFileWhenDetached(paths.logFile);if(!acquireInstanceLock(paths.lockFile)){console.log(`${tag} already running`);return 0}if(!existsSync(manifest.host)){console.error(`${tag} the AppKit host is missing: ${manifest.host}`);releaseInstanceLock(paths.lockFile);return 1}if(!existsSync(manifest.nativeBundle)){console.error(`${tag} the native screens are missing: ${manifest.nativeBundle}`);releaseInstanceLock(paths.lockFile);return 1}let agent;try{if(manifest.projectRoot&&manifest.appRoutes)process.chdir(manifest.projectRoot);agent=await startDesktopAgent({handler:await options.handler(),name:manifest.appName,version:manifest.version,port:manifest.port,portFile:paths.portFile,staticDir:manifest.staticDir})}catch(error){console.error(`${tag} could not start: ${error instanceof Error?error.stack??error.message:String(error)}`);releaseInstanceLock(paths.lockFile);return 1}console.log(`${tag} ${manifest.version} serving on ${agent.url}`);const command=agentHostCommand(manifest,agent.url),host=options.spawn?options.spawn(command):(()=>{const child=Bun.spawn(command,{stdio:["ignore","inherit","pipe"]});new Response(child.stderr).text().then((stderr)=>{const lines=stderr.split(`
|
|
22
|
+
`}export async function runDesktopAgentApp(options){const{manifest}=options,paths=options.paths??desktopAgentPaths(manifest.appName),tag=`[${manifest.appName}]`;if(options.logWhenDetached!==!1)logToFileWhenDetached(paths.logFile);if(!acquireInstanceLock(paths.lockFile)){console.log(`${tag} already running`);return 0}if(!existsSync(manifest.host)){console.error(`${tag} the AppKit host is missing: ${manifest.host}`);releaseInstanceLock(paths.lockFile);return 1}if(!existsSync(manifest.nativeBundle)){console.error(`${tag} the native screens are missing: ${manifest.nativeBundle}`);releaseInstanceLock(paths.lockFile);return 1}let agent;try{if(manifest.projectRoot&&manifest.appRoutes)process.chdir(manifest.projectRoot);process.env[AGENT_DATA_DIR_ENV]=paths.dataDir;agent=await startDesktopAgent({handler:await options.handler(),name:manifest.appName,version:manifest.version,port:manifest.port,portFile:paths.portFile,staticDir:manifest.staticDir})}catch(error){console.error(`${tag} could not start: ${error instanceof Error?error.stack??error.message:String(error)}`);releaseInstanceLock(paths.lockFile);return 1}console.log(`${tag} ${manifest.version} serving on ${agent.url}`);const command=agentHostCommand(manifest,agent.url),host=options.spawn?options.spawn(command):(()=>{const child=Bun.spawn(command,{stdio:["ignore","inherit","pipe"]});new Response(child.stderr).text().then((stderr)=>{const lines=stderr.split(`
|
|
23
23
|
`).filter((line)=>line.trim());if(lines.length)console.error(`[craft] ${lines.join(`
|
|
24
24
|
`)}`)});return{exited:child.exited,kill:()=>child.kill()}})();let stopped=!1;const stop=()=>{if(stopped)return;stopped=!0;host.kill();agent.stop();releaseInstanceLock(paths.lockFile)},onSignal=()=>{stop();process.exit(0)};for(const signal of["SIGTERM","SIGINT","SIGHUP"])process.on(signal,onSignal);const code=await host.exited;console.log(`${tag} window closed (${code})`);for(const signal of["SIGTERM","SIGINT","SIGHUP"])process.off(signal,onSignal);stop();return 0}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/desktop-build",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.75.
|
|
5
|
+
"version": "0.75.401",
|
|
6
6
|
"description": "Build and launch Craft desktop applications for Stacks",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"contributors": [
|
|
@@ -73,15 +73,15 @@
|
|
|
73
73
|
"prepublishOnly": "bun run build"
|
|
74
74
|
},
|
|
75
75
|
"dependencies": {
|
|
76
|
-
"@stacksjs/config": "0.75.
|
|
77
|
-
"@stacksjs/router": "0.75.
|
|
78
|
-
"@stacksjs/server": "0.75.
|
|
79
|
-
"craft-native": ">=0.0.
|
|
76
|
+
"@stacksjs/config": "0.75.401",
|
|
77
|
+
"@stacksjs/router": "0.75.401",
|
|
78
|
+
"@stacksjs/server": "0.75.401",
|
|
79
|
+
"craft-native": ">=0.0.411"
|
|
80
80
|
},
|
|
81
81
|
"peerDependencies": {
|
|
82
|
-
"@stacksjs/config": "0.75.
|
|
83
|
-
"@stacksjs/router": "0.75.
|
|
84
|
-
"@stacksjs/server": "0.75.
|
|
82
|
+
"@stacksjs/config": "0.75.401",
|
|
83
|
+
"@stacksjs/router": "0.75.401",
|
|
84
|
+
"@stacksjs/server": "0.75.401"
|
|
85
85
|
},
|
|
86
86
|
"peerDependenciesMeta": {
|
|
87
87
|
"@stacksjs/config": {
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
}
|
|
96
96
|
},
|
|
97
97
|
"devDependencies": {
|
|
98
|
-
"@stacksjs/build": "0.75.
|
|
98
|
+
"@stacksjs/build": "0.75.401",
|
|
99
99
|
"better-dx": "^0.2.24"
|
|
100
100
|
}
|
|
101
101
|
}
|