@choochmeque/tauri-windows-bundle 0.1.6 → 0.1.7

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
@@ -47,9 +47,12 @@ npx @choochmeque/tauri-windows-bundle init
47
47
  This creates:
48
48
  - `src-tauri/gen/windows/bundle.config.json` - MSIX-specific configuration
49
49
  - `src-tauri/gen/windows/AppxManifest.xml.template` - Manifest template
50
- - `src-tauri/gen/windows/Assets/` - Placeholder icons
50
+ - `src-tauri/gen/windows/Assets/` - Icons (copied from `src-tauri/icons/` or placeholders)
51
+ - Adds `@choochmeque/tauri-windows-bundle` as devDependency
51
52
  - Adds `tauri:windows:build` script to package.json
52
53
 
54
+ **Note:** If Tauri icons exist in `src-tauri/icons/`, they are automatically copied. The wide tile (310x150) is generated by centering the square icon.
55
+
53
56
  ### Configure
54
57
 
55
58
  Edit `src-tauri/gen/windows/bundle.config.json`:
@@ -110,6 +113,8 @@ npx @choochmeque/tauri-windows-bundle build [options]
110
113
  --arch <archs> Architectures (comma-separated: x64,arm64) [default: x64]
111
114
  --release Build in release mode
112
115
  --min-windows <ver> Minimum Windows version [default: 10.0.17763.0]
116
+ --runner <runner> Build runner (cargo, pnpm, npm, yarn, bun) [default: cargo]
117
+ --verbose Show full build output instead of spinner
113
118
 
114
119
  npx @choochmeque/tauri-windows-bundle extension list
115
120
  -p, --path <path> Path to Tauri project
package/dist/cli.js CHANGED
@@ -2,6 +2,7 @@
2
2
  import { Command } from 'commander';
3
3
  import * as fs from 'node:fs';
4
4
  import * as path from 'node:path';
5
+ import { Jimp } from 'jimp';
5
6
  import { fileURLToPath } from 'node:url';
6
7
  import { glob } from 'glob';
7
8
  import { exec, spawn } from 'node:child_process';
@@ -101,18 +102,80 @@ function generateGitignore(windowsDir) {
101
102
  fs.writeFileSync(gitignorePath, content);
102
103
  }
103
104
 
104
- async function generateAssets(windowsDir) {
105
+ // Map MSIX asset names to Tauri icon names
106
+ const TAURI_ICON_MAP = {
107
+ 'StoreLogo.png': 'StoreLogo.png',
108
+ 'Square44x44Logo.png': 'Square44x44Logo.png',
109
+ 'Square150x150Logo.png': 'Square150x150Logo.png',
110
+ 'LargeTile.png': 'Square310x310Logo.png',
111
+ };
112
+ function getTauriIconsDir(projectRoot) {
113
+ return path.join(projectRoot, 'src-tauri', 'icons');
114
+ }
115
+ async function generateAssets(windowsDir, projectRoot) {
105
116
  const assetsDir = path.join(windowsDir, 'Assets');
106
117
  fs.mkdirSync(assetsDir, { recursive: true });
118
+ const tauriIconsDir = projectRoot ? getTauriIconsDir(projectRoot) : null;
119
+ let copiedFromTauri = false;
107
120
  for (const asset of MSIX_ASSETS) {
108
121
  const width = asset.width || asset.size || 50;
109
122
  const height = asset.height || asset.size || 50;
110
123
  const assetPath = path.join(assetsDir, asset.name);
111
- // Generate a simple placeholder PNG
112
- const pngData = createPlaceholderPng(width, height);
113
- fs.writeFileSync(assetPath, pngData);
124
+ // Check if we can copy from Tauri icons
125
+ const tauriIconName = TAURI_ICON_MAP[asset.name];
126
+ const tauriIconPath = tauriIconsDir && tauriIconName ? path.join(tauriIconsDir, tauriIconName) : null;
127
+ if (tauriIconPath && fs.existsSync(tauriIconPath)) {
128
+ fs.copyFileSync(tauriIconPath, assetPath);
129
+ copiedFromTauri = true;
130
+ }
131
+ else if (asset.name === 'Wide310x150Logo.png' && tauriIconsDir) {
132
+ // Generate wide tile from square icon
133
+ const generated = await generateWideTile(tauriIconsDir, assetPath);
134
+ if (!generated) {
135
+ const pngData = createPlaceholderPng(width, height);
136
+ fs.writeFileSync(assetPath, pngData);
137
+ }
138
+ else {
139
+ copiedFromTauri = true;
140
+ }
141
+ }
142
+ else {
143
+ // Fall back to placeholder
144
+ const pngData = createPlaceholderPng(width, height);
145
+ fs.writeFileSync(assetPath, pngData);
146
+ }
147
+ }
148
+ if (copiedFromTauri) {
149
+ console.log(' Copied assets from src-tauri/icons');
150
+ }
151
+ else {
152
+ console.log(' Generated placeholder assets - replace with real icons before publishing');
114
153
  }
115
- console.log(' Generated placeholder assets - replace with real icons before publishing');
154
+ return copiedFromTauri;
155
+ }
156
+ async function generateWideTile(tauriIconsDir, outputPath) {
157
+ // Try to find a square icon to use as source
158
+ const sourceIcons = ['Square150x150Logo.png', 'Square142x142Logo.png', 'icon.png', '128x128.png'];
159
+ for (const iconName of sourceIcons) {
160
+ const iconPath = path.join(tauriIconsDir, iconName);
161
+ if (fs.existsSync(iconPath)) {
162
+ try {
163
+ const image = await Jimp.read(iconPath);
164
+ const iconSize = 150; // Height of the wide tile
165
+ const resized = image.clone().resize({ w: iconSize, h: iconSize });
166
+ // Create 310x150 canvas with transparent background
167
+ const canvas = new Jimp({ width: 310, height: 150, color: 0x00000000 });
168
+ const x = Math.floor((310 - iconSize) / 2);
169
+ canvas.composite(resized, x, 0);
170
+ await canvas.write(outputPath);
171
+ return true;
172
+ }
173
+ catch {
174
+ // Try next icon
175
+ }
176
+ }
177
+ }
178
+ return false;
116
179
  }
117
180
  function createPlaceholderPng(width, height) {
118
181
  // Create a minimal valid PNG file (solid gray square)
@@ -225,6 +288,10 @@ function findPackageRoot(startDir) {
225
288
  const PACKAGE_ROOT = findPackageRoot(__dirname$1);
226
289
  const TEMPLATES_DIR = path.join(PACKAGE_ROOT, 'templates');
227
290
  const EXTENSIONS_DIR = path.join(TEMPLATES_DIR, 'extensions');
291
+ function getPackageVersion() {
292
+ const pkg = JSON.parse(fs.readFileSync(path.join(PACKAGE_ROOT, 'package.json'), 'utf-8'));
293
+ return pkg.version;
294
+ }
228
295
  function loadTemplate(templatePath) {
229
296
  return fs.readFileSync(templatePath, 'utf-8');
230
297
  }
@@ -454,20 +521,25 @@ async function init(options) {
454
521
  // Generate AppxManifest.xml template
455
522
  generateManifestTemplate(windowsDir);
456
523
  console.log(' Created AppxManifest.xml.template');
457
- // Generate placeholder assets
458
- await generateAssets(windowsDir);
524
+ // Generate assets (copy from src-tauri/icons or generate placeholders)
525
+ const assetsCopied = await generateAssets(windowsDir, projectRoot);
459
526
  // Generate .gitignore
460
527
  generateGitignore(windowsDir);
461
- // Update package.json with build script
528
+ // Update package.json with devDependency and build script
462
529
  updatePackageJson(projectRoot);
463
- console.log(' Added tauri:windows:build script to package.json');
464
530
  console.log('\n Windows bundle configuration created!');
465
531
  console.log(`\nNext steps:`);
466
- console.log(` 1. Edit src-tauri/gen/windows/bundle.config.json`);
532
+ console.log(` 1. Run: pnpm install`);
533
+ console.log(` 2. Edit src-tauri/gen/windows/bundle.config.json`);
467
534
  console.log(` - Set your publisher CN (from your code signing certificate)`);
468
535
  console.log(` - Set your publisher display name`);
469
- console.log(` 2. Replace placeholder icons in src-tauri/gen/windows/Assets/`);
470
- console.log(` 3. Run: pnpm tauri:windows:build`);
536
+ if (!assetsCopied) {
537
+ console.log(` 3. Replace placeholder icons in src-tauri/gen/windows/Assets/`);
538
+ console.log(` 4. Run: pnpm tauri:windows:build`);
539
+ }
540
+ else {
541
+ console.log(` 3. Run: pnpm tauri:windows:build`);
542
+ }
471
543
  }
472
544
  function updatePackageJson(projectRoot) {
473
545
  const packageJsonPath = path.join(projectRoot, 'package.json');
@@ -478,13 +550,16 @@ function updatePackageJson(projectRoot) {
478
550
  try {
479
551
  const content = fs.readFileSync(packageJsonPath, 'utf-8');
480
552
  const pkg = JSON.parse(content);
481
- if (!pkg.scripts) {
482
- pkg.scripts = {};
483
- }
553
+ // Add devDependency
554
+ pkg.devDependencies = pkg.devDependencies || {};
555
+ pkg.devDependencies['@choochmeque/tauri-windows-bundle'] = `^${getPackageVersion()}`;
556
+ // Add script
557
+ pkg.scripts = pkg.scripts || {};
484
558
  if (!pkg.scripts['tauri:windows:build']) {
485
559
  pkg.scripts['tauri:windows:build'] = 'tauri-windows-bundle build';
486
- fs.writeFileSync(packageJsonPath, JSON.stringify(pkg, null, 2) + '\n');
487
560
  }
561
+ fs.writeFileSync(packageJsonPath, JSON.stringify(pkg, null, 2) + '\n');
562
+ console.log(' Updated package.json with devDependency and build script');
488
563
  }
489
564
  catch (error) {
490
565
  console.log(` Warning: Could not update package.json: ${error instanceof Error ? error.message : error}`);
@@ -1,3 +1,4 @@
1
1
  import type { MergedConfig } from '../types.js';
2
+ export declare function getPackageVersion(): string;
2
3
  export declare function generateManifestTemplate(windowsDir: string): void;
3
4
  export declare function generateManifest(config: MergedConfig, arch: string, minVersion: string): string;
@@ -1 +1 @@
1
- export declare function generateAssets(windowsDir: string): Promise<void>;
1
+ export declare function generateAssets(windowsDir: string, projectRoot?: string): Promise<boolean>;
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as fs from 'node:fs';
2
2
  import * as path from 'node:path';
3
+ import { Jimp } from 'jimp';
3
4
  import { fileURLToPath } from 'node:url';
4
5
  import { glob } from 'glob';
5
6
  import { exec, spawn } from 'node:child_process';
@@ -99,18 +100,80 @@ function generateGitignore(windowsDir) {
99
100
  fs.writeFileSync(gitignorePath, content);
100
101
  }
101
102
 
102
- async function generateAssets(windowsDir) {
103
+ // Map MSIX asset names to Tauri icon names
104
+ const TAURI_ICON_MAP = {
105
+ 'StoreLogo.png': 'StoreLogo.png',
106
+ 'Square44x44Logo.png': 'Square44x44Logo.png',
107
+ 'Square150x150Logo.png': 'Square150x150Logo.png',
108
+ 'LargeTile.png': 'Square310x310Logo.png',
109
+ };
110
+ function getTauriIconsDir(projectRoot) {
111
+ return path.join(projectRoot, 'src-tauri', 'icons');
112
+ }
113
+ async function generateAssets(windowsDir, projectRoot) {
103
114
  const assetsDir = path.join(windowsDir, 'Assets');
104
115
  fs.mkdirSync(assetsDir, { recursive: true });
116
+ const tauriIconsDir = projectRoot ? getTauriIconsDir(projectRoot) : null;
117
+ let copiedFromTauri = false;
105
118
  for (const asset of MSIX_ASSETS) {
106
119
  const width = asset.width || asset.size || 50;
107
120
  const height = asset.height || asset.size || 50;
108
121
  const assetPath = path.join(assetsDir, asset.name);
109
- // Generate a simple placeholder PNG
110
- const pngData = createPlaceholderPng(width, height);
111
- fs.writeFileSync(assetPath, pngData);
122
+ // Check if we can copy from Tauri icons
123
+ const tauriIconName = TAURI_ICON_MAP[asset.name];
124
+ const tauriIconPath = tauriIconsDir && tauriIconName ? path.join(tauriIconsDir, tauriIconName) : null;
125
+ if (tauriIconPath && fs.existsSync(tauriIconPath)) {
126
+ fs.copyFileSync(tauriIconPath, assetPath);
127
+ copiedFromTauri = true;
128
+ }
129
+ else if (asset.name === 'Wide310x150Logo.png' && tauriIconsDir) {
130
+ // Generate wide tile from square icon
131
+ const generated = await generateWideTile(tauriIconsDir, assetPath);
132
+ if (!generated) {
133
+ const pngData = createPlaceholderPng(width, height);
134
+ fs.writeFileSync(assetPath, pngData);
135
+ }
136
+ else {
137
+ copiedFromTauri = true;
138
+ }
139
+ }
140
+ else {
141
+ // Fall back to placeholder
142
+ const pngData = createPlaceholderPng(width, height);
143
+ fs.writeFileSync(assetPath, pngData);
144
+ }
145
+ }
146
+ if (copiedFromTauri) {
147
+ console.log(' Copied assets from src-tauri/icons');
148
+ }
149
+ else {
150
+ console.log(' Generated placeholder assets - replace with real icons before publishing');
112
151
  }
113
- console.log(' Generated placeholder assets - replace with real icons before publishing');
152
+ return copiedFromTauri;
153
+ }
154
+ async function generateWideTile(tauriIconsDir, outputPath) {
155
+ // Try to find a square icon to use as source
156
+ const sourceIcons = ['Square150x150Logo.png', 'Square142x142Logo.png', 'icon.png', '128x128.png'];
157
+ for (const iconName of sourceIcons) {
158
+ const iconPath = path.join(tauriIconsDir, iconName);
159
+ if (fs.existsSync(iconPath)) {
160
+ try {
161
+ const image = await Jimp.read(iconPath);
162
+ const iconSize = 150; // Height of the wide tile
163
+ const resized = image.clone().resize({ w: iconSize, h: iconSize });
164
+ // Create 310x150 canvas with transparent background
165
+ const canvas = new Jimp({ width: 310, height: 150, color: 0x00000000 });
166
+ const x = Math.floor((310 - iconSize) / 2);
167
+ canvas.composite(resized, x, 0);
168
+ await canvas.write(outputPath);
169
+ return true;
170
+ }
171
+ catch {
172
+ // Try next icon
173
+ }
174
+ }
175
+ }
176
+ return false;
114
177
  }
115
178
  function createPlaceholderPng(width, height) {
116
179
  // Create a minimal valid PNG file (solid gray square)
@@ -223,6 +286,10 @@ function findPackageRoot(startDir) {
223
286
  const PACKAGE_ROOT = findPackageRoot(__dirname$1);
224
287
  const TEMPLATES_DIR = path.join(PACKAGE_ROOT, 'templates');
225
288
  const EXTENSIONS_DIR = path.join(TEMPLATES_DIR, 'extensions');
289
+ function getPackageVersion() {
290
+ const pkg = JSON.parse(fs.readFileSync(path.join(PACKAGE_ROOT, 'package.json'), 'utf-8'));
291
+ return pkg.version;
292
+ }
226
293
  function loadTemplate(templatePath) {
227
294
  return fs.readFileSync(templatePath, 'utf-8');
228
295
  }
@@ -452,20 +519,25 @@ async function init(options) {
452
519
  // Generate AppxManifest.xml template
453
520
  generateManifestTemplate(windowsDir);
454
521
  console.log(' Created AppxManifest.xml.template');
455
- // Generate placeholder assets
456
- await generateAssets(windowsDir);
522
+ // Generate assets (copy from src-tauri/icons or generate placeholders)
523
+ const assetsCopied = await generateAssets(windowsDir, projectRoot);
457
524
  // Generate .gitignore
458
525
  generateGitignore(windowsDir);
459
- // Update package.json with build script
526
+ // Update package.json with devDependency and build script
460
527
  updatePackageJson(projectRoot);
461
- console.log(' Added tauri:windows:build script to package.json');
462
528
  console.log('\n Windows bundle configuration created!');
463
529
  console.log(`\nNext steps:`);
464
- console.log(` 1. Edit src-tauri/gen/windows/bundle.config.json`);
530
+ console.log(` 1. Run: pnpm install`);
531
+ console.log(` 2. Edit src-tauri/gen/windows/bundle.config.json`);
465
532
  console.log(` - Set your publisher CN (from your code signing certificate)`);
466
533
  console.log(` - Set your publisher display name`);
467
- console.log(` 2. Replace placeholder icons in src-tauri/gen/windows/Assets/`);
468
- console.log(` 3. Run: pnpm tauri:windows:build`);
534
+ if (!assetsCopied) {
535
+ console.log(` 3. Replace placeholder icons in src-tauri/gen/windows/Assets/`);
536
+ console.log(` 4. Run: pnpm tauri:windows:build`);
537
+ }
538
+ else {
539
+ console.log(` 3. Run: pnpm tauri:windows:build`);
540
+ }
469
541
  }
470
542
  function updatePackageJson(projectRoot) {
471
543
  const packageJsonPath = path.join(projectRoot, 'package.json');
@@ -476,13 +548,16 @@ function updatePackageJson(projectRoot) {
476
548
  try {
477
549
  const content = fs.readFileSync(packageJsonPath, 'utf-8');
478
550
  const pkg = JSON.parse(content);
479
- if (!pkg.scripts) {
480
- pkg.scripts = {};
481
- }
551
+ // Add devDependency
552
+ pkg.devDependencies = pkg.devDependencies || {};
553
+ pkg.devDependencies['@choochmeque/tauri-windows-bundle'] = `^${getPackageVersion()}`;
554
+ // Add script
555
+ pkg.scripts = pkg.scripts || {};
482
556
  if (!pkg.scripts['tauri:windows:build']) {
483
557
  pkg.scripts['tauri:windows:build'] = 'tauri-windows-bundle build';
484
- fs.writeFileSync(packageJsonPath, JSON.stringify(pkg, null, 2) + '\n');
485
558
  }
559
+ fs.writeFileSync(packageJsonPath, JSON.stringify(pkg, null, 2) + '\n');
560
+ console.log(' Updated package.json with devDependency and build script');
486
561
  }
487
562
  catch (error) {
488
563
  console.log(` Warning: Could not update package.json: ${error instanceof Error ? error.message : error}`);
@@ -1512,4 +1587,4 @@ async function extensionRemove(type, name, options) {
1512
1587
  }
1513
1588
  }
1514
1589
 
1515
- export { DEFAULT_CAPABILITIES, DEFAULT_MIN_WINDOWS_VERSION, DEFAULT_RUNNER, MSIX_ASSETS, build, extensionAddAppExecutionAlias, extensionAddAppService, extensionAddAutoplay, extensionAddBackgroundTask, extensionAddContextMenu, extensionAddFileAssociation, extensionAddPreviewHandler, extensionAddProtocol, extensionAddThumbnailHandler, extensionDisablePrintTaskSettings, extensionDisableShareTarget, extensionDisableStartupTask, extensionDisableToastActivation, extensionEnablePrintTaskSettings, extensionEnableShareTarget, extensionEnableStartupTask, extensionEnableToastActivation, extensionList, extensionRemove, findProjectRoot, generateManifest, generateManifestTemplate, getWindowsDir, init, prepareAppxContent, readBundleConfig$1 as readBundleConfig, readTauriConfig, toFourPartVersion };
1590
+ export { DEFAULT_CAPABILITIES, DEFAULT_MIN_WINDOWS_VERSION, DEFAULT_RUNNER, MSIX_ASSETS, 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, toFourPartVersion };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@choochmeque/tauri-windows-bundle",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "MSIX packaging tool for Tauri apps - Windows Store ready bundles",
5
5
  "type": "module",
6
6
  "bin": {
@@ -28,7 +28,8 @@
28
28
  ],
29
29
  "dependencies": {
30
30
  "commander": "^14.0.2",
31
- "glob": "^13.0.0"
31
+ "glob": "^13.0.0",
32
+ "jimp": "^1.6.0"
32
33
  },
33
34
  "devDependencies": {
34
35
  "@eslint/js": "^9.0.0",
@@ -37,11 +38,11 @@
37
38
  "@types/node": "^25.0.3",
38
39
  "@vitest/coverage-v8": "^2.0.0",
39
40
  "eslint": "^9.0.0",
40
- "typescript-eslint": "^8.0.0",
41
41
  "prettier": "^3.0.0",
42
42
  "rollup": "^4.0.0",
43
43
  "tslib": "^2.6.0",
44
44
  "typescript": "^5.3.3",
45
+ "typescript-eslint": "^8.0.0",
45
46
  "vitest": "^2.0.0"
46
47
  },
47
48
  "scripts": {