@promptlycms/prompts 0.4.0 → 0.4.1-canary.e46a98c

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/README.md CHANGED
@@ -180,6 +180,24 @@ const [first, second] = await promptly.getComposers([
180
180
  ]);
181
181
  ```
182
182
 
183
+ ### HTML blocks
184
+
185
+ Composers can contain raw HTML blocks (for vendor-specific markup like MSO conditional comments in transactional emails). These surface as a distinct `html_block` segment type:
186
+
187
+ ```typescript
188
+ const composer = await promptly.getComposer('my-email-composer', {
189
+ input: { country: 'United Kingdom' },
190
+ });
191
+
192
+ for (const segment of composer.segments) {
193
+ if (segment.type === 'html_block') {
194
+ console.log(segment.html); // raw HTML, byte-exact
195
+ }
196
+ }
197
+ ```
198
+
199
+ Variable references inside an `html_block` (e.g. `<span data-variable-ref data-field-path="country">`) are interpolated normally during `formatComposer()` / `compose()`. Embedded prompt references inside an `html_block` are passed through opaquely — they aren't resolved as named prompts.
200
+
183
201
  ## Model auto-detection
184
202
 
185
203
  The SDK automatically resolves models configured in the CMS to the correct AI SDK provider based on the model name prefix:
@@ -232,7 +250,7 @@ declare module '@promptlycms/prompts' {
232
250
  }
233
251
  ```
234
252
 
235
- With this file present, `getPrompt()` and `getPrompts()` return typed `userMessage` functions with autocomplete. `getComposer()` and `getComposers()` get typed `input` and named prompt properties. Unknown IDs fall back to `Record<string, string>`.
253
+ With this file present, `getPrompt()` and `getPrompts()` return typed `userMessage` functions with autocomplete. `getComposer()` and `getComposers()` only accept generated composer IDs, with typed `input` and named prompt properties. Unknown prompt IDs fall back to `Record<string, unknown>`.
236
254
 
237
255
  Add the generated file to version control so types are available without running codegen in CI. Re-run `npx promptly generate` whenever you add, remove, or rename template variables in the CMS.
238
256
 
@@ -286,7 +304,7 @@ Fetch a single composer. Returns `ComposerResult` with named prompt properties,
286
304
 
287
305
  | Option | Type | Description |
288
306
  |-----------|---------------------------|----------------------|
289
- | `input` | `Record<string, string>` | Template variables to interpolate |
307
+ | `input` | `Record<string, unknown>` | Template variables to interpolate |
290
308
  | `version` | `string` | Specific version to fetch (default: latest) |
291
309
 
292
310
  ### `client.getComposers(entries)`
package/dist/cli.js CHANGED
@@ -86,6 +86,28 @@ var extractTemplateVariables = (text) => {
86
86
  }
87
87
  return [...vars];
88
88
  };
89
+ var extractStaticSegmentVariables = (content) => {
90
+ const vars = /* @__PURE__ */ new Set();
91
+ const varRefRegex = /<span[^>]*\sdata-variable-ref(?:="[^"]*")?[^>]*\sdata-field-path="([^"]+)"[^>]*><\/span>/g;
92
+ const varRefAltRegex = /<span[^>]*\sdata-field-path="([^"]+)"[^>]*\sdata-variable-ref(?:="[^"]*")?[^>]*><\/span>/g;
93
+ const mustacheRegex = /\{\{(\w[\w.]*)\}\}/g;
94
+ for (const match of content.matchAll(varRefRegex)) {
95
+ if (match[1]) {
96
+ vars.add(match[1]);
97
+ }
98
+ }
99
+ for (const match of content.matchAll(varRefAltRegex)) {
100
+ if (match[1]) {
101
+ vars.add(match[1]);
102
+ }
103
+ }
104
+ for (const match of content.matchAll(mustacheRegex)) {
105
+ if (match[1]) {
106
+ vars.add(match[1]);
107
+ }
108
+ }
109
+ return [...vars];
110
+ };
89
111
  var fetchAllPrompts = async (apiKey, baseUrl) => {
90
112
  const url = new URL("/prompts", baseUrl ?? DEFAULT_BASE_URL);
91
113
  url.searchParams.set("include_versions", "true");
@@ -115,14 +137,21 @@ var fetchAllComposers = async (apiKey, baseUrl) => {
115
137
  var extractComposerVariables = (composer) => {
116
138
  const vars = /* @__PURE__ */ new Set();
117
139
  for (const segment of composer.segments) {
118
- if (segment.type !== "prompt") {
119
- continue;
120
- }
121
- if (!segment.userMessage) {
122
- continue;
123
- }
124
- for (const v of extractTemplateVariables(segment.userMessage)) {
125
- vars.add(v);
140
+ if (segment.type === "prompt") {
141
+ if (!segment.userMessage) {
142
+ continue;
143
+ }
144
+ for (const v of extractTemplateVariables(segment.userMessage)) {
145
+ vars.add(v);
146
+ }
147
+ } else if (segment.type === "static") {
148
+ for (const v of extractStaticSegmentVariables(segment.content)) {
149
+ vars.add(v);
150
+ }
151
+ } else if (segment.type === "html_block") {
152
+ for (const v of extractStaticSegmentVariables(segment.html)) {
153
+ vars.add(v);
154
+ }
126
155
  }
127
156
  }
128
157
  return [...vars];
@@ -252,6 +281,13 @@ var buildSchemaMap = (schema) => {
252
281
  }
253
282
  return map;
254
283
  };
284
+ var TYPE_IDENTIFIER_RE = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
285
+ var typePropertyKey = (key) => {
286
+ if (TYPE_IDENTIFIER_RE.test(key)) {
287
+ return key;
288
+ }
289
+ return `'${key.replaceAll("\\", "\\\\").replaceAll("'", "\\'")}'`;
290
+ };
255
291
  var generateMappedTypeBlock = (group, indent, schemaMap = /* @__PURE__ */ new Map()) => {
256
292
  const lines = [];
257
293
  const { versions, variables } = group;
@@ -333,6 +369,7 @@ var generateTypeDeclaration = (prompts, composers = []) => {
333
369
  lines.push(" interface ComposerVariableMap {");
334
370
  for (const composer of composers) {
335
371
  const variables = extractComposerVariables(composer);
372
+ const composerKey = typePropertyKey(composer.composerId);
336
373
  const schemaMap = buildSchemaMap(composer.config.schema);
337
374
  const versions = ["'latest'"];
338
375
  if (composer.publishedVersions) {
@@ -342,7 +379,7 @@ var generateTypeDeclaration = (prompts, composers = []) => {
342
379
  } else {
343
380
  versions.push(`'${composer.version}'`);
344
381
  }
345
- lines.push(` '${composer.composerId}': {`);
382
+ lines.push(` ${composerKey}: {`);
346
383
  if (versions.length === 1) {
347
384
  if (variables.length === 0) {
348
385
  lines.push(` [V in ${versions[0]}]: Record<string, never>;`);
@@ -375,11 +412,12 @@ var generateTypeDeclaration = (prompts, composers = []) => {
375
412
  lines.push(" interface ComposerPromptMap {");
376
413
  for (const composer of composers) {
377
414
  const names = extractComposerPromptNames(composer);
415
+ const composerKey = typePropertyKey(composer.composerId);
378
416
  if (names.length === 0) {
379
- lines.push(` '${composer.composerId}': never;`);
417
+ lines.push(` ${composerKey}: never;`);
380
418
  } else {
381
419
  const union = names.map((n) => `'${n}'`).join(" | ");
382
- lines.push(` '${composer.composerId}': ${union};`);
420
+ lines.push(` ${composerKey}: ${union};`);
383
421
  }
384
422
  }
385
423
  lines.push(" }");
package/dist/index.cjs CHANGED
@@ -275,6 +275,13 @@ var createPromptlyClient = (config) => {
275
275
  });
276
276
  continue;
277
277
  }
278
+ if (segment.type === "html_block") {
279
+ processedSegments.push({
280
+ type: "static",
281
+ content: interpolateStaticSegment(segment.html, input)
282
+ });
283
+ continue;
284
+ }
278
285
  const camelName = toCamelCase(segment.promptName);
279
286
  if (!promptsByName.has(camelName)) {
280
287
  const segmentConfig = segment.config;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as PromptlyClientConfig, a as PromptlyClient, E as ErrorCode } from './types-DIVyjOlH.cjs';
2
- export { C as ComposerConfig, b as ComposerFormatFn, c as ComposerGenerateFn, d as ComposerId, e as ComposerInputFor, f as ComposerPrompt, g as ComposerPromptMap, h as ComposerPromptNamesFor, i as ComposerPromptSegment, j as ComposerRequest, k as ComposerResponse, l as ComposerResult, m as ComposerSegment, n as ComposerStaticSegment, o as ComposerVariableMap, p as ComposerVersion, q as ErrorResponse, F as FormatInput, G as GetComposerOptions, r as GetOptions, s as PromptConfig, t as PromptId, u as PromptMessage, v as PromptRequest, w as PromptResponse, x as PromptResult, y as PromptVariableMap, z as PromptVersion, A as PublishedVersion, S as SchemaField, B as SchemaFieldParams, V as ValidationRule } from './types-DIVyjOlH.cjs';
1
+ import { P as PromptlyClientConfig, a as PromptlyClient, E as ErrorCode } from './types-DaIU82yN.cjs';
2
+ export { C as ComposerConfig, b as ComposerFormatFn, c as ComposerGenerateFn, d as ComposerHtmlBlockSegment, e as ComposerId, f as ComposerInputFor, g as ComposerPrompt, h as ComposerPromptMap, i as ComposerPromptNamesFor, j as ComposerPromptSegment, k as ComposerRequest, l as ComposerResponse, m as ComposerResult, n as ComposerSegment, o as ComposerStaticSegment, p as ComposerVariableMap, q as ComposerVersion, r as ErrorResponse, F as FormatInput, G as GetComposerOptions, s as GetOptions, t as PromptConfig, u as PromptId, v as PromptMessage, w as PromptRequest, x as PromptResponse, y as PromptResult, z as PromptVariableMap, A as PromptVersion, B as PublishedVersion, S as SchemaField, D as SchemaFieldParams, V as ValidationRule } from './types-DaIU82yN.cjs';
3
3
  import 'ai';
4
4
 
5
5
  declare const getSdkModelId: (modelId: string) => string;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as PromptlyClientConfig, a as PromptlyClient, E as ErrorCode } from './types-DIVyjOlH.js';
2
- export { C as ComposerConfig, b as ComposerFormatFn, c as ComposerGenerateFn, d as ComposerId, e as ComposerInputFor, f as ComposerPrompt, g as ComposerPromptMap, h as ComposerPromptNamesFor, i as ComposerPromptSegment, j as ComposerRequest, k as ComposerResponse, l as ComposerResult, m as ComposerSegment, n as ComposerStaticSegment, o as ComposerVariableMap, p as ComposerVersion, q as ErrorResponse, F as FormatInput, G as GetComposerOptions, r as GetOptions, s as PromptConfig, t as PromptId, u as PromptMessage, v as PromptRequest, w as PromptResponse, x as PromptResult, y as PromptVariableMap, z as PromptVersion, A as PublishedVersion, S as SchemaField, B as SchemaFieldParams, V as ValidationRule } from './types-DIVyjOlH.js';
1
+ import { P as PromptlyClientConfig, a as PromptlyClient, E as ErrorCode } from './types-DaIU82yN.js';
2
+ export { C as ComposerConfig, b as ComposerFormatFn, c as ComposerGenerateFn, d as ComposerHtmlBlockSegment, e as ComposerId, f as ComposerInputFor, g as ComposerPrompt, h as ComposerPromptMap, i as ComposerPromptNamesFor, j as ComposerPromptSegment, k as ComposerRequest, l as ComposerResponse, m as ComposerResult, n as ComposerSegment, o as ComposerStaticSegment, p as ComposerVariableMap, q as ComposerVersion, r as ErrorResponse, F as FormatInput, G as GetComposerOptions, s as GetOptions, t as PromptConfig, u as PromptId, v as PromptMessage, w as PromptRequest, x as PromptResponse, y as PromptResult, z as PromptVariableMap, A as PromptVersion, B as PublishedVersion, S as SchemaField, D as SchemaFieldParams, V as ValidationRule } from './types-DaIU82yN.js';
3
3
  import 'ai';
4
4
 
5
5
  declare const getSdkModelId: (modelId: string) => string;
package/dist/index.js CHANGED
@@ -234,6 +234,13 @@ var createPromptlyClient = (config) => {
234
234
  });
235
235
  continue;
236
236
  }
237
+ if (segment.type === "html_block") {
238
+ processedSegments.push({
239
+ type: "static",
240
+ content: interpolateStaticSegment(segment.html, input)
241
+ });
242
+ continue;
243
+ }
237
244
  const camelName = toCamelCase(segment.promptName);
238
245
  if (!promptsByName.has(camelName)) {
239
246
  const segmentConfig = segment.config;
package/dist/schema.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { S as SchemaField } from './types-DIVyjOlH.cjs';
2
+ import { S as SchemaField } from './types-DaIU82yN.cjs';
3
3
  import 'ai';
4
4
 
5
5
  declare const buildFieldSchema: (field: SchemaField) => z.ZodTypeAny;
package/dist/schema.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { S as SchemaField } from './types-DIVyjOlH.js';
2
+ import { S as SchemaField } from './types-DaIU82yN.js';
3
3
  import 'ai';
4
4
 
5
5
  declare const buildFieldSchema: (field: SchemaField) => z.ZodTypeAny;
@@ -108,7 +108,11 @@ type ComposerPromptSegment = {
108
108
  userMessage: string | null;
109
109
  config: Record<string, unknown>;
110
110
  };
111
- type ComposerSegment = ComposerStaticSegment | ComposerPromptSegment;
111
+ type ComposerHtmlBlockSegment = {
112
+ type: 'html_block';
113
+ html: string;
114
+ };
115
+ type ComposerSegment = ComposerStaticSegment | ComposerPromptSegment | ComposerHtmlBlockSegment;
112
116
  type ComposerConfig = {
113
117
  schema: SchemaField[];
114
118
  inputData: unknown;
@@ -128,7 +132,8 @@ interface ComposerVariableMap {
128
132
  }
129
133
  interface ComposerPromptMap {
130
134
  }
131
- type ComposerId = keyof ComposerVariableMap | (string & {});
135
+ type KnownComposerId = Extract<keyof ComposerVariableMap, string>;
136
+ type ComposerId = [KnownComposerId] extends [never] ? string : KnownComposerId;
132
137
  type ComposerVersion<Id extends string> = Id extends keyof ComposerVariableMap ? Exclude<keyof ComposerVariableMap[Id], 'latest'> : string;
133
138
  type ComposerInputFor<Id extends string, Ver extends string = 'latest'> = Id extends keyof ComposerVariableMap ? Ver extends keyof ComposerVariableMap[Id] ? ComposerVariableMap[Id][Ver] : Record<string, unknown> : Record<string, unknown>;
134
139
  type ComposerPromptNamesFor<Id extends string> = Id extends keyof ComposerPromptMap ? ComposerPromptMap[Id] : string;
@@ -159,12 +164,12 @@ type ComposerResult<Names extends string = string> = {
159
164
  } & {
160
165
  [K in Names]: ComposerPrompt;
161
166
  };
162
- type GetComposerOptions<Id extends string = string, V extends string = 'latest'> = {
167
+ type GetComposerOptions<Id extends string = ComposerId, V extends string = 'latest'> = {
163
168
  input?: ComposerInputFor<Id, V>;
164
169
  version?: V;
165
170
  };
166
171
  type ComposerRequest = {
167
- composerId: string;
172
+ composerId: ComposerId;
168
173
  input?: Record<string, unknown>;
169
174
  version?: string;
170
175
  };
@@ -191,8 +196,8 @@ type GetOptions<V extends string = string> = {
191
196
  type PromptlyClient = {
192
197
  getPrompt: <T extends string, V extends PromptVersion<T> | 'latest' = 'latest'>(promptId: T, options?: GetOptions<V>) => Promise<PromptResult<VariablesFor<T, V>>>;
193
198
  getPrompts: <const T extends readonly PromptRequest[]>(entries: T) => Promise<GetPromptsResults<T>>;
194
- getComposer: <T extends string, V extends ComposerVersion<T> | 'latest' = 'latest'>(composerId: T, options?: GetComposerOptions<T, V>) => Promise<ComposerResult<ComposerPromptNamesFor<T>>>;
199
+ getComposer: <T extends ComposerId, V extends ComposerVersion<T> | 'latest' = 'latest'>(composerId: T, options?: GetComposerOptions<T, V>) => Promise<ComposerResult<ComposerPromptNamesFor<T>>>;
195
200
  getComposers: <const T extends readonly ComposerRequest[]>(entries: T) => Promise<GetComposersResults<T>>;
196
201
  };
197
202
 
198
- export type { PublishedVersion as A, SchemaFieldParams as B, ComposerConfig as C, ErrorCode as E, FormatInput as F, GetComposerOptions as G, PromptlyClientConfig as P, SchemaField as S, ValidationRule as V, PromptlyClient as a, ComposerFormatFn as b, ComposerGenerateFn as c, ComposerId as d, ComposerInputFor as e, ComposerPrompt as f, ComposerPromptMap as g, ComposerPromptNamesFor as h, ComposerPromptSegment as i, ComposerRequest as j, ComposerResponse as k, ComposerResult as l, ComposerSegment as m, ComposerStaticSegment as n, ComposerVariableMap as o, ComposerVersion as p, ErrorResponse as q, GetOptions as r, PromptConfig as s, PromptId as t, PromptMessage as u, PromptRequest as v, PromptResponse as w, PromptResult as x, PromptVariableMap as y, PromptVersion as z };
203
+ export type { PromptVersion as A, PublishedVersion as B, ComposerConfig as C, SchemaFieldParams as D, ErrorCode as E, FormatInput as F, GetComposerOptions as G, PromptlyClientConfig as P, SchemaField as S, ValidationRule as V, PromptlyClient as a, ComposerFormatFn as b, ComposerGenerateFn as c, ComposerHtmlBlockSegment as d, ComposerId as e, ComposerInputFor as f, ComposerPrompt as g, ComposerPromptMap as h, ComposerPromptNamesFor as i, ComposerPromptSegment as j, ComposerRequest as k, ComposerResponse as l, ComposerResult as m, ComposerSegment as n, ComposerStaticSegment as o, ComposerVariableMap as p, ComposerVersion as q, ErrorResponse as r, GetOptions as s, PromptConfig as t, PromptId as u, PromptMessage as v, PromptRequest as w, PromptResponse as x, PromptResult as y, PromptVariableMap as z };
@@ -108,7 +108,11 @@ type ComposerPromptSegment = {
108
108
  userMessage: string | null;
109
109
  config: Record<string, unknown>;
110
110
  };
111
- type ComposerSegment = ComposerStaticSegment | ComposerPromptSegment;
111
+ type ComposerHtmlBlockSegment = {
112
+ type: 'html_block';
113
+ html: string;
114
+ };
115
+ type ComposerSegment = ComposerStaticSegment | ComposerPromptSegment | ComposerHtmlBlockSegment;
112
116
  type ComposerConfig = {
113
117
  schema: SchemaField[];
114
118
  inputData: unknown;
@@ -128,7 +132,8 @@ interface ComposerVariableMap {
128
132
  }
129
133
  interface ComposerPromptMap {
130
134
  }
131
- type ComposerId = keyof ComposerVariableMap | (string & {});
135
+ type KnownComposerId = Extract<keyof ComposerVariableMap, string>;
136
+ type ComposerId = [KnownComposerId] extends [never] ? string : KnownComposerId;
132
137
  type ComposerVersion<Id extends string> = Id extends keyof ComposerVariableMap ? Exclude<keyof ComposerVariableMap[Id], 'latest'> : string;
133
138
  type ComposerInputFor<Id extends string, Ver extends string = 'latest'> = Id extends keyof ComposerVariableMap ? Ver extends keyof ComposerVariableMap[Id] ? ComposerVariableMap[Id][Ver] : Record<string, unknown> : Record<string, unknown>;
134
139
  type ComposerPromptNamesFor<Id extends string> = Id extends keyof ComposerPromptMap ? ComposerPromptMap[Id] : string;
@@ -159,12 +164,12 @@ type ComposerResult<Names extends string = string> = {
159
164
  } & {
160
165
  [K in Names]: ComposerPrompt;
161
166
  };
162
- type GetComposerOptions<Id extends string = string, V extends string = 'latest'> = {
167
+ type GetComposerOptions<Id extends string = ComposerId, V extends string = 'latest'> = {
163
168
  input?: ComposerInputFor<Id, V>;
164
169
  version?: V;
165
170
  };
166
171
  type ComposerRequest = {
167
- composerId: string;
172
+ composerId: ComposerId;
168
173
  input?: Record<string, unknown>;
169
174
  version?: string;
170
175
  };
@@ -191,8 +196,8 @@ type GetOptions<V extends string = string> = {
191
196
  type PromptlyClient = {
192
197
  getPrompt: <T extends string, V extends PromptVersion<T> | 'latest' = 'latest'>(promptId: T, options?: GetOptions<V>) => Promise<PromptResult<VariablesFor<T, V>>>;
193
198
  getPrompts: <const T extends readonly PromptRequest[]>(entries: T) => Promise<GetPromptsResults<T>>;
194
- getComposer: <T extends string, V extends ComposerVersion<T> | 'latest' = 'latest'>(composerId: T, options?: GetComposerOptions<T, V>) => Promise<ComposerResult<ComposerPromptNamesFor<T>>>;
199
+ getComposer: <T extends ComposerId, V extends ComposerVersion<T> | 'latest' = 'latest'>(composerId: T, options?: GetComposerOptions<T, V>) => Promise<ComposerResult<ComposerPromptNamesFor<T>>>;
195
200
  getComposers: <const T extends readonly ComposerRequest[]>(entries: T) => Promise<GetComposersResults<T>>;
196
201
  };
197
202
 
198
- export type { PublishedVersion as A, SchemaFieldParams as B, ComposerConfig as C, ErrorCode as E, FormatInput as F, GetComposerOptions as G, PromptlyClientConfig as P, SchemaField as S, ValidationRule as V, PromptlyClient as a, ComposerFormatFn as b, ComposerGenerateFn as c, ComposerId as d, ComposerInputFor as e, ComposerPrompt as f, ComposerPromptMap as g, ComposerPromptNamesFor as h, ComposerPromptSegment as i, ComposerRequest as j, ComposerResponse as k, ComposerResult as l, ComposerSegment as m, ComposerStaticSegment as n, ComposerVariableMap as o, ComposerVersion as p, ErrorResponse as q, GetOptions as r, PromptConfig as s, PromptId as t, PromptMessage as u, PromptRequest as v, PromptResponse as w, PromptResult as x, PromptVariableMap as y, PromptVersion as z };
203
+ export type { PromptVersion as A, PublishedVersion as B, ComposerConfig as C, SchemaFieldParams as D, ErrorCode as E, FormatInput as F, GetComposerOptions as G, PromptlyClientConfig as P, SchemaField as S, ValidationRule as V, PromptlyClient as a, ComposerFormatFn as b, ComposerGenerateFn as c, ComposerHtmlBlockSegment as d, ComposerId as e, ComposerInputFor as f, ComposerPrompt as g, ComposerPromptMap as h, ComposerPromptNamesFor as i, ComposerPromptSegment as j, ComposerRequest as k, ComposerResponse as l, ComposerResult as m, ComposerSegment as n, ComposerStaticSegment as o, ComposerVariableMap as p, ComposerVersion as q, ErrorResponse as r, GetOptions as s, PromptConfig as t, PromptId as u, PromptMessage as v, PromptRequest as w, PromptResponse as x, PromptResult as y, PromptVariableMap as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@promptlycms/prompts",
3
- "version": "0.4.0",
3
+ "version": "0.4.1-canary.e46a98c",
4
4
  "description": "TypeScript SDK for Promptly CMS — fetch prompts, build Zod schemas, generate typed code",
5
5
  "type": "module",
6
6
  "exports": {