liftie 3.56.2 → 3.56.4

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/lib/cli/noaa.js CHANGED
@@ -1,7 +1,6 @@
1
1
  const { program } = require('commander');
2
2
  const { writeFileSync } = require('node:fs');
3
3
  const { resolve } = require('node:path');
4
- const superagent = require('superagent');
5
4
 
6
5
  const forEachResort = require('./for-each-resort');
7
6
 
@@ -31,28 +30,25 @@ function noaaForResort(resortId, { overwrite }) {
31
30
  const descriptor = readDescriptor(resortId);
32
31
 
33
32
  const { ll } = descriptor;
34
- const url = `https://api.weather.gov/points/${points(ll)}`;
35
- superagent(url)
36
- .accept('application/geo+json')
37
- .set('User-Agent', userAgent)
38
- .then(
39
- res => {
40
- const {
41
- body: {
42
- properties: { gridId, gridX, gridY }
43
- }
44
- } = res;
45
- const noaa = `${gridId}/${gridX},${gridY}`;
46
- if (overwrite) {
47
- descriptor.noaa = noaa;
48
- writeDescriptor(resortId, descriptor);
49
- }
50
- console.log(resortId, noaa);
51
- },
52
- e => {
53
- console.error('Cannot find NOAA station for:', resortId, e.response.text);
33
+ fetch(`https://api.weather.gov/points/${points(ll)}`, {
34
+ headers: {
35
+ 'User-Agent': userAgent,
36
+ Accept: 'application/geo+json'
37
+ }
38
+ })
39
+ .then(res => res.json())
40
+ .then(body => {
41
+ const {
42
+ properties: { gridId, gridX, gridY }
43
+ } = body;
44
+ const noaa = `${gridId}/${gridX},${gridY}`;
45
+ if (overwrite) {
46
+ descriptor.noaa = noaa;
47
+ writeDescriptor(resortId, descriptor);
54
48
  }
55
- );
49
+ console.log(resortId, noaa);
50
+ })
51
+ .catch(e => console.error('Cannot find NOAA station for:', resortId, e));
56
52
  }
57
53
 
58
54
  function descriptorPath(resortId, absolute) {
package/lib/lifts/pipe.js CHANGED
@@ -1,19 +1,21 @@
1
1
  const request = require('./request');
2
- const parseHtml = require('./parser').html;
2
+ const { html: parseHtml } = require('./parser');
3
3
 
4
4
  module.exports = (url, parse, fn) => {
5
5
  request(url)
6
- .buffer(true)
7
- .on('error', fn)
8
- .end((err, res) => {
9
- if (err && !url.ignoreErrors) {
10
- console.error('Error', url, err.status);
11
- return fn(err.status);
6
+ .then(async res => {
7
+ if (res.status < 200 || res.status >= 300) {
8
+ console.error('Error', url, res.status);
9
+ if (!url.ignoreErrors) {
10
+ return fn(res.status);
11
+ }
12
12
  }
13
- if (!res.text) {
13
+ const text = await res.text();
14
+ if (!text) {
14
15
  console.error('Empty response', url);
15
16
  return fn('empty response');
16
17
  }
17
- parseHtml(res.text, parse, fn);
18
- });
18
+ parseHtml(text, parse, fn);
19
+ })
20
+ .catch(fn);
19
21
  };
@@ -1,19 +1,16 @@
1
- const superagent = require('superagent');
2
-
3
1
  const userAgent = 'Mozilla/5.0 (compatible; Liftie/1.0; +https://liftie.info)';
4
2
 
5
- module.exports = ({ host, pathname, query, http2 }) => {
6
- const req = superagent
7
- .agent()
8
- .get(host + pathname)
9
- .redirects(4)
10
- .set('User-Agent', userAgent)
11
- .set('Accept', '*/*');
3
+ module.exports = request;
4
+
5
+ function request({ host, pathname, query }) {
6
+ const fullUrl = new URL(pathname, host);
12
7
  if (query) {
13
- req.query(query);
14
- }
15
- if (http2) {
16
- req.http2(true);
8
+ fullUrl.search = new URLSearchParams(query).toString();
17
9
  }
18
- return req;
19
- };
10
+ return fetch(fullUrl, {
11
+ headers: {
12
+ 'User-Agent': userAgent,
13
+ Accept: '*/*'
14
+ }
15
+ });
16
+ }
package/lib/lifts/rest.js CHANGED
@@ -1,46 +1,39 @@
1
- const superagent = require('superagent');
1
+ const { html: parseHtml } = require('./parser');
2
+
2
3
  const userAgent = 'liftie/1.0.0 (https://liftie.info)';
3
- const parseHtml = require('./parser').html;
4
4
 
5
5
  module.exports = rest;
6
6
 
7
7
  function rest(url, parse, fn) {
8
- const fullUrl = url.host + url.pathname;
9
-
10
- const request = url.body ? superagent.post(fullUrl).send(url.body) : superagent.get(fullUrl);
11
-
8
+ const fullUrl = new URL(url.pathname, url.host);
12
9
  if (url.query) {
13
- request.query(url.query);
10
+ fullUrl.search = new URLSearchParams(url.query).toString();
14
11
  }
15
- if (url.http2) {
16
- request.http2(true);
12
+ const reqInit = {
13
+ headers: {
14
+ 'User-Agent': userAgent,
15
+ Accept: 'application/json'
16
+ }
17
+ };
18
+ if (url.body) {
19
+ reqInit.body = JSON.stringify(url.body);
20
+ reqInit.method = 'POST';
17
21
  }
18
22
 
19
- request.set('User-Agent', userAgent).set('Accept', 'application/json').on('error', fn);
20
-
21
- request.then(
22
- res => {
23
- let { body, text } = res;
24
- if (url.html) {
25
- return parseHtml(body, parse, fn);
23
+ fetch(fullUrl, reqInit)
24
+ .then(async res => {
25
+ if (res.status < 200 || res.status >= 300) {
26
+ return fn(res.status);
26
27
  }
27
- if (url.json) {
28
- // used when client does not send proper Content-Type
29
- try {
30
- body = JSON.parse(text);
31
- } catch {
32
- console.error('cannot parse', url);
33
- body = {};
34
- }
28
+ if (url.html) {
29
+ return parseHtml(await res.text(), parse, fn);
35
30
  }
31
+ const body = await res.json();
36
32
  if (parse.isAsync) {
37
33
  parse(body, fn);
38
34
  } else {
39
35
  fn(null, parse(body));
40
36
  }
41
- },
42
- ({ status }) => {
43
- fn(status);
44
- }
45
- );
37
+ })
38
+ .catch(fn);
46
39
  }
@@ -6,8 +6,7 @@
6
6
  },
7
7
  "api": {
8
8
  "host": "https://www.jacksonhole.com",
9
- "pathname": "/api/all.json",
10
- "http2": true
9
+ "pathname": "/api/all.json"
11
10
  },
12
11
  "tags": [
13
12
  "Wyoming"
@@ -1,8 +1,7 @@
1
- const superagent = require('superagent');
2
1
  const debug = require('debug')('liftie:weather');
3
2
  const { iconsFromUrl } = require('./icons');
4
3
 
5
- module.exports = fetch;
4
+ module.exports = fetchWeather;
6
5
 
7
6
  const userAgent = 'Mozilla/5.0 (compatible; Liftie/1.0; +https://liftie.info)';
8
7
 
@@ -30,7 +29,7 @@ function normalize(data, ll) {
30
29
  };
31
30
  }
32
31
 
33
- function fetch(resort, fn) {
32
+ function fetchWeather(resort, fn) {
34
33
  debug('fetch weather from NOAA for %s', resort.id);
35
34
 
36
35
  const { ll } = resort;
@@ -39,14 +38,17 @@ function fetch(resort, fn) {
39
38
  return process.nextTick(fn);
40
39
  }
41
40
  const url = `https://api.weather.gov/gridpoints/${resort.noaa}/forecast`;
42
- superagent(url).redirects(0).accept('application/geo+json').set('User-Agent', userAgent).then(onData, onError);
43
-
44
- function onError(err) {
45
- debug('NOAA API error', err);
46
- fn();
47
- }
48
-
49
- function onData({ body }) {
50
- fn(null, normalize(body, ll));
51
- }
41
+ fetch(url, {
42
+ method: 'GET',
43
+ headers: {
44
+ 'User-Agent': userAgent,
45
+ Accept: 'application/geo+json'
46
+ }
47
+ })
48
+ .then(res => res.json())
49
+ .then(body => fn(null, normalize(body, ll)))
50
+ .catch(err => {
51
+ debug('NOAA API error', err);
52
+ fn();
53
+ });
52
54
  }
@@ -1,4 +1,3 @@
1
- const superagent = require('superagent');
2
1
  const debug = require('debug')('liftie:weather');
3
2
 
4
3
  const millis = require('../tools/millis');
@@ -8,7 +7,7 @@ const { iconsFrom } = require('./icons');
8
7
  // not more than 30 a minute (60 per documentation)
9
8
  const limit = limiter(30, millis.minute);
10
9
 
11
- module.exports = fetch;
10
+ module.exports = fetchForecast;
12
11
 
13
12
  function tempInF(kelvins) {
14
13
  return Math.round((kelvins - 273.15) * 1.8) + 32;
@@ -74,26 +73,25 @@ function sanitize({ city, list }) {
74
73
  };
75
74
  }
76
75
 
77
- function fetch(resort, appid, fn) {
76
+ function fetchForecast(resort, appid, fn) {
78
77
  limit(err => {
79
78
  if (err) {
80
79
  debug('Weather API limit %s', resort.id);
81
80
  return fn(err);
82
81
  }
83
82
  debug('request weather for %s', resort.id);
84
- superagent
85
- .get('https://api.openweathermap.org/data/2.5/forecast')
86
- .query({
87
- lon: resort.ll[0],
88
- lat: resort.ll[1],
89
- appid
90
- })
91
- .end((err, res) => {
92
- if (err) {
93
- console.error('Weather fetch error', resort.name, err.status);
94
- return fn(err.status);
95
- }
96
- fn(null, sanitize(res.body));
83
+
84
+ const url = new URL('https://api.openweathermap.org/data/2.5/forecast');
85
+ url.searchParams.set('lon', resort.ll[0]);
86
+ url.searchParams.set('lat', resort.ll[1]);
87
+ url.searchParams.set('appid', appid);
88
+
89
+ fetch(url)
90
+ .then(res => res.json())
91
+ .then(body => fn(null, sanitize(body)))
92
+ .catch(err => {
93
+ console.error('Weather fetch error', resort.name, err.status);
94
+ return fn(err.status);
97
95
  });
98
96
  });
99
97
  }
package/lib/webcams.js CHANGED
@@ -1,4 +1,3 @@
1
- const superagent = require('superagent');
2
1
  const debug = require('debug')('liftie:webcams');
3
2
 
4
3
  const { minute } = require('./tools/millis');
@@ -6,7 +5,7 @@ const limiter = require('./tools/limiter');
6
5
 
7
6
  const userAgent = 'Mozilla/5.0 (compatible; Liftie/1.0; +https://liftie.info)';
8
7
 
9
- module.exports = fetch;
8
+ module.exports = fetchWebcams;
10
9
  module.exports.interval = {
11
10
  active: 8.5 * minute, // v3 API images are only valid for 10 minutes
12
11
  inactive: Number.POSITIVE_INFINITY
@@ -34,7 +33,7 @@ function getStatic({ webcams }) {
34
33
  }
35
34
  }
36
35
 
37
- function fetch(resort, fn) {
36
+ function fetchWebcams(resort, fn) {
38
37
  debug('Fetching webcams for %s', resort.id);
39
38
  const { WEBCAMS_API_KEY } = process.env;
40
39
  if (!resort.ll || !WEBCAMS_API_KEY) {
@@ -56,19 +55,23 @@ function fetch(resort, fn) {
56
55
  sp.set('limit', 5);
57
56
  sp.set('nearby', `${lat},${lon},5`);
58
57
  sp.set('include', 'images,urls');
59
- superagent(url)
60
- .set('User-Agent', userAgent)
61
- .accept('application/json')
62
- .set('x-windy-api-key', WEBCAMS_API_KEY)
63
- .then(onData, onError);
58
+ fetch(url, {
59
+ headers: {
60
+ Accept: 'application/json',
61
+ 'User-Agent': userAgent,
62
+ 'x-windy-api-key': WEBCAMS_API_KEY
63
+ }
64
+ })
65
+ .then(res => res.json())
66
+ .then(onData)
67
+ .catch(onError);
64
68
 
65
69
  function onError(err) {
66
70
  debug('Webcam API error', err);
67
71
  fn(null, getStatic(resort));
68
72
  }
69
73
 
70
- function onData({ body }) {
71
- const { webcams } = body;
74
+ function onData({ webcams }) {
72
75
  if (webcams.length < 1) {
73
76
  return fn(null, getStatic(resort));
74
77
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "liftie",
3
- "version": "3.56.2",
3
+ "version": "3.56.4",
4
4
  "description": "Clean, simple, easy to read, fast ski resort lift status",
5
5
  "keywords": [
6
6
  "ski",
@@ -53,19 +53,21 @@
53
53
  "parseurl": "^1.3.3",
54
54
  "qs": "^6.13.1",
55
55
  "ro-rating": "~2",
56
- "superagent": "~10",
57
56
  "tiny-pager": "^1.0.0",
58
57
  "to-title-case": "^1.0.0"
59
58
  },
60
59
  "devDependencies": {
61
60
  "@biomejs/biome": "^1.5.1",
62
- "@pirxpilot/replay": "^2.2.1",
61
+ "@pirxpilot/stylus": "^1.2.0",
63
62
  "commander": "~13",
64
63
  "postcss": "~8",
65
64
  "postcss-cachify": "^4.0.0",
66
65
  "postcss-cli-simple": "~4.0.0",
67
66
  "prompt": "~1",
68
- "stylus": "^0.64.0"
67
+ "undici": "^7.10.0"
68
+ },
69
+ "resolutions": {
70
+ "on-headers": "npm:@pirxpilot/on-headers@2.0.0"
69
71
  },
70
72
  "pnpm": {
71
73
  "overrides": {