betterstart-cli 0.0.3 → 0.0.5

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.
@@ -66,7 +66,7 @@ export function CopyableCodeBlock({ label, code, language, tabs }: CopyableCodeB
66
66
 
67
67
  {codeTabs.map((tab) => (
68
68
  <TabsContent key={tab.id} value={tab.id} className="min-h-0 overflow-auto">
69
- <CardContent className="p-0 overflow-auto">
69
+ <CardContent className="p-0 overflow-auto select-text">
70
70
  <React.Suspense fallback={<PlainCodeFallback code={tab.code} />}>
71
71
  <LazyCodeMirror code={tab.code} language={tab.language} theme={codeTheme} />
72
72
  </React.Suspense>
@@ -92,7 +92,7 @@ export function CopyableCodeBlock({ label, code, language, tabs }: CopyableCodeB
92
92
  {isCopied ? <Check /> : <Copy />}
93
93
  </Button>
94
94
  </CardHeader>
95
- <CardContent className="p-0 overflow-auto">
95
+ <CardContent className="p-0 overflow-auto select-text">
96
96
  <React.Suspense fallback={<PlainCodeFallback code={code} />}>
97
97
  <LazyCodeMirror code={code} language={language} theme={codeTheme} />
98
98
  </React.Suspense>
@@ -19,10 +19,20 @@ const compactCodeTheme = EditorView.theme({
19
19
  '&': {
20
20
  fontSize: '12px'
21
21
  },
22
+ '.cm-editor': {
23
+ userSelect: 'text'
24
+ },
22
25
  '.cm-content': {
26
+ userSelect: 'text',
23
27
  padding: '10px 0 14px'
24
28
  },
29
+ '.cm-scroller': {
30
+ userSelect: 'text',
31
+ fontFamily:
32
+ 'ui-monospace, SFMono-Regular, "SF Mono", Consolas, "Liberation Mono", Menlo, monospace'
33
+ },
25
34
  '.cm-gutters': {
35
+ userSelect: 'none',
26
36
  padding: '0 0 14px'
27
37
  },
28
38
  '.cm-content, .cm-gutters': {
@@ -33,10 +43,6 @@ const compactCodeTheme = EditorView.theme({
33
43
  },
34
44
  '.cm-line': {
35
45
  padding: '0 16px'
36
- },
37
- '.cm-scroller': {
38
- fontFamily:
39
- 'ui-monospace, SFMono-Regular, "SF Mono", Consolas, "Liberation Mono", Menlo, monospace'
40
46
  }
41
47
  })
42
48
 
@@ -58,8 +64,8 @@ export default function DevModeCodeMirror({ code, language, theme }: DevModeCode
58
64
  return (
59
65
  <CodeMirror
60
66
  value={code}
61
- editable={false}
62
67
  readOnly
68
+ className="select-text"
63
69
  basicSetup={codeMirrorSetup}
64
70
  extensions={extensions}
65
71
  theme={theme === 'dark' ? githubDark : githubLight}
@@ -2,7 +2,15 @@ import type { AdminMedia } from '@admin/types'
2
2
 
3
3
  export type CreateMediaInput = Omit<
4
4
  AdminMedia,
5
- 'id' | 'createdAt' | 'updatedAt' | 'createdBy' | 'updatedBy' | 'createdByUser' | 'updatedByUser'
5
+ | 'id'
6
+ | 'createdAt'
7
+ | 'updatedAt'
8
+ | 'createdAtFormatted'
9
+ | 'updatedAtFormatted'
10
+ | 'createdBy'
11
+ | 'updatedBy'
12
+ | 'createdByUser'
13
+ | 'updatedByUser'
6
14
  >
7
15
 
8
16
  export interface CreateMediaResult {
@@ -20,6 +20,8 @@ export interface AdminMedia {
20
20
  tags: string[] | null
21
21
  createdAt: string
22
22
  updatedAt: string
23
+ createdAtFormatted?: string
24
+ updatedAtFormatted?: string
23
25
  createdBy: string | null
24
26
  updatedBy: string | null
25
27
  createdByUser?: AdminUserSummary | null
package/dist/cli.js CHANGED
@@ -3892,12 +3892,17 @@ function buildResultMapping(allDbFields, relationshipFields, Plural, camelPlural
3892
3892
  ` const createdByUser = row.createdByUser as { id?: string | null; name?: string | null; email?: string | null } | null | undefined`,
3893
3893
  ` const updatedByUser = row.updatedByUser as { id?: string | null; name?: string | null; email?: string | null } | null | undefined`
3894
3894
  ].filter(Boolean).join("\n");
3895
+ const mappedTimestampFields = allDbFields.some((f) => f.name === "createdAtFormatted") ? [] : [
3896
+ ` createdAtFormatted: formatActionDate(row.createdAt)`,
3897
+ ` updatedAtFormatted: formatActionDate(row.updatedAt)`
3898
+ ];
3895
3899
  const rowMappings = allDbFields.map((f) => {
3896
3900
  if (f.type === "relationship" && !f.multiple) {
3897
3901
  return ` ${f.name}: ${f.name}?.id ? { id: ${f.name}.id, name: ${f.name}.name ?? undefined, title: ${f.name}.title ?? undefined, slug: ${f.name}.slug ?? undefined, label: ${f.name}.label ?? undefined } : null`;
3898
3902
  }
3899
3903
  return ` ${f.name}: row.${f.name}`;
3900
3904
  }).concat([
3905
+ ...mappedTimestampFields,
3901
3906
  ` createdByUser: createdByUser?.id ? { id: createdByUser.id, name: createdByUser.name ?? '', email: createdByUser.email ?? '' } : null`,
3902
3907
  ` updatedByUser: updatedByUser?.id ? { id: updatedByUser.id, name: updatedByUser.name ?? '', email: updatedByUser.email ?? '' } : null`
3903
3908
  ]).join(",\n");
@@ -3938,9 +3943,14 @@ function buildSingleRowMapping(allDbFields, _relationshipFields, typeName, htmlF
3938
3943
  return ` ${f.name}: row.${f.name}`;
3939
3944
  });
3940
3945
  const htmlMappings = htmlFields.map((f) => ` ${f.name}Html: row.${f.name}Html`);
3946
+ const singleTimestampFields = allDbFields.some((f) => f.name === "createdAtFormatted") ? [] : [
3947
+ ` createdAtFormatted: formatActionDate(row.createdAt)`,
3948
+ ` updatedAtFormatted: formatActionDate(row.updatedAt)`
3949
+ ];
3941
3950
  const mappings = [
3942
3951
  ...fieldMappings,
3943
3952
  ...htmlMappings,
3953
+ ...singleTimestampFields,
3944
3954
  ` createdByUser: row.createdByUser?.id ? { id: row.createdByUser.id, name: row.createdByUser.name, email: row.createdByUser.email } : null`,
3945
3955
  ` updatedByUser: row.updatedByUser?.id ? { id: row.updatedByUser.id, name: row.updatedByUser.name, email: row.updatedByUser.email } : null`
3946
3956
  ].join(",\n");
@@ -4172,6 +4182,7 @@ var SINGLE_ACTION_FIELD_EXCLUSIONS = /* @__PURE__ */ new Set(["id", "createdAt",
4172
4182
  var DEFAULT_ADMIN_IMPORT_ALIAS = "@admin";
4173
4183
  var SAMPLE_UUID = "00000000-0000-4000-8000-000000000001";
4174
4184
  var SINGLETON_ID = "00000000-0000-0000-0000-000000000001";
4185
+ var SAMPLE_FORMATTED_TIMESTAMP = "Jan 01, 2026";
4175
4186
  function isActionField(field, exclusions) {
4176
4187
  return !field.primaryKey && !exclusions.has(field.name) && !isAuthorshipFieldName(field.name) && !isLayoutField(field.type);
4177
4188
  }
@@ -4354,6 +4365,8 @@ function sampleAdminMedia() {
4354
4365
  tags: ["example"],
4355
4366
  createdAt: "2026-01-01T00:00:00.000Z",
4356
4367
  updatedAt: "2026-01-01T00:00:00.000Z",
4368
+ createdAtFormatted: SAMPLE_FORMATTED_TIMESTAMP,
4369
+ updatedAtFormatted: SAMPLE_FORMATTED_TIMESTAMP,
4357
4370
  createdBy: "user-id",
4358
4371
  updatedBy: "user-id"
4359
4372
  };
@@ -4392,7 +4405,7 @@ function createEntityDataObject(schema) {
4392
4405
  return field.type === "image" || field.type === "video" || field.type === "media";
4393
4406
  });
4394
4407
  const galleryFields = regularDbFields.filter((field) => field.type === "gallery");
4395
- return {
4408
+ return addFormattedTimestamps({
4396
4409
  ...Object.fromEntries(allDbFields.map((field) => [field.name, sampleSchemaOutputValue(field)])),
4397
4410
  ...Object.fromEntries(
4398
4411
  htmlOutputFields.map((field) => [
@@ -4407,7 +4420,17 @@ function createEntityDataObject(schema) {
4407
4420
  ),
4408
4421
  createdByUser: sampleAdminUserSummary(),
4409
4422
  updatedByUser: sampleAdminUserSummary()
4410
- };
4423
+ });
4424
+ }
4425
+ function addFormattedTimestamps(data) {
4426
+ const output = { ...data };
4427
+ if (typeof output.createdAt === "string") {
4428
+ output.createdAtFormatted = SAMPLE_FORMATTED_TIMESTAMP;
4429
+ }
4430
+ if (typeof output.updatedAt === "string") {
4431
+ output.updatedAtFormatted = SAMPLE_FORMATTED_TIMESTAMP;
4432
+ }
4433
+ return output;
4411
4434
  }
4412
4435
  function getSingleAllDbFields(schema) {
4413
4436
  const dbFields = flattenFields(schema.fields).filter(
@@ -4430,7 +4453,7 @@ function getSingleAllDbFields(schema) {
4430
4453
  function createSingleDataObject(schema) {
4431
4454
  const dbFields = getSingleAllDbFields(schema);
4432
4455
  const htmlOutputFields = getHtmlOutputFields(dbFields);
4433
- return {
4456
+ return addFormattedTimestamps({
4434
4457
  ...Object.fromEntries(dbFields.map((field) => [field.name, sampleSingleOutputValue(field)])),
4435
4458
  ...Object.fromEntries(
4436
4459
  htmlOutputFields.map((field) => [
@@ -4440,7 +4463,7 @@ function createSingleDataObject(schema) {
4440
4463
  ),
4441
4464
  createdByUser: sampleAdminUserSummary(),
4442
4465
  updatedByUser: sampleAdminUserSummary()
4443
- };
4466
+ });
4444
4467
  }
4445
4468
  function createFormSubmissionObject(fields) {
4446
4469
  return {
@@ -7935,7 +7958,6 @@ function genTypesContent(ctx) {
7935
7958
  }
7936
7959
  const parts = [
7937
7960
  ctx.dataInterface,
7938
- ctx.displayDataInterface || null,
7939
7961
  ctx.responseInterface,
7940
7962
  ctx.filtersInterface,
7941
7963
  ctx.hasCreatableSelectFields ? buildSelectOptionTypes(ctx) : null,
@@ -8022,6 +8044,19 @@ function genHelpersContent(ctx) {
8022
8044
  lines.push(`import type { AdminMedia } from '@admin/types'`);
8023
8045
  }
8024
8046
  lines.push(`import type { ${ctx.Singular} } from './types'`);
8047
+ lines.push("");
8048
+ lines.push(`export function formatActionDate(value: unknown): string {
8049
+ if (typeof value !== 'string') return ''
8050
+ const date = new Date(value)
8051
+ if (Number.isNaN(date.getTime())) return ''
8052
+
8053
+ return date.toLocaleDateString('en-US', {
8054
+ month: 'short',
8055
+ day: '2-digit',
8056
+ year: 'numeric',
8057
+ timeZone: 'UTC'
8058
+ })
8059
+ }`);
8025
8060
  lines.push("");
8026
8061
  if (ctx.hasListRels) {
8027
8062
  const exportedFn = ctx.populateListRelsFn.replace("async function", "export async function").trim();
@@ -8134,10 +8169,32 @@ function generateResolveMediaFunction(ctx) {
8134
8169
  }`
8135
8170
  ).join("\n");
8136
8171
  const assignSingle = singleFields.map(
8137
- (name) => ` row.${name}Media = (row.${name} && !row.${name}.startsWith('http')) ? mediaMap.get(row.${name}) ?? null : null`
8172
+ (name) => ` row.${name}Media = row.${name} && !row.${name}.startsWith('http')
8173
+ ? (() => {
8174
+ const media = mediaMap.get(row.${name})
8175
+ if (!media) return null
8176
+ return {
8177
+ ...media,
8178
+ createdAtFormatted: formatActionDate(media.createdAt),
8179
+ updatedAtFormatted: formatActionDate(media.updatedAt)
8180
+ }
8181
+ })()
8182
+ : null`
8138
8183
  ).join("\n");
8139
8184
  const assignArray = arrayFields.map(
8140
- (name) => ` row.${name}Media = Array.isArray(row.${name}) ? row.${name}.map((id: string) => mediaMap.get(id)).filter(Boolean) as AdminMedia[] : []`
8185
+ (name) => ` row.${name}Media = Array.isArray(row.${name})
8186
+ ? row.${name}
8187
+ .map((id: string) => {
8188
+ const media = mediaMap.get(id)
8189
+ if (!media) return null
8190
+ return {
8191
+ ...media,
8192
+ createdAtFormatted: formatActionDate(media.createdAt),
8193
+ updatedAtFormatted: formatActionDate(media.updatedAt)
8194
+ }
8195
+ })
8196
+ .filter(Boolean) as AdminMedia[]
8197
+ : []`
8141
8198
  ).join("\n");
8142
8199
  return `export async function resolve${ctx.Singular}MediaFields(rows: ${ctx.Singular}[]): Promise<${ctx.Singular}[]> {
8143
8200
  if (rows.length === 0) return rows
@@ -8177,7 +8234,7 @@ function genGetPluralContent(ctx) {
8177
8234
  if (ctx.hasRelationships) drizzle.push("eq");
8178
8235
  const sortedDrizzle = [...new Set(drizzle)].sort();
8179
8236
  const typeImports = [`${ctx.Plural}Page`, `${ctx.Plural}Query`, `${ctx.Singular}`];
8180
- const helperImports = [];
8237
+ const helperImports = ["formatActionDate"];
8181
8238
  if (ctx.hasListRels) helperImports.push(`populate${ctx.Singular}ListRelationships`);
8182
8239
  if (ctx.hasMediaFields) helperImports.push(`resolve${ctx.Singular}MediaFields`);
8183
8240
  const populateImport = helperImports.length > 0 ? `
@@ -8267,7 +8324,7 @@ function genGetByIdContent(ctx) {
8267
8324
  const dbImports = [ctx.tableVar, "user", ...ctx.relTableImports].sort();
8268
8325
  const drizzle = ["eq"];
8269
8326
  const sortedDrizzle = [...new Set(drizzle)].sort();
8270
- const byIdHelperImports = [];
8327
+ const byIdHelperImports = ["formatActionDate"];
8271
8328
  if (ctx.hasListRels) byIdHelperImports.push(`populate${ctx.Singular}ListRelationships`);
8272
8329
  if (ctx.hasMediaFields) byIdHelperImports.push(`resolve${ctx.Singular}MediaFields`);
8273
8330
  const populateImport = byIdHelperImports.length > 0 ? `
@@ -8302,14 +8359,14 @@ export async function get${ctx.Singular}ById(id: string): Promise<${ctx.Singular
8302
8359
  }
8303
8360
  function genGetBySlugContent(ctx) {
8304
8361
  if (!ctx.hasSlug) return null;
8305
- const returnType = ctx.hasHtmlOutput ? `${ctx.Singular}View` : `${ctx.Singular}`;
8306
8362
  const dbImports = [ctx.tableVar, "user", ...ctx.relTableImports].sort();
8307
8363
  const drizzle = ["eq"];
8308
8364
  const sortedDrizzle = [...new Set(drizzle)].sort();
8309
- const typeImport = ctx.hasHtmlOutput ? `${ctx.Singular}View` : `${ctx.Singular}`;
8310
- const extraTypes = ctx.hasListRels && ctx.hasHtmlOutput ? `, ${ctx.Singular}` : "";
8311
- const populateImport = ctx.hasListRels ? `
8312
- import { populate${ctx.Singular}ListRelationships } from './helpers'` : "";
8365
+ const bySlugHelperImports = ["formatActionDate"];
8366
+ if (ctx.hasListRels) bySlugHelperImports.push(`populate${ctx.Singular}ListRelationships`);
8367
+ if (ctx.hasMediaFields) bySlugHelperImports.push(`resolve${ctx.Singular}MediaFields`);
8368
+ const populateImport = bySlugHelperImports.length > 0 ? `
8369
+ import { ${bySlugHelperImports.join(", ")} } from './helpers'` : "";
8313
8370
  return `'use server'
8314
8371
 
8315
8372
  import db from '@admin/db'
@@ -8318,19 +8375,19 @@ import { ${sortedDrizzle.join(", ")} } from 'drizzle-orm'
8318
8375
  import { alias } from 'drizzle-orm/pg-core'
8319
8376
  ${ctx.cacheReadImport}
8320
8377
  import { ${ctx.camelPlural}CacheTags } from './types'
8321
- import type { ${typeImport}${extraTypes} } from './types'${populateImport}
8378
+ import type { ${ctx.Singular} } from './types'${populateImport}
8322
8379
 
8323
8380
  ${buildAuthorshipAliasBlock()}
8324
8381
 
8325
- export async function get${ctx.Singular}BySlug(slug: string): Promise<${returnType} | null> {
8382
+ export async function get${ctx.Singular}BySlug(slug: string): Promise<${ctx.Singular} | null> {
8326
8383
  'use cache'${ctx.cacheLifeLine}
8327
8384
  cacheTag(${ctx.camelPlural}CacheTags.bySlug(slug))
8328
8385
  cacheTag(${ctx.camelPlural}CacheTags.all)
8329
8386
 
8330
8387
  try {
8331
- const result = await ${ctx.displaySelectClause}.where(eq(${ctx.tableVar}.slug, slug)).limit(1)
8388
+ const result = await ${ctx.selectClause}.where(eq(${ctx.tableVar}.slug, slug)).limit(1)
8332
8389
  if (result.length === 0) return null
8333
- ${ctx.displaySingleRowReturn}
8390
+ ${ctx.singleRowReturn}
8334
8391
  } catch (error) {
8335
8392
  console.error('Error fetching ${ctx.singular} by slug:', error)
8336
8393
  return null
@@ -9213,7 +9270,6 @@ function genBarrelContent(files, ctx) {
9213
9270
  const lines = [];
9214
9271
  const typeNames = [
9215
9272
  `${ctx.Singular}`,
9216
- ctx.hasHtmlOutput ? `${ctx.Singular}View` : null,
9217
9273
  `${ctx.Plural}Page`,
9218
9274
  `${ctx.Plural}Query`,
9219
9275
  `${ctx.Singular}CreateInput`,
@@ -9790,27 +9846,18 @@ function buildEntityContext(schema, nextMajorVersion) {
9790
9846
  const mediaTypeImport = hasMediaFields ? `
9791
9847
  import type { AdminMedia } from '@admin/types'
9792
9848
  ` : "";
9849
+ const hasTimestampFields = allDbFields.some((f) => f.name === "createdAt") && allDbFields.some((f) => f.name === "updatedAt");
9850
+ const hasFormattedTimestampFields = allDbFields.some((f) => f.name === "createdAtFormatted");
9851
+ const timestampFields = hasTimestampFields && !hasFormattedTimestampFields ? "\n createdAtFormatted: string\n updatedAtFormatted: string" : "";
9793
9852
  const dataInterface = `${mediaTypeImport}${buildAuthorshipUserType()}
9794
9853
 
9795
9854
  export interface ${Singular} {
9796
9855
  ${dataFields}${htmlFieldTypes ? `
9797
9856
  ${htmlFieldTypes}` : ""}${m2mFieldTypes ? `
9798
9857
  ${m2mFieldTypes}` : ""}${mediaCompanionTypes ? `
9799
- ${mediaCompanionTypes}` : ""}
9858
+ ${mediaCompanionTypes}` : ""}${timestampFields}
9800
9859
  ${buildAuthorshipDataFields()}
9801
9860
  }`;
9802
- const displayDbFields = allDbFields.filter(
9803
- (f) => !htmlOutputFields.some((h) => h.name === f.name)
9804
- );
9805
- const displayDataFields = displayDbFields.map(
9806
- (f) => ` ${quotePropertyName(f.name)}: ${getFieldType(f, "output")}${f.required || f.primaryKey ? "" : " | null"}`
9807
- ).join("\n");
9808
- const displayDataInterface = hasHtmlOutput ? `export interface ${Singular}View {
9809
- ${displayDataFields}${htmlFieldTypes ? `
9810
- ${htmlFieldTypes}` : ""}${m2mFieldTypes ? `
9811
- ${m2mFieldTypes}` : ""}
9812
- ${buildAuthorshipDataFields()}
9813
- }` : "";
9814
9861
  const responseInterface = `export interface ${Plural}Page {
9815
9862
  ${camelPlural}: ${Singular}[]
9816
9863
  total: number
@@ -9870,20 +9917,6 @@ ${updateInterfaceFields}${hasDraft ? `
9870
9917
  authorshipSelects,
9871
9918
  authorshipJoins
9872
9919
  ) : buildExplicitSelect(listDbFields, tableVar, [], authorshipSelects, authorshipJoins) : selectClause;
9873
- const displaySelectClause = hasHtmlOutput && hasSlug ? hasRelationships ? buildRelationshipSelect(
9874
- displayDbFields,
9875
- relationshipFields,
9876
- tableVar,
9877
- htmlOutputFields,
9878
- authorshipSelects,
9879
- authorshipJoins
9880
- ) : buildExplicitSelect(
9881
- displayDbFields,
9882
- tableVar,
9883
- htmlOutputFields,
9884
- authorshipSelects,
9885
- authorshipJoins
9886
- ) : selectClause;
9887
9920
  const filterConditions = filterableFields.map((f) => {
9888
9921
  if (dateRangeFilterFields.has(f.name)) {
9889
9922
  return ` if (query?.${f.name}) {
@@ -9974,23 +10007,6 @@ ${searchFields.map((f) => ` ilike(${tableVar}.${f}, searchTerm)`).join(
9974
10007
  const singleRowReturn = hasMediaFields ? `${baseSingleRowReturn.replace(/return ([\s\S]+)$/, `const singleRow = $1
9975
10008
  const [resolved] = await resolve${Singular}MediaFields([singleRow])
9976
10009
  return resolved`)}` : baseSingleRowReturn;
9977
- const displaySingleRowReturn = hasHtmlOutput ? (() => {
9978
- const displayType = `${Singular}View`;
9979
- if (hasRelationships && hasListRels) {
9980
- return `const row = result[0]
9981
- return await populate${Singular}ListRelationships(${buildSingleRowMapping(displayDbFields, relationshipFields, Singular, htmlOutputFields)}) as unknown as ${displayType}`;
9982
- }
9983
- if (hasRelationships) {
9984
- return `const row = result[0]
9985
- return ${buildSingleRowMapping(displayDbFields, relationshipFields, displayType, htmlOutputFields)}`;
9986
- }
9987
- if (hasListRels) {
9988
- return `const row = result[0]
9989
- return await populate${Singular}ListRelationships(${buildSingleRowMapping(displayDbFields, relationshipFields, Singular, htmlOutputFields)}) as unknown as ${displayType}`;
9990
- }
9991
- return `const row = result[0]
9992
- return ${buildSingleRowMapping(displayDbFields, relationshipFields, displayType, htmlOutputFields)}`;
9993
- })() : singleRowReturn;
9994
10010
  const nextMajor = nextMajorVersion ?? 16;
9995
10011
  const cacheInvalidationFn = nextMajor >= 16 ? "updateTag" : "revalidateTag";
9996
10012
  const cacheReadImport = nextMajor >= 16 ? `import { cacheLife, cacheTag } from 'next/cache'` : `import { unstable_cacheTag as cacheTag } from 'next/cache'`;
@@ -10029,20 +10045,17 @@ ${searchFields.map((f) => ` ilike(${tableVar}.${f}, searchTerm)`).join(
10029
10045
  relTableImports,
10030
10046
  listRelTableImports,
10031
10047
  dataInterface,
10032
- displayDataInterface,
10033
10048
  responseInterface,
10034
10049
  filtersInterface,
10035
10050
  createInterface,
10036
10051
  updateInterface,
10037
10052
  selectClause,
10038
10053
  listSelectClause,
10039
- displaySelectClause,
10040
10054
  filterConditions,
10041
10055
  searchBlock,
10042
10056
  resultMapping,
10043
10057
  listResultMapping,
10044
10058
  singleRowReturn,
10045
- displaySingleRowReturn,
10046
10059
  fieldMeta,
10047
10060
  createMappings,
10048
10061
  htmlCreateBlock,
@@ -10119,6 +10132,9 @@ function generateSingleActions(schema, actionsDir, options = {}) {
10119
10132
  (f) => ` ${quotePropertyName(f.name)}: ${getFieldType(f, "output")}${f.required || f.primaryKey ? "" : " | null"}`
10120
10133
  ).join("\n");
10121
10134
  const htmlFieldTypes = htmlOutputFields.map((f) => ` ${f.name}Html: string`).join("\n");
10135
+ const hasTimestampFields = allDbFields.some((f) => f.name === "createdAt") && allDbFields.some((f) => f.name === "updatedAt");
10136
+ const hasFormattedTimestampFields = allDbFields.some((f) => f.name === "createdAtFormatted");
10137
+ const timestampFields = hasTimestampFields && !hasFormattedTimestampFields ? "\n createdAtFormatted: string\n updatedAtFormatted: string" : "";
10122
10138
  const upsertInterfaceFields = upsertFields.map((f) => ` ${quotePropertyName(f.name)}?: ${getFieldType(f, "input")}`).join("\n");
10123
10139
  const fieldMeta = upsertFields.map((f) => `{ name: '${f.name}', type: '${f.type}', required: ${f.required ?? false} }`).join(",\n ");
10124
10140
  const cacheTag = `${schema.name}:all`;
@@ -10144,7 +10160,7 @@ function generateSingleActions(schema, actionsDir, options = {}) {
10144
10160
  buildAuthorshipUserType(),
10145
10161
  `export interface ${Singular} {
10146
10162
  ${dataFields}${htmlFieldTypes ? `
10147
- ${htmlFieldTypes}` : ""}
10163
+ ${htmlFieldTypes}` : ""}${timestampFields}
10148
10164
  ${buildAuthorshipDataFields()}
10149
10165
  }`,
10150
10166
  `export interface ${Singular}UpsertInput {
@@ -10186,6 +10202,19 @@ ${buildAuthorshipAliasBlock()}
10186
10202
 
10187
10203
  const SINGLETON_ID = '${singletonId}'
10188
10204
 
10205
+ function formatActionDate(value: unknown): string {
10206
+ if (typeof value !== 'string') return ''
10207
+ const date = new Date(value)
10208
+ if (Number.isNaN(date.getTime())) return ''
10209
+
10210
+ return date.toLocaleDateString('en-US', {
10211
+ month: 'short',
10212
+ day: '2-digit',
10213
+ year: 'numeric',
10214
+ timeZone: 'UTC'
10215
+ })
10216
+ }
10217
+
10189
10218
  export async function get${Singular}(): Promise<${Singular} | null> {
10190
10219
  'use cache'${cacheLifeLine}
10191
10220
  cacheTag(${cacheTagsVar}.all)
@@ -14123,9 +14152,6 @@ function generateHook(schema, hooksDir, options = {}) {
14123
14152
  const Plural = toPascalCase(plural);
14124
14153
  const dbFields = flattenFields(schema.fields);
14125
14154
  const hasSlugField = dbFields.some((f) => f.name === "slug");
14126
- const hasHtmlOutput = dbFields.some(
14127
- (f) => (f.type === "richtext" || f.type === "markdown") && f.output === "html"
14128
- );
14129
14155
  const resolvedFilters = resolveEntityFilters(schema).map((filter) => ({
14130
14156
  ...filter,
14131
14157
  variableName: toCamelCase(filter.key),
@@ -14143,12 +14169,7 @@ function generateHook(schema, hooksDir, options = {}) {
14143
14169
  }
14144
14170
  }
14145
14171
  }
14146
- const typeImports = [
14147
- `type ${Singular}`,
14148
- ...hasHtmlOutput && hasSlugField ? [`type ${Singular}View`] : [],
14149
- `type ${Plural}Page`,
14150
- `type ${Plural}Query`
14151
- ];
14172
+ const typeImports = [`type ${Singular}`, `type ${Plural}Page`, `type ${Plural}Query`];
14152
14173
  const filterParams = hasFilters ? resolvedFilters.flatMap(
14153
14174
  (filter) => filter.type === "date-range" ? [`${filter.fromVariableName}?: string`, `${filter.toVariableName}?: string`] : [`${filter.variableName}?: string`]
14154
14175
  ).join(", ") : "";
@@ -14200,10 +14221,9 @@ export function use${Singular}(id: string | null | undefined): UseQueryResult<${
14200
14221
  enabled: !!id,
14201
14222
  })
14202
14223
  }`;
14203
- const slugReturnType = hasHtmlOutput ? `${Singular}View` : `${Singular}`;
14204
14224
  const slugHook = hasSlugField ? `
14205
14225
 
14206
- export function use${Singular}BySlug(slug: string | null | undefined): UseQueryResult<${slugReturnType} | null, Error> {
14226
+ export function use${Singular}BySlug(slug: string | null | undefined): UseQueryResult<${Singular} | null, Error> {
14207
14227
  return useQuery({
14208
14228
  queryKey: ['${singular}', 'slug', slug],
14209
14229
  queryFn: () => (slug ? get${Singular}BySlug(slug) : Promise.resolve(null)),