@stack-spot/portal-network 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/package.json +7 -6
  3. package/src/apis.json +2 -10
  4. package/src/client/account.ts +111 -4
  5. package/src/error/CanceledError.ts +3 -0
  6. package/src/error/DefaultAPIError.ts +27 -1
  7. package/src/error/StackspotAPIError.ts +33 -1
  8. package/src/index.ts +1 -0
  9. package/src/network/AutoInfiniteQuery.ts +104 -0
  10. package/src/network/AutoOperation.ts +7 -1
  11. package/src/network/AutoQuery.ts +2 -1
  12. package/src/network/ManualInfiniteQuery.ts +95 -0
  13. package/src/network/ManualQuery.ts +2 -2
  14. package/src/network/NetworkClient.ts +53 -41
  15. package/src/network/ReactQueryNetworkClient.ts +131 -33
  16. package/src/network/react-query-client.ts +3 -0
  17. package/src/network/types.ts +207 -11
  18. package/src/utils/use-extended-list.ts +80 -0
  19. package/.generate-api.failed.json +0 -1
  20. package/dist/api/account.d.ts +0 -2368
  21. package/dist/api/account.d.ts.map +0 -1
  22. package/dist/api/account.js +0 -1521
  23. package/dist/api/account.js.map +0 -1
  24. package/dist/api/ai.d.ts +0 -1432
  25. package/dist/api/ai.d.ts.map +0 -1
  26. package/dist/api/ai.js +0 -1342
  27. package/dist/api/ai.js.map +0 -1
  28. package/dist/api/apiRuntime.d.ts +0 -922
  29. package/dist/api/apiRuntime.d.ts.map +0 -1
  30. package/dist/api/apiRuntime.js +0 -599
  31. package/dist/api/apiRuntime.js.map +0 -1
  32. package/dist/api/cloudAccount.d.ts +0 -473
  33. package/dist/api/cloudAccount.d.ts.map +0 -1
  34. package/dist/api/cloudAccount.js +0 -300
  35. package/dist/api/cloudAccount.js.map +0 -1
  36. package/dist/api/cloudServices.d.ts +0 -1233
  37. package/dist/api/cloudServices.d.ts.map +0 -1
  38. package/dist/api/cloudServices.js +0 -715
  39. package/dist/api/cloudServices.js.map +0 -1
  40. package/dist/api/insights.d.ts +0 -123
  41. package/dist/api/insights.d.ts.map +0 -1
  42. package/dist/api/insights.js +0 -112
  43. package/dist/api/insights.js.map +0 -1
  44. package/dist/api/plugin.d.ts +0 -368
  45. package/dist/api/plugin.d.ts.map +0 -1
  46. package/dist/api/plugin.js +0 -218
  47. package/dist/api/plugin.js.map +0 -1
  48. package/dist/api/serviceCatalog.d.ts +0 -737
  49. package/dist/api/serviceCatalog.d.ts.map +0 -1
  50. package/dist/api/serviceCatalog.js +0 -611
  51. package/dist/api/serviceCatalog.js.map +0 -1
  52. package/dist/api/workflows.d.ts +0 -366
  53. package/dist/api/workflows.d.ts.map +0 -1
  54. package/dist/api/workflows.js +0 -175
  55. package/dist/api/workflows.js.map +0 -1
  56. package/dist/api/workspace.js +0 -1476
  57. package/dist/api/workspace.js.map +0 -1
  58. package/dist/api/workspaceManager.d.ts +0 -1121
  59. package/dist/api/workspaceManager.d.ts.map +0 -1
  60. package/dist/api/workspaceManager.js +0 -357
  61. package/dist/api/workspaceManager.js.map +0 -1
  62. package/dist/api/workspaceSearchEngine.d.ts +0 -93
  63. package/dist/api/workspaceSearchEngine.d.ts.map +0 -1
  64. package/dist/api/workspaceSearchEngine.js +0 -55
  65. package/dist/api/workspaceSearchEngine.js.map +0 -1
  66. package/dist/apis.json +0 -129
  67. package/dist/client/account.d.ts +0 -46
  68. package/dist/client/account.d.ts.map +0 -1
  69. package/dist/client/account.js +0 -104
  70. package/dist/client/account.js.map +0 -1
  71. package/dist/error/CanceledError.d.ts +0 -5
  72. package/dist/error/CanceledError.d.ts.map +0 -1
  73. package/dist/error/CanceledError.js +0 -7
  74. package/dist/error/CanceledError.js.map +0 -1
  75. package/dist/error/DefaultAPIError.d.ts +0 -9
  76. package/dist/error/DefaultAPIError.d.ts.map +0 -1
  77. package/dist/error/DefaultAPIError.js +0 -58
  78. package/dist/error/DefaultAPIError.js.map +0 -1
  79. package/dist/error/StackspotAPIError.d.ts +0 -19
  80. package/dist/error/StackspotAPIError.d.ts.map +0 -1
  81. package/dist/error/StackspotAPIError.js +0 -39
  82. package/dist/error/StackspotAPIError.js.map +0 -1
  83. package/dist/error/dictionary/account.d.ts +0 -55
  84. package/dist/error/dictionary/account.d.ts.map +0 -1
  85. package/dist/error/dictionary/account.js +0 -55
  86. package/dist/error/dictionary/account.js.map +0 -1
  87. package/dist/error/dictionary/action.d.ts +0 -163
  88. package/dist/error/dictionary/action.d.ts.map +0 -1
  89. package/dist/error/dictionary/action.js +0 -163
  90. package/dist/error/dictionary/action.js.map +0 -1
  91. package/dist/error/dictionary/base.d.ts +0 -21
  92. package/dist/error/dictionary/base.d.ts.map +0 -1
  93. package/dist/error/dictionary/base.js +0 -21
  94. package/dist/error/dictionary/base.js.map +0 -1
  95. package/dist/error/dictionary/cnt-fields.d.ts +0 -13
  96. package/dist/error/dictionary/cnt-fields.d.ts.map +0 -1
  97. package/dist/error/dictionary/cnt-fields.js +0 -13
  98. package/dist/error/dictionary/cnt-fields.js.map +0 -1
  99. package/dist/error/dictionary/cnt.d.ts +0 -79
  100. package/dist/error/dictionary/cnt.d.ts.map +0 -1
  101. package/dist/error/dictionary/cnt.js +0 -79
  102. package/dist/error/dictionary/cnt.js.map +0 -1
  103. package/dist/error/dictionary/rte.d.ts +0 -23
  104. package/dist/error/dictionary/rte.d.ts.map +0 -1
  105. package/dist/error/dictionary/rte.js +0 -23
  106. package/dist/error/dictionary/rte.js.map +0 -1
  107. package/dist/error/dictionary/rtm.d.ts +0 -9
  108. package/dist/error/dictionary/rtm.d.ts.map +0 -1
  109. package/dist/error/dictionary/rtm.js +0 -9
  110. package/dist/error/dictionary/rtm.js.map +0 -1
  111. package/dist/error/dictionary/workspace-fields.d.ts +0 -9
  112. package/dist/error/dictionary/workspace-fields.d.ts.map +0 -1
  113. package/dist/error/dictionary/workspace-fields.js +0 -9
  114. package/dist/error/dictionary/workspace-fields.js.map +0 -1
  115. package/dist/error/dictionary/workspace.d.ts +0 -99
  116. package/dist/error/dictionary/workspace.d.ts.map +0 -1
  117. package/dist/error/dictionary/workspace.js +0 -99
  118. package/dist/error/dictionary/workspace.js.map +0 -1
  119. package/dist/index.d.ts +0 -6
  120. package/dist/index.d.ts.map +0 -1
  121. package/dist/index.js +0 -6
  122. package/dist/index.js.map +0 -1
  123. package/dist/network/AutoMutation.d.ts +0 -10
  124. package/dist/network/AutoMutation.d.ts.map +0 -1
  125. package/dist/network/AutoMutation.js +0 -20
  126. package/dist/network/AutoMutation.js.map +0 -1
  127. package/dist/network/AutoOperation.d.ts +0 -19
  128. package/dist/network/AutoOperation.d.ts.map +0 -1
  129. package/dist/network/AutoOperation.js +0 -99
  130. package/dist/network/AutoOperation.js.map +0 -1
  131. package/dist/network/AutoQuery.d.ts +0 -19
  132. package/dist/network/AutoQuery.d.ts.map +0 -1
  133. package/dist/network/AutoQuery.js +0 -70
  134. package/dist/network/AutoQuery.js.map +0 -1
  135. package/dist/network/ManualMutation.d.ts +0 -11
  136. package/dist/network/ManualMutation.d.ts.map +0 -1
  137. package/dist/network/ManualMutation.js +0 -32
  138. package/dist/network/ManualMutation.js.map +0 -1
  139. package/dist/network/ManualOperation.d.ts +0 -13
  140. package/dist/network/ManualOperation.d.ts.map +0 -1
  141. package/dist/network/ManualOperation.js +0 -53
  142. package/dist/network/ManualOperation.js.map +0 -1
  143. package/dist/network/ManualQuery.d.ts +0 -20
  144. package/dist/network/ManualQuery.d.ts.map +0 -1
  145. package/dist/network/ManualQuery.js +0 -77
  146. package/dist/network/ManualQuery.js.map +0 -1
  147. package/dist/network/NetworkClient.d.ts +0 -20
  148. package/dist/network/NetworkClient.d.ts.map +0 -1
  149. package/dist/network/NetworkClient.js +0 -85
  150. package/dist/network/NetworkClient.js.map +0 -1
  151. package/dist/network/ReactQueryNetworkClient.d.ts +0 -16
  152. package/dist/network/ReactQueryNetworkClient.d.ts.map +0 -1
  153. package/dist/network/ReactQueryNetworkClient.js +0 -125
  154. package/dist/network/ReactQueryNetworkClient.js.map +0 -1
  155. package/dist/network/react-query-client.d.ts +0 -3
  156. package/dist/network/react-query-client.d.ts.map +0 -1
  157. package/dist/network/react-query-client.js +0 -3
  158. package/dist/network/react-query-client.js.map +0 -1
  159. package/dist/network/types.d.ts +0 -55
  160. package/dist/network/types.d.ts.map +0 -1
  161. package/dist/network/types.js +0 -2
  162. package/dist/network/types.js.map +0 -1
  163. package/src/api/plugin.ts +0 -685
package/CHANGELOG.md ADDED
@@ -0,0 +1,21 @@
1
+ # Changelog
2
+
3
+ ## [0.3.0](https://github.com/stack-spot/portal-commons/compare/portal-network@v0.2.0...portal-network@v0.3.0) (2024-08-02)
4
+
5
+
6
+ ### Features
7
+
8
+ * network - member ([#220](https://github.com/stack-spot/portal-commons/issues/220)) ([5bf22c2](https://github.com/stack-spot/portal-commons/commit/5bf22c29e25215052c0ad63dd6266695f437994b))
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * rewrite network client methods ([#216](https://github.com/stack-spot/portal-commons/issues/216)) ([f71bcfe](https://github.com/stack-spot/portal-commons/commit/f71bcfe53c95593e59e4cf69f23b176ab96cf02a))
14
+
15
+ ## [0.2.0](https://github.com/stack-spot/portal-commons/compare/portal-network-v0.1.0...portal-network@v0.2.0) (2024-07-31)
16
+
17
+
18
+ ### Features
19
+
20
+ * network library ([eec8b1b](https://github.com/stack-spot/portal-commons/commit/eec8b1b24c77d055884b8ed8c2ccac452c5b16e2))
21
+ * network: infinite query ([#214](https://github.com/stack-spot/portal-commons/issues/214)) ([aded3f7](https://github.com/stack-spot/portal-commons/commit/aded3f78665a829fd31d78766be7d5942aaa62e3))
package/package.json CHANGED
@@ -1,13 +1,19 @@
1
1
  {
2
2
  "name": "@stack-spot/portal-network",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "exports": {
8
8
  ".": "./dist/index.js",
9
+ "./package.json": "./package.json",
9
10
  "./api/*": "./dist/api/*.js"
10
11
  },
12
+ "scripts": {
13
+ "build": "rimraf dist && tsc-silent -p tsconfig.build.json --suppress @/src/api/ && tsc-esm-fix --target='dist'",
14
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
15
+ "generate": "tsx ./scripts/generate-apis.ts"
16
+ },
11
17
  "peerDependencies": {
12
18
  "@stack-spot/auth": "^5.2.0",
13
19
  "@stack-spot/opa": "^2.2.0",
@@ -47,10 +53,5 @@
47
53
  "dependencies": {
48
54
  "@oazapfts/runtime": "^1.0.3",
49
55
  "lodash": "^4.17.21"
50
- },
51
- "scripts": {
52
- "build": "rimraf dist && tsc-silent -p tsconfig.build.json --suppress @/src/api/ && tsc-esm-fix --target='dist'",
53
- "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
54
- "generate": "tsx ./scripts/generate-apis.ts"
55
56
  }
56
57
  }
package/src/apis.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "ai": {
3
3
  "url": {
4
- "dev": "https://code-buddy-api.dev.stackspot.com",
5
- "stg": "https://code-buddy-api.stg.stackspot.com",
4
+ "dev": "https://genai-code-buddy-api.dev.stackspot.com",
5
+ "stg": "https://genai-code-buddy-api.stg.stackspot.com",
6
6
  "prd": "https://genai-code-buddy-api.stackspot.com"
7
7
  },
8
8
  "docs": "/openapi.json"
@@ -79,14 +79,6 @@
79
79
  },
80
80
  "docs": "/v3/api-docs"
81
81
  },
82
- "plugin": {
83
- "url": {
84
- "dev": "https://content-plugin-api.dev.stackspot.com",
85
- "stg": "https://content-plugin-api.stg.stackspot.com",
86
- "prd": "https://plugin-api.v1.stackspot.com"
87
- },
88
- "docs": "/openapi.json"
89
- },
90
82
  "workflows": {
91
83
  "url": {
92
84
  "dev": "https://workflow-workflow-api.dev.stackspot.com",
@@ -1,9 +1,19 @@
1
1
  import { HttpError } from '@oazapfts/runtime'
2
2
  import {
3
- accountDataIsAvailable, create, createPartner,
3
+ accountDataIsAvailable,
4
+ bindToGroups, bindToRoles, create, createPartner,
5
+ createUser,
6
+ deactivateFidoCredentials,
4
7
  defaults,
5
- deletePartner, getFeatures, getPartnerAccount, getPartnersSharingAllowed,
6
- getPersonalClientCredentials, updatePartnerAccountAdminData, updatePartnerAccountData, validateNewPartnerData,
8
+ deleteMember,
9
+ deletePartner, enableFidoCredentials, getAccountMembers1, getAllMemberFidoCredentials, getFeatures,
10
+ getMemberById,
11
+ getMemberGroups,
12
+ getPartnerAccount, getPartnersSharingAllowed,
13
+ getPersonalClientCredentials,
14
+ getResources1,
15
+ getRoles1, removeRoleFromMember, resetPassword, updatePartnerAccountAdminData, updatePartnerAccountData, updateUser,
16
+ validateNewPartnerData,
7
17
  validatePartnerAssociationLimit,
8
18
  } from '../api/account'
9
19
  import apis from '../apis.json'
@@ -21,17 +31,54 @@ class AccountClient extends ReactQueryNetworkClient {
21
31
  return new DefaultAPIError(error.data, error.status, accountDictionary, error.headers)
22
32
  }
23
33
 
34
+ /**
35
+ * Gets credentials from personal service client (create if not exists one to the logged user).
36
+ */
24
37
  generatePersonalClientCredentials = this.mutation(getPersonalClientCredentials)
25
- create = this.mutation(create)
38
+ /**
39
+ * Creates a Feature Flag
40
+ */
41
+ createFeatureFlag = this.mutation(create)
42
+ /**
43
+ * Returns information if account data (name and slug) are available to be registered
44
+ */
26
45
  isAvailable = this.query(accountDataIsAvailable)
46
+ /**
47
+ * Lists all Feature Flags in an Account
48
+ */
27
49
  featureFlags = this.query(getFeatures)
50
+ /**
51
+ * Gets Partners with whom it is allowed to share content.
52
+ */
28
53
  partners = this.query(getPartnersSharingAllowed)
54
+ /**
55
+ * Gets Partner by account Id
56
+ */
29
57
  partner = this.query(getPartnerAccount)
58
+ /**
59
+ * Creates an Account Order for Partner
60
+ */
30
61
  createPartner = this.mutation(createPartner)
62
+ /**
63
+ * Updates Partner Account data.
64
+ */
31
65
  updatePartner = this.mutation(updatePartnerAccountData)
66
+ /**
67
+ * Updates Partner Account Admin data.
68
+ */
32
69
  updatePartnerAdmin = this.mutation(updatePartnerAccountAdminData)
70
+ /**
71
+ * Deletes Partner
72
+ */
33
73
  deactivatePartner = this.mutation(deletePartner)
74
+ /**
75
+ * Validates new Partner account data
76
+ */
34
77
  validateNewPartnerData = this.mutation(validateNewPartnerData)
78
+ /**
79
+ * Validates the association limit for the partner. Yields `{ isValid: true }` if valid or `{ isValid: false, message: string }`
80
+ * otherwise.
81
+ */
35
82
  validatePartnerAssociationLimit = this.query({
36
83
  name: 'validatePartnerAssociationLimit',
37
84
  request: async (signal) => {
@@ -47,6 +94,66 @@ class AccountClient extends ReactQueryNetworkClient {
47
94
  }
48
95
  },
49
96
  })
97
+ /**
98
+ * Gets member by id.
99
+ */
100
+ member = this.query(getMemberById)
101
+ /**
102
+ * Gets all members (paginated).
103
+ */
104
+ allMembers = this.infiniteQuery(getAccountMembers1)
105
+ /**
106
+ * Gets member Groups (paginated).
107
+ */
108
+ memberGroups = this.infiniteQuery(getMemberGroups)
109
+ /**
110
+ * Gets member roles (paginated).
111
+ */
112
+ memberRoles = this.infiniteQuery(getRoles1)
113
+ /**
114
+ * Gets member resources.
115
+ */
116
+ memberResources = this.query(getResources1)
117
+ /**
118
+ * Gets All Fido credentials for the given member (paginated).
119
+ */
120
+ fidoCredentials = this.infiniteQuery(getAllMemberFidoCredentials, { accumulator: 'items' })
121
+ /**
122
+ * Creates member on current tenant.
123
+ */
124
+ createMember = this.mutation(createUser)
125
+ /**
126
+ * Updates member on current tenant.
127
+ */
128
+ updateMember = this.mutation(updateUser)
129
+ /**
130
+ * Adds a member to several groups.
131
+ */
132
+ addMemberToGroups = this.mutation(bindToGroups)
133
+ /**
134
+ * Attributes several roles to a member.
135
+ */
136
+ addRolesToMember = this.mutation(bindToRoles)
137
+ /**
138
+ * Removes a role from a member.
139
+ */
140
+ removeRoleFromMember = this.mutation(removeRoleFromMember)
141
+ /**
142
+ * Sends an e-mail to reset the password of the member with the provided e-mail address.
143
+ */
144
+ resetMemberPassword = this.mutation(resetPassword)
145
+ /**
146
+ * Enables Fido credentials for the given member.
147
+ */
148
+ enableFidoCredentials = this.mutation(enableFidoCredentials)
149
+ /**
150
+ * Disables Fido credentials for the given member.
151
+ */
152
+ disableFidoCredentials = this.mutation(deactivateFidoCredentials)
153
+ /**
154
+ * Removes a member from a group
155
+ */
156
+ removeMemberFromGroup = this.mutation(deleteMember)
50
157
  }
51
158
 
52
159
  export const accountClient = new AccountClient()
@@ -1,5 +1,8 @@
1
1
  import { StackspotAPIError } from './StackspotAPIError'
2
2
 
3
+ /**
4
+ * This error is thrown when a request is canceled by the user before it completes.
5
+ */
3
6
  export class CanceledError extends StackspotAPIError {
4
7
  constructor() {
5
8
  super({ status: 0, message: lang => lang === 'en' ? 'Canceled by the user' : 'Cancelado pelo usuário' })
@@ -34,11 +34,37 @@ function createMessage(raw: ErrorResponse, dictionary: Dictionary, language: Lan
34
34
  return `${title}\n${details?.join('\n')}`
35
35
  }
36
36
 
37
+ /**
38
+ * This represents the Error thrown by most Stackspot APIs.
39
+ */
37
40
  export class DefaultAPIError extends StackspotAPIError {
41
+ /**
42
+ * The error object as defined by the Stackspot API. If the response doesn't match the expected format this will be undefined.
43
+ */
38
44
  data?: ErrorResponse
45
+ /**
46
+ * The response data, if this matches the expected format expected by a Stackspot Error, it will be the same as `data`.
47
+ */
39
48
  raw?: any
40
49
 
41
- constructor(rawResponse: any, status: number, dictionary: Dictionary, headers?: Headers) {
50
+ constructor(
51
+ /**
52
+ * The response's data
53
+ */
54
+ rawResponse: any,
55
+ /**
56
+ * The response's status
57
+ */
58
+ status: number,
59
+ /**
60
+ * A dictionary for translating error codes and descriptions.
61
+ */
62
+ dictionary: Dictionary,
63
+ /**
64
+ * The response's headers.
65
+ */
66
+ headers?: Headers,
67
+ ) {
42
68
  super({
43
69
  status: status,
44
70
  code: rawResponse.code,
@@ -3,16 +3,42 @@ import { Language, getLanguage } from '@stack-spot/portal-translate'
3
3
  type InternationalizedMessage = (language: Language) => string
4
4
 
5
5
  interface ErrorProperties {
6
+ /**
7
+ * The response's status.
8
+ */
6
9
  status: number,
10
+ /**
11
+ * The response's headers.
12
+ */
7
13
  headers?: Headers,
14
+ /**
15
+ * The error code defined by the API, if any.
16
+ */
8
17
  code?: string,
18
+ /**
19
+ * The error message: may be a simple string or a function that returns a string depending on the language passed as parameter.
20
+ *
21
+ * If not provided, will attempt to use the error code or 'unknown'.
22
+ */
9
23
  message?: InternationalizedMessage | string,
24
+ /**
25
+ * The error's stack trace, if any.
26
+ */
10
27
  stack?: string,
11
28
  }
12
29
 
13
30
  export class StackspotAPIError extends Error {
31
+ /**
32
+ * The response's status.
33
+ */
14
34
  status: number
35
+ /**
36
+ * The response's headers.
37
+ */
15
38
  headers: Headers | undefined
39
+ /**
40
+ * The error code defined by the API, if any.
41
+ */
16
42
  code: string | undefined
17
43
  private intl?: InternationalizedMessage
18
44
 
@@ -25,7 +51,13 @@ export class StackspotAPIError extends Error {
25
51
  this.intl = typeof message === 'string' ? () => message : message
26
52
  }
27
53
 
54
+ /**
55
+ * Translates the error to the given language.
56
+ * @param language
57
+ * @returns an error message
58
+ */
28
59
  translate(language: Language = getLanguage()) {
29
- return this.intl?.(language) ?? this.message
60
+ const unknown = language === 'en' ? 'unknown error' : 'erro desconhecido'
61
+ return this.intl?.(language) ?? this.message ?? this.code ?? (this.status === 0 ? unknown : `${this.status}`)
30
62
  }
31
63
  }
package/src/index.ts CHANGED
@@ -3,3 +3,4 @@ export { DefaultAPIError } from './error/DefaultAPIError'
3
3
  export { StackspotAPIError } from './error/StackspotAPIError'
4
4
  export { NetworkClient } from './network/NetworkClient'
5
5
  export { queryClient } from './network/react-query-client'
6
+ export { useExtendedList } from './utils/use-extended-list'
@@ -0,0 +1,104 @@
1
+ /* eslint-disable react-hooks/rules-of-hooks */
2
+
3
+ import {
4
+ InfiniteData, QueryFunctionContext, QueryKey,
5
+ UseInfiniteQueryResult,
6
+ useInfiniteQuery,
7
+ useSuspenseInfiniteQuery,
8
+ } from '@tanstack/react-query'
9
+ import { StackspotAPIError } from '../error/StackspotAPIError'
10
+ import { AutoQuery } from './AutoQuery'
11
+ import { queryClient } from './react-query-client'
12
+ import { AutoQueryObjectParams, InfiniteQueryObject, InfiniteQueryOptions, UseInfiniteQueryObjectOptions } from './types'
13
+
14
+ export class AutoInfiniteQuery<Variables, Result, PageParamName extends keyof Variables, Accumulator extends keyof Result | ''>
15
+ extends AutoQuery<Variables, Result>
16
+ implements InfiniteQueryObject<Variables, Result, Accumulator>
17
+ {
18
+ private options: Required<InfiniteQueryOptions<Variables, Result, PageParamName, Accumulator | ''>>
19
+
20
+ constructor(
21
+ params: AutoQueryObjectParams<Variables, Result>,
22
+ options: InfiniteQueryOptions<Variables, Result, PageParamName, Accumulator>,
23
+ ) {
24
+ super(params)
25
+ this.options = {
26
+ ...options,
27
+ accumulator: options.accumulator ?? '',
28
+ defaultVariables: options.defaultVariables ?? {},
29
+ }
30
+ }
31
+
32
+ private createInfiniteQueryFn(
33
+ variables: Variables | undefined,
34
+ ): (context: QueryFunctionContext<QueryKey, Variables[PageParamName]>) => Promise<Result> {
35
+ return async ({ pageParam }) => {
36
+ const paginatedVariables = {
37
+ ...variables,
38
+ [this.options.pageParamName]: pageParam ?? variables?.[this.options.pageParamName],
39
+ } as Variables
40
+ if (!this.currentRequests.has(paginatedVariables)) this.currentRequests.set(paginatedVariables, this.callFn(paginatedVariables))
41
+ const result = await this.currentRequests.get(paginatedVariables)
42
+ this.currentRequests.delete(paginatedVariables)
43
+ return result!
44
+ }
45
+ }
46
+
47
+ private getListFromData(data: InfiniteData<Result> | undefined) {
48
+ return data?.pages.map(
49
+ page => this.options.accumulator ? page[this.options.accumulator as keyof Result] : page,
50
+ ).flat() as Accumulator extends keyof Result ? Result[Accumulator] : Result
51
+ }
52
+
53
+ private useInfiniteQueryResult(suspense: boolean, variables = {} as Variables, options?: UseInfiniteQueryObjectOptions) {
54
+ variables = { ...variables, ...this.options.defaultVariables }
55
+ const use = suspense ? useSuspenseInfiniteQuery : useInfiniteQuery
56
+ return use<any, any, any, any, any>({
57
+ ...options,
58
+ queryKey: ['infinite', ...this.getKey(variables)],
59
+ queryFn: this.createInfiniteQueryFn(variables),
60
+ initialPageParam: this.options.initialPageParam,
61
+ getNextPageParam: (lastPage, allPages, lastPageParam, allPageParams) =>
62
+ this.options.getNextPageParam({ variables, lastPage, allPages, lastPageParam, allPageParams }),
63
+ }, queryClient) as UseInfiniteQueryResult<InfiniteData<Result>, StackspotAPIError>
64
+ }
65
+
66
+ useInfiniteQuery(
67
+ variables?: Variables,
68
+ options?: UseInfiniteQueryObjectOptions,
69
+ ): [
70
+ Accumulator extends keyof Result ? Result[Accumulator] : Result,
71
+ UseInfiniteQueryResult<InfiniteData<Result>, StackspotAPIError>,
72
+ ] {
73
+ const result = this.useInfiniteQueryResult(true, variables, options)
74
+ return [
75
+ this.getListFromData(result.data),
76
+ result,
77
+ ]
78
+ }
79
+
80
+ useStatefulInfiniteQuery(
81
+ variables?: Variables,
82
+ options?: UseInfiniteQueryObjectOptions,
83
+ ): [
84
+ Accumulator extends keyof Result ? Result[Accumulator] : Result,
85
+ boolean,
86
+ StackspotAPIError | undefined | null,
87
+ UseInfiniteQueryResult<InfiniteData<Result>, StackspotAPIError>,
88
+ ] {
89
+ const result = this.useInfiniteQueryResult(false, variables, options)
90
+ return [
91
+ this.getListFromData(result.data),
92
+ result.isPending,
93
+ result.error,
94
+ result,
95
+ ]
96
+ }
97
+
98
+ async invalidate(variables?: Partial<Variables> | undefined): Promise<void> {
99
+ await Promise.all([
100
+ super.invalidate(variables),
101
+ queryClient.invalidateQueries({ queryKey: ['infinite', ...this.getKey(variables)] }),
102
+ ])
103
+ }
104
+ }
@@ -61,7 +61,13 @@ export abstract class AutoOperation<Variables> implements OperationObject<Variab
61
61
  ? [options?: Omit<UseQueryOptions, 'queryFn' | 'queryKey'>]
62
62
  : [variables?: Partial<Variables>, options?: Omit<UseQueryOptions, 'queryFn' | 'queryKey'>]
63
63
  ) {
64
- const [variables, options] = args.length === 2 ? args : [undefined, args[0]]
64
+ /* `this.fn` is a oazapfts function, i.e. it has arity 1 or 2. If it accepts variables, its arity is 2: the 1st parameter is the
65
+ variables and the 2nd is the RequestOpts. If it doesn't accept variables, its arity is one: it accepts only the RequestOpts.
66
+ We can use this information to determine what the type of `args` actually is at runtime. If variables are accepted, than the 1st
67
+ argument is the variables and the 2nd is the query options, otherwise, it has a single argument, which is the query options. */
68
+ const [variables, options] = this.fn.length > 1
69
+ ? args as [Variables, Omit<UseQueryOptions, 'queryFn' | 'queryKey'> | undefined]
70
+ : [undefined, args[0] as Omit<UseQueryOptions, 'queryFn' | 'queryKey'> | undefined]
65
71
  const result = useQuery({
66
72
  ...options,
67
73
  queryKey: this.getPermissionKey(variables as Variables),
@@ -10,7 +10,8 @@ export class AutoQuery<Variables, Result> extends AutoOperation<Variables> imple
10
10
  /**
11
11
  * Prevents the same request from being triggered more than once if subsequent calls are made before the first ends.
12
12
  */
13
- private currentRequests = new Map<Variables | undefined, Promise<Result>>()
13
+ protected currentRequests = new Map<Variables | undefined, Promise<Result>>()
14
+
14
15
  constructor(params: AutoQueryObjectParams<Variables, Result>) {
15
16
  super(params)
16
17
  }
@@ -0,0 +1,95 @@
1
+ /* eslint-disable react-hooks/rules-of-hooks */
2
+
3
+ import { InfiniteData, QueryFunctionContext, QueryKey, UseInfiniteQueryResult, useInfiniteQuery, useSuspenseInfiniteQuery } from '@tanstack/react-query'
4
+ import { StackspotAPIError } from '../error/StackspotAPIError'
5
+ import { ManualQuery } from './ManualQuery'
6
+ import { queryClient } from './react-query-client'
7
+ import { FullOperationConfig, InfiniteQueryConfig, InfiniteQueryObject, UseInfiniteQueryObjectOptions } from './types'
8
+
9
+ export class ManualInfiniteQuery<
10
+ Variables extends Record<string, any>,
11
+ Result,
12
+ PageParamName extends keyof Variables,
13
+ Accumulator extends keyof Result | ''
14
+ > extends ManualQuery<Variables, Result> implements InfiniteQueryObject<Variables, Result, Accumulator> {
15
+ constructor(config: InfiniteQueryConfig<Variables, Result, PageParamName, Accumulator> & { apiName: string }) {
16
+ super(config as FullOperationConfig<any, any>)
17
+ }
18
+
19
+ private getConfig() {
20
+ return this.config as unknown as InfiniteQueryConfig<Variables, Result, PageParamName, Accumulator>
21
+ }
22
+
23
+ private createInfiniteQueryFn(
24
+ variables: Variables,
25
+ ): (context: QueryFunctionContext<QueryKey, Variables[PageParamName]>) => Promise<Result> {
26
+ return async ({ pageParam }) => {
27
+ const paginatedVariables = {
28
+ ...variables,
29
+ [this.getConfig().pageParamName]: pageParam ?? variables?.[this.getConfig().pageParamName],
30
+ } as Variables
31
+ if (!this.currentRequests.has(paginatedVariables)) this.currentRequests.set(paginatedVariables, this.makeRequest(paginatedVariables))
32
+ const result = await this.currentRequests.get(paginatedVariables)
33
+ this.currentRequests.delete(paginatedVariables)
34
+ return result!
35
+ }
36
+ }
37
+
38
+ private getListFromData(data: InfiniteData<Result> | undefined) {
39
+ return data?.pages.map(
40
+ page => this.getConfig().accumulator ? page[this.getConfig().accumulator as keyof Result] : page,
41
+ ).flat() as Accumulator extends keyof Result ? Result[Accumulator] : Result
42
+ }
43
+
44
+ private useInfiniteQueryResult(suspense: boolean, variables = {} as Variables, options?: UseInfiniteQueryObjectOptions) {
45
+ variables = { ...variables, ...this.getConfig().defaultVariables }
46
+ const use = suspense ? useSuspenseInfiniteQuery : useInfiniteQuery
47
+ return use<any, any, any, any, any>({
48
+ ...options,
49
+ queryKey: ['infinite', ...this.getKey(variables)],
50
+ queryFn: this.createInfiniteQueryFn(variables),
51
+ initialPageParam: this.getConfig().initialPageParam,
52
+ getNextPageParam: (lastPage, allPages, lastPageParam, allPageParams) =>
53
+ this.getConfig().getNextPageParam({ variables, lastPage, allPages, lastPageParam, allPageParams }),
54
+ }, queryClient) as UseInfiniteQueryResult<InfiniteData<Result>, StackspotAPIError>
55
+ }
56
+
57
+ useInfiniteQuery(
58
+ variables?: Variables,
59
+ options?: UseInfiniteQueryObjectOptions,
60
+ ): [
61
+ Accumulator extends keyof Result ? Result[Accumulator] : Result,
62
+ UseInfiniteQueryResult<InfiniteData<Result>, StackspotAPIError>,
63
+ ] {
64
+ const result = this.useInfiniteQueryResult(true, variables, options)
65
+ return [
66
+ this.getListFromData(result.data),
67
+ result,
68
+ ]
69
+ }
70
+
71
+ useStatefulInfiniteQuery(
72
+ variables?: Variables,
73
+ options?: UseInfiniteQueryObjectOptions,
74
+ ): [
75
+ Accumulator extends keyof Result ? Result[Accumulator] : Result,
76
+ boolean,
77
+ StackspotAPIError | undefined | null,
78
+ UseInfiniteQueryResult<InfiniteData<Result>, StackspotAPIError>,
79
+ ] {
80
+ const result = this.useInfiniteQueryResult(false, variables, options)
81
+ return [
82
+ this.getListFromData(result.data),
83
+ result.isPending,
84
+ result.error,
85
+ result,
86
+ ]
87
+ }
88
+
89
+ async invalidate(variables?: Partial<Variables> | undefined): Promise<void> {
90
+ await Promise.all([
91
+ super.invalidate(variables),
92
+ queryClient.invalidateQueries({ queryKey: ['infinite', ...this.getKey(variables)] }),
93
+ ])
94
+ }
95
+ }
@@ -13,13 +13,13 @@ export class ManualQuery<
13
13
  /**
14
14
  * Prevents the same request from being triggered more than once if subsequent calls are made before the first ends.
15
15
  */
16
- private currentRequests = new Map<Record<string, any> | undefined, Promise<Result>>()
16
+ protected currentRequests = new Map<Record<string, any> | undefined, Promise<Result>>()
17
17
 
18
18
  constructor(config: FullOperationConfig<Variables extends void ? [AbortSignal] : [AbortSignal, Variables], Result>) {
19
19
  super(config)
20
20
  }
21
21
 
22
- private async makeRequest(variables: Record<string, any> | undefined) {
22
+ protected async makeRequest(variables: Record<string, any> | undefined) {
23
23
  const abortController = new AbortController()
24
24
  this.abortMap.set(variables, [abortController])
25
25
  try {