@stati/core 1.14.0 → 1.15.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.
@@ -74,8 +74,12 @@ export declare const DEFAULT_LOCALE = "en-US";
74
74
  export declare const DEFAULT_TS_SRC_DIR = "src";
75
75
  /** Default TypeScript output directory (relative to build output) */
76
76
  export declare const DEFAULT_TS_OUT_DIR = "_assets";
77
- /** Default TypeScript entry point filename */
78
- export declare const DEFAULT_TS_ENTRY_POINT = "main.ts";
79
- /** Default TypeScript bundle name */
80
- export declare const DEFAULT_TS_BUNDLE_NAME = "bundle";
77
+ /**
78
+ * Default bundle configuration when `bundles` is not specified.
79
+ * Creates a single global bundle from 'main.ts' entry point.
80
+ */
81
+ export declare const DEFAULT_BUNDLES: readonly [{
82
+ readonly entryPoint: "main.ts";
83
+ readonly bundleName: "main";
84
+ }];
81
85
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,iDAAiD;AACjD,eAAO,MAAM,eAAe,SAAS,CAAC;AAEtC,+CAA+C;AAC/C,eAAO,MAAM,eAAe,SAAS,CAAC;AAEtC,sCAAsC;AACtC,eAAO,MAAM,kBAAkB,WAAW,CAAC;AAE3C,iCAAiC;AACjC,eAAO,MAAM,cAAc,WAAW,CAAC;AAEvC,4DAA4D;AAC5D,eAAO,MAAM,YAAY,UAAU,CAAC;AAEpC,kCAAkC;AAClC,eAAO,MAAM,iBAAiB,kBAAkB,CAAC;AAIjD,qEAAqE;AACrE,eAAO,MAAM,sBAAsB,iCAAkC,CAAC;AAEtE,mCAAmC;AACnC,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAE/C,2CAA2C;AAC3C,eAAO,MAAM,oBAAoB,UAEhC,CAAC;AAIF,sCAAsC;AACtC,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAErC,kCAAkC;AAClC,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC,sCAAsC;AACtC,eAAO,MAAM,gBAAgB,cAAc,CAAC;AAE5C,0CAA0C;AAC1C,eAAO,MAAM,oBAAoB,0BAAmD,CAAC;AAIrF,wDAAwD;AACxD,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AAEzC,+DAA+D;AAC/D,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAE5C,qEAAqE;AACrE,eAAO,MAAM,wBAAwB,QAAQ,CAAC;AAI9C,4BAA4B;AAC5B,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC,0BAA0B;AAC1B,eAAO,MAAM,gBAAgB,QAA0B,CAAC;AAExD,yBAAyB;AACzB,eAAO,MAAM,eAAe,QAAwB,CAAC;AAErD,0BAA0B;AAC1B,eAAO,MAAM,gBAAgB,QAAsB,CAAC;AAEpD,8BAA8B;AAC9B,eAAO,MAAM,oBAAoB,QAAyB,CAAC;AAI3D,oDAAoD;AACpD,eAAO,MAAM,aAAa,QAAyB,CAAC;AAEpD,iDAAiD;AACjD,eAAO,MAAM,cAAc,QAA0B,CAAC;AAEtD,6CAA6C;AAC7C,eAAO,MAAM,UAAU,QAAmB,CAAC;AAE3C,iDAAiD;AACjD,eAAO,MAAM,WAAW,QAAuB,CAAC;AAEhD,uCAAuC;AACvC,eAAO,MAAM,WAAW,QAAsB,CAAC;AAE/C,2CAA2C;AAC3C,eAAO,MAAM,SAAS,QAAkB,CAAC;AAEzC,6CAA6C;AAC7C,eAAO,MAAM,UAAU,QAAmB,CAAC;AAI3C,kCAAkC;AAClC,eAAO,MAAM,kBAAkB,SAAS,CAAC;AAEzC,8BAA8B;AAC9B,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AAExC,+BAA+B;AAC/B,eAAO,MAAM,eAAe,eAAgC,CAAC;AAE7D,mEAAmE;AACnE,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAIvC,yBAAyB;AACzB,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAElD,8CAA8C;AAC9C,eAAO,MAAM,cAAc,UAAU,CAAC;AAItC,0CAA0C;AAC1C,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AAExC,qEAAqE;AACrE,eAAO,MAAM,kBAAkB,YAAY,CAAC;AAE5C,8CAA8C;AAC9C,eAAO,MAAM,sBAAsB,YAAY,CAAC;AAEhD,qCAAqC;AACrC,eAAO,MAAM,sBAAsB,WAAW,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,iDAAiD;AACjD,eAAO,MAAM,eAAe,SAAS,CAAC;AAEtC,+CAA+C;AAC/C,eAAO,MAAM,eAAe,SAAS,CAAC;AAEtC,sCAAsC;AACtC,eAAO,MAAM,kBAAkB,WAAW,CAAC;AAE3C,iCAAiC;AACjC,eAAO,MAAM,cAAc,WAAW,CAAC;AAEvC,4DAA4D;AAC5D,eAAO,MAAM,YAAY,UAAU,CAAC;AAEpC,kCAAkC;AAClC,eAAO,MAAM,iBAAiB,kBAAkB,CAAC;AAIjD,qEAAqE;AACrE,eAAO,MAAM,sBAAsB,iCAAkC,CAAC;AAEtE,mCAAmC;AACnC,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAE/C,2CAA2C;AAC3C,eAAO,MAAM,oBAAoB,UAEhC,CAAC;AAIF,sCAAsC;AACtC,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAErC,kCAAkC;AAClC,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC,sCAAsC;AACtC,eAAO,MAAM,gBAAgB,cAAc,CAAC;AAE5C,0CAA0C;AAC1C,eAAO,MAAM,oBAAoB,0BAAmD,CAAC;AAIrF,wDAAwD;AACxD,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AAEzC,+DAA+D;AAC/D,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAE5C,qEAAqE;AACrE,eAAO,MAAM,wBAAwB,QAAQ,CAAC;AAI9C,4BAA4B;AAC5B,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC,0BAA0B;AAC1B,eAAO,MAAM,gBAAgB,QAA0B,CAAC;AAExD,yBAAyB;AACzB,eAAO,MAAM,eAAe,QAAwB,CAAC;AAErD,0BAA0B;AAC1B,eAAO,MAAM,gBAAgB,QAAsB,CAAC;AAEpD,8BAA8B;AAC9B,eAAO,MAAM,oBAAoB,QAAyB,CAAC;AAI3D,oDAAoD;AACpD,eAAO,MAAM,aAAa,QAAyB,CAAC;AAEpD,iDAAiD;AACjD,eAAO,MAAM,cAAc,QAA0B,CAAC;AAEtD,6CAA6C;AAC7C,eAAO,MAAM,UAAU,QAAmB,CAAC;AAE3C,iDAAiD;AACjD,eAAO,MAAM,WAAW,QAAuB,CAAC;AAEhD,uCAAuC;AACvC,eAAO,MAAM,WAAW,QAAsB,CAAC;AAE/C,2CAA2C;AAC3C,eAAO,MAAM,SAAS,QAAkB,CAAC;AAEzC,6CAA6C;AAC7C,eAAO,MAAM,UAAU,QAAmB,CAAC;AAI3C,kCAAkC;AAClC,eAAO,MAAM,kBAAkB,SAAS,CAAC;AAEzC,8BAA8B;AAC9B,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AAExC,+BAA+B;AAC/B,eAAO,MAAM,eAAe,eAAgC,CAAC;AAE7D,mEAAmE;AACnE,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAIvC,yBAAyB;AACzB,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAElD,8CAA8C;AAC9C,eAAO,MAAM,cAAc,UAAU,CAAC;AAItC,0CAA0C;AAC1C,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AAExC,qEAAqE;AACrE,eAAO,MAAM,kBAAkB,YAAY,CAAC;AAE5C;;;GAGG;AACH,eAAO,MAAM,eAAe;;;EAA2D,CAAC"}
package/dist/constants.js CHANGED
@@ -83,7 +83,8 @@ export const DEFAULT_LOCALE = 'en-US';
83
83
  export const DEFAULT_TS_SRC_DIR = 'src';
84
84
  /** Default TypeScript output directory (relative to build output) */
85
85
  export const DEFAULT_TS_OUT_DIR = '_assets';
86
- /** Default TypeScript entry point filename */
87
- export const DEFAULT_TS_ENTRY_POINT = 'main.ts';
88
- /** Default TypeScript bundle name */
89
- export const DEFAULT_TS_BUNDLE_NAME = 'bundle';
86
+ /**
87
+ * Default bundle configuration when `bundles` is not specified.
88
+ * Creates a single global bundle from 'main.ts' entry point.
89
+ */
90
+ export const DEFAULT_BUNDLES = [{ entryPoint: 'main.ts', bundleName: 'main' }];
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/core/build.ts"],"names":[],"mappings":"AA8CA,OAAO,KAAK,EAEV,UAAU,EACV,MAAM,EAMP,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,iDAAiD;IACjD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA4FD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAsB,KAAK,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CAW3E"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/core/build.ts"],"names":[],"mappings":"AA+CA,OAAO,KAAK,EAEV,UAAU,EACV,MAAM,EAMP,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,iDAAiD;IACjD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA4FD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAsB,KAAK,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CAW3E"}
@@ -1,4 +1,4 @@
1
- import { ensureDir, writeFile, remove, pathExists, stat, readdir, copyFile, resolveOutDir, resolveStaticDir, resolveCacheDir, enableInventoryTracking, disableInventoryTracking, clearInventory, writeTailwindClassInventory, getInventorySize, isTailwindUsed, loadPreviousInventory, compileTypeScript, autoInjectBundle, } from './utils/index.js';
1
+ import { ensureDir, writeFile, remove, pathExists, stat, readdir, copyFile, resolveOutDir, resolveStaticDir, resolveCacheDir, enableInventoryTracking, disableInventoryTracking, clearInventory, writeTailwindClassInventory, getInventorySize, isTailwindUsed, loadPreviousInventory, compileTypeScript, autoInjectBundles, getBundlePathsForPage, } from './utils/index.js';
2
2
  import { join, dirname, relative, posix } from 'node:path';
3
3
  import { loadConfig } from '../config/loader.js';
4
4
  import { loadContent } from './content.js';
@@ -9,7 +9,7 @@ import { loadCacheManifest, saveCacheManifest, shouldRebuildPage, createCacheEnt
9
9
  import { generateSitemap, generateRobotsTxtFromConfig, autoInjectSEO, } from '../seo/index.js';
10
10
  import { generateRSSFeeds, validateRSSConfig } from '../rss/index.js';
11
11
  import { getEnv } from '../env.js';
12
- import { DEFAULT_TS_OUT_DIR, DEFAULT_OUT_DIR } from '../constants.js';
12
+ import { DEFAULT_OUT_DIR } from '../constants.js';
13
13
  /**
14
14
  * Recursively calculates the total size of a directory in bytes.
15
15
  * Used for build statistics.
@@ -184,7 +184,7 @@ async function loadContentAndBuildNavigation(config, options, logger) {
184
184
  /**
185
185
  * Processes pages with ISG caching logic.
186
186
  */
187
- async function processPagesWithCache(pages, manifest, config, outDir, md, eta, navigation, buildTime, options, logger, assets) {
187
+ async function processPagesWithCache(pages, manifest, config, outDir, md, eta, navigation, buildTime, options, logger, compiledBundles) {
188
188
  let cacheHits = 0;
189
189
  let cacheMisses = 0;
190
190
  // Build context
@@ -250,6 +250,9 @@ async function processPagesWithCache(pages, manifest, config, outDir, md, eta, n
250
250
  }
251
251
  // Render markdown to HTML
252
252
  const htmlContent = renderMarkdown(page.content, md);
253
+ // Compute matched bundle paths for this page
254
+ const bundlePaths = getBundlePathsForPage(page.url, compiledBundles);
255
+ const assets = bundlePaths.length > 0 ? { bundlePaths } : undefined;
253
256
  // Render with template
254
257
  let finalHtml = await renderPage(page, htmlContent, config, eta, navigation, pages, assets);
255
258
  // Auto-inject SEO tags if enabled
@@ -265,9 +268,10 @@ async function processPagesWithCache(pages, manifest, config, outDir, md, eta, n
265
268
  }
266
269
  finalHtml = autoInjectSEO(finalHtml, injectOptions);
267
270
  }
268
- // Auto-inject TypeScript bundle script tag if available
269
- if (assets?.bundlePath) {
270
- finalHtml = autoInjectBundle(finalHtml, assets.bundlePath);
271
+ // Auto-inject TypeScript bundle script tags if available and autoInject is enabled (default: true)
272
+ const shouldAutoInject = config.typescript?.autoInject !== false;
273
+ if (shouldAutoInject && assets && assets.bundlePaths.length > 0) {
274
+ finalHtml = autoInjectBundles(finalHtml, assets.bundlePaths);
271
275
  }
272
276
  const renderTime = Date.now() - startTime;
273
277
  if (logger.updateTreeNode) {
@@ -389,30 +393,22 @@ async function buildInternal(options = {}) {
389
393
  // Store navigation hash in manifest for change detection in dev server
390
394
  manifest.navigationHash = navigationHash;
391
395
  // Compile TypeScript if enabled
392
- let tsResult;
393
- let assets;
396
+ let compiledBundles = [];
394
397
  if (config.typescript?.enabled) {
395
- tsResult = await compileTypeScript({
398
+ compiledBundles = await compileTypeScript({
396
399
  projectRoot: process.cwd(),
397
400
  config: config.typescript,
398
401
  outDir: config.outDir || DEFAULT_OUT_DIR,
399
402
  mode: getEnv() === 'production' ? 'production' : 'development',
400
403
  logger,
401
404
  });
402
- if (tsResult?.bundleFilename) {
403
- const assetsDir = config.typescript.outDir || DEFAULT_TS_OUT_DIR;
404
- assets = {
405
- bundleName: tsResult.bundleFilename,
406
- bundlePath: posix.join('/', assetsDir, tsResult.bundleFilename),
407
- };
408
- }
409
405
  }
410
406
  // Process pages with ISG caching logic
411
407
  if (logger.step) {
412
408
  console.log(); // Add spacing before page processing
413
409
  }
414
410
  const buildTime = new Date();
415
- const pageProcessingResult = await processPagesWithCache(pages, manifest, config, outDir, md, eta, navigation, buildTime, options, logger, assets);
411
+ const pageProcessingResult = await processPagesWithCache(pages, manifest, config, outDir, md, eta, navigation, buildTime, options, logger, compiledBundles);
416
412
  cacheHits = pageProcessingResult.cacheHits;
417
413
  cacheMisses = pageProcessingResult.cacheMisses;
418
414
  // Write Tailwind class inventory after all templates have been rendered (if Tailwind is used)
@@ -1 +1 @@
1
- {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/core/dev.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAe,MAAM,EAAE,MAAM,mBAAmB,CAAC;AA2B7D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;CACb;AA4SD,wBAAsB,eAAe,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,SAAS,CAAC,CAwaxF"}
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/core/dev.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAe,MAAM,EAAE,MAAM,mBAAmB,CAAC;AA2B7D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;CACb;AA4SD,wBAAsB,eAAe,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,SAAS,CAAC,CA+axF"}
package/dist/core/dev.js CHANGED
@@ -291,7 +291,7 @@ export async function createDevServer(options = {}) {
291
291
  lastBuildError = error;
292
292
  };
293
293
  let watcher = null;
294
- let tsWatcher = null;
294
+ let tsWatchers = [];
295
295
  const isBuildingRef = { value: false };
296
296
  let isStopping = false;
297
297
  /**
@@ -523,15 +523,14 @@ export async function createDevServer(options = {}) {
523
523
  // TypeScript watcher setup (initial compilation is handled by performInitialBuild)
524
524
  if (config.typescript?.enabled) {
525
525
  try {
526
- // Start TypeScript watcher for hot reload
527
- tsWatcher = await createTypeScriptWatcher({
526
+ // Start TypeScript watchers for hot reload (one per bundle)
527
+ tsWatchers = await createTypeScriptWatcher({
528
528
  projectRoot: process.cwd(),
529
529
  config: config.typescript,
530
530
  outDir: config.outDir || DEFAULT_OUT_DIR,
531
- mode: 'development',
532
531
  logger,
533
- onRebuild: (bundlePath, compileTimeMs) => {
534
- logger.info?.(`⚡ ${bundlePath} recompiled in ${compileTimeMs}ms`);
532
+ onRebuild: (_results, compileTimeMs) => {
533
+ logger.info?.(`⚡ TypeScript recompiled in ${compileTimeMs}ms`);
535
534
  // Broadcast reload to WebSocket clients
536
535
  if (wsServer) {
537
536
  wsServer.clients.forEach((client) => {
@@ -599,10 +598,17 @@ export async function createDevServer(options = {}) {
599
598
  await watcher.close();
600
599
  watcher = null;
601
600
  }
602
- // Clean up TypeScript watcher
603
- if (tsWatcher) {
604
- await tsWatcher.dispose();
605
- tsWatcher = null;
601
+ // Clean up TypeScript watchers
602
+ if (tsWatchers.length > 0) {
603
+ await Promise.all(tsWatchers.map(async (w) => {
604
+ try {
605
+ await w.dispose();
606
+ }
607
+ catch (error) {
608
+ logger.warning(`Failed to dispose TypeScript watcher: ${error}`);
609
+ }
610
+ }));
611
+ tsWatchers = [];
606
612
  }
607
613
  if (wsServer) {
608
614
  wsServer.close();
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Bundle matching utilities for per-page TypeScript bundle targeting.
3
+ * Determines which bundles should be included on each page based on glob patterns.
4
+ * @module core/utils/bundle-matching
5
+ */
6
+ import type { BundleConfig } from '../../types/config.js';
7
+ /**
8
+ * Error thrown when bundle configuration contains duplicate bundleNames.
9
+ */
10
+ export declare class DuplicateBundleNameError extends Error {
11
+ constructor(duplicates: string[]);
12
+ }
13
+ /**
14
+ * Validates that all bundles have unique bundleNames.
15
+ * Throws DuplicateBundleNameError if duplicates are found.
16
+ *
17
+ * @param bundles - Array of bundle configurations to validate
18
+ * @throws {DuplicateBundleNameError} When duplicate bundleNames are detected
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * validateUniqueBundleNames([
23
+ * { entryPoint: 'core.ts', bundleName: 'core' },
24
+ * { entryPoint: 'docs.ts', bundleName: 'docs' }
25
+ * ]); // OK
26
+ *
27
+ * validateUniqueBundleNames([
28
+ * { entryPoint: 'a.ts', bundleName: 'main' },
29
+ * { entryPoint: 'b.ts', bundleName: 'main' }
30
+ * ]); // Throws DuplicateBundleNameError
31
+ * ```
32
+ */
33
+ export declare function validateUniqueBundleNames(bundles: BundleConfig[]): void;
34
+ /**
35
+ * Compiled bundle info with resolved paths for matched bundles.
36
+ * Used to track bundle metadata after compilation.
37
+ */
38
+ export interface CompiledBundleInfo {
39
+ /** The original bundle configuration */
40
+ config: BundleConfig;
41
+ /** The compiled bundle filename (e.g., 'core-a1b2c3d4.js') */
42
+ filename: string;
43
+ /** The full path to the bundle (e.g., '/_assets/core-a1b2c3d4.js') */
44
+ path: string;
45
+ }
46
+ /**
47
+ * Determines which bundles should be included on a specific page.
48
+ * Filters bundles based on their include/exclude glob patterns.
49
+ *
50
+ * Matching logic:
51
+ * 1. If no `include` patterns: bundle is global (matches all pages)
52
+ * 2. If `include` patterns exist: page must match at least one pattern
53
+ * 3. If page matches any `exclude` pattern: bundle is excluded (exclude takes precedence)
54
+ * 4. Bundle order from config is preserved
55
+ *
56
+ * @param pageOutputPath - The page's output URL path (e.g., '/docs/api/hooks.html')
57
+ * @param bundles - Array of bundle configurations to filter
58
+ * @returns Array of bundles that match this page, in config order
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * const bundles: BundleConfig[] = [
63
+ * { entryPoint: 'core.ts', bundleName: 'core' }, // global
64
+ * { entryPoint: 'docs.ts', bundleName: 'docs', include: ['/docs/**'] },
65
+ * { entryPoint: 'playground.ts', bundleName: 'playground', include: ['/examples/**'], exclude: ['/examples/simple/**'] }
66
+ * ];
67
+ *
68
+ * matchBundlesForPage('/docs/api/hooks.html', bundles);
69
+ * // Returns: [{ entryPoint: 'core.ts', ... }, { entryPoint: 'docs.ts', ... }]
70
+ *
71
+ * matchBundlesForPage('/examples/advanced/demo.html', bundles);
72
+ * // Returns: [{ entryPoint: 'core.ts', ... }, { entryPoint: 'playground.ts', ... }]
73
+ *
74
+ * matchBundlesForPage('/examples/simple/basic.html', bundles);
75
+ * // Returns: [{ entryPoint: 'core.ts', ... }] - playground excluded
76
+ * ```
77
+ */
78
+ export declare function matchBundlesForPage(pageOutputPath: string, bundles: BundleConfig[]): BundleConfig[];
79
+ /**
80
+ * Gets bundle paths for a page from compiled bundle info.
81
+ * Filters compiled bundles based on page matching and returns only the paths.
82
+ *
83
+ * @param pageOutputPath - The page's output URL path (e.g., '/docs/api/hooks.html')
84
+ * @param compiledBundles - Array of compiled bundle info
85
+ * @returns Array of bundle paths matched for this page, in config order
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * const compiled: CompiledBundleInfo[] = [
90
+ * { config: { entryPoint: 'core.ts', bundleName: 'core' }, filename: 'core-abc.js', path: '/_assets/core-abc.js' },
91
+ * { config: { entryPoint: 'docs.ts', bundleName: 'docs', include: ['/docs/**'] }, filename: 'docs-def.js', path: '/_assets/docs-def.js' }
92
+ * ];
93
+ *
94
+ * getBundlePathsForPage('/docs/api/hooks.html', compiled);
95
+ * // Returns: ['/_assets/core-abc.js', '/_assets/docs-def.js']
96
+ * ```
97
+ */
98
+ export declare function getBundlePathsForPage(pageOutputPath: string, compiledBundles: CompiledBundleInfo[]): string[];
99
+ //# sourceMappingURL=bundle-matching.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundle-matching.utils.d.ts","sourceRoot":"","sources":["../../../src/core/utils/bundle-matching.utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAG1D;;GAEG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;gBACrC,UAAU,EAAE,MAAM,EAAE;CAOjC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI,CAqBvE;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,wCAAwC;IACxC,MAAM,EAAE,YAAY,CAAC;IACrB,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,mBAAmB,CACjC,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,YAAY,EAAE,GACtB,YAAY,EAAE,CAyBhB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,qBAAqB,CACnC,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,kBAAkB,EAAE,GACpC,MAAM,EAAE,CAaV"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Bundle matching utilities for per-page TypeScript bundle targeting.
3
+ * Determines which bundles should be included on each page based on glob patterns.
4
+ * @module core/utils/bundle-matching
5
+ */
6
+ import { matchesGlob } from './glob-patterns.utils.js';
7
+ /**
8
+ * Error thrown when bundle configuration contains duplicate bundleNames.
9
+ */
10
+ export class DuplicateBundleNameError extends Error {
11
+ constructor(duplicates) {
12
+ super(`Duplicate bundleName(s) found in configuration: ${duplicates.join(', ')}. ` +
13
+ 'Each bundle must have a unique bundleName.');
14
+ this.name = 'DuplicateBundleNameError';
15
+ }
16
+ }
17
+ /**
18
+ * Validates that all bundles have unique bundleNames.
19
+ * Throws DuplicateBundleNameError if duplicates are found.
20
+ *
21
+ * @param bundles - Array of bundle configurations to validate
22
+ * @throws {DuplicateBundleNameError} When duplicate bundleNames are detected
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * validateUniqueBundleNames([
27
+ * { entryPoint: 'core.ts', bundleName: 'core' },
28
+ * { entryPoint: 'docs.ts', bundleName: 'docs' }
29
+ * ]); // OK
30
+ *
31
+ * validateUniqueBundleNames([
32
+ * { entryPoint: 'a.ts', bundleName: 'main' },
33
+ * { entryPoint: 'b.ts', bundleName: 'main' }
34
+ * ]); // Throws DuplicateBundleNameError
35
+ * ```
36
+ */
37
+ export function validateUniqueBundleNames(bundles) {
38
+ if (!bundles || bundles.length === 0) {
39
+ return;
40
+ }
41
+ const seen = new Set();
42
+ const duplicates = [];
43
+ for (const bundle of bundles) {
44
+ if (seen.has(bundle.bundleName)) {
45
+ if (!duplicates.includes(bundle.bundleName)) {
46
+ duplicates.push(bundle.bundleName);
47
+ }
48
+ }
49
+ else {
50
+ seen.add(bundle.bundleName);
51
+ }
52
+ }
53
+ if (duplicates.length > 0) {
54
+ throw new DuplicateBundleNameError(duplicates);
55
+ }
56
+ }
57
+ /**
58
+ * Determines which bundles should be included on a specific page.
59
+ * Filters bundles based on their include/exclude glob patterns.
60
+ *
61
+ * Matching logic:
62
+ * 1. If no `include` patterns: bundle is global (matches all pages)
63
+ * 2. If `include` patterns exist: page must match at least one pattern
64
+ * 3. If page matches any `exclude` pattern: bundle is excluded (exclude takes precedence)
65
+ * 4. Bundle order from config is preserved
66
+ *
67
+ * @param pageOutputPath - The page's output URL path (e.g., '/docs/api/hooks.html')
68
+ * @param bundles - Array of bundle configurations to filter
69
+ * @returns Array of bundles that match this page, in config order
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * const bundles: BundleConfig[] = [
74
+ * { entryPoint: 'core.ts', bundleName: 'core' }, // global
75
+ * { entryPoint: 'docs.ts', bundleName: 'docs', include: ['/docs/**'] },
76
+ * { entryPoint: 'playground.ts', bundleName: 'playground', include: ['/examples/**'], exclude: ['/examples/simple/**'] }
77
+ * ];
78
+ *
79
+ * matchBundlesForPage('/docs/api/hooks.html', bundles);
80
+ * // Returns: [{ entryPoint: 'core.ts', ... }, { entryPoint: 'docs.ts', ... }]
81
+ *
82
+ * matchBundlesForPage('/examples/advanced/demo.html', bundles);
83
+ * // Returns: [{ entryPoint: 'core.ts', ... }, { entryPoint: 'playground.ts', ... }]
84
+ *
85
+ * matchBundlesForPage('/examples/simple/basic.html', bundles);
86
+ * // Returns: [{ entryPoint: 'core.ts', ... }] - playground excluded
87
+ * ```
88
+ */
89
+ export function matchBundlesForPage(pageOutputPath, bundles) {
90
+ if (!bundles || bundles.length === 0) {
91
+ return [];
92
+ }
93
+ // Normalize path to use forward slashes
94
+ const normalizedPath = pageOutputPath.replace(/\\/g, '/');
95
+ return bundles.filter((bundle) => {
96
+ // Check exclude patterns first (they take precedence)
97
+ if (bundle.exclude && bundle.exclude.length > 0) {
98
+ const matchesExclude = bundle.exclude.some((pattern) => matchesGlob(normalizedPath, pattern));
99
+ if (matchesExclude) {
100
+ return false;
101
+ }
102
+ }
103
+ // If no include patterns, bundle is global (matches all pages)
104
+ if (!bundle.include || bundle.include.length === 0) {
105
+ return true;
106
+ }
107
+ // Check if page matches any include pattern
108
+ return bundle.include.some((pattern) => matchesGlob(normalizedPath, pattern));
109
+ });
110
+ }
111
+ /**
112
+ * Gets bundle paths for a page from compiled bundle info.
113
+ * Filters compiled bundles based on page matching and returns only the paths.
114
+ *
115
+ * @param pageOutputPath - The page's output URL path (e.g., '/docs/api/hooks.html')
116
+ * @param compiledBundles - Array of compiled bundle info
117
+ * @returns Array of bundle paths matched for this page, in config order
118
+ *
119
+ * @example
120
+ * ```typescript
121
+ * const compiled: CompiledBundleInfo[] = [
122
+ * { config: { entryPoint: 'core.ts', bundleName: 'core' }, filename: 'core-abc.js', path: '/_assets/core-abc.js' },
123
+ * { config: { entryPoint: 'docs.ts', bundleName: 'docs', include: ['/docs/**'] }, filename: 'docs-def.js', path: '/_assets/docs-def.js' }
124
+ * ];
125
+ *
126
+ * getBundlePathsForPage('/docs/api/hooks.html', compiled);
127
+ * // Returns: ['/_assets/core-abc.js', '/_assets/docs-def.js']
128
+ * ```
129
+ */
130
+ export function getBundlePathsForPage(pageOutputPath, compiledBundles) {
131
+ if (!compiledBundles || compiledBundles.length === 0) {
132
+ return [];
133
+ }
134
+ const matchedConfigs = matchBundlesForPage(pageOutputPath, compiledBundles.map((b) => b.config));
135
+ // Map matched configs back to their paths, preserving order
136
+ const matchedNames = new Set(matchedConfigs.map((c) => c.bundleName));
137
+ return compiledBundles.filter((b) => matchedNames.has(b.config.bundleName)).map((b) => b.path);
138
+ }
@@ -18,7 +18,9 @@ export { createErrorOverlay, parseErrorDetails } from './error-overlay.utils.js'
18
18
  export type { ErrorDetails } from './error-overlay.utils.js';
19
19
  export { getStatiVersion } from './version.utils.js';
20
20
  export { globToRegex, matchesGlob } from './glob-patterns.utils.js';
21
+ export { matchBundlesForPage, getBundlePathsForPage, validateUniqueBundleNames, DuplicateBundleNameError, } from './bundle-matching.utils.js';
22
+ export type { CompiledBundleInfo } from './bundle-matching.utils.js';
21
23
  export { createFallbackLogger } from './logger.utils.js';
22
- export { compileTypeScript, createTypeScriptWatcher, compileStatiConfig, cleanupCompiledConfig, autoInjectBundle, } from './typescript.utils.js';
23
- export type { CompileOptions, CompileResult, WatchOptions } from './typescript.utils.js';
24
+ export { compileTypeScript, createTypeScriptWatcher, compileStatiConfig, cleanupCompiledConfig, autoInjectBundles, } from './typescript.utils.js';
25
+ export type { CompileOptions, WatchOptions } from './typescript.utils.js';
24
26
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/utils/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACL,QAAQ,EACR,SAAS,EACT,UAAU,EACV,SAAS,EACT,MAAM,EACN,QAAQ,EACR,OAAO,EACP,IAAI,GACL,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGhD,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,2BAA2B,EAC3B,cAAc,EACd,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAC;AAG9E,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAC3F,YAAY,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAGpE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAG/F,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAGxE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACzE,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACjF,YAAY,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAGrD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAGzD,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,kBAAkB,EAClB,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/utils/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACL,QAAQ,EACR,SAAS,EACT,UAAU,EACV,SAAS,EACT,MAAM,EACN,QAAQ,EACR,OAAO,EACP,IAAI,GACL,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGhD,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,2BAA2B,EAC3B,cAAc,EACd,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAC;AAG9E,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAC3F,YAAY,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAGpE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAG/F,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAGxE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACzE,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACjF,YAAY,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAGrD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGpE,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAGrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAGzD,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC"}
@@ -28,7 +28,9 @@ export { createErrorOverlay, parseErrorDetails } from './error-overlay.utils.js'
28
28
  export { getStatiVersion } from './version.utils.js';
29
29
  // Glob pattern utilities
30
30
  export { globToRegex, matchesGlob } from './glob-patterns.utils.js';
31
+ // Bundle matching utilities
32
+ export { matchBundlesForPage, getBundlePathsForPage, validateUniqueBundleNames, DuplicateBundleNameError, } from './bundle-matching.utils.js';
31
33
  // Logger utilities
32
34
  export { createFallbackLogger } from './logger.utils.js';
33
35
  // TypeScript compilation utilities
34
- export { compileTypeScript, createTypeScriptWatcher, compileStatiConfig, cleanupCompiledConfig, autoInjectBundle, } from './typescript.utils.js';
36
+ export { compileTypeScript, createTypeScriptWatcher, compileStatiConfig, cleanupCompiledConfig, autoInjectBundles, } from './typescript.utils.js';
@@ -1,9 +1,11 @@
1
1
  /**
2
2
  * TypeScript compilation utilities using esbuild.
3
3
  * Provides functions for compiling TypeScript files and watching for changes.
4
+ * Supports multiple bundles with per-page targeting.
4
5
  * @module core/utils/typescript
5
6
  */
6
7
  import * as esbuild from 'esbuild';
8
+ import { type CompiledBundleInfo } from './bundle-matching.utils.js';
7
9
  import type { TypeScriptConfig } from '../../types/config.js';
8
10
  import type { Logger } from '../../types/logging.js';
9
11
  /**
@@ -21,71 +23,69 @@ export interface CompileOptions {
21
23
  /** Logger instance for output */
22
24
  logger: Logger;
23
25
  }
24
- /**
25
- * Result of TypeScript compilation.
26
- */
27
- export interface CompileResult {
28
- /** The generated bundle filename (e.g., 'bundle-a1b2c3d4.js'), or undefined if compilation was skipped */
29
- bundleFilename?: string;
30
- }
31
26
  /**
32
27
  * Options for TypeScript file watcher.
28
+ * Note: Watcher is always in development mode (no hash, no minify, with sourcemaps).
33
29
  */
34
30
  export interface WatchOptions {
35
- /** Project root directory */
31
+ /** Root directory of the project */
36
32
  projectRoot: string;
37
33
  /** TypeScript configuration */
38
34
  config: TypeScriptConfig;
39
- /** Output directory for the build */
35
+ /** Output directory (defaults to 'dist') */
40
36
  outDir?: string;
41
- /** Build mode */
42
- mode: 'development' | 'production';
43
- /** Logger instance */
37
+ /** Logger instance for output */
44
38
  logger: Logger;
45
- /** Callback when rebuild completes, receives bundle path and compile time in ms */
46
- onRebuild: (bundlePath: string, compileTimeMs: number) => void;
39
+ /** Callback invoked when files are recompiled, receives results and compile time in ms */
40
+ onRebuild: (results: CompiledBundleInfo[], compileTimeMs: number) => void;
47
41
  }
48
42
  /**
49
43
  * Compile TypeScript files using esbuild.
50
- * Returns the generated bundle filename for template injection.
44
+ * Supports multiple bundles with parallel compilation.
51
45
  *
52
46
  * @param options - Compilation options
53
- * @returns The compilation result with bundle filename
47
+ * @returns Array of compilation results for each bundle
54
48
  *
55
49
  * @example
56
50
  * ```typescript
57
- * const result = await compileTypeScript({
51
+ * const results = await compileTypeScript({
58
52
  * projectRoot: process.cwd(),
59
- * config: { enabled: true },
53
+ * config: {
54
+ * enabled: true,
55
+ * bundles: [
56
+ * { entryPoint: 'core.ts', bundleName: 'core' },
57
+ * { entryPoint: 'docs.ts', bundleName: 'docs', include: ['/docs/**'] }
58
+ * ]
59
+ * },
60
60
  * mode: 'production',
61
61
  * logger: console,
62
62
  * });
63
- * console.log(result.bundleFilename); // 'bundle-a1b2c3d4.js'
63
+ * console.log(results[0].bundlePath); // '/_assets/core-a1b2c3d4.js'
64
64
  * ```
65
65
  */
66
- export declare function compileTypeScript(options: CompileOptions): Promise<CompileResult>;
66
+ export declare function compileTypeScript(options: CompileOptions): Promise<CompiledBundleInfo[]>;
67
67
  /**
68
68
  * Create an esbuild watch context for development.
69
69
  * Watches for TypeScript file changes and recompiles automatically.
70
+ * Supports multiple bundles with selective recompilation.
70
71
  *
71
72
  * @param options - Watch options including rebuild callback
72
- * @returns The esbuild build context for cleanup
73
+ * @returns Array of esbuild build contexts for cleanup
73
74
  *
74
75
  * @example
75
76
  * ```typescript
76
- * const watcher = await createTypeScriptWatcher({
77
+ * const watchers = await createTypeScriptWatcher({
77
78
  * projectRoot: process.cwd(),
78
79
  * config: { enabled: true },
79
- * mode: 'development',
80
80
  * logger: console,
81
- * onRebuild: () => console.log('Rebuilt!'),
81
+ * onRebuild: (results, compileTimeMs) => console.log(`Rebuilt ${results.length} bundles in ${compileTimeMs}ms`),
82
82
  * });
83
83
  *
84
84
  * // Later, cleanup:
85
- * await watcher.dispose();
85
+ * await Promise.all(watchers.map(w => w.dispose()));
86
86
  * ```
87
87
  */
88
- export declare function createTypeScriptWatcher(options: WatchOptions): Promise<esbuild.BuildContext>;
88
+ export declare function createTypeScriptWatcher(options: WatchOptions): Promise<esbuild.BuildContext[]>;
89
89
  /**
90
90
  * Compile stati.config.ts to a temporary JS file for import.
91
91
  * Returns the path to the compiled file.
@@ -108,20 +108,32 @@ export declare function compileStatiConfig(configPath: string): Promise<string>;
108
108
  */
109
109
  export declare function cleanupCompiledConfig(compiledPath: string): Promise<void>;
110
110
  /**
111
- * Auto-inject TypeScript bundle script tag into HTML before </body>.
112
- * Similar to SEO auto-injection, this adds the script tag automatically
111
+ * Validates a bundle path for safety against XSS attacks.
112
+ * Only allows safe ASCII characters: alphanumeric, hyphens, underscores, dots, and forward slashes.
113
+ * Must start with / and end with .js, no encoded characters or unicode allowed.
114
+ *
115
+ * @param bundlePath - The bundle path to validate
116
+ * @returns true if the path is safe, false otherwise
117
+ *
118
+ * @internal
119
+ */
120
+ export declare function isValidBundlePath(bundlePath: string): boolean;
121
+ /**
122
+ * Auto-inject TypeScript bundle script tags into HTML before </body>.
123
+ * Similar to SEO auto-injection, this adds script tags automatically
113
124
  * so users don't need to modify their templates.
125
+ * Supports multiple bundles - injects all matched bundles in order.
114
126
  *
115
127
  * @param html - Rendered HTML content
116
- * @param bundlePath - Path to the compiled bundle (e.g., '/_assets/bundle-a1b2c3d4.js')
117
- * @returns HTML with injected script tag
128
+ * @param bundlePaths - Array of paths to compiled bundles (e.g., ['/_assets/core.js', '/_assets/docs.js'])
129
+ * @returns HTML with injected script tags
118
130
  *
119
131
  * @example
120
132
  * ```typescript
121
133
  * const html = '<html><body>Content</body></html>';
122
- * const enhanced = autoInjectBundle(html, '/_assets/bundle.js');
123
- * // Returns: '<html><body>Content\n <script type="module" src="/_assets/bundle.js"></script>\n</body></html>'
134
+ * const enhanced = autoInjectBundles(html, ['/_assets/core.js', '/_assets/docs.js']);
135
+ * // Returns HTML with both script tags injected before </body>
124
136
  * ```
125
137
  */
126
- export declare function autoInjectBundle(html: string, bundlePath: string): string;
138
+ export declare function autoInjectBundles(html: string, bundlePaths: string[]): string;
127
139
  //# sourceMappingURL=typescript.utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"typescript.utils.d.ts","sourceRoot":"","sources":["../../../src/core/utils/typescript.utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAInC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AASrD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,oCAAoC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,MAAM,EAAE,gBAAgB,CAAC;IACzB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uBAAuB;IACvB,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,0GAA0G;IAC1G,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,MAAM,EAAE,gBAAgB,CAAC;IACzB,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iBAAiB;IACjB,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,mFAAmF;IACnF,SAAS,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;CAChE;AAiCD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CA+CvF;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAsD/B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgB5E;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM/E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAsCzE"}
1
+ {"version":3,"file":"typescript.utils.d.ts","sourceRoot":"","sources":["../../../src/core/utils/typescript.utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAInC,OAAO,EAA6B,KAAK,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChG,OAAO,KAAK,EAAE,gBAAgB,EAAgB,MAAM,uBAAuB,CAAC;AAC5E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAQrD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,oCAAoC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,MAAM,EAAE,gBAAgB,CAAC;IACzB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uBAAuB;IACvB,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,oCAAoC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,MAAM,EAAE,gBAAgB,CAAC;IACzB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,0FAA0F;IAC1F,SAAS,EAAE,CAAC,OAAO,EAAE,kBAAkB,EAAE,EAAE,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3E;AAmGD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAuC9F;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAqFjC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgB5E;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM/E;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAqC7D;AAiBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,CA8B7E"}