Skip to content

Conversation

@drifter089
Copy link
Owner

@drifter089 drifter089 commented Dec 5, 2025

Summary

Sets up Nango integrations infrastructure for continuous data syncing from external APIs. This replaces manual API fetching with automated syncs that keep data fresh.

Key Changes

  • Initialize nango-integrations/ folder with Nango CLI (v0.69.14)
  • Add example GitHub sync that fetches issues across all user repositories
  • Add TypeScript types for Nango sync records and processing
  • Configure ESLint to exclude CLI-generated Nango code

Next Steps

  • Add more syncs for YouTube, PostHog, and other integrations
  • Implement webhook handler for sync completion notifications
  • Add MetricDataPoint table for time-series storage

Summary by CodeRabbit

  • New Features

    • Added GitHub integration to create issues and sync repository issues
    • Added connection deletion event handler for GitHub
  • Chores

    • Configured project build system and dependencies

✏️ Tip: You can customize this high-level summary in your review settings.

- Initialize nango-integrations folder with CLI (v0.69.14)
- Add example GitHub sync for fetching issues across repos
- Add sync types for Nango record handling
- Exclude nango-integrations from eslint (CLI-generated code)
@vercel
Copy link

vercel bot commented Dec 5, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
org-os Error Error Dec 5, 2025 2:20pm

@coderabbitai
Copy link

coderabbitai bot commented Dec 5, 2025

Walkthrough

Introduces a new nango-integrations package with GitHub integration modules for fetching user issues and creating issues, plus a pre-connection-deletion lifecycle event handler. Includes TypeScript source files, compiled CommonJS artifacts, and package configuration. Also adds sync service type definitions for record metadata, pagination, and processing results.

Changes

Cohort / File(s) Summary
ESLint Configuration
eslint.config.js
Adds nango-integrations/** to ignore patterns
Package Setup
nango-integrations/.gitignore, nango-integrations/package.json, nango-integrations/tsconfig.json, nango-integrations/index.ts
Initializes nango-integrations package with standard ignores, npm metadata (nango 0.69.14, zod 4.0.5), TypeScript configuration, and aggregates module imports
GitHub Action: Create Issue
nango-integrations/github/actions/createIssue.ts, nango-integrations/build/github_actions_createIssue.cjs
TypeScript source and CommonJS build for GitHub issue creation action with Zod-validated input schema and GitHub API POST implementation
GitHub On-Event: Pre-Connection-Deletion
nango-integrations/github/on-events/pre-connection-deletion.ts, nango-integrations/build/github_on-events_pre-connection-deletion.cjs
TypeScript source and CommonJS build for connection deletion lifecycle event handler with async logging
GitHub Sync: Fetch Issues
nango-integrations/github/syncs/fetchIssues.ts, nango-integrations/build/github_syncs_fetchIssues.cjs
TypeScript source and CommonJS build for paginated GitHub issue synchronization across all user repositories with filtering, mapping, batch saving, and cleanup
Sync Service Types
src/server/api/services/sync/types.ts
New type definitions for NangoRecord, NangoRecordMetadata, NangoListRecordsResponse, SyncConfigInput, SyncStatus, and SyncProcessResult

Sequence Diagram(s)

sequenceDiagram
    participant Nango as Nango Sync
    participant GitHub as GitHub API
    participant DB as Nango Database
    
    rect rgb(200, 220, 240)
    note over Nango,DB: Fetch Issues Workflow
    end
    
    Nango->>GitHub: GET /user/repos (paginated, limit=100)
    GitHub-->>Nango: User repositories
    
    loop For each repository
        Nango->>GitHub: GET /repos/{owner}/{repo}/issues (paginated, limit=100)
        GitHub-->>Nango: Issues list
        
        rect rgb(240, 220, 200)
        note over Nango: Filter pull requests,<br/>map to GithubIssue schema
        end
        
        Nango->>DB: batchSave(GithubIssue records)
        DB-->>Nango: Batch saved
        
        rect rgb(220, 240, 220)
        note over Nango: Log batch progress
        end
    end
    
    Nango->>DB: Delete previous GithubIssue records
    DB-->>Nango: Records deleted
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Nango SDK patterns: Integration with Nango actions, syncs, and on-event lifecycle; requires familiarity with Nango conventions and API
  • GitHub API implementation: Pagination handling, filtering pull requests vs. issues, and repository enumeration need validation
  • Build artifacts: CommonJS compiled versions present alongside TypeScript sources; verify build correctness or confirm generation process
  • Schema validation: Multiple Zod schemas across action input, sync models, and new service types; ensure consistency and correctness
  • Record lifecycle: New metadata fields (deleted_at, last_action, cursors) and SyncProcessResult aggregations require careful integration review

Poem

🐰 A warren of syncs now hops with glee,
Fetching issues from GitHub's grand spree,
Batch-saving records with care and with grace,
Events deleted, connections erased,
Integrations complete—let the data flow free!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding Nango integrations infrastructure for data syncing, which aligns with the primary objective of the PR.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch nango-sync-setup

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (7)
src/server/api/services/sync/types.ts (1)

5-41: Consider adding Zod schemas for runtime validation.

Since this code will process external data from Nango syncs and Zod is already a project dependency, consider adding Zod schemas alongside these TypeScript types to provide runtime validation and type safety when parsing API responses.

Example approach:

import { z } from "zod";

export const NangoRecordMetadataSchema = z.object({
  deleted_at: z.string().nullable(),
  last_action: z.enum(["ADDED", "UPDATED", "DELETED"]),
  first_seen_at: z.string(),
  last_modified_at: z.string(),
  cursor: z.string(),
});

export type NangoRecordMetadata = z.infer<typeof NangoRecordMetadataSchema>;

export const NangoRecordSchema = <T extends z.ZodTypeAny>(dataSchema: T) =>
  z.object({
    id: z.string(),
    _nango_metadata: NangoRecordMetadataSchema,
    data: dataSchema,
  });

export type NangoRecord<T = Record<string, unknown>> = {
  id: string;
  _nango_metadata: NangoRecordMetadata;
  data: T;
};

// Similar patterns for other interfaces...

This would enable safe parsing of external API responses with .parse() or .safeParse().

nango-integrations/github/actions/createIssue.ts (2)

4-16: Input schema fields are largely unused by the action.

The issueSchema requires 11 fields (id, owner, repo, etc.), but the exec function only uses input.title. The action also ignores input.owner and input.repo, hardcoding the target repository to NangoHQ/interactive-demo.

If this is intentional for demo purposes, consider simplifying the input schema to only require the fields actually used, or add a comment clarifying the intent.

-const issueSchema = z.object({
-  id: z.string(),
-  owner: z.string(),
-  repo: z.string(),
-  issue_number: z.number(),
-  title: z.string(),
-  state: z.string(),
-  author: z.string(),
-  author_id: z.number(),
-  body: z.string(),
-  date_created: z.string(),
-  date_last_modified: z.string(),
-});
+// Minimal schema for demo action - only title is used
+const issueSchema = z.object({
+  title: z.string(),
+});

26-35: Missing error handling for the GitHub API proxy call.

The exec function does not handle potential errors from nango.proxy(). If the API call fails (e.g., rate limiting, auth issues, network errors), the error will propagate unhandled.

Consider adding error handling or at minimum logging failures for observability.

  exec: async (nango, input) => {
-    await nango.proxy({
-      endpoint: "/repos/NangoHQ/interactive-demo/issues",
-      data: {
-        title: `[demo] ${input.title}`,
-        body: `This issue was created automatically using Nango Action.`,
-        labels: ["automatic"],
-      },
-    });
+    try {
+      await nango.proxy({
+        endpoint: "/repos/NangoHQ/interactive-demo/issues",
+        data: {
+          title: `[demo] ${input.title}`,
+          body: `This issue was created automatically using Nango Action.`,
+          labels: ["automatic"],
+        },
+      });
+    } catch (error) {
+      await nango.log(`Failed to create issue: ${error}`);
+      throw error;
+    }
   },
nango-integrations/github/syncs/fetchIssues.ts (2)

84-98: Avoid any[] return type; define a repository interface for type safety.

Using any[] loses type information and can mask bugs. Consider defining a minimal interface for the repository shape you need.

+interface GithubRepository {
+  name: string;
+  owner: { login: string };
+}

-async function getAllRepositories(nango: NangoSyncLocal): Promise<any[]> {
-  const records: any[] = [];
+async function getAllRepositories(nango: NangoSyncLocal): Promise<GithubRepository[]> {
+  const records: GithubRepository[] = [];

75-78: Webhook handler is a no-op placeholder.

The onWebhook handler only logs the payload without processing it. If webhook handling isn't needed yet, consider adding a TODO comment or removing it to avoid confusion.

nango-integrations/build/github_on-events_pre-connection-deletion.cjs (1)

27-35: Placeholder implementation for connection deletion.

The event handler currently only logs a message. For production use, consider implementing cleanup logic such as deleting synced records or notifying downstream systems.

nango-integrations/build/github_syncs_fetchIssues.cjs (1)

106-118: Helper function is correct but could use better typing.

The repository fetching logic is sound. Consider adding proper TypeScript types for the repository objects in the source file instead of any[] for better type safety.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6c09cc8 and d64377d.

⛔ Files ignored due to path filters (1)
  • nango-integrations/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (12)
  • eslint.config.js (1 hunks)
  • nango-integrations/.gitignore (1 hunks)
  • nango-integrations/build/github_actions_createIssue.cjs (1 hunks)
  • nango-integrations/build/github_on-events_pre-connection-deletion.cjs (1 hunks)
  • nango-integrations/build/github_syncs_fetchIssues.cjs (1 hunks)
  • nango-integrations/github/actions/createIssue.ts (1 hunks)
  • nango-integrations/github/on-events/pre-connection-deletion.ts (1 hunks)
  • nango-integrations/github/syncs/fetchIssues.ts (1 hunks)
  • nango-integrations/index.ts (1 hunks)
  • nango-integrations/package.json (1 hunks)
  • nango-integrations/tsconfig.json (1 hunks)
  • src/server/api/services/sync/types.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: In TypeScript files, use @typescript-eslint/consistent-type-imports to enforce inline type imports and sort imports with @trivago/prettier-plugin-sort-imports
Use the tRPC server caller API from src/trpc/server.ts directly in Server Components for 10x faster performance instead of client-side hooks

Files:

  • nango-integrations/github/on-events/pre-connection-deletion.ts
  • src/server/api/services/sync/types.ts
  • nango-integrations/github/actions/createIssue.ts
  • nango-integrations/index.ts
  • nango-integrations/github/syncs/fetchIssues.ts
**/*.{tsx,ts}

📄 CodeRabbit inference engine (CLAUDE.md)

Use TanStack Query (via tRPC hooks) for server state management, client-side data fetching, and automatic cache invalidation

Files:

  • nango-integrations/github/on-events/pre-connection-deletion.ts
  • src/server/api/services/sync/types.ts
  • nango-integrations/github/actions/createIssue.ts
  • nango-integrations/index.ts
  • nango-integrations/github/syncs/fetchIssues.ts
src/server/api/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Add new tRPC routers in src/server/api/routers/[name].ts and register them in the appRouter in src/server/api/root.ts

Files:

  • src/server/api/services/sync/types.ts
🧠 Learnings (1)
📚 Learning: 2025-12-02T13:36:55.215Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-02T13:36:55.215Z
Learning: Applies to **/*.{ts,tsx} : In TypeScript files, use `typescript-eslint/consistent-type-imports` to enforce inline type imports and sort imports with trivago/prettier-plugin-sort-imports

Applied to files:

  • eslint.config.js
  • nango-integrations/tsconfig.json
🧬 Code graph analysis (5)
nango-integrations/github/actions/createIssue.ts (1)
src/server/nango.ts (1)
  • nango (12-12)
nango-integrations/build/github_actions_createIssue.cjs (1)
src/server/nango.ts (1)
  • nango (12-12)
nango-integrations/build/github_on-events_pre-connection-deletion.cjs (1)
src/server/nango.ts (1)
  • nango (12-12)
nango-integrations/build/github_syncs_fetchIssues.cjs (1)
src/server/nango.ts (1)
  • nango (12-12)
nango-integrations/github/syncs/fetchIssues.ts (2)
src/server/nango.ts (1)
  • nango (12-12)
nango-integrations/build/github_syncs_fetchIssues.cjs (6)
  • repos (69-69)
  • proxyConfig (71-76)
  • proxyConfig (108-113)
  • issues (78-78)
  • mappedIssues (79-91)
  • records (107-107)
🔇 Additional comments (8)
eslint.config.js (1)

11-11: LGTM! Appropriate exclusion of CLI-generated code.

Adding nango-integrations/** to the ESLint ignores aligns with the PR objective to exclude CLI-generated Nango code from linting.

nango-integrations/.gitignore (1)

1-8: LGTM! Standard ignore patterns.

The ignore rules appropriately cover environment files, Nango build artifacts, and Node.js dependencies.

nango-integrations/tsconfig.json (1)

1-30: LGTM! Strict TypeScript configuration managed by Nango CLI.

The configuration enables comprehensive strict type checking, which will help catch errors early. As noted in line 3, this file is managed by Nango and should not be manually edited.

nango-integrations/package.json (1)

14-15: Both nango@0.69.14 and zod@4.0.5 are valid, published versions with no known security vulnerabilities. Zod's recent ReDoS vulnerability affected versions 3.21.0–3.22.3 only, and Nango has no reported security advisories for this release. These versions are safe to use.

nango-integrations/index.ts (1)

1-3: LGTM!

The side-effect imports correctly aggregate GitHub integration modules for runtime registration. Using .js extensions is appropriate for ESM output.

nango-integrations/build/github_actions_createIssue.cjs (1)

1-74: Verify if committing build artifacts is intentional.

This appears to be a CLI-generated build artifact. Typically, build outputs are excluded from version control (via .gitignore) and regenerated during CI/CD. However, some deployment workflows require pre-built artifacts.

Please confirm this is intentional for Nango's deployment model. If the build step can run during deployment, consider adding nango-integrations/build/ to .gitignore.

nango-integrations/github/on-events/pre-connection-deletion.ts (1)

3-9: Placeholder implementation is functional but minimal.

The handler currently only logs "Executed". For production use, consider implementing actual cleanup logic (e.g., revoking tokens, cleaning up external resources) before connection deletion.

This is fine as scaffolding for the initial setup.

nango-integrations/build/github_syncs_fetchIssues.cjs (1)

51-104: Sync logic is well-structured.

The sync implementation correctly:

  • Filters out pull requests (Line 78)
  • Batches saves for efficiency (Line 93)
  • Cleans up stale records from previous runs (Line 98)

The hourly frequency with full sync may require attention to GitHub API rate limits (5,000 requests/hour for authenticated requests). Since the Nango SDK (@nangohq/node@0.69.10) handles pagination internally, verify that rate limit backoff and retry logic are enabled in your Nango configuration to avoid hitting 429 errors during multi-repository syncs.

Comment on lines +1 to +41
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// nango-integrations/github/on-events/pre-connection-deletion.ts
var pre_connection_deletion_exports = {};
__export(pre_connection_deletion_exports, {
default: () => pre_connection_deletion_default,
onEvent: () => onEvent
});
module.exports = __toCommonJS(pre_connection_deletion_exports);
var onEvent = {
type: "onEvent",
event: "pre-connection-deletion",
// 'post-connection-creation' | 'validate-connection'
description: "This script is executed before a connection is deleted",
exec: async (nango) => {
await nango.log("Executed");
}
};
var pre_connection_deletion_default = onEvent;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
onEvent
});
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsibmFuZ28taW50ZWdyYXRpb25zL2dpdGh1Yi9vbi1ldmVudHMvcHJlLWNvbm5lY3Rpb24tZGVsZXRpb24udHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB7IGNyZWF0ZU9uRXZlbnQgfSBmcm9tICduYW5nbyc7XG5leHBvcnQgY29uc3Qgb25FdmVudCA9IHtcbiAgdHlwZTogXCJvbkV2ZW50XCIsXG4gIGV2ZW50OiAncHJlLWNvbm5lY3Rpb24tZGVsZXRpb24nLFxuICAvLyAncG9zdC1jb25uZWN0aW9uLWNyZWF0aW9uJyB8ICd2YWxpZGF0ZS1jb25uZWN0aW9uJ1xuICBkZXNjcmlwdGlvbjogJ1RoaXMgc2NyaXB0IGlzIGV4ZWN1dGVkIGJlZm9yZSBhIGNvbm5lY3Rpb24gaXMgZGVsZXRlZCcsXG4gIGV4ZWM6IGFzeW5jIG5hbmdvID0+IHtcbiAgICBhd2FpdCBuYW5nby5sb2coJ0V4ZWN1dGVkJyk7XG4gIH1cbn07XG5leHBvcnQgZGVmYXVsdCBvbkV2ZW50OyJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ08sSUFBTSxVQUFVO0FBQUEsRUFDckIsTUFBTTtBQUFBLEVBQ04sT0FBTztBQUFBO0FBQUEsRUFFUCxhQUFhO0FBQUEsRUFDYixNQUFNLE9BQU0sVUFBUztBQUNuQixVQUFNLE1BQU0sSUFBSSxVQUFVO0FBQUEsRUFDNUI7QUFDRjtBQUNBLElBQU8sa0NBQVE7IiwKICAibmFtZXMiOiBbXQp9Cg==
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Nango integration framework build artifacts deployment requirements

💡 Result:

Summary of key build-artifact / deployment requirements for Nango integrations:

  • Nango CLI + project layout: install the nango CLI (npm) and keep integrations in a version-controlled nango-integrations/ folder (nango init creates structure). [1][2]
  • Runtime tooling: Node.js/npm for building functions, and Docker (or Docker Compose) when using local/self‑hosted Nango or sample apps. [2][3][4]
  • Environment variables / secrets: provide NANGO_SECRET_KEY_DEV and NANGO_SECRET_KEY_PROD for CLI auth, set NANGO_HOSTPORT to your instance URL for self‑hosted, and any .env in ./nango-integrations with these values. CI deploys must supply those secrets. [1][2]
  • Encryption key (self-hosted): a persistent NANGO_ENCRYPTION_KEY is required for self‑hosted deployments (cannot be re‑generated later). [5]
  • Deployment commands / CI: use nango deploy (can target envs like dev/prod); CI should install nango CLI, load env secrets, and may pass flags like --auto-confirm or --allow-destructive when needed. [1][2][5]
  • Ports / infra (self-hosted): default OSS ports (server 3003, Postgres 5432) when using docker-compose; adapt as needed in .env/docker-compose. [4]
  • Best practices: keep integrations in source control, include .env templates, and automate deploys in CI with appropriate secret management. [2][3]

Sources: Nango CLI & env docs; Functions/setup and deploy guides; Sample app deployment; Self-hosting (docker compose); note on NANGO_ENCRYPTION_KEY. [1][2][3][4][5]


🏁 Script executed:

# Check if there are other similar compiled artifacts in the build directory
fd -e cjs nango-integrations/build/ | head -20

Repository: drifter089/orgOS

Length of output: 465


🏁 Script executed:

# Look for build configuration and CI/CD setup
fd -e json -e yaml -e yml -e toml . | grep -E "(package\.json|tsconfig|esbuild|webpack|build|ci)" | head -30

Repository: drifter089/orgOS

Length of output: 151


🏁 Script executed:

# Search for documentation about nango-integrations structure
find . -name "README*" -o -name "*.md" | xargs grep -l "nango-integrations\|build artifact" 2>/dev/null | head -10

Repository: drifter089/orgOS

Length of output: 42


🏁 Script executed:

# Explore nango-integrations directory structure
ls -la nango-integrations/ 2>/dev/null | head -20

Repository: drifter089/orgOS

Length of output: 620


🏁 Script executed:

# Check the actual build directory
ls -la nango-integrations/build/ 2>/dev/null | head -30

Repository: drifter089/orgOS

Length of output: 423


🏁 Script executed:

# Check package.json build scripts
cat nango-integrations/package.json | head -50

Repository: drifter089/orgOS

Length of output: 342


🏁 Script executed:

# Check .gitignore for build patterns
cat .gitignore 2>/dev/null

Repository: drifter089/orgOS

Length of output: 874


🏁 Script executed:

# Look for nango CLI config (nango.yaml or similar)
find nango-integrations -name "nango.yaml" -o -name "nango.yml" -o -name ".nangorc*" 2>/dev/null

Repository: drifter089/orgOS

Length of output: 42


🏁 Script executed:

# Verify the nango-integrations/.gitignore specifically
cat nango-integrations/.gitignore

Repository: drifter089/orgOS

Length of output: 147


🏁 Script executed:

# Check if build files are tracked by git
cd nango-integrations && git ls-files build/ 2>/dev/null || echo "Not in git or error"

Repository: drifter089/orgOS

Length of output: 182


🏁 Script executed:

# Look at the source TypeScript files
find nango-integrations/github -name "*.ts" -type f | head -10

Repository: drifter089/orgOS

Length of output: 218


🏁 Script executed:

# Check git history to see if build files were recently added
git log --oneline nango-integrations/build/ 2>/dev/null | head -5

Repository: drifter089/orgOS

Length of output: 127


🏁 Script executed:

# Verify the compilation flow - does nango compile generate these files?
cat nango-integrations/tsconfig.json

Repository: drifter089/orgOS

Length of output: 986


Remove committed build artifacts from the nango-integrations/build directory.

The compiled .cjs files in nango-integrations/build/ are build artifacts generated by nango compile from TypeScript sources. Nango's own tsconfig.json explicitly excludes the build directory, indicating these files should not be in version control. They are regenerated during deployment via nango deploy. Remove all .cjs files from nango-integrations/build/ and add build/ to nango-integrations/.gitignore. Keep only the source .ts files in nango-integrations/github/.

🤖 Prompt for AI Agents
In nango-integrations/build/github_on-events_pre-connection-deletion.cjs (lines
1-41): this is a compiled build artifact that should not be committed; remove
this .cjs file (and any other files under nango-integrations/build/), add build/
to nango-integrations/.gitignore, ensure only the original TypeScript source
files remain under nango-integrations/github/, and update the commit so the
build output is no longer tracked.

Comment on lines +38 to +50
var issueSchema = z.object({
id: z.string(),
owner: z.string(),
repo: z.string(),
issue_number: z.number(),
title: z.string(),
state: z.string(),
author: z.string(),
author_id: z.number(),
body: z.string(),
date_created: z.string(),
date_last_modified: z.string()
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Find the source TypeScript file
find . -name "fetchIssues.ts" -type f

Repository: drifter089/orgOS

Length of output: 108


🌐 Web query:

GitHub REST API issue object body field null

💡 Result:

Common causes

  • The issue really has no body (empty) — then the JSON "body" is null.
  • You're requesting the default/other media type that doesn't return the raw "body" field; GitHub exposes different representations (body, body_text, body_html) only when the appropriate Accept media type is used.
    What to do
  • Verify the issue actually has text in the web UI.
  • Request the body explicitly by sending an Accept header such as:
    • application/vnd.github.raw+json (returns body)
    • application/vnd.github.text+json (returns body_text)
    • application/vnd.github.html+json (returns body_html)
    • application/vnd.github.full+json (returns body, body_text, body_html)
      References
  • GitHub REST issues docs (media types & body fields). [1] [2]

Sources
[1] REST API endpoints for issues — GitHub Docs. [turn0search0]
[2] REST API endpoints for issues (Enterprise) — GitHub Docs. [turn0search3]


🏁 Script executed:

cat -n ./nango-integrations/github/syncs/fetchIssues.ts

Repository: drifter089/orgOS

Length of output: 3295


Fix nullable body field in schema.

The body field is defined as z.string(), but GitHub's API returns null for issues without a description. This causes validation failures when syncing such issues. Update the schema in the source TypeScript file:

- body: z.string(),
+ body: z.string().nullable(),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
var issueSchema = z.object({
id: z.string(),
owner: z.string(),
repo: z.string(),
issue_number: z.number(),
title: z.string(),
state: z.string(),
author: z.string(),
author_id: z.number(),
body: z.string(),
date_created: z.string(),
date_last_modified: z.string()
});
var issueSchema = z.object({
id: z.string(),
owner: z.string(),
repo: z.string(),
issue_number: z.number(),
title: z.string(),
state: z.string(),
author: z.string(),
author_id: z.number(),
body: z.string().nullable(),
date_created: z.string(),
date_last_modified: z.string()
});
🤖 Prompt for AI Agents
In nango-integrations/build/github_syncs_fetchIssues.cjs around lines 38 to 50,
the issueSchema defines body as z.string() which fails when GitHub returns null;
replace the body schema with a nullable string (e.g., change body: z.string() to
body: z.string().nullable()) so validation accepts both string and null; update
the source TypeScript schema (not just the built CJS) and rebuild to propagate
the change.

Comment on lines +68 to +97
exec: async (nango) => {
const repos = await getAllRepositories(nango);
for (const repo of repos) {
const proxyConfig = {
endpoint: `/repos/${repo.owner.login}/${repo.name}/issues`,
paginate: {
limit: LIMIT
}
};
for await (const issueBatch of nango.paginate(proxyConfig)) {
const issues = issueBatch.filter((issue) => !("pull_request" in issue));
const mappedIssues = issues.map((issue) => ({
id: issue.id,
owner: repo.owner.login,
repo: repo.name,
issue_number: issue.number,
title: issue.title,
state: issue.state,
author: issue.user.login,
author_id: issue.user.id,
body: issue.body,
date_created: issue.created_at,
date_last_modified: issue.updated_at
}));
if (mappedIssues.length > 0) {
await nango.batchSave(mappedIssues, "GithubIssue");
await nango.log(`Sent ${mappedIssues.length} issues from ${repo.owner.login}/${repo.name}`);
}
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add error handling for individual repository failures.

The sync iterates through all repositories without try-catch blocks. If fetching issues from one repository fails (e.g., due to permissions or API errors), the entire sync will fail and subsequent repositories won't be processed.

Consider wrapping the per-repository logic in try-catch in the source TypeScript file:

for (const repo of repos) {
  try {
    const proxyConfig = { /* ... */ };
    for await (const issueBatch of nango.paginate(proxyConfig)) {
      // ... existing logic
    }
  } catch (error) {
    await nango.log(`Failed to fetch issues from ${repo.owner.login}/${repo.name}: ${error}`);
    // Continue with next repository
  }
}
🤖 Prompt for AI Agents
In nango-integrations/build/github_syncs_fetchIssues.cjs around lines 68 to 97,
the loop over repos lacks per-repository error handling so a failure fetching
one repo's issues can abort the whole sync; wrap the logic that builds
proxyConfig and the for-await-of nango.paginate(...) processing (including
filtering, mapping, batchSave and log) in a try-catch that on catch awaits
nango.log with a message containing the repo owner/name and the caught error,
then continues to the next repo so other repositories still get processed.

Comment on lines +5 to +6
const issueSchema = z.object({
id: z.string(),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Type mismatch: id schema expects string but GitHub returns number.

GitHub's API returns issue.id as a number, but the schema defines id: z.string(). At line 50, you assign id: issue.id directly without conversion, which will cause Zod validation to fail if schema validation is enabled.

 const issueSchema = z.object({
-  id: z.string(),
+  id: z.number(),
   owner: z.string(),

Or convert at mapping time:

         const mappedIssues: GithubIssue[] = issues.map((issue) => ({
-          id: issue.id,
+          id: String(issue.id),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const issueSchema = z.object({
id: z.string(),
const issueSchema = z.object({
id: z.number(),
owner: z.string(),
🤖 Prompt for AI Agents
In nango-integrations/github/syncs/fetchIssues.ts around lines 5 to 6 and the
mapping at line ~50, the Zod schema defines id: z.string() but GitHub returns
issue.id as a number; fix by making the schema and mapping consistent — either
change the schema to id: z.number() (and update any downstream code expecting a
string) or keep a string schema and coerce the value (use z.coerce.string() for
the schema or convert the id when mapping with String(issue.id)); ensure the
chosen approach is applied both in the schema and where issue.id is assigned so
Zod validation succeeds.

Comment on lines +49 to +61
const mappedIssues: GithubIssue[] = issues.map((issue) => ({
id: issue.id,
owner: repo.owner.login,
repo: repo.name,
issue_number: issue.number,
title: issue.title,
state: issue.state,
author: issue.user.login,
author_id: issue.user.id,
body: issue.body,
date_created: issue.created_at,
date_last_modified: issue.updated_at,
}));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Potential null reference errors in issue mapping.

Several GitHub API fields can be null:

  • issue.body is nullable (returns null for issues without a body)
  • issue.user can be null for deleted/ghost users, causing issue.user.login and issue.user.id to throw
         const mappedIssues: GithubIssue[] = issues.map((issue) => ({
           id: issue.id,
           owner: repo.owner.login,
           repo: repo.name,
           issue_number: issue.number,
           title: issue.title,
           state: issue.state,
-          author: issue.user.login,
-          author_id: issue.user.id,
-          body: issue.body,
+          author: issue.user?.login ?? "ghost",
+          author_id: issue.user?.id ?? 0,
+          body: issue.body ?? "",
           date_created: issue.created_at,
           date_last_modified: issue.updated_at,
         }));
🤖 Prompt for AI Agents
In nango-integrations/github/syncs/fetchIssues.ts around lines 49 to 61 the
mapping assumes issue.user and issue.body are non-null which can throw for
deleted/ghost users or issues without a body; update the mapping to safely
handle nullables by using optional chaining and sensible fallbacks (e.g.,
issue.user?.login ?? null or 'ghost', issue.user?.id ?? null) and defaulting
issue.body to '' or null to match your GithubIssue type, and if needed adjust
the GithubIssue type to accept nullable author/author_id/body so the compiler
reflects these safe values.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants