unplugin-keywords 2.12.0 → 2.13.1
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 +7 -3
- package/dist/api.d.ts +2 -1
- package/dist/api.js +1 -1
- package/dist/bun.js +1 -1
- package/dist/esbuild.js +1 -1
- package/dist/farm.js +1 -1
- package/dist/{hash-BJl6coaB.js → hash-C4xUIITd.js} +45 -25
- package/dist/hash-C4xUIITd.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/{plugin-B-GMuoNu.js → plugin-cEMprzlf.js} +36 -11
- package/dist/plugin-cEMprzlf.js.map +1 -0
- package/dist/rolldown.js +1 -1
- package/dist/rollup.js +1 -1
- package/dist/rspack.js +1 -1
- package/dist/vite.js +1 -1
- package/dist/webpack.js +1 -1
- package/package.json +2 -6
- package/dist/hash-BJl6coaB.js.map +0 -1
- package/dist/plugin-B-GMuoNu.js.map +0 -1
package/README.md
CHANGED
|
@@ -77,9 +77,9 @@ const _="b";const a={a:_,c:data};
|
|
|
77
77
|
```
|
|
78
78
|
<!-- prettier-ignore-end -->
|
|
79
79
|
|
|
80
|
-
##
|
|
80
|
+
## Tri-Module System
|
|
81
81
|
|
|
82
|
-
`unplugin-keywords` provides
|
|
82
|
+
`unplugin-keywords` provides three distinct virtual modules. By default, the shortest possible compression is used, but the tri-module system allows for stable cross-boundary contracts and static literal deduplication when necessary.
|
|
83
83
|
|
|
84
84
|
- **`~keywords` (Lexical Counter):**
|
|
85
85
|
Generates the shortest safe sequential identifiers (min length: 1, e.g., `"a"`, `"b"`). Intended for **internal and local** implementations where cross-boundary stability is irrelevant. This is the default for maximum minification.
|
|
@@ -89,8 +89,12 @@ const _="b";const a={a:_,c:data};
|
|
|
89
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
90
|
_Convention:_ `import * as PK from '~keywords/public';`
|
|
91
91
|
|
|
92
|
+
- **`~keywords/raw` (Literal String):**
|
|
93
|
+
Yields the exact, unobfuscated string literal (e.g., `"function"`, `"click"`). Ideal for standard APIs and repeating language keywords. Ensures a single memory instance of the string across your bundle.
|
|
94
|
+
_Convention:_ `import * as RK from '~keywords/raw';`
|
|
95
|
+
|
|
92
96
|
**Module Separation:**
|
|
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.*`.
|
|
97
|
+
To minimize bundle size, identifiers can be partitioned: use `PK.*` for properties exposed to consumers, use `RK.*` for deduplicating raw strings like `typeof fn === RK.function`, and obscure all internal state and private members behind the default `K.*`.
|
|
94
98
|
|
|
95
99
|
## Integration
|
|
96
100
|
|
package/dist/api.d.ts
CHANGED
|
@@ -8,13 +8,14 @@ import { FileResult } from "@babel/core";
|
|
|
8
8
|
interface KeywordSet {
|
|
9
9
|
local: Set<string>;
|
|
10
10
|
public: Set<string>;
|
|
11
|
+
raw: Set<string>;
|
|
11
12
|
}
|
|
12
13
|
declare const transformCode: (code: string, id: string) => {
|
|
13
14
|
code: string;
|
|
14
15
|
map: NonNullable<FileResult["map"]> | null;
|
|
15
16
|
keywords: KeywordSet;
|
|
16
17
|
} | null;
|
|
17
|
-
declare const extractKeywords: (code: string) => KeywordSet | null;
|
|
18
|
+
declare const extractKeywords: (code: string, id: string) => KeywordSet | null;
|
|
18
19
|
//#endregion
|
|
19
20
|
//#region src/internal/cli.d.ts
|
|
20
21
|
interface RunnerOptions {
|
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-
|
|
1
|
+
import { a as transformCode, i as extractKeywords, n as createHasher, r as createRunner, t as createCounter } from "./hash-C4xUIITd.js";
|
|
2
2
|
//#region src/api.ts
|
|
3
3
|
/**
|
|
4
4
|
* @license
|
package/dist/bun.js
CHANGED
package/dist/esbuild.js
CHANGED
package/dist/farm.js
CHANGED
|
@@ -11,8 +11,10 @@ import { createHmac, hkdfSync } from "node:crypto";
|
|
|
11
11
|
*/
|
|
12
12
|
const VIRTUAL_MODULE_ID = "~keywords";
|
|
13
13
|
const VIRTUAL_PUBLIC_MODULE_ID = "~keywords/public";
|
|
14
|
+
const VIRTUAL_RAW_MODULE_ID = "~keywords/raw";
|
|
14
15
|
const VIRTUAL_INTERNAL_MODULE_ID = "~keywords-internal";
|
|
15
16
|
const VIRTUAL_INTERNAL_PUBLIC_MODULE_ID = "~keywords-internal/public";
|
|
17
|
+
const VIRTUAL_INTERNAL_RAW_MODULE_ID = "~keywords-internal/raw";
|
|
16
18
|
const PLUGIN_NAME = "unplugin-keywords";
|
|
17
19
|
//#endregion
|
|
18
20
|
//#region src/internal/encode.ts
|
|
@@ -67,18 +69,21 @@ const transformPlugin = (mode) => {
|
|
|
67
69
|
enter(_, state) {
|
|
68
70
|
state.keywords = {
|
|
69
71
|
local: /* @__PURE__ */ new Set(),
|
|
70
|
-
public: /* @__PURE__ */ new Set()
|
|
72
|
+
public: /* @__PURE__ */ new Set(),
|
|
73
|
+
raw: /* @__PURE__ */ new Set()
|
|
71
74
|
};
|
|
72
75
|
state.keywordUids = {
|
|
73
76
|
local: /* @__PURE__ */ new Map(),
|
|
74
|
-
public: /* @__PURE__ */ new Map()
|
|
77
|
+
public: /* @__PURE__ */ new Map(),
|
|
78
|
+
raw: /* @__PURE__ */ new Map()
|
|
75
79
|
};
|
|
76
80
|
},
|
|
77
81
|
exit(path, state) {
|
|
78
82
|
const metadata = state.file.metadata;
|
|
79
83
|
metadata.keywords = {
|
|
80
84
|
local: Array.from(state.keywords.local),
|
|
81
|
-
public: Array.from(state.keywords.public)
|
|
85
|
+
public: Array.from(state.keywords.public),
|
|
86
|
+
raw: Array.from(state.keywords.raw)
|
|
82
87
|
};
|
|
83
88
|
if (mode === "transform") {
|
|
84
89
|
const newImports = [];
|
|
@@ -90,16 +95,21 @@ const transformPlugin = (mode) => {
|
|
|
90
95
|
const encoded = encodeIdentifier(keyword);
|
|
91
96
|
newImports.push(types.importDeclaration([types.importDefaultSpecifier(safeId)], types.stringLiteral(`${VIRTUAL_INTERNAL_PUBLIC_MODULE_ID}/_/${encoded}`)));
|
|
92
97
|
}
|
|
98
|
+
for (const [keyword, safeId] of state.keywordUids.raw.entries()) {
|
|
99
|
+
const encoded = encodeIdentifier(keyword);
|
|
100
|
+
newImports.push(types.importDeclaration([types.importDefaultSpecifier(safeId)], types.stringLiteral(`${VIRTUAL_INTERNAL_RAW_MODULE_ID}/_/${encoded}`)));
|
|
101
|
+
}
|
|
93
102
|
if (newImports.length > 0) path.unshiftContainer("body", newImports);
|
|
94
103
|
}
|
|
95
104
|
}
|
|
96
105
|
},
|
|
97
106
|
ImportDeclaration(path, state) {
|
|
98
107
|
const sourceValue = path.node.source.value;
|
|
99
|
-
if (sourceValue !== "~keywords" && sourceValue !== "~keywords/public") return;
|
|
108
|
+
if (sourceValue !== "~keywords" && sourceValue !== "~keywords/public" && sourceValue !== "~keywords/raw") return;
|
|
100
109
|
const isPublic = sourceValue === VIRTUAL_PUBLIC_MODULE_ID;
|
|
101
|
-
const
|
|
102
|
-
const
|
|
110
|
+
const isRaw = sourceValue === VIRTUAL_RAW_MODULE_ID;
|
|
111
|
+
const targetSet = isRaw ? state.keywords.raw : isPublic ? state.keywords.public : state.keywords.local;
|
|
112
|
+
const targetMap = isRaw ? state.keywordUids.raw : isPublic ? state.keywordUids.public : state.keywordUids.local;
|
|
103
113
|
const programScope = path.scope.getProgramParent();
|
|
104
114
|
const processKeyword = (keyword) => {
|
|
105
115
|
targetSet.add(keyword);
|
|
@@ -178,9 +188,10 @@ const transformPlugin = (mode) => {
|
|
|
178
188
|
},
|
|
179
189
|
ExportNamedDeclaration(path, state) {
|
|
180
190
|
const sourceValue = path.node.source?.value;
|
|
181
|
-
if (sourceValue !== "~keywords" && sourceValue !== "~keywords/public") return;
|
|
191
|
+
if (sourceValue !== "~keywords" && sourceValue !== "~keywords/public" && sourceValue !== "~keywords/raw") return;
|
|
182
192
|
const isPublic = sourceValue === VIRTUAL_PUBLIC_MODULE_ID;
|
|
183
|
-
const
|
|
193
|
+
const isRaw = sourceValue === VIRTUAL_RAW_MODULE_ID;
|
|
194
|
+
const targetSet = isRaw ? state.keywords.raw : isPublic ? state.keywords.public : state.keywords.local;
|
|
184
195
|
if (mode === "extract") {
|
|
185
196
|
for (const specifierPath of path.get("specifiers")) if (specifierPath.isExportSpecifier()) {
|
|
186
197
|
const local = specifierPath.node.local;
|
|
@@ -195,7 +206,7 @@ const transformPlugin = (mode) => {
|
|
|
195
206
|
const keyword = types.isIdentifier(local) ? local.name : local.value;
|
|
196
207
|
targetSet.add(keyword);
|
|
197
208
|
const encoded = encodeIdentifier(keyword);
|
|
198
|
-
const targetModuleId = isPublic ? VIRTUAL_INTERNAL_PUBLIC_MODULE_ID : VIRTUAL_INTERNAL_MODULE_ID;
|
|
209
|
+
const targetModuleId = isRaw ? VIRTUAL_INTERNAL_RAW_MODULE_ID : isPublic ? VIRTUAL_INTERNAL_PUBLIC_MODULE_ID : VIRTUAL_INTERNAL_MODULE_ID;
|
|
199
210
|
return types.exportNamedDeclaration(null, [types.exportSpecifier(types.identifier("default"), specifierPath.node.exported)], types.stringLiteral(`${targetModuleId}/_/${encoded}`));
|
|
200
211
|
}
|
|
201
212
|
return null;
|
|
@@ -207,8 +218,9 @@ const transformPlugin = (mode) => {
|
|
|
207
218
|
};
|
|
208
219
|
return () => plugin;
|
|
209
220
|
};
|
|
221
|
+
const isJsx = (id) => /\.m?[jt]sx$/.test(id);
|
|
210
222
|
const transformCode = (code, id) => {
|
|
211
|
-
if (!code.includes("~keywords") && !code.includes("~keywords/public")) return null;
|
|
223
|
+
if (!code.includes("~keywords") && !code.includes("~keywords/public") && !code.includes("~keywords/raw")) return null;
|
|
212
224
|
const result = transformSync(code, {
|
|
213
225
|
babelrc: false,
|
|
214
226
|
configFile: false,
|
|
@@ -216,13 +228,14 @@ const transformCode = (code, id) => {
|
|
|
216
228
|
sourceMaps: true,
|
|
217
229
|
ast: false,
|
|
218
230
|
plugins: [transformPlugin("transform")],
|
|
219
|
-
parserOpts: { plugins: ["
|
|
231
|
+
parserOpts: { plugins: ["typescript", ...isJsx(id) ? ["jsx"] : []] }
|
|
220
232
|
});
|
|
221
233
|
if (!result) return null;
|
|
222
234
|
const metadata = result.metadata;
|
|
223
235
|
const keywords = {
|
|
224
236
|
local: new Set(metadata?.keywords?.local ?? []),
|
|
225
|
-
public: new Set(metadata?.keywords?.public ?? [])
|
|
237
|
+
public: new Set(metadata?.keywords?.public ?? []),
|
|
238
|
+
raw: new Set(metadata?.keywords?.raw ?? [])
|
|
226
239
|
};
|
|
227
240
|
return {
|
|
228
241
|
code: result.code ?? "",
|
|
@@ -230,8 +243,8 @@ const transformCode = (code, id) => {
|
|
|
230
243
|
keywords
|
|
231
244
|
};
|
|
232
245
|
};
|
|
233
|
-
const extractKeywords = (code) => {
|
|
234
|
-
if (!code.includes("~keywords") && !code.includes("~keywords/public")) return null;
|
|
246
|
+
const extractKeywords = (code, id) => {
|
|
247
|
+
if (!code.includes("~keywords") && !code.includes("~keywords/public") && !code.includes("~keywords/raw")) return null;
|
|
235
248
|
let result;
|
|
236
249
|
try {
|
|
237
250
|
result = transformSync(code, {
|
|
@@ -242,7 +255,7 @@ const extractKeywords = (code) => {
|
|
|
242
255
|
code: false,
|
|
243
256
|
plugins: [transformPlugin("extract")],
|
|
244
257
|
parserOpts: {
|
|
245
|
-
plugins: ["
|
|
258
|
+
plugins: ["typescript", ...isJsx(id) ? ["jsx"] : []],
|
|
246
259
|
errorRecovery: true
|
|
247
260
|
}
|
|
248
261
|
});
|
|
@@ -253,7 +266,8 @@ const extractKeywords = (code) => {
|
|
|
253
266
|
const metadata = result.metadata;
|
|
254
267
|
return {
|
|
255
268
|
local: new Set(metadata?.keywords?.local ?? []),
|
|
256
|
-
public: new Set(metadata?.keywords?.public ?? [])
|
|
269
|
+
public: new Set(metadata?.keywords?.public ?? []),
|
|
270
|
+
raw: new Set(metadata?.keywords?.raw ?? [])
|
|
257
271
|
};
|
|
258
272
|
};
|
|
259
273
|
//#endregion
|
|
@@ -262,12 +276,13 @@ const extractKeywords = (code) => {
|
|
|
262
276
|
* @license
|
|
263
277
|
* SPDX-License-Identifier: MIT
|
|
264
278
|
*/
|
|
265
|
-
const generateTypeDeclaration = (keywords,
|
|
279
|
+
const generateTypeDeclaration = (keywords, mode = "local") => {
|
|
266
280
|
const sortedKeywords = Array.from(keywords).sort();
|
|
267
281
|
const content = [];
|
|
268
282
|
for (const keyword of sortedKeywords) {
|
|
269
283
|
const safeName = toSafeVarName(encodeIdentifier(keyword));
|
|
270
|
-
const
|
|
284
|
+
const hash = mode === "public" ? "*".repeat(7) : "==";
|
|
285
|
+
const value = mode === "raw" ? keyword : `${hash}.${keyword}`;
|
|
271
286
|
content.push(`declare const ${safeName}: ${JSON.stringify(value)};`);
|
|
272
287
|
}
|
|
273
288
|
content.push("");
|
|
@@ -289,7 +304,8 @@ const generateTypeDeclaration = (keywords, isPublic = false) => {
|
|
|
289
304
|
const collectKeywordsFromRoot = async (root, silent, ignoredDirs = [], concurrency = 100) => {
|
|
290
305
|
const collectedKeywords = {
|
|
291
306
|
local: /* @__PURE__ */ new Set(),
|
|
292
|
-
public: /* @__PURE__ */ new Set()
|
|
307
|
+
public: /* @__PURE__ */ new Set(),
|
|
308
|
+
raw: /* @__PURE__ */ new Set()
|
|
293
309
|
};
|
|
294
310
|
const start = performance.now();
|
|
295
311
|
if (!silent) console.error("Scanning project files for keywords...");
|
|
@@ -302,17 +318,18 @@ const collectKeywordsFromRoot = async (root, silent, ignoredDirs = [], concurren
|
|
|
302
318
|
let processed = 0;
|
|
303
319
|
await pLimit({ concurrency }).map(files, async (file) => {
|
|
304
320
|
try {
|
|
305
|
-
const keywords = extractKeywords(await readFile(file, "utf-8"));
|
|
321
|
+
const keywords = extractKeywords(await readFile(file, "utf-8"), file);
|
|
306
322
|
if (!keywords) return;
|
|
307
323
|
for (const keyword of keywords.local) collectedKeywords.local.add(keyword);
|
|
308
324
|
for (const keyword of keywords.public) collectedKeywords.public.add(keyword);
|
|
325
|
+
for (const keyword of keywords.raw) collectedKeywords.raw.add(keyword);
|
|
309
326
|
processed++;
|
|
310
327
|
} catch (error) {
|
|
311
328
|
if (!silent) console.error(`Failed to process ${file}: ${error}`);
|
|
312
329
|
}
|
|
313
330
|
});
|
|
314
331
|
const elapsed = performance.now() - start;
|
|
315
|
-
if (!silent) console.error(`Scan complete: ${processed}/${files.length} files, ${collectedKeywords.local.size} local, ${collectedKeywords.public.size} public keywords (${elapsed.toFixed(2)}ms).`);
|
|
332
|
+
if (!silent) console.error(`Scan complete: ${processed}/${files.length} files, ${collectedKeywords.local.size} local, ${collectedKeywords.public.size} public, ${collectedKeywords.raw.size} raw keywords (${elapsed.toFixed(2)}ms).`);
|
|
316
333
|
return collectedKeywords;
|
|
317
334
|
};
|
|
318
335
|
const pkgJson = {
|
|
@@ -321,7 +338,8 @@ const pkgJson = {
|
|
|
321
338
|
sideEffects: false,
|
|
322
339
|
exports: {
|
|
323
340
|
".": { types: "./index.d.ts" },
|
|
324
|
-
"./public": { types: "./public.d.ts" }
|
|
341
|
+
"./public": { types: "./public.d.ts" },
|
|
342
|
+
"./raw": { types: "./raw.d.ts" }
|
|
325
343
|
}
|
|
326
344
|
};
|
|
327
345
|
const createRunner = (options) => {
|
|
@@ -332,11 +350,13 @@ const createRunner = (options) => {
|
|
|
332
350
|
},
|
|
333
351
|
async save(keywords) {
|
|
334
352
|
const content = generateTypeDeclaration(keywords.local);
|
|
335
|
-
const publicContent = generateTypeDeclaration(keywords.public,
|
|
353
|
+
const publicContent = generateTypeDeclaration(keywords.public, "public");
|
|
354
|
+
const rawContent = generateTypeDeclaration(keywords.raw, "raw");
|
|
336
355
|
const outPath = path.join(root, outDir);
|
|
337
356
|
await mkdir(outPath, { recursive: true });
|
|
338
357
|
await writeFile(path.join(outPath, "index.d.ts"), `${content.trim()}\n`);
|
|
339
358
|
await writeFile(path.join(outPath, "public.d.ts"), `${publicContent.trim()}\n`);
|
|
359
|
+
await writeFile(path.join(outPath, "raw.d.ts"), `${rawContent.trim()}\n`);
|
|
340
360
|
await writeFile(path.join(outPath, "package.json"), `${JSON.stringify(pkgJson, null, 2)}\n`);
|
|
341
361
|
},
|
|
342
362
|
async run() {
|
|
@@ -2741,6 +2761,6 @@ const createCounter = (secret) => {
|
|
|
2741
2761
|
};
|
|
2742
2762
|
};
|
|
2743
2763
|
//#endregion
|
|
2744
|
-
export { transformCode as a, VIRTUAL_INTERNAL_MODULE_ID as c,
|
|
2764
|
+
export { transformCode as a, VIRTUAL_INTERNAL_MODULE_ID as c, VIRTUAL_MODULE_ID as d, VIRTUAL_PUBLIC_MODULE_ID as f, extractKeywords as i, VIRTUAL_INTERNAL_PUBLIC_MODULE_ID as l, createHasher as n, encodeIdentifier as o, VIRTUAL_RAW_MODULE_ID as p, createRunner as r, PLUGIN_NAME as s, createCounter as t, VIRTUAL_INTERNAL_RAW_MODULE_ID as u };
|
|
2745
2765
|
|
|
2746
|
-
//# sourceMappingURL=hash-
|
|
2766
|
+
//# sourceMappingURL=hash-C4xUIITd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash-C4xUIITd.js","names":["t","blacklist","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';\nexport const VIRTUAL_RAW_MODULE_ID = '~keywords/raw';\n\nexport const VIRTUAL_INTERNAL_MODULE_ID = '~keywords-internal';\nexport const VIRTUAL_INTERNAL_PUBLIC_MODULE_ID = '~keywords-internal/public';\nexport const VIRTUAL_INTERNAL_RAW_MODULE_ID = '~keywords-internal/raw';\n\nexport const PLUGIN_NAME = 'unplugin-keywords';\n\nexport const HASH_LENGTH = 7;\n\nexport const KEYWORD_ROUTE = '_';\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,\n PLUGIN_NAME,\n VIRTUAL_INTERNAL_MODULE_ID,\n VIRTUAL_INTERNAL_PUBLIC_MODULE_ID,\n VIRTUAL_INTERNAL_RAW_MODULE_ID,\n VIRTUAL_MODULE_ID,\n VIRTUAL_PUBLIC_MODULE_ID,\n VIRTUAL_RAW_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 raw: 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 raw: Map<string, t.Identifier>;\n };\n}\n\ninterface TransformMetadata {\n keywords?: { local: string[]; public: string[]; raw: 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 = {\n local: new Set(),\n public: new Set(),\n raw: new Set(),\n };\n state.keywordUids = {\n local: new Map(),\n public: new Map(),\n raw: new Map(),\n };\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 raw: Array.from(state.keywords.raw),\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_INTERNAL_MODULE_ID}/${KEYWORD_ROUTE}/${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_INTERNAL_PUBLIC_MODULE_ID}/${KEYWORD_ROUTE}/${encoded}`,\n ),\n ),\n );\n }\n for (const [keyword, safeId] of state.keywordUids.raw.entries()) {\n const encoded = encodeIdentifier(keyword);\n newImports.push(\n t.importDeclaration(\n [t.importDefaultSpecifier(safeId)],\n t.stringLiteral(\n `${VIRTUAL_INTERNAL_RAW_MODULE_ID}/${KEYWORD_ROUTE}/${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 sourceValue !== VIRTUAL_RAW_MODULE_ID\n ) {\n return;\n }\n const isPublic = sourceValue === VIRTUAL_PUBLIC_MODULE_ID;\n const isRaw = sourceValue === VIRTUAL_RAW_MODULE_ID;\n const targetSet = isRaw\n ? state.keywords.raw\n : isPublic\n ? state.keywords.public\n : state.keywords.local;\n const targetMap = isRaw\n ? state.keywordUids.raw\n : 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 sourceValue !== VIRTUAL_RAW_MODULE_ID\n ) {\n return;\n }\n const isPublic = sourceValue === VIRTUAL_PUBLIC_MODULE_ID;\n const isRaw = sourceValue === VIRTUAL_RAW_MODULE_ID;\n const targetSet = isRaw\n ? state.keywords.raw\n : 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 const targetModuleId = isRaw\n ? VIRTUAL_INTERNAL_RAW_MODULE_ID\n : isPublic\n ? VIRTUAL_INTERNAL_PUBLIC_MODULE_ID\n : VIRTUAL_INTERNAL_MODULE_ID;\n return t.exportNamedDeclaration(\n null,\n [\n t.exportSpecifier(\n t.identifier('default'),\n specifierPath.node.exported,\n ),\n ],\n t.stringLiteral(\n `${targetModuleId}/${KEYWORD_ROUTE}/${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;\n};\n\nconst isJsx = (id: string): boolean => /\\.m?[jt]sx$/.test(id);\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 !code.includes(VIRTUAL_RAW_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: ['typescript', ...(isJsx(id) ? (['jsx'] as const) : [])],\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 raw: new Set(metadata?.keywords?.raw ?? []),\n };\n return {\n code: result.code ?? '',\n map: result.map ?? null,\n keywords,\n };\n};\n\nexport const extractKeywords = (\n code: string,\n id: string,\n): KeywordSet | null => {\n if (\n !code.includes(VIRTUAL_MODULE_ID) &&\n !code.includes(VIRTUAL_PUBLIC_MODULE_ID) &&\n !code.includes(VIRTUAL_RAW_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: ['typescript', ...(isJsx(id) ? (['jsx'] as const) : [])],\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 raw: new Set(metadata?.keywords?.raw ?? []),\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 mode: 'local' | 'public' | 'raw' = 'local',\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 = mode === 'public' ? '*'.repeat(HASH_LENGTH) : '==';\n const value =\n mode === 'raw' ? keyword : `${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 { 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 = {\n local: new Set(),\n public: new Set(),\n raw: new Set(),\n };\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, file);\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 for (const keyword of keywords.raw) {\n collectedKeywords.raw.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, ` +\n `${collectedKeywords.local.size} local, ` +\n `${collectedKeywords.public.size} public, ` +\n `${collectedKeywords.raw.size} raw keywords ` +\n `(${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 './raw': {\n types: './raw.d.ts',\n },\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, 'public');\n const rawContent = generateTypeDeclaration(keywords.raw, 'raw');\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(path.join(outPath, 'raw.d.ts'), `${rawContent.trim()}\\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 blacklist from 'virtual:blacklist';\nimport {\n HASH_LENGTH,\n VIRTUAL_MODULE_ID,\n VIRTUAL_PUBLIC_MODULE_ID,\n} from './constants.js';\n\nconst ALPHA_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';\nconst BASE62_CHARS = `${ALPHA_CHARS}0123456789`;\n\nconst ALPHA_LEN = BigInt(ALPHA_CHARS.length); // 52n\nconst BASE62_LEN = BigInt(BASE62_CHARS.length); // 62n\n\nexport type Hasher = (input: string) => string;\n\n// Format: [1 Alpha] + [N Base62]\nexport const createHasher = (secret: string): Hasher => {\n const base62TailLength = HASH_LENGTH - 1;\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 let retry = 0;\n let result: string;\n\n do {\n const r = retry.toString();\n retry++;\n const payload = `${info.length}:${info}|${input.length}:${input}|${r.length}:${r}`;\n const hasher = createHmac('sha256', secret);\n const buffer = hasher.update(payload).digest('hex');\n\n let entropy = BigInt(`0x${buffer}`);\n result = '';\n\n result += ALPHA_CHARS[Number(entropy % ALPHA_LEN)];\n entropy /= ALPHA_LEN;\n for (let i = 0; i < base62TailLength; i++) {\n result += BASE62_CHARS[Number(entropy % BASE62_LEN)];\n entropy /= BASE62_LEN;\n }\n } while (blacklist.has(result));\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 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: string;\n do {\n result = '';\n let current = index;\n index++;\n\n result += shuffledAlpha[current % shuffledAlpha.length];\n current = Math.floor(current / shuffledAlpha.length);\n while (current > 0) {\n current--;\n result += shuffledBase62[current % shuffledBase62.length];\n current = Math.floor(current / shuffledBase62.length);\n }\n } while (blacklist.has(result));\n\n cache.set(input, result);\n return result;\n };\n};\n"],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as transformCode, c as VIRTUAL_INTERNAL_MODULE_ID, d as VIRTUAL_PUBLIC_MODULE_ID, i as extractKeywords, l as VIRTUAL_INTERNAL_PUBLIC_MODULE_ID, n as createHasher, o as encodeIdentifier, r as createRunner, s as PLUGIN_NAME, t as createCounter, u as
|
|
1
|
+
import { a as transformCode, c as VIRTUAL_INTERNAL_MODULE_ID, d as VIRTUAL_MODULE_ID, f as VIRTUAL_PUBLIC_MODULE_ID, i as extractKeywords, l as VIRTUAL_INTERNAL_PUBLIC_MODULE_ID, n as createHasher, o as encodeIdentifier, p as VIRTUAL_RAW_MODULE_ID, r as createRunner, s as PLUGIN_NAME, t as createCounter, u as VIRTUAL_INTERNAL_RAW_MODULE_ID } from "./hash-C4xUIITd.js";
|
|
2
2
|
import { readFile } from "node:fs/promises";
|
|
3
3
|
import pLimit from "p-limit";
|
|
4
4
|
//#region src/internal/plugin.ts
|
|
@@ -13,14 +13,15 @@ const splitQuery = (id) => {
|
|
|
13
13
|
return [id.slice(0, index), id.slice(index + 1)];
|
|
14
14
|
};
|
|
15
15
|
const toIncludes = (id) => [new RegExp(`^${id}/`)];
|
|
16
|
-
const SUFFIX_REGEX = /\.m?[jt]sx
|
|
16
|
+
const SUFFIX_REGEX = /\.m?[jt]sx?($|\?)/;
|
|
17
17
|
const COMMON_EXCLUDES = [/\/node_modules\//];
|
|
18
18
|
const unpluginFactory = ({ isDev, secret }) => {
|
|
19
19
|
const runner = createRunner({ silent: true });
|
|
20
20
|
const runnerLimit = pLimit({ concurrency: 1 });
|
|
21
21
|
const typegenKeywords = {
|
|
22
22
|
local: /* @__PURE__ */ new Set(),
|
|
23
|
-
public: /* @__PURE__ */ new Set()
|
|
23
|
+
public: /* @__PURE__ */ new Set(),
|
|
24
|
+
raw: /* @__PURE__ */ new Set()
|
|
24
25
|
};
|
|
25
26
|
let isInitialized = false;
|
|
26
27
|
const runInit = async () => {
|
|
@@ -28,6 +29,7 @@ const unpluginFactory = ({ isDev, secret }) => {
|
|
|
28
29
|
const keywords = await runner.collect();
|
|
29
30
|
for (const keyword of keywords.local) typegenKeywords.local.add(keyword);
|
|
30
31
|
for (const keyword of keywords.public) typegenKeywords.public.add(keyword);
|
|
32
|
+
for (const keyword of keywords.raw) typegenKeywords.raw.add(keyword);
|
|
31
33
|
await runner.save(typegenKeywords);
|
|
32
34
|
isInitialized = true;
|
|
33
35
|
} catch {}
|
|
@@ -41,7 +43,7 @@ const unpluginFactory = ({ isDev, secret }) => {
|
|
|
41
43
|
hasherPublic = createHasher(secret);
|
|
42
44
|
hasherLocal = createCounter(secret);
|
|
43
45
|
resolvedMap = /* @__PURE__ */ new Map();
|
|
44
|
-
runnerLimit(async () => {
|
|
46
|
+
if (!isInitialized) runnerLimit(async () => {
|
|
45
47
|
if (!isInitialized) await runInit();
|
|
46
48
|
});
|
|
47
49
|
},
|
|
@@ -50,7 +52,11 @@ const unpluginFactory = ({ isDev, secret }) => {
|
|
|
50
52
|
},
|
|
51
53
|
resolveId: {
|
|
52
54
|
filter: { id: {
|
|
53
|
-
include: [
|
|
55
|
+
include: [
|
|
56
|
+
...toIncludes(VIRTUAL_INTERNAL_MODULE_ID),
|
|
57
|
+
...toIncludes(VIRTUAL_INTERNAL_PUBLIC_MODULE_ID),
|
|
58
|
+
...toIncludes(VIRTUAL_INTERNAL_RAW_MODULE_ID)
|
|
59
|
+
],
|
|
54
60
|
exclude: COMMON_EXCLUDES
|
|
55
61
|
} },
|
|
56
62
|
handler(id) {
|
|
@@ -59,7 +65,11 @@ const unpluginFactory = ({ isDev, secret }) => {
|
|
|
59
65
|
},
|
|
60
66
|
load: {
|
|
61
67
|
filter: { id: {
|
|
62
|
-
include: [
|
|
68
|
+
include: [
|
|
69
|
+
...toIncludes(resolveId(VIRTUAL_INTERNAL_MODULE_ID)),
|
|
70
|
+
...toIncludes(resolveId(VIRTUAL_INTERNAL_PUBLIC_MODULE_ID)),
|
|
71
|
+
...toIncludes(resolveId(VIRTUAL_INTERNAL_RAW_MODULE_ID))
|
|
72
|
+
],
|
|
63
73
|
exclude: COMMON_EXCLUDES
|
|
64
74
|
} },
|
|
65
75
|
handler(id) {
|
|
@@ -74,10 +84,15 @@ const unpluginFactory = ({ isDev, secret }) => {
|
|
|
74
84
|
include: [SUFFIX_REGEX],
|
|
75
85
|
exclude: COMMON_EXCLUDES
|
|
76
86
|
},
|
|
77
|
-
code: { include: [
|
|
87
|
+
code: { include: [
|
|
88
|
+
VIRTUAL_MODULE_ID,
|
|
89
|
+
VIRTUAL_PUBLIC_MODULE_ID,
|
|
90
|
+
VIRTUAL_RAW_MODULE_ID
|
|
91
|
+
] }
|
|
78
92
|
},
|
|
79
93
|
handler(code, id) {
|
|
80
|
-
const
|
|
94
|
+
const [validId] = splitQuery(id);
|
|
95
|
+
const result = transformCode(code, validId);
|
|
81
96
|
if (!result) return null;
|
|
82
97
|
const { code: transformed, map, keywords } = result;
|
|
83
98
|
for (const keyword of keywords.local) {
|
|
@@ -94,6 +109,11 @@ const unpluginFactory = ({ isDev, secret }) => {
|
|
|
94
109
|
const value = isDev ? `${hash}.${keyword}` : hash;
|
|
95
110
|
resolvedMap.set(resolvedId, `export default ${JSON.stringify(value)};\n`);
|
|
96
111
|
}
|
|
112
|
+
for (const keyword of keywords.raw) {
|
|
113
|
+
const resolvedId = resolveId(`${VIRTUAL_INTERNAL_RAW_MODULE_ID}/_/${encodeIdentifier(keyword)}`);
|
|
114
|
+
if (resolvedMap.has(resolvedId)) continue;
|
|
115
|
+
resolvedMap.set(resolvedId, `export default ${JSON.stringify(keyword)};\n`);
|
|
116
|
+
}
|
|
97
117
|
return {
|
|
98
118
|
code: transformed,
|
|
99
119
|
map
|
|
@@ -102,13 +122,14 @@ const unpluginFactory = ({ isDev, secret }) => {
|
|
|
102
122
|
},
|
|
103
123
|
async watchChange(id, { event }) {
|
|
104
124
|
if (!SUFFIX_REGEX.test(id) || COMMON_EXCLUDES.some((regex) => regex.test(id)) || event === "delete") return;
|
|
125
|
+
const [validId] = splitQuery(id);
|
|
105
126
|
let code;
|
|
106
127
|
try {
|
|
107
|
-
code = await readFile(
|
|
128
|
+
code = await readFile(validId, "utf-8");
|
|
108
129
|
} catch {
|
|
109
130
|
return;
|
|
110
131
|
}
|
|
111
|
-
const keywords = extractKeywords(code);
|
|
132
|
+
const keywords = extractKeywords(code, validId);
|
|
112
133
|
if (!keywords) return;
|
|
113
134
|
let isAdded = false;
|
|
114
135
|
for (const keyword of keywords.local) if (!typegenKeywords.local.has(keyword)) {
|
|
@@ -119,6 +140,10 @@ const unpluginFactory = ({ isDev, secret }) => {
|
|
|
119
140
|
typegenKeywords.public.add(keyword);
|
|
120
141
|
isAdded = true;
|
|
121
142
|
}
|
|
143
|
+
for (const keyword of keywords.raw) if (!typegenKeywords.raw.has(keyword)) {
|
|
144
|
+
typegenKeywords.raw.add(keyword);
|
|
145
|
+
isAdded = true;
|
|
146
|
+
}
|
|
122
147
|
if (!isInitialized || isAdded) runnerLimit(async () => {
|
|
123
148
|
if (!isInitialized) await runInit();
|
|
124
149
|
else if (isAdded) try {
|
|
@@ -131,4 +156,4 @@ const unpluginFactory = ({ isDev, secret }) => {
|
|
|
131
156
|
//#endregion
|
|
132
157
|
export { unpluginFactory as t };
|
|
133
158
|
|
|
134
|
-
//# sourceMappingURL=plugin-
|
|
159
|
+
//# sourceMappingURL=plugin-cEMprzlf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-cEMprzlf.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,\n PLUGIN_NAME,\n VIRTUAL_INTERNAL_MODULE_ID,\n VIRTUAL_INTERNAL_PUBLIC_MODULE_ID,\n VIRTUAL_INTERNAL_RAW_MODULE_ID,\n VIRTUAL_MODULE_ID,\n VIRTUAL_PUBLIC_MODULE_ID,\n VIRTUAL_RAW_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 = {\n local: new Set(),\n public: new Set(),\n raw: new Set(),\n };\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 for (const keyword of keywords.raw) {\n typegenKeywords.raw.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 if (!isInitialized) {\n runnerLimit(async () => {\n if (!isInitialized) {\n await runInit();\n }\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_INTERNAL_MODULE_ID),\n ...toIncludes(VIRTUAL_INTERNAL_PUBLIC_MODULE_ID),\n ...toIncludes(VIRTUAL_INTERNAL_RAW_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_INTERNAL_MODULE_ID)),\n ...toIncludes(resolveId(VIRTUAL_INTERNAL_PUBLIC_MODULE_ID)),\n ...toIncludes(resolveId(VIRTUAL_INTERNAL_RAW_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: [\n VIRTUAL_MODULE_ID,\n VIRTUAL_PUBLIC_MODULE_ID,\n VIRTUAL_RAW_MODULE_ID,\n ],\n },\n },\n handler(code, id) {\n const [validId] = splitQuery(id);\n const result = transformCode(code, validId);\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_INTERNAL_MODULE_ID}/${KEYWORD_ROUTE}/${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_INTERNAL_PUBLIC_MODULE_ID}/${KEYWORD_ROUTE}/${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 for (const keyword of keywords.raw) {\n const encoded = encodeIdentifier(keyword);\n const resolvedId = resolveId(\n `${VIRTUAL_INTERNAL_RAW_MODULE_ID}/${KEYWORD_ROUTE}/${encoded}`,\n );\n if (resolvedMap.has(resolvedId)) {\n continue;\n }\n resolvedMap.set(\n resolvedId,\n `export default ${JSON.stringify(keyword)};\\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 const [validId] = splitQuery(id);\n let code: string;\n try {\n code = await readFile(validId, 'utf-8');\n } catch {\n return;\n }\n const keywords = extractKeywords(code, validId);\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 for (const keyword of keywords.raw) {\n if (!typegenKeywords.raw.has(keyword)) {\n typegenKeywords.raw.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
package/dist/rollup.js
CHANGED
package/dist/rspack.js
CHANGED
package/dist/vite.js
CHANGED
package/dist/webpack.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "unplugin-keywords",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.13.1",
|
|
4
4
|
"description": "A build plugin for structural string literal minification and obfuscation.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"unplugin",
|
|
@@ -59,10 +59,6 @@
|
|
|
59
59
|
"types": "./dist/webpack.d.ts",
|
|
60
60
|
"default": "./dist/webpack.js"
|
|
61
61
|
},
|
|
62
|
-
"./cli": {
|
|
63
|
-
"types": "./dist/cli.d.ts",
|
|
64
|
-
"default": "./dist/cli.js"
|
|
65
|
-
},
|
|
66
62
|
"./package.json": "./package.json"
|
|
67
63
|
},
|
|
68
64
|
"bin": {
|
|
@@ -80,7 +76,7 @@
|
|
|
80
76
|
},
|
|
81
77
|
"devDependencies": {
|
|
82
78
|
"@biomejs/biome": "^2.4.14",
|
|
83
|
-
"@mdn/browser-compat-data": "^
|
|
79
|
+
"@mdn/browser-compat-data": "^8.0.0",
|
|
84
80
|
"@tsconfig/bases": "^1.0.23",
|
|
85
81
|
"@types/node": "^25.6.0",
|
|
86
82
|
"globals": "^17.6.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hash-BJl6coaB.js","names":["t","blacklist","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 VIRTUAL_INTERNAL_MODULE_ID = '~keywords-internal';\nexport const VIRTUAL_INTERNAL_PUBLIC_MODULE_ID = '~keywords-internal/public';\n\nexport const PLUGIN_NAME = 'unplugin-keywords';\n\nexport const HASH_LENGTH = 7;\n\nexport const KEYWORD_ROUTE = '_';\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,\n PLUGIN_NAME,\n VIRTUAL_INTERNAL_MODULE_ID,\n VIRTUAL_INTERNAL_PUBLIC_MODULE_ID,\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_INTERNAL_MODULE_ID}/${KEYWORD_ROUTE}/${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_INTERNAL_PUBLIC_MODULE_ID}/${KEYWORD_ROUTE}/${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 const targetModuleId = isPublic\n ? VIRTUAL_INTERNAL_PUBLIC_MODULE_ID\n : VIRTUAL_INTERNAL_MODULE_ID;\n return t.exportNamedDeclaration(\n null,\n [\n t.exportSpecifier(\n t.identifier('default'),\n specifierPath.node.exported,\n ),\n ],\n t.stringLiteral(\n `${targetModuleId}/${KEYWORD_ROUTE}/${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;\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 { 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, ` +\n `${collectedKeywords.local.size} local, ` +\n `${collectedKeywords.public.size} public keywords ` +\n `(${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 },\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 blacklist from 'virtual:blacklist';\nimport {\n HASH_LENGTH,\n VIRTUAL_MODULE_ID,\n VIRTUAL_PUBLIC_MODULE_ID,\n} from './constants.js';\n\nconst ALPHA_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';\nconst BASE62_CHARS = `${ALPHA_CHARS}0123456789`;\n\nconst ALPHA_LEN = BigInt(ALPHA_CHARS.length); // 52n\nconst BASE62_LEN = BigInt(BASE62_CHARS.length); // 62n\n\nexport type Hasher = (input: string) => string;\n\n// Format: [1 Alpha] + [N Base62]\nexport const createHasher = (secret: string): Hasher => {\n const base62TailLength = HASH_LENGTH - 1;\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 let retry = 0;\n let result: string;\n\n do {\n const r = retry.toString();\n retry++;\n const payload = `${info.length}:${info}|${input.length}:${input}|${r.length}:${r}`;\n const hasher = createHmac('sha256', secret);\n const buffer = hasher.update(payload).digest('hex');\n\n let entropy = BigInt(`0x${buffer}`);\n result = '';\n\n result += ALPHA_CHARS[Number(entropy % ALPHA_LEN)];\n entropy /= ALPHA_LEN;\n for (let i = 0; i < base62TailLength; i++) {\n result += BASE62_CHARS[Number(entropy % BASE62_LEN)];\n entropy /= BASE62_LEN;\n }\n } while (blacklist.has(result));\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 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: string;\n do {\n result = '';\n let current = index;\n index++;\n\n result += shuffledAlpha[current % shuffledAlpha.length];\n current = Math.floor(current / shuffledAlpha.length);\n while (current > 0) {\n current--;\n result += shuffledBase62[current % shuffledBase62.length];\n current = Math.floor(current / shuffledBase62.length);\n }\n } while (blacklist.has(result));\n\n cache.set(input, result);\n return result;\n };\n};\n"],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-B-GMuoNu.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,\n PLUGIN_NAME,\n VIRTUAL_INTERNAL_MODULE_ID,\n VIRTUAL_INTERNAL_PUBLIC_MODULE_ID,\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_INTERNAL_MODULE_ID),\n ...toIncludes(VIRTUAL_INTERNAL_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_INTERNAL_MODULE_ID)),\n ...toIncludes(resolveId(VIRTUAL_INTERNAL_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_INTERNAL_MODULE_ID}/${KEYWORD_ROUTE}/${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_INTERNAL_PUBLIC_MODULE_ID}/${KEYWORD_ROUTE}/${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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"}
|