diff --git a/package-lock.json b/package-lock.json index 999693b..8dd7ee4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,9 @@ }, "peerDependencies": { "@aws-sdk/client-timestream-query": ">= 3 < 4", - "@aws-sdk/client-timestream-write": ">= 3 < 4" + "@aws-sdk/client-timestream-write": ">= 3 < 4", + "@types/uuid": ">= 8 < 9", + "uuid": ">= 8 < 9" } }, "node_modules/@aws-crypto/ie11-detection": { @@ -2525,6 +2527,12 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, + "node_modules/@types/uuid": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", + "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", + "peer": true + }, "node_modules/@types/yargs": { "version": "16.0.4", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", @@ -10292,6 +10300,12 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, + "@types/uuid": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", + "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", + "peer": true + }, "@types/yargs": { "version": "16.0.4", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", diff --git a/package.json b/package.json index 8b5825b..d50a2d7 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,9 @@ "license": "BSD-3-Clause", "peerDependencies": { "@aws-sdk/client-timestream-query": ">= 3 < 4", - "@aws-sdk/client-timestream-write": ">= 3 < 4" + "@aws-sdk/client-timestream-write": ">= 3 < 4", + "@types/uuid": ">= 8 < 9", + "uuid": ">= 8 < 9" }, "devDependencies": { "@nordicsemiconductor/asset-tracker-cloud-code-style": "11.0.21", diff --git a/src/index.ts b/src/index.ts index 2ac56ec..2b64c02 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1,5 @@ -export * from './parseResult' export * from './client' +export * from './index' +export * from './parseResult' +export * from './toRecord' +export * from './toTimestreamType' diff --git a/src/toRecord.spec.ts b/src/toRecord.spec.ts new file mode 100644 index 0000000..d46fb53 --- /dev/null +++ b/src/toRecord.spec.ts @@ -0,0 +1,37 @@ +import { MeasureValueType } from '@aws-sdk/client-timestream-write' +import { toRecord } from '.' + +describe('toRecord()', () => { + it('should convert sensor data to a timestream record', () => { + const ts = Date.now() + expect( + toRecord({ + name: 'bat', + v: 3.3, + ts, + dimensions: { measureGroup: 'someGroup' }, + }), + ).toEqual({ + Dimensions: [ + { + Name: 'measureGroup', + Value: 'someGroup', + }, + ], + MeasureName: 'bat', + MeasureValue: `3.3`, + MeasureValueType: MeasureValueType.DOUBLE, + Time: ts.toString(), + }) + }) + it('should ignore sensor data if the value is not defined', () => { + expect( + toRecord({ + name: 'bat', + v: undefined, + ts: Date.now(), + dimensions: { measureGroup: 'someGroup' }, + }), + ).toEqual(undefined) + }) +}) diff --git a/src/toRecord.ts b/src/toRecord.ts new file mode 100644 index 0000000..d545f25 --- /dev/null +++ b/src/toRecord.ts @@ -0,0 +1,26 @@ +import { _Record } from '@aws-sdk/client-timestream-write' +import { toTimestreamType } from './toTimestreamType' + +export const toRecord = ({ + name, + ts, + v, + dimensions, +}: { + name: string + ts: number + v?: { toString: () => string } + dimensions?: Record +}): _Record | undefined => { + if (v === undefined) return + return { + Dimensions: Object.entries(dimensions ?? {}).map(([Name, Value]) => ({ + Name, + Value, + })), + MeasureName: name, + MeasureValue: v.toString(), + MeasureValueType: toTimestreamType(v), + Time: ts.toString(), + } +} diff --git a/src/toTimestreamType.spec.ts b/src/toTimestreamType.spec.ts new file mode 100644 index 0000000..05cf412 --- /dev/null +++ b/src/toTimestreamType.spec.ts @@ -0,0 +1,13 @@ +import { toTimestreamType } from './toTimestreamType' + +describe('toTimestreamType', () => { + it.each([ + [true, 'BOOLEAN'], + [1.1, 'DOUBLE'], + [1, 'DOUBLE'], + ['foo', 'VARCHAR'], + ['12345678901234567890', 'VARCHAR'], + ])('should determind %s as %s', (v, expected) => { + expect(toTimestreamType(v)).toEqual(expected) + }) +}) diff --git a/src/toTimestreamType.ts b/src/toTimestreamType.ts new file mode 100644 index 0000000..78aaf44 --- /dev/null +++ b/src/toTimestreamType.ts @@ -0,0 +1,8 @@ +import { MeasureValueType } from '@aws-sdk/client-timestream-write' + +export const toTimestreamType = (v: unknown): MeasureValueType => { + if (typeof v === 'string') return MeasureValueType.VARCHAR + if (typeof v === 'boolean') return MeasureValueType.BOOLEAN + if (Number.isInteger(v)) return MeasureValueType.DOUBLE + return MeasureValueType.DOUBLE +}