From 3a06e2549b162417128596b3984923b903f867c6 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 8 Jul 2026 10:42:56 -0700 Subject: [PATCH 1/4] refactor(utils): consolidate duplicated helpers onto @sim/utils Replaces ~90 hand-rolled reimplementations of error-message extraction, postgres error-code checks, sleep, Math.random, retry/backoff, object filtering/omission, noop, string truncation, date/time formatting, email normalization, and plain-object type guards with the shared @sim/utils exports. Wires check:utils into CI (test-build.yml) so these patterns don't regress. --- .github/workflows/test-build.yml | 3 ++ apps/sim/app/(auth)/login/login-form.tsx | 7 +-- .../[executionId]/resume-page-client.tsx | 3 +- .../changelog-timeline/changelog-timeline.tsx | 13 ++--- apps/sim/app/api/auth/oauth/utils.ts | 4 +- .../app/api/billing/invoices/route.test.ts | 3 +- .../cron/renew-subscriptions/route.test.ts | 3 +- .../app/api/files/public/[token]/otp/route.ts | 5 +- .../app/api/files/public/[token]/sso/route.ts | 3 +- apps/sim/app/api/function/execute/route.ts | 7 +-- apps/sim/app/api/logs/export/route.ts | 3 +- .../api/mcp/servers/test-connection/route.ts | 3 +- apps/sim/app/api/memory/route.ts | 3 +- apps/sim/app/api/mothership/execute/route.ts | 4 +- .../organizations/[id]/invitations/route.ts | 5 +- .../api/organizations/[id]/members/route.ts | 3 +- apps/sim/app/api/schedules/execute/route.ts | 3 +- .../app/api/table/import-csv/route.test.ts | 3 +- apps/sim/app/api/v1/admin/credits/route.ts | 3 +- .../v1/knowledge/[id]/documents/route.test.ts | 3 +- .../webhooks/poll/[provider]/route.test.ts | 3 +- .../api/workspace-events/poll/route.test.ts | 3 +- .../app/f/[token]/public-file-email-auth.tsx | 9 ++-- .../app/f/[token]/public-file-sso-auth.tsx | 5 +- .../resource-chrome-fallback.tsx | 3 +- .../dirty-on-open.test.ts | 4 +- .../raw-markdown-snippet-view.test.ts | 4 +- .../chat-surface-context.tsx | 3 +- .../suggested-actions/suggested-actions.tsx | 3 +- .../home/hooks/stream/turn-model.ts | 5 +- .../document-tags-modal.tsx | 9 ++-- .../knowledge/[id]/[documentId]/document.tsx | 3 +- .../knowledge/[id]/[documentId]/loading.tsx | 3 +- .../[workspaceId]/knowledge/[id]/loading.tsx | 3 +- .../app/workspace/[workspaceId]/logs/utils.ts | 20 +------- .../settings/components/billing/billing.tsx | 12 +---- .../components/mothership/mothership.tsx | 5 +- .../organization-member-lists.tsx | 9 ++-- .../components/teammates/teammates.tsx | 7 +-- .../tables/[tableId]/loading.tsx | 3 +- .../import-csv-dialog/import-csv-dialog.tsx | 3 +- .../deploy-modal/components/chat/chat.tsx | 3 +- .../components/sidebar/hooks/use-drag-drop.ts | 3 +- .../sidebar/hooks/use-sidebar-list-context.ts | 2 +- apps/sim/blocks/blocks/cloudformation.ts | 5 +- apps/sim/blocks/blocks/new_relic.ts | 5 +- apps/sim/blocks/blocks/square.ts | 3 +- apps/sim/blocks/blocks/wiza.ts | 5 +- apps/sim/connectors/x/x.ts | 3 +- .../components/access-control.tsx | 3 +- .../components/group-detail.tsx | 3 +- .../executor/handlers/agent/agent-handler.ts | 3 +- apps/sim/hooks/queries/unsubscribe.test.tsx | 3 +- .../contracts/tools/aws/sts-assume-role.ts | 3 +- .../lib/billing/validation/seat-management.ts | 3 +- .../sim/lib/copilot/chat/workspace-context.ts | 3 +- .../copilot/tools/server/files/doc-compile.ts | 5 +- .../tools/server/files/doc-compiled-store.ts | 5 +- .../server/files/file-intent-store.test.ts | 3 +- .../tools/server/knowledge/knowledge-base.ts | 3 +- .../hosted-key-rate-limiter.test.ts | 3 +- apps/sim/lib/core/security/deployment.ts | 5 +- apps/sim/lib/core/utils/background.test.ts | 3 +- apps/sim/lib/core/utils/multipart.ts | 15 ++---- apps/sim/lib/events/pubsub.ts | 2 +- apps/sim/lib/execution/e2b.ts | 2 +- apps/sim/lib/file-parsers/xlsx-parser.ts | 5 +- .../knowledge/connectors/sync-engine.test.ts | 5 +- .../lib/knowledge/connectors/sync-engine.ts | 8 ++- .../lib/logs/execution/progress-markers.ts | 5 +- apps/sim/lib/messaging/sms/service.ts | 3 +- apps/sim/lib/monitoring/metrics.ts | 3 +- apps/sim/lib/table/sql.ts | 8 ++- apps/sim/lib/tokenization/utils.ts | 6 +-- apps/sim/lib/webhooks/processor.ts | 3 +- apps/sim/lib/workflows/schedules/utils.ts | 23 +-------- apps/sim/lib/workflows/subblocks/display.ts | 2 +- apps/sim/lib/workspaces/organization/utils.ts | 3 +- apps/sim/providers/utils.ts | 3 +- apps/sim/stores/chat/store.ts | 5 +- apps/sim/tools/amplitude/funnels.ts | 6 +-- apps/sim/tools/github/issue_comment.ts | 3 +- apps/sim/tools/github/list_issue_comments.ts | 3 +- apps/sim/tools/github/list_pr_comments.ts | 3 +- apps/sim/tools/github/update_comment.ts | 3 +- apps/sim/tools/incidentio/utils.ts | 7 +-- apps/sim/tools/index.ts | 49 +++++-------------- apps/sim/tools/notion/update_block.ts | 5 +- bun.lock | 1 + packages/logger/package.json | 1 + packages/logger/src/index.ts | 3 +- .../workflow-persistence/src/subblocks.ts | 3 +- scripts/create-single-release.ts | 3 +- 93 files changed, 213 insertions(+), 258 deletions(-) diff --git a/.github/workflows/test-build.yml b/.github/workflows/test-build.yml index 53a18cf16fd..5d906dc709a 100644 --- a/.github/workflows/test-build.yml +++ b/.github/workflows/test-build.yml @@ -116,6 +116,9 @@ jobs: - name: API contract boundary audit run: bun run check:api-validation:strict + - name: Shared utils enforcement audit + run: bun run check:utils + - name: Zustand v5 selector audit run: bun run check:zustand-v5 diff --git a/apps/sim/app/(auth)/login/login-form.tsx b/apps/sim/app/(auth)/login/login-form.tsx index d0f1fa59a29..9fd5adb148c 100644 --- a/apps/sim/app/(auth)/login/login-form.tsx +++ b/apps/sim/app/(auth)/login/login-form.tsx @@ -11,6 +11,7 @@ import { } from '@sim/emcn' import { createLogger } from '@sim/logger' import { getErrorMessage } from '@sim/utils/errors' +import { normalizeEmail } from '@sim/utils/string' import { useRouter, useSearchParams } from 'next/navigation' import { requestJson } from '@/lib/api/client/request' import { forgetPasswordContract } from '@/lib/api/contracts' @@ -45,7 +46,7 @@ const validateEmailField = (emailValue: string): string[] => { return errors } - const validation = quickValidateEmail(emailValue.trim().toLowerCase()) + const validation = quickValidateEmail(normalizeEmail(emailValue)) if (!validation.isValid) { errors.push(validation.reason || 'Please enter a valid email address.') } @@ -159,7 +160,7 @@ export default function LoginPage({ const formData = new FormData(e.currentTarget) const emailRaw = formData.get('email') as string - const email = emailRaw.trim().toLowerCase() + const email = normalizeEmail(emailRaw) const emailValidationErrors = validateEmailField(email) setEmailErrors(emailValidationErrors) @@ -277,7 +278,7 @@ export default function LoginPage({ return } - const emailValidation = quickValidateEmail(forgotPasswordEmail.trim().toLowerCase()) + const emailValidation = quickValidateEmail(normalizeEmail(forgotPasswordEmail)) if (!emailValidation.isValid) { setResetStatus({ type: 'error', diff --git a/apps/sim/app/(interfaces)/resume/[workflowId]/[executionId]/resume-page-client.tsx b/apps/sim/app/(interfaces)/resume/[workflowId]/[executionId]/resume-page-client.tsx index e6bf318c428..88a7cf3edae 100644 --- a/apps/sim/app/(interfaces)/resume/[workflowId]/[executionId]/resume-page-client.tsx +++ b/apps/sim/app/(interfaces)/resume/[workflowId]/[executionId]/resume-page-client.tsx @@ -18,6 +18,7 @@ import { TableRow, Tooltip, } from '@sim/emcn' +import { formatDateTime } from '@sim/utils/formatting' import { useQueryClient } from '@tanstack/react-query' import { RefreshCw } from 'lucide-react' import { useRouter } from 'next/navigation' @@ -68,7 +69,7 @@ const STATUS_BADGE_VARIANT: Record(initialEntries) const [loading, setLoading] = useState(false) @@ -133,7 +126,9 @@ export function ChangelogTimeline({ initialEntries }: ChangelogTimelineProps) { ) : null} - {formatDate(entry.date)} + + {formatDate(new Date(entry.date))} +