diff --git a/package.json b/package.json index 8e9bc37..a1b47f6 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,10 @@ "./operations": { "require": "./cjs/operations.js", "default": "./mjs/operations.js" + }, + "./codec": { + "require": "./cjs/codec/index.js", + "default": "./mjs/codec/index.js" } }, "files": [ diff --git a/src/__tests__/codec.test.ts b/src/__tests__/codec.test.ts new file mode 100644 index 0000000..088bcf0 --- /dev/null +++ b/src/__tests__/codec.test.ts @@ -0,0 +1,36 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { test, expect, describe } from 'vitest'; +import { encode, decode } from '../codec'; +import { + tokenGroupSimple, + tokenGroupWithArrays, + tokenGroupWithArraysAndDates, + tokensSimple, + tokensWithArrays, + tokensWithArraysAndDates, +} from './property-filter-fixtures'; + +describe('codec', () => { + test.each([ + tokenGroupSimple, + tokenGroupWithArrays, + tokenGroupWithArraysAndDates, + tokensSimple, + tokensWithArrays, + tokensWithArraysAndDates, + ])('encode/decode property filters', propertyFilter => { + const encoded = encode(propertyFilter); + const decoded = decode(encoded); + expect(decoded).toStrictEqual(propertyFilter); + }); + + test('decode should return null if the input string is invalid json and defaultResult is not provided', () => { + expect(decode('invalid json')).toBeNull(); + }); + + test('decode should return the defaultResult if the input string is invalid json and defaultResult is provided', () => { + const defaultResult = { operation: 'and', tokens: [], tokenGroups: [] }; + expect(decode('invalid json', defaultResult)).toStrictEqual(defaultResult); + }); +}); diff --git a/src/__tests__/property-filter-fixtures.ts b/src/__tests__/property-filter-fixtures.ts new file mode 100644 index 0000000..7545528 --- /dev/null +++ b/src/__tests__/property-filter-fixtures.ts @@ -0,0 +1,191 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +export const tokenGroupSimple = { + tokens: [], + operation: 'and', + tokenGroups: [ + { + propertyKey: 'instanceid', + operator: '=', + value: 'i-2dc5ce28a0328391', + }, + ], +}; + +export const tokenGroupWithArrays = { + tokens: [], + operation: 'and', + tokenGroups: [ + { + propertyKey: 'instanceid', + operator: '=', + value: 'i-2dc5ce28a0328391', + }, + { + propertyKey: 'state', + operator: '=', + value: ['STOPPED', 'STOPPING', 'PENDING'], + }, + { + propertyKey: 'stopped', + operator: '=', + value: true, + }, + { + propertyKey: 'instancetype', + operator: '=', + value: 't2.medium', + }, + ], +}; + +export const tokenGroupWithArraysAndDates = { + tokens: [], + operation: 'and', + tokenGroups: [ + { + propertyKey: 'instanceid', + operator: '=', + value: 'i-2dc5ce28a0328391', + }, + { + propertyKey: 'state', + operator: '=', + value: ['STOPPED', 'STOPPING', 'PENDING'], + }, + { + propertyKey: 'stopped', + operator: '=', + value: true, + }, + { + propertyKey: 'instancetype', + operator: '=', + value: 't2.medium', + }, + { + propertyKey: 'averagelatency', + operator: '<=', + value: '123', + }, + { + propertyKey: 'availablestorage', + operator: '=', + value: '6.86', + }, + { + propertyKey: 'owner', + operator: '=', + value: ['admin512', 'admin0', 'admin6621'], + }, + { + propertyKey: 'privateipaddress', + operator: ':', + value: '116.198.231.86', + }, + { + propertyKey: 'publicdns', + operator: '=', + value: 'ec2-23-50-59-84.us-west-1.compute.amazonaws.com', + }, + { + propertyKey: 'publicdns', + operator: ':', + value: 'ec2-11-56-64-85.eu-west-2.compute.amazonaws.com', + }, + { + propertyKey: 'ipv4publicip', + operator: ':', + value: '90.77.83.18', + }, + { + propertyKey: 'securitygroup', + operator: '!=', + value: 'launch-wizard-66', + }, + { + propertyKey: 'releasedate', + operator: '>=', + value: '2024-12-21', + }, + ], +}; + +export const tokensSimple = { + tokens: [ + { + propertyKey: 'instanceid', + operator: '=', + value: 'i-2dc5ce28a0328391', + }, + ], + operation: 'and', +}; + +export const tokensWithArrays = { + tokens: [ + { + propertyKey: 'instanceid', + operator: '=', + value: 'i-2dc5ce28a0328391', + }, + { + propertyKey: 'state', + operator: '!=', + value: ['STOPPING', 'PENDING'], + }, + { + propertyKey: 'stopped', + operator: '=', + value: false, + }, + { + propertyKey: 'instancetype', + operator: ':', + value: 't3.nano', + }, + ], + operation: 'and', +}; + +export const tokensWithArraysAndDates = { + tokens: [ + { + propertyKey: 'instanceid', + operator: '=', + value: 'i-2dc5ce28a0328391', + }, + { + propertyKey: 'state', + operator: '!=', + value: ['STOPPING', 'PENDING'], + }, + { + propertyKey: 'stopped', + operator: '=', + value: false, + }, + { + propertyKey: 'instancetype', + operator: ':', + value: 't3.nano', + }, + { + propertyKey: 'releasedate', + operator: '<=', + value: '2024-12-20', + }, + { + propertyKey: 'launchdate', + operator: '>', + value: '2024-12-01', + }, + { + propertyKey: 'tags', + operator: '!:', + value: ['AAA', 'AB'], + }, + ], + operation: 'and', +}; diff --git a/src/codec/index.ts b/src/codec/index.ts new file mode 100644 index 0000000..9d213d1 --- /dev/null +++ b/src/codec/index.ts @@ -0,0 +1,16 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +export function encode(queryObject: T): string { + return encodeURIComponent(JSON.stringify(queryObject)); +} + +export function decode(queryString: string, defaultResult: T): T; +export function decode(queryString: string, defaultResult?: undefined): T | null; +export function decode(queryString: string, defaultResult?: T): T | null { + try { + return JSON.parse(decodeURIComponent(queryString)); + } catch (error) { + return defaultResult ?? null; + } +}