@globalbrain/sefirot 4.31.0 → 4.32.0
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/client.d.ts +5 -0
- package/config/nuxt.d.ts +1 -0
- package/config/nuxt.js +1 -1
- package/config/vite.js +3 -2
- package/lib/components/SActionList.vue +2 -2
- package/lib/components/SActionMenu.vue +4 -4
- package/lib/components/SAvatar.vue +1 -1
- package/lib/components/SAvatarStack.vue +12 -12
- package/lib/components/SButton.vue +5 -7
- package/lib/components/SCard.vue +2 -2
- package/lib/components/SChartBar.vue +37 -12
- package/lib/components/SChartPie.vue +13 -7
- package/lib/components/SControlActionBarCollapse.vue +2 -4
- package/lib/components/SControlInputSearch.vue +7 -2
- package/lib/components/SDataListItem.vue +1 -3
- package/lib/components/SDescAvatar.vue +1 -1
- package/lib/components/SDescDay.vue +2 -2
- package/lib/components/SDescFile.vue +2 -4
- package/lib/components/SDescItem.vue +2 -1
- package/lib/components/SDescLabel.vue +1 -1
- package/lib/components/SDescLink.vue +2 -7
- package/lib/components/SDescPill.vue +2 -4
- package/lib/components/SDescText.vue +2 -2
- package/lib/components/SDropdown.vue +1 -1
- package/lib/components/SDropdownSectionFilter.vue +11 -11
- package/lib/components/SFragment.vue +1 -1
- package/lib/components/SInputAddon.vue +13 -11
- package/lib/components/SInputBase.vue +11 -11
- package/lib/components/SInputCheckbox.vue +6 -3
- package/lib/components/SInputCheckboxes.vue +7 -3
- package/lib/components/SInputDate.vue +3 -5
- package/lib/components/SInputDropdown.vue +26 -28
- package/lib/components/SInputDropdownItem.vue +21 -11
- package/lib/components/SInputFile.vue +9 -6
- package/lib/components/SInputFileUpload.vue +9 -11
- package/lib/components/SInputFileUploadItem.vue +8 -4
- package/lib/components/SInputHMS.vue +3 -1
- package/lib/components/SInputImage.vue +4 -2
- package/lib/components/SInputNumber.vue +9 -10
- package/lib/components/SInputRadio.vue +3 -2
- package/lib/components/SInputRadios.vue +6 -5
- package/lib/components/SInputSegments.vue +5 -7
- package/lib/components/SInputSegmentsOption.vue +1 -2
- package/lib/components/SInputSelect.vue +6 -4
- package/lib/components/SInputSwitch.vue +4 -1
- package/lib/components/SInputSwitches.vue +5 -3
- package/lib/components/SInputText.vue +16 -16
- package/lib/components/SInputTextarea.vue +7 -3
- package/lib/components/SInputYMD.vue +3 -1
- package/lib/components/SLink.vue +2 -2
- package/lib/components/SLocalNav.vue +1 -1
- package/lib/components/SLocalNavActions.vue +1 -1
- package/lib/components/SLocalNavMenu.vue +2 -2
- package/lib/components/SLoginPagePasswordDialog.vue +2 -2
- package/lib/components/SM.vue +1 -1
- package/lib/components/SMFade.vue +1 -1
- package/lib/components/SMarkdown.vue +3 -2
- package/lib/components/SModal.vue +2 -2
- package/lib/components/SSnackbar.vue +2 -2
- package/lib/components/SSteps.vue +6 -6
- package/lib/components/STable.vue +70 -27
- package/lib/components/STableCell.vue +14 -17
- package/lib/components/STableCellAvatars.vue +1 -1
- package/lib/components/STableCellDay.vue +12 -5
- package/lib/components/STableCellNumber.vue +2 -3
- package/lib/components/STableCellPath.vue +2 -2
- package/lib/components/STableCellText.vue +2 -3
- package/lib/components/STableColumn.vue +38 -16
- package/lib/components/STableFooter.vue +10 -2
- package/lib/components/STableHeader.vue +0 -1
- package/lib/components/STableHeaderMenu.vue +4 -4
- package/lib/components/STableHeaderMenuItem.vue +1 -1
- package/lib/components/STooltip.vue +3 -3
- package/lib/composables/Dropdown.ts +10 -1
- package/lib/composables/Error.ts +37 -37
- package/lib/composables/Grid.ts +1 -4
- package/lib/composables/Image.ts +2 -3
- package/lib/composables/Lang.ts +1 -1
- package/lib/composables/Markdown.ts +1 -1
- package/lib/composables/Table.ts +0 -2
- package/lib/composables/Theme.ts +1 -1
- package/lib/composables/Utils.ts +11 -4
- package/lib/composables/Validation.ts +1 -4
- package/lib/http/Http.ts +23 -17
- package/lib/styles/variables-deprecated.css +0 -1
- package/lib/styles/variables.css +16 -16
- package/lib/support/Chart.ts +0 -1
- package/lib/support/DateRange.ts +1 -1
- package/lib/support/Day.ts +12 -65
- package/lib/support/File.ts +7 -16
- package/lib/support/Utils.ts +7 -40
- package/lib/validation/Rule.ts +6 -21
- package/lib/validation/rules/decimal.ts +3 -3
- package/lib/validation/rules/email.ts +1 -1
- package/lib/validation/rules/index.ts +1 -1
- package/lib/validation/rules/negativeInteger.ts +1 -1
- package/lib/validation/rules/positiveInteger.ts +1 -1
- package/lib/validation/rules/requiredHms.ts +2 -2
- package/lib/validation/rules/requiredIf.ts +1 -4
- package/lib/validation/rules/requiredYmd.ts +2 -2
- package/lib/validation/rules/slackChannelName.ts +4 -1
- package/lib/validation/rules/zeroOrNegativeInteger.ts +1 -1
- package/lib/validation/rules/zeroOrPositiveInteger.ts +1 -1
- package/lib/validation/validators/after.ts +1 -5
- package/lib/validation/validators/afterOrEqual.ts +1 -5
- package/lib/validation/validators/before.ts +1 -4
- package/lib/validation/validators/beforeOrEqual.ts +1 -5
- package/lib/validation/validators/decimal.ts +7 -9
- package/lib/validation/validators/email.ts +4 -8
- package/lib/validation/validators/fileExtension.ts +7 -15
- package/lib/validation/validators/hms.ts +26 -15
- package/lib/validation/validators/index.ts +0 -2
- package/lib/validation/validators/maxFileSize.ts +3 -13
- package/lib/validation/validators/maxLength.ts +1 -7
- package/lib/validation/validators/maxTotalFileSize.ts +3 -26
- package/lib/validation/validators/maxValue.ts +2 -6
- package/lib/validation/validators/minLength.ts +1 -7
- package/lib/validation/validators/minValue.ts +2 -6
- package/lib/validation/validators/month.ts +1 -7
- package/lib/validation/validators/negativeInteger.ts +1 -7
- package/lib/validation/validators/positiveInteger.ts +1 -7
- package/lib/validation/validators/required.ts +5 -28
- package/lib/validation/validators/requiredHmsIf.ts +11 -13
- package/lib/validation/validators/requiredIf.ts +5 -11
- package/lib/validation/validators/requiredYmdIf.ts +11 -13
- package/lib/validation/validators/slackChannelName.ts +11 -11
- package/lib/validation/validators/url.ts +7 -5
- package/lib/validation/validators/ymd.ts +36 -30
- package/package.json +38 -38
- package/lib/validation/validators/requiredHms.ts +0 -9
- package/lib/validation/validators/requiredYmd.ts +0 -9
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import { type Day, isDay } from '../../support/Day'
|
|
2
2
|
|
|
3
3
|
export function beforeOrEqual(value: unknown, date: Day): boolean {
|
|
4
|
-
|
|
5
|
-
return false
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
return value.isBefore(date) || value.isSame(date)
|
|
4
|
+
return isDay(value) && isDay(date) && (value.isBefore(date, 'day') || value.isSame(date, 'day'))
|
|
9
5
|
}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import { isNumber, isString } from '../../support/Utils'
|
|
2
|
-
|
|
3
|
-
const regExp = /^[-]?\d*(\.\d+)?$/
|
|
4
|
-
|
|
5
1
|
export function decimal(value: unknown): boolean {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
2
|
+
const num = Number(value)
|
|
3
|
+
return (
|
|
4
|
+
!Number.isNaN(num)
|
|
5
|
+
&& num >= Number.MIN_SAFE_INTEGER
|
|
6
|
+
&& num <= Number.MAX_SAFE_INTEGER
|
|
7
|
+
&& num.toString() === value?.toString().replace(/(?:(\.\d*[1-9])|\.)0+$/, '$1')
|
|
8
|
+
)
|
|
11
9
|
}
|
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
export const hostnameRE = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*?\.(?:xn--[a-z0-9-]{2,59}|[a-z]{2,63})\.?$/i
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
const
|
|
3
|
+
// https://colinhacks.com/essays/reasonable-email-regex
|
|
4
|
+
const emailRE = new RegExp(`^(?!\\.)(?!.+\\.\\.)[\\w'+\\-.]*[\\w'+\\-]@${hostnameRE.source.slice(1)}`, 'i')
|
|
5
5
|
|
|
6
6
|
export function email(value: unknown): boolean {
|
|
7
|
-
|
|
8
|
-
return false
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
return regExp.test(value)
|
|
7
|
+
return typeof value === 'string' && emailRE.test(value)
|
|
12
8
|
}
|
|
@@ -1,20 +1,12 @@
|
|
|
1
|
-
import { getExtension } from '../../support/File'
|
|
2
|
-
import { isFile } from '../../support/Utils'
|
|
3
|
-
|
|
4
1
|
export function fileExtension(value: unknown, extensions: string[]): boolean {
|
|
5
|
-
if (!
|
|
6
|
-
return false
|
|
7
|
-
}
|
|
2
|
+
if (!(value instanceof File)) { return false }
|
|
8
3
|
|
|
9
|
-
|
|
4
|
+
extensions = extensions.map((ext) => ext.toLowerCase())
|
|
5
|
+
const fileExtension = value.name.split('.').pop()!.toLowerCase()
|
|
10
6
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
if (extension === 'jpg') {
|
|
15
|
-
return ['jpg', 'jpeg', 'JPG', 'JPEG'].includes(fileExtension)
|
|
16
|
-
}
|
|
7
|
+
if (fileExtension === 'jpg' || fileExtension === 'jpeg') {
|
|
8
|
+
return extensions.includes('jpg') || extensions.includes('jpeg')
|
|
9
|
+
}
|
|
17
10
|
|
|
18
|
-
|
|
19
|
-
})
|
|
11
|
+
return extensions.includes(fileExtension)
|
|
20
12
|
}
|
|
@@ -1,21 +1,32 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type HmsType } from '../../support/Day'
|
|
2
|
+
import { isObject } from '../../support/Utils'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
return false
|
|
6
|
-
}
|
|
4
|
+
const hourRE = /^(?:[01]?\d|2[0-3])$/
|
|
5
|
+
const minuteAndSecondRE = /^[0-5]?\d$/
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
export function hms(
|
|
8
|
+
value: unknown,
|
|
9
|
+
required: HmsType[] = ['h', 'm', 's'],
|
|
10
|
+
rejectNull = false
|
|
11
|
+
): boolean {
|
|
12
|
+
if (!isObject(value)) { return false }
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
+
const { hour, minute, second } = value
|
|
15
|
+
const requiredSet = new Set(required)
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
return (
|
|
18
|
+
isValidPart(hour, requiredSet.has('h'), hourRE)
|
|
19
|
+
&& isValidPart(minute, requiredSet.has('m'), minuteAndSecondRE)
|
|
20
|
+
&& isValidPart(second, requiredSet.has('s'), minuteAndSecondRE)
|
|
21
|
+
)
|
|
16
22
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
function isValidPart(
|
|
24
|
+
v: unknown,
|
|
25
|
+
req: boolean,
|
|
26
|
+
re: RegExp
|
|
27
|
+
): v is string | null | undefined {
|
|
28
|
+
if (v === undefined) { return !req }
|
|
29
|
+
if (v === null) { return !rejectNull || !req }
|
|
30
|
+
return typeof v === 'string' && re.test(v)
|
|
31
|
+
}
|
|
21
32
|
}
|
|
@@ -18,10 +18,8 @@ export * from './month'
|
|
|
18
18
|
export * from './negativeInteger'
|
|
19
19
|
export * from './positiveInteger'
|
|
20
20
|
export * from './required'
|
|
21
|
-
export * from './requiredHms'
|
|
22
21
|
export * from './requiredHmsIf'
|
|
23
22
|
export * from './requiredIf'
|
|
24
|
-
export * from './requiredYmd'
|
|
25
23
|
export * from './requiredYmdIf'
|
|
26
24
|
export * from './slackChannelName'
|
|
27
25
|
export * from './url'
|
|
@@ -1,17 +1,7 @@
|
|
|
1
|
-
import { isFile } from '../../support/Utils'
|
|
2
|
-
|
|
3
1
|
export function maxFileSize(value: unknown, size: string): boolean {
|
|
4
|
-
if (!
|
|
5
|
-
return false
|
|
6
|
-
}
|
|
2
|
+
if (!(value instanceof File)) { return false }
|
|
7
3
|
|
|
8
|
-
const factor = /gb/i.test(size)
|
|
9
|
-
? 1e9
|
|
10
|
-
: /mb/i.test(size)
|
|
11
|
-
? 1e6
|
|
12
|
-
: /kb/i.test(size)
|
|
13
|
-
? 1e3
|
|
14
|
-
: 1
|
|
4
|
+
const factor = /gb/i.test(size) ? 1e9 : /mb/i.test(size) ? 1e6 : /kb/i.test(size) ? 1e3 : 1
|
|
15
5
|
|
|
16
|
-
return value.size <= factor *
|
|
6
|
+
return value.size <= factor * Number.parseFloat(size.replace(/[^\d.]/g, ''))
|
|
17
7
|
}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { isString } from '../../support/Utils'
|
|
2
|
-
|
|
3
1
|
export function maxLength(value: unknown, length: number): boolean {
|
|
4
|
-
|
|
5
|
-
return false
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
return value.length <= length
|
|
2
|
+
return (typeof value === 'string' || Array.isArray(value)) && value.length <= length
|
|
9
3
|
}
|
|
@@ -1,31 +1,8 @@
|
|
|
1
|
-
import { isFile } from '../../support/Utils'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Validates if the total size of the given files is smaller than the
|
|
5
|
-
* given size.
|
|
6
|
-
*/
|
|
7
1
|
export function maxTotalFileSize(value: unknown, size: string): boolean {
|
|
8
|
-
if (!
|
|
9
|
-
return false
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
if (value.length === 0) {
|
|
13
|
-
return true
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const factor = /gb/i.test(size)
|
|
17
|
-
? 1e9
|
|
18
|
-
: /mb/i.test(size)
|
|
19
|
-
? 1e6
|
|
20
|
-
: /kb/i.test(size)
|
|
21
|
-
? 1e3
|
|
22
|
-
: 1
|
|
2
|
+
if (!Array.isArray(value) || value.some((v) => !(v instanceof File))) { return false }
|
|
23
3
|
|
|
4
|
+
const factor = /gb/i.test(size) ? 1e9 : /mb/i.test(size) ? 1e6 : /kb/i.test(size) ? 1e3 : 1
|
|
24
5
|
const total = value.reduce((total, file) => total + file.size, 0)
|
|
25
6
|
|
|
26
|
-
return total <= factor *
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function isArrayOfFiles(value: unknown): value is File[] {
|
|
30
|
-
return Array.isArray(value) && value.every((v) => isFile(v))
|
|
7
|
+
return total <= factor * Number.parseFloat(size.replace(/[^\d.]/g, ''))
|
|
31
8
|
}
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { decimal } from './decimal'
|
|
2
2
|
|
|
3
3
|
export function maxValue(value: unknown, max: number) {
|
|
4
|
-
|
|
5
|
-
return +value <= max
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
return false
|
|
4
|
+
return (decimal(value) || value instanceof Date) && Number(value) <= max
|
|
9
5
|
}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { isString } from '../../support/Utils'
|
|
2
|
-
|
|
3
1
|
export function minLength(value: unknown, length: number): boolean {
|
|
4
|
-
|
|
5
|
-
return false
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
return value.length >= length
|
|
2
|
+
return (typeof value === 'string' || Array.isArray(value)) && value.length >= length
|
|
9
3
|
}
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { decimal } from './decimal'
|
|
2
2
|
|
|
3
3
|
export function minValue(value: unknown, min: number) {
|
|
4
|
-
|
|
5
|
-
return +value >= min
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
return false
|
|
4
|
+
return (decimal(value) || value instanceof Date) && Number(value) >= min
|
|
9
5
|
}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { isNumber } from '../../support/Utils'
|
|
2
|
-
|
|
3
1
|
export function negativeInteger(value: unknown): boolean {
|
|
4
|
-
|
|
5
|
-
return false
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
return Number.isInteger(value) && value < 0
|
|
2
|
+
return Number.isInteger(value) && value < 0 && value >= Number.MIN_SAFE_INTEGER
|
|
9
3
|
}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { isNumber } from '../../support/Utils'
|
|
2
|
-
|
|
3
1
|
export function positiveInteger(value: unknown): boolean {
|
|
4
|
-
|
|
5
|
-
return false
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
return Number.isInteger(value) && value > 0
|
|
2
|
+
return Number.isInteger(value) && value > 0 && value <= Number.MAX_SAFE_INTEGER
|
|
9
3
|
}
|
|
@@ -1,29 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
if (
|
|
5
|
-
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
return _required(value)
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function _required(value: unknown): boolean {
|
|
12
|
-
if (Array.isArray(value)) {
|
|
13
|
-
return !!value.length
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
if (value == null) {
|
|
17
|
-
return false
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
if (value === false) {
|
|
21
|
-
return true
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if (isDate(value)) {
|
|
25
|
-
return !Number.isNaN(value.getTime())
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return !!String(value).length
|
|
1
|
+
export function required(value: unknown, trim = true): boolean {
|
|
2
|
+
if (value == null) { return false }
|
|
3
|
+
if (typeof value === 'number' || value instanceof Date) { return !Number.isNaN(+value) }
|
|
4
|
+
if (Array.isArray(value)) { return !!value.length }
|
|
5
|
+
return trim ? !!String(value).trim() : !!String(value)
|
|
29
6
|
}
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
import { type HmsType } from '../../support/Day'
|
|
2
|
-
import {
|
|
2
|
+
import { hms } from './hms'
|
|
3
3
|
import { type RequiredIfCondition } from './requiredIf'
|
|
4
4
|
|
|
5
|
-
export async function requiredHmsIf(
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
return requiredHms(value, required)
|
|
16
|
-
}
|
|
5
|
+
export async function requiredHmsIf(
|
|
6
|
+
value: unknown,
|
|
7
|
+
condition: RequiredIfCondition,
|
|
8
|
+
required: HmsType[] = ['h', 'm', 's']
|
|
9
|
+
): Promise<boolean> {
|
|
10
|
+
if (
|
|
11
|
+
(typeof condition === 'boolean' && condition)
|
|
12
|
+
|| (typeof condition === 'string' && condition)
|
|
13
|
+
|| (typeof condition === 'function' && (await condition()))
|
|
14
|
+
) { return hms(value, required, true) }
|
|
17
15
|
|
|
18
16
|
return true
|
|
19
17
|
}
|
|
@@ -3,17 +3,11 @@ import { required } from './required'
|
|
|
3
3
|
export type RequiredIfCondition = boolean | string | (() => boolean) | (() => Promise<boolean>)
|
|
4
4
|
|
|
5
5
|
export async function requiredIf(value: unknown, condition: RequiredIfCondition): Promise<boolean> {
|
|
6
|
-
if (
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return required(value)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
if (typeof condition === 'function' && (await condition())) {
|
|
15
|
-
return required(value)
|
|
16
|
-
}
|
|
6
|
+
if (
|
|
7
|
+
(typeof condition === 'boolean' && condition)
|
|
8
|
+
|| (typeof condition === 'string' && condition)
|
|
9
|
+
|| (typeof condition === 'function' && (await condition()))
|
|
10
|
+
) { return required(value) }
|
|
17
11
|
|
|
18
12
|
return true
|
|
19
13
|
}
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
import { type YmdType } from '../../support/Day'
|
|
2
2
|
import { type RequiredIfCondition } from './requiredIf'
|
|
3
|
-
import {
|
|
3
|
+
import { ymd } from './ymd'
|
|
4
4
|
|
|
5
|
-
export async function requiredYmdIf(
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
return requiredYmd(value, required)
|
|
16
|
-
}
|
|
5
|
+
export async function requiredYmdIf(
|
|
6
|
+
value: unknown,
|
|
7
|
+
condition: RequiredIfCondition,
|
|
8
|
+
required: YmdType[] = ['y', 'm', 'd']
|
|
9
|
+
): Promise<boolean> {
|
|
10
|
+
if (
|
|
11
|
+
(typeof condition === 'boolean' && condition)
|
|
12
|
+
|| (typeof condition === 'string' && condition)
|
|
13
|
+
|| (typeof condition === 'function' && (await condition()))
|
|
14
|
+
) { return ymd(value, required, true) }
|
|
17
15
|
|
|
18
16
|
return true
|
|
19
17
|
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { isString } from '../../support/Utils'
|
|
2
|
-
|
|
3
1
|
export interface SlackChannelNameOptions {
|
|
4
2
|
offset?: number
|
|
5
3
|
}
|
|
6
4
|
|
|
7
|
-
export function slackChannelName(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
5
|
+
export function slackChannelName(
|
|
6
|
+
value: unknown,
|
|
7
|
+
{ offset = 0 }: SlackChannelNameOptions = {}
|
|
8
|
+
): boolean {
|
|
9
|
+
return (
|
|
10
|
+
typeof value === 'string'
|
|
11
|
+
&& /^[\p{L}\p{N}\p{M}_-]+$/u.test(value)
|
|
12
|
+
&& /\p{L}|\p{N}/u.test(value)
|
|
13
|
+
&& value.length <= 80 - offset
|
|
14
|
+
&& value.toLowerCase() === value
|
|
15
|
+
)
|
|
16
16
|
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { hostnameRE } from './email'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const protocolRE = /^https?:$/i
|
|
4
4
|
|
|
5
5
|
export function url(value: unknown): boolean {
|
|
6
|
-
if (
|
|
6
|
+
if (typeof value !== 'string') { return false }
|
|
7
|
+
try {
|
|
8
|
+
const url = new URL(value)
|
|
9
|
+
return protocolRE.test(url.protocol) && hostnameRE.test(url.hostname)
|
|
10
|
+
} catch {
|
|
7
11
|
return false
|
|
8
12
|
}
|
|
9
|
-
|
|
10
|
-
return regExp.test(value)
|
|
11
13
|
}
|
|
@@ -1,32 +1,38 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
export function ymd(
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { type YmdType } from '../../support/Day'
|
|
2
|
+
import { isObject } from '../../support/Utils'
|
|
3
|
+
|
|
4
|
+
export function ymd(
|
|
5
|
+
value: unknown,
|
|
6
|
+
required: YmdType[] = ['y', 'm', 'd'],
|
|
7
|
+
rejectNull = false
|
|
8
|
+
): boolean {
|
|
9
|
+
if (!isObject(value)) { return false }
|
|
10
|
+
|
|
11
|
+
const { year, month, date } = value
|
|
12
|
+
const requiredSet = new Set(required)
|
|
13
|
+
|
|
14
|
+
if (
|
|
15
|
+
!isValidPart(year, requiredSet.has('y'), 1000, 2999)
|
|
16
|
+
|| !isValidPart(month, requiredSet.has('m'), 1, 12)
|
|
17
|
+
|| !isValidPart(date, requiredSet.has('d'), 1, 31)
|
|
18
|
+
) { return false }
|
|
19
|
+
|
|
20
|
+
const now = new Date()
|
|
21
|
+
const y = year ?? now.getFullYear()
|
|
22
|
+
const m = month ?? (year ? 1 : now.getMonth() + 1)
|
|
23
|
+
const d = date ?? (year || month ? 1 : now.getDate())
|
|
24
|
+
|
|
25
|
+
const dt = new Date(y, m - 1, d)
|
|
26
|
+
return dt.getFullYear() === y && dt.getMonth() === m - 1 && dt.getDate() === d
|
|
27
|
+
|
|
28
|
+
function isValidPart(
|
|
29
|
+
v: unknown,
|
|
30
|
+
req: boolean,
|
|
31
|
+
min: number,
|
|
32
|
+
max: number
|
|
33
|
+
): v is number | null | undefined {
|
|
34
|
+
if (v === undefined) { return !req }
|
|
35
|
+
if (v === null) { return !rejectNull || !req }
|
|
36
|
+
return Number.isInteger(v) && v >= min && v <= max
|
|
7
37
|
}
|
|
8
|
-
|
|
9
|
-
return required.every((r) => {
|
|
10
|
-
const _value = value[YmdMap[r]]
|
|
11
|
-
|
|
12
|
-
if (_value === null) {
|
|
13
|
-
return true
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
if (r === 'y') {
|
|
17
|
-
return _value > 0 && _value <= 9999
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
if (r === 'm') {
|
|
21
|
-
return _value > 0 && _value <= 12
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const d = day(new Date(2020, value.month ? value.month - 1 : 1, _value))
|
|
25
|
-
|
|
26
|
-
if (d.month() + 1 !== (value.month ?? 1)) {
|
|
27
|
-
return false
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return d.isValid()
|
|
31
|
-
})
|
|
32
38
|
}
|