@logux/server 0.13.1 → 0.15.0
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/LICENSE +1 -1
- package/README.md +18 -41
- package/{base-server → add-http-pages}/hello.html +34 -26
- package/add-http-pages/index.js +24 -0
- package/add-sync-map/index.d.ts +1 -3
- package/add-sync-map/index.js +4 -10
- package/base-server/index.d.ts +175 -119
- package/base-server/index.js +272 -184
- package/context/index.d.ts +70 -61
- package/context/index.js +33 -20
- package/create-reporter/index.js +80 -93
- package/human-formatter/index.js +60 -85
- package/human-formatter/utils.js +14 -0
- package/index.d.ts +1 -1
- package/index.js +1 -9
- package/options-loader/index.js +46 -14
- package/options-loader/index.test.js +3 -3
- package/options-loader/test.env +2 -0
- package/package.json +21 -32
- package/request/index.d.ts +1 -99
- package/request/index.js +2 -40
- package/server/index.d.ts +31 -40
- package/server/index.js +26 -22
- package/server-client/index.d.ts +21 -12
- package/server-client/index.js +56 -11
- package/test-client/index.d.ts +24 -7
- package/test-client/index.js +8 -8
- package/test-server/index.d.ts +27 -14
- package/test-server/index.js +25 -5
- package/url-pattern/index.js +28 -0
- package/bind-backend-proxy/index.js +0 -325
- package/bind-control-server/index.js +0 -137
- package/request/test.test.js +0 -134
package/human-formatter/index.js
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
import { once } from 'node:events'
|
|
2
1
|
import os from 'node:os'
|
|
3
|
-
import {
|
|
4
|
-
import pico from 'picocolors'
|
|
5
|
-
import pino from 'pino'
|
|
6
|
-
import abstractTransport from 'pino-abstract-transport'
|
|
7
|
-
import stripAnsi from 'strip-ansi'
|
|
2
|
+
import { stripVTControlCharacters, styleText } from 'node:util'
|
|
8
3
|
|
|
9
|
-
import { mulberry32, onceXmur3 } from './utils.js'
|
|
4
|
+
import { isBinary, mulberry32, onceXmur3 } from './utils.js'
|
|
10
5
|
|
|
6
|
+
const BINARY_MARK = '[binary]'
|
|
11
7
|
const INDENT = ' '
|
|
12
8
|
const PADDING = ' '
|
|
13
9
|
const SEPARATOR = os.EOL + os.EOL
|
|
@@ -30,10 +26,11 @@ const PARAMS_BLACKLIST = {
|
|
|
30
26
|
}
|
|
31
27
|
|
|
32
28
|
const LABELS = {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
29
|
+
20: str => label(' DEBUG ', 'white', 'bgWhite', 'black', str),
|
|
30
|
+
30: str => label(' INFO ', 'green', 'bgGreen', 'black', str),
|
|
31
|
+
40: str => label(' WARN ', 'yellow', 'bgYellow', 'black', str),
|
|
32
|
+
50: str => label(' ERROR ', 'red', 'bgRed', 'white', str),
|
|
33
|
+
60: str => label(' FATAL ', 'red', 'bgRed', 'white', str)
|
|
37
34
|
}
|
|
38
35
|
|
|
39
36
|
const COLORS = ['red', 'green', 'yellow', 'blue', 'magenta', 'cyan']
|
|
@@ -50,16 +47,16 @@ function formatNow() {
|
|
|
50
47
|
}
|
|
51
48
|
|
|
52
49
|
function rightPag(str, length) {
|
|
53
|
-
let add = length -
|
|
50
|
+
let add = length - stripVTControlCharacters(str).length
|
|
54
51
|
for (let i = 0; i < add; i++) str += ' '
|
|
55
52
|
return str
|
|
56
53
|
}
|
|
57
54
|
|
|
58
|
-
function label(
|
|
59
|
-
let pagged = rightPag(
|
|
60
|
-
let time =
|
|
61
|
-
let highlighted = message.replace(/`([^`]+)`/g,
|
|
62
|
-
return `${pagged}${
|
|
55
|
+
function label(type, color, labelBg, labelText, message) {
|
|
56
|
+
let pagged = rightPag(styleText(labelBg, styleText(labelText, type)), 8)
|
|
57
|
+
let time = styleText('dim', `at ${formatNow()}`)
|
|
58
|
+
let highlighted = message.replace(/`([^`]+)`/g, styleText('yellow', '$1'))
|
|
59
|
+
return `${pagged}${styleText('bold', styleText(color, highlighted))} ${time}`
|
|
63
60
|
}
|
|
64
61
|
|
|
65
62
|
function formatName(key) {
|
|
@@ -88,7 +85,7 @@ function shuffledColors(str) {
|
|
|
88
85
|
return result
|
|
89
86
|
}
|
|
90
87
|
|
|
91
|
-
function splitAndColorize(
|
|
88
|
+
function splitAndColorize(partLength, str) {
|
|
92
89
|
let strBuilder = []
|
|
93
90
|
let colors = shuffledColors(str)
|
|
94
91
|
|
|
@@ -104,58 +101,57 @@ function splitAndColorize(c, partLength, str) {
|
|
|
104
101
|
if (strToColorize.length === 1) {
|
|
105
102
|
color = colors[Math.abs(n - 1) % colors.length]
|
|
106
103
|
}
|
|
107
|
-
strBuilder.push(
|
|
104
|
+
strBuilder.push(styleText(color, strToColorize))
|
|
108
105
|
}
|
|
109
106
|
|
|
110
107
|
return strBuilder.join('')
|
|
111
108
|
}
|
|
112
109
|
|
|
113
|
-
function formatNodeId(
|
|
110
|
+
function formatNodeId(nodeId) {
|
|
114
111
|
let pos = nodeId.lastIndexOf(':')
|
|
115
112
|
if (pos === -1) {
|
|
116
113
|
return nodeId
|
|
117
114
|
} else {
|
|
118
115
|
let s = nodeId.split(':')
|
|
119
|
-
let id =
|
|
120
|
-
let random = splitAndColorize(
|
|
116
|
+
let id = styleText('bold', s[0])
|
|
117
|
+
let random = splitAndColorize(3, s[1])
|
|
121
118
|
return `${id}:${random}`
|
|
122
119
|
}
|
|
123
120
|
}
|
|
124
121
|
|
|
125
|
-
function formatValue(
|
|
126
|
-
if (
|
|
127
|
-
return '
|
|
122
|
+
function formatValue(value) {
|
|
123
|
+
if (isBinary(value)) {
|
|
124
|
+
return styleText('bold', BINARY_MARK)
|
|
125
|
+
} else if (typeof value === 'string') {
|
|
126
|
+
return '"' + styleText('bold', value) + '"'
|
|
128
127
|
} else if (Array.isArray(value)) {
|
|
129
|
-
return formatArray(
|
|
128
|
+
return formatArray(value)
|
|
130
129
|
} else if (typeof value === 'object' && value) {
|
|
131
|
-
return formatObject(
|
|
130
|
+
return formatObject(value)
|
|
132
131
|
} else {
|
|
133
|
-
return
|
|
132
|
+
return styleText('bold', `${value}`)
|
|
134
133
|
}
|
|
135
134
|
}
|
|
136
135
|
|
|
137
|
-
function formatObject(
|
|
138
|
-
let items = Object.keys(obj).map(k => `${k}: ${formatValue(
|
|
136
|
+
function formatObject(obj) {
|
|
137
|
+
let items = Object.keys(obj).map(k => `${k}: ${formatValue(obj[k])}`)
|
|
139
138
|
return '{ ' + items.join(', ') + ' }'
|
|
140
139
|
}
|
|
141
140
|
|
|
142
|
-
function formatArray(
|
|
143
|
-
let items = array.map(i => formatValue(
|
|
141
|
+
function formatArray(array) {
|
|
142
|
+
let items = array.map(i => formatValue(i))
|
|
144
143
|
return '[' + items.join(', ') + ']'
|
|
145
144
|
}
|
|
146
145
|
|
|
147
|
-
function formatActionId(
|
|
146
|
+
function formatActionId(id) {
|
|
148
147
|
let p = id.split(' ')
|
|
149
148
|
if (p.length === 1) {
|
|
150
149
|
return p
|
|
151
150
|
}
|
|
152
|
-
return `${
|
|
153
|
-
c,
|
|
154
|
-
p[1]
|
|
155
|
-
)} ${c.bold(p[2])}`
|
|
151
|
+
return `${styleText('bold', splitAndColorize(4, p[0]))} ${formatNodeId(p[1])}`
|
|
156
152
|
}
|
|
157
153
|
|
|
158
|
-
function formatParams(
|
|
154
|
+
function formatParams(params, parent) {
|
|
159
155
|
let maxName = params.reduce((max, param) => {
|
|
160
156
|
let name = param[0]
|
|
161
157
|
return name.length > max ? name.length : max
|
|
@@ -168,31 +164,36 @@ function formatParams(c, params, parent) {
|
|
|
168
164
|
|
|
169
165
|
let start = PADDING + rightPag(`${name}: `, maxName + 2)
|
|
170
166
|
|
|
171
|
-
if (
|
|
172
|
-
return start +
|
|
167
|
+
if (isBinary(value)) {
|
|
168
|
+
return start + styleText('bold', BINARY_MARK)
|
|
169
|
+
} else if (
|
|
170
|
+
name === 'Node ID' ||
|
|
171
|
+
(parent === 'Meta' && name === 'server')
|
|
172
|
+
) {
|
|
173
|
+
return start + formatNodeId(value)
|
|
173
174
|
} else if (
|
|
174
175
|
parent === 'Meta' &&
|
|
175
176
|
(name === 'clients' || name === 'excludeClients')
|
|
176
177
|
) {
|
|
177
|
-
return `${start}[${value.map(v => `"${formatNodeId(
|
|
178
|
+
return `${start}[${value.map(v => `"${formatNodeId(v)}"`).join()}]`
|
|
178
179
|
} else if (name === 'Action ID' || (parent === 'Meta' && name === 'id')) {
|
|
179
|
-
return start + formatActionId(
|
|
180
|
+
return start + formatActionId(value)
|
|
180
181
|
} else if (Array.isArray(value)) {
|
|
181
|
-
return start + formatArray(
|
|
182
|
+
return start + formatArray(value)
|
|
182
183
|
} else if (typeof value === 'object' && value) {
|
|
183
184
|
let nested = Object.keys(value).map(key => [key, value[key]])
|
|
184
185
|
return (
|
|
185
186
|
start +
|
|
186
187
|
NEXT_LINE +
|
|
187
188
|
INDENT +
|
|
188
|
-
formatParams(
|
|
189
|
+
formatParams(nested, name)
|
|
189
190
|
.split(NEXT_LINE)
|
|
190
191
|
.join(NEXT_LINE + INDENT)
|
|
191
192
|
)
|
|
192
193
|
} else if (typeof value === 'string' && parent) {
|
|
193
|
-
return start + '"' +
|
|
194
|
+
return start + '"' + styleText('bold', value) + '"'
|
|
194
195
|
} else {
|
|
195
|
-
return start +
|
|
196
|
+
return start + styleText('bold', `${value}`)
|
|
196
197
|
}
|
|
197
198
|
})
|
|
198
199
|
.join(NEXT_LINE)
|
|
@@ -212,7 +213,7 @@ function splitByLength(string, max) {
|
|
|
212
213
|
return lines.map(i => i.trim())
|
|
213
214
|
}
|
|
214
215
|
|
|
215
|
-
function prettyStackTrace(
|
|
216
|
+
function prettyStackTrace(stack, basepath) {
|
|
216
217
|
return stack
|
|
217
218
|
.split('\n')
|
|
218
219
|
.slice(1)
|
|
@@ -220,24 +221,25 @@ function prettyStackTrace(c, stack, basepath) {
|
|
|
220
221
|
let match = line.match(/\s+at ([^(]+) \(([^)]+)\)/)
|
|
221
222
|
let isSystem = !match || !match[2].startsWith(basepath)
|
|
222
223
|
if (isSystem) {
|
|
223
|
-
return
|
|
224
|
+
return styleText('gray', line.replace(/^\s*/, PADDING))
|
|
224
225
|
} else {
|
|
225
226
|
let func = match[1]
|
|
226
227
|
let relative = match[2].slice(basepath.length)
|
|
227
228
|
let converted = `${PADDING}at ${func} (./${relative})`
|
|
228
229
|
let isDependency = match[2].includes('node_modules')
|
|
229
|
-
return isDependency
|
|
230
|
+
return isDependency
|
|
231
|
+
? styleText('gray', converted)
|
|
232
|
+
: styleText('red', converted)
|
|
230
233
|
}
|
|
231
234
|
})
|
|
232
235
|
.join(NEXT_LINE)
|
|
233
236
|
}
|
|
234
237
|
|
|
235
|
-
function humanFormatter(options) {
|
|
236
|
-
let c = pico.createColors(options.color)
|
|
238
|
+
export default function humanFormatter(options) {
|
|
237
239
|
let basepath = options.basepath
|
|
238
240
|
|
|
239
241
|
return function format(record) {
|
|
240
|
-
let message = [LABELS[record.level](
|
|
242
|
+
let message = [LABELS[record.level](record.msg)]
|
|
241
243
|
let params = Object.keys(record)
|
|
242
244
|
.filter(key => !PARAMS_BLACKLIST[key])
|
|
243
245
|
.map(key => [formatName(key), record[key]])
|
|
@@ -252,53 +254,26 @@ function humanFormatter(options) {
|
|
|
252
254
|
}
|
|
253
255
|
|
|
254
256
|
if (record.err && record.err.stack) {
|
|
255
|
-
message.push(prettyStackTrace(
|
|
257
|
+
message.push(prettyStackTrace(record.err.stack, basepath))
|
|
256
258
|
}
|
|
257
259
|
|
|
258
|
-
message.push(formatParams(
|
|
260
|
+
message.push(formatParams(params))
|
|
259
261
|
|
|
260
262
|
if (record.note) {
|
|
261
263
|
let note = record.note
|
|
262
264
|
if (typeof note === 'string') {
|
|
263
|
-
note = note.replace(/`([^`]+)`/g,
|
|
265
|
+
note = note.replace(/`([^`]+)`/g, styleText('bold', '$1'))
|
|
264
266
|
note = [].concat(
|
|
265
267
|
...note
|
|
266
268
|
.split('\n')
|
|
267
269
|
.map(row => splitByLength(row, 80 - PADDING.length))
|
|
268
270
|
)
|
|
269
271
|
}
|
|
270
|
-
message.push(
|
|
272
|
+
message.push(
|
|
273
|
+
note.map(i => PADDING + styleText('gray', i)).join(NEXT_LINE)
|
|
274
|
+
)
|
|
271
275
|
}
|
|
272
276
|
|
|
273
277
|
return message.filter(i => i !== '').join(NEXT_LINE) + SEPARATOR
|
|
274
278
|
}
|
|
275
279
|
}
|
|
276
|
-
|
|
277
|
-
export default async function (options) {
|
|
278
|
-
let format = humanFormatter(options)
|
|
279
|
-
let destination = pino.destination({
|
|
280
|
-
dest: options.destination || 1,
|
|
281
|
-
sync: options.sync || false
|
|
282
|
-
})
|
|
283
|
-
await once(destination, 'ready')
|
|
284
|
-
let transform = new Transform({
|
|
285
|
-
autoDestroy: true,
|
|
286
|
-
objectMode: true,
|
|
287
|
-
transform(chunk, encoding, callback) {
|
|
288
|
-
callback(null, format(chunk))
|
|
289
|
-
}
|
|
290
|
-
})
|
|
291
|
-
|
|
292
|
-
return abstractTransport(
|
|
293
|
-
source => {
|
|
294
|
-
source.pipe(transform)
|
|
295
|
-
transform.pipe(destination)
|
|
296
|
-
},
|
|
297
|
-
{
|
|
298
|
-
close(err, cb) {
|
|
299
|
-
transform.end()
|
|
300
|
-
transform.on('close', cb.bind(null, err))
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
)
|
|
304
|
-
}
|
package/human-formatter/utils.js
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
export const BINARY = {
|
|
2
|
+
toJSON() {
|
|
3
|
+
return '[binary]'
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function isBinary(value) {
|
|
8
|
+
return (
|
|
9
|
+
value === BINARY ||
|
|
10
|
+
ArrayBuffer.isView(value) ||
|
|
11
|
+
value instanceof ArrayBuffer
|
|
12
|
+
)
|
|
13
|
+
}
|
|
14
|
+
|
|
1
15
|
export function onceXmur3(str) {
|
|
2
16
|
let h = 1779033703 ^ str.length
|
|
3
17
|
for (let i = 0; i < str.length; i++) {
|
package/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export {
|
|
|
16
16
|
ServerMeta,
|
|
17
17
|
wasNot403
|
|
18
18
|
} from './base-server/index.js'
|
|
19
|
-
export {
|
|
19
|
+
export { Context, ConnectContext, ChannelContext } from './context/index.js'
|
|
20
20
|
export { filterMeta } from './filter-meta/index.js'
|
|
21
21
|
export {
|
|
22
22
|
del,
|
package/index.js
CHANGED
|
@@ -8,15 +8,7 @@ export { ALLOWED_META } from './allowed-meta/index.js'
|
|
|
8
8
|
export { BaseServer, wasNot403 } from './base-server/index.js'
|
|
9
9
|
export { Context } from './context/index.js'
|
|
10
10
|
export { filterMeta } from './filter-meta/index.js'
|
|
11
|
-
export {
|
|
12
|
-
del,
|
|
13
|
-
get,
|
|
14
|
-
patch,
|
|
15
|
-
post,
|
|
16
|
-
put,
|
|
17
|
-
request,
|
|
18
|
-
ResponseError
|
|
19
|
-
} from './request/index.js'
|
|
11
|
+
export { ResponseError } from './request/index.js'
|
|
20
12
|
export { Server } from './server/index.js'
|
|
21
13
|
export { TestClient } from './test-client/index.js'
|
|
22
14
|
export { TestServer } from './test-server/index.js'
|
package/options-loader/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
import { styleText } from 'node:util'
|
|
3
4
|
|
|
4
5
|
export function loadOptions(spec, process, env) {
|
|
5
6
|
let rawCliArgs = gatherCliArgs(process.argv)
|
|
@@ -18,7 +19,7 @@ export function loadOptions(spec, process, env) {
|
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
let cliArgs = parseValues(spec, mapArgs(rawCliArgs, namesMap))
|
|
21
|
-
let dotenvArgs =
|
|
22
|
+
let dotenvArgs = loadEnv(env)
|
|
22
23
|
if (dotenvArgs) {
|
|
23
24
|
dotenvArgs = Object.fromEntries(
|
|
24
25
|
Object.entries(dotenvArgs).filter(([key]) =>
|
|
@@ -72,17 +73,38 @@ function parseValues(spec, args) {
|
|
|
72
73
|
parsed[key] = parsingResult[1]
|
|
73
74
|
} else {
|
|
74
75
|
throw Error(
|
|
75
|
-
`Failed to parse ${
|
|
76
|
+
`Failed to parse ${styleText('bold', key)} argument value. \n` +
|
|
76
77
|
parsingResult[0]
|
|
77
|
-
}`
|
|
78
78
|
)
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
return parsed
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
function
|
|
85
|
-
|
|
84
|
+
function loadEnv(file) {
|
|
85
|
+
if (!file || !existsSync(file)) {
|
|
86
|
+
file = join(process.cwd(), '.env')
|
|
87
|
+
if (!existsSync(file)) return undefined
|
|
88
|
+
}
|
|
89
|
+
let result = {}
|
|
90
|
+
let lines
|
|
91
|
+
try {
|
|
92
|
+
lines = readFileSync(file, 'utf8').split('\n')
|
|
93
|
+
} catch {
|
|
94
|
+
/* c8 ignore next 2 */
|
|
95
|
+
return undefined
|
|
96
|
+
}
|
|
97
|
+
for (let line of lines) {
|
|
98
|
+
if (line.trim().startsWith('#') || !line.includes('=')) {
|
|
99
|
+
continue
|
|
100
|
+
}
|
|
101
|
+
let [key, ...valueParts] = line.split('=')
|
|
102
|
+
result[key] = valueParts
|
|
103
|
+
.join('=')
|
|
104
|
+
.trim()
|
|
105
|
+
.replace(/(^"|"$|^'|'$)/g, '')
|
|
106
|
+
}
|
|
107
|
+
return result
|
|
86
108
|
}
|
|
87
109
|
|
|
88
110
|
function mapArgs(parsedCliArgs, argsSpec) {
|
|
@@ -106,8 +128,9 @@ function composeHelp(spec, argv) {
|
|
|
106
128
|
let nameColumnLength = Math.max(...options.map(it => it.full.length))
|
|
107
129
|
let envColumnLength = Math.max(...options.map(it => it.env.length))
|
|
108
130
|
|
|
109
|
-
let composeName = name =>
|
|
110
|
-
|
|
131
|
+
let composeName = name =>
|
|
132
|
+
styleText('yellow', name.padEnd(nameColumnLength + 2))
|
|
133
|
+
let composeEnv = env => styleText('cyan', env.padEnd(envColumnLength + 2))
|
|
111
134
|
let composeOptionHelp = option => {
|
|
112
135
|
return (
|
|
113
136
|
composeName(option.full) + composeEnv(option.env) + option.description
|
|
@@ -120,7 +143,7 @@ function composeHelp(spec, argv) {
|
|
|
120
143
|
let lastPart = pathParts[pathParts.length - 1]
|
|
121
144
|
examples = [
|
|
122
145
|
'',
|
|
123
|
-
|
|
146
|
+
styleText('bold', 'Examples:'),
|
|
124
147
|
...spec.examples.map(i => i.replace('$0', lastPart))
|
|
125
148
|
]
|
|
126
149
|
}
|
|
@@ -128,7 +151,7 @@ function composeHelp(spec, argv) {
|
|
|
128
151
|
return [
|
|
129
152
|
'Start Logux Server',
|
|
130
153
|
'',
|
|
131
|
-
|
|
154
|
+
styleText('bold', 'Options:'),
|
|
132
155
|
...options.map(option => composeOptionHelp(option)),
|
|
133
156
|
...examples
|
|
134
157
|
].join('\n')
|
|
@@ -157,7 +180,8 @@ export function oneOf(options, rawValue) {
|
|
|
157
180
|
if (!options.includes(rawValue)) {
|
|
158
181
|
let opt = JSON.stringify(options)
|
|
159
182
|
return [
|
|
160
|
-
`Expected ${
|
|
183
|
+
`Expected ${styleText('green', 'one of ' + opt)}, ` +
|
|
184
|
+
`got ${styleText('red', `${rawValue}`)}`,
|
|
161
185
|
null
|
|
162
186
|
]
|
|
163
187
|
} else {
|
|
@@ -168,7 +192,11 @@ export function oneOf(options, rawValue) {
|
|
|
168
192
|
export function number(rawValue) {
|
|
169
193
|
let parsed = Number.parseInt(rawValue, 10)
|
|
170
194
|
if (Number.isNaN(parsed)) {
|
|
171
|
-
return [
|
|
195
|
+
return [
|
|
196
|
+
`Expected ${styleText('green', 'number')}, ` +
|
|
197
|
+
`got ${styleText('red', `${rawValue}`)}`,
|
|
198
|
+
null
|
|
199
|
+
]
|
|
172
200
|
} else {
|
|
173
201
|
return [null, parsed]
|
|
174
202
|
}
|
|
@@ -176,7 +204,11 @@ export function number(rawValue) {
|
|
|
176
204
|
|
|
177
205
|
export function string(rawValue) {
|
|
178
206
|
if (typeof rawValue !== 'string') {
|
|
179
|
-
return [
|
|
207
|
+
return [
|
|
208
|
+
`Expected ${styleText('green', 'string')}, ` +
|
|
209
|
+
`got ${styleText('red', `${rawValue}`)}`,
|
|
210
|
+
null
|
|
211
|
+
]
|
|
180
212
|
} else {
|
|
181
213
|
return [null, rawValue]
|
|
182
214
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import '../test/force-colors.js'
|
|
2
|
+
|
|
1
3
|
import { resolve } from 'node:path'
|
|
2
4
|
import { describe, expect, it } from 'vitest'
|
|
3
5
|
|
|
@@ -73,9 +75,7 @@ describe('loadOptions', () => {
|
|
|
73
75
|
}
|
|
74
76
|
},
|
|
75
77
|
fakeProcess([], {}),
|
|
76
|
-
|
|
77
|
-
path: resolve(process.cwd(), 'options-loader/test.env')
|
|
78
|
-
}
|
|
78
|
+
resolve(process.cwd(), 'options-loader/test.env')
|
|
79
79
|
)
|
|
80
80
|
|
|
81
81
|
expect(options.port).toEqual(31337)
|
package/options-loader/test.env
CHANGED
package/package.json
CHANGED
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@logux/server",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Build own Logux server
|
|
3
|
+
"version": "0.15.0",
|
|
4
|
+
"description": "Build own Logux server",
|
|
5
5
|
"keywords": [
|
|
6
|
-
"
|
|
7
|
-
"server",
|
|
8
|
-
"framework",
|
|
9
|
-
"websocket",
|
|
10
|
-
"proxy",
|
|
6
|
+
"collaborative",
|
|
11
7
|
"crdt",
|
|
12
|
-
"event sourcing",
|
|
13
8
|
"distributed systems",
|
|
14
|
-
"
|
|
9
|
+
"event sourcing",
|
|
10
|
+
"framework",
|
|
11
|
+
"logux",
|
|
12
|
+
"proxy",
|
|
13
|
+
"server",
|
|
14
|
+
"websocket"
|
|
15
15
|
],
|
|
16
|
-
"author": "Andrey Sitnik <andrey@sitnik.ru>",
|
|
17
|
-
"license": "MIT",
|
|
18
16
|
"homepage": "https://logux.org/",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"author": "Andrey Sitnik <andrey@sitnik.es>",
|
|
19
19
|
"repository": "logux/server",
|
|
20
|
-
"engines": {
|
|
21
|
-
"node": "^18.0.0 || ^20.0.0 || >=22.0.0"
|
|
22
|
-
},
|
|
23
20
|
"type": "module",
|
|
24
21
|
"types": "./index.d.ts",
|
|
25
22
|
"exports": {
|
|
@@ -27,23 +24,15 @@
|
|
|
27
24
|
"./package.json": "./package.json"
|
|
28
25
|
},
|
|
29
26
|
"dependencies": {
|
|
30
|
-
"@logux/actions": "^0.
|
|
31
|
-
"@logux/core": "^0.
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"
|
|
40
|
-
"node-fetch": "^3.3.2",
|
|
41
|
-
"picocolors": "^1.0.1",
|
|
42
|
-
"pino": "9.3.2",
|
|
43
|
-
"pino-abstract-transport": "^1.2.0",
|
|
44
|
-
"semver": "^7.6.3",
|
|
45
|
-
"strip-ansi": "^7.1.0",
|
|
46
|
-
"url-pattern": "^1.0.3",
|
|
47
|
-
"ws": "^8.18.0"
|
|
27
|
+
"@logux/actions": "^0.6.0",
|
|
28
|
+
"@logux/core": "^0.11.0",
|
|
29
|
+
"cookie": "^2.0.1",
|
|
30
|
+
"fastq": "^1.20.1",
|
|
31
|
+
"nanoevents": "^10.0.0",
|
|
32
|
+
"nanoid": "^6.0.1",
|
|
33
|
+
"ws": "^8.21.3"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": "^22.5.0 || ^24.0.0 || >=26.0.0"
|
|
48
37
|
}
|
|
49
38
|
}
|
package/request/index.d.ts
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import type { RequestInit } from 'node-fetch'
|
|
2
|
-
import type fetch from 'node-fetch'
|
|
3
|
-
|
|
4
1
|
/**
|
|
5
2
|
* Throwing this error in `accessAndProcess` or `accessAndLoad`
|
|
6
3
|
* will deny the action.
|
|
@@ -9,100 +6,5 @@ export class ResponseError extends Error {
|
|
|
9
6
|
name: 'ResponseError'
|
|
10
7
|
statusCode: number
|
|
11
8
|
|
|
12
|
-
constructor(
|
|
13
|
-
statusCode: number,
|
|
14
|
-
url: string,
|
|
15
|
-
opts: RequestInit,
|
|
16
|
-
response: string
|
|
17
|
-
)
|
|
9
|
+
constructor(statusCode: number, url: string)
|
|
18
10
|
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Syntax sugar around `node-fetch`, which throws {@link ResponseError}
|
|
22
|
-
* on non-2xx response.
|
|
23
|
-
*
|
|
24
|
-
* @param url Resource URL.
|
|
25
|
-
* @param opts `fetch()` options.
|
|
26
|
-
* @param fetcher A way to replace `fetch()` for tests.
|
|
27
|
-
*/
|
|
28
|
-
export function request<Body = any>(
|
|
29
|
-
url: string,
|
|
30
|
-
opts?: RequestInit,
|
|
31
|
-
fetcher?: typeof fetch
|
|
32
|
-
): Body
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Syntax sugar for `GET` requests by `node-fetch`, throwing
|
|
36
|
-
* {@link ResponseError} on non-2xx response and parsing JSON response.
|
|
37
|
-
*
|
|
38
|
-
* ```js
|
|
39
|
-
* import { get } from '@logux/server'
|
|
40
|
-
*
|
|
41
|
-
* let user = get(url)
|
|
42
|
-
* ```
|
|
43
|
-
*
|
|
44
|
-
* @param url Resource URL.
|
|
45
|
-
* @param opts `fetch()` options.
|
|
46
|
-
* @param fetcher A way to replace `fetch()` for tests.
|
|
47
|
-
*/
|
|
48
|
-
export function get<Body = any>(
|
|
49
|
-
url: string,
|
|
50
|
-
opts?: Omit<RequestInit, 'method'>,
|
|
51
|
-
fetcher?: typeof fetch
|
|
52
|
-
): Body
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Syntax sugar for `POST` requests by `node-fetch`, throwing
|
|
56
|
-
* {@link ResponseError} on non-2xx response.
|
|
57
|
-
*
|
|
58
|
-
* @param url Resource URL.
|
|
59
|
-
* @param opts `fetch()` options.
|
|
60
|
-
* @param fetcher A way to replace `fetch()` for tests.
|
|
61
|
-
*/
|
|
62
|
-
export function post<Body = any>(
|
|
63
|
-
url: string,
|
|
64
|
-
opts?: Omit<RequestInit, 'method'>,
|
|
65
|
-
fetcher?: typeof fetch
|
|
66
|
-
): Body
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Syntax sugar for `PUT` requests by `node-fetch`, throwing
|
|
70
|
-
* {@link ResponseError} on non-2xx response and parsing JSON response.
|
|
71
|
-
*
|
|
72
|
-
* @param url Resource URL.
|
|
73
|
-
* @param opts `fetch()` options.
|
|
74
|
-
* @param fetcher A way to replace `fetch()` for tests.
|
|
75
|
-
*/
|
|
76
|
-
export function put<Body = any>(
|
|
77
|
-
url: string,
|
|
78
|
-
opts?: Omit<RequestInit, 'method'>,
|
|
79
|
-
fetcher?: typeof fetch
|
|
80
|
-
): Body
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Syntax sugar for `PATCH` requests by `node-fetch`, throwing
|
|
84
|
-
* {@link ResponseError} on non-2xx response and parsing JSON response.
|
|
85
|
-
*
|
|
86
|
-
* @param url Resource URL.
|
|
87
|
-
* @param opts `fetch()` options.
|
|
88
|
-
* @param fetcher A way to replace `fetch()` for tests.
|
|
89
|
-
*/
|
|
90
|
-
export function patch<Body = any>(
|
|
91
|
-
url: string,
|
|
92
|
-
opts?: Omit<RequestInit, 'method'>,
|
|
93
|
-
fetcher?: typeof fetch
|
|
94
|
-
): Body
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Syntax sugar for `DELETE` requests by `node-fetch`, throwing
|
|
98
|
-
* {@link ResponseError} on non-2xx response and parsing JSON response.
|
|
99
|
-
*
|
|
100
|
-
* @param url Resource URL.
|
|
101
|
-
* @param opts `fetch()` options.
|
|
102
|
-
* @param fetcher A way to replace `fetch()` for tests.
|
|
103
|
-
*/
|
|
104
|
-
export function del<Body = any>(
|
|
105
|
-
url: string,
|
|
106
|
-
opts?: Omit<RequestInit, 'method'>,
|
|
107
|
-
fetcher?: typeof fetch
|
|
108
|
-
): Body
|