# Migrating from javascript-obfuscator

Use `jso-protector` when you want JavaScript Obfuscator account credentials, hosted HTTP API protection, CI guardrails, release manifests, and the same release workflow across the online tool, CLI, Node API, and build plugins.

Use a local-only obfuscator when source code cannot leave the build machine.

## Replace the package command

```bash
npm remove javascript-obfuscator
npm install --save-dev ./packages/jso-protector
npx jso-protector --init
```

For an application in another folder, pin the local package with a `file:` dependency:

```json
{
  "devDependencies": {
    "jso-protector": "file:../packages/jso-protector"
  }
}
```

For internal sharing without publishing to npm, install a private tarball produced by `npm pack --json`.

Set credentials from the JavaScript Obfuscator dashboard:

```bash
set JSO_API_KEY=base64-api-key
set JSO_API_PASSWORD=base64-api-password
```

Long aliases also work:

```bash
set JAVASCRIPT_OBFUSCATOR_API_KEY=base64-api-key
set JAVASCRIPT_OBFUSCATOR_API_PASSWORD=base64-api-password
```

## Map familiar concepts

| javascript-obfuscator concept | jso-protector / HTTP API direction |
| --- | --- |
| `stringArray`, `stringArrayEncoding` | `MoveStrings`, `EncodeStrings`, `EncryptStrings` |
| Identifier rename settings | `ReplaceNames`, `RenameGlobals`, `RenameMembers`, `IdentityStyle` |
| `reservedNames` | `reservedNames`, `--reserved-name`, or `VariableExclusion` |
| Control-flow and dead-code transforms | `DeepObfuscate`, `ReorderCode`, `FlatTransform`, `AddDeadCode`, `DeadcodeLevel` |
| Formatting and compact output | `SelfCompression`, `CompressionRatio`, `WriteFormats` |
| Domain and date restrictions | `domainLock` maps to `LockDomain` and `LockDomainList`; date locks use `LockDate`, `LockDateValue` |

The names are not a one-to-one copy. Run this before porting a large config:

```bash
jso-protector --list-options --json
jso-protector --list-presets --json
jso-protector --list-migration-map --json
```

`--list-migration-map` includes a summary with mapped, direct, approximate, review-only, and total known option counts. Use that summary in migration tooling to decide whether a project can be converted automatically or needs manual review first.

You can generate a starter config from a common `javascript-obfuscator` JSON or trusted CommonJS config file:

```bash
jso-protector --migrate-javascript-obfuscator javascript-obfuscator.json --output jso.config.json
jso-protector --migrate-javascript-obfuscator javascript-obfuscator.config.cjs --output jso.config.json
jso-protector --config jso.config.json --release-check --json
jso-protector --config jso.config.json --validate-config --json
```

Use `--json` with the migration command when internal tooling needs the generated config plus a per-config summary, mapped options, review items, and unmapped option lists:

```bash
jso-protector --migrate-javascript-obfuscator javascript-obfuscator.json --json
```

The converter maps familiar settings such as string arrays, control-flow flattening, dead-code insertion, identifier styles, `parseHtml`, `domainLock`, reserved names, and target runtime. When you protect inline scripts inside template files, add `markupExtensions` for the file types you ship such as `.php`, `.aspx`, or `.jsp`. The report summary includes source option, mapped, direct, approximate, review-only, unmapped, and automatic coverage counts, a review reference for every known review-only option, then prints the next validate, dry-run, doctor, release-check, and protect commands. Use `--release-check --json` when you want those preflight checks in one CI report. CommonJS source configs execute as Node.js code, so only migrate configs from your own repository or another trusted source.

You can also keep simple package scripts close to their old shape by using compatibility flags directly:

```bash
jso-protector src/app.js
jso-protector dist --output dist-protected --options-preset high-obfuscation --control-flow-flattening --string-array-encoding rc4 --reserved-names "^PublicApi$"
```

For direct single-file scripts, `jso-protector src/app.js` writes `src/app-obfuscated.js` when no `--output` or config `output` is set. Folder and config-file workflows keep using the configured output folder, usually `dist-protected`.

Mapped compatibility flags include `--options-preset`, `--parse-html`, `--string-array`, `--string-array-encoding`, `--unicode-escape-sequence`, `--control-flow-flattening`, `--dead-code-injection`, `--dead-code-injection-threshold`, `--identifier-names-generator`, `--rename-globals`, `--rename-properties`, `--reserved-names`, `--domain-lock`, `--target`, and `--compact`. Config and Node API `domainLock` arrays map to `LockDomain` plus newline-delimited `LockDomainList`; review `domainLockRedirectUrl` separately because the hosted API lock message is not a redirect. `--options-preset default`, `low-obfuscation`, `vm-default`, and `vm-low-obfuscation` map to `standard`; `medium-obfuscation` and `vm-medium-obfuscation` map to `balanced`; `high-obfuscation`, `vm-high-obfuscation`, `vm-ultra-high-obfuscation`, and `vm-anti-llm` map to `maximum`.

The same mapped compatibility keys can live in `jso.config.json` while you are migrating. Explicit `options` values override the compatibility mapping, so you can start familiar and then tune exact hosted API fields without changing scripts.

The CLI also accepts common review-only flags such as `--source-map`, `--source-map-sources-mode`, `--identifier-names-cache`, `--identifier-names-cache-path`, `--identifiers-dictionary`, `--identifiers-prefix`, `--self-defending`, `--debug-protection`, `--disable-console-output`, `--reserved-strings`, `--rename-properties-mode`, `--numbers-to-expressions`, `--seed`, `--simplify`, `--split-strings`, and string-array wrapper/index flags so older scripts do not fail immediately. `--ignore-imports` is handled directly and preserves import/export-from statements plus common static `require()` and `import()` statements before the remaining code is protected. Other review-only flags emit compatibility warnings when there is no one-to-one hosted API mapping. Run `jso-protector --explain-compat self-defending --json` or replace `self-defending` with any mapped or review-only option to see the recommended migration action.

## Start with a conservative config

```json
{
  "$schema": "./node_modules/jso-protector/jso.config.schema.json",
  "apiKey": "$JSO_API_KEY",
  "apiPassword": "$JSO_API_PASSWORD",
  "input": "dist",
  "output": "dist-protected",
  "preset": "balanced",
  "exclude": ["**/*.map", "**/vendor/**", "**/polyfills-*.js"],
  "parseHtml": false,
  "honorConditionalComments": false,
  "reservedNames": ["^PublicApi$", "^renderWidget$"],
  "manifest": "dist-protected/jso-manifest.json",
  "maxGrowthRatio": 8,
  "options": {
    "OptimizationMode": "Web",
    "LockDomain": false
  }
}
```

## Replace direct Node usage

```js
const { obfuscate, obfuscateMultiple, getOptionsByPreset, protectCode } = require("jso-protector");

const obfuscationResult = await obfuscate(sourceCode, {
  apiKey: process.env.JSO_API_KEY,
  apiPassword: process.env.JSO_API_PASSWORD,
  controlFlowFlattening: true,
  domainLock: ["example.com", "app.example.com"],
  identifierNamesGenerator: "hexadecimal",
  reservedNames: ["^PublicApi$"],
  stringArrayEncoding: ["rc4"]
}, "app.js");

const protectedCode = obfuscationResult.getObfuscatedCode();
const alsoProtectedCode = obfuscationResult.toString();

const multipleResults = await obfuscateMultiple({
  "foo.js": "var foo = 1;",
  "bar.js": "var bar = 2;"
}, {
  apiKey: process.env.JSO_API_KEY,
  apiPassword: process.env.JSO_API_PASSWORD,
  ...getOptionsByPreset("balanced")
});
```

`obfuscate(code, options, fileName)` and `obfuscateMultiple(sourceCodesObject, options)` are the closest replacements for `JavaScriptObfuscator.obfuscate(...)` and `JavaScriptObfuscator.obfuscateMultiple(...)`, but they return Promises because protection happens through the hosted HTTP API. They accept common `javascript-obfuscator` option names directly, including `stringArray`, `stringArrayEncoding`, `controlFlowFlattening`, `deadCodeInjection`, `deadCodeInjectionThreshold`, `identifierNamesGenerator`, `renameGlobals`, `renameProperties`, `reservedNames`, `compact`, and `target`.

Use `getOptionsByPreset("standard" | "balanced" | "maximum")` when replacing preset lookup helpers, and `translateJavascriptObfuscatorOptions(sourceOptions, overrides)` when migration tooling needs to inspect the mapped hosted API config before making the API call.

## JS-Confuser migration

Use the dedicated JS-Confuser helpers when the current project is built around `js-confuser` rather than `javascript-obfuscator`:

```bash
jso-protector --list-js-confuser-migration-map --json
jso-protector --explain-js-confuser-compat lock.endDate --json
jso-protector --migrate-js-confuser js-confuser.config.cjs --output jso.config.json
```

The current JS-Confuser migration path maps common preset, lock, identifier, string, minify, and control-flow settings into the nearest hosted API equivalents. Runtime-only features such as integrity checks, self-defending locks, start-date gating, custom countermeasures, opaque predicates, dispatcher mode, and similar JS-Confuser-specific transforms are intentionally surfaced as review items rather than guessed automatically.

Existing custom build scripts can also use `protectCode(options, code, fileName)` when they prefer the JavaScript Obfuscator API naming:

```js
const { protectCode } = require("jso-protector");

const protectedCode = await protectCode({
  apiKey: process.env.JSO_API_KEY,
  apiPassword: process.env.JSO_API_PASSWORD,
  preset: "balanced",
  reservedNames: ["^PublicApi$"]
}, sourceCode, "app.js");
```

For full build output, prefer the CLI or a bundle plugin so the release can remove stale source maps, write a manifest, and enforce size budgets.

## Replace bundler plugins

```js
const jsoProtector = require("jso-protector/vite");

module.exports = {
  plugins: [
    jsoProtector({
      apiKey: process.env.JSO_API_KEY,
      apiPassword: process.env.JSO_API_PASSWORD,
      preset: "balanced",
      include: ["assets/*.js"],
      exclude: ["**/vendor/**"],
      manifest: "dist/jso-manifest.json",
      maxGrowthRatio: 8
    })
  ]
};
```

Equivalent entrypoints are available for Rollup, Webpack, Webpack loader, Browserify, esbuild, React Native (`jso-protector/react-native`), Gulp, and Grunt.

## Checklist

1. Run `jso-protector --release-check --json` and confirm the file list.
2. Exclude vendor bundles, polyfills, generated framework runtime files, and source maps.
3. Add `reservedNames` for public globals, framework entry points, and names called by external code.
4. Protect into a separate output folder first, then run browser smoke tests.
5. Add `manifest`, `maxOutputBytes`, or `maxGrowthRatio` once the protected output is stable.
6. Verify the protected artifact with `jso-protector --verify-manifest dist-protected/jso-manifest.json` before publishing or after unpacking CI artifacts.
