# Cloudflare Worker के अंदर JavaScript को obfuscate करें

@afterpack/wasm के साथ AfterPack को अपने Cloudflare Worker में चलाएँ, अपनी Pro key pass करके AfterPack के cloud में build करें, और हर result को rotation window के हिसाब से cache करें।

Source: https://www.afterpack.dev/hi/docs/workers

AfterPack Cloudflare Worker से दो तरीकों से चलता है, एक ही package और एक ही call से। Key के बिना, Free engine **आपके** Worker के अंदर चलता है, एक WebAssembly module के रूप में जिसे आप npm से install करते हैं। अपनी [Pro](https://www.afterpack.dev/hi/docs/pro) key के साथ, build **AfterPack के** cloud में Pro engine पर चलती है।

यह पेज दोनों को कवर करता है, फिर बताता है कि result को कैसे cache करें ताकि हर asset हर rotation window में एक ही बार build हो।

## AfterPack, आपके अपने Worker के अंदर

[`@afterpack/wasm`](https://npmjs.com/package/@afterpack/wasm) WebAssembly में compile किया गया AfterPack है। यह वही Rust engine है जिसे [CLI](https://www.afterpack.dev/hi/docs/cli) और [framework plugins](https://www.afterpack.dev/hi/docs/frameworks) चलाते हैं, बस आपकी मशीन की architecture के बजाय `wasm32` के लिए build किया गया।

```bash
npm install @afterpack/wasm
```

```javascript
import { obfuscate } from "@afterpack/wasm";

export default {
  async fetch(request) {
    const source = await request.text();
    const result = await obfuscate({ path: "app.js", source }, { preset: "hard" });
    return new Response(result.bytes, {
      headers: { "content-type": "application/javascript" },
    });
  },
};
```

यही पूरा integration है। कोई `init` call नहीं, कोई `nodejs_compat` flag नहीं, `.wasm` फ़ाइल के लिए कोई wrangler rule नहीं। Module का कोई WebAssembly import नहीं है, इसलिए पहली बार `obfuscate` call करने पर वह synchronously instantiate हो जाता है, और package का `exports` map आपके bundler को अपने आप Worker के अनुरूप entry दे देता है। वही import Node में भी काम करता है, जहाँ एक अलग entry binary को disk से पढ़ती है।

Surface [`@afterpack/core`](https://npmjs.com/package/@afterpack/core) जैसी ही है — `obfuscate`, `obfuscateAll`, `version`, सभी async, और सभी ऐसी build पर throw करते हैं जो ship नहीं हो सकती। Configuration वही object है जो [Configuration](https://www.afterpack.dev/hi/docs/config) पर documented है, [`preset`](https://www.afterpack.dev/hi/docs/config#preset) और [`seed`](https://www.afterpack.dev/hi/docs/config#seed) समेत।

> **जब तक मजबूरी न हो, `@afterpack/core` इस्तेमाल करें**
>
> `@afterpack/core` एक native binary ship करता है और तेज़ है। `@afterpack/wasm` तब चुनें जब host native binary load नहीं कर सकता: एक Worker, एक sandboxed CI image, एक edge function।

### इसकी लागत क्या है

Engine binary package के अंदर, पहले से compiled, ship होती है।

| | Bytes | Size |
|---|---:|---|
| Raw `.wasm` | 4,573,321 | 4.36 MiB |
| Gzipped | 1,307,772 | 1.25 MiB |

Cloudflare की Worker size सीमा free plan पर 3 MB compressed और paid पर 10 MB है, इसलिए engine दोनों में फ़िट हो जाता है। Free plan में जो फ़िट नहीं होता वह *काम* है: वह CPU को हर invocation पर 10 ms तक सीमित करता है, और laptop के एक core पर 185 KB bundle को obfuscate करने में डिफ़ॉल्ट [`light`](https://www.afterpack.dev/hi/docs/config) preset पर 0.3 सेकंड से कम और `medium` पर लगभग 1 सेकंड लगते हैं। Demo से आगे की किसी भी चीज़ के लिए Workers Paid चाहिए।

जो Worker हर request पर वही asset obfuscate करता है, वह हर बार वह CPU खर्च करता है। जहाँ हर request पर नया आकार आपका लक्ष्य नहीं है, वहाँ [result को एक rotation window के लिए cache करना](#cache-the-result-for-a-rotation-window), या यह काम अपनी build में करके output serve करना, bill कम रखता है।

### आपके host किए package की क्षमताएँ और सीमाएँ

आपका install किया `.wasm` Free protection करता है। Pro transforms केवल AfterPack के infrastructure पर चलते हैं, इसलिए package में unlock करने लायक कुछ नहीं है: bypass करने के लिए कोई key check नहीं, कोई switch नहीं जो host की गई copy को Pro build में बदल दे। एक [`key`](https://www.afterpack.dev/hi/docs/config#key) काम को [cloud](https://www.afterpack.dev/hi/docs/cloud-api) की ओर भेजती है; यह local पर कुछ भी चालू नहीं करती।

Published package एक npm provenance record रखता है — package version, उसे build करने वाला workflow, और artifact digest — ताकि आप अपने install किए bytes को उन्हें बनाने वाली build से जोड़ सकें।

## Pro, आपके अपने Worker से

उसी `obfuscate()` call की config में अपनी [`key`](https://www.afterpack.dev/hi/docs/config#key) pass करें, उदाहरण के लिए Worker secret से, और build AfterPack के cloud में Pro engine पर चलती है:

```javascript
import { obfuscate } from "@afterpack/wasm";

export default {
  async fetch(request, env) {
    const source = await request.text();
    const result = await obfuscate(
      { path: "app.js", source },
      { preset: "hard", key: env.AFTERPACK_KEY },
    );
    return new Response(result.bytes, {
      headers: { "content-type": "application/javascript" },
    });
  },
};
```

Package आपके लिए [`POST /v1/obfuscate/batch`](https://www.afterpack.dev/hi/docs/cloud-api) पर request भेजता है, इसलिए Worker को API हाथ से code नहीं करनी पड़ती। Worker के लिए बहुत बड़ी फ़ाइलें अपने आप containers में चली जाती हैं। Pro engine कभी आपके Worker में ship नहीं होता: यह केवल AfterPack के infrastructure पर चलता है, और ऊपर बताई tier सीमा यही है।

हर call एक metered Pro build है ([Pro की लागत](https://www.afterpack.dev/hi/docs/pro#what-pro-costs)), साथ में Cloudflare के network के अंदर एक तेज़ request। आप हर request पर build कर सकते हैं, लेकिन हर एक का bill बनता है, इसलिए इसके बजाय [result को एक rotation window के लिए cache करें](#cache-the-result-for-a-rotation-window)।

आपका source आपके Worker से बाहर जाता है और AfterPack के cloud में process होता है, memory में और persist किए बिना, जैसा [Privacy & data handling](https://www.afterpack.dev/hi/docs/privacy) में बताया गया है। अगर cloud तक नहीं पहुँचा जा सकता, तो call [fail closed](https://www.afterpack.dev/hi/docs/diagnostics#fail-closed-no-exceptions) होती है: वह error throw करती है और कुछ भी बिना सुरक्षा के ship नहीं होता। [Cloud API reference](https://www.afterpack.dev/hi/docs/cloud-api) पूरा wire contract है, और [Deployment modes](https://www.afterpack.dev/hi/docs/deployment-modes) बताता है कि engine की जगह बदलने पर क्या बदलता है।

> **Pro कभी ऐसे wasm के रूप में ship नहीं होगा जिसे आप host करें**
>
> जो package आपके अपने infrastructure पर Pro transforms चलाने का दावा करता है, वह हमारा नहीं है। इस नाम से कुछ भी install करने से पहले npm provenance record जाँचें।

## Result को एक rotation window के लिए cache करें

[`seed`](https://www.afterpack.dev/hi/docs/config#seed) को मौजूदा time window से निकालें और result को ऐसी key के तहत cache करें जिसमें window शामिल हो। तब हर location हर window में asset को एक बार build करती है और window ख़त्म होने तक उसे serve करती है, Free और Pro दोनों पर:

```javascript
import { obfuscate } from "@afterpack/wasm";
import source from "./pricing.client.js";

const WINDOW_SECONDS = 600;

export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);
    if (url.pathname !== "/pricing.js") {
      return new Response("Not found", { status: 404 });
    }

    const now = Math.floor(Date.now() / 1000);
    const slot = Math.floor(now / WINDOW_SECONDS);
    const secondsLeft = (slot + 1) * WINDOW_SECONDS - now;
    const cacheKey = new Request(`${url.origin}/pricing.js?slot=${slot}`);

    let response = await caches.default.match(cacheKey);
    if (!response) {
      const result = await obfuscate(
        { path: "pricing.js", source },
        { preset: "hard", seed: `pricing.js:${slot}`, key: env.AFTERPACK_KEY },
      );
      response = new Response(result.bytes, {
        headers: {
          "content-type": "application/javascript",
          "cache-control": `public, max-age=${secondsLeft}`,
        },
      });
      ctx.waitUntil(caches.default.put(cacheKey, response.clone()));
    }

    response = new Response(response.body, response);
    response.headers.set("cache-control", `public, max-age=${secondsLeft}`);
    return response;
  },
};
```

`AFTERPACK_KEY` secret के बिना `key` undefined रहती है और वही Worker आपके Worker के अंदर Free पर build करता है। Source फ़ाइल wrangler के `Text` rule के ज़रिए string के रूप में import होती है, जैसा [पूरे walkthrough](https://www.afterpack.dev/hi/blog/obfuscate-javascript-cloudflare-workers) में है।

Window seed और cache key दोनों में है, इसलिए एक ही deployment चलाने वाली हर location एक window में वही bytes serve करती है, और नई window कभी पुरानी entry नहीं पढ़ती। बाहर जाने वाला `cache-control` window के अंत तक उल्टी गिनती करता है, इसलिए browser कभी उसके बाद copy नहीं रखता। Cache API entries को हर data center में अलग store करता है और dashboard editor में कोई असर नहीं करता, इसलिए इसे `wrangler dev` या किसी deployed route पर test करें।

## चुनाव

| आप चाहते हैं | इस्तेमाल करें |
|---|---|
| Worker में obfuscation, आपके account से कुछ बाहर न जाए | [`@afterpack/wasm`](https://npmjs.com/package/@afterpack/wasm), यही पेज |
| सामान्य Node build में obfuscation | [`@afterpack/core`](https://www.afterpack.dev/hi/docs/frameworks) या [CLI](https://www.afterpack.dev/hi/docs/cli) |
| [Pro](https://www.afterpack.dev/hi/docs/pro) hardening और region-स्तर के [directives](https://www.afterpack.dev/hi/docs/directives), Worker से | वही call एक [`key`](https://www.afterpack.dev/hi/docs/config#key) के साथ, जो AfterPack के cloud में build करती है |
| हर window में नई शक्ल, हर visitor के लिए build के बिना | [Rotation-window cache](#cache-the-result-for-a-rotation-window) |

## आगे

- [Deployment modes](https://www.afterpack.dev/hi/docs/deployment-modes): local बनाम cloud, और हर एक क्या store करता है।
- [Cloud API reference](https://www.afterpack.dev/hi/docs/cloud-api): वह contract जिसे Worker Pro builds के लिए call करता है।
- [Configuration](https://www.afterpack.dev/hi/docs/config): हर key जिसे दोनों packages स्वीकार करते हैं।
- [Tiers](https://www.afterpack.dev/hi/docs/tiers): Free में क्या शामिल है, और Pro क्या जोड़ता है।
- [Privacy & data handling](https://www.afterpack.dev/hi/docs/privacy): हर mode में आपकी मशीन से क्या बाहर जाता है।
