@markbrutx/promptbook-core 0.4.1 → 0.4.3

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/bundle.d.ts CHANGED
@@ -16,12 +16,16 @@ export interface SerializeBookOptions {
16
16
  * `{ fragments: new Map([...]), compositions: new Map([...]),
17
17
  * codePrompts: new Map([...]), warnings: [...] }`.
18
18
  *
19
- * The result is pure JavaScript (only `new Map`, arrays, object and scalar
20
- * literals) so it can be embedded in a module or reconstructed directly. Map
21
- * entries are sorted by key and optional fields are omitted when absent, so the
22
- * same book always produces byte-identical output.
19
+ * The default (untyped) result is pure JavaScript (only `new Map`, arrays, object
20
+ * and scalar literals) so it can be embedded in a module or reconstructed directly.
21
+ * With `typed: true` the maps carry TypeScript generic arguments
22
+ * (`new Map<string, Fragment>(...)`), which assumes the consuming module imports
23
+ * those types. Map entries are sorted by key and optional fields are omitted when
24
+ * absent, so the same book always produces byte-identical output.
23
25
  */
24
- export declare function serializeBookExpression(book: PromptBook): string;
26
+ export declare function serializeBookExpression(book: PromptBook, options?: {
27
+ typed?: boolean;
28
+ }): string;
25
29
  /**
26
30
  * Serialize a {@link PromptBook} to an importable TypeScript module exporting
27
31
  * `book: PromptBook`. Folding a prompts folder into a single module lets a
@@ -1 +1 @@
1
- {"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAuD,UAAU,EAAQ,MAAM,YAAY,CAAC;AAExG,yCAAyC;AACzC,MAAM,WAAW,oBAAoB;IACnC,wGAAwG;IACxG,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAuGD;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAMhE;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,GAAE,oBAAyB,GAAG,MAAM,CAY1F;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAK1D"}
1
+ {"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAuD,UAAU,EAAQ,MAAM,YAAY,CAAC;AAExG,yCAAyC;AACzC,MAAM,WAAW,oBAAoB;IACnC,wGAAwG;IACxG,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAiHD;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,MAAM,CAmBnG;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,GAAE,oBAAyB,GAAG,MAAM,CAc1F;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAK1D"}
package/dist/bundle.js CHANGED
@@ -74,33 +74,42 @@ function canonicalCodePrompt(codePrompt) {
74
74
  /**
75
75
  * Emit `new Map([...])` with one `[key, value]` entry per line (entries pre-sorted).
76
76
  *
77
- * An empty map serializes to `new Map()` (not `new Map([])`): without entries to
78
- * infer from, `new Map([])` widens to `Map<unknown, unknown>`, which is not
79
- * assignable to `Map<string, T>` in a plain (annotation-free) module. `new Map()`
80
- * infers `Map<any, any>`, which stays assignable, so plain bundles type-check
81
- * against `PromptBook` even when a map is empty.
77
+ * `typeName` adds explicit constructor type arguments (`new Map<string, T>(...)`),
78
+ * emitted in typed mode. They matter for two reasons:
79
+ * - Without entries, a bare `new Map([])` widens to `Map<unknown, unknown>`,
80
+ * which is not assignable to `Map<string, T>`. The empty case drops the array
81
+ * argument entirely (`new Map()` / `new Map<string, T>()`) so it stays assignable.
82
+ * - The `: PromptBook` annotation does not flow a contextual type through the
83
+ * generic `new Map(...)` call, so heterogeneous entries (e.g. rules whose
84
+ * `when` keys differ) infer excess `?: undefined` members that clash with the
85
+ * target's index signature. Explicit type arguments contextually type each
86
+ * entry against `T`, eliminating that widening.
82
87
  */
83
- function serializeMap(entries, canonical) {
88
+ function serializeMap(entries, canonical, typeName) {
89
+ const generic = typeName ? `<string, ${typeName}>` : "";
84
90
  if (entries.length === 0) {
85
- return "new Map()";
91
+ return `new Map${generic}()`;
86
92
  }
87
93
  const lines = entries.map(([key, value]) => ` [${JSON.stringify(key)}, ${JSON.stringify(canonical(value))}],`);
88
- return `new Map([\n${lines.join("\n")}\n ])`;
94
+ return `new Map${generic}([\n${lines.join("\n")}\n ])`;
89
95
  }
90
96
  /**
91
97
  * Serialize a {@link PromptBook} to a deterministic, evaluable expression:
92
98
  * `{ fragments: new Map([...]), compositions: new Map([...]),
93
99
  * codePrompts: new Map([...]), warnings: [...] }`.
94
100
  *
95
- * The result is pure JavaScript (only `new Map`, arrays, object and scalar
96
- * literals) so it can be embedded in a module or reconstructed directly. Map
97
- * entries are sorted by key and optional fields are omitted when absent, so the
98
- * same book always produces byte-identical output.
101
+ * The default (untyped) result is pure JavaScript (only `new Map`, arrays, object
102
+ * and scalar literals) so it can be embedded in a module or reconstructed directly.
103
+ * With `typed: true` the maps carry TypeScript generic arguments
104
+ * (`new Map<string, Fragment>(...)`), which assumes the consuming module imports
105
+ * those types. Map entries are sorted by key and optional fields are omitted when
106
+ * absent, so the same book always produces byte-identical output.
99
107
  */
100
- export function serializeBookExpression(book) {
101
- const fragments = serializeMap(sortedEntries(book.fragments), canonicalFragment);
102
- const compositions = serializeMap(sortedEntries(book.compositions), canonicalComposition);
103
- const codePrompts = serializeMap(sortedEntries(book.codePrompts), canonicalCodePrompt);
108
+ export function serializeBookExpression(book, options = {}) {
109
+ const typed = options.typed === true;
110
+ const fragments = serializeMap(sortedEntries(book.fragments), canonicalFragment, typed ? "Fragment" : undefined);
111
+ const compositions = serializeMap(sortedEntries(book.compositions), canonicalComposition, typed ? "Composition" : undefined);
112
+ const codePrompts = serializeMap(sortedEntries(book.codePrompts), canonicalCodePrompt, typed ? "CodePrompt" : undefined);
104
113
  const warnings = JSON.stringify(book.warnings);
105
114
  return `{\n fragments: ${fragments},\n compositions: ${compositions},\n codePrompts: ${codePrompts},\n warnings: ${warnings},\n}`;
106
115
  }
@@ -119,9 +128,11 @@ export function serializeBook(book, options = {}) {
119
128
  const importSpecifier = options.importSpecifier ?? "@markbrutx/promptbook-core";
120
129
  return [
121
130
  "// Code generated by `promptbook bundle`; do not edit by hand.",
122
- ...(typed ? [`import type { PromptBook } from "${importSpecifier}";`] : []),
131
+ ...(typed
132
+ ? [`import type { PromptBook, Fragment, Composition, CodePrompt } from "${importSpecifier}";`]
133
+ : []),
123
134
  "",
124
- `export const book${typed ? ": PromptBook" : ""} = ${serializeBookExpression(book)};`,
135
+ `export const book${typed ? ": PromptBook" : ""} = ${serializeBookExpression(book, { typed })};`,
125
136
  "",
126
137
  "export default book;",
127
138
  "",
@@ -1 +1 @@
1
- {"version":3,"file":"bundle.js","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bundle.js","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"AAeA,2FAA2F;AAC3F,SAAS,WAAW,CAAC,CAAS,EAAE,CAAS;IACvC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpC,CAAC;AAED,sEAAsE;AACtE,SAAS,aAAa,CAAI,GAAmB;IAC3C,OAAO,CAAC,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpE,CAAC;AAED,sFAAsF;AACtF,SAAS,OAAO,CAAC,GAA4B;IAC3C,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACnB,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,+DAA+D;AAC/D,gFAAgF;AAChF,6EAA6E;AAC7E,2EAA2E;AAC3E,6EAA6E;AAE7E,SAAS,iBAAiB,CAAC,QAAkB;IAC3C,MAAM,OAAO,GAA8C;QACzD,EAAE,EAAE,QAAQ,CAAC,EAAE;QACf,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,UAAU,EAAE,QAAQ,CAAC,UAAU;KAChC,CAAC;IACF,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,aAAa,CAAC,IAAU;IAC/B,MAAM,OAAO,GAA0C;QACrD,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK,EAAE,IAAI,CAAC,KAAK;KAClB,CAAC;IACF,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,oBAAoB,CAAC,WAAwB;IACpD,MAAM,OAAO,GAAiD;QAC5D,IAAI,EAAE,WAAW,CAAC,IAAI;QACtB,IAAI,EAAE,WAAW,CAAC,IAAI;QACtB,KAAK,EAAE,WAAW,CAAC,KAAK;QACxB,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC;QAC3C,UAAU,EAAE,WAAW,CAAC,UAAU;KACnC,CAAC;IACF,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,yBAAyB,CAAC,MAAwB;IACzD,MAAM,OAAO,GAAsD;QACjE,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,MAAM,EAAE,MAAM,CAAC,MAAM;KACtB,CAAC;IACF,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,mBAAmB,CAAC,UAAsB;IACjD,MAAM,OAAO,GAAgD;QAC3D,IAAI,EAAE,UAAU,CAAC,IAAI;QACrB,WAAW,EAAE,UAAU,CAAC,WAAW;QACnC,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC;QAC1D,UAAU,EAAE,UAAU,CAAC,UAAU;KAClC,CAAC;IACF,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAS,YAAY,CACnB,OAAsB,EACtB,SAAgC,EAChC,QAAiB;IAEjB,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,YAAY,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACxD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,UAAU,OAAO,IAAI,CAAC;IAC/B,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CACvB,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,QAAQ,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,CACvF,CAAC;IACF,OAAO,UAAU,OAAO,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;AAC1D,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAgB,EAAE,OAAO,GAAwB,EAAE;IACzF,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,KAAK,IAAI,CAAC;IACrC,MAAM,SAAS,GAAG,YAAY,CAC5B,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,EAC7B,iBAAiB,EACjB,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAC/B,CAAC;IACF,MAAM,YAAY,GAAG,YAAY,CAC/B,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,EAChC,oBAAoB,EACpB,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAClC,CAAC;IACF,MAAM,WAAW,GAAG,YAAY,CAC9B,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,EAC/B,mBAAmB,EACnB,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CACjC,CAAC;IACF,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC/C,OAAO,mBAAmB,SAAS,sBAAsB,YAAY,qBAAqB,WAAW,kBAAkB,QAAQ,MAAM,CAAC;AACxI,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa,CAAC,IAAgB,EAAE,OAAO,GAAyB,EAAE;IAChF,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,KAAK,KAAK,CAAC;IACtC,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,4BAA4B,CAAC;IAChF,OAAO;QACL,gEAAgE;QAChE,GAAG,CAAC,KAAK;YACP,CAAC,CAAC,CAAC,uEAAuE,eAAe,IAAI,CAAC;YAC9F,CAAC,CAAC,EAAE,CAAC;QACP,EAAE;QACF,oBAAoB,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,MAAM,uBAAuB,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,GAAG;QAChG,EAAE;QACF,sBAAsB;QACtB,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAgB;IAChD,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7F,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAC;IACtG,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC;IACnG,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;AAC3G,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markbrutx/promptbook-core",
3
- "version": "0.4.1",
3
+ "version": "0.4.3",
4
4
  "description": "Agnostic, deterministic core for composing prompts from reusable fragments via declarative rules.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/bundle.ts CHANGED
@@ -98,20 +98,30 @@ function canonicalCodePrompt(codePrompt: CodePrompt): Record<string, unknown> {
98
98
  /**
99
99
  * Emit `new Map([...])` with one `[key, value]` entry per line (entries pre-sorted).
100
100
  *
101
- * An empty map serializes to `new Map()` (not `new Map([])`): without entries to
102
- * infer from, `new Map([])` widens to `Map<unknown, unknown>`, which is not
103
- * assignable to `Map<string, T>` in a plain (annotation-free) module. `new Map()`
104
- * infers `Map<any, any>`, which stays assignable, so plain bundles type-check
105
- * against `PromptBook` even when a map is empty.
101
+ * `typeName` adds explicit constructor type arguments (`new Map<string, T>(...)`),
102
+ * emitted in typed mode. They matter for two reasons:
103
+ * - Without entries, a bare `new Map([])` widens to `Map<unknown, unknown>`,
104
+ * which is not assignable to `Map<string, T>`. The empty case drops the array
105
+ * argument entirely (`new Map()` / `new Map<string, T>()`) so it stays assignable.
106
+ * - The `: PromptBook` annotation does not flow a contextual type through the
107
+ * generic `new Map(...)` call, so heterogeneous entries (e.g. rules whose
108
+ * `when` keys differ) infer excess `?: undefined` members that clash with the
109
+ * target's index signature. Explicit type arguments contextually type each
110
+ * entry against `T`, eliminating that widening.
106
111
  */
107
- function serializeMap<T>(entries: [string, T][], canonical: (value: T) => unknown): string {
112
+ function serializeMap<T>(
113
+ entries: [string, T][],
114
+ canonical: (value: T) => unknown,
115
+ typeName?: string,
116
+ ): string {
117
+ const generic = typeName ? `<string, ${typeName}>` : "";
108
118
  if (entries.length === 0) {
109
- return "new Map()";
119
+ return `new Map${generic}()`;
110
120
  }
111
121
  const lines = entries.map(
112
122
  ([key, value]) => ` [${JSON.stringify(key)}, ${JSON.stringify(canonical(value))}],`,
113
123
  );
114
- return `new Map([\n${lines.join("\n")}\n ])`;
124
+ return `new Map${generic}([\n${lines.join("\n")}\n ])`;
115
125
  }
116
126
 
117
127
  /**
@@ -119,15 +129,30 @@ function serializeMap<T>(entries: [string, T][], canonical: (value: T) => unknow
119
129
  * `{ fragments: new Map([...]), compositions: new Map([...]),
120
130
  * codePrompts: new Map([...]), warnings: [...] }`.
121
131
  *
122
- * The result is pure JavaScript (only `new Map`, arrays, object and scalar
123
- * literals) so it can be embedded in a module or reconstructed directly. Map
124
- * entries are sorted by key and optional fields are omitted when absent, so the
125
- * same book always produces byte-identical output.
132
+ * The default (untyped) result is pure JavaScript (only `new Map`, arrays, object
133
+ * and scalar literals) so it can be embedded in a module or reconstructed directly.
134
+ * With `typed: true` the maps carry TypeScript generic arguments
135
+ * (`new Map<string, Fragment>(...)`), which assumes the consuming module imports
136
+ * those types. Map entries are sorted by key and optional fields are omitted when
137
+ * absent, so the same book always produces byte-identical output.
126
138
  */
127
- export function serializeBookExpression(book: PromptBook): string {
128
- const fragments = serializeMap(sortedEntries(book.fragments), canonicalFragment);
129
- const compositions = serializeMap(sortedEntries(book.compositions), canonicalComposition);
130
- const codePrompts = serializeMap(sortedEntries(book.codePrompts), canonicalCodePrompt);
139
+ export function serializeBookExpression(book: PromptBook, options: { typed?: boolean } = {}): string {
140
+ const typed = options.typed === true;
141
+ const fragments = serializeMap(
142
+ sortedEntries(book.fragments),
143
+ canonicalFragment,
144
+ typed ? "Fragment" : undefined,
145
+ );
146
+ const compositions = serializeMap(
147
+ sortedEntries(book.compositions),
148
+ canonicalComposition,
149
+ typed ? "Composition" : undefined,
150
+ );
151
+ const codePrompts = serializeMap(
152
+ sortedEntries(book.codePrompts),
153
+ canonicalCodePrompt,
154
+ typed ? "CodePrompt" : undefined,
155
+ );
131
156
  const warnings = JSON.stringify(book.warnings);
132
157
  return `{\n fragments: ${fragments},\n compositions: ${compositions},\n codePrompts: ${codePrompts},\n warnings: ${warnings},\n}`;
133
158
  }
@@ -147,9 +172,11 @@ export function serializeBook(book: PromptBook, options: SerializeBookOptions =
147
172
  const importSpecifier = options.importSpecifier ?? "@markbrutx/promptbook-core";
148
173
  return [
149
174
  "// Code generated by `promptbook bundle`; do not edit by hand.",
150
- ...(typed ? [`import type { PromptBook } from "${importSpecifier}";`] : []),
175
+ ...(typed
176
+ ? [`import type { PromptBook, Fragment, Composition, CodePrompt } from "${importSpecifier}";`]
177
+ : []),
151
178
  "",
152
- `export const book${typed ? ": PromptBook" : ""} = ${serializeBookExpression(book)};`,
179
+ `export const book${typed ? ": PromptBook" : ""} = ${serializeBookExpression(book, { typed })};`,
153
180
  "",
154
181
  "export default book;",
155
182
  "",