@superblocksteam/shared 0.9607.3 → 0.9608.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 (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
@@ -41,6 +41,7 @@ export * from './GetPublicApiResponseBody.js';
41
41
  export * from './GetPublicOrganizationSummaryResponseBody.js';
42
42
  export * from './IssueSuperblocksResponseBody.js';
43
43
  export * from './GetAllApplicationsResponseBody.js';
44
+ export * from './GetRecentApplicationsResponseBody.js';
44
45
  export * from './PatchApplicationResponseBody.js';
45
46
  export * from './PatchHomePageItemsResponseBody.js';
46
47
  export * from './ListApplicationBuildsResponseBody.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/response/index.ts"],"names":[],"mappings":"AAAA,cAAc,yCAAyC,CAAC;AACxD,cAAc,wCAAwC,CAAC;AACvD,cAAc,oCAAoC,CAAC;AACnD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,yBAAyB,CAAC;AACxC,cAAc,wCAAwC,CAAC;AACvD,cAAc,yCAAyC,CAAC;AACxD,cAAc,iCAAiC,CAAC;AAChD,cAAc,oCAAoC,CAAC;AACnD,cAAc,0CAA0C,CAAC;AACzD,cAAc,qCAAqC,CAAC;AACpD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8CAA8C,CAAC;AAC7D,cAAc,sCAAsC,CAAC;AACrD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,oDAAoD,CAAC;AACnE,cAAc,wCAAwC,CAAC;AACvD,cAAc,wCAAwC,CAAC;AACvD,cAAc,uCAAuC,CAAC;AACtD,cAAc,uCAAuC,CAAC;AACtD,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC;AACrD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4CAA4C,CAAC;AAC3D,cAAc,oCAAoC,CAAC;AACnD,cAAc,wCAAwC,CAAC;AACvD,cAAc,yCAAyC,CAAC;AACxD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,uCAAuC,CAAC;AACtD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wCAAwC,CAAC;AACvD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+CAA+C,CAAC;AAC9D,cAAc,uCAAuC,CAAC;AACtD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,+CAA+C,CAAC;AAC9D,cAAc,mCAAmC,CAAC;AAClD,cAAc,qCAAqC,CAAC;AACpD,cAAc,mCAAmC,CAAC;AAClD,cAAc,qCAAqC,CAAC;AACpD,cAAc,wCAAwC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/response/index.ts"],"names":[],"mappings":"AAAA,cAAc,yCAAyC,CAAC;AACxD,cAAc,wCAAwC,CAAC;AACvD,cAAc,oCAAoC,CAAC;AACnD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,yBAAyB,CAAC;AACxC,cAAc,wCAAwC,CAAC;AACvD,cAAc,yCAAyC,CAAC;AACxD,cAAc,iCAAiC,CAAC;AAChD,cAAc,oCAAoC,CAAC;AACnD,cAAc,0CAA0C,CAAC;AACzD,cAAc,qCAAqC,CAAC;AACpD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8CAA8C,CAAC;AAC7D,cAAc,sCAAsC,CAAC;AACrD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,oDAAoD,CAAC;AACnE,cAAc,wCAAwC,CAAC;AACvD,cAAc,wCAAwC,CAAC;AACvD,cAAc,uCAAuC,CAAC;AACtD,cAAc,uCAAuC,CAAC;AACtD,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC;AACrD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4CAA4C,CAAC;AAC3D,cAAc,oCAAoC,CAAC;AACnD,cAAc,wCAAwC,CAAC;AACvD,cAAc,yCAAyC,CAAC;AACxD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,uCAAuC,CAAC;AACtD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wCAAwC,CAAC;AACvD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+CAA+C,CAAC;AAC9D,cAAc,uCAAuC,CAAC;AACtD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,+CAA+C,CAAC;AAC9D,cAAc,mCAAmC,CAAC;AAClD,cAAc,qCAAqC,CAAC;AACpD,cAAc,wCAAwC,CAAC;AACvD,cAAc,mCAAmC,CAAC;AAClD,cAAc,qCAAqC,CAAC;AACpD,cAAc,wCAAwC,CAAC"}
@@ -41,6 +41,7 @@ export * from './GetPublicApiResponseBody.js';
41
41
  export * from './GetPublicOrganizationSummaryResponseBody.js';
42
42
  export * from './IssueSuperblocksResponseBody.js';
43
43
  export * from './GetAllApplicationsResponseBody.js';
44
+ export * from './GetRecentApplicationsResponseBody.js';
44
45
  export * from './PatchApplicationResponseBody.js';
45
46
  export * from './PatchHomePageItemsResponseBody.js';
46
47
  export * from './ListApplicationBuildsResponseBody.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/types/response/index.ts"],"names":[],"mappings":"AAAA,cAAc,yCAAyC,CAAC;AACxD,cAAc,wCAAwC,CAAC;AACvD,cAAc,oCAAoC,CAAC;AACnD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,yBAAyB,CAAC;AACxC,cAAc,wCAAwC,CAAC;AACvD,cAAc,yCAAyC,CAAC;AACxD,cAAc,iCAAiC,CAAC;AAChD,cAAc,oCAAoC,CAAC;AACnD,cAAc,0CAA0C,CAAC;AACzD,cAAc,qCAAqC,CAAC;AACpD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8CAA8C,CAAC;AAC7D,cAAc,sCAAsC,CAAC;AACrD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,oDAAoD,CAAC;AACnE,cAAc,wCAAwC,CAAC;AACvD,cAAc,wCAAwC,CAAC;AACvD,cAAc,uCAAuC,CAAC;AACtD,cAAc,uCAAuC,CAAC;AACtD,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC;AACrD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4CAA4C,CAAC;AAC3D,cAAc,oCAAoC,CAAC;AACnD,cAAc,wCAAwC,CAAC;AACvD,cAAc,yCAAyC,CAAC;AACxD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,uCAAuC,CAAC;AACtD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wCAAwC,CAAC;AACvD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+CAA+C,CAAC;AAC9D,cAAc,uCAAuC,CAAC;AACtD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,+CAA+C,CAAC;AAC9D,cAAc,mCAAmC,CAAC;AAClD,cAAc,qCAAqC,CAAC;AACpD,cAAc,mCAAmC,CAAC;AAClD,cAAc,qCAAqC,CAAC;AACpD,cAAc,wCAAwC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/types/response/index.ts"],"names":[],"mappings":"AAAA,cAAc,yCAAyC,CAAC;AACxD,cAAc,wCAAwC,CAAC;AACvD,cAAc,oCAAoC,CAAC;AACnD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,yBAAyB,CAAC;AACxC,cAAc,wCAAwC,CAAC;AACvD,cAAc,yCAAyC,CAAC;AACxD,cAAc,iCAAiC,CAAC;AAChD,cAAc,oCAAoC,CAAC;AACnD,cAAc,0CAA0C,CAAC;AACzD,cAAc,qCAAqC,CAAC;AACpD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8CAA8C,CAAC;AAC7D,cAAc,sCAAsC,CAAC;AACrD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,oDAAoD,CAAC;AACnE,cAAc,wCAAwC,CAAC;AACvD,cAAc,wCAAwC,CAAC;AACvD,cAAc,uCAAuC,CAAC;AACtD,cAAc,uCAAuC,CAAC;AACtD,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC;AACrD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4CAA4C,CAAC;AAC3D,cAAc,oCAAoC,CAAC;AACnD,cAAc,wCAAwC,CAAC;AACvD,cAAc,yCAAyC,CAAC;AACxD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,uCAAuC,CAAC;AACtD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wCAAwC,CAAC;AACvD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+CAA+C,CAAC;AAC9D,cAAc,uCAAuC,CAAC;AACtD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,+CAA+C,CAAC;AAC9D,cAAc,mCAAmC,CAAC;AAClD,cAAc,qCAAqC,CAAC;AACpD,cAAc,wCAAwC,CAAC;AACvD,cAAc,mCAAmC,CAAC;AAClD,cAAc,qCAAqC,CAAC;AACpD,cAAc,wCAAwC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superblocksteam/shared",
3
- "version": "0.9607.3",
3
+ "version": "0.9608.1",
4
4
  "description": "Superblocks Shared Resources",
5
5
  "license": "Superblocks Community Software License",
6
6
  "repository": "https://github.com/superblocksteam/shared.git",
@@ -0,0 +1,55 @@
1
+ import { describe, expect, test } from 'vitest';
2
+
3
+ import { ViewMode } from '../types/event/index.js';
4
+ import { type AppDatabaseTagCompatibility, rollUpAppDatabaseCompatibility } from './appDatabaseCompatibility.js';
5
+
6
+ function tag(overrides: Partial<AppDatabaseTagCompatibility> & Pick<AppDatabaseTagCompatibility, 'profileKey' | 'supportState'>) {
7
+ return {
8
+ availableModes: [ViewMode.EDITOR],
9
+ missingOperations: [],
10
+ requiredOperations: ['ensure_database', 'migrate_schema'],
11
+ ...overrides
12
+ } satisfies AppDatabaseTagCompatibility;
13
+ }
14
+
15
+ describe('rolling up per-tag support into an app-wide verdict', () => {
16
+ test('an app whose every data tag is served is compatible', () => {
17
+ const rollUp = rollUpAppDatabaseCompatibility([
18
+ tag({ profileKey: 'staging', supportState: 'supported' }),
19
+ tag({ profileKey: 'production', supportState: 'supported' })
20
+ ]);
21
+
22
+ expect(rollUp).toEqual({ needsAttention: false, overallState: 'compatible' });
23
+ });
24
+
25
+ test('one unserved data tag makes the whole app incompatible even when siblings are served', () => {
26
+ const rollUp = rollUpAppDatabaseCompatibility([
27
+ tag({ profileKey: 'staging', supportState: 'supported' }),
28
+ tag({ missingOperations: ['ensure_database'], profileKey: 'restricted', supportState: 'unsupported' })
29
+ ]);
30
+
31
+ expect(rollUp).toEqual({ needsAttention: true, overallState: 'incompatible' });
32
+ });
33
+
34
+ test('a capability lookup outage is reported as temporary rather than as a missing capability', () => {
35
+ const rollUp = rollUpAppDatabaseCompatibility([
36
+ tag({ profileKey: 'staging', supportState: 'temporarily_unavailable' }),
37
+ tag({ profileKey: 'production', supportState: 'temporarily_unavailable' })
38
+ ]);
39
+
40
+ expect(rollUp).toEqual({ needsAttention: false, overallState: 'temporarily_unavailable' });
41
+ });
42
+
43
+ test('a permanently unserved tag is still reported while another tag is only temporarily unknown', () => {
44
+ const rollUp = rollUpAppDatabaseCompatibility([
45
+ tag({ profileKey: 'staging', supportState: 'temporarily_unavailable' }),
46
+ tag({ missingOperations: ['migrate_schema'], profileKey: 'restricted', supportState: 'unsupported' })
47
+ ]);
48
+
49
+ expect(rollUp).toEqual({ needsAttention: true, overallState: 'incompatible' });
50
+ });
51
+
52
+ test('an app with no data tags to check is compatible', () => {
53
+ expect(rollUpAppDatabaseCompatibility([])).toEqual({ needsAttention: false, overallState: 'compatible' });
54
+ });
55
+ });
@@ -0,0 +1,62 @@
1
+ import type { ViewMode } from '../types/event/index.js';
2
+ import type { LifecycleOperation } from './index.js';
3
+
4
+ /**
5
+ * Whether lifecycle workers can serve App Database work for one data tag.
6
+ *
7
+ * `unsupported` is a standing gap: workers are connected, but none of them
8
+ * handles this tag. `temporarily_unavailable` means we could not tell —
9
+ * nothing is registered right now, or the lookup itself failed — so the tag
10
+ * may start working again without anyone changing the app.
11
+ */
12
+ export const APP_DATABASE_TAG_SUPPORT_STATES = ['supported', 'temporarily_unavailable', 'unsupported'] as const;
13
+ export type AppDatabaseTagSupportState = (typeof APP_DATABASE_TAG_SUPPORT_STATES)[number];
14
+
15
+ export const APP_DATABASE_COMPATIBILITY_STATES = ['compatible', 'incompatible', 'temporarily_unavailable'] as const;
16
+ export type AppDatabaseCompatibilityState = (typeof APP_DATABASE_COMPATIBILITY_STATES)[number];
17
+
18
+ /** Lifecycle operations an App Database cannot work without. */
19
+ export const APP_DATABASE_REQUIRED_OPERATIONS: readonly LifecycleOperation[] = ['ensure_database', 'migrate_schema'];
20
+
21
+ export type AppDatabaseTagCompatibility = {
22
+ /** App view modes that offer this data tag, for messaging. */
23
+ availableModes: ViewMode[];
24
+ missingOperations: LifecycleOperation[];
25
+ profileKey: string;
26
+ requiredOperations: LifecycleOperation[];
27
+ supportState: AppDatabaseTagSupportState;
28
+ };
29
+
30
+ export type AppDatabaseCompatibility = {
31
+ applicationId: string;
32
+ /**
33
+ * Whether the app declares an App Database right now. An app without one is
34
+ * never blocked by a data tag gap, so callers use this to stay quiet instead
35
+ * of warning about a problem the user does not have.
36
+ */
37
+ hasAppDatabase: boolean;
38
+ /** True only when someone has to change the app for it to work again. */
39
+ needsAttention: boolean;
40
+ overallState: AppDatabaseCompatibilityState;
41
+ /** Every data tag the app can run App Database work for, sorted by key. */
42
+ tags: AppDatabaseTagCompatibility[];
43
+ };
44
+
45
+ /**
46
+ * Fold per-tag support into the app-wide verdict. A standing gap outranks a
47
+ * temporary one: a tag no worker serves has to be reported even while another
48
+ * tag's capability is momentarily unknown, otherwise the outage hides work the
49
+ * user actually has to do.
50
+ */
51
+ export function rollUpAppDatabaseCompatibility(tags: readonly AppDatabaseTagCompatibility[]): {
52
+ needsAttention: boolean;
53
+ overallState: AppDatabaseCompatibilityState;
54
+ } {
55
+ if (tags.some((tag) => tag.supportState === 'unsupported')) {
56
+ return { needsAttention: true, overallState: 'incompatible' };
57
+ }
58
+ if (tags.some((tag) => tag.supportState === 'temporarily_unavailable')) {
59
+ return { needsAttention: false, overallState: 'temporarily_unavailable' };
60
+ }
61
+ return { needsAttention: false, overallState: 'compatible' };
62
+ }
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, test } from 'vitest';
2
2
 
3
- import { analyzeDestructiveMigrations } from './destructiveMigrations.js';
3
+ import { analyzeDestructiveMigrations, analyzeDestructiveMigrationsRequiringAck } from './destructiveMigrations.js';
4
4
 
5
5
  describe('analyzeDestructiveMigrations', () => {
6
6
  test('returns empty when SQL has no destructive statements', () => {
@@ -114,3 +114,110 @@ CREATE TABLE users (id int);
114
114
  expect(findings[1]).toMatchObject({ fileName: 'b.sql', kind: 'truncate' });
115
115
  });
116
116
  });
117
+
118
+ describe('analyzeDestructiveMigrationsRequiringAck', () => {
119
+ test('does not require an ack for a drop of a table created earlier in the same batch', () => {
120
+ // The whole set runs as one batch. Dropping a table that this batch just
121
+ // created removes nothing that existed before the batch started.
122
+ expect(
123
+ analyzeDestructiveMigrationsRequiringAck([
124
+ { fileName: '0001_init.sql', sql: 'CREATE TABLE users (id int);' },
125
+ { fileName: '0002_drop.sql', sql: 'DROP TABLE users;' }
126
+ ])
127
+ ).toEqual([]);
128
+ });
129
+
130
+ test('still requires an ack for a drop of a table the batch never created', () => {
131
+ // A ready database can hold tables written by the app with no migrate
132
+ // history. A DROP of those is genuinely destructive.
133
+ expect(analyzeDestructiveMigrationsRequiringAck([{ fileName: '0001_drop.sql', sql: 'DROP TABLE orders;' }])).toEqual([
134
+ expect.objectContaining({ fileName: '0001_drop.sql', kind: 'drop_table' })
135
+ ]);
136
+ });
137
+
138
+ test('still requires an ack when the drop appears before the create in the batch', () => {
139
+ // DROP then CREATE would wipe any pre-existing table of that name.
140
+ expect(
141
+ analyzeDestructiveMigrationsRequiringAck([
142
+ { fileName: '0001_drop.sql', sql: 'DROP TABLE users;' },
143
+ { fileName: '0002_init.sql', sql: 'CREATE TABLE users (id int);' }
144
+ ])
145
+ ).toEqual([expect.objectContaining({ kind: 'drop_table' })]);
146
+ });
147
+
148
+ test('does not require an ack for truncate or drop column on a table created earlier in the batch', () => {
149
+ expect(
150
+ analyzeDestructiveMigrationsRequiringAck([
151
+ {
152
+ fileName: '0001_init.sql',
153
+ sql: 'CREATE TABLE users (id int, email text); ALTER TABLE users ADD COLUMN name text;'
154
+ },
155
+ {
156
+ fileName: '0002_cleanup.sql',
157
+ sql: 'TRUNCATE TABLE users; ALTER TABLE users DROP COLUMN email;'
158
+ }
159
+ ])
160
+ ).toEqual([]);
161
+ });
162
+
163
+ test('still requires an ack for drop database and drop schema even after creates in the batch', () => {
164
+ expect(
165
+ analyzeDestructiveMigrationsRequiringAck([
166
+ { fileName: '0001.sql', sql: 'CREATE SCHEMA app; CREATE DATABASE scratch;' },
167
+ { fileName: '0002.sql', sql: 'DROP SCHEMA app; DROP DATABASE scratch;' }
168
+ ])
169
+ .map((finding) => finding.kind)
170
+ .sort()
171
+ ).toEqual(['drop_database', 'drop_schema']);
172
+ });
173
+
174
+ test('still requires an ack for a multi-table drop when any target was not created in the batch', () => {
175
+ // DROP TABLE can list several names. Covering only the first must not
176
+ // suppress the statement — the other names may already hold customer data.
177
+ expect(
178
+ analyzeDestructiveMigrationsRequiringAck([
179
+ { fileName: '0001_init.sql', sql: 'CREATE TABLE users (id int);' },
180
+ { fileName: '0002_drop.sql', sql: 'DROP TABLE IF EXISTS users, orders;' }
181
+ ])
182
+ ).toEqual([expect.objectContaining({ kind: 'drop_table' })]);
183
+ });
184
+
185
+ test('still requires an ack for a multi-table truncate when any target was not created in the batch', () => {
186
+ expect(
187
+ analyzeDestructiveMigrationsRequiringAck([
188
+ { fileName: '0001_init.sql', sql: 'CREATE TABLE users (id int);' },
189
+ { fileName: '0002_cleanup.sql', sql: 'TRUNCATE TABLE users, orders;' }
190
+ ])
191
+ ).toEqual([expect.objectContaining({ kind: 'truncate' })]);
192
+ });
193
+
194
+ test('does not require an ack for a multi-table drop when every target was created in the batch', () => {
195
+ expect(
196
+ analyzeDestructiveMigrationsRequiringAck([
197
+ { fileName: '0001_init.sql', sql: 'CREATE TABLE users (id int); CREATE TABLE orders (id int);' },
198
+ { fileName: '0002_drop.sql', sql: 'DROP TABLE users, orders;' }
199
+ ])
200
+ ).toEqual([]);
201
+ });
202
+
203
+ test('still requires an ack when create and drop use different schema qualification', () => {
204
+ // Exact identifier match only. public.users and users may be the same
205
+ // relation in Postgres, but we cannot prove that from the SQL text alone,
206
+ // so mismatched spelling stays acknowledged (fail closed).
207
+ expect(
208
+ analyzeDestructiveMigrationsRequiringAck([
209
+ { fileName: '0001_init.sql', sql: 'CREATE TABLE users (id int);' },
210
+ { fileName: '0002_drop.sql', sql: 'DROP TABLE public.users;' }
211
+ ])
212
+ ).toEqual([expect.objectContaining({ kind: 'drop_table' })]);
213
+ });
214
+
215
+ test('does not require an ack when create and drop use the same schema-qualified name', () => {
216
+ expect(
217
+ analyzeDestructiveMigrationsRequiringAck([
218
+ { fileName: '0001_init.sql', sql: 'CREATE TABLE public.users (id int);' },
219
+ { fileName: '0002_drop.sql', sql: 'DROP TABLE public.users;' }
220
+ ])
221
+ ).toEqual([]);
222
+ });
223
+ });
@@ -81,6 +81,99 @@ function classifyStatement(statement: string): DestructiveMigrationKind | undefi
81
81
  return undefined;
82
82
  }
83
83
 
84
+ function normalizeSqlIdent(raw: string): string {
85
+ return raw.replace(/"/g, '').toLowerCase();
86
+ }
87
+
88
+ /** Optional schema-qualified identifier, with optional quoting on each part. */
89
+ const SQL_IDENT = String.raw`(?:"[^"]+"|\w+)(?:\.(?:"[^"]+"|\w+))?`;
90
+
91
+ function matchFirstIdent(statement: string, pattern: RegExp): string | undefined {
92
+ const match = pattern.exec(statement);
93
+ const raw = match?.[1];
94
+ return raw === undefined ? undefined : normalizeSqlIdent(raw);
95
+ }
96
+
97
+ /**
98
+ * Pull every table name from a comma-separated DROP TABLE / TRUNCATE list.
99
+ * Returns undefined when the list cannot be parsed safely — callers must then
100
+ * require acknowledgment (fail closed).
101
+ */
102
+ function matchTableListTargets(statement: string, header: RegExp): string[] | undefined {
103
+ const headerMatch = header.exec(statement);
104
+ if (headerMatch === null) {
105
+ return undefined;
106
+ }
107
+ const afterHeader = statement.slice(headerMatch[0].length);
108
+ const listPart = afterHeader.split(/\b(?:CASCADE|RESTRICT|CONTINUE\s+IDENTITY|RESTART\s+IDENTITY)\b/i)[0] ?? '';
109
+ const tables: string[] = [];
110
+ for (const part of listPart.split(',')) {
111
+ const trimmed = part.trim();
112
+ if (trimmed.length === 0) {
113
+ continue;
114
+ }
115
+ // TRUNCATE allows ONLY before each name.
116
+ const raw = matchFirstIdent(trimmed, new RegExp(String.raw`^(?:ONLY\s+)?(${SQL_IDENT})`, 'i'));
117
+ if (raw === undefined) {
118
+ return undefined;
119
+ }
120
+ tables.push(raw);
121
+ }
122
+ return tables.length > 0 ? tables : undefined;
123
+ }
124
+
125
+ function allTablesCreatedInBatch(tables: string[] | undefined, createdTables: Set<string>): boolean {
126
+ return tables !== undefined && tables.length > 0 && tables.every((table) => createdTables.has(table));
127
+ }
128
+
129
+ function recordCreates(statement: string, createdTables: Set<string>, createdColumns: Set<string>): void {
130
+ const table = matchFirstIdent(statement, new RegExp(String.raw`^\s*CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?(${SQL_IDENT})`, 'i'));
131
+ if (table !== undefined) {
132
+ createdTables.add(table);
133
+ }
134
+ const addColumn = new RegExp(String.raw`^\s*ALTER\s+TABLE\s+(${SQL_IDENT})\s+ADD\s+(?:COLUMN\s+)?(${SQL_IDENT})`, 'i').exec(statement);
135
+ if (addColumn?.[1] !== undefined && addColumn[2] !== undefined) {
136
+ createdColumns.add(`${normalizeSqlIdent(addColumn[1])}.${normalizeSqlIdent(addColumn[2])}`);
137
+ }
138
+ }
139
+
140
+ function isCoveredByEarlierCreate(
141
+ kind: DestructiveMigrationKind,
142
+ statement: string,
143
+ createdTables: Set<string>,
144
+ createdColumns: Set<string>
145
+ ): boolean {
146
+ switch (kind) {
147
+ case 'drop_table': {
148
+ return allTablesCreatedInBatch(matchTableListTargets(statement, /^\s*DROP\s+TABLE\s+(?:IF\s+EXISTS\s+)?/i), createdTables);
149
+ }
150
+ case 'truncate': {
151
+ return allTablesCreatedInBatch(matchTableListTargets(statement, /^\s*TRUNCATE\s+(?:TABLE\s+)?/i), createdTables);
152
+ }
153
+ case 'drop_column': {
154
+ const alterDrop = new RegExp(
155
+ String.raw`^\s*ALTER\s+TABLE\s+(${SQL_IDENT})\s+[\s\S]*?\bDROP\s+(?:COLUMN\s+)?(?!CONSTRAINT\b|INDEX\b|TRIGGER\b|RULE\b|POLICY\b|STATISTICS\b|IDENTITY\b|NOT\b|DEFAULT\b|EXPRESSION\b)(${SQL_IDENT})`,
156
+ 'i'
157
+ ).exec(statement);
158
+ if (alterDrop?.[1] !== undefined && alterDrop[2] !== undefined) {
159
+ const table = normalizeSqlIdent(alterDrop[1]);
160
+ const column = normalizeSqlIdent(alterDrop[2]);
161
+ return createdTables.has(table) || createdColumns.has(`${table}.${column}`);
162
+ }
163
+ // Standalone DROP COLUMN has no table context — cannot prove coverage.
164
+ return false;
165
+ }
166
+ case 'drop_database':
167
+ case 'drop_schema':
168
+ // Creating the container in the same batch does not prove it is free of
169
+ // customer data, so these always require an acknowledgment.
170
+ return false;
171
+ default: {
172
+ return false;
173
+ }
174
+ }
175
+ }
176
+
84
177
  /**
85
178
  * Scans migration SQL for schema-destroying statements that require an
86
179
  * explicit user acknowledgment before apply/deploy.
@@ -103,3 +196,39 @@ export function analyzeDestructiveMigrations(files: DestructiveMigrationFile[]):
103
196
  }
104
197
  return findings;
105
198
  }
199
+
200
+ /**
201
+ * Like analyzeDestructiveMigrations, but omits drops/truncates of objects this
202
+ * same unscanned batch created earlier. Those remove nothing that existed before
203
+ * the batch started, so they are not acknowledged. A drop that appears before
204
+ * its create, or that targets an object the batch never creates, still requires
205
+ * an ack — including when the control plane has never migrated this binding,
206
+ * because a ready database can hold tables the app wrote without migrations.
207
+ *
208
+ * DROP DATABASE / DROP SCHEMA are never suppressed this way: creating the
209
+ * container in the same batch does not prove it is free of customer data.
210
+ */
211
+ export function analyzeDestructiveMigrationsRequiringAck(files: DestructiveMigrationFile[]): DestructiveMigrationFinding[] {
212
+ const createdTables = new Set<string>();
213
+ const createdColumns = new Set<string>();
214
+ const findings: DestructiveMigrationFinding[] = [];
215
+ for (const file of files) {
216
+ const statements = splitStatements(stripSqlComments(file.sql));
217
+ for (const statement of statements) {
218
+ recordCreates(statement, createdTables, createdColumns);
219
+ const kind = classifyStatement(statement);
220
+ if (kind === undefined) {
221
+ continue;
222
+ }
223
+ if (isCoveredByEarlierCreate(kind, statement, createdTables, createdColumns)) {
224
+ continue;
225
+ }
226
+ findings.push({
227
+ fileName: file.fileName,
228
+ kind,
229
+ excerpt: excerptFor(statement)
230
+ });
231
+ }
232
+ }
233
+ return findings;
234
+ }
@@ -78,6 +78,7 @@ export const LIFECYCLE_ERROR_CODES = [
78
78
  'terraform_failed',
79
79
  'migration_failed',
80
80
  'callback_failed',
81
+ 'configuration_conflict',
81
82
  // Server-side classification for a terminal callback that arrived for a
82
83
  // request whose desiredSpecHash no longer matches the binding (binding has
83
84
  // moved to a newer spec). The callback's metadata/state is discarded and
@@ -87,6 +88,176 @@ export const LIFECYCLE_ERROR_CODES = [
87
88
 
88
89
  export type LifecycleErrorCode = (typeof LIFECYCLE_ERROR_CODES)[number];
89
90
 
91
+ export const LIFECYCLE_PROVIDER_DIAGNOSTIC_PHASES = ['apply', 'destroy', 'init', 'plan', 'unknown'] as const;
92
+ export const MAX_LIFECYCLE_PROVIDER_DIAGNOSTICS = 3;
93
+ export const LIFECYCLE_PROVIDER_DIAGNOSTIC_AWS_SERVICE_PATTERN = /^[a-z][a-z0-9-]{0,31}$/;
94
+ export const LIFECYCLE_PROVIDER_DIAGNOSTIC_AWS_OPERATION_PATTERN = /^[A-Za-z][A-Za-z0-9]{0,63}$/;
95
+ export const LIFECYCLE_PROVIDER_DIAGNOSTIC_AWS_ERROR_CODE_PATTERN = /^[A-Za-z][A-Za-z0-9.]{0,63}$/;
96
+ export const LIFECYCLE_PROVIDER_DIAGNOSTIC_AWS_REQUEST_ID_PATTERN =
97
+ /^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/;
98
+ export const LIFECYCLE_PROVIDER_DIAGNOSTIC_AWS_S3_REQUEST_ID_PATTERN = /^[0-9A-Za-z]{16}$/;
99
+ export const LIFECYCLE_PROVIDER_DIAGNOSTIC_AWS_DYNAMODB_REQUEST_ID_PATTERN = /^[0-9A-Za-z]{52}$/;
100
+ export const LIFECYCLE_PROVIDER_DIAGNOSTIC_POSTGRESQL_SQL_STATE_PATTERN = /^[0-9A-Za-z]{5}$/;
101
+
102
+ export function isLifecycleProviderDiagnosticAwsRequestId(service: string, requestId: unknown): requestId is string {
103
+ if (typeof requestId !== 'string') {
104
+ return false;
105
+ }
106
+ if (LIFECYCLE_PROVIDER_DIAGNOSTIC_AWS_REQUEST_ID_PATTERN.test(requestId)) {
107
+ return true;
108
+ }
109
+ if (service === 's3') {
110
+ return LIFECYCLE_PROVIDER_DIAGNOSTIC_AWS_S3_REQUEST_ID_PATTERN.test(requestId);
111
+ }
112
+ if (service === 'dynamodb') {
113
+ return LIFECYCLE_PROVIDER_DIAGNOSTIC_AWS_DYNAMODB_REQUEST_ID_PATTERN.test(requestId);
114
+ }
115
+ return false;
116
+ }
117
+
118
+ export type LifecycleProviderDiagnosticPhase = (typeof LIFECYCLE_PROVIDER_DIAGNOSTIC_PHASES)[number];
119
+
120
+ type LifecycleProviderDiagnosticBase = {
121
+ phase: LifecycleProviderDiagnosticPhase;
122
+ retryable: boolean;
123
+ };
124
+
125
+ export type LifecycleAwsProviderDiagnostic = LifecycleProviderDiagnosticBase & {
126
+ provider: 'aws';
127
+ service: string;
128
+ operation: string;
129
+ errorCode: string;
130
+ requestId?: string;
131
+ nextAction: 'review_aws_operation';
132
+ };
133
+
134
+ export type LifecyclePostgresqlProviderDiagnostic = LifecycleProviderDiagnosticBase & {
135
+ provider: 'postgresql';
136
+ sqlState: string;
137
+ nextAction: 'review_database_operation';
138
+ };
139
+
140
+ // Sanitized, allowlisted provider facts emitted by the lifecycle worker.
141
+ // Provider-authored summary/detail text is deliberately not part of this
142
+ // contract; consumers can display these fields without forwarding raw
143
+ // OpenTofu output.
144
+ export type LifecycleProviderDiagnostic = LifecycleAwsProviderDiagnostic | LifecyclePostgresqlProviderDiagnostic;
145
+
146
+ export type LifecycleProviderDiagnosticCandidateProvider = 'aws' | 'postgresql' | 'unknown';
147
+
148
+ export type LifecycleProviderDiagnosticCandidateInspection = {
149
+ provider: LifecycleProviderDiagnosticCandidateProvider;
150
+ diagnostic?: LifecycleProviderDiagnostic;
151
+ rejectedFields?: string[];
152
+ sanitizedFields?: string[];
153
+ };
154
+
155
+ const lifecycleProviderDiagnosticPhases = new Set<string>(LIFECYCLE_PROVIDER_DIAGNOSTIC_PHASES);
156
+
157
+ function lifecycleProviderDiagnosticCandidateProvider(value: unknown): LifecycleProviderDiagnosticCandidateProvider {
158
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
159
+ return 'unknown';
160
+ }
161
+ const provider = (value as Record<string, unknown>).provider;
162
+ return provider === 'aws' || provider === 'postgresql' ? provider : 'unknown';
163
+ }
164
+
165
+ function lifecycleProviderDiagnosticPhase(value: unknown): LifecycleProviderDiagnosticPhase {
166
+ return typeof value === 'string' && lifecycleProviderDiagnosticPhases.has(value)
167
+ ? (value as LifecycleProviderDiagnosticPhase)
168
+ : 'unknown';
169
+ }
170
+
171
+ function invalidDiagnosticString(value: unknown, pattern: RegExp): boolean {
172
+ return typeof value !== 'string' || !pattern.test(value);
173
+ }
174
+
175
+ /**
176
+ * Canonical validation boundary for one provider diagnostic. The output is
177
+ * rebuilt from allowlisted facts, provider-authored text and unknown fields are
178
+ * discarded, and decorative fields such as nextAction are derived locally.
179
+ */
180
+ export function inspectLifecycleProviderDiagnosticCandidate(value: unknown): LifecycleProviderDiagnosticCandidateInspection {
181
+ const provider = lifecycleProviderDiagnosticCandidateProvider(value);
182
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
183
+ return { provider, rejectedFields: ['(root)'] };
184
+ }
185
+ const candidate = value as Record<string, unknown>;
186
+ if (provider === 'unknown') {
187
+ return { provider, rejectedFields: ['provider'] };
188
+ }
189
+
190
+ if (provider === 'aws') {
191
+ const rejectedFields: string[] = [];
192
+ if (invalidDiagnosticString(candidate.errorCode, LIFECYCLE_PROVIDER_DIAGNOSTIC_AWS_ERROR_CODE_PATTERN)) {
193
+ rejectedFields.push('errorCode');
194
+ }
195
+ if (invalidDiagnosticString(candidate.operation, LIFECYCLE_PROVIDER_DIAGNOSTIC_AWS_OPERATION_PATTERN)) {
196
+ rejectedFields.push('operation');
197
+ }
198
+ if (typeof candidate.retryable !== 'boolean') {
199
+ rejectedFields.push('retryable');
200
+ }
201
+ if (invalidDiagnosticString(candidate.service, LIFECYCLE_PROVIDER_DIAGNOSTIC_AWS_SERVICE_PATTERN)) {
202
+ rejectedFields.push('service');
203
+ }
204
+ if (rejectedFields.length > 0) {
205
+ return { provider, rejectedFields };
206
+ }
207
+
208
+ const requestId = candidate.requestId;
209
+ const hasSafeRequestId = isLifecycleProviderDiagnosticAwsRequestId(candidate.service as string, requestId);
210
+ return {
211
+ diagnostic: {
212
+ errorCode: candidate.errorCode as string,
213
+ nextAction: 'review_aws_operation',
214
+ operation: candidate.operation as string,
215
+ phase: lifecycleProviderDiagnosticPhase(candidate.phase),
216
+ provider,
217
+ ...(hasSafeRequestId ? { requestId } : {}),
218
+ retryable: candidate.retryable as boolean,
219
+ service: candidate.service as string
220
+ },
221
+ provider,
222
+ ...(requestId !== undefined && !hasSafeRequestId ? { sanitizedFields: ['requestId'] } : {})
223
+ };
224
+ }
225
+
226
+ const rejectedFields: string[] = [];
227
+ if (typeof candidate.retryable !== 'boolean') {
228
+ rejectedFields.push('retryable');
229
+ }
230
+ if (invalidDiagnosticString(candidate.sqlState, LIFECYCLE_PROVIDER_DIAGNOSTIC_POSTGRESQL_SQL_STATE_PATTERN)) {
231
+ rejectedFields.push('sqlState');
232
+ }
233
+ if (rejectedFields.length > 0) {
234
+ return { provider, rejectedFields };
235
+ }
236
+ return {
237
+ diagnostic: {
238
+ nextAction: 'review_database_operation',
239
+ phase: lifecycleProviderDiagnosticPhase(candidate.phase),
240
+ provider,
241
+ retryable: candidate.retryable as boolean,
242
+ sqlState: candidate.sqlState as string
243
+ },
244
+ provider
245
+ };
246
+ }
247
+
248
+ export function sanitizeLifecycleProviderDiagnostics(value: unknown): LifecycleProviderDiagnostic[] | undefined {
249
+ if (!Array.isArray(value)) {
250
+ return undefined;
251
+ }
252
+ const diagnostics = value
253
+ .flatMap((candidate) => {
254
+ const diagnostic = inspectLifecycleProviderDiagnosticCandidate(candidate).diagnostic;
255
+ return diagnostic ? [diagnostic] : [];
256
+ })
257
+ .slice(0, MAX_LIFECYCLE_PROVIDER_DIAGNOSTICS);
258
+ return diagnostics.length > 0 ? diagnostics : undefined;
259
+ }
260
+
90
261
  export type PhysicalMasterCredentialRef = {
91
262
  resolver: 'aws_secrets_manager';
92
263
  ref: string;
@@ -201,6 +372,7 @@ export type LifecycleMigration = {
201
372
 
202
373
  export {
203
374
  analyzeDestructiveMigrations,
375
+ analyzeDestructiveMigrationsRequiringAck,
204
376
  DESTRUCTIVE_MIGRATION_ACK_REQUIRED,
205
377
  DESTRUCTIVE_MIGRATION_ACK_REQUIRED_MESSAGE,
206
378
  DESTRUCTIVE_MIGRATION_SCAN_UNAVAILABLE
@@ -234,6 +406,7 @@ export type PhysicalPoolProvisioningActor = {
234
406
 
235
407
  export type PhysicalPoolProvisioningError = {
236
408
  code: string;
409
+ diagnostics?: LifecycleProviderDiagnostic[];
237
410
  message: string;
238
411
  };
239
412