Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c616694
feat(windows): add support for windows uwp/appx capabilities
regnete Dec 9, 2025
34a5131
Merge remote-tracking branch 'electron-userland/master' into feat/win…
regnete Dec 9, 2025
53e4933
Merge branch 'electron-userland:master' into feat/windows-capabilities
regnete Dec 9, 2025
e0b77de
Merge branch 'master' into feat/windows-capabilities
regnete Dec 12, 2025
61dde96
Merge branch 'master' into feat/windows-capabilities
regnete Jan 19, 2026
e47eae4
Merge branch 'feat/windows-capabilities' of https://github.com/sitewa…
regnete Jan 19, 2026
bb7762e
optimization suggested by mmaietta
regnete Jan 19, 2026
b6aaaec
optimization suggested by mmaietta
regnete Jan 19, 2026
a44f0ca
removed unused namespaces
regnete Jan 19, 2026
377689c
updated
regnete Jan 19, 2026
6e8f22b
Create serious-doors-retire.md
regnete Jan 19, 2026
13caa27
code layout
regnete Jan 20, 2026
2ec9711
avoid double space in generated xml fragment
regnete Jan 20, 2026
8c1fa66
Merge branch 'electron-userland:master' into feat/windows-capabilities
regnete Jan 20, 2026
3fbebf3
validate capability names (https://github.com/electron-userland/elect…
regnete Jan 20, 2026
372e00b
tests for capability feature (https://github.com/electron-userland/el…
regnete Jan 20, 2026
83c0a75
fixed typo
regnete Jan 21, 2026
0ed5d58
fixed order of capabilities
regnete Jan 26, 2026
84d9613
fixed capability related test
regnete Jan 26, 2026
f65eb81
fixed compile errors
regnete Jan 27, 2026
f0c27b1
Merge branch 'electron-userland:master' into feat/windows-capabilities
regnete Jan 28, 2026
653db19
prettier
regnete Jan 28, 2026
7a8217d
Merge remote-tracking branch 'origin/feat/windows-capabilities' into …
regnete Jan 28, 2026
4849551
fixed appx capabilities order, removed uap11 namespace as not support…
regnete Jan 28, 2026
dca9e38
removed uap11 namespace as not supported by MakeAppx.exe
regnete Jan 28, 2026
5654d24
removed uap11 namespace as not supported by MakeAppx.exe
regnete Jan 28, 2026
2f9a5fb
fixed code style
regnete Jan 29, 2026
92b748c
Merge branch 'master' into feat/windows-capabilities
regnete Jan 29, 2026
2ca7e45
Merge branch 'master' into feat/windows-capabilities
regnete Jan 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/serious-doors-retire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"app-builder-lib": minor
---

adding optional config property `capabilities` to AppxOptions (#9436)
16 changes: 15 additions & 1 deletion packages/app-builder-lib/scheme.json
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,26 @@
"string"
]
},
"capabilities": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"description": "The list of [capabilities](https://learn.microsoft.com/en-us/windows/uwp/packaging/app-capability-declarations) to be added to an `appmanifest.xml`.\nThe `runFullTrust` capability is obligatory for electron apps and will be auto added if not specified here.\nDefaults to `['runFullTrust']` if omitted\nExample: `['runFullTrust', 'privateNetworkClientServer', 'webcam']`"
},
"customExtensionsPath": {
"description": "Relative path to custom extensions xml to be included in an `appmanifest.xml`.",
"type": "string"
},
"customManifestPath": {
"description": "(Advanced Option) Relative path to custom `appmanifest.xml` (file name doesn't matter, it'll be renamed) located in build resources directory.\nSupports the following template macros:\n\n- ${publisher}\n- ${publisherDisplayName}\n- ${version}\n- ${applicationId}\n- ${identityName}\n- ${executable}\n- ${displayName}\n- ${description}\n- ${backgroundColor}\n- ${logo}\n- ${square150x150Logo}\n- ${square44x44Logo}\n- ${lockScreen}\n- ${defaultTile}\n- ${splashScreen}\n- ${arch}\n- ${resourceLanguages}\n- ${extensions}\n- ${minVersion}\n- ${maxVersionTested}",
"description": "(Advanced Option) Relative path to custom `appmanifest.xml` (file name doesn't matter, it'll be renamed) located in build resources directory.\nSupports the following template macros:\n\n- ${publisher}\n- ${publisherDisplayName}\n- ${version}\n- ${applicationId}\n- ${identityName}\n- ${executable}\n- ${displayName}\n- ${description}\n- ${backgroundColor}\n- ${logo}\n- ${square150x150Logo}\n- ${square44x44Logo}\n- ${lockScreen}\n- ${defaultTile}\n- ${splashScreen}\n- ${arch}\n- ${resourceLanguages}\n- ${capabilities}\n- ${extensions}\n- ${minVersion}\n- ${maxVersionTested}",
"type": "string"
},
"displayName": {
Expand Down
9 changes: 9 additions & 0 deletions packages/app-builder-lib/src/options/AppXOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ export interface AppXOptions extends TargetSpecificOptions {
*/
readonly customExtensionsPath?: string

/**
* The list of [capabilities](https://learn.microsoft.com/en-us/windows/uwp/packaging/app-capability-declarations) to be added to an `appmanifest.xml`.
* The `runFullTrust` capability is obligatory for electron apps and will be auto added if not specified here.
* Defaults to `['runFullTrust']` if omitted
* Example: `['runFullTrust', 'privateNetworkClientServer', 'webcam']`
*/
readonly capabilities?: Array<string> | null

/**
* (Advanced Option) Relative path to custom `appmanifest.xml` (file name doesn't matter, it'll be renamed) located in build resources directory.
* Supports the following template macros:
Expand All @@ -72,6 +80,7 @@ export interface AppXOptions extends TargetSpecificOptions {
* - ${splashScreen}
* - ${arch}
* - ${resourceLanguages}
* - ${capabilities}
* - ${extensions}
* - ${minVersion}
* - ${maxVersionTested}
Expand Down
284 changes: 284 additions & 0 deletions packages/app-builder-lib/src/targets/AppxCapabilities.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
export interface Capability {
readonly nsAlias: string | null
readonly nsURI: string | null
readonly name: string

toXMLString(): string
}

type CapabilityConfig = {
nsAlias: string | null
nsURI: string | null
declareNS: boolean
elementName: string
}

class AppxCapability implements Capability {
constructor(
public readonly nsAlias: string | null,
public readonly nsURI: string | null,
private readonly declareNS: boolean,
private readonly elementName: string,
public readonly name: string
) {
if (!this.nsAlias && this.declareNS) {
throw new Error("local declaration of namespace without prefix is not supported")
}
}

toXMLString(): string {
const tagName = this.nsAlias ? `${this.nsAlias}:${this.elementName}` : this.elementName
if (this.declareNS) {
return `<${tagName} xmlns:${this.nsAlias}="${this.nsURI}" Name="${this.name}"/>`
}
return `<${tagName} Name="${this.name}"/>`
}
}

// Capability type configurations
const CAPABILITY_TYPES: Record<string, CapabilityConfig> = {
common: {
nsAlias: null,
nsURI: "http://schemas.microsoft.com/appx/manifest/foundation/windows10",
declareNS: false,
elementName: "Capability",
},
uap: {
nsAlias: "uap",
nsURI: "http://schemas.microsoft.com/appx/manifest/uap/windows10",
declareNS: false, // ns already declared in template
elementName: "Capability",
},
device: {
nsAlias: null,
nsURI: "http://schemas.microsoft.com/appx/manifest/foundation/windows10",
declareNS: false,
elementName: "DeviceCapability",
},
uap6: {
nsAlias: "uap6",
nsURI: "http://schemas.microsoft.com/appx/manifest/uap/windows10/6",
declareNS: true,
elementName: "Capability",
},
uap7: {
nsAlias: "uap7",
nsURI: "http://schemas.microsoft.com/appx/manifest/uap/windows10/7",
declareNS: true,
elementName: "Capability",
},
mobile: {
nsAlias: "mobile",
nsURI: "http://schemas.microsoft.com/appx/manifest/mobile/windows10",
declareNS: true,
elementName: "Capability",
},
rescap: {
nsAlias: "rescap",
nsURI: "http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities",
declareNS: false, // ns already declared in template
elementName: "Capability",
},
} as const

type CapabilityType = keyof typeof CAPABILITY_TYPES

// Map of capability types to their capability names (grouped by type)
const CAPABILITY_MAP = new Map<CapabilityType, string[]>([
// Common capabilities
[
"common",
[
"internetClient",
"internetClientServer",
"privateNetworkClientServer",
"codeGeneration",
"allJoyn",
"backgroundMediaPlayback",
"remoteSystem",
"spatialPerception",
"userDataTasks",
"userNotificationListener",
],
],

// UAP capabilities
[
"uap",
[
"musicLibrary",
"picturesLibrary",
"videosLibrary",
"removableStorage",
"appointments",
"contacts",
"phoneCall",
"phoneCallHistoryPublic",
"userAccountInformation",
"voipCall",
"objects3D",
"chat",
"blockedChatMessages",
"enterpriseAuthentication",
"sharedUserCertificates",
"documentsLibrary",
],
],

// Mobile capabilities
["mobile", ["recordedCallsFolder"]],

// Restricted capabilities
[
"rescap",
[
"enterpriseDataPolicy",
"appCaptureSettings",
"cellularDeviceControl",
"cellularDeviceIdentity",
"cellularMessaging",
"deviceUnlock",
"dualSimTiles",
"enterpriseDeviceLockdown",
"inputInjectionBrokered",
"inputObservation",
"inputSuppression",
"networkingVpnProvider",
"packageManagement",
"screenDuplication",
"userPrincipalName",
"walletSystem",
"locationHistory",
"confirmAppClose",
"phoneCallHistory",
"appointmentsSystem",
"chatSystem",
"contactsSystem",
"email",
"emailSystem",
"phoneCallHistorySystem",
"smsSend",
"userDataSystem",
"previewStore",
"firstSignInSettings",
"teamEditionExperience",
"remotePassportAuthentication",
"previewUiComposition",
"secureAssessment",
"networkConnectionManagerProvisioning",
"networkDataPlanProvisioning",
"slapiQueryLicenseValue",
"extendedBackgroundTaskTime",
"extendedExecutionBackgroundAudio",
"extendedExecutionCritical",
"extendedExecutionUnconstrained",
"deviceManagementDmAccount",
"deviceManagementFoundation",
"deviceManagementWapSecurityPolicies",
"deviceManagementEmailAccount",
"packagePolicySystem",
"gameList",
"xboxAccessoryManagement",
"cortanaSpeechAccessory",
"accessoryManager",
"interopServices",
"inputForegroundObservation",
"oemDeployment",
"oemPublicDirectory",
"appLicensing",
"locationSystem",
"userDataAccountsProvider",
"previewPenWorkspace",
"secondaryAuthenticationFactor",
"storeLicenseManagement",
"userSystemId",
"targetedContent",
"uiAutomation",
"gameBarServices",
"appCaptureServices",
"appBroadcastServices",
"audioDeviceConfiguration",
"backgroundMediaRecording",
"previewInkWorkspace",
"startScreenManagement",
"cortanaPermissions",
"allAppMods",
"expandedResources",
"protectedApp",
"gameMonitor",
"appDiagnostics",
"devicePortalProvider",
"enterpriseCloudSSO",
"backgroundVoIP",
"oneProcessVoIP",
"developmentModeNetwork",
"broadFileSystemAccess",
"smbios",
"runFullTrust",
"allowElevation",
"teamEditionDeviceCredential",
"teamEditionView",
"cameraProcessingExtension",
"networkDataUsageManagement",
"phoneLineTransportManagement",
"unvirtualizedResources",
"modifiableApp",
"packageWriteRedirectionCompatibilityShim",
"customInstallActions",
"packagedServices",
"localSystemServices",
"backgroundSpatialPerception",
"uiAccess",
],
],

// UAP6 capabilities
["uap6", ["graphicsCapture"]],

// UAP7 capabilities
["uap7", ["globalMediaControl"]],

// Device capabilities
[
"device",
[
"location",
"microphone",
"webcam",
"proximity",
"pointOfService",
"wiFiControl",
"radios",
"optical",
"activity",
"humanPresence",
"serialcommunication",
"gazeInput",
"lowLevel",
"packageQuery",
],
],
])

// Factory function to create capabilities
function createCapability(type: CapabilityType, name: string): Capability {
const config = CAPABILITY_TYPES[type]
if (!config) {
throw new Error(`unknown capability type '${type}'`)
}
return new AppxCapability(config.nsAlias, config.nsURI, config.declareNS, config.elementName, name)
}

// Export ordered list of all capabilities (order matters per Microsoft docs)
// Schema: https://learn.microsoft.com/en-us/uwp/schemas/appxpackage/uapmanifestschema/schema-root
// Packaging: https://learn.microsoft.com/en-us/windows/uwp/packaging/app-capability-declarations
// !! the docs are not clear in which order is correct. the schema doc specifies an order that differs from the order described in packaging doc !!
// https://learn.microsoft.com/en-us/answers/questions/92754/why-does-the-order-of-items-in-(capabilities)-of-p
// as stated in the above post the packaging docs is the one to follow as MakeAppx.exe is following this specification when it checks the manifests validity
export const CAPABILITIES: Capability[] = Array.from(CAPABILITY_MAP.entries()).flatMap(([type, names]) => names.map(name => createCapability(type, name)))

const CAPABILITY_NAMES: Set<string> = new Set<string>(Array.from(CAPABILITY_MAP.values()).flat())

export function isValidCapabilityName(name: string | null | undefined): boolean {
return !!name && CAPABILITY_NAMES.has(name)
}
Loading
Loading