UNPKG

2.55 kBPlain TextView Raw
1import { dayjs } from '@naturalcycles/time-lib'
2import { Extension, StringSchema } from 'joi'
3import * as Joi from 'joi'
4import { AnySchemaTyped } from './joi.model'
5
6export interface ExtendedStringSchema extends StringSchema, AnySchemaTyped<string> {
7 dateString(min?: string, max?: string): this
8}
9
10export interface DateStringParams {
11 min?: string
12 max?: string
13}
14
15export function stringExtensions(joi: typeof Joi): Extension {
16 return {
17 type: 'string',
18 base: joi.string(),
19 messages: {
20 'string.dateString': '"{{#label}}" must be an ISO8601 date (yyyy-mm-dd)',
21 'string.dateStringMin': '"{{#label}}" must be not earlier than {{#min}}',
22 'string.dateStringMax': '"{{#label}}" must be not later than {{#max}}',
23 'string.dateStringCalendarAccuracy': '"{{#label}}" must be a VALID calendar date',
24 },
25 rules: {
26 dateString: {
27 method(min?: string, max?: string) {
28 // tslint:disable-next-line:no-invalid-this
29 return this.$_addRule({
30 name: 'dateString',
31 args: { min, max } as DateStringParams,
32 })
33 },
34 args: [
35 {
36 name: 'min',
37 ref: true,
38 assert: v => typeof v === 'string',
39 message: 'must be a string',
40 },
41 {
42 name: 'max',
43 ref: true,
44 assert: v => typeof v === 'string',
45 message: 'must be a string',
46 },
47 ],
48 validate(v: string, helpers, args: DateStringParams) {
49 // console.log('dateString validate called', {v, args})
50
51 let err: string | undefined
52 let { min, max } = args
53
54 // Today allows +-14 hours gap to account for different timezones
55 if (max === 'today') {
56 max = dayjs().add(14, 'hour').toISODate()
57 }
58 if (min === 'today') {
59 min = dayjs().subtract(14, 'hour').toISODate()
60 }
61 // console.log('min/max', min, max)
62
63 const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(v)
64 if (!m || m.length <= 1) {
65 err = 'string.dateString'
66 } else if (min && v < min) {
67 err = 'string.dateStringMin'
68 } else if (max && v > max) {
69 err = 'string.dateStringMax'
70 } else if (!dayjs(v).isValid()) {
71 err = 'string.dateStringCalendarAccuracy'
72 }
73
74 if (err) {
75 return helpers.error(err, args)
76 }
77
78 return v // validation passed
79 },
80 },
81 },
82 }
83}