feat: 🎸 Replaced Moment with Luxon (#30)

* feat: 🎸 Replaced Moment with Luxon

Replaced Moment with Luxon since the former is deprecated for various
reasons. Also updated types to be fully serialized.

BREAKING CHANGE: 🧨 Change to types (moment -> strings) and api.getSchedule (moment ->
luxon.DateTime)
This commit is contained in:
Johan Öbrink 2021-01-03 13:08:53 +01:00 committed by GitHub
parent 40166f3280
commit e41f0bf435
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 72 additions and 64 deletions

View File

@ -1,4 +1,4 @@
import { Moment } from 'moment'
import { DateTime } from 'luxon'
import { EventEmitter } from 'events'
import {
checkStatus, LoginStatusChecker,
@ -95,8 +95,8 @@ export class Api extends EventEmitter {
return parse.classmates(data)
}
async getSchedule(child: Child, from: Moment, to: Moment): Promise<ScheduleItem[]> {
const url = routes.schedule(child.sdsId, from.format('YYYY-MM-DD'), to.format('YYYY-MM-DD'))
async getSchedule(child: Child, from: DateTime, to: DateTime): Promise<ScheduleItem[]> {
const url = routes.schedule(child.sdsId, from.toISODate(), to.toISODate())
const response = await this.fetch('schedule', url, this.session)
const data = await response.json()
return parse.schedule(data)

View File

@ -1,6 +1,4 @@
import * as moment from 'moment'
import * as parse from "./parse"
import { NewsItem } from "./types"
describe('parse', () => {
let response: parse.EtjanstResponse
@ -99,8 +97,8 @@ describe('parse', () => {
location: null,
title: 'Jullov',
description: 'hello',
startDate: moment(new Date('2020-12-21 09:00')),
endDate: moment(new Date('2021-01-08 10:00')),
startDate: '2020-12-21T09:00:00.000+01:00',
endDate: '2021-01-08T10:00:00.000+01:00',
allDay: false,
}])
})
@ -205,8 +203,8 @@ describe('parse', () => {
title: 'Canceled: Julavslutning 8C',
description: 'Nåt kul',
location: 'Lakritskolan',
startDate: moment(new Date('2020-12-14 14:10')),
endDate: moment(new Date('2020-12-14 14:40')),
startDate: '2020-12-14T14:10:00.000+01:00',
endDate: '2020-12-14T14:40:00.000+01:00',
oneDayEvent: true,
allDayEvent: false,
}])
@ -273,8 +271,8 @@ describe('parse', () => {
expect(item.header).toEqual('Problemet med att se betyg i bild, slöjd och teknik löst!')
expect(item.imageUrl).toEqual('A703552D-DBF3-45B0-8E67-6E062105A0C5.jpeg')
expect(item.intro).toEqual('Hej,Nu är problemet löst! Alla betyg syns som de ska.God jul!...')
expect(item.modified).toEqual(moment(new Date('18 december 2020 16:18')))
expect(item.published).toEqual(moment(new Date('18 december 2020 16:15')))
expect(item.modified).toEqual('2020-12-18T16:18:00.000+01:00')
expect(item.published).toEqual('2020-12-18T16:15:00.000+01:00')
})
it('parses body correctly', () => {
const [item] = parse.news(response)
@ -376,7 +374,7 @@ describe('parse', () => {
message: 'Betygen är publicerade.',
sender: 'Elevdokumentation',
url: 'https://elevdokumentation.stockholm.se/loa3/gradesStudent.do',
dateCreated: moment(new Date('2020-12-18T15:59:46.34')),
dateCreated: '2020-12-18T15:59:46.340+01:00',
category: null,
type: 'webnotify',
}])

View File

@ -1,4 +1,4 @@
import * as moment from 'moment'
import { DateTime, DateTimeOptions } from 'luxon'
import * as h2m from 'h2m'
import { htmlDecode } from 'js-htmlencode'
import {
@ -7,6 +7,12 @@ import {
const camel = require('camelcase-keys')
const dateTimeOptions: DateTimeOptions = {
locale: 'sv',
setZone: true,
zone: 'Europe/Stockholm',
}
export interface EtjanstResponse {
Success: boolean
Error: string | null
@ -67,8 +73,8 @@ export const calendarItem = ({
description,
location,
allDay: allDayEvent,
startDate: longEventDateTime ? moment(new Date(longEventDateTime)) : undefined,
endDate: longEndDateTime ? moment(new Date(longEndDateTime)) : undefined,
startDate: longEventDateTime ? DateTime.fromSQL(longEventDateTime, dateTimeOptions).toISO() : undefined,
endDate: longEndDateTime ? DateTime.fromSQL(longEndDateTime, dateTimeOptions).toISO() : undefined,
})
export const calendar = (data: any): CalendarItem[] => etjanst(data).map(calendarItem)
@ -80,8 +86,8 @@ export const newsItem = ({
intro: preamble,
imageUrl: bannerImageUrl,
body: htmlDecode(h2m(body)),
published: moment(new Date(pubDateSe)),
modified: moment(new Date(modDateSe)),
published: DateTime.fromFormat(pubDateSe, 'dd LLLL yyyy HH:mm', dateTimeOptions).toISO(),
modified: DateTime.fromFormat(modDateSe, 'dd LLLL yyyy HH:mm', dateTimeOptions).toISO(),
})
export const news = (data: any): NewsItem[] => etjanst(data).newsItems.map(newsItem)
@ -92,8 +98,8 @@ export const scheduleItem = ({
description,
location,
allDayEvent,
startDate: moment(new Date(longEventDateTime)),
endDate: moment(new Date(longEndDateTime)),
startDate: DateTime.fromSQL(longEventDateTime, dateTimeOptions).toISO(),
endDate: DateTime.fromSQL(longEndDateTime, dateTimeOptions).toISO(),
oneDayEvent: isSameDay,
})
export const schedule = (data: any): ScheduleItem[] => etjanst(data).map(scheduleItem)
@ -131,7 +137,7 @@ export const notification = ({
message: messagetext,
sender: name,
url: linkbackurl,
dateCreated: moment(new Date(dateCreated)),
dateCreated: DateTime.fromISO(dateCreated, dateTimeOptions).toISO(),
category,
type,
})

View File

@ -1,5 +1,3 @@
import { Moment } from 'moment'
export interface AsyncishFunction { (): void | Promise<void> }
export interface RequestInit {
@ -36,13 +34,13 @@ export interface AuthTicket {
* @interface CalendarItem
*/
export interface CalendarItem {
id: number;
title: string;
description?: string;
location?: string;
startDate?: Moment;
endDate?: Moment;
allDay?: boolean;
id: number
title: string
description?: string
location?: string
startDate?: string
endDate?: string
allDay?: boolean
}
/**
@ -50,21 +48,21 @@ export interface CalendarItem {
* @interface Child
*/
export interface Child {
id: string;
id: string
/**
* <p>Special ID used to access certain subsystems</p>
* @type {string}
* @memberof Child
*/
sdsId: string;
name: string;
sdsId: string
name: string
/**
* <p>F - förskola, GR - grundskola?</p>
* @type {string}
* @memberof Child
*/
status?: string;
schoolId?: string;
status?: string
schoolId?: string
}
/**
@ -72,11 +70,11 @@ export interface Child {
* @interface Classmate
*/
export interface Classmate {
sisId: string;
className?: string;
firstname: string;
lastname: string;
guardians: Guardian[];
sisId: string
className?: string
firstname: string
lastname: string
guardians: Guardian[]
}
/**
@ -84,11 +82,11 @@ export interface Classmate {
* @interface Guardian
*/
export interface Guardian {
email?: string;
firstname: string;
lastname: string;
mobile?: string;
address?: string;
email?: string
firstname: string
lastname: string
mobile?: string
address?: string
}
/**
@ -97,13 +95,13 @@ export interface Guardian {
* @interface NewsItem
*/
export interface NewsItem {
id?: string;
header?: string;
intro?: string;
body?: string;
published: Moment;
modified?: Moment;
imageUrl?: string;
id?: string
header?: string
intro?: string
body?: string
published: string
modified?: string
imageUrl?: string
}
/**
@ -113,7 +111,7 @@ export interface NewsItem {
export interface Notification {
id: string
sender: string
dateCreated: Moment
dateCreated: string
message: string
/**
* <p>
@ -136,8 +134,8 @@ export interface ScheduleItem {
title: string
description?: string
location?: string
startDate: Moment
endDate: Moment
startDate: string
endDate: string
oneDayEvent: boolean
allDayEvent: boolean
}

View File

@ -20,6 +20,7 @@
},
"devDependencies": {
"@types/jest": "^26.0.19",
"@types/luxon": "^1.25.0",
"@types/node-fetch": "^2.5.7",
"@typescript-eslint/eslint-plugin": "^4.10.0",
"@typescript-eslint/parser": "^4.10.0",
@ -39,6 +40,6 @@
"events": "^3.2.0",
"h2m": "^0.7.0",
"js-htmlencode": "^0.3.0",
"moment": "^2.29.1"
"luxon": "^1.25.0"
}
}

8
run.js
View File

@ -1,4 +1,4 @@
const moment = require('moment')
const { DateTime } = require('luxon')
const nodeFetch = require('node-fetch')
const { CookieJar } = require('tough-cookie')
const fetchCookie = require('fetch-cookie/node-fetch')
@ -71,15 +71,15 @@ async function run() {
// console.log(classmates)
console.log('schedule')
const schedule = await api.getSchedule(children[0], moment().subtract(1, 'week'), moment())
const schedule = await api.getSchedule(children[0], DateTime.local(), DateTime.local().plus({ week: 1 }))
// console.log(schedule)
console.log('news')
const news = await api.getNews(children[0])
// console.log(news)
console.log('image')
const blob = await api.getImage(news[0].imageUrl)
// console.log('image')
// const blob = await api.getImage(news[0].imageUrl)
// console.log(blob)
// const arrayBuffer = await blob.arrayBuffer()

View File

@ -593,6 +593,11 @@
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
"@types/luxon@^1.25.0":
version "1.25.0"
resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-1.25.0.tgz#3d6fe591fac874f48dd225cb5660b2b785a21a05"
integrity sha512-iIJp2CP6C32gVqI08HIYnzqj55tlLnodIBMCcMf28q9ckqMfMzocCmIzd9JWI/ALLPMUiTkCu1JGv3FFtu6t3g==
"@types/node-fetch@^2.5.7":
version "2.5.7"
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.7.tgz#20a2afffa882ab04d44ca786449a276f9f6bbf3c"
@ -3186,6 +3191,11 @@ lru-cache@^6.0.0:
dependencies:
yallist "^4.0.0"
luxon@^1.25.0:
version "1.25.0"
resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.25.0.tgz#d86219e90bc0102c0eb299d65b2f5e95efe1fe72"
integrity sha512-hEgLurSH8kQRjY6i4YLey+mcKVAWXbDNlZRmM6AgWDJ1cY3atl8Ztf5wEY7VBReFbmGnwQPz7KYJblL8B2k0jQ==
make-dir@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
@ -3301,11 +3311,6 @@ mkdirp@1.x:
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
moment@^2.29.1:
version "2.29.1"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"