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.
- package/dist/assets/adapters/next/templates/init/components/shared/dev-mode/copyable-code-block.tsx +2 -2
- package/dist/assets/adapters/next/templates/init/components/shared/dev-mode/dev-mode-code-mirror.tsx +11 -5
- package/dist/assets/adapters/next/templates/init/lib/actions/media/types.ts +9 -1
- package/dist/assets/adapters/next/templates/init/types/index.ts +2 -0
- package/dist/cli.js +98 -78
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/assets/adapters/next/templates/init/components/shared/dev-mode/copyable-code-block.tsx
CHANGED
|
@@ -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>
|
package/dist/assets/adapters/next/templates/init/components/shared/dev-mode/dev-mode-code-mirror.tsx
CHANGED
|
@@ -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
|
-
|
|
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 {
|
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 =
|
|
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})
|
|
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
|
|
8310
|
-
|
|
8311
|
-
|
|
8312
|
-
|
|
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 { ${
|
|
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<${
|
|
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.
|
|
8388
|
+
const result = await ${ctx.selectClause}.where(eq(${ctx.tableVar}.slug, slug)).limit(1)
|
|
8332
8389
|
if (result.length === 0) return null
|
|
8333
|
-
${ctx.
|
|
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<${
|
|
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)),
|