@hello.nrfcloud.com/nrfcloud-api-helpers 1.1.4 → 1.2.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.
@@ -1,29 +1,15 @@
1
1
  import { SSMClient } from '@aws-sdk/client-ssm';
2
2
  import { get } from '@bifravst/aws-ssm-settings-helpers';
3
- import { getAccountsFromAllSettings } from './getAllAccounts.js';
4
- import { validateSettings } from './settings.js';
5
3
  import { NRFCLOUD_ACCOUNT_SCOPE } from './scope.js';
4
+ import { groupByAccount } from './groupByAccount.js';
5
+ import { validateSettings } from './settings.js';
6
6
  /**
7
7
  * Returns settings for all accounts
8
8
  */
9
- export const getAllAccountsSettings = async ({ ssm, stackName, }) => {
10
- const allSettings = await get(ssm)({
11
- stackName,
12
- scope: NRFCLOUD_ACCOUNT_SCOPE,
13
- })();
14
- const accounts = getAccountsFromAllSettings(allSettings);
15
- return [...accounts].reduce((allAccountSettings, account) => ({
16
- ...allAccountSettings,
17
- [account]: validateSettings(Object.entries(allSettings)
18
- .filter(([k]) => k.startsWith(`${account}/`))
19
- .map(([k, v]) => [
20
- k.replace(new RegExp(`^${account}/`), ''),
21
- v,
22
- ])
23
- .reduce((s, [k, v]) => ({ ...s, [k]: v }), {})),
24
- }), {});
25
- };
26
- console.log(await getAllAccountsSettings({
27
- ssm: new SSMClient(),
28
- stackName: 'hello-nrfcloud-backend',
29
- }));
9
+ export const getAllAccountsSettings = async ({ ssm, stackName, }) => Object.entries(groupByAccount(await get(ssm)({
10
+ stackName,
11
+ scope: NRFCLOUD_ACCOUNT_SCOPE,
12
+ })())).reduce((allSettings, [account, settings]) => ({
13
+ ...allSettings,
14
+ [account]: validateSettings(settings),
15
+ }), {});
@@ -0,0 +1 @@
1
+ export declare const groupByAccount: (allSettings: Record<string, string>) => Record<string, Record<string, string>>;
@@ -0,0 +1,14 @@
1
+ import { getAccountsFromAllSettings } from './getAllAccounts.js';
2
+ export const groupByAccount = (allSettings) => {
3
+ const accounts = getAccountsFromAllSettings(allSettings);
4
+ return [...accounts].reduce((allAccountSettings, account) => ({
5
+ ...allAccountSettings,
6
+ [account]: Object.entries(allSettings)
7
+ .filter(([k]) => k.startsWith(`${account}/`))
8
+ .map(([k, v]) => [
9
+ k.replace(new RegExp(`^${account}/`), ''),
10
+ v,
11
+ ])
12
+ .reduce((s, [k, v]) => ({ ...s, [k]: v }), {}),
13
+ }), {});
14
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,20 @@
1
+ import { it, describe } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { groupByAccount } from './groupByAccount.js';
4
+ void describe('groupByAccount()', () => {
5
+ void it('should group settings by account', () => assert.deepEqual(groupByAccount({
6
+ 'elite/accountDeviceClientId': 'account-4db55163-7593-4d63-9679-d16fbc2d464f',
7
+ 'elite/healthCheckModel': 'PCA20035+solar',
8
+ 'acme/mqttEndpoint': 'mqtt.nrfcloud.com',
9
+ 'acme/teamId': 'f4ba6ede-7867-43eb-a495-7e0de108f52e',
10
+ }), {
11
+ acme: {
12
+ mqttEndpoint: 'mqtt.nrfcloud.com',
13
+ teamId: 'f4ba6ede-7867-43eb-a495-7e0de108f52e',
14
+ },
15
+ elite: {
16
+ accountDeviceClientId: 'account-4db55163-7593-4d63-9679-d16fbc2d464f',
17
+ healthCheckModel: 'PCA20035+solar',
18
+ },
19
+ }));
20
+ });
@@ -1,5 +1,5 @@
1
1
  export * from './settings.js';
2
2
  export * from './scope.js';
3
- export * from './initializeAccount.js';
4
3
  export * from './getAllAccounts.js';
5
4
  export * from './getAllAccountsSettings.js';
5
+ export * from './groupByAccount.js';
@@ -1,5 +1,5 @@
1
1
  export * from './settings.js';
2
2
  export * from './scope.js';
3
- export * from './initializeAccount.js';
4
3
  export * from './getAllAccounts.js';
5
4
  export * from './getAllAccountsSettings.js';
5
+ export * from './groupByAccount.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hello.nrfcloud.com/nrfcloud-api-helpers",
3
- "version": "1.1.4",
3
+ "version": "1.2.1",
4
4
  "description": "Helper functions for integrating nRF Cloud APIs in AWS lambdas written in TypeScript.",
5
5
  "exports": {
6
6
  "./*": {
@@ -1,10 +0,0 @@
1
- import { SSMClient } from '@aws-sdk/client-ssm';
2
- /**
3
- * Initializes the nRF Cloud Account
4
- */
5
- export declare const initializeAccount: ({ ssm, stackName, account, iotEndpoint, }: {
6
- ssm: SSMClient;
7
- stackName: string;
8
- account: string;
9
- iotEndpoint: string;
10
- }) => (reset?: boolean) => Promise<void>;
@@ -1,73 +0,0 @@
1
- import { SSMClient } from '@aws-sdk/client-ssm';
2
- import chalk from 'chalk';
3
- import { NRFCLOUD_ACCOUNT_SCOPE, nrfCloudAccount } from './scope.js';
4
- import { get } from '@bifravst/aws-ssm-settings-helpers';
5
- import { createAccountDevice } from '../api/createAccountDevice.js';
6
- import { deleteAccountDevice } from '../api/deleteAccountDevice.js';
7
- import { getAccountInfo } from '../api/getAccountInfo.js';
8
- import { defaultApiEndpoint, getSettings as getNRFCloudSettings, putSettings as putNRFCloudSettings, } from './settings.js';
9
- /**
10
- * Initializes the nRF Cloud Account
11
- */
12
- export const initializeAccount = ({ ssm, stackName, account, iotEndpoint, }) => async (reset = false) => {
13
- const settingsReader = get(ssm)({
14
- stackName,
15
- scope: NRFCLOUD_ACCOUNT_SCOPE,
16
- context: nrfCloudAccount(account),
17
- });
18
- const { apiKey, apiEndpoint } = await settingsReader();
19
- if (apiKey === undefined)
20
- throw new Error(`nRF Cloud API key not configured.`);
21
- let settingsWithAccountDevice = undefined;
22
- try {
23
- settingsWithAccountDevice = await getNRFCloudSettings({
24
- ssm,
25
- stackName,
26
- account,
27
- })();
28
- console.log(chalk.white('Stack settings'));
29
- Object.entries(settingsWithAccountDevice).forEach(([k, v]) => console.log(chalk.yellow(`${k}:`), chalk.blue(v)));
30
- console.log();
31
- }
32
- catch (err) {
33
- console.log(chalk.magenta(`Stack not configured.`));
34
- }
35
- const effectiveEndpoint = apiEndpoint === undefined ? defaultApiEndpoint : new URL(apiEndpoint);
36
- const accountInfo = await getAccountInfo({
37
- endpoint: effectiveEndpoint,
38
- apiKey,
39
- });
40
- if ('error' in accountInfo) {
41
- console.error(chalk.red('⚠️'), '', chalk.red(accountInfo.error.message));
42
- process.exit(1);
43
- }
44
- console.log(chalk.yellow('AWS IoT endpoint:'), chalk.blue(iotEndpoint));
45
- console.log();
46
- console.log(chalk.white('nRF Cloud account info:'));
47
- Object.entries(accountInfo).forEach(([k, v]) => console.log(chalk.yellow(`${k}:`), chalk.blue(v)));
48
- console.log();
49
- if (reset === true) {
50
- console.debug(chalk.magenta(`Deleting account device ...`));
51
- await deleteAccountDevice({ apiKey, endpoint: effectiveEndpoint });
52
- console.log(chalk.green(`Account device deleted.`));
53
- }
54
- if (settingsWithAccountDevice === undefined || reset === true) {
55
- console.debug(chalk.magenta(`Generating new account device credentials ...`));
56
- const { clientCert, privateKey } = await createAccountDevice({
57
- apiKey,
58
- endpoint: effectiveEndpoint,
59
- });
60
- if (privateKey === undefined) {
61
- console.error(chalk.red('⚠️'), chalk.red('Account device exists'));
62
- throw new Error(`Account device exists in account ${accountInfo.team.tenantId}`);
63
- }
64
- console.log(chalk.green(`Account device created.`));
65
- await putNRFCloudSettings({ ssm, stackName, account })({
66
- accountDeviceClientCert: clientCert,
67
- accountDevicePrivateKey: privateKey,
68
- accountDeviceClientId: `account-${accountInfo.team.tenantId}`,
69
- mqttEndpoint: accountInfo.mqttEndpoint,
70
- mqttTopicPrefix: accountInfo.mqttTopicPrefix,
71
- });
72
- }
73
- };