@superblocksteam/shared 0.9607.2 → 0.9608.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 (294) hide show
  1. package/dist/database-lifecycle/appDatabaseCompatibility.d.ts +49 -0
  2. package/dist/database-lifecycle/appDatabaseCompatibility.d.ts.map +1 -0
  3. package/dist/database-lifecycle/appDatabaseCompatibility.js +32 -0
  4. package/dist/database-lifecycle/appDatabaseCompatibility.js.map +1 -0
  5. package/dist/database-lifecycle/appDatabaseCompatibility.test.d.ts +2 -0
  6. package/dist/database-lifecycle/appDatabaseCompatibility.test.d.ts.map +1 -0
  7. package/dist/database-lifecycle/appDatabaseCompatibility.test.js +47 -0
  8. package/dist/database-lifecycle/appDatabaseCompatibility.test.js.map +1 -0
  9. package/dist/database-lifecycle/destructiveMigrations.d.ts +12 -0
  10. package/dist/database-lifecycle/destructiveMigrations.d.ts.map +1 -1
  11. package/dist/database-lifecycle/destructiveMigrations.js +114 -0
  12. package/dist/database-lifecycle/destructiveMigrations.js.map +1 -1
  13. package/dist/database-lifecycle/destructiveMigrations.test.js +79 -0
  14. package/dist/database-lifecycle/destructiveMigrations.test.js.map +1 -1
  15. package/dist/database-lifecycle/index.d.ts +46 -2
  16. package/dist/database-lifecycle/index.d.ts.map +1 -1
  17. package/dist/database-lifecycle/index.js +127 -1
  18. package/dist/database-lifecycle/index.js.map +1 -1
  19. package/dist/database-lifecycle/providerDiagnostics.test.d.ts +2 -0
  20. package/dist/database-lifecycle/providerDiagnostics.test.d.ts.map +1 -0
  21. package/dist/database-lifecycle/providerDiagnostics.test.js +119 -0
  22. package/dist/database-lifecycle/providerDiagnostics.test.js.map +1 -0
  23. package/dist/environment-compatibility/appEnvironmentCompatibility.d.ts +65 -0
  24. package/dist/environment-compatibility/appEnvironmentCompatibility.d.ts.map +1 -0
  25. package/dist/environment-compatibility/appEnvironmentCompatibility.js +87 -0
  26. package/dist/environment-compatibility/appEnvironmentCompatibility.js.map +1 -0
  27. package/dist/environment-compatibility/appEnvironmentCompatibility.test.d.ts +2 -0
  28. package/dist/environment-compatibility/appEnvironmentCompatibility.test.d.ts.map +1 -0
  29. package/dist/environment-compatibility/appEnvironmentCompatibility.test.js +285 -0
  30. package/dist/environment-compatibility/appEnvironmentCompatibility.test.js.map +1 -0
  31. package/dist/errors/http.d.ts +15 -4
  32. package/dist/errors/http.d.ts.map +1 -1
  33. package/dist/errors/http.js +25 -7
  34. package/dist/errors/http.js.map +1 -1
  35. package/dist/errors/http.test.d.ts +2 -0
  36. package/dist/errors/http.test.d.ts.map +1 -0
  37. package/dist/errors/http.test.js +28 -0
  38. package/dist/errors/http.test.js.map +1 -0
  39. package/dist/index.d.ts +2 -0
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +2 -0
  42. package/dist/index.js.map +1 -1
  43. package/dist/plugins/templates/restApiIntegration.d.ts.map +1 -1
  44. package/dist/plugins/templates/restApiIntegration.js +2 -0
  45. package/dist/plugins/templates/restApiIntegration.js.map +1 -1
  46. package/dist/plugins/templates/shared/auth.d.ts +3 -1
  47. package/dist/plugins/templates/shared/auth.d.ts.map +1 -1
  48. package/dist/plugins/templates/shared/auth.js +129 -17
  49. package/dist/plugins/templates/shared/auth.js.map +1 -1
  50. package/dist/plugins/templates/shared/auth.test.d.ts +2 -0
  51. package/dist/plugins/templates/shared/auth.test.d.ts.map +1 -0
  52. package/dist/plugins/templates/shared/auth.test.js +116 -0
  53. package/dist/plugins/templates/shared/auth.test.js.map +1 -0
  54. package/dist/plugins/templates/shared/restapiintegration.d.ts +2 -0
  55. package/dist/plugins/templates/shared/restapiintegration.d.ts.map +1 -1
  56. package/dist/plugins/templates/shared/restapiintegration.js +3 -1
  57. package/dist/plugins/templates/shared/restapiintegration.js.map +1 -1
  58. package/dist/socket/dist-entry.test.d.ts +2 -0
  59. package/dist/socket/dist-entry.test.d.ts.map +1 -0
  60. package/dist/socket/dist-entry.test.js +34 -0
  61. package/dist/socket/dist-entry.test.js.map +1 -0
  62. package/dist/socket/heartbeat.d.ts +258 -0
  63. package/dist/socket/heartbeat.d.ts.map +1 -0
  64. package/dist/socket/heartbeat.js +307 -0
  65. package/dist/socket/heartbeat.js.map +1 -0
  66. package/dist/socket/heartbeat.test.d.ts +2 -0
  67. package/dist/socket/heartbeat.test.d.ts.map +1 -0
  68. package/dist/socket/heartbeat.test.js +431 -0
  69. package/dist/socket/heartbeat.test.js.map +1 -0
  70. package/dist/socket/index.d.ts +1 -0
  71. package/dist/socket/index.d.ts.map +1 -1
  72. package/dist/socket/index.js +1 -0
  73. package/dist/socket/index.js.map +1 -1
  74. package/dist/socket/util.d.ts.map +1 -1
  75. package/dist/socket/util.js +15 -1
  76. package/dist/socket/util.js.map +1 -1
  77. package/dist/socket/util.test.js +12 -2
  78. package/dist/socket/util.test.js.map +1 -1
  79. package/dist/types/ai/index.d.ts +3 -0
  80. package/dist/types/ai/index.d.ts.map +1 -1
  81. package/dist/types/ai/index.js +3 -0
  82. package/dist/types/ai/index.js.map +1 -1
  83. package/dist/types/application/index.d.ts +12 -0
  84. package/dist/types/application/index.d.ts.map +1 -1
  85. package/dist/types/application/index.js.map +1 -1
  86. package/dist/types/codeSecurity/index.d.ts +55 -1
  87. package/dist/types/codeSecurity/index.d.ts.map +1 -1
  88. package/dist/types/codeSecurity/index.js +21 -1
  89. package/dist/types/codeSecurity/index.js.map +1 -1
  90. package/dist/types/codeSecurity/index.test.d.ts +2 -0
  91. package/dist/types/codeSecurity/index.test.d.ts.map +1 -0
  92. package/dist/types/codeSecurity/index.test.js +19 -0
  93. package/dist/types/codeSecurity/index.test.js.map +1 -0
  94. package/dist/types/datasource/auth.d.ts +12 -1
  95. package/dist/types/datasource/auth.d.ts.map +1 -1
  96. package/dist/types/datasource/auth.js +20 -2
  97. package/dist/types/datasource/auth.js.map +1 -1
  98. package/dist/types/datasource/auth.test.js +3 -1
  99. package/dist/types/datasource/auth.test.js.map +1 -1
  100. package/dist/types/group/index.d.ts +1 -3
  101. package/dist/types/group/index.d.ts.map +1 -1
  102. package/dist/types/group/index.js +1 -3
  103. package/dist/types/group/index.js.map +1 -1
  104. package/dist/types/integration/index.d.ts +11 -1
  105. package/dist/types/integration/index.d.ts.map +1 -1
  106. package/dist/types/integration/index.js +11 -1
  107. package/dist/types/integration/index.js.map +1 -1
  108. package/dist/types/plugin/form.d.ts +32 -0
  109. package/dist/types/plugin/form.d.ts.map +1 -1
  110. package/dist/types/plugin/form.js +73 -1
  111. package/dist/types/plugin/form.js.map +1 -1
  112. package/dist/types/plugin/form.test.js +128 -0
  113. package/dist/types/plugin/form.test.js.map +1 -1
  114. package/dist/types/profile/index.d.ts +16 -1
  115. package/dist/types/profile/index.d.ts.map +1 -1
  116. package/dist/types/profile/index.js +7 -1
  117. package/dist/types/profile/index.js.map +1 -1
  118. package/dist/types/rbac/index.d.ts +2 -0
  119. package/dist/types/rbac/index.d.ts.map +1 -1
  120. package/dist/types/rbac/index.js +2 -0
  121. package/dist/types/rbac/index.js.map +1 -1
  122. package/dist/types/response/GetRecentApplicationsResponseBody.d.ts +4 -0
  123. package/dist/types/response/GetRecentApplicationsResponseBody.d.ts.map +1 -0
  124. package/dist/types/response/GetRecentApplicationsResponseBody.js +3 -0
  125. package/dist/types/response/GetRecentApplicationsResponseBody.js.map +1 -0
  126. package/dist/types/response/index.d.ts +1 -0
  127. package/dist/types/response/index.d.ts.map +1 -1
  128. package/dist/types/response/index.js +1 -0
  129. package/dist/types/response/index.js.map +1 -1
  130. package/dist-esm/database-lifecycle/appDatabaseCompatibility.d.ts +49 -0
  131. package/dist-esm/database-lifecycle/appDatabaseCompatibility.d.ts.map +1 -0
  132. package/dist-esm/database-lifecycle/appDatabaseCompatibility.js +28 -0
  133. package/dist-esm/database-lifecycle/appDatabaseCompatibility.js.map +1 -0
  134. package/dist-esm/database-lifecycle/appDatabaseCompatibility.test.d.ts +2 -0
  135. package/dist-esm/database-lifecycle/appDatabaseCompatibility.test.d.ts.map +1 -0
  136. package/dist-esm/database-lifecycle/appDatabaseCompatibility.test.js +45 -0
  137. package/dist-esm/database-lifecycle/appDatabaseCompatibility.test.js.map +1 -0
  138. package/dist-esm/database-lifecycle/destructiveMigrations.d.ts +12 -0
  139. package/dist-esm/database-lifecycle/destructiveMigrations.d.ts.map +1 -1
  140. package/dist-esm/database-lifecycle/destructiveMigrations.js +113 -0
  141. package/dist-esm/database-lifecycle/destructiveMigrations.js.map +1 -1
  142. package/dist-esm/database-lifecycle/destructiveMigrations.test.js +80 -1
  143. package/dist-esm/database-lifecycle/destructiveMigrations.test.js.map +1 -1
  144. package/dist-esm/database-lifecycle/index.d.ts +46 -2
  145. package/dist-esm/database-lifecycle/index.d.ts.map +1 -1
  146. package/dist-esm/database-lifecycle/index.js +123 -1
  147. package/dist-esm/database-lifecycle/index.js.map +1 -1
  148. package/dist-esm/database-lifecycle/providerDiagnostics.test.d.ts +2 -0
  149. package/dist-esm/database-lifecycle/providerDiagnostics.test.d.ts.map +1 -0
  150. package/dist-esm/database-lifecycle/providerDiagnostics.test.js +117 -0
  151. package/dist-esm/database-lifecycle/providerDiagnostics.test.js.map +1 -0
  152. package/dist-esm/environment-compatibility/appEnvironmentCompatibility.d.ts +65 -0
  153. package/dist-esm/environment-compatibility/appEnvironmentCompatibility.d.ts.map +1 -0
  154. package/dist-esm/environment-compatibility/appEnvironmentCompatibility.js +79 -0
  155. package/dist-esm/environment-compatibility/appEnvironmentCompatibility.js.map +1 -0
  156. package/dist-esm/environment-compatibility/appEnvironmentCompatibility.test.d.ts +2 -0
  157. package/dist-esm/environment-compatibility/appEnvironmentCompatibility.test.d.ts.map +1 -0
  158. package/dist-esm/environment-compatibility/appEnvironmentCompatibility.test.js +283 -0
  159. package/dist-esm/environment-compatibility/appEnvironmentCompatibility.test.js.map +1 -0
  160. package/dist-esm/errors/http.d.ts +15 -4
  161. package/dist-esm/errors/http.d.ts.map +1 -1
  162. package/dist-esm/errors/http.js +22 -6
  163. package/dist-esm/errors/http.js.map +1 -1
  164. package/dist-esm/errors/http.test.d.ts +2 -0
  165. package/dist-esm/errors/http.test.d.ts.map +1 -0
  166. package/dist-esm/errors/http.test.js +26 -0
  167. package/dist-esm/errors/http.test.js.map +1 -0
  168. package/dist-esm/index.d.ts +2 -0
  169. package/dist-esm/index.d.ts.map +1 -1
  170. package/dist-esm/index.js +2 -0
  171. package/dist-esm/index.js.map +1 -1
  172. package/dist-esm/plugins/templates/restApiIntegration.d.ts.map +1 -1
  173. package/dist-esm/plugins/templates/restApiIntegration.js +2 -0
  174. package/dist-esm/plugins/templates/restApiIntegration.js.map +1 -1
  175. package/dist-esm/plugins/templates/shared/auth.d.ts +3 -1
  176. package/dist-esm/plugins/templates/shared/auth.d.ts.map +1 -1
  177. package/dist-esm/plugins/templates/shared/auth.js +129 -17
  178. package/dist-esm/plugins/templates/shared/auth.js.map +1 -1
  179. package/dist-esm/plugins/templates/shared/auth.test.d.ts +2 -0
  180. package/dist-esm/plugins/templates/shared/auth.test.d.ts.map +1 -0
  181. package/dist-esm/plugins/templates/shared/auth.test.js +114 -0
  182. package/dist-esm/plugins/templates/shared/auth.test.js.map +1 -0
  183. package/dist-esm/plugins/templates/shared/restapiintegration.d.ts +2 -0
  184. package/dist-esm/plugins/templates/shared/restapiintegration.d.ts.map +1 -1
  185. package/dist-esm/plugins/templates/shared/restapiintegration.js +3 -1
  186. package/dist-esm/plugins/templates/shared/restapiintegration.js.map +1 -1
  187. package/dist-esm/socket/dist-entry.test.d.ts +2 -0
  188. package/dist-esm/socket/dist-entry.test.d.ts.map +1 -0
  189. package/dist-esm/socket/dist-entry.test.js +29 -0
  190. package/dist-esm/socket/dist-entry.test.js.map +1 -0
  191. package/dist-esm/socket/heartbeat.d.ts +258 -0
  192. package/dist-esm/socket/heartbeat.d.ts.map +1 -0
  193. package/dist-esm/socket/heartbeat.js +303 -0
  194. package/dist-esm/socket/heartbeat.js.map +1 -0
  195. package/dist-esm/socket/heartbeat.test.d.ts +2 -0
  196. package/dist-esm/socket/heartbeat.test.d.ts.map +1 -0
  197. package/dist-esm/socket/heartbeat.test.js +429 -0
  198. package/dist-esm/socket/heartbeat.test.js.map +1 -0
  199. package/dist-esm/socket/index.d.ts +1 -0
  200. package/dist-esm/socket/index.d.ts.map +1 -1
  201. package/dist-esm/socket/index.js +1 -0
  202. package/dist-esm/socket/index.js.map +1 -1
  203. package/dist-esm/socket/util.d.ts.map +1 -1
  204. package/dist-esm/socket/util.js +15 -1
  205. package/dist-esm/socket/util.js.map +1 -1
  206. package/dist-esm/socket/util.test.js +12 -2
  207. package/dist-esm/socket/util.test.js.map +1 -1
  208. package/dist-esm/types/ai/index.d.ts +3 -0
  209. package/dist-esm/types/ai/index.d.ts.map +1 -1
  210. package/dist-esm/types/ai/index.js +3 -0
  211. package/dist-esm/types/ai/index.js.map +1 -1
  212. package/dist-esm/types/application/index.d.ts +12 -0
  213. package/dist-esm/types/application/index.d.ts.map +1 -1
  214. package/dist-esm/types/application/index.js.map +1 -1
  215. package/dist-esm/types/codeSecurity/index.d.ts +55 -1
  216. package/dist-esm/types/codeSecurity/index.d.ts.map +1 -1
  217. package/dist-esm/types/codeSecurity/index.js +17 -1
  218. package/dist-esm/types/codeSecurity/index.js.map +1 -1
  219. package/dist-esm/types/codeSecurity/index.test.d.ts +2 -0
  220. package/dist-esm/types/codeSecurity/index.test.d.ts.map +1 -0
  221. package/dist-esm/types/codeSecurity/index.test.js +17 -0
  222. package/dist-esm/types/codeSecurity/index.test.js.map +1 -0
  223. package/dist-esm/types/datasource/auth.d.ts +12 -1
  224. package/dist-esm/types/datasource/auth.d.ts.map +1 -1
  225. package/dist-esm/types/datasource/auth.js +19 -2
  226. package/dist-esm/types/datasource/auth.js.map +1 -1
  227. package/dist-esm/types/datasource/auth.test.js +3 -1
  228. package/dist-esm/types/datasource/auth.test.js.map +1 -1
  229. package/dist-esm/types/group/index.d.ts +1 -3
  230. package/dist-esm/types/group/index.d.ts.map +1 -1
  231. package/dist-esm/types/group/index.js +1 -3
  232. package/dist-esm/types/group/index.js.map +1 -1
  233. package/dist-esm/types/integration/index.d.ts +11 -1
  234. package/dist-esm/types/integration/index.d.ts.map +1 -1
  235. package/dist-esm/types/integration/index.js +11 -1
  236. package/dist-esm/types/integration/index.js.map +1 -1
  237. package/dist-esm/types/plugin/form.d.ts +32 -0
  238. package/dist-esm/types/plugin/form.d.ts.map +1 -1
  239. package/dist-esm/types/plugin/form.js +68 -0
  240. package/dist-esm/types/plugin/form.js.map +1 -1
  241. package/dist-esm/types/plugin/form.test.js +129 -1
  242. package/dist-esm/types/plugin/form.test.js.map +1 -1
  243. package/dist-esm/types/profile/index.d.ts +16 -1
  244. package/dist-esm/types/profile/index.d.ts.map +1 -1
  245. package/dist-esm/types/profile/index.js +7 -1
  246. package/dist-esm/types/profile/index.js.map +1 -1
  247. package/dist-esm/types/rbac/index.d.ts +2 -0
  248. package/dist-esm/types/rbac/index.d.ts.map +1 -1
  249. package/dist-esm/types/rbac/index.js +2 -0
  250. package/dist-esm/types/rbac/index.js.map +1 -1
  251. package/dist-esm/types/response/GetRecentApplicationsResponseBody.d.ts +4 -0
  252. package/dist-esm/types/response/GetRecentApplicationsResponseBody.d.ts.map +1 -0
  253. package/dist-esm/types/response/GetRecentApplicationsResponseBody.js +2 -0
  254. package/dist-esm/types/response/GetRecentApplicationsResponseBody.js.map +1 -0
  255. package/dist-esm/types/response/index.d.ts +1 -0
  256. package/dist-esm/types/response/index.d.ts.map +1 -1
  257. package/dist-esm/types/response/index.js +1 -0
  258. package/dist-esm/types/response/index.js.map +1 -1
  259. package/package.json +1 -1
  260. package/src/database-lifecycle/appDatabaseCompatibility.test.ts +55 -0
  261. package/src/database-lifecycle/appDatabaseCompatibility.ts +62 -0
  262. package/src/database-lifecycle/destructiveMigrations.test.ts +108 -1
  263. package/src/database-lifecycle/destructiveMigrations.ts +129 -0
  264. package/src/database-lifecycle/index.ts +173 -0
  265. package/src/database-lifecycle/providerDiagnostics.test.ts +134 -0
  266. package/src/environment-compatibility/appEnvironmentCompatibility.test.ts +326 -0
  267. package/src/environment-compatibility/appEnvironmentCompatibility.ts +173 -0
  268. package/src/errors/http.test.ts +32 -0
  269. package/src/errors/http.ts +24 -6
  270. package/src/index.ts +2 -0
  271. package/src/plugins/templates/restApiIntegration.ts +2 -0
  272. package/src/plugins/templates/shared/auth.test.ts +162 -0
  273. package/src/plugins/templates/shared/auth.ts +135 -18
  274. package/src/plugins/templates/shared/restapiintegration.ts +3 -1
  275. package/src/socket/dist-entry.test.ts +29 -0
  276. package/src/socket/heartbeat.test.ts +538 -0
  277. package/src/socket/heartbeat.ts +469 -0
  278. package/src/socket/index.ts +1 -0
  279. package/src/socket/util.test.ts +14 -2
  280. package/src/socket/util.ts +15 -1
  281. package/src/types/ai/index.ts +3 -0
  282. package/src/types/application/index.ts +14 -0
  283. package/src/types/codeSecurity/index.test.ts +21 -0
  284. package/src/types/codeSecurity/index.ts +83 -1
  285. package/src/types/datasource/auth.test.ts +3 -1
  286. package/src/types/datasource/auth.ts +24 -3
  287. package/src/types/group/index.ts +1 -3
  288. package/src/types/integration/index.ts +14 -0
  289. package/src/types/plugin/form.test.ts +174 -1
  290. package/src/types/plugin/form.ts +100 -2
  291. package/src/types/profile/index.ts +19 -1
  292. package/src/types/rbac/index.ts +2 -0
  293. package/src/types/response/GetRecentApplicationsResponseBody.ts +4 -0
  294. package/src/types/response/index.ts +1 -0
@@ -10,6 +10,18 @@ export class HttpError extends Error {
10
10
  }
11
11
  }
12
12
 
13
+ /**
14
+ * An upstream failure that may resolve on its own, so the caller is invited to try again.
15
+ * `retryAfterSeconds` is surfaced to HTTP clients as the Retry-After response header.
16
+ */
17
+ export abstract class RetryableHttpError extends HttpError {
18
+ retryAfterSeconds?: number;
19
+ constructor(status: number, message: string, title: string, retryAfterSeconds?: number) {
20
+ super(status, message, title);
21
+ this.retryAfterSeconds = retryAfterSeconds;
22
+ }
23
+ }
24
+
13
25
  export class BadRequestError extends HttpError {
14
26
  constructor(message: string) {
15
27
  super(400, message, 'Bad request');
@@ -53,9 +65,9 @@ export class NotImplementedError extends HttpError {
53
65
  }
54
66
  }
55
67
 
56
- export class BadGatewayError extends HttpError {
57
- constructor(message: string) {
58
- super(502, message, 'Bad gateway');
68
+ export class BadGatewayError extends RetryableHttpError {
69
+ constructor(message: string, retryAfterSeconds?: number) {
70
+ super(502, message, 'Bad gateway', retryAfterSeconds);
59
71
  }
60
72
  }
61
73
 
@@ -96,9 +108,15 @@ export class FailedDependencyError extends HttpError {
96
108
  }
97
109
  }
98
110
 
99
- export class ServiceUnavailableError extends HttpError {
100
- constructor(message?: string) {
101
- super(503, message || 'Service Unavailable', 'Service Unavailable');
111
+ export class ServiceUnavailableError extends RetryableHttpError {
112
+ constructor(message?: string, retryAfterSeconds?: number) {
113
+ super(503, message || 'Service Unavailable', 'Service Unavailable', retryAfterSeconds);
114
+ }
115
+ }
116
+
117
+ export class GatewayTimeoutError extends RetryableHttpError {
118
+ constructor(message?: string, retryAfterSeconds?: number) {
119
+ super(504, message || 'Gateway timeout', 'Gateway timeout', retryAfterSeconds);
102
120
  }
103
121
  }
104
122
 
package/src/index.ts CHANGED
@@ -27,4 +27,6 @@ export * from './tracing/errorSanitizer.js';
27
27
  export * from './jwt/index.js';
28
28
  export * from './org-features/index.js';
29
29
  export * from './database-lifecycle/index.js';
30
+ export * from './database-lifecycle/appDatabaseCompatibility.js';
30
31
  export * from './database-lifecycle/edit-lifecycle-capability.js';
32
+ export * from './environment-compatibility/appEnvironmentCompatibility.js';
@@ -67,6 +67,8 @@ export const RestApiIntegrationPlugin: Plugin = {
67
67
  },
68
68
  ...authSections({
69
69
  startVersion: RestApiIntegrationPluginVersions.V1,
70
+ pkceStartVersion: RestApiIntegrationPluginVersions.V16,
71
+ confidentialPkceStartVersion: RestApiIntegrationPluginVersions.V17,
70
72
  pluginId: ExtendedIntegrationPluginId.REST_API,
71
73
  pluginName: 'REST API',
72
74
  enabledMethods: {
@@ -0,0 +1,162 @@
1
+ import { describe, expect, test } from 'vitest';
2
+
3
+ import {
4
+ ExtendedIntegrationPluginId,
5
+ FormComponentType,
6
+ FormItem,
7
+ getDisplayName,
8
+ getRowItemsFromSectionItem,
9
+ IntegrationAuthType
10
+ } from '../../../types/index.js';
11
+ import { authSections } from './auth.js';
12
+
13
+ const buildAuthFields = (pkceStartVersion?: string, confidentialPkceStartVersion?: string): FormItem[] =>
14
+ authSections({
15
+ startVersion: '0.0.1',
16
+ pkceStartVersion,
17
+ confidentialPkceStartVersion,
18
+ pluginId: ExtendedIntegrationPluginId.REST_API,
19
+ pluginName: 'REST API',
20
+ // Matches the REST API integration, the only plugin that offers PKCE.
21
+ enabledMethods: { basic: true, firebase: true, oauth: true, bearer: true, apiKey: true }
22
+ }).flatMap((section) => section.items.flatMap((item) => getRowItemsFromSectionItem(item)));
23
+
24
+ const findOrdinaryClientSecret = (fields: FormItem[]): FormItem | undefined =>
25
+ fields.find(
26
+ (field) =>
27
+ field.name === 'authConfig.clientSecret' &&
28
+ field.display?.show?.authType?.includes(IntegrationAuthType.OAUTH2_CODE) &&
29
+ field.display.show['authConfig.usePkce']?.includes('false')
30
+ );
31
+
32
+ describe('PKCE display conditions', () => {
33
+ test('shows the client secret for every way the PKCE marker can be unset', () => {
34
+ const show = findOrdinaryClientSecret(buildAuthFields('0.0.16'))?.display?.show;
35
+
36
+ // `display.show` compares String(value), so each of these is a form value
37
+ // that means "PKCE is off" and must keep the field visible.
38
+ expect(show?.['authConfig.usePkce']).toEqual(expect.arrayContaining(['', '0', 'false', 'null', 'undefined']));
39
+ });
40
+
41
+ test('shows an optional client secret directly after the client ID for confidential PKCE clients', () => {
42
+ const publicFields = buildAuthFields('0.0.16');
43
+ const fields = buildAuthFields('0.0.16', '0.0.17');
44
+ const clientIdIndex = fields.findIndex(
45
+ (field) => field.name === 'authConfig.clientId' && field.display?.show?.authType?.includes(IntegrationAuthType.OAUTH2_CODE)
46
+ );
47
+ const clientSecretIndex = fields.findIndex(
48
+ (field) => field.name === 'authConfig.clientSecret' && !field.hidden && field.display?.show?.['authConfig.usePkce']?.includes('true')
49
+ );
50
+ const clientSecret = fields[clientSecretIndex];
51
+ const clientAuthMethod = fields.find(
52
+ (field) =>
53
+ field.name === 'authConfig.clientAuthMethod' && !field.hidden && field.display?.show?.['authConfig.usePkce']?.includes('true')
54
+ );
55
+
56
+ expect(
57
+ publicFields.find(
58
+ (field) =>
59
+ field.name === 'authConfig.clientSecret' && !field.hidden && field.display?.show?.['authConfig.usePkce']?.includes('true')
60
+ )
61
+ ).toBeUndefined();
62
+ expect(clientSecretIndex).toBe(clientIdIndex + 1);
63
+ expect(clientSecret?.startVersion).toBe('0.0.17');
64
+ expect(clientSecret?.rules).toEqual([{ required: false }]);
65
+ expect(clientSecret?.tooltip).toEqual({
66
+ markdownText: 'Only required for confidential OAuth clients.'
67
+ });
68
+ expect(fields.some((field) => field.name === 'authConfig.usePkceClientSecret')).toBe(false);
69
+ expect(clientAuthMethod?.display?.show?.['authConfig.usePkce']).toEqual(['1', 'true']);
70
+ });
71
+
72
+ test('leaves the condition off plugins that do not offer PKCE', () => {
73
+ const clientSecret = buildAuthFields().find(
74
+ (field) => field.name === 'authConfig.clientSecret' && field.display?.show?.authType?.includes(IntegrationAuthType.OAUTH2_CODE)
75
+ );
76
+
77
+ expect(clientSecret?.display?.show).toBeDefined();
78
+ expect(clientSecret?.display?.show?.['authConfig.usePkce']).toBeUndefined();
79
+ expect(clientSecret?.rules).toEqual([{ required: true, message: 'Client secret is required' }]);
80
+ });
81
+ });
82
+
83
+ describe('PKCE field clearing', () => {
84
+ test('leaves client credential fields clearable so switching auth type still empties them', () => {
85
+ // cleanFormData skips any item marked doNotClearOnDependenciesChange, so a
86
+ // marked field survives every dependency change, including switching the
87
+ // auth type to Basic or None. That leaked authConfig.clientAuthMethod into
88
+ // payloads that should not have an authConfig at all. Keeping the value
89
+ // across PKCE toggles is done with the hidden preservation items below
90
+ // instead.
91
+ const fields = buildAuthFields('0.0.16', '0.0.17');
92
+
93
+ for (const name of ['authConfig.clientSecret', 'authConfig.clientAuthMethod']) {
94
+ const items = fields.filter((field) => field.name === name);
95
+ expect(items.length).toBeGreaterThan(0);
96
+ for (const item of items) {
97
+ expect(item.doNotClearOnDependenciesChange).toBeUndefined();
98
+ }
99
+ }
100
+ });
101
+
102
+ test('keeps confidential credentials when only public PKCE is supported', () => {
103
+ const fields = buildAuthFields('0.0.16', '0.0.17');
104
+
105
+ for (const name of ['authConfig.clientSecret', 'authConfig.clientAuthMethod']) {
106
+ const preservation = fields.find(
107
+ (field) =>
108
+ field.name === name &&
109
+ field.startVersion === '0.0.16' &&
110
+ field.hidden === true &&
111
+ field.display?.show?.['authConfig.usePkce']?.includes('true')
112
+ );
113
+ expect(preservation, name).toBeDefined();
114
+ }
115
+ });
116
+ });
117
+
118
+ describe('PKCE dropdown option', () => {
119
+ test('labels itself off the ordinary authorization code option', () => {
120
+ const authTypeField = buildAuthFields('0.0.16').find((field) => field.name === 'authType');
121
+ const options = 'options' in authTypeField! ? authTypeField.options : [];
122
+ const pkceOption = options.find((option) => option.key === `${IntegrationAuthType.OAUTH2_CODE}-pkce`);
123
+
124
+ // Naming it by hand let it drift to "OAuth2.0" while every sibling said
125
+ // "OAuth2".
126
+ expect(pkceOption?.displayName).toBe(`${getDisplayName(IntegrationAuthType.OAUTH2_CODE)} (with PKCE)`);
127
+ });
128
+ });
129
+
130
+ describe('OAuth connect button', () => {
131
+ test('sends the PKCE marker along with the rest of the auth config', () => {
132
+ // No shipped plugin has both the connect button and PKCE today: the button
133
+ // needs oauth2BringYourOwn or oauth2SuperblocksClient, and PKCE is REST API
134
+ // only. Build a plugin with both so the forwarding contract is pinned down
135
+ // before some plugin ends up in that combination.
136
+ const fields = authSections({
137
+ startVersion: '0.0.1',
138
+ pkceStartVersion: '0.0.16',
139
+ pluginId: ExtendedIntegrationPluginId.REST_API,
140
+ pluginName: 'REST API',
141
+ enabledMethods: {
142
+ oauth: true,
143
+ oauth2BringYourOwn: {
144
+ tokenUrl: 'https://provider.example.com/token',
145
+ authorizationUrl: 'https://provider.example.com/authorize',
146
+ revokeTokenUrl: 'https://provider.example.com/revoke',
147
+ iconUrl: 'https://provider.example.com/icon.png'
148
+ }
149
+ }
150
+ }).flatMap((section) => section.items.flatMap((item) => getRowItemsFromSectionItem(item)));
151
+
152
+ const forwardedValues = fields.flatMap((field) =>
153
+ field.name === 'oauth-connect-button' && field.componentType === FormComponentType.BUTTON ? (field.valuesFromContext ?? []) : []
154
+ );
155
+
156
+ // The button forwards exactly these form values to the connect saga, and
157
+ // the saga decides whether to run PKCE from the marker. Leave it out and
158
+ // the saga can never see PKCE as enabled.
159
+ expect(forwardedValues).toContain('authConfig.usePkce');
160
+ expect(forwardedValues).not.toContain('authConfig.usePkceClientSecret');
161
+ });
162
+ });
@@ -84,6 +84,26 @@ type OAuth2Config = {
84
84
 
85
85
  type OAuth2HostedClientConfig = OAuth2Config & { clientId: string };
86
86
 
87
+ /**
88
+ * Every value `authConfig.usePkce` can hold while PKCE is off. `display.show`
89
+ * matches on the stringified form value, so a spelling missing from this list
90
+ * hides the field it guards instead of showing it.
91
+ */
92
+ const PKCE_OFF_MARKERS = ['', '0', 'false', 'null', 'undefined'];
93
+ const PKCE_ON_MARKERS = ['1', 'true'];
94
+ const CLIENT_AUTH_METHOD_OPTIONS: DropdownOption[] = [
95
+ {
96
+ displayName: 'Send client credentials in body',
97
+ key: ClientAuthMethod.POST,
98
+ value: ClientAuthMethod.POST
99
+ },
100
+ {
101
+ displayName: 'Send as Basic Auth header',
102
+ key: ClientAuthMethod.BASIC,
103
+ value: ClientAuthMethod.BASIC
104
+ }
105
+ ];
106
+
87
107
  const AUTH_METHODS_TO_TYPES = {
88
108
  basic: IntegrationAuthType.BASIC,
89
109
  firebase: IntegrationAuthType.FIREBASE,
@@ -103,6 +123,8 @@ const AUTH_METHODS_TO_TYPES = {
103
123
 
104
124
  export const authSections = ({
105
125
  startVersion,
126
+ pkceStartVersion,
127
+ confidentialPkceStartVersion,
106
128
  endVersion,
107
129
  pluginId,
108
130
  pluginName,
@@ -115,6 +137,8 @@ export const authSections = ({
115
137
  prependItems = []
116
138
  }: {
117
139
  startVersion: string;
140
+ pkceStartVersion?: string;
141
+ confidentialPkceStartVersion?: string;
118
142
  endVersion?: string;
119
143
  pluginId: ExtendedIntegrationPluginId;
120
144
  pluginName: string;
@@ -171,10 +195,11 @@ export const authSections = ({
171
195
  {
172
196
  name: isProto ? 'connection.auth.method.case' : 'authType',
173
197
  label: 'Authentication',
198
+ secondaryName: pkceStartVersion ? 'authConfig.usePkce' : undefined,
174
199
  startVersion: startVersion,
175
200
  componentType: FormComponentType.DROPDOWN,
176
201
  initialValue: authTypeInitialValue,
177
- options: authTypeOptions({ enabledMethods, allowNone, isProto, apiKeyFormDisplayName }),
202
+ options: authTypeOptions({ enabledMethods, allowNone, apiKeyFormDisplayName, pkceStartVersion }),
178
203
  disabled: !allowNone && enabledMethodKeys.length === 1
179
204
  }
180
205
  ],
@@ -789,6 +814,24 @@ export const authSections = ({
789
814
  }
790
815
  }
791
816
  } as FormItem,
817
+ ...(confidentialPkceStartVersion
818
+ ? [
819
+ {
820
+ ...BASE_CLIENT_SECRET,
821
+ startVersion: confidentialPkceStartVersion,
822
+ rules: [{ required: false }],
823
+ tooltip: {
824
+ markdownText: 'Only required for confidential OAuth clients.'
825
+ },
826
+ display: {
827
+ show: {
828
+ authType: [IntegrationAuthType.OAUTH2_CODE],
829
+ 'authConfig.usePkce': PKCE_ON_MARKERS
830
+ }
831
+ }
832
+ } as FormItem
833
+ ]
834
+ : []),
792
835
  {
793
836
  ...BASE_CLIENT_ID,
794
837
  startVersion,
@@ -804,10 +847,29 @@ export const authSections = ({
804
847
  startVersion,
805
848
  display: {
806
849
  show: {
807
- authType: [IntegrationAuthType.OAUTH2_PASSWORD, IntegrationAuthType.OAUTH2_CLIENT_CREDS, IntegrationAuthType.OAUTH2_CODE]
850
+ authType: [IntegrationAuthType.OAUTH2_PASSWORD, IntegrationAuthType.OAUTH2_CLIENT_CREDS, IntegrationAuthType.OAUTH2_CODE],
851
+ ...(pkceStartVersion ? { 'authConfig.usePkce': PKCE_OFF_MARKERS } : {})
808
852
  }
809
853
  }
810
854
  } as FormItem,
855
+ ...(pkceStartVersion
856
+ ? [
857
+ {
858
+ // Keep a confidential client's stored secret if the current
859
+ // agent only supports public PKCE.
860
+ ...BASE_CLIENT_SECRET,
861
+ startVersion: pkceStartVersion,
862
+ hidden: true,
863
+ rules: [{ required: false }],
864
+ display: {
865
+ show: {
866
+ authType: [IntegrationAuthType.OAUTH2_CODE],
867
+ 'authConfig.usePkce': PKCE_ON_MARKERS
868
+ }
869
+ }
870
+ } as FormItem
871
+ ]
872
+ : []),
811
873
  {
812
874
  ...BASE_CLIENT_SECRET,
813
875
  startVersion,
@@ -883,24 +945,69 @@ export const authSections = ({
883
945
  startVersion: startVersion,
884
946
  componentType: FormComponentType.DROPDOWN,
885
947
  initialValue: ClientAuthMethod.POST,
886
- options: [
887
- {
888
- displayName: 'Send client credentials in body',
889
- key: ClientAuthMethod.POST,
890
- value: ClientAuthMethod.POST
891
- },
892
- {
893
- displayName: 'Send as Basic Auth header',
894
- key: ClientAuthMethod.BASIC,
895
- value: ClientAuthMethod.BASIC
896
- }
897
- ],
948
+ options: CLIENT_AUTH_METHOD_OPTIONS,
898
949
  display: {
899
950
  show: {
900
- authType: [IntegrationAuthType.OAUTH2_CODE]
951
+ authType: [IntegrationAuthType.OAUTH2_CODE],
952
+ ...(pkceStartVersion ? { 'authConfig.usePkce': PKCE_OFF_MARKERS } : {})
901
953
  }
902
954
  }
903
955
  },
956
+ ...(confidentialPkceStartVersion
957
+ ? [
958
+ {
959
+ label: 'Client authentication',
960
+ name: 'authConfig.clientAuthMethod',
961
+ startVersion: confidentialPkceStartVersion,
962
+ componentType: FormComponentType.DROPDOWN,
963
+ initialValue: ClientAuthMethod.POST,
964
+ options: CLIENT_AUTH_METHOD_OPTIONS,
965
+ display: {
966
+ show: {
967
+ authType: [IntegrationAuthType.OAUTH2_CODE],
968
+ 'authConfig.usePkce': PKCE_ON_MARKERS
969
+ }
970
+ }
971
+ } satisfies FormItem
972
+ ]
973
+ : []),
974
+ ...(pkceStartVersion
975
+ ? [
976
+ {
977
+ // Keep the stored method if the current agent only supports
978
+ // public PKCE. No initial value avoids writing a default into
979
+ // configs that never chose one.
980
+ label: 'Client authentication',
981
+ name: 'authConfig.clientAuthMethod',
982
+ startVersion: pkceStartVersion,
983
+ componentType: FormComponentType.DROPDOWN,
984
+ hidden: true,
985
+ options: CLIENT_AUTH_METHOD_OPTIONS,
986
+ display: {
987
+ show: {
988
+ authType: [IntegrationAuthType.OAUTH2_CODE],
989
+ 'authConfig.usePkce': PKCE_ON_MARKERS
990
+ }
991
+ }
992
+ } satisfies FormItem
993
+ ]
994
+ : []),
995
+ ...(pkceStartVersion
996
+ ? [
997
+ {
998
+ label: '',
999
+ name: 'authConfig.usePkce',
1000
+ startVersion: pkceStartVersion,
1001
+ componentType: FormComponentType.CHECKBOX,
1002
+ hidden: true,
1003
+ display: {
1004
+ show: {
1005
+ authType: [IntegrationAuthType.OAUTH2_CODE]
1006
+ }
1007
+ }
1008
+ } satisfies FormItem
1009
+ ]
1010
+ : []),
904
1011
  {
905
1012
  label: 'Send state parameter',
906
1013
  name: 'authConfig.sendOAuthState',
@@ -1361,6 +1468,7 @@ export const authSections = ({
1361
1468
  'authConfig.authorizationUrl',
1362
1469
  'authConfig.refreshTokenFromServer',
1363
1470
  'authConfig.clientAuthMethod',
1471
+ 'authConfig.usePkce',
1364
1472
  'dynamicWorkflowConfiguration.enabled',
1365
1473
  'dynamicWorkflowConfiguration.workflowId'
1366
1474
  ],
@@ -1467,13 +1575,13 @@ function apiKeyAuthOptions(pluginId: ExtendedIntegrationPluginId): DropdownOptio
1467
1575
  function authTypeOptions({
1468
1576
  enabledMethods,
1469
1577
  allowNone = true,
1470
- isProto = false,
1471
- apiKeyFormDisplayName
1578
+ apiKeyFormDisplayName,
1579
+ pkceStartVersion
1472
1580
  }: {
1473
1581
  enabledMethods: AuthMethods;
1474
1582
  allowNone?: boolean;
1475
- isProto?: boolean;
1476
1583
  apiKeyFormDisplayName?: string;
1584
+ pkceStartVersion?: string;
1477
1585
  }): DropdownOption[] {
1478
1586
  const options: DropdownOption[] = allowNone
1479
1587
  ? [
@@ -1537,6 +1645,15 @@ function authTypeOptions({
1537
1645
  value: IntegrationAuthType.OAUTH2_CODE,
1538
1646
  key: IntegrationAuthType.OAUTH2_CODE
1539
1647
  });
1648
+ if (pkceStartVersion) {
1649
+ options.push({
1650
+ displayName: `${getDisplayName(IntegrationAuthType.OAUTH2_CODE)} (with PKCE)`,
1651
+ value: IntegrationAuthType.OAUTH2_CODE,
1652
+ key: `${IntegrationAuthType.OAUTH2_CODE}-pkce`,
1653
+ secondaryValue: true,
1654
+ startVersion: pkceStartVersion
1655
+ });
1656
+ }
1540
1657
  options.push({
1541
1658
  displayName: getDisplayName(IntegrationAuthType.OAUTH2_IMPLICIT),
1542
1659
  value: IntegrationAuthType.OAUTH2_IMPLICIT,
@@ -8,5 +8,7 @@ export const RestApiIntegrationPluginVersions = {
8
8
  V7: '0.0.7',
9
9
  V8: '0.0.8',
10
10
  V13: '0.0.13',
11
- V14: '0.0.14'
11
+ V14: '0.0.14',
12
+ V16: '0.0.16',
13
+ V17: '0.0.17'
12
14
  };
@@ -0,0 +1,29 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { createRequire } from 'node:module';
3
+ import path from 'node:path';
4
+
5
+ import { describe, expect, it } from 'vitest';
6
+
7
+ /**
8
+ * Gateway (and the CLI esbuild bundle Cursor MCP loads) resolve
9
+ * `@superblocksteam/shared` to this package's Node entry (`dist/`), not
10
+ * `src/`. A stale dist that predates SocketHeartbeat makes Cursor MCP crash
11
+ * with: "does not provide an export named 'SocketHeartbeat'". Rebuild shared
12
+ * before Gateway and the CLI after changing this export.
13
+ */
14
+ describe('Node package entry', () => {
15
+ it('exports SocketHeartbeat as a named binding Gateway can import', async () => {
16
+ const require = createRequire(path.join(process.cwd(), 'package.json'));
17
+ let entry: string;
18
+ try {
19
+ entry = require.resolve('@superblocksteam/shared');
20
+ } catch {
21
+ return;
22
+ }
23
+ if (!existsSync(entry)) {
24
+ return;
25
+ }
26
+ const shared = await import(entry);
27
+ expect(typeof shared.SocketHeartbeat).toBe('function');
28
+ });
29
+ });