# Electron app को obfuscate करें

@afterpack/electron main, preload और renderer को एक ही call में एक seed के साथ wire करता है, और electron-vite के bytecodePlugin और असुरक्षित backups को आपका source ship करने से पहले ही अस्वीकार कर देता है।

Source: https://www.afterpack.dev/hi/docs/frameworks/electron

`@afterpack/electron` एक Electron app के ship किए जाने वाले तीनों programs (main, preload, renderer) को एक ही call से obfuscate करता है, और उन सबमें एक build seed साझा करता है। हाथ से wire करने पर हर leg अपनी अलग bundler build होता है और अपना random seed लेता है, इसलिए एक ही application के हिस्से संरचना में एक-दूसरे से असंबंधित निकलते हैं।

electron-builder कोई bundler नहीं है। यह पहले से built app को installer में package करता है और आपके JavaScript को कभी नहीं छूता, इसलिए AfterPack हो या न हो, इसके ऊपर एक bundler चाहिए।

## Install

```bash
npm install -D @afterpack/electron
```

```ts
// electron.vite.config.ts
import { withAfterpack } from "@afterpack/electron";
import { defineConfig, externalizeDepsPlugin } from "electron-vite";

export default withAfterpack(
  defineConfig({
    main: { plugins: [externalizeDepsPlugin()] },
    preload: { plugins: [externalizeDepsPlugin()] },
    renderer: {},
  }),
);
```

`withAfterpack` पूरे electron-vite config को wrap करता है (object, function या promise, जिस भी रूप में `defineConfig` लौटाए) और config में घोषित हर leg में [`@afterpack/vite`](https://www.afterpack.dev/hi/docs/frameworks/vite) wire करता है, किसी अघोषित leg में कभी नहीं। Peer dependency: `vite ^5 \| ^6 \| ^7 \| ^8`।

## Build

Pass को कैसे wire करें, यह इस पर निर्भर है कि आपका toolchain तीनों legs को एक call में configure करता है, या हर leg के लिए एक config।

### एक समय में एक leg

जो toolchains हर leg को अलग से configure करते हैं (`@electron-forge/plugin-vite` के साथ Electron Forge), वे इसके बजाय हर config में एक बार `afterpackElectron` call करते हैं:

```ts
// vite.main.config.ts   (and vite.preload.config.ts / vite.renderer.config.ts)
import { afterpackElectron } from "@afterpack/electron";

export default { plugins: [afterpackElectron({ leg: "main" })] };
```

`leg` ज़रूरी है।

### एक seed, तीन तरीके

- **electron-vite (`withAfterpack`)** और **Forge + `plugin-vite`**: तीनों configs एक ही Node process में build होते हैं, इसलिए legs अपने आप एक seed साझा करते हैं।
- **`vite-plugin-electron`**: यह भी एक process है। `afterpackElectron({ leg: "renderer" })` को `plugins` में सबसे आख़िर में, `vite-plugin-electron` के बाद रखें, ताकि AfterPack का `generateBundle` तैयार bundle को seal करे।
- **हाथ से लिखी scripts जो हर leg को अलग command के रूप में चलाती हैं**: कोई साझा process नहीं है, इसलिए उनमें seed को एक environment variable से pin करें:

```jsonc
// package.json
"build": "AFTERPACK_seed=git vite build -c vite.main.ts && vite build -c vite.renderer.ts"
```

`AFTERPACK_seed` वही values लेता है जो [`seed`](https://www.afterpack.dev/hi/docs/config#seed): एक integer, `"git"` (`HEAD` से निकाला गया), या कोई भी दूसरी string, जिसे engine hash करता है। स्पष्ट `seed` option फिर भी इससे ऊपर रहता है। [Seed strategy](https://www.afterpack.dev/hi/docs/best-practices#seed-strategy) बताती है कि seed कब pin करें और कब नहीं।

## Verify

[Protection Map](https://www.afterpack.dev/hi/docs/protection-map) हर leg के लिए अलग, `.afterpack/<leg>/protectionMap.html` में लिखा जाता है, जब कोई source map मिल सके और build CI (`CI=true` या `CI=1`) में न चल रही हो। [Production](https://www.afterpack.dev/hi/docs/config#build-mode) mode इसे बंद नहीं करता, लेकिन electron-vite तब तक कोई source maps emit नहीं करता जब तक आप उन्हें न माँगें, इसलिए map डिफ़ॉल्ट रूप से बंद रहता है। main, preload और renderer को अलग-अलग जाँचें। हर रिपोर्ट में आपका पूरा source होता है। इसे कभी commit या serve न करें।

> **App के अंदर source maps कभी ship न करें**
>
> `app.asar` में मौजूद एक `.map` आपके मूल source तक पहुँचता है। जो कुछ भी आप package करते हैं, उसके लिए source-map emission बंद रखें (production में डिफ़ॉल्ट यही है)।

## Options

हर [configuration key](https://www.afterpack.dev/hi/docs/config) यहाँ भी काम करती है, `withAfterpack(config, options)` से हर leg पर लागू, या `afterpackElectron(options)` से हर leg के लिए आगे भेजी गई। ये options केवल इसी package में हैं:

| Option | Type | Default |
|---|---|---|
| `leg` | `"main" \| "preload" \| "renderer"` | `afterpackElectron` पर ज़रूरी |
| `projectRoot` | `string` | `process.cwd()`। electron-vite renderer build का root `src/renderer/` रखता है। अगर आपकी build कहीं और से चलती है तो इसे override करें |

[`seed`](https://www.afterpack.dev/hi/docs/config#seed) डिफ़ॉल्ट रूप से एक नया value होता है जो एक build session के हर leg में साझा होता है। [`protectionMap.enabled`](https://www.afterpack.dev/hi/docs/config#protectionMap-enabled) सामान्य source-map नियम का पालन करता है, और हर leg अपनी रिपोर्ट `.afterpack/<leg>/protectionMap.html` में लिखता है।

```ts
// Heavier protection, reproducible per commit, applied to every leg:
withAfterpack(config, { preset: "hard", seed: "git" });
```

## Directives

हर leg के नीचे [`@afterpack/vite`](https://www.afterpack.dev/hi/docs/frameworks/vite) wire होता है, इसलिए [directive capture](https://www.afterpack.dev/hi/docs/frameworks/vite#directives) वहाँ भी उसी तरह काम करता है।

## Edge cases

### Support matrix

| Toolchain | Wiring | अपने आप एक seed? |
|---|---|---|
| electron-vite | `withAfterpack(defineConfig({ … }))`, एक call | हाँ |
| Forge + `plugin-vite` | तीनों configs में से हर एक में `afterpackElectron({ leg })` | हाँ |
| Forge + `plugin-webpack` | हर config में [`@afterpack/webpack`](https://www.afterpack.dev/hi/docs/frameworks/webpack) | हाँ |
| `vite-plugin-electron` | `afterpackElectron({ leg: "renderer" })`, **सबसे आख़िर में** रखा गया | हाँ, जब उस plugin के बाद रखा जाए |
| electron-builder | यह package करता है, bundle नहीं; इसके ऊपर वाले bundler को wire करें | लागू नहीं |
| हाथ से लिखी scripts (अलग processes) | हर leg के लिए एक plugin, या `npx afterpack@latest <dir>` | नहीं; `AFTERPACK_seed` pin करें |

### यह क्या अस्वीकार करता है

इस package से wire किए गए किसी भी leg पर दो fail-closed checks लागू होते हैं।

**`bytecodePlugin`।** electron-vite का अपना `bytecodePlugin` emit किए गए हर chunk को 3 लाइन के loader stub से बदल देता है और असली application को V8 bytecode (`.jsc`) के रूप में ship करता है। दोनों एक साथ नहीं चल सकते, क्योंकि bytecode उस chunk को बदल देता है जिसे Rollup ने generate किया था। Build उस leg पर fail होती है जहाँ `bytecodePlugin` चालू है, या जहाँ भी बाद में output में कोई `.jsc`/`.cjsc` फ़ाइल दिखे। दोनों में से एक को हटाएँ।

**`build.backup: true`।** [Backups](https://www.afterpack.dev/hi/docs/config#build-backup) सीधे अस्वीकार किए जाते हैं: call आगे बढ़ने के बजाय throw करता है, क्योंकि `.backup.<hash>.js` आपका पूरा मूल source है, जो output के बगल में उसी tree में लिखा जाता है जिसे आपका packager `app.asar` में copy करता है। App install करने वाले हर user को यह मिल जाता।

यही जोखिम हर उस artifact पर लागू होता है जिसे बाहर रखना आपका packager नहीं जानता। electron-builder का डिफ़ॉल्ट `files` glob `dot: true` के साथ match करता है और डिफ़ॉल्ट रूप से `.afterpack/` को बाहर नहीं रखता। इन्हें package की जाने वाली चीज़ों से बाहर रखें:

```jsonc
// electron-builder
"files": ["**/*", "!.afterpack/**", "!**/*.backup.*", "!**/*.map"]
// electron-forge
packagerConfig: { ignore: [/^\/\.afterpack/, /\.backup\./, /\.map$/] }
```

[Source maps](https://www.afterpack.dev/hi/docs/config#sourceMap-enabled) पर अस्वीकार के बजाय एक warning मिलती है: `app.asar` के अंदर `sourcesContent` वाला `.map` पूरा deobfuscation है। `sourceMap: { enabled: true, emitUrl: true }` केवल local debug builds तक सीमित रखें और package की जाने वाली चीज़ों से `*.map` बाहर रखें।

### IPC channels

Channel names दोनों bundles में byte-for-byte मेल खाने चाहिए। `ipcMain.on("save-file", …)` और `ipcRenderer.send("save-file", …)` दोनों तरफ़ एक ही string हैं। वे सामान्य emit किए गए JavaScript में सामान्य string literals हैं, इसलिए दोनों legs को एक ही [seed](https://www.afterpack.dev/hi/docs/config#seed) और एक ही posture ([`preset`](https://www.afterpack.dev/hi/docs/config#preset) / [`complexity`](https://www.afterpack.dev/hi/docs/config#complexity)) पर रखना ही दोनों हिस्सों को consistent रखता है।

अगर कोई channel name literal के रूप में लिखे जाने के बजाय runtime पर बनाया जाता है, तो उस construction को ऐसे module में रखें जिसे आप [`paths.exclude`](https://www.afterpack.dev/hi/docs/config#paths-exclude) से बाहर रखते हैं, या bundler-plugin की एक [`regions`](https://www.afterpack.dev/hi/docs/config#regions) entry ([Pro](https://www.afterpack.dev/hi/docs/pro#what-pro-buys)) से उस region का posture कम करें।

### Plugin के बिना: CLI

Dependency नहीं जोड़ना चाहते, या किसी leg को Vite के अलावा किसी और चीज़ से build कर रहे हैं? तो build के बाद हर output directory पर एक बार [`npx afterpack@latest`](https://www.afterpack.dev/hi/docs/cli) चलाएँ:

```bash
npx afterpack@latest out/main --seed=git
npx afterpack@latest out/renderer --seed=git
```

[Path argument](https://www.afterpack.dev/hi/docs/cli#usage) न दें, तो CLI `out/` पहचान लेता है, वह directory जिसमें electron-vite लिखता है; आपकी directory अलग हो तो उसका नाम दें। हर run directory में जाता है, हर `.js`/`.mjs`/`.cjs` इकट्ठा करता है, और उन्हें [उसी जगह](https://www.afterpack.dev/hi/docs/cli#what-a-run-does) obfuscate करता है; argument के रूप में एक अकेली फ़ाइल भी काम करती है। हर run में एक ही [`--seed`](https://www.afterpack.dev/hi/docs/config#seed) pin करें: मौजूदा commit से निकाला गया `git` इसकी गारंटी का सबसे आसान तरीका है। CLI run पर ऊपर के कोई भी अस्वीकार लागू नहीं होते; उसे जो भी JavaScript मिलता है, उसे obfuscate कर देता है। सभी runs में एक ही [`--seed`](https://www.afterpack.dev/hi/docs/config#seed) और [`--preset`](https://www.afterpack.dev/hi/docs/config#preset) रखें।

## आगे

- [Frameworks](https://www.afterpack.dev/hi/docs/frameworks): पूरी matrix।
- [Vite](https://www.afterpack.dev/hi/docs/frameworks/vite): options का वह अर्थ जिसे यह package आगे भेजता है।
- [CLI reference](https://www.afterpack.dev/hi/docs/cli#flags): fallback तरीके की flags सूची।
- [Builds & CI](https://www.afterpack.dev/hi/docs/builds): seeds, dev-बनाम-prod, वही bytes promote करना।
- [Electron app के license logic को protect करें](https://www.afterpack.dev/hi/docs/use-cases/electron-license-logic): इसे local license या trial check पर लागू करना।
- [Best practices → Seed strategy](https://www.afterpack.dev/hi/docs/best-practices#seed-strategy): कब pin करें, कब नहीं।
- [Protection Map](https://www.afterpack.dev/hi/docs/protection-map): रिपोर्ट पढ़ना।
- [Configuration](https://www.afterpack.dev/hi/docs/config): हर option, और कौन-सी surface उसे सेट कर सकती है।
