@finnair/v-validation-luxon
Advanced tools
Comparing version 1.1.0-alpha.9 to 1.1.0
@@ -6,2 +6,13 @@ # Change Log | ||
# [1.1.0](https://github.com/finnair/v-validation/compare/v1.0.1...v1.1.0) (2022-08-29) | ||
### Features | ||
* Support for Luxon ([94b3806](https://github.com/finnair/v-validation/commit/94b38060e07feeb0abb8c81659d8bda537a4d9aa)) | ||
# [1.1.0-alpha.9](https://github.com/finnair/v-validation/compare/v1.1.0-alpha.8...v1.1.0-alpha.9) (2022-08-19) | ||
@@ -8,0 +19,0 @@ |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const luxon_1 = require("luxon"); | ||
console.log(luxon_1.DateTime.fromFormat('2022-08-19+0', 'yyyy-MM-ddZ').toJSON()); | ||
console.log(luxon_1.DateTime.fromSQL('09:24:15').toJSON()); |
import { ValidationContext, Validator, ValidationResult } from '@finnair/v-validation'; | ||
import { Path } from '@finnair/path'; | ||
import { DateTime } from 'luxon'; | ||
import { DateTime, DateTimeJSOptions, DateTimeOptions } from 'luxon'; | ||
import { LuxonDateTime } from './luxon'; | ||
@@ -11,7 +11,27 @@ export declare type LuxonInput = string | DateTime | LuxonDateTime; | ||
type: string; | ||
proto: any; | ||
pattern: RegExp; | ||
proto?: any; | ||
parser: (value: string, match: RegExpExecArray) => DateTime; | ||
} | ||
export declare function validateLuxon({ value, path, ctx, type, proto, pattern, parser }: ValidateLuxonParams): Promise<ValidationResult>; | ||
declare function localDate(options?: DateTimeOptions): import("@finnair/v-validation").ValidatorFnWrapper; | ||
declare function localTime(options?: DateTimeOptions): import("@finnair/v-validation").ValidatorFnWrapper; | ||
declare function dateTime(options?: DateTimeOptions): import("@finnair/v-validation").ValidatorFnWrapper; | ||
declare function dateTimeUtc(options?: DateTimeOptions): import("@finnair/v-validation").ValidatorFnWrapper; | ||
declare function dateTimeMillis(options?: DateTimeOptions): import("@finnair/v-validation").ValidatorFnWrapper; | ||
declare function dateTimeMillisUtc(options?: DateTimeOptions): import("@finnair/v-validation").ValidatorFnWrapper; | ||
declare function dateTimeFromISO(options?: DateTimeOptions): import("@finnair/v-validation").ValidatorFnWrapper; | ||
declare function dateTimeFromRFC2822(options?: DateTimeOptions): import("@finnair/v-validation").ValidatorFnWrapper; | ||
declare function dateTimeFromHTTP(options?: DateTimeOptions): import("@finnair/v-validation").ValidatorFnWrapper; | ||
declare function dateTimeFromSQL(options?: DateTimeOptions): import("@finnair/v-validation").ValidatorFnWrapper; | ||
export interface ValidateLuxonNumberParams { | ||
value: any; | ||
path: Path; | ||
ctx: ValidationContext; | ||
type: string; | ||
parser: (value: number) => DateTime; | ||
} | ||
export declare function validateLuxonNumber({ value, path, ctx, type, parser }: ValidateLuxonNumberParams): Promise<ValidationResult>; | ||
declare function dateTimeFromMillis(options?: DateTimeJSOptions): import("@finnair/v-validation").ValidatorFnWrapper; | ||
declare function dateTimeFromSeconds(options?: DateTimeJSOptions): import("@finnair/v-validation").ValidatorFnWrapper; | ||
export declare class DurationValidator extends Validator { | ||
@@ -21,9 +41,16 @@ validatePath(value: any, path: Path, ctx: ValidationContext): Promise<ValidationResult>; | ||
export declare const Vluxon: { | ||
localDate: () => import("@finnair/v-validation").ValidatorFnWrapper; | ||
localTime: () => import("@finnair/v-validation").ValidatorFnWrapper; | ||
dateTime: () => import("@finnair/v-validation").ValidatorFnWrapper; | ||
dateTimeUtc: () => import("@finnair/v-validation").ValidatorFnWrapper; | ||
dateTimeMillis: () => import("@finnair/v-validation").ValidatorFnWrapper; | ||
dateTimeMillisUtc: () => import("@finnair/v-validation").ValidatorFnWrapper; | ||
localDate: typeof localDate; | ||
localTime: typeof localTime; | ||
dateTime: typeof dateTime; | ||
dateTimeUtc: typeof dateTimeUtc; | ||
dateTimeMillis: typeof dateTimeMillis; | ||
dateTimeMillisUtc: typeof dateTimeMillisUtc; | ||
dateTimeFromISO: typeof dateTimeFromISO; | ||
dateTimeFromRFC2822: typeof dateTimeFromRFC2822; | ||
dateTimeFromHTTP: typeof dateTimeFromHTTP; | ||
dateTimeFromSQL: typeof dateTimeFromSQL; | ||
dateTimeFromSeconds: typeof dateTimeFromSeconds; | ||
dateTimeFromMillis: typeof dateTimeFromMillis; | ||
duration: () => DurationValidator; | ||
}; | ||
export {}; |
@@ -12,3 +12,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Vluxon = exports.DurationValidator = exports.validateLuxon = void 0; | ||
exports.Vluxon = exports.DurationValidator = exports.validateLuxonNumber = exports.validateLuxon = void 0; | ||
const v_validation_1 = require("@finnair/v-validation"); | ||
@@ -22,3 +22,3 @@ const luxon_1 = require("luxon"); | ||
} | ||
if (value instanceof proto) { | ||
if (proto && value instanceof proto) { | ||
return ctx.success(value); | ||
@@ -28,3 +28,3 @@ } | ||
if (value.isValid) { | ||
return ctx.success(new proto(value)); | ||
return success(value); | ||
} | ||
@@ -37,3 +37,3 @@ } | ||
if (dateTime.isValid) { | ||
return ctx.success(new proto(dateTime)); | ||
return success(dateTime); | ||
} | ||
@@ -43,2 +43,5 @@ } | ||
return ctx.failure(v_validation_1.defaultViolations.date(value, path, type), value); | ||
function success(dateTime) { | ||
return ctx.success(proto ? new proto(dateTime) : dateTime); | ||
} | ||
}); | ||
@@ -48,4 +51,4 @@ } | ||
const datePattern = /^\d{4}-\d{2}-\d{2}$/; | ||
function localDateValidator(value, path, ctx) { | ||
return validateLuxon({ | ||
function localDate(options = { setZone: true }) { | ||
return v_validation_1.V.fn((value, path, ctx) => validateLuxon({ | ||
value, | ||
@@ -58,7 +61,7 @@ path, | ||
parser: (value) => luxon_1.DateTime.fromISO(value, { zone: luxon_1.FixedOffsetZone.utcInstance }), | ||
}); | ||
})); | ||
} | ||
const timePattern = /^\d{2}:\d{2}:\d{2}$/; | ||
function localTimeValidator(value, path, ctx) { | ||
return validateLuxon({ | ||
function localTime(options = { zone: luxon_1.FixedOffsetZone.utcInstance }) { | ||
return v_validation_1.V.fn((value, path, ctx) => validateLuxon({ | ||
value, | ||
@@ -70,8 +73,8 @@ path, | ||
pattern: timePattern, | ||
parser: (value) => luxon_1.DateTime.fromISO(value, { zone: luxon_1.FixedOffsetZone.utcInstance }), | ||
}); | ||
parser: (value) => luxon_1.DateTime.fromISO(value, options), | ||
})); | ||
} | ||
const dateTimePattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:Z|[+-]\d{2}(?::?\d{2})?)$/; | ||
function dateTimeValidator(value, path, ctx) { | ||
return validateLuxon({ | ||
function dateTime(options = { setZone: true }) { | ||
return v_validation_1.V.fn((value, path, ctx) => validateLuxon({ | ||
value, | ||
@@ -83,7 +86,7 @@ path, | ||
pattern: dateTimePattern, | ||
parser: (value) => luxon_1.DateTime.fromISO(value, { setZone: true }), | ||
}); | ||
parser: (value) => luxon_1.DateTime.fromISO(value, options), | ||
})); | ||
} | ||
function dateTimeUtcValidator(value, path, ctx) { | ||
return validateLuxon({ | ||
function dateTimeUtc(options = { zone: luxon_1.FixedOffsetZone.utcInstance }) { | ||
return v_validation_1.V.fn((value, path, ctx) => validateLuxon({ | ||
value, | ||
@@ -95,8 +98,8 @@ path, | ||
pattern: dateTimePattern, | ||
parser: (value) => luxon_1.DateTime.fromISO(value, { zone: luxon_1.FixedOffsetZone.utcInstance }), | ||
}); | ||
parser: (value) => luxon_1.DateTime.fromISO(value, options), | ||
})); | ||
} | ||
const dateTimeMillisPattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}(?:Z|[+-]\d{2}(?::?\d{2})?)$/; | ||
function dateTimeMillisValidator(value, path, ctx) { | ||
return validateLuxon({ | ||
function dateTimeMillis(options = { setZone: true }) { | ||
return v_validation_1.V.fn((value, path, ctx) => validateLuxon({ | ||
value, | ||
@@ -108,7 +111,7 @@ path, | ||
pattern: dateTimeMillisPattern, | ||
parser: (value) => luxon_1.DateTime.fromISO(value, { setZone: true }), | ||
}); | ||
parser: (value) => luxon_1.DateTime.fromISO(value, options), | ||
})); | ||
} | ||
function dateTimeMillisUtcValidator(value, path, ctx) { | ||
return validateLuxon({ | ||
function dateTimeMillisUtc(options = { zone: luxon_1.FixedOffsetZone.utcInstance }) { | ||
return v_validation_1.V.fn((value, path, ctx) => validateLuxon({ | ||
value, | ||
@@ -120,5 +123,83 @@ path, | ||
pattern: dateTimeMillisPattern, | ||
parser: (value) => luxon_1.DateTime.fromISO(value, { zone: luxon_1.FixedOffsetZone.utcInstance }), | ||
parser: (value) => luxon_1.DateTime.fromISO(value, options), | ||
})); | ||
} | ||
function dateTimeFromISO(options = { setZone: true }) { | ||
return v_validation_1.V.fn((value, path, ctx) => validateLuxon({ | ||
value, | ||
path, | ||
ctx, | ||
type: 'ISODateTime', | ||
pattern: /./, | ||
parser: (value) => luxon_1.DateTime.fromISO(value, options), | ||
})); | ||
} | ||
function dateTimeFromRFC2822(options = { setZone: true }) { | ||
return v_validation_1.V.fn((value, path, ctx) => validateLuxon({ | ||
value, | ||
path, | ||
ctx, | ||
type: 'RFC2822DateTime', | ||
pattern: /./, | ||
parser: (value) => luxon_1.DateTime.fromRFC2822(value, options), | ||
})); | ||
} | ||
function dateTimeFromHTTP(options = { setZone: true }) { | ||
return v_validation_1.V.fn((value, path, ctx) => validateLuxon({ | ||
value, | ||
path, | ||
ctx, | ||
type: 'HTTPDateTime', | ||
pattern: /./, | ||
parser: (value) => luxon_1.DateTime.fromHTTP(value, options), | ||
})); | ||
} | ||
function dateTimeFromSQL(options = { zone: luxon_1.FixedOffsetZone.utcInstance }) { | ||
return v_validation_1.V.fn((value, path, ctx) => validateLuxon({ | ||
value, | ||
path, | ||
ctx, | ||
type: 'SQLDateTime', | ||
pattern: /./, | ||
parser: (value) => luxon_1.DateTime.fromSQL(value, options), | ||
})); | ||
} | ||
function validateLuxonNumber({ value, path, ctx, type, parser }) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if ((0, v_validation_1.isNullOrUndefined)(value)) { | ||
return ctx.failure(v_validation_1.defaultViolations.notNull(path), value); | ||
} | ||
else if (luxon_1.DateTime.isDateTime(value)) { | ||
if (value.isValid) { | ||
return ctx.success(value); | ||
} | ||
} | ||
else if (typeof value === 'number' && !Number.isNaN(value)) { | ||
const dateTime = parser(value); | ||
if (dateTime.isValid) { | ||
return ctx.success(dateTime); | ||
} | ||
} | ||
return ctx.failure(v_validation_1.defaultViolations.date(value, path, type), value); | ||
}); | ||
} | ||
exports.validateLuxonNumber = validateLuxonNumber; | ||
function dateTimeFromMillis(options = { zone: luxon_1.FixedOffsetZone.utcInstance }) { | ||
return v_validation_1.V.fn((value, path, ctx) => validateLuxonNumber({ | ||
value, | ||
path, | ||
ctx, | ||
type: 'MillisDateTime', | ||
parser: value => luxon_1.DateTime.fromMillis(value, options), | ||
})); | ||
} | ||
function dateTimeFromSeconds(options = { zone: luxon_1.FixedOffsetZone.utcInstance }) { | ||
return v_validation_1.V.fn((value, path, ctx) => validateLuxonNumber({ | ||
value, | ||
path, | ||
ctx, | ||
type: 'SecondsDateTime', | ||
parser: value => luxon_1.DateTime.fromSeconds(value, options), | ||
})); | ||
} | ||
const durationPattern = /^P(?!$)(\d+(?:\.\d+)?Y)?(\d+(?:\.\d+)?M)?(\d+(?:\.\d+)?W)?(\d+(?:\.\d+)?D)?(T(?=\d)(\d+(?:\.\d+)?H)?(\d+(?:\.\d+)?M)?(\d+(?:\.\d+)?S)?)?$/; | ||
@@ -146,9 +227,17 @@ class DurationValidator extends v_validation_1.Validator { | ||
exports.Vluxon = { | ||
localDate: () => v_validation_1.V.fn(localDateValidator), | ||
localTime: () => v_validation_1.V.fn(localTimeValidator), | ||
dateTime: () => v_validation_1.V.fn(dateTimeValidator), | ||
dateTimeUtc: () => v_validation_1.V.fn(dateTimeUtcValidator), | ||
dateTimeMillis: () => v_validation_1.V.fn(dateTimeMillisValidator), | ||
dateTimeMillisUtc: () => v_validation_1.V.fn(dateTimeMillisUtcValidator), | ||
// DateTime wrapper validators | ||
localDate, | ||
localTime, | ||
dateTime, | ||
dateTimeUtc, | ||
dateTimeMillis, | ||
dateTimeMillisUtc, | ||
// Plain DateTime validators | ||
dateTimeFromISO, | ||
dateTimeFromRFC2822, | ||
dateTimeFromHTTP, | ||
dateTimeFromSQL, | ||
dateTimeFromSeconds, | ||
dateTimeFromMillis, | ||
duration: () => new DurationValidator(), | ||
}; |
{ | ||
"name": "@finnair/v-validation-luxon", | ||
"version": "1.1.0-alpha.9", | ||
"version": "1.1.0", | ||
"private": false, | ||
@@ -28,4 +28,4 @@ "description": "Luxon validators", | ||
"dependencies": { | ||
"@finnair/path": "^1.1.0-alpha.6", | ||
"@finnair/v-validation": "^1.1.0-alpha.6", | ||
"@finnair/path": "^1.1.0", | ||
"@finnair/v-validation": "^1.1.0", | ||
"luxon": "3.0.1" | ||
@@ -36,3 +36,3 @@ }, | ||
}, | ||
"gitHead": "dcae3dd01e676de15d600898de5188c8384cb360" | ||
"gitHead": "860263e814c178790766b48e22d8a8995e33ae40" | ||
} |
@@ -7,3 +7,4 @@ [![npm version](https://badge.fury.io/js/%40finnair%2Fv-validation-luxon.svg)](https://badge.fury.io/js/%40finnair%2Fv-validation-luxon) | ||
`Vluxon` extension uses custom wrapper types for Luxon DateTime to support full JSON roundtrip with strict validation. | ||
`Vluxon` extension provides custom wrapper types for Luxon DateTime to support full JSON roundtrip with strict validation. | ||
Also plain DateTime validators are provided and custom formats are easy to define (see the code for examples). | ||
@@ -28,18 +29,65 @@ [Documentation for `v-validation`](https://github.com/finnair/v-validation). | ||
`validateLuxon` functions can be used to build custom DateTime validators/converters | ||
by supplying a RegExp pattern and a wrapper class (subclass of LuxonDateTime). | ||
The wrapper class should guarantee proper `toJSON()` and other required properties | ||
for the type (e.g. timezone handling). | ||
Vluxon contains both plain DateTime validators and also validators that return | ||
DateTime wrappers that guarantee some normalizations (zone, date and/or time) and | ||
especially JSON serialization in the given format. The wrappers are immutable and | ||
they allow easy access to the DateTime instance for further processing. | ||
`validateLuxon` function can be used to build custom DateTime validators/converters | ||
by supplying a RegExp pattern and a parser function. | ||
Time zone 00:00 is serialized as `Z`. | ||
## Supported DateTime Wrapper Types | ||
| Vluxon . | Format | Description | | ||
| ----------------- | -------------------------- | ------------------------------------------------------ | | ||
| date | `YYYY-MM-DD` | Local date. | | ||
| dateUtc | `YYYY-MM-DD` | Date in UTC time zone. | | ||
| dateTime | `YYYY-MM-DDTHH:mm:ssZ` | Date and time in local (parsed) time zone. | | ||
| dateTimeUtc | `YYYY-MM-DDTHH:mm:ssZ` | Date and time in UTC time zone. | | ||
| dateTimeMillis | `YYYY-MM-DDTHH:mm:ss.SSSZ` | Date and time with millis in local (parsed) time zone. | | ||
| dateTimeMillisUtc | `YYYY-MM-DDTHH:mm:ss.SSSZ` | Date and time with millis in UTC time zone. | | ||
| time | `HH:mm:ss` | Local time. | | ||
| duration | ISO 8601 Duration | Luxon `Duration` with pattern validation. | | ||
| Class | Description | | ||
| ---------------------- | ----------------------------------------------------------------------------------------------------------- | | ||
| LuxonDateTime | Abstract base class for the wrappers. | | ||
| LocalDateLuxon | Input and JSON output in `yyyy-MM-dd` format. Time normalized to midnight UTC. | | ||
| LocalTimeLuxon | Input and JSON output in `HH:mm:ss` format. Date normalized to 1970-01-01 UTC (Unix Epoch). | | ||
| DateTimeLuxon | Input and JSON output in `yyyy-MM-ddTHH:mm:ssZ` format in local/given/parsed zone with milliseconds zeroed. | | ||
| DateTimeUtcLuxon | Input and JSON output in `yyyy-MM-ddTHH:mm:ssZ` format in UTC zone with milliseconds zeroed. | | ||
| DateTimeMillisLuxon | Input and JSON output in `yyyy-MM-ddTHH:mm:ss.SSSZ` format in local/given/parsed zone. | | ||
| DateTimeMillisUtcLuxon | Input and JSON output in `yyyy-MM-ddTHH:mm:ss.SSSZ` format in UTC zone. | | ||
### Constructors | ||
Wrapper types may be constructed with `new` from DateTime instance, but there are also shortcuts: | ||
| Static Method | Description | | ||
| ---------------------------------------------------------------------- | --------------------------------------------------------------- | | ||
| `now()` | Current time in `DateTime*` types. | | ||
| `nowUtc()` | Current UTC time in `Local*` types. | | ||
| `nowLocal(options?: DateTimeJSOptions)` | Current local time in `Local*` types (defaults to system zone). | | ||
| `fromISO(value: string, options?: DateTimeOptions)` | Parse from ISO format (see Luxon `DateTime.fromISO`). | | ||
| `fromFormat(value: string, format: string, options?: DateTimeOptions)` | Parse from custom format (see Luxon `DateTime.fromFormat`). | | ||
| `fromJSDate(date: Date, options?: { zone?: string \| Zone })` | From JavaScript Date object (see Luxon `DateTime.fromJSDate`). | | ||
| `fromMillis(millis: number, options?: DateTimeJSOptions)` | From Unix millis timestamp (see Luxon `DateTime.fromMillis`). | | ||
### Instance Methods | ||
Wrappers are meant to be as thin as possible with most of the DateTime functionality accessed directly from the wrapped | ||
DateTime instance which is public readonly fiedl. However there are a few convenience methods for working with the wrapper types: | ||
| Method | Description | | ||
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | | ||
| `as(type)` | Conversion to the given type that extends LuxonDateTime. Note that the conversion is not guaranted to be lossless. | | ||
| `wrap(fn: (dateTime: DateTime) => DateTime)` | Executes the given function on the wrapped DateTime and rewraps the result. | | ||
| `apply<R>(fn: (dateTime: DateTime) => R): R` | Executes the given function on the wrapped DateTime and returns the result as it is. | | ||
| `valueOf()` | Conversion to millis. This allows comparing wrapper types directly using `==`, `<`, `>`, `<=` or `>=`. | | ||
| `equals(other: any)` | Type-aware equality. | | ||
| `toJSON()` | Type-specific serialization (string). | | ||
## Build-in Validators | ||
| Vluxon. | Format | Description | | ||
| ------------------- | -------------------------- | --------------------------------------------------------- | | ||
| localDate | `yyyy-MM-dd` | Local date (time normalized to midninght UTC). | | ||
| localTime | `HH:mm:ss` | Local time (date normalized to 1970-01-01). | | ||
| dateTime | `yyyy-MM-ddTHH:mm:ssZ` | Date and time in local (parsed) time zone. | | ||
| dateTimeUtc | `yyyy-MM-ddTHH:mm:ssZ` | Date and time in UTC time zone. | | ||
| dateTimeMillis | `yyyy-MM-ddTHH:mm:ss.SSSZ` | Date and time with millis in local (parsed) time zone. | | ||
| dateTimeMillisUtc | `yyyy-MM-ddTHH:mm:ss.SSSZ` | Date and time with millis in UTC time zone. | | ||
| dateTimeFromISO | Any ISO | Plain Luxon DateTime from ISO format. | | ||
| dateTimeFromRFC2822 | RFC2822 | Plain Luxon DateTime from RFC2822 format. | | ||
| dateTimeFromHTTP | HTTP date-time | Plain Luxon DateTime from HTTP format. | | ||
| dateTimeFromSQL | SQL date-time | Plain Luxon DateTime from SQL format. | | ||
| dateTimeFromSeconds | Unix timestamp (number) | Plain Luxon DateTime from Unix timestamp in seconds. | | ||
| dateTimeFromMillis | Unix timestamp (number) | Plain Luxon DateTime from Unix timestamp in milliseconds. | | ||
| duration | ISO 8601 Duration | Luxon `Duration` with pattern validation. | |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
39190
643
0
92
Updated@finnair/path@^1.1.0
Updated@finnair/v-validation@^1.1.0