Repo cleanup and updates

This commit is contained in:
Darren Clarke 2025-11-10 14:55:22 +01:00 committed by GitHub
parent 3a1063e40e
commit 99f8d7e2eb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
72 changed files with 11857 additions and 16439 deletions

View file

@ -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";

View 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;

View 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);
}

View file

@ -138,15 +138,57 @@ 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() as any],
// 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;
},
});

View file

@ -1,6 +1,6 @@
{
"name": "@link-stack/bridge-common",
"version": "3.2.0b3",
"version": "3.3.0-beta.1",
"main": "build/main/index.js",
"type": "module",
"author": "Darren Clarke <darren@redaranj.com>",
@ -15,8 +15,9 @@
"pg": "^8.16.3"
},
"devDependencies": {
"@link-stack/eslint-config": "*",
"@link-stack/typescript-config": "*",
"@link-stack/eslint-config": "workspace:*",
"@link-stack/typescript-config": "workspace:*",
"@types/pg": "^8.15.5",
"typescript": "^5.9.3"
}
}

View file

@ -1,13 +1,13 @@
{
"name": "@link-stack/bridge-ui",
"version": "3.2.0b3",
"version": "3.3.0-beta.1",
"scripts": {
"build": "tsc -p tsconfig.json"
},
"dependencies": {
"@link-stack/bridge-common": "*",
"@link-stack/signal-api": "*",
"@link-stack/ui": "*",
"@link-stack/bridge-common": "workspace:*",
"@link-stack/signal-api": "workspace:*",
"@link-stack/ui": "workspace:*",
"@mui/material": "^6",
"@mui/x-data-grid-pro": "^7",
"kysely": "0.27.5",

View file

@ -38,8 +38,6 @@ export const colors: any = {
helpYellow: "#fff4d5",
dwcDarkBlue: "#191847",
hazyMint: "#ecf7f8",
leafcutterElectricBlue: "#4d6aff",
leafcutterLightBlue: "#fafbfd",
waterbearElectricPurple: "#332c83",
waterbearLightSmokePurple: "#eff3f8",
bumpedPurple: "#212058",

View file

@ -0,0 +1,2 @@
// Placeholder entry point for eslint-config package
module.exports = {};

View file

@ -1,10 +1,11 @@
{
"name": "@link-stack/eslint-config",
"version": "3.2.0b3",
"version": "3.3.0-beta.1",
"description": "amigo's eslint config",
"main": "index.js",
"author": "Abel Luck <abel@guardianproject.info>",
"license": "AGPL-3.0-or-later",
"private": false,
"private": true,
"scripts": {
"fmt": "prettier \"profile/**/*.js\" --write"
},

View file

@ -0,0 +1,2 @@
// Placeholder entry point for jest-config package
module.exports = {};

View file

@ -1,10 +1,11 @@
{
"name": "@link-stack/jest-config",
"version": "3.2.0b3",
"version": "3.3.0-beta.1",
"description": "",
"main": "index.js",
"author": "Abel Luck <abel@guardianproject.info>",
"license": "AGPL-3.0-or-later",
"private": false,
"private": true,
"engines": {
"node": ">=14"
},

View file

@ -1,6 +1,6 @@
{
"name": "@link-stack/logger",
"version": "3.2.0b3",
"version": "3.3.0-beta.1",
"description": "Shared logging utility for Link Stack monorepo",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
@ -23,8 +23,8 @@
"pino-pretty": "^13.1.1"
},
"devDependencies": {
"@link-stack/eslint-config": "*",
"@link-stack/typescript-config": "*",
"@link-stack/eslint-config": "workspace:*",
"@link-stack/typescript-config": "workspace:*",
"@types/node": "^24.7.0",
"eslint": "^9.37.0",
"tsup": "^8.5.0",
@ -33,4 +33,4 @@
"publishConfig": {
"access": "public"
}
}
}

View file

@ -17,6 +17,7 @@ export const getPinoConfig = (): LoggerOptions => {
timestamp: () => `,"timestamp":"${new Date(Date.now()).toISOString()}"`,
redact: {
paths: [
// Top-level sensitive fields
'password',
'token',
'secret',
@ -24,11 +25,35 @@ export const getPinoConfig = (): LoggerOptions => {
'apiKey',
'authorization',
'cookie',
'HandshakeKey',
'receivedSecret',
'access_token',
'refresh_token',
'zammadCsrfToken',
'clientSecret',
// Nested sensitive fields (one level)
'*.password',
'*.token',
'*.secret',
'*.api_key',
'*.apiKey',
'*.authorization',
'*.cookie',
'*.access_token',
'*.refresh_token',
'*.zammadCsrfToken',
'*.HandshakeKey',
'*.receivedSecret',
'*.clientSecret',
// Common nested patterns
'payload.HandshakeKey',
'headers.authorization',
'headers.cookie',
'headers.Authorization',
'headers.Cookie',
'credentials.password',
'credentials.secret',
'credentials.token',
],
censor: '[REDACTED]',
},

View file

@ -1,6 +1,6 @@
{
"name": "@link-stack/signal-api",
"version": "3.2.0b3",
"version": "3.3.0-beta.1",
"type": "module",
"main": "build/index.js",
"exports": {
@ -13,8 +13,8 @@
},
"devDependencies": {
"@openapitools/openapi-generator-cli": "^2.24.0",
"@link-stack/typescript-config": "*",
"@link-stack/eslint-config": "*",
"@link-stack/typescript-config": "workspace:*",
"@link-stack/eslint-config": "workspace:*",
"@types/node": "^24",
"typescript": "^5"
}

View file

@ -0,0 +1,2 @@
// Placeholder entry point for typescript-config package
module.exports = {};

View file

@ -1,6 +1,6 @@
{
"name": "@link-stack/typescript-config",
"version": "3.2.0b3",
"version": "3.3.0-beta.1",
"description": "Shared TypeScript config",
"license": "AGPL-3.0-or-later",
"author": "Abel Luck <abel@guardianproject.info>",

View file

@ -1,6 +1,6 @@
{
"name": "@link-stack/ui",
"version": "3.2.0b3",
"version": "3.3.0-beta.1",
"description": "",
"scripts": {
"build": "tsc -p tsconfig.json"

View file

@ -43,8 +43,6 @@ export const colors: any = {
helpYellow: "#fff4d5",
dwcDarkBlue: "#191847",
hazyMint: "#ecf7f8",
leafcutterElectricBlue: "#4d6aff",
leafcutterLightBlue: "#fafbfd",
waterbearElectricPurple: "#332c83",
waterbearLightSmokePurple: "#eff3f8",
bumpedPurple: "#212058",

View file

@ -1,14 +1,14 @@
{
"name": "@link-stack/zammad-addon-bridge",
"displayName": "Bridge",
"version": "3.2.0b3",
"version": "3.3.0-beta.1",
"description": "An addon that adds CDR Bridge channels to Zammad.",
"scripts": {
"build": "node '../../node_modules/@link-stack/zammad-addon-common/dist/build.js'",
"migrate": "node '../../node_modules/@link-stack/zammad-addon-common/dist/migrate.js'"
"build": "node '../zammad-addon-common/dist/build.js'",
"migrate": "node '../zammad-addon-common/dist/migrate.js'"
},
"dependencies": {
"@link-stack/zammad-addon-common": "*"
"@link-stack/zammad-addon-common": "workspace:*"
},
"author": "",
"license": "AGPL-3.0-or-later"

View file

@ -1,6 +1,6 @@
{
"name": "@link-stack/zammad-addon-common",
"version": "3.2.0b3",
"version": "3.3.0-beta.1",
"description": "",
"bin": {
"zpm-build": "./dist/build.js",
@ -16,7 +16,7 @@
"author": "",
"license": "AGPL-3.0-or-later",
"dependencies": {
"@link-stack/logger": "*",
"@link-stack/logger": "workspace:*",
"glob": "^11.0.3"
}
}

View file

@ -1,14 +1,14 @@
{
"name": "@link-stack/zammad-addon-hardening",
"displayName": "Hardening",
"version": "3.2.0b3",
"version": "3.3.0-beta.1",
"description": "A Zammad addon that hardens a Zammad instance according to CDR's needs.",
"scripts": {
"build": "node '../../node_modules/@link-stack/zammad-addon-common/dist/build.js'",
"migrate": "node '../../node_modules/@link-stack/zammad-addon-common/dist/migrate.js'"
"build": "node '../zammad-addon-common/dist/build.js'",
"migrate": "node '../zammad-addon-common/dist/migrate.js'"
},
"dependencies": {
"@link-stack/zammad-addon-common": "*"
"@link-stack/zammad-addon-common": "workspace:*"
},
"author": "",
"license": "AGPL-3.0-or-later"