WhatsApp/Signal/Formstack/admin updates
This commit is contained in:
parent
bcecf61a46
commit
d0cc5a21de
451 changed files with 16139 additions and 39623 deletions
|
|
@ -9,3 +9,12 @@ export type {
|
|||
User,
|
||||
} from "./lib/database.js";
|
||||
export { getWorkerUtils } from "./lib/utils.js";
|
||||
export {
|
||||
getMaxAttachmentSize,
|
||||
getMaxTotalAttachmentSize,
|
||||
MAX_ATTACHMENTS,
|
||||
} from "./lib/config/attachments.js";
|
||||
export {
|
||||
getSignalAutoGroupNameTemplate,
|
||||
buildSignalGroupName,
|
||||
} from "./lib/config/signal.js";
|
||||
|
|
|
|||
36
packages/bridge-common/lib/config/attachments.ts
Normal file
36
packages/bridge-common/lib/config/attachments.ts
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Attachment size configuration for messaging channels
|
||||
*
|
||||
* Environment variables:
|
||||
* - BRIDGE_MAX_ATTACHMENT_SIZE_MB: Maximum size for a single attachment in MB (default: 50)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get the maximum attachment size in bytes from environment variable
|
||||
* Defaults to 50MB if not set
|
||||
*/
|
||||
export function getMaxAttachmentSize(): number {
|
||||
const envValue = process.env.BRIDGE_MAX_ATTACHMENT_SIZE_MB;
|
||||
const sizeInMB = envValue ? parseInt(envValue, 10) : 50;
|
||||
|
||||
// Validate the value
|
||||
if (isNaN(sizeInMB) || sizeInMB <= 0) {
|
||||
console.warn(`Invalid BRIDGE_MAX_ATTACHMENT_SIZE_MB value: ${envValue}, using default 50MB`);
|
||||
return 50 * 1024 * 1024;
|
||||
}
|
||||
|
||||
return sizeInMB * 1024 * 1024;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum total size for all attachments in a message
|
||||
* This is 4x the single attachment size
|
||||
*/
|
||||
export function getMaxTotalAttachmentSize(): number {
|
||||
return getMaxAttachmentSize() * 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximum number of attachments per message
|
||||
*/
|
||||
export const MAX_ATTACHMENTS = 10;
|
||||
29
packages/bridge-common/lib/config/signal.ts
Normal file
29
packages/bridge-common/lib/config/signal.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* Signal configuration
|
||||
*
|
||||
* Environment variables:
|
||||
* - SIGNAL_AUTO_GROUP_NAME_TEMPLATE: Template for auto-created group names (default: "Support Request: {conversationId}")
|
||||
* Available placeholders: {conversationId}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get the Signal auto-group name template from environment variable
|
||||
* Defaults to "Support Request: {conversationId}" if not set
|
||||
*/
|
||||
export function getSignalAutoGroupNameTemplate(): string {
|
||||
const template = process.env.SIGNAL_AUTO_GROUP_NAME_TEMPLATE;
|
||||
|
||||
if (!template) {
|
||||
return "Support Request: {conversationId}";
|
||||
}
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a Signal group name from the template and conversation ID
|
||||
*/
|
||||
export function buildSignalGroupName(conversationId: string): string {
|
||||
const template = getSignalAutoGroupNameTemplate();
|
||||
return template.replace('{conversationId}', conversationId);
|
||||
}
|
||||
|
|
@ -1,19 +1,12 @@
|
|||
import { PostgresDialect, CamelCasePlugin } from "kysely";
|
||||
import type {
|
||||
GeneratedAlways,
|
||||
Generated,
|
||||
ColumnType,
|
||||
Selectable,
|
||||
} from "kysely";
|
||||
import type { GeneratedAlways, Generated, ColumnType, Selectable } from "kysely";
|
||||
import pg from "pg";
|
||||
import { KyselyAuth } from "@auth/kysely-adapter";
|
||||
const { Pool, types } = pg;
|
||||
|
||||
type Timestamp = ColumnType<Date, Date | string>;
|
||||
|
||||
types.setTypeParser(types.builtins.TIMESTAMPTZ, (val) =>
|
||||
new Date(val).toISOString(),
|
||||
);
|
||||
types.setTypeParser(types.builtins.TIMESTAMPTZ, (val) => new Date(val).toISOString());
|
||||
|
||||
type GraphileJob = {
|
||||
taskIdentifier: string;
|
||||
|
|
@ -138,15 +131,67 @@ export type VoiceLine = Selectable<Database["VoiceLine"]>;
|
|||
export type Webhook = Selectable<Database["Webhook"]>;
|
||||
export type User = Selectable<Database["User"]>;
|
||||
|
||||
export const db = new KyselyAuth<Database>({
|
||||
dialect: new PostgresDialect({
|
||||
pool: new Pool({
|
||||
host: process.env.DATABASE_HOST,
|
||||
database: process.env.DATABASE_NAME,
|
||||
port: parseInt(process.env.DATABASE_PORT!),
|
||||
user: process.env.DATABASE_USER,
|
||||
password: process.env.DATABASE_PASSWORD,
|
||||
}),
|
||||
}) as any,
|
||||
plugins: [new CamelCasePlugin()],
|
||||
// Lazy database initialization to avoid errors during build time
|
||||
let _db: KyselyAuth<Database> | undefined;
|
||||
|
||||
function getDb(): KyselyAuth<Database> {
|
||||
if (_db) {
|
||||
return _db;
|
||||
}
|
||||
|
||||
// Validate environment variables
|
||||
const DATABASE_HOST = process.env.DATABASE_HOST;
|
||||
const DATABASE_NAME = process.env.DATABASE_NAME;
|
||||
const DATABASE_PORT = process.env.DATABASE_PORT;
|
||||
const DATABASE_USER = process.env.DATABASE_USER;
|
||||
const DATABASE_PASSWORD = process.env.DATABASE_PASSWORD;
|
||||
|
||||
if (
|
||||
!DATABASE_HOST ||
|
||||
!DATABASE_NAME ||
|
||||
!DATABASE_PORT ||
|
||||
!DATABASE_USER ||
|
||||
!DATABASE_PASSWORD
|
||||
) {
|
||||
throw new Error(
|
||||
"Missing required database environment variables: DATABASE_HOST, DATABASE_NAME, DATABASE_PORT, DATABASE_USER, DATABASE_PASSWORD",
|
||||
);
|
||||
}
|
||||
|
||||
const port = parseInt(DATABASE_PORT, 10);
|
||||
if (isNaN(port) || port < 1 || port > 65535) {
|
||||
throw new Error(
|
||||
`Invalid DATABASE_PORT: ${DATABASE_PORT}. Must be a number between 1 and 65535.`,
|
||||
);
|
||||
}
|
||||
|
||||
_db = new KyselyAuth<Database>({
|
||||
dialect: new PostgresDialect({
|
||||
pool: new Pool({
|
||||
host: DATABASE_HOST,
|
||||
database: DATABASE_NAME,
|
||||
port,
|
||||
user: DATABASE_USER,
|
||||
password: DATABASE_PASSWORD,
|
||||
}),
|
||||
}) as any,
|
||||
plugins: [new CamelCasePlugin() as any],
|
||||
});
|
||||
|
||||
return _db;
|
||||
}
|
||||
|
||||
// Export db as a getter that lazily initializes the database
|
||||
export const db = new Proxy({} as KyselyAuth<Database>, {
|
||||
get(_target, prop) {
|
||||
const instance = getDb();
|
||||
const value = (instance as any)[prop];
|
||||
|
||||
// If it's a function, bind it to the actual instance to preserve 'this' context
|
||||
if (typeof value === "function") {
|
||||
return value.bind(instance);
|
||||
}
|
||||
|
||||
return value;
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@link-stack/bridge-common",
|
||||
"version": "2.2.0",
|
||||
"version": "3.3.0",
|
||||
"main": "build/main/index.js",
|
||||
"type": "module",
|
||||
"author": "Darren Clarke <darren@redaranj.com>",
|
||||
|
|
@ -9,14 +9,15 @@
|
|||
"build": "tsc -p tsconfig.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@auth/kysely-adapter": "^1.5.2",
|
||||
"@auth/kysely-adapter": "^1.10.0",
|
||||
"graphile-worker": "^0.16.6",
|
||||
"kysely": "0.26.1",
|
||||
"pg": "^8.13.0"
|
||||
"kysely": "0.27.5",
|
||||
"pg": "^8.16.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@link-stack/eslint-config": "*",
|
||||
"@link-stack/typescript-config": "*",
|
||||
"typescript": "^5.6.2"
|
||||
"@link-stack/eslint-config": "workspace:*",
|
||||
"@link-stack/typescript-config": "workspace:*",
|
||||
"@types/pg": "^8.15.5",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue