Skip to content
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

feat: allow using WebClient APIs without argument #1809

Merged
merged 7 commits into from
Jun 10, 2024
Merged

feat: allow using WebClient APIs without argument #1809

merged 7 commits into from
Jun 10, 2024

Conversation

davidlj95
Copy link
Contributor

@davidlj95 davidlj95 commented Jun 10, 2024

Summary

Suggest an implementation for #1769 by using void & union types

Introduced OptionalArgument for explicitness

Fixes #1769

To pay special attention:

Requirements (place an x in each [ ])

Copy link

codecov bot commented Jun 10, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 81.62%. Comparing base (bb21de9) to head (f352c99).
Report is 3 commits behind head on main.

Current head f352c99 differs from pull request most recent head f98f005

Please upload reports for the commit f98f005 to get more accurate results.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1809   +/-   ##
=======================================
  Coverage   81.62%   81.62%           
=======================================
  Files          35       35           
  Lines        7684     7684           
  Branches      316      316           
=======================================
  Hits         6272     6272           
  Misses       1400     1400           
  Partials       12       12           
Flag Coverage Δ
cli-hooks 95.07% <ø> (ø)
cli-test 53.80% <ø> (ø)
oauth 76.51% <ø> (ø)
socket-mode 59.41% <ø> (ø)
web-api 96.48% <ø> (ø)
webhook 95.20% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Copy link
Contributor

@filmaj filmaj left a comment

Choose a reason for hiding this comment

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

Hey this looks good to me and thank you for the PR!

One note about #1769 is that we'll want to add this to all methods that accept all optional arguments. Here's a brief search I did just based on the tests where the changes in this PR would apply:

➜ ack "all optional" test/types
test/types/methods/admin.emoji.test-d.ts
42:expectAssignable<Parameters<typeof web.admin.emoji.list>>([{}]); // all optional args

test/types/methods/admin.conversations.test-d.ts
160:}]); // all optional args
293:}]); // all optional args

test/types/methods/usergroups.test-d.ts
37:expectAssignable<Parameters<typeof web.usergroups.list>>([{}]); // all optional properties

test/types/methods/admin.barriers.test-d.ts
56:expectAssignable<Parameters<typeof web.admin.barriers.list>>([{}]); // all optional args

test/types/methods/dnd.test-d.ts
10:expectAssignable<Parameters<typeof web.dnd.endDnd>>([{}]); // all optional args
16:expectAssignable<Parameters<typeof web.dnd.endSnooze>>([{}]); // all optional args
22:expectAssignable<Parameters<typeof web.dnd.info>>([{}]); // all optional args

test/types/methods/openid.test-d.ts
28:expectAssignable<Parameters<typeof web.openid.connect.userInfo>>([{}]); // all optional args

test/types/methods/api.test-d.ts
10:expectAssignable<Parameters<typeof web.api.test>>([{}]); // all optional args

test/types/methods/rtm.test-d.ts
10:expectAssignable<Parameters<typeof web.rtm.connect>>([{}]); // all optional arguments
16:expectAssignable<Parameters<typeof web.rtm.start>>([{}]); // all optional arguments

test/types/methods/admin.teams.test-d.ts
35:expectAssignable<Parameters<typeof web.admin.teams.list>>([{}]); // all optional

test/types/methods/team.test-d.ts
10:expectAssignable<Parameters<typeof web.team.accessLogs>>([{}]); // all optional arguments
16:expectAssignable<Parameters<typeof web.team.billableInfo>>([{}]); // all optional arguments
22:expectAssignable<Parameters<typeof web.team.billing.info>>([{}]); // all optional arguments
28:expectAssignable<Parameters<typeof web.team.integrationLogs>>([{}]); // all optional arguments
34:expectAssignable<Parameters<typeof web.team.profile.get>>([{}]); // all optional arguments
40:expectAssignable<Parameters<typeof web.team.preferences.list>>([{}]); // all optional arguments

test/types/methods/auth.test-d.ts
10:expectAssignable<Parameters<typeof web.auth.revoke>>([{}]); // all optional args
16:expectAssignable<Parameters<typeof web.auth.teams.list>>([{}]); // all optional args
22:expectAssignable<Parameters<typeof web.auth.test>>([{}]); // all optional args

test/types/methods/admin.roles.test-d.ts
52:expectAssignable<Parameters<typeof web.admin.roles.listAssignments>>([{}]); // all optional

test/types/methods/reactions.test-d.ts
58:expectAssignable<Parameters<typeof web.reactions.list>>([{}]); // all optional args

test/types/methods/conversations.test-d.ts
174:expectAssignable<Parameters<typeof web.conversations.list>>([{}]); // all optional args
180:expectAssignable<Parameters<typeof web.conversations.listConnectInvites>>([{}]); // all optional args

test/types/methods/bots.test-d.ts
10:expectAssignable<Parameters<typeof web.bots.info>>([{}]); // all optional args

test/types/methods/reminders.test-d.ts
79:expectAssignable<Parameters<typeof web.reminders.list>>([{}]); // all optional args

test/types/methods/chat.test-d.ts
375:expectAssignable<Parameters<typeof web.chat.scheduledMessages.list>>([{}]); // all optional args

test/types/methods/admin.apps.test-d.ts
10:expectAssignable<Parameters<typeof web.admin.apps.activities.list>>([{}]); // all optional args

test/types/methods/emoji.test-d.ts
10:expectAssignable<Parameters<typeof web.emoji.list>>([{}]); // all optional args

test/types/methods/apps.test-d.ts
10:expectAssignable<Parameters<typeof web.apps.connections.open>>([{}]); // all optional args

test/types/methods/admin.users.test-d.ts
79:expectAssignable<Parameters<typeof web.admin.users.list>>([{}]); // all optional args is ok
157:expectAssignable<Parameters<typeof web.admin.users.session.list>>([{}]); // all optional args is OK
264:expectAssignable<Parameters<typeof web.admin.users.unsupportedVersions.export>>([{}]); // all optional args OK

test/types/methods/admin.workflows.test-d.ts
73:expectAssignable<Parameters<typeof web.admin.workflows.search>>([{}]); // all optional args OK

Would you be able to add the same changes to all of the above methods that support purely optional arguments?

@davidlj95
Copy link
Contributor Author

Hey this looks good to me and thank you for the PR!

One note about #1769 is that we'll want to add this to all methods that accept all optional arguments. Here's a brief search I did just based on the tests where the changes in this PR would apply:

Thanks! 😊 Oh nice then 💪 I just did a few as kind of a demo of what I'd look like. If looks good, will apply it around. Thanks for searching the places where changes are needed

btw I'm thinking about adding some utility like

type OptionalArgument<T> = T | void

So the intention is more explicit and can easily be refactored around in case we need to detect in which places args are optional

Would you be able to add the same changes to all of the above methods that support purely optional arguments?

Sure!

@davidlj95 davidlj95 changed the title feat: allow using (auth|api).test without args feat: allow using WebClient APIs without argument Jun 10, 2024

// https://api.slack.com/methods/apps.connections.open
export interface AppsConnectionsOpenArguments { }
export type AppsConnectionsOpenArguments = OptionalArgument<object>;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

⚠️ BREAKING CHANGE (technically, not pragmatically)

OpenIDConnectUserInfoArguments & AppsConnectionsOpenArgument are declared as empty interfaces.

An empty interface allows for any non nullable value, not an object with no properties. It is well explained in typescript-eslint rule no-empty-interface. In order to specify an empty object, object can be used. Using that then

This would be a breaking change if someone is using a non-nullable and non-object value as argument to one of those methods. Like apps.connections.open(42). But that shouldn't have worked in the first place

Copy link
Contributor Author

@davidlj95 davidlj95 Jun 10, 2024

Choose a reason for hiding this comment

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

Can use {} to keep same type as before and ignore ESLint rule complaining about it if we want to be sure no breaking change happens (could be done in next major as cleanup?)

Copy link
Contributor

Choose a reason for hiding this comment

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

Huh, TIL! I think as long as the previous "expected" usage of these methods (i.e. needing to provide an empty object {} as a parameter for these methods that accept optional arguments) are a) enshrined in tests and b) pass, then that's all that matters to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same here tbh! Didn't know about that either, it was ESLint rule complaining that lead me through the rabbit hole.

Noice then 👍

// https://api.slack.com/methods/team.info
export interface TeamInfoArguments extends TokenOverridable {
export type TeamInfoArguments = OptionalArgument<TokenOverridable & {
/**
Copy link
Contributor Author

Choose a reason for hiding this comment

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

☝️ This one has no type tests, but it's optional too

Copy link
Contributor

Choose a reason for hiding this comment

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

Can we add missing type tests while we're here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in f98f005

@davidlj95 davidlj95 requested a review from filmaj June 10, 2024 17:37
Copy link
Contributor

@filmaj filmaj left a comment

Choose a reason for hiding this comment

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

Thanks for the work and explanation around extending from empty interfaces! I learned something today 😄

If there is a missing test, then if you could please add it, that would be awesome! Otherwise everything looks good to me.


// https://api.slack.com/methods/apps.connections.open
export interface AppsConnectionsOpenArguments { }
export type AppsConnectionsOpenArguments = OptionalArgument<object>;
Copy link
Contributor

Choose a reason for hiding this comment

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

Huh, TIL! I think as long as the previous "expected" usage of these methods (i.e. needing to provide an empty object {} as a parameter for these methods that accept optional arguments) are a) enshrined in tests and b) pass, then that's all that matters to me.

// https://api.slack.com/methods/team.info
export interface TeamInfoArguments extends TokenOverridable {
export type TeamInfoArguments = OptionalArgument<TokenOverridable & {
/**
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we add missing type tests while we're here?

@filmaj filmaj added semver:patch enhancement M-T: A feature request for new functionality area:typescript issues that specifically impact using the package from typescript projects pkg:web-api applies to `@slack/web-api` auto-triage-skip labels Jun 10, 2024
@filmaj filmaj added this to the [email protected] milestone Jun 10, 2024
Comment on lines +24 to +28
// team.info
// -- sad path
// -- happy path
expectAssignable<Parameters<typeof web.team.info>>([{}]); // all optional arguments
expectAssignable<Parameters<typeof web.team.info>>([]); // no arg is fine
Copy link
Contributor Author

Choose a reason for hiding this comment

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

🆕 team.info API type tests

@filmaj filmaj merged commit 9f2935f into slackapi:main Jun 10, 2024
19 checks passed
@davidlj95 davidlj95 deleted the feat-allow-test-no-args branch June 10, 2024 18:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:typescript issues that specifically impact using the package from typescript projects auto-triage-skip cla:signed enhancement M-T: A feature request for new functionality pkg:web-api applies to `@slack/web-api` semver:patch
Projects
None yet
Development

Successfully merging this pull request may close these issues.

web-api: Consider removing need to provide empty object as argument to zero-argument methods
2 participants