UNPKG

@lonu/stc

Version:

A tool for converting OpenApi/Swagger/Apifox into code.

551 lines (550 loc) 23.2 kB
// Copyright 2018-2026 the Deno authors. MIT license. // This module is browser compatible. var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var _DateTimeFormatter_formatParts; function digits(value, count = 2) { return String(value).padStart(count, "0"); } const QUOTED_LITERAL_REGEXP = /^(')(?<value>\\.|[^\']*)\1/; const LITERAL_REGEXP = /^(?<value>.+?\s*)/; const SYMBOL_REGEXP = /^(?<symbol>([a-zA-Z])\2*)/; // according to unicode symbols (http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table) function formatToFormatParts(format) { const formatParts = []; let index = 0; while (index < format.length) { const substring = format.slice(index); const symbol = SYMBOL_REGEXP.exec(substring)?.groups?.symbol; switch (symbol) { case "yyyy": formatParts.push({ type: "year", value: "numeric" }); index += symbol.length; continue; case "yy": formatParts.push({ type: "year", value: "2-digit" }); index += symbol.length; continue; case "MM": formatParts.push({ type: "month", value: "2-digit" }); index += symbol.length; continue; case "M": formatParts.push({ type: "month", value: "numeric" }); index += symbol.length; continue; case "dd": formatParts.push({ type: "day", value: "2-digit" }); index += symbol.length; continue; case "d": formatParts.push({ type: "day", value: "numeric" }); index += symbol.length; continue; case "HH": formatParts.push({ type: "hour", value: "2-digit" }); index += symbol.length; continue; case "H": formatParts.push({ type: "hour", value: "numeric" }); index += symbol.length; continue; case "hh": formatParts.push({ type: "hour", value: "2-digit", hour12: true }); index += symbol.length; continue; case "h": formatParts.push({ type: "hour", value: "numeric", hour12: true }); index += symbol.length; continue; case "mm": formatParts.push({ type: "minute", value: "2-digit" }); index += symbol.length; continue; case "m": formatParts.push({ type: "minute", value: "numeric" }); index += symbol.length; continue; case "ss": formatParts.push({ type: "second", value: "2-digit" }); index += symbol.length; continue; case "s": formatParts.push({ type: "second", value: "numeric" }); index += symbol.length; continue; case "SSS": formatParts.push({ type: "fractionalSecond", value: 3 }); index += symbol.length; continue; case "SS": formatParts.push({ type: "fractionalSecond", value: 2 }); index += symbol.length; continue; case "S": formatParts.push({ type: "fractionalSecond", value: 1 }); index += symbol.length; continue; case "a": formatParts.push({ type: "dayPeriod", value: 1 }); index += symbol.length; continue; } const quotedLiteralMatch = QUOTED_LITERAL_REGEXP.exec(substring); if (quotedLiteralMatch) { const value = quotedLiteralMatch.groups.value; formatParts.push({ type: "literal", value }); index += quotedLiteralMatch[0].length; continue; } const literalGroups = LITERAL_REGEXP.exec(substring).groups; const value = literalGroups.value; formatParts.push({ type: "literal", value }); index += value.length; } return formatParts; } function sortDateTimeFormatParts(parts) { let result = []; const typeArray = [ "year", "month", "day", "hour", "minute", "second", "fractionalSecond", ]; for (const type of typeArray) { const current = parts.findIndex((el) => el.type === type); if (current !== -1) { result = result.concat(parts.splice(current, 1)); } } result = result.concat(parts); return result; } export class DateTimeFormatter { constructor(formatString) { _DateTimeFormatter_formatParts.set(this, void 0); __classPrivateFieldSet(this, _DateTimeFormatter_formatParts, formatToFormatParts(formatString), "f"); } format(date, options = {}) { let string = ""; const utc = options.timeZone === "UTC"; for (const part of __classPrivateFieldGet(this, _DateTimeFormatter_formatParts, "f")) { const type = part.type; switch (type) { case "year": { const value = utc ? date.getUTCFullYear() : date.getFullYear(); switch (part.value) { case "numeric": { string += value; break; } case "2-digit": { string += digits(value, 2).slice(-2); break; } default: throw new Error(`FormatterError: value "${part.value}" is not supported`); } break; } case "month": { const value = (utc ? date.getUTCMonth() : date.getMonth()) + 1; switch (part.value) { case "numeric": { string += value; break; } case "2-digit": { string += digits(value, 2); break; } default: throw new Error(`FormatterError: value "${part.value}" is not supported`); } break; } case "day": { const value = utc ? date.getUTCDate() : date.getDate(); switch (part.value) { case "numeric": { string += value; break; } case "2-digit": { string += digits(value, 2); break; } default: throw new Error(`FormatterError: value "${part.value}" is not supported`); } break; } case "hour": { let value = utc ? date.getUTCHours() : date.getHours(); if (part.hour12) { if (value === 0) value = 12; else if (value > 12) value -= 12; } switch (part.value) { case "numeric": { string += value; break; } case "2-digit": { string += digits(value, 2); break; } default: throw new Error(`FormatterError: value "${part.value}" is not supported`); } break; } case "minute": { const value = utc ? date.getUTCMinutes() : date.getMinutes(); switch (part.value) { case "numeric": { string += value; break; } case "2-digit": { string += digits(value, 2); break; } default: throw new Error(`FormatterError: value "${part.value}" is not supported`); } break; } case "second": { const value = utc ? date.getUTCSeconds() : date.getSeconds(); switch (part.value) { case "numeric": { string += value; break; } case "2-digit": { string += digits(value, 2); break; } default: throw new Error(`FormatterError: value "${part.value}" is not supported`); } break; } case "fractionalSecond": { const value = utc ? date.getUTCMilliseconds() : date.getMilliseconds(); string += digits(value, 3).slice(0, Number(part.value)); break; } // FIXME(bartlomieju) case "timeZoneName": { // string += utc ? "Z" : part.value break; } case "dayPeriod": { string += date.getHours() >= 12 ? "PM" : "AM"; break; } case "literal": { string += part.value; break; } default: throw new Error(`FormatterError: { ${part.type} ${part.value} }`); } } return string; } formatToParts(string) { const parts = []; for (const part of __classPrivateFieldGet(this, _DateTimeFormatter_formatParts, "f")) { const type = part.type; let length = 0; let value = ""; switch (part.type) { case "year": { switch (part.value) { case "numeric": { value = /^\d{4}/.exec(string)?.[0]; length = value?.length; break; } case "2-digit": { value = /^\d{2}/.exec(string)?.[0]; length = value?.length; break; } default: throw new Error(`ParserError: value "${part.value}" is not supported`); } break; } case "month": { switch (part.value) { case "numeric": { value = /^\d{1,2}/.exec(string)?.[0]; length = value?.length; break; } case "2-digit": { value = /^\d{2}/.exec(string)?.[0]; length = value?.length; break; } case "narrow": { value = /^[a-zA-Z]+/.exec(string)?.[0]; length = value?.length; break; } case "short": { value = /^[a-zA-Z]+/.exec(string)?.[0]; length = value?.length; break; } case "long": { value = /^[a-zA-Z]+/.exec(string)?.[0]; length = value?.length; break; } default: throw new Error(`ParserError: value "${part.value}" is not supported`); } break; } case "day": { switch (part.value) { case "numeric": { value = /^\d{1,2}/.exec(string)?.[0]; length = value?.length; break; } case "2-digit": { value = /^\d{2}/.exec(string)?.[0]; length = value?.length; break; } default: throw new Error(`ParserError: value "${part.value}" is not supported`); } break; } case "hour": { switch (part.value) { case "numeric": { value = /^\d{1,2}/.exec(string)?.[0]; length = value?.length; if (part.hour12 && parseInt(value) > 12) { // TODO(iuioiua): Replace with throwing an error // deno-lint-ignore no-console console.error(`Trying to parse hour greater than 12, use 'H' instead of 'h'.`); } break; } case "2-digit": { value = /^\d{2}/.exec(string)?.[0]; length = value?.length; if (part.hour12 && parseInt(value) > 12) { // TODO(iuioiua): Replace with throwing an error // deno-lint-ignore no-console console.error(`Trying to parse hour greater than 12, use 'HH' instead of 'hh'.`); } break; } default: // TODO(iuioiua): Correct error type and message throw new Error(`ParserError: value "${part.value}" is not supported`); } break; } case "minute": { switch (part.value) { case "numeric": { value = /^\d{1,2}/.exec(string)?.[0]; length = value?.length; break; } case "2-digit": { value = /^\d{2}/.exec(string)?.[0]; length = value?.length; break; } default: throw new Error(`ParserError: value "${part.value}" is not supported`); } break; } case "second": { switch (part.value) { case "numeric": { value = /^\d{1,2}/.exec(string)?.[0]; length = value?.length; break; } case "2-digit": { value = /^\d{2}/.exec(string)?.[0]; length = value?.length; break; } default: throw new Error(`ParserError: value "${part.value}" is not supported`); } break; } case "fractionalSecond": { value = new RegExp(`^\\d{${part.value}}`).exec(string)?.[0]; length = value?.length; break; } case "timeZoneName": { value = part.value; length = value?.length; break; } case "dayPeriod": { value = /^[AP](?:\.M\.|M\.?)/i.exec(string)?.[0]; switch (value.toUpperCase()) { case "AM": value = "AM"; length = 2; break; case "AM.": value = "AM"; length = 3; break; case "A.M.": value = "AM"; length = 4; break; case "PM": value = "PM"; length = 2; break; case "PM.": value = "PM"; length = 3; break; case "P.M.": value = "PM"; length = 4; break; default: throw new Error(`DayPeriod '${value}' is not supported.`); } break; } case "literal": { if (!string.startsWith(part.value)) { throw new Error(`Literal "${part.value}" not found "${string.slice(0, 25)}"`); } value = part.value; length = value?.length; break; } default: throw new Error(`Cannot format the date, the value (${part.value}) of the type (${part.type}) is given`); } if (!value) { throw new Error(`Cannot format value: The value is not valid for part { ${type} ${value} } ${string.slice(0, 25)}`); } parts.push({ type, value }); string = string.slice(length); } if (string.length) { throw new Error(`datetime string was not fully parsed! ${string.slice(0, 25)}`); } return parts; } partsToDate(parts) { parts = sortDateTimeFormatParts(parts); const date = new Date(); const utc = parts.find((part) => part.type === "timeZoneName" && part.value === "UTC"); const dayPart = parts.find((part) => part.type === "day"); utc ? date.setUTCHours(0, 0, 0, 0) : date.setHours(0, 0, 0, 0); for (const part of parts) { switch (part.type) { case "year": { const value = Number(part.value.padStart(4, "20")); utc ? date.setUTCFullYear(value) : date.setFullYear(value); break; } case "month": { const value = Number(part.value) - 1; if (dayPart) { utc ? date.setUTCMonth(value, Number(dayPart.value)) : date.setMonth(value, Number(dayPart.value)); } else { utc ? date.setUTCMonth(value) : date.setMonth(value); } break; } case "day": { const value = Number(part.value); utc ? date.setUTCDate(value) : date.setDate(value); break; } case "hour": { let value = Number(part.value); const dayPeriod = parts.find((part) => part.type === "dayPeriod"); if (dayPeriod) { switch (dayPeriod.value.toUpperCase()) { case "AM": case "AM.": case "A.M.": // ignore break; case "PM": case "PM.": case "P.M.": value += 12; break; default: throw new Error(`dayPeriod '${dayPeriod.value}' is not supported.`); } } utc ? date.setUTCHours(value) : date.setHours(value); break; } case "minute": { const value = Number(part.value); utc ? date.setUTCMinutes(value) : date.setMinutes(value); break; } case "second": { const value = Number(part.value); utc ? date.setUTCSeconds(value) : date.setSeconds(value); break; } case "fractionalSecond": { const value = Number(part.value); utc ? date.setUTCMilliseconds(value) : date.setMilliseconds(value); break; } } } return date; } parse(string) { const parts = this.formatToParts(string); return this.partsToDate(parts); } } _DateTimeFormatter_formatParts = new WeakMap();