@betterstart/cli 0.1.31 → 0.1.32

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/cli.js CHANGED
@@ -2723,6 +2723,10 @@ function generateActions(schema, cwd, actionsDir, options = {}) {
2723
2723
  }
2724
2724
  }
2725
2725
  const populateListRelsFn = hasListRels ? generatePopulateListRelsFunction(allListRelQueries, Singular) : "";
2726
+ const htmlOutputFields = regularDbFields.filter(
2727
+ (f) => (f.type === "richtext" || f.type === "markdown") && f.output === "html"
2728
+ );
2729
+ const hasHtmlOutput = htmlOutputFields.length > 0;
2726
2730
  const hasSlug = regularDbFields.some((f) => f.name === "slug");
2727
2731
  const hasDraft = schema.actions?.draft === true;
2728
2732
  const hasPublished = regularDbFields.some((f) => f.name === "published");
@@ -2769,8 +2773,10 @@ function generateActions(schema, cwd, actionsDir, options = {}) {
2769
2773
  (f) => ` ${quotePropertyName2(f.name)}: ${getFieldType(f, "output")}${f.required ? "" : " | null"}`
2770
2774
  ).join("\n");
2771
2775
  const m2mFieldTypes = m2mFields.map((f) => ` ${quotePropertyName2(f.name)}: number[]`).join("\n");
2776
+ const htmlFieldTypes = htmlOutputFields.map((f) => ` ${f.name}Html: string`).join("\n");
2772
2777
  const dataInterface = `export interface ${Singular}Data {
2773
- ${dataFields}${m2mFieldTypes ? `
2778
+ ${dataFields}${htmlFieldTypes ? `
2779
+ ${htmlFieldTypes}` : ""}${m2mFieldTypes ? `
2774
2780
  ${m2mFieldTypes}` : ""}
2775
2781
  }`;
2776
2782
  const responseInterface = `export interface ${Plural}Response {
@@ -2837,6 +2843,10 @@ ${searchFields.map((f) => ` ilike(${tableVar}.${f}, searchTerm)`).join(
2837
2843
  }`;
2838
2844
  const fieldMeta = createFields.map((f) => `{ name: '${f.name}', type: '${f.type}', required: ${f.required ?? false} }`).join(",\n ");
2839
2845
  const createMappings = createFields.map((f) => ` ${f.name}: ${generateFieldMapping(f)}`).join(",\n");
2846
+ const htmlCreateBlock = hasHtmlOutput ? `
2847
+ const { renderMarkdownSync } = await import('@cms/lib/markdown/render')
2848
+ ` + htmlOutputFields.map((f) => ` const ${f.name}Html = renderMarkdownSync(input.${f.name} || '')`).join("\n") + "\n" : "";
2849
+ const htmlCreateMappings = htmlOutputFields.map((f) => ` ${f.name}Html`).join(",\n");
2840
2850
  const distinctFns = hasFilters ? (schema.filters || []).map(
2841
2851
  (filter) => `
2842
2852
  export async function getDistinct${Plural}${toPascalCase5(filter.field)}(): Promise<string[]> {
@@ -3004,9 +3014,10 @@ export async function create${Singular}(input: Create${Singular}Input): Promise<
3004
3014
  .orderBy(desc(${tableVar}.sortOrder))
3005
3015
  .limit(1)
3006
3016
  const nextSortOrder = (maxSortOrderResult[0]?.maxOrder ?? 0) + 1
3007
-
3017
+ ${htmlCreateBlock}
3008
3018
  const result = await db.insert(${tableVar}).values({
3009
- ${createMappings},${hasDraft ? `
3019
+ ${createMappings},${hasHtmlOutput ? `
3020
+ ${htmlCreateMappings},` : ""}${hasDraft ? `
3010
3021
  published: input.published ?? false,` : ""}
3011
3022
  sortOrder: nextSortOrder,
3012
3023
  createdAt: new Date().toISOString(),
@@ -3046,7 +3057,11 @@ ${autoSlugUpdate}
3046
3057
  processedData[key] = value
3047
3058
  }
3048
3059
  }
3049
-
3060
+ ${hasHtmlOutput ? `
3061
+ const { renderMarkdownSync } = await import('@cms/lib/markdown/render')
3062
+ ` + htmlOutputFields.map((f) => ` if (processedData.${f.name} !== undefined) {
3063
+ processedData.${f.name}Html = renderMarkdownSync(String(processedData.${f.name} || ''))
3064
+ }`).join("\n") + "\n" : ""}
3050
3065
  const result = await db.update(${tableVar})
3051
3066
  .set({ ...processedData, updatedAt: new Date().toISOString() })
3052
3067
  .where(eq(${tableVar}.id, id))
@@ -3150,6 +3165,10 @@ function generateSingleActions(schema, cwd, actionsDir, options = {}) {
3150
3165
  const dbFields = flattenFields(schema.fields).filter(
3151
3166
  (f) => !(f.type === "relationship" && f.multiple === true)
3152
3167
  );
3168
+ const singleHtmlOutputFields = dbFields.filter(
3169
+ (f) => (f.type === "richtext" || f.type === "markdown") && f.output === "html"
3170
+ );
3171
+ const singleHasHtmlOutput = singleHtmlOutputFields.length > 0;
3153
3172
  const allDbFields = [...dbFields];
3154
3173
  if (!dbFields.some((f) => f.name === "createdAt")) {
3155
3174
  allDbFields.push({ name: "createdAt", type: "timestamp", required: true });
@@ -3163,8 +3182,10 @@ function generateSingleActions(schema, cwd, actionsDir, options = {}) {
3163
3182
  const dataFields = allDbFields.map(
3164
3183
  (f) => ` ${quotePropertyName2(f.name)}: ${getFieldType(f, "output")}${f.required ? "" : " | null"}`
3165
3184
  ).join("\n");
3185
+ const singleHtmlFieldTypes = singleHtmlOutputFields.map((f) => ` ${f.name}Html: string`).join("\n");
3166
3186
  const dataInterface = `export interface ${Singular}Data {
3167
- ${dataFields}
3187
+ ${dataFields}${singleHtmlFieldTypes ? `
3188
+ ${singleHtmlFieldTypes}` : ""}
3168
3189
  }`;
3169
3190
  const upsertInterfaceFields = upsertFields.map(
3170
3191
  (f) => ` ${quotePropertyName2(f.name)}${f.required ? "" : "?"}: ${getFieldType(f, "input")}`
@@ -3175,6 +3196,7 @@ ${upsertInterfaceFields}
3175
3196
  const upsertMappings = upsertFields.map((f) => ` ${f.name}: ${generateFieldMapping(f)}`).join(",\n");
3176
3197
  const fieldMeta = upsertFields.map((f) => `{ name: '${f.name}', type: '${f.type}', required: ${f.required ?? false} }`).join(",\n ");
3177
3198
  const cacheTag = `${schema.name}:all`;
3199
+ const singleHtmlUpsertMappings = singleHtmlOutputFields.map((f) => ` ${f.name}Html`).join(",\n");
3178
3200
  const content = `'use server'
3179
3201
 
3180
3202
  import db from '@cms/db'
@@ -3223,14 +3245,18 @@ export async function upsert${Singular}(input: Upsert${Singular}Input): Promise<
3223
3245
  processedData[key] = value
3224
3246
  }
3225
3247
  }
3226
-
3248
+ ${singleHasHtmlOutput ? `
3249
+ const { renderMarkdownSync } = await import('@cms/lib/markdown/render')
3250
+ ` + singleHtmlOutputFields.map((f) => ` if (processedData.${f.name} !== undefined) {
3251
+ processedData.${f.name}Html = renderMarkdownSync(String(processedData.${f.name} || ''))
3252
+ }`).join("\n") + "\n" + singleHtmlOutputFields.map((f) => ` const ${f.name}Html = renderMarkdownSync(input.${f.name} || '')`).join("\n") + "\n" : ""}
3227
3253
  const now = new Date().toISOString()
3228
3254
 
3229
3255
  const result = await db
3230
3256
  .insert(${tableVar})
3231
3257
  .values({
3232
3258
  id: 1,
3233
- ${upsertMappings},
3259
+ ${upsertMappings},${singleHasHtmlOutput ? "\n" + singleHtmlOutputFields.map((f) => ` ${f.name}Html`).join(",\n") + "," : ""}
3234
3260
  createdAt: now,
3235
3261
  updatedAt: now
3236
3262
  })
@@ -4553,7 +4579,14 @@ function generateTableDefinition(schema, requiredImports, needsSql) {
4553
4579
  const fieldDefs = dbFields.map((field) => {
4554
4580
  const drizzleType = toDrizzleType(field, requiredImports);
4555
4581
  const modifiers = getFieldModifiers(field, needsSql);
4556
- return ` ${field.name}: ${drizzleType}${modifiers}`;
4582
+ const line = ` ${field.name}: ${drizzleType}${modifiers}`;
4583
+ if ((field.type === "richtext" || field.type === "markdown") && field.output === "html") {
4584
+ const snakeName = field.name.replace(/([A-Z])/g, "_$1").toLowerCase();
4585
+ requiredImports.add("text");
4586
+ return `${line},
4587
+ ${field.name}Html: text('${snakeName}_html')`;
4588
+ }
4589
+ return line;
4557
4590
  }).join(",\n");
4558
4591
  let publishedField = "";
4559
4592
  if (hasDraftMode && !hasPublishedField) {
@@ -10580,7 +10613,6 @@ function markdownRenderTemplate() {
10580
10613
  return `import { transformerNotationDiff, transformerNotationHighlight } from '@shikijs/transformers'
10581
10614
  import { renderToString } from 'katex'
10582
10615
  import MarkdownIt from 'markdown-it'
10583
- import dollarmath from 'markdown-it-dollarmath'
10584
10616
  import { createHighlighterCoreSync } from 'shiki/core'
10585
10617
  import { createJavaScriptRegexEngine } from 'shiki/engine/javascript'
10586
10618
  import css from 'shiki/langs/css.mjs'
@@ -10668,6 +10700,68 @@ function headingAnchorPlugin(md: MarkdownIt) {
10668
10700
  })
10669
10701
  }
10670
10702
 
10703
+ // --- Inline KaTeX math plugin (replaces markdown-it-dollarmath) ---
10704
+
10705
+ function mathPlugin(md: MarkdownIt) {
10706
+ // Inline: $...$
10707
+ md.inline.ruler.after('escape', 'math_inline', (state, silent) => {
10708
+ if (state.src.charCodeAt(state.pos) !== 0x24) return false
10709
+ if (state.src.charCodeAt(state.pos + 1) === 0x24) return false
10710
+ const start = state.pos + 1
10711
+ let end = start
10712
+ while (end < state.posMax && state.src.charCodeAt(end) !== 0x24) {
10713
+ if (state.src.charCodeAt(end) === 0x5C) end++
10714
+ end++
10715
+ }
10716
+ if (end >= state.posMax) return false
10717
+ const content = state.src.slice(start, end).trim()
10718
+ if (!content) return false
10719
+ if (!silent) {
10720
+ const token = state.push('math_inline', 'math', 0)
10721
+ token.content = content
10722
+ token.markup = '$'
10723
+ }
10724
+ state.pos = end + 1
10725
+ return true
10726
+ })
10727
+
10728
+ md.renderer.rules.math_inline = (tokens, idx) => {
10729
+ return renderToString(tokens[idx].content, { displayMode: false, throwOnError: false, strict: 'ignore' })
10730
+ }
10731
+
10732
+ // Block: $$...$$
10733
+ md.block.ruler.after('blockquote', 'math_block', (state, startLine, endLine, silent) => {
10734
+ const startPos = state.bMarks[startLine] + state.tShift[startLine]
10735
+ if (state.src.charCodeAt(startPos) !== 0x24 || state.src.charCodeAt(startPos + 1) !== 0x24) return false
10736
+ if (silent) return true
10737
+ let nextLine = startLine
10738
+ let found = false
10739
+ while (nextLine < endLine) {
10740
+ nextLine++
10741
+ if (nextLine >= endLine) break
10742
+ const pos = state.bMarks[nextLine] + state.tShift[nextLine]
10743
+ const max = state.eMarks[nextLine]
10744
+ const line = state.src.slice(pos, max).trim()
10745
+ if (line === '$$') { found = true; break }
10746
+ }
10747
+ if (!found) return false
10748
+ const contentLines: string[] = []
10749
+ for (let i = startLine + 1; i < nextLine; i++) {
10750
+ contentLines.push(state.src.slice(state.bMarks[i] + state.tShift[i], state.eMarks[i]))
10751
+ }
10752
+ const token = state.push('math_block', 'math', 0)
10753
+ token.content = contentLines.join('\\n').trim()
10754
+ token.markup = '$$'
10755
+ token.map = [startLine, nextLine + 1]
10756
+ state.line = nextLine + 1
10757
+ return true
10758
+ })
10759
+
10760
+ md.renderer.rules.math_block = (tokens, idx) => {
10761
+ return '<div class="math-display">' + renderToString(tokens[idx].content, { displayMode: true, throwOnError: false, strict: 'ignore' }) + '</div>\\n'
10762
+ }
10763
+ }
10764
+
10671
10765
  // --- Markdown-it Instance ---
10672
10766
 
10673
10767
  const md = MarkdownIt({
@@ -10688,26 +10782,7 @@ const md = MarkdownIt({
10688
10782
  },
10689
10783
  })
10690
10784
  .use(headingAnchorPlugin)
10691
- .use(dollarmath, {
10692
- allow_space: false,
10693
- allow_digits: false,
10694
- double_inline: true,
10695
- allow_labels: true,
10696
- allow_blank_lines: true,
10697
- renderer(content: string, { displayMode }: { displayMode: boolean }) {
10698
- return renderToString(content, {
10699
- displayMode,
10700
- throwOnError: false,
10701
- strict: 'ignore',
10702
- })
10703
- },
10704
- labelNormalizer(label: string) {
10705
- return label.replace(/[\\s]+/g, '-')
10706
- },
10707
- labelRenderer(label: string) {
10708
- return \`<a href="#\${label}" class="mathlabel" title="Permalink to this equation">\xB6</a>\`
10709
- },
10710
- })
10785
+ .use(mathPlugin)
10711
10786
 
10712
10787
  export function renderMarkdownSync(src: string): string {
10713
10788
  const trimmedContent = trimMathBlock(src)
@@ -11560,7 +11635,6 @@ var CORE_DEPS = [
11560
11635
  "@shikijs/transformers",
11561
11636
  "katex",
11562
11637
  "markdown-it",
11563
- "markdown-it-dollarmath",
11564
11638
  // Drag-and-drop
11565
11639
  "@dnd-kit/core",
11566
11640
  "@dnd-kit/sortable",