SlideShare a Scribd company logo
1 of 36
Building a friendly Kotlin SDK to
connect to JetBrains Space
Maarten Balliauw
@maartenballiauw
Agenda
JetBrains Space
JetBrains Space HTTP API
Building a Kotlin SDK for the Space HTTP API
Code generation
Developer experience
JetBrains Space
JetBrains Space
Integrated Team Environment
https://jetbrains.space
People
Teams
Projects
-
Workspaces
for teams
Collaboration
JetBrains Space
demo
The Space HTTP API
Integrated Team Environment
More information in Space == more value from Space
Internal integrations out of the box
Vacation shown in profile
Blog post targeted to team/location
Calendar integration in blog post
Everything can be a ToDo item
...
What with external integrations? Extensibility?
Everything as an HTTP API!
What do you want to build? Which integration do you need?
Import data
Post to chat
Manage users, teams, and locations programatically
Build dashboards
???
“Open up everything”
Large HTTP API surface...
HTTP API Playground to explore!
HTTP API Playground
demo
$fields
Top-level fields returned by default
Unless $fields query parameter used
Use $fields to be specific, or get nested fields
$fields=id,icon,name
$fields=id,name,boards(id,description)
$fields=id,name,boards(id,info(columns))
$fields=*,boards(id,description)
Building a Kotlin SDK
for the Space HTTP API
Hello, Kotlin! 👋
Goal: make our users succesful at using Space in their team/organization
Provide a ready-to-use SDK
Minimal configuration needed
Discoverability
TL;DR: Lead integration developers on the shortest path to success
How? Handcrafted
No.
Over 150 API endpoints
Over 700 object types
Churn during Space EAP / Space Beta
How? OpenAPI?
Use openapi-generator, generate based on OpenAPI / Swagger document
Some incompatible object types needed custom code generation
How? Custom code generation
Space exposes HTTP API Model
Enumerations
DTOs (objects passed around)
Resources
+ data types, nullability,
default values, ...
https://your.jetbrains.space/api/http/http-api-model?$fields=dto,enums,urlParams,resources(*,nestedResources!)
Enumeration model
class HA_Enum(
val id: TID,
val name: String,
val values: List<String>,
val deprecation: HA_Deprecation?
)
data class HA_Deprecation(
val message: String,
val since: String,
val forRemoval: Boolean
)
Enumeration code generator
fun visit(enumType: HA_Enum) = buildString {
enumType.deprecation?.let {
appendLine("@Deprecated(message = "${it.message}") }
val enumClassName = enumType.name.kotlinClassNameJoined()
appendLine("enum class $enumClassName {")
enumType.values.forEach {
appendLine("$it,")
}
appendLine("}")
}
enum class AbsenceListMode {
All,
WithAccessibleReasonUnapproved,
WithAccessibleReasonAll
}
DTO model
class HA_Dto(
val id: TID,
val name: String,
val fields: List<HA_DtoField>,
val hierarchyRole: HierarchyRole,
val extends: Ref?,
val implements: List<Ref>,
val inheritors: List<Ref>,
val deprecation: HA_Deprecation?,
val record: Boolean
)
class HA_DtoField(val field: HA_Field, val extension: Boolean)
data class HA_Field(
val name: String,
val type: HA_Type,
val deprecation: HA_Deprecation?,
val optional: Boolean,
val defaultValue: HA_DefaultValue?
)
Endpoints model
Endpoint id, name, base path
Resource id, name, path, parameters
Resource id, name, path, parameters
Resource id, name, path, parameters
...
+ parameter types
+ return types
+ default values (const, variable)
Custom code generation
demo
Strings? KotlinPoet?
Generally, a few ways to generate code:
String-based
Write strings directly
Use a template engine
Easy to recognize what gets written
Model-based
KotlinPoet https://square.github.io/kotlinpoet/
Safety (e.g. can’t forget to write class name)
KotlinPoet
Kotlin and Java API for generating .kt source files
Ensures all properties of code are in place (modifier, type name, ...)
Callable references
Formatting of generated code
https://square.github.io/kotlinpoet/
FunSpec.builder("main")
.addStatement("val helloWorld = %L", helloFunction.reference())
.build()
Extension functions everywhere
Many places where we need:
Kotlin class name from string
Kotlin classs from Space model type (Enum/DTO/URL parameter/...)
fun String.kotlinClassName(): List<String> = split(".")
fun HA_Dto.getClassName() =
ClassName("space.jetbrains.api.runtime.types", name.kotlinClassName())
fun HA_UrlParameterOption.getClassName() =
ClassName("space.jetbrains.api.runtime.types", optionName.kotlinClassName())
Developer experience
The ideal “Getting started”
1. Register application in Space
2. Add to Gradle file
dependencies {
implementation "org.jetbrains:space-sdk-jvm:$space_version"
}
3. Create connection
val spaceClient = SpaceHttpClient(HttpClient())
.withServiceAccountTokenSource(
"client-id",
"client-secret",
"https://your.jetbrains.space/")
4. Profit!
Large API surface
Remember $fields ?
Top-level fields returned by default
Unless $fields query parameter used
Use $fields to be specific, or get nested fields
$fields
Top-level fields by default, partial builder to be specific
val memberProfile = spaceClient.teamDirectory.profiles
.getProfile(ProfileIdentifier.Username("Heather.Stewart"))
val memberProfile = spaceClient.teamDirectory.profiles
.getProfile(ProfileIdentifier.Username("Heather.Stewart")) {
defaultPartial() // with all top level fields
managers { // include managers
id() // with their id
username() // and their username
name { // and their name
firstName() // with firstName
lastName() // and firstName
}
}
}
API playground
Building a chat message...
spaceClient.chats.messages.sendMessage(
recipient = MessageRecipient.Channel(ChatChannel.FromName(chatChannelName)),
content = ChatMessage.Block(
style = MessageStyle.SUCCESS,
outline = MessageOutline(icon = null, text = "Have you tried JetBrains Space?"),
sections = listOf(
MessageSection(
header = "JetBrains Space",
elements = listOf(
MessageText(accessory = MessageIcon(ApiIcon("space"), MessageStyle.SUCCESS),
content = "JetBrains Space is an Integrated Team Environment."),
MessageText(accessory = null, content = "Have you tried JetBrains Space?"),
MessageDivider,
MessageText(accessory = null, content = "Get access at https://www.jetbrains.com/space/")
),
footer = "Check it out at https://www.jetbrains.com/space/"
)
),
messageData = null
),
unfurlLinks = false
)
spaceClient.chats.messages.sendMessage(
recipient = MessageRecipient.Channel(ChatChannel.FromName(chatChannelName)),
content = message {
style = MessageStyle.SUCCESS
outline = MessageOutline(icon = null, text = "Have you tried JetBrains Space?")
section {
header = "JetBrains Space"
textWithIcon("JetBrains Space is an Integrated Team Environment.", "space",
MessageStyle.SUCCESS)
text("Have you tried JetBrains Space?")
divider()
text("Get access at https://www.jetbrains.com/space/")
footer = "Check it out at https://www.jetbrains.com/space/"
}
},
unfurlLinks = false
)
Building a chat message...
Identifiers and factory methods
Developer experience
demo
Conclusion
Conclusion
JetBrains Space is an Integrated Team Environment
JetBrains Space HTTP API exposes everything
Building a Kotlin SDK for the Space HTTP API
Goal: make our users succesful at using Space
Provide a ready-to-use SDK
Minimal configuration needed
Discoverability
Code generation
Focus on developer experience
Thank you!
https://blog.maartenballiauw.be
@maartenballiauw

More Related Content

More from Maarten Balliauw

More from Maarten Balliauw (20)

CloudBurst 2019 - Indexing and searching NuGet.org with Azure Functions and S...
CloudBurst 2019 - Indexing and searching NuGet.org with Azure Functions and S...CloudBurst 2019 - Indexing and searching NuGet.org with Azure Functions and S...
CloudBurst 2019 - Indexing and searching NuGet.org with Azure Functions and S...
 
NDC Oslo 2019 - Indexing and searching NuGet.org with Azure Functions and Search
NDC Oslo 2019 - Indexing and searching NuGet.org with Azure Functions and SearchNDC Oslo 2019 - Indexing and searching NuGet.org with Azure Functions and Search
NDC Oslo 2019 - Indexing and searching NuGet.org with Azure Functions and Search
 
Approaches for application request throttling - Cloud Developer Days Poland
Approaches for application request throttling - Cloud Developer Days PolandApproaches for application request throttling - Cloud Developer Days Poland
Approaches for application request throttling - Cloud Developer Days Poland
 
Indexing and searching NuGet.org with Azure Functions and Search - Cloud Deve...
Indexing and searching NuGet.org with Azure Functions and Search - Cloud Deve...Indexing and searching NuGet.org with Azure Functions and Search - Cloud Deve...
Indexing and searching NuGet.org with Azure Functions and Search - Cloud Deve...
 
Approaches for application request throttling - dotNetCologne
Approaches for application request throttling - dotNetCologneApproaches for application request throttling - dotNetCologne
Approaches for application request throttling - dotNetCologne
 
CodeStock - Exploring .NET memory management - a trip down memory lane
CodeStock - Exploring .NET memory management - a trip down memory laneCodeStock - Exploring .NET memory management - a trip down memory lane
CodeStock - Exploring .NET memory management - a trip down memory lane
 
ConFoo Montreal - Microservices for building an IDE - The innards of JetBrain...
ConFoo Montreal - Microservices for building an IDE - The innards of JetBrain...ConFoo Montreal - Microservices for building an IDE - The innards of JetBrain...
ConFoo Montreal - Microservices for building an IDE - The innards of JetBrain...
 
ConFoo Montreal - Approaches for application request throttling
ConFoo Montreal - Approaches for application request throttlingConFoo Montreal - Approaches for application request throttling
ConFoo Montreal - Approaches for application request throttling
 
Microservices for building an IDE – The innards of JetBrains Rider - TechDays...
Microservices for building an IDE – The innards of JetBrains Rider - TechDays...Microservices for building an IDE – The innards of JetBrains Rider - TechDays...
Microservices for building an IDE – The innards of JetBrains Rider - TechDays...
 
JetBrains Day Seoul - Exploring .NET’s memory management – a trip down memory...
JetBrains Day Seoul - Exploring .NET’s memory management – a trip down memory...JetBrains Day Seoul - Exploring .NET’s memory management – a trip down memory...
JetBrains Day Seoul - Exploring .NET’s memory management – a trip down memory...
 
DotNetFest - Let’s refresh our memory! Memory management in .NET
DotNetFest - Let’s refresh our memory! Memory management in .NETDotNetFest - Let’s refresh our memory! Memory management in .NET
DotNetFest - Let’s refresh our memory! Memory management in .NET
 
VISUG - Approaches for application request throttling
VISUG - Approaches for application request throttlingVISUG - Approaches for application request throttling
VISUG - Approaches for application request throttling
 
What is going on - Application diagnostics on Azure - TechDays Finland
What is going on - Application diagnostics on Azure - TechDays FinlandWhat is going on - Application diagnostics on Azure - TechDays Finland
What is going on - Application diagnostics on Azure - TechDays Finland
 
ConFoo - Exploring .NET’s memory management – a trip down memory lane
ConFoo - Exploring .NET’s memory management – a trip down memory laneConFoo - Exploring .NET’s memory management – a trip down memory lane
ConFoo - Exploring .NET’s memory management – a trip down memory lane
 
ConFoo - NuGet beyond Hello World
ConFoo - NuGet beyond Hello WorldConFoo - NuGet beyond Hello World
ConFoo - NuGet beyond Hello World
 
Approaches to application request throttling
Approaches to application request throttlingApproaches to application request throttling
Approaches to application request throttling
 
NuGet beyond Hello World - DotNext Piter 2017
NuGet beyond Hello World - DotNext Piter 2017NuGet beyond Hello World - DotNext Piter 2017
NuGet beyond Hello World - DotNext Piter 2017
 
Exploring .NET memory management (iSense)
Exploring .NET memory management (iSense)Exploring .NET memory management (iSense)
Exploring .NET memory management (iSense)
 
Exploring .NET memory management - JetBrains webinar
Exploring .NET memory management - JetBrains webinarExploring .NET memory management - JetBrains webinar
Exploring .NET memory management - JetBrains webinar
 
DNS for Developers - ConFoo Montreal
DNS for Developers - ConFoo MontrealDNS for Developers - ConFoo Montreal
DNS for Developers - ConFoo Montreal
 

Recently uploaded

Recently uploaded (20)

Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 

Building a friendly Kotlin SDK to connect to JetBrains Space

  • 1. Building a friendly Kotlin SDK to connect to JetBrains Space Maarten Balliauw @maartenballiauw
  • 2. Agenda JetBrains Space JetBrains Space HTTP API Building a Kotlin SDK for the Space HTTP API Code generation Developer experience
  • 4. JetBrains Space Integrated Team Environment https://jetbrains.space People Teams Projects - Workspaces for teams Collaboration
  • 7. Integrated Team Environment More information in Space == more value from Space Internal integrations out of the box Vacation shown in profile Blog post targeted to team/location Calendar integration in blog post Everything can be a ToDo item ... What with external integrations? Extensibility?
  • 8. Everything as an HTTP API! What do you want to build? Which integration do you need? Import data Post to chat Manage users, teams, and locations programatically Build dashboards ??? “Open up everything” Large HTTP API surface... HTTP API Playground to explore!
  • 10. $fields Top-level fields returned by default Unless $fields query parameter used Use $fields to be specific, or get nested fields $fields=id,icon,name $fields=id,name,boards(id,description) $fields=id,name,boards(id,info(columns)) $fields=*,boards(id,description)
  • 11. Building a Kotlin SDK for the Space HTTP API
  • 12. Hello, Kotlin! 👋 Goal: make our users succesful at using Space in their team/organization Provide a ready-to-use SDK Minimal configuration needed Discoverability TL;DR: Lead integration developers on the shortest path to success
  • 13. How? Handcrafted No. Over 150 API endpoints Over 700 object types Churn during Space EAP / Space Beta
  • 14. How? OpenAPI? Use openapi-generator, generate based on OpenAPI / Swagger document Some incompatible object types needed custom code generation
  • 15. How? Custom code generation Space exposes HTTP API Model Enumerations DTOs (objects passed around) Resources + data types, nullability, default values, ... https://your.jetbrains.space/api/http/http-api-model?$fields=dto,enums,urlParams,resources(*,nestedResources!)
  • 16. Enumeration model class HA_Enum( val id: TID, val name: String, val values: List<String>, val deprecation: HA_Deprecation? ) data class HA_Deprecation( val message: String, val since: String, val forRemoval: Boolean )
  • 17. Enumeration code generator fun visit(enumType: HA_Enum) = buildString { enumType.deprecation?.let { appendLine("@Deprecated(message = "${it.message}") } val enumClassName = enumType.name.kotlinClassNameJoined() appendLine("enum class $enumClassName {") enumType.values.forEach { appendLine("$it,") } appendLine("}") } enum class AbsenceListMode { All, WithAccessibleReasonUnapproved, WithAccessibleReasonAll }
  • 18. DTO model class HA_Dto( val id: TID, val name: String, val fields: List<HA_DtoField>, val hierarchyRole: HierarchyRole, val extends: Ref?, val implements: List<Ref>, val inheritors: List<Ref>, val deprecation: HA_Deprecation?, val record: Boolean ) class HA_DtoField(val field: HA_Field, val extension: Boolean) data class HA_Field( val name: String, val type: HA_Type, val deprecation: HA_Deprecation?, val optional: Boolean, val defaultValue: HA_DefaultValue? )
  • 19. Endpoints model Endpoint id, name, base path Resource id, name, path, parameters Resource id, name, path, parameters Resource id, name, path, parameters ... + parameter types + return types + default values (const, variable)
  • 21. Strings? KotlinPoet? Generally, a few ways to generate code: String-based Write strings directly Use a template engine Easy to recognize what gets written Model-based KotlinPoet https://square.github.io/kotlinpoet/ Safety (e.g. can’t forget to write class name)
  • 22. KotlinPoet Kotlin and Java API for generating .kt source files Ensures all properties of code are in place (modifier, type name, ...) Callable references Formatting of generated code https://square.github.io/kotlinpoet/ FunSpec.builder("main") .addStatement("val helloWorld = %L", helloFunction.reference()) .build()
  • 23. Extension functions everywhere Many places where we need: Kotlin class name from string Kotlin classs from Space model type (Enum/DTO/URL parameter/...) fun String.kotlinClassName(): List<String> = split(".") fun HA_Dto.getClassName() = ClassName("space.jetbrains.api.runtime.types", name.kotlinClassName()) fun HA_UrlParameterOption.getClassName() = ClassName("space.jetbrains.api.runtime.types", optionName.kotlinClassName())
  • 25. The ideal “Getting started” 1. Register application in Space 2. Add to Gradle file dependencies { implementation "org.jetbrains:space-sdk-jvm:$space_version" } 3. Create connection val spaceClient = SpaceHttpClient(HttpClient()) .withServiceAccountTokenSource( "client-id", "client-secret", "https://your.jetbrains.space/") 4. Profit!
  • 27. Remember $fields ? Top-level fields returned by default Unless $fields query parameter used Use $fields to be specific, or get nested fields
  • 28. $fields Top-level fields by default, partial builder to be specific val memberProfile = spaceClient.teamDirectory.profiles .getProfile(ProfileIdentifier.Username("Heather.Stewart")) val memberProfile = spaceClient.teamDirectory.profiles .getProfile(ProfileIdentifier.Username("Heather.Stewart")) { defaultPartial() // with all top level fields managers { // include managers id() // with their id username() // and their username name { // and their name firstName() // with firstName lastName() // and firstName } } }
  • 30. Building a chat message... spaceClient.chats.messages.sendMessage( recipient = MessageRecipient.Channel(ChatChannel.FromName(chatChannelName)), content = ChatMessage.Block( style = MessageStyle.SUCCESS, outline = MessageOutline(icon = null, text = "Have you tried JetBrains Space?"), sections = listOf( MessageSection( header = "JetBrains Space", elements = listOf( MessageText(accessory = MessageIcon(ApiIcon("space"), MessageStyle.SUCCESS), content = "JetBrains Space is an Integrated Team Environment."), MessageText(accessory = null, content = "Have you tried JetBrains Space?"), MessageDivider, MessageText(accessory = null, content = "Get access at https://www.jetbrains.com/space/") ), footer = "Check it out at https://www.jetbrains.com/space/" ) ), messageData = null ), unfurlLinks = false )
  • 31. spaceClient.chats.messages.sendMessage( recipient = MessageRecipient.Channel(ChatChannel.FromName(chatChannelName)), content = message { style = MessageStyle.SUCCESS outline = MessageOutline(icon = null, text = "Have you tried JetBrains Space?") section { header = "JetBrains Space" textWithIcon("JetBrains Space is an Integrated Team Environment.", "space", MessageStyle.SUCCESS) text("Have you tried JetBrains Space?") divider() text("Get access at https://www.jetbrains.com/space/") footer = "Check it out at https://www.jetbrains.com/space/" } }, unfurlLinks = false ) Building a chat message...
  • 35. Conclusion JetBrains Space is an Integrated Team Environment JetBrains Space HTTP API exposes everything Building a Kotlin SDK for the Space HTTP API Goal: make our users succesful at using Space Provide a ready-to-use SDK Minimal configuration needed Discoverability Code generation Focus on developer experience

Editor's Notes

  1. https://pixabay.com
  2. Clear cookies and auth in demo.jetbrains.space! Setup everything to work with demo.jetbrains.space space-api-client, space-api-client-samples, and space-app-tutorials open in IJ
  3. Show home page and mention what is shown (relevat info for me) Show project, mention repo’s, issues, checklists, ... Always possible to annotate and ask questions inline in code. Other folks will see this pop up in chat, so they do not necesarily have to switch context if it’s a minor question. Mention issues, and again, chat integration. Everything can be a to-do as well, use the lightning bolt icon. Automation/CI integrated. Absences integrated is where things get interesting. Who should I contact for certain responsibility? Is that other perso naround to look at my code review? Blogs. Organization-wide, for specific teams or locations. E.g. To share post-mortems, or team announcements, without overloading others. Again, relevant infomation to you. Many other things such as a knowledge base, artifact repo’s for NuGet, NPM, Docker, ...
  4. Show HTTP API playground, send a chat message or something like that. Or get profile info. Mention different endpoints, API’s grouped by functionality Mention request builder, all that, easy to reproduce Show getting a profile, selecting properties, and highlight $fields
  5. Show space-api-client API model classes, show: HA_Enum, HA_Dto, HierarchyRole enumeration Show Main.kt to see how it is bootstrapped Show space/jetbrains/api/generator/GenerateTypes.kt:44 Using KotlinPoet (more on that later) Show the extension methods, like kotlinClassNameJoined() and annotationSpecs.deprecation
  6. KotlinPoet in Kotlin SDK
  7. Show space-api-client-samples Show connection setup Show using team directory Get profiles with their name – explain $fields here. No partial -> get top level Partial -> specific, but has code completion Show exception case where we help you out (unknown property accessor) Chat: show message builder DSL Show identifiers with chat