@choochmeque/tauri-windows-bundle 0.1.15 → 0.1.16

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/README.md CHANGED
@@ -12,6 +12,7 @@ MSIX packaging tool for Tauri apps - create Windows Store ready bundles with mul
12
12
  - **Multiarch Support** - Build for x64 and arm64 in one bundle
13
13
  - **tauri.conf.json Integration** - Automatically reads app name, version, icons, and resources
14
14
  - **Code Signing** - Support for PFX certificates and Windows certificate store
15
+ - **Resource Indexing** - Optional `resources.pri` generation for qualified assets
15
16
  - **Windows Extensions** - Share Target, File Associations, Protocol Handlers, Startup Task, Context Menus, Background Tasks, App Execution Alias, App Services, Toast Activation, Autoplay, Print Task Settings, Thumbnail/Preview Handlers
16
17
 
17
18
  ## Prerequisites
@@ -69,6 +70,10 @@ Edit `src-tauri/gen/windows/bundle.config.json`:
69
70
  "signing": {
70
71
  "pfx": null,
71
72
  "pfxPassword": null
73
+ },
74
+ "resourceIndex": {
75
+ "enabled": false,
76
+ "keepConfig": false
72
77
  }
73
78
  }
74
79
  ```
@@ -93,6 +98,10 @@ Edit `src-tauri/gen/windows/bundle.config.json`:
93
98
 
94
99
  Note: `runFullTrust` is always auto-added (required for Tauri apps).
95
100
 
101
+ `resourceIndex.enabled` generates `resources.pri` via `msixbundle-cli --makepri` before packing. Enable this when using qualified assets (for example, scale-specific logos like `Square44x44Logo.scale-200.png`).
102
+
103
+ `resourceIndex.keepConfig` keeps generated `priconfig.xml` in each `AppxContent` directory for debugging.
104
+
96
105
  **Auto-read from tauri.conf.json / tauri.windows.conf.json:**
97
106
  - `displayName` ← `productName`
98
107
  - `version` ← `version` (auto-converted to 4-part: `1.0.0` → `1.0.0.0`)
package/dist/cli.js CHANGED
@@ -197,6 +197,10 @@ function generateBundleConfig(windowsDir, _tauriConfig) {
197
197
  pfx: null,
198
198
  pfxPassword: null,
199
199
  },
200
+ resourceIndex: {
201
+ enabled: false,
202
+ keepConfig: false,
203
+ },
200
204
  };
201
205
  const configPath = path.join(windowsDir, 'bundle.config.json');
202
206
  fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
@@ -433,6 +437,17 @@ function generateManifest(config, arch, minVersion, windowsDir) {
433
437
  };
434
438
  return replaceTemplateVariables(getManifestTemplate(windowsDir), variables);
435
439
  }
440
+ function getDefaultLanguageFromManifestXml(manifestXml) {
441
+ const languageMatch = manifestXml.match(/<Resource\b[^>]*\bLanguage="([^"]+)"/i);
442
+ return languageMatch?.[1];
443
+ }
444
+ function getDefaultLanguageFromManifestFile(manifestPath) {
445
+ if (!fs.existsSync(manifestPath)) {
446
+ return undefined;
447
+ }
448
+ const manifest = fs.readFileSync(manifestPath, 'utf-8');
449
+ return getDefaultLanguageFromManifestXml(manifest);
450
+ }
436
451
  function generateExtensions(config) {
437
452
  const extensions = [];
438
453
  if (config.extensions?.shareTarget) {
@@ -714,6 +729,8 @@ function prepareAppxContent(projectRoot, arch, config, tauriConfig, minVersion,
714
729
  const srcTauriDir = path.join(projectRoot, 'src-tauri');
715
730
  const buildDir = path.join(srcTauriDir, 'target', target, 'release');
716
731
  const appxDir = path.join(srcTauriDir, 'target', 'appx', arch);
732
+ // Clear stale output from previous builds
733
+ fs.rmSync(appxDir, { recursive: true, force: true });
717
734
  // Create directories
718
735
  fs.mkdirSync(path.join(appxDir, 'Assets'), { recursive: true });
719
736
  // Copy exe
@@ -774,6 +791,16 @@ function copyBundledResources(projectRoot, appxDir, tauriConfig) {
774
791
 
775
792
  const execPromise = promisify(exec);
776
793
  const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
794
+ function isCiEnvironment() {
795
+ const ci = process.env.CI;
796
+ if (!ci)
797
+ return false;
798
+ const normalized = ci.toLowerCase();
799
+ return normalized !== '0' && normalized !== 'false';
800
+ }
801
+ function shouldAnimateSpinner() {
802
+ return Boolean(process.stdout.isTTY) && !isCiEnvironment();
803
+ }
777
804
  class Spinner {
778
805
  frameIndex = 0;
779
806
  intervalId = null;
@@ -838,7 +865,7 @@ function isVersionSufficient(version, minVersion) {
838
865
  return false;
839
866
  return patch >= minPatch;
840
867
  }
841
- const MIN_MSIXBUNDLE_CLI_VERSION = '1.1.0';
868
+ const MIN_MSIXBUNDLE_CLI_VERSION = '1.1.4';
842
869
  async function promptInstall(message) {
843
870
  const rl = readline.createInterface({
844
871
  input: process.stdin,
@@ -854,6 +881,8 @@ async function promptInstall(message) {
854
881
  async function execWithProgress(command, options) {
855
882
  const verbose = options?.verbose ?? false;
856
883
  const message = options?.message ?? 'Running...';
884
+ const useSpinner = !verbose && shouldAnimateSpinner();
885
+ const useStaticProgress = !verbose && !useSpinner;
857
886
  return new Promise((resolve, reject) => {
858
887
  const [cmd, ...args] = command.split(' ');
859
888
  const child = spawn(cmd, args, {
@@ -863,10 +892,13 @@ async function execWithProgress(command, options) {
863
892
  });
864
893
  let spinner = null;
865
894
  let capturedOutput = '';
866
- if (!verbose) {
895
+ if (useSpinner) {
867
896
  spinner = new Spinner(message);
868
897
  spinner.start();
869
898
  }
899
+ else if (useStaticProgress) {
900
+ console.log(message);
901
+ }
870
902
  child.stdout?.on('data', (data) => {
871
903
  if (verbose) {
872
904
  process.stdout.write(data);
@@ -886,10 +918,16 @@ async function execWithProgress(command, options) {
886
918
  child.on('close', (code) => {
887
919
  if (code === 0) {
888
920
  spinner?.stop(true);
921
+ if (useStaticProgress) {
922
+ console.log(`Done: ${message}`);
923
+ }
889
924
  resolve();
890
925
  }
891
926
  else {
892
927
  spinner?.fail();
928
+ if (useStaticProgress) {
929
+ console.error(`Failed: ${message}`);
930
+ }
893
931
  if (!verbose && capturedOutput) {
894
932
  console.error('\nBuild output:\n' + capturedOutput);
895
933
  }
@@ -898,6 +936,9 @@ async function execWithProgress(command, options) {
898
936
  });
899
937
  child.on('error', (error) => {
900
938
  spinner?.fail();
939
+ if (useStaticProgress) {
940
+ console.error(`Failed: ${message}`);
941
+ }
901
942
  if (!verbose && capturedOutput) {
902
943
  console.error('\nBuild output:\n' + capturedOutput);
903
944
  }
@@ -1029,6 +1070,17 @@ async function build(options) {
1029
1070
  outDir,
1030
1071
  ...appxDirs.flatMap(({ arch, dir }) => [`--dir-${arch}`, dir]),
1031
1072
  ];
1073
+ // Resource index generation (resources.pri)
1074
+ if (bundleConfig.resourceIndex?.enabled) {
1075
+ const defaultLanguage = getDefaultLanguageFromManifestFile(path.join(appxDirs[0].dir, 'AppxManifest.xml'));
1076
+ args.push('--makepri');
1077
+ if (defaultLanguage) {
1078
+ args.push('--makepri-default-language', defaultLanguage);
1079
+ }
1080
+ if (bundleConfig.resourceIndex.keepConfig) {
1081
+ args.push('--makepri-keep-config');
1082
+ }
1083
+ }
1032
1084
  // Signing
1033
1085
  if (bundleConfig.signing?.pfx) {
1034
1086
  args.push('--pfx', bundleConfig.signing.pfx);
@@ -2,3 +2,5 @@ import type { MergedConfig } from '../types.js';
2
2
  export declare function getPackageVersion(): string;
3
3
  export declare function generateManifestTemplate(windowsDir: string): void;
4
4
  export declare function generateManifest(config: MergedConfig, arch: string, minVersion: string, windowsDir: string): string;
5
+ export declare function getDefaultLanguageFromManifestXml(manifestXml: string): string | undefined;
6
+ export declare function getDefaultLanguageFromManifestFile(manifestPath: string): string | undefined;
package/dist/index.js CHANGED
@@ -194,6 +194,10 @@ function generateBundleConfig(windowsDir, _tauriConfig) {
194
194
  pfx: null,
195
195
  pfxPassword: null,
196
196
  },
197
+ resourceIndex: {
198
+ enabled: false,
199
+ keepConfig: false,
200
+ },
197
201
  };
198
202
  const configPath = path.join(windowsDir, 'bundle.config.json');
199
203
  fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
@@ -430,6 +434,17 @@ function generateManifest(config, arch, minVersion, windowsDir) {
430
434
  };
431
435
  return replaceTemplateVariables(getManifestTemplate(windowsDir), variables);
432
436
  }
437
+ function getDefaultLanguageFromManifestXml(manifestXml) {
438
+ const languageMatch = manifestXml.match(/<Resource\b[^>]*\bLanguage="([^"]+)"/i);
439
+ return languageMatch?.[1];
440
+ }
441
+ function getDefaultLanguageFromManifestFile(manifestPath) {
442
+ if (!fs.existsSync(manifestPath)) {
443
+ return undefined;
444
+ }
445
+ const manifest = fs.readFileSync(manifestPath, 'utf-8');
446
+ return getDefaultLanguageFromManifestXml(manifest);
447
+ }
433
448
  function generateExtensions(config) {
434
449
  const extensions = [];
435
450
  if (config.extensions?.shareTarget) {
@@ -711,6 +726,8 @@ function prepareAppxContent(projectRoot, arch, config, tauriConfig, minVersion,
711
726
  const srcTauriDir = path.join(projectRoot, 'src-tauri');
712
727
  const buildDir = path.join(srcTauriDir, 'target', target, 'release');
713
728
  const appxDir = path.join(srcTauriDir, 'target', 'appx', arch);
729
+ // Clear stale output from previous builds
730
+ fs.rmSync(appxDir, { recursive: true, force: true });
714
731
  // Create directories
715
732
  fs.mkdirSync(path.join(appxDir, 'Assets'), { recursive: true });
716
733
  // Copy exe
@@ -771,6 +788,16 @@ function copyBundledResources(projectRoot, appxDir, tauriConfig) {
771
788
 
772
789
  const execPromise = promisify(exec);
773
790
  const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
791
+ function isCiEnvironment() {
792
+ const ci = process.env.CI;
793
+ if (!ci)
794
+ return false;
795
+ const normalized = ci.toLowerCase();
796
+ return normalized !== '0' && normalized !== 'false';
797
+ }
798
+ function shouldAnimateSpinner() {
799
+ return Boolean(process.stdout.isTTY) && !isCiEnvironment();
800
+ }
774
801
  class Spinner {
775
802
  frameIndex = 0;
776
803
  intervalId = null;
@@ -835,7 +862,7 @@ function isVersionSufficient(version, minVersion) {
835
862
  return false;
836
863
  return patch >= minPatch;
837
864
  }
838
- const MIN_MSIXBUNDLE_CLI_VERSION = '1.1.0';
865
+ const MIN_MSIXBUNDLE_CLI_VERSION = '1.1.4';
839
866
  async function promptInstall(message) {
840
867
  const rl = readline.createInterface({
841
868
  input: process.stdin,
@@ -851,6 +878,8 @@ async function promptInstall(message) {
851
878
  async function execWithProgress(command, options) {
852
879
  const verbose = options?.verbose ?? false;
853
880
  const message = options?.message ?? 'Running...';
881
+ const useSpinner = !verbose && shouldAnimateSpinner();
882
+ const useStaticProgress = !verbose && !useSpinner;
854
883
  return new Promise((resolve, reject) => {
855
884
  const [cmd, ...args] = command.split(' ');
856
885
  const child = spawn(cmd, args, {
@@ -860,10 +889,13 @@ async function execWithProgress(command, options) {
860
889
  });
861
890
  let spinner = null;
862
891
  let capturedOutput = '';
863
- if (!verbose) {
892
+ if (useSpinner) {
864
893
  spinner = new Spinner(message);
865
894
  spinner.start();
866
895
  }
896
+ else if (useStaticProgress) {
897
+ console.log(message);
898
+ }
867
899
  child.stdout?.on('data', (data) => {
868
900
  if (verbose) {
869
901
  process.stdout.write(data);
@@ -883,10 +915,16 @@ async function execWithProgress(command, options) {
883
915
  child.on('close', (code) => {
884
916
  if (code === 0) {
885
917
  spinner?.stop(true);
918
+ if (useStaticProgress) {
919
+ console.log(`Done: ${message}`);
920
+ }
886
921
  resolve();
887
922
  }
888
923
  else {
889
924
  spinner?.fail();
925
+ if (useStaticProgress) {
926
+ console.error(`Failed: ${message}`);
927
+ }
890
928
  if (!verbose && capturedOutput) {
891
929
  console.error('\nBuild output:\n' + capturedOutput);
892
930
  }
@@ -895,6 +933,9 @@ async function execWithProgress(command, options) {
895
933
  });
896
934
  child.on('error', (error) => {
897
935
  spinner?.fail();
936
+ if (useStaticProgress) {
937
+ console.error(`Failed: ${message}`);
938
+ }
898
939
  if (!verbose && capturedOutput) {
899
940
  console.error('\nBuild output:\n' + capturedOutput);
900
941
  }
@@ -1026,6 +1067,17 @@ async function build(options) {
1026
1067
  outDir,
1027
1068
  ...appxDirs.flatMap(({ arch, dir }) => [`--dir-${arch}`, dir]),
1028
1069
  ];
1070
+ // Resource index generation (resources.pri)
1071
+ if (bundleConfig.resourceIndex?.enabled) {
1072
+ const defaultLanguage = getDefaultLanguageFromManifestFile(path.join(appxDirs[0].dir, 'AppxManifest.xml'));
1073
+ args.push('--makepri');
1074
+ if (defaultLanguage) {
1075
+ args.push('--makepri-default-language', defaultLanguage);
1076
+ }
1077
+ if (bundleConfig.resourceIndex.keepConfig) {
1078
+ args.push('--makepri-keep-config');
1079
+ }
1080
+ }
1029
1081
  // Signing
1030
1082
  if (bundleConfig.signing?.pfx) {
1031
1083
  args.push('--pfx', bundleConfig.signing.pfx);
@@ -1755,4 +1807,4 @@ async function extensionRemove(type, name, options) {
1755
1807
  }
1756
1808
  }
1757
1809
 
1758
- export { DEFAULT_CAPABILITIES, DEFAULT_MIN_WINDOWS_VERSION, DEFAULT_RUNNER, DEVICE_CAPABILITIES, GENERAL_CAPABILITIES, MSIX_ASSETS, RESTRICTED_CAPABILITIES, build, extensionAddAppExecutionAlias, extensionAddAppService, extensionAddAutoplay, extensionAddBackgroundTask, extensionAddContextMenu, extensionAddFileAssociation, extensionAddPreviewHandler, extensionAddProtocol, extensionAddThumbnailHandler, extensionDisablePrintTaskSettings, extensionDisableShareTarget, extensionDisableStartupTask, extensionDisableToastActivation, extensionEnablePrintTaskSettings, extensionEnableShareTarget, extensionEnableStartupTask, extensionEnableToastActivation, extensionList, extensionRemove, findProjectRoot, generateManifest, generateManifestTemplate, getPackageVersion, getWindowsDir, init, prepareAppxContent, readBundleConfig$1 as readBundleConfig, readTauriConfig, readTauriWindowsConfig, resolveVersion, toFourPartVersion, validateCapabilities };
1810
+ export { DEFAULT_CAPABILITIES, DEFAULT_MIN_WINDOWS_VERSION, DEFAULT_RUNNER, DEVICE_CAPABILITIES, GENERAL_CAPABILITIES, MSIX_ASSETS, RESTRICTED_CAPABILITIES, build, extensionAddAppExecutionAlias, extensionAddAppService, extensionAddAutoplay, extensionAddBackgroundTask, extensionAddContextMenu, extensionAddFileAssociation, extensionAddPreviewHandler, extensionAddProtocol, extensionAddThumbnailHandler, extensionDisablePrintTaskSettings, extensionDisableShareTarget, extensionDisableStartupTask, extensionDisableToastActivation, extensionEnablePrintTaskSettings, extensionEnableShareTarget, extensionEnableStartupTask, extensionEnableToastActivation, extensionList, extensionRemove, findProjectRoot, generateManifest, generateManifestTemplate, getDefaultLanguageFromManifestFile, getDefaultLanguageFromManifestXml, getPackageVersion, getWindowsDir, init, prepareAppxContent, readBundleConfig$1 as readBundleConfig, readTauriConfig, readTauriWindowsConfig, resolveVersion, toFourPartVersion, validateCapabilities };
package/dist/types.d.ts CHANGED
@@ -24,6 +24,10 @@ export interface CapabilitiesConfig {
24
24
  export interface BundleConfig {
25
25
  publisher?: string;
26
26
  publisherDisplayName?: string;
27
+ resourceIndex?: {
28
+ enabled?: boolean;
29
+ keepConfig?: boolean;
30
+ };
27
31
  capabilities?: CapabilitiesConfig;
28
32
  extensions?: {
29
33
  shareTarget?: boolean;
@@ -16,7 +16,7 @@ export declare function execAsync(command: string, options?: {
16
16
  export declare function isMsixbundleCliInstalled(): Promise<boolean>;
17
17
  export declare function getMsixbundleCliVersion(): Promise<string | null>;
18
18
  export declare function isVersionSufficient(version: string, minVersion: string): boolean;
19
- export declare const MIN_MSIXBUNDLE_CLI_VERSION = "1.1.0";
19
+ export declare const MIN_MSIXBUNDLE_CLI_VERSION = "1.1.4";
20
20
  export declare function promptInstall(message: string): Promise<boolean>;
21
21
  export interface ExecWithProgressOptions {
22
22
  cwd?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@choochmeque/tauri-windows-bundle",
3
- "version": "0.1.15",
3
+ "version": "0.1.16",
4
4
  "description": "MSIX packaging tool for Tauri apps - Windows Store ready bundles",
5
5
  "type": "module",
6
6
  "bin": {