@drmxrcy/tcg-config 0.0.0-202602060542
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/package.json +30 -0
- package/src/auth.ts +95 -0
- package/src/index.ts +16 -0
- package/src/schema.ts +137 -0
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@drmxrcy/tcg-config",
|
|
3
|
+
"version": "0.0.0-202602060542",
|
|
4
|
+
"private": false,
|
|
5
|
+
"main": "./src/index.ts",
|
|
6
|
+
"types": "./src/index.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"src/"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"typecheck": "tsc --noEmit",
|
|
12
|
+
"format": "bun x @biomejs/biome check --fix --max-diagnostics=none --diagnostic-level=error --linter-enabled=false ./src",
|
|
13
|
+
"lint": "bun x @biomejs/biome lint --write ./src",
|
|
14
|
+
"check-types": "tsc --noEmit"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@t3-oss/env-core": "^0.11.1",
|
|
18
|
+
"zod": "^3.24.0"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@biomejs/biome": "2.3.11",
|
|
22
|
+
"@drmxrcy/tcg-typescript-config": "workspace:*",
|
|
23
|
+
"@types/node": "^22.15.30",
|
|
24
|
+
"typescript": "^5.8.3"
|
|
25
|
+
},
|
|
26
|
+
"exports": {
|
|
27
|
+
".": "./src/index.ts",
|
|
28
|
+
"./auth": "./src/auth.ts"
|
|
29
|
+
}
|
|
30
|
+
}
|
package/src/auth.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { createEnv } from "@t3-oss/env-core";
|
|
2
|
+
import type { z } from "zod";
|
|
3
|
+
import { authServerSchema } from "./schema";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Auth Service environment validation using @t3-oss/env-core.
|
|
7
|
+
*
|
|
8
|
+
* This validates all auth service environment variables at startup and provides
|
|
9
|
+
* type-safe access throughout the application.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Type of the validated environment object.
|
|
14
|
+
* Extracts the inferred type from the Zod schema.
|
|
15
|
+
*/
|
|
16
|
+
export type AuthEnv = z.infer<z.ZodObject<typeof authServerSchema>>;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Validated environment object for Auth Service.
|
|
20
|
+
*
|
|
21
|
+
* Access environment variables like:
|
|
22
|
+
* - `authEnv.AUTH_DATABASE_URL`
|
|
23
|
+
* - `authEnv.AUTH_PORT`
|
|
24
|
+
* - `authEnv.AUTH_SECRET`
|
|
25
|
+
*
|
|
26
|
+
* All values are properly typed and validated.
|
|
27
|
+
*/
|
|
28
|
+
export const authEnv = createEnv({
|
|
29
|
+
isServer: true,
|
|
30
|
+
server: authServerSchema,
|
|
31
|
+
runtimeEnv: process.env,
|
|
32
|
+
emptyStringAsUndefined: true,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Parse environment variables from a custom runtime environment.
|
|
37
|
+
*
|
|
38
|
+
* Use this for embedded mode where environment variables
|
|
39
|
+
* come from a source other than process.env.
|
|
40
|
+
*
|
|
41
|
+
* @param runtimeEnv - Object containing environment variables
|
|
42
|
+
* @returns Validated environment object
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* const parsed = parseAuthEnv({
|
|
47
|
+
* AUTH_DATABASE_URL: 'postgres://...',
|
|
48
|
+
* AUTH_SECRET: '...'
|
|
49
|
+
* });
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export function parseAuthEnv(
|
|
53
|
+
runtimeEnv: Record<string, string | undefined>,
|
|
54
|
+
): AuthEnv {
|
|
55
|
+
return createEnv({
|
|
56
|
+
isServer: true,
|
|
57
|
+
server: authServerSchema,
|
|
58
|
+
runtimeEnv,
|
|
59
|
+
emptyStringAsUndefined: true,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Assert that the environment is valid.
|
|
65
|
+
*
|
|
66
|
+
* Throws an error if required environment variables are missing.
|
|
67
|
+
* Call this at application startup to fail fast.
|
|
68
|
+
*
|
|
69
|
+
* @returns The validated environment object
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* if (process.env.NODE_ENV !== 'test') {
|
|
74
|
+
* assertAuthEnv();
|
|
75
|
+
* }
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
export function assertAuthEnv(): AuthEnv {
|
|
79
|
+
// Accessing authEnv will trigger validation
|
|
80
|
+
// If validation fails, createEnv throws an error
|
|
81
|
+
return authEnv;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Get an environment variable value with type safety.
|
|
86
|
+
*
|
|
87
|
+
* This is a convenience function for accessing individual variables.
|
|
88
|
+
* Prefer direct access via `authEnv.VARIABLE_NAME` for better IDE support.
|
|
89
|
+
*
|
|
90
|
+
* @param key - Environment variable name
|
|
91
|
+
* @returns The environment variable value
|
|
92
|
+
*/
|
|
93
|
+
export function getAuthEnv<K extends keyof AuthEnv>(key: K): AuthEnv[K] {
|
|
94
|
+
return authEnv[key];
|
|
95
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @drmxrcy/tcg-config - Environment configuration package
|
|
3
|
+
*
|
|
4
|
+
* Provides type-safe environment variable validation using Zod and @t3-oss/env-core.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Auth service environment exports
|
|
8
|
+
export {
|
|
9
|
+
type AuthEnv,
|
|
10
|
+
assertAuthEnv,
|
|
11
|
+
authEnv,
|
|
12
|
+
getAuthEnv,
|
|
13
|
+
parseAuthEnv,
|
|
14
|
+
} from "./auth";
|
|
15
|
+
// Schema exports
|
|
16
|
+
export * from "./schema";
|
package/src/schema.ts
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Zod schemas for Auth Service environment variables.
|
|
5
|
+
* All auth-specific variables use AUTH_ prefix for clarity in multi-service deployments.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// Database
|
|
10
|
+
// ============================================================================
|
|
11
|
+
|
|
12
|
+
export const authDatabaseUrlSchema = z
|
|
13
|
+
.string()
|
|
14
|
+
.url({
|
|
15
|
+
message: "AUTH_DATABASE_URL must be a valid PostgreSQL connection string",
|
|
16
|
+
})
|
|
17
|
+
.describe("PostgreSQL connection string for auth database");
|
|
18
|
+
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// Authentication (Better Auth)
|
|
21
|
+
// ============================================================================
|
|
22
|
+
|
|
23
|
+
export const authSecretSchema = z
|
|
24
|
+
.string()
|
|
25
|
+
.min(32, { message: "AUTH_SECRET must be at least 32 characters" })
|
|
26
|
+
.describe("Better Auth secret for session encryption");
|
|
27
|
+
|
|
28
|
+
export const authDiscordClientIdSchema = z
|
|
29
|
+
.string()
|
|
30
|
+
.min(1)
|
|
31
|
+
.optional()
|
|
32
|
+
.describe("Discord OAuth client ID");
|
|
33
|
+
|
|
34
|
+
export const authDiscordClientSecretSchema = z
|
|
35
|
+
.string()
|
|
36
|
+
.min(1)
|
|
37
|
+
.optional()
|
|
38
|
+
.describe("Discord OAuth client secret");
|
|
39
|
+
|
|
40
|
+
// ============================================================================
|
|
41
|
+
// Server Configuration
|
|
42
|
+
// ============================================================================
|
|
43
|
+
|
|
44
|
+
export const authPortSchema = z
|
|
45
|
+
.string()
|
|
46
|
+
.optional()
|
|
47
|
+
.default("3001")
|
|
48
|
+
.transform((val) => Number.parseInt(val, 10))
|
|
49
|
+
.pipe(
|
|
50
|
+
z
|
|
51
|
+
.number()
|
|
52
|
+
.int()
|
|
53
|
+
.min(1, { message: "AUTH_PORT must be at least 1" })
|
|
54
|
+
.max(65535, { message: "AUTH_PORT must be at most 65535" }),
|
|
55
|
+
)
|
|
56
|
+
.describe("Auth service port");
|
|
57
|
+
|
|
58
|
+
export const authCorsOriginSchema = z
|
|
59
|
+
.string()
|
|
60
|
+
.optional()
|
|
61
|
+
.default("*")
|
|
62
|
+
.describe("CORS origin for auth service");
|
|
63
|
+
|
|
64
|
+
export const authBaseUrlSchema = z
|
|
65
|
+
.string()
|
|
66
|
+
.url({ message: "AUTH_BASE_URL must be a valid URL" })
|
|
67
|
+
.optional()
|
|
68
|
+
.default("http://localhost:3001")
|
|
69
|
+
.describe("Base URL for auth service (used for JWT issuer/audience)");
|
|
70
|
+
|
|
71
|
+
export const nodeEnvSchema = z
|
|
72
|
+
.enum(["development", "production", "test"])
|
|
73
|
+
.optional()
|
|
74
|
+
.default("development")
|
|
75
|
+
.describe("Node environment");
|
|
76
|
+
|
|
77
|
+
// ============================================================================
|
|
78
|
+
// Rate Limiting
|
|
79
|
+
// ============================================================================
|
|
80
|
+
|
|
81
|
+
const createRateLimitSchema = (defaultValue: string) =>
|
|
82
|
+
z
|
|
83
|
+
.string()
|
|
84
|
+
.optional()
|
|
85
|
+
.default(defaultValue)
|
|
86
|
+
.transform((val) => Number.parseInt(val, 10))
|
|
87
|
+
.pipe(
|
|
88
|
+
z
|
|
89
|
+
.number()
|
|
90
|
+
.int()
|
|
91
|
+
.min(1, { message: "Rate limit value must be at least 1" }),
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
export const authRateLimitEnabledSchema = z
|
|
95
|
+
.enum(["true", "false"])
|
|
96
|
+
.optional()
|
|
97
|
+
.default("true")
|
|
98
|
+
.transform((val) => val !== "false")
|
|
99
|
+
.describe("Enable rate limiting");
|
|
100
|
+
|
|
101
|
+
export const authRateLimitGlobalMaxSchema = createRateLimitSchema(
|
|
102
|
+
"200",
|
|
103
|
+
).describe("Global requests per window");
|
|
104
|
+
|
|
105
|
+
export const authRateLimitGlobalMaxAuthSchema = createRateLimitSchema(
|
|
106
|
+
"300",
|
|
107
|
+
).describe("Global requests per window for authenticated users");
|
|
108
|
+
|
|
109
|
+
export const authRateLimitAuthMaxSchema = createRateLimitSchema("10").describe(
|
|
110
|
+
"Auth endpoint requests per window",
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
// ============================================================================
|
|
114
|
+
// Combined Schema for Auth Service
|
|
115
|
+
// ============================================================================
|
|
116
|
+
|
|
117
|
+
export const authServerSchema = {
|
|
118
|
+
// Database
|
|
119
|
+
AUTH_DATABASE_URL: authDatabaseUrlSchema,
|
|
120
|
+
|
|
121
|
+
// Authentication
|
|
122
|
+
AUTH_SECRET: authSecretSchema,
|
|
123
|
+
AUTH_DISCORD_CLIENT_ID: authDiscordClientIdSchema,
|
|
124
|
+
AUTH_DISCORD_CLIENT_SECRET: authDiscordClientSecretSchema,
|
|
125
|
+
|
|
126
|
+
// Server
|
|
127
|
+
AUTH_PORT: authPortSchema,
|
|
128
|
+
AUTH_CORS_ORIGIN: authCorsOriginSchema,
|
|
129
|
+
AUTH_BASE_URL: authBaseUrlSchema,
|
|
130
|
+
NODE_ENV: nodeEnvSchema,
|
|
131
|
+
|
|
132
|
+
// Rate Limiting
|
|
133
|
+
AUTH_RATE_LIMIT_ENABLED: authRateLimitEnabledSchema,
|
|
134
|
+
AUTH_RATE_LIMIT_GLOBAL_MAX: authRateLimitGlobalMaxSchema,
|
|
135
|
+
AUTH_RATE_LIMIT_GLOBAL_MAX_AUTH: authRateLimitGlobalMaxAuthSchema,
|
|
136
|
+
AUTH_RATE_LIMIT_AUTH_MAX: authRateLimitAuthMaxSchema,
|
|
137
|
+
};
|