@stacksjs/stx 0.2.144 → 0.2.146

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.
@@ -32,8 +32,6 @@ export function hasUserImports(code) {
32
32
  const source = match[1];
33
33
  if (/\.css(?:\?.*)?$/.test(source))
34
34
  continue;
35
- if (source === "@stacksjs/browser")
36
- continue;
37
35
  if (!EXTERNAL_PATTERNS.some((p) => p.test(source))) {
38
36
  logBundlerDiagnostic("detected side-effect import:", source);
39
37
  return !0;
@@ -94,6 +94,7 @@ export declare interface VendorCssImport {
94
94
  export declare interface BrowserCoreAutoImportResult {
95
95
  code: string
96
96
  imports: string[]
97
+ models: string[]
97
98
  }
98
99
  // =============================================================================
99
100
  // Types
@@ -270,13 +270,19 @@ export function injectBrowserCoreAutoImports(code) {
270
270
  if (explicitlyImported.has(symbol) || locallyDeclared.has(symbol))
271
271
  return !1;
272
272
  return new RegExp(`\\b${symbol}\\b`).test(code);
273
- });
274
- if (imports.length === 0)
275
- return { code, imports };
273
+ }), models = detectModelUsage(code).filter((model) => !explicitlyImported.has(model) && !locallyDeclared.has(model));
274
+ if (imports.length === 0 && models.length === 0)
275
+ return { code, imports, models };
276
276
  return {
277
- code: `import { ${imports.join(", ")} } from '@stacksjs/browser'
277
+ code: `${[
278
+ imports.length > 0 ? `import { ${imports.join(", ")} } from '@stacksjs/browser'` : "",
279
+ models.length > 0 ? "import '@stacksjs/browser'" : "",
280
+ models.length > 0 ? `const { ${models.join(", ")} } = window.StacksBrowser || {}` : ""
281
+ ].filter(Boolean).join(`
282
+ `)}
278
283
  ${code}`,
279
- imports
284
+ imports,
285
+ models
280
286
  };
281
287
  }
282
288
  const JS_BUILTINS = new Set([
@@ -344,6 +350,18 @@ function detectModelUsage(code) {
344
350
  models.add(match[1]);
345
351
  return Array.from(models);
346
352
  }
353
+ function collectLocalBindings(code) {
354
+ const bindings = new Set;
355
+ for (const match of code.matchAll(/\b(?:const|let|var|function|class)\s+([A-Za-z_$][\w$]*)/g))
356
+ bindings.add(match[1]);
357
+ for (const match of code.matchAll(/\b(?:const|let|var)\s*\{([^}]*)\}/g))
358
+ for (const binding of match[1].split(",")) {
359
+ const localName = binding.trim().split(/[:=]/).pop()?.trim();
360
+ if (localName && /^[A-Za-z_$][\w$]*$/.test(localName))
361
+ bindings.add(localName);
362
+ }
363
+ return bindings;
364
+ }
347
365
  function transformAutoImports(code) {
348
366
  const usedStxImports = new Set, usedBrowserImports = new Set;
349
367
  let transformedCode = code;
@@ -354,30 +372,43 @@ function transformAutoImports(code) {
354
372
  const imports = match[1], source = match[2];
355
373
  if (match[0].includes("import type"))
356
374
  continue;
357
- imports.split(",").map((s) => s.trim().split(/\s+as\s+/)[0]).filter((s) => s.length > 0).forEach((name) => {
358
- existingImports.add(name);
375
+ const aliases = [];
376
+ for (const rawSpecifier of imports.split(",")) {
377
+ const specifier = rawSpecifier.trim();
378
+ if (!specifier || specifier.startsWith("type "))
379
+ continue;
380
+ const aliasMatch = specifier.match(/^([A-Za-z_$][\w$]*)(?:\s+as\s+([A-Za-z_$][\w$]*))?$/);
381
+ if (!aliasMatch)
382
+ continue;
383
+ const importedName = aliasMatch[1], localName = aliasMatch[2] || importedName;
384
+ existingImports.add(importedName);
385
+ existingImports.add(localName);
359
386
  if (source === "stx" || source === "@stacksjs/stx")
360
- usedStxImports.add(name);
387
+ usedStxImports.add(importedName);
361
388
  else
362
- usedBrowserImports.add(name);
363
- });
364
- transformedCode = transformedCode.replace(match[0], "// [auto-import processed]");
389
+ usedBrowserImports.add(importedName);
390
+ if (localName !== importedName)
391
+ aliases.push(`${localName} = ${importedName}`);
392
+ }
393
+ const replacement = aliases.length > 0 ? `var ${aliases.join(", ")}; /* [auto-import processed] */` : "// [auto-import processed]";
394
+ transformedCode = transformedCode.replace(match[0], replacement);
365
395
  }
396
+ const locallyDeclared = collectLocalBindings(transformedCode);
366
397
  for (const symbol of STX_AUTO_IMPORTS) {
367
- if (existingImports.has(symbol))
398
+ if (existingImports.has(symbol) || locallyDeclared.has(symbol))
368
399
  continue;
369
400
  if (new RegExp(`\\b${symbol}\\s*\\(`, "g").test(transformedCode))
370
401
  usedStxImports.add(symbol);
371
402
  }
372
403
  for (const symbol of BROWSER_CORE_IMPORTS) {
373
- if (existingImports.has(symbol))
404
+ if (existingImports.has(symbol) || locallyDeclared.has(symbol))
374
405
  continue;
375
406
  if (new RegExp(`\\b${symbol}\\b`, "g").test(transformedCode))
376
407
  usedBrowserImports.add(symbol);
377
408
  }
378
409
  const detectedModels = detectModelUsage(transformedCode);
379
410
  for (const model of detectedModels)
380
- if (!existingImports.has(model))
411
+ if (!existingImports.has(model) && !locallyDeclared.has(model))
381
412
  usedBrowserImports.add(model);
382
413
  return {
383
414
  code: transformedCode,
@@ -813,7 +844,7 @@ export async function processClientScript(scriptContent, options = {}) {
813
844
  code = cssExtraction.code;
814
845
  const vendorStyleTags = renderVendorStyleTags(cssExtraction.styles), browserCoreImports = injectBrowserCoreAutoImports(code);
815
846
  code = browserCoreImports.code;
816
- bundledBrowserImports = browserCoreImports.imports;
847
+ bundledBrowserImports = [...browserCoreImports.imports, ...browserCoreImports.models];
817
848
  const { hasUserImports, bundleClientScript } = await importOnce("stx/client-script-bundler", () => import("./client-script-bundler.js"));
818
849
  if (hasUserImports(code)) {
819
850
  code = await bundleClientScript(code, options.filePath || "", {