@stack-spot/portal-network 0.2.0 → 0.3.1

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 (164) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/api/account.d.ts +2368 -0
  3. package/dist/api/account.d.ts.map +1 -0
  4. package/dist/api/account.js +1521 -0
  5. package/dist/api/account.js.map +1 -0
  6. package/dist/api/ai.d.ts +1432 -0
  7. package/dist/api/ai.d.ts.map +1 -0
  8. package/dist/api/ai.js +1342 -0
  9. package/dist/api/ai.js.map +1 -0
  10. package/dist/api/apiRuntime.d.ts +922 -0
  11. package/dist/api/apiRuntime.d.ts.map +1 -0
  12. package/dist/api/apiRuntime.js +599 -0
  13. package/dist/api/apiRuntime.js.map +1 -0
  14. package/dist/api/cloudAccount.d.ts +473 -0
  15. package/dist/api/cloudAccount.d.ts.map +1 -0
  16. package/dist/api/cloudAccount.js +300 -0
  17. package/dist/api/cloudAccount.js.map +1 -0
  18. package/dist/api/cloudServices.d.ts +1233 -0
  19. package/dist/api/cloudServices.d.ts.map +1 -0
  20. package/dist/api/cloudServices.js +715 -0
  21. package/dist/api/cloudServices.js.map +1 -0
  22. package/dist/api/insights.d.ts +123 -0
  23. package/dist/api/insights.d.ts.map +1 -0
  24. package/dist/api/insights.js +112 -0
  25. package/dist/api/insights.js.map +1 -0
  26. package/dist/api/serviceCatalog.d.ts +737 -0
  27. package/dist/api/serviceCatalog.d.ts.map +1 -0
  28. package/dist/api/serviceCatalog.js +611 -0
  29. package/dist/api/serviceCatalog.js.map +1 -0
  30. package/dist/api/workflows.d.ts +366 -0
  31. package/dist/api/workflows.d.ts.map +1 -0
  32. package/dist/api/workflows.js +175 -0
  33. package/dist/api/workflows.js.map +1 -0
  34. package/dist/api/workspace.js +1476 -0
  35. package/dist/api/workspace.js.map +1 -0
  36. package/dist/api/workspaceManager.d.ts +1121 -0
  37. package/dist/api/workspaceManager.d.ts.map +1 -0
  38. package/dist/api/workspaceManager.js +357 -0
  39. package/dist/api/workspaceManager.js.map +1 -0
  40. package/dist/api/workspaceSearchEngine.d.ts +93 -0
  41. package/dist/api/workspaceSearchEngine.d.ts.map +1 -0
  42. package/dist/api/workspaceSearchEngine.js +55 -0
  43. package/dist/api/workspaceSearchEngine.js.map +1 -0
  44. package/dist/apis.json +121 -0
  45. package/dist/client/account.d.ts +217 -0
  46. package/dist/client/account.d.ts.map +1 -0
  47. package/dist/client/account.js +276 -0
  48. package/dist/client/account.js.map +1 -0
  49. package/dist/error/CanceledError.d.ts +8 -0
  50. package/dist/error/CanceledError.d.ts.map +1 -0
  51. package/dist/error/CanceledError.js +10 -0
  52. package/dist/error/CanceledError.js.map +1 -0
  53. package/dist/error/DefaultAPIError.d.ts +34 -0
  54. package/dist/error/DefaultAPIError.d.ts.map +1 -0
  55. package/dist/error/DefaultAPIError.js +82 -0
  56. package/dist/error/DefaultAPIError.js.map +1 -0
  57. package/dist/error/StackspotAPIError.d.ts +50 -0
  58. package/dist/error/StackspotAPIError.d.ts.map +1 -0
  59. package/dist/error/StackspotAPIError.js +54 -0
  60. package/dist/error/StackspotAPIError.js.map +1 -0
  61. package/dist/error/dictionary/account.d.ts +55 -0
  62. package/dist/error/dictionary/account.d.ts.map +1 -0
  63. package/dist/error/dictionary/account.js +55 -0
  64. package/dist/error/dictionary/account.js.map +1 -0
  65. package/dist/error/dictionary/action.d.ts +163 -0
  66. package/dist/error/dictionary/action.d.ts.map +1 -0
  67. package/dist/error/dictionary/action.js +163 -0
  68. package/dist/error/dictionary/action.js.map +1 -0
  69. package/dist/error/dictionary/base.d.ts +21 -0
  70. package/dist/error/dictionary/base.d.ts.map +1 -0
  71. package/dist/error/dictionary/base.js +21 -0
  72. package/dist/error/dictionary/base.js.map +1 -0
  73. package/dist/error/dictionary/cnt-fields.d.ts +13 -0
  74. package/dist/error/dictionary/cnt-fields.d.ts.map +1 -0
  75. package/dist/error/dictionary/cnt-fields.js +13 -0
  76. package/dist/error/dictionary/cnt-fields.js.map +1 -0
  77. package/dist/error/dictionary/cnt.d.ts +79 -0
  78. package/dist/error/dictionary/cnt.d.ts.map +1 -0
  79. package/dist/error/dictionary/cnt.js +79 -0
  80. package/dist/error/dictionary/cnt.js.map +1 -0
  81. package/dist/error/dictionary/rte.d.ts +23 -0
  82. package/dist/error/dictionary/rte.d.ts.map +1 -0
  83. package/dist/error/dictionary/rte.js +23 -0
  84. package/dist/error/dictionary/rte.js.map +1 -0
  85. package/dist/error/dictionary/rtm.d.ts +9 -0
  86. package/dist/error/dictionary/rtm.d.ts.map +1 -0
  87. package/dist/error/dictionary/rtm.js +9 -0
  88. package/dist/error/dictionary/rtm.js.map +1 -0
  89. package/dist/error/dictionary/workspace-fields.d.ts +9 -0
  90. package/dist/error/dictionary/workspace-fields.d.ts.map +1 -0
  91. package/dist/error/dictionary/workspace-fields.js +9 -0
  92. package/dist/error/dictionary/workspace-fields.js.map +1 -0
  93. package/dist/error/dictionary/workspace.d.ts +99 -0
  94. package/dist/error/dictionary/workspace.d.ts.map +1 -0
  95. package/dist/error/dictionary/workspace.js +99 -0
  96. package/dist/error/dictionary/workspace.js.map +1 -0
  97. package/dist/index.d.ts +7 -0
  98. package/dist/index.d.ts.map +1 -0
  99. package/dist/index.js +7 -0
  100. package/dist/index.js.map +1 -0
  101. package/dist/network/AutoInfiniteQuery.d.ts +23 -0
  102. package/dist/network/AutoInfiniteQuery.d.ts.map +1 -0
  103. package/dist/network/AutoInfiniteQuery.js +70 -0
  104. package/dist/network/AutoInfiniteQuery.js.map +1 -0
  105. package/dist/network/AutoMutation.d.ts +10 -0
  106. package/dist/network/AutoMutation.d.ts.map +1 -0
  107. package/dist/network/AutoMutation.js +20 -0
  108. package/dist/network/AutoMutation.js.map +1 -0
  109. package/dist/network/AutoOperation.d.ts +19 -0
  110. package/dist/network/AutoOperation.d.ts.map +1 -0
  111. package/dist/network/AutoOperation.js +105 -0
  112. package/dist/network/AutoOperation.js.map +1 -0
  113. package/dist/network/AutoQuery.d.ts +19 -0
  114. package/dist/network/AutoQuery.d.ts.map +1 -0
  115. package/dist/network/AutoQuery.js +70 -0
  116. package/dist/network/AutoQuery.js.map +1 -0
  117. package/dist/network/ManualInfiniteQuery.d.ts +25 -0
  118. package/dist/network/ManualInfiniteQuery.d.ts.map +1 -0
  119. package/dist/network/ManualInfiniteQuery.js +62 -0
  120. package/dist/network/ManualInfiniteQuery.js.map +1 -0
  121. package/dist/network/ManualMutation.d.ts +11 -0
  122. package/dist/network/ManualMutation.d.ts.map +1 -0
  123. package/dist/network/ManualMutation.js +32 -0
  124. package/dist/network/ManualMutation.js.map +1 -0
  125. package/dist/network/ManualOperation.d.ts +13 -0
  126. package/dist/network/ManualOperation.d.ts.map +1 -0
  127. package/dist/network/ManualOperation.js +53 -0
  128. package/dist/network/ManualOperation.js.map +1 -0
  129. package/dist/network/ManualQuery.d.ts +20 -0
  130. package/dist/network/ManualQuery.d.ts.map +1 -0
  131. package/dist/network/ManualQuery.js +77 -0
  132. package/dist/network/ManualQuery.js.map +1 -0
  133. package/dist/network/NetworkClient.d.ts +58 -0
  134. package/dist/network/NetworkClient.d.ts.map +1 -0
  135. package/dist/network/NetworkClient.js +107 -0
  136. package/dist/network/NetworkClient.js.map +1 -0
  137. package/dist/network/ReactQueryNetworkClient.d.ts +78 -0
  138. package/dist/network/ReactQueryNetworkClient.d.ts.map +1 -0
  139. package/dist/network/ReactQueryNetworkClient.js +144 -0
  140. package/dist/network/ReactQueryNetworkClient.js.map +1 -0
  141. package/dist/network/react-query-client.d.ts +6 -0
  142. package/dist/network/react-query-client.d.ts.map +1 -0
  143. package/dist/network/react-query-client.js +6 -0
  144. package/dist/network/react-query-client.js.map +1 -0
  145. package/dist/network/types.d.ts +234 -0
  146. package/dist/network/types.d.ts.map +1 -0
  147. package/dist/network/types.js +2 -0
  148. package/dist/network/types.js.map +1 -0
  149. package/dist/utils/use-extended-list.d.ts +39 -0
  150. package/dist/utils/use-extended-list.d.ts.map +1 -0
  151. package/dist/utils/use-extended-list.js +36 -0
  152. package/dist/utils/use-extended-list.js.map +1 -0
  153. package/package.json +1 -1
  154. package/src/client/account.ts +79 -14
  155. package/src/error/DefaultAPIError.ts +2 -3
  156. package/src/error/StackspotAPIError.ts +1 -1
  157. package/src/index.ts +1 -0
  158. package/src/network/AutoInfiniteQuery.ts +7 -0
  159. package/src/network/AutoOperation.ts +7 -1
  160. package/src/network/ManualInfiniteQuery.ts +7 -0
  161. package/src/network/NetworkClient.ts +16 -70
  162. package/src/network/ReactQueryNetworkClient.ts +18 -38
  163. package/src/network/types.ts +0 -10
  164. package/src/utils/use-extended-list.ts +80 -0
@@ -1,10 +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, getAccountMembers1, getFeatures,
8
+ deleteMember,
9
+ deletePartner, enableFidoCredentials, getAccountMembers1, getAllMemberFidoCredentials, getFeatures,
10
+ getMemberById,
11
+ getMemberGroups,
6
12
  getPartnerAccount, getPartnersSharingAllowed,
7
- getPersonalClientCredentials, updatePartnerAccountAdminData, updatePartnerAccountData, validateNewPartnerData,
13
+ getPersonalClientCredentials,
14
+ getResources1,
15
+ getRoles1, removeRoleFromMember, resetPassword, updatePartnerAccountAdminData, updatePartnerAccountData, updateUser,
16
+ validateNewPartnerData,
8
17
  validatePartnerAssociationLimit,
9
18
  } from '../api/account'
10
19
  import apis from '../apis.json'
@@ -23,11 +32,11 @@ class AccountClient extends ReactQueryNetworkClient {
23
32
  }
24
33
 
25
34
  /**
26
- * Get credentials from personal service client (create if not exists one to the logged user).
35
+ * Gets credentials from personal service client (create if not exists one to the logged user).
27
36
  */
28
37
  generatePersonalClientCredentials = this.mutation(getPersonalClientCredentials)
29
38
  /**
30
- * Create a Feature Flag
39
+ * Creates a Feature Flag
31
40
  */
32
41
  createFeatureFlag = this.mutation(create)
33
42
  /**
@@ -35,35 +44,35 @@ class AccountClient extends ReactQueryNetworkClient {
35
44
  */
36
45
  isAvailable = this.query(accountDataIsAvailable)
37
46
  /**
38
- * List Feature Flags in an Account
47
+ * Lists all Feature Flags in an Account
39
48
  */
40
49
  featureFlags = this.query(getFeatures)
41
50
  /**
42
- * Get Partners with whom it is allowed to share content.
51
+ * Gets Partners with whom it is allowed to share content.
43
52
  */
44
53
  partners = this.query(getPartnersSharingAllowed)
45
54
  /**
46
- * Get Partner by account Id
55
+ * Gets Partner by account Id
47
56
  */
48
57
  partner = this.query(getPartnerAccount)
49
58
  /**
50
- * Create an Account Order for Partner
59
+ * Creates an Account Order for Partner
51
60
  */
52
61
  createPartner = this.mutation(createPartner)
53
62
  /**
54
- * Update Partner Account data.
63
+ * Updates Partner Account data.
55
64
  */
56
65
  updatePartner = this.mutation(updatePartnerAccountData)
57
66
  /**
58
- * Update Partner Account Admin data.
67
+ * Updates Partner Account Admin data.
59
68
  */
60
69
  updatePartnerAdmin = this.mutation(updatePartnerAccountAdminData)
61
70
  /**
62
- * Delete Partner
71
+ * Deletes Partner
63
72
  */
64
73
  deactivatePartner = this.mutation(deletePartner)
65
74
  /**
66
- * Validate new Partner account data
75
+ * Validates new Partner account data
67
76
  */
68
77
  validateNewPartnerData = this.mutation(validateNewPartnerData)
69
78
  /**
@@ -86,9 +95,65 @@ class AccountClient extends ReactQueryNetworkClient {
86
95
  },
87
96
  })
88
97
  /**
89
- * Get all members (paginated).
98
+ * Gets member by id.
99
+ */
100
+ member = this.query(getMemberById)
101
+ /**
102
+ * Gets all members (paginated).
90
103
  */
91
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)
92
157
  }
93
158
 
94
159
  export const accountClient = new AccountClient()
@@ -1,5 +1,4 @@
1
1
  import { Dictionary, Language } from '@stack-spot/portal-translate'
2
- import { every, isEmpty, isString } from 'lodash'
3
2
  import { ErrorResponse } from '../api/account'
4
3
  import { StackspotAPIError } from './StackspotAPIError'
5
4
  import { baseDictionary } from './dictionary/base'
@@ -24,12 +23,12 @@ function getTitle(raw: ErrorResponse, dictionary: Dictionary, language: Language
24
23
 
25
24
  function createMessage(raw: ErrorResponse, dictionary: Dictionary, language: Language) {
26
25
  const title = getTitle(raw, dictionary, language)
27
- if (isEmpty(raw.validationDetails)) return title
26
+ if (!raw.validationDetails?.length) return title
28
27
  const api = raw.code?.split(/[-_]/)[0]
29
28
  const details = raw.validationDetails?.map((detail) => {
30
29
  const dict: Record<string, string> = (fieldDictionary[api?.toLowerCase() as keyof typeof fieldDictionary] ?? {})[language] ?? {}
31
30
  const name = dict[detail.code] || detail.field || (raw.code !== detail.code && dictionary[language][detail.code]) || ''
32
- return name ? `${name}${detail.values && every(detail.values, isString) ? `\n${detail.values.join('\n')}` : ''}` : undefined
31
+ return name ? `${name}${detail.values ? `\n${detail.values.join('\n')}` : ''}` : undefined
33
32
  })?.filter(d => !!d)
34
33
  return `${title}\n${details?.join('\n')}`
35
34
  }
@@ -58,6 +58,6 @@ export class StackspotAPIError extends Error {
58
58
  */
59
59
  translate(language: Language = getLanguage()) {
60
60
  const unknown = language === 'en' ? 'unknown error' : 'erro desconhecido'
61
- return this.intl?.(language) ?? this.message ?? this.code ?? this.status === 0 ? unknown : `${this.status}`
61
+ return this.intl?.(language) ?? this.message ?? this.code ?? (this.status === 0 ? unknown : `${this.status}`)
62
62
  }
63
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'
@@ -94,4 +94,11 @@ export class AutoInfiniteQuery<Variables, Result, PageParamName extends keyof Va
94
94
  result,
95
95
  ]
96
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
+ }
97
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),
@@ -85,4 +85,11 @@ export class ManualInfiniteQuery<
85
85
  result,
86
86
  ]
87
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
+ }
88
95
  }
@@ -1,7 +1,6 @@
1
- import { mergeHeaders } from '@oazapfts/runtime/headers'
2
1
  import { AuthenticationError } from '@stack-spot/auth'
3
2
  import { requestPermission } from '@stack-spot/opa'
4
- import { Env, HTTPMethod, RequestOptions, RequestWithBody, SessionManager } from './types'
3
+ import { Env, HTTPMethod, SessionManager } from './types'
5
4
 
6
5
  /**
7
6
  * A set of methods for performing network requests to an API.
@@ -72,82 +71,29 @@ export abstract class NetworkClient {
72
71
  return sessionManager
73
72
  }
74
73
 
75
- private sendRequest(path: string, method: HTTPMethod, request?: RequestWithBody): Promise<Response> {
74
+ /**
75
+ * Makes a request (same signature as `globalThis.fetch`). This request will prepend the base url to the url and, if there's an active
76
+ * session, include authentication headers.
77
+ * @param input the url or request object.
78
+ * @param init the fetch options.
79
+ * @returns a promise with the Response.
80
+ */
81
+ protected fetch(input: string | URL | Request, init?: RequestInit): Promise<Response> {
76
82
  const sessionManager = this.getSessionManager()
77
- const url = this.resolveURL(path)
83
+ let inputWithBaseUrl: string | URL | Request = ''
84
+ if (typeof input === 'string') inputWithBaseUrl = this.resolveURL(input)
85
+ else if (input instanceof URL) inputWithBaseUrl = this.resolveURL(input.toString())
86
+ else inputWithBaseUrl = { ...input, url: this.resolveURL(input.url).toString() }
87
+ // some APIs throw errors if the method is lowercase, the following line prevents it
88
+ if (init?.method) init.method = init.method.toUpperCase()
78
89
  try {
79
- if (request?.params) {
80
- Object.keys(request.params).forEach((key) => {
81
- const value = request?.params?.[key]
82
- if (value !== undefined) url.searchParams.set(key, value)
83
- })
84
- }
85
- const isFormData = request?.body instanceof FormData
86
- const isJsonContent = (typeof request?.body === 'object') && !isFormData
87
- const body = isJsonContent ? JSON.stringify(request.body) : request?.body as string | FormData
88
- const defaultHeaders: Record<string, string> = isJsonContent ? { 'Content-Type': 'application/json' } : {}
89
- const headers = mergeHeaders(defaultHeaders, request?.headers)
90
- return (
91
- sessionManager.hasSession()
92
- ? sessionManager.getSession().fetch(url, { method: method.toUpperCase(), headers, body, signal: request?.signal })
93
- : fetch(url, { method: method.toUpperCase(), headers, body, signal: request?.signal })
94
- )
90
+ return sessionManager.hasSession() ? sessionManager.getSession().fetch(inputWithBaseUrl, init) : fetch(inputWithBaseUrl, init)
95
91
  } catch (error) {
96
92
  if (error instanceof AuthenticationError) sessionManager.endSession()
97
93
  throw error
98
94
  }
99
95
  }
100
96
 
101
- /**
102
- * Performs a GET request with the parameters provided.
103
- * @param path the path to the resource.
104
- * @param request the request options.
105
- * @returns a promise that resolves to response's data.
106
- */
107
- protected get(path: string, request?: RequestOptions) {
108
- return this.sendRequest(path, 'get', request)
109
- }
110
-
111
- /**
112
- * Performs a POST request with the parameters provided.
113
- * @param path the path to the resource.
114
- * @param request the request options.
115
- * @returns a promise that resolves to response's data.
116
- */
117
- protected post(path: string, request?: RequestWithBody) {
118
- return this.sendRequest(path, 'post', request)
119
- }
120
-
121
- /**
122
- * Performs a PUT request with the parameters provided.
123
- * @param path the path to the resource.
124
- * @param request the request options.
125
- * @returns a promise that resolves to response's data.
126
- */
127
- protected put(path: string, request?: RequestWithBody) {
128
- return this.sendRequest(path, 'put', request)
129
- }
130
-
131
- /**
132
- * Performs a PATCH request with the parameters provided.
133
- * @param path the path to the resource.
134
- * @param request the request options.
135
- * @returns a promise that resolves to response's data.
136
- */
137
- protected patch(path: string, request?: RequestWithBody) {
138
- return this.sendRequest(path, 'patch', request)
139
- }
140
-
141
- /**
142
- * Performs a DELETE request with the parameters provided.
143
- * @param path the path to the resource.
144
- * @param request the request options.
145
- * @returns a promise that resolves to response's data.
146
- */
147
- protected delete(path: string, request?: RequestWithBody) {
148
- return this.sendRequest(path, 'delete', request)
149
- }
150
-
151
97
  /**
152
98
  * Checks whether or not the current account is freemium.
153
99
  * @returns true if it's a freemium account, false otherwise.
@@ -26,22 +26,7 @@ export abstract class ReactQueryNetworkClient extends NetworkClient {
26
26
  constructor(baseURL: Record<Env, string>, defaults: Defaults<any>) {
27
27
  super(baseURL)
28
28
  defaults.baseUrl = ''
29
- defaults.fetch = (...args) => this.#onFetch(...args)
30
- }
31
-
32
- #getMappedHeaders(headers: HeadersInit | undefined) {
33
- if (!headers) return undefined
34
- if (headers instanceof Headers) {
35
- const headersMap: Record<string, string> = {}
36
- headers.forEach((value, key) => headersMap[key] = value)
37
- return headersMap
38
- }
39
- if (Array.isArray(headers)) {
40
- const headersMap: Record<string, string> = {}
41
- headers.forEach(([key, value]) => headersMap[key] = value)
42
- return headersMap
43
- }
44
- return headers
29
+ defaults.fetch = (...args) => this.fetch(...args)
45
30
  }
46
31
 
47
32
  #parseErrorData(error: HttpError) {
@@ -80,13 +65,6 @@ export abstract class ReactQueryNetworkClient extends NetworkClient {
80
65
  }
81
66
  )
82
67
 
83
- #onFetch(input: string | URL | Request, init?: RequestInit | undefined): Promise<Response> {
84
- const [path, method, body, headers] = input instanceof Request
85
- ? [input.url, input.method as HTTPMethod, input.body, input.headers]
86
- : [`${input}`, (init?.method?.toLowerCase() || 'get') as HTTPMethod, init?.body, init?.headers]
87
- return this[method](path, { body: body as any, headers: this.#getMappedHeaders(headers), signal: init?.signal })
88
- }
89
-
90
68
  /**
91
69
  * Receives an HttpError and returns a StackspotAPIError.
92
70
  * @param error the original HttpError created by oazapfts.
@@ -169,6 +147,20 @@ export abstract class ReactQueryNetworkClient extends NetworkClient {
169
147
  >(
170
148
  config: Omit<InfiniteQueryConfig<Variables, Result, PageParamName, Accumulator>, 'permission'>,
171
149
  ): Omit<InfiniteQueryObject<Variables, Result, Accumulator>, 'isAllowed' | 'useAllowed' | 'getPermissionKey'>
150
+ /**
151
+ * Builds a query automatically by using a function generated by oazapfts.
152
+ * @param fn the oazapfts function.
153
+ * @param options the configuration for the infinite query.
154
+ */
155
+ protected infiniteQuery<
156
+ Variables extends Record<string, any>,
157
+ Result,
158
+ PageParamName extends keyof Variables,
159
+ Accumulator extends keyof Result,
160
+ >(
161
+ fn: (variables: Variables, opts?: RequestOpts) => Promise<Result>,
162
+ options: Partial<InfiniteQueryOptions<Variables, Result, PageParamName, Accumulator>>,
163
+ ): InfiniteQueryObject<Variables, Result, Accumulator>
172
164
  /**
173
165
  * Builds a query automatically by using a function generated by oazapfts with the variables `page` and `size`.
174
166
  * @param fn the oazapfts function that returns an array.
@@ -184,21 +176,9 @@ export abstract class ReactQueryNetworkClient extends NetworkClient {
184
176
  fn: (variables: Variables, opts?: RequestOpts) => Promise<Result>,
185
177
  options?: Partial<InfiniteQueryOptions<Variables, Result, PageParamName, Accumulator>>,
186
178
  ): InfiniteQueryObject<Variables, Result, Accumulator>
187
- /**
188
- * Builds a query automatically by using a function generated by oazapfts.
189
- * @param fn the oazapfts function.
190
- * @param options the configuration for the infinite query.
191
- */
192
- protected infiniteQuery<
193
- Variables extends Record<string, any>,
194
- Result,
195
- PageParamName extends keyof Variables,
196
- Accumulator extends keyof Result,
197
- >(
198
- fn: (variables: Variables, opts?: RequestOpts) => Promise<Result>,
199
- options: InfiniteQueryOptions<Variables, Result, PageParamName, Accumulator>,
200
- ): InfiniteQueryObject<Variables, Result, Accumulator>
201
- protected infiniteQuery(fnOrConfig: any, options?: InfiniteQueryOptions<any, any, any, any>): InfiniteQueryObject<any, any, any> {
179
+ protected infiniteQuery(
180
+ fnOrConfig: any, options?: Partial<InfiniteQueryOptions<any, any, any, any>>,
181
+ ): InfiniteQueryObject<any, any, any> {
202
182
  return typeof fnOrConfig === 'function'
203
183
  ? new AutoInfiniteQuery(
204
184
  {
@@ -9,16 +9,6 @@ export interface SessionManager {
9
9
  getSession(): Session,
10
10
  }
11
11
 
12
- export interface RequestOptions {
13
- params?: Record<string, string | undefined>,
14
- headers?: Record<string, string>,
15
- signal?: AbortSignal | null,
16
- }
17
-
18
- export interface RequestWithBody extends RequestOptions {
19
- body?: string | object | FormData,
20
- }
21
-
22
12
  export type Env = 'dev' | 'stg' | 'prd'
23
13
 
24
14
  export type HTTPMethod = 'post' | 'patch' | 'delete' | 'put' | 'get'
@@ -0,0 +1,80 @@
1
+ import { useEffect, useRef, useState } from 'react'
2
+
3
+ type ExtensionMap<T> = Record<string, (item: T) => any>
4
+
5
+ type Unpromisify<T> = T extends Promise<infer R> ? R : T
6
+
7
+ type Extension<E extends ExtensionMap<any>> = { [K in keyof E]?: Unpromisify<ReturnType<E[K]>> }
8
+
9
+ type ItemWithExtensions<T, E extends ExtensionMap<T>> = T & Extension<E>
10
+
11
+ /**
12
+ * Computes the given extensions for the items in the list passed as parameter. An extension will, most of the times, return a promise,
13
+ * but it can return whatever you'd like.
14
+ *
15
+ * If the extensions are promises and are still loading, the items won't have the corresponding keys.
16
+ *
17
+ * Attention: once an extension is calculated for an item, it's never calculated again. An item is identified by the parameter "idProp"
18
+ * (3rd), which is "id" by default.
19
+ *
20
+ * @example
21
+ * ```
22
+ * const [groups] = accountClient.memberGroups.useInfiniteQuery({ memberId: 'someId' })
23
+ * const extendedGroups = useExtendedList(groups, {
24
+ * canRemoveMemberFromGroup: group => accountClient.removeMemberFromGroup.isAllowed({ groupId: group.id, memberId: 'someId' }),
25
+ * title: group => `${group.name} (${group.totalUsers})`,
26
+ * })
27
+ * ```
28
+ * Above, each item in `extendedGroups` will have the properties `canRemoveMemberFromGroup` and `title`, once all permission have been
29
+ * fetched.
30
+ *
31
+ * @param list the items to compute extensions for.
32
+ * @param extensions an object where the keys are the extension names and the values are functions that return the value of the extension.
33
+ * @param idProp the name of the property that can be used as an id. 'id' by default.
34
+ * @returns an array with 2 items:
35
+ * - [0]: the list with the permission properties.
36
+ * - [1]: true if waiting for a promise, false otherwise.
37
+ */
38
+ export function useExtendedList<T, E extends ExtensionMap<T>>(
39
+ list: T[], extensions: E, idProp: keyof T,
40
+ ): [ItemWithExtensions<T, E>[], boolean]
41
+ export function useExtendedList<T extends { id: string }, E extends ExtensionMap<T>>(
42
+ list: T[], extensions: E, idProp?: keyof T,
43
+ ): [ItemWithExtensions<T, E>[], boolean]
44
+ export function useExtendedList<T, E extends ExtensionMap<T>>(
45
+ list: T[], extensions: E, idProp = 'id' as keyof T,
46
+ ): [ItemWithExtensions<T, E>[], boolean] {
47
+ const [listWithExtensions, setListWithExtensions] = useState(list as ItemWithExtensions<T, E>[])
48
+ const [isLoading, setLoading] = useState(true)
49
+ const extensionMap = useRef(new Map<any, Extension<E>>())
50
+ const listId = list.map(i => i[idProp]).join(';')
51
+
52
+ useEffect(() => {
53
+ async function update() {
54
+ setLoading(true)
55
+ const newList = await Promise.all(list.map(async (item) => {
56
+ const itemExtensions: Extension<E> = extensionMap.current.get(item[idProp]) ?? {}
57
+ if (Object.keys(itemExtensions).length === 0) {
58
+ await Promise.all(Object.keys(extensions).map(async (key: keyof E) => {
59
+ try {
60
+ // "await" because it might be a promise
61
+ itemExtensions[key] = await extensions[key](item)
62
+ } catch (error) {
63
+ // eslint-disable-next-line no-console
64
+ console.error(`Failed to compute extension "${String(key)}" for item with id "${item[idProp]}". It will have undefined as its value, which may cause errors ahead. Caused by the error below:`)
65
+ // eslint-disable-next-line no-console
66
+ console.error(error)
67
+ }
68
+ }))
69
+ extensionMap.current.set(item[idProp], itemExtensions)
70
+ }
71
+ return { ...item, ...itemExtensions }
72
+ }))
73
+ setLoading(false)
74
+ setListWithExtensions(newList)
75
+ }
76
+ update()
77
+ }, [listId])
78
+
79
+ return [listWithExtensions.length ? listWithExtensions : list as ItemWithExtensions<T, E>[], isLoading]
80
+ }