@promptlycms/prompts 0.6.0 → 0.6.1-canary.8246366

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
@@ -172,9 +172,11 @@ const output = formatComposer({
172
172
  ```
173
173
 
174
174
  Prompt results are treated as text by default. Newlines in strings or `{ text }`
175
- results are preserved as `<br>` tags when the composer output is assembled. If a
176
- prompt result already contains trusted HTML, pass `{ html: '<p>...</p>' }` to
177
- `formatComposer()` to insert it without newline conversion.
175
+ results are preserved as `<br>` tags when the composer output is assembled. If
176
+ text prompt output is placed in its own rich-text paragraph, the SDK also keeps
177
+ the visible paragraph gap in email-safe HTML. If a prompt result already
178
+ contains trusted HTML, pass `{ html: '<p>...</p>' }` to `formatComposer()` to
179
+ insert it without newline conversion.
178
180
 
179
181
  Batch fetch multiple composers in parallel:
180
182
 
package/dist/cli.js CHANGED
@@ -365,63 +365,57 @@ var generateTypeDeclaration = (prompts, composers = []) => {
365
365
  }
366
366
  }
367
367
  lines.push(" }");
368
- if (composers.length > 0) {
369
- lines.push(" interface ComposerVariableMap {");
370
- for (const composer of composers) {
371
- const variables = extractComposerVariables(composer);
372
- const composerKey = typePropertyKey(composer.composerId);
373
- const schemaMap = buildSchemaMap(composer.config.schema);
374
- const versions = ["'latest'"];
375
- if (composer.publishedVersions) {
376
- for (const pv of composer.publishedVersions) {
377
- versions.push(`'${pv.version}'`);
378
- }
379
- } else {
380
- versions.push(`'${composer.version}'`);
368
+ lines.push(" interface ComposerVariableMap {");
369
+ for (const composer of composers) {
370
+ const variables = extractComposerVariables(composer);
371
+ const composerKey = typePropertyKey(composer.composerId);
372
+ const schemaMap = buildSchemaMap(composer.config.schema);
373
+ const versions = ["'latest'"];
374
+ if (composer.publishedVersions) {
375
+ for (const pv of composer.publishedVersions) {
376
+ versions.push(`'${pv.version}'`);
381
377
  }
382
- lines.push(` ${composerKey}: {`);
383
- if (versions.length === 1) {
384
- if (variables.length === 0) {
385
- lines.push(` [V in ${versions[0]}]: Record<string, never>;`);
386
- } else {
387
- lines.push(` [V in ${versions[0]}]: {`);
388
- for (const v of variables) {
389
- lines.push(
390
- ` ${v}: ${schemaFieldToTsType(schemaMap.get(v))};`
391
- );
392
- }
393
- lines.push(" };");
394
- }
378
+ } else {
379
+ versions.push(`'${composer.version}'`);
380
+ }
381
+ lines.push(` ${composerKey}: {`);
382
+ if (versions.length === 1) {
383
+ if (variables.length === 0) {
384
+ lines.push(` [V in ${versions[0]}]: Record<string, never>;`);
395
385
  } else {
396
- const versionUnion = versions.join(" | ");
397
- if (variables.length === 0) {
398
- lines.push(` [V in ${versionUnion}]: Record<string, never>;`);
399
- } else {
400
- lines.push(` [V in ${versionUnion}]: {`);
401
- for (const v of variables) {
402
- lines.push(
403
- ` ${v}: ${schemaFieldToTsType(schemaMap.get(v))};`
404
- );
405
- }
406
- lines.push(" };");
386
+ lines.push(` [V in ${versions[0]}]: {`);
387
+ for (const v of variables) {
388
+ lines.push(` ${v}: ${schemaFieldToTsType(schemaMap.get(v))};`);
407
389
  }
390
+ lines.push(" };");
408
391
  }
409
- lines.push(" };");
410
- }
411
- lines.push(" }");
412
- lines.push(" interface ComposerPromptMap {");
413
- for (const composer of composers) {
414
- const names = extractComposerPromptNames(composer);
415
- const composerKey = typePropertyKey(composer.composerId);
416
- if (names.length === 0) {
417
- lines.push(` ${composerKey}: never;`);
392
+ } else {
393
+ const versionUnion = versions.join(" | ");
394
+ if (variables.length === 0) {
395
+ lines.push(` [V in ${versionUnion}]: Record<string, never>;`);
418
396
  } else {
419
- const union = names.map((n) => `'${n}'`).join(" | ");
420
- lines.push(` ${composerKey}: ${union};`);
397
+ lines.push(` [V in ${versionUnion}]: {`);
398
+ for (const v of variables) {
399
+ lines.push(` ${v}: ${schemaFieldToTsType(schemaMap.get(v))};`);
400
+ }
401
+ lines.push(" };");
421
402
  }
422
403
  }
423
- lines.push(" }");
404
+ lines.push(" };");
405
+ }
406
+ lines.push(" }");
407
+ lines.push(" interface ComposerPromptMap {");
408
+ for (const composer of composers) {
409
+ const names = extractComposerPromptNames(composer);
410
+ const composerKey = typePropertyKey(composer.composerId);
411
+ if (names.length === 0) {
412
+ lines.push(` ${composerKey}: never;`);
413
+ } else {
414
+ const union = names.map((n) => `'${n}'`).join(" | ");
415
+ lines.push(` ${composerKey}: ${union};`);
416
+ }
424
417
  }
418
+ lines.push(" }");
425
419
  lines.push("}");
426
420
  lines.push("");
427
421
  return lines.join("\n");
@@ -473,7 +467,19 @@ var warnMissingProviders = (prompts, composers = []) => {
473
467
  var generate = async (apiKey, outputPath, baseUrl) => {
474
468
  const [prompts, composers] = await Promise.all([
475
469
  fetchAllPrompts(apiKey, baseUrl),
476
- fetchAllComposers(apiKey, baseUrl).catch(() => [])
470
+ fetchAllComposers(apiKey, baseUrl).catch((err) => {
471
+ if (err instanceof PromptlyError) {
472
+ console.warn(
473
+ ` Warning: failed to fetch composers (${err.code}, HTTP ${err.status}): ${err.message}`
474
+ );
475
+ console.warn(
476
+ " Composer types will be omitted from promptly-env.d.ts."
477
+ );
478
+ } else {
479
+ console.warn(` Warning: failed to fetch composers: ${String(err)}`);
480
+ }
481
+ return [];
482
+ })
477
483
  ]);
478
484
  if (prompts.length === 0 && composers.length === 0) {
479
485
  console.log(" No prompts or composers found for this API key.");
package/dist/index.cjs CHANGED
@@ -192,15 +192,25 @@ var preserveEmptyParagraphs = (content) => content.replace(
192
192
  (_, attributes) => `<p${attributes ?? ""}><br></p>`
193
193
  );
194
194
  var preserveTextLineBreaks = (content) => content.replace(/\r\n?/g, "\n").replaceAll("\n", "<br>");
195
+ var isHtmlFormatInput = (input) => typeof input === "object" && input !== null && "html" in input;
195
196
  var formatComposerInput = (input) => {
196
197
  if (typeof input === "string") {
197
198
  return preserveTextLineBreaks(input);
198
199
  }
199
- if ("html" in input) {
200
+ if (isHtmlFormatInput(input)) {
200
201
  return input.html;
201
202
  }
202
203
  return preserveTextLineBreaks(input.text);
203
204
  };
205
+ var STANDALONE_PROMPT_OPEN_PARAGRAPH_REGEX = /<\/p>\s*<p(?:\s[^>]*)?>\s*$/i;
206
+ var STANDALONE_PROMPT_CLOSE_PARAGRAPH_REGEX = /^\s*<\/p>/i;
207
+ var EXPLICIT_SPACER_BEFORE_OPEN_PARAGRAPH_REGEX = /<p(?:\s[^>]*)?>\s*<br\s*\/?>\s*<\/p>\s*<p(?:\s[^>]*)?>\s*$/i;
208
+ var shouldPrefixStandalonePromptText = (previous, next) => {
209
+ if (previous?.type !== "static" || next?.type !== "static") {
210
+ return false;
211
+ }
212
+ return STANDALONE_PROMPT_OPEN_PARAGRAPH_REGEX.test(previous.content) && STANDALONE_PROMPT_CLOSE_PARAGRAPH_REGEX.test(next.content) && !EXPLICIT_SPACER_BEFORE_OPEN_PARAGRAPH_REGEX.test(previous.content);
213
+ };
204
214
  var interpolateStaticSegment = (content, input) => {
205
215
  let result = content;
206
216
  result = result.replace(
@@ -320,7 +330,7 @@ var createPromptlyClient = (config) => {
320
330
  }
321
331
  const formatComposer = (results) => {
322
332
  const parts = [];
323
- for (const seg of processedSegments) {
333
+ for (const [index, seg] of processedSegments.entries()) {
324
334
  if (seg.type === "static") {
325
335
  parts.push(seg.content);
326
336
  continue;
@@ -329,7 +339,12 @@ var createPromptlyClient = (config) => {
329
339
  if (val === void 0) {
330
340
  continue;
331
341
  }
332
- parts.push(formatComposerInput(val));
342
+ const formattedInput = formatComposerInput(val);
343
+ const prefix = isHtmlFormatInput(val) || !shouldPrefixStandalonePromptText(
344
+ processedSegments[index - 1],
345
+ processedSegments[index + 1]
346
+ ) ? "" : "<br>";
347
+ parts.push(`${prefix}${formattedInput}`);
333
348
  }
334
349
  return parts.join("");
335
350
  };
package/dist/index.js CHANGED
@@ -151,15 +151,25 @@ var preserveEmptyParagraphs = (content) => content.replace(
151
151
  (_, attributes) => `<p${attributes ?? ""}><br></p>`
152
152
  );
153
153
  var preserveTextLineBreaks = (content) => content.replace(/\r\n?/g, "\n").replaceAll("\n", "<br>");
154
+ var isHtmlFormatInput = (input) => typeof input === "object" && input !== null && "html" in input;
154
155
  var formatComposerInput = (input) => {
155
156
  if (typeof input === "string") {
156
157
  return preserveTextLineBreaks(input);
157
158
  }
158
- if ("html" in input) {
159
+ if (isHtmlFormatInput(input)) {
159
160
  return input.html;
160
161
  }
161
162
  return preserveTextLineBreaks(input.text);
162
163
  };
164
+ var STANDALONE_PROMPT_OPEN_PARAGRAPH_REGEX = /<\/p>\s*<p(?:\s[^>]*)?>\s*$/i;
165
+ var STANDALONE_PROMPT_CLOSE_PARAGRAPH_REGEX = /^\s*<\/p>/i;
166
+ var EXPLICIT_SPACER_BEFORE_OPEN_PARAGRAPH_REGEX = /<p(?:\s[^>]*)?>\s*<br\s*\/?>\s*<\/p>\s*<p(?:\s[^>]*)?>\s*$/i;
167
+ var shouldPrefixStandalonePromptText = (previous, next) => {
168
+ if (previous?.type !== "static" || next?.type !== "static") {
169
+ return false;
170
+ }
171
+ return STANDALONE_PROMPT_OPEN_PARAGRAPH_REGEX.test(previous.content) && STANDALONE_PROMPT_CLOSE_PARAGRAPH_REGEX.test(next.content) && !EXPLICIT_SPACER_BEFORE_OPEN_PARAGRAPH_REGEX.test(previous.content);
172
+ };
163
173
  var interpolateStaticSegment = (content, input) => {
164
174
  let result = content;
165
175
  result = result.replace(
@@ -279,7 +289,7 @@ var createPromptlyClient = (config) => {
279
289
  }
280
290
  const formatComposer = (results) => {
281
291
  const parts = [];
282
- for (const seg of processedSegments) {
292
+ for (const [index, seg] of processedSegments.entries()) {
283
293
  if (seg.type === "static") {
284
294
  parts.push(seg.content);
285
295
  continue;
@@ -288,7 +298,12 @@ var createPromptlyClient = (config) => {
288
298
  if (val === void 0) {
289
299
  continue;
290
300
  }
291
- parts.push(formatComposerInput(val));
301
+ const formattedInput = formatComposerInput(val);
302
+ const prefix = isHtmlFormatInput(val) || !shouldPrefixStandalonePromptText(
303
+ processedSegments[index - 1],
304
+ processedSegments[index + 1]
305
+ ) ? "" : "<br>";
306
+ parts.push(`${prefix}${formattedInput}`);
292
307
  }
293
308
  return parts.join("");
294
309
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@promptlycms/prompts",
3
- "version": "0.6.0",
3
+ "version": "0.6.1-canary.8246366",
4
4
  "description": "TypeScript SDK for Promptly CMS — fetch prompts, build Zod schemas, generate typed code",
5
5
  "type": "module",
6
6
  "exports": {