mirror of
https://github.com/Cameri/nostream.git
synced 2025-06-21 06:00:51 +02:00
feat(utils): refactor settings to use yaml
This commit is contained in:
parent
8b8c4b4eaa
commit
5a8107f73c
@ -354,8 +354,7 @@ You can change the default folder by setting the `NOSTR_CONFIG_DIR` environment
|
|||||||
Run nostream using one of the quick-start guides at least once and `nostream/.nostr/settings.json` will be created.
|
Run nostream using one of the quick-start guides at least once and `nostream/.nostr/settings.json` will be created.
|
||||||
Any changes made to the settings file will be read on the next start.
|
Any changes made to the settings file will be read on the next start.
|
||||||
|
|
||||||
A sample settings file is included at the project root under the name `settings.sample.json`. Feel free to copy it to `nostream/.nostr/settings.json`
|
Default settings can be found under `resources/default-settings.yaml`. Feel free to copy it to `nostream/.nostr/settings.yaml` if you would like to have a settings file before running the relay first.
|
||||||
if you would like to have a settings file before running the relay first.
|
|
||||||
|
|
||||||
See [CONFIGURATION.md](CONFIGURATION.md) for a detailed explanation of each environment variable and setting.
|
See [CONFIGURATION.md](CONFIGURATION.md) for a detailed explanation of each environment variable and setting.
|
||||||
## Dev Channel
|
## Dev Channel
|
||||||
|
@ -1,216 +0,0 @@
|
|||||||
{
|
|
||||||
"info": {
|
|
||||||
"relay_url": "wss://nostream.your-domain.com",
|
|
||||||
"name": "nostream.your-domain.com",
|
|
||||||
"description": "A nostr relay written in Typescript.",
|
|
||||||
"pubkey": "replace-with-your-pubkey",
|
|
||||||
"contact": "operator@your-domain.com"
|
|
||||||
},
|
|
||||||
"payments": {
|
|
||||||
"enabled": false,
|
|
||||||
"processor": "zebedee",
|
|
||||||
"feeSchedules": {
|
|
||||||
"admission": [{
|
|
||||||
"enabled": false,
|
|
||||||
"descripton": "Admission fee charged per public key in msats (1000 msats = 1 satoshi)",
|
|
||||||
"amount": 1000000,
|
|
||||||
"whitelists": {
|
|
||||||
"pubkeys": ["replace-with-your-pubkey"]
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
"publication": [
|
|
||||||
{
|
|
||||||
"enabled": false,
|
|
||||||
"description": "Publication fee charged per event in msats (1000 msats = 1 satoshi)",
|
|
||||||
"amount": 10,
|
|
||||||
"whitelists": {
|
|
||||||
"pubkeys": ["replace-with-your-pubkey"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"paymentProcessors": {
|
|
||||||
"zebedee": {
|
|
||||||
"baseURL": "https://api.zebedee.io/",
|
|
||||||
"callbackBaseURL": "https://nostream.your-domain.com/callbacks/zebedee"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"network": {
|
|
||||||
"maxPayloadSize": 131072,
|
|
||||||
"remoteIpHeader": "x-forwarded-for",
|
|
||||||
"idleTimeout": 60
|
|
||||||
},
|
|
||||||
"workers": {
|
|
||||||
"count": 0
|
|
||||||
},
|
|
||||||
"limits": {
|
|
||||||
"invoice": {
|
|
||||||
"rateLimits": [
|
|
||||||
{
|
|
||||||
"period": 60000,
|
|
||||||
"rate": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"period": 3600000,
|
|
||||||
"rate": 30
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"period": 86400000,
|
|
||||||
"rate": 360
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ipWhitelist": [
|
|
||||||
"::1",
|
|
||||||
"::ffff:10.10.10.1"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"connection": {
|
|
||||||
"rateLimits": [
|
|
||||||
{
|
|
||||||
"period": 60000,
|
|
||||||
"rate": 12
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"period": 3600000,
|
|
||||||
"rate": 360
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"period": 86400000,
|
|
||||||
"rate": 2880
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ipWhitelist": [
|
|
||||||
"::1",
|
|
||||||
"::ffff:10.10.10.1"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"event": {
|
|
||||||
"eventId": {
|
|
||||||
"minLeadingZeroBits": 0
|
|
||||||
},
|
|
||||||
"kind": {
|
|
||||||
"whitelist": [],
|
|
||||||
"blacklist": []
|
|
||||||
},
|
|
||||||
"pubkey": {
|
|
||||||
"minBalanceMsats": 0,
|
|
||||||
"minLeadingZeroBits": 0,
|
|
||||||
"whitelist": [],
|
|
||||||
"blacklist": []
|
|
||||||
},
|
|
||||||
"createdAt": {
|
|
||||||
"maxPositiveDelta": 900,
|
|
||||||
"maxNegativeDelta": 0
|
|
||||||
},
|
|
||||||
"content": [
|
|
||||||
{
|
|
||||||
"description": "64 KB for event kind ranges 0-10 and 40-49",
|
|
||||||
"kinds": [[0, 10], [40, 49]],
|
|
||||||
"maxLength": 65536
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "96 KB for event kind ranges 11-39 and 50-max",
|
|
||||||
"kinds": [[11, 39], [50, 9007199254740991]],
|
|
||||||
"maxLength": 98304
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"rateLimits": [
|
|
||||||
{
|
|
||||||
"description": "6 events/min for event kinds 0, 3, 40 and 41",
|
|
||||||
"kinds": [0, 3, 40, 41],
|
|
||||||
"period": 60000,
|
|
||||||
"rate": 6
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "12 events/min for event kinds 1, 2, 4 and 42",
|
|
||||||
"kinds": [1, 2, 4, 42],
|
|
||||||
"period": 60000,
|
|
||||||
"rate": 12
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "360 events/hour for event kinds 1, 2, 4 and 42",
|
|
||||||
"kinds": [1, 2, 4, 42],
|
|
||||||
"period": 3600000,
|
|
||||||
"rate": 360
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "30 events/min for event kind ranges 5-7 and 43-49",
|
|
||||||
"kinds": [[5, 7], [43, 49]],
|
|
||||||
"period": 60000,
|
|
||||||
"rate": 30
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "24 events/min for replaceable events and parameterized replaceable events",
|
|
||||||
"kinds": [[10000, 19999], [30000, 39999]],
|
|
||||||
"period": 60000,
|
|
||||||
"rate": 24
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "60 events/min for ephemeral events",
|
|
||||||
"kinds": [[20000, 29999]],
|
|
||||||
"period": 60000,
|
|
||||||
"rate": 60
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "720 events/hour for all events",
|
|
||||||
"period": 3600000,
|
|
||||||
"rate": 720
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "2880 events/day for all events",
|
|
||||||
"period": 86400000,
|
|
||||||
"rate": 2880
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"whitelists": {
|
|
||||||
"pubkeys": [],
|
|
||||||
"ipAddresses": [
|
|
||||||
"::1",
|
|
||||||
"::ffff:10.10.10.1"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"client": {
|
|
||||||
"subscription": {
|
|
||||||
"maxSubscriptions": 10,
|
|
||||||
"maxFilters": 10
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"message": {
|
|
||||||
"rateLimits": [
|
|
||||||
{
|
|
||||||
"description": "60 subscriptions/min",
|
|
||||||
"types": ["REQ"],
|
|
||||||
"period": 60000,
|
|
||||||
"rate": 60
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "2880 subscriptions/hour",
|
|
||||||
"types": ["REQ"],
|
|
||||||
"period": 3600000,
|
|
||||||
"rate": 2880
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "120 raw messages/min",
|
|
||||||
"period": 60000,
|
|
||||||
"rate": 120
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "3600 raw messages/hour",
|
|
||||||
"period": 3600000,
|
|
||||||
"rate": 3600
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "86400 raw messages/day",
|
|
||||||
"period": 86400000,
|
|
||||||
"rate": 86400
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ipWhitelist": [
|
|
||||||
"::1",
|
|
||||||
"::ffff:10.10.10.1"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
173
resources/default-settings.yaml
Executable file
173
resources/default-settings.yaml
Executable file
@ -0,0 +1,173 @@
|
|||||||
|
info:
|
||||||
|
relay_url: wss://nostream.your-domain.com
|
||||||
|
name: nostream.your-domain.com
|
||||||
|
description: A nostr relay written in Typescript.
|
||||||
|
pubkey: replace-with-your-pubkey
|
||||||
|
contact: operator@your-domain.com
|
||||||
|
payments:
|
||||||
|
enabled: false
|
||||||
|
processor: zebedee
|
||||||
|
feeSchedules:
|
||||||
|
admission:
|
||||||
|
- enabled: false
|
||||||
|
descripton: Admission fee charged per public key in msats (1000 msats = 1 satoshi)
|
||||||
|
amount: 1000000
|
||||||
|
whitelists:
|
||||||
|
pubkeys:
|
||||||
|
- replace-with-your-pubkey
|
||||||
|
publication:
|
||||||
|
- enabled: false
|
||||||
|
description: Publication fee charged per event in msats (1000 msats = 1 satoshi)
|
||||||
|
amount: 10
|
||||||
|
whitelists:
|
||||||
|
pubkeys:
|
||||||
|
- replace-with-your-pubkey
|
||||||
|
paymentProcessors:
|
||||||
|
zebedee:
|
||||||
|
baseURL: https://api.zebedee.io/
|
||||||
|
callbackBaseURL: https://nostream.your-domain.com/callbacks/zebedee
|
||||||
|
network:
|
||||||
|
maxPayloadSize: 131072
|
||||||
|
remoteIpHeader: x-forwarded-for
|
||||||
|
idleTimeout: 60
|
||||||
|
workers:
|
||||||
|
count: 0
|
||||||
|
limits:
|
||||||
|
invoice:
|
||||||
|
rateLimits:
|
||||||
|
- period: 60000
|
||||||
|
rate: 1
|
||||||
|
- period: 3600000
|
||||||
|
rate: 30
|
||||||
|
- period: 86400000
|
||||||
|
rate: 360
|
||||||
|
ipWhitelist:
|
||||||
|
- "::1"
|
||||||
|
- "::ffff:10.10.10.1"
|
||||||
|
connection:
|
||||||
|
rateLimits:
|
||||||
|
- period: 60000
|
||||||
|
rate: 12
|
||||||
|
- period: 3600000
|
||||||
|
rate: 360
|
||||||
|
- period: 86400000
|
||||||
|
rate: 2880
|
||||||
|
ipWhitelist:
|
||||||
|
- "::1"
|
||||||
|
- "::ffff:10.10.10.1"
|
||||||
|
event:
|
||||||
|
eventId:
|
||||||
|
minLeadingZeroBits: 0
|
||||||
|
kind:
|
||||||
|
whitelist: []
|
||||||
|
blacklist: []
|
||||||
|
pubkey:
|
||||||
|
minBalanceMsats: 0
|
||||||
|
minLeadingZeroBits: 0
|
||||||
|
whitelist: []
|
||||||
|
blacklist: []
|
||||||
|
createdAt:
|
||||||
|
maxPositiveDelta: 900
|
||||||
|
maxNegativeDelta: 0
|
||||||
|
content:
|
||||||
|
- description: 64 KB for event kind ranges 0-10 and 40-49
|
||||||
|
kinds:
|
||||||
|
- - 0
|
||||||
|
- 10
|
||||||
|
- - 40
|
||||||
|
- 49
|
||||||
|
maxLength: 65536
|
||||||
|
- description: 96 KB for event kind ranges 11-39 and 50-max
|
||||||
|
kinds:
|
||||||
|
- - 11
|
||||||
|
- 39
|
||||||
|
- - 50
|
||||||
|
- 9007199254740991
|
||||||
|
maxLength: 98304
|
||||||
|
rateLimits:
|
||||||
|
- description: 6 events/min for event kinds 0, 3, 40 and 41
|
||||||
|
kinds:
|
||||||
|
- 0
|
||||||
|
- 3
|
||||||
|
- 40
|
||||||
|
- 41
|
||||||
|
period: 60000
|
||||||
|
rate: 6
|
||||||
|
- description: 12 events/min for event kinds 1, 2, 4 and 42
|
||||||
|
kinds:
|
||||||
|
- 1
|
||||||
|
- 2
|
||||||
|
- 4
|
||||||
|
- 42
|
||||||
|
period: 60000
|
||||||
|
rate: 12
|
||||||
|
- description: 360 events/hour for event kinds 1, 2, 4 and 42
|
||||||
|
kinds:
|
||||||
|
- 1
|
||||||
|
- 2
|
||||||
|
- 4
|
||||||
|
- 42
|
||||||
|
period: 3600000
|
||||||
|
rate: 360
|
||||||
|
- description: 30 events/min for event kind ranges 5-7 and 43-49
|
||||||
|
kinds:
|
||||||
|
- - 5
|
||||||
|
- 7
|
||||||
|
- - 43
|
||||||
|
- 49
|
||||||
|
period: 60000
|
||||||
|
rate: 30
|
||||||
|
- description: 24 events/min for replaceable events and parameterized replaceable
|
||||||
|
events
|
||||||
|
kinds:
|
||||||
|
- - 10000
|
||||||
|
- 19999
|
||||||
|
- - 30000
|
||||||
|
- 39999
|
||||||
|
period: 60000
|
||||||
|
rate: 24
|
||||||
|
- description: 60 events/min for ephemeral events
|
||||||
|
kinds:
|
||||||
|
- - 20000
|
||||||
|
- 29999
|
||||||
|
period: 60000
|
||||||
|
rate: 60
|
||||||
|
- description: 720 events/hour for all events
|
||||||
|
period: 3600000
|
||||||
|
rate: 720
|
||||||
|
- description: 2880 events/day for all events
|
||||||
|
period: 86400000
|
||||||
|
rate: 2880
|
||||||
|
whitelists:
|
||||||
|
pubkeys: []
|
||||||
|
ipAddresses:
|
||||||
|
- "::1"
|
||||||
|
- "::ffff:10.10.10.1"
|
||||||
|
client:
|
||||||
|
subscription:
|
||||||
|
maxSubscriptions: 10
|
||||||
|
maxFilters: 10
|
||||||
|
message:
|
||||||
|
rateLimits:
|
||||||
|
- description: 60 subscriptions/min
|
||||||
|
types:
|
||||||
|
- REQ
|
||||||
|
period: 60000
|
||||||
|
rate: 60
|
||||||
|
- description: 2880 subscriptions/hour
|
||||||
|
types:
|
||||||
|
- REQ
|
||||||
|
period: 3600000
|
||||||
|
rate: 2880
|
||||||
|
- description: 120 raw messages/min
|
||||||
|
period: 60000
|
||||||
|
rate: 120
|
||||||
|
- description: 3600 raw messages/hour
|
||||||
|
period: 3600000
|
||||||
|
rate: 3600
|
||||||
|
- description: 86400 raw messages/day
|
||||||
|
period: 86400000
|
||||||
|
rate: 86400
|
||||||
|
ipWhitelist:
|
||||||
|
- "::1"
|
||||||
|
- "::ffff:10.10.10.1"
|
@ -1,134 +0,0 @@
|
|||||||
{
|
|
||||||
"info": {
|
|
||||||
"relay_url": "wss://nostream.your-domain.com",
|
|
||||||
"name": "nostream.your-domain.com",
|
|
||||||
"description": "A nostr relay written in TypeScript.",
|
|
||||||
"pubkey": "replace-with-your-pubkey",
|
|
||||||
"contact": "operator@your-domain.com"
|
|
||||||
},
|
|
||||||
"network": {
|
|
||||||
"maxPayloadSize": 131072,
|
|
||||||
"remoteIpHeader": "x-forwarded-for",
|
|
||||||
"idleTimeout": 60
|
|
||||||
},
|
|
||||||
"workers": {
|
|
||||||
"count": 0
|
|
||||||
},
|
|
||||||
"limits": {
|
|
||||||
"connection": {
|
|
||||||
"rateLimits": [
|
|
||||||
{
|
|
||||||
"period": 60000,
|
|
||||||
"rate": 12
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"period": 3600000,
|
|
||||||
"rate": 360
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"period": 86400000,
|
|
||||||
"rate": 2880
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ipWhitelist": [
|
|
||||||
"::1",
|
|
||||||
"::ffff:10.10.10.1"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"event": {
|
|
||||||
"eventId": {
|
|
||||||
"minLeadingZeroBits": 0
|
|
||||||
},
|
|
||||||
"kind": {
|
|
||||||
"whitelist": [],
|
|
||||||
"blacklist": []
|
|
||||||
},
|
|
||||||
"pubkey": {
|
|
||||||
"minBalanceMsats": 10000,
|
|
||||||
"minLeadingZeroBits": 0,
|
|
||||||
"whitelist": [],
|
|
||||||
"blacklist": []
|
|
||||||
},
|
|
||||||
"createdAt": {
|
|
||||||
"maxPositiveDelta": 900,
|
|
||||||
"maxNegativeDelta": 0
|
|
||||||
},
|
|
||||||
"content": {
|
|
||||||
"maxLength": 1048576
|
|
||||||
},
|
|
||||||
"rateLimits": [
|
|
||||||
{
|
|
||||||
"kinds": [0, 3, 40, 41],
|
|
||||||
"period": 60000,
|
|
||||||
"rate": 6
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"kinds": [1, 2, 4, 42],
|
|
||||||
"period": 60000,
|
|
||||||
"rate": 12
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"kinds": [1, 2, 4, 42],
|
|
||||||
"period": 3600000,
|
|
||||||
"rate": 360
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"kinds": [[5, 7], [43, 49]],
|
|
||||||
"period": 60000,
|
|
||||||
"rate": 30
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"kinds": [[10000, 19999], [30000, 39999]],
|
|
||||||
"period": 60000,
|
|
||||||
"rate": 24
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"kinds": [[20000, 29999]],
|
|
||||||
"period": 60000,
|
|
||||||
"rate": 60
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"period": 3600000,
|
|
||||||
"rate": 720
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"period": 86400000,
|
|
||||||
"rate": 2880
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"whitelists": {
|
|
||||||
"pubkeys": [],
|
|
||||||
"ipAddresses": [
|
|
||||||
"::1",
|
|
||||||
"::ffff:10.10.10.1"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"client": {
|
|
||||||
"subscription": {
|
|
||||||
"maxSubscriptions": 10,
|
|
||||||
"maxFilters": 10
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"message": {
|
|
||||||
"rateLimits": [
|
|
||||||
{
|
|
||||||
"period": 60000,
|
|
||||||
"rate": 120
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"period": 3600000,
|
|
||||||
"rate": 3600
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"period": 86400000,
|
|
||||||
"rate": 86400
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ipWhitelist": [
|
|
||||||
"::1",
|
|
||||||
"::ffff:10.10.10.1"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,25 +2,36 @@ import fs from 'fs'
|
|||||||
import { homedir } from 'os'
|
import { homedir } from 'os'
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
import { mergeDeepRight } from 'ramda'
|
import { mergeDeepRight } from 'ramda'
|
||||||
|
import yaml from 'js-yaml'
|
||||||
|
|
||||||
import { createLogger } from '../factories/logger-factory'
|
import { createLogger } from '../factories/logger-factory'
|
||||||
import defaultSettingsJson from '../../resources/default-settings.json'
|
|
||||||
import { ISettings } from '../@types/settings'
|
import { ISettings } from '../@types/settings'
|
||||||
|
|
||||||
const debug = createLogger('settings')
|
const debug = createLogger('settings')
|
||||||
|
|
||||||
|
const FileType = {
|
||||||
|
yaml: 'yaml',
|
||||||
|
json: 'json',
|
||||||
|
}
|
||||||
|
|
||||||
export class SettingsStatic {
|
export class SettingsStatic {
|
||||||
static _settings: ISettings
|
static _settings: ISettings
|
||||||
|
|
||||||
public static getSettingsFilePath(filename = 'settings.json') {
|
public static getSettingsFileBasePath(): string {
|
||||||
return join(
|
return process.env.NOSTR_CONFIG_DIR ?? join(homedir(), '.nostr')
|
||||||
process.env.NOSTR_CONFIG_DIR ?? join(homedir(), '.nostr'),
|
|
||||||
filename
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static loadSettings(path: string) {
|
public static getDefaultSettingsFilePath(): string {
|
||||||
debug('loading settings from %s', path)
|
return `${join(process.cwd(), 'resources')}/default-settings.yaml`
|
||||||
|
}
|
||||||
|
|
||||||
|
public static loadAndParseYamlFile(path: string): ISettings {
|
||||||
|
const defaultSettingsFileContent = fs.readFileSync(path, 'utf8')
|
||||||
|
const defaults = yaml.load(defaultSettingsFileContent) as ISettings
|
||||||
|
return defaults
|
||||||
|
}
|
||||||
|
|
||||||
|
public static loadAndParseJsonFile(path: string) {
|
||||||
return JSON.parse(
|
return JSON.parse(
|
||||||
fs.readFileSync(
|
fs.readFileSync(
|
||||||
path,
|
path,
|
||||||
@ -29,28 +40,65 @@ export class SettingsStatic {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static settingsFileType(path) {
|
||||||
|
const files = fs.readdirSync(path).filter(fn => fn.startsWith('settings'))
|
||||||
|
if (files.length) {
|
||||||
|
const extension = files.pop().split('.')[1]
|
||||||
|
return FileType[extension]
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static loadSettings(path: string, fileType) {
|
||||||
|
debug('loading settings from %s', path)
|
||||||
|
|
||||||
|
switch (fileType) {
|
||||||
|
case FileType.json: {
|
||||||
|
debug('settings.json is deprecated, please use a yaml file based on resources/default-settings.yaml')
|
||||||
|
return this.loadAndParseJsonFile(path)
|
||||||
|
}
|
||||||
|
case FileType.yaml: {
|
||||||
|
return this.loadAndParseYamlFile(path)
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw new Error('settings file was missing or did not contain .yaml or .json extensions.')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static createSettings(): ISettings {
|
public static createSettings(): ISettings {
|
||||||
if (SettingsStatic._settings) {
|
if (SettingsStatic._settings) {
|
||||||
return SettingsStatic._settings
|
return SettingsStatic._settings
|
||||||
}
|
}
|
||||||
debug('creating settings')
|
debug('creating settings')
|
||||||
const path = SettingsStatic.getSettingsFilePath()
|
|
||||||
const defaults = defaultSettingsJson as ISettings
|
const basePath = SettingsStatic.getSettingsFileBasePath()
|
||||||
|
if (!fs.existsSync(basePath)) {
|
||||||
|
fs.mkdirSync(basePath)
|
||||||
|
}
|
||||||
|
const defaultsFilePath = SettingsStatic.getDefaultSettingsFilePath()
|
||||||
|
const fileType = SettingsStatic.settingsFileType(basePath)
|
||||||
|
const settingsFilePath = `${basePath}/settings.${fileType}`
|
||||||
|
|
||||||
|
const defaults = SettingsStatic.loadSettings(defaultsFilePath, FileType.yaml)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (fs.existsSync(path)) {
|
if (fileType) {
|
||||||
SettingsStatic._settings = mergeDeepRight(
|
SettingsStatic._settings = mergeDeepRight(
|
||||||
defaults,
|
defaults,
|
||||||
SettingsStatic.loadSettings(path)
|
SettingsStatic.loadSettings(settingsFilePath, fileType)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
SettingsStatic.saveSettings(path, defaults)
|
SettingsStatic.saveSettings(basePath, defaults)
|
||||||
SettingsStatic._settings = mergeDeepRight({}, defaults)
|
SettingsStatic._settings = mergeDeepRight({}, defaults)
|
||||||
}
|
}
|
||||||
|
|
||||||
return SettingsStatic._settings
|
return SettingsStatic._settings
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
debug('error reading config file at %s: %o', path, error)
|
debug('error reading config file at %s: %o', settingsFilePath, error)
|
||||||
|
|
||||||
return defaults
|
return defaults
|
||||||
}
|
}
|
||||||
@ -59,9 +107,9 @@ export class SettingsStatic {
|
|||||||
public static saveSettings(path: string, settings: ISettings) {
|
public static saveSettings(path: string, settings: ISettings) {
|
||||||
debug('saving settings to %s: %o', path, settings)
|
debug('saving settings to %s: %o', path, settings)
|
||||||
return fs.writeFileSync(
|
return fs.writeFileSync(
|
||||||
path,
|
`${path}/settings.yaml`,
|
||||||
JSON.stringify(settings, null, 2),
|
yaml.dump(settings),
|
||||||
{ encoding: 'utf-8' }
|
{ encoding: 'utf-8' },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,22 +19,45 @@ describe('SettingsStatic', () => {
|
|||||||
process.env = originalEnv
|
process.env = originalEnv
|
||||||
})
|
})
|
||||||
|
|
||||||
it('returns string ending with settings.json by default', () => {
|
it('returns string ending with .nostr/ by default', () => {
|
||||||
expect(SettingsStatic.getSettingsFilePath()).to.be.a('string').and.to.match(/settings\.json$/)
|
expect(SettingsStatic.getSettingsFileBasePath()).to.be.a('string').and.to.match(/s\.nostr$/)
|
||||||
})
|
|
||||||
|
|
||||||
it('returns string ending with given string', () => {
|
|
||||||
expect(SettingsStatic.getSettingsFilePath('ending')).to.be.a('string').and.to.match(/ending$/)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('returns path begins with user\'s home dir by default', () => {
|
it('returns path begins with user\'s home dir by default', () => {
|
||||||
expect(SettingsStatic.getSettingsFilePath()).to.be.a('string').and.equal(`${join(homedir(), '.nostr')}/settings.json`)
|
expect(SettingsStatic.getSettingsFileBasePath()).to.be.a('string').and.equal(`${join(homedir(), '.nostr')}/`)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('returns path with NOSTR_CONFIG_DIR if set', () => {
|
it('returns path with NOSTR_CONFIG_DIR if set', () => {
|
||||||
process.env.NOSTR_CONFIG_DIR = '/some/path'
|
process.env.NOSTR_CONFIG_DIR = '/some/path'
|
||||||
|
|
||||||
expect(SettingsStatic.getSettingsFilePath()).to.be.a('string').and.equal('/some/path/settings.json')
|
expect(SettingsStatic.getSettingsFileBasePath()).to.be.a('string').and.equal('/some/path/')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('.getDefaultSettingsFilePath', () => {
|
||||||
|
let originalEnv: NodeJS.ProcessEnv
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
originalEnv = process.env
|
||||||
|
process.env = {}
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
process.env = originalEnv
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns string ending with settings.json by default', () => {
|
||||||
|
expect(SettingsStatic.getDefaultSettingsFilePath()).to.be.a('string').and.to.match(/settings\.yaml$/)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns path begins with user\'s home dir by default', () => {
|
||||||
|
expect(SettingsStatic.getDefaultSettingsFilePath()).to.be.a('string').and.equal(`${join(homedir(), '.nostr')}/settings.yaml`)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns path with NOSTR_CONFIG_DIR if set', () => {
|
||||||
|
process.env.NOSTR_CONFIG_DIR = '/some/path'
|
||||||
|
|
||||||
|
expect(SettingsStatic.getDefaultSettingsFilePath()).to.be.a('string').and.equal('/some/path/settings.yaml')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -52,7 +75,7 @@ describe('SettingsStatic', () => {
|
|||||||
it('loads settings from given path', () => {
|
it('loads settings from given path', () => {
|
||||||
readFileSyncStub.returns('"content"')
|
readFileSyncStub.returns('"content"')
|
||||||
|
|
||||||
expect(SettingsStatic.loadSettings('/some/path')).to.equal('content')
|
expect(SettingsStatic.loadSettings('/some/path', 'yaml')).to.equal('content')
|
||||||
|
|
||||||
expect(readFileSyncStub).to.have.been.calledOnceWithExactly(
|
expect(readFileSyncStub).to.have.been.calledOnceWithExactly(
|
||||||
'/some/path',
|
'/some/path',
|
||||||
@ -75,7 +98,7 @@ describe('SettingsStatic', () => {
|
|||||||
sandbox = Sinon.createSandbox()
|
sandbox = Sinon.createSandbox()
|
||||||
|
|
||||||
existsSyncStub = sandbox.stub(fs, 'existsSync')
|
existsSyncStub = sandbox.stub(fs, 'existsSync')
|
||||||
getSettingsFilePathStub = sandbox.stub(SettingsStatic, 'getSettingsFilePath')
|
getSettingsFilePathStub = sandbox.stub(SettingsStatic, 'getSettingsFileBasePath')
|
||||||
saveSettingsStub = sandbox.stub(SettingsStatic, 'saveSettings')
|
saveSettingsStub = sandbox.stub(SettingsStatic, 'saveSettings')
|
||||||
loadSettingsStub = sandbox.stub(SettingsStatic, 'loadSettings')
|
loadSettingsStub = sandbox.stub(SettingsStatic, 'loadSettings')
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user