add redis, cassandra support, change helpers to lib
Some checks failed
Code quality checks / biome (push) Failing after 9s
Some checks failed
Code quality checks / biome (push) Failing after 9s
This commit is contained in:
parent
a3555c73d2
commit
ab81475ad6
8 changed files with 145 additions and 6 deletions
19
.env.example
Normal file
19
.env.example
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# NODE_ENV=development
|
||||||
|
HOST=0.0.0.0
|
||||||
|
PORT=8080
|
||||||
|
|
||||||
|
# Redis (Required)
|
||||||
|
REDIS_URL=redis://localhost:6379
|
||||||
|
REDIS_TTL=3600
|
||||||
|
|
||||||
|
# Cassandra (Required)
|
||||||
|
CASSANDRA_HOST=localhost
|
||||||
|
CASSANDRA_PORT=9042
|
||||||
|
CASSANDRA_DATACENTER=datacenter1
|
||||||
|
CASSANDRA_CONTACT_POINTS=localhost
|
||||||
|
|
||||||
|
# Optional
|
||||||
|
CASSANDRA_KEYSPACE=
|
||||||
|
CASSANDRA_USERNAME=
|
||||||
|
CASSANDRA_AUTH_ENABLED=false
|
||||||
|
CASSANDRA_PASSWORD=
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
||||||
/node_modules
|
/node_modules
|
||||||
bun.lock
|
bun.lock
|
||||||
|
.env
|
||||||
|
|
|
@ -1,6 +1,51 @@
|
||||||
|
import { logger } from "@creations.works/logger";
|
||||||
|
|
||||||
export const environment: Environment = {
|
export const environment: Environment = {
|
||||||
port: Number.parseInt(process.env.PORT || "8080", 10),
|
port: Number.parseInt(process.env.PORT || "", 10),
|
||||||
host: process.env.HOST || "0.0.0.0",
|
host: process.env.HOST || "0.0.0.0",
|
||||||
development:
|
development:
|
||||||
process.env.NODE_ENV === "development" || process.argv.includes("--dev"),
|
process.env.NODE_ENV === "development" || process.argv.includes("--dev"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const redisTtl: number = process.env.REDIS_TTL
|
||||||
|
? Number.parseInt(process.env.REDIS_TTL, 10)
|
||||||
|
: 60 * 60 * 1; // 1 hour
|
||||||
|
|
||||||
|
export const cassandra: CassandraConfig = {
|
||||||
|
host: process.env.CASSANDRA_HOST || "localhost",
|
||||||
|
port: Number.parseInt(process.env.CASSANDRA_PORT || "9042", 10),
|
||||||
|
keyspace: process.env.CASSANDRA_KEYSPACE || "",
|
||||||
|
username: process.env.CASSANDRA_USERNAME || "",
|
||||||
|
password: process.env.CASSANDRA_PASSWORD || "",
|
||||||
|
datacenter: process.env.CASSANDRA_DATACENTER || "",
|
||||||
|
contactPoints: (process.env.CASSANDRA_CONTACT_POINTS || "localhost").split(","),
|
||||||
|
authEnabled: process.env.CASSANDRA_AUTH_ENABLED === "false",
|
||||||
|
};
|
||||||
|
|
||||||
|
export function verifyRequiredVariables(): void {
|
||||||
|
const requiredVariables = [
|
||||||
|
"HOST",
|
||||||
|
"PORT",
|
||||||
|
"REDIS_URL",
|
||||||
|
"REDIS_TTL",
|
||||||
|
"CASSANDRA_HOST",
|
||||||
|
"CASSANDRA_PORT",
|
||||||
|
"CASSANDRA_CONTACT_POINTS",
|
||||||
|
"CASSANDRA_AUTH_ENABLED",
|
||||||
|
"CASSANDRA_DATACENTER",
|
||||||
|
];
|
||||||
|
|
||||||
|
let hasError = false;
|
||||||
|
|
||||||
|
for (const key of requiredVariables) {
|
||||||
|
const value = process.env[key];
|
||||||
|
if (value === undefined || value.trim() === "") {
|
||||||
|
logger.error(`Missing or empty environment variable: ${key}`);
|
||||||
|
hasError = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasError) {
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
"typescript": "^5.8.3"
|
"typescript": "^5.8.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@creations.works/logger": "^1.0.3"
|
"@creations.works/logger": "^1.0.3",
|
||||||
|
"cassandra-driver": "^4.8.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
21
src/index.ts
21
src/index.ts
|
@ -1,12 +1,27 @@
|
||||||
import { logger } from "@creations.works/logger";
|
import { CassandraService } from "@/lib/cassandra";
|
||||||
|
|
||||||
import { serverHandler } from "@/server";
|
import { serverHandler } from "@/server";
|
||||||
|
import { verifyRequiredVariables } from "@config/environment";
|
||||||
|
import { logger } from "@creations.works/logger";
|
||||||
|
import { redis } from "bun";
|
||||||
|
|
||||||
async function main(): Promise<void> {
|
async function main(): Promise<void> {
|
||||||
|
verifyRequiredVariables();
|
||||||
|
|
||||||
|
// Redis
|
||||||
|
try {
|
||||||
|
await redis.connect();
|
||||||
|
logger.info("Redis connection successful.");
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(["Redis connection failed:", error as Error]);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
await CassandraService.connect();
|
||||||
|
|
||||||
serverHandler.initialize();
|
serverHandler.initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
main().catch((error: Error) => {
|
main().catch((error: Error) => {
|
||||||
logger.error(["Error initializing the server:", error]);
|
logger.error(error);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
|
|
47
src/lib/cassandra.ts
Normal file
47
src/lib/cassandra.ts
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import { cassandra as config } from "@config/environment";
|
||||||
|
import { logger } from "@creations.works/logger";
|
||||||
|
import { Client, auth } from "cassandra-driver";
|
||||||
|
|
||||||
|
class CassandraService {
|
||||||
|
private static instance: Client | null = null;
|
||||||
|
|
||||||
|
private constructor() {}
|
||||||
|
|
||||||
|
public static getClient(): Client {
|
||||||
|
if (!CassandraService.instance) {
|
||||||
|
CassandraService.instance = new Client({
|
||||||
|
contactPoints: config.contactPoints,
|
||||||
|
localDataCenter: config.datacenter,
|
||||||
|
keyspace: config.keyspace,
|
||||||
|
authProvider: config.authEnabled
|
||||||
|
? new auth.PlainTextAuthProvider(config.username, config.password)
|
||||||
|
: undefined,
|
||||||
|
protocolOptions: {
|
||||||
|
port: config.port,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return CassandraService.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async connect(): Promise<void> {
|
||||||
|
try {
|
||||||
|
await CassandraService.getClient().connect();
|
||||||
|
logger.info("Connected to Cassandra successfully.");
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(["Failed to connect to Cassandra:", error as Error]);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async shutdown(): Promise<void> {
|
||||||
|
if (CassandraService.instance) {
|
||||||
|
await CassandraService.instance.shutdown();
|
||||||
|
logger.info("Cassandra client shut down.");
|
||||||
|
CassandraService.instance = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { CassandraService };
|
|
@ -5,7 +5,7 @@
|
||||||
"@/*": ["src/*"],
|
"@/*": ["src/*"],
|
||||||
"@config/*": ["config/*"],
|
"@config/*": ["config/*"],
|
||||||
"@types/*": ["types/*"],
|
"@types/*": ["types/*"],
|
||||||
"@helpers/*": ["src/helpers/*"]
|
"@lib/*": ["src/lib/*"]
|
||||||
},
|
},
|
||||||
"typeRoots": ["./src/types", "./node_modules/@types"],
|
"typeRoots": ["./src/types", "./node_modules/@types"],
|
||||||
// Enable latest features
|
// Enable latest features
|
||||||
|
|
11
types/config.d.ts
vendored
11
types/config.d.ts
vendored
|
@ -3,3 +3,14 @@ type Environment = {
|
||||||
host: string;
|
host: string;
|
||||||
development: boolean;
|
development: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type CassandraConfig = {
|
||||||
|
host: string;
|
||||||
|
port: number;
|
||||||
|
keyspace: string;
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
datacenter: string;
|
||||||
|
contactPoints: string[];
|
||||||
|
authEnabled: boolean;
|
||||||
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue