serverless-ircd 0.2.0 → 0.4.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/.github/workflows/ci.yml +2 -2
- package/.github/workflows/deploy-aws.yml +1 -3
- package/.github/workflows/deploy-cf-tcp.yml +87 -0
- package/.github/workflows/deploy-cf.yml +1 -1
- package/.node-version +1 -0
- package/.nvmrc +1 -0
- package/CHANGELOG.md +258 -18
- package/README.md +72 -30
- package/apps/aws-stack/README.md +2 -2
- package/apps/aws-stack/bin/aws.ts +7 -0
- package/apps/aws-stack/package.json +4 -4
- package/apps/aws-stack/src/aws-stack.ts +118 -6
- package/apps/aws-stack/tests/stack.test.ts +98 -3
- package/apps/cf-tcp-container/Dockerfile +69 -0
- package/apps/cf-tcp-container/package.json +34 -0
- package/apps/cf-tcp-container/src/config-loader.ts +145 -0
- package/apps/cf-tcp-container/src/container-do.ts +38 -0
- package/apps/cf-tcp-container/src/container-server.ts +363 -0
- package/apps/cf-tcp-container/src/main.ts +77 -0
- package/apps/cf-tcp-container/src/persistence.ts +144 -0
- package/apps/cf-tcp-container/src/worker.ts +41 -0
- package/apps/cf-tcp-container/terraform/provider.tf +24 -0
- package/apps/cf-tcp-container/terraform/spectrum.tf +81 -0
- package/apps/cf-tcp-container/tests/config-loader.test.ts +217 -0
- package/apps/cf-tcp-container/tests/container-server.test.ts +465 -0
- package/apps/cf-tcp-container/tests/persistence.test.ts +227 -0
- package/apps/cf-tcp-container/tests/tls-e2e.test.ts +275 -0
- package/apps/cf-tcp-container/tsconfig.build.json +17 -0
- package/apps/cf-tcp-container/tsconfig.test.json +15 -0
- package/apps/cf-tcp-container/vitest.config.ts +26 -0
- package/apps/cf-tcp-container/wrangler.toml +63 -0
- package/apps/cf-worker/package.json +1 -1
- package/apps/cf-worker/scripts/smoke.mjs +0 -0
- package/apps/cf-worker/src/worker.ts +8 -2
- package/apps/cf-worker/tests/smoke.test.ts +1 -0
- package/apps/cf-worker/wrangler.test.toml +11 -1
- package/apps/cf-worker/wrangler.toml +69 -19
- package/apps/local-cli/package.json +1 -1
- package/apps/local-cli/src/config-loader.ts +11 -0
- package/apps/local-cli/src/main.ts +1 -1
- package/apps/local-cli/src/server.ts +46 -3
- package/apps/local-cli/tests/e2e.test.ts +52 -0
- package/package.json +19 -16
- package/packages/aws-adapter/package.json +3 -3
- package/packages/aws-adapter/src/account-store.ts +121 -0
- package/packages/aws-adapter/src/admission.ts +74 -0
- package/packages/aws-adapter/src/aws-runtime.ts +124 -34
- package/packages/aws-adapter/src/cdk-table-defs.ts +5 -1
- package/packages/aws-adapter/src/config-loader.ts +62 -0
- package/packages/aws-adapter/src/dynamo-account-store.ts +95 -0
- package/packages/aws-adapter/src/handlers/connect.ts +64 -8
- package/packages/aws-adapter/src/handlers/default.ts +43 -2
- package/packages/aws-adapter/src/handlers/disconnect.ts +27 -8
- package/packages/aws-adapter/src/handlers/index.ts +120 -9
- package/packages/aws-adapter/src/handlers/nlb-stream.ts +481 -0
- package/packages/aws-adapter/src/handlers/ping-checker.ts +1 -1
- package/packages/aws-adapter/src/index.ts +13 -0
- package/packages/aws-adapter/tests/account-store-dynamo.test.ts +182 -0
- package/packages/aws-adapter/tests/account-store.test.ts +279 -0
- package/packages/aws-adapter/tests/admission.test.ts +70 -0
- package/packages/aws-adapter/tests/aws-harness.ts +13 -1
- package/packages/aws-adapter/tests/config-loader.test.ts +75 -0
- package/packages/aws-adapter/tests/connect.test.ts +78 -0
- package/packages/aws-adapter/tests/disconnect-fanout.test.ts +343 -0
- package/packages/aws-adapter/tests/gone-exception.test.ts +31 -26
- package/packages/aws-adapter/tests/handlers.test.ts +194 -47
- package/packages/aws-adapter/tests/nlb-stream.test.ts +478 -0
- package/packages/aws-adapter/tests/ping-checker.test.ts +34 -29
- package/packages/aws-adapter/tests/sweeper.test.ts +25 -18
- package/packages/aws-adapter/tests/transactions.test.ts +25 -20
- package/packages/cf-adapter/package.json +1 -1
- package/packages/cf-adapter/src/cf-runtime.ts +40 -22
- package/packages/cf-adapter/src/channel-do.ts +40 -1
- package/packages/cf-adapter/src/channel-registry-do.ts +58 -0
- package/packages/cf-adapter/src/config-loader.ts +62 -0
- package/packages/cf-adapter/src/connection-do.ts +181 -31
- package/packages/cf-adapter/src/d1-account-store.ts +198 -0
- package/packages/cf-adapter/src/env.ts +58 -8
- package/packages/cf-adapter/src/index.ts +11 -9
- package/packages/cf-adapter/tests/cf-harness.ts +11 -1
- package/packages/cf-adapter/tests/cf-integration.test.ts +2 -1
- package/packages/cf-adapter/tests/cf-runtime.test.ts +91 -0
- package/packages/cf-adapter/tests/config-loader.test.ts +22 -0
- package/packages/cf-adapter/tests/connection-do-channel-registration.test.ts +37 -0
- package/packages/cf-adapter/tests/connection-do-no-batching-reservation.test.ts +52 -0
- package/packages/cf-adapter/tests/connection-do-sasl-d1.test.ts +166 -0
- package/packages/cf-adapter/tests/connection-do.test.ts +40 -0
- package/packages/cf-adapter/tests/d1-account-store.test.ts +226 -0
- package/packages/cf-adapter/tests/raw-modules.d.ts +11 -0
- package/packages/cf-adapter/tests/worker/main.ts +9 -1
- package/packages/cf-adapter/tests/worker/stubs/channel-stub.ts +7 -1
- package/packages/cf-adapter/wrangler.test.toml +18 -1
- package/packages/in-memory-runtime/package.json +1 -1
- package/packages/in-memory-runtime/src/in-memory-runtime.ts +14 -28
- package/packages/in-memory-runtime/tests/in-memory-runtime.test.ts +19 -0
- package/packages/irc-core/package.json +8 -2
- package/packages/irc-core/scripts/generate-build-info.mjs +31 -0
- package/packages/irc-core/src/caps/capabilities.ts +23 -2
- package/packages/irc-core/src/case-fold.ts +64 -0
- package/packages/irc-core/src/cloak.ts +1 -1
- package/packages/irc-core/src/commands/cap.ts +8 -1
- package/packages/irc-core/src/commands/index.ts +11 -0
- package/packages/irc-core/src/commands/invite.ts +6 -9
- package/packages/irc-core/src/commands/ison.ts +61 -0
- package/packages/irc-core/src/commands/isupport.ts +1 -1
- package/packages/irc-core/src/commands/join.ts +4 -3
- package/packages/irc-core/src/commands/kick.ts +4 -11
- package/packages/irc-core/src/commands/list.ts +5 -4
- package/packages/irc-core/src/commands/mode.ts +5 -9
- package/packages/irc-core/src/commands/motd-lines.ts +127 -0
- package/packages/irc-core/src/commands/motd.ts +6 -110
- package/packages/irc-core/src/commands/oper.ts +151 -0
- package/packages/irc-core/src/commands/quit.ts +12 -0
- package/packages/irc-core/src/commands/registration.ts +26 -19
- package/packages/irc-core/src/commands/sasl.ts +72 -9
- package/packages/irc-core/src/commands/server-info.ts +129 -0
- package/packages/irc-core/src/commands/tagmsg.ts +205 -0
- package/packages/irc-core/src/commands/userhost.ts +84 -0
- package/packages/irc-core/src/commands/whowas.ts +113 -0
- package/packages/irc-core/src/config.ts +84 -3
- package/packages/irc-core/src/credential-hashing.ts +124 -0
- package/packages/irc-core/src/effects.ts +6 -29
- package/packages/irc-core/src/index.ts +3 -0
- package/packages/irc-core/src/ports.ts +240 -7
- package/packages/irc-core/src/protocol/numerics.ts +14 -8
- package/packages/irc-core/src/types.ts +60 -1
- package/packages/irc-core/tests/account-store.test.ts +131 -0
- package/packages/irc-core/tests/caps/capabilities.test.ts +4 -3
- package/packages/irc-core/tests/case-fold.test.ts +80 -0
- package/packages/irc-core/tests/commands/cap.test.ts +33 -1
- package/packages/irc-core/tests/commands/ison.test.ts +166 -0
- package/packages/irc-core/tests/commands/kick.test.ts +15 -0
- package/packages/irc-core/tests/commands/oper.test.ts +257 -0
- package/packages/irc-core/tests/commands/quit.test.ts +69 -2
- package/packages/irc-core/tests/commands/registration.test.ts +256 -19
- package/packages/irc-core/tests/commands/sasl.test.ts +118 -10
- package/packages/irc-core/tests/commands/server-info.test.ts +274 -0
- package/packages/irc-core/tests/commands/tagmsg.test.ts +662 -0
- package/packages/irc-core/tests/commands/userhost.test.ts +264 -0
- package/packages/irc-core/tests/commands/who.test.ts +22 -4
- package/packages/irc-core/tests/commands/whois.test.ts +8 -1
- package/packages/irc-core/tests/commands/whowas.test.ts +312 -0
- package/packages/irc-core/tests/config.test.ts +170 -1
- package/packages/irc-core/tests/credential-hashing.test.ts +170 -0
- package/packages/irc-core/tests/effects.test.ts +0 -27
- package/packages/irc-core/tests/nick-history-store.test.ts +162 -0
- package/packages/irc-core/tests/numerics.test.ts +12 -0
- package/packages/irc-core/tests/types.test.ts +35 -1
- package/packages/irc-core/tsconfig.build.json +1 -1
- package/packages/irc-core/tsconfig.test.json +1 -1
- package/packages/irc-server/package.json +1 -1
- package/packages/irc-server/src/actor.ts +182 -14
- package/packages/irc-server/src/dispatch.ts +0 -3
- package/packages/irc-server/src/index.ts +10 -2
- package/packages/irc-server/src/routing.ts +21 -0
- package/packages/irc-server/src/transport.ts +101 -0
- package/packages/irc-server/tests/actor.test.ts +617 -1
- package/packages/irc-server/tests/dispatch.test.ts +0 -17
- package/packages/irc-server/tests/routing.test.ts +7 -0
- package/packages/irc-server/tests/transport.test.ts +230 -0
- package/packages/irc-test-support/package.json +1 -1
- package/packages/irc-test-support/src/harness.ts +44 -9
- package/packages/irc-test-support/src/in-memory-harness.ts +78 -13
- package/packages/irc-test-support/src/index.ts +3 -0
- package/packages/irc-test-support/src/scenarios.ts +132 -2
- package/packages/irc-test-support/tests/in-memory-harness.test.ts +2 -1
- package/packages/irc-test-support/tests/in-memory-scenarios.test.ts +23 -9
- package/pnpm-workspace.yaml +9 -0
- package/tools/ci-hardening/package.json +1 -1
- package/tools/package.json +4 -0
- package/tools/seed-aws-accounts.ts +79 -0
- package/tools/seed-cf-accounts.ts +104 -0
- package/tools/tcp-ws-forwarder/package.json +1 -1
- package/AGENTS.md +0 -5
- package/MOTD.txt +0 -3
- package/PLAN-FIXES.md +0 -358
- package/PLAN.md +0 -420
- package/dashboards/cloudwatch-irc.json +0 -139
- package/docs/AWS-Adapter-Architecture.md +0 -494
- package/docs/AWS-Deployment.md +0 -1107
- package/docs/Cloudflare-Deployment-Guide.md +0 -660
- package/docs/Home.md +0 -1
- package/docs/Observability.md +0 -87
- package/docs/PlanIRCv3Websocket.md +0 -489
- package/docs/PlanWebClient.md +0 -451
- package/docs/Release-Process.md +0 -440
- package/progress.md +0 -107
- package/tickets.md +0 -2485
- package/webircgateway/LICENSE +0 -201
- package/webircgateway/Makefile +0 -44
- package/webircgateway/README.md +0 -134
- package/webircgateway/config.conf.example +0 -135
- package/webircgateway/go.mod +0 -16
- package/webircgateway/go.sum +0 -89
- package/webircgateway/main.go +0 -118
- package/webircgateway/pkg/dnsbl/dnsbl.go +0 -121
- package/webircgateway/pkg/identd/identd.go +0 -86
- package/webircgateway/pkg/identd/rpcclient.go +0 -59
- package/webircgateway/pkg/irc/isupport.go +0 -56
- package/webircgateway/pkg/irc/message.go +0 -217
- package/webircgateway/pkg/irc/state.go +0 -79
- package/webircgateway/pkg/proxy/proxy.go +0 -129
- package/webircgateway/pkg/proxy/server.go +0 -237
- package/webircgateway/pkg/recaptcha/recaptcha.go +0 -59
- package/webircgateway/pkg/webircgateway/client.go +0 -741
- package/webircgateway/pkg/webircgateway/client_command_handlers.go +0 -495
- package/webircgateway/pkg/webircgateway/config.go +0 -385
- package/webircgateway/pkg/webircgateway/gateway.go +0 -278
- package/webircgateway/pkg/webircgateway/gateway_utils.go +0 -133
- package/webircgateway/pkg/webircgateway/hooks.go +0 -152
- package/webircgateway/pkg/webircgateway/letsencrypt.go +0 -41
- package/webircgateway/pkg/webircgateway/messagetags.go +0 -103
- package/webircgateway/pkg/webircgateway/transport_kiwiirc.go +0 -206
- package/webircgateway/pkg/webircgateway/transport_sockjs.go +0 -107
- package/webircgateway/pkg/webircgateway/transport_tcp.go +0 -113
- package/webircgateway/pkg/webircgateway/transport_websocket.go +0 -126
- package/webircgateway/pkg/webircgateway/utils.go +0 -147
- package/webircgateway/plugins/example/plugin.go +0 -11
- package/webircgateway/plugins/stats/plugin.go +0 -52
- package/webircgateway/staticcheck.conf +0 -1
- package/webircgateway/webircgateway.svg +0 -3
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
# Cloudflare Spectrum config for the ServerlessIRCd TCP+TLS transport.
|
|
3
|
+
#
|
|
4
|
+
# Spectrum terminates TLS on port 6697 and forwards plaintext TCP to the
|
|
5
|
+
# container origin. The origin is the Cloudflare Container (or external
|
|
6
|
+
# compute) running the IRC core on port 6667.
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# terraform init
|
|
10
|
+
# terraform apply \
|
|
11
|
+
# -var zone_id=YOUR_ZONE_ID \
|
|
12
|
+
# -var origin_address=container-origin.example.com \
|
|
13
|
+
# -var hostname=irc.example.com
|
|
14
|
+
#
|
|
15
|
+
# The `tls = "flexible"` mode means TLS is terminated by Spectrum and the
|
|
16
|
+
# connection to the origin is plaintext (matching the container's plaintext
|
|
17
|
+
# TCP listener). For mTLS passthrough (SASL EXTERNAL via client cert), set
|
|
18
|
+
# `tls = "full"` and configure the origin to present its own certificate.
|
|
19
|
+
###############################################################################
|
|
20
|
+
|
|
21
|
+
variable "zone_id" {
|
|
22
|
+
type = string
|
|
23
|
+
description = "Cloudflare zone ID for the domain (e.g. example.com)."
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
variable "origin_address" {
|
|
27
|
+
type = string
|
|
28
|
+
description = "Hostname or IP of the TCP origin (CF Container or external compute)."
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
variable "origin_port" {
|
|
32
|
+
type = number
|
|
33
|
+
default = 6667
|
|
34
|
+
description = "Port the TCP origin listens on (plaintext IRC)."
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
variable "hostname" {
|
|
38
|
+
type = string
|
|
39
|
+
default = "irc.example.com"
|
|
40
|
+
description = "Public hostname clients connect to (irc+tls on :6697)."
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
variable "spectrum_port" {
|
|
44
|
+
type = number
|
|
45
|
+
default = 6697
|
|
46
|
+
description = "Public port Spectrum listens on (IRC-over-TLS)."
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
variable "tls_mode" {
|
|
50
|
+
type = string
|
|
51
|
+
default = "flexible"
|
|
52
|
+
description = "Spectrum TLS mode: flexible (TLS→CF, plain→origin) or full (TLS end-to-end)."
|
|
53
|
+
|
|
54
|
+
validation {
|
|
55
|
+
condition = contains(["flexible", "full", "strict"], var.tls_mode)
|
|
56
|
+
error_message = "tls_mode must be one of: flexible, full, strict."
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
resource "cloudflare_spectrum_application" "irc_tls" {
|
|
61
|
+
zone_id = var.zone_id
|
|
62
|
+
protocol = "tcp/${var.spectrum_port}"
|
|
63
|
+
|
|
64
|
+
dns {
|
|
65
|
+
type = "CNAME"
|
|
66
|
+
name = var.hostname
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
origin_dns {
|
|
70
|
+
name = var.origin_address
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
origin_port = var.origin_port
|
|
74
|
+
tls = var.tls_mode
|
|
75
|
+
ip_firewall = true
|
|
76
|
+
argo_smart_routing = true
|
|
77
|
+
|
|
78
|
+
# PROXY protocol v1 forwards the real client IP to the origin so the
|
|
79
|
+
# container's admission gate (per-IP limits) sees the actual source.
|
|
80
|
+
proxy_protocol = "v1"
|
|
81
|
+
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { type ContainerConfigEnv, loadContainerConfig } from '../src/config-loader.js';
|
|
3
|
+
|
|
4
|
+
describe('config-loader — IRC server config', () => {
|
|
5
|
+
it('parses required serverName and networkName', () => {
|
|
6
|
+
const cfg = loadContainerConfig({ SERVER_NAME: 'irc.example.com', NETWORK_NAME: 'ExampleNet' });
|
|
7
|
+
expect(cfg.server.serverName).toBe('irc.example.com');
|
|
8
|
+
expect(cfg.server.networkName).toBe('ExampleNet');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('splits MOTD_LINES on newline', () => {
|
|
12
|
+
const cfg = loadContainerConfig({
|
|
13
|
+
SERVER_NAME: 'irc.test',
|
|
14
|
+
NETWORK_NAME: 'TestNet',
|
|
15
|
+
MOTD_LINES: 'line one\nline two\nline three',
|
|
16
|
+
});
|
|
17
|
+
expect(cfg.server.motdLines).toEqual(['line one', 'line two', 'line three']);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('coerces numeric env vars', () => {
|
|
21
|
+
const cfg = loadContainerConfig({
|
|
22
|
+
SERVER_NAME: 'irc.test',
|
|
23
|
+
NETWORK_NAME: 'TestNet',
|
|
24
|
+
MAX_CHANNELS_PER_USER: '5',
|
|
25
|
+
NICK_LEN: '20',
|
|
26
|
+
});
|
|
27
|
+
expect(cfg.server.maxChannelsPerUser).toBe(5);
|
|
28
|
+
expect(cfg.server.nickLen).toBe(20);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('parses SASL accounts from newline-delimited user:password', () => {
|
|
32
|
+
const cfg = loadContainerConfig({
|
|
33
|
+
SERVER_NAME: 'irc.test',
|
|
34
|
+
NETWORK_NAME: 'TestNet',
|
|
35
|
+
SASL_ACCOUNTS: 'alice:secret\nbob:pass2',
|
|
36
|
+
});
|
|
37
|
+
expect(cfg.server.saslAccounts).toEqual([
|
|
38
|
+
{ username: 'alice', password: 'secret' },
|
|
39
|
+
{ username: 'bob', password: 'pass2' },
|
|
40
|
+
]);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('applies schema default serverName when unset', () => {
|
|
44
|
+
const cfg = loadContainerConfig({ NETWORK_NAME: 'TestNet' } as ContainerConfigEnv);
|
|
45
|
+
expect(cfg.server.serverName).toBe('irc.example.com');
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe('config-loader — container-specific knobs', () => {
|
|
50
|
+
it('defaults tcpPort to 6667', () => {
|
|
51
|
+
const cfg = loadContainerConfig({ SERVER_NAME: 'irc.test', NETWORK_NAME: 'TestNet' });
|
|
52
|
+
expect(cfg.tcpPort).toBe(6667);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('defaults tcpHost to 0.0.0.0 (bind-all for Spectrum origin)', () => {
|
|
56
|
+
const cfg = loadContainerConfig({ SERVER_NAME: 'irc.test', NETWORK_NAME: 'TestNet' });
|
|
57
|
+
expect(cfg.tcpHost).toBe('0.0.0.0');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('reads TCP_PORT override', () => {
|
|
61
|
+
const cfg = loadContainerConfig({
|
|
62
|
+
SERVER_NAME: 'irc.test',
|
|
63
|
+
NETWORK_NAME: 'TestNet',
|
|
64
|
+
TCP_PORT: '7000',
|
|
65
|
+
});
|
|
66
|
+
expect(cfg.tcpPort).toBe(7000);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('reads TCP_HOST override', () => {
|
|
70
|
+
const cfg = loadContainerConfig({
|
|
71
|
+
SERVER_NAME: 'irc.test',
|
|
72
|
+
NETWORK_NAME: 'TestNet',
|
|
73
|
+
TCP_HOST: '127.0.0.1',
|
|
74
|
+
});
|
|
75
|
+
expect(cfg.tcpHost).toBe('127.0.0.1');
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('persistencePath is undefined when PERSISTENCE_PATH is unset', () => {
|
|
79
|
+
const cfg = loadContainerConfig({ SERVER_NAME: 'irc.test', NETWORK_NAME: 'TestNet' });
|
|
80
|
+
expect(cfg.persistencePath).toBeUndefined();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('reads PERSISTENCE_PATH', () => {
|
|
84
|
+
const cfg = loadContainerConfig({
|
|
85
|
+
SERVER_NAME: 'irc.test',
|
|
86
|
+
NETWORK_NAME: 'TestNet',
|
|
87
|
+
PERSISTENCE_PATH: '/data/state.json',
|
|
88
|
+
});
|
|
89
|
+
expect(cfg.persistencePath).toBe('/data/state.json');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('defaults snapshotIntervalMs to 60_000', () => {
|
|
93
|
+
const cfg = loadContainerConfig({ SERVER_NAME: 'irc.test', NETWORK_NAME: 'TestNet' });
|
|
94
|
+
expect(cfg.snapshotIntervalMs).toBe(60_000);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('reads SNAPSHOT_INTERVAL_MS override', () => {
|
|
98
|
+
const cfg = loadContainerConfig({
|
|
99
|
+
SERVER_NAME: 'irc.test',
|
|
100
|
+
NETWORK_NAME: 'TestNet',
|
|
101
|
+
SNAPSHOT_INTERVAL_MS: '5000',
|
|
102
|
+
});
|
|
103
|
+
expect(cfg.snapshotIntervalMs).toBe(5000);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('passes through SERVER_VERSION, CREATED_AT, CHANNEL_PREFIXES, and QUIT_MESSAGE', () => {
|
|
107
|
+
const cfg = loadContainerConfig({
|
|
108
|
+
SERVER_NAME: 'irc.test',
|
|
109
|
+
NETWORK_NAME: 'TestNet',
|
|
110
|
+
SERVER_VERSION: '2.0.0',
|
|
111
|
+
CREATED_AT: '1700000000000',
|
|
112
|
+
CHANNEL_PREFIXES: '#&',
|
|
113
|
+
QUIT_MESSAGE: 'Bye',
|
|
114
|
+
});
|
|
115
|
+
expect(cfg.server.serverVersion).toBe('2.0.0');
|
|
116
|
+
expect(cfg.server.createdAt).toBe(1_700_000_000_000);
|
|
117
|
+
expect(cfg.server.channelPrefixes).toBe('#&');
|
|
118
|
+
expect(cfg.server.quitMessage).toBe('Bye');
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('passes CREATED_AT string verbatim when non-numeric', () => {
|
|
122
|
+
const cfg = loadContainerConfig({
|
|
123
|
+
SERVER_NAME: 'irc.test',
|
|
124
|
+
NETWORK_NAME: 'TestNet',
|
|
125
|
+
CREATED_AT: 'a sunny day',
|
|
126
|
+
});
|
|
127
|
+
expect(cfg.server.createdAt).toBe('a sunny day');
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('coerces MAX_CLIENTS, MAX_TARGETS_PER_COMMAND, CHANNEL_LEN, TOPIC_LEN, MAX_LIST_ENTRIES', () => {
|
|
131
|
+
const cfg = loadContainerConfig({
|
|
132
|
+
SERVER_NAME: 'irc.test',
|
|
133
|
+
NETWORK_NAME: 'TestNet',
|
|
134
|
+
MAX_CLIENTS: '500',
|
|
135
|
+
MAX_TARGETS_PER_COMMAND: '3',
|
|
136
|
+
CHANNEL_LEN: '64',
|
|
137
|
+
TOPIC_LEN: '500',
|
|
138
|
+
MAX_LIST_ENTRIES: '10',
|
|
139
|
+
});
|
|
140
|
+
expect(cfg.server.maxClients).toBe(500);
|
|
141
|
+
expect(cfg.server.maxTargetsPerCommand).toBe(3);
|
|
142
|
+
expect(cfg.server.channelLen).toBe(64);
|
|
143
|
+
expect(cfg.server.topicLen).toBe(500);
|
|
144
|
+
expect(cfg.server.maxListEntries).toBe(10);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('parses OPER_USER + OPER_PASSWORD into operCreds', () => {
|
|
148
|
+
const cfg = loadContainerConfig({
|
|
149
|
+
SERVER_NAME: 'irc.test',
|
|
150
|
+
NETWORK_NAME: 'TestNet',
|
|
151
|
+
OPER_USER: 'admin',
|
|
152
|
+
OPER_PASSWORD: 'secret',
|
|
153
|
+
});
|
|
154
|
+
expect(cfg.server.operCreds).toEqual([{ user: 'admin', password: 'secret' }]);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('skips malformed SASL account lines', () => {
|
|
158
|
+
const cfg = loadContainerConfig({
|
|
159
|
+
SERVER_NAME: 'irc.test',
|
|
160
|
+
NETWORK_NAME: 'TestNet',
|
|
161
|
+
SASL_ACCOUNTS: 'alice:secret\nbadline\n \n:bobpass',
|
|
162
|
+
});
|
|
163
|
+
expect(cfg.server.saslAccounts).toEqual([{ username: 'alice', password: 'secret' }]);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('defaults tcpPort when TCP_PORT is empty or invalid', () => {
|
|
167
|
+
const cfg1 = loadContainerConfig({
|
|
168
|
+
SERVER_NAME: 'irc.test',
|
|
169
|
+
NETWORK_NAME: 'TestNet',
|
|
170
|
+
TCP_PORT: '',
|
|
171
|
+
});
|
|
172
|
+
expect(cfg1.tcpPort).toBe(6667);
|
|
173
|
+
const cfg2 = loadContainerConfig({
|
|
174
|
+
SERVER_NAME: 'irc.test',
|
|
175
|
+
NETWORK_NAME: 'TestNet',
|
|
176
|
+
TCP_PORT: 'not-a-number',
|
|
177
|
+
});
|
|
178
|
+
expect(cfg2.tcpPort).toBe(6667);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('defaults tcpHost when TCP_HOST is empty', () => {
|
|
182
|
+
const cfg = loadContainerConfig({
|
|
183
|
+
SERVER_NAME: 'irc.test',
|
|
184
|
+
NETWORK_NAME: 'TestNet',
|
|
185
|
+
TCP_HOST: ' ',
|
|
186
|
+
});
|
|
187
|
+
expect(cfg.tcpHost).toBe('0.0.0.0');
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('defaults snapshotIntervalMs when SNAPSHOT_INTERVAL_MS is invalid', () => {
|
|
191
|
+
const cfg = loadContainerConfig({
|
|
192
|
+
SERVER_NAME: 'irc.test',
|
|
193
|
+
NETWORK_NAME: 'TestNet',
|
|
194
|
+
SNAPSHOT_INTERVAL_MS: 'abc',
|
|
195
|
+
});
|
|
196
|
+
expect(cfg.snapshotIntervalMs).toBe(60_000);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('disables persistence when PERSISTENCE_PATH is empty', () => {
|
|
200
|
+
const cfg = loadContainerConfig({
|
|
201
|
+
SERVER_NAME: 'irc.test',
|
|
202
|
+
NETWORK_NAME: 'TestNet',
|
|
203
|
+
PERSISTENCE_PATH: '',
|
|
204
|
+
});
|
|
205
|
+
expect(cfg.persistencePath).toBeUndefined();
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it('omits motdLines when MOTD_LINES is empty', () => {
|
|
209
|
+
const cfg = loadContainerConfig({
|
|
210
|
+
SERVER_NAME: 'irc.test',
|
|
211
|
+
NETWORK_NAME: 'TestNet',
|
|
212
|
+
MOTD_LINES: '',
|
|
213
|
+
});
|
|
214
|
+
// Schema default applies; just verify it doesn't crash.
|
|
215
|
+
expect(cfg.server.serverName).toBe('irc.test');
|
|
216
|
+
});
|
|
217
|
+
});
|