Skip to content

Commit eb9f8b6

Browse files
authored
fix: syntax error with datetime fields and standardize date/datetime formats (#3698)
1 parent 7cff2b9 commit eb9f8b6

File tree

6 files changed

+55
-16
lines changed

6 files changed

+55
-16
lines changed

playground/content.config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ const collections = {
7878
schema: z.object({
7979
name: z.string(),
8080
email: z.string().email(),
81+
birthday: z.string().date(),
82+
lastloginat: z.string().datetime(),
8183
}),
8284
}),
8385
org: defineCollection({

playground/content/org/people.csv

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
name,email
2-
John Doe,john.doe@example.com
3-
Jane Smith,jane.smith@example.com
4-
Bob Johnson,bob.johnson@example.com
5-
Alice Brown,alice.brown@example.com
6-
Charlie Wilson,charlie.wilson@example.com
7-
Diana Lee,diana.lee@example.com
8-
Eve Davis,eve.davis@example.com
9-
Frank Miller,frank.miller@example.com
10-
Grace Taylor,grace.taylor@example.com
11-
Henry Anderson,henry.anderson@example.com
1+
name,email,birthday,lastloginat
2+
John Doe,john.doe@example.com,1993-01-06,2026-01-24 20:00:00
3+
Jane Smith,jane.smith@example.com,1993-01-06,2026-01-24 20:00:00
4+
Bob Johnson,bob.johnson@example.com,1993-01-06,2026-01-24 20:00:00
5+
Alice Brown,alice.brown@example.com,1993-01-06,2026-01-24 20:00:00
6+
Charlie Wilson,charlie.wilson@example.com,1993-01-06,2026-01-24 20:00:00
7+
Diana Lee,diana.lee@example.com,1993-01-06,2026-01-24 20:00:00
8+
Eve Davis,eve.davis@example.com,1993-01-06,2026-01-24 20:00:00
9+
Frank Miller,frank.miller@example.com,1993-01-06,2026-01-24 20:00:00
10+
Grace Taylor,grace.taylor@example.com,1993-01-06,2026-01-24 20:00:00
11+
Henry Anderson,henry.anderson@example.com,1993-01-06,2026-01-24 20:00:00

src/runtime/internal/preview/collection.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { getOrderedSchemaKeys } from '../schema'
66
import { parseSourceBase } from './utils'
77
import { withoutPrefixNumber, withoutRoot } from './files'
88
import type { CollectionInfo, ResolvedCollectionSource } from '@nuxt/content'
9+
import { formatDate, formatDateTime } from '../../../utils/content/transformers/utils'
910

1011
export const getCollectionByFilePath = (path: string, collections: Record<string, CollectionInfo>): { collection: CollectionInfo | undefined, matchedSource: ResolvedCollectionSource | undefined } => {
1112
let matchedSource: ResolvedCollectionSource | undefined
@@ -131,8 +132,12 @@ function computeValuesBasedOnCollectionSchema(collection: CollectionInfo, data:
131132
// @ts-expect-error format does exist
132133
else if (type === 'string' || ['string', 'enum'].includes(value.type)) {
133134
// @ts-expect-error format does exist
134-
if (['data', 'datetime'].includes(value.format)) {
135-
values.push(valueToInsert !== 'NULL' ? `'${new Date(valueToInsert).toISOString()}'` : defaultValue)
135+
if (value.format === 'date') {
136+
values.push(valueToInsert !== 'NULL' ? `'${formatDate(valueToInsert)}'` : defaultValue)
137+
}
138+
// @ts-expect-error format does exist
139+
else if (value.format === 'datetime') {
140+
values.push(valueToInsert !== 'NULL' ? `'${formatDateTime(valueToInsert)}'` : defaultValue)
136141
}
137142
else {
138143
values.push(`'${String(valueToInsert).replace(/\n/g, '\\n').replace(/'/g, '\'\'')}'`)

src/utils/collection.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { defineLocalSource, defineGitSource } from './source'
66
import { emptyStandardSchema, mergeStandardSchema, metaStandardSchema, pageStandardSchema, infoStandardSchema, detectSchemaVendor, replaceComponentSchemas } from './schema'
77
import { logger } from './dev'
88
import nuxtContentContext from './context'
9+
import { formatDate, formatDateTime } from './content/transformers/utils'
910

1011
export function getTableName(name: string) {
1112
return `_content_${name}`
@@ -175,7 +176,10 @@ export function generateCollectionInsert(collection: ResolvedCollection, data: P
175176
values.push(Number(valueToInsert))
176177
}
177178
else if (property?.sqlType === 'DATE') {
178-
values.push(`'${new Date(valueToInsert as string).toISOString()}'`)
179+
values.push(`'${formatDate(valueToInsert as string)}'`)
180+
}
181+
else if (property?.sqlType === 'DATETIME') {
182+
values.push(`'${formatDateTime(valueToInsert as string)}'`)
179183
}
180184
else if (property?.enum) {
181185
values.push(`'${String(valueToInsert).replace(/\n/g, '\\n').replace(/'/g, '\'\'')}'`)

src/utils/content/transformers/utils.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,29 @@ import type { ContentTransformer } from '../../../types/content'
33
export const defineTransformer = (transformer: ContentTransformer) => {
44
return transformer
55
}
6+
7+
export const formatDateTime = (datetime: string): string => {
8+
const d = new Date(datetime)
9+
if (Number.isNaN(d.getTime())) {
10+
throw new TypeError(`Invalid datetime value: "${datetime}"`)
11+
}
12+
13+
const hours = d.getHours()
14+
const minutes = d.getMinutes()
15+
const seconds = d.getSeconds()
16+
17+
return `${formatDate(datetime)} ${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`
18+
}
19+
20+
export const formatDate = (date: string): string => {
21+
const d = new Date(date)
22+
if (Number.isNaN(d.getTime())) {
23+
throw new TypeError(`Invalid date value: "${date}"`)
24+
}
25+
26+
const year = d.getFullYear()
27+
const month = d.getMonth() + 1
28+
const day = d.getDate()
29+
30+
return `${year.toString().padStart(4, '0')}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`
31+
}

test/unit/generateCollectionInsert.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ describe('generateCollectionInsert', () => {
1717
otherField: z.string().default('untitled'),
1818
otherField2: z.boolean().default(true),
1919
date: z.date().default(new Date('2022-01-01')),
20+
dateString: z.string().date().default('2022-01-01'),
21+
datetimeString: z.string().datetime().default('2022-01-01 20:00:00'),
2022
object: z.object({ foo: z.string() }).default(() => ({ foo: 'bar' })),
2123
array: z.array(z.string()).default(() => []),
2224
}),
@@ -31,7 +33,7 @@ describe('generateCollectionInsert', () => {
3133
expect(sql[0]).toBe([
3234
`INSERT INTO ${getTableName('content')}`,
3335
' VALUES',
34-
' (\'foo.md\', \'[]\', 13, \'2022-01-01T00:00:00.000Z\', \'md\', \'{}\', \'{"foo":"bar"}\', \'untitled\', true, \'foo\', \'bnUQ85H_Zf72faGIQhV0i9QeTEnf1ueEIaMAO8aAAGw\');',
36+
' (\'foo.md\', \'[]\', 13, \'2022-01-01\', \'2022-01-01\', \'2022-01-01 20:00:00\', \'md\', \'{}\', \'{"foo":"bar"}\', \'untitled\', true, \'foo\', \'qOlPCMRxWbrtFhHMqkJLriaEnrze1H-G48FLCfDo13M\');',
3537
].join(''))
3638
})
3739

@@ -64,7 +66,7 @@ describe('generateCollectionInsert', () => {
6466
expect(sql[0]).toBe([
6567
`INSERT INTO ${getTableName('content')}`,
6668
' VALUES',
67-
' (\'foo.md\', \'["foo"]\', 42, \'2022-01-02T00:00:00.000Z\', \'md\', \'{}\', \'{"foo":"baz"}\', \'foo\', false, \'foo\', \'ImMjHvkHl82Jx1bjlpanb9d3i_HQIbjNFverKKbZLME\');',
69+
' (\'foo.md\', \'["foo"]\', 42, \'2022-01-02\', \'md\', \'{}\', \'{"foo":"baz"}\', \'foo\', false, \'foo\', \'uppo29zBKkTDGdRbmj29XkaEcWcpEnA1UYLgajzyWw0\');',
6870
].join(''))
6971
})
7072

0 commit comments

Comments
 (0)