unplugin-keywords 2.9.0 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -24,7 +24,7 @@ Traditional JavaScript minifiers rely on property mangling (e.g., Terser's `mang
24
24
  - **Gradual Adoption:**
25
25
  Unlike global mangling flags that affect the entire codebase simultaneously, installing this plugin alters nothing by default. It allows incremental adoption on a per-file or per-module basis.
26
26
  - **Cross-Boundary Consistency:**
27
- Standard mangled properties cannot safely cross package boundaries; a property mangled to `a` in Package A will not map to `a` in Package B. Because `~keywords` relies on deterministic hashing, identical keys inherently produce identical hashes across independent builds, preserving structural contracts.
27
+ Standard mangled properties cannot safely cross package boundaries; a property mangled to `a` in Package A will not map to `a` in Package B. Because `~keywords/public` relies on deterministic hashing, identical keys inherently produce identical hashes across independent builds, preserving structural contracts.
28
28
  - **Universal Application:**
29
29
  Standard minifiers only mangle object keys, leaving string literal values intact. This plugin processes both keys and values uniformly (e.g., `[K.type]: K.SET_USER`). It extends obfuscation to literal types (`const mode: typeof K.extract | typeof K.transform = K.extract`) and even arbitrary static strings (`throw new Error(K['Invalid State'])`).
30
30
  - **Trade-offs:**
@@ -37,7 +37,7 @@ A side-by-side comparison of minified bundles:
37
37
  | [Unmodified](https://github.com/cueaz/unplugin-keywords/blob/main/demo/signals/src/original.ts) (Standard Minification) | [Keywordified](https://github.com/cueaz/unplugin-keywords/blob/main/demo/signals/src/keywordified.ts) (Literal Obfuscation) |
38
38
  | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
39
39
  | <picture><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/cueaz/unplugin-keywords/refs/heads/main/demo/signals/dist_sample/original.min.js.light.png" width="400"><img src="https://raw.githubusercontent.com/cueaz/unplugin-keywords/refs/heads/main/demo/signals/dist_sample/original.min.js.dark.png" width="400" alt="Original"></picture> | <picture><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/cueaz/unplugin-keywords/refs/heads/main/demo/signals/dist_sample/keywordified.min.js.light.png" width="400"><img src="https://raw.githubusercontent.com/cueaz/unplugin-keywords/refs/heads/main/demo/signals/dist_sample/keywordified.min.js.dark.png" width="400" alt="Keywordified"></picture> |
40
- | 6.86 kB │ gzip: **2.09 kB** | **5.40 kB** │ gzip: 2.05 kB |
40
+ | 6.86 kB │ gzip: 2.09 kB | 5.40 kB │ gzip: 2.05 kB |
41
41
 
42
42
  > [!NOTE]
43
43
  > **Baseline Metrics:** Both the "Unmodified" and "Keywordified" metrics represent standard `tsdown` minification. The official [`@preact/signals-core@1.14.1`](https://bundlephobia.com/package/@preact/signals-core@1.14.1) release achieves a smaller footprint (5.4 kB Minified / 1.9 kB Gzipped) by employing a hand-crafted [`mangle.json`](https://github.com/preactjs/signals/blob/main/mangle.json) for manual property obfuscation.
@@ -65,32 +65,32 @@ const action = {
65
65
  ```
66
66
 
67
67
  **2. AST Transformation:**
68
- During the build phase, the plugin traverses the AST, resolving bindings and statically resolving member expressions. It replaces valid identifier access with a generated AST node pointing to a deterministic base62 hash or a minimal lexical sequence.
68
+ During the build phase, the plugin traverses the AST, resolving bindings and statically resolving member expressions. It replaces valid identifier access with a generated AST node pointing to a minimal lexical sequence (or a deterministic hash, depending on the module).
69
69
 
70
70
  **3. Minified Output (Production):**
71
- The bundler receives the transformed code and processes the hashed literals. Depending on the frequency of usage, the minifier will either inline the strings directly or extract them into single-character variables to save bytes.
71
+ The bundler receives the transformed code and processes the obfuscated literals. Depending on the frequency of usage, the minifier will either inline the short strings directly or assign them to variables to save bytes.
72
72
 
73
73
  <!-- prettier-ignore-start -->
74
74
  ```ts
75
75
  // Example of minifier output: strings may be inlined or assigned to variables if used multiple times
76
- const _="z2pL21k";const a={a3fB9zX:_,k1Mw8pA:data};
76
+ const _="b0";const a={a0:_,c0:data};
77
77
  ```
78
78
  <!-- prettier-ignore-end -->
79
79
 
80
80
  ## Dual-Module Architecture
81
81
 
82
- `unplugin-keywords` provides two distinct virtual modules. While exclusively using `K.*` is a perfectly valid and robust approach, the dual-module system allows further bundle size reduction.
82
+ `unplugin-keywords` provides two distinct virtual modules. By default, the shortest possible compression is used, but the dual-module system allows for stable cross-boundary contracts when necessary.
83
83
 
84
- - **`~keywords` (Stable Hash):**
85
- Generates deterministic, key-derived hashes (e.g., `"z2pL21k"`). Designed for **public-facing APIs** and structural contracts that must remain consistent across package boundaries (e.g., `package.json` exports).
84
+ - **`~keywords` (Lexical Counter):**
85
+ Generates the shortest safe sequential identifiers (min length: 2, e.g., `"a0"`, `"b0"`). Intended for **internal and local** implementations where cross-boundary stability is irrelevant. This is the default for maximum minification.
86
86
  _Convention:_ `import * as K from '~keywords';`
87
87
 
88
- - **`~keywords/local` (Lexical Counter):**
89
- Generates the shortest possible sequential identifiers (min length: 2, e.g., `"a0"`, `"b0"`). Intended for **internal and local** implementations where cross-boundary stability is irrelevant.
90
- _Convention:_ `import * as L from '~keywords/local';`
88
+ - **`~keywords/public` (Stable Hash):**
89
+ Generates deterministic, key-derived hashes (e.g., `"z2pL21k"`). Designed for **public-facing APIs** and structural contracts that must remain consistent across package boundaries (e.g., `package.json` exports).
90
+ _Convention:_ `import * as PK from '~keywords/public';`
91
91
 
92
92
  **Module Separation:**
93
- To minimize bundle size, identifiers can be partitioned: bind public interfaces to `K.*`, and obscure all internal state and private members behind `L.*`.
93
+ To minimize bundle size, identifiers can be partitioned: use `PK.*` for properties exposed to consumers, and obscure all internal state and private members behind the default `K.*`.
94
94
 
95
95
  ## Integration
96
96
 
@@ -143,7 +143,7 @@ The namespace import pattern is applicable in class-based architectures where st
143
143
  */
144
144
 
145
145
  import * as K from '~keywords';
146
- import * as L from '~keywords/local';
146
+ import * as PK from '~keywords/public';
147
147
 
148
148
  import {
149
149
  AsyncDirective,
@@ -155,43 +155,43 @@ import { forAwaitOf, Pauser, PseudoWeakRef } from './private-async-helpers.js';
155
155
  type Mapper<T> = (v: T, index?: number) => unknown;
156
156
 
157
157
  export class AsyncReplaceDirective extends AsyncDirective {
158
- private [L.__value]?: AsyncIterable<unknown>;
159
- private [L.__weakThis] = new PseudoWeakRef(this);
160
- private [L.__pauser] = new Pauser();
158
+ private [K.__value]?: AsyncIterable<unknown>;
159
+ private [K.__weakThis] = new PseudoWeakRef(this);
160
+ private [K.__pauser] = new Pauser();
161
161
 
162
- [K.render]<T>(_value: AsyncIterable<T>, _mapper?: Mapper<T>) {
162
+ [PK.render]<T>(_value: AsyncIterable<T>, _mapper?: Mapper<T>) {
163
163
  return noChange;
164
164
  }
165
165
 
166
- override [K.update](
166
+ override [PK.update](
167
167
  _part: ChildPart,
168
168
  [value, mapper]: DirectiveParameters<this>,
169
169
  ) {
170
- if (!this[K.isConnected]) {
171
- this[K.disconnected]();
170
+ if (!this[PK.isConnected]) {
171
+ this[PK.disconnected]();
172
172
  }
173
173
 
174
- if (value === this[L.__value]) {
174
+ if (value === this[K.__value]) {
175
175
  return noChange;
176
176
  }
177
- this[L.__value] = value;
177
+ this[K.__value] = value;
178
178
  let i = 0;
179
- const { [L.__weakThis]: weakThis, [L.__pauser]: pauser } = this;
179
+ const { [K.__weakThis]: weakThis, [K.__pauser]: pauser } = this;
180
180
 
181
181
  forAwaitOf(value, async (v: unknown) => {
182
- while (pauser[L.get]()) {
183
- await pauser[L.get]();
182
+ while (pauser[K.get]()) {
183
+ await pauser[K.get]();
184
184
  }
185
185
 
186
- const _this = weakThis[L.deref]();
186
+ const _this = weakThis[K.deref]();
187
187
  if (_this !== undefined) {
188
- if (_this[L.__value] !== value) {
188
+ if (_this[K.__value] !== value) {
189
189
  return false;
190
190
  }
191
191
  if (mapper !== undefined) {
192
192
  v = mapper(v, i);
193
193
  }
194
- _this[K.commitValue](v, i);
194
+ _this[PK.commitValue](v, i);
195
195
  i++;
196
196
  }
197
197
  return true;
@@ -200,23 +200,23 @@ export class AsyncReplaceDirective extends AsyncDirective {
200
200
  return noChange;
201
201
  }
202
202
 
203
- protected [K.commitValue](value: unknown, _index: number) {
204
- this[K.setValue](value);
203
+ protected [PK.commitValue](value: unknown, _index: number) {
204
+ this[PK.setValue](value);
205
205
  }
206
206
 
207
- override [K.disconnected]() {
208
- this[L.__weakThis][L.disconnect]();
209
- this[L.__pauser][L.pause]();
207
+ override [PK.disconnected]() {
208
+ this[K.__weakThis][K.disconnect]();
209
+ this[K.__pauser][K.pause]();
210
210
  }
211
211
 
212
- override [K.reconnected]() {
213
- this[L.__weakThis][L.reconnect](this);
214
- this[L.__pauser][L.resume]();
212
+ override [PK.reconnected]() {
213
+ this[K.__weakThis][K.reconnect](this);
214
+ this[K.__pauser][K.resume]();
215
215
  }
216
216
  }
217
217
  ```
218
218
 
219
- _In production, all internal properties (e.g., `__value`, `__pauser`) will be completely minified to short sequence identifiers (via `~keywords/local`), obfuscating internal property names from the bundled Lit component._
219
+ _In production, all internal properties (e.g., `__value`, `__pauser`) will be completely minified to short sequence identifiers (via `~keywords`), obfuscating internal property names from the bundled Lit component._
220
220
 
221
221
  > [!TIP]
222
222
  > Native ECMAScript private fields (`#prop`) are safely mangled by standard minifiers, eliminating the need for plugin obfuscation for internal class state.
package/dist/api.d.ts CHANGED
@@ -6,8 +6,8 @@ import { FileResult } from "@babel/core";
6
6
  * SPDX-License-Identifier: MIT
7
7
  */
8
8
  interface KeywordSet {
9
- main: Set<string>;
10
9
  local: Set<string>;
10
+ public: Set<string>;
11
11
  }
12
12
  declare const transformCode: (code: string, id: string) => {
13
13
  code: string;
package/dist/api.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as transformCode, i as extractKeywords, n as createHasher, r as createRunner, t as createCounter } from "./hash-CvUe2HGU.js";
1
+ import { a as transformCode, i as extractKeywords, n as createHasher, r as createRunner, t as createCounter } from "./hash-DCwSROqn.js";
2
2
  //#region src/api.ts
3
3
  /**
4
4
  * @license
package/dist/bun.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as unpluginFactory } from "./plugin-BxpZVMN0.js";
1
+ import { t as unpluginFactory } from "./plugin-DrcLx4Tu.js";
2
2
  import { createBunPlugin } from "unplugin";
3
3
  //#region src/bun.ts
4
4
  /**
package/dist/esbuild.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as unpluginFactory } from "./plugin-BxpZVMN0.js";
1
+ import { t as unpluginFactory } from "./plugin-DrcLx4Tu.js";
2
2
  import { createEsbuildPlugin } from "unplugin";
3
3
  //#region src/esbuild.ts
4
4
  /**
package/dist/farm.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as unpluginFactory } from "./plugin-BxpZVMN0.js";
1
+ import { t as unpluginFactory } from "./plugin-DrcLx4Tu.js";
2
2
  import { createFarmPlugin } from "unplugin";
3
3
  //#region src/farm.ts
4
4
  /**
@@ -10,7 +10,7 @@ import { createHmac, hkdfSync } from "node:crypto";
10
10
  * SPDX-License-Identifier: MIT
11
11
  */
12
12
  const VIRTUAL_MODULE_ID = "~keywords";
13
- const VIRTUAL_LOCAL_MODULE_ID = "~keywords/local";
13
+ const VIRTUAL_PUBLIC_MODULE_ID = "~keywords/public";
14
14
  const PLUGIN_NAME = "unplugin-keywords";
15
15
  //#endregion
16
16
  //#region src/internal/encode.ts
@@ -64,29 +64,29 @@ const transformPlugin = (mode) => {
64
64
  Program: {
65
65
  enter(_, state) {
66
66
  state.keywords = {
67
- main: /* @__PURE__ */ new Set(),
68
- local: /* @__PURE__ */ new Set()
67
+ local: /* @__PURE__ */ new Set(),
68
+ public: /* @__PURE__ */ new Set()
69
69
  };
70
70
  state.keywordUids = {
71
- main: /* @__PURE__ */ new Map(),
72
- local: /* @__PURE__ */ new Map()
71
+ local: /* @__PURE__ */ new Map(),
72
+ public: /* @__PURE__ */ new Map()
73
73
  };
74
74
  },
75
75
  exit(path, state) {
76
76
  const metadata = state.file.metadata;
77
77
  metadata.keywords = {
78
- main: Array.from(state.keywords.main),
79
- local: Array.from(state.keywords.local)
78
+ local: Array.from(state.keywords.local),
79
+ public: Array.from(state.keywords.public)
80
80
  };
81
81
  if (mode === "transform") {
82
82
  const newImports = [];
83
- for (const [keyword, safeId] of state.keywordUids.main.entries()) {
83
+ for (const [keyword, safeId] of state.keywordUids.local.entries()) {
84
84
  const encoded = encodeIdentifier(keyword);
85
85
  newImports.push(types.importDeclaration([types.importDefaultSpecifier(safeId)], types.stringLiteral(`${VIRTUAL_MODULE_ID}/_/${encoded}`)));
86
86
  }
87
- for (const [keyword, safeId] of state.keywordUids.local.entries()) {
87
+ for (const [keyword, safeId] of state.keywordUids.public.entries()) {
88
88
  const encoded = encodeIdentifier(keyword);
89
- newImports.push(types.importDeclaration([types.importDefaultSpecifier(safeId)], types.stringLiteral(`${VIRTUAL_LOCAL_MODULE_ID}/_/${encoded}`)));
89
+ newImports.push(types.importDeclaration([types.importDefaultSpecifier(safeId)], types.stringLiteral(`${VIRTUAL_PUBLIC_MODULE_ID}/_/${encoded}`)));
90
90
  }
91
91
  if (newImports.length > 0) path.unshiftContainer("body", newImports);
92
92
  }
@@ -94,10 +94,10 @@ const transformPlugin = (mode) => {
94
94
  },
95
95
  ImportDeclaration(path, state) {
96
96
  const sourceValue = path.node.source.value;
97
- if (sourceValue !== "~keywords" && sourceValue !== "~keywords/local") return;
98
- const isLocal = sourceValue === VIRTUAL_LOCAL_MODULE_ID;
99
- const targetSet = isLocal ? state.keywords.local : state.keywords.main;
100
- const targetMap = isLocal ? state.keywordUids.local : state.keywordUids.main;
97
+ if (sourceValue !== "~keywords" && sourceValue !== "~keywords/public") return;
98
+ const isPublic = sourceValue === VIRTUAL_PUBLIC_MODULE_ID;
99
+ const targetSet = isPublic ? state.keywords.public : state.keywords.local;
100
+ const targetMap = isPublic ? state.keywordUids.public : state.keywordUids.local;
101
101
  const programScope = path.scope.getProgramParent();
102
102
  const processKeyword = (keyword) => {
103
103
  targetSet.add(keyword);
@@ -176,8 +176,8 @@ const transformPlugin = (mode) => {
176
176
  },
177
177
  ExportNamedDeclaration(path, state) {
178
178
  const sourceValue = path.node.source?.value;
179
- if (sourceValue !== "~keywords" && sourceValue !== "~keywords/local") return;
180
- const targetSet = sourceValue === "~keywords/local" ? state.keywords.local : state.keywords.main;
179
+ if (sourceValue !== "~keywords" && sourceValue !== "~keywords/public") return;
180
+ const targetSet = sourceValue === "~keywords/public" ? state.keywords.public : state.keywords.local;
181
181
  if (mode === "extract") {
182
182
  for (const specifierPath of path.get("specifiers")) if (specifierPath.isExportSpecifier()) {
183
183
  const local = specifierPath.node.local;
@@ -204,7 +204,7 @@ const transformPlugin = (mode) => {
204
204
  return (() => plugin);
205
205
  };
206
206
  const transformCode = (code, id) => {
207
- if (!code.includes("~keywords") && !code.includes("~keywords/local")) return null;
207
+ if (!code.includes("~keywords") && !code.includes("~keywords/public")) return null;
208
208
  const result = transformSync(code, {
209
209
  babelrc: false,
210
210
  configFile: false,
@@ -217,8 +217,8 @@ const transformCode = (code, id) => {
217
217
  if (!result) return null;
218
218
  const metadata = result.metadata;
219
219
  const keywords = {
220
- main: new Set(metadata?.keywords?.main ?? []),
221
- local: new Set(metadata?.keywords?.local ?? [])
220
+ local: new Set(metadata?.keywords?.local ?? []),
221
+ public: new Set(metadata?.keywords?.public ?? [])
222
222
  };
223
223
  return {
224
224
  code: result.code ?? "",
@@ -227,7 +227,7 @@ const transformCode = (code, id) => {
227
227
  };
228
228
  };
229
229
  const extractKeywords = (code) => {
230
- if (!code.includes("~keywords") && !code.includes("~keywords/local")) return null;
230
+ if (!code.includes("~keywords") && !code.includes("~keywords/public")) return null;
231
231
  let result;
232
232
  try {
233
233
  result = transformSync(code, {
@@ -248,8 +248,8 @@ const extractKeywords = (code) => {
248
248
  if (!result) return null;
249
249
  const metadata = result.metadata;
250
250
  return {
251
- main: new Set(metadata?.keywords?.main ?? []),
252
- local: new Set(metadata?.keywords?.local ?? [])
251
+ local: new Set(metadata?.keywords?.local ?? []),
252
+ public: new Set(metadata?.keywords?.public ?? [])
253
253
  };
254
254
  };
255
255
  //#endregion
@@ -258,12 +258,12 @@ const extractKeywords = (code) => {
258
258
  * @license
259
259
  * SPDX-License-Identifier: MIT
260
260
  */
261
- const generateTypeDeclaration = (keywords, isLocal = false) => {
261
+ const generateTypeDeclaration = (keywords, isPublic = false) => {
262
262
  const sortedKeywords = Array.from(keywords).sort();
263
263
  const content = [];
264
264
  for (const keyword of sortedKeywords) {
265
265
  const safeName = toSafeVarName(encodeIdentifier(keyword));
266
- const value = `${isLocal ? "==" : "*".repeat(7)}.${keyword}`;
266
+ const value = `${isPublic ? "*".repeat(7) : "=="}.${keyword}`;
267
267
  content.push(`declare const ${safeName}: ${JSON.stringify(value)};`);
268
268
  }
269
269
  content.push("");
@@ -284,8 +284,8 @@ const generateTypeDeclaration = (keywords, isLocal = false) => {
284
284
  */
285
285
  const collectKeywordsFromRoot = async (root, silent, ignoredDirs = [], concurrency = 100) => {
286
286
  const collectedKeywords = {
287
- main: /* @__PURE__ */ new Set(),
288
- local: /* @__PURE__ */ new Set()
287
+ local: /* @__PURE__ */ new Set(),
288
+ public: /* @__PURE__ */ new Set()
289
289
  };
290
290
  const start = performance.now();
291
291
  if (!silent) console.error("Scanning project files for keywords...");
@@ -300,15 +300,15 @@ const collectKeywordsFromRoot = async (root, silent, ignoredDirs = [], concurren
300
300
  try {
301
301
  const keywords = extractKeywords(await readFile(file, "utf-8"));
302
302
  if (!keywords) return;
303
- for (const keyword of keywords.main) collectedKeywords.main.add(keyword);
304
303
  for (const keyword of keywords.local) collectedKeywords.local.add(keyword);
304
+ for (const keyword of keywords.public) collectedKeywords.public.add(keyword);
305
305
  processed++;
306
306
  } catch (error) {
307
307
  if (!silent) console.error(`Failed to process ${file}: ${error}`);
308
308
  }
309
309
  });
310
310
  const elapsed = performance.now() - start;
311
- if (!silent) console.error(`Scan complete: ${processed}/${files.length} files, ${collectedKeywords.main.size} main, ${collectedKeywords.local.size} local keywords (${elapsed.toFixed(2)}ms).`);
311
+ if (!silent) console.error(`Scan complete: ${processed}/${files.length} files, ${collectedKeywords.local.size} local, ${collectedKeywords.public.size} public keywords (${elapsed.toFixed(2)}ms).`);
312
312
  return collectedKeywords;
313
313
  };
314
314
  const pkgJson = {
@@ -317,9 +317,9 @@ const pkgJson = {
317
317
  sideEffects: false,
318
318
  exports: {
319
319
  ".": { types: "./index.d.ts" },
320
- "./local": { types: "./local.d.ts" },
320
+ "./public": { types: "./public.d.ts" },
321
321
  [`./_/*`]: `./_/*`,
322
- [`./local/_/*`]: `./local/_/*`
322
+ [`./public/_/*`]: `./public/_/*`
323
323
  }
324
324
  };
325
325
  const createRunner = (options) => {
@@ -329,12 +329,12 @@ const createRunner = (options) => {
329
329
  return collectKeywordsFromRoot(root, silent);
330
330
  },
331
331
  async save(keywords) {
332
- const content = generateTypeDeclaration(keywords.main);
333
- const localContent = generateTypeDeclaration(keywords.local, true);
332
+ const content = generateTypeDeclaration(keywords.local);
333
+ const publicContent = generateTypeDeclaration(keywords.public, true);
334
334
  const outPath = path.join(root, outDir);
335
335
  await mkdir(outPath, { recursive: true });
336
336
  await writeFile(path.join(outPath, "index.d.ts"), `${content.trim()}\n`);
337
- await writeFile(path.join(outPath, "local.d.ts"), `${localContent.trim()}\n`);
337
+ await writeFile(path.join(outPath, "public.d.ts"), `${publicContent.trim()}\n`);
338
338
  await writeFile(path.join(outPath, "package.json"), `${JSON.stringify(pkgJson, null, 2)}\n`);
339
339
  },
340
340
  async run() {
@@ -361,7 +361,7 @@ const createHasher = (secret) => {
361
361
  const cache = /* @__PURE__ */ new Map();
362
362
  return (input) => {
363
363
  if (cache.has(input)) return cache.get(input);
364
- const payload = `9:${VIRTUAL_MODULE_ID}|${input.length}:${input}`;
364
+ const payload = `16:${VIRTUAL_PUBLIC_MODULE_ID}|${input.length}:${input}`;
365
365
  const buffer = createHmac("sha256", secret).update(payload).digest("hex");
366
366
  let entropy = BigInt(`0x${buffer}`);
367
367
  let result = "";
@@ -379,7 +379,7 @@ const createHasher = (secret) => {
379
379
  };
380
380
  const shuffle = (str, secret, salt) => {
381
381
  const arr = Array.from(str);
382
- const keyingMaterial = hkdfSync("sha256", secret, salt, VIRTUAL_LOCAL_MODULE_ID, (arr.length - 1) * 4);
382
+ const keyingMaterial = hkdfSync("sha256", secret, salt, VIRTUAL_MODULE_ID, (arr.length - 1) * 4);
383
383
  const prngBuffer = Buffer.from(keyingMaterial);
384
384
  let byteOffset = 0;
385
385
  for (let i = arr.length - 1; i > 0; i--) {
@@ -417,6 +417,6 @@ const createCounter = (secret) => {
417
417
  };
418
418
  };
419
419
  //#endregion
420
- export { transformCode as a, VIRTUAL_LOCAL_MODULE_ID as c, extractKeywords as i, VIRTUAL_MODULE_ID as l, createHasher as n, encodeIdentifier as o, createRunner as r, PLUGIN_NAME as s, createCounter as t };
420
+ export { transformCode as a, VIRTUAL_MODULE_ID as c, extractKeywords as i, VIRTUAL_PUBLIC_MODULE_ID as l, createHasher as n, encodeIdentifier as o, createRunner as r, PLUGIN_NAME as s, createCounter as t };
421
421
 
422
- //# sourceMappingURL=hash-CvUe2HGU.js.map
422
+ //# sourceMappingURL=hash-DCwSROqn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash-DCwSROqn.js","names":["t","info"],"sources":["../src/internal/constants.ts","../src/internal/encode.ts","../src/internal/transform.ts","../src/internal/typegen.ts","../src/internal/cli.ts","../src/internal/hash.ts"],"sourcesContent":["/**\n * @license\n * SPDX-License-Identifier: MIT\n */\n\nexport const VIRTUAL_MODULE_ID = '~keywords';\nexport const VIRTUAL_PUBLIC_MODULE_ID = '~keywords/public';\n\nexport const PLUGIN_NAME = 'unplugin-keywords';\n\nexport const HASH_LENGTH = 7;\n\nexport const KEYWORD_ROUTE_SEGMENT = '_';\n\n// URL-safe so that K.abc can be used in URL\nexport const DEBUG_SEPARATOR = '.';\n","/**\n * @license\n * SPDX-License-Identifier: MIT\n */\n\ndeclare const __encoded__: unique symbol;\ntype Encoded = string & { [__encoded__]: never };\n\nexport const encodeIdentifier = (identifier: string): Encoded => {\n let encoded = '';\n for (let i = 0; i < identifier.length; i++) {\n const c = identifier[i] as string;\n if (/[a-zA-Z0-9_]/.test(c)) {\n encoded += c;\n } else if (c === '$') {\n encoded += '$$';\n } else {\n encoded += `$${c.charCodeAt(0).toString(16).padStart(4, '0')}`;\n }\n }\n return encoded as Encoded;\n};\n\nexport const toSafeVarName = (encoded: Encoded): string => `_$${encoded}`;\n","/**\n * @license\n * SPDX-License-Identifier: MIT\n */\n\nimport {\n type FileResult,\n type NodePath,\n type PluginItem,\n type PluginObject,\n type PluginPass,\n types as t,\n transformSync,\n} from '@babel/core';\nimport {\n KEYWORD_ROUTE_SEGMENT,\n PLUGIN_NAME,\n VIRTUAL_MODULE_ID,\n VIRTUAL_PUBLIC_MODULE_ID,\n} from './constants.js';\nimport { encodeIdentifier, toSafeVarName } from './encode.js';\n\nexport interface KeywordSet {\n local: Set<string>;\n public: Set<string>;\n}\n\nconst isPureTypeSpace = (path: NodePath): boolean => {\n let current: NodePath | null = path;\n while (current) {\n const parent = current.parentPath;\n if (!parent) {\n break;\n }\n // 1. Value crossings via `typeof`\n if (parent.isTSTypeQuery()) {\n return false;\n }\n // 2. Computed keys (e.g., interface I { [Abc]: string })\n if ('computed' in parent.node && parent.node.computed) {\n if (current.key === 'key' || current.key === 'property') {\n return false;\n }\n }\n // 3-A. Definitive Type Contexts\n if (\n parent.isTSType() ||\n parent.isTSTypeParameterDeclaration() ||\n parent.isTSTypeParameterInstantiation() ||\n parent.isTSClassImplements() ||\n parent.isTSInterfaceHeritage()\n ) {\n return true;\n }\n // 3-B. Type Declaration Identifiers (e.g., interface Abc {}, type Abc = {})\n if (\n parent.isTSInterfaceDeclaration() ||\n parent.isTSTypeAliasDeclaration() ||\n parent.isTSEnumDeclaration() ||\n parent.isTSModuleDeclaration()\n ) {\n if (current.key === 'id') {\n return true;\n }\n }\n // 4. Continue up structural TS nodes (A.B.C)\n if (parent.isTSQualifiedName() || parent.isTSEntityName()) {\n current = current.parentPath;\n continue;\n }\n // 5. If we reach standard JS statements/expressions, it implies Value Space.\n if (parent.isExpression() || parent.isStatement()) {\n break;\n }\n current = current.parentPath;\n }\n return false;\n};\n\ninterface TransformState extends PluginPass {\n keywords: KeywordSet;\n keywordUids: {\n local: Map<string, t.Identifier>;\n public: Map<string, t.Identifier>;\n };\n}\n\ninterface TransformMetadata {\n keywords?: { local: string[]; public: string[] };\n}\n\nconst transformPlugin = (mode: 'extract' | 'transform'): PluginItem => {\n const plugin: PluginObject<TransformState> = {\n name: `${PLUGIN_NAME}:${mode}`,\n\n visitor: {\n Program: {\n enter(_, state) {\n state.keywords = { local: new Set(), public: new Set() };\n state.keywordUids = { local: new Map(), public: new Map() };\n },\n\n exit(path, state) {\n const metadata = state.file.metadata as TransformMetadata;\n metadata.keywords = {\n local: Array.from(state.keywords.local),\n public: Array.from(state.keywords.public),\n };\n\n if (mode === 'transform') {\n const newImports = [];\n for (const [keyword, safeId] of state.keywordUids.local.entries()) {\n const encoded = encodeIdentifier(keyword);\n newImports.push(\n t.importDeclaration(\n [t.importDefaultSpecifier(safeId)],\n t.stringLiteral(\n `${VIRTUAL_MODULE_ID}/${KEYWORD_ROUTE_SEGMENT}/${encoded}`,\n ),\n ),\n );\n }\n for (const [\n keyword,\n safeId,\n ] of state.keywordUids.public.entries()) {\n const encoded = encodeIdentifier(keyword);\n newImports.push(\n t.importDeclaration(\n [t.importDefaultSpecifier(safeId)],\n t.stringLiteral(\n `${VIRTUAL_PUBLIC_MODULE_ID}/${KEYWORD_ROUTE_SEGMENT}/${encoded}`,\n ),\n ),\n );\n }\n if (newImports.length > 0) {\n path.unshiftContainer('body', newImports);\n }\n }\n },\n },\n\n ImportDeclaration(path, state) {\n const sourceValue = path.node.source.value;\n if (\n sourceValue !== VIRTUAL_MODULE_ID &&\n sourceValue !== VIRTUAL_PUBLIC_MODULE_ID\n ) {\n return;\n }\n const isPublic = sourceValue === VIRTUAL_PUBLIC_MODULE_ID;\n const targetSet = isPublic\n ? state.keywords.public\n : state.keywords.local;\n const targetMap = isPublic\n ? state.keywordUids.public\n : state.keywordUids.local;\n\n const programScope = path.scope.getProgramParent();\n const processKeyword = (keyword: string): t.Identifier | null => {\n targetSet.add(keyword);\n if (mode === 'extract') {\n return null;\n }\n if (targetMap.has(keyword)) {\n return targetMap.get(keyword) as t.Identifier;\n }\n const encoded = encodeIdentifier(keyword);\n const safeName = toSafeVarName(encoded);\n const uid = programScope.generateUidIdentifier(safeName);\n targetMap.set(keyword, uid);\n return uid;\n };\n\n for (const specifierPath of path.get('specifiers')) {\n const localName = specifierPath.node.local.name;\n const binding = path.scope.getBinding(localName);\n if (!binding) {\n continue;\n }\n\n // Case A: Default & Named Imports\n if (\n specifierPath.isImportDefaultSpecifier() ||\n specifierPath.isImportSpecifier()\n ) {\n let keyword: string;\n if (specifierPath.isImportDefaultSpecifier()) {\n keyword = 'default';\n } else {\n const imported = specifierPath.node.imported;\n keyword = t.isIdentifier(imported)\n ? imported.name\n : imported.value;\n }\n const uidNode = processKeyword(keyword);\n if (!uidNode) {\n continue;\n }\n\n // 1) Fast Path: Values & JSX\n for (const refPath of binding.referencePaths) {\n if (isPureTypeSpace(refPath)) {\n continue;\n }\n if (refPath.isJSXIdentifier()) {\n refPath.replaceWith(t.jsxIdentifier(uidNode.name));\n } else {\n refPath.replaceWith(t.cloneNode(uidNode));\n }\n }\n\n // 2) Slow Path: TS Types\n // NOTE: Can be skipped due to type erasure, but for consistency\n path.parentPath.traverse({\n // e.g., type T = typeof abc;\n TSTypeQuery(tsPath) {\n if (\n t.isIdentifier(tsPath.node.exprName) &&\n tsPath.node.exprName.name === localName &&\n tsPath.scope.getBinding(localName) === binding\n ) {\n tsPath.get('exprName').replaceWith(t.cloneNode(uidNode));\n }\n },\n });\n }\n\n // Case B: Namespace Imports\n else if (specifierPath.isImportNamespaceSpecifier()) {\n // 1) Fast Path: JS Values & JSX accesses\n for (const refPath of binding.referencePaths) {\n if (isPureTypeSpace(refPath)) {\n continue;\n }\n const parentPath = refPath.parentPath;\n if (!parentPath) {\n continue;\n }\n if (\n parentPath.isMemberExpression() &&\n parentPath.node.object === refPath.node\n ) {\n const propNode = parentPath.node.property;\n let keyword: string | undefined;\n if (!parentPath.node.computed && t.isIdentifier(propNode)) {\n keyword = propNode.name;\n } else if (\n parentPath.node.computed &&\n t.isStringLiteral(propNode)\n ) {\n keyword = propNode.value;\n }\n if (keyword) {\n const uidNode = processKeyword(keyword);\n if (uidNode) {\n parentPath.replaceWith(t.cloneNode(uidNode));\n }\n }\n } else if (\n parentPath.isJSXMemberExpression() &&\n parentPath.node.object === refPath.node\n ) {\n const keyword = parentPath.node.property.name;\n const uidNode = processKeyword(keyword);\n if (uidNode) {\n parentPath.replaceWith(t.jsxIdentifier(uidNode.name));\n }\n }\n }\n\n // 2) Slow Path: TS Namespace Types\n path.parentPath.traverse({\n // e.g., type T = typeof A.abc;\n TSTypeQuery(tsPath) {\n const expr = tsPath.node.exprName;\n if (\n t.isTSQualifiedName(expr) &&\n t.isIdentifier(expr.left) &&\n expr.left.name === localName &&\n tsPath.scope.getBinding(localName) === binding\n ) {\n const keyword = expr.right.name;\n const uidNode = processKeyword(keyword);\n if (uidNode) {\n tsPath.get('exprName').replaceWith(t.cloneNode(uidNode));\n }\n }\n },\n\n // e.g., type T = ((typeof A))['prop'];\n TSIndexedAccessType(tsPath) {\n const objPath = tsPath.get('objectType') as NodePath;\n if (\n objPath.isTSTypeQuery() &&\n t.isIdentifier(objPath.node.exprName) &&\n objPath.node.exprName.name === localName &&\n tsPath.scope.getBinding(localName) === binding\n ) {\n const indexNode = tsPath.node.indexType;\n if (\n t.isTSLiteralType(indexNode) &&\n t.isStringLiteral(indexNode.literal)\n ) {\n const keyword = indexNode.literal.value;\n const uidNode = processKeyword(keyword);\n if (uidNode) {\n tsPath.replaceWith(t.tsTypeQuery(t.cloneNode(uidNode)));\n }\n }\n }\n },\n });\n }\n }\n\n if (mode === 'transform') {\n path.remove();\n }\n },\n\n ExportNamedDeclaration(path, state) {\n const sourceValue = path.node.source?.value;\n if (\n sourceValue !== VIRTUAL_MODULE_ID &&\n sourceValue !== VIRTUAL_PUBLIC_MODULE_ID\n ) {\n return;\n }\n const isPublic = sourceValue === VIRTUAL_PUBLIC_MODULE_ID;\n const targetSet = isPublic\n ? state.keywords.public\n : state.keywords.local;\n\n if (mode === 'extract') {\n for (const specifierPath of path.get('specifiers')) {\n if (specifierPath.isExportSpecifier()) {\n const local = specifierPath.node.local as\n | t.Identifier\n | t.StringLiteral; // local can be a StringLiteral in ES2022\n const keyword = t.isIdentifier(local) ? local.name : local.value;\n targetSet.add(keyword);\n }\n }\n return;\n }\n\n const newExports = path\n .get('specifiers')\n .map((specifierPath) => {\n if (specifierPath.isExportSpecifier()) {\n const local = specifierPath.node.local as\n | t.Identifier\n | t.StringLiteral; // local can be a StringLiteral in ES2022\n const keyword = t.isIdentifier(local) ? local.name : local.value;\n targetSet.add(keyword);\n const encoded = encodeIdentifier(keyword);\n return t.exportNamedDeclaration(\n null,\n [\n t.exportSpecifier(\n t.identifier('default'),\n specifierPath.node.exported,\n ),\n ],\n t.stringLiteral(\n `${sourceValue}/${KEYWORD_ROUTE_SEGMENT}/${encoded}`,\n ),\n );\n }\n return null;\n })\n .filter((node): node is t.ExportNamedDeclaration => node !== null);\n\n if (newExports.length > 0) {\n path.replaceWithMultiple(newExports);\n } else {\n path.remove();\n }\n },\n },\n };\n\n return (() => plugin as PluginObject) as PluginItem;\n};\n\nexport const transformCode = (\n code: string,\n id: string,\n): {\n code: string;\n map: NonNullable<FileResult['map']> | null;\n keywords: KeywordSet;\n} | null => {\n if (\n !code.includes(VIRTUAL_MODULE_ID) &&\n !code.includes(VIRTUAL_PUBLIC_MODULE_ID)\n ) {\n return null;\n }\n const result = transformSync(code, {\n babelrc: false,\n configFile: false,\n filename: id,\n sourceMaps: true,\n ast: false,\n plugins: [transformPlugin('transform')],\n parserOpts: {\n plugins: ['jsx', 'typescript'],\n },\n });\n if (!result) {\n return null;\n }\n const metadata = result.metadata as TransformMetadata | undefined;\n const keywords: KeywordSet = {\n local: new Set(metadata?.keywords?.local ?? []),\n public: new Set(metadata?.keywords?.public ?? []),\n };\n return {\n code: result.code ?? '',\n map: result.map ?? null,\n keywords,\n };\n};\n\nexport const extractKeywords = (code: string): KeywordSet | null => {\n if (\n !code.includes(VIRTUAL_MODULE_ID) &&\n !code.includes(VIRTUAL_PUBLIC_MODULE_ID)\n ) {\n return null;\n }\n let result: FileResult | null;\n try {\n result = transformSync(code, {\n babelrc: false,\n configFile: false,\n sourceMaps: false,\n ast: false,\n code: false,\n plugins: [transformPlugin('extract')],\n parserOpts: {\n plugins: ['jsx', 'typescript'],\n errorRecovery: true,\n },\n });\n } catch {\n return null;\n }\n if (!result) {\n return null;\n }\n const metadata = result.metadata as TransformMetadata | undefined;\n return {\n local: new Set(metadata?.keywords?.local ?? []),\n public: new Set(metadata?.keywords?.public ?? []),\n };\n};\n","/**\n * @license\n * SPDX-License-Identifier: MIT\n */\n\nimport { DEBUG_SEPARATOR, HASH_LENGTH } from './constants.js';\nimport { encodeIdentifier, toSafeVarName } from './encode.js';\n\nexport const generateTypeDeclaration = (\n keywords: Set<string>,\n isPublic: boolean = false,\n): string => {\n const sortedKeywords = Array.from(keywords).sort();\n const content = [];\n\n for (const keyword of sortedKeywords) {\n const encoded = encodeIdentifier(keyword);\n const safeName = toSafeVarName(encoded);\n const hash = isPublic ? '*'.repeat(HASH_LENGTH) : '==';\n const value = `${hash}${DEBUG_SEPARATOR}${keyword}`;\n content.push(`declare const ${safeName}: ${JSON.stringify(value)};`);\n }\n content.push('');\n\n content.push('export {');\n for (const keyword of sortedKeywords) {\n const encoded = encodeIdentifier(keyword);\n const safeName = toSafeVarName(encoded);\n content.push(` ${safeName} as ${JSON.stringify(keyword)},`);\n }\n content.push('};');\n content.push('');\n\n return content.join('\\n');\n};\n","/**\n * @license\n * SPDX-License-Identifier: MIT\n */\n\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { globby } from 'globby';\nimport pLimit from 'p-limit';\nimport { KEYWORD_ROUTE_SEGMENT } from './constants.js';\nimport { extractKeywords, type KeywordSet } from './transform.js';\nimport { generateTypeDeclaration } from './typegen.js';\n\nconst collectKeywordsFromRoot = async (\n root: string,\n silent: boolean,\n ignoredDirs: string[] = [],\n concurrency: number = 100,\n): Promise<KeywordSet> => {\n const collectedKeywords: KeywordSet = { local: new Set(), public: new Set() };\n\n const start = performance.now();\n if (!silent) {\n console.error('Scanning project files for keywords...');\n }\n\n const files = await globby('**/*.{js,ts,mjs,mts,jsx,tsx,mjsx,mtsx}', {\n cwd: root,\n absolute: false,\n ignore: ['**/node_modules/**', ...ignoredDirs.map((dir) => `${dir}/**`)],\n gitignore: true,\n });\n\n let processed = 0;\n const limit = pLimit({ concurrency });\n await limit.map(files, async (file) => {\n try {\n const code = await readFile(file, 'utf-8');\n const keywords = extractKeywords(code);\n if (!keywords) {\n return;\n }\n for (const keyword of keywords.local) {\n collectedKeywords.local.add(keyword);\n }\n for (const keyword of keywords.public) {\n collectedKeywords.public.add(keyword);\n }\n processed++;\n } catch (error) {\n if (!silent) {\n console.error(`Failed to process ${file}: ${error}`);\n }\n }\n });\n\n const elapsed = performance.now() - start;\n if (!silent) {\n console.error(\n `Scan complete: ${processed}/${files.length} files, ${collectedKeywords.local.size} local, ${collectedKeywords.public.size} public keywords (${elapsed.toFixed(2)}ms).`,\n );\n }\n\n return collectedKeywords;\n};\n\nconst pkgJson = {\n private: true,\n type: 'module',\n sideEffects: false,\n exports: {\n '.': {\n types: './index.d.ts',\n },\n './public': {\n types: './public.d.ts',\n },\n [`./${KEYWORD_ROUTE_SEGMENT}/*`]: `./${KEYWORD_ROUTE_SEGMENT}/*`,\n [`./public/${KEYWORD_ROUTE_SEGMENT}/*`]: `./public/${KEYWORD_ROUTE_SEGMENT}/*`,\n },\n};\n\ninterface RunnerOptions {\n root: string;\n silent: boolean;\n outDir: string;\n}\n\nexport const createRunner = (options?: Partial<RunnerOptions>) => {\n const {\n root = process.cwd(),\n silent = false,\n outDir = path.join('node_modules', '~keywords'),\n } = options ?? {};\n return {\n async collect(): Promise<KeywordSet> {\n return collectKeywordsFromRoot(root, silent);\n },\n\n async save(keywords: KeywordSet): Promise<void> {\n const content = generateTypeDeclaration(keywords.local);\n const publicContent = generateTypeDeclaration(keywords.public, true);\n const outPath = path.join(root, outDir);\n await mkdir(outPath, { recursive: true });\n await writeFile(path.join(outPath, 'index.d.ts'), `${content.trim()}\\n`);\n await writeFile(\n path.join(outPath, 'public.d.ts'),\n `${publicContent.trim()}\\n`,\n );\n await writeFile(\n path.join(outPath, 'package.json'),\n `${JSON.stringify(pkgJson, null, 2)}\\n`,\n );\n },\n\n async run(): Promise<void> {\n const keywords = await this.collect();\n await this.save(keywords);\n },\n };\n};\n","/**\n * @license\n * SPDX-License-Identifier: MIT\n */\n\nimport { createHmac, hkdfSync } from 'node:crypto';\nimport {\n HASH_LENGTH,\n VIRTUAL_MODULE_ID,\n VIRTUAL_PUBLIC_MODULE_ID,\n} from './constants.js';\n\nconst ALPHA_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';\nconst DIGIT_CHARS = '0123456789';\nconst BASE62_CHARS = ALPHA_CHARS + DIGIT_CHARS;\n\nconst ALPHA_LEN = BigInt(ALPHA_CHARS.length); // 52n\nconst DIGIT_LEN = BigInt(DIGIT_CHARS.length); // 10n\nconst BASE62_LEN = BigInt(BASE62_CHARS.length); // 62n\n\nexport type Hasher = (input: string) => string;\n\n// Format: [1 Alpha] + [1 Digit] + [N Base62]\n// Avoids any collisions with standard JS API identifiers\nexport const createHasher = (secret: string): Hasher => {\n const base62TailLength = HASH_LENGTH - 2;\n if (base62TailLength < 0 || base62TailLength > 9) {\n // 520 * 62^9 < 2^64 < 520 * 62^10\n throw new Error('Invalid MAX_HASH_LENGTH');\n }\n\n const cache = new Map<string, string>();\n return (input) => {\n if (cache.has(input)) {\n return cache.get(input) as string;\n }\n\n const info = VIRTUAL_PUBLIC_MODULE_ID;\n const payload = `${info.length}:${info}|${input.length}:${input}`;\n const hasher = createHmac('sha256', secret);\n const buffer = hasher.update(payload).digest('hex');\n\n let entropy = BigInt(`0x${buffer}`);\n let result = '';\n\n result += ALPHA_CHARS[Number(entropy % ALPHA_LEN)];\n entropy /= ALPHA_LEN;\n result += DIGIT_CHARS[Number(entropy % DIGIT_LEN)];\n entropy /= DIGIT_LEN;\n for (let i = 0; i < base62TailLength; i++) {\n result += BASE62_CHARS[Number(entropy % BASE62_LEN)];\n entropy /= BASE62_LEN;\n }\n\n cache.set(input, result);\n return result;\n };\n};\n\n// Fisher-Yates based deterministic shuffle\nconst shuffle = (str: string, secret: string, salt: string): string => {\n const arr = Array.from(str);\n const requiredBytes = (arr.length - 1) * 4;\n\n const info = VIRTUAL_MODULE_ID;\n const keyingMaterial = hkdfSync('sha256', secret, salt, info, requiredBytes);\n const prngBuffer = Buffer.from(keyingMaterial);\n\n let byteOffset = 0;\n for (let i = arr.length - 1; i > 0; i--) {\n const random32 = prngBuffer.readUInt32BE(byteOffset);\n byteOffset += 4;\n const j = random32 % (i + 1);\n const temp = arr[i] as string;\n arr[i] = arr[j] as string;\n arr[j] = temp;\n }\n\n return arr.join('');\n};\n\nexport const createCounter = (secret: string): Hasher => {\n const shuffledAlpha = shuffle(ALPHA_CHARS, secret, 'alpha');\n const shuffledDigit = shuffle(DIGIT_CHARS, secret, 'digit');\n const shuffledBase62 = shuffle(BASE62_CHARS, secret, 'base62');\n\n let index = 0;\n const cache = new Map<string, string>();\n return (input) => {\n if (cache.has(input)) {\n return cache.get(input) as string;\n }\n\n let result = '';\n let current = index;\n index++;\n\n result += shuffledAlpha[current % shuffledAlpha.length];\n current = Math.floor(current / shuffledAlpha.length);\n result += shuffledDigit[current % shuffledDigit.length];\n current = Math.floor(current / shuffledDigit.length);\n while (current > 0) {\n current--;\n result += shuffledBase62[current % shuffledBase62.length];\n current = Math.floor(current / shuffledBase62.length);\n }\n\n cache.set(input, result);\n return result;\n };\n};\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as unpluginFactory } from "./plugin-BxpZVMN0.js";
1
+ import { t as unpluginFactory } from "./plugin-DrcLx4Tu.js";
2
2
  import { createUnplugin } from "unplugin";
3
3
  //#region src/index.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { a as transformCode, c as VIRTUAL_LOCAL_MODULE_ID, i as extractKeywords, l as VIRTUAL_MODULE_ID, n as createHasher, o as encodeIdentifier, r as createRunner, s as PLUGIN_NAME, t as createCounter } from "./hash-CvUe2HGU.js";
1
+ import { a as transformCode, c as VIRTUAL_MODULE_ID, i as extractKeywords, l as VIRTUAL_PUBLIC_MODULE_ID, n as createHasher, o as encodeIdentifier, r as createRunner, s as PLUGIN_NAME, t as createCounter } from "./hash-DCwSROqn.js";
2
2
  import { readFile } from "node:fs/promises";
3
3
  import pLimit from "p-limit";
4
4
  //#region src/internal/plugin.ts
@@ -19,35 +19,38 @@ const unpluginFactory = ({ isDev, secret }) => {
19
19
  const runner = createRunner({ silent: true });
20
20
  const runnerLimit = pLimit({ concurrency: 1 });
21
21
  const typegenKeywords = {
22
- main: /* @__PURE__ */ new Set(),
23
- local: /* @__PURE__ */ new Set()
22
+ local: /* @__PURE__ */ new Set(),
23
+ public: /* @__PURE__ */ new Set()
24
24
  };
25
25
  let isInitialized = false;
26
26
  const runInit = async () => {
27
27
  try {
28
28
  const keywords = await runner.collect();
29
- for (const keyword of keywords.main) typegenKeywords.main.add(keyword);
30
29
  for (const keyword of keywords.local) typegenKeywords.local.add(keyword);
30
+ for (const keyword of keywords.public) typegenKeywords.public.add(keyword);
31
31
  await runner.save(typegenKeywords);
32
32
  isInitialized = true;
33
33
  } catch {}
34
34
  };
35
- let hasherMain;
35
+ let hasherPublic;
36
36
  let hasherLocal;
37
37
  let resolvedMap;
38
38
  return {
39
39
  name: PLUGIN_NAME,
40
40
  buildStart() {
41
- hasherMain = createHasher(secret);
41
+ hasherPublic = createHasher(secret);
42
42
  hasherLocal = createCounter(secret);
43
43
  resolvedMap = /* @__PURE__ */ new Map();
44
44
  runnerLimit(async () => {
45
45
  if (!isInitialized) await runInit();
46
46
  });
47
47
  },
48
+ async buildEnd() {
49
+ await runnerLimit(() => Promise.resolve());
50
+ },
48
51
  resolveId: {
49
52
  filter: { id: {
50
- include: [...toIncludes(VIRTUAL_MODULE_ID), ...toIncludes(VIRTUAL_LOCAL_MODULE_ID)],
53
+ include: [...toIncludes(VIRTUAL_MODULE_ID), ...toIncludes(VIRTUAL_PUBLIC_MODULE_ID)],
51
54
  exclude: COMMON_EXCLUDES
52
55
  } },
53
56
  handler(id) {
@@ -56,7 +59,7 @@ const unpluginFactory = ({ isDev, secret }) => {
56
59
  },
57
60
  load: {
58
61
  filter: { id: {
59
- include: [...toIncludes(resolveId(VIRTUAL_MODULE_ID)), ...toIncludes(resolveId(VIRTUAL_LOCAL_MODULE_ID))],
62
+ include: [...toIncludes(resolveId(VIRTUAL_MODULE_ID)), ...toIncludes(resolveId(VIRTUAL_PUBLIC_MODULE_ID))],
60
63
  exclude: COMMON_EXCLUDES
61
64
  } },
62
65
  handler(id) {
@@ -71,23 +74,23 @@ const unpluginFactory = ({ isDev, secret }) => {
71
74
  include: [SUFFIX_REGEX],
72
75
  exclude: COMMON_EXCLUDES
73
76
  },
74
- code: { include: [VIRTUAL_MODULE_ID, VIRTUAL_LOCAL_MODULE_ID] }
77
+ code: { include: [VIRTUAL_MODULE_ID, VIRTUAL_PUBLIC_MODULE_ID] }
75
78
  },
76
79
  handler(code, id) {
77
80
  const result = transformCode(code, id);
78
81
  if (!result) return null;
79
82
  const { code: transformed, map, keywords } = result;
80
- for (const keyword of keywords.main) {
83
+ for (const keyword of keywords.local) {
81
84
  const resolvedId = resolveId(`${VIRTUAL_MODULE_ID}/_/${encodeIdentifier(keyword)}`);
82
85
  if (resolvedMap.has(resolvedId)) continue;
83
- const hash = hasherMain(keyword);
86
+ const hash = hasherLocal(keyword);
84
87
  const value = isDev ? `${hash}.${keyword}` : hash;
85
88
  resolvedMap.set(resolvedId, `export default ${JSON.stringify(value)};\n`);
86
89
  }
87
- for (const keyword of keywords.local) {
88
- const resolvedId = resolveId(`${VIRTUAL_LOCAL_MODULE_ID}/_/${encodeIdentifier(keyword)}`);
90
+ for (const keyword of keywords.public) {
91
+ const resolvedId = resolveId(`${VIRTUAL_PUBLIC_MODULE_ID}/_/${encodeIdentifier(keyword)}`);
89
92
  if (resolvedMap.has(resolvedId)) continue;
90
- const hash = hasherLocal(keyword);
93
+ const hash = hasherPublic(keyword);
91
94
  const value = isDev ? `${hash}.${keyword}` : hash;
92
95
  resolvedMap.set(resolvedId, `export default ${JSON.stringify(value)};\n`);
93
96
  }
@@ -108,14 +111,14 @@ const unpluginFactory = ({ isDev, secret }) => {
108
111
  const keywords = extractKeywords(code);
109
112
  if (!keywords) return;
110
113
  let isAdded = false;
111
- for (const keyword of keywords.main) if (!typegenKeywords.main.has(keyword)) {
112
- typegenKeywords.main.add(keyword);
113
- isAdded = true;
114
- }
115
114
  for (const keyword of keywords.local) if (!typegenKeywords.local.has(keyword)) {
116
115
  typegenKeywords.local.add(keyword);
117
116
  isAdded = true;
118
117
  }
118
+ for (const keyword of keywords.public) if (!typegenKeywords.public.has(keyword)) {
119
+ typegenKeywords.public.add(keyword);
120
+ isAdded = true;
121
+ }
119
122
  if (!isInitialized || isAdded) runnerLimit(async () => {
120
123
  if (!isInitialized) await runInit();
121
124
  else if (isAdded) try {
@@ -128,4 +131,4 @@ const unpluginFactory = ({ isDev, secret }) => {
128
131
  //#endregion
129
132
  export { unpluginFactory as t };
130
133
 
131
- //# sourceMappingURL=plugin-BxpZVMN0.js.map
134
+ //# sourceMappingURL=plugin-DrcLx4Tu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-DrcLx4Tu.js","names":[],"sources":["../src/internal/plugin.ts"],"sourcesContent":["/**\n * @license\n * SPDX-License-Identifier: MIT\n */\n\nimport { readFile } from 'node:fs/promises';\nimport pLimit from 'p-limit';\nimport type { UnpluginFactory } from 'unplugin';\nimport { createRunner } from './cli.js';\nimport {\n DEBUG_SEPARATOR,\n KEYWORD_ROUTE_SEGMENT,\n PLUGIN_NAME,\n VIRTUAL_MODULE_ID,\n VIRTUAL_PUBLIC_MODULE_ID,\n} from './constants.js';\nimport { encodeIdentifier } from './encode.js';\nimport { createCounter, createHasher, type Hasher } from './hash.js';\nimport {\n extractKeywords,\n type KeywordSet,\n transformCode,\n} from './transform.js';\n\nconst resolveId = (id: string): string => `\\0${id}`;\n\nconst splitQuery = (id: string): [string, string | undefined] => {\n const index = id.indexOf('?');\n if (index === -1) {\n return [id, undefined];\n }\n return [id.slice(0, index), id.slice(index + 1)];\n};\n\nconst toIncludes = (id: string): RegExp[] => [new RegExp(`^${id}/`)];\n\nconst SUFFIX_REGEX = /\\.m?[jt]sx?$/;\nconst COMMON_EXCLUDES = [/\\/node_modules\\//];\n\nexport interface Options {\n /**\n * If true, preserves the original keyword as a suffix in the generated\n * identifier for easier debugging (e.g., `\"zXpL21k.SET_USER\"`).\n */\n isDev: boolean;\n /**\n * The cryptographic key used to initialize the deterministic HMAC algorithm.\n * Modifying this value will globally rotate all generated hashes.\n * To ensure cross-boundary consistency between independent builds,\n * they must share the same secret key.\n */\n secret: string;\n}\n\nexport const unpluginFactory: UnpluginFactory<Options> = ({\n isDev,\n secret,\n}) => {\n const runner = createRunner({ silent: true });\n const runnerLimit = pLimit({ concurrency: 1 });\n const typegenKeywords: KeywordSet = { local: new Set(), public: new Set() };\n\n let isInitialized = false;\n const runInit = async () => {\n try {\n const keywords = await runner.collect();\n for (const keyword of keywords.local) {\n typegenKeywords.local.add(keyword);\n }\n for (const keyword of keywords.public) {\n typegenKeywords.public.add(keyword);\n }\n await runner.save(typegenKeywords);\n isInitialized = true;\n } catch {}\n };\n\n let hasherPublic: Hasher;\n let hasherLocal: Hasher;\n let resolvedMap: Map<string, string>;\n\n return {\n name: PLUGIN_NAME,\n\n buildStart() {\n hasherPublic = createHasher(secret);\n hasherLocal = createCounter(secret);\n resolvedMap = new Map();\n runnerLimit(async () => {\n if (!isInitialized) {\n await runInit();\n }\n });\n },\n\n async buildEnd() {\n // Flush the background queue\n await runnerLimit(() => Promise.resolve());\n },\n\n resolveId: {\n filter: {\n id: {\n include: [\n ...toIncludes(VIRTUAL_MODULE_ID),\n ...toIncludes(VIRTUAL_PUBLIC_MODULE_ID),\n ],\n exclude: COMMON_EXCLUDES,\n },\n },\n handler(id) {\n return resolveId(id);\n },\n },\n\n load: {\n filter: {\n id: {\n include: [\n ...toIncludes(resolveId(VIRTUAL_MODULE_ID)),\n ...toIncludes(resolveId(VIRTUAL_PUBLIC_MODULE_ID)),\n ],\n exclude: COMMON_EXCLUDES,\n },\n },\n handler(id) {\n const [validId] = splitQuery(id);\n if (resolvedMap.has(validId)) {\n return resolvedMap.get(validId);\n }\n return null;\n },\n },\n\n transform: {\n filter: {\n id: {\n include: [SUFFIX_REGEX],\n exclude: COMMON_EXCLUDES,\n },\n code: {\n include: [VIRTUAL_MODULE_ID, VIRTUAL_PUBLIC_MODULE_ID],\n },\n },\n handler(code, id) {\n const result = transformCode(code, id);\n if (!result) {\n return null;\n }\n const { code: transformed, map, keywords } = result;\n for (const keyword of keywords.local) {\n const encoded = encodeIdentifier(keyword);\n const resolvedId = resolveId(\n `${VIRTUAL_MODULE_ID}/${KEYWORD_ROUTE_SEGMENT}/${encoded}`,\n );\n if (resolvedMap.has(resolvedId)) {\n continue;\n }\n const hash = hasherLocal(keyword);\n const value = isDev ? `${hash}${DEBUG_SEPARATOR}${keyword}` : hash;\n resolvedMap.set(\n resolvedId,\n `export default ${JSON.stringify(value)};\\n`,\n );\n }\n for (const keyword of keywords.public) {\n const encoded = encodeIdentifier(keyword);\n const resolvedId = resolveId(\n `${VIRTUAL_PUBLIC_MODULE_ID}/${KEYWORD_ROUTE_SEGMENT}/${encoded}`,\n );\n if (resolvedMap.has(resolvedId)) {\n continue;\n }\n const hash = hasherPublic(keyword);\n const value = isDev ? `${hash}${DEBUG_SEPARATOR}${keyword}` : hash;\n resolvedMap.set(\n resolvedId,\n `export default ${JSON.stringify(value)};\\n`,\n );\n }\n return { code: transformed, map };\n },\n },\n\n async watchChange(id, { event }) {\n if (\n !SUFFIX_REGEX.test(id) ||\n COMMON_EXCLUDES.some((regex) => regex.test(id)) ||\n event === 'delete'\n ) {\n return;\n }\n let code: string;\n try {\n code = await readFile(id, 'utf-8');\n } catch {\n return;\n }\n const keywords = extractKeywords(code);\n if (!keywords) {\n return;\n }\n let isAdded = false;\n for (const keyword of keywords.local) {\n if (!typegenKeywords.local.has(keyword)) {\n typegenKeywords.local.add(keyword);\n isAdded = true;\n }\n }\n for (const keyword of keywords.public) {\n if (!typegenKeywords.public.has(keyword)) {\n typegenKeywords.public.add(keyword);\n isAdded = true;\n }\n }\n if (!isInitialized || isAdded) {\n runnerLimit(async () => {\n if (!isInitialized) {\n await runInit();\n } else if (isAdded) {\n try {\n await runner.save(typegenKeywords);\n } catch {}\n }\n });\n }\n },\n };\n};\n"],"mappings":"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"}
package/dist/rolldown.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as unpluginFactory } from "./plugin-BxpZVMN0.js";
1
+ import { t as unpluginFactory } from "./plugin-DrcLx4Tu.js";
2
2
  import { createRolldownPlugin } from "unplugin";
3
3
  //#region src/rolldown.ts
4
4
  /**
package/dist/rollup.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as unpluginFactory } from "./plugin-BxpZVMN0.js";
1
+ import { t as unpluginFactory } from "./plugin-DrcLx4Tu.js";
2
2
  import { createRollupPlugin } from "unplugin";
3
3
  //#region src/rollup.ts
4
4
  /**
package/dist/rspack.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as unpluginFactory } from "./plugin-BxpZVMN0.js";
1
+ import { t as unpluginFactory } from "./plugin-DrcLx4Tu.js";
2
2
  import { createRspackPlugin } from "unplugin";
3
3
  //#region src/rspack.ts
4
4
  /**
package/dist/vite.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as unpluginFactory } from "./plugin-BxpZVMN0.js";
1
+ import { t as unpluginFactory } from "./plugin-DrcLx4Tu.js";
2
2
  import { createVitePlugin } from "unplugin";
3
3
  //#region src/vite.ts
4
4
  /**
package/dist/webpack.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as unpluginFactory } from "./plugin-BxpZVMN0.js";
1
+ import { t as unpluginFactory } from "./plugin-DrcLx4Tu.js";
2
2
  import { createWebpackPlugin } from "unplugin";
3
3
  //#region src/webpack.ts
4
4
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unplugin-keywords",
3
- "version": "2.9.0",
3
+ "version": "2.10.0",
4
4
  "description": "A build plugin for structural string literal minification and obfuscation.",
5
5
  "keywords": [
6
6
  "unplugin",
@@ -1 +0,0 @@
1
- {"version":3,"file":"hash-CvUe2HGU.js","names":["t","info"],"sources":["../src/internal/constants.ts","../src/internal/encode.ts","../src/internal/transform.ts","../src/internal/typegen.ts","../src/internal/cli.ts","../src/internal/hash.ts"],"sourcesContent":["/**\n * @license\n * SPDX-License-Identifier: MIT\n */\n\nexport const VIRTUAL_MODULE_ID = '~keywords';\nexport const VIRTUAL_LOCAL_MODULE_ID = '~keywords/local';\n\nexport const PLUGIN_NAME = 'unplugin-keywords';\n\nexport const HASH_LENGTH = 7;\n\nexport const KEYWORD_ROUTE_SEGMENT = '_';\n\n// URL-safe so that K.abc can be used in URL\nexport const DEBUG_SEPARATOR = '.';\n","/**\n * @license\n * SPDX-License-Identifier: MIT\n */\n\ndeclare const __encoded__: unique symbol;\ntype Encoded = string & { [__encoded__]: never };\n\nexport const encodeIdentifier = (identifier: string): Encoded => {\n let encoded = '';\n for (let i = 0; i < identifier.length; i++) {\n const c = identifier[i] as string;\n if (/[a-zA-Z0-9_]/.test(c)) {\n encoded += c;\n } else if (c === '$') {\n encoded += '$$';\n } else {\n encoded += `$${c.charCodeAt(0).toString(16).padStart(4, '0')}`;\n }\n }\n return encoded as Encoded;\n};\n\nexport const toSafeVarName = (encoded: Encoded): string => `_$${encoded}`;\n","/**\n * @license\n * SPDX-License-Identifier: MIT\n */\n\nimport {\n type FileResult,\n type NodePath,\n type PluginItem,\n type PluginObject,\n type PluginPass,\n types as t,\n transformSync,\n} from '@babel/core';\nimport {\n KEYWORD_ROUTE_SEGMENT,\n PLUGIN_NAME,\n VIRTUAL_LOCAL_MODULE_ID,\n VIRTUAL_MODULE_ID,\n} from './constants.js';\nimport { encodeIdentifier, toSafeVarName } from './encode.js';\n\nexport interface KeywordSet {\n main: Set<string>;\n local: Set<string>;\n}\n\nconst isPureTypeSpace = (path: NodePath): boolean => {\n let current: NodePath | null = path;\n while (current) {\n const parent = current.parentPath;\n if (!parent) {\n break;\n }\n // 1. Value crossings via `typeof`\n if (parent.isTSTypeQuery()) {\n return false;\n }\n // 2. Computed keys (e.g., interface I { [Abc]: string })\n if ('computed' in parent.node && parent.node.computed) {\n if (current.key === 'key' || current.key === 'property') {\n return false;\n }\n }\n // 3-A. Definitive Type Contexts\n if (\n parent.isTSType() ||\n parent.isTSTypeParameterDeclaration() ||\n parent.isTSTypeParameterInstantiation() ||\n parent.isTSClassImplements() ||\n parent.isTSInterfaceHeritage()\n ) {\n return true;\n }\n // 3-B. Type Declaration Identifiers (e.g., interface Abc {}, type Abc = {})\n if (\n parent.isTSInterfaceDeclaration() ||\n parent.isTSTypeAliasDeclaration() ||\n parent.isTSEnumDeclaration() ||\n parent.isTSModuleDeclaration()\n ) {\n if (current.key === 'id') {\n return true;\n }\n }\n // 4. Continue up structural TS nodes (A.B.C)\n if (parent.isTSQualifiedName() || parent.isTSEntityName()) {\n current = current.parentPath;\n continue;\n }\n // 5. If we reach standard JS statements/expressions, it implies Value Space.\n if (parent.isExpression() || parent.isStatement()) {\n break;\n }\n current = current.parentPath;\n }\n return false;\n};\n\ninterface TransformState extends PluginPass {\n keywords: KeywordSet;\n keywordUids: {\n main: Map<string, t.Identifier>;\n local: Map<string, t.Identifier>;\n };\n}\n\ninterface TransformMetadata {\n keywords?: { main: string[]; local: string[] };\n}\n\nconst transformPlugin = (mode: 'extract' | 'transform'): PluginItem => {\n const plugin: PluginObject<TransformState> = {\n name: `${PLUGIN_NAME}:${mode}`,\n\n visitor: {\n Program: {\n enter(_, state) {\n state.keywords = { main: new Set(), local: new Set() };\n state.keywordUids = { main: new Map(), local: new Map() };\n },\n\n exit(path, state) {\n const metadata = state.file.metadata as TransformMetadata;\n metadata.keywords = {\n main: Array.from(state.keywords.main),\n local: Array.from(state.keywords.local),\n };\n\n if (mode === 'transform') {\n const newImports = [];\n for (const [keyword, safeId] of state.keywordUids.main.entries()) {\n const encoded = encodeIdentifier(keyword);\n newImports.push(\n t.importDeclaration(\n [t.importDefaultSpecifier(safeId)],\n t.stringLiteral(\n `${VIRTUAL_MODULE_ID}/${KEYWORD_ROUTE_SEGMENT}/${encoded}`,\n ),\n ),\n );\n }\n for (const [keyword, safeId] of state.keywordUids.local.entries()) {\n const encoded = encodeIdentifier(keyword);\n newImports.push(\n t.importDeclaration(\n [t.importDefaultSpecifier(safeId)],\n t.stringLiteral(\n `${VIRTUAL_LOCAL_MODULE_ID}/${KEYWORD_ROUTE_SEGMENT}/${encoded}`,\n ),\n ),\n );\n }\n if (newImports.length > 0) {\n path.unshiftContainer('body', newImports);\n }\n }\n },\n },\n\n ImportDeclaration(path, state) {\n const sourceValue = path.node.source.value;\n if (\n sourceValue !== VIRTUAL_MODULE_ID &&\n sourceValue !== VIRTUAL_LOCAL_MODULE_ID\n ) {\n return;\n }\n const isLocal = sourceValue === VIRTUAL_LOCAL_MODULE_ID;\n const targetSet = isLocal ? state.keywords.local : state.keywords.main;\n const targetMap = isLocal\n ? state.keywordUids.local\n : state.keywordUids.main;\n\n const programScope = path.scope.getProgramParent();\n const processKeyword = (keyword: string): t.Identifier | null => {\n targetSet.add(keyword);\n if (mode === 'extract') {\n return null;\n }\n if (targetMap.has(keyword)) {\n return targetMap.get(keyword) as t.Identifier;\n }\n const encoded = encodeIdentifier(keyword);\n const safeName = toSafeVarName(encoded);\n const uid = programScope.generateUidIdentifier(safeName);\n targetMap.set(keyword, uid);\n return uid;\n };\n\n for (const specifierPath of path.get('specifiers')) {\n const localName = specifierPath.node.local.name;\n const binding = path.scope.getBinding(localName);\n if (!binding) {\n continue;\n }\n\n // Case A: Default & Named Imports\n if (\n specifierPath.isImportDefaultSpecifier() ||\n specifierPath.isImportSpecifier()\n ) {\n let keyword: string;\n if (specifierPath.isImportDefaultSpecifier()) {\n keyword = 'default';\n } else {\n const imported = specifierPath.node.imported;\n keyword = t.isIdentifier(imported)\n ? imported.name\n : imported.value;\n }\n const uidNode = processKeyword(keyword);\n if (!uidNode) {\n continue;\n }\n\n // 1) Fast Path: Values & JSX\n for (const refPath of binding.referencePaths) {\n if (isPureTypeSpace(refPath)) {\n continue;\n }\n if (refPath.isJSXIdentifier()) {\n refPath.replaceWith(t.jsxIdentifier(uidNode.name));\n } else {\n refPath.replaceWith(t.cloneNode(uidNode));\n }\n }\n\n // 2) Slow Path: TS Types\n // NOTE: Can be skipped due to type erasure, but for consistency\n path.parentPath.traverse({\n // e.g., type T = typeof abc;\n TSTypeQuery(tsPath) {\n if (\n t.isIdentifier(tsPath.node.exprName) &&\n tsPath.node.exprName.name === localName &&\n tsPath.scope.getBinding(localName) === binding\n ) {\n tsPath.get('exprName').replaceWith(t.cloneNode(uidNode));\n }\n },\n });\n }\n\n // Case B: Namespace Imports\n else if (specifierPath.isImportNamespaceSpecifier()) {\n // 1) Fast Path: JS Values & JSX accesses\n for (const refPath of binding.referencePaths) {\n if (isPureTypeSpace(refPath)) {\n continue;\n }\n const parentPath = refPath.parentPath;\n if (!parentPath) {\n continue;\n }\n if (\n parentPath.isMemberExpression() &&\n parentPath.node.object === refPath.node\n ) {\n const propNode = parentPath.node.property;\n let keyword: string | undefined;\n if (!parentPath.node.computed && t.isIdentifier(propNode)) {\n keyword = propNode.name;\n } else if (\n parentPath.node.computed &&\n t.isStringLiteral(propNode)\n ) {\n keyword = propNode.value;\n }\n if (keyword) {\n const uidNode = processKeyword(keyword);\n if (uidNode) {\n parentPath.replaceWith(t.cloneNode(uidNode));\n }\n }\n } else if (\n parentPath.isJSXMemberExpression() &&\n parentPath.node.object === refPath.node\n ) {\n const keyword = parentPath.node.property.name;\n const uidNode = processKeyword(keyword);\n if (uidNode) {\n parentPath.replaceWith(t.jsxIdentifier(uidNode.name));\n }\n }\n }\n\n // 2) Slow Path: TS Namespace Types\n path.parentPath.traverse({\n // e.g., type T = typeof A.abc;\n TSTypeQuery(tsPath) {\n const expr = tsPath.node.exprName;\n if (\n t.isTSQualifiedName(expr) &&\n t.isIdentifier(expr.left) &&\n expr.left.name === localName &&\n tsPath.scope.getBinding(localName) === binding\n ) {\n const keyword = expr.right.name;\n const uidNode = processKeyword(keyword);\n if (uidNode) {\n tsPath.get('exprName').replaceWith(t.cloneNode(uidNode));\n }\n }\n },\n\n // e.g., type T = ((typeof A))['prop'];\n TSIndexedAccessType(tsPath) {\n const objPath = tsPath.get('objectType') as NodePath;\n if (\n objPath.isTSTypeQuery() &&\n t.isIdentifier(objPath.node.exprName) &&\n objPath.node.exprName.name === localName &&\n tsPath.scope.getBinding(localName) === binding\n ) {\n const indexNode = tsPath.node.indexType;\n if (\n t.isTSLiteralType(indexNode) &&\n t.isStringLiteral(indexNode.literal)\n ) {\n const keyword = indexNode.literal.value;\n const uidNode = processKeyword(keyword);\n if (uidNode) {\n tsPath.replaceWith(t.tsTypeQuery(t.cloneNode(uidNode)));\n }\n }\n }\n },\n });\n }\n }\n\n if (mode === 'transform') {\n path.remove();\n }\n },\n\n ExportNamedDeclaration(path, state) {\n const sourceValue = path.node.source?.value;\n if (\n sourceValue !== VIRTUAL_MODULE_ID &&\n sourceValue !== VIRTUAL_LOCAL_MODULE_ID\n ) {\n return;\n }\n const isLocal = sourceValue === VIRTUAL_LOCAL_MODULE_ID;\n const targetSet = isLocal ? state.keywords.local : state.keywords.main;\n\n if (mode === 'extract') {\n for (const specifierPath of path.get('specifiers')) {\n if (specifierPath.isExportSpecifier()) {\n const local = specifierPath.node.local as\n | t.Identifier\n | t.StringLiteral; // local can be a StringLiteral in ES2022\n const keyword = t.isIdentifier(local) ? local.name : local.value;\n targetSet.add(keyword);\n }\n }\n return;\n }\n\n const newExports = path\n .get('specifiers')\n .map((specifierPath) => {\n if (specifierPath.isExportSpecifier()) {\n const local = specifierPath.node.local as\n | t.Identifier\n | t.StringLiteral; // local can be a StringLiteral in ES2022\n const keyword = t.isIdentifier(local) ? local.name : local.value;\n targetSet.add(keyword);\n const encoded = encodeIdentifier(keyword);\n return t.exportNamedDeclaration(\n null,\n [\n t.exportSpecifier(\n t.identifier('default'),\n specifierPath.node.exported,\n ),\n ],\n t.stringLiteral(\n `${sourceValue}/${KEYWORD_ROUTE_SEGMENT}/${encoded}`,\n ),\n );\n }\n return null;\n })\n .filter((node): node is t.ExportNamedDeclaration => node !== null);\n\n if (newExports.length > 0) {\n path.replaceWithMultiple(newExports);\n } else {\n path.remove();\n }\n },\n },\n };\n\n return (() => plugin as PluginObject) as PluginItem;\n};\n\nexport const transformCode = (\n code: string,\n id: string,\n): {\n code: string;\n map: NonNullable<FileResult['map']> | null;\n keywords: KeywordSet;\n} | null => {\n if (\n !code.includes(VIRTUAL_MODULE_ID) &&\n !code.includes(VIRTUAL_LOCAL_MODULE_ID)\n ) {\n return null;\n }\n const result = transformSync(code, {\n babelrc: false,\n configFile: false,\n filename: id,\n sourceMaps: true,\n ast: false,\n plugins: [transformPlugin('transform')],\n parserOpts: {\n plugins: ['jsx', 'typescript'],\n },\n });\n if (!result) {\n return null;\n }\n const metadata = result.metadata as TransformMetadata | undefined;\n const keywords: KeywordSet = {\n main: new Set(metadata?.keywords?.main ?? []),\n local: new Set(metadata?.keywords?.local ?? []),\n };\n return {\n code: result.code ?? '',\n map: result.map ?? null,\n keywords,\n };\n};\n\nexport const extractKeywords = (code: string): KeywordSet | null => {\n if (\n !code.includes(VIRTUAL_MODULE_ID) &&\n !code.includes(VIRTUAL_LOCAL_MODULE_ID)\n ) {\n return null;\n }\n let result: FileResult | null;\n try {\n result = transformSync(code, {\n babelrc: false,\n configFile: false,\n sourceMaps: false,\n ast: false,\n code: false,\n plugins: [transformPlugin('extract')],\n parserOpts: {\n plugins: ['jsx', 'typescript'],\n errorRecovery: true,\n },\n });\n } catch {\n return null;\n }\n if (!result) {\n return null;\n }\n const metadata = result.metadata as TransformMetadata | undefined;\n return {\n main: new Set(metadata?.keywords?.main ?? []),\n local: new Set(metadata?.keywords?.local ?? []),\n };\n};\n","/**\n * @license\n * SPDX-License-Identifier: MIT\n */\n\nimport { DEBUG_SEPARATOR, HASH_LENGTH } from './constants.js';\nimport { encodeIdentifier, toSafeVarName } from './encode.js';\n\nexport const generateTypeDeclaration = (\n keywords: Set<string>,\n isLocal: boolean = false,\n): string => {\n const sortedKeywords = Array.from(keywords).sort();\n const content = [];\n\n for (const keyword of sortedKeywords) {\n const encoded = encodeIdentifier(keyword);\n const safeName = toSafeVarName(encoded);\n const hash = isLocal ? '==' : '*'.repeat(HASH_LENGTH);\n const value = `${hash}${DEBUG_SEPARATOR}${keyword}`;\n content.push(`declare const ${safeName}: ${JSON.stringify(value)};`);\n }\n content.push('');\n\n content.push('export {');\n for (const keyword of sortedKeywords) {\n const encoded = encodeIdentifier(keyword);\n const safeName = toSafeVarName(encoded);\n content.push(` ${safeName} as ${JSON.stringify(keyword)},`);\n }\n content.push('};');\n content.push('');\n\n return content.join('\\n');\n};\n","/**\n * @license\n * SPDX-License-Identifier: MIT\n */\n\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { globby } from 'globby';\nimport pLimit from 'p-limit';\nimport { KEYWORD_ROUTE_SEGMENT } from './constants.js';\nimport { extractKeywords, type KeywordSet } from './transform.js';\nimport { generateTypeDeclaration } from './typegen.js';\n\nconst collectKeywordsFromRoot = async (\n root: string,\n silent: boolean,\n ignoredDirs: string[] = [],\n concurrency: number = 100,\n): Promise<KeywordSet> => {\n const collectedKeywords: KeywordSet = { main: new Set(), local: new Set() };\n\n const start = performance.now();\n if (!silent) {\n console.error('Scanning project files for keywords...');\n }\n\n const files = await globby('**/*.{js,ts,mjs,mts,jsx,tsx,mjsx,mtsx}', {\n cwd: root,\n absolute: false,\n ignore: ['**/node_modules/**', ...ignoredDirs.map((dir) => `${dir}/**`)],\n gitignore: true,\n });\n\n let processed = 0;\n const limit = pLimit({ concurrency });\n await limit.map(files, async (file) => {\n try {\n const code = await readFile(file, 'utf-8');\n const keywords = extractKeywords(code);\n if (!keywords) {\n return;\n }\n for (const keyword of keywords.main) {\n collectedKeywords.main.add(keyword);\n }\n for (const keyword of keywords.local) {\n collectedKeywords.local.add(keyword);\n }\n processed++;\n } catch (error) {\n if (!silent) {\n console.error(`Failed to process ${file}: ${error}`);\n }\n }\n });\n\n const elapsed = performance.now() - start;\n if (!silent) {\n console.error(\n `Scan complete: ${processed}/${files.length} files, ${collectedKeywords.main.size} main, ${collectedKeywords.local.size} local keywords (${elapsed.toFixed(2)}ms).`,\n );\n }\n\n return collectedKeywords;\n};\n\nconst pkgJson = {\n private: true,\n type: 'module',\n sideEffects: false,\n exports: {\n '.': {\n types: './index.d.ts',\n },\n './local': {\n types: './local.d.ts',\n },\n [`./${KEYWORD_ROUTE_SEGMENT}/*`]: `./${KEYWORD_ROUTE_SEGMENT}/*`,\n [`./local/${KEYWORD_ROUTE_SEGMENT}/*`]: `./local/${KEYWORD_ROUTE_SEGMENT}/*`,\n },\n};\n\ninterface RunnerOptions {\n root: string;\n silent: boolean;\n outDir: string;\n}\n\nexport const createRunner = (options?: Partial<RunnerOptions>) => {\n const {\n root = process.cwd(),\n silent = false,\n outDir = path.join('node_modules', '~keywords'),\n } = options ?? {};\n return {\n async collect(): Promise<KeywordSet> {\n return collectKeywordsFromRoot(root, silent);\n },\n\n async save(keywords: KeywordSet): Promise<void> {\n const content = generateTypeDeclaration(keywords.main);\n const localContent = generateTypeDeclaration(keywords.local, true);\n const outPath = path.join(root, outDir);\n await mkdir(outPath, { recursive: true });\n await writeFile(path.join(outPath, 'index.d.ts'), `${content.trim()}\\n`);\n await writeFile(\n path.join(outPath, 'local.d.ts'),\n `${localContent.trim()}\\n`,\n );\n await writeFile(\n path.join(outPath, 'package.json'),\n `${JSON.stringify(pkgJson, null, 2)}\\n`,\n );\n },\n\n async run(): Promise<void> {\n const keywords = await this.collect();\n await this.save(keywords);\n },\n };\n};\n","/**\n * @license\n * SPDX-License-Identifier: MIT\n */\n\nimport { createHmac, hkdfSync } from 'node:crypto';\nimport {\n HASH_LENGTH,\n VIRTUAL_LOCAL_MODULE_ID,\n VIRTUAL_MODULE_ID,\n} from './constants.js';\n\nconst ALPHA_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';\nconst DIGIT_CHARS = '0123456789';\nconst BASE62_CHARS = ALPHA_CHARS + DIGIT_CHARS;\n\nconst ALPHA_LEN = BigInt(ALPHA_CHARS.length); // 52n\nconst DIGIT_LEN = BigInt(DIGIT_CHARS.length); // 10n\nconst BASE62_LEN = BigInt(BASE62_CHARS.length); // 62n\n\nexport type Hasher = (input: string) => string;\n\n// Format: [1 Alpha] + [1 Digit] + [N Base62]\n// Avoids any collisions with standard JS API identifiers\nexport const createHasher = (secret: string): Hasher => {\n const base62TailLength = HASH_LENGTH - 2;\n if (base62TailLength < 0 || base62TailLength > 9) {\n // 520 * 62^9 < 2^64 < 520 * 62^10\n throw new Error('Invalid MAX_HASH_LENGTH');\n }\n\n const cache = new Map<string, string>();\n return (input) => {\n if (cache.has(input)) {\n return cache.get(input) as string;\n }\n\n const info = VIRTUAL_MODULE_ID;\n const payload = `${info.length}:${info}|${input.length}:${input}`;\n const hasher = createHmac('sha256', secret);\n const buffer = hasher.update(payload).digest('hex');\n\n let entropy = BigInt(`0x${buffer}`);\n let result = '';\n\n result += ALPHA_CHARS[Number(entropy % ALPHA_LEN)];\n entropy /= ALPHA_LEN;\n result += DIGIT_CHARS[Number(entropy % DIGIT_LEN)];\n entropy /= DIGIT_LEN;\n for (let i = 0; i < base62TailLength; i++) {\n result += BASE62_CHARS[Number(entropy % BASE62_LEN)];\n entropy /= BASE62_LEN;\n }\n\n cache.set(input, result);\n return result;\n };\n};\n\n// Fisher-Yates based deterministic shuffle\nconst shuffle = (str: string, secret: string, salt: string): string => {\n const arr = Array.from(str);\n const requiredBytes = (arr.length - 1) * 4;\n\n const info = VIRTUAL_LOCAL_MODULE_ID;\n const keyingMaterial = hkdfSync('sha256', secret, salt, info, requiredBytes);\n const prngBuffer = Buffer.from(keyingMaterial);\n\n let byteOffset = 0;\n for (let i = arr.length - 1; i > 0; i--) {\n const random32 = prngBuffer.readUInt32BE(byteOffset);\n byteOffset += 4;\n const j = random32 % (i + 1);\n const temp = arr[i] as string;\n arr[i] = arr[j] as string;\n arr[j] = temp;\n }\n\n return arr.join('');\n};\n\nexport const createCounter = (secret: string): Hasher => {\n const shuffledAlpha = shuffle(ALPHA_CHARS, secret, 'alpha');\n const shuffledDigit = shuffle(DIGIT_CHARS, secret, 'digit');\n const shuffledBase62 = shuffle(BASE62_CHARS, secret, 'base62');\n\n let index = 0;\n const cache = new Map<string, string>();\n return (input) => {\n if (cache.has(input)) {\n return cache.get(input) as string;\n }\n\n let result = '';\n let current = index;\n index++;\n\n result += shuffledAlpha[current % shuffledAlpha.length];\n current = Math.floor(current / shuffledAlpha.length);\n result += shuffledDigit[current % shuffledDigit.length];\n current = Math.floor(current / shuffledDigit.length);\n while (current > 0) {\n current--;\n result += shuffledBase62[current % shuffledBase62.length];\n current = Math.floor(current / shuffledBase62.length);\n }\n\n cache.set(input, result);\n return result;\n };\n};\n"],"mappings":";;;;;;;;;;;AAKA,MAAa,oBAAoB;AACjC,MAAa,0BAA0B;AAEvC,MAAa,cAAc;;;;;;;ACA3B,MAAa,oBAAoB,eAAgC;CAC/D,IAAI,UAAU;CACd,KAAK,IAAI,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;EAC1C,MAAM,IAAI,WAAW;EACrB,IAAI,eAAe,KAAK,EAAE,EACxB,WAAW;OACN,IAAI,MAAM,KACf,WAAW;OAEX,WAAW,IAAI,EAAE,WAAW,EAAE,CAAC,SAAS,GAAG,CAAC,SAAS,GAAG,IAAI;;CAGhE,OAAO;;AAGT,MAAa,iBAAiB,YAA6B,KAAK;;;;;;;ACIhE,MAAM,mBAAmB,SAA4B;CACnD,IAAI,UAA2B;CAC/B,OAAO,SAAS;EACd,MAAM,SAAS,QAAQ;EACvB,IAAI,CAAC,QACH;EAGF,IAAI,OAAO,eAAe,EACxB,OAAO;EAGT,IAAI,cAAc,OAAO,QAAQ,OAAO,KAAK;OACvC,QAAQ,QAAQ,SAAS,QAAQ,QAAQ,YAC3C,OAAO;;EAIX,IACE,OAAO,UAAU,IACjB,OAAO,8BAA8B,IACrC,OAAO,gCAAgC,IACvC,OAAO,qBAAqB,IAC5B,OAAO,uBAAuB,EAE9B,OAAO;EAGT,IACE,OAAO,0BAA0B,IACjC,OAAO,0BAA0B,IACjC,OAAO,qBAAqB,IAC5B,OAAO,uBAAuB;OAE1B,QAAQ,QAAQ,MAClB,OAAO;;EAIX,IAAI,OAAO,mBAAmB,IAAI,OAAO,gBAAgB,EAAE;GACzD,UAAU,QAAQ;GAClB;;EAGF,IAAI,OAAO,cAAc,IAAI,OAAO,aAAa,EAC/C;EAEF,UAAU,QAAQ;;CAEpB,OAAO;;AAeT,MAAM,mBAAmB,SAA8C;CACrE,MAAM,SAAuC;EAC3C,MAAM,GAAG,YAAY,GAAG;EAExB,SAAS;GACP,SAAS;IACP,MAAM,GAAG,OAAO;KACd,MAAM,WAAW;MAAE,sBAAM,IAAI,KAAK;MAAE,uBAAO,IAAI,KAAK;MAAE;KACtD,MAAM,cAAc;MAAE,sBAAM,IAAI,KAAK;MAAE,uBAAO,IAAI,KAAK;MAAE;;IAG3D,KAAK,MAAM,OAAO;KAChB,MAAM,WAAW,MAAM,KAAK;KAC5B,SAAS,WAAW;MAClB,MAAM,MAAM,KAAK,MAAM,SAAS,KAAK;MACrC,OAAO,MAAM,KAAK,MAAM,SAAS,MAAM;MACxC;KAED,IAAI,SAAS,aAAa;MACxB,MAAM,aAAa,EAAE;MACrB,KAAK,MAAM,CAAC,SAAS,WAAW,MAAM,YAAY,KAAK,SAAS,EAAE;OAChE,MAAM,UAAU,iBAAiB,QAAQ;OACzC,WAAW,KACTA,MAAE,kBACA,CAACA,MAAE,uBAAuB,OAAO,CAAC,EAClCA,MAAE,cACA,GAAG,kBAAkB,KAA4B,UAClD,CACF,CACF;;MAEH,KAAK,MAAM,CAAC,SAAS,WAAW,MAAM,YAAY,MAAM,SAAS,EAAE;OACjE,MAAM,UAAU,iBAAiB,QAAQ;OACzC,WAAW,KACTA,MAAE,kBACA,CAACA,MAAE,uBAAuB,OAAO,CAAC,EAClCA,MAAE,cACA,GAAG,wBAAwB,KAA4B,UACxD,CACF,CACF;;MAEH,IAAI,WAAW,SAAS,GACtB,KAAK,iBAAiB,QAAQ,WAAW;;;IAIhD;GAED,kBAAkB,MAAM,OAAO;IAC7B,MAAM,cAAc,KAAK,KAAK,OAAO;IACrC,IACE,gBAAA,eACA,gBAAA,mBAEA;IAEF,MAAM,UAAU,gBAAgB;IAChC,MAAM,YAAY,UAAU,MAAM,SAAS,QAAQ,MAAM,SAAS;IAClE,MAAM,YAAY,UACd,MAAM,YAAY,QAClB,MAAM,YAAY;IAEtB,MAAM,eAAe,KAAK,MAAM,kBAAkB;IAClD,MAAM,kBAAkB,YAAyC;KAC/D,UAAU,IAAI,QAAQ;KACtB,IAAI,SAAS,WACX,OAAO;KAET,IAAI,UAAU,IAAI,QAAQ,EACxB,OAAO,UAAU,IAAI,QAAQ;KAG/B,MAAM,WAAW,cADD,iBAAiB,QACK,CAAC;KACvC,MAAM,MAAM,aAAa,sBAAsB,SAAS;KACxD,UAAU,IAAI,SAAS,IAAI;KAC3B,OAAO;;IAGT,KAAK,MAAM,iBAAiB,KAAK,IAAI,aAAa,EAAE;KAClD,MAAM,YAAY,cAAc,KAAK,MAAM;KAC3C,MAAM,UAAU,KAAK,MAAM,WAAW,UAAU;KAChD,IAAI,CAAC,SACH;KAIF,IACE,cAAc,0BAA0B,IACxC,cAAc,mBAAmB,EACjC;MACA,IAAI;MACJ,IAAI,cAAc,0BAA0B,EAC1C,UAAU;WACL;OACL,MAAM,WAAW,cAAc,KAAK;OACpC,UAAUA,MAAE,aAAa,SAAS,GAC9B,SAAS,OACT,SAAS;;MAEf,MAAM,UAAU,eAAe,QAAQ;MACvC,IAAI,CAAC,SACH;MAIF,KAAK,MAAM,WAAW,QAAQ,gBAAgB;OAC5C,IAAI,gBAAgB,QAAQ,EAC1B;OAEF,IAAI,QAAQ,iBAAiB,EAC3B,QAAQ,YAAYA,MAAE,cAAc,QAAQ,KAAK,CAAC;YAElD,QAAQ,YAAYA,MAAE,UAAU,QAAQ,CAAC;;MAM7C,KAAK,WAAW,SAAS,EAEvB,YAAY,QAAQ;OAClB,IACEA,MAAE,aAAa,OAAO,KAAK,SAAS,IACpC,OAAO,KAAK,SAAS,SAAS,aAC9B,OAAO,MAAM,WAAW,UAAU,KAAK,SAEvC,OAAO,IAAI,WAAW,CAAC,YAAYA,MAAE,UAAU,QAAQ,CAAC;SAG7D,CAAC;YAIC,IAAI,cAAc,4BAA4B,EAAE;MAEnD,KAAK,MAAM,WAAW,QAAQ,gBAAgB;OAC5C,IAAI,gBAAgB,QAAQ,EAC1B;OAEF,MAAM,aAAa,QAAQ;OAC3B,IAAI,CAAC,YACH;OAEF,IACE,WAAW,oBAAoB,IAC/B,WAAW,KAAK,WAAW,QAAQ,MACnC;QACA,MAAM,WAAW,WAAW,KAAK;QACjC,IAAI;QACJ,IAAI,CAAC,WAAW,KAAK,YAAYA,MAAE,aAAa,SAAS,EACvD,UAAU,SAAS;aACd,IACL,WAAW,KAAK,YAChBA,MAAE,gBAAgB,SAAS,EAE3B,UAAU,SAAS;QAErB,IAAI,SAAS;SACX,MAAM,UAAU,eAAe,QAAQ;SACvC,IAAI,SACF,WAAW,YAAYA,MAAE,UAAU,QAAQ,CAAC;;cAG3C,IACL,WAAW,uBAAuB,IAClC,WAAW,KAAK,WAAW,QAAQ,MACnC;QACA,MAAM,UAAU,WAAW,KAAK,SAAS;QACzC,MAAM,UAAU,eAAe,QAAQ;QACvC,IAAI,SACF,WAAW,YAAYA,MAAE,cAAc,QAAQ,KAAK,CAAC;;;MAM3D,KAAK,WAAW,SAAS;OAEvB,YAAY,QAAQ;QAClB,MAAM,OAAO,OAAO,KAAK;QACzB,IACEA,MAAE,kBAAkB,KAAK,IACzBA,MAAE,aAAa,KAAK,KAAK,IACzB,KAAK,KAAK,SAAS,aACnB,OAAO,MAAM,WAAW,UAAU,KAAK,SACvC;SACA,MAAM,UAAU,KAAK,MAAM;SAC3B,MAAM,UAAU,eAAe,QAAQ;SACvC,IAAI,SACF,OAAO,IAAI,WAAW,CAAC,YAAYA,MAAE,UAAU,QAAQ,CAAC;;;OAM9D,oBAAoB,QAAQ;QAC1B,MAAM,UAAU,OAAO,IAAI,aAAa;QACxC,IACE,QAAQ,eAAe,IACvBA,MAAE,aAAa,QAAQ,KAAK,SAAS,IACrC,QAAQ,KAAK,SAAS,SAAS,aAC/B,OAAO,MAAM,WAAW,UAAU,KAAK,SACvC;SACA,MAAM,YAAY,OAAO,KAAK;SAC9B,IACEA,MAAE,gBAAgB,UAAU,IAC5BA,MAAE,gBAAgB,UAAU,QAAQ,EACpC;UACA,MAAM,UAAU,UAAU,QAAQ;UAClC,MAAM,UAAU,eAAe,QAAQ;UACvC,IAAI,SACF,OAAO,YAAYA,MAAE,YAAYA,MAAE,UAAU,QAAQ,CAAC,CAAC;;;;OAKhE,CAAC;;;IAIN,IAAI,SAAS,aACX,KAAK,QAAQ;;GAIjB,uBAAuB,MAAM,OAAO;IAClC,MAAM,cAAc,KAAK,KAAK,QAAQ;IACtC,IACE,gBAAA,eACA,gBAAA,mBAEA;IAGF,MAAM,YADU,gBAAA,oBACY,MAAM,SAAS,QAAQ,MAAM,SAAS;IAElE,IAAI,SAAS,WAAW;KACtB,KAAK,MAAM,iBAAiB,KAAK,IAAI,aAAa,EAChD,IAAI,cAAc,mBAAmB,EAAE;MACrC,MAAM,QAAQ,cAAc,KAAK;MAGjC,MAAM,UAAUA,MAAE,aAAa,MAAM,GAAG,MAAM,OAAO,MAAM;MAC3D,UAAU,IAAI,QAAQ;;KAG1B;;IAGF,MAAM,aAAa,KAChB,IAAI,aAAa,CACjB,KAAK,kBAAkB;KACtB,IAAI,cAAc,mBAAmB,EAAE;MACrC,MAAM,QAAQ,cAAc,KAAK;MAGjC,MAAM,UAAUA,MAAE,aAAa,MAAM,GAAG,MAAM,OAAO,MAAM;MAC3D,UAAU,IAAI,QAAQ;MACtB,MAAM,UAAU,iBAAiB,QAAQ;MACzC,OAAOA,MAAE,uBACP,MACA,CACEA,MAAE,gBACAA,MAAE,WAAW,UAAU,EACvB,cAAc,KAAK,SACpB,CACF,EACDA,MAAE,cACA,GAAG,YAAY,KAA4B,UAC5C,CACF;;KAEH,OAAO;MACP,CACD,QAAQ,SAA2C,SAAS,KAAK;IAEpE,IAAI,WAAW,SAAS,GACtB,KAAK,oBAAoB,WAAW;SAEpC,KAAK,QAAQ;;GAGlB;EACF;CAED,cAAc;;AAGhB,MAAa,iBACX,MACA,OAKU;CACV,IACE,CAAC,KAAK,SAAA,YAA2B,IACjC,CAAC,KAAK,SAAA,kBAAiC,EAEvC,OAAO;CAET,MAAM,SAAS,cAAc,MAAM;EACjC,SAAS;EACT,YAAY;EACZ,UAAU;EACV,YAAY;EACZ,KAAK;EACL,SAAS,CAAC,gBAAgB,YAAY,CAAC;EACvC,YAAY,EACV,SAAS,CAAC,OAAO,aAAa,EAC/B;EACF,CAAC;CACF,IAAI,CAAC,QACH,OAAO;CAET,MAAM,WAAW,OAAO;CACxB,MAAM,WAAuB;EAC3B,MAAM,IAAI,IAAI,UAAU,UAAU,QAAQ,EAAE,CAAC;EAC7C,OAAO,IAAI,IAAI,UAAU,UAAU,SAAS,EAAE,CAAC;EAChD;CACD,OAAO;EACL,MAAM,OAAO,QAAQ;EACrB,KAAK,OAAO,OAAO;EACnB;EACD;;AAGH,MAAa,mBAAmB,SAAoC;CAClE,IACE,CAAC,KAAK,SAAA,YAA2B,IACjC,CAAC,KAAK,SAAA,kBAAiC,EAEvC,OAAO;CAET,IAAI;CACJ,IAAI;EACF,SAAS,cAAc,MAAM;GAC3B,SAAS;GACT,YAAY;GACZ,YAAY;GACZ,KAAK;GACL,MAAM;GACN,SAAS,CAAC,gBAAgB,UAAU,CAAC;GACrC,YAAY;IACV,SAAS,CAAC,OAAO,aAAa;IAC9B,eAAe;IAChB;GACF,CAAC;SACI;EACN,OAAO;;CAET,IAAI,CAAC,QACH,OAAO;CAET,MAAM,WAAW,OAAO;CACxB,OAAO;EACL,MAAM,IAAI,IAAI,UAAU,UAAU,QAAQ,EAAE,CAAC;EAC7C,OAAO,IAAI,IAAI,UAAU,UAAU,SAAS,EAAE,CAAC;EAChD;;;;;;;;AC3bH,MAAa,2BACX,UACA,UAAmB,UACR;CACX,MAAM,iBAAiB,MAAM,KAAK,SAAS,CAAC,MAAM;CAClD,MAAM,UAAU,EAAE;CAElB,KAAK,MAAM,WAAW,gBAAgB;EAEpC,MAAM,WAAW,cADD,iBAAiB,QACK,CAAC;EAEvC,MAAM,QAAQ,GADD,UAAU,OAAO,IAAI,OAAA,EAAmB,IACX;EAC1C,QAAQ,KAAK,iBAAiB,SAAS,IAAI,KAAK,UAAU,MAAM,CAAC,GAAG;;CAEtE,QAAQ,KAAK,GAAG;CAEhB,QAAQ,KAAK,WAAW;CACxB,KAAK,MAAM,WAAW,gBAAgB;EAEpC,MAAM,WAAW,cADD,iBAAiB,QACK,CAAC;EACvC,QAAQ,KAAK,KAAK,SAAS,MAAM,KAAK,UAAU,QAAQ,CAAC,GAAG;;CAE9D,QAAQ,KAAK,KAAK;CAClB,QAAQ,KAAK,GAAG;CAEhB,OAAO,QAAQ,KAAK,KAAK;;;;;;;;ACpB3B,MAAM,0BAA0B,OAC9B,MACA,QACA,cAAwB,EAAE,EAC1B,cAAsB,QACE;CACxB,MAAM,oBAAgC;EAAE,sBAAM,IAAI,KAAK;EAAE,uBAAO,IAAI,KAAK;EAAE;CAE3E,MAAM,QAAQ,YAAY,KAAK;CAC/B,IAAI,CAAC,QACH,QAAQ,MAAM,yCAAyC;CAGzD,MAAM,QAAQ,MAAM,OAAO,0CAA0C;EACnE,KAAK;EACL,UAAU;EACV,QAAQ,CAAC,sBAAsB,GAAG,YAAY,KAAK,QAAQ,GAAG,IAAI,KAAK,CAAC;EACxE,WAAW;EACZ,CAAC;CAEF,IAAI,YAAY;CAEhB,MADc,OAAO,EAAE,aAAa,CACzB,CAAC,IAAI,OAAO,OAAO,SAAS;EACrC,IAAI;GAEF,MAAM,WAAW,gBAAgB,MADd,SAAS,MAAM,QAAQ,CACJ;GACtC,IAAI,CAAC,UACH;GAEF,KAAK,MAAM,WAAW,SAAS,MAC7B,kBAAkB,KAAK,IAAI,QAAQ;GAErC,KAAK,MAAM,WAAW,SAAS,OAC7B,kBAAkB,MAAM,IAAI,QAAQ;GAEtC;WACO,OAAO;GACd,IAAI,CAAC,QACH,QAAQ,MAAM,qBAAqB,KAAK,IAAI,QAAQ;;GAGxD;CAEF,MAAM,UAAU,YAAY,KAAK,GAAG;CACpC,IAAI,CAAC,QACH,QAAQ,MACN,kBAAkB,UAAU,GAAG,MAAM,OAAO,UAAU,kBAAkB,KAAK,KAAK,SAAS,kBAAkB,MAAM,KAAK,mBAAmB,QAAQ,QAAQ,EAAE,CAAC,MAC/J;CAGH,OAAO;;AAGT,MAAM,UAAU;CACd,SAAS;CACT,MAAM;CACN,aAAa;CACb,SAAS;EACP,KAAK,EACH,OAAO,gBACR;EACD,WAAW,EACT,OAAO,gBACR;GACA,UAAiC;GACjC,gBAAuC;EACzC;CACF;AAQD,MAAa,gBAAgB,YAAqC;CAChE,MAAM,EACJ,OAAO,QAAQ,KAAK,EACpB,SAAS,OACT,SAAS,KAAK,KAAK,gBAAgB,YAAY,KAC7C,WAAW,EAAE;CACjB,OAAO;EACL,MAAM,UAA+B;GACnC,OAAO,wBAAwB,MAAM,OAAO;;EAG9C,MAAM,KAAK,UAAqC;GAC9C,MAAM,UAAU,wBAAwB,SAAS,KAAK;GACtD,MAAM,eAAe,wBAAwB,SAAS,OAAO,KAAK;GAClE,MAAM,UAAU,KAAK,KAAK,MAAM,OAAO;GACvC,MAAM,MAAM,SAAS,EAAE,WAAW,MAAM,CAAC;GACzC,MAAM,UAAU,KAAK,KAAK,SAAS,aAAa,EAAE,GAAG,QAAQ,MAAM,CAAC,IAAI;GACxE,MAAM,UACJ,KAAK,KAAK,SAAS,aAAa,EAChC,GAAG,aAAa,MAAM,CAAC,IACxB;GACD,MAAM,UACJ,KAAK,KAAK,SAAS,eAAe,EAClC,GAAG,KAAK,UAAU,SAAS,MAAM,EAAE,CAAC,IACrC;;EAGH,MAAM,MAAqB;GACzB,MAAM,WAAW,MAAM,KAAK,SAAS;GACrC,MAAM,KAAK,KAAK,SAAS;;EAE5B;;;;;;;;AC3GH,MAAM,cAAc;AACpB,MAAM,cAAc;AACpB,MAAM,eAAe,cAAc;AAEnC,MAAM,YAAY,OAAO,GAAmB;AAC5C,MAAM,YAAY,OAAO,GAAmB;AAC5C,MAAM,aAAa,OAAO,aAAa,OAAO;AAM9C,MAAa,gBAAgB,WAA2B;CACtD,MAAM,mBAAA;CACN,IAAI,mBAAmB,KAAK,mBAAmB,GAE7C,MAAM,IAAI,MAAM,0BAA0B;CAG5C,MAAM,wBAAQ,IAAI,KAAqB;CACvC,QAAQ,UAAU;EAChB,IAAI,MAAM,IAAI,MAAM,EAClB,OAAO,MAAM,IAAI,MAAM;EAIzB,MAAM,UAAU,KAAkB,kBAAK,GAAG,MAAM,OAAO,GAAG;EAE1D,MAAM,SADS,WAAW,UAAU,OACf,CAAC,OAAO,QAAQ,CAAC,OAAO,MAAM;EAEnD,IAAI,UAAU,OAAO,KAAK,SAAS;EACnC,IAAI,SAAS;EAEb,UAAU,YAAY,OAAO,UAAU,UAAU;EACjD,WAAW;EACX,UAAU,YAAY,OAAO,UAAU,UAAU;EACjD,WAAW;EACX,KAAK,IAAI,IAAI,GAAG,IAAI,kBAAkB,KAAK;GACzC,UAAU,aAAa,OAAO,UAAU,WAAW;GACnD,WAAW;;EAGb,MAAM,IAAI,OAAO,OAAO;EACxB,OAAO;;;AAKX,MAAM,WAAW,KAAa,QAAgB,SAAyB;CACrE,MAAM,MAAM,MAAM,KAAK,IAAI;CAI3B,MAAM,iBAAiB,SAAS,UAAU,QAAQ,MAAMC,0BAHjC,IAAI,SAAS,KAAK,EAGmC;CAC5E,MAAM,aAAa,OAAO,KAAK,eAAe;CAE9C,IAAI,aAAa;CACjB,KAAK,IAAI,IAAI,IAAI,SAAS,GAAG,IAAI,GAAG,KAAK;EACvC,MAAM,WAAW,WAAW,aAAa,WAAW;EACpD,cAAc;EACd,MAAM,IAAI,YAAY,IAAI;EAC1B,MAAM,OAAO,IAAI;EACjB,IAAI,KAAK,IAAI;EACb,IAAI,KAAK;;CAGX,OAAO,IAAI,KAAK,GAAG;;AAGrB,MAAa,iBAAiB,WAA2B;CACvD,MAAM,gBAAgB,QAAQ,aAAa,QAAQ,QAAQ;CAC3D,MAAM,gBAAgB,QAAQ,aAAa,QAAQ,QAAQ;CAC3D,MAAM,iBAAiB,QAAQ,cAAc,QAAQ,SAAS;CAE9D,IAAI,QAAQ;CACZ,MAAM,wBAAQ,IAAI,KAAqB;CACvC,QAAQ,UAAU;EAChB,IAAI,MAAM,IAAI,MAAM,EAClB,OAAO,MAAM,IAAI,MAAM;EAGzB,IAAI,SAAS;EACb,IAAI,UAAU;EACd;EAEA,UAAU,cAAc,UAAU,cAAc;EAChD,UAAU,KAAK,MAAM,UAAU,cAAc,OAAO;EACpD,UAAU,cAAc,UAAU,cAAc;EAChD,UAAU,KAAK,MAAM,UAAU,cAAc,OAAO;EACpD,OAAO,UAAU,GAAG;GAClB;GACA,UAAU,eAAe,UAAU,eAAe;GAClD,UAAU,KAAK,MAAM,UAAU,eAAe,OAAO;;EAGvD,MAAM,IAAI,OAAO,OAAO;EACxB,OAAO"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"plugin-BxpZVMN0.js","names":[],"sources":["../src/internal/plugin.ts"],"sourcesContent":["/**\n * @license\n * SPDX-License-Identifier: MIT\n */\n\nimport { readFile } from 'node:fs/promises';\nimport pLimit from 'p-limit';\nimport type { UnpluginFactory } from 'unplugin';\nimport { createRunner } from './cli.js';\nimport {\n DEBUG_SEPARATOR,\n KEYWORD_ROUTE_SEGMENT,\n PLUGIN_NAME,\n VIRTUAL_LOCAL_MODULE_ID,\n VIRTUAL_MODULE_ID,\n} from './constants.js';\nimport { encodeIdentifier } from './encode.js';\nimport { createCounter, createHasher, type Hasher } from './hash.js';\nimport {\n extractKeywords,\n type KeywordSet,\n transformCode,\n} from './transform.js';\n\nconst resolveId = (id: string): string => `\\0${id}`;\n\nconst splitQuery = (id: string): [string, string | undefined] => {\n const index = id.indexOf('?');\n if (index === -1) {\n return [id, undefined];\n }\n return [id.slice(0, index), id.slice(index + 1)];\n};\n\nconst toIncludes = (id: string): RegExp[] => [new RegExp(`^${id}/`)];\n\nconst SUFFIX_REGEX = /\\.m?[jt]sx?$/;\nconst COMMON_EXCLUDES = [/\\/node_modules\\//];\n\nexport interface Options {\n /**\n * If true, preserves the original keyword as a suffix in the generated\n * identifier for easier debugging (e.g., `\"zXpL21k.SET_USER\"`).\n */\n isDev: boolean;\n /**\n * The cryptographic key used to initialize the deterministic HMAC algorithm.\n * Modifying this value will globally rotate all generated hashes.\n * To ensure cross-boundary consistency between independent builds,\n * they must share the same secret key.\n */\n secret: string;\n}\n\nexport const unpluginFactory: UnpluginFactory<Options> = ({\n isDev,\n secret,\n}) => {\n const runner = createRunner({ silent: true });\n const runnerLimit = pLimit({ concurrency: 1 });\n const typegenKeywords: KeywordSet = { main: new Set(), local: new Set() };\n\n let isInitialized = false;\n const runInit = async () => {\n try {\n const keywords = await runner.collect();\n for (const keyword of keywords.main) {\n typegenKeywords.main.add(keyword);\n }\n for (const keyword of keywords.local) {\n typegenKeywords.local.add(keyword);\n }\n await runner.save(typegenKeywords);\n isInitialized = true;\n } catch {}\n };\n\n let hasherMain: Hasher;\n let hasherLocal: Hasher;\n let resolvedMap: Map<string, string>;\n\n return {\n name: PLUGIN_NAME,\n\n buildStart() {\n hasherMain = createHasher(secret);\n hasherLocal = createCounter(secret);\n resolvedMap = new Map();\n runnerLimit(async () => {\n if (!isInitialized) {\n await runInit();\n }\n });\n },\n\n resolveId: {\n filter: {\n id: {\n include: [\n ...toIncludes(VIRTUAL_MODULE_ID),\n ...toIncludes(VIRTUAL_LOCAL_MODULE_ID),\n ],\n exclude: COMMON_EXCLUDES,\n },\n },\n handler(id) {\n return resolveId(id);\n },\n },\n\n load: {\n filter: {\n id: {\n include: [\n ...toIncludes(resolveId(VIRTUAL_MODULE_ID)),\n ...toIncludes(resolveId(VIRTUAL_LOCAL_MODULE_ID)),\n ],\n exclude: COMMON_EXCLUDES,\n },\n },\n handler(id) {\n const [validId] = splitQuery(id);\n if (resolvedMap.has(validId)) {\n return resolvedMap.get(validId);\n }\n return null;\n },\n },\n\n transform: {\n filter: {\n id: {\n include: [SUFFIX_REGEX],\n exclude: COMMON_EXCLUDES,\n },\n code: {\n include: [VIRTUAL_MODULE_ID, VIRTUAL_LOCAL_MODULE_ID],\n },\n },\n handler(code, id) {\n const result = transformCode(code, id);\n if (!result) {\n return null;\n }\n const { code: transformed, map, keywords } = result;\n for (const keyword of keywords.main) {\n const encoded = encodeIdentifier(keyword);\n const resolvedId = resolveId(\n `${VIRTUAL_MODULE_ID}/${KEYWORD_ROUTE_SEGMENT}/${encoded}`,\n );\n if (resolvedMap.has(resolvedId)) {\n continue;\n }\n const hash = hasherMain(keyword);\n const value = isDev ? `${hash}${DEBUG_SEPARATOR}${keyword}` : hash;\n resolvedMap.set(\n resolvedId,\n `export default ${JSON.stringify(value)};\\n`,\n );\n }\n for (const keyword of keywords.local) {\n const encoded = encodeIdentifier(keyword);\n const resolvedId = resolveId(\n `${VIRTUAL_LOCAL_MODULE_ID}/${KEYWORD_ROUTE_SEGMENT}/${encoded}`,\n );\n if (resolvedMap.has(resolvedId)) {\n continue;\n }\n const hash = hasherLocal(keyword);\n const value = isDev ? `${hash}${DEBUG_SEPARATOR}${keyword}` : hash;\n resolvedMap.set(\n resolvedId,\n `export default ${JSON.stringify(value)};\\n`,\n );\n }\n return { code: transformed, map };\n },\n },\n\n async watchChange(id, { event }) {\n if (\n !SUFFIX_REGEX.test(id) ||\n COMMON_EXCLUDES.some((regex) => regex.test(id)) ||\n event === 'delete'\n ) {\n return;\n }\n let code: string;\n try {\n code = await readFile(id, 'utf-8');\n } catch {\n return;\n }\n const keywords = extractKeywords(code);\n if (!keywords) {\n return;\n }\n let isAdded = false;\n for (const keyword of keywords.main) {\n if (!typegenKeywords.main.has(keyword)) {\n typegenKeywords.main.add(keyword);\n isAdded = true;\n }\n }\n for (const keyword of keywords.local) {\n if (!typegenKeywords.local.has(keyword)) {\n typegenKeywords.local.add(keyword);\n isAdded = true;\n }\n }\n if (!isInitialized || isAdded) {\n runnerLimit(async () => {\n if (!isInitialized) {\n await runInit();\n } else if (isAdded) {\n try {\n await runner.save(typegenKeywords);\n } catch {}\n }\n });\n }\n },\n };\n};\n"],"mappings":"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"}