-
Notifications
You must be signed in to change notification settings - Fork 48
Add automatic JS binding generation from WinRT metadata #375
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -4,8 +4,12 @@ import { generateCppAddonFiles } from './cpp-addon-utils'; | |||||
| import { generateCsAddonFiles } from './cs-addon-utils'; | ||||||
| import { addElectronDebugIdentity, clearElectronDebugIdentity } from './msix-utils'; | ||||||
| import { getWinappCliPath, callWinappCli, callWinappCliCapture, WINAPP_CLI_CALLER_VALUE } from './winapp-cli-utils'; | ||||||
| import { autoGenerateJsBindings, generateJsBindings, readJsBindingsConfig } from './js-bindings-utils'; | ||||||
| import { getProjectRootDir } from './utils'; | ||||||
| import { spawn } from 'child_process'; | ||||||
| import * as fs from 'fs'; | ||||||
| import * as path from 'path'; | ||||||
| import * as readline from 'readline'; | ||||||
|
|
||||||
| // CLI name - change this to rebrand the tool | ||||||
| const CLI_NAME = 'winapp'; | ||||||
|
|
@@ -67,6 +71,16 @@ export async function main(): Promise<void> { | |||||
|
|
||||||
| // Route everything else to winapp-cli | ||||||
| await callWinappCli(args, { exitOnError: true }); | ||||||
|
|
||||||
| // Post-init: prompt user to generate JS/TS bindings if this is a Node.js project | ||||||
| if (command === 'init') { | ||||||
| await promptJsBindingsAfterInit({ verbose: args.includes('--verbose') }); | ||||||
| } | ||||||
|
|
||||||
| // Post-restore: auto-generate JS bindings if already configured | ||||||
| if (command === 'restore') { | ||||||
| await autoGenerateJsBindings({ verbose: args.includes('--verbose') }); | ||||||
| } | ||||||
| } catch (error) { | ||||||
| logErrorAndExit(error); | ||||||
| } | ||||||
|
|
@@ -204,6 +218,7 @@ async function showCombinedHelp(): Promise<void> { | |||||
| console.log(''); | ||||||
| console.log('Node.js Subcommands:'); | ||||||
| console.log(' node create-addon Generate native addon files for Electron'); | ||||||
| console.log(' node generate-bindings Generate JS/TS bindings from WinRT metadata'); | ||||||
| console.log(' node add-electron-debug-identity Add package identity to Electron debug process'); | ||||||
| console.log(' node clear-electron-debug-identity Remove package identity from Electron debug process'); | ||||||
| console.log(''); | ||||||
|
|
@@ -268,13 +283,15 @@ async function handleNode(args: string[]): Promise<void> { | |||||
| console.log(''); | ||||||
| console.log('Subcommands:'); | ||||||
| console.log(' create-addon Generate native addon files for Electron'); | ||||||
| console.log(' generate-bindings Generate JS/TS bindings from WinRT metadata'); | ||||||
| console.log(' add-electron-debug-identity Add package identity to Electron debug process'); | ||||||
| console.log(' clear-electron-debug-identity Remove package identity from Electron debug process'); | ||||||
| console.log(''); | ||||||
| console.log('Examples:'); | ||||||
| console.log(` ${CLI_NAME} node create-addon --help`); | ||||||
| console.log(` ${CLI_NAME} node create-addon --name myAddon`); | ||||||
| console.log(` ${CLI_NAME} node create-addon --name myCsAddon --template cs`); | ||||||
| console.log(` ${CLI_NAME} node generate-bindings`); | ||||||
| console.log(` ${CLI_NAME} node add-electron-debug-identity`); | ||||||
| console.log(` ${CLI_NAME} node clear-electron-debug-identity`); | ||||||
| console.log(''); | ||||||
|
|
@@ -298,6 +315,10 @@ async function handleNode(args: string[]): Promise<void> { | |||||
| await handleClearElectronDebugIdentity(subcommandArgs); | ||||||
| break; | ||||||
|
|
||||||
| case 'generate-bindings': | ||||||
| await handleGenerateBindings(subcommandArgs); | ||||||
| break; | ||||||
|
|
||||||
|
Comment on lines
+318
to
+321
|
||||||
| default: | ||||||
| console.error(`❌ Unknown node subcommand: ${subcommand}`); | ||||||
| console.error(`Run "${CLI_NAME} node" for available subcommands.`); | ||||||
|
|
@@ -504,6 +525,161 @@ async function handleClearElectronDebugIdentity(args: string[]): Promise<void> { | |||||
| } | ||||||
| } | ||||||
|
|
||||||
| async function handleGenerateBindings(args: string[]): Promise<void> { | ||||||
| const options = parseArgs(args, { verbose: false }); | ||||||
|
|
||||||
| if (options.help) { | ||||||
| console.log(`Usage: ${CLI_NAME} node generate-bindings [options]`); | ||||||
| console.log(''); | ||||||
| console.log('Generate JS/TS bindings from WinRT metadata'); | ||||||
| console.log(''); | ||||||
| console.log('Reads the jsBindings section from winapp.yaml and generates typed'); | ||||||
| console.log('bindings using winrt-meta. This runs automatically after restore/init'); | ||||||
| console.log('if configured, but can also be called manually.'); | ||||||
| console.log(''); | ||||||
| console.log('Options:'); | ||||||
| console.log(' --verbose Enable verbose output (default: false)'); | ||||||
| console.log(' --help Show this help'); | ||||||
| console.log(''); | ||||||
| console.log('winapp.yaml configuration:'); | ||||||
| console.log(' jsBindings:'); | ||||||
| console.log(' lang: js # js | cjs | ts (default: js)'); | ||||||
| console.log(' output: generated-js # output directory'); | ||||||
| console.log(' packages: # NuGet packages with .winmd metadata'); | ||||||
| console.log(' - Microsoft.WindowsAppSDK.AI'); | ||||||
| console.log(' systemTypes: # additional Windows SDK classes'); | ||||||
| console.log(' - namespace: Windows.Storage'); | ||||||
| console.log(' classes: StorageFile'); | ||||||
| console.log(''); | ||||||
| console.log('Prerequisites:'); | ||||||
| console.log(' - winrt-meta must be installed (npm install -D winrt-meta)'); | ||||||
|
||||||
| console.log(' - winrt-meta must be installed (npm install -D winrt-meta)'); | |
| console.log(' - winrt-meta is included with @microsoft/winappcli'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
autoGenerateJsBindings()is called after everywinapp restore, butgenerateJsBindings()currently auto-creates a defaultjsBindingssection when none exists. This means restore can unexpectedly modifywinapp.yamland attempt generation even when the user hasn’t opted in (and will warn if no consumerpackage.jsonis found due togetProjectRootDir()throwing). Consider guarding the restore hook to only run whenjsBindingsis already present (and only in Node projects), and/or adding an option togenerateJsBindings()to disable auto-init behavior for the restore path.