Conversation
|
Note
|
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Description check | The description is entirely empty—all required sections lack content, and all checklist items remain unchecked. | Fill in the 'Describe your changes' and 'Issue ticket number and link' sections with substantive information, and verify or check relevant checklist items based on implementation details. |
✅ Passed checks (2 passed)
| Check name | Status | Explanation |
|---|---|---|
| Title check | ✅ Passed | The title clearly summarizes the main change: adding a new HubSpot action to fetch companies by domain. |
| 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
- Commit unit tests in branch
bastien/hubspot/get-company-by-domain
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.
Comment @coderabbitai help to get the list of available commands and usage tips.
🤖 My Senior Dev11 files reviewed • 3 need attention
💬 Try: 📖 All commands & personasYou can interact with me by mentioning In PR comments or on any line of code:
Slash commands:
AI Personas (mention to get their perspective):
For the best experience, view this PR on myseniordev.com — includes AI chat, file annotations, and interactive reviews. |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
integrations/.nango/nango.json (1)
5805-5825: Align HubSpot scopes (and optionally path naming) with existing actionsThe action wiring looks structurally correct, but two small consistency points:
- Other HubSpot company read flows (e.g., the
companiessync) list both"crm.objects.companies.read"and"oauth"inscopes. Here you only include the granular scope. For consistency with the rest of the HubSpot config and to better document required permissions, consider adding"oauth"as well.- Nit: most company endpoints here use plural
"/companies"while this action uses"/company/search". If there isn’t a strong reason to diverge, you might want to align the path naming with the existing pattern for easier discoverability.integrations/hubspot/tests/hubspot-get-company-by-domain.test.ts (1)
1-19: Happy-path test is solid; consider a not-found case laterThis test correctly exercises the action against the Nango mock harness and validates the expected output. If you want stronger coverage later, you could add a second test for the “no company found” scenario.
integrations/.nango/schema.ts (1)
5417-5425: New HubSpot get-company-by-domain action types look correct; consider naming consistencyThe input/output shapes are minimal and coherent (
domainin,name/domain/created_atout) and match the general HubSpot action patterns in this file.If you want tighter internal consistency with other HubSpot company models here (
Company,ActionOutput_hubspot_createcompany, etc.), consider renamingcreated_attocreated_dateunless you explicitly prefer mirroring HubSpot’screatedAtfield.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
integrations/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (10)
integrations/.nango/nango.json(1 hunks)integrations/.nango/schema.json(2 hunks)integrations/.nango/schema.ts(2 hunks)integrations/hubspot/actions/get-company-by-domain.ts(1 hunks)integrations/hubspot/mocks/get-company-by-domain/input.json(1 hunks)integrations/hubspot/mocks/get-company-by-domain/output.json(1 hunks)integrations/hubspot/mocks/nango/post/proxy/crm/v3/objects/companies/search/get-company-by-domain/21ca0bdc7ba4b2bed957f428e1b3ceb43e07bced.json(1 hunks)integrations/hubspot/tests/hubspot-get-company-by-domain.test.ts(1 hunks)integrations/index.ts(1 hunks)integrations/package.json(1 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{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/hubspot/actions/get-company-by-domain.tsintegrations/hubspot/tests/hubspot-get-company-by-domain.test.tsintegrations/index.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/hubspot/actions/get-company-by-domain.tsintegrations/hubspot/tests/hubspot-get-company-by-domain.test.tsintegrations/index.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/hubspot/actions/get-company-by-domain.tsintegrations/hubspot/tests/hubspot-get-company-by-domain.test.tsintegrations/index.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.tsfile containing typed third-party API responses.- Proxy calls should use retries (default:
10).- Use
await nango.log()instead ofconsole.logfor logging.- Use the
paramsproperty in proxy calls instead of appending params onto the endpoint.- Use
nango.paginatewherever possible for pagination.- Always use
ProxyConfigurationfor 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
execfunction 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
mappersdirectory.- Mapper files should follow the
mappers/to-{entity}.tsnaming 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
execfunction must be the default export and placed at the top.- Use
ActionErroronly 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/hubspot/actions/get-company-by-domain.tsintegrations/hubspot/tests/hubspot-get-company-by-domain.test.tsintegrations/index.ts
**/*.{test,spec}.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/typescript-development-guidelines-shortcuts.mdc)
Confirm test coverage
Files:
integrations/hubspot/tests/hubspot-get-company-by-domain.test.ts
**/index.ts
📄 CodeRabbit inference engine (.cursor/rules/nango-script-best-practices.mdc)
When adding a new integration, do not remove unrelated entries in index.ts
Files:
integrations/index.ts
integrations/**/index.ts
⚙️ CodeRabbit configuration file
integrations/**/index.ts: - UsecreateSync()andcreateAction()for inline configuration.
If
syncType: 'full', then the sync should also haveawait nango.deleteRecordsFromPreviousExecutionsas the last line in the sync with the model name as the argument.If the sync requires metadata, set
autoStart: falseand document the metadata as a Zod schema.Scopes should be explicitly documented in the
scopesarray.Use Zod schemas for input, output, and metadata validation.
Define models using Zod schemas in
models.tsfiles.If
syncType: 'full', then the sync should also haveawait nango.deleteRecordsFromPreviousExecutions("ModelName")as the last line in the sync codeIf the sync requires metadata, then the sync should be set to
autoStart: false. The metadata should be defined as a Zod schema in the sync configurationScopes should be documented in the sync/action configuration
For optional properties in models, use the
.optional()method in Zod schemasEndpoints should be concise and simple, not necessarily reflecting the exact third-party API path
Model names and endpoint paths should not be duplicated within an integration
When adding a new integration, take care to not remove unrelated entries in the index.ts file
For enum values in models, use Zod's
.enum()method
Files:
integrations/index.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 **/index.ts : When adding a new integration, do not remove unrelated entries in index.ts
Applied to files:
integrations/hubspot/tests/hubspot-get-company-by-domain.test.tsintegrations/index.ts
🪛 GitHub Actions: Lint
integrations/hubspot/actions/get-company-by-domain.ts
[error] 7-7: prettier/prettier: Delete ⏎········ (unnecessary newline). Please format the file.
🪛 GitHub Check: lint-code
integrations/hubspot/actions/get-company-by-domain.ts
[failure] 7-7:
Delete ⏎········
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: tests (ubuntu-latest, 22.x)
- GitHub Check: tests (ubuntu-latest, 20.x)
🔇 Additional comments (10)
integrations/hubspot/mocks/get-company-by-domain/input.json (1)
1-3: Input mock is valid.The JSON structure is correct and provides a realistic test input with the domain parameter.
integrations/hubspot/mocks/get-company-by-domain/output.json (2)
1-5: Output mock is valid.The JSON structure is well-formed. However, verify that the output fields (particularly
created_at) match the schema definition in your action implementation and the HubSpot CRM v3 search API response structure.
1-5: Note: PR checklist shows critical items unchecked.Your PR checklist indicates that "I added tests" and other best practices are unchecked. Ensure that:
- Unit tests exist and pass for this action
- External API calls include proper retries
- All other checklist items are addressed before merging
integrations/hubspot/mocks/nango/post/proxy/crm/v3/objects/companies/search/get-company-by-domain/21ca0bdc7ba4b2bed957f428e1b3ceb43e07bced.json (1)
1-50: Mock payload matches HubSpot search usageThe mock request/response shape (filters on
domain,properties: ['name','domain','createdate'], and top-levelcreatedAt) aligns with the new action’s expectations and should work well for tests.integrations/index.ts (1)
329-329: HubSpot action import wiring looks correctThe new
get-company-by-domainaction is registered consistently with other HubSpot actions, and no unrelated entries were touched.integrations/package.json (1)
15-21: Clarify nango downgrade to 0.69.14The root package.json pins
nangoto^0.69.18, but integrations/package.json pins it to0.69.14. Confirm this downgrade is intentional and doesn't drop needed features or bugfixes for your workflow.integrations/.nango/schema.ts (1)
2-2: Header version bump is fineThe generator version update to
v0.69.14is consistent with an auto-regenerated schema and has no functional impact. Just keep it in sync with the Nango version in package.json.integrations/.nango/schema.json (3)
26793-26830: Clarify schema design for nullable required fields.The output schema marks
nameandcreated_atas both required and nullable (type: ["string", "null"]). This is technically valid but semantically ambiguous—does the action guarantee these fields will be present (possibly as null), or can they be omitted? Verify this design matches the handler implementation and API contract.
62677-62677: Explain the Nango version downgrade.The schema was generated with Nango v0.69.14, representing a downgrade from v0.69.17. Clarify the reason: Is there a regression in newer versions, or a compatibility issue with this action? This should be documented in the PR description.
26793-26830: Verify PR checklist completeness.The PR description shows all checklist items unchecked (tests, retries, pagination, metadata handling). Since this file is auto-generated, the actual implementation details—handler logic, error handling, retry configuration, and test coverage—aren't visible here. Please ensure the implementation files (
integrations/hubspot/actions/get-company-by-domain.tsand corresponding tests) meet the integration guidelines before merging.
| // Input schema | ||
| const GetCompanyByDomainInput = z.object({ | ||
| domain: z.string() | ||
| .describe('Company domain to search for. Example: "nango.dev"') | ||
| }); | ||
|
|
||
| // Output schema | ||
| const GetCompanyByDomainOutput = z.object({ | ||
| name: z.union([z.string(), z.null()]), | ||
| domain: z.string(), | ||
| created_at: z.union([z.string(), z.null()]) | ||
| }); | ||
|
|
||
| const action = createAction({ | ||
| description: 'Fetch a company by domain from HubSpot', | ||
| version: '1.0.0', | ||
|
|
||
| endpoint: { | ||
| method: 'POST', | ||
| path: '/company/search', | ||
| group: 'Companies' | ||
| }, | ||
|
|
||
| input: GetCompanyByDomainInput, | ||
| output: GetCompanyByDomainOutput, | ||
| scopes: ['crm.objects.companies.read'], | ||
|
|
||
| exec: async (nango, input): Promise<z.infer<typeof GetCompanyByDomainOutput>> => { | ||
| const config: ProxyConfiguration = { | ||
| // https://developers.hubspot.com/docs/api/crm/search | ||
| endpoint: 'crm/v3/objects/companies/search', | ||
| data: { | ||
| filterGroups: [ | ||
| { | ||
| filters: [ | ||
| { | ||
| propertyName: 'domain', | ||
| operator: 'EQ', | ||
| value: input.domain | ||
| } | ||
| ] | ||
| } | ||
| ], | ||
| properties: ['name', 'domain', 'createdate'] | ||
| }, | ||
| retries: 3 | ||
| }; | ||
|
|
||
| const response = await nango.post(config); | ||
|
|
||
| // Extract first result from search | ||
| const company = response.data.results?.[0]; | ||
|
|
||
| if (!company) { | ||
| throw new Error(`No company found with domain: ${input.domain}`); | ||
| } | ||
|
|
||
| return { | ||
| name: company.properties?.name ?? null, | ||
| domain: company.properties?.domain, | ||
| created_at: company.createdAt ?? null | ||
| }; | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# First, locate the file and check its current state
find . -name "get-company-by-domain.ts" -type f 2>/dev/null | head -20Repository: NangoHQ/integration-templates
Length of output: 128
🏁 Script executed:
#!/bin/bash
# List HubSpot integration structure
ls -la integrations/hubspot/actions/ 2>/dev/null | head -20Repository: NangoHQ/integration-templates
Length of output: 1325
🏁 Script executed:
#!/bin/bash
# Check if file exists and show its content
if [ -f "integrations/hubspot/actions/get-company-by-domain.ts" ]; then
wc -l "integrations/hubspot/actions/get-company-by-domain.ts"
echo "---FILE CONTENT---"
cat -n "integrations/hubspot/actions/get-company-by-domain.ts"
else
echo "File not found"
find . -path "*/hubspot/actions*" -type f 2>/dev/null | head -10
fiRepository: NangoHQ/integration-templates
Length of output: 2740
🏁 Script executed:
#!/bin/bash
# Check coding guidelines application for .ts files in integrations
rg "Document all code|JSDoc" . --type ts -B 2 -A 2 | head -30Repository: NangoHQ/integration-templates
Length of output: 55
🏁 Script executed:
#!/bin/bash
# Check for existing JSDoc patterns in other HubSpot actions
find integrations/hubspot/actions -name "*.ts" -type f 2>/dev/null | head -3 | xargs -I {} sh -c 'echo "=== {} ===" && head -30 {}'Repository: NangoHQ/integration-templates
Length of output: 3284
🏁 Script executed:
#!/bin/bash
# Check for nango.ActionError usage patterns in existing actions
rg "nango\.ActionError|throw new Error" integrations/hubspot/ -A 2 | head -40Repository: NangoHQ/integration-templates
Length of output: 2035
Replace generic Error with nango.ActionError and fix domain output typing
Two issues need fixing:
-
Use
nango.ActionErrorfor the "no company found" case
Line 59 uses a genericError, but all other HubSpot actions thrownango.ActionErrorfor actionable errors. Change to:- if (!company) { - throw new Error(`No company found with domain: ${input.domain}`); - } + if (!company) { + throw new nango.ActionError({ + message: `No company found with domain: ${input.domain}` + }); + }
-
Guarantee the
domainfield in the return object
Line 64 returnscompany.properties?.domain, which could beundefined. The Zod schema (line 14) requiresdomain: z.string(). Fallback to the input domain:- domain: company.properties?.domain, + domain: company.properties?.domain ?? input.domain,
🧰 Tools
🪛 GitHub Actions: Lint
[error] 7-7: prettier/prettier: Delete ⏎········ (unnecessary newline). Please format the file.
🪛 GitHub Check: lint-code
[failure] 7-7:
Delete ⏎········
🤖 Prompt for AI Agents
In integrations/hubspot/actions/get-company-by-domain.ts around lines 5-67,
replace the generic throw new Error(...) when no company is found with throw new
nango.ActionError(...) so the action uses the platform-specific error type, and
ensure the returned domain is always a string by returning
company.properties?.domain ?? input.domain (or otherwise coercing to
input.domain) so it matches the Zod schema's required string type.
| const GetCompanyByDomainOutput = z.object({ | ||
| name: z.union([z.string(), z.null()]), | ||
| domain: z.string(), | ||
| created_at: z.union([z.string(), z.null()]) |
There was a problem hiding this comment.
z.string().nullable() is more concise
| const company = response.data.results?.[0]; | ||
|
|
||
| if (!company) { | ||
| throw new Error(`No company found with domain: ${input.domain}`); |
There was a problem hiding this comment.
should it throw or return an empty result?
Describe your changes
Issue ticket number and link
Checklist before requesting a review (skip if just adding/editing APIs & templates)
retriesnango.paginatecall is used instead of awhile (true)loopnango.yamlhasauto_start: falsefullsync thentrack_deletes: trueis set