merge staging

This commit is contained in:
dal 2025-09-22 09:35:24 -06:00
commit ddc9748ad8
No known key found for this signature in database
GPG Key ID: 16F4B0E1E9F61122
9 changed files with 29 additions and 38 deletions

View File

@ -104,7 +104,7 @@ Only utilize the required/default fields unless the user specifically requests t
# style: percent # style: percent
# replaceMissingDataWith: 0 # replaceMissingDataWith: 0
# numberSeparatorStyle: ',' # numberSeparatorStyle: ','
# multiplier: 100 # if calculated and not already multiplied # multiplier: 100 # Use 100 if SQL returns 0.75 for 75%; use 1 if SQL returns 75 for 75%
# minimumFractionDigits: 1 # minimumFractionDigits: 1
# maximumFractionDigits: 2 # maximumFractionDigits: 2
# ------------------------------------- # -------------------------------------
@ -348,15 +348,21 @@ definitions:
type: string type: string
enum: enum:
- currency # Note: The "$" sign is automatically prepended. - currency # Note: The "$" sign is automatically prepended.
- percent # Note: "%" sign is appended. For percentage values: - percent # Note: "%" sign is automatically appended as a suffix.
# - If the value comes directly from a database column, use multiplier: 1 # IMPORTANT: You MUST analyze the SQL query to determine the correct multiplier:
# - If the value is calculated in your SQL query and not already multiplied by 100, use multiplier: 100 # - If SQL returns decimal ratios (e.g., 0.75 for 75%), use multiplier: 100
# - If SQL returns percentage values (e.g., 75 for 75%), use multiplier: 1 (or omit it)
- number - number
- date # Note: For date columns, consider setting xAxisTimeInterval in xAxisConfig to control date grouping (day, week, month, quarter, year) - date # Note: For date columns, consider setting xAxisTimeInterval in xAxisConfig to control date grouping (day, week, month, quarter, year)
- string - string
multiplier: multiplier:
type: number type: number
description: Value to multiply the number by before display. Default value is 1. For percentages, the multiplier depends on how the data is sourced: if the value comes directly from a database column, use multiplier: 1; if the value is calculated in your SQL query and not already multiplied by 100, use multiplier: 100. description: |
Value to multiply the number by before display. Default: 1.
For percentages with style: percent, you MUST examine the SQL query and data format:
- If SQL returns decimal ratios (e.g., 0.75), use multiplier: 100 to convert to percentage (75%)
- If SQL returns percentage values (e.g., 75), use multiplier: 1 or omit this field
The agent must analyze the actual SQL query and understand the data format, not make assumptions.
displayName: displayName:
type: string type: string
description: Custom display name for the column description: Custom display name for the column

View File

@ -2,7 +2,8 @@
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"extends": ["../../biome.json"], "extends": ["../../biome.json"],
"files": { "files": {
"include": ["src/**/*", "scripts/**/*"] "include": ["src/**/*"],
"ignore": ["scripts/**/*"]
}, },
"overrides": [ "overrides": [
{ {

View File

@ -1,6 +1,6 @@
import { config } from 'dotenv';
import * as path from 'path'; import * as path from 'path';
import { fileURLToPath } from 'url'; import { fileURLToPath } from 'url';
import { config } from 'dotenv';
// Get the directory name for ES modules // Get the directory name for ES modules
const __filename = fileURLToPath(import.meta.url); const __filename = fileURLToPath(import.meta.url);
@ -60,29 +60,12 @@ export function initializePool<T extends Record<string, postgres.PostgresType>>(
} }
// Create postgres client with pool configuration // Create postgres client with pool configuration
// Disable SSL for local development // SSL is controlled via the connection string (e.g., ?sslmode=require)
const isDevelopment =
process.env.ENVIRONMENT === 'development' || process.env.NODE_ENV === 'development';
console.log(
'Database connection - ENVIRONMENT:',
process.env.ENVIRONMENT,
'NODE_ENV:',
process.env.NODE_ENV,
'isDevelopment:',
isDevelopment
);
globalPool = postgres(connectionString, { globalPool = postgres(connectionString, {
max: poolSize, max: poolSize,
idle_timeout: 30, idle_timeout: 30,
connect_timeout: 30, connect_timeout: 30,
prepare: true, prepare: true,
ssl: isDevelopment
? false
: {
rejectUnauthorized: false, // Allow self-signed certificates
},
...config, ...config,
}); });

View File

@ -10,7 +10,7 @@ vi.mock('../../connection', () => ({
// Mock drizzle-orm // Mock drizzle-orm
vi.mock('drizzle-orm', async (importOriginal) => { vi.mock('drizzle-orm', async (importOriginal) => {
const actual = (await importOriginal()) as any; const actual = (await importOriginal()) as Record<string, unknown>;
return { return {
...actual, ...actual,
sql: actual.sql, sql: actual.sql,

View File

@ -10,7 +10,7 @@ vi.mock('../../connection', () => ({
// Mock drizzle-orm // Mock drizzle-orm
vi.mock('drizzle-orm', async (importOriginal) => { vi.mock('drizzle-orm', async (importOriginal) => {
const actual = (await importOriginal()) as any; const actual = (await importOriginal()) as Record<string, unknown>;
return { return {
...actual, ...actual,
sql: actual.sql, sql: actual.sql,

View File

@ -82,10 +82,10 @@ describe('getOrganizationDocs', () => {
organizationId: '123e4567-e89b-12d3-a456-426614174000', organizationId: '123e4567-e89b-12d3-a456-426614174000',
}; };
let mockSelect: any; let mockSelect: ReturnType<typeof vi.fn>;
let mockFrom: any; let mockFrom: ReturnType<typeof vi.fn>;
let mockWhere: any; let mockWhere: ReturnType<typeof vi.fn>;
let mockOrderBy: any; let mockOrderBy: ReturnType<typeof vi.fn>;
beforeEach(() => { beforeEach(() => {
vi.clearAllMocks(); vi.clearAllMocks();

View File

@ -124,10 +124,10 @@ describe('upsertDoc', () => {
organizationId: '123e4567-e89b-12d3-a456-426614174000', organizationId: '123e4567-e89b-12d3-a456-426614174000',
}; };
let mockInsert: any; let mockInsert: ReturnType<typeof vi.fn>;
let mockValues: any; let mockValues: ReturnType<typeof vi.fn>;
let mockOnConflictDoUpdate: any; let mockOnConflictDoUpdate: ReturnType<typeof vi.fn>;
let mockReturning: any; let mockReturning: ReturnType<typeof vi.fn>;
beforeEach(() => { beforeEach(() => {
vi.clearAllMocks(); vi.clearAllMocks();

View File

@ -87,9 +87,10 @@ export async function createShortcut(input: CreateShortcutInput) {
.returning(); .returning();
return created; return created;
} catch (error: any) { } catch (error: unknown) {
// Handle unique constraint violation // Handle unique constraint violation
if (error?.code === '23505' && error?.constraint?.includes('unique')) { const dbError = error as { code?: string; constraint?: string };
if (dbError?.code === '23505' && dbError?.constraint?.includes('unique')) {
throw new Error(`Shortcut with name '${validated.name}' already exists`); throw new Error(`Shortcut with name '${validated.name}' already exists`);
} }
throw error; throw error;

View File

@ -16,7 +16,7 @@ export type UpdateShortcutInput = z.infer<typeof UpdateShortcutInputSchema>;
export async function updateShortcut(input: UpdateShortcutInput) { export async function updateShortcut(input: UpdateShortcutInput) {
const validated = UpdateShortcutInputSchema.parse(input); const validated = UpdateShortcutInputSchema.parse(input);
const updateData: Record<string, any> = { const updateData: Record<string, unknown> = {
updatedBy: validated.updatedBy, updatedBy: validated.updatedBy,
updatedAt: new Date().toISOString(), updatedAt: new Date().toISOString(),
}; };