Skip to content

Commit 2626ce1

Browse files
Copilotcrazyrob425
andauthored
fix ci typecheck and add windows nsis installer prep scaffolding
Agent-Logs-Url: https://github.com/crazyrob425/KDP-E-Book-Generator/sessions/aae21f70-8b76-4e1c-89fd-59c0c3dad1a7 Co-authored-by: crazyrob425 <247058665+crazyrob425@users.noreply.github.com>
1 parent d674248 commit 2626ce1

15 files changed

Lines changed: 299 additions & 3 deletions

File tree

.github/workflows/release.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ jobs:
3939
- name: Install frontend dependencies
4040
run: npm ci
4141

42+
- name: Prepare NSIS branding assets
43+
run: npm run brand:nsis
44+
45+
- name: Generate release update scaffold
46+
run: npm run release:scaffold-update
47+
4248
# ── Rust ──────────────────────────────────────────────────────────────
4349
- name: Set up Rust
4450
uses: dtolnay/rust-toolchain@stable
@@ -71,6 +77,8 @@ jobs:
7177
env:
7278
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
7379
VITE_GOOGLE_API_KEY: ${{ secrets.VITE_GOOGLE_API_KEY }}
80+
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
81+
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
7482
with:
7583
tagName: ${{ github.ref_name }}
7684
releaseName: "KDP E-Book Generator ${{ github.ref_name }}"

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,17 @@ If using the standalone backend mode, follow `/server/README.md`.
176176
npx tsc -p server/tsconfig.json --noEmit
177177
```
178178

179+
## 🧩 Windows Installer Prep (NSIS)
180+
181+
- Build NSIS branding assets:
182+
```bash
183+
npm run brand:nsis
184+
```
185+
- Generate release update metadata scaffold:
186+
```bash
187+
npm run release:scaffold-update
188+
```
189+
179190
## 🛠️ Troubleshooting
180191

181192
- **`vite: not found`**

docs/DEPLOYMENT_ROADMAP.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,15 @@ Installers land in `src-tauri/target/release/bundle/`:
121121

122122
The `.github/workflows/release.yml` workflow builds installers for all platforms and publishes them as a GitHub Release automatically.
123123

124+
### Windows installer prep stack (NSIS)
125+
126+
- `npm run brand:nsis` generates:
127+
- `src-tauri/installer-assets/nsis-header.bmp`
128+
- `src-tauri/installer-assets/nsis-sidebar.bmp`
129+
- `src-tauri/installer/nsis-hooks.nsh` enforces a legal confirmation gate before install.
130+
- `src-tauri/installer/EULA.txt` is bundled as the installer license file.
131+
- `npm run release:scaffold-update` generates `release/updates/latest.json.template` for updater metadata handoff.
132+
124133
**To cut a release:**
125134

126135
```bash

package-lock.json

Lines changed: 89 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
"dev": "vite",
88
"build": "vite build",
99
"preview": "vite preview",
10+
"brand:nsis": "node scripts/branding/build-nsis-assets.mjs",
11+
"release:scaffold-update": "node scripts/release/generate-update-scaffold.mjs",
1012
"tauri:dev": "concurrently -k \"cd server && npm run start\" \"tauri dev\"",
1113
"tauri:build": "tauri build"
1214
},
@@ -61,6 +63,7 @@
6163
"devDependencies": {
6264
"@tauri-apps/api": "^2.9.1",
6365
"@tauri-apps/cli": "^2.9.6",
66+
"@types/express": "^5.0.6",
6467
"@types/node": "^22.14.0",
6568
"@vitejs/plugin-react": "^5.0.0",
6669
"concurrently": "^8.2.2",
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"version": "2.1.0",
3+
"notes": "Draft update metadata scaffold for v2.1.0.",
4+
"pub_date": "2026-04-15T03:21:44.738Z",
5+
"platforms": {
6+
"windows-x86_64": {
7+
"signature": "<replace-with-signature>",
8+
"url": "<replace-with-release-asset-url>"
9+
},
10+
"darwin-aarch64": {
11+
"signature": "<replace-with-signature>",
12+
"url": "<replace-with-release-asset-url>"
13+
},
14+
"darwin-x86_64": {
15+
"signature": "<replace-with-signature>",
16+
"url": "<replace-with-release-asset-url>"
17+
},
18+
"linux-x86_64": {
19+
"signature": "<replace-with-signature>",
20+
"url": "<replace-with-release-asset-url>"
21+
}
22+
}
23+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import fs from 'node:fs/promises';
2+
import path from 'node:path';
3+
import sharp from 'sharp';
4+
5+
const root = process.cwd();
6+
const source = path.join(root, 'src-tauri', 'icons', 'icon.png');
7+
const outDir = path.join(root, 'src-tauri', 'installer-assets');
8+
const sidebarImage = path.join(outDir, 'nsis-sidebar.bmp');
9+
const headerImage = path.join(outDir, 'nsis-header.bmp');
10+
const installerIcon = path.join(root, 'src-tauri', 'icons', 'icon.ico');
11+
12+
await fs.mkdir(outDir, { recursive: true });
13+
14+
const toBmp24 = async (inputPath, width, height, outputPath) => {
15+
const { data, info } = await sharp(inputPath)
16+
.resize(width, height, { fit: 'cover' })
17+
.flatten({ background: '#111827' })
18+
.ensureAlpha()
19+
.raw()
20+
.toBuffer({ resolveWithObject: true });
21+
22+
const bytesPerPixel = 3;
23+
const rowStride = info.width * bytesPerPixel;
24+
const paddedRowStride = Math.ceil(rowStride / 4) * 4;
25+
const pixelDataSize = paddedRowStride * info.height;
26+
const fileHeaderSize = 14;
27+
const dibHeaderSize = 40;
28+
const pixelDataOffset = fileHeaderSize + dibHeaderSize;
29+
const fileSize = pixelDataOffset + pixelDataSize;
30+
const bmp = Buffer.alloc(fileSize);
31+
32+
bmp.write('BM', 0, 2, 'ascii');
33+
bmp.writeUInt32LE(fileSize, 2);
34+
bmp.writeUInt32LE(pixelDataOffset, 10);
35+
bmp.writeUInt32LE(dibHeaderSize, 14);
36+
bmp.writeInt32LE(info.width, 18);
37+
bmp.writeInt32LE(info.height, 22);
38+
bmp.writeUInt16LE(1, 26);
39+
bmp.writeUInt16LE(24, 28);
40+
bmp.writeUInt32LE(0, 30);
41+
bmp.writeUInt32LE(pixelDataSize, 34);
42+
43+
let outOffset = pixelDataOffset;
44+
for (let y = info.height - 1; y >= 0; y--) {
45+
for (let x = 0; x < info.width; x++) {
46+
const inOffset = (y * info.width + x) * info.channels;
47+
const r = data[inOffset];
48+
const g = data[inOffset + 1];
49+
const b = data[inOffset + 2];
50+
bmp[outOffset++] = b;
51+
bmp[outOffset++] = g;
52+
bmp[outOffset++] = r;
53+
}
54+
while ((outOffset - pixelDataOffset) % paddedRowStride !== 0) {
55+
bmp[outOffset++] = 0x00;
56+
}
57+
}
58+
59+
await fs.writeFile(outputPath, bmp);
60+
};
61+
62+
await toBmp24(source, 164, 314, sidebarImage);
63+
await toBmp24(source, 150, 57, headerImage);
64+
65+
console.log('NSIS branding assets prepared:');
66+
console.log(`- ${headerImage}`);
67+
console.log(`- ${sidebarImage}`);
68+
console.log(`- ${installerIcon}`);
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import fs from 'node:fs/promises';
2+
import path from 'node:path';
3+
4+
const root = process.cwd();
5+
const packageJsonPath = path.join(root, 'package.json');
6+
const outDir = path.join(root, 'release', 'updates');
7+
const outPath = path.join(outDir, 'latest.json.template');
8+
9+
const pkg = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
10+
const version = pkg.version;
11+
12+
const scaffold = {
13+
version,
14+
notes: `Draft update metadata scaffold for v${version}.`,
15+
pub_date: new Date().toISOString(),
16+
platforms: {
17+
'windows-x86_64': {
18+
signature: '<replace-with-signature>',
19+
url: '<replace-with-release-asset-url>'
20+
},
21+
'darwin-aarch64': {
22+
signature: '<replace-with-signature>',
23+
url: '<replace-with-release-asset-url>'
24+
},
25+
'darwin-x86_64': {
26+
signature: '<replace-with-signature>',
27+
url: '<replace-with-release-asset-url>'
28+
},
29+
'linux-x86_64': {
30+
signature: '<replace-with-signature>',
31+
url: '<replace-with-release-asset-url>'
32+
}
33+
}
34+
};
35+
36+
await fs.mkdir(outDir, { recursive: true });
37+
await fs.writeFile(outPath, `${JSON.stringify(scaffold, null, 2)}\n`, 'utf8');
38+
39+
console.log(`Update scaffold generated at ${outPath}`);

server/declarations.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
declare module 'google-trends-api' {
2+
const googleTrends: any;
3+
export default googleTrends;
4+
}

server/tsconfig.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,16 @@
22
"compilerOptions": {
33
"target": "ES2020",
44
"module": "commonjs",
5-
"rootDir": "./",
5+
"rootDir": "../",
66
"outDir": "./dist",
77
"esModuleInterop": true,
88
"forceConsistentCasingInFileNames": true,
99
"strict": true,
1010
"skipLibCheck": true
11-
}
11+
},
12+
"include": [
13+
"./**/*.ts",
14+
"./**/*.d.ts",
15+
"../types.ts"
16+
]
1217
}

0 commit comments

Comments
 (0)