@hyperfixi/vite-plugin 2.0.0 → 2.1.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/dist/index.cjs +360 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +173 -1
- package/dist/index.d.ts +173 -1
- package/dist/index.js +357 -1
- package/dist/index.js.map +1 -1
- package/package.json +11 -3
package/dist/index.cjs
CHANGED
|
@@ -30,11 +30,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
DomainAggregator: () => DomainAggregator,
|
|
34
|
+
DomainScanner: () => DomainScanner,
|
|
33
35
|
REGIONS: () => REGIONS,
|
|
34
36
|
SUPPORTED_LANGUAGES: () => SUPPORTED_LANGUAGES,
|
|
35
37
|
clearCustomKeywords: () => clearCustomKeywords,
|
|
36
38
|
clearSemanticParser: () => clearSemanticParser,
|
|
37
39
|
default: () => index_default,
|
|
40
|
+
descriptorToScanRule: () => descriptorToScanRule,
|
|
38
41
|
detectLanguages: () => detectLanguages,
|
|
39
42
|
getAllLanguageCodes: () => getAllLanguageCodes,
|
|
40
43
|
getKeywordsForLanguage: () => getKeywordsForLanguage,
|
|
@@ -522,6 +525,8 @@ var POLISH_KEYWORDS = /* @__PURE__ */ new Set([
|
|
|
522
525
|
"zwi\u0119ksz",
|
|
523
526
|
"zwieksz",
|
|
524
527
|
"zmniejsz",
|
|
528
|
+
"uzyskaj",
|
|
529
|
+
"pobierz",
|
|
525
530
|
"wywo\u0142aj",
|
|
526
531
|
"wywolaj",
|
|
527
532
|
"wyzw\xF3l",
|
|
@@ -1861,6 +1866,15 @@ async function evaluate(node, ctx) {
|
|
|
1861
1866
|
const obj = await evaluate(node.object, ctx);
|
|
1862
1867
|
if (obj == null) return undefined;
|
|
1863
1868
|
const prop = node.computed ? await evaluate(node.property, ctx) : node.property;
|
|
1869
|
+
if (prop === 'values' && obj instanceof Element) {
|
|
1870
|
+
if (obj instanceof HTMLFormElement) return new FormData(obj);
|
|
1871
|
+
const fd = new FormData();
|
|
1872
|
+
obj.querySelectorAll('input, select, textarea').forEach(input => {
|
|
1873
|
+
const name = input.getAttribute('name');
|
|
1874
|
+
if (name && 'value' in input) fd.append(name, input.value);
|
|
1875
|
+
});
|
|
1876
|
+
return fd;
|
|
1877
|
+
}
|
|
1864
1878
|
return obj[prop];
|
|
1865
1879
|
|
|
1866
1880
|
case 'call': {
|
|
@@ -2945,6 +2959,9 @@ function compileExpression(node) {
|
|
|
2945
2959
|
if (prop.startsWith("*")) {
|
|
2946
2960
|
return `${obj}.style.${prop.slice(1)}`;
|
|
2947
2961
|
}
|
|
2962
|
+
if (prop === "values") {
|
|
2963
|
+
return `(function(el){if(el instanceof HTMLFormElement)return new FormData(el);var fd=new FormData();el.querySelectorAll('input,select,textarea').forEach(function(i){var n=i.getAttribute('name');if(n&&'value'in i)fd.append(n,i.value)});return fd})(${obj})`;
|
|
2964
|
+
}
|
|
2948
2965
|
return `${obj}.${prop}`;
|
|
2949
2966
|
}
|
|
2950
2967
|
case "member": {
|
|
@@ -3268,6 +3285,290 @@ function extractScripts(html) {
|
|
|
3268
3285
|
return scripts;
|
|
3269
3286
|
}
|
|
3270
3287
|
|
|
3288
|
+
// src/server-bridge-integration.ts
|
|
3289
|
+
var import_node_path = require("path");
|
|
3290
|
+
var import_promises = require("fs/promises");
|
|
3291
|
+
var serverBridge = null;
|
|
3292
|
+
var loadAttempted = false;
|
|
3293
|
+
var lastRouteHash = "";
|
|
3294
|
+
async function loadServerBridge(debug) {
|
|
3295
|
+
if (loadAttempted) return serverBridge;
|
|
3296
|
+
loadAttempted = true;
|
|
3297
|
+
try {
|
|
3298
|
+
const mod = await import("@hyperfixi/server-bridge");
|
|
3299
|
+
serverBridge = mod;
|
|
3300
|
+
if (debug) {
|
|
3301
|
+
console.log("[hyperfixi] Server-bridge loaded successfully");
|
|
3302
|
+
}
|
|
3303
|
+
return serverBridge;
|
|
3304
|
+
} catch {
|
|
3305
|
+
console.warn(
|
|
3306
|
+
"[hyperfixi] @hyperfixi/server-bridge is not installed. Install it to enable server route generation: npm install @hyperfixi/server-bridge"
|
|
3307
|
+
);
|
|
3308
|
+
return null;
|
|
3309
|
+
}
|
|
3310
|
+
}
|
|
3311
|
+
function computeRouteHash(routes) {
|
|
3312
|
+
return routes.map((r) => `${r.method}:${r.path}`).sort().join("|");
|
|
3313
|
+
}
|
|
3314
|
+
async function runServerBridge(cwd, options, debug, force) {
|
|
3315
|
+
const mod = serverBridge ?? await loadServerBridge(debug);
|
|
3316
|
+
if (!mod) return;
|
|
3317
|
+
try {
|
|
3318
|
+
const outputDir = (0, import_node_path.resolve)(cwd, options.output ?? "./server/routes");
|
|
3319
|
+
const result = await mod.generate({
|
|
3320
|
+
dir: cwd,
|
|
3321
|
+
framework: options.framework ?? "express",
|
|
3322
|
+
output: options.output,
|
|
3323
|
+
typescript: options.typescript,
|
|
3324
|
+
ignore: options.ignore
|
|
3325
|
+
});
|
|
3326
|
+
const routeHash = computeRouteHash(result.routes);
|
|
3327
|
+
if (!force && routeHash === lastRouteHash) {
|
|
3328
|
+
if (debug) {
|
|
3329
|
+
console.log("[hyperfixi] Server-bridge: routes unchanged, skipping generation");
|
|
3330
|
+
}
|
|
3331
|
+
return;
|
|
3332
|
+
}
|
|
3333
|
+
lastRouteHash = routeHash;
|
|
3334
|
+
if (result.routes.length === 0) {
|
|
3335
|
+
if (debug) {
|
|
3336
|
+
console.log("[hyperfixi] Server-bridge: no routes found");
|
|
3337
|
+
}
|
|
3338
|
+
return;
|
|
3339
|
+
}
|
|
3340
|
+
await (0, import_promises.mkdir)(outputDir, { recursive: true });
|
|
3341
|
+
for (const file of result.generated.files) {
|
|
3342
|
+
const filePath = (0, import_node_path.join)(outputDir, file.path);
|
|
3343
|
+
const fileDir = (0, import_node_path.join)(filePath, "..");
|
|
3344
|
+
await (0, import_promises.mkdir)(fileDir, { recursive: true });
|
|
3345
|
+
await (0, import_promises.writeFile)(filePath, file.content, "utf-8");
|
|
3346
|
+
}
|
|
3347
|
+
const manifest = mod.createManifest(result.routes);
|
|
3348
|
+
await mod.saveManifest(outputDir, manifest);
|
|
3349
|
+
if (debug) {
|
|
3350
|
+
console.log(
|
|
3351
|
+
`[hyperfixi] Server-bridge: generated ${result.generated.files.length} file(s) for ${result.routes.length} route(s) in ${outputDir}/`
|
|
3352
|
+
);
|
|
3353
|
+
}
|
|
3354
|
+
if (result.scan.conflicts.length > 0) {
|
|
3355
|
+
console.warn(
|
|
3356
|
+
`[hyperfixi] Server-bridge: ${result.scan.conflicts.length} route conflict(s) detected`
|
|
3357
|
+
);
|
|
3358
|
+
}
|
|
3359
|
+
} catch (err) {
|
|
3360
|
+
console.error(
|
|
3361
|
+
"[hyperfixi] Server-bridge generation failed:",
|
|
3362
|
+
err instanceof Error ? err.message : err
|
|
3363
|
+
);
|
|
3364
|
+
}
|
|
3365
|
+
}
|
|
3366
|
+
|
|
3367
|
+
// src/domain-scanner.ts
|
|
3368
|
+
function buildAttributePatterns(attributes) {
|
|
3369
|
+
const patterns = [];
|
|
3370
|
+
for (const attr of attributes) {
|
|
3371
|
+
const escaped = attr.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3372
|
+
patterns.push(new RegExp(`${escaped}\\s*=\\s*"([^"]+)"`, "g"));
|
|
3373
|
+
patterns.push(new RegExp(`${escaped}\\s*=\\s*'([^']+)'`, "g"));
|
|
3374
|
+
patterns.push(new RegExp(`${escaped}\\s*=\\s*\`([^\`]+)\``, "g"));
|
|
3375
|
+
}
|
|
3376
|
+
return patterns;
|
|
3377
|
+
}
|
|
3378
|
+
function buildScriptPatterns(scriptTypes) {
|
|
3379
|
+
return scriptTypes.map((type) => {
|
|
3380
|
+
const escaped = type.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3381
|
+
return new RegExp(`<script[^>]*type=["']?${escaped}["']?[^>]*>([\\s\\S]*?)<\\/script>`, "gi");
|
|
3382
|
+
});
|
|
3383
|
+
}
|
|
3384
|
+
function detectKeywords(snippet, keywords) {
|
|
3385
|
+
const detectedKeywords = /* @__PURE__ */ new Set();
|
|
3386
|
+
const detectedLanguages = /* @__PURE__ */ new Set();
|
|
3387
|
+
for (const [lang, kwList] of Object.entries(keywords)) {
|
|
3388
|
+
for (const kw of kwList) {
|
|
3389
|
+
const isLatin = /^[a-zA-Z]/.test(kw);
|
|
3390
|
+
const found = isLatin ? new RegExp(`\\b${kw.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`, "i").test(snippet) : snippet.includes(kw);
|
|
3391
|
+
if (found) {
|
|
3392
|
+
detectedKeywords.add(kw);
|
|
3393
|
+
detectedLanguages.add(lang);
|
|
3394
|
+
}
|
|
3395
|
+
}
|
|
3396
|
+
}
|
|
3397
|
+
return { detectedKeywords, detectedLanguages };
|
|
3398
|
+
}
|
|
3399
|
+
var DomainScanner = class {
|
|
3400
|
+
constructor(rules) {
|
|
3401
|
+
this.rules = rules;
|
|
3402
|
+
const allAttrs = rules.flatMap((r) => [...r.attributes]);
|
|
3403
|
+
const allScriptTypes = rules.flatMap((r) => r.scriptTypes ? [...r.scriptTypes] : []);
|
|
3404
|
+
const parts = [];
|
|
3405
|
+
for (const attr of allAttrs) {
|
|
3406
|
+
parts.push(attr.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
|
|
3407
|
+
}
|
|
3408
|
+
for (const type of allScriptTypes) {
|
|
3409
|
+
parts.push(type.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
|
|
3410
|
+
}
|
|
3411
|
+
this.quickCheckPattern = parts.length > 0 ? new RegExp(parts.join("|"), "i") : null;
|
|
3412
|
+
}
|
|
3413
|
+
/**
|
|
3414
|
+
* Fast pre-check: does this code contain any domain-related attributes?
|
|
3415
|
+
*/
|
|
3416
|
+
hasAnyDomainUsage(code) {
|
|
3417
|
+
if (!this.quickCheckPattern) return false;
|
|
3418
|
+
return this.quickCheckPattern.test(code);
|
|
3419
|
+
}
|
|
3420
|
+
/**
|
|
3421
|
+
* Scan a file for all registered domain syntaxes.
|
|
3422
|
+
* Returns one DomainFileUsage per domain that had matches.
|
|
3423
|
+
*/
|
|
3424
|
+
scan(code, _id) {
|
|
3425
|
+
const results = [];
|
|
3426
|
+
for (const rule of this.rules) {
|
|
3427
|
+
const snippets = [];
|
|
3428
|
+
const attrPatterns = buildAttributePatterns(rule.attributes);
|
|
3429
|
+
for (const pattern of attrPatterns) {
|
|
3430
|
+
pattern.lastIndex = 0;
|
|
3431
|
+
let match;
|
|
3432
|
+
while (match = pattern.exec(code)) {
|
|
3433
|
+
const value = match[1].trim();
|
|
3434
|
+
if (value) snippets.push(value);
|
|
3435
|
+
}
|
|
3436
|
+
}
|
|
3437
|
+
if (rule.scriptTypes) {
|
|
3438
|
+
const scriptPatterns = buildScriptPatterns(rule.scriptTypes);
|
|
3439
|
+
for (const pattern of scriptPatterns) {
|
|
3440
|
+
pattern.lastIndex = 0;
|
|
3441
|
+
let match;
|
|
3442
|
+
while (match = pattern.exec(code)) {
|
|
3443
|
+
const value = match[1].trim();
|
|
3444
|
+
if (value) snippets.push(value);
|
|
3445
|
+
}
|
|
3446
|
+
}
|
|
3447
|
+
}
|
|
3448
|
+
if (snippets.length === 0) continue;
|
|
3449
|
+
const allDetectedKeywords = /* @__PURE__ */ new Set();
|
|
3450
|
+
const allDetectedLanguages = /* @__PURE__ */ new Set();
|
|
3451
|
+
if (rule.keywords) {
|
|
3452
|
+
for (const snippet of snippets) {
|
|
3453
|
+
const { detectedKeywords, detectedLanguages } = detectKeywords(snippet, rule.keywords);
|
|
3454
|
+
for (const kw of detectedKeywords) allDetectedKeywords.add(kw);
|
|
3455
|
+
for (const lang of detectedLanguages) allDetectedLanguages.add(lang);
|
|
3456
|
+
}
|
|
3457
|
+
}
|
|
3458
|
+
results.push({
|
|
3459
|
+
domain: rule.domain,
|
|
3460
|
+
detectedKeywords: allDetectedKeywords,
|
|
3461
|
+
detectedLanguages: allDetectedLanguages,
|
|
3462
|
+
snippetCount: snippets.length
|
|
3463
|
+
});
|
|
3464
|
+
}
|
|
3465
|
+
return results;
|
|
3466
|
+
}
|
|
3467
|
+
};
|
|
3468
|
+
function descriptorToScanRule(descriptor) {
|
|
3469
|
+
if (!descriptor.scanConfig) return null;
|
|
3470
|
+
return {
|
|
3471
|
+
domain: descriptor.name,
|
|
3472
|
+
attributes: [...descriptor.scanConfig.attributes],
|
|
3473
|
+
scriptTypes: descriptor.scanConfig.scriptTypes ? [...descriptor.scanConfig.scriptTypes] : void 0,
|
|
3474
|
+
keywords: descriptor.scanConfig.keywords ? Object.fromEntries(
|
|
3475
|
+
Object.entries(descriptor.scanConfig.keywords).map(([k, v]) => [k, [...v]])
|
|
3476
|
+
) : void 0
|
|
3477
|
+
};
|
|
3478
|
+
}
|
|
3479
|
+
|
|
3480
|
+
// src/domain-aggregator.ts
|
|
3481
|
+
var DomainAggregator = class {
|
|
3482
|
+
constructor() {
|
|
3483
|
+
this.fileUsage = /* @__PURE__ */ new Map();
|
|
3484
|
+
this.cache = null;
|
|
3485
|
+
}
|
|
3486
|
+
/**
|
|
3487
|
+
* Add or update domain usage for a file.
|
|
3488
|
+
* Returns true if usage changed (invalidates cache).
|
|
3489
|
+
*/
|
|
3490
|
+
add(filePath, usage) {
|
|
3491
|
+
const existing = this.fileUsage.get(filePath);
|
|
3492
|
+
const changed = !existing || !this.isEqual(existing, usage);
|
|
3493
|
+
if (changed) {
|
|
3494
|
+
this.fileUsage.set(filePath, usage);
|
|
3495
|
+
this.cache = null;
|
|
3496
|
+
}
|
|
3497
|
+
return changed;
|
|
3498
|
+
}
|
|
3499
|
+
/**
|
|
3500
|
+
* Remove a file's domain usage.
|
|
3501
|
+
* Returns true if the file was tracked.
|
|
3502
|
+
*/
|
|
3503
|
+
remove(filePath) {
|
|
3504
|
+
const had = this.fileUsage.has(filePath);
|
|
3505
|
+
if (had) {
|
|
3506
|
+
this.fileUsage.delete(filePath);
|
|
3507
|
+
this.cache = null;
|
|
3508
|
+
}
|
|
3509
|
+
return had;
|
|
3510
|
+
}
|
|
3511
|
+
/**
|
|
3512
|
+
* Get aggregated usage across all files.
|
|
3513
|
+
* Result is cached until add/remove changes it.
|
|
3514
|
+
*/
|
|
3515
|
+
getUsage() {
|
|
3516
|
+
if (this.cache) return this.cache;
|
|
3517
|
+
const domainMap = /* @__PURE__ */ new Map();
|
|
3518
|
+
for (const usages of this.fileUsage.values()) {
|
|
3519
|
+
for (const usage of usages) {
|
|
3520
|
+
let entry = domainMap.get(usage.domain);
|
|
3521
|
+
if (!entry) {
|
|
3522
|
+
entry = {
|
|
3523
|
+
detectedKeywords: /* @__PURE__ */ new Set(),
|
|
3524
|
+
detectedLanguages: /* @__PURE__ */ new Set(),
|
|
3525
|
+
fileCount: 0,
|
|
3526
|
+
totalSnippets: 0
|
|
3527
|
+
};
|
|
3528
|
+
domainMap.set(usage.domain, entry);
|
|
3529
|
+
}
|
|
3530
|
+
entry.fileCount++;
|
|
3531
|
+
entry.totalSnippets += usage.snippetCount;
|
|
3532
|
+
for (const kw of usage.detectedKeywords) entry.detectedKeywords.add(kw);
|
|
3533
|
+
for (const lang of usage.detectedLanguages) entry.detectedLanguages.add(lang);
|
|
3534
|
+
}
|
|
3535
|
+
}
|
|
3536
|
+
this.cache = Array.from(domainMap.entries()).map(([domain, data]) => ({
|
|
3537
|
+
domain,
|
|
3538
|
+
detectedKeywords: data.detectedKeywords,
|
|
3539
|
+
detectedLanguages: data.detectedLanguages,
|
|
3540
|
+
fileCount: data.fileCount,
|
|
3541
|
+
totalSnippets: data.totalSnippets
|
|
3542
|
+
}));
|
|
3543
|
+
return this.cache;
|
|
3544
|
+
}
|
|
3545
|
+
/**
|
|
3546
|
+
* Get aggregated usage for a specific domain.
|
|
3547
|
+
*/
|
|
3548
|
+
getUsageForDomain(domain) {
|
|
3549
|
+
return this.getUsage().find((u) => u.domain === domain) ?? null;
|
|
3550
|
+
}
|
|
3551
|
+
/**
|
|
3552
|
+
* Clear all tracked data.
|
|
3553
|
+
*/
|
|
3554
|
+
clear() {
|
|
3555
|
+
this.fileUsage.clear();
|
|
3556
|
+
this.cache = null;
|
|
3557
|
+
}
|
|
3558
|
+
// ---------------------------------------------------------------------------
|
|
3559
|
+
// Private
|
|
3560
|
+
// ---------------------------------------------------------------------------
|
|
3561
|
+
isEqual(a, b) {
|
|
3562
|
+
if (a.length !== b.length) return false;
|
|
3563
|
+
for (let i = 0; i < a.length; i++) {
|
|
3564
|
+
if (a[i].domain !== b[i].domain) return false;
|
|
3565
|
+
if (a[i].snippetCount !== b[i].snippetCount) return false;
|
|
3566
|
+
if (a[i].detectedKeywords.size !== b[i].detectedKeywords.size) return false;
|
|
3567
|
+
}
|
|
3568
|
+
return true;
|
|
3569
|
+
}
|
|
3570
|
+
};
|
|
3571
|
+
|
|
3271
3572
|
// src/index.ts
|
|
3272
3573
|
var VIRTUAL_MODULE_ID = "virtual:hyperfixi";
|
|
3273
3574
|
var RESOLVED_VIRTUAL_MODULE_ID = "\0" + VIRTUAL_MODULE_ID;
|
|
@@ -3277,6 +3578,8 @@ function hyperfixi(options = {}) {
|
|
|
3277
3578
|
const scanner = new Scanner(options);
|
|
3278
3579
|
const aggregator = new Aggregator();
|
|
3279
3580
|
const generator = new Generator(options);
|
|
3581
|
+
const domainScanner = options.domains && options.domains.length > 0 ? new DomainScanner(options.domains) : null;
|
|
3582
|
+
const domainAggregator = domainScanner ? new DomainAggregator() : null;
|
|
3280
3583
|
let server = null;
|
|
3281
3584
|
let cachedBundle = null;
|
|
3282
3585
|
let lastUsageHash = "";
|
|
@@ -3379,11 +3682,14 @@ function hyperfixi(options = {}) {
|
|
|
3379
3682
|
/**
|
|
3380
3683
|
* Configure plugin based on Vite mode
|
|
3381
3684
|
*/
|
|
3382
|
-
configResolved(config) {
|
|
3685
|
+
async configResolved(config) {
|
|
3383
3686
|
isDev = config.command === "serve";
|
|
3384
3687
|
if (options.debug) {
|
|
3385
3688
|
console.log("[hyperfixi] Plugin initialized, mode:", isDev ? "development" : "production");
|
|
3386
3689
|
}
|
|
3690
|
+
if (options.serverBridge) {
|
|
3691
|
+
await loadServerBridge(options.debug);
|
|
3692
|
+
}
|
|
3387
3693
|
},
|
|
3388
3694
|
/**
|
|
3389
3695
|
* Store server reference and pre-scan HTML files for HMR
|
|
@@ -3396,6 +3702,25 @@ function hyperfixi(options = {}) {
|
|
|
3396
3702
|
}
|
|
3397
3703
|
const scannedFiles = await scanner.scanProject(cwd);
|
|
3398
3704
|
aggregator.loadFromScan(scannedFiles);
|
|
3705
|
+
if (domainScanner && domainAggregator) {
|
|
3706
|
+
for (const [filePath] of scannedFiles) {
|
|
3707
|
+
try {
|
|
3708
|
+
const fs = await import("fs");
|
|
3709
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
3710
|
+
if (domainScanner.hasAnyDomainUsage(content)) {
|
|
3711
|
+
const domainUsages = domainScanner.scan(content, filePath);
|
|
3712
|
+
if (domainUsages.length > 0) {
|
|
3713
|
+
domainAggregator.add(filePath, domainUsages);
|
|
3714
|
+
}
|
|
3715
|
+
}
|
|
3716
|
+
} catch {
|
|
3717
|
+
}
|
|
3718
|
+
}
|
|
3719
|
+
if (options.debug) {
|
|
3720
|
+
const domainSummary = domainAggregator.getUsage();
|
|
3721
|
+
console.log("[hyperfixi] Domain pre-scan:", domainSummary);
|
|
3722
|
+
}
|
|
3723
|
+
}
|
|
3399
3724
|
if (options.debug) {
|
|
3400
3725
|
const summary = aggregator.getSummary();
|
|
3401
3726
|
console.log("[hyperfixi] Pre-scan complete:", summary);
|
|
@@ -3442,6 +3767,12 @@ function hyperfixi(options = {}) {
|
|
|
3442
3767
|
}
|
|
3443
3768
|
const usage = scanner.scan(code, id);
|
|
3444
3769
|
const changed = aggregator.add(id, usage);
|
|
3770
|
+
if (domainScanner && domainAggregator && domainScanner.hasAnyDomainUsage(code)) {
|
|
3771
|
+
const domainUsages = domainScanner.scan(code, id);
|
|
3772
|
+
if (domainUsages.length > 0) {
|
|
3773
|
+
domainAggregator.add(id, domainUsages);
|
|
3774
|
+
}
|
|
3775
|
+
}
|
|
3445
3776
|
if (changed && server) {
|
|
3446
3777
|
setImmediate(() => {
|
|
3447
3778
|
const currentHash = computeUsageHash(aggregator.getUsage());
|
|
@@ -3471,6 +3802,9 @@ function hyperfixi(options = {}) {
|
|
|
3471
3802
|
invalidateVirtualModule();
|
|
3472
3803
|
}
|
|
3473
3804
|
}
|
|
3805
|
+
if (options.serverBridge && server) {
|
|
3806
|
+
await runServerBridge(server.config.root, options.serverBridge, options.debug);
|
|
3807
|
+
}
|
|
3474
3808
|
} catch {
|
|
3475
3809
|
if (aggregator.remove(file)) {
|
|
3476
3810
|
invalidateVirtualModule();
|
|
@@ -3501,6 +3835,25 @@ function hyperfixi(options = {}) {
|
|
|
3501
3835
|
}
|
|
3502
3836
|
const scannedFiles = await scanner.scanProject(cwd);
|
|
3503
3837
|
aggregator.loadFromScan(scannedFiles);
|
|
3838
|
+
if (domainScanner && domainAggregator) {
|
|
3839
|
+
for (const [filePath] of scannedFiles) {
|
|
3840
|
+
try {
|
|
3841
|
+
const fs = await import("fs");
|
|
3842
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
3843
|
+
if (domainScanner.hasAnyDomainUsage(content)) {
|
|
3844
|
+
const domainUsages = domainScanner.scan(content, filePath);
|
|
3845
|
+
if (domainUsages.length > 0) {
|
|
3846
|
+
domainAggregator.add(filePath, domainUsages);
|
|
3847
|
+
}
|
|
3848
|
+
}
|
|
3849
|
+
} catch {
|
|
3850
|
+
}
|
|
3851
|
+
}
|
|
3852
|
+
if (options.debug) {
|
|
3853
|
+
const domainSummary = domainAggregator.getUsage();
|
|
3854
|
+
console.log("[hyperfixi] Domain build scan:", domainSummary);
|
|
3855
|
+
}
|
|
3856
|
+
}
|
|
3504
3857
|
if (mode === "compile") {
|
|
3505
3858
|
const usage = aggregator.getUsage();
|
|
3506
3859
|
if (usage.detectedLanguages.size > 0) {
|
|
@@ -3526,6 +3879,9 @@ function hyperfixi(options = {}) {
|
|
|
3526
3879
|
languages: summary.languages
|
|
3527
3880
|
});
|
|
3528
3881
|
}
|
|
3882
|
+
if (options.serverBridge) {
|
|
3883
|
+
await runServerBridge(cwd, options.serverBridge, options.debug, true);
|
|
3884
|
+
}
|
|
3529
3885
|
}
|
|
3530
3886
|
}
|
|
3531
3887
|
};
|
|
@@ -3533,10 +3889,13 @@ function hyperfixi(options = {}) {
|
|
|
3533
3889
|
var index_default = hyperfixi;
|
|
3534
3890
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3535
3891
|
0 && (module.exports = {
|
|
3892
|
+
DomainAggregator,
|
|
3893
|
+
DomainScanner,
|
|
3536
3894
|
REGIONS,
|
|
3537
3895
|
SUPPORTED_LANGUAGES,
|
|
3538
3896
|
clearCustomKeywords,
|
|
3539
3897
|
clearSemanticParser,
|
|
3898
|
+
descriptorToScanRule,
|
|
3540
3899
|
detectLanguages,
|
|
3541
3900
|
getAllLanguageCodes,
|
|
3542
3901
|
getKeywordsForLanguage,
|