@barefootjs/hono 0.1.3 → 0.3.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.
@@ -1 +1 @@
1
- {"version":3,"file":"hono-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/hono-adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hono-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/hono-adapter.ts"],"names":[],"mappings":"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"}
@@ -447,14 +447,24 @@ export default ${this.componentName}` : "";
447
447
  if (loop.bodyIsMultiRoot) {
448
448
  safeChildren = `<>{bfComment('bf-loop-i')}${children}</>`;
449
449
  }
450
- const chainedArray = applyHonoLoopChain(loop);
450
+ let chainedArray = applyHonoLoopChain(loop);
451
451
  const iterMethod = loop.method ?? "map";
452
+ let callbackParam;
453
+ if (loop.iterationShape === "entries" && loop.index) {
454
+ chainedArray = `[...${chainedArray}.entries()]`;
455
+ callbackParam = `([${loop.index}${indexAnnotation}, ${loop.param}${paramAnnotation}])`;
456
+ } else if (loop.iterationShape === "keys") {
457
+ chainedArray = `[...${chainedArray}.keys()]`;
458
+ callbackParam = `(${loop.param}${paramAnnotation})`;
459
+ } else {
460
+ callbackParam = `(${loop.param}${paramAnnotation}${indexParam})`;
461
+ }
452
462
  if (loop.flatMapCallback) {
453
463
  mapExpr = `{${chainedArray}.flatMap(${loop.flatMapCallback.params} => ${loop.flatMapCallback.rawBody})}`;
454
464
  } else if (preamble) {
455
- mapExpr = `{${chainedArray}.${iterMethod}((${loop.param}${paramAnnotation}${indexParam}) => { ${preamble} return ${safeChildren} })}`;
465
+ mapExpr = `{${chainedArray}.${iterMethod}(${callbackParam} => { ${preamble} return ${safeChildren} })}`;
456
466
  } else {
457
- mapExpr = `{${chainedArray}.${iterMethod}((${loop.param}${paramAnnotation}${indexParam}) => ${safeChildren})}`;
467
+ mapExpr = `{${chainedArray}.${iterMethod}(${callbackParam} => ${safeChildren})}`;
458
468
  }
459
469
  return `{bfComment('loop:${loop.markerId}')}${mapExpr}{bfComment('/loop:${loop.markerId}')}`;
460
470
  }
package/dist/app.d.ts CHANGED
@@ -63,14 +63,48 @@ export interface BarefootBuildManifest {
63
63
  */
64
64
  export declare function manifestToScriptUrls(manifest: BarefootBuildManifest, base: string): string[];
65
65
  export declare function relPathFromComponentsBase(p: string): string;
66
+ /**
67
+ * Shape of `barefoot-externals.json`, written by `bf build` when
68
+ * `externals` / `bundleEntries` are configured. Only the fields
69
+ * `BfImportMap` consumes are typed here; the build also emits an
70
+ * `externals` array (the `--external` list) which the importmap
71
+ * doesn't need. Fields are optional so a partial/hand-written
72
+ * manifest still type-checks. See issue #1639.
73
+ */
74
+ export interface BarefootExternalsManifest {
75
+ /** Entries for the `<script type="importmap">`. */
76
+ importmap?: {
77
+ imports?: Record<string, string>;
78
+ };
79
+ /** URLs to emit as `<link rel="modulepreload">`. */
80
+ preloads?: string[];
81
+ }
66
82
  export interface BfImportMapProps {
67
83
  /** Base URL where the runtime + component bundles are served. */
68
84
  base: string;
85
+ /**
86
+ * Contents of `barefoot-externals.json` (import it and pass it
87
+ * through). Its `importmap.imports` are merged on top of the
88
+ * built-in `@barefootjs/client*` mappings so islands importing
89
+ * configured externals (e.g. `zod`, `@barefootjs/form`) resolve in
90
+ * the browser. When omitted, only the `@barefootjs/client*`
91
+ * mappings are emitted — the pre-#1639 behavior.
92
+ */
93
+ externals?: BarefootExternalsManifest;
94
+ /**
95
+ * Whether to also emit `<link rel="modulepreload">` for the
96
+ * manifest's `preloads`. Defaults to `true`; set `false` to emit
97
+ * the importmap only.
98
+ */
99
+ preload?: boolean;
69
100
  }
70
101
  /**
71
102
  * Emits the `<script type="importmap">` that maps the bare
72
103
  * `@barefootjs/client` / `@barefootjs/client/runtime` specifiers to
73
- * the runtime bundle. Place in `<head>`.
104
+ * the runtime bundle, plus any externals from `barefoot-externals.json`
105
+ * passed via the `externals` prop. Also emits `<link rel="modulepreload">`
106
+ * for the manifest's `preloads` unless `preload` is `false`. Place in
107
+ * `<head>`.
74
108
  */
75
109
  export declare function BfImportMap(props: BfImportMapProps): HtmlEscapedString | Promise<HtmlEscapedString>;
76
110
  export interface BfScriptsProps {
package/dist/app.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAA;AAE7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAQxD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,qBAAqB;IACpC,YAAY,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACpC,CAAC,aAAa,EAAE,MAAM,GAAG;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,SAAS,CAAA;CAChF;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,qBAAqB,EAC/B,IAAI,EAAE,MAAM,GACX,MAAM,EAAE,CAWV;AAED,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE3D;AAID,MAAM,WAAW,gBAAgB;IAC/B,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAA;CACb;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CASnG;AAED,MAAM,WAAW,cAAc;IAC7B,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAA;IACZ,6DAA6D;IAC7D,QAAQ,EAAE,qBAAqB,CAAA;CAChC;AAQD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAa/F;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,GAAE,gBAAqB,GAAG,iBAAiB,GAAG,IAAI,CAelF;AAID,MAAM,WAAW,wBAAwB;IACvC,yBAAyB;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;;;OAMG;IACH,OAAO,EAAE,OAAO,CAAA;CACjB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,wBAAwB,GAAG,iBAAiB,CAanF"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAA;AAE7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAQxD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,qBAAqB;IACpC,YAAY,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACpC,CAAC,aAAa,EAAE,MAAM,GAAG;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,SAAS,CAAA;CAChF;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,qBAAqB,EAC/B,IAAI,EAAE,MAAM,GACX,MAAM,EAAE,CAWV;AAED,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE3D;AAID;;;;;;;GAOG;AACH,MAAM,WAAW,yBAAyB;IACxC,mDAAmD;IACnD,SAAS,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAA;IAChD,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAA;IACZ;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,yBAAyB,CAAA;IACrC;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAkBnG;AAOD,MAAM,WAAW,cAAc;IAC7B,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAA;IACZ,6DAA6D;IAC7D,QAAQ,EAAE,qBAAqB,CAAA;CAChC;AAQD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAa/F;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,GAAE,gBAAqB,GAAG,iBAAiB,GAAG,IAAI,CAelF;AAID,MAAM,WAAW,wBAAwB;IACvC,yBAAyB;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;;;OAMG;IACH,OAAO,EAAE,OAAO,CAAA;CACjB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,wBAAwB,GAAG,iBAAiB,CAanF"}
package/dist/app.js CHANGED
@@ -84,13 +84,18 @@ function relPathFromComponentsBase(p) {
84
84
  }
85
85
  function BfImportMap(props) {
86
86
  const base = props.base.replace(/\/$/, "");
87
- const json = JSON.stringify({
88
- imports: {
89
- "@barefootjs/client": `${base}/barefoot.js`,
90
- "@barefootjs/client/runtime": `${base}/barefoot.js`
91
- }
92
- });
93
- return html`<script type="importmap">${raw(json)}</script>`;
87
+ const imports = {
88
+ "@barefootjs/client": `${base}/barefoot.js`,
89
+ "@barefootjs/client/runtime": `${base}/barefoot.js`,
90
+ ...props.externals?.importmap?.imports ?? {}
91
+ };
92
+ const json = JSON.stringify({ imports });
93
+ const preloads = props.preload === false ? [] : props.externals?.preloads ?? [];
94
+ const links = preloads.map((href) => `<link rel="modulepreload" href="${escapeAttr(href)}">`).join("");
95
+ return html`<script type="importmap">${raw(json)}</script>${raw(links)}`;
96
+ }
97
+ function escapeAttr(value) {
98
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;");
94
99
  }
95
100
  var __bfEmptyManifestWarned = false;
96
101
  function BfScripts(props) {
package/dist/build.js CHANGED
@@ -447,14 +447,24 @@ export default ${this.componentName}` : "";
447
447
  if (loop.bodyIsMultiRoot) {
448
448
  safeChildren = `<>{bfComment('bf-loop-i')}${children}</>`;
449
449
  }
450
- const chainedArray = applyHonoLoopChain(loop);
450
+ let chainedArray = applyHonoLoopChain(loop);
451
451
  const iterMethod = loop.method ?? "map";
452
+ let callbackParam;
453
+ if (loop.iterationShape === "entries" && loop.index) {
454
+ chainedArray = `[...${chainedArray}.entries()]`;
455
+ callbackParam = `([${loop.index}${indexAnnotation}, ${loop.param}${paramAnnotation}])`;
456
+ } else if (loop.iterationShape === "keys") {
457
+ chainedArray = `[...${chainedArray}.keys()]`;
458
+ callbackParam = `(${loop.param}${paramAnnotation})`;
459
+ } else {
460
+ callbackParam = `(${loop.param}${paramAnnotation}${indexParam})`;
461
+ }
452
462
  if (loop.flatMapCallback) {
453
463
  mapExpr = `{${chainedArray}.flatMap(${loop.flatMapCallback.params} => ${loop.flatMapCallback.rawBody})}`;
454
464
  } else if (preamble) {
455
- mapExpr = `{${chainedArray}.${iterMethod}((${loop.param}${paramAnnotation}${indexParam}) => { ${preamble} return ${safeChildren} })}`;
465
+ mapExpr = `{${chainedArray}.${iterMethod}(${callbackParam} => { ${preamble} return ${safeChildren} })}`;
456
466
  } else {
457
- mapExpr = `{${chainedArray}.${iterMethod}((${loop.param}${paramAnnotation}${indexParam}) => ${safeChildren})}`;
467
+ mapExpr = `{${chainedArray}.${iterMethod}(${callbackParam} => ${safeChildren})}`;
458
468
  }
459
469
  return `{bfComment('loop:${loop.markerId}')}${mapExpr}{bfComment('/loop:${loop.markerId}')}`;
460
470
  }
package/dist/index.js CHANGED
@@ -447,14 +447,24 @@ export default ${this.componentName}` : "";
447
447
  if (loop.bodyIsMultiRoot) {
448
448
  safeChildren = `<>{bfComment('bf-loop-i')}${children}</>`;
449
449
  }
450
- const chainedArray = applyHonoLoopChain(loop);
450
+ let chainedArray = applyHonoLoopChain(loop);
451
451
  const iterMethod = loop.method ?? "map";
452
+ let callbackParam;
453
+ if (loop.iterationShape === "entries" && loop.index) {
454
+ chainedArray = `[...${chainedArray}.entries()]`;
455
+ callbackParam = `([${loop.index}${indexAnnotation}, ${loop.param}${paramAnnotation}])`;
456
+ } else if (loop.iterationShape === "keys") {
457
+ chainedArray = `[...${chainedArray}.keys()]`;
458
+ callbackParam = `(${loop.param}${paramAnnotation})`;
459
+ } else {
460
+ callbackParam = `(${loop.param}${paramAnnotation}${indexParam})`;
461
+ }
452
462
  if (loop.flatMapCallback) {
453
463
  mapExpr = `{${chainedArray}.flatMap(${loop.flatMapCallback.params} => ${loop.flatMapCallback.rawBody})}`;
454
464
  } else if (preamble) {
455
- mapExpr = `{${chainedArray}.${iterMethod}((${loop.param}${paramAnnotation}${indexParam}) => { ${preamble} return ${safeChildren} })}`;
465
+ mapExpr = `{${chainedArray}.${iterMethod}(${callbackParam} => { ${preamble} return ${safeChildren} })}`;
456
466
  } else {
457
- mapExpr = `{${chainedArray}.${iterMethod}((${loop.param}${paramAnnotation}${indexParam}) => ${safeChildren})}`;
467
+ mapExpr = `{${chainedArray}.${iterMethod}(${callbackParam} => ${safeChildren})}`;
458
468
  }
459
469
  return `{bfComment('loop:${loop.markerId}')}${mapExpr}{bfComment('/loop:${loop.markerId}')}`;
460
470
  }
package/dist/scripts.js CHANGED
@@ -84,13 +84,18 @@ function relPathFromComponentsBase(p) {
84
84
  }
85
85
  function BfImportMap(props) {
86
86
  const base = props.base.replace(/\/$/, "");
87
- const json = JSON.stringify({
88
- imports: {
89
- "@barefootjs/client": `${base}/barefoot.js`,
90
- "@barefootjs/client/runtime": `${base}/barefoot.js`
91
- }
92
- });
93
- return html`<script type="importmap">${raw(json)}</script>`;
87
+ const imports = {
88
+ "@barefootjs/client": `${base}/barefoot.js`,
89
+ "@barefootjs/client/runtime": `${base}/barefoot.js`,
90
+ ...props.externals?.importmap?.imports ?? {}
91
+ };
92
+ const json = JSON.stringify({ imports });
93
+ const preloads = props.preload === false ? [] : props.externals?.preloads ?? [];
94
+ const links = preloads.map((href) => `<link rel="modulepreload" href="${escapeAttr(href)}">`).join("");
95
+ return html`<script type="importmap">${raw(json)}</script>${raw(links)}`;
96
+ }
97
+ function escapeAttr(value) {
98
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;");
94
99
  }
95
100
  var __bfEmptyManifestWarned = false;
96
101
  function BfScripts(props) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barefootjs/hono",
3
- "version": "0.1.3",
3
+ "version": "0.3.0",
4
4
  "description": "Hono integration for BarefootJS",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -101,9 +101,9 @@
101
101
  "directory": "packages/adapter-hono"
102
102
  },
103
103
  "peerDependencies": {
104
- "@barefootjs/client": "0.1.3",
105
- "@barefootjs/jsx": "0.1.3",
106
- "@barefootjs/shared": "0.1.3",
104
+ "@barefootjs/client": ">=0.2.0",
105
+ "@barefootjs/jsx": ">=0.2.0",
106
+ "@barefootjs/shared": ">=0.2.0",
107
107
  "hono": "^4.0.0"
108
108
  },
109
109
  "devDependencies": {
@@ -0,0 +1,88 @@
1
+ /**
2
+ * BfImportMap tests
3
+ *
4
+ * Verifies the importmap merges configured externals from
5
+ * `barefoot-externals.json` (issue #1639) and emits modulepreload
6
+ * links, while preserving the pre-#1639 `@barefootjs/client*` defaults
7
+ * when no externals are passed.
8
+ */
9
+ import { describe, test, expect } from 'bun:test'
10
+ import { BfImportMap, type BarefootExternalsManifest } from '../app'
11
+
12
+ function parseImportMap(html: string): Record<string, string> {
13
+ const match = html.match(/<script type="importmap">(.*?)<\/script>/s)
14
+ if (!match) throw new Error(`no importmap in: ${html}`)
15
+ return JSON.parse(match[1]).imports
16
+ }
17
+
18
+ describe('BfImportMap', () => {
19
+ test('emits @barefootjs/client defaults when no externals passed', () => {
20
+ const html = String(BfImportMap({ base: '/components' }))
21
+ expect(parseImportMap(html)).toEqual({
22
+ '@barefootjs/client': '/components/barefoot.js',
23
+ '@barefootjs/client/runtime': '/components/barefoot.js',
24
+ })
25
+ expect(html).not.toContain('modulepreload')
26
+ })
27
+
28
+ test('strips trailing slash from base', () => {
29
+ const html = String(BfImportMap({ base: '/components/' }))
30
+ expect(parseImportMap(html)['@barefootjs/client']).toBe('/components/barefoot.js')
31
+ })
32
+
33
+ test('merges externals importmap on top of the client defaults', () => {
34
+ const externals: BarefootExternalsManifest = {
35
+ importmap: {
36
+ imports: {
37
+ zod: 'https://esm.sh/zod@4.4.3',
38
+ '@barefootjs/form': '/components/form.js',
39
+ },
40
+ },
41
+ preloads: [],
42
+ }
43
+ const imports = parseImportMap(String(BfImportMap({ base: '/components', externals })))
44
+ expect(imports).toEqual({
45
+ '@barefootjs/client': '/components/barefoot.js',
46
+ '@barefootjs/client/runtime': '/components/barefoot.js',
47
+ zod: 'https://esm.sh/zod@4.4.3',
48
+ '@barefootjs/form': '/components/form.js',
49
+ })
50
+ })
51
+
52
+ test('manifest @barefootjs/client mapping wins over the prop-derived one', () => {
53
+ const externals: BarefootExternalsManifest = {
54
+ importmap: { imports: { '@barefootjs/client': '/vendor/barefoot.js' } },
55
+ }
56
+ const imports = parseImportMap(String(BfImportMap({ base: '/components', externals })))
57
+ expect(imports['@barefootjs/client']).toBe('/vendor/barefoot.js')
58
+ })
59
+
60
+ test('emits modulepreload links for manifest preloads', () => {
61
+ const externals: BarefootExternalsManifest = {
62
+ importmap: { imports: {} },
63
+ preloads: ['/components/form.js', 'https://esm.sh/zod@4.4.3'],
64
+ }
65
+ const html = String(BfImportMap({ base: '/components', externals }))
66
+ expect(html).toContain('<link rel="modulepreload" href="/components/form.js">')
67
+ expect(html).toContain('<link rel="modulepreload" href="https://esm.sh/zod@4.4.3">')
68
+ })
69
+
70
+ test('preload=false suppresses modulepreload links', () => {
71
+ const externals: BarefootExternalsManifest = {
72
+ preloads: ['/components/form.js'],
73
+ }
74
+ const html = String(BfImportMap({ base: '/components', externals, preload: false }))
75
+ expect(html).not.toContain('modulepreload')
76
+ // importmap still emitted
77
+ expect(parseImportMap(html)['@barefootjs/client']).toBe('/components/barefoot.js')
78
+ })
79
+
80
+ test('escapes double quotes in preload hrefs', () => {
81
+ const externals: BarefootExternalsManifest = {
82
+ preloads: ['/components/"onerror=alert(1).js'],
83
+ }
84
+ const html = String(BfImportMap({ base: '/components', externals }))
85
+ expect(html).not.toContain('"onerror=alert(1)')
86
+ expect(html).toContain('&quot;onerror=alert(1)')
87
+ })
88
+ })
@@ -822,17 +822,32 @@ export class HonoAdapter extends JsxAdapter implements IRNodeEmitter<HonoRenderC
822
822
  // for both SSR (runtime-eval) and CSR (template fallback).
823
823
  // `.toSorted` (non-mutating) preserves shared prop arrays across
824
824
  // renders — `.sort()` here would reorder `_p.items` in place.
825
- const chainedArray = applyHonoLoopChain(loop)
825
+ let chainedArray = applyHonoLoopChain(loop)
826
826
  const iterMethod = loop.method ?? 'map'
827
827
 
828
+ // Re-emit `.entries()` / `.keys()` / `.values()` for Hono's runtime
829
+ // JS evaluation. The IR stripped the iterator call and synthesised
830
+ // param/index, so we reconstruct proper JS: `[...arr.entries()]`
831
+ // (spread into an array so `.map()` works).
832
+ let callbackParam: string
833
+ if (loop.iterationShape === 'entries' && loop.index) {
834
+ chainedArray = `[...${chainedArray}.entries()]`
835
+ callbackParam = `([${loop.index}${indexAnnotation}, ${loop.param}${paramAnnotation}])`
836
+ } else if (loop.iterationShape === 'keys') {
837
+ chainedArray = `[...${chainedArray}.keys()]`
838
+ callbackParam = `(${loop.param}${paramAnnotation})`
839
+ } else {
840
+ callbackParam = `(${loop.param}${paramAnnotation}${indexParam})`
841
+ }
842
+
828
843
  if (loop.flatMapCallback) {
829
844
  // Complex flatMap: use the original raw callback body (preserves JSX
830
845
  // for Hono's runtime JSX evaluation).
831
846
  mapExpr = `{${chainedArray}.flatMap(${loop.flatMapCallback.params} => ${loop.flatMapCallback.rawBody})}`
832
847
  } else if (preamble) {
833
- mapExpr = `{${chainedArray}.${iterMethod}((${loop.param}${paramAnnotation}${indexParam}) => { ${preamble} return ${safeChildren} })}`
848
+ mapExpr = `{${chainedArray}.${iterMethod}(${callbackParam} => { ${preamble} return ${safeChildren} })}`
834
849
  } else {
835
- mapExpr = `{${chainedArray}.${iterMethod}((${loop.param}${paramAnnotation}${indexParam}) => ${safeChildren})}`
850
+ mapExpr = `{${chainedArray}.${iterMethod}(${callbackParam} => ${safeChildren})}`
836
851
  }
837
852
  // Wrap with loop boundary markers so reconciliation doesn't affect siblings.
838
853
  // bfComment('loop:<id>') → <!--bf-loop:<id>-->. The marker id is unique
package/src/app.ts CHANGED
@@ -88,25 +88,72 @@ export function relPathFromComponentsBase(p: string): string {
88
88
 
89
89
  // ── JSX components ─────────────────────────────────────────────────────────
90
90
 
91
+ /**
92
+ * Shape of `barefoot-externals.json`, written by `bf build` when
93
+ * `externals` / `bundleEntries` are configured. Only the fields
94
+ * `BfImportMap` consumes are typed here; the build also emits an
95
+ * `externals` array (the `--external` list) which the importmap
96
+ * doesn't need. Fields are optional so a partial/hand-written
97
+ * manifest still type-checks. See issue #1639.
98
+ */
99
+ export interface BarefootExternalsManifest {
100
+ /** Entries for the `<script type="importmap">`. */
101
+ importmap?: { imports?: Record<string, string> }
102
+ /** URLs to emit as `<link rel="modulepreload">`. */
103
+ preloads?: string[]
104
+ }
105
+
91
106
  export interface BfImportMapProps {
92
107
  /** Base URL where the runtime + component bundles are served. */
93
108
  base: string
109
+ /**
110
+ * Contents of `barefoot-externals.json` (import it and pass it
111
+ * through). Its `importmap.imports` are merged on top of the
112
+ * built-in `@barefootjs/client*` mappings so islands importing
113
+ * configured externals (e.g. `zod`, `@barefootjs/form`) resolve in
114
+ * the browser. When omitted, only the `@barefootjs/client*`
115
+ * mappings are emitted — the pre-#1639 behavior.
116
+ */
117
+ externals?: BarefootExternalsManifest
118
+ /**
119
+ * Whether to also emit `<link rel="modulepreload">` for the
120
+ * manifest's `preloads`. Defaults to `true`; set `false` to emit
121
+ * the importmap only.
122
+ */
123
+ preload?: boolean
94
124
  }
95
125
 
96
126
  /**
97
127
  * Emits the `<script type="importmap">` that maps the bare
98
128
  * `@barefootjs/client` / `@barefootjs/client/runtime` specifiers to
99
- * the runtime bundle. Place in `<head>`.
129
+ * the runtime bundle, plus any externals from `barefoot-externals.json`
130
+ * passed via the `externals` prop. Also emits `<link rel="modulepreload">`
131
+ * for the manifest's `preloads` unless `preload` is `false`. Place in
132
+ * `<head>`.
100
133
  */
101
134
  export function BfImportMap(props: BfImportMapProps): HtmlEscapedString | Promise<HtmlEscapedString> {
102
135
  const base = props.base.replace(/\/$/, '')
103
- const json = JSON.stringify({
104
- imports: {
105
- '@barefootjs/client': `${base}/barefoot.js`,
106
- '@barefootjs/client/runtime': `${base}/barefoot.js`,
107
- },
108
- })
109
- return html`<script type="importmap">${raw(json)}</script>`
136
+ // Built-in defaults first, then manifest imports so a configured
137
+ // `@barefootjs/client` mapping (emitted by `bf build` against the
138
+ // build's `externalsBasePath`) wins over the prop-derived one.
139
+ const imports: Record<string, string> = {
140
+ '@barefootjs/client': `${base}/barefoot.js`,
141
+ '@barefootjs/client/runtime': `${base}/barefoot.js`,
142
+ ...(props.externals?.importmap?.imports ?? {}),
143
+ }
144
+ const json = JSON.stringify({ imports })
145
+
146
+ const preloads = props.preload === false ? [] : props.externals?.preloads ?? []
147
+ const links = preloads
148
+ .map((href) => `<link rel="modulepreload" href="${escapeAttr(href)}">`)
149
+ .join('')
150
+
151
+ return html`<script type="importmap">${raw(json)}</script>${raw(links)}`
152
+ }
153
+
154
+ /** Minimal double-quoted-attribute escaping for config-derived URLs. */
155
+ function escapeAttr(value: string): string {
156
+ return value.replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;')
110
157
  }
111
158
 
112
159
  export interface BfScriptsProps {