Skip to content

Commit

Permalink
Merge branch 'master' into zbulu
Browse files Browse the repository at this point in the history
  • Loading branch information
MikeZeDev committed Nov 17, 2024
2 parents 0e05a52 + fbd734a commit 5cce29a
Show file tree
Hide file tree
Showing 239 changed files with 1,835 additions and 1,957 deletions.
15 changes: 5 additions & 10 deletions .github/workflows/continuous-deployment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ on:

permissions:
contents: read
deployments: write

jobs:
deploy:
Expand All @@ -22,7 +21,7 @@ jobs:
- name: Install NodeJS
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: 22.x
- name: Install NPM Packages
run: npm install
- name: Code Inspection
Expand All @@ -32,20 +31,16 @@ jobs:
- name: Build Web-Application
run: npm run build --workspace=web
- name: Deploy App to CloudFlare
uses: cloudflare/pages-action@v1
uses: cloudflare/wrangler-action@v3
with:
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
projectName: haruneko
directory: ./web/build
command: pages deploy ./web/build --project-name=haruneko --commit-dirty=true
- name: Build Documentation
run: npm run build --workspace=docs
- name: Deploy Docs to CloudFlare
uses: cloudflare/pages-action@v1
uses: cloudflare/wrangler-action@v3
with:
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
projectName: haruneko-docs
directory: ./docs/.vitepress/dist
command: pages deploy ./docs/.vitepress/dist --project-name=haruneko-docs --commit-dirty=true
2 changes: 1 addition & 1 deletion .github/workflows/create-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- name: Install NodeJS
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: 22.x
- name: Install NPM Packages
run: npm install
- name: Build Application
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pull-request-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- name: Install NodeJS
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: 22.x
- name: Install NPM Packages
id: packages
run: npm install
Expand Down Expand Up @@ -48,7 +48,7 @@ jobs:
- name: Install NodeJS
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: 22.x
- name: Install NPM Packages
id: packages
run: npm install
Expand Down
26 changes: 18 additions & 8 deletions .github/workflows/pull-request-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ name: Pull Request (Deployment)

on:
pull_request:
types: [ labeled ]
types: [ synchronize, labeled ]

permissions:
contents: read
deployments: write
pull-requests: write

jobs:
pull-request-deploy:
if: ${{ contains(github.event.pull_request.labels.*.name, 'Deploy PR') }}
name: Publish Web-Application (Preview)
runs-on: ubuntu-latest
steps:
Expand All @@ -20,17 +21,26 @@ jobs:
- name: Install NodeJS
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: 22.x
- name: Install NPM Packages
run: npm install
- name: Build Web-Application
run: npm run build --workspace=web
- name: Deploy App to CloudFlare
if: ${{ contains(github.event.pull_request.labels.*.name, 'Deploy PR') }}
uses: cloudflare/pages-action@v1
id: deploy
uses: cloudflare/wrangler-action@v3
with:
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
projectName: haruneko
directory: ./web/build
command: pages deploy ./web/build --project-name=haruneko --commit-dirty=true
- name: Comment Deployment
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '## 🔥 Preview Deployment\nRun the command below to preview this pull-request directly in HaruNeko\n```sh\nhakuneko.exe --origin=${{ steps.deploy.outputs.deployment-url }}\n```'
})
4 changes: 2 additions & 2 deletions .github/workflows/website-metrics.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- name: Install NodeJS
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: 22.x
- name: Install NPM Packages
run: npm install
- name: Process Websites
Expand All @@ -38,4 +38,4 @@ jobs:
with:
retention-days: 30
name: website-metrics.html
path: web/scripts/cache/website-metrics.html
path: web/scripts/cache/website-metrics.html
4 changes: 1 addition & 3 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
engine-strict = true
legacy-peer-deps = true
strict-peer-deps = false
engine-strict = true
8 changes: 4 additions & 4 deletions app/electron/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
"npm": ">=10.2.4"
},
"dependencies": {
"websocket-rpc": "github:manga-download/websocket-rpc#v1.2.6",
"yargs": "17.7.2"
"commander": "^12.1.0",
"websocket-rpc": "github:manga-download/websocket-rpc#v1.2.6"
},
"devDependencies": {
"@types/ws": "8.5.12",
"@types/ws": "8.5.13",
"extract-zip": "2.0.1",
"electron": "33.0.2",
"electron": "33.2.0",
"plist": "3.1.0"
},
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion app/electron/scripts/build-app.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ const manifest = {
};

await fs.writeFile(targetFile, JSON.stringify(manifest, null, 4));
await run('npm install --only=production', dirBuild);
await run('npm install --omit=dev', dirBuild);
30 changes: 19 additions & 11 deletions app/electron/src/Main.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import path from 'path';
import yargs from 'yargs';
import fs from 'fs/promises';
import { app } from 'electron';
import { Command } from 'commander';
import { IPC } from './ipc/InterProcessCommunication';
import { ApplicationWindow } from './ipc/ApplicationWindow';
import { FetchProvider } from './ipc/FetchProvider';
Expand All @@ -13,6 +13,22 @@ import { RemoteProcedureCallManager } from './ipc/RemoteProcedureCallManager';
import { RemoteProcedureCallContract } from './ipc/RemoteProcedureCallContract';
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true';

type CLIOptions = {
origin?: string;
}

function ParseCLI(): CLIOptions {
try {
const argv = new Command()
.allowUnknownOption(true)
.option('--origin [url]', 'custom location from which the web-app shall be loaded')
.parse(process.argv, { from: 'electron' });
return argv.opts<CLIOptions>();
} catch {
return {};
}
}

type Manifest = {
url: string;
'user-agent': undefined | string;
Expand All @@ -25,15 +41,6 @@ async function LoadManifest(): Promise<Manifest> {
return JSON.parse(content) as Manifest;
}

async function GetArgumentURL(): Promise<string | undefined> {
try {
const argv = await yargs(process.argv).argv;
return argv.origin as string;
} catch {
return undefined;
}
}

async function SetupUserDataDirectory(manifest: Manifest): Promise<void> {
// TODO: This detection is more like a hack and does not use the provided path
if(manifest['chromium-args']?.includes('--user-data-dir=userdata')) {
Expand Down Expand Up @@ -69,6 +76,7 @@ async function CreateApplicationWindow(): Promise<ApplicationWindow> {

async function OpenWindow(): Promise<void> {
InitializeMenu();
const argv = ParseCLI();
const manifest = await LoadManifest();
await SetupUserDataDirectory(manifest);
app.userAgentFallback = manifest['user-agent'] ?? app.userAgentFallback.split(/\s+/).filter(segment => !/(hakuneko|electron)/i.test(segment)).join(' ');
Expand All @@ -81,7 +89,7 @@ async function OpenWindow(): Promise<void> {
new RemoteBrowserWindowController(ipc);
new BloatGuard(ipc, win.webContents);
win.RegisterChannels(ipc);
return win.loadURL(await GetArgumentURL() ?? manifest.url);
return win.loadURL(argv.origin ?? manifest.url ?? 'about:blank');
}

OpenWindow();
13 changes: 7 additions & 6 deletions app/electron/src/ipc/FetchProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,6 @@ export class FetchProvider {
for (const originalHeaderName in details.requestHeaders) {
const normalizedHeaderName = originalHeaderName.toLowerCase();
const originalHeaderValue = details.requestHeaders[originalHeaderName];
if(normalizedHeaderName === 'origin' && this.IsMatchingAppHost(originalHeaderValue)) {
updatedHeaders[normalizedHeaderName] = uri.origin;
}
if(normalizedHeaderName === 'referer' && this.IsMatchingAppHost(originalHeaderValue)) {
updatedHeaders[normalizedHeaderName] = uri.href;
}
if (normalizedHeaderName.startsWith(this.fetchApiSupportedPrefix)) {
const revealedHeaderName = normalizedHeaderName.replace(this.fetchApiSupportedPrefix, '');
updatedHeaders[revealedHeaderName] = originalHeaderValue;
Expand All @@ -73,6 +67,13 @@ export class FetchProvider {
}
}

// Prevent leaking HakuNeko's host in certain headers
[ 'origin', 'referer' ].forEach(key => {
if(key in updatedHeaders && this.IsMatchingAppHost(updatedHeaders[key])) {
updatedHeaders[key] = uri.origin;
}
});

return {
cancel: false,
requestHeaders: updatedHeaders,
Expand Down
3 changes: 1 addition & 2 deletions app/electron/src/ipc/RemoteBrowserWindow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ export class RemoteBrowserWindowController {
windowOptions.webPreferences.preload = await this.CreatePreloadScriptFile(windowOptions.webPreferences.preload);
}
const win = new BrowserWindow(windowOptions);
win.removeMenu();
win.setMenu(null);
win.autoHideMenuBar = true;
win.setMenuBarVisibility(false);
win.webContents.debugger.attach('1.3');
win.webContents.setWindowOpenHandler(() => { return { action: 'deny' }; });
Expand Down
6 changes: 3 additions & 3 deletions app/nw/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
"npm": ">=10.2.4"
},
"dependencies": {
"websocket-rpc": "github:manga-download/websocket-rpc#v1.2.6",
"yargs": "17.7.2"
"commander": "^12.1.0",
"websocket-rpc": "github:manga-download/websocket-rpc#v1.2.6"
},
"devDependencies": {
"@types/ws": "8.5.12",
"@types/ws": "8.5.13",
"extract-zip": "2.0.1",
"nw": "0.93.0-sdk",
"plist": "3.1.0"
Expand Down
2 changes: 1 addition & 1 deletion app/nw/scripts/build-app.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ const manifest = {
};

await fs.writeFile(targetFile, JSON.stringify(manifest, null, 4));
await run('npm install --only=production', dirBuild);
await run('npm install --omit=dev', dirBuild);
29 changes: 16 additions & 13 deletions app/nw/src/App.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import yargs from 'yargs';
import { Command } from 'commander';
import { IPC } from './ipc/InterProcessCommunication';
import { RPCServer } from '../../src/rpc/Server';
import { RemoteProcedureCallContract } from './ipc/RemoteProcedureCallContract';
Expand All @@ -10,21 +10,23 @@ type Manifest = {
//'chromium-args': undefined | string;
};

async function GetArgumentURL(): Promise<string|undefined> {
type CLIOptions = {
origin?: string;
}

function ParseCLI(): CLIOptions {
try {
/*
type Arguments = {
origin?: string;
}
*/
const argv/*: Arguments*/ = await yargs(nw.App.argv).argv;
return argv.origin as string;
const argv = new Command()
.allowUnknownOption(true)
.option('--origin [url]', 'custom location from which the web-app shall be loaded')
.parse(nw.App.argv, { from: 'user' });
return argv.opts<CLIOptions>();
} catch {
return undefined;
return {};
}
}

async function GetDefaultURL(): Promise<string|undefined> {
function GetDefaultURL(): string | undefined {
try {
return (nw.App.manifest as Manifest).url;
} catch {
Expand All @@ -33,12 +35,13 @@ async function GetDefaultURL(): Promise<string|undefined> {
}

async function OpenWindow() {
const argv = ParseCLI();
const ipc = new IPC();
const rpc = new RPCServer('/hakuneko', new RemoteProcedureCallContract(ipc));
new RemoteProcedureCallManager(rpc, ipc);

const url = await GetArgumentURL() ?? await GetDefaultURL();
const win = await new Promise<NWJS_Helpers.win>((resolve, reject) => nw.Window.open(url ?? 'about:blank', {
const url = argv.origin ?? GetDefaultURL() ?? 'about:blank';
const win = await new Promise<NWJS_Helpers.win>((resolve, reject) => nw.Window.open(url, {
id: 'hakuneko',
show: url ? false : true,
frame: url ? false : true,
Expand Down
2 changes: 1 addition & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "hakuneko-docs",
"type": "module",
"devDependencies": {
"vitepress": "^1.4.1"
"vitepress": "^1.5.0"
},
"scripts": {
"check": "",
Expand Down
19 changes: 10 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,26 @@
"docs"
],
"devDependencies": {
"@stylistic/eslint-plugin": "^2.9.0",
"@types/chrome": "^0.0.279",
"@stylistic/eslint-plugin": "^2.10.1",
"@types/chrome": "^0.0.283",
"@types/jsdom": "^21.1.7",
"@types/nw.js": "^0.92.0",
"eslint": "^9.13.0",
"eslint": "^9.15.0",
"eslint-plugin-tsdoc": "^0.3.0",
"jsdom": "^25.0.1",
"puppeteer-core": "^23.6.0",
"tslib": "^2.8.0",
"puppeteer-core": "^23.8.0",
"tslib": "^2.8.1",
"typescript": "^5.6.3",
"typescript-eslint": "^8.11.0",
"vite": "^5.4.9",
"vitest": "^2.1.3",
"typescript-eslint": "^8.14.0",
"vite": "^5.4.11",
"vitest": "^2.1.5",
"vitest-mock-extended": "^2.0.2"
},
"scripts": {
"check": "npm run check --workspaces",
"test": "npm run test --workspaces",
"test:e2e": "npm run build --workspaces && vitest run --config=test/vitest.e2e.js",
"test:websites": "npm run build --workspaces && vitest run --config=test/vitest.websites.js"
"test:websites": "npm run build --workspaces && vitest run --config=test/vitest.websites.js",
"npm:clean-install": "npm update --package-lock-only && npm ci"
}
}
Loading

0 comments on commit 5cce29a

Please sign in to comment.