@alwaysai/device-agent 0.0.13 → 0.0.15

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 (151) hide show
  1. package/lib/application-control/backup.js +3 -3
  2. package/lib/application-control/backup.js.map +1 -1
  3. package/lib/application-control/index.d.ts +4 -4
  4. package/lib/application-control/index.d.ts.map +1 -1
  5. package/lib/application-control/index.js +1 -4
  6. package/lib/application-control/index.js.map +1 -1
  7. package/lib/application-control/install.d.ts +1 -1
  8. package/lib/application-control/install.d.ts.map +1 -1
  9. package/lib/application-control/install.js +41 -54
  10. package/lib/application-control/install.js.map +1 -1
  11. package/lib/application-control/models.d.ts +0 -4
  12. package/lib/application-control/models.d.ts.map +1 -1
  13. package/lib/application-control/models.js +13 -22
  14. package/lib/application-control/models.js.map +1 -1
  15. package/lib/application-control/status.d.ts +0 -6
  16. package/lib/application-control/status.d.ts.map +1 -1
  17. package/lib/application-control/status.js +3 -19
  18. package/lib/application-control/status.js.map +1 -1
  19. package/lib/application-control/utils.d.ts +3 -0
  20. package/lib/application-control/utils.d.ts.map +1 -1
  21. package/lib/application-control/utils.js +50 -21
  22. package/lib/application-control/utils.js.map +1 -1
  23. package/lib/cloud-connection/bootstrap-provision.d.ts +1 -1
  24. package/lib/cloud-connection/bootstrap-provision.d.ts.map +1 -1
  25. package/lib/cloud-connection/bootstrap-provision.js +9 -9
  26. package/lib/cloud-connection/bootstrap-provision.js.map +1 -1
  27. package/lib/cloud-connection/cmd-status.d.ts +8 -0
  28. package/lib/cloud-connection/cmd-status.d.ts.map +1 -0
  29. package/lib/cloud-connection/cmd-status.js +62 -0
  30. package/lib/cloud-connection/cmd-status.js.map +1 -0
  31. package/lib/cloud-connection/device-agent-cloud-connection.d.ts +10 -2
  32. package/lib/cloud-connection/device-agent-cloud-connection.d.ts.map +1 -1
  33. package/lib/cloud-connection/device-agent-cloud-connection.js +156 -66
  34. package/lib/cloud-connection/device-agent-cloud-connection.js.map +1 -1
  35. package/lib/cloud-connection/device-agent.d.ts.map +1 -1
  36. package/lib/cloud-connection/device-agent.js +4 -3
  37. package/lib/cloud-connection/device-agent.js.map +1 -1
  38. package/lib/cloud-connection/live-updates-handler.d.ts +10 -18
  39. package/lib/cloud-connection/live-updates-handler.d.ts.map +1 -1
  40. package/lib/cloud-connection/live-updates-handler.js +50 -50
  41. package/lib/cloud-connection/live-updates-handler.js.map +1 -1
  42. package/lib/cloud-connection/messages.d.ts +3 -1
  43. package/lib/cloud-connection/messages.d.ts.map +1 -1
  44. package/lib/cloud-connection/messages.js +13 -1
  45. package/lib/cloud-connection/messages.js.map +1 -1
  46. package/lib/cloud-connection/passthrough-handler.d.ts +11 -0
  47. package/lib/cloud-connection/passthrough-handler.d.ts.map +1 -0
  48. package/lib/cloud-connection/passthrough-handler.js +59 -0
  49. package/lib/cloud-connection/passthrough-handler.js.map +1 -0
  50. package/lib/cloud-connection/publisher.d.ts +1 -0
  51. package/lib/cloud-connection/publisher.d.ts.map +1 -1
  52. package/lib/cloud-connection/publisher.js +14 -0
  53. package/lib/cloud-connection/publisher.js.map +1 -1
  54. package/lib/cloud-connection/shadow-handler.d.ts +2 -3
  55. package/lib/cloud-connection/shadow-handler.d.ts.map +1 -1
  56. package/lib/cloud-connection/shadow-handler.js +18 -4
  57. package/lib/cloud-connection/shadow-handler.js.map +1 -1
  58. package/lib/cloud-connection/shadow-handler.test.d.ts +2 -0
  59. package/lib/cloud-connection/shadow-handler.test.d.ts.map +1 -0
  60. package/lib/cloud-connection/shadow-handler.test.js +321 -0
  61. package/lib/cloud-connection/shadow-handler.test.js.map +1 -0
  62. package/lib/environment.d.ts +1 -0
  63. package/lib/environment.d.ts.map +1 -1
  64. package/lib/environment.js +3 -2
  65. package/lib/environment.js.map +1 -1
  66. package/lib/index.js +2 -2
  67. package/lib/index.js.map +1 -1
  68. package/lib/infrastructure/agent-config.d.ts +15 -48
  69. package/lib/infrastructure/agent-config.d.ts.map +1 -1
  70. package/lib/infrastructure/agent-config.js.map +1 -1
  71. package/lib/infrastructure/agent-config.test.js +0 -6
  72. package/lib/infrastructure/agent-config.test.js.map +1 -1
  73. package/lib/infrastructure/system-id.js +2 -2
  74. package/lib/infrastructure/system-id.js.map +1 -1
  75. package/lib/infrastructure/tokens-and-device-cfg.d.ts.map +1 -1
  76. package/lib/infrastructure/tokens-and-device-cfg.js +5 -9
  77. package/lib/infrastructure/tokens-and-device-cfg.js.map +1 -1
  78. package/lib/local-connection/rabbitmq-connection.d.ts +4 -0
  79. package/lib/local-connection/rabbitmq-connection.d.ts.map +1 -0
  80. package/lib/local-connection/rabbitmq-connection.js +58 -0
  81. package/lib/local-connection/rabbitmq-connection.js.map +1 -0
  82. package/lib/subcommands/app/app.d.ts +4 -3
  83. package/lib/subcommands/app/app.d.ts.map +1 -1
  84. package/lib/subcommands/app/app.js +78 -27
  85. package/lib/subcommands/app/app.js.map +1 -1
  86. package/lib/subcommands/app/index.js +2 -2
  87. package/lib/subcommands/device/clean.js +4 -4
  88. package/lib/subcommands/device/clean.js.map +1 -1
  89. package/lib/subcommands/device/device.d.ts +1 -1
  90. package/lib/subcommands/device/device.d.ts.map +1 -1
  91. package/lib/subcommands/device/device.js +9 -10
  92. package/lib/subcommands/device/device.js.map +1 -1
  93. package/lib/subcommands/index.d.ts +0 -1
  94. package/lib/subcommands/index.d.ts.map +1 -1
  95. package/lib/subcommands/login.d.ts +0 -1
  96. package/lib/subcommands/login.d.ts.map +1 -1
  97. package/lib/subcommands/login.js +1 -9
  98. package/lib/subcommands/login.js.map +1 -1
  99. package/lib/util/directories.d.ts +11 -12
  100. package/lib/util/directories.d.ts.map +1 -1
  101. package/lib/util/directories.js +24 -29
  102. package/lib/util/directories.js.map +1 -1
  103. package/lib/util/fetch-with-timeout.d.ts +4 -0
  104. package/lib/util/fetch-with-timeout.d.ts.map +1 -0
  105. package/lib/util/fetch-with-timeout.js +15 -0
  106. package/lib/util/fetch-with-timeout.js.map +1 -0
  107. package/lib/util/logger.js +1 -0
  108. package/lib/util/logger.js.map +1 -1
  109. package/lib/util/require-logged-in-and-paid-plan.d.ts +2 -0
  110. package/lib/util/require-logged-in-and-paid-plan.d.ts.map +1 -0
  111. package/lib/util/require-logged-in-and-paid-plan.js +18 -0
  112. package/lib/util/require-logged-in-and-paid-plan.js.map +1 -0
  113. package/package.json +20 -32
  114. package/readme.md +100 -89
  115. package/src/application-control/backup.ts +3 -3
  116. package/src/application-control/index.ts +0 -6
  117. package/src/application-control/install.ts +53 -73
  118. package/src/application-control/models.ts +7 -19
  119. package/src/application-control/status.ts +3 -19
  120. package/src/application-control/utils.ts +61 -22
  121. package/src/cloud-connection/bootstrap-provision.ts +13 -10
  122. package/src/cloud-connection/cmd-status.ts +71 -0
  123. package/src/cloud-connection/device-agent-cloud-connection.ts +211 -102
  124. package/src/cloud-connection/device-agent.ts +7 -4
  125. package/src/cloud-connection/live-updates-handler.ts +79 -86
  126. package/src/cloud-connection/messages.ts +22 -1
  127. package/src/cloud-connection/passthrough-handler.ts +67 -0
  128. package/src/cloud-connection/publisher.ts +21 -0
  129. package/src/cloud-connection/shadow-handler.test.ts +361 -0
  130. package/src/cloud-connection/shadow-handler.ts +28 -7
  131. package/src/environment.ts +4 -1
  132. package/src/index.ts +2 -2
  133. package/src/infrastructure/agent-config.test.ts +0 -7
  134. package/src/infrastructure/agent-config.ts +24 -2
  135. package/src/infrastructure/system-id.ts +1 -1
  136. package/src/infrastructure/tokens-and-device-cfg.ts +8 -13
  137. package/src/local-connection/rabbitmq-connection.ts +53 -0
  138. package/src/subcommands/app/app.ts +82 -31
  139. package/src/subcommands/app/index.ts +4 -4
  140. package/src/subcommands/device/clean.ts +4 -4
  141. package/src/subcommands/device/device.ts +13 -13
  142. package/src/subcommands/login.ts +1 -9
  143. package/src/util/directories.ts +31 -29
  144. package/src/util/fetch-with-timeout.ts +18 -0
  145. package/src/util/logger.ts +2 -0
  146. package/src/util/require-logged-in-and-paid-plan.ts +16 -0
  147. package/lib/cloud-connection/app-install-status.d.ts +0 -16
  148. package/lib/cloud-connection/app-install-status.d.ts.map +0 -1
  149. package/lib/cloud-connection/app-install-status.js +0 -53
  150. package/lib/cloud-connection/app-install-status.js.map +0 -1
  151. package/src/cloud-connection/app-install-status.ts +0 -62
@@ -1,15 +1,24 @@
1
1
  import compose from 'docker-compose';
2
2
  import * as path from 'path';
3
3
  import * as fs from 'fs';
4
- import { TARGET_JSON_FILE_NAME } from 'alwaysai/lib/constants';
4
+ import {
5
+ DOCKER_COMPOSE_FILE,
6
+ TARGET_JSON_FILE_NAME
7
+ } from 'alwaysai/lib/constants';
5
8
 
6
9
  import { AgentConfigFile } from '../infrastructure/agent-config';
7
- import nodeFetch from 'node-fetch';
8
- import { TargetJsonFile } from 'alwaysai/lib/core/app';
9
- import { appDeployLinuxAndRemoteDevice } from 'alwaysai/lib/components/app';
10
+ import { fetchWithTimeout } from '../util/fetch-with-timeout';
11
+ import {
12
+ getDockerComposeCmdForApp,
13
+ TargetJsonFile,
14
+ updateDockerComposeTargetHw,
15
+ writeDockerComposeFile,
16
+ writeStandaloneDockerfile
17
+ } from 'alwaysai/lib/core/app';
10
18
  import { runInDir } from '../util/run-in-dir';
11
19
  import { logger } from '../util/logger';
12
20
  import { APP_ROOT } from '../util/directories';
21
+ import { JsSpawner } from 'alwaysai/lib/util/spawner';
13
22
 
14
23
  export function getAppDir(projectId: string): string {
15
24
  return path.join(APP_ROOT, projectId);
@@ -21,6 +30,11 @@ export async function requireAppInstalled(props: { projectId: string }) {
21
30
  if (!(await AgentConfigFile().isAppPresent({ projectId }))) {
22
31
  throw new Error('Application is not installed');
23
32
  }
33
+ }
34
+
35
+ export async function requireAppReady(props: { projectId: string }) {
36
+ const { projectId } = props;
37
+ await requireAppInstalled({ projectId });
24
38
  if (!(await AgentConfigFile().isAppReady({ projectId }))) {
25
39
  throw new Error('Application is not done installing or updating');
26
40
  }
@@ -30,23 +44,28 @@ export async function buildApp(props: { appDir: string }) {
30
44
  const { appDir } = props;
31
45
 
32
46
  // Build standalone image and docker-compose
33
- const targetJson = TargetJsonFile(appDir);
34
- const targetConfig = targetJson.read();
35
- if (targetConfig.targetProtocol !== 'docker:') {
47
+ const targetJsonFile = TargetJsonFile(appDir);
48
+ const targetCfg = targetJsonFile.read();
49
+ if (targetCfg.targetProtocol !== 'docker:') {
36
50
  throw new Error(`${TARGET_JSON_FILE_NAME} is not properly configured!`);
37
51
  }
38
52
  await runInDir(
39
- appDeployLinuxAndRemoteDevice,
40
- [
41
- {
42
- yes: true,
43
- generateDockerCompose: true,
44
- logs: false,
45
- stop: false,
46
- targetJson,
47
- targetConfig
53
+ async () => {
54
+ await writeStandaloneDockerfile();
55
+ const spawner = JsSpawner();
56
+ const targetHardware = targetCfg.targetHardware;
57
+ if (await spawner.exists(DOCKER_COMPOSE_FILE)) {
58
+ await updateDockerComposeTargetHw({
59
+ targetHardware
60
+ });
61
+ } else {
62
+ await writeDockerComposeFile({
63
+ spawner: JsSpawner(),
64
+ cmd: await getDockerComposeCmdForApp({ targetHardware })
65
+ });
48
66
  }
49
- ],
67
+ },
68
+ [],
50
69
  appDir
51
70
  );
52
71
 
@@ -59,17 +78,37 @@ export async function buildApp(props: { appDir: string }) {
59
78
  }
60
79
  }
61
80
 
81
+ class HTTPResponseError extends Error {
82
+ public response;
83
+ constructor(response) {
84
+ super(`HTTP Error Response: ${response.status} ${response.statusText}`);
85
+ this.response = response;
86
+ }
87
+ }
88
+
89
+ const checkStatus = (response) => {
90
+ if (response.ok) {
91
+ // response.status >= 200 && response.status < 300
92
+ return response;
93
+ } else {
94
+ throw new HTTPResponseError(response);
95
+ }
96
+ };
97
+
62
98
  export async function downloadPackageUsingPresignedUrl(props: {
63
99
  localDest: string;
64
100
  presignedUrl: string;
65
101
  }): Promise<void> {
66
102
  const { localDest, presignedUrl } = props;
67
- logger.info(`Downloading app package from ${presignedUrl}`);
68
- const response = await nodeFetch(presignedUrl);
69
- if (response.status !== 200) {
70
- // If the URL is invalid; I think we shouldn't get here with the new changes
103
+ logger.debug(`Downloading package from ${presignedUrl}`);
104
+ let response: any;
105
+ try {
106
+ response = await fetchWithTimeout(presignedUrl);
107
+ } catch (error) {
108
+ const errorBody =
109
+ error.type === 'aborted' ? error : await error.response.text();
71
110
  throw new Error(
72
- `Status Code: ${response.status}, ${response.statusText}. Response: ${response.body}`
111
+ `downloadPackageUsingPresignedUrl: Error=${error}\n${errorBody}`
73
112
  );
74
113
  }
75
114
 
@@ -1,28 +1,28 @@
1
- import { logger } from 'alwaysai/lib/util';
2
1
  import { getIoTCoreEndpointUrl } from '../infrastructure/urls';
3
2
  import { rmBootstrapCertsAndClose } from '../util/clean-certs';
4
3
  import {
5
- BOOTSTRAP_DEVICE_PRIVATE_KEY_FILE_PATH,
6
- BOOTSTRAP_DEVICE_CERTIFICATE_FILE_PATH,
4
+ BOOTSTRAP_PRIVATE_KEY_FILE_PATH,
5
+ BOOTSTRAP_CERTIFICATE_FILE_PATH,
7
6
  AWS_ROOT_CERTIFICATE_FILE_PATH
8
7
  } from '../util/directories';
9
8
  import { getDeviceUuid } from '../util/get-device-id';
9
+ import { logger } from '../util/logger';
10
10
  import { BootstrapAgent } from './device-agent';
11
11
 
12
- export function bootstrapProvision() {
12
+ export async function bootstrapProvision() {
13
13
  setTimeout(rmBootstrapCertsAndClose, 60000);
14
14
 
15
15
  const clientId = getDeviceUuid();
16
16
  const bootstrapConfig = {
17
- keyPath: BOOTSTRAP_DEVICE_PRIVATE_KEY_FILE_PATH(),
18
- certPath: BOOTSTRAP_DEVICE_CERTIFICATE_FILE_PATH(),
17
+ keyPath: BOOTSTRAP_PRIVATE_KEY_FILE_PATH(),
18
+ certPath: BOOTSTRAP_CERTIFICATE_FILE_PATH(),
19
19
  caPath: AWS_ROOT_CERTIFICATE_FILE_PATH,
20
20
  clientId,
21
21
  host: getIoTCoreEndpointUrl()
22
22
  };
23
23
 
24
24
  const bootstrapAgent = new BootstrapAgent(bootstrapConfig);
25
- bootstrapAgent.subscribeToAllTopics();
25
+ await bootstrapAgent.subscribeToAllTopics();
26
26
 
27
27
  bootstrapAgent.publishMessage('$aws/certificates/create/json', '');
28
28
 
@@ -30,9 +30,12 @@ export function bootstrapProvision() {
30
30
  logger.info('Your device is being provisioned');
31
31
  });
32
32
 
33
- bootstrapAgent.device.on('message', (topic: string, payload: string) => {
34
- bootstrapAgent.handleAwsCertificateTopics(topic, payload);
35
- });
33
+ bootstrapAgent.device.on(
34
+ 'message',
35
+ async (topic: string, payload: string) => {
36
+ await bootstrapAgent.handleAwsCertificateTopics(topic, payload);
37
+ }
38
+ );
36
39
 
37
40
  bootstrapAgent.device.on('packetsend', (packet: any) => {
38
41
  logger.debug(`Sending packet: ${JSON.stringify({ packet }, null, 2)}`);
@@ -0,0 +1,71 @@
1
+ import { logger } from '../util/logger';
2
+
3
+ type CmdStatusType = 'idle' | 'in_progress';
4
+
5
+ class CmdStatus {
6
+ private projectId: string;
7
+ private status: CmdStatusType;
8
+
9
+ constructor(projectId: string, status: CmdStatusType) {
10
+ this.projectId = projectId;
11
+ this.status = status;
12
+ }
13
+
14
+ public getProjectId() {
15
+ return this.projectId;
16
+ }
17
+
18
+ public update(status: CmdStatusType) {
19
+ this.status = status;
20
+ }
21
+
22
+ public getStatus(): CmdStatusType {
23
+ return this.status;
24
+ }
25
+ }
26
+
27
+ export class CmdStatusManager {
28
+ private apps: { [projectId: string]: CmdStatus } = {};
29
+
30
+ public async start(projectId: string) {
31
+ if (!(projectId in this.apps)) {
32
+ const cmdStatus = new CmdStatus(projectId, 'in_progress');
33
+ this.apps[projectId] = cmdStatus;
34
+ } else if (this.apps[projectId].getStatus() !== 'in_progress') {
35
+ this.apps[projectId].update('in_progress');
36
+ } else {
37
+ logger.debug(
38
+ `Ignoring start for ${projectId} since it already has a command in progress`
39
+ );
40
+ return;
41
+ }
42
+ logger.debug(`Started command for ${projectId}`);
43
+ }
44
+
45
+ public async stop(projectId: string) {
46
+ if (
47
+ !(projectId in this.apps) ||
48
+ this.apps[projectId].getStatus() === 'idle'
49
+ ) {
50
+ throw new Error(`No ongoing command to stop for ${projectId}`);
51
+ }
52
+ this.apps[projectId].update('idle');
53
+ logger.debug(`Stopped command for ${projectId}`);
54
+ }
55
+
56
+ public isCmdInProgress(projectId: string): boolean {
57
+ if (!(projectId in this.apps)) {
58
+ return false;
59
+ }
60
+ return this.apps[projectId].getStatus() === 'in_progress';
61
+ }
62
+
63
+ public anyCmdInProgress() {
64
+ for (const projectId in this.apps) {
65
+ if (this.apps[projectId].getStatus() === 'in_progress') {
66
+ return true;
67
+ }
68
+ }
69
+ return false;
70
+ }
71
+ }