@cardql/node
Version:
CardQL SDK for Node.js and serverless applications
301 lines (294 loc) • 7.56 kB
JavaScript
// src/index.ts
export * from "@cardql/core";
// src/client.ts
import { CardQL as CoreCardQL, CardQLClient, CardQLApi } from "@cardql/core";
// src/config.ts
function createConfigFromEnv(overrides = {}) {
const config = {
apiKey: overrides.apiKey || process.env.CARDQL_API_KEY || "",
endpoint: overrides.endpoint || process.env.CARDQL_ENDPOINT || "https://api.cardql.com/graphql",
timeout: overrides.timeout || parseInt(process.env.CARDQL_TIMEOUT || "30000"),
retries: overrides.retries || parseInt(process.env.CARDQL_RETRIES || "3")
};
if (!config.apiKey) {
throw new Error(
"CardQL API key is required. Set CARDQL_API_KEY environment variable or provide apiKey in config."
);
}
if (!config.endpoint) {
throw new Error(
"CardQL endpoint is required. Set CARDQL_ENDPOINT environment variable or provide endpoint in config."
);
}
return config;
}
function validateConfig(config) {
if (!config.apiKey?.trim()) {
throw new Error("CardQL API key cannot be empty");
}
if (!config.endpoint?.trim()) {
throw new Error("CardQL endpoint cannot be empty");
}
try {
new URL(config.endpoint);
} catch {
throw new Error("CardQL endpoint must be a valid URL");
}
if (config.timeout && (config.timeout < 1e3 || config.timeout > 3e5)) {
throw new Error(
"CardQL timeout must be between 1000ms and 300000ms (5 minutes)"
);
}
if (config.retries && (config.retries < 0 || config.retries > 10)) {
throw new Error("CardQL retries must be between 0 and 10");
}
}
var environmentConfigs = {
development: {
timeout: 3e4,
retries: 3,
enableLogging: true,
logLevel: "debug"
},
staging: {
timeout: 3e4,
retries: 3,
enableLogging: true,
logLevel: "info"
},
production: {
timeout: 15e3,
retries: 2,
enableLogging: false,
logLevel: "error"
}
};
// src/logger.ts
var Logger = class {
enabled;
level;
constructor(enabled = false, level = "info") {
this.enabled = enabled;
this.level = level;
}
shouldLog(level) {
if (!this.enabled) return false;
const levels = {
error: 0,
warn: 1,
info: 2,
debug: 3
};
return levels[level] <= levels[this.level];
}
formatMessage(level, message, metadata) {
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
const prefix = `[${timestamp}] [${level.toUpperCase()}] [CardQL]`;
if (metadata) {
return `${prefix} ${message} ${JSON.stringify(metadata)}`;
}
return `${prefix} ${message}`;
}
error(message, metadata) {
if (this.shouldLog("error")) {
console.error(this.formatMessage("error", message, metadata));
}
}
warn(message, metadata) {
if (this.shouldLog("warn")) {
console.warn(this.formatMessage("warn", message, metadata));
}
}
info(message, metadata) {
if (this.shouldLog("info")) {
console.info(this.formatMessage("info", message, metadata));
}
}
debug(message, metadata) {
if (this.shouldLog("debug")) {
console.debug(this.formatMessage("debug", message, metadata));
}
}
setEnabled(enabled) {
this.enabled = enabled;
}
setLevel(level) {
this.level = level;
}
};
var defaultLogger = new Logger();
// src/client.ts
var NodeCardQLClient = class extends CardQLClient {
logger;
constructor(config, logger) {
super(config);
this.logger = logger || defaultLogger;
}
async request(query, variables) {
this.logger.debug("Making GraphQL request", {
query: query.substring(0, 100) + "...",
variables
});
try {
const result = await super.request(query, variables);
this.logger.debug("GraphQL request successful");
return result;
} catch (error) {
this.logger.error("GraphQL request failed", {
error: error.message,
code: error.code
});
throw error;
}
}
};
var NodeCardQL = class _NodeCardQL extends CoreCardQL {
client;
api;
logger;
constructor(config) {
const finalConfig = config ? {
...createConfigFromEnv(),
...config
} : createConfigFromEnv();
validateConfig(finalConfig);
const logger = new Logger(
config?.enableLogging ?? false,
config?.logLevel ?? "info"
);
const nodeClient = new NodeCardQLClient(finalConfig, logger);
super(finalConfig);
this.client = nodeClient;
this.api = new CardQLApi(this.client);
this.logger = logger;
this.logger.info("CardQL Node.js client initialized", {
endpoint: finalConfig.endpoint,
timeout: finalConfig.timeout,
retries: finalConfig.retries
});
}
/**
* Create instance with environment-specific defaults
*/
static forEnvironment(env, overrides = {}) {
const envConfig = environmentConfigs[env];
return new _NodeCardQL({
...envConfig,
...overrides,
env
});
}
/**
* Enable or disable logging
*/
setLogging(enabled, level) {
this.logger.setEnabled(enabled);
if (level) {
this.logger.setLevel(level);
}
}
/**
* Health check method to verify connectivity
*/
async healthCheck() {
try {
this.logger.info("Performing health check...");
await this.api.getAccounts();
this.logger.info("Health check passed");
return true;
} catch (error) {
this.logger.error("Health check failed", { error: error.message });
return false;
}
}
/**
* Get client statistics
*/
getStats() {
return {
endpoint: this.client["config"].endpoint,
timeout: this.client["config"].timeout || 3e4,
retries: this.client["config"].retries || 3,
loggingEnabled: this.logger["enabled"]
};
}
};
// src/middleware.ts
function cardqlMiddleware(options = {}) {
const cardql = new NodeCardQL(options);
if (!options.skipHealthCheck) {
cardql.healthCheck().catch((error) => {
console.warn("[CardQL] Initial health check failed:", error.message);
});
}
return (req, res, next) => {
req.cardql = cardql;
next();
};
}
function cardqlErrorHandler() {
return (error, req, res, next) => {
if (error.code && error.message) {
const statusCode = getHttpStatusFromCardQLError(error);
res.status(statusCode).json({
error: {
message: error.message,
code: error.code,
details: error.details
}
});
return;
}
next(error);
};
}
function getHttpStatusFromCardQLError(error) {
switch (error.code) {
case "UNAUTHENTICATED":
case "INVALID_API_KEY":
return 401;
case "FORBIDDEN":
case "INSUFFICIENT_PERMISSIONS":
return 403;
case "NOT_FOUND":
case "RESOURCE_NOT_FOUND":
return 404;
case "VALIDATION_ERROR":
case "INVALID_INPUT":
return 400;
case "RATE_LIMITED":
return 429;
case "HTTP_ERROR":
return error.details?.status || 500;
default:
return 500;
}
}
function createCardQLContext(config) {
return {
cardql: new NodeCardQL(config)
};
}
function withCardQL(handler, config) {
const cardql = new NodeCardQL(config);
return async (event, context) => {
return handler(event, { ...context, cardql });
};
}
// src/index.ts
var index_default = NodeCardQL;
export {
NodeCardQL as CardQL,
Logger,
NodeCardQL,
NodeCardQLClient,
cardqlErrorHandler,
cardqlMiddleware,
createCardQLContext,
createConfigFromEnv,
index_default as default,
defaultLogger,
environmentConfigs,
validateConfig,
withCardQL
};