@screenly/edge-apps 1.0.0-rc.1 → 1.0.0-rc.2

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/README.md CHANGED
@@ -6,8 +6,14 @@ A TypeScript library for interfacing with the Screenly Edge Apps API.
6
6
 
7
7
  ## Installation
8
8
 
9
- > [!IMPORTANT]
10
- > This package requires [Bun](https://bun.sh). The `edge-apps-scripts` CLI will not work with `npm` or `node` at this time.
9
+ > [!NOTE]
10
+ > Requires Node.js >= 20.6.0.
11
+
12
+ ```bash
13
+ npm install @screenly/edge-apps
14
+ ```
15
+
16
+ Or with Bun:
11
17
 
12
18
  ```bash
13
19
  bun add @screenly/edge-apps
@@ -20,26 +26,22 @@ When developing Edge Apps locally using the library from this repository, you sh
20
26
  First, in the root of this repository:
21
27
 
22
28
  ```bash
23
- bun link
29
+ npm install
30
+ npm run build
31
+ npm link
24
32
  ```
25
33
 
26
34
  Then in your Edge App directory:
27
35
 
28
36
  ```bash
29
37
  cd /path/to/your-edge-app
30
- bun link @screenly/edge-apps
38
+ npm link @screenly/edge-apps
31
39
  ```
32
40
 
33
41
  To unlink the package when you're done with local development, run the following in your Edge App directory:
34
42
 
35
43
  ```bash
36
- bun install --force
37
- ```
38
-
39
- Then in the root of this repository:
40
-
41
- ```bash
42
- bun unlink
44
+ npm install
43
45
  ```
44
46
 
45
47
  ## Quick Start
@@ -97,7 +99,7 @@ signalReady()
97
99
 
98
100
  ## Web Components
99
101
 
100
- This library includes reusable web components for building consistent Edge Apps. See the [components documentation](https://github.com/Screenly/edge-apps-library/blob/master/docs/components.md) for usage details.
102
+ This library includes reusable web components for building consistent Edge Apps. See the [components documentation](https://github.com/Screenly/edge-apps-library/blob/main/docs/components.md) for usage details.
101
103
 
102
104
  ## Edge Apps Scripts CLI
103
105
 
@@ -110,13 +112,13 @@ This package provides the `edge-apps-scripts` CLI tool for running shared develo
110
112
  Start the Vite development server with mock data from `screenly.yml` and `mock-data.yml`:
111
113
 
112
114
  ```bash
113
- bun run dev
115
+ npm run dev
114
116
  ```
115
117
 
116
118
  #### Building
117
119
 
118
120
  ```bash
119
- bun run build
121
+ npm run build
120
122
  ```
121
123
 
122
124
  #### Linting
@@ -124,13 +126,13 @@ bun run build
124
126
  To lint your Edge App:
125
127
 
126
128
  ```bash
127
- bun run lint
129
+ npm run lint
128
130
  ```
129
131
 
130
132
  To lint and automatically fix issues:
131
133
 
132
134
  ```bash
133
- bun run lint -- --fix
135
+ npm run lint -- --fix
134
136
  ```
135
137
 
136
138
  #### Type Checking
@@ -138,7 +140,7 @@ bun run lint -- --fix
138
140
  Run TypeScript type checking:
139
141
 
140
142
  ```bash
141
- bun run type-check
143
+ npm run type-check
142
144
  ```
143
145
 
144
146
  ### Command-Line Utilities for Edge Apps
@@ -158,7 +160,7 @@ It is recommended to add the following scripts to your Edge App's `package.json`
158
160
  "build:dev": "edge-apps-scripts build:dev",
159
161
  "lint": "edge-apps-scripts lint",
160
162
  "type-check": "edge-apps-scripts type-check",
161
- "deploy": "bun run build && screenly edge-app deploy --path=dist/"
163
+ "deploy": "npm run build && screenly edge-app deploy --path=dist/"
162
164
  }
163
165
  }
164
166
  ```
@@ -197,7 +199,7 @@ import type {
197
199
  ## Development
198
200
 
199
201
  ```bash
200
- bun install # Install dependencies
201
- bun test # Run tests
202
- bun run build # Build library
202
+ npm install # Install dependencies
203
+ npm test # Run tests
204
+ npm run build # Build library
203
205
  ```
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@screenly/edge-apps",
3
- "version": "1.0.0-rc.1",
3
+ "version": "1.0.0-rc.2",
4
4
  "description": "A TypeScript library for interfacing with Screenly Edge Apps API",
5
5
  "type": "module",
6
6
  "engines": {
@@ -79,6 +79,10 @@
79
79
  ],
80
80
  "author": "Screenly",
81
81
  "license": "MIT",
82
+ "repository": {
83
+ "type": "git",
84
+ "url": "https://github.com/Screenly/edge-apps-library"
85
+ },
82
86
  "publishConfig": {
83
87
  "access": "public"
84
88
  },
@@ -2,6 +2,8 @@ import http from 'http'
2
2
  import https from 'https'
3
3
  import { URL } from 'url'
4
4
 
5
+ const MAX_REDIRECTS = 10
6
+
5
7
  function setCorsHeaders(res) {
6
8
  res.setHeader('Access-Control-Allow-Origin', '*')
7
9
  res.setHeader(
@@ -12,7 +14,80 @@ function setCorsHeaders(res) {
12
14
  res.setHeader('Access-Control-Max-Age', '86400')
13
15
  }
14
16
 
15
- function makeProxyRequest(httpModule, parsedUrl, req, res) {
17
+ function handleRedirect(
18
+ location,
19
+ req,
20
+ res,
21
+ proxyRes,
22
+ currentUrl,
23
+ redirectCount,
24
+ ) {
25
+ if (redirectCount >= MAX_REDIRECTS) {
26
+ proxyRes.resume()
27
+ res.writeHead(508, { 'Content-Type': 'application/json' })
28
+ res.end(JSON.stringify({ error: 'Too many redirects' }))
29
+ return
30
+ }
31
+
32
+ try {
33
+ const redirectUrl = new URL(location, currentUrl)
34
+ if (redirectUrl.protocol !== 'http:' && redirectUrl.protocol !== 'https:') {
35
+ proxyRes.resume()
36
+ res.writeHead(502, { 'Content-Type': 'application/json' })
37
+ res.end(JSON.stringify({ error: 'Invalid redirect location' }))
38
+ return
39
+ }
40
+ const redirectModule = redirectUrl.protocol === 'https:' ? https : http
41
+ proxyRes.resume()
42
+ makeProxyRequest(redirectModule, redirectUrl, req, res, redirectCount + 1)
43
+ } catch {
44
+ proxyRes.resume()
45
+ res.writeHead(502, { 'Content-Type': 'application/json' })
46
+ res.end(JSON.stringify({ error: 'Invalid redirect location' }))
47
+ }
48
+ }
49
+
50
+ function handleProxyResponse(proxyRes, req, res, currentUrl, redirectCount) {
51
+ if (
52
+ proxyRes.statusCode >= 301 &&
53
+ proxyRes.statusCode <= 308 &&
54
+ proxyRes.headers.location &&
55
+ ['GET', 'HEAD'].includes(req.method)
56
+ ) {
57
+ handleRedirect(
58
+ proxyRes.headers.location,
59
+ req,
60
+ res,
61
+ proxyRes,
62
+ currentUrl,
63
+ redirectCount,
64
+ )
65
+ return
66
+ }
67
+
68
+ const excludeHeaders = [
69
+ 'connection',
70
+ 'keep-alive',
71
+ 'proxy-authenticate',
72
+ 'proxy-authorization',
73
+ 'te',
74
+ 'trailers',
75
+ 'transfer-encoding',
76
+ 'upgrade',
77
+ ]
78
+
79
+ Object.keys(proxyRes.headers).forEach((key) => {
80
+ if (!excludeHeaders.includes(key.toLowerCase())) {
81
+ res.setHeader(key, proxyRes.headers[key])
82
+ }
83
+ })
84
+
85
+ setCorsHeaders(res)
86
+ res.writeHead(proxyRes.statusCode)
87
+ proxyRes.pipe(res)
88
+ }
89
+
90
+ function makeProxyRequest(httpModule, parsedUrl, req, res, redirectCount = 0) {
16
91
  const options = {
17
92
  hostname: parsedUrl.hostname,
18
93
  port: parsedUrl.port || (parsedUrl.protocol === 'https:' ? 443 : 80),
@@ -29,38 +104,15 @@ function makeProxyRequest(httpModule, parsedUrl, req, res) {
29
104
  delete options.headers['x-forwarded-proto']
30
105
  delete options.headers['x-forwarded-host']
31
106
 
32
- const proxyReq = httpModule.request(options, (proxyRes) => {
33
- const excludeHeaders = [
34
- 'connection',
35
- 'keep-alive',
36
- 'proxy-authenticate',
37
- 'proxy-authorization',
38
- 'te',
39
- 'trailers',
40
- 'transfer-encoding',
41
- 'upgrade',
42
- ]
43
-
44
- Object.keys(proxyRes.headers).forEach((key) => {
45
- if (!excludeHeaders.includes(key.toLowerCase())) {
46
- res.setHeader(key, proxyRes.headers[key])
47
- }
48
- })
49
-
50
- res.writeHead(proxyRes.statusCode)
51
- proxyRes.pipe(res)
52
- })
107
+ const proxyReq = httpModule.request(options, (proxyRes) =>
108
+ handleProxyResponse(proxyRes, req, res, parsedUrl, redirectCount),
109
+ )
53
110
 
54
111
  proxyReq.on('error', (error) => {
55
112
  console.error('Proxy error:', error.message)
56
113
  if (!res.headersSent) {
57
114
  res.writeHead(500, { 'Content-Type': 'application/json' })
58
- res.end(
59
- JSON.stringify({
60
- error: 'Proxy error',
61
- message: error.message,
62
- }),
63
- )
115
+ res.end(JSON.stringify({ error: 'Proxy error', message: error.message }))
64
116
  }
65
117
  })
66
118
 
@@ -68,11 +120,7 @@ function makeProxyRequest(httpModule, parsedUrl, req, res) {
68
120
  proxyReq.destroy()
69
121
  if (!res.headersSent) {
70
122
  res.writeHead(504, { 'Content-Type': 'application/json' })
71
- res.end(
72
- JSON.stringify({
73
- error: 'Gateway timeout',
74
- }),
75
- )
123
+ res.end(JSON.stringify({ error: 'Gateway timeout' }))
76
124
  }
77
125
  })
78
126