-
Notifications
You must be signed in to change notification settings - Fork 195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add integration with leadsquared #649 #671
Add integration with leadsquared #649 #671
Conversation
Qovery can create a Preview Environment for this PR.
This comment has been generated from Qovery AI 🤖.
|
|
WalkthroughWalkthroughThe integration with LeadSquared CRM introduces new services and mappers for managing contacts, deals, tasks, and engagements. Each service implements a corresponding interface, providing methods for adding and synchronizing data with LeadSquared. TypeScript types are defined to enhance type safety, while utility methods facilitate data transformation and API interaction. This comprehensive integration supports both reading and writing data, enriching the CRM capabilities significantly. Changes
Assessment against linked issues
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (invoked as PR comments)
Additionally, you can add CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 27
Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Files selected for processing (12)
- packages/api/src/crm/contact/services/leadsquared/index.ts (1 hunks)
- packages/api/src/crm/contact/services/leadsquared/mappers.ts (1 hunks)
- packages/api/src/crm/contact/services/leadsquared/types.ts (1 hunks)
- packages/api/src/crm/deal/services/leadsquared/index.ts (1 hunks)
- packages/api/src/crm/deal/services/leadsquared/mappers.ts (1 hunks)
- packages/api/src/crm/deal/services/leadsquared/types.ts (1 hunks)
- packages/api/src/crm/engagement/services/leadsquared/index.ts (1 hunks)
- packages/api/src/crm/engagement/services/leadsquared/mappers.ts (1 hunks)
- packages/api/src/crm/engagement/services/leadsquared/types.ts (1 hunks)
- packages/api/src/crm/task/services/leadsquared/index.ts (1 hunks)
- packages/api/src/crm/task/services/leadsquared/mappers.ts (1 hunks)
- packages/api/src/crm/task/services/leadsquared/types.ts (1 hunks)
Additional context used
Biome
packages/api/src/crm/task/services/leadsquared/index.ts
[error] 22-22: Template literals are preferred over string concatenation.
Unsafe fix: Use a template literal.
(lint/style/useTemplate)
[error] 66-66: The catch clause that only rethrows the original error is redundant.
These unnecessary catch clauses can be confusing. It is recommended to remove them.
(lint/complexity/noUselessCatch)
[error] 112-112: The catch clause that only rethrows the original error is redundant.
These unnecessary catch clauses can be confusing. It is recommended to remove them.
(lint/complexity/noUselessCatch)
packages/api/src/crm/deal/services/leadsquared/index.ts
[error] 23-23: Template literals are preferred over string concatenation.
Unsafe fix: Use a template literal.
(lint/style/useTemplate)
[error] 75-75: The catch clause that only rethrows the original error is redundant.
These unnecessary catch clauses can be confusing. It is recommended to remove them.
(lint/complexity/noUselessCatch)
[error] 114-114: The catch clause that only rethrows the original error is redundant.
These unnecessary catch clauses can be confusing. It is recommended to remove them.
(lint/complexity/noUselessCatch)
packages/api/src/crm/contact/services/leadsquared/index.ts
[error] 27-27: Template literals are preferred over string concatenation.
Unsafe fix: Use a template literal.
(lint/style/useTemplate)
[error] 81-81: The catch clause that only rethrows the original error is redundant.
These unnecessary catch clauses can be confusing. It is recommended to remove them.
(lint/complexity/noUselessCatch)
[error] 137-137: The catch clause that only rethrows the original error is redundant.
These unnecessary catch clauses can be confusing. It is recommended to remove them.
(lint/complexity/noUselessCatch)
packages/api/src/crm/contact/services/leadsquared/mappers.ts
[error] 44-44: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 112-112: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 123-123: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 129-129: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 135-135: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 141-141: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
packages/api/src/crm/engagement/services/leadsquared/index.ts
[error] 30-30: Template literals are preferred over string concatenation.
Unsafe fix: Use a template literal.
(lint/style/useTemplate)
[error] 71-71: The catch clause that only rethrows the original error is redundant.
These unnecessary catch clauses can be confusing. It is recommended to remove them.
(lint/complexity/noUselessCatch)
[error] 107-107: The catch clause that only rethrows the original error is redundant.
These unnecessary catch clauses can be confusing. It is recommended to remove them.
(lint/complexity/noUselessCatch)
[error] 150-150: The catch clause that only rethrows the original error is redundant.
These unnecessary catch clauses can be confusing. It is recommended to remove them.
(lint/complexity/noUselessCatch)
[error] 185-185: The catch clause that only rethrows the original error is redundant.
These unnecessary catch clauses can be confusing. It is recommended to remove them.
(lint/complexity/noUselessCatch)
[error] 226-226: The catch clause that only rethrows the original error is redundant.
These unnecessary catch clauses can be confusing. It is recommended to remove them.
(lint/complexity/noUselessCatch)
[error] 271-271: The catch clause that only rethrows the original error is redundant.
These unnecessary catch clauses can be confusing. It is recommended to remove them.
(lint/complexity/noUselessCatch)
[error] 294-294: The catch clause that only rethrows the original error is redundant.
These unnecessary catch clauses can be confusing. It is recommended to remove them.
(lint/complexity/noUselessCatch)
Additional comments not posted (33)
packages/api/src/crm/task/services/leadsquared/types.ts (4)
1-3
: LGTM!The
KeyValuePair
interface is well-defined and allows flexibility for key-value pairs.
5-38
: LGTM!The
LeadSquaredTask
interface is well-structured and uses string literals effectively for specific fields, enhancing type safety.
40-40
: LGTM!The
LeadSquaredTaskInput
type correctly usesPartial
to allow optional fields.
41-41
: LGTM!The
LeadSquaredTaskOutput
type, being identical toLeadSquaredTaskInput
, is consistent and flexible for handling outputs.packages/api/src/crm/deal/services/leadsquared/types.ts (4)
1-4
: LGTM!The
LeadDetail
type is well-defined and correctly typed.
6-9
: LGTM!The
Field
type is well-defined and correctly typed.
22-25
: LGTM!The
LeadSquaredDealInput
type is comprehensive and correctly typed.
27-51
: LGTM!The
LeadSquaredDealOutput
type is comprehensive and correctly typed.packages/api/src/crm/contact/services/leadsquared/types.ts (4)
1-96
: LGTM!The
LeadSquaredContact
type is comprehensive and well-documented with comments for field descriptions.
98-105
: LGTM!The
LeadSquaredContactResponse
type is well-defined and correctly typed.
107-108
: LGTM!The
LeadSquaredContactInput
type is comprehensive and correctly typed.
108-108
: LGTM!The
LeadSquaredContactOutput
type is comprehensive and correctly typed.packages/api/src/crm/engagement/services/leadsquared/types.ts (8)
1-3
: LGTM!The
KeyValuePair
interface is well-defined and allows flexibility for key-value pairs.
5-26
: LGTM!The
LeadSquaredEngagementCall
type is well-structured and uses string literals effectively for specific fields, enhancing type safety.
28-37
: LGTM!The
SenderType
andRecipientType
types are well-defined and enhance type safety with string literals.
39-61
: LGTM!The
LeadSquaredEngagementEmail
type is comprehensive and correctly typed.
63-65
: LGTM!The
LeadSquaredEngagementEmailInput
type is comprehensive and correctly typed.
65-65
: LGTM!The
LeadSquaredEngagementEmailOutput
type is comprehensive and correctly typed.
67-101
: LGTM!The
LeadSquaredEngagementMeeting
type is comprehensive and correctly typed.
102-115
: LGTM!The types for
LeadSquaredEngagementCallInput
,LeadSquaredEngagementMeetingInput
,LeadSquaredEngagementMeetingOutput
,LeadSquaredEngagementOutput
, andLeadSquaredEngagementInput
are comprehensive and correctly typed.packages/api/src/crm/deal/services/leadsquared/mappers.ts (3)
24-65
: LGTM!The
desunify
function correctly maps unified CRM deal input to LeadSquared-specific input.
67-88
: LGTM!The
unify
function correctly handles both single and multiple LeadSquared deal outputs.
90-145
: LGTM!The
mapSingleDealToUnified
function accurately maps LeadSquared deal output to unified CRM deal output, handling custom field mappings and stage ingestion.packages/api/src/crm/task/services/leadsquared/mappers.ts (3)
24-85
: LGTM!The
desunify
function correctly maps unified CRM task input to LeadSquared-specific input.
87-108
: LGTM!The
unify
function correctly handles both single and multiple LeadSquared task outputs.
110-177
: LGTM!The
mapSingleTaskToUnified
function accurately maps LeadSquared task output to unified CRM task output, handling custom field mappings and related entity associations.packages/api/src/crm/contact/services/leadsquared/mappers.ts (1)
96-175
: LGTM!The
mapSingleContactToUnified
function accurately maps LeadSquared contact output to unified CRM contact output, handling custom field mappings and contact details.Tools
Biome
[error] 112-112: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 123-123: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 129-129: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 135-135: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 141-141: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
packages/api/src/crm/engagement/services/leadsquared/mappers.ts (6)
22-32
: Constructor implementation looks good.The constructor correctly initializes dependencies and registers the mapper with the registry.
44-63
: Desunify method implementation looks good.The method correctly handles different engagement types and returns the appropriate LeadSquared-specific format.
65-119
: DesunifyEmail method implementation looks good.The method correctly transforms unified email engagement inputs into LeadSquared-specific format, including optional mappings and ID conversions.
121-187
: DesunifyMeeting method implementation looks good.The method correctly transforms unified meeting engagement inputs into LeadSquared-specific format, including optional mappings and ID conversions.
241-269
: Unify method implementation looks good.The method correctly handles different engagement types and returns the appropriate unified format.
271-363
: UnifyMeeting and UnifyEmail methods implementation looks good.Both methods correctly transform LeadSquared-specific outputs into a unified format, including optional mappings and ID conversions.
type Opportunity = { | ||
Filelds: Field[]; | ||
OpportunityEventCode: number; | ||
OpportunityNote?: string; | ||
OpportunityDateTime?: string; //date and time is in the yyyy-mm-dd hh:mm:ss format. | ||
OverwriteFields?: boolean; | ||
UpdateEmptyFields?: boolean; | ||
DoNotPostDuplicateActivity?: boolean; | ||
DoNotChangeOwner?: boolean; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix typo in property name.
The property Filelds
should be corrected to Fields
.
Fix the typo as follows:
- Filelds: Field[];
+ Fields: Field[];
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.
type Opportunity = { | |
Filelds: Field[]; | |
OpportunityEventCode: number; | |
OpportunityNote?: string; | |
OpportunityDateTime?: string; //date and time is in the yyyy-mm-dd hh:mm:ss format. | |
OverwriteFields?: boolean; | |
UpdateEmptyFields?: boolean; | |
DoNotPostDuplicateActivity?: boolean; | |
DoNotChangeOwner?: boolean; | |
}; | |
type Opportunity = { | |
Fields: Field[]; | |
OpportunityEventCode: number; | |
OpportunityNote?: string; | |
OpportunityDateTime?: string; //date and time is in the yyyy-mm-dd hh:mm:ss format. | |
OverwriteFields?: boolean; | |
UpdateEmptyFields?: boolean; | |
DoNotPostDuplicateActivity?: boolean; | |
DoNotChangeOwner?: boolean; | |
}; |
} catch (error) { | ||
throw error; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove redundant catch block.
The catch block that only rethrows the original error is unnecessary and can be removed.
Remove the catch block as follows:
- } catch (error) {
- throw error;
- }
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.
} catch (error) { | |
throw error; | |
} |
Tools
Biome
[error] 112-112: The catch clause that only rethrows the original error is redundant.
These unnecessary catch clauses can be confusing. It is recommended to remove them.
(lint/complexity/noUselessCatch)
this.logger.setContext( | ||
CrmObject.task.toUpperCase() + ':' + LeadSquaredService.name, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use template literals instead of string concatenation.
Replace the string concatenation with a template literal for better readability.
Fix the code as follows:
- CrmObject.task.toUpperCase() + ':' + LeadSquaredService.name,
+ `${CrmObject.task.toUpperCase()}:${LeadSquaredService.name}`,
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.
this.logger.setContext( | |
CrmObject.task.toUpperCase() + ':' + LeadSquaredService.name, | |
this.logger.setContext( | |
`${CrmObject.task.toUpperCase()}:${LeadSquaredService.name}`, |
Tools
Biome
[error] 22-22: Template literals are preferred over string concatenation.
Unsafe fix: Use a template literal.
(lint/style/useTemplate)
} catch (error) { | ||
throw error; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove redundant catch block.
The catch block that only rethrows the original error is unnecessary and can be removed.
Remove the catch block as follows:
- } catch (error) {
- throw error;
- }
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.
} catch (error) { | |
throw error; | |
} |
Tools
Biome
[error] 66-66: The catch clause that only rethrows the original error is redundant.
These unnecessary catch clauses can be confusing. It is recommended to remove them.
(lint/complexity/noUselessCatch)
statusCode: 200, | ||
}; | ||
} catch (error) { | ||
throw error; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove redundant catch clause.
The catch clause that only rethrows the original error is unnecessary and can be removed to simplify the code.
- } catch (error) {
- throw error;
- }
+ }
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.
throw error; | |
} |
Tools
Biome
[error] 114-114: The catch clause that only rethrows the original error is redundant.
These unnecessary catch clauses can be confusing. It is recommended to remove them.
(lint/complexity/noUselessCatch)
} catch (error) { | ||
throw error; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove redundant catch clause.
The catch clause only rethrows the original error, which is unnecessary and can be removed to simplify the code.
Remove the redundant catch clause as follows:
- } catch (error) {
- throw error;
- }
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.
} catch (error) { | |
throw error; | |
} |
Tools
Biome
[error] 271-271: The catch clause that only rethrows the original error is redundant.
These unnecessary catch clauses can be confusing. It is recommended to remove them.
(lint/complexity/noUselessCatch)
formatDate(date: Date): string { | ||
const year = date.getUTCFullYear(); | ||
const month = date.getUTCMonth(); | ||
const currentDate = date.getUTCDate(); | ||
const hours = date.getUTCHours(); | ||
const minutes = date.getUTCMinutes(); | ||
const seconds = date.getUTCSeconds(); | ||
return `${year}-${month}-${currentDate} ${hours}:${minutes}:${seconds}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adjust the month value in date formatting.
The getUTCMonth()
method returns a zero-based month index. Add 1 to the month value to get the correct month number.
Fix the month calculation as follows:
- const month = date.getUTCMonth();
+ const month = date.getUTCMonth() + 1;
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.
formatDate(date: Date): string { | |
const year = date.getUTCFullYear(); | |
const month = date.getUTCMonth(); | |
const currentDate = date.getUTCDate(); | |
const hours = date.getUTCHours(); | |
const minutes = date.getUTCMinutes(); | |
const seconds = date.getUTCSeconds(); | |
return `${year}-${month}-${currentDate} ${hours}:${minutes}:${seconds}`; | |
formatDate(date: Date): string { | |
const year = date.getUTCFullYear(); | |
const month = date.getUTCMonth() + 1; | |
const currentDate = date.getUTCDate(); | |
const hours = date.getUTCHours(); | |
const minutes = date.getUTCMinutes(); | |
const seconds = date.getUTCSeconds(); | |
return `${year}-${month}-${currentDate} ${hours}:${minutes}:${seconds}`; |
} catch (error) { | ||
throw error; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove redundant catch clause.
The catch clause only rethrows the original error, which is unnecessary and can be removed to simplify the code.
Remove the redundant catch clause as follows:
- } catch (error) {
- throw error;
- }
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.
} catch (error) { | |
throw error; | |
} |
Tools
Biome
[error] 71-71: The catch clause that only rethrows the original error is redundant.
These unnecessary catch clauses can be confusing. It is recommended to remove them.
(lint/complexity/noUselessCatch)
private async desunifyCall( | ||
source: UnifiedCrmEngagementInput, | ||
customFieldMappings?: { | ||
slug: string; | ||
remote_id: string; | ||
}[], | ||
): Promise<LeadSquaredEngagementInput> { | ||
const result: LeadSquaredEngagementCallInput = { | ||
Direction: source.direction === 'INBOUND' ? 'Inbound' : 'Outbound', | ||
CallerSource: source.content || '', | ||
LeadId: source.company_id || '', | ||
SourceNumber: '', // todo, | ||
DisplayNumber: '', // todo | ||
DestinationNumber: '', // todo, | ||
}; | ||
|
||
if (source.start_at && source.end_time) { | ||
const startDate = new Date(source.start_at); | ||
const endDate = new Date(source.end_time); | ||
|
||
// Calculate the difference in milliseconds | ||
const diffMilliseconds = endDate.getTime() - startDate.getTime(); | ||
|
||
// Convert milliseconds to seconds | ||
const durationInSeconds = Math.round(diffMilliseconds / 1000); | ||
result.StartTime = this.formatDate(startDate); | ||
result.EndTime = this.formatDate(endDate); | ||
result.CallDuration = durationInSeconds; | ||
result.Status = 'Answered'; | ||
} | ||
|
||
if (source.user_id) { | ||
const owner_id = await this.utils.getRemoteIdFromUserUuid(source.user_id); | ||
if (owner_id) { | ||
result.UserId = owner_id; | ||
} | ||
} | ||
|
||
if (customFieldMappings && source.field_mappings) { | ||
for (const [k, v] of Object.entries(source.field_mappings)) { | ||
const mapping = customFieldMappings.find( | ||
(mapping) => mapping.slug === k, | ||
); | ||
if (mapping) { | ||
result[mapping.remote_id] = v; | ||
} | ||
} | ||
} | ||
|
||
return result; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Address TODO comments in desunifyCall method.
The method includes TODO comments for SourceNumber
, DisplayNumber
, and DestinationNumber
. Ensure these fields are properly handled before deploying.
Would you like me to assist in implementing these fields or open a GitHub issue to track this task?
formatDate(date: Date): string { | ||
const year = date.getUTCFullYear(); | ||
const month = date.getUTCMonth(); | ||
const currentDate = date.getUTCDate(); | ||
const hours = date.getUTCHours(); | ||
const minutes = date.getUTCMinutes(); | ||
const seconds = date.getUTCSeconds(); | ||
return `${year}-${month}-${currentDate} ${hours}:${minutes}:${seconds}`; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adjust the month value in date formatting.
The getUTCMonth()
method returns a zero-based month index. Add 1 to the month value to get the correct month number.
Fix the month calculation as follows:
- const month = date.getUTCMonth();
+ const month = date.getUTCMonth() + 1;
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.
formatDate(date: Date): string { | |
const year = date.getUTCFullYear(); | |
const month = date.getUTCMonth(); | |
const currentDate = date.getUTCDate(); | |
const hours = date.getUTCHours(); | |
const minutes = date.getUTCMinutes(); | |
const seconds = date.getUTCSeconds(); | |
return `${year}-${month}-${currentDate} ${hours}:${minutes}:${seconds}`; | |
} | |
formatDate(date: Date): string { | |
const year = date.getUTCFullYear(); | |
const month = date.getUTCMonth() + 1; | |
const currentDate = date.getUTCDate(); | |
const hours = date.getUTCHours(); | |
const minutes = date.getUTCMinutes(); | |
const seconds = date.getUTCSeconds(); | |
return `${year}-${month}-${currentDate} ${hours}:${minutes}:${seconds}`; | |
} |
fixes #649
Integrated the following objects:
Summary by CodeRabbit
New Features
Type Definitions
Documentation