Skip to content

Conversation

@sohan2410
Copy link

@sohan2410 sohan2410 commented Dec 4, 2025

Describe your changes

  • Added user_fields for zendesk sync users

Issue ticket number and link

Checklist before requesting a review (skip if just adding/editing APIs & templates)

  • I added tests, otherwise the reason is:
  • External API requests have retries
  • Pagination is used where appropriate
  • The built in nango.paginate call is used instead of a while (true) loop
  • Third party requests are NOT parallelized (this can cause issues with rate limits)
  • If a sync requires metadata the nango.yaml has auto_start: false
  • If the sync is a full sync then track_deletes: true is set
  • I followed the best practices and guidelines from the Writing Integration Scripts doc

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 4, 2025

Note

.coderabbit.yaml has unrecognized properties

CodeRabbit is using all valid settings from your configuration. Unrecognized properties (listed below) have been ignored and may indicate typos or deprecated fields that can be removed.

⚠️ Parsing warnings (1)
Validation error: Unrecognized key(s) in object: 'auto_resolve_threads'
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Walkthrough

Adds an optional user_fields property across the Zendesk integration: ZendeskUser.user_fields was made optional, the Zod User schema gained an optional user_fields record, the Zendesk→internal user mapping now preserves user_fields, mocks for batchSave users were updated to include user_fields, and generated Nango/internal JSON schemas were updated to include user_fields (and several $comment generator-version strings changed). No control-flow logic or API signatures were otherwise modified.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Heterogeneous but small changes across types, schema, mapping, mocks, and generated JSON.
  • Areas to check:
    • integrations/zendesk/types.ts — callers that assume user_fields is present may need guards for undefined.
    • integrations/zendesk/models.ts — Zod schema shape and downstream validation/parse sites.
    • integrations/zendesk/syncs/users.ts — mapping correctness for null/undefined user_fields.
    • integrations/zendesk/mocks/users/User/batchSave.json — test/fixture expectations.
    • integrations/.nango/schema.json and internal/flows.zero.json — review added user_fields schema and $comment version changes for generated-schema consumers.

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Description check ❓ Inconclusive The description is minimal but covers the primary change. However, it lacks detail about the scope of modifications, does not explain why user_fields were added, and leaves all checklist items unchecked without explanations. Expand the description to explain the rationale for adding user_fields, clarify whether tests were added, and address unchecked checklist items with explanations or confirmations where applicable.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding user_fields to Zendesk user sync data. It is concise, clear, and directly reflects the changeset across multiple files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

@sohan2410
Copy link
Author

@khaliqgant to review

lastName: lastName || '',
email: zUser.email
email: zUser.email,
user_fields: zUser.user_fields
Copy link
Member

Choose a reason for hiding this comment

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

Thanks! You need to add this user_fields property and its shape to the User object in the models

Copy link
Member

@khaliqgant khaliqgant left a comment

Choose a reason for hiding this comment

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

Changes requested inline

Copy link
Contributor

@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: 0

🧹 Nitpick comments (1)
integrations/zendesk/models.ts (1)

24-30: Clarify user_fields semantics; current Zod type may be stricter than Zendesk’s payloads

The addition looks consistent with the rest of the model, but a couple of details are worth double‑checking:

  • Zendesk’s user_fields is a generic object whose values can be strings, dates, numbers, booleans, or null, and the field itself is not mandatory on the user resource. (developer.zendesk.com)
  • Here it’s required and constrained to record<string, string>. That’s fine if the mapper normalizes everything to strings and always provides at least {}; otherwise you risk Zod output validation failures when a custom field is non‑string or user_fields is missing.

If the intention is to mirror Zendesk’s raw data more closely, consider relaxing the type and/or making it optional:

 export const User = z.object({
   id: z.string(),
   firstName: z.string(),
   lastName: z.string(),
   email: z.string(),
-  user_fields: z.record(z.string(), z.string())
+  // Map of Zendesk custom user field key -> value.
+  // If you don't normalize values to strings in the mapper,
+  // allow the raw value types here.
+  user_fields: z
+    .record(z.string(), z.union([z.string(), z.number(), z.boolean(), z.null()]))
+    .optional()
 });

If you do want the canonical User shape to expose only string values, I’d keep z.record(z.string(), z.string()) but ensure the mapper explicitly coerces every value to string and always supplies {} rather than undefined, and optionally add a short JSDoc comment describing that contract for integrators. Based on learnings, this keeps models.ts as the user-facing layer while raw Zendesk response types live in types.ts.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e158708 and 9491640.

📒 Files selected for processing (1)
  • integrations/zendesk/models.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/typescript-development-guidelines-shortcuts.mdc)

**/*.{ts,tsx}: Classes must use PascalCase naming convention
Variables, functions, and methods must use camelCase naming convention
Files and directories must use kebab-case naming convention
Use descriptive names for functions, combining verbs and nouns (e.g., getUserData)
Prefer arrow functions for simple operations
Use default parameters and object destructuring in functions
Document all code (classes, functions, methods, fields, types, interfaces) with JSDoc using only TypeDoc compatible tags
When writing JSDocs, only use TypeDoc compatible tags
For any new types, prefer to create a Zod schema and a Zod inference type for the created schema
Create custom types/interfaces for complex structures
Use 'readonly' for immutable properties
If an import is only used as a type in the file, use 'import type' instead of 'import'
Utilize Lodash, 'Promise.all()', and other standard techniques to optimize performance when working with large datasets
Always write JSDocs for all code: classes, functions, methods, fields, types, interfaces
Use strong typing and avoid 'any'
Ensure proper typing
Review naming conventions

Files:

  • integrations/zendesk/models.ts
**/*.{ts,tsx,env}

📄 CodeRabbit inference engine (.cursor/rules/typescript-development-guidelines-shortcuts.mdc)

Constants and environment variables must use UPPERCASE naming convention

Files:

  • integrations/zendesk/models.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/nango-script-best-practices.mdc)

**/*.ts: In full syncs (syncType: 'full'), include await nango.deleteRecordsFromPreviousExecutions('ModelName') as the last line in exec
If a sync requires metadata, set autoStart: false and define metadata as a Zod schema in the sync configuration
Document scopes in sync/action configuration (scopes: [...] in createSync or createAction)
In Zod models, mark optional properties using .optional()
For enum values in models, use z.enum([...])
Keep endpoint definitions concise and avoid redundant provider/version details in path
Use comments to explain logic and link to external API documentation
Add a comment with the external endpoint URL above each API request
Avoid mutating function arguments; prefer returning new values
ProxyConfiguration.endpoint should be a path relative to the provider base_url from providers.yaml
Import user-facing types from the models file instead of redefining them
Include .js extension for non-type imports; omit .js for type-only imports
Do not define interfaces mirroring Zod models; import the generated types from models instead
Set retries: 10 for sync proxy calls by default
Set retries: 3 for action proxy calls by default
Use await nango.log for logging; avoid console.log
Use the params property instead of appending query params to endpoint URLs
Prefer built-in nango.paginate for pagination when available
Type all requests with ProxyConfiguration
Add an API documentation link as a comment immediately above each endpoint in ProxyConfiguration
Validate script inputs and outputs with Zod
Validate and normalize date inputs using new Date; accept flexible formats and convert to provider expectations
Use nango.zodValidateInput helper for input validation
Define syncs using createSync with inline configuration
Always paginate to retrieve all records in syncs
Avoid parallelizing requests in syncs to preserve retries and rate limits
Do not wrap sync exec in try-catch; Nango manages error reporting
Batch save records early and frequently (e.g., 1...

Files:

  • integrations/zendesk/models.ts
integrations/**/**.ts

⚙️ CodeRabbit configuration file

integrations/**/**.ts: - Use TypeScript best practices and ensure typings are strictly defined.

  • Use comments to explain logic and link to external API documentation.
  • Place endpoint URLs as comments above API requests.
  • Avoid modifying arguments and prefer returning new values.
  • Create a types.ts file containing typed third-party API responses.
  • Proxy calls should use retries (default: 10).
  • Use await nango.log() instead of console.log for logging.
  • Use the params property in proxy calls instead of appending params onto the endpoint.
  • Use nango.paginate wherever possible for pagination.
  • Always use ProxyConfiguration for proxy request configurations.
  • Validate inputs/outputs using zod.
  • Ensure date inputs are valid and converted using new Date() to the provider's expected format.

Syncs

  • Use createSync() to define sync configuration inline.
  • The exec function must be the default export and placed at the top.
  • Always paginate requests to ensure all records are retrieved.
  • Avoid parallel requests to maintain the retry policy and prevent rate limits.
  • Mapping logic should be in a dedicated function.
  • Shared mapping logic should be stored in a mappers directory.
  • Mapper files should follow the mappers/to-{entity}.ts naming convention.
  • Avoid type casting and rely on TypeScript's type checking.
  • If the sync is incremental, use nango.lastSyncDate.

Actions

  • Use createAction() to define action configuration inline.
  • The exec function must be the default export and placed at the top.
  • Use ActionError only for specific error messages, otherwise rely on script failure.

Example:

throw new nango.ActionError<ActionErrorResponse>({
  message: 'Missing some parameter that will prevent the action from successfully running'
});

TypeScript Development Guidelines

Syncs

  • Use createSync() to define syncs with inline configuration
  • Always paginate requests to retrieve all records
  • Avoid parallel...

Files:

  • integrations/zendesk/models.ts
🧠 Learnings (2)
📚 Learning: 2025-09-29T10:08:50.360Z
Learnt from: CR
Repo: NangoHQ/integration-templates PR: 0
File: .cursor/rules/nango-script-best-practices.mdc:0-0
Timestamp: 2025-09-29T10:08:50.360Z
Learning: Applies to **/types.ts : Add a types.ts file for raw third-party API response types, prefixed with the integration name (e.g., GoogleUserResponse)

Applied to files:

  • integrations/zendesk/models.ts
📚 Learning: 2025-09-29T10:08:50.360Z
Learnt from: CR
Repo: NangoHQ/integration-templates PR: 0
File: .cursor/rules/nango-script-best-practices.mdc:0-0
Timestamp: 2025-09-29T10:08:50.360Z
Learning: Applies to **/*.ts : Import user-facing types from the models file instead of redefining them

Applied to files:

  • integrations/zendesk/models.ts

@sohan2410 sohan2410 requested a review from khaliqgant December 5, 2025 22:38
@sohan2410
Copy link
Author

@khaliqgant to review

Copy link
Contributor

@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: 1

🧹 Nitpick comments (2)
integrations/zendesk/types.ts (1)

233-233: Prefer unknown over any for type safety.

The user_fields property uses any, which disables type checking. Using unknown would maintain type safety while still allowing dynamic fields.

Apply this diff:

-  user_fields?: Record<string, any>;
+  user_fields?: Record<string, unknown>;
integrations/zendesk/models.ts (1)

28-29: Consider z.unknown() instead of z.any() for better type safety.

The user_fields property uses z.any() for values, which bypasses type checking. Using z.unknown() would provide better type safety while still allowing dynamic fields from the API.

Apply this diff to use z.unknown():

   email: z.string(),
-  user_fields: z.record(z.string(), z.any()).optional()
+  user_fields: z.record(z.string(), z.unknown()).optional()

Additionally, verify the actual structure of user_fields in the Zendesk API documentation:

What is the structure of user_fields in the Zendesk Users API response?
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a2544b9 and 27fc649.

📒 Files selected for processing (4)
  • integrations/.nango/schema.json (2 hunks)
  • integrations/zendesk/models.ts (1 hunks)
  • integrations/zendesk/types.ts (1 hunks)
  • internal/flows.zero.json (127 hunks)
✅ Files skipped from review due to trivial changes (1)
  • integrations/.nango/schema.json
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/typescript-development-guidelines-shortcuts.mdc)

**/*.{ts,tsx}: Classes must use PascalCase naming convention
Variables, functions, and methods must use camelCase naming convention
Files and directories must use kebab-case naming convention
Use descriptive names for functions, combining verbs and nouns (e.g., getUserData)
Prefer arrow functions for simple operations
Use default parameters and object destructuring in functions
Document all code (classes, functions, methods, fields, types, interfaces) with JSDoc using only TypeDoc compatible tags
When writing JSDocs, only use TypeDoc compatible tags
For any new types, prefer to create a Zod schema and a Zod inference type for the created schema
Create custom types/interfaces for complex structures
Use 'readonly' for immutable properties
If an import is only used as a type in the file, use 'import type' instead of 'import'
Utilize Lodash, 'Promise.all()', and other standard techniques to optimize performance when working with large datasets
Always write JSDocs for all code: classes, functions, methods, fields, types, interfaces
Use strong typing and avoid 'any'
Ensure proper typing
Review naming conventions

Files:

  • integrations/zendesk/types.ts
  • integrations/zendesk/models.ts
**/*.{ts,tsx,env}

📄 CodeRabbit inference engine (.cursor/rules/typescript-development-guidelines-shortcuts.mdc)

Constants and environment variables must use UPPERCASE naming convention

Files:

  • integrations/zendesk/types.ts
  • integrations/zendesk/models.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/nango-script-best-practices.mdc)

**/*.ts: In full syncs (syncType: 'full'), include await nango.deleteRecordsFromPreviousExecutions('ModelName') as the last line in exec
If a sync requires metadata, set autoStart: false and define metadata as a Zod schema in the sync configuration
Document scopes in sync/action configuration (scopes: [...] in createSync or createAction)
In Zod models, mark optional properties using .optional()
For enum values in models, use z.enum([...])
Keep endpoint definitions concise and avoid redundant provider/version details in path
Use comments to explain logic and link to external API documentation
Add a comment with the external endpoint URL above each API request
Avoid mutating function arguments; prefer returning new values
ProxyConfiguration.endpoint should be a path relative to the provider base_url from providers.yaml
Import user-facing types from the models file instead of redefining them
Include .js extension for non-type imports; omit .js for type-only imports
Do not define interfaces mirroring Zod models; import the generated types from models instead
Set retries: 10 for sync proxy calls by default
Set retries: 3 for action proxy calls by default
Use await nango.log for logging; avoid console.log
Use the params property instead of appending query params to endpoint URLs
Prefer built-in nango.paginate for pagination when available
Type all requests with ProxyConfiguration
Add an API documentation link as a comment immediately above each endpoint in ProxyConfiguration
Validate script inputs and outputs with Zod
Validate and normalize date inputs using new Date; accept flexible formats and convert to provider expectations
Use nango.zodValidateInput helper for input validation
Define syncs using createSync with inline configuration
Always paginate to retrieve all records in syncs
Avoid parallelizing requests in syncs to preserve retries and rate limits
Do not wrap sync exec in try-catch; Nango manages error reporting
Batch save records early and frequently (e.g., 1...

Files:

  • integrations/zendesk/types.ts
  • integrations/zendesk/models.ts
**/types.ts

📄 CodeRabbit inference engine (.cursor/rules/nango-script-best-practices.mdc)

**/types.ts: Add a types.ts file for raw third-party API response types, prefixed with the integration name (e.g., GoogleUserResponse)
Prefix raw API response type names with the integration name to avoid conflicts

Files:

  • integrations/zendesk/types.ts
integrations/**/**.ts

⚙️ CodeRabbit configuration file

integrations/**/**.ts: - Use TypeScript best practices and ensure typings are strictly defined.

  • Use comments to explain logic and link to external API documentation.
  • Place endpoint URLs as comments above API requests.
  • Avoid modifying arguments and prefer returning new values.
  • Create a types.ts file containing typed third-party API responses.
  • Proxy calls should use retries (default: 10).
  • Use await nango.log() instead of console.log for logging.
  • Use the params property in proxy calls instead of appending params onto the endpoint.
  • Use nango.paginate wherever possible for pagination.
  • Always use ProxyConfiguration for proxy request configurations.
  • Validate inputs/outputs using zod.
  • Ensure date inputs are valid and converted using new Date() to the provider's expected format.

Syncs

  • Use createSync() to define sync configuration inline.
  • The exec function must be the default export and placed at the top.
  • Always paginate requests to ensure all records are retrieved.
  • Avoid parallel requests to maintain the retry policy and prevent rate limits.
  • Mapping logic should be in a dedicated function.
  • Shared mapping logic should be stored in a mappers directory.
  • Mapper files should follow the mappers/to-{entity}.ts naming convention.
  • Avoid type casting and rely on TypeScript's type checking.
  • If the sync is incremental, use nango.lastSyncDate.

Actions

  • Use createAction() to define action configuration inline.
  • The exec function must be the default export and placed at the top.
  • Use ActionError only for specific error messages, otherwise rely on script failure.

Example:

throw new nango.ActionError<ActionErrorResponse>({
  message: 'Missing some parameter that will prevent the action from successfully running'
});

TypeScript Development Guidelines

Syncs

  • Use createSync() to define syncs with inline configuration
  • Always paginate requests to retrieve all records
  • Avoid parallel...

Files:

  • integrations/zendesk/types.ts
  • integrations/zendesk/models.ts
🔇 Additional comments (1)
internal/flows.zero.json (1)

92758-92768: Verify the schema permissiveness for user_fields.

The user_fields property uses an anyOf pattern with {} and {"not": {}}, which is overly permissive and allows any value. Clarify whether this open-ended schema is intentional to accommodate arbitrary Zendesk user field data or if stricter validation is needed.

Confirm that test coverage has been added for this new field and that the feature has been validated end-to-end.

"jsonSchema": {
"$schema": "http://json-schema.org/draft-07/schema#",
"$comment": "This file was generated by Nango (v0.69.14)",
"$comment": "This file was generated by Nango (v0.68.1)",
Copy link
Contributor

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

🏁 Script executed:

git diff HEAD~1 internal/flows.zero.json | head -200

Repository: NangoHQ/integration-templates

Length of output: 202


Verify intentionality of bulk version downgrade across unrelated integrations.

This file change downgrades the Nango generator version from v0.69.14 to v0.68.1 across approximately 120+ integration templates (Algolia, Anrok, Asana, Ashby, Attio, Brex, and others). The PR title indicates a Zendesk-specific feature addition, creating a scope mismatch. Confirm whether this bulk regeneration with an older version is intentional or an unintended side-effect, and validate that it does not introduce regressions or incompatibilities in unrelated integrations.

@sohan2410 sohan2410 force-pushed the sohan/add-user-field-zendesk branch from dba70fb to bc724bc Compare December 6, 2025 14:54
@sohan2410 sohan2410 force-pushed the sohan/add-user-field-zendesk branch from 4b87269 to 621a374 Compare December 6, 2025 15:03
@my-senior-dev-pr-review
Copy link

🤖 My Senior Dev

6 files reviewed • 4 critical • 2 need review

  • integrations/.nango/schema.json — The schema defines core data structures; adding 'user_fields' impacts validation and security.
  • integrations/zendesk/syncs/users.ts — Critical sync logic is modified to handle 'user_fields', which could affect data integrity if handled incorrectly.

View full analysis →

Copy link
Contributor

@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: 1

🧹 Nitpick comments (1)
integrations/zendesk/models.ts (1)

28-29: Optional user_fields on User schema is consistent; consider a shared JSON type later

Adding user_fields: z.record(z.string(), z.any()).optional() lines up with how other flexible metadata blobs are modeled here and with the ZendeskUser.user_fields shape. If you keep extending usage of these arbitrary field maps, it may be worth introducing a shared JSON-like type (e.g. type JsonValue = string | number | boolean | null | JsonValue[] | { [k: string]: JsonValue }) and using Record<string, JsonValue> / z.record(z.string(), z.unknown()) instead of any in a follow-up to strengthen typing, but this change itself looks fine as-is.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9127408 and c4d11b9.

📒 Files selected for processing (3)
  • integrations/.nango/schema.json (1 hunks)
  • integrations/zendesk/models.ts (1 hunks)
  • integrations/zendesk/types.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/typescript-development-guidelines-shortcuts.mdc)

**/*.{ts,tsx}: Classes must use PascalCase naming convention
Variables, functions, and methods must use camelCase naming convention
Files and directories must use kebab-case naming convention
Use descriptive names for functions, combining verbs and nouns (e.g., getUserData)
Prefer arrow functions for simple operations
Use default parameters and object destructuring in functions
Document all code (classes, functions, methods, fields, types, interfaces) with JSDoc using only TypeDoc compatible tags
When writing JSDocs, only use TypeDoc compatible tags
For any new types, prefer to create a Zod schema and a Zod inference type for the created schema
Create custom types/interfaces for complex structures
Use 'readonly' for immutable properties
If an import is only used as a type in the file, use 'import type' instead of 'import'
Utilize Lodash, 'Promise.all()', and other standard techniques to optimize performance when working with large datasets
Always write JSDocs for all code: classes, functions, methods, fields, types, interfaces
Use strong typing and avoid 'any'
Ensure proper typing
Review naming conventions

Files:

  • integrations/zendesk/models.ts
  • integrations/zendesk/types.ts
**/*.{ts,tsx,env}

📄 CodeRabbit inference engine (.cursor/rules/typescript-development-guidelines-shortcuts.mdc)

Constants and environment variables must use UPPERCASE naming convention

Files:

  • integrations/zendesk/models.ts
  • integrations/zendesk/types.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/nango-script-best-practices.mdc)

**/*.ts: In full syncs (syncType: 'full'), include await nango.deleteRecordsFromPreviousExecutions('ModelName') as the last line in exec
If a sync requires metadata, set autoStart: false and define metadata as a Zod schema in the sync configuration
Document scopes in sync/action configuration (scopes: [...] in createSync or createAction)
In Zod models, mark optional properties using .optional()
For enum values in models, use z.enum([...])
Keep endpoint definitions concise and avoid redundant provider/version details in path
Use comments to explain logic and link to external API documentation
Add a comment with the external endpoint URL above each API request
Avoid mutating function arguments; prefer returning new values
ProxyConfiguration.endpoint should be a path relative to the provider base_url from providers.yaml
Import user-facing types from the models file instead of redefining them
Include .js extension for non-type imports; omit .js for type-only imports
Do not define interfaces mirroring Zod models; import the generated types from models instead
Set retries: 10 for sync proxy calls by default
Set retries: 3 for action proxy calls by default
Use await nango.log for logging; avoid console.log
Use the params property instead of appending query params to endpoint URLs
Prefer built-in nango.paginate for pagination when available
Type all requests with ProxyConfiguration
Add an API documentation link as a comment immediately above each endpoint in ProxyConfiguration
Validate script inputs and outputs with Zod
Validate and normalize date inputs using new Date; accept flexible formats and convert to provider expectations
Use nango.zodValidateInput helper for input validation
Define syncs using createSync with inline configuration
Always paginate to retrieve all records in syncs
Avoid parallelizing requests in syncs to preserve retries and rate limits
Do not wrap sync exec in try-catch; Nango manages error reporting
Batch save records early and frequently (e.g., 1...

Files:

  • integrations/zendesk/models.ts
  • integrations/zendesk/types.ts
integrations/**/**.ts

⚙️ CodeRabbit configuration file

integrations/**/**.ts: - Use TypeScript best practices and ensure typings are strictly defined.

  • Use comments to explain logic and link to external API documentation.
  • Place endpoint URLs as comments above API requests.
  • Avoid modifying arguments and prefer returning new values.
  • Create a types.ts file containing typed third-party API responses.
  • Proxy calls should use retries (default: 10).
  • Use await nango.log() instead of console.log for logging.
  • Use the params property in proxy calls instead of appending params onto the endpoint.
  • Use nango.paginate wherever possible for pagination.
  • Always use ProxyConfiguration for proxy request configurations.
  • Validate inputs/outputs using zod.
  • Ensure date inputs are valid and converted using new Date() to the provider's expected format.

Syncs

  • Use createSync() to define sync configuration inline.
  • The exec function must be the default export and placed at the top.
  • Always paginate requests to ensure all records are retrieved.
  • Avoid parallel requests to maintain the retry policy and prevent rate limits.
  • Mapping logic should be in a dedicated function.
  • Shared mapping logic should be stored in a mappers directory.
  • Mapper files should follow the mappers/to-{entity}.ts naming convention.
  • Avoid type casting and rely on TypeScript's type checking.
  • If the sync is incremental, use nango.lastSyncDate.

Actions

  • Use createAction() to define action configuration inline.
  • The exec function must be the default export and placed at the top.
  • Use ActionError only for specific error messages, otherwise rely on script failure.

Example:

throw new nango.ActionError<ActionErrorResponse>({
  message: 'Missing some parameter that will prevent the action from successfully running'
});

TypeScript Development Guidelines

Syncs

  • Use createSync() to define syncs with inline configuration
  • Always paginate requests to retrieve all records
  • Avoid parallel...

Files:

  • integrations/zendesk/models.ts
  • integrations/zendesk/types.ts
**/types.ts

📄 CodeRabbit inference engine (.cursor/rules/nango-script-best-practices.mdc)

**/types.ts: Add a types.ts file for raw third-party API response types, prefixed with the integration name (e.g., GoogleUserResponse)
Prefix raw API response type names with the integration name to avoid conflicts

Files:

  • integrations/zendesk/types.ts
🧠 Learnings (1)
📚 Learning: 2025-09-29T10:08:50.360Z
Learnt from: CR
Repo: NangoHQ/integration-templates PR: 0
File: .cursor/rules/nango-script-best-practices.mdc:0-0
Timestamp: 2025-09-29T10:08:50.360Z
Learning: Applies to **/*.ts : Import user-facing types from the models file instead of redefining them

Applied to files:

  • integrations/zendesk/models.ts
🔇 Additional comments (1)
integrations/zendesk/types.ts (1)

233-233: Making ZendeskUser.user_fields optional matches real payloads and the new model

Changing to user_fields?: Record<string, any>; aligns with Zendesk users that may not have custom fields and keeps the shape consistent with the User Zod model; no further changes needed here for this PR.

Comment on lines +58525 to 58535
"user_fields": {
"type": "object",
"additionalProperties": {
"anyOf": [
{},
{
"not": {}
}
]
}
}
Copy link
Contributor

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

🏁 Script executed:

# First, check if the file exists and get context around the specified lines
head -n 58540 integrations/.nango/schema.json | tail -n 20

Repository: NangoHQ/integration-templates

Length of output: 202


🏁 Script executed:

# Check the file header to verify if it's auto-generated
head -n 10 integrations/.nango/schema.json

Repository: NangoHQ/integration-templates

Length of output: 202


🏁 Script executed:

# Search for TypeScript models.ts to find user_fields definition
find . -name "models.ts" -type f | head -5

Repository: NangoHQ/integration-templates

Length of output: 202


🌐 Web query:

JSON Schema empty schema {} vs {"not": {}} anyOf semantics

💡 Result:

Short answer

  • {} (empty object schema) places no constraints — every instance validates. [1][2]
  • {"not": {}} negates the empty schema (which always passes), so it always fails (no instance validates). [2][3]

anyOf behavior

  • anyOf succeeds if at least one subschema validates.
    • anyOf: [ {} ] accepts every instance (because {} accepts everything). [1][2]
    • anyOf: [ { "not": {} } ] rejects every instance (because that single subschema always fails). [2][3]
  • Mixed examples:
    • anyOf: [ { "type": "string" }, {} ] is equivalent to {} (accepts all instances).
    • anyOf: [ { "type": "string" }, { "not": {} } ] is equivalent to { "type": "string" } (the always-failing subschema has no effect).

Notes / references

  • Formal spec: empty schema = no properties = accepts all; boolean schemas true/false semantics. [1]
  • Explanation of "not" (negation) and examples showing {"not": {}} is always false. [2][3]

Sources
[1] JSON Schema specification (empty schema / boolean schemas).
[2] JSON Schema blog / tutorial (empty schema and "not, empty object" example).
[3] learnjsonschema: "not" keyword explanation.


🌐 Web query:

Nango v0.69.14 schema generation auto-generated files

💡 Result:

Short answer: In Nango (including v0.69.14) the CLI's schema generation creates two auto-generated files under the .nango directory: .nango/schema.ts (TypeScript models) and .nango/schema.json (JSON Schema used for validation). These files are safe to version with your repo and are used by the CLI/runtime for automatic input/output validation. [1][2]

Sources

  • Nango docs — Data validation (explains .nango/schema.ts and .nango/schema.json). [1]
  • Nango GitHub — release v0.69.14 (release exists). [2]

Simplify the contradictory JSON schema pattern for user_fields.

The anyOf pattern combining {} and {"not": {}} is semantically invalid. The empty schema {} matches any value, while {"not": {}} matches nothing (since it negates the always-permissive empty schema). This makes the anyOf condition unsatisfiable.

Simplify this to:

"user_fields": {
  "type": "object",
  "additionalProperties": {}
}

Or, if you need to be explicit about allowing any type within the object properties, use true:

"user_fields": {
  "type": "object",
  "additionalProperties": true
}

This file is auto-generated by Nango v0.69.14. The contradictory schema pattern indicates a bug in Nango's schema generation logic that should be reported or fixed upstream.

🤖 Prompt for AI Agents
In integrations/.nango/schema.json around lines 58525 to 58535, the user_fields
schema uses an invalid anyOf combining "{}" (matches everything) and '{"not":
{}}' (matches nothing), making the condition contradictory; replace the anyOf
block with a simple additionalProperties schema that allows any value — either
an empty object for permissive properties or the boolean true to explicitly
allow any type — to produce a valid, non-contradictory JSON Schema.

Copy link
Member

@khaliqgant khaliqgant left a comment

Choose a reason for hiding this comment

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

Thank you for your contribution! The only thing missing is a version bump of this sync so it can be displayed in the Nango UI as an upgraded template and users can receive this update

@khaliqgant
Copy link
Member

Finished this up in #431 to close the loop on this.

@khaliqgant khaliqgant closed this Jan 20, 2026
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