rebuildjs 0.71.0 → 0.71.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rebuildjs",
3
- "version": "0.71.0",
3
+ "version": "0.71.1",
4
4
  "description": "Reactive esbuild...simple hackable alternative to vite for Multi Page Apps",
5
5
  "keywords": [
6
6
  "reactive",
@@ -29,6 +29,7 @@ export declare function rebuildjs__ready__wait(timeout?:number):rmemo__wait_ret_
29
29
  export declare function rebuildjs_browser__build(config?:rebuildjs_build_config_T):Promise<BuildContext|undefined>
30
30
  export declare function rebuildjs_server__build(config?:rebuildjs_build_config_T):Promise<BuildContext|undefined>
31
31
  export declare function server__external_(config?:Partial<BuildOptions>):Promise<string[]>
32
+ export declare function ts_resolve_node_modules_plugin_():Plugin
32
33
  export declare function rebuildjs_plugin_():Plugin
33
34
  export declare function cssBundle__annotate(cssBundle:string, suffix?:string):string
34
35
  export declare function server__metafile__update(
@@ -43,5 +44,9 @@ export type rebuildjs_build_config_T =
43
44
  Partial<BuildOptions>&{ rebuildjs?:rebuildjs_plugin_config_T }
44
45
  export type rebuildjs_plugin_config_T = {
45
46
  watch?:boolean
47
+ /** External directories to watch for file changes during dev mode.
48
+ * When a file in these directories changes, esbuild triggers a rebuild.
49
+ * Useful for watching source files from other monorepos (e.g., rappstack-dev). */
50
+ watch_dirs?:string[]
46
51
  }
47
52
  export type rebuildjs__ready__add__ready$__T = ctx__be_T<rmemo_T<boolean>, 'app'>
@@ -20,7 +20,7 @@ import {
20
20
  import { short_uuid_ } from 'ctx-core/uuid'
21
21
  import { build, context } from 'esbuild'
22
22
  import { fdir } from 'fdir'
23
- import { cp, link, mkdir, readFile, rm } from 'node:fs/promises'
23
+ import { cp, link, mkdir, readFile, rm, watch } from 'node:fs/promises'
24
24
  import { basename, dirname, extname, join, relative, resolve } from 'node:path'
25
25
  import {
26
26
  app_path_,
@@ -264,7 +264,7 @@ export async function rebuildjs_browser__build(config) {
264
264
  entryPoints.push(path)
265
265
  }
266
266
  const external = [dist_path_(app_ctx) + '/*', ...(esbuild__config.external ?? [])]
267
- const plugins = [rebuildjs_plugin_(), ...(esbuild__config.plugins ?? [])]
267
+ const plugins = [ts_resolve_node_modules_plugin_(), rebuildjs_plugin_(), ...(esbuild__config.plugins ?? [])]
268
268
  /** @type {import('esbuild').BuildOptions} */
269
269
  const esbuild_config = {
270
270
  entryNames: '[name]-[hash]',
@@ -290,6 +290,9 @@ export async function rebuildjs_browser__build(config) {
290
290
  if (rebuildjs?.watch ?? !is_prod_(app_ctx)) {
291
291
  const esbuild_ctx = await context(esbuild_config)
292
292
  await esbuild_ctx.watch()
293
+ if (rebuildjs?.watch_dirs?.length) {
294
+ watch_dirs__start(esbuild_ctx, rebuildjs.watch_dirs, 'browser')
295
+ }
293
296
  console.log('browser__build|watch')
294
297
  return esbuild_ctx
295
298
  } else {
@@ -326,7 +329,7 @@ export async function rebuildjs_server__build(config) {
326
329
  entryPoints.push(path)
327
330
  }
328
331
  const external = [dist_path_(app_ctx) + '/*', ...server__external_(esbuild__config)]
329
- const plugins = [rebuildjs_plugin_(), ...(esbuild__config.plugins || [])]
332
+ const plugins = [ts_resolve_node_modules_plugin_(), rebuildjs_plugin_(), ...(esbuild__config.plugins || [])]
330
333
  const esbuild_config = {
331
334
  entryNames: '[name]-[hash]',
332
335
  assetNames: '[name]-[hash]',
@@ -351,6 +354,9 @@ export async function rebuildjs_server__build(config) {
351
354
  if (rebuildjs?.watch ?? !is_prod_(app_ctx)) {
352
355
  const esbuild_ctx = await context(esbuild_config)
353
356
  await esbuild_ctx.watch()
357
+ if (rebuildjs?.watch_dirs?.length) {
358
+ watch_dirs__start(esbuild_ctx, rebuildjs.watch_dirs, 'server')
359
+ }
354
360
  console.log('server__build|watch')
355
361
  return esbuild_ctx
356
362
  } else {
@@ -361,6 +367,41 @@ export async function rebuildjs_server__build(config) {
361
367
  return undefined
362
368
  }
363
369
  }
370
+ /**
371
+ * Watch external directories and trigger esbuild rebuild on file changes.
372
+ * Used to watch source files from other monorepos (e.g., rappstack-dev)
373
+ * that aren't in the esbuild module graph.
374
+ * @param {import('esbuild').BuildContext} esbuild_ctx
375
+ * @param {string[]} dirs
376
+ * @param {string} label
377
+ */
378
+ function watch_dirs__start(esbuild_ctx, dirs, label) {
379
+ let rebuild_timer = null
380
+ for (const dir of dirs) {
381
+ ;(async ()=>{
382
+ try {
383
+ const watcher = watch(dir, { recursive: true })
384
+ for await (const event of watcher) {
385
+ if (!event.filename) continue
386
+ if (!/\.(ts|tsx|js|jsx|css)$/.test(event.filename)) continue
387
+ // Debounce: wait 100ms for batch changes
388
+ if (rebuild_timer) clearTimeout(rebuild_timer)
389
+ rebuild_timer = setTimeout(async ()=>{
390
+ rebuild_timer = null
391
+ console.log(`watch_dirs|${label}|rebuild`, event.filename)
392
+ try {
393
+ await esbuild_ctx.rebuild()
394
+ } catch (err) {
395
+ console.error(`watch_dirs|${label}|rebuild|error`, err.message)
396
+ }
397
+ }, 100)
398
+ }
399
+ } catch (err) {
400
+ console.error(`watch_dirs|${label}|watch|error`, dir, err.message)
401
+ }
402
+ })()
403
+ }
404
+ }
364
405
  /**
365
406
  * @param {rebuildjs_build_config_T}[config]
366
407
  * @returns {Promise<string[]>}
@@ -368,6 +409,32 @@ export async function rebuildjs_server__build(config) {
368
409
  export function server__external_(config) {
369
410
  return ['bun', 'node_modules/*', ...(config.external || [])]
370
411
  }
412
+ /**
413
+ * esbuild plugin that resolves `.ts` files from node_modules package exports.
414
+ * esbuild 0.27+ blocks `.ts` resolution from node_modules by default.
415
+ * This plugin intercepts bare specifier imports (e.g. `@rappstack/ui--server/css`)
416
+ * and resolves them through bun's module resolution, allowing `.ts` targets.
417
+ * @returns {import('esbuild').Plugin}
418
+ */
419
+ export function ts_resolve_node_modules_plugin_() {
420
+ return {
421
+ name: 'ts_resolve_node_modules',
422
+ setup(build) {
423
+ const absWorkingDir = build.initialOptions.absWorkingDir || process.cwd()
424
+ build.onResolve({ filter: /^[^./]/ }, async (args)=>{
425
+ if (args.pluginData?.fromTsResolve) return
426
+ try {
427
+ const resolved = Bun.resolveSync(args.path, absWorkingDir)
428
+ if (resolved && (resolved.endsWith('.ts') || resolved.endsWith('.tsx'))) {
429
+ return { path: resolved }
430
+ }
431
+ } catch {
432
+ // Let esbuild handle the resolution
433
+ }
434
+ })
435
+ }
436
+ }
437
+ }
371
438
  /**
372
439
  * @returns {import('esbuild').Plugin}
373
440
  * @private