Skip to content

Commit b96f54d

Browse files
committed
feat(cli): add command to mark devices as unsupported
1 parent 6fd8178 commit b96f54d

File tree

4 files changed

+108
-3
lines changed

4 files changed

+108
-3
lines changed

cli/cli.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { cleanBackupCertificates } from './commands/clean-backup-certificates.js
3131
import { listnRFCloudAccountsCommand } from './commands/list-nrfcloud-accounts.js'
3232
import { configureRFCloudAccountCommand } from './commands/configure-nrfcloud-account.js'
3333
import { getNRFCloudBulkOpsStatus } from './commands/get-nrfcloud-bulkops-status.js'
34+
import { importUnsupportedDevice } from './commands/import-unsupported-device.js'
3435

3536
const ssm = new SSMClient({})
3637
const iot = new IoTClient({})
@@ -159,6 +160,10 @@ const CLI = async ({ isCI }: { isCI: boolean }) => {
159160
ssm,
160161
stackName: STACK_NAME,
161162
}),
163+
importUnsupportedDevice({
164+
db,
165+
devicesTableName: outputs.devicesTableName,
166+
}),
162167
)
163168
} catch (error) {
164169
console.warn(chalk.yellow('⚠️'), chalk.yellow((error as Error).message))

cli/commands/import-devices.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export const importDevicesCommand = ({
3232
action: async (account, model, provisioningList, { windows }) => {
3333
const devicesList = (await readFile(provisioningList, 'utf-8'))
3434
.trim()
35-
.split(windows === true ? '\n' : '\r\n')
35+
.split(windows === true ? '\r\n' : '\n')
3636
.map((s) =>
3737
s.split(';').map((s) => s.replace(/^"/, '').replace(/"$/, '')),
3838
)
@@ -52,15 +52,15 @@ export const importDevicesCommand = ({
5252
console.error(
5353
chalk.yellow('⚠️'),
5454
chalk.yellow(`Not an IMEI:`),
55-
chalk.red(imei),
55+
chalk.red(JSON.stringify(imei)),
5656
)
5757
return false
5858
}
5959
if (!isFingerprint(fingerprint)) {
6060
console.error(
6161
chalk.yellow('⚠️'),
6262
chalk.yellow(`Not a fingerprint:`),
63-
chalk.red(fingerprint),
63+
chalk.red(JSON.stringify(fingerprint)),
6464
)
6565
return false
6666
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { type DynamoDBClient } from '@aws-sdk/client-dynamodb'
2+
import { isFingerprint } from '@hello.nrfcloud.com/proto/fingerprint'
3+
import chalk from 'chalk'
4+
import { markFingerprintAsUnsupported } from '../../devices/markFingerprintAsUnsupported.js'
5+
import type { CommandDefinition } from './CommandDefinition.js'
6+
import { isIMEI } from './import-devices.js'
7+
import { readFile } from 'node:fs/promises'
8+
9+
export const importUnsupportedDevice = ({
10+
db,
11+
devicesTableName,
12+
}: {
13+
db: DynamoDBClient
14+
devicesTableName: string
15+
}): CommandDefinition => ({
16+
command: 'unsupported-device <deviceList>',
17+
help: 'Marks the fingerprint to belong to an unsupported device. The deviceList is expected to be a tab-separated list with IMEI and fingerprint',
18+
options: [
19+
{
20+
flags: '-w, --windows',
21+
description: `Use Windows line ends`,
22+
},
23+
],
24+
action: async (devicesList, { windows }) => {
25+
for (const [deviceId, fingerprint] of (await readFile(devicesList, 'utf-8'))
26+
.trim()
27+
.split(windows === true ? '\r\n' : '\n')
28+
.map((s) => s.trim().split('\t'))) {
29+
if (!isFingerprint(fingerprint)) {
30+
console.error(
31+
chalk.yellow('⚠️'),
32+
chalk.yellow(`Not a fingerprint:`),
33+
chalk.red(JSON.stringify(fingerprint)),
34+
)
35+
process.exit(1)
36+
}
37+
if (!isIMEI(deviceId)) {
38+
console.error(
39+
chalk.yellow('⚠️'),
40+
chalk.yellow(`Not an IMEI:`),
41+
chalk.red(JSON.stringify(deviceId)),
42+
)
43+
process.exit(1)
44+
}
45+
46+
const res = await markFingerprintAsUnsupported({
47+
db,
48+
devicesTableName,
49+
})({
50+
fingerprint,
51+
deviceId,
52+
})
53+
if ('error' in res) {
54+
console.error(chalk.red(`Failed to store fingerprint!`))
55+
console.error(res.error.message)
56+
} else {
57+
console.log(
58+
chalk.green(`Marked fingerprint as unsupported:`),
59+
chalk.cyan(fingerprint),
60+
chalk.blue(deviceId),
61+
)
62+
}
63+
}
64+
},
65+
})
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { PutItemCommand, type DynamoDBClient } from '@aws-sdk/client-dynamodb'
2+
import { marshall } from '@aws-sdk/util-dynamodb'
3+
4+
export const markFingerprintAsUnsupported =
5+
({
6+
db,
7+
devicesTableName,
8+
}: {
9+
db: DynamoDBClient
10+
devicesTableName: string
11+
}) =>
12+
async ({
13+
fingerprint,
14+
deviceId,
15+
}: {
16+
fingerprint: string
17+
deviceId: string
18+
}): Promise<{ success: true } | { error: Error }> => {
19+
try {
20+
await db.send(
21+
new PutItemCommand({
22+
TableName: devicesTableName,
23+
Item: marshall({
24+
fingerprint,
25+
deviceId,
26+
model: 'unsupported',
27+
}),
28+
ConditionExpression: 'attribute_not_exists(fingerprint)',
29+
}),
30+
)
31+
return { success: true }
32+
} catch (error) {
33+
return { error: error as Error }
34+
}
35+
}

0 commit comments

Comments
 (0)