@stacksjs/desktop-build 0.75.397 → 0.75.398
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/macos-app.js +2 -2
- package/package.json +8 -8
package/dist/macos-app.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{existsSync}from"node:fs";import{join,resolve}from"node:path";import{pathToFileURL}from"node:url";import{plistValue,renderUserlandPlistEntries,xmlEscape}from"./index";export const MACOS_DEFAULTS={minimumSystemVersion:"13.0",category:"public.app-category.productivity",nativeScreensDir:"resources/native",initialScreen:"Main",window:{width:1180,height:760,minWidth:820,minHeight:520}};export async function loadDesktopConfig(root){const file=join(root,"config/desktop.ts");if(!existsSync(file))return null;return(await import(`${pathToFileURL(file).href}?t=${Date.now()}`)).default??null}export async function hasMacosDesktop(root){return Boolean((await loadDesktopConfig(root))?.macos)}export async function loadMacosDesktop(root,packageVersion="0.0.0"){const config=await loadDesktopConfig(root);return config?.macos?resolveMacosDesktop(config.macos,packageVersion):null}export function resolveMacosDesktop(config,packageVersion="0.0.0"){const version=config.version??packageVersion,agent=config.agent?config.agent===!0?{}:{...config.agent}:null;return{...config,agent,url:agent?"http://127.0.0.1":config.url??"",version,buildNumber:config.buildNumber??version.split(/[-+]/)[0],minimumSystemVersion:config.minimumSystemVersion??MACOS_DEFAULTS.minimumSystemVersion,category:config.category??MACOS_DEFAULTS.category,nativeScreensDir:config.nativeScreensDir??MACOS_DEFAULTS.nativeScreensDir,initialScreen:config.initialScreen??(Array.isArray(config.nativeScreens)?config.nativeScreens.includes("Main")?"Main":config.nativeScreens[0]:Object.keys(config.nativeScreens).includes("Main")?"Main":Object.keys(config.nativeScreens)[0])??MACOS_DEFAULTS.initialScreen,sandbox:config.sandbox!==!1,executable:config.appName}}export function validateMacosDesktop(config){const errors=[];if(!config.appName?.trim())errors.push("macos.appName is required");if(!/^[A-Za-z0-9][A-Za-z0-9.-]*\.[A-Za-z0-9.-]+$/.test(config.bundleId??""))errors.push("macos.bundleId must be a reverse-DNS identifier such as com.example.app");if(config.teamId!==void 0&&!/^[A-Z0-9]{10}$/.test(config.teamId))errors.push("macos.teamId must be the 10-character Apple Developer team ID");if(!/^\d+(?:\.\d+){0,2}$/.test(config.version))errors.push(`macos.version must be one to three numeric components, not "${config.version}"`);if(!/^[A-Za-z0-9.-]+$/.test(config.buildNumber))errors.push("macos.buildNumber must contain only letters, numbers, periods and hyphens");if(!/^\d+(?:\.\d+){0,2}$/.test(config.minimumSystemVersion))errors.push("macos.minimumSystemVersion must be a macOS version such as 13.0");if(!/^public\.app-category\.[a-z][a-z0-9-]*$/.test(config.category))errors.push("macos.category must be an LSApplicationCategoryType such as public.app-category.productivity");if(!config.agent)try{const url=new URL(config.url);if(!["http:","https:"].includes(url.protocol))errors.push("macos.url must be an http(s) origin")}catch{errors.push("macos.url must be the server origin the app talks to, e.g. https://example.com, or turn on macos.agent to run the API inside the app")}else if(config.agent.port!==void 0&&!(Number.isInteger(config.agent.port)&&config.agent.port>1024&&config.agent.port<65536))errors.push("macos.agent.port must be a port above 1024");for(const[index,item]of(config.dockMenu??[]).entries()){if(!item?.title?.trim())errors.push(`macos.dockMenu[${index}] needs a title`);if(!item?.action?.trim())errors.push(`macos.dockMenu[${index}] needs an action`)}const names=Object.keys(macosScreens(config));if(!names.length)errors.push("macos.nativeScreens must name at least one screen");if(names.length&&!names.includes(config.initialScreen))errors.push(`macos.initialScreen "${config.initialScreen}" is not one of the native screens (${names.join(", ")})`);for(const scheme of config.urlSchemes??[])if(!/^[a-z][a-z0-9+.-]*$/.test(scheme))errors.push(`macos.urlSchemes: "${scheme}" is not a valid URL scheme`);return errors}export function macosScreens(config){const dir=config.nativeScreensDir??MACOS_DEFAULTS.nativeScreensDir;if(Array.isArray(config.nativeScreens))return Object.fromEntries(config.nativeScreens.map((name)=>[name,`${dir}/${name}.stx`]));return{...config.nativeScreens}}export function renderHostConfig(config){const window={...MACOS_DEFAULTS.window,...config.window};return`${JSON.stringify({...config.agent?{}:{apiUrl:config.url.replace(/\/+$/,"")},title:config.appName,route:config.initialScreen,session:Boolean(config.agent),titlebarStyle:window.titlebarStyle??"standard",width:window.width,height:window.height,minWidth:window.minWidth,minHeight:window.minHeight,...config.webkit?{webkit:!0}:{},...config.dockMenu?.length?{dockMenu:config.dockMenu.map((item)=>({title:item.title,action:item.action}))}:{}},null,2)}
|
|
2
|
-
`}export function hostArguments(config,nativeBundle){return["--api-url",config.url.replace(/\/+$/,""),"--native-bundle",nativeBundle,...windowArguments(config),"--no-session"]}export function agentHostArguments(config){return windowArguments(config)}function windowArguments(config){const window={...MACOS_DEFAULTS.window,...config.window};return["--title",config.appName,"--route",config.initialScreen,"--titlebar-style",window.titlebarStyle??"standard","--width",String(window.width),"--height",String(window.height),"--min-width",String(window.minWidth),"--min-height",String(window.minHeight)]}const OWNED_KEYS=["CFBundleIdentifier","CFBundleExecutable","CFBundleName","CFBundleDisplayName","CFBundleShortVersionString","CFBundleVersion","CFBundlePackageType","LSApplicationCategoryType","LSMinimumSystemVersion","CFBundleIconFile","CFBundleURLTypes"];export const BROWSER_DOCUMENT_TYPES=[{name:"HTML document",types:["public.html"]},{name:"XHTML document",types:["public.xhtml"]},{name:"Web archive",types:["com.apple.webarchive"]},{name:"PDF document",types:["com.adobe.pdf"]}];export function defaultUsageDescriptions(appName){return{camera:`${appName} uses the camera when you allow a page or feature to.`,microphone:`${appName} uses the microphone when you allow a page or feature to.`,location:`${appName} uses your location when you allow a page or feature to.`}}export function permissionUsageDescriptions(config){const permissions=config.permissions??{},defaults=defaultUsageDescriptions(config.appName),sentence=(value,fallback)=>typeof value==="string"&&value.trim()?value:value?fallback:void 0,usage={},camera=sentence(permissions.camera,defaults.camera);if(camera)usage.NSCameraUsageDescription=camera;const microphone=sentence(permissions.microphone,defaults.microphone);if(microphone)usage.NSMicrophoneUsageDescription=microphone;const location=sentence(permissions.location,defaults.location);if(location){usage.NSLocationUsageDescription=location;usage.NSLocationWhenInUseUsageDescription=location}return usage}export function renderMacosInfoPlist(config,options={}){const owns=config.defaultBrowser?[...OWNED_KEYS,"CFBundleDocumentTypes"]:OWNED_KEYS,declared={...permissionUsageDescriptions(config),...config.usageDescriptions,...config.infoPlist};if(config.defaultBrowser&&declared.NSAppTransportSecurity===void 0)declared.NSAppTransportSecurity={NSAllowsArbitraryLoadsInWebContent:!0};const{xml:extra,ignored}=renderUserlandPlistEntries(Object.fromEntries(Object.entries(declared).filter(([key])=>!owns.includes(key)))),owned=Object.keys(declared).filter((key)=>owns.includes(key)),urlTypes=[];if(config.urlSchemes?.length)urlTypes.push({CFBundleURLName:config.bundleId,CFBundleURLSchemes:config.urlSchemes});if(config.defaultBrowser)urlTypes.push({CFBundleURLName:"Web site URL",CFBundleTypeRole:"Viewer",CFBundleURLSchemes:["http","https"]});const schemes=urlTypes.length?` <key>CFBundleURLTypes</key>${plistValue(urlTypes," ")}
|
|
1
|
+
import{existsSync}from"node:fs";import{join,resolve}from"node:path";import{pathToFileURL}from"node:url";import{plistValue,renderUserlandPlistEntries,xmlEscape}from"./index";export const MACOS_DEFAULTS={minimumSystemVersion:"13.0",category:"public.app-category.productivity",nativeScreensDir:"resources/native",initialScreen:"Main",window:{width:1180,height:760,minWidth:820,minHeight:520}};export async function loadDesktopConfig(root){const file=join(root,"config/desktop.ts");if(!existsSync(file))return null;return(await import(`${pathToFileURL(file).href}?t=${Date.now()}`)).default??null}export async function hasMacosDesktop(root){return Boolean((await loadDesktopConfig(root))?.macos)}export async function loadMacosDesktop(root,packageVersion="0.0.0"){const config=await loadDesktopConfig(root);return config?.macos?resolveMacosDesktop(config.macos,packageVersion):null}export function resolveMacosDesktop(config,packageVersion="0.0.0"){const version=config.version??packageVersion,agent=config.agent?config.agent===!0?{}:{...config.agent}:null;return{...config,agent,url:agent?"http://127.0.0.1":config.url??"",version,buildNumber:config.buildNumber??version.split(/[-+]/)[0],minimumSystemVersion:config.minimumSystemVersion??MACOS_DEFAULTS.minimumSystemVersion,category:config.category??MACOS_DEFAULTS.category,nativeScreensDir:config.nativeScreensDir??MACOS_DEFAULTS.nativeScreensDir,initialScreen:config.initialScreen??(Array.isArray(config.nativeScreens)?config.nativeScreens.includes("Main")?"Main":config.nativeScreens[0]:Object.keys(config.nativeScreens).includes("Main")?"Main":Object.keys(config.nativeScreens)[0])??MACOS_DEFAULTS.initialScreen,sandbox:config.sandbox!==!1,executable:config.appName}}export function validateMacosDesktop(config){const errors=[];if(!config.appName?.trim())errors.push("macos.appName is required");if(!/^[A-Za-z0-9][A-Za-z0-9.-]*\.[A-Za-z0-9.-]+$/.test(config.bundleId??""))errors.push("macos.bundleId must be a reverse-DNS identifier such as com.example.app");if(config.teamId!==void 0&&!/^[A-Z0-9]{10}$/.test(config.teamId))errors.push("macos.teamId must be the 10-character Apple Developer team ID");if(!/^\d+(?:\.\d+){0,2}$/.test(config.version))errors.push(`macos.version must be one to three numeric components, not "${config.version}"`);if(!/^[A-Za-z0-9.-]+$/.test(config.buildNumber))errors.push("macos.buildNumber must contain only letters, numbers, periods and hyphens");if(!/^\d+(?:\.\d+){0,2}$/.test(config.minimumSystemVersion))errors.push("macos.minimumSystemVersion must be a macOS version such as 13.0");if(!/^public\.app-category\.[a-z][a-z0-9-]*$/.test(config.category))errors.push("macos.category must be an LSApplicationCategoryType such as public.app-category.productivity");if(!config.agent)try{const url=new URL(config.url);if(!["http:","https:"].includes(url.protocol))errors.push("macos.url must be an http(s) origin")}catch{errors.push("macos.url must be the server origin the app talks to, e.g. https://example.com, or turn on macos.agent to run the API inside the app")}else if(config.agent.port!==void 0&&!(Number.isInteger(config.agent.port)&&config.agent.port>1024&&config.agent.port<65536))errors.push("macos.agent.port must be a port above 1024");const lights=config.window?.trafficLights;if(lights!==void 0&&!(Array.isArray(lights)&&lights.length===2&&lights.every((value)=>Number.isFinite(value)&&value>=0)))errors.push("macos.window.trafficLights must be [x, y], two points from the window's top-left");for(const[index,item]of(config.dockMenu??[]).entries()){if(!item?.title?.trim())errors.push(`macos.dockMenu[${index}] needs a title`);if(!item?.action?.trim())errors.push(`macos.dockMenu[${index}] needs an action`)}const names=Object.keys(macosScreens(config));if(!names.length)errors.push("macos.nativeScreens must name at least one screen");if(names.length&&!names.includes(config.initialScreen))errors.push(`macos.initialScreen "${config.initialScreen}" is not one of the native screens (${names.join(", ")})`);for(const scheme of config.urlSchemes??[])if(!/^[a-z][a-z0-9+.-]*$/.test(scheme))errors.push(`macos.urlSchemes: "${scheme}" is not a valid URL scheme`);return errors}export function macosScreens(config){const dir=config.nativeScreensDir??MACOS_DEFAULTS.nativeScreensDir;if(Array.isArray(config.nativeScreens))return Object.fromEntries(config.nativeScreens.map((name)=>[name,`${dir}/${name}.stx`]));return{...config.nativeScreens}}export function renderHostConfig(config){const window={...MACOS_DEFAULTS.window,...config.window};return`${JSON.stringify({...config.agent?{}:{apiUrl:config.url.replace(/\/+$/,"")},title:config.appName,route:config.initialScreen,session:Boolean(config.agent),titlebarStyle:window.titlebarStyle??"standard",width:window.width,height:window.height,minWidth:window.minWidth,minHeight:window.minHeight,...window.trafficLights?{trafficLights:window.trafficLights}:{},...config.webkit?{webkit:!0}:{},...config.dockMenu?.length?{dockMenu:config.dockMenu.map((item)=>({title:item.title,action:item.action}))}:{}},null,2)}
|
|
2
|
+
`}export function hostArguments(config,nativeBundle){return["--api-url",config.url.replace(/\/+$/,""),"--native-bundle",nativeBundle,...windowArguments(config),"--no-session"]}export function agentHostArguments(config){return windowArguments(config)}function windowArguments(config){const window={...MACOS_DEFAULTS.window,...config.window};return["--title",config.appName,"--route",config.initialScreen,"--titlebar-style",window.titlebarStyle??"standard","--width",String(window.width),"--height",String(window.height),"--min-width",String(window.minWidth),"--min-height",String(window.minHeight),...window.trafficLights?["--traffic-lights",window.trafficLights.join(",")]:[]]}const OWNED_KEYS=["CFBundleIdentifier","CFBundleExecutable","CFBundleName","CFBundleDisplayName","CFBundleShortVersionString","CFBundleVersion","CFBundlePackageType","LSApplicationCategoryType","LSMinimumSystemVersion","CFBundleIconFile","CFBundleURLTypes"];export const BROWSER_DOCUMENT_TYPES=[{name:"HTML document",types:["public.html"]},{name:"XHTML document",types:["public.xhtml"]},{name:"Web archive",types:["com.apple.webarchive"]},{name:"PDF document",types:["com.adobe.pdf"]}];export function defaultUsageDescriptions(appName){return{camera:`${appName} uses the camera when you allow a page or feature to.`,microphone:`${appName} uses the microphone when you allow a page or feature to.`,location:`${appName} uses your location when you allow a page or feature to.`}}export function permissionUsageDescriptions(config){const permissions=config.permissions??{},defaults=defaultUsageDescriptions(config.appName),sentence=(value,fallback)=>typeof value==="string"&&value.trim()?value:value?fallback:void 0,usage={},camera=sentence(permissions.camera,defaults.camera);if(camera)usage.NSCameraUsageDescription=camera;const microphone=sentence(permissions.microphone,defaults.microphone);if(microphone)usage.NSMicrophoneUsageDescription=microphone;const location=sentence(permissions.location,defaults.location);if(location){usage.NSLocationUsageDescription=location;usage.NSLocationWhenInUseUsageDescription=location}return usage}export function renderMacosInfoPlist(config,options={}){const owns=config.defaultBrowser?[...OWNED_KEYS,"CFBundleDocumentTypes"]:OWNED_KEYS,declared={...permissionUsageDescriptions(config),...config.usageDescriptions,...config.infoPlist};if(config.defaultBrowser&&declared.NSAppTransportSecurity===void 0)declared.NSAppTransportSecurity={NSAllowsArbitraryLoadsInWebContent:!0};const{xml:extra,ignored}=renderUserlandPlistEntries(Object.fromEntries(Object.entries(declared).filter(([key])=>!owns.includes(key)))),owned=Object.keys(declared).filter((key)=>owns.includes(key)),urlTypes=[];if(config.urlSchemes?.length)urlTypes.push({CFBundleURLName:config.bundleId,CFBundleURLSchemes:config.urlSchemes});if(config.defaultBrowser)urlTypes.push({CFBundleURLName:"Web site URL",CFBundleTypeRole:"Viewer",CFBundleURLSchemes:["http","https"]});const schemes=urlTypes.length?` <key>CFBundleURLTypes</key>${plistValue(urlTypes," ")}
|
|
3
3
|
`:"",documents=config.defaultBrowser?` <key>CFBundleDocumentTypes</key>${plistValue(BROWSER_DOCUMENT_TYPES.map((type)=>({CFBundleTypeName:type.name,CFBundleTypeRole:"Viewer",LSHandlerRank:"Default",LSItemContentTypes:type.types}))," ")}
|
|
4
4
|
`:"",icon=options.iconFile?` <key>CFBundleIconFile</key><string>${xmlEscape(options.iconFile)}</string>
|
|
5
5
|
`:"";return{xml:`<?xml version="1.0" encoding="UTF-8"?>
|
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.398",
|
|
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.
|
|
76
|
+
"@stacksjs/config": "0.75.398",
|
|
77
|
+
"@stacksjs/router": "0.75.398",
|
|
78
|
+
"@stacksjs/server": "0.75.398",
|
|
79
79
|
"craft-native": ">=0.0.341"
|
|
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.398",
|
|
83
|
+
"@stacksjs/router": "0.75.398",
|
|
84
|
+
"@stacksjs/server": "0.75.398"
|
|
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.398",
|
|
99
99
|
"better-dx": "^0.2.24"
|
|
100
100
|
}
|
|
101
101
|
}
|