@alwaysai/device-agent 1.5.0 → 2.0.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 (305) hide show
  1. package/lib/application-control/config.d.ts.map +1 -1
  2. package/lib/application-control/config.js +8 -3
  3. package/lib/application-control/config.js.map +1 -1
  4. package/lib/application-control/environment-variables.d.ts +5 -5
  5. package/lib/application-control/environment-variables.d.ts.map +1 -1
  6. package/lib/application-control/environment-variables.js +25 -38
  7. package/lib/application-control/environment-variables.js.map +1 -1
  8. package/lib/application-control/environment-variables.test.js +27 -7
  9. package/lib/application-control/environment-variables.test.js.map +1 -1
  10. package/lib/application-control/index.d.ts +4 -4
  11. package/lib/application-control/index.d.ts.map +1 -1
  12. package/lib/application-control/index.js +1 -4
  13. package/lib/application-control/index.js.map +1 -1
  14. package/lib/application-control/install.d.ts +4 -1
  15. package/lib/application-control/install.d.ts.map +1 -1
  16. package/lib/application-control/install.js +24 -8
  17. package/lib/application-control/install.js.map +1 -1
  18. package/lib/application-control/models.d.ts +0 -11
  19. package/lib/application-control/models.d.ts.map +1 -1
  20. package/lib/application-control/models.js +5 -54
  21. package/lib/application-control/models.js.map +1 -1
  22. package/lib/application-control/utils.d.ts +0 -4
  23. package/lib/application-control/utils.d.ts.map +1 -1
  24. package/lib/application-control/utils.js +12 -22
  25. package/lib/application-control/utils.js.map +1 -1
  26. package/lib/cloud-connection/base-message-handler.d.ts +27 -0
  27. package/lib/cloud-connection/base-message-handler.d.ts.map +1 -0
  28. package/lib/cloud-connection/base-message-handler.js +72 -0
  29. package/lib/cloud-connection/base-message-handler.js.map +1 -0
  30. package/lib/cloud-connection/bootstrap-provision.js +3 -2
  31. package/lib/cloud-connection/bootstrap-provision.js.map +1 -1
  32. package/lib/cloud-connection/connection-manager.d.ts +21 -0
  33. package/lib/cloud-connection/connection-manager.d.ts.map +1 -0
  34. package/lib/cloud-connection/connection-manager.js +158 -0
  35. package/lib/cloud-connection/connection-manager.js.map +1 -0
  36. package/lib/cloud-connection/device-agent-cloud-connection.d.ts +9 -30
  37. package/lib/cloud-connection/device-agent-cloud-connection.d.ts.map +1 -1
  38. package/lib/cloud-connection/device-agent-cloud-connection.js +69 -508
  39. package/lib/cloud-connection/device-agent-cloud-connection.js.map +1 -1
  40. package/lib/cloud-connection/device-agent-message-handler.d.ts +22 -0
  41. package/lib/cloud-connection/device-agent-message-handler.d.ts.map +1 -0
  42. package/lib/cloud-connection/device-agent-message-handler.js +357 -0
  43. package/lib/cloud-connection/device-agent-message-handler.js.map +1 -0
  44. package/lib/cloud-connection/device-agent.d.ts.map +1 -1
  45. package/lib/cloud-connection/device-agent.js +11 -9
  46. package/lib/cloud-connection/device-agent.js.map +1 -1
  47. package/lib/cloud-connection/live-updates-handler.d.ts +19 -28
  48. package/lib/cloud-connection/live-updates-handler.d.ts.map +1 -1
  49. package/lib/cloud-connection/live-updates-handler.js +60 -172
  50. package/lib/cloud-connection/live-updates-handler.js.map +1 -1
  51. package/lib/cloud-connection/live-updates-handler.test.js +71 -165
  52. package/lib/cloud-connection/live-updates-handler.test.js.map +1 -1
  53. package/lib/cloud-connection/message-dispatcher.d.ts +10 -0
  54. package/lib/cloud-connection/message-dispatcher.d.ts.map +1 -0
  55. package/lib/cloud-connection/message-dispatcher.js +27 -0
  56. package/lib/cloud-connection/message-dispatcher.js.map +1 -0
  57. package/lib/cloud-connection/passthrough-handler.d.ts +4 -1
  58. package/lib/cloud-connection/passthrough-handler.d.ts.map +1 -1
  59. package/lib/cloud-connection/passthrough-handler.js +30 -11
  60. package/lib/cloud-connection/passthrough-handler.js.map +1 -1
  61. package/lib/cloud-connection/shadow-handler.d.ts +11 -3
  62. package/lib/cloud-connection/shadow-handler.d.ts.map +1 -1
  63. package/lib/cloud-connection/shadow-handler.js +133 -28
  64. package/lib/cloud-connection/shadow-handler.js.map +1 -1
  65. package/lib/cloud-connection/shadow-handler.test.js +45 -57
  66. package/lib/cloud-connection/shadow-handler.test.js.map +1 -1
  67. package/lib/cloud-connection/shadow.d.ts.map +1 -1
  68. package/lib/cloud-connection/shadow.js +2 -1
  69. package/lib/cloud-connection/shadow.js.map +1 -1
  70. package/lib/cloud-connection/transaction-manager.d.ts +12 -3
  71. package/lib/cloud-connection/transaction-manager.d.ts.map +1 -1
  72. package/lib/cloud-connection/transaction-manager.js +29 -28
  73. package/lib/cloud-connection/transaction-manager.js.map +1 -1
  74. package/lib/cloud-connection/transaction-manager.test.js +46 -5
  75. package/lib/cloud-connection/transaction-manager.test.js.map +1 -1
  76. package/lib/device-control/device-control.d.ts +8 -8
  77. package/lib/device-control/device-control.d.ts.map +1 -1
  78. package/lib/device-control/device-control.js +95 -71
  79. package/lib/device-control/device-control.js.map +1 -1
  80. package/lib/docker/docker-compose.d.ts.map +1 -1
  81. package/lib/docker/docker-compose.js +2 -1
  82. package/lib/docker/docker-compose.js.map +1 -1
  83. package/lib/infrastructure/agent-config.d.ts +2 -1
  84. package/lib/infrastructure/agent-config.d.ts.map +1 -1
  85. package/lib/infrastructure/agent-config.js +7 -7
  86. package/lib/infrastructure/agent-config.js.map +1 -1
  87. package/lib/infrastructure/agent-config.test.js +3 -1
  88. package/lib/infrastructure/agent-config.test.js.map +1 -1
  89. package/lib/infrastructure/config-check-utility.d.ts +6 -0
  90. package/lib/infrastructure/config-check-utility.d.ts.map +1 -0
  91. package/lib/infrastructure/config-check-utility.js +67 -0
  92. package/lib/infrastructure/config-check-utility.js.map +1 -0
  93. package/lib/infrastructure/config-check-utility.test.d.ts +2 -0
  94. package/lib/infrastructure/config-check-utility.test.d.ts.map +1 -0
  95. package/lib/infrastructure/config-check-utility.test.js +109 -0
  96. package/lib/infrastructure/config-check-utility.test.js.map +1 -0
  97. package/lib/infrastructure/device-certificate.d.ts +10 -0
  98. package/lib/infrastructure/device-certificate.d.ts.map +1 -0
  99. package/lib/infrastructure/device-certificate.js +47 -0
  100. package/lib/infrastructure/device-certificate.js.map +1 -0
  101. package/lib/infrastructure/device-certificate.test.d.ts +2 -0
  102. package/lib/infrastructure/device-certificate.test.d.ts.map +1 -0
  103. package/lib/infrastructure/device-certificate.test.js +24 -0
  104. package/lib/infrastructure/device-certificate.test.js.map +1 -0
  105. package/lib/infrastructure/legacy-migration/legacy-file.test.d.ts +2 -0
  106. package/lib/infrastructure/legacy-migration/legacy-file.test.d.ts.map +1 -0
  107. package/lib/infrastructure/legacy-migration/legacy-file.test.js +61 -0
  108. package/lib/infrastructure/legacy-migration/legacy-file.test.js.map +1 -0
  109. package/lib/infrastructure/legacy-migration/legacy-files.d.ts +75 -0
  110. package/lib/infrastructure/legacy-migration/legacy-files.d.ts.map +1 -0
  111. package/lib/infrastructure/legacy-migration/legacy-files.js +75 -0
  112. package/lib/infrastructure/legacy-migration/legacy-files.js.map +1 -0
  113. package/lib/infrastructure/legacy-migration/legacy-migration.d.ts +6 -0
  114. package/lib/infrastructure/legacy-migration/legacy-migration.d.ts.map +1 -0
  115. package/lib/infrastructure/legacy-migration/legacy-migration.js +149 -0
  116. package/lib/infrastructure/legacy-migration/legacy-migration.js.map +1 -0
  117. package/lib/infrastructure/legacy-migration/legacy-migration.test.d.ts +2 -0
  118. package/lib/infrastructure/legacy-migration/legacy-migration.test.d.ts.map +1 -0
  119. package/lib/infrastructure/legacy-migration/legacy-migration.test.js +226 -0
  120. package/lib/infrastructure/legacy-migration/legacy-migration.test.js.map +1 -0
  121. package/lib/infrastructure/require-files-present-ready.test.d.ts +2 -0
  122. package/lib/infrastructure/require-files-present-ready.test.d.ts.map +1 -0
  123. package/lib/infrastructure/require-files-present-ready.test.js +44 -0
  124. package/lib/infrastructure/require-files-present-ready.test.js.map +1 -0
  125. package/lib/infrastructure/required-config-checks.d.ts +2 -0
  126. package/lib/infrastructure/required-config-checks.d.ts.map +1 -0
  127. package/lib/infrastructure/required-config-checks.js +30 -0
  128. package/lib/infrastructure/required-config-checks.js.map +1 -0
  129. package/lib/infrastructure/tokens-and-device-cfg.d.ts.map +1 -1
  130. package/lib/infrastructure/tokens-and-device-cfg.js +11 -8
  131. package/lib/infrastructure/tokens-and-device-cfg.js.map +1 -1
  132. package/lib/jobs/job-handler.d.ts +23 -0
  133. package/lib/jobs/job-handler.d.ts.map +1 -0
  134. package/lib/jobs/job-handler.js +131 -0
  135. package/lib/jobs/job-handler.js.map +1 -0
  136. package/lib/local-connection/rabbitmq-connection.d.ts.map +1 -1
  137. package/lib/local-connection/rabbitmq-connection.js +14 -14
  138. package/lib/local-connection/rabbitmq-connection.js.map +1 -1
  139. package/lib/secure-tunneling/secure-tunnel-message-handler.d.ts +8 -0
  140. package/lib/secure-tunneling/secure-tunnel-message-handler.d.ts.map +1 -0
  141. package/lib/secure-tunneling/secure-tunnel-message-handler.js +42 -0
  142. package/lib/secure-tunneling/secure-tunnel-message-handler.js.map +1 -0
  143. package/lib/secure-tunneling/secure-tunneling.d.ts +9 -9
  144. package/lib/secure-tunneling/secure-tunneling.d.ts.map +1 -1
  145. package/lib/secure-tunneling/secure-tunneling.js +21 -16
  146. package/lib/secure-tunneling/secure-tunneling.js.map +1 -1
  147. package/lib/secure-tunneling/secure-tunneling.test.js +11 -13
  148. package/lib/secure-tunneling/secure-tunneling.test.js.map +1 -1
  149. package/lib/subcommands/app/analytics.d.ts.map +1 -1
  150. package/lib/subcommands/app/analytics.js +1 -2
  151. package/lib/subcommands/app/analytics.js.map +1 -1
  152. package/lib/subcommands/app/env-vars.d.ts +4 -0
  153. package/lib/subcommands/app/env-vars.d.ts.map +1 -1
  154. package/lib/subcommands/app/env-vars.js +52 -6
  155. package/lib/subcommands/app/env-vars.js.map +1 -1
  156. package/lib/subcommands/app/index.d.ts.map +1 -1
  157. package/lib/subcommands/app/index.js +1 -3
  158. package/lib/subcommands/app/index.js.map +1 -1
  159. package/lib/subcommands/app/models.d.ts +0 -11
  160. package/lib/subcommands/app/models.d.ts.map +1 -1
  161. package/lib/subcommands/app/models.js +2 -58
  162. package/lib/subcommands/app/models.js.map +1 -1
  163. package/lib/subcommands/app/shadow.d.ts.map +1 -1
  164. package/lib/subcommands/app/shadow.js +6 -5
  165. package/lib/subcommands/app/shadow.js.map +1 -1
  166. package/lib/subcommands/app/version.d.ts +2 -0
  167. package/lib/subcommands/app/version.d.ts.map +1 -1
  168. package/lib/subcommands/app/version.js +16 -6
  169. package/lib/subcommands/app/version.js.map +1 -1
  170. package/lib/subcommands/config.d.ts +2 -0
  171. package/lib/subcommands/config.d.ts.map +1 -0
  172. package/lib/subcommands/config.js +39 -0
  173. package/lib/subcommands/config.js.map +1 -0
  174. package/lib/subcommands/device/clean.d.ts +1 -1
  175. package/lib/subcommands/device/clean.d.ts.map +1 -1
  176. package/lib/subcommands/device/clean.js +23 -13
  177. package/lib/subcommands/device/clean.js.map +1 -1
  178. package/lib/subcommands/device/index.d.ts.map +1 -1
  179. package/lib/subcommands/device/index.js +3 -1
  180. package/lib/subcommands/device/index.js.map +1 -1
  181. package/lib/subcommands/device/init.js +8 -8
  182. package/lib/subcommands/device/init.js.map +1 -1
  183. package/lib/subcommands/device/migrate.d.ts +2 -0
  184. package/lib/subcommands/device/migrate.d.ts.map +1 -0
  185. package/lib/subcommands/device/migrate.js +24 -0
  186. package/lib/subcommands/device/migrate.js.map +1 -0
  187. package/lib/subcommands/device/refresh.d.ts.map +1 -1
  188. package/lib/subcommands/device/refresh.js +1 -0
  189. package/lib/subcommands/device/refresh.js.map +1 -1
  190. package/lib/subcommands/index.d.ts +1 -1
  191. package/lib/subcommands/index.d.ts.map +1 -1
  192. package/lib/subcommands/index.js +3 -1
  193. package/lib/subcommands/index.js.map +1 -1
  194. package/lib/subcommands/rabbitmq-connection.d.ts +1 -1
  195. package/lib/subcommands/rabbitmq-connection.d.ts.map +1 -1
  196. package/lib/util/aai-error.d.ts +12 -0
  197. package/lib/util/aai-error.d.ts.map +1 -0
  198. package/lib/util/aai-error.js +11 -0
  199. package/lib/util/aai-error.js.map +1 -0
  200. package/lib/util/aws-regions.d.ts +2 -0
  201. package/lib/util/aws-regions.d.ts.map +1 -0
  202. package/lib/util/{cloud-mode-ready.js → aws-regions.js} +2 -20
  203. package/lib/util/aws-regions.js.map +1 -0
  204. package/lib/util/check-for-updates.d.ts.map +1 -1
  205. package/lib/util/check-for-updates.js +5 -28
  206. package/lib/util/check-for-updates.js.map +1 -1
  207. package/lib/util/clean-certs.d.ts.map +1 -1
  208. package/lib/util/clean-certs.js +5 -4
  209. package/lib/util/clean-certs.js.map +1 -1
  210. package/lib/util/directories.d.ts +4 -18
  211. package/lib/util/directories.d.ts.map +1 -1
  212. package/lib/util/directories.js +18 -32
  213. package/lib/util/directories.js.map +1 -1
  214. package/lib/util/file.d.ts +4 -0
  215. package/lib/util/file.d.ts.map +1 -1
  216. package/lib/util/file.js +65 -4
  217. package/lib/util/file.js.map +1 -1
  218. package/lib/util/get-device-id.d.ts.map +1 -1
  219. package/lib/util/get-device-id.js +7 -1
  220. package/lib/util/get-device-id.js.map +1 -1
  221. package/lib/util/http-client.js +3 -3
  222. package/lib/util/http-client.js.map +1 -1
  223. package/package.json +19 -17
  224. package/readme.md +12 -32
  225. package/src/application-control/config.ts +9 -12
  226. package/src/application-control/environment-variables.test.ts +28 -7
  227. package/src/application-control/environment-variables.ts +42 -59
  228. package/src/application-control/index.ts +3 -16
  229. package/src/application-control/install.ts +39 -13
  230. package/src/application-control/models.ts +6 -87
  231. package/src/application-control/utils.ts +10 -25
  232. package/src/cloud-connection/base-message-handler.ts +118 -0
  233. package/src/cloud-connection/bootstrap-provision.ts +7 -7
  234. package/src/cloud-connection/connection-manager.ts +187 -0
  235. package/src/cloud-connection/device-agent-cloud-connection.ts +130 -723
  236. package/src/cloud-connection/device-agent-message-handler.ts +642 -0
  237. package/src/cloud-connection/device-agent.ts +16 -7
  238. package/src/cloud-connection/live-updates-handler.test.ts +121 -189
  239. package/src/cloud-connection/live-updates-handler.ts +105 -232
  240. package/src/cloud-connection/message-dispatcher.ts +33 -0
  241. package/src/cloud-connection/passthrough-handler.ts +55 -18
  242. package/src/cloud-connection/shadow-handler.test.ts +45 -57
  243. package/src/cloud-connection/shadow-handler.ts +224 -54
  244. package/src/cloud-connection/shadow.ts +4 -1
  245. package/src/cloud-connection/transaction-manager.test.ts +68 -6
  246. package/src/cloud-connection/transaction-manager.ts +69 -41
  247. package/src/device-control/device-control.ts +102 -70
  248. package/src/docker/docker-compose.ts +3 -2
  249. package/src/infrastructure/agent-config.test.ts +6 -2
  250. package/src/infrastructure/agent-config.ts +8 -7
  251. package/src/infrastructure/config-check-utility.test.ts +154 -0
  252. package/src/infrastructure/config-check-utility.ts +77 -0
  253. package/src/infrastructure/device-certificate.test.ts +40 -0
  254. package/src/infrastructure/device-certificate.ts +58 -0
  255. package/src/infrastructure/legacy-migration/legacy-file.test.ts +88 -0
  256. package/src/infrastructure/legacy-migration/legacy-files.ts +101 -0
  257. package/src/infrastructure/legacy-migration/legacy-migration.test.ts +396 -0
  258. package/src/infrastructure/legacy-migration/legacy-migration.ts +229 -0
  259. package/src/infrastructure/require-files-present-ready.test.ts +53 -0
  260. package/src/infrastructure/required-config-checks.ts +33 -0
  261. package/src/infrastructure/tokens-and-device-cfg.ts +12 -10
  262. package/src/jobs/job-handler.ts +146 -0
  263. package/src/local-connection/rabbitmq-connection.ts +22 -17
  264. package/src/secure-tunneling/secure-tunnel-message-handler.ts +56 -0
  265. package/src/secure-tunneling/secure-tunneling.test.ts +20 -22
  266. package/src/secure-tunneling/secure-tunneling.ts +41 -29
  267. package/src/subcommands/app/analytics.ts +2 -4
  268. package/src/subcommands/app/env-vars.ts +72 -9
  269. package/src/subcommands/app/index.ts +3 -11
  270. package/src/subcommands/app/models.ts +5 -81
  271. package/src/subcommands/app/shadow.ts +6 -5
  272. package/src/subcommands/app/version.ts +23 -6
  273. package/src/subcommands/config.ts +42 -0
  274. package/src/subcommands/device/clean.ts +31 -17
  275. package/src/subcommands/device/index.ts +3 -1
  276. package/src/subcommands/device/init.ts +11 -11
  277. package/src/subcommands/device/migrate.ts +20 -0
  278. package/src/subcommands/device/refresh.ts +1 -0
  279. package/src/subcommands/index.ts +3 -1
  280. package/src/util/aai-error.ts +20 -0
  281. package/src/util/{cloud-mode-ready.ts → aws-regions.ts} +0 -24
  282. package/src/util/check-for-updates.ts +14 -30
  283. package/src/util/clean-certs.ts +8 -4
  284. package/src/util/directories.ts +23 -67
  285. package/src/util/file.ts +83 -3
  286. package/src/util/get-device-id.ts +7 -7
  287. package/src/util/http-client.ts +2 -2
  288. package/lib/util/cloud-mode-ready.d.ts +0 -3
  289. package/lib/util/cloud-mode-ready.d.ts.map +0 -1
  290. package/lib/util/cloud-mode-ready.js.map +0 -1
  291. package/lib/util/download-file.d.ts +0 -6
  292. package/lib/util/download-file.d.ts.map +0 -1
  293. package/lib/util/download-file.js +0 -25
  294. package/lib/util/download-file.js.map +0 -1
  295. package/lib/util/fetch-with-timeout.d.ts +0 -4
  296. package/lib/util/fetch-with-timeout.d.ts.map +0 -1
  297. package/lib/util/fetch-with-timeout.js +0 -30
  298. package/lib/util/fetch-with-timeout.js.map +0 -1
  299. package/lib/util/parsing.d.ts +0 -2
  300. package/lib/util/parsing.d.ts.map +0 -1
  301. package/lib/util/parsing.js +0 -17
  302. package/lib/util/parsing.js.map +0 -1
  303. package/src/util/download-file.ts +0 -25
  304. package/src/util/fetch-with-timeout.ts +0 -35
  305. package/src/util/parsing.ts +0 -11
@@ -68,13 +68,11 @@ describe('Test Shadow Handler', () => {
68
68
 
69
69
  test('handle project shadow empty delta', async () => {
70
70
  const payload = {
71
- desired: {
72
- [projectId1]: {}
73
- }
71
+ [projectId1]: {}
74
72
  };
75
73
 
76
74
  const updates = await shadowHandler.handleProjectShadow({
77
- topic: getShadowTopic(clientId, 'projects', 'update/accepted'),
75
+ topic: getShadowTopic(clientId, 'projects', 'update/delta'),
78
76
  payload,
79
77
  clientToken: ''
80
78
  });
@@ -104,16 +102,14 @@ describe('Test Shadow Handler', () => {
104
102
 
105
103
  const payload = {
106
104
  state: {
107
- desired: {
108
- [projectId1]: {
109
- appConfig: JSON.stringify(appCfg1)
110
- }
105
+ [projectId1]: {
106
+ appConfig: JSON.stringify(appCfg1)
111
107
  }
112
108
  }
113
109
  };
114
110
 
115
111
  const updates = await shadowHandler.handleProjectShadow({
116
- topic: getShadowTopic(clientId, 'projects', 'update/accepted'),
112
+ topic: getShadowTopic(clientId, 'projects', 'update/delta'),
117
113
  payload,
118
114
  clientToken: ''
119
115
  });
@@ -153,16 +149,14 @@ describe('Test Shadow Handler', () => {
153
149
 
154
150
  const payload = {
155
151
  state: {
156
- desired: {
157
- [projectId1]: {
158
- appConfig: JSON.stringify(appCfg1)
159
- }
152
+ [projectId1]: {
153
+ appConfig: JSON.stringify(appCfg1)
160
154
  }
161
155
  }
162
156
  };
163
157
 
164
158
  const updates = await shadowHandler.handleProjectShadow({
165
- topic: getShadowTopic(clientId, 'projects', 'update/accepted'),
159
+ topic: getShadowTopic(clientId, 'projects', 'update/delta'),
166
160
  payload,
167
161
  clientToken: ''
168
162
  });
@@ -220,19 +214,17 @@ describe('Test Shadow Handler', () => {
220
214
  };
221
215
  const payload = {
222
216
  state: {
223
- desired: {
224
- [projectId1]: {
225
- appConfig: JSON.stringify(appCfg1)
226
- },
227
- [projectId2]: {
228
- appConfig: JSON.stringify(appCfg2)
229
- }
217
+ [projectId1]: {
218
+ appConfig: JSON.stringify(appCfg1)
219
+ },
220
+ [projectId2]: {
221
+ appConfig: JSON.stringify(appCfg2)
230
222
  }
231
223
  }
232
224
  };
233
225
 
234
226
  const updates = await shadowHandler.handleProjectShadow({
235
- topic: getShadowTopic(clientId, 'projects', 'update/accepted'),
227
+ topic: getShadowTopic(clientId, 'projects', 'update/delta'),
236
228
  payload,
237
229
  clientToken: ''
238
230
  });
@@ -281,16 +273,14 @@ describe('Test Shadow Handler', () => {
281
273
 
282
274
  const payload = {
283
275
  state: {
284
- desired: {
285
- [projectId1]: {
286
- appConfig: JSON.stringify(appCfg1)
287
- }
276
+ [projectId1]: {
277
+ appConfig: JSON.stringify(appCfg1)
288
278
  }
289
279
  }
290
280
  };
291
281
 
292
282
  const updates = await shadowHandler.handleProjectShadow({
293
- topic: getShadowTopic(clientId, 'projects', 'update/accepted'),
283
+ topic: getShadowTopic(clientId, 'projects', 'update/delta'),
294
284
  payload,
295
285
  clientToken: ''
296
286
  });
@@ -365,10 +355,8 @@ describe('Test Shadow Handler', () => {
365
355
 
366
356
  const payload = {
367
357
  state: {
368
- desired: {
369
- [projectId1]: {
370
- appConfig: appCfg1 // This is missing JSON.stringify() making this an unparsable object.
371
- }
358
+ [projectId1]: {
359
+ appConfig: appCfg1 // This is missing JSON.stringify() making this an unparsable object.
372
360
  }
373
361
  }
374
362
  };
@@ -378,7 +366,7 @@ describe('Test Shadow Handler', () => {
378
366
  .mockReturnValue({} as unknown as Logger);
379
367
 
380
368
  const updates = await shadowHandler.handleProjectShadow({
381
- topic: getShadowTopic(clientId, 'projects', 'update/accepted'),
369
+ topic: getShadowTopic(clientId, 'projects', 'update/delta'),
382
370
  payload,
383
371
  clientToken: ''
384
372
  });
@@ -393,13 +381,15 @@ describe('Test Shadow Handler', () => {
393
381
  describe('handle project shadow env vars', () => {
394
382
  test('handle a response from the getAccepted from the cloud', async () => {
395
383
  const envVars1 = {
396
- VAR0: 'value0'
384
+ service: {
385
+ VAR0: 'value0'
386
+ }
397
387
  };
398
388
  const payload = {
399
389
  state: {
400
390
  reported: {
401
391
  [projectId1]: {
402
- envVars: { service: envVars1 }
392
+ envVars: JSON.stringify(envVars1)
403
393
  }
404
394
  }
405
395
  }
@@ -414,22 +404,20 @@ describe('Test Shadow Handler', () => {
414
404
  });
415
405
  test('handle project shadow env vars update delta', async () => {
416
406
  const envVars1 = {
417
- VAR1: 'value1'
407
+ service: {
408
+ VAR1: 'value1'
409
+ }
418
410
  };
419
411
  const payload = {
420
412
  state: {
421
- desired: {
422
- [projectId1]: {
423
- envVars: {
424
- service: envVars1
425
- }
426
- }
413
+ [projectId1]: {
414
+ envVars: JSON.stringify(envVars1)
427
415
  }
428
416
  }
429
417
  };
430
418
 
431
419
  const updates = await shadowHandler.handleProjectShadow({
432
- topic: getShadowTopic(clientId, 'projects', 'update/accepted'),
420
+ topic: getShadowTopic(clientId, 'projects', 'update/delta'),
433
421
  payload,
434
422
  clientToken: ''
435
423
  });
@@ -438,36 +426,36 @@ describe('Test Shadow Handler', () => {
438
426
  projectId: projectId1,
439
427
  txId: expect.any(String),
440
428
  envVarUpdate: {
441
- envVars: { service: envVars1 }
429
+ envVars: envVars1
442
430
  }
443
431
  });
444
432
  });
445
433
 
446
434
  test('handle project shadow env vars update delta for two projects', async () => {
447
435
  const service1 = {
448
- VAR1: 'value1'
436
+ service: {
437
+ VAR1: 'value1'
438
+ }
449
439
  };
450
440
  const service2 = {
451
- VAR2: 'value2'
441
+ service: {
442
+ VAR2: 'value2'
443
+ }
452
444
  };
453
445
 
454
446
  const payload = {
455
447
  state: {
456
- desired: {
457
- [projectId1]: {
458
- envVars: {
459
- service: service1
460
- }
461
- },
462
- [projectId2]: {
463
- envVars: { service: service2 }
464
- }
448
+ [projectId1]: {
449
+ envVars: JSON.stringify(service1)
450
+ },
451
+ [projectId2]: {
452
+ envVars: JSON.stringify(service2)
465
453
  }
466
454
  }
467
455
  };
468
456
 
469
457
  const updates = await shadowHandler.handleProjectShadow({
470
- topic: getShadowTopic(clientId, 'projects', 'update/accepted'),
458
+ topic: getShadowTopic(clientId, 'projects', 'update/delta'),
471
459
  payload,
472
460
  clientToken: ''
473
461
  });
@@ -476,14 +464,14 @@ describe('Test Shadow Handler', () => {
476
464
  projectId: projectId1,
477
465
  txId: expect.any(String),
478
466
  envVarUpdate: {
479
- envVars: { service: service1 }
467
+ envVars: service1
480
468
  }
481
469
  });
482
470
  expect(updates[1]).toEqual({
483
471
  projectId: projectId2,
484
472
  txId: expect.any(String),
485
473
  envVarUpdate: {
486
- envVars: { service: service2 }
474
+ envVars: service2
487
475
  }
488
476
  });
489
477
  });
@@ -3,28 +3,39 @@ import {
3
3
  validateAppConfig
4
4
  } from '@alwaysai/app-configuration-schemas';
5
5
  import {
6
+ buildSignedUrlsRequestMessage,
7
+ buildToClientStatusResponseMessage,
8
+ buildUpdateShadowMessage,
6
9
  EnvVars,
10
+ generateTxId,
11
+ getShadowTopic,
12
+ getUpdateDeltaStateFromMessage,
13
+ keyMirrors,
14
+ ProjectShadowUpdate,
15
+ SecureTunnelShadowUpdate,
16
+ SignedUrlsRequestPayload,
17
+ validateEnvVarSchemaShadowUpdate,
18
+ validateProjectShadowUpdate
19
+ } from '@alwaysai/device-agent-schemas';
20
+ import {
21
+ buildBaseShadowMessage,
22
+ DeviceAgentStatusShadowUpdate,
23
+ ShadowProjectsUpdateAll
24
+ } from '@alwaysai/device-agent-schemas/lib/shadow-schema';
25
+ import { stringifyError } from 'alwaysai/lib/util';
26
+ import {
7
27
  getAllEnvs,
8
28
  readAppCfgFile,
9
- setEnv
29
+ setEnv,
30
+ updateAppCfg
10
31
  } from '../application-control';
11
32
  import { getSystemInformation } from '../device-control/device-control';
12
33
  import { logger } from '../util/logger';
13
34
  import { Publisher } from './publisher';
14
35
  import { AppConfigModels, getAppCfgModelsDiff } from './shadow';
15
- import {
16
- generateTxId,
17
- validateProjectShadowUpdate,
18
- buildBaseShadowMessage,
19
- buildUpdateProjectShadowMessage,
20
- buildUpdateSystemInfoShadowMessage,
21
- getShadowTopic,
22
- ShadowProjectsUpdateAll,
23
- getDesiredFromMessage,
24
- ProjectShadowUpdate,
25
- buildUpdateSecureTunnelShadowMessage,
26
- SecureTunnelShadowDescriptionReported
27
- } from '@alwaysai/device-agent-schemas';
36
+ import { pruneModels } from '../application-control/models';
37
+ import { MessageHandler } from './message-dispatcher';
38
+ import { BaseHandler } from './base-message-handler';
28
39
 
29
40
  export type AppConfigUpdate = {
30
41
  newAppCfg: AppConfig;
@@ -112,9 +123,11 @@ export class ShadowHandler {
112
123
  // Handle errors and validation
113
124
  try {
114
125
  newAppCfg = JSON.parse(appConfig);
115
- } catch (error) {
126
+ } catch (e) {
116
127
  logger.error(
117
- `Could not parse the appConfig for transaction ${txId}!\n${error}`
128
+ `Could not parse the appConfig for transaction ${txId}!\n${stringifyError(
129
+ e
130
+ )}`
118
131
  );
119
132
  return null;
120
133
  }
@@ -145,6 +158,40 @@ export class ShadowHandler {
145
158
  return appCfgUpdate;
146
159
  }
147
160
 
161
+ private async generateEnvVarsUpdate({
162
+ envVars,
163
+ txId,
164
+ projectId
165
+ }: {
166
+ envVars: string;
167
+ txId: string;
168
+ projectId: string;
169
+ }): Promise<EnvVarUpdate | null> {
170
+ let newEnvVars: any;
171
+ try {
172
+ newEnvVars = JSON.parse(envVars);
173
+ } catch (e) {
174
+ logger.error(
175
+ `Could not parse the environment variables for transaction ${txId}!\n${stringifyError(
176
+ e
177
+ )}`
178
+ );
179
+ return null;
180
+ }
181
+
182
+ if (!validateEnvVarSchemaShadowUpdate(newEnvVars)) {
183
+ logger.error(
184
+ `Received invalid environment variables update for ${projectId}!\n${JSON.stringify(
185
+ validateEnvVarSchemaShadowUpdate.errors,
186
+ null,
187
+ 2
188
+ )}`
189
+ );
190
+ return null;
191
+ }
192
+ return { envVars: newEnvVars };
193
+ }
194
+
148
195
  private async processProjectShadowUpdates({
149
196
  delta
150
197
  }: {
@@ -218,7 +265,14 @@ export class ShadowHandler {
218
265
  `Found a delta for app environment variable shadow. Updating ${projectId}`
219
266
  );
220
267
  const envVars = projectDelta.envVars;
221
- shadowUpdate.envVarUpdate = { envVars };
268
+ const envVarsUpdate = await this.generateEnvVarsUpdate({
269
+ envVars,
270
+ txId,
271
+ projectId
272
+ });
273
+ if (envVarsUpdate) {
274
+ shadowUpdate.envVarUpdate = envVarsUpdate;
275
+ }
222
276
  }
223
277
 
224
278
  return shadowUpdate.appCfgUpdate || shadowUpdate.envVarUpdate
@@ -242,24 +296,14 @@ export class ShadowHandler {
242
296
  throw Error(`Topic ${topic} is not in the ${this.projectShadowTopics}`);
243
297
  }
244
298
  switch (topic) {
245
- case this.shadowTopics.project.updateAccepted: {
246
- if (clientToken === this.clientId) {
247
- logger.debug(
248
- `Ignoring message as it was caused by Device Agent itself: ${JSON.stringify(
249
- { topic, payload },
250
- null,
251
- 2
252
- )}`
253
- );
254
- break;
255
- }
256
- const desired = getDesiredFromMessage(payload);
257
- if (!desired) {
299
+ case this.shadowTopics.project.updateDelta: {
300
+ const delta = getUpdateDeltaStateFromMessage(payload);
301
+ if (!delta) {
258
302
  logger.debug(
259
- `No desired state found in message: ${JSON.stringify(payload)}`
303
+ `No delta state found in message: ${JSON.stringify(payload)}`
260
304
  );
261
305
  } else {
262
- return await this.processProjectShadowUpdates({ delta: desired });
306
+ return await this.processProjectShadowUpdates({ delta });
263
307
  }
264
308
  break;
265
309
  }
@@ -274,21 +318,18 @@ export class ShadowHandler {
274
318
  );
275
319
  break;
276
320
  }
277
- if (payload.state.delta) {
278
- return await this.processProjectShadowUpdates({
279
- delta: payload.state.delta
280
- });
281
- } else {
282
- logger.info(
283
- `No delta in projects.getAccepted in named shadow '${
284
- topic.split('/')[5]
285
- }'`
321
+ const delta = getUpdateDeltaStateFromMessage(payload);
322
+ if (!delta) {
323
+ logger.debug(
324
+ `No delta state found in message: ${JSON.stringify(payload)}`
286
325
  );
326
+ } else {
327
+ return await this.processProjectShadowUpdates({ delta });
287
328
  }
288
329
  break;
289
330
  }
290
331
  case this.shadowTopics.project.getRejected:
291
- case this.shadowTopics.project.updateDelta:
332
+ case this.shadowTopics.project.updateAccepted:
292
333
  case this.shadowTopics.project.updateRejected: {
293
334
  // Not handling these for now
294
335
  break;
@@ -310,7 +351,10 @@ export class ShadowHandler {
310
351
  this.publisher.publish(
311
352
  getShadowTopic(this.clientId, 'system-info', 'update'),
312
353
  JSON.stringify(
313
- buildUpdateSystemInfoShadowMessage(this.clientId, systemInfo)
354
+ buildUpdateShadowMessage({
355
+ clientId: this.clientId,
356
+ reported: systemInfo
357
+ })
314
358
  )
315
359
  );
316
360
  }
@@ -322,13 +366,13 @@ export class ShadowHandler {
322
366
  const toReport: ShadowProjectsUpdateAll = {
323
367
  [projectId]: {
324
368
  appConfig: JSON.stringify(appCfg),
325
- envVars
369
+ envVars: JSON.stringify(envVars)
326
370
  }
327
371
  };
328
372
  this.publisher.publish(
329
373
  getShadowTopic(this.clientId, 'projects', 'update'),
330
374
  JSON.stringify(
331
- buildUpdateProjectShadowMessage({
375
+ buildUpdateShadowMessage({
332
376
  clientId: this.clientId,
333
377
  reported: toReport
334
378
  })
@@ -344,15 +388,15 @@ export class ShadowHandler {
344
388
  envVars: EnvVars;
345
389
  }) {
346
390
  await setEnv({ projectId, envVars });
347
-
391
+ const currentEnvs = await getAllEnvs({ projectId });
348
392
  this.publisher.publish(
349
393
  getShadowTopic(this.clientId, 'projects', 'update'),
350
394
  JSON.stringify(
351
- buildUpdateProjectShadowMessage({
395
+ buildUpdateShadowMessage({
352
396
  clientId: this.clientId,
353
397
  reported: {
354
398
  [projectId]: {
355
- envVars
399
+ envVars: JSON.stringify(currentEnvs)
356
400
  }
357
401
  }
358
402
  })
@@ -361,15 +405,29 @@ export class ShadowHandler {
361
405
  }
362
406
 
363
407
  public async updateSecureTunnelShadow(
364
- secureTunnelShadowUpdate: SecureTunnelShadowDescriptionReported
408
+ secureTunnelShadowUpdate: SecureTunnelShadowUpdate
365
409
  ) {
366
410
  this.publisher.publish(
367
411
  getShadowTopic(this.clientId, 'secure-tunnel', 'update'),
368
412
  JSON.stringify(
369
- buildUpdateSecureTunnelShadowMessage(
370
- secureTunnelShadowUpdate,
371
- this.clientId
372
- )
413
+ buildUpdateShadowMessage({
414
+ reported: secureTunnelShadowUpdate,
415
+ clientId: this.clientId
416
+ })
417
+ )
418
+ );
419
+ }
420
+
421
+ public async updateDeviceAgentStatusShadow(
422
+ deviceAgentStatusShadowUpdate: DeviceAgentStatusShadowUpdate
423
+ ) {
424
+ this.publisher.publish(
425
+ getShadowTopic(this.clientId, 'device-agent-status', 'update'),
426
+ JSON.stringify(
427
+ buildUpdateShadowMessage({
428
+ reported: deviceAgentStatusShadowUpdate,
429
+ clientId: this.clientId
430
+ })
373
431
  )
374
432
  );
375
433
  }
@@ -385,7 +443,7 @@ export class ShadowHandler {
385
443
  this.publisher.publish(
386
444
  getShadowTopic(this.clientId, 'projects', 'update'),
387
445
  JSON.stringify(
388
- buildUpdateProjectShadowMessage({
446
+ buildUpdateShadowMessage({
389
447
  clientId: this.clientId,
390
448
  reported: { [projectId]: null },
391
449
  desired: { [projectId]: null }
@@ -394,3 +452,115 @@ export class ShadowHandler {
394
452
  );
395
453
  }
396
454
  }
455
+
456
+ export class ProjectShadowMessageHandler
457
+ extends BaseHandler
458
+ implements MessageHandler<any>
459
+ {
460
+ public async handle(message: any, topic: string): Promise<void> {
461
+ const shadowUpdates = await this.shadowHandler.handleProjectShadow({
462
+ topic,
463
+ payload: message,
464
+ clientToken: message.clientToken
465
+ });
466
+ if (shadowUpdates.length) {
467
+ const shadowUpdatePromises: Promise<void>[] = [];
468
+ for (const shadowUpdate of shadowUpdates) {
469
+ const projectId = shadowUpdate.projectId;
470
+ const txId = shadowUpdate.txId;
471
+ shadowUpdatePromises.push(
472
+ this.txnMgr
473
+ .runTransactionStep({
474
+ func: () =>
475
+ this.handleProjectShadowConfigUpdate(shadowUpdate, txId),
476
+ projectId,
477
+ txId,
478
+ start: true,
479
+ liveUpdatesPublishFn: async () =>
480
+ this.publisher.publishToClient(
481
+ buildToClientStatusResponseMessage(
482
+ this.clientId,
483
+ { status: keyMirrors.statusResponse.in_progress },
484
+ txId
485
+ ),
486
+ logger.silly
487
+ ),
488
+ stepName: topic
489
+ })
490
+ .catch((e) => {
491
+ logger.error(
492
+ `There was an issue updating project shadow config for ${projectId}!\n${stringifyError(
493
+ e
494
+ )}`
495
+ );
496
+ })
497
+ );
498
+ }
499
+
500
+ await Promise.all(shadowUpdatePromises);
501
+ }
502
+ }
503
+
504
+ private handleProjectShadowConfigUpdate = async (
505
+ update: ShadowUpdate,
506
+ txId: string
507
+ ): Promise<boolean> => {
508
+ const { projectId, appCfgUpdate, envVarUpdate } = update;
509
+
510
+ if (
511
+ appCfgUpdate?.updatedModels &&
512
+ Object.keys(appCfgUpdate.updatedModels).length
513
+ ) {
514
+ // When there are model updates request signed URLs and wait to apply config changes
515
+ const { updatedModels } = appCfgUpdate;
516
+
517
+ logger.debug(
518
+ `Requesting presigned urls from cloud for model versions: ${JSON.stringify(
519
+ updatedModels
520
+ )}`
521
+ );
522
+ const modelsOnlyUrlsRequestPayload: SignedUrlsRequestPayload = {
523
+ modelsOnlyUrlsRequest: {
524
+ projectId,
525
+ models: updatedModels
526
+ }
527
+ };
528
+ const message = buildSignedUrlsRequestMessage(
529
+ this.clientId,
530
+ modelsOnlyUrlsRequestPayload,
531
+ txId
532
+ );
533
+ this.publisher.publishToCloud(message);
534
+
535
+ this.txnMgr.setAppCfgUpdateToTx(txId, update);
536
+
537
+ return false;
538
+ }
539
+
540
+ if (appCfgUpdate) {
541
+ await this.atomicApplicationUpdate(async () => {
542
+ await pruneModels({
543
+ projectId,
544
+ appCfg: appCfgUpdate.newAppCfg
545
+ });
546
+ await updateAppCfg({
547
+ projectId,
548
+ newAppCfg: appCfgUpdate.newAppCfg
549
+ });
550
+ }, projectId);
551
+ }
552
+
553
+ if (envVarUpdate) {
554
+ await this.atomicApplicationUpdate(
555
+ async () =>
556
+ await this.shadowHandler.updateProjectEnvVars({
557
+ projectId,
558
+ envVars: envVarUpdate.envVars
559
+ }),
560
+ projectId,
561
+ true
562
+ );
563
+ }
564
+ return true;
565
+ };
566
+ }
@@ -1,6 +1,7 @@
1
1
  import { logger } from '../util/logger';
2
2
  import { readAppCfgFile } from '../application-control';
3
3
  import { AppConfig } from '@alwaysai/app-configuration-schemas';
4
+ import { stringifyError } from 'alwaysai/lib/util';
4
5
 
5
6
  export type AppConfigModels = {
6
7
  [modelId: string]: number;
@@ -43,7 +44,9 @@ export const getAppCfgModelsDiff = async ({
43
44
  newScripts[scriptName] = shadowScripts[scriptName];
44
45
  });
45
46
  } catch (e) {
46
- logger.error(`Error parsing app config update: ${e.message}`);
47
+ logger.error(
48
+ `Error parsing app config update for ${projectId}!\n${stringifyError(e)}`
49
+ );
47
50
  }
48
51
 
49
52
  return { scripts: newScripts, updatedModels, untouchedModels };