@tapflowio/relay 0.8.2 → 0.9.1
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/dist/RelayServer.d.ts +10 -0
- package/dist/RelayServer.d.ts.map +1 -1
- package/dist/RelayServer.js +53 -5
- package/dist/RelayServer.js.map +1 -1
- package/dist/api/builds.d.ts.map +1 -1
- package/dist/api/builds.js +14 -13
- package/dist/api/builds.js.map +1 -1
- package/dist/api/comments.d.ts.map +1 -1
- package/dist/api/comments.js +23 -10
- package/dist/api/comments.js.map +1 -1
- package/dist/api/team.d.ts.map +1 -1
- package/dist/api/team.js +4 -2
- package/dist/api/team.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/cert/AcmeCertProvider.d.ts +55 -0
- package/dist/lib/cert/AcmeCertProvider.d.ts.map +1 -0
- package/dist/lib/cert/AcmeCertProvider.js +62 -0
- package/dist/lib/cert/AcmeCertProvider.js.map +1 -0
- package/dist/lib/cert/AcmeClientIssuer.d.ts +23 -0
- package/dist/lib/cert/AcmeClientIssuer.d.ts.map +1 -0
- package/dist/lib/cert/AcmeClientIssuer.js +54 -0
- package/dist/lib/cert/AcmeClientIssuer.js.map +1 -0
- package/dist/lib/cert/CertProvider.d.ts +30 -0
- package/dist/lib/cert/CertProvider.d.ts.map +1 -0
- package/dist/lib/cert/CertProvider.js +4 -0
- package/dist/lib/cert/CertProvider.js.map +1 -0
- package/dist/lib/cert/CloudflareDnsProvider.d.ts +40 -0
- package/dist/lib/cert/CloudflareDnsProvider.d.ts.map +1 -0
- package/dist/lib/cert/CloudflareDnsProvider.js +93 -0
- package/dist/lib/cert/CloudflareDnsProvider.js.map +1 -0
- package/dist/lib/cert/DiskCertStore.d.ts +10 -0
- package/dist/lib/cert/DiskCertStore.d.ts.map +1 -0
- package/dist/lib/cert/DiskCertStore.js +35 -0
- package/dist/lib/cert/DiskCertStore.js.map +1 -0
- package/dist/lib/cert/DnsProvider.d.ts +7 -0
- package/dist/lib/cert/DnsProvider.d.ts.map +1 -0
- package/dist/lib/cert/DnsProvider.js +2 -0
- package/dist/lib/cert/DnsProvider.js.map +1 -0
- package/dist/lib/cert/ImportCertProvider.d.ts +20 -0
- package/dist/lib/cert/ImportCertProvider.d.ts.map +1 -0
- package/dist/lib/cert/ImportCertProvider.js +24 -0
- package/dist/lib/cert/ImportCertProvider.js.map +1 -0
- package/dist/lib/cert/VercelDnsProvider.d.ts +38 -0
- package/dist/lib/cert/VercelDnsProvider.d.ts.map +1 -0
- package/dist/lib/cert/VercelDnsProvider.js +146 -0
- package/dist/lib/cert/VercelDnsProvider.js.map +1 -0
- package/dist/lib/cert/accountKey.d.ts +2 -0
- package/dist/lib/cert/accountKey.d.ts.map +1 -0
- package/dist/lib/cert/accountKey.js +23 -0
- package/dist/lib/cert/accountKey.js.map +1 -0
- package/dist/lib/cert/addressPublisher.d.ts +20 -0
- package/dist/lib/cert/addressPublisher.d.ts.map +1 -0
- package/dist/lib/cert/addressPublisher.js +103 -0
- package/dist/lib/cert/addressPublisher.js.map +1 -0
- package/dist/lib/cert/createCertProvider.d.ts +20 -0
- package/dist/lib/cert/createCertProvider.d.ts.map +1 -0
- package/dist/lib/cert/createCertProvider.js +25 -0
- package/dist/lib/cert/createCertProvider.js.map +1 -0
- package/dist/lib/cert/dnsRegistry.d.ts +24 -0
- package/dist/lib/cert/dnsRegistry.d.ts.map +1 -0
- package/dist/lib/cert/dnsRegistry.js +36 -0
- package/dist/lib/cert/dnsRegistry.js.map +1 -0
- package/dist/lib/cert/index.d.ts +23 -0
- package/dist/lib/cert/index.d.ts.map +1 -0
- package/dist/lib/cert/index.js +12 -0
- package/dist/lib/cert/index.js.map +1 -0
- package/dist/lib/cert/parseCert.d.ts +3 -0
- package/dist/lib/cert/parseCert.d.ts.map +1 -0
- package/dist/lib/cert/parseCert.js +6 -0
- package/dist/lib/cert/parseCert.js.map +1 -0
- package/dist/lib/cert/renewal.d.ts +13 -0
- package/dist/lib/cert/renewal.d.ts.map +1 -0
- package/dist/lib/cert/renewal.js +28 -0
- package/dist/lib/cert/renewal.js.map +1 -0
- package/dist/lib/config.d.ts +23 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +51 -3
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/cors.d.ts +2 -0
- package/dist/lib/cors.d.ts.map +1 -0
- package/dist/lib/cors.js +18 -0
- package/dist/lib/cors.js.map +1 -0
- package/dist/lib/csrf.d.ts +3 -0
- package/dist/lib/csrf.d.ts.map +1 -0
- package/dist/lib/csrf.js +42 -0
- package/dist/lib/csrf.js.map +1 -0
- package/dist/lib/loadEnvFile.d.ts +2 -0
- package/dist/lib/loadEnvFile.d.ts.map +1 -0
- package/dist/lib/loadEnvFile.js +19 -0
- package/dist/lib/loadEnvFile.js.map +1 -0
- package/dist/lib/proxyConfig.d.ts +6 -0
- package/dist/lib/proxyConfig.d.ts.map +1 -0
- package/dist/lib/proxyConfig.js +27 -0
- package/dist/lib/proxyConfig.js.map +1 -0
- package/dist/lib/publicUrl.d.ts +3 -0
- package/dist/lib/publicUrl.d.ts.map +1 -0
- package/dist/lib/publicUrl.js +17 -0
- package/dist/lib/publicUrl.js.map +1 -0
- package/dist/lib/uploads.d.ts +2 -0
- package/dist/lib/uploads.d.ts.map +1 -0
- package/dist/lib/uploads.js +14 -0
- package/dist/lib/uploads.js.map +1 -0
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +13 -1
- package/dist/router.js.map +1 -1
- package/dist/server.js +43 -6
- package/dist/server.js.map +1 -1
- package/package.json +9 -8
- package/public/assets/AppCenter-CH3MXel8.js +16 -0
- package/public/assets/AppCenter-CH3MXel8.js.br +0 -0
- package/public/assets/Default-CK_yhJO6.js +1 -0
- package/public/assets/Default-CK_yhJO6.js.br +0 -0
- package/public/assets/Invite-9g1gI701.js +1 -0
- package/public/assets/Invite-9g1gI701.js.br +0 -0
- package/public/assets/MacResources-41d3_9X2.js +5 -0
- package/public/assets/MacResources-41d3_9X2.js.br +0 -0
- package/public/assets/NotFound-DsMP9eZN.js +1 -0
- package/public/assets/NotFound-DsMP9eZN.js.br +2 -0
- package/public/assets/QASession-B02bILlB.js +130 -0
- package/public/assets/QASession-B02bILlB.js.br +0 -0
- package/public/assets/ResetPassword-DsXsNFTA.js +1 -0
- package/public/assets/ResetPassword-DsXsNFTA.js.br +0 -0
- package/public/assets/Setup-CouJNq4v.js +1 -0
- package/public/assets/Setup-CouJNq4v.js.br +0 -0
- package/public/assets/Team-DUG0YTtb.js +6 -0
- package/public/assets/Team-DUG0YTtb.js.br +0 -0
- package/public/assets/Tokens-BWBEl4ax.js +6 -0
- package/public/assets/Tokens-BWBEl4ax.js.br +0 -0
- package/public/assets/alert-dialog-qlHDtr4B.js +1 -0
- package/public/assets/alert-dialog-qlHDtr4B.js.br +0 -0
- package/public/assets/badge-Cx2-XXcg.js +1 -0
- package/public/assets/badge-Cx2-XXcg.js.br +0 -0
- package/public/assets/build-format-BvNznvYq.js +11 -0
- package/public/assets/build-format-BvNznvYq.js.br +0 -0
- package/public/assets/dialog-DzNUT3NF.js +11 -0
- package/public/assets/dialog-DzNUT3NF.js.br +0 -0
- package/public/assets/index-BI7E3MD-.css +1 -0
- package/public/assets/index-BI7E3MD-.css.br +0 -0
- package/public/assets/index-Dfs85Uiw.js +274 -0
- package/public/assets/index-Dfs85Uiw.js.br +0 -0
- package/public/assets/inter-latin-ext-standard-normal-DpK-iCPk.woff2 +0 -0
- package/public/assets/inter-latin-standard-normal-BwkfbSeq.woff2 +0 -0
- package/public/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/public/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/public/assets/pencil-CrO7Me4O.js +6 -0
- package/public/assets/pencil-CrO7Me4O.js.br +0 -0
- package/public/assets/plus-DnAOz8DL.js +6 -0
- package/public/assets/plus-DnAOz8DL.js.br +0 -0
- package/public/assets/table-BXnp_tRt.js +1 -0
- package/public/assets/table-BXnp_tRt.js.br +0 -0
- package/public/assets/tabs-BTnhanO2.js +1 -0
- package/public/assets/tabs-BTnhanO2.js.br +0 -0
- package/public/assets/tinyh264.worker-DiJ50Hai.js.br +0 -0
- package/public/favicon.svg.br +0 -0
- package/public/index.html +2 -2
- package/public/index.html.br +0 -0
- package/public/logo-dark.svg.br +0 -0
- package/public/logo.svg.br +0 -0
- package/public/assets/index-Bhoumejm.js +0 -520
- package/public/assets/index-DX5Pf9T6.css +0 -1
- package/public/assets/inter-cyrillic-400-normal-HOLc17fK.woff +0 -0
- package/public/assets/inter-cyrillic-400-normal-obahsSVq.woff2 +0 -0
- package/public/assets/inter-cyrillic-500-normal-BasfLYem.woff2 +0 -0
- package/public/assets/inter-cyrillic-500-normal-CxZf_p3X.woff +0 -0
- package/public/assets/inter-cyrillic-600-normal-4D_pXhcN.woff +0 -0
- package/public/assets/inter-cyrillic-600-normal-CWCymEST.woff2 +0 -0
- package/public/assets/inter-cyrillic-ext-400-normal-BQZuk6qB.woff2 +0 -0
- package/public/assets/inter-cyrillic-ext-400-normal-DQukG94-.woff +0 -0
- package/public/assets/inter-cyrillic-ext-500-normal-B0yAr1jD.woff2 +0 -0
- package/public/assets/inter-cyrillic-ext-500-normal-BmqWE9Dz.woff +0 -0
- package/public/assets/inter-cyrillic-ext-600-normal-Bcila6Z-.woff +0 -0
- package/public/assets/inter-cyrillic-ext-600-normal-Dfes3d0z.woff2 +0 -0
- package/public/assets/inter-greek-400-normal-B4URO6DV.woff2 +0 -0
- package/public/assets/inter-greek-400-normal-q2sYcFCs.woff +0 -0
- package/public/assets/inter-greek-500-normal-BIZE56-Y.woff2 +0 -0
- package/public/assets/inter-greek-500-normal-Xzm54t5V.woff +0 -0
- package/public/assets/inter-greek-600-normal-BZpKdvQh.woff +0 -0
- package/public/assets/inter-greek-600-normal-plRanbMR.woff2 +0 -0
- package/public/assets/inter-greek-ext-400-normal-DGGRlc-M.woff2 +0 -0
- package/public/assets/inter-greek-ext-400-normal-KugGGMne.woff +0 -0
- package/public/assets/inter-greek-ext-500-normal-2j5mBUwD.woff +0 -0
- package/public/assets/inter-greek-ext-500-normal-C4iEst2y.woff2 +0 -0
- package/public/assets/inter-greek-ext-600-normal-B8X0CLgF.woff +0 -0
- package/public/assets/inter-greek-ext-600-normal-DRtmH8MT.woff2 +0 -0
- package/public/assets/inter-latin-400-normal-C38fXH4l.woff2 +0 -0
- package/public/assets/inter-latin-400-normal-CyCys3Eg.woff +0 -0
- package/public/assets/inter-latin-500-normal-BL9OpVg8.woff +0 -0
- package/public/assets/inter-latin-500-normal-Cerq10X2.woff2 +0 -0
- package/public/assets/inter-latin-600-normal-CiBQ2DWP.woff +0 -0
- package/public/assets/inter-latin-600-normal-LgqL8muc.woff2 +0 -0
- package/public/assets/inter-latin-ext-400-normal-77YHD8bZ.woff +0 -0
- package/public/assets/inter-latin-ext-400-normal-C1nco2VV.woff2 +0 -0
- package/public/assets/inter-latin-ext-500-normal-BxGbmqWO.woff +0 -0
- package/public/assets/inter-latin-ext-500-normal-CV4jyFjo.woff2 +0 -0
- package/public/assets/inter-latin-ext-600-normal-CIVaiw4L.woff +0 -0
- package/public/assets/inter-latin-ext-600-normal-D2bJ5OIk.woff2 +0 -0
- package/public/assets/inter-vietnamese-400-normal-Bbgyi5SW.woff +0 -0
- package/public/assets/inter-vietnamese-400-normal-DMkecbls.woff2 +0 -0
- package/public/assets/inter-vietnamese-500-normal-DOriooB6.woff2 +0 -0
- package/public/assets/inter-vietnamese-500-normal-mJboJaSs.woff +0 -0
- package/public/assets/inter-vietnamese-600-normal-BuLX-rYi.woff +0 -0
- package/public/assets/inter-vietnamese-600-normal-Cc8MFFhd.woff2 +0 -0
- package/public/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
- package/public/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
- package/public/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
- package/public/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
- package/public/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
- package/public/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/public/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
- package/public/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
- package/public/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
package/dist/lib/config.d.ts
CHANGED
|
@@ -22,6 +22,17 @@ declare const configSchema: z.ZodObject<{
|
|
|
22
22
|
provider: z.ZodLiteral<"tailscale">;
|
|
23
23
|
publicUrl: z.ZodOptional<z.ZodString>;
|
|
24
24
|
}, z.core.$strip>], "provider">>;
|
|
25
|
+
tls: z.ZodNullable<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
26
|
+
mode: z.ZodLiteral<"byo-api-token">;
|
|
27
|
+
domain: z.ZodString;
|
|
28
|
+
dnsProvider: z.ZodString;
|
|
29
|
+
publishAddress: z.ZodOptional<z.ZodBoolean>;
|
|
30
|
+
address: z.ZodOptional<z.ZodString>;
|
|
31
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
32
|
+
mode: z.ZodLiteral<"import-cert">;
|
|
33
|
+
certPath: z.ZodString;
|
|
34
|
+
keyPath: z.ZodString;
|
|
35
|
+
}, z.core.$strip>], "mode">>;
|
|
25
36
|
smtp: z.ZodObject<{
|
|
26
37
|
host: z.ZodString;
|
|
27
38
|
port: z.ZodNumber;
|
|
@@ -32,6 +43,7 @@ declare const configSchema: z.ZodObject<{
|
|
|
32
43
|
}, z.core.$strip>;
|
|
33
44
|
}, z.core.$strip>;
|
|
34
45
|
export type TapflowConfig = z.infer<typeof configSchema>;
|
|
46
|
+
export declare let loadedEnvPath: string | null;
|
|
35
47
|
export declare function loadOrCreatePersistedSecret(dataDir: string): string;
|
|
36
48
|
export declare const config: {
|
|
37
49
|
local: {
|
|
@@ -56,6 +68,17 @@ export declare const config: {
|
|
|
56
68
|
provider: "tailscale";
|
|
57
69
|
publicUrl?: string | undefined;
|
|
58
70
|
} | null;
|
|
71
|
+
tls: {
|
|
72
|
+
mode: "byo-api-token";
|
|
73
|
+
domain: string;
|
|
74
|
+
dnsProvider: string;
|
|
75
|
+
publishAddress?: boolean | undefined;
|
|
76
|
+
address?: string | undefined;
|
|
77
|
+
} | {
|
|
78
|
+
mode: "import-cert";
|
|
79
|
+
certPath: string;
|
|
80
|
+
keyPath: string;
|
|
81
|
+
} | null;
|
|
59
82
|
smtp: {
|
|
60
83
|
host: string;
|
|
61
84
|
port: number;
|
package/dist/lib/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAmDvB,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAoBhB,CAAA;AAEF,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAA;AA+BxD,eAAO,IAAI,aAAa,EAAE,MAAM,GAAG,IAAW,CAAA;AA4G9C,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAkBnE;AAaD,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAS,CAAA;AAC5B,eAAO,MAAM,SAAS,QAAkB,CAAA"}
|
package/dist/lib/config.js
CHANGED
|
@@ -4,6 +4,8 @@ import crypto from 'crypto';
|
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import { createLogger } from '@tapflowio/agent-core';
|
|
6
6
|
import { parseTrustedProxies } from './clientAddress.js';
|
|
7
|
+
import { dnsProviders } from './cert/dnsRegistry.js';
|
|
8
|
+
import { loadDataDirEnv } from './loadEnvFile.js';
|
|
7
9
|
const logger = createLogger('relay:config');
|
|
8
10
|
const tunnelSshSchema = z.object({
|
|
9
11
|
host: z.string().min(1),
|
|
@@ -21,6 +23,26 @@ const tailscaleTunnelSchema = z.object({
|
|
|
21
23
|
publicUrl: z.string().optional(),
|
|
22
24
|
});
|
|
23
25
|
const tunnelSchema = z.discriminatedUnion('provider', [ratholeTunnelSchema, tailscaleTunnelSchema]);
|
|
26
|
+
// LAN HTTPS (issue #232) — secure context용 TLS 종단 설정. 골격: v1은 LAN 가지만 구현.
|
|
27
|
+
// 비밀(DNS API 토큰)은 config 파일이 아니라 env에서 읽는다(예: TAPFLOW_CLOUDFLARE_TOKEN).
|
|
28
|
+
const importCertTlsSchema = z.object({
|
|
29
|
+
mode: z.literal('import-cert'),
|
|
30
|
+
certPath: z.string().min(1),
|
|
31
|
+
keyPath: z.string().min(1),
|
|
32
|
+
});
|
|
33
|
+
const byoApiTokenTlsSchema = z.object({
|
|
34
|
+
mode: z.literal('byo-api-token'),
|
|
35
|
+
domain: z.string().min(1),
|
|
36
|
+
// 유효 provider는 레지스트리가 정한다(새 provider 추가 시 스키마 무변경).
|
|
37
|
+
dnsProvider: z.string().min(1).refine((n) => dnsProviders.has(n), {
|
|
38
|
+
message: `unknown dnsProvider (available: ${dnsProviders.names().join(', ')})`,
|
|
39
|
+
}),
|
|
40
|
+
// 도메인 A 레코드를 LAN IP로 자동 발행(기본 ON). false면 사용자가 직접 관리.
|
|
41
|
+
publishAddress: z.boolean().optional(),
|
|
42
|
+
// 자동 감지 대신 쓸 고정 LAN IP(멀티NIC/VPN 환경 오버라이드).
|
|
43
|
+
address: z.string().min(1).optional(),
|
|
44
|
+
});
|
|
45
|
+
const tlsSchema = z.discriminatedUnion('mode', [byoApiTokenTlsSchema, importCertTlsSchema]);
|
|
24
46
|
const configSchema = z.object({
|
|
25
47
|
local: z.object({
|
|
26
48
|
port: z.number().int().min(1).max(65535),
|
|
@@ -32,6 +54,7 @@ const configSchema = z.object({
|
|
|
32
54
|
url: z.string().nullable(),
|
|
33
55
|
}),
|
|
34
56
|
tunnel: tunnelSchema.nullable(),
|
|
57
|
+
tls: tlsSchema.nullable(),
|
|
35
58
|
smtp: z.object({
|
|
36
59
|
host: z.string(),
|
|
37
60
|
port: z.number().int().min(1).max(65535),
|
|
@@ -52,6 +75,7 @@ const DEFAULTS = {
|
|
|
52
75
|
url: null,
|
|
53
76
|
},
|
|
54
77
|
tunnel: null,
|
|
78
|
+
tls: null,
|
|
55
79
|
smtp: {
|
|
56
80
|
host: '',
|
|
57
81
|
port: 587,
|
|
@@ -64,6 +88,8 @@ const DEFAULTS = {
|
|
|
64
88
|
function resolveDataDir(raw) {
|
|
65
89
|
return path.isAbsolute(raw) ? raw : path.join(process.cwd(), raw);
|
|
66
90
|
}
|
|
91
|
+
// Populated by load(): path of the dataDir/.env that was loaded, or null. CLI/server use it for a "loaded credentials" log.
|
|
92
|
+
export let loadedEnvPath = null;
|
|
67
93
|
function load() {
|
|
68
94
|
let file = {};
|
|
69
95
|
const configPath = path.join(process.cwd(), 'tapflow.config.json');
|
|
@@ -78,10 +104,17 @@ function load() {
|
|
|
78
104
|
if (file.local != null && 'jwtSecret' in file.local) {
|
|
79
105
|
logger.warn('local.jwtSecret in tapflow.config.json is deprecated — use JWT_SECRET env var instead');
|
|
80
106
|
}
|
|
107
|
+
// Resolve dataDir first, then load <dataDir>/.env, so every secret read below (JWT_SECRET, SMTP,
|
|
108
|
+
// DNS/ACME tokens) defaults to the .env file. dataDir itself can't come from .env (chicken-and-egg):
|
|
109
|
+
// it's set only by config.json or TAPFLOW_DATA_DIR. ambient process.env still wins over the file.
|
|
110
|
+
let dataDir = resolveDataDir(file.local?.dataDir ?? DEFAULTS.local.dataDir);
|
|
111
|
+
if (process.env.TAPFLOW_DATA_DIR)
|
|
112
|
+
dataDir = resolveDataDir(process.env.TAPFLOW_DATA_DIR);
|
|
113
|
+
loadedEnvPath = loadDataDirEnv(dataDir);
|
|
81
114
|
const cfg = {
|
|
82
115
|
local: {
|
|
83
116
|
port: file.local?.port ?? DEFAULTS.local.port,
|
|
84
|
-
dataDir
|
|
117
|
+
dataDir,
|
|
85
118
|
wsBackpressureBytes: DEFAULTS.local.wsBackpressureBytes,
|
|
86
119
|
trustedProxies: parseTrustedProxies(process.env.TAPFLOW_TRUSTED_PROXIES),
|
|
87
120
|
},
|
|
@@ -105,6 +138,22 @@ function load() {
|
|
|
105
138
|
: null,
|
|
106
139
|
};
|
|
107
140
|
})(),
|
|
141
|
+
tls: (() => {
|
|
142
|
+
if (file.tls == null)
|
|
143
|
+
return null;
|
|
144
|
+
const t = file.tls;
|
|
145
|
+
if (t.mode === 'import-cert') {
|
|
146
|
+
return { mode: 'import-cert', certPath: t.certPath ?? '', keyPath: t.keyPath ?? '' };
|
|
147
|
+
}
|
|
148
|
+
// Pass mode/provider through (no silent default) so zod rejects a missing/misspelled provider.
|
|
149
|
+
return {
|
|
150
|
+
mode: t.mode,
|
|
151
|
+
domain: t.domain ?? '',
|
|
152
|
+
dnsProvider: t.dnsProvider ?? '',
|
|
153
|
+
...(t.publishAddress !== undefined ? { publishAddress: t.publishAddress } : {}),
|
|
154
|
+
...(t.address !== undefined ? { address: t.address } : {}),
|
|
155
|
+
};
|
|
156
|
+
})(),
|
|
108
157
|
smtp: {
|
|
109
158
|
host: file.smtp?.host ?? DEFAULTS.smtp.host,
|
|
110
159
|
port: file.smtp?.port ?? DEFAULTS.smtp.port,
|
|
@@ -116,8 +165,7 @@ function load() {
|
|
|
116
165
|
};
|
|
117
166
|
if (process.env.TAPFLOW_PORT)
|
|
118
167
|
cfg.local.port = Number(process.env.TAPFLOW_PORT);
|
|
119
|
-
|
|
120
|
-
cfg.local.dataDir = resolveDataDir(process.env.TAPFLOW_DATA_DIR);
|
|
168
|
+
// TAPFLOW_DATA_DIR is already applied above (before the .env load) — it can't be set from .env.
|
|
121
169
|
if (process.env.TAPFLOW_WS_BACKPRESSURE_BYTES)
|
|
122
170
|
cfg.local.wsBackpressureBytes = Number(process.env.TAPFLOW_WS_BACKPRESSURE_BYTES);
|
|
123
171
|
if (process.env.TAPFLOW_RELAY_URL)
|
package/dist/lib/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,MAAM,MAAM,QAAQ,CAAA;AAC3B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,MAAM,MAAM,QAAQ,CAAA;AAC3B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEjD,MAAM,MAAM,GAAG,YAAY,CAAC,cAAc,CAAC,CAAA;AAE3C,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC/B,CAAC,CAAA;AAEF,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;IAC9B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,GAAG,EAAE,eAAe,CAAC,QAAQ,EAAE;CAChC,CAAC,CAAA;AAEF,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;IAChC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACjC,CAAC,CAAA;AAEF,MAAM,YAAY,GAAG,CAAC,CAAC,kBAAkB,CAAC,UAAU,EAAE,CAAC,mBAAmB,EAAE,qBAAqB,CAAC,CAAC,CAAA;AAEnG,0EAA0E;AAC1E,yEAAyE;AACzE,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;IAC9B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAC3B,CAAC,CAAA;AAEF,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC;IAChC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,oDAAoD;IACpD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;QAChE,OAAO,EAAE,mCAAmC,YAAY,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;KAC/E,CAAC;IACF,sDAAsD;IACtD,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACtC,4CAA4C;IAC5C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CACtC,CAAC,CAAA;AAEF,MAAM,SAAS,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,CAAC,CAAA;AAE3F,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC;QACxC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1B,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5C,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;KACpC,CAAC;IACF,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAC3B,CAAC;IACF,MAAM,EAAE,YAAY,CAAC,QAAQ,EAAE;IAC/B,GAAG,EAAE,SAAS,CAAC,QAAQ,EAAE;IACzB,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;QACb,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;QAChB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC;QACxC,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE;QACnB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;QAChB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;QAChB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;KACjB,CAAC;CACH,CAAC,CAAA;AAMF,MAAM,QAAQ,GAAG;IACf,KAAK,EAAE;QACL,IAAI,EAAE,IAAI;QACV,OAAO,EAAE,eAAe;QACxB,mBAAmB,EAAE,SAAS;QAC9B,cAAc,EAAE,EAAE;KACnB;IACD,KAAK,EAAE;QACL,GAAG,EAAE,IAAI;KACV;IACD,MAAM,EAAE,IAAI;IACZ,GAAG,EAAE,IAAI;IACT,IAAI,EAAE;QACJ,IAAI,EAAE,EAAE;QACR,IAAI,EAAE,GAAG;QACT,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,EAAE;QACR,IAAI,EAAE,EAAE;QACR,IAAI,EAAE,iCAAiC;KACxC;CACsB,CAAA;AAEzB,SAAS,cAAc,CAAC,GAAW;IACjC,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,GAAG,CAAC,CAAA;AACnE,CAAC;AAED,4HAA4H;AAC5H,MAAM,CAAC,IAAI,aAAa,GAAkB,IAAI,CAAA;AAE9C,SAAS,IAAI;IACX,IAAI,IAAI,GAAqE,EAAE,CAAA;IAE/E,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,qBAAqB,CAAC,CAAA;IAClE,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAgB,CAAA;QACxE,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAA;QACrE,CAAC;IACH,CAAC;IAED,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,IAAI,WAAW,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACpD,MAAM,CAAC,IAAI,CAAC,uFAAuF,CAAC,CAAA;IACtG,CAAC;IAED,iGAAiG;IACjG,qGAAqG;IACrG,kGAAkG;IAClG,IAAI,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAC3E,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB;QAAE,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;IACxF,aAAa,GAAG,cAAc,CAAC,OAAO,CAAC,CAAA;IAEvC,MAAM,GAAG,GAAkB;QACzB,KAAK,EAAE;YACL,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI;YAC7C,OAAO;YACP,mBAAmB,EAAE,QAAQ,CAAC,KAAK,CAAC,mBAAmB;YACvD,cAAc,EAAE,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;SACzE;QACD,KAAK,EAAE;YACL,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,IAAI;SAC7B;QACD,MAAM,EAAE,CAAC,GAAG,EAAE;YACZ,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI;gBAAE,OAAO,IAAI,CAAA;YACpC,MAAM,CAAC,GAAG,IAAI,CAAC,MAAyI,CAAA;YACxJ,IAAI,CAAC,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;gBAC/B,OAAO,EAAE,QAAQ,EAAE,WAAoB,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,CAAA;YACnE,CAAC;YACD,qFAAqF;YACrF,OAAO;gBACL,QAAQ,EAAE,CAAC,CAAC,QAAqB;gBACjC,UAAU,EAAE,CAAC,CAAC,UAAU,IAAI,EAAE;gBAC9B,SAAS,EAAE,CAAC,CAAC,SAAS,IAAI,EAAE;gBAC5B,GAAG,EAAE,CAAC,CAAC,GAAG,IAAI,IAAI;oBAChB,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE;oBAC5E,CAAC,CAAC,IAAI;aACT,CAAA;QACH,CAAC,CAAC,EAAE;QACJ,GAAG,EAAE,CAAC,GAAG,EAAE;YACT,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI;gBAAE,OAAO,IAAI,CAAA;YACjC,MAAM,CAAC,GAAG,IAAI,CAAC,GAGd,CAAA;YACD,IAAI,CAAC,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;gBAC7B,OAAO,EAAE,IAAI,EAAE,aAAsB,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,EAAE,EAAE,CAAA;YAC/F,CAAC;YACD,+FAA+F;YAC/F,OAAO;gBACL,IAAI,EAAE,CAAC,CAAC,IAAuB;gBAC/B,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE;gBACtB,WAAW,EAAE,CAAC,CAAC,WAAW,IAAI,EAAE;gBAChC,GAAG,CAAC,CAAC,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC/E,GAAG,CAAC,CAAC,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC3D,CAAA;QACH,CAAC,CAAC,EAAE;QACJ,IAAI,EAAE;YACJ,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI;YAC3C,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI;YAC3C,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM;YACjD,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI;YAC3C,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI;YAC3C,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI;SAC5C;KACF,CAAA;IAED,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY;QAAE,GAAG,CAAC,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;IAC/E,gGAAgG;IAChG,IAAI,OAAO,CAAC,GAAG,CAAC,6BAA6B;QAAE,GAAG,CAAC,KAAK,CAAC,mBAAmB,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAA;IAChI,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB;QAAE,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,IAAI,CAAA;IACxF,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS;QAAE,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAA;IAChE,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS;QAAE,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;IACxE,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW;QAAE,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,MAAM,CAAA;IACjF,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS;QAAE,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAA;IAChE,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS;QAAE,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAA;IAChE,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS;QAAE,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAA;IAEhE,qFAAqF;IACrF,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAC1F,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,YAAY,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAA;IAC9C,CAAC;IAED,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;IAC1C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YACxC,MAAM,CAAC,KAAK,CAAC,iBAAiB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;QAC1E,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAA;AACpB,CAAC;AAED,6DAA6D;AAC7D,kEAAkE;AAClE,MAAM,UAAU,2BAA2B,CAAC,OAAe;IACzD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAA;IACnD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAA;QAC5D,IAAI,QAAQ,CAAC,MAAM,IAAI,EAAE;YAAE,OAAO,QAAQ,CAAA;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,kBAAkB;IACpB,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;IAC3D,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC1C,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IACrD,IAAI,CAAC;QACH,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,KAAK,CAAC,CAAA;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,qDAAqD;IACvD,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,yCAAyC,UAAU,+BAA+B,CAAC,CAAA;IAC/F,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAS,aAAa;IACpB,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACzC,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;YACvC,MAAM,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAA;YACzE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;QACD,OAAO,OAAO,CAAC,GAAG,CAAC,UAAU,CAAA;IAC/B,CAAC;IACD,OAAO,2BAA2B,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;AAC1D,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,EAAE,CAAA;AAC5B,MAAM,CAAC,MAAM,SAAS,GAAG,aAAa,EAAE,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cors.d.ts","sourceRoot":"","sources":["../../src/lib/cors.ts"],"names":[],"mappings":"AAKA,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAC1B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAS/B"}
|
package/dist/lib/cors.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// #4 — CORS 출처 제한.
|
|
2
|
+
// 기존엔 모든 응답에 `Access-Control-Allow-Origin: *` + `Allow-Headers: Authorization`을 줘서,
|
|
3
|
+
// PAT(Authorization 헤더)를 cross-origin 스크립트에서 사용할 수 있었다. 허용 출처 allowlist에
|
|
4
|
+
// 든 origin만 에코하고, 그 외에는 CORS 헤더를 부여하지 않는다(브라우저가 cross-origin을 차단).
|
|
5
|
+
// same-origin 요청과 비-브라우저(CLI/서버-서버, Origin 헤더 없음)는 CORS와 무관하게 그대로 동작한다.
|
|
6
|
+
export function resolveCorsHeaders(origin, allowedOrigins) {
|
|
7
|
+
if (!origin)
|
|
8
|
+
return null;
|
|
9
|
+
if (!allowedOrigins.has(origin))
|
|
10
|
+
return null;
|
|
11
|
+
return {
|
|
12
|
+
'Access-Control-Allow-Origin': origin,
|
|
13
|
+
'Vary': 'Origin',
|
|
14
|
+
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
|
15
|
+
'Access-Control-Allow-Methods': 'GET, POST, PATCH, DELETE, OPTIONS',
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=cors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cors.js","sourceRoot":"","sources":["../../src/lib/cors.ts"],"names":[],"mappings":"AAAA,mBAAmB;AACnB,oFAAoF;AACpF,yEAAyE;AACzE,mEAAmE;AACnE,wEAAwE;AACxE,MAAM,UAAU,kBAAkB,CAChC,MAA0B,EAC1B,cAA2B;IAE3B,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAA;IACxB,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAA;IAC5C,OAAO;QACL,6BAA6B,EAAE,MAAM;QACrC,MAAM,EAAE,QAAQ;QAChB,8BAA8B,EAAE,6BAA6B;QAC7D,8BAA8B,EAAE,mCAAmC;KACpE,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csrf.d.ts","sourceRoot":"","sources":["../../src/lib/csrf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAkB5B,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,EAAE,IAAI,CAAC,mBAAmB,EACjC,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAC1B,OAAO,CAoBT"}
|
package/dist/lib/csrf.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// #5 — CSRF 경량 가드.
|
|
2
|
+
// 상태 변경 API가 `SameSite=Lax` 쿠키에만 의존하면 일부 cross-site 요청이 통과할 수 있다.
|
|
3
|
+
// 쿠키로 인증된 상태 변경 요청은 Origin이 same-origin(Host 일치)이거나 신뢰 allowlist에 있을 때만
|
|
4
|
+
// 허용하고, 그 외 cross-origin은 차단한다. 브라우저는 상태 변경 요청에 Origin을 강제로 붙이므로
|
|
5
|
+
// 대시보드(same-origin)는 그대로 통과하고, 공격자 origin은 막힌다.
|
|
6
|
+
// 면제: 안전 메서드(GET/HEAD/OPTIONS), PAT 인증(Authorization — 쿠키 자동 전송이 아님),
|
|
7
|
+
// 쿠키 없는 요청(미인증/login/init), Origin 없는 요청(비-브라우저; 브라우저는 cross-site에 Origin을 생략하지 못한다).
|
|
8
|
+
const SAFE_METHODS = new Set(['GET', 'HEAD', 'OPTIONS']);
|
|
9
|
+
// Loopback origins are the local dev machine (e.g. Vite :3001 proxying to the relay :4000), never a
|
|
10
|
+
// remote attacker — a cross-site page can't forge a localhost Origin, so exempting these is safe.
|
|
11
|
+
function isLoopbackHost(hostname) {
|
|
12
|
+
const h = hostname.replace(/^\[|\]$/g, '');
|
|
13
|
+
return h === 'localhost' || h === '127.0.0.1' || h === '::1';
|
|
14
|
+
}
|
|
15
|
+
export function isCsrfBlocked(method, headers, allowedOrigins) {
|
|
16
|
+
if (SAFE_METHODS.has((method ?? 'GET').toUpperCase()))
|
|
17
|
+
return false;
|
|
18
|
+
if (headers['authorization'])
|
|
19
|
+
return false;
|
|
20
|
+
const cookie = headers['cookie'];
|
|
21
|
+
const hasCookieAuth = typeof cookie === 'string' && cookie.includes('tapflow_token=');
|
|
22
|
+
if (!hasCookieAuth)
|
|
23
|
+
return false;
|
|
24
|
+
const origin = headers['origin'];
|
|
25
|
+
if (!origin)
|
|
26
|
+
return false;
|
|
27
|
+
if (allowedOrigins.has(origin))
|
|
28
|
+
return false;
|
|
29
|
+
const host = headers['host'];
|
|
30
|
+
try {
|
|
31
|
+
const url = new URL(origin);
|
|
32
|
+
if (host && url.host === host)
|
|
33
|
+
return false;
|
|
34
|
+
if (isLoopbackHost(url.hostname))
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// malformed Origin → treat as cross-origin (blocked below)
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=csrf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csrf.js","sourceRoot":"","sources":["../../src/lib/csrf.ts"],"names":[],"mappings":"AAEA,mBAAmB;AACnB,kEAAkE;AAClE,wEAAwE;AACxE,iEAAiE;AACjE,gDAAgD;AAChD,sEAAsE;AACtE,4FAA4F;AAC5F,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAA;AAExD,oGAAoG;AACpG,kGAAkG;AAClG,SAAS,cAAc,CAAC,QAAgB;IACtC,MAAM,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;IAC1C,OAAO,CAAC,KAAK,WAAW,IAAI,CAAC,KAAK,WAAW,IAAI,CAAC,KAAK,KAAK,CAAA;AAC9D,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,MAA0B,EAC1B,OAAiC,EACjC,cAA2B;IAE3B,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;QAAE,OAAO,KAAK,CAAA;IACnE,IAAI,OAAO,CAAC,eAAe,CAAC;QAAE,OAAO,KAAK,CAAA;IAC1C,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IAChC,MAAM,aAAa,GAAG,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAA;IACrF,IAAI,CAAC,aAAa;QAAE,OAAO,KAAK,CAAA;IAEhC,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IAChC,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAA;IACzB,IAAI,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAA;IAE5C,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAC5B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAA;QAC3B,IAAI,IAAI,IAAI,GAAG,CAAC,IAAI,KAAK,IAAI;YAAE,OAAO,KAAK,CAAA;QAC3C,IAAI,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,OAAO,KAAK,CAAA;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,2DAA2D;IAC7D,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadEnvFile.d.ts","sourceRoot":"","sources":["../../src/lib/loadEnvFile.ts"],"names":[],"mappings":"AAMA,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAU7D"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
// gitignore된 <dataDir>/.env 에서 자격 증명(JWT_SECRET·SMTP·DNS/ACME 토큰 등)을 로드한다.
|
|
4
|
+
// config.load()가 secret을 읽기 전에 호출되어 .env가 모든 비밀의 기본 경로가 된다(#287에서 시작).
|
|
5
|
+
// process.loadEnvFile 은 기존 process.env 값을 안 덮으므로 ambient(셸) 가 항상 우선.
|
|
6
|
+
export function loadDataDirEnv(dataDir) {
|
|
7
|
+
const envPath = path.join(dataDir, '.env');
|
|
8
|
+
if (!fs.existsSync(envPath))
|
|
9
|
+
return null;
|
|
10
|
+
try {
|
|
11
|
+
process.loadEnvFile(envPath);
|
|
12
|
+
return envPath;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
// 손상된 파일은 무시 — 자격 증명이 없으면 cert 발급 시점에 명확히 실패한다.
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=loadEnvFile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadEnvFile.js","sourceRoot":"","sources":["../../src/lib/loadEnvFile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,2EAA2E;AAC3E,uEAAuE;AACvE,qEAAqE;AACrE,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IAC1C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAA;IACxC,IAAI,CAAC;QACH,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;QAC5B,OAAO,OAAO,CAAA;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,gDAAgD;QAChD,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { TapflowConfig } from './config.js';
|
|
2
|
+
type ProxyCfg = Pick<TapflowConfig, 'tunnel' | 'relay' | 'local'>;
|
|
3
|
+
export declare function buildCorsOrigins(cfg: ProxyCfg, port: number): string[];
|
|
4
|
+
export declare function proxyWithoutPublicUrlWarning(cfg: ProxyCfg): string | null;
|
|
5
|
+
export {};
|
|
6
|
+
//# sourceMappingURL=proxyConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxyConfig.d.ts","sourceRoot":"","sources":["../../src/lib/proxyConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAGhD,KAAK,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC,CAAA;AAGjE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAStE;AAGD,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAQzE"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { buildInviteBaseUrl } from './publicUrl.js';
|
|
2
|
+
// Allow cross-origin PAT use only from the configured public origin + loopback (LAN is same-origin).
|
|
3
|
+
export function buildCorsOrigins(cfg, port) {
|
|
4
|
+
// Skip buildInviteBaseUrl's localhost fallback — it would allowlist a stale loopback at config.local.port under a different --port.
|
|
5
|
+
const configuredOrigin = (() => {
|
|
6
|
+
if (!cfg.tunnel?.publicUrl && !cfg.relay.url)
|
|
7
|
+
return null;
|
|
8
|
+
try {
|
|
9
|
+
return new URL(buildInviteBaseUrl(cfg)).origin;
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
})();
|
|
15
|
+
const origins = [configuredOrigin, `http://localhost:${port}`, `http://127.0.0.1:${port}`]
|
|
16
|
+
.filter((o) => o !== null);
|
|
17
|
+
return [...new Set(origins)];
|
|
18
|
+
}
|
|
19
|
+
// A proxied/tunneled relay needs a public URL, or the CSRF/CORS allowlist stays loopback-only and blocks proxied POSTs.
|
|
20
|
+
export function proxyWithoutPublicUrlWarning(cfg) {
|
|
21
|
+
if (cfg.local.trustedProxies.length > 0 && !cfg.tunnel?.publicUrl && !cfg.relay.url) {
|
|
22
|
+
return ('TAPFLOW_TRUSTED_PROXIES is set but no public URL (tunnel.publicUrl / relay.url) is configured. ' +
|
|
23
|
+
'Cross-origin dashboard requests may be blocked by the CSRF guard — set the public URL for proxied deployments.');
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=proxyConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxyConfig.js","sourceRoot":"","sources":["../../src/lib/proxyConfig.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAInD,qGAAqG;AACrG,MAAM,UAAU,gBAAgB,CAAC,GAAa,EAAE,IAAY;IAC1D,oIAAoI;IACpI,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE;QAC7B,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG;YAAE,OAAO,IAAI,CAAA;QACzD,IAAI,CAAC;YAAC,OAAO,IAAI,GAAG,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAA;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,IAAI,CAAA;QAAC,CAAC;IAC9E,CAAC,CAAC,EAAE,CAAA;IACJ,MAAM,OAAO,GAAG,CAAC,gBAAgB,EAAE,oBAAoB,IAAI,EAAE,EAAE,oBAAoB,IAAI,EAAE,CAAC;SACvF,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAA;IACzC,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAA;AAC9B,CAAC;AAED,wHAAwH;AACxH,MAAM,UAAU,4BAA4B,CAAC,GAAa;IACxD,IAAI,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QACpF,OAAO,CACL,iGAAiG;YACjG,gHAAgH,CACjH,CAAA;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publicUrl.d.ts","sourceRoot":"","sources":["../../src/lib/publicUrl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAMhD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,IAAI,CAAC,aAAa,EAAE,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC,GAAG,MAAM,CAOjG"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// #6 — 초대/공개 링크의 신뢰 base URL.
|
|
2
|
+
// `req.headers.host`/`x-forwarded-proto`는 클라이언트가 조작할 수 있어(Host 인젝션) 피싱 링크가
|
|
3
|
+
// 정상 메일로 발송될 수 있다. 따라서 Host 헤더 대신 설정값에서만 base를 도출한다.
|
|
4
|
+
// 우선순위: 터널 공개 URL → 설정된 relay URL(ws→http 변환) → localhost 폴백.
|
|
5
|
+
export function buildInviteBaseUrl(cfg) {
|
|
6
|
+
if (cfg.tunnel?.publicUrl)
|
|
7
|
+
return stripTrailingSlash(cfg.tunnel.publicUrl);
|
|
8
|
+
if (cfg.relay.url) {
|
|
9
|
+
const http = cfg.relay.url.replace(/^ws:\/\//i, 'http://').replace(/^wss:\/\//i, 'https://');
|
|
10
|
+
return stripTrailingSlash(http);
|
|
11
|
+
}
|
|
12
|
+
return `http://localhost:${cfg.local.port}`;
|
|
13
|
+
}
|
|
14
|
+
function stripTrailingSlash(u) {
|
|
15
|
+
return u.replace(/\/+$/, '');
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=publicUrl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publicUrl.js","sourceRoot":"","sources":["../../src/lib/publicUrl.ts"],"names":[],"mappings":"AAEA,8BAA8B;AAC9B,2EAA2E;AAC3E,qDAAqD;AACrD,8DAA8D;AAC9D,MAAM,UAAU,kBAAkB,CAAC,GAAsD;IACvF,IAAI,GAAG,CAAC,MAAM,EAAE,SAAS;QAAE,OAAO,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IAC1E,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QAClB,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,UAAU,CAAC,CAAA;QAC5F,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAA;IACjC,CAAC;IACD,OAAO,oBAAoB,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAA;AAC7C,CAAC;AAED,SAAS,kBAAkB,CAAC,CAAS;IACnC,OAAO,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;AAC9B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uploads.d.ts","sourceRoot":"","sources":["../../src/lib/uploads.ts"],"names":[],"mappings":"AAIA,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAQhE"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
// 업로드 정리: 파일을 삭제하되 이미 없으면(ENOENT) 조용히 넘기고, 그 외 에러만 경고한다.
|
|
3
|
+
// builds/comments 업로드 핸들러가 거부·만료된 파일을 정리할 때 공유한다.
|
|
4
|
+
export function unlinkSafe(filePath, label) {
|
|
5
|
+
try {
|
|
6
|
+
fs.unlinkSync(filePath);
|
|
7
|
+
}
|
|
8
|
+
catch (err) {
|
|
9
|
+
if (err.code !== 'ENOENT') {
|
|
10
|
+
console.warn(`[tapflow] failed to delete ${label}`, err.message);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=uploads.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uploads.js","sourceRoot":"","sources":["../../src/lib/uploads.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAA;AAEnB,yDAAyD;AACzD,kDAAkD;AAClD,MAAM,UAAU,UAAU,CAAC,QAAgB,EAAE,KAAa;IACxD,IAAI,CAAC;QACH,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAA;IACzB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACrD,OAAO,CAAC,IAAI,CAAC,8BAA8B,KAAK,EAAE,EAAG,GAAa,CAAC,OAAO,CAAC,CAAA;QAC7E,CAAC;IACH,CAAC;AACH,CAAC"}
|
package/dist/router.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAa5B,KAAK,OAAO,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,EAAE,IAAI,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;AAS5H,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAc;IAE5B,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;IAQxD,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAClC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IACnC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IACpC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAE/B,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,EAAE,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;CAsBpF;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAIlF;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAOnE;AAED,wBAAsB,QAAQ,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,CAAC,CAAC,CAGjF"}
|
package/dist/router.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
import { createLogger } from '@tapflowio/agent-core';
|
|
2
|
+
const logger = createLogger('relay:router');
|
|
3
|
+
// 로그에 토큰이 새지 않도록 마스킹: PAT(tflw_pat_…)와 세션 JWT(eyJ….….…).
|
|
4
|
+
// 메시지·스택뿐 아니라 method/url(경로 파라미터에 토큰이 섞인 경우)까지 포함해 로그 라인 전체에 적용한다.
|
|
5
|
+
function redactSecrets(s) {
|
|
6
|
+
return s
|
|
7
|
+
.replace(/tflw_pat_[A-Za-z0-9_-]+/g, 'tflw_pat_***')
|
|
8
|
+
.replace(/eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g, '[jwt]');
|
|
9
|
+
}
|
|
1
10
|
export class Router {
|
|
2
11
|
routes = [];
|
|
3
12
|
on(method, path, handler) {
|
|
@@ -25,7 +34,10 @@ export class Router {
|
|
|
25
34
|
try {
|
|
26
35
|
await route.handler(req, res, params);
|
|
27
36
|
}
|
|
28
|
-
catch (
|
|
37
|
+
catch (err) {
|
|
38
|
+
// 관측성: 스택을 삼키지 말고 기록한다. 단 응답 본문에는 상세를 노출하지 않는다.
|
|
39
|
+
const detail = err instanceof Error ? (err.stack ?? err.message) : String(err);
|
|
40
|
+
logger.error(redactSecrets(`${method} ${url} — handler error: ${detail}`));
|
|
29
41
|
json(res, 500, { error: 'Internal server error' });
|
|
30
42
|
}
|
|
31
43
|
return true;
|
package/dist/router.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
|
package/dist/server.js
CHANGED
|
@@ -1,17 +1,54 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import { initDb } from './db.js';
|
|
3
3
|
import { RelayServer } from './RelayServer.js';
|
|
4
|
-
import { config } from './lib/config.js';
|
|
4
|
+
import { config, loadedEnvPath } from './lib/config.js';
|
|
5
|
+
import { buildCorsOrigins, proxyWithoutPublicUrlWarning } from './lib/proxyConfig.js';
|
|
6
|
+
import { createCertProvider, startCertRenewal, startAddressPublisher } from './lib/cert/index.js';
|
|
5
7
|
import { createLogger } from '@tapflowio/agent-core';
|
|
6
8
|
const logger = createLogger('relay');
|
|
7
9
|
const { port, dataDir } = config.local;
|
|
10
|
+
// config loaded <dataDir>/.env before reading any secret (JWT/SMTP/DNS tokens); just report it here.
|
|
11
|
+
if (loadedEnvPath)
|
|
12
|
+
logger.info(`Loaded credentials from ${loadedEnvPath}`);
|
|
8
13
|
const dbPath = path.join(dataDir, 'tapflow.db');
|
|
9
14
|
const uploadsDir = path.join(dataDir, 'uploads');
|
|
10
15
|
initDb(dbPath);
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
16
|
+
const corsOrigins = buildCorsOrigins(config, port);
|
|
17
|
+
const proxyWarning = proxyWithoutPublicUrlWarning(config);
|
|
18
|
+
if (proxyWarning)
|
|
19
|
+
logger.warn(proxyWarning);
|
|
20
|
+
async function main() {
|
|
21
|
+
let tls;
|
|
22
|
+
let provider = null;
|
|
23
|
+
if (config.tls) {
|
|
24
|
+
provider = createCertProvider(config.tls, { dataDir });
|
|
25
|
+
const material = await provider.ensureCert();
|
|
26
|
+
tls = { cert: material.cert, key: material.key };
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
logger.info('TLS disabled — serving HTTP. Secure-context features (e.g. WebCodecs hardware decode) require HTTPS; ' +
|
|
30
|
+
'configure tls in tapflow.config.json to enable.');
|
|
31
|
+
}
|
|
32
|
+
const server = new RelayServer({ port, uploadsDir, wsBackpressureBytes: config.local.wsBackpressureBytes, trustedProxies: config.local.trustedProxies, corsOrigins, tls });
|
|
33
|
+
await server.start();
|
|
34
|
+
logger.info(`tapflow relay running on port ${port} (${tls ? 'https' : 'http'})`);
|
|
35
|
+
const stopRenewal = provider
|
|
36
|
+
? startCertRenewal(provider, { onRenew: (m) => server.updateTlsContext({ cert: m.cert, key: m.key }) })
|
|
37
|
+
: null;
|
|
38
|
+
// byo-api-token: publish the relay's LAN IP to the domain's A record so teammates just open the URL.
|
|
39
|
+
const stopPublish = config.tls?.mode === 'byo-api-token' && config.tls.publishAddress !== false
|
|
40
|
+
? startAddressPublisher(config.tls)
|
|
41
|
+
: null;
|
|
42
|
+
const shutdown = () => {
|
|
43
|
+
stopRenewal?.();
|
|
44
|
+
stopPublish?.();
|
|
45
|
+
void server.stop().then(() => process.exit(0));
|
|
46
|
+
};
|
|
47
|
+
process.on('SIGTERM', shutdown);
|
|
48
|
+
process.on('SIGINT', shutdown);
|
|
49
|
+
}
|
|
50
|
+
void main().catch((err) => {
|
|
51
|
+
logger.error(`relay failed to start: ${String(err)}`);
|
|
52
|
+
process.exit(1);
|
|
14
53
|
});
|
|
15
|
-
process.on('SIGTERM', () => server.stop().then(() => process.exit(0)));
|
|
16
|
-
process.on('SIGINT', () => server.stop().then(() => process.exit(0)));
|
|
17
54
|
//# sourceMappingURL=server.js.map
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tapflowio/relay",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"description": "WebSocket relay server for tapflow — NAT traversal, session routing, JWT auth, bundled dashboard",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tapflow",
|
|
@@ -39,29 +39,30 @@
|
|
|
39
39
|
"LICENSE"
|
|
40
40
|
],
|
|
41
41
|
"engines": {
|
|
42
|
-
"node": ">=20"
|
|
42
|
+
"node": ">=20.12.0"
|
|
43
43
|
},
|
|
44
44
|
"publishConfig": {
|
|
45
45
|
"access": "public"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"
|
|
48
|
+
"acme-client": "^5.4.0",
|
|
49
|
+
"better-sqlite3": "^12.11.1",
|
|
49
50
|
"busboy": "^1.6.0",
|
|
50
51
|
"jsonwebtoken": "^9.0.3",
|
|
51
|
-
"nodemailer": "^8.0.
|
|
52
|
-
"ws": "^8.
|
|
52
|
+
"nodemailer": "^8.0.11",
|
|
53
|
+
"ws": "^8.21.0",
|
|
53
54
|
"zod": "^4.4.3",
|
|
54
|
-
"@tapflowio/agent-core": "0.
|
|
55
|
+
"@tapflowio/agent-core": "0.9.1"
|
|
55
56
|
},
|
|
56
57
|
"devDependencies": {
|
|
57
58
|
"@types/better-sqlite3": "^7.6.13",
|
|
58
59
|
"@types/busboy": "^1.5.4",
|
|
59
60
|
"@types/jsonwebtoken": "^9.0.10",
|
|
60
|
-
"@types/node": "^20.
|
|
61
|
+
"@types/node": "^20.19.43",
|
|
61
62
|
"@types/nodemailer": "^8.0.0",
|
|
62
63
|
"@types/ws": "^8.0.0",
|
|
63
64
|
"typescript": "^5.0.0",
|
|
64
|
-
"vitest": "^4.1.
|
|
65
|
+
"vitest": "^4.1.9"
|
|
65
66
|
},
|
|
66
67
|
"scripts": {
|
|
67
68
|
"build": "tsc && rm -rf dist/migrations && cp -r src/migrations dist/migrations",
|