├── web
├── .eslintignore
├── amplify
│ ├── package.json
│ ├── functions
│ │ ├── list-sensors
│ │ │ ├── resource.ts
│ │ │ └── handler.ts
│ │ └── send-sensor-value
│ │ │ ├── resource.ts
│ │ │ └── handler.ts
│ ├── auth
│ │ └── resource.ts
│ ├── tsconfig.json
│ ├── data
│ │ └── resource.ts
│ └── backend.ts
├── public
│ └── favicon.ico
├── src
│ ├── main.jsx
│ ├── App.jsx
│ ├── MapPage.css
│ ├── graphql
│ │ ├── queries.js
│ │ ├── subscriptions.js
│ │ └── mutations.js
│ └── MapPage.jsx
├── vite.config.js
├── .graphqlconfig.yml
├── index.html
├── README.md
├── .eslintrc.cjs
├── .gitignore
└── package.json
├── .gitignore
├── images
├── map.jpg
└── architecture.jpg
├── sensor
├── .gitignore
├── policy.json
├── package.json
├── certs
│ └── AmazonRootCA1.pem
├── index.js
├── sensors.json
├── delete-sensors.js
├── create-sensors.js
└── package-lock.json
├── CODE_OF_CONDUCT.md
├── LICENSE
├── CONTRIBUTING.md
└── README.md
/web/.eslintignore:
--------------------------------------------------------------------------------
1 | amplify-codegen-temp/models/models
--------------------------------------------------------------------------------
/web/amplify/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module"
3 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | #VS Code
6 | .vscode
7 |
--------------------------------------------------------------------------------
/images/map.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/aws-appsync-iot-core-realtime-dashboard/HEAD/images/map.jpg
--------------------------------------------------------------------------------
/images/architecture.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/aws-appsync-iot-core-realtime-dashboard/HEAD/images/architecture.jpg
--------------------------------------------------------------------------------
/web/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/aws-appsync-iot-core-realtime-dashboard/HEAD/web/public/favicon.ico
--------------------------------------------------------------------------------
/web/src/main.jsx:
--------------------------------------------------------------------------------
1 | import ReactDOM from 'react-dom/client'
2 | import App from './App.jsx'
3 |
4 | ReactDOM.createRoot(document.getElementById('root')).render(
5 |
6 | )
7 |
--------------------------------------------------------------------------------
/sensor/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # node.js
6 | #
7 | node_modules/
8 | npm-debug.log
9 | yarn-error.log
10 |
11 | # AWS IOT thing certificates
12 | certs/*.crt
13 | certs/*.key
14 |
--------------------------------------------------------------------------------
/web/amplify/functions/list-sensors/resource.ts:
--------------------------------------------------------------------------------
1 | import { defineFunction } from "@aws-amplify/backend";
2 |
3 | export const listSensors = defineFunction({
4 | entry: "./handler.ts",
5 | name: "listSensors",
6 | });
7 |
--------------------------------------------------------------------------------
/web/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | define:{
8 | global:{}
9 | }
10 | })
11 |
--------------------------------------------------------------------------------
/web/amplify/functions/send-sensor-value/resource.ts:
--------------------------------------------------------------------------------
1 | import { defineFunction } from "@aws-amplify/backend";
2 |
3 | export const sendSensorValue = defineFunction({
4 | entry: "./handler.ts",
5 | name: "sendSensorValue",
6 | resourceGroupName: "data",
7 | });
8 |
--------------------------------------------------------------------------------
/sensor/policy.json:
--------------------------------------------------------------------------------
1 | {
2 | "Version": "2012-10-17",
3 | "Statement": [
4 | {
5 | "Effect": "Allow",
6 | "Action": "iot:Connect",
7 | "Resource": "*"
8 | },
9 | {
10 | "Effect": "Allow",
11 | "Action": "iot:Publish",
12 | "Resource": "*"
13 | }
14 | ]
15 | }
--------------------------------------------------------------------------------
/web/amplify/auth/resource.ts:
--------------------------------------------------------------------------------
1 | import { defineAuth } from '@aws-amplify/backend';
2 |
3 | /**
4 | * Define and configure your auth resource
5 | * @see https://docs.amplify.aws/gen2/build-a-backend/auth
6 | */
7 | export const auth = defineAuth({
8 | loginWith: {
9 | email: true,
10 | },
11 | });
12 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | ## Code of Conduct
2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
4 | opensource-codeofconduct@amazon.com with any additional questions or comments.
5 |
--------------------------------------------------------------------------------
/web/.graphqlconfig.yml:
--------------------------------------------------------------------------------
1 | projects:
2 | sensorsapi:
3 | schemaPath: src/graphql/schema.json
4 | includes:
5 | - src/graphql/**/*.js
6 | excludes:
7 | - ./amplify/**
8 | extensions:
9 | amplify:
10 | codeGenTarget: javascript
11 | generatedFileName: ''
12 | docsFilePath: src/graphql
13 | extensions:
14 | amplify:
15 | version: 3
16 |
--------------------------------------------------------------------------------
/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Bay Health
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/web/src/App.jsx:
--------------------------------------------------------------------------------
1 | import "@aws-amplify/ui-react/styles.css";
2 | import { withAuthenticator } from "@aws-amplify/ui-react";
3 | import { Amplify } from "aws-amplify";
4 |
5 | import MapPage from "./MapPage";
6 |
7 | import awsExports from "../amplify_outputs.json";
8 |
9 | Amplify.configure(awsExports);
10 |
11 | const App = () => {
12 | return ;
13 | };
14 |
15 | export default withAuthenticator(App);
16 |
--------------------------------------------------------------------------------
/web/amplify/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2022",
4 | "module": "es2022",
5 | "moduleResolution": "bundler",
6 | "resolveJsonModule": true,
7 | "esModuleInterop": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "strict": true,
10 | "skipLibCheck": true,
11 | "paths": {
12 | "$amplify/*": [
13 | "../.amplify/generated/*"
14 | ]
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/sensor/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "aws-iot-core-appsync-realtime-dashboard-sensor",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "node index.js"
8 | },
9 | "author": "David Moser ",
10 | "license": "MIT-0",
11 | "dependencies": {
12 | "@aws-sdk/client-iot": "^3.708.0",
13 | "argparse": "^2.0.1",
14 | "aws-iot-device-sdk": "^2.2.15"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/web/README.md:
--------------------------------------------------------------------------------
1 | # React + Vite
2 |
3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4 |
5 | Currently, two official plugins are available:
6 |
7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9 |
--------------------------------------------------------------------------------
/web/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: { browser: true, es2020: true },
4 | extends: [
5 | 'eslint:recommended',
6 | 'plugin:react/recommended',
7 | 'plugin:react/jsx-runtime',
8 | 'plugin:react-hooks/recommended',
9 | ],
10 | ignorePatterns: ['dist', '.eslintrc.cjs'],
11 | parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
12 | settings: { react: { version: '18.2' } },
13 | plugins: ['react-refresh'],
14 | rules: {
15 | 'react-refresh/only-export-components': [
16 | 'warn',
17 | { allowConstantExport: true },
18 | ],
19 | },
20 | }
21 |
--------------------------------------------------------------------------------
/web/src/MapPage.css:
--------------------------------------------------------------------------------
1 | body { margin: 0; padding: 0; }
2 |
3 | #container {
4 | height: 100%;
5 | }
6 |
7 | #map {
8 | width: 100%;
9 | height: 100%;
10 | }
11 |
12 | #banner {
13 | position: absolute;
14 | width: 100%;
15 | font: 2em sans-serif;
16 | padding: 12px;
17 | color: #ffffff;
18 | opacity: 75%;
19 | background-color: #1D1C1B;
20 | z-index: 200;
21 | }
22 |
23 | .sensor {
24 | border-radius: 50%;
25 | height: 2em;
26 | width: 2em;
27 | cursor: pointer;
28 | }
29 |
30 | .fullscreen-map {
31 | position: absolute;
32 | top: 0;
33 | bottom: 0;
34 | width: 100%;
35 | height: 100%;
36 | z-index: 100;
37 | }
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | this software and associated documentation files (the "Software"), to deal in
5 | the Software without restriction, including without limitation the rights to
6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7 | the Software, and to permit persons to whom the Software is furnished to do so.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
10 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
11 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
12 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
13 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
14 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
15 |
16 |
--------------------------------------------------------------------------------
/web/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
26 | #amplify-do-not-edit-begin
27 | amplify/\#current-cloud-backend
28 | amplify/.config/local-*
29 | amplify/logs
30 | amplify/mock-data
31 | amplify/mock-api-resources
32 | amplify/backend/amplify-meta.json
33 | amplify/backend/.temp
34 | build/
35 | dist/
36 | node_modules/
37 | aws-exports.js
38 | awsconfiguration.json
39 | amplifyconfiguration.json
40 | amplifyconfiguration.dart
41 | amplify-build-config.json
42 | amplify-gradle-config.json
43 | amplifytools.xcconfig
44 | .secret-*
45 | **.sample
46 | #amplify-do-not-edit-end
47 |
48 | team-provider-info.json
49 |
50 | # amplify
51 | .amplify
52 | amplify_outputs*
53 | amplifyconfiguration*
54 |
--------------------------------------------------------------------------------
/web/amplify/functions/list-sensors/handler.ts:
--------------------------------------------------------------------------------
1 | import type { Handler } from "aws-lambda";
2 | import { IoTClient, SearchIndexCommand } from "@aws-sdk/client-iot";
3 |
4 | const iotClient = new IoTClient();
5 |
6 | export const handler: Handler = async (event) => {
7 | console.log("event", event);
8 |
9 | //query all sensors that have reported a shadow and of type water quality sensor
10 | //you must have fleet indexing enabled in IoT Core with REGISTRY_AND_SHADOW indexed
11 |
12 | var params = {
13 | queryString:
14 | "shadow.reported.name:* AND thingTypeName:WATER_QUALITY_SENSOR",
15 | };
16 |
17 | var command = new SearchIndexCommand(params);
18 |
19 | var result = await iotClient.send(command);
20 |
21 | // return array of sensors
22 | return result.things?.map((thing) => {
23 | const shadow = JSON.parse(thing?.shadow!);
24 | return {
25 | sensorId: thing.thingName,
26 | name: shadow.reported.name || "",
27 | enabled: shadow.reported.enabled || false,
28 | geo: {
29 | latitude: shadow.reported.geo?.latitude || 0,
30 | longitude: shadow.reported.geo?.longitude || 0,
31 | },
32 | status: shadow.reported.status || 0,
33 | };
34 | });
35 | };
36 |
--------------------------------------------------------------------------------
/sensor/certs/AmazonRootCA1.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF
3 | ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
4 | b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL
5 | MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
6 | b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj
7 | ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM
8 | 9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw
9 | IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6
10 | VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L
11 | 93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm
12 | jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
13 | AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA
14 | A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI
15 | U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs
16 | N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv
17 | o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU
18 | 5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy
19 | rqXRfboQnoZsG4q5WTP468SQvvG5
20 | -----END CERTIFICATE-----
21 |
--------------------------------------------------------------------------------
/web/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "web",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "@aws-amplify/ui-react": "^6.10.0",
14 | "@aws-sdk/client-iot": "^3.782.0",
15 | "@aws-sdk/protocol-http": "^3.374.0",
16 | "@aws-sdk/signature-v4": "^3.374.0",
17 | "aws-amplify": "^6.14.1",
18 | "maplibre-gl": "^2.1.2",
19 | "maplibre-gl-js-amplify": "^4.0.2",
20 | "react": "^18.2.0",
21 | "react-dom": "^18.2.0"
22 | },
23 | "devDependencies": {
24 | "@aws-amplify/backend": "^1.15.0",
25 | "@aws-amplify/backend-cli": "^1.5.0",
26 | "@types/react": "^18.2.48",
27 | "@types/react-dom": "^18.2.18",
28 | "@vitejs/plugin-react": "^4.3.4",
29 | "aws-cdk": "^2.1007.0",
30 | "aws-cdk-lib": "^2.188.0",
31 | "constructs": "^10.4.2",
32 | "esbuild": "^0.25.2",
33 | "eslint": "^8.56.0",
34 | "eslint-plugin-react": "^7.37.5",
35 | "eslint-plugin-react-hooks": "^4.6.0",
36 | "eslint-plugin-react-refresh": "^0.4.5",
37 | "tsx": "^4.19.3",
38 | "typescript": "^5.8.3",
39 | "vite": "^5.0.13"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/web/src/graphql/queries.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | // this is an auto generated file. This will be overwritten
3 |
4 | export const listSensors = /* GraphQL */ `
5 | query ListSensors {
6 | listSensors {
7 | sensorId
8 | name
9 | enabled
10 | geo {
11 | latitude
12 | longitude
13 | __typename
14 | }
15 | status
16 | __typename
17 | }
18 | }
19 | `;
20 | export const getSensorValue = /* GraphQL */ `
21 | query GetSensorValue($id: ID!) {
22 | getSensorValue(id: $id) {
23 | id
24 | sensorId
25 | pH
26 | temperature
27 | salinity
28 | disolvedO2
29 | status
30 | timestamp
31 | createdAt
32 | updatedAt
33 | __typename
34 | }
35 | }
36 | `;
37 | export const listSensorValues = /* GraphQL */ `
38 | query ListSensorValues(
39 | $filter: ModelSensorValueFilterInput
40 | $limit: Int
41 | $nextToken: String
42 | ) {
43 | listSensorValues(filter: $filter, limit: $limit, nextToken: $nextToken) {
44 | items {
45 | id
46 | sensorId
47 | pH
48 | temperature
49 | salinity
50 | disolvedO2
51 | status
52 | timestamp
53 | createdAt
54 | updatedAt
55 | __typename
56 | }
57 | nextToken
58 | __typename
59 | }
60 | }
61 | `;
62 |
--------------------------------------------------------------------------------
/web/src/graphql/subscriptions.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | // this is an auto generated file. This will be overwritten
3 |
4 | export const onCreateSensorValue = /* GraphQL */ `
5 | subscription OnCreateSensorValue(
6 | $filter: ModelSubscriptionSensorValueFilterInput
7 | ) {
8 | onCreateSensorValue(filter: $filter) {
9 | id
10 | sensorId
11 | pH
12 | temperature
13 | salinity
14 | disolvedO2
15 | status
16 | timestamp
17 | createdAt
18 | updatedAt
19 | __typename
20 | }
21 | }
22 | `;
23 | export const onUpdateSensorValue = /* GraphQL */ `
24 | subscription OnUpdateSensorValue(
25 | $filter: ModelSubscriptionSensorValueFilterInput
26 | ) {
27 | onUpdateSensorValue(filter: $filter) {
28 | id
29 | sensorId
30 | pH
31 | temperature
32 | salinity
33 | disolvedO2
34 | status
35 | timestamp
36 | createdAt
37 | updatedAt
38 | __typename
39 | }
40 | }
41 | `;
42 | export const onDeleteSensorValue = /* GraphQL */ `
43 | subscription OnDeleteSensorValue(
44 | $filter: ModelSubscriptionSensorValueFilterInput
45 | ) {
46 | onDeleteSensorValue(filter: $filter) {
47 | id
48 | sensorId
49 | pH
50 | temperature
51 | salinity
52 | disolvedO2
53 | status
54 | timestamp
55 | createdAt
56 | updatedAt
57 | __typename
58 | }
59 | }
60 | `;
61 |
--------------------------------------------------------------------------------
/web/amplify/data/resource.ts:
--------------------------------------------------------------------------------
1 | import { type ClientSchema, a, defineData } from "@aws-amplify/backend";
2 | import { listSensors } from "../functions/list-sensors/resource";
3 | import { sendSensorValue } from "../functions/send-sensor-value/resource";
4 |
5 | const schema = a
6 | .schema({
7 | SensorValue: a.model({
8 | id: a.id(),
9 | sensorId: a.string().required(),
10 | pH: a.float().required(),
11 | temperature: a.float().required(),
12 | salinity: a.float().required(),
13 | disolvedO2: a.float().required(),
14 | status: a.integer().required(),
15 | timestamp: a.timestamp().required(),
16 | }),
17 | Geo: a.customType({
18 | latitude: a.float(),
19 | longitude: a.float(),
20 | }),
21 | Sensor: a.customType({
22 | sensorId: a.string().required(),
23 | name: a.string().required(),
24 | geo: a.ref("Geo").required(),
25 | enabled: a.boolean().required(),
26 | status: a.integer().required(),
27 | }),
28 | listSensors: a
29 | .query()
30 | .returns(a.ref("Sensor").array())
31 | .handler(a.handler.function(listSensors)),
32 | })
33 | .authorization((allow) => [
34 | allow.authenticated(),
35 | allow.resource(sendSensorValue),
36 | ]);
37 |
38 | export type Schema = ClientSchema;
39 |
40 | export const data = defineData({
41 | schema,
42 | authorizationModes: {
43 | defaultAuthorizationMode: "userPool",
44 | },
45 | });
46 |
--------------------------------------------------------------------------------
/web/src/graphql/mutations.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | // this is an auto generated file. This will be overwritten
3 |
4 | export const createSensorValue = /* GraphQL */ `
5 | mutation CreateSensorValue(
6 | $input: CreateSensorValueInput!
7 | $condition: ModelSensorValueConditionInput
8 | ) {
9 | createSensorValue(input: $input, condition: $condition) {
10 | id
11 | sensorId
12 | pH
13 | temperature
14 | salinity
15 | disolvedO2
16 | status
17 | timestamp
18 | createdAt
19 | updatedAt
20 | __typename
21 | }
22 | }
23 | `;
24 | export const updateSensorValue = /* GraphQL */ `
25 | mutation UpdateSensorValue(
26 | $input: UpdateSensorValueInput!
27 | $condition: ModelSensorValueConditionInput
28 | ) {
29 | updateSensorValue(input: $input, condition: $condition) {
30 | id
31 | sensorId
32 | pH
33 | temperature
34 | salinity
35 | disolvedO2
36 | status
37 | timestamp
38 | createdAt
39 | updatedAt
40 | __typename
41 | }
42 | }
43 | `;
44 | export const deleteSensorValue = /* GraphQL */ `
45 | mutation DeleteSensorValue(
46 | $input: DeleteSensorValueInput!
47 | $condition: ModelSensorValueConditionInput
48 | ) {
49 | deleteSensorValue(input: $input, condition: $condition) {
50 | id
51 | sensorId
52 | pH
53 | temperature
54 | salinity
55 | disolvedO2
56 | status
57 | timestamp
58 | createdAt
59 | updatedAt
60 | __typename
61 | }
62 | }
63 | `;
64 |
--------------------------------------------------------------------------------
/web/amplify/functions/send-sensor-value/handler.ts:
--------------------------------------------------------------------------------
1 | import type { Handler } from "aws-lambda";
2 | import crypto from "@aws-crypto/sha256-js";
3 | import { defaultProvider } from "@aws-sdk/credential-provider-node";
4 | import { SignatureV4 } from "@aws-sdk/signature-v4";
5 | import { HttpRequest } from "@aws-sdk/protocol-http";
6 | import { default as fetch, Request } from "node-fetch";
7 |
8 | const GRAPHQL_ENDPOINT = process.env.AMPLIFY_DATA_GRAPHQL_ENDPOINT || "";
9 | const AWS_REGION = process.env.AWS_REGION || "";
10 | const { Sha256 } = crypto;
11 |
12 | export const handler: Handler = async (event) => {
13 | console.log("event", event);
14 |
15 | //set a random sensor status 1-3
16 | let status = Math.floor(Math.random() * 3) + 1;
17 |
18 | const query = /* GraphQL */ `
19 | mutation CreateSensorValue($input: CreateSensorValueInput!) {
20 | createSensorValue(input: $input) {
21 | id
22 | sensorId
23 | pH
24 | temperature
25 | salinity
26 | disolvedO2
27 | status
28 | timestamp
29 | createdAt
30 | updatedAt
31 | }
32 | }
33 | `;
34 |
35 | const variables = {
36 | input: {
37 | sensorId: event.sensorId,
38 | pH: event.data.pH,
39 | temperature: event.data.temperature,
40 | salinity: event.data.salinity,
41 | disolvedO2: event.data.disolvedO2,
42 | status: status,
43 | timestamp: event.data.timestamp,
44 | },
45 | };
46 |
47 | const endpoint = new URL(GRAPHQL_ENDPOINT);
48 |
49 | const signer = new SignatureV4({
50 | credentials: defaultProvider(),
51 | region: AWS_REGION,
52 | service: "appsync",
53 | sha256: Sha256,
54 | });
55 |
56 | const requestToBeSigned = new HttpRequest({
57 | method: "POST",
58 | headers: {
59 | "Content-Type": "application/json",
60 | host: endpoint.host,
61 | },
62 | hostname: endpoint.host,
63 | body: JSON.stringify({ query, variables }),
64 | path: endpoint.pathname,
65 | });
66 |
67 | const signed = await signer.sign(requestToBeSigned);
68 | const request = new Request(endpoint, signed);
69 |
70 | let statusCode = 200;
71 | let body;
72 | let response;
73 |
74 | try {
75 | response = await fetch(request);
76 | body = await response.json();
77 | console.log(body);
78 | } catch (error: any) {
79 | console.log(error);
80 | statusCode = 500;
81 | body = {
82 | errors: [
83 | {
84 | message: error.message,
85 | },
86 | ],
87 | };
88 | }
89 |
90 | return {
91 | statusCode,
92 | body: JSON.stringify(body),
93 | };
94 | };
95 |
--------------------------------------------------------------------------------
/sensor/index.js:
--------------------------------------------------------------------------------
1 | const awsIot = require('aws-iot-device-sdk');
2 |
3 | //load the sensors file that contains the location of the device certificates and the clientId of the sensor
4 | var sensors = require('./sensors.json');
5 |
6 | //constants used in the application
7 | const SHADOW_TOPIC = "$aws/things/[thingName]/shadow/update";
8 | const VALUE_TOPIC = "dt/bay-health/SF/[thingName]/sensor-value"; //topic to which sensor values will be published
9 |
10 | //shadow document to be transmitted at statup
11 | var shadowDocument = {
12 | state: {
13 | reported: {
14 | name: "",
15 | enabled: true,
16 | geo: {
17 | latitude: 0,
18 | longitude: 0
19 | }
20 | }
21 | }
22 | }
23 |
24 | async function run(sensor) {
25 |
26 | //initialize the IOT device
27 | var device = awsIot.device(sensor.settings);
28 |
29 | //create a placeholder for the message
30 | var msg = {
31 | pH: 0,
32 | temperature: 0,
33 | salinity: 0,
34 | disolvedO2: 0,
35 | timestamp: new Date().getTime()
36 | }
37 |
38 | device.on('connect', function() {
39 |
40 | console.log('connected to IoT Hub');
41 |
42 | //publish the shadow document for the sensor
43 | var topic = SHADOW_TOPIC.replace('[thingName]', sensor.settings.clientId);
44 |
45 | shadowDocument.state.reported.name = sensor.name;
46 | shadowDocument.state.reported.enabled = true;
47 | shadowDocument.state.reported.geo.latitude = sensor.geo.latitude;
48 | shadowDocument.state.reported.geo.longitude = sensor.geo.longitude;
49 |
50 | device.publish(topic, JSON.stringify(shadowDocument));
51 |
52 | console.log('published to shadow topic ' + topic + ' ' + JSON.stringify(shadowDocument));
53 |
54 | //publish new value readings based on value_rate
55 | setInterval(function(){
56 |
57 | //calculate randome values for each sensor reading
58 | msg.pH = RandomValue(50, 100) / 10;
59 | msg.temperature = RandomValue(480, 570) / 10;
60 | msg.salinity = RandomValue(200, 350) / 10;
61 | msg.disolvedO2 = RandomValue(40, 120) / 10;
62 |
63 | msg.timestamp = new Date().getTime();
64 |
65 | //publish the sensor reading message
66 | var topic = VALUE_TOPIC.replace('[thingName]', sensor.settings.clientId);
67 |
68 | device.publish(topic, JSON.stringify(msg));
69 |
70 | console.log('published to telemetry topic ' + topic + ' ' + JSON.stringify(msg));
71 |
72 | }, sensor.frequency);
73 | });
74 |
75 | device.on('error', function(error) {
76 | console.log('Error: ', error);
77 | });
78 | }
79 |
80 | function RandomValue (min, max) {
81 | return Math.floor(Math.random() * (max - min + 1) ) + min;
82 | }
83 |
84 | //run simulation for each sensor
85 | sensors.forEach((sensor) => {
86 | run(sensor);
87 | })
88 |
--------------------------------------------------------------------------------
/sensor/sensors.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "SF Bay - East",
4 | "thingTypeName": "WATER_QUALITY_SENSOR",
5 | "manufacturer": "Xylem",
6 | "model": "WQ201",
7 | "firmware": "1.30",
8 | "frequency": 3000,
9 | "geo": {
10 | "latitude": 37.692625,
11 | "longitude": -122.200682
12 | },
13 | "settings": {
14 | "host": "",
15 | "keyPath": "",
16 | "certPath": "",
17 | "caPath": "",
18 | "certificateArn": "",
19 | "clientId": "sensor-sf-east"
20 | }
21 | },
22 | {
23 | "name": "SF Bay - Southeast",
24 | "thingTypeName": "WATER_QUALITY_SENSOR",
25 | "manufacturer": "Xylem",
26 | "model": "WQ201",
27 | "firmware": "1.30",
28 | "frequency": 3200,
29 | "geo": {
30 | "latitude": 37.612215,
31 | "longitude": -122.162933
32 | },
33 | "settings": {
34 | "host": "",
35 | "keyPath": "",
36 | "certPath": "",
37 | "caPath": "",
38 | "certificateArn": "",
39 | "clientId": "sensor-sf-southeast"
40 | }
41 | },
42 | {
43 | "name": "SF Bay - Southwest",
44 | "thingTypeName": "WATER_QUALITY_SENSOR",
45 | "manufacturer": "Xylem",
46 | "model": "WQ201",
47 | "firmware": "1.30",
48 | "frequency": 3400,
49 | "geo": {
50 | "latitude": 37.602464,
51 | "longitude": -122.338036
52 | },
53 | "settings": {
54 | "host": "",
55 | "keyPath": "",
56 | "certPath": "",
57 | "caPath": "",
58 | "certificateArn": "",
59 | "clientId": "sensor-sf-southwest"
60 | }
61 | },
62 | {
63 | "name": "SF Bay - West",
64 | "thingTypeName": "WATER_QUALITY_SENSOR",
65 | "manufacturer": "Xylem",
66 | "model": "WQ201",
67 | "firmware": "1.30",
68 | "frequency": 3600,
69 | "geo": {
70 | "latitude": 37.66228,
71 | "longitude": -122.36549
72 | },
73 | "settings": {
74 | "host": "",
75 | "keyPath": "",
76 | "certPath": "",
77 | "caPath": "",
78 | "certificateArn": "",
79 | "clientId": "sensor-sf-west"
80 | }
81 | },
82 | {
83 | "name": "SF Bay - Northwest",
84 | "thingTypeName": "WATER_QUALITY_SENSOR",
85 | "manufacturer": "Xylem",
86 | "model": "WQ201",
87 | "firmware": "1.30",
88 | "frequency": 3800,
89 | "geo": {
90 | "latitude": 37.751372,
91 | "longitude": -122.359999
92 | },
93 | "settings": {
94 | "host": "",
95 | "keyPath": "",
96 | "certPath": "",
97 | "caPath": "",
98 | "certificateArn": "",
99 | "clientId": "sensor-sf-northwest"
100 | }
101 | },
102 | {
103 | "name": "SF Bay - North",
104 | "thingTypeName": "WATER_QUALITY_SENSOR",
105 | "manufacturer": "Xylem",
106 | "model": "WQ201",
107 | "firmware": "1.30",
108 | "frequency": 4000,
109 | "geo": {
110 | "latitude": 37.800307,
111 | "longitude": -122.354788
112 | },
113 | "settings": {
114 | "host": "",
115 | "keyPath": "",
116 | "certPath": "",
117 | "caPath": "",
118 | "certificateArn": "",
119 | "clientId": "sensor-sf-north"
120 | }
121 | }
122 | ]
--------------------------------------------------------------------------------
/sensor/delete-sensors.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs').promises;
2 | const {
3 | IoTClient,
4 | DetachThingPrincipalCommand,
5 | DeleteThingCommand,
6 | DetachPolicyCommand,
7 | DeletePolicyCommand,
8 | UpdateCertificateCommand,
9 | DeleteCertificateCommand
10 | } = require("@aws-sdk/client-iot");
11 |
12 | const { ArgumentParser } = require('argparse');
13 |
14 | //constants used in the app - do not change
15 | const SENSORS_FILE = './sensors.json';
16 |
17 | //open sensor definition file
18 | var sensors = require(SENSORS_FILE);
19 |
20 | async function deleteSensors(profile, region){
21 |
22 | try {
23 |
24 | const iotClient = new IoTClient({ profile: profile, region: region });
25 |
26 | //iterate over all sensors and create policies, certs, and things
27 | sensors.forEach(async (sensor) => {
28 |
29 | //remove the iot core endpoint
30 | sensor.settings.host = "";
31 |
32 | //attach thing to certificate
33 | var command = new DetachThingPrincipalCommand({thingName: sensor.settings.clientId, principal: sensor.settings.certificateArn})
34 | await iotClient.send(command)
35 |
36 | //delete the thing
37 | command = new DeleteThingCommand({thingName: sensor.settings.clientId})
38 | await iotClient.send(command)
39 |
40 | //detach policy from certificate
41 | var policyName = 'Policy-' + sensor.settings.clientId;
42 | command = new DetachPolicyCommand({ policyName: policyName, target: sensor.settings.certificateArn})
43 | await iotClient.send(command)
44 |
45 | //delete the IOT policy
46 | command = new DeletePolicyCommand({policyName: policyName})
47 | await iotClient.send(command)
48 |
49 | //delete the certificates
50 | var certificateId = sensor.settings.certificateArn.split('/')[1];
51 | command = new UpdateCertificateCommand({certificateId:certificateId, newStatus:"INACTIVE"})
52 | await iotClient.send(command)
53 |
54 | command = new DeleteCertificateCommand({certificateId:certificateId, forceDelete:true})
55 | await iotClient.send(command)
56 | sensor.settings.certificateArn = ""
57 |
58 | //delete the certificate files
59 | await fs.unlink(sensor.settings.keyPath);
60 | sensor.settings.keyPath = "";
61 |
62 | await fs.unlink(sensor.settings.certPath);
63 | sensor.settings.certPath = "";
64 | sensor.settings.caPath = "";
65 |
66 | //save the updated settings file
67 | let data = JSON.stringify(sensors, null, 2);
68 | await fs.writeFile(SENSORS_FILE, data);
69 | })
70 |
71 | //display results
72 | console.log('IoT Things removed: ' + sensors.length);
73 | console.log('AWS Profile: ' + profile);
74 | console.log('AWS Region: ' + region);
75 |
76 | sensors.forEach((sensor) => {
77 | console.log('Thing Name: ' + sensor.settings.clientId);
78 | })
79 |
80 | }
81 | catch (err) {
82 | console.log('Error deleting sensors');
83 | console.log(err.message);
84 | }
85 | }
86 |
87 | // parse for profile command line arguent
88 | const parser = new ArgumentParser({
89 | description: 'Deletes IoT Things for sensors defined in sensors.json'
90 | });
91 |
92 | parser.add_argument('--profile', {default: 'default'});
93 | parser.add_argument('--region', {default: 'us-east-1'});
94 |
95 | args = parser.parse_args()
96 |
97 | deleteSensors(args.profile, args.region);
98 |
--------------------------------------------------------------------------------
/web/amplify/backend.ts:
--------------------------------------------------------------------------------
1 | import { defineBackend } from "@aws-amplify/backend";
2 | import { Policy, PolicyStatement, ServicePrincipal } from "aws-cdk-lib/aws-iam";
3 | import { CfnMap } from "aws-cdk-lib/aws-location";
4 | import { CfnTopicRule } from "aws-cdk-lib/aws-iot";
5 | import { auth } from "./auth/resource";
6 | import { data } from "./data/resource";
7 | import { listSensors } from "./functions/list-sensors/resource";
8 | import { sendSensorValue } from "./functions/send-sensor-value/resource";
9 |
10 | const backend = defineBackend({
11 | auth,
12 | data,
13 | listSensors,
14 | sendSensorValue,
15 | });
16 |
17 | // disable unauthenticated access
18 | const { cfnIdentityPool } = backend.auth.resources.cfnResources;
19 | cfnIdentityPool.allowUnauthenticatedIdentities = false;
20 |
21 | // Mapping Resources
22 | const geoStack = backend.createStack("geo-stack");
23 |
24 | // create a map
25 | const map = new CfnMap(geoStack, "Map", {
26 | mapName: "SensorMap",
27 | description: "Sensor Map",
28 | configuration: {
29 | style: "VectorEsriDarkGrayCanvas",
30 | },
31 | pricingPlan: "RequestBasedUsage",
32 | tags: [
33 | {
34 | key: "name",
35 | value: "SensorMap",
36 | },
37 | ],
38 | });
39 |
40 | // create an IAM policy to allow interacting with geo resource
41 | const myGeoPolicy = new Policy(geoStack, "GeoPolicy", {
42 | policyName: "myGeoPolicy",
43 | statements: [
44 | new PolicyStatement({
45 | actions: [
46 | "geo:GetMapTile",
47 | "geo:GetMapSprites",
48 | "geo:GetMapGlyphs",
49 | "geo:GetMapStyleDescriptor",
50 | ],
51 | resources: [map.attrArn],
52 | }),
53 | ],
54 | });
55 |
56 | // apply the policy to the authenticated role
57 | backend.auth.resources.authenticatedUserIamRole.attachInlinePolicy(myGeoPolicy);
58 |
59 | // patch the map resource to the expected output configuration
60 | backend.addOutput({
61 | geo: {
62 | aws_region: geoStack.region,
63 | maps: {
64 | items: {
65 | [map.mapName]: {
66 | style: "VectorEsriDarkGrayCanvas",
67 | },
68 | },
69 | default: map.mapName,
70 | },
71 | },
72 | });
73 |
74 | // IoT Resources
75 |
76 | // grant the list sensors function access to search all IoT devices
77 | const listSensorsLambda = backend.listSensors.resources.lambda;
78 |
79 | listSensorsLambda.addToRolePolicy(
80 | new PolicyStatement({
81 | actions: ["iot:SearchIndex"],
82 | resources: ["arn:aws:iot:*:*:*"],
83 | })
84 | );
85 |
86 | const iotStack = backend.createStack("iot-stack");
87 |
88 | const sendSensorValueLambda = backend.sendSensorValue.resources.lambda;
89 |
90 | // create a rule to process messages from the sensors - send them to the lambda function
91 | const rule = new CfnTopicRule(iotStack, "SendSensorValueRule", {
92 | topicRulePayload: {
93 | sql: "select * as data, topic(4) as sensorId from 'dt/bay-health/SF/+/sensor-value'",
94 | actions: [
95 | {
96 | lambda: {
97 | functionArn: sendSensorValueLambda.functionArn,
98 | },
99 | },
100 | ],
101 | },
102 | });
103 |
104 | // allow IoT rule to invoke the lambda function
105 | sendSensorValueLambda.addPermission("AllowIoTInvoke", {
106 | principal: new ServicePrincipal("iot.amazonaws.com"),
107 | sourceArn: `arn:aws:iot:${iotStack.region}:${iotStack.account}:rule/SendSensorValueRule*`,
108 | });
109 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing Guidelines
2 |
3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional
4 | documentation, we greatly value feedback and contributions from our community.
5 |
6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary
7 | information to effectively respond to your bug report or contribution.
8 |
9 |
10 | ## Reporting Bugs/Feature Requests
11 |
12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features.
13 |
14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already
15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
16 |
17 | * A reproducible test case or series of steps
18 | * The version of our code being used
19 | * Any modifications you've made relevant to the bug
20 | * Anything unusual about your environment or deployment
21 |
22 |
23 | ## Contributing via Pull Requests
24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that:
25 |
26 | 1. You are working against the latest source on the *master* branch.
27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already.
28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted.
29 |
30 | To send us a pull request, please:
31 |
32 | 1. Fork the repository.
33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change.
34 | 3. Ensure local tests pass.
35 | 4. Commit to your fork using clear commit messages.
36 | 5. Send us a pull request, answering any default questions in the pull request interface.
37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation.
38 |
39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
41 |
42 |
43 | ## Finding contributions to work on
44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start.
45 |
46 |
47 | ## Code of Conduct
48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
50 | opensource-codeofconduct@amazon.com with any additional questions or comments.
51 |
52 |
53 | ## Security issue notifications
54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue.
55 |
56 |
57 | ## Licensing
58 |
59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution.
60 |
61 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes.
62 |
--------------------------------------------------------------------------------
/web/src/MapPage.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 | import { createMap } from "maplibre-gl-js-amplify";
3 | import { Marker } from "maplibre-gl";
4 | import { generateClient } from "aws-amplify/api";
5 | import { listSensors } from "./graphql/queries";
6 | import { onCreateSensorValue } from "./graphql/subscriptions";
7 |
8 | import "maplibre-gl/dist/maplibre-gl.css";
9 | import "./MapPage.css";
10 |
11 | const MapPage = () => {
12 | useEffect(() => {
13 | var map;
14 |
15 | const CreateSensorMarker = (sensor) => {
16 | var marker = document.createElement("div");
17 | marker.id = "sensor-image-" + sensor.sensorId;
18 | marker.className = "sensor";
19 |
20 | let sensorColor = "white";
21 | marker.style.backgroundColor = sensorColor;
22 | marker.style.border = "border: 0.1em solid " + sensorColor + ";";
23 |
24 | return marker;
25 | };
26 |
27 | // call api to get list of sensors and display them as markers on the map
28 | async function DisplaySensors(map) {
29 | const client = generateClient();
30 | const response = await client.graphql({ query: listSensors });
31 | console.log("API Response:", response);
32 |
33 | if (response && response.data) {
34 | console.log("sensors retrived");
35 |
36 | response.data.listSensors.forEach((sensor) => {
37 | var marker = CreateSensorMarker(sensor);
38 | console.log(sensor);
39 | new Marker({ element: marker })
40 | .setLngLat([sensor.geo.longitude, sensor.geo.latitude])
41 | .addTo(map);
42 | });
43 | }
44 | }
45 |
46 | // configure and display the map
47 | async function initializeMap() {
48 | try {
49 | map = await createMap({
50 | container: "map",
51 | center: [-122.2, 37.705],
52 | zoom: 10,
53 | maxZoom: 10,
54 | });
55 |
56 | map.repaint = true;
57 |
58 | console.log("Map Rendered");
59 |
60 | await DisplaySensors(map);
61 | } catch (error) {
62 | console.log("error fetching sensors", error);
63 | }
64 | }
65 |
66 | initializeMap();
67 | }, []);
68 |
69 | // start subscription for sensor status changes and update sensor marker color
70 | useEffect(() => {
71 | const UpdateSensorMarker = (sensorId, status) => {
72 | var marker = document.getElementById("sensor-image-" + sensorId);
73 |
74 | if (marker) {
75 | let sensorColor = "";
76 |
77 | if (status === 1) {
78 | sensorColor = "green";
79 | } else if (status === 2) {
80 | sensorColor = "yellow";
81 | } else if (status === 3) {
82 | sensorColor = "red";
83 | } else {
84 | sensorColor = "white";
85 | }
86 |
87 | marker.style.backgroundColor = sensorColor;
88 | marker.style.border = `border: 0.1em solid ${sensorColor};`;
89 |
90 | console.log(sensorId + " updated");
91 | }
92 | };
93 |
94 | const client = generateClient();
95 | const createSub = client.graphql({ query: onCreateSensorValue }).subscribe({
96 | next: ({ data }) => {
97 | UpdateSensorMarker(
98 | data.onCreateSensorValue.sensorId,
99 | data.onCreateSensorValue.status
100 | );
101 | },
102 | error: (error) => console.warn(error),
103 | });
104 | }, []);
105 |
106 | return (
107 |
108 |
Bay Health
109 |
110 |
111 | );
112 | };
113 |
114 | export default MapPage;
115 |
--------------------------------------------------------------------------------
/sensor/create-sensors.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs').promises;
2 | const {
3 | IoTClient,
4 | DescribeEndpointCommand,
5 | UpdateIndexingConfigurationCommand,
6 | CreatePolicyCommand,
7 | CreateKeysAndCertificateCommand,
8 | CreateThingTypeCommand,
9 | CreateThingCommand,
10 | AttachPolicyCommand,
11 | AttachThingPrincipalCommand
12 | } = require("@aws-sdk/client-iot");
13 |
14 | const { ArgumentParser } = require('argparse');
15 |
16 | //constants used in the app - do not change
17 | const SENSORS_FILE = './sensors.json';
18 | const CERT_FOLDER = './certs/';
19 | const POLICY_FILE = './policy.json';
20 | const ROOT_CA_FILE = 'AmazonRootCA1.pem';
21 |
22 | //open sensor definition file
23 | var sensors = require(SENSORS_FILE);
24 | const policyDocument = require(POLICY_FILE);
25 |
26 | async function createSensors(profile, region){
27 |
28 | try {
29 |
30 | const iotClient = new IoTClient({ profile: profile, region: region });
31 |
32 | // get the regional IOT endpoint
33 | var params = { endpointType: 'iot:Data-ATS'};
34 | var command = new DescribeEndpointCommand(params);
35 | const response = await iotClient.send(command);
36 | const host = response.endpointAddress;
37 |
38 | //enable thing fleet indexing to enable searching things
39 | params = {
40 | thingIndexingConfiguration: {
41 | thingIndexingMode: "REGISTRY_AND_SHADOW"
42 | }
43 | }
44 |
45 | command = new UpdateIndexingConfigurationCommand(params)
46 | var result = await iotClient.send(command)
47 |
48 | //iterate over all sensors and create policies, certs, and things
49 | sensors.forEach(async (sensor) => {
50 |
51 | //set the iot core endpoint
52 | sensor.settings.host = host;
53 |
54 | //create the IOT policy
55 | var policyName = 'Policy-' + sensor.settings.clientId;
56 | var policy = { policyName: policyName, policyDocument: JSON.stringify(policyDocument)};
57 | command = new CreatePolicyCommand(policy)
58 | result = await iotClient.send(command)
59 |
60 | //create the certificates
61 | command = new CreateKeysAndCertificateCommand({setAsActive:true});
62 | result = await iotClient.send(command)
63 | sensor.settings.certificateArn = result.certificateArn;
64 | const certificatePem = result.certificatePem;
65 | const privateKey = result.keyPair.PrivateKey;
66 |
67 | //save the certificate
68 | var fileName = CERT_FOLDER + sensor.settings.clientId + '-certificate.pem.crt';
69 | sensor.settings.certPath = fileName;
70 | await fs.writeFile(fileName, certificatePem);
71 |
72 | //save the private key
73 | fileName = CERT_FOLDER + sensor.settings.clientId + '-private.pem.key';
74 | sensor.settings.keyPath = fileName;
75 | await fs.writeFile(fileName, privateKey);
76 |
77 | //save the AWS root certificate
78 | sensor.settings.caPath = CERT_FOLDER + ROOT_CA_FILE;
79 |
80 | // //create the thing type
81 | params = {
82 | thingTypeName: sensor.thingTypeName
83 | }
84 |
85 | command = new CreateThingTypeCommand(params)
86 | result = await iotClient.send(command)
87 |
88 | //create the thing
89 | params = {
90 | thingName: sensor.settings.clientId,
91 | attributePayload: {
92 | attributes: {
93 | 'Manufacturer': sensor.manufacturer,
94 | 'Model': sensor.model,
95 | 'Firmware': sensor.firmware
96 | },
97 | merge: false
98 | },
99 | thingTypeName: sensor.thingTypeName
100 | };
101 |
102 | command = new CreateThingCommand(params)
103 | await iotClient.send(command)
104 |
105 | //attach policy to certificate
106 | command = new AttachPolicyCommand({ policyName: policyName, target: sensor.settings.certificateArn})
107 | await iotClient.send(command)
108 |
109 | //attach thing to certificate
110 | command = new AttachThingPrincipalCommand({thingName: sensor.settings.clientId, principal: sensor.settings.certificateArn})
111 | await iotClient.send(command)
112 |
113 | //save the updated settings file
114 | let data = JSON.stringify(sensors, null, 2);
115 | await fs.writeFile(SENSORS_FILE, data);
116 | })
117 |
118 | //display results
119 | console.log('IoT Things provisioned');
120 | console.log('AWS Profile: ' + profile);
121 | console.log('AWS Region: ' + region);
122 |
123 | sensors.forEach((sensor) => {
124 | console.log('Thing Name: ' + sensor.settings.clientId);
125 | })
126 |
127 | }
128 | catch (err) {
129 | console.log('Error creating sensors');
130 | console.log(err.message);
131 | }
132 |
133 | }
134 |
135 | // parse for profile command line arguent
136 | const parser = new ArgumentParser({
137 | description: 'Creates IoT Things for sensors defined in sensors.json'
138 | });
139 |
140 | parser.add_argument('--profile', {default: 'default'});
141 | parser.add_argument('--region', {default: 'us-east-1'});
142 |
143 | args = parser.parse_args()
144 |
145 | createSensors(args.profile, args.region);
146 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Realtime IoT Dashboard with AWS AppSync and Amazon Location Service
2 |
3 | **Update!!!** this project has been updated to use [**Amplify Gen2**](https://docs.amplify.aws/react/) to deploy the backend services in AWS.
4 |
5 | This application demonstrates a web application dashboard receiving real-time updates from a series of IoT sensors. It depicts a fictitious set of pH sensors deployed around the San Francisco Bay. The solution is built with React, AWS AppSync, Amazon Location Service, AWS Amplify, and AWS IoT technologies.
6 |
7 | 
8 |
9 | The sensors are represented as the colored dots. Their color will fluxuate between red, green, and yellow based on the messages received from the sensors.
10 |
11 | ## Architecture
12 |
13 | 
14 |
15 | 1. The sensor component is developed with the AWS IoT Device SDK for JavaScript. The sensors are registered as _Things_ in IoT Core and publish random values to the Cloud on a configurable frequency. Metadata about each sensor, such as its geolocation, is stored in a _Thing Shadow_.
16 |
17 | 2. Rules in IoT Core subscribe to the message topic and forward the JSON payload to a Lambda function and the IoT Analytics pipeline.
18 |
19 | 3. The Node.js Lambda function executes a GraphQL mutation in AppSync. The mutation saves the sensor's value in DynamoDB and broadcasts the value in real-time to the web dashboard. The Lambda function uses an IAM role and policy to obtain permissions to interact with AppSync.
20 |
21 | 4. The React web dashboard application is written in JavaScript and subscribes to the AppSync sensor subscriptions. When new values are received, an Amazon Location Service map is updated in real-time to reflect the new sensor values. The application uses Cognito to authenticate users and allow them to perform the AppSync subscription.
22 |
23 | ## Getting Started
24 |
25 | ## **Prerequisites**
26 |
27 | The following software was used in the development of this application. While it may work with alternative versions, we recommend you deploy the specified minimum version.
28 |
29 | 1. An AWS account in which you have Administrator access.
30 |
31 | 2. [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) (v2.15.3) the AWS Command Line Interface (CLI) is used to configure your connection credentials to AWS. These credentials are used by the CDK, Amplify, and the CLI.
32 |
33 | 3. [Node.js](https://nodejs.org/en/download/) (v18.19.0) with NPM (v10.1.0)
34 |
35 | ## **Installation**
36 |
37 | **Clone this code repository**
38 |
39 | ```
40 | git clone https://github.com/aws-samples/aws-appsync-iot-core-realtime-dashboard.git
41 | ```
42 |
43 | **Switch to the project's web folder**
44 |
45 | ```
46 | cd aws-appsync-iot-core-realtime-dashboard/web
47 | ```
48 |
49 | **Install the web app's Node.js packages**
50 |
51 | ```
52 | npm install
53 | ```
54 |
55 | **Deploy the Infrastructure with Amplify Gen2**
56 |
57 | ```
58 | npx ampx sandbox
59 | ```
60 |
61 | The deployment is complete when you see the following output:
62 |
63 | ```bash
64 | File written: amplify_outputs.json
65 | ```
66 |
67 | Press **CTRL-C** to exit the deployment.
68 |
69 | Resources created in your account include:
70 |
71 | - AppSync GraphQL API
72 | - DynamoDB Table
73 | - Cognito User Pool
74 | - Lambda Functions (2)
75 | - IoT Rule
76 | - Amazon Location Service Map
77 |
78 | **Install the IoT sensor simulator**
79 |
80 | Open a new terminal window then switch to the app's **sensor** folder (aws-appsync-iot-core-realtime-dashboard/sensor).
81 |
82 | Install the Node js packages, and run the Node js app to create your sensor as a _Thing_ in AWS IoT Core. It will also create and install the certificates your sensor needs to authenticate to IoT Core.
83 |
84 | From the app's **sensor** folder:
85 |
86 | ```
87 | npm install
88 | node create-sensors.js
89 | ```
90 |
91 | _Note - the profile and region arguments are optional. If not specified the app will create the sensors using your default AWS Profile in us-east-1_
92 |
93 | ## Run the web app
94 |
95 | **Start the IoT sensor**
96 |
97 | From the **sensor** terminal window:
98 |
99 | ```
100 | node index.js
101 | ```
102 |
103 | You will see output from the app as it connects to IoT Core and publishes new messages for six sensors every few seconds.
104 |
105 | ```
106 | published to shadow topic $aws/things/sensor-sf-north/shadow/update {"state":{"reported":{"name":"SF Bay - North","enabled":true,"geo":{"latitude":37.800307,"longitude":-122.354788}}}}
107 |
108 | published to telemetry topic dt/bay-health/SF/sensor-sf-north/sensor-value {"pH":5,"temperature":54.7,"salinity":25,"disolvedO2":6.1,"timestamp":1591831843844}
109 | ```
110 |
111 | **Start the web app**
112 |
113 | Switch back to the terminal window pointing to the **web** folder and run:
114 |
115 | ```
116 | npm run dev
117 | ```
118 |
119 | This will launch the application in your machine's default web browser.
120 |
121 | **Sign-up and Sign-in**
122 |
123 | The web app requires users to authenticate via Cognito. The first screen you will see is a logon screen. Click the **Create account** link and create a new account using your email address.
124 |
125 | Cognito will then email you a confirmation code. Enter this code into the subsequent confirmation screen and logon to the app with your credentials.
126 |
127 | **Use the web app**
128 |
129 | You should now see a screen similar to the one at the top of this guide. If you look at the terminal window running the sensor app, you shoud see the values being published to the Cloud reflected in the web app's sensor icon in real-time.
130 |
131 | ## Cleanup
132 |
133 | Once you are finished working with this project, you may want to delete the resources it created in your AWS account.
134 |
135 | From the **web** folder:
136 |
137 | ```
138 | npx ampx sandbox delete
139 | ```
140 |
141 | From the **sensor** folder:
142 |
143 | ```
144 | node delete-sensors.js
145 | ```
146 |
147 | _Note - the profile and region arguments are optional. If not specified the app will delete the sensors using your default AWS Profile in us-east-1_
148 |
149 | ## License
150 |
151 | This sample code is made available under a modified MIT-0 license. See the LICENSE file.
152 |
--------------------------------------------------------------------------------
/sensor/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "aws-iot-core-appsync-realtime-dashboard-sensor",
3 | "version": "1.0.0",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "aws-iot-core-appsync-realtime-dashboard-sensor",
9 | "version": "1.0.0",
10 | "license": "MIT-0",
11 | "dependencies": {
12 | "@aws-sdk/client-iot": "^3.708.0",
13 | "argparse": "^2.0.1",
14 | "aws-iot-device-sdk": "^2.2.15"
15 | }
16 | },
17 | "node_modules/@aws-crypto/sha256-browser": {
18 | "version": "5.2.0",
19 | "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz",
20 | "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==",
21 | "license": "Apache-2.0",
22 | "dependencies": {
23 | "@aws-crypto/sha256-js": "^5.2.0",
24 | "@aws-crypto/supports-web-crypto": "^5.2.0",
25 | "@aws-crypto/util": "^5.2.0",
26 | "@aws-sdk/types": "^3.222.0",
27 | "@aws-sdk/util-locate-window": "^3.0.0",
28 | "@smithy/util-utf8": "^2.0.0",
29 | "tslib": "^2.6.2"
30 | }
31 | },
32 | "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": {
33 | "version": "2.2.0",
34 | "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
35 | "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
36 | "license": "Apache-2.0",
37 | "dependencies": {
38 | "tslib": "^2.6.2"
39 | },
40 | "engines": {
41 | "node": ">=14.0.0"
42 | }
43 | },
44 | "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": {
45 | "version": "2.2.0",
46 | "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
47 | "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
48 | "license": "Apache-2.0",
49 | "dependencies": {
50 | "@smithy/is-array-buffer": "^2.2.0",
51 | "tslib": "^2.6.2"
52 | },
53 | "engines": {
54 | "node": ">=14.0.0"
55 | }
56 | },
57 | "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": {
58 | "version": "2.3.0",
59 | "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
60 | "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
61 | "license": "Apache-2.0",
62 | "dependencies": {
63 | "@smithy/util-buffer-from": "^2.2.0",
64 | "tslib": "^2.6.2"
65 | },
66 | "engines": {
67 | "node": ">=14.0.0"
68 | }
69 | },
70 | "node_modules/@aws-crypto/sha256-js": {
71 | "version": "5.2.0",
72 | "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz",
73 | "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==",
74 | "license": "Apache-2.0",
75 | "dependencies": {
76 | "@aws-crypto/util": "^5.2.0",
77 | "@aws-sdk/types": "^3.222.0",
78 | "tslib": "^2.6.2"
79 | },
80 | "engines": {
81 | "node": ">=16.0.0"
82 | }
83 | },
84 | "node_modules/@aws-crypto/supports-web-crypto": {
85 | "version": "5.2.0",
86 | "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz",
87 | "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==",
88 | "license": "Apache-2.0",
89 | "dependencies": {
90 | "tslib": "^2.6.2"
91 | }
92 | },
93 | "node_modules/@aws-crypto/util": {
94 | "version": "5.2.0",
95 | "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz",
96 | "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==",
97 | "license": "Apache-2.0",
98 | "dependencies": {
99 | "@aws-sdk/types": "^3.222.0",
100 | "@smithy/util-utf8": "^2.0.0",
101 | "tslib": "^2.6.2"
102 | }
103 | },
104 | "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": {
105 | "version": "2.2.0",
106 | "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
107 | "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
108 | "license": "Apache-2.0",
109 | "dependencies": {
110 | "tslib": "^2.6.2"
111 | },
112 | "engines": {
113 | "node": ">=14.0.0"
114 | }
115 | },
116 | "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": {
117 | "version": "2.2.0",
118 | "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
119 | "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
120 | "license": "Apache-2.0",
121 | "dependencies": {
122 | "@smithy/is-array-buffer": "^2.2.0",
123 | "tslib": "^2.6.2"
124 | },
125 | "engines": {
126 | "node": ">=14.0.0"
127 | }
128 | },
129 | "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": {
130 | "version": "2.3.0",
131 | "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
132 | "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
133 | "license": "Apache-2.0",
134 | "dependencies": {
135 | "@smithy/util-buffer-from": "^2.2.0",
136 | "tslib": "^2.6.2"
137 | },
138 | "engines": {
139 | "node": ">=14.0.0"
140 | }
141 | },
142 | "node_modules/@aws-sdk/client-iot": {
143 | "version": "3.709.0",
144 | "resolved": "https://registry.npmjs.org/@aws-sdk/client-iot/-/client-iot-3.709.0.tgz",
145 | "integrity": "sha512-kGwf86ih+yflbJSJoS+0ZzI6oRhWzeXydlkytrLVFu0deHDa4txUJJt406VoIAJNyD1JLHbn7xDmCxzc+MOWlw==",
146 | "license": "Apache-2.0",
147 | "dependencies": {
148 | "@aws-crypto/sha256-browser": "5.2.0",
149 | "@aws-crypto/sha256-js": "5.2.0",
150 | "@aws-sdk/client-sso-oidc": "3.709.0",
151 | "@aws-sdk/client-sts": "3.709.0",
152 | "@aws-sdk/core": "3.709.0",
153 | "@aws-sdk/credential-provider-node": "3.709.0",
154 | "@aws-sdk/middleware-host-header": "3.709.0",
155 | "@aws-sdk/middleware-logger": "3.709.0",
156 | "@aws-sdk/middleware-recursion-detection": "3.709.0",
157 | "@aws-sdk/middleware-user-agent": "3.709.0",
158 | "@aws-sdk/region-config-resolver": "3.709.0",
159 | "@aws-sdk/types": "3.709.0",
160 | "@aws-sdk/util-endpoints": "3.709.0",
161 | "@aws-sdk/util-user-agent-browser": "3.709.0",
162 | "@aws-sdk/util-user-agent-node": "3.709.0",
163 | "@smithy/config-resolver": "^3.0.13",
164 | "@smithy/core": "^2.5.5",
165 | "@smithy/fetch-http-handler": "^4.1.2",
166 | "@smithy/hash-node": "^3.0.11",
167 | "@smithy/invalid-dependency": "^3.0.11",
168 | "@smithy/middleware-content-length": "^3.0.13",
169 | "@smithy/middleware-endpoint": "^3.2.5",
170 | "@smithy/middleware-retry": "^3.0.30",
171 | "@smithy/middleware-serde": "^3.0.11",
172 | "@smithy/middleware-stack": "^3.0.11",
173 | "@smithy/node-config-provider": "^3.1.12",
174 | "@smithy/node-http-handler": "^3.3.2",
175 | "@smithy/protocol-http": "^4.1.8",
176 | "@smithy/smithy-client": "^3.5.0",
177 | "@smithy/types": "^3.7.2",
178 | "@smithy/url-parser": "^3.0.11",
179 | "@smithy/util-base64": "^3.0.0",
180 | "@smithy/util-body-length-browser": "^3.0.0",
181 | "@smithy/util-body-length-node": "^3.0.0",
182 | "@smithy/util-defaults-mode-browser": "^3.0.30",
183 | "@smithy/util-defaults-mode-node": "^3.0.30",
184 | "@smithy/util-endpoints": "^2.1.7",
185 | "@smithy/util-middleware": "^3.0.11",
186 | "@smithy/util-retry": "^3.0.11",
187 | "@smithy/util-utf8": "^3.0.0",
188 | "@types/uuid": "^9.0.1",
189 | "tslib": "^2.6.2",
190 | "uuid": "^9.0.1"
191 | },
192 | "engines": {
193 | "node": ">=16.0.0"
194 | }
195 | },
196 | "node_modules/@aws-sdk/client-sso": {
197 | "version": "3.709.0",
198 | "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.709.0.tgz",
199 | "integrity": "sha512-Qxeo8cN0jNy6Wnbqq4wucffAGJM6sJjofoTgNtPA6cC7sPYx7aYC6OAAAo6NaMRY+WywOKdS9Wgjx2QYRxKx7w==",
200 | "license": "Apache-2.0",
201 | "dependencies": {
202 | "@aws-crypto/sha256-browser": "5.2.0",
203 | "@aws-crypto/sha256-js": "5.2.0",
204 | "@aws-sdk/core": "3.709.0",
205 | "@aws-sdk/middleware-host-header": "3.709.0",
206 | "@aws-sdk/middleware-logger": "3.709.0",
207 | "@aws-sdk/middleware-recursion-detection": "3.709.0",
208 | "@aws-sdk/middleware-user-agent": "3.709.0",
209 | "@aws-sdk/region-config-resolver": "3.709.0",
210 | "@aws-sdk/types": "3.709.0",
211 | "@aws-sdk/util-endpoints": "3.709.0",
212 | "@aws-sdk/util-user-agent-browser": "3.709.0",
213 | "@aws-sdk/util-user-agent-node": "3.709.0",
214 | "@smithy/config-resolver": "^3.0.13",
215 | "@smithy/core": "^2.5.5",
216 | "@smithy/fetch-http-handler": "^4.1.2",
217 | "@smithy/hash-node": "^3.0.11",
218 | "@smithy/invalid-dependency": "^3.0.11",
219 | "@smithy/middleware-content-length": "^3.0.13",
220 | "@smithy/middleware-endpoint": "^3.2.5",
221 | "@smithy/middleware-retry": "^3.0.30",
222 | "@smithy/middleware-serde": "^3.0.11",
223 | "@smithy/middleware-stack": "^3.0.11",
224 | "@smithy/node-config-provider": "^3.1.12",
225 | "@smithy/node-http-handler": "^3.3.2",
226 | "@smithy/protocol-http": "^4.1.8",
227 | "@smithy/smithy-client": "^3.5.0",
228 | "@smithy/types": "^3.7.2",
229 | "@smithy/url-parser": "^3.0.11",
230 | "@smithy/util-base64": "^3.0.0",
231 | "@smithy/util-body-length-browser": "^3.0.0",
232 | "@smithy/util-body-length-node": "^3.0.0",
233 | "@smithy/util-defaults-mode-browser": "^3.0.30",
234 | "@smithy/util-defaults-mode-node": "^3.0.30",
235 | "@smithy/util-endpoints": "^2.1.7",
236 | "@smithy/util-middleware": "^3.0.11",
237 | "@smithy/util-retry": "^3.0.11",
238 | "@smithy/util-utf8": "^3.0.0",
239 | "tslib": "^2.6.2"
240 | },
241 | "engines": {
242 | "node": ">=16.0.0"
243 | }
244 | },
245 | "node_modules/@aws-sdk/client-sso-oidc": {
246 | "version": "3.709.0",
247 | "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.709.0.tgz",
248 | "integrity": "sha512-1w6egz17QQy661lNCRmZZlqIANEbD6g2VFAQIJbVwSiu7brg+GUns+mT1eLLLHAMQc1sL0Ds8/ybSK2SrgGgIA==",
249 | "license": "Apache-2.0",
250 | "dependencies": {
251 | "@aws-crypto/sha256-browser": "5.2.0",
252 | "@aws-crypto/sha256-js": "5.2.0",
253 | "@aws-sdk/core": "3.709.0",
254 | "@aws-sdk/credential-provider-node": "3.709.0",
255 | "@aws-sdk/middleware-host-header": "3.709.0",
256 | "@aws-sdk/middleware-logger": "3.709.0",
257 | "@aws-sdk/middleware-recursion-detection": "3.709.0",
258 | "@aws-sdk/middleware-user-agent": "3.709.0",
259 | "@aws-sdk/region-config-resolver": "3.709.0",
260 | "@aws-sdk/types": "3.709.0",
261 | "@aws-sdk/util-endpoints": "3.709.0",
262 | "@aws-sdk/util-user-agent-browser": "3.709.0",
263 | "@aws-sdk/util-user-agent-node": "3.709.0",
264 | "@smithy/config-resolver": "^3.0.13",
265 | "@smithy/core": "^2.5.5",
266 | "@smithy/fetch-http-handler": "^4.1.2",
267 | "@smithy/hash-node": "^3.0.11",
268 | "@smithy/invalid-dependency": "^3.0.11",
269 | "@smithy/middleware-content-length": "^3.0.13",
270 | "@smithy/middleware-endpoint": "^3.2.5",
271 | "@smithy/middleware-retry": "^3.0.30",
272 | "@smithy/middleware-serde": "^3.0.11",
273 | "@smithy/middleware-stack": "^3.0.11",
274 | "@smithy/node-config-provider": "^3.1.12",
275 | "@smithy/node-http-handler": "^3.3.2",
276 | "@smithy/protocol-http": "^4.1.8",
277 | "@smithy/smithy-client": "^3.5.0",
278 | "@smithy/types": "^3.7.2",
279 | "@smithy/url-parser": "^3.0.11",
280 | "@smithy/util-base64": "^3.0.0",
281 | "@smithy/util-body-length-browser": "^3.0.0",
282 | "@smithy/util-body-length-node": "^3.0.0",
283 | "@smithy/util-defaults-mode-browser": "^3.0.30",
284 | "@smithy/util-defaults-mode-node": "^3.0.30",
285 | "@smithy/util-endpoints": "^2.1.7",
286 | "@smithy/util-middleware": "^3.0.11",
287 | "@smithy/util-retry": "^3.0.11",
288 | "@smithy/util-utf8": "^3.0.0",
289 | "tslib": "^2.6.2"
290 | },
291 | "engines": {
292 | "node": ">=16.0.0"
293 | },
294 | "peerDependencies": {
295 | "@aws-sdk/client-sts": "^3.709.0"
296 | }
297 | },
298 | "node_modules/@aws-sdk/client-sts": {
299 | "version": "3.709.0",
300 | "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.709.0.tgz",
301 | "integrity": "sha512-cBAvlPg6yslXNL385UUGFPw+XY+lA9BzioNdIFkMo3fEUlTShogTtiWz4LsyLHoN6LhKojssP9DSmmWKWjCZIw==",
302 | "license": "Apache-2.0",
303 | "dependencies": {
304 | "@aws-crypto/sha256-browser": "5.2.0",
305 | "@aws-crypto/sha256-js": "5.2.0",
306 | "@aws-sdk/client-sso-oidc": "3.709.0",
307 | "@aws-sdk/core": "3.709.0",
308 | "@aws-sdk/credential-provider-node": "3.709.0",
309 | "@aws-sdk/middleware-host-header": "3.709.0",
310 | "@aws-sdk/middleware-logger": "3.709.0",
311 | "@aws-sdk/middleware-recursion-detection": "3.709.0",
312 | "@aws-sdk/middleware-user-agent": "3.709.0",
313 | "@aws-sdk/region-config-resolver": "3.709.0",
314 | "@aws-sdk/types": "3.709.0",
315 | "@aws-sdk/util-endpoints": "3.709.0",
316 | "@aws-sdk/util-user-agent-browser": "3.709.0",
317 | "@aws-sdk/util-user-agent-node": "3.709.0",
318 | "@smithy/config-resolver": "^3.0.13",
319 | "@smithy/core": "^2.5.5",
320 | "@smithy/fetch-http-handler": "^4.1.2",
321 | "@smithy/hash-node": "^3.0.11",
322 | "@smithy/invalid-dependency": "^3.0.11",
323 | "@smithy/middleware-content-length": "^3.0.13",
324 | "@smithy/middleware-endpoint": "^3.2.5",
325 | "@smithy/middleware-retry": "^3.0.30",
326 | "@smithy/middleware-serde": "^3.0.11",
327 | "@smithy/middleware-stack": "^3.0.11",
328 | "@smithy/node-config-provider": "^3.1.12",
329 | "@smithy/node-http-handler": "^3.3.2",
330 | "@smithy/protocol-http": "^4.1.8",
331 | "@smithy/smithy-client": "^3.5.0",
332 | "@smithy/types": "^3.7.2",
333 | "@smithy/url-parser": "^3.0.11",
334 | "@smithy/util-base64": "^3.0.0",
335 | "@smithy/util-body-length-browser": "^3.0.0",
336 | "@smithy/util-body-length-node": "^3.0.0",
337 | "@smithy/util-defaults-mode-browser": "^3.0.30",
338 | "@smithy/util-defaults-mode-node": "^3.0.30",
339 | "@smithy/util-endpoints": "^2.1.7",
340 | "@smithy/util-middleware": "^3.0.11",
341 | "@smithy/util-retry": "^3.0.11",
342 | "@smithy/util-utf8": "^3.0.0",
343 | "tslib": "^2.6.2"
344 | },
345 | "engines": {
346 | "node": ">=16.0.0"
347 | }
348 | },
349 | "node_modules/@aws-sdk/core": {
350 | "version": "3.709.0",
351 | "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.709.0.tgz",
352 | "integrity": "sha512-7kuSpzdOTAE026j85wq/fN9UDZ70n0OHw81vFqMWwlEFtm5IQ/MRCLKcC4HkXxTdfy1PqFlmoXxWqeBa15tujw==",
353 | "license": "Apache-2.0",
354 | "dependencies": {
355 | "@aws-sdk/types": "3.709.0",
356 | "@smithy/core": "^2.5.5",
357 | "@smithy/node-config-provider": "^3.1.12",
358 | "@smithy/property-provider": "^3.1.11",
359 | "@smithy/protocol-http": "^4.1.8",
360 | "@smithy/signature-v4": "^4.2.4",
361 | "@smithy/smithy-client": "^3.5.0",
362 | "@smithy/types": "^3.7.2",
363 | "@smithy/util-middleware": "^3.0.11",
364 | "fast-xml-parser": "4.4.1",
365 | "tslib": "^2.6.2"
366 | },
367 | "engines": {
368 | "node": ">=16.0.0"
369 | }
370 | },
371 | "node_modules/@aws-sdk/credential-provider-env": {
372 | "version": "3.709.0",
373 | "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.709.0.tgz",
374 | "integrity": "sha512-ZMAp9LSikvHDFVa84dKpQmow6wsg956Um20cKuioPpX2GGreJFur7oduD+tRJT6FtIOHn+64YH+0MwiXLhsaIQ==",
375 | "license": "Apache-2.0",
376 | "dependencies": {
377 | "@aws-sdk/core": "3.709.0",
378 | "@aws-sdk/types": "3.709.0",
379 | "@smithy/property-provider": "^3.1.11",
380 | "@smithy/types": "^3.7.2",
381 | "tslib": "^2.6.2"
382 | },
383 | "engines": {
384 | "node": ">=16.0.0"
385 | }
386 | },
387 | "node_modules/@aws-sdk/credential-provider-http": {
388 | "version": "3.709.0",
389 | "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.709.0.tgz",
390 | "integrity": "sha512-lIS7XLwCOyJnLD70f+VIRr8DNV1HPQe9oN6aguYrhoczqz7vDiVZLe3lh714cJqq9rdxzFypK5DqKHmcscMEPQ==",
391 | "license": "Apache-2.0",
392 | "dependencies": {
393 | "@aws-sdk/core": "3.709.0",
394 | "@aws-sdk/types": "3.709.0",
395 | "@smithy/fetch-http-handler": "^4.1.2",
396 | "@smithy/node-http-handler": "^3.3.2",
397 | "@smithy/property-provider": "^3.1.11",
398 | "@smithy/protocol-http": "^4.1.8",
399 | "@smithy/smithy-client": "^3.5.0",
400 | "@smithy/types": "^3.7.2",
401 | "@smithy/util-stream": "^3.3.2",
402 | "tslib": "^2.6.2"
403 | },
404 | "engines": {
405 | "node": ">=16.0.0"
406 | }
407 | },
408 | "node_modules/@aws-sdk/credential-provider-ini": {
409 | "version": "3.709.0",
410 | "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.709.0.tgz",
411 | "integrity": "sha512-qCF8IIGcPoUp+Ib3ANhbF5gElxFd+kIrtv2/1tKdvhudMANstQbMiWV0LTH47ZZR6c3as4iSrm09NZnpEoD/pA==",
412 | "license": "Apache-2.0",
413 | "dependencies": {
414 | "@aws-sdk/core": "3.709.0",
415 | "@aws-sdk/credential-provider-env": "3.709.0",
416 | "@aws-sdk/credential-provider-http": "3.709.0",
417 | "@aws-sdk/credential-provider-process": "3.709.0",
418 | "@aws-sdk/credential-provider-sso": "3.709.0",
419 | "@aws-sdk/credential-provider-web-identity": "3.709.0",
420 | "@aws-sdk/types": "3.709.0",
421 | "@smithy/credential-provider-imds": "^3.2.8",
422 | "@smithy/property-provider": "^3.1.11",
423 | "@smithy/shared-ini-file-loader": "^3.1.12",
424 | "@smithy/types": "^3.7.2",
425 | "tslib": "^2.6.2"
426 | },
427 | "engines": {
428 | "node": ">=16.0.0"
429 | },
430 | "peerDependencies": {
431 | "@aws-sdk/client-sts": "^3.709.0"
432 | }
433 | },
434 | "node_modules/@aws-sdk/credential-provider-node": {
435 | "version": "3.709.0",
436 | "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.709.0.tgz",
437 | "integrity": "sha512-4HRX9KYWPSjO5O/Vg03YAsebKpvTjTvpK1n7zHYBmlLMBLxUrVsL1nNKKC5p2/7OW3RL8XR1ki3QkoV7kGRxUQ==",
438 | "license": "Apache-2.0",
439 | "dependencies": {
440 | "@aws-sdk/credential-provider-env": "3.709.0",
441 | "@aws-sdk/credential-provider-http": "3.709.0",
442 | "@aws-sdk/credential-provider-ini": "3.709.0",
443 | "@aws-sdk/credential-provider-process": "3.709.0",
444 | "@aws-sdk/credential-provider-sso": "3.709.0",
445 | "@aws-sdk/credential-provider-web-identity": "3.709.0",
446 | "@aws-sdk/types": "3.709.0",
447 | "@smithy/credential-provider-imds": "^3.2.8",
448 | "@smithy/property-provider": "^3.1.11",
449 | "@smithy/shared-ini-file-loader": "^3.1.12",
450 | "@smithy/types": "^3.7.2",
451 | "tslib": "^2.6.2"
452 | },
453 | "engines": {
454 | "node": ">=16.0.0"
455 | }
456 | },
457 | "node_modules/@aws-sdk/credential-provider-process": {
458 | "version": "3.709.0",
459 | "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.709.0.tgz",
460 | "integrity": "sha512-IAC+jPlGQII6jhIylHOwh3RgSobqlgL59nw2qYTURr8hMCI0Z1p5y2ee646HTVt4WeCYyzUAXfxr6YI/Vitv+Q==",
461 | "license": "Apache-2.0",
462 | "dependencies": {
463 | "@aws-sdk/core": "3.709.0",
464 | "@aws-sdk/types": "3.709.0",
465 | "@smithy/property-provider": "^3.1.11",
466 | "@smithy/shared-ini-file-loader": "^3.1.12",
467 | "@smithy/types": "^3.7.2",
468 | "tslib": "^2.6.2"
469 | },
470 | "engines": {
471 | "node": ">=16.0.0"
472 | }
473 | },
474 | "node_modules/@aws-sdk/credential-provider-sso": {
475 | "version": "3.709.0",
476 | "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.709.0.tgz",
477 | "integrity": "sha512-rYdTDOxazS2GdGScelsRK5CAkktRLCCdRjlwXaxrcW57j749hEqxcF5uTv9RD6WBwInfedcSywErNZB+hylQlg==",
478 | "license": "Apache-2.0",
479 | "dependencies": {
480 | "@aws-sdk/client-sso": "3.709.0",
481 | "@aws-sdk/core": "3.709.0",
482 | "@aws-sdk/token-providers": "3.709.0",
483 | "@aws-sdk/types": "3.709.0",
484 | "@smithy/property-provider": "^3.1.11",
485 | "@smithy/shared-ini-file-loader": "^3.1.12",
486 | "@smithy/types": "^3.7.2",
487 | "tslib": "^2.6.2"
488 | },
489 | "engines": {
490 | "node": ">=16.0.0"
491 | }
492 | },
493 | "node_modules/@aws-sdk/credential-provider-web-identity": {
494 | "version": "3.709.0",
495 | "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.709.0.tgz",
496 | "integrity": "sha512-2lbDfE0IQ6gma/7BB2JpkjW5G0wGe4AS0x80oybYAYYviJmUtIR3Cn2pXun6bnAWElt4wYKl4su7oC36rs5rNA==",
497 | "license": "Apache-2.0",
498 | "dependencies": {
499 | "@aws-sdk/core": "3.709.0",
500 | "@aws-sdk/types": "3.709.0",
501 | "@smithy/property-provider": "^3.1.11",
502 | "@smithy/types": "^3.7.2",
503 | "tslib": "^2.6.2"
504 | },
505 | "engines": {
506 | "node": ">=16.0.0"
507 | },
508 | "peerDependencies": {
509 | "@aws-sdk/client-sts": "^3.709.0"
510 | }
511 | },
512 | "node_modules/@aws-sdk/middleware-host-header": {
513 | "version": "3.709.0",
514 | "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.709.0.tgz",
515 | "integrity": "sha512-8gQYCYAaIw4lOCd5WYdf15Y/61MgRsAnrb2eiTl+icMlUOOzl8aOl5iDwm/Idp0oHZTflwxM4XSvGXO83PRWcw==",
516 | "license": "Apache-2.0",
517 | "dependencies": {
518 | "@aws-sdk/types": "3.709.0",
519 | "@smithy/protocol-http": "^4.1.8",
520 | "@smithy/types": "^3.7.2",
521 | "tslib": "^2.6.2"
522 | },
523 | "engines": {
524 | "node": ">=16.0.0"
525 | }
526 | },
527 | "node_modules/@aws-sdk/middleware-logger": {
528 | "version": "3.709.0",
529 | "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.709.0.tgz",
530 | "integrity": "sha512-jDoGSccXv9zebnpUoisjWd5u5ZPIalrmm6TjvPzZ8UqzQt3Beiz0tnQwmxQD6KRc7ADweWP5Ntiqzbw9xpVajg==",
531 | "license": "Apache-2.0",
532 | "dependencies": {
533 | "@aws-sdk/types": "3.709.0",
534 | "@smithy/types": "^3.7.2",
535 | "tslib": "^2.6.2"
536 | },
537 | "engines": {
538 | "node": ">=16.0.0"
539 | }
540 | },
541 | "node_modules/@aws-sdk/middleware-recursion-detection": {
542 | "version": "3.709.0",
543 | "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.709.0.tgz",
544 | "integrity": "sha512-PObL/wLr4lkfbQ0yXUWaoCWu/jcwfwZzCjsUiXW/H6hW9b/00enZxmx7OhtJYaR6xmh/Lcx5wbhIoDCbzdv0tw==",
545 | "license": "Apache-2.0",
546 | "dependencies": {
547 | "@aws-sdk/types": "3.709.0",
548 | "@smithy/protocol-http": "^4.1.8",
549 | "@smithy/types": "^3.7.2",
550 | "tslib": "^2.6.2"
551 | },
552 | "engines": {
553 | "node": ">=16.0.0"
554 | }
555 | },
556 | "node_modules/@aws-sdk/middleware-user-agent": {
557 | "version": "3.709.0",
558 | "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.709.0.tgz",
559 | "integrity": "sha512-ooc9ZJvgkjPhi9q05XwSfNTXkEBEIfL4hleo5rQBKwHG3aTHvwOM7LLzhdX56QZVa6sorPBp6fwULuRDSqiQHw==",
560 | "license": "Apache-2.0",
561 | "dependencies": {
562 | "@aws-sdk/core": "3.709.0",
563 | "@aws-sdk/types": "3.709.0",
564 | "@aws-sdk/util-endpoints": "3.709.0",
565 | "@smithy/core": "^2.5.5",
566 | "@smithy/protocol-http": "^4.1.8",
567 | "@smithy/types": "^3.7.2",
568 | "tslib": "^2.6.2"
569 | },
570 | "engines": {
571 | "node": ">=16.0.0"
572 | }
573 | },
574 | "node_modules/@aws-sdk/region-config-resolver": {
575 | "version": "3.709.0",
576 | "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.709.0.tgz",
577 | "integrity": "sha512-/NoCAMEVKAg3kBKOrNtgOfL+ECt6nrl+L7q2SyYmrcY4tVCmwuECVqewQaHc03fTnJijfKLccw0Fj+6wOCnB6w==",
578 | "license": "Apache-2.0",
579 | "dependencies": {
580 | "@aws-sdk/types": "3.709.0",
581 | "@smithy/node-config-provider": "^3.1.12",
582 | "@smithy/types": "^3.7.2",
583 | "@smithy/util-config-provider": "^3.0.0",
584 | "@smithy/util-middleware": "^3.0.11",
585 | "tslib": "^2.6.2"
586 | },
587 | "engines": {
588 | "node": ">=16.0.0"
589 | }
590 | },
591 | "node_modules/@aws-sdk/token-providers": {
592 | "version": "3.709.0",
593 | "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.709.0.tgz",
594 | "integrity": "sha512-q5Ar6k71nci43IbULFgC8a89d/3EHpmd7HvBzqVGRcHnoPwh8eZDBfbBXKH83NGwcS1qPSRYiDbVfeWPm4/1jA==",
595 | "license": "Apache-2.0",
596 | "dependencies": {
597 | "@aws-sdk/types": "3.709.0",
598 | "@smithy/property-provider": "^3.1.11",
599 | "@smithy/shared-ini-file-loader": "^3.1.12",
600 | "@smithy/types": "^3.7.2",
601 | "tslib": "^2.6.2"
602 | },
603 | "engines": {
604 | "node": ">=16.0.0"
605 | },
606 | "peerDependencies": {
607 | "@aws-sdk/client-sso-oidc": "^3.709.0"
608 | }
609 | },
610 | "node_modules/@aws-sdk/types": {
611 | "version": "3.709.0",
612 | "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.709.0.tgz",
613 | "integrity": "sha512-ArtLTMxgjf13Kfu3gWH3Ez9Q5TkDdcRZUofpKH3pMGB/C6KAbeSCtIIDKfoRTUABzyGlPyCrZdnFjKyH+ypIpg==",
614 | "license": "Apache-2.0",
615 | "dependencies": {
616 | "@smithy/types": "^3.7.2",
617 | "tslib": "^2.6.2"
618 | },
619 | "engines": {
620 | "node": ">=16.0.0"
621 | }
622 | },
623 | "node_modules/@aws-sdk/util-endpoints": {
624 | "version": "3.709.0",
625 | "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.709.0.tgz",
626 | "integrity": "sha512-Mbc7AtL5WGCTKC16IGeUTz+sjpC3ptBda2t0CcK0kMVw3THDdcSq6ZlNKO747cNqdbwUvW34oHteUiHv4/z88Q==",
627 | "license": "Apache-2.0",
628 | "dependencies": {
629 | "@aws-sdk/types": "3.709.0",
630 | "@smithy/types": "^3.7.2",
631 | "@smithy/util-endpoints": "^2.1.7",
632 | "tslib": "^2.6.2"
633 | },
634 | "engines": {
635 | "node": ">=16.0.0"
636 | }
637 | },
638 | "node_modules/@aws-sdk/util-locate-window": {
639 | "version": "3.693.0",
640 | "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.693.0.tgz",
641 | "integrity": "sha512-ttrag6haJLWABhLqtg1Uf+4LgHWIMOVSYL+VYZmAp2v4PUGOwWmWQH0Zk8RM7YuQcLfH/EoR72/Yxz6A4FKcuw==",
642 | "license": "Apache-2.0",
643 | "dependencies": {
644 | "tslib": "^2.6.2"
645 | },
646 | "engines": {
647 | "node": ">=16.0.0"
648 | }
649 | },
650 | "node_modules/@aws-sdk/util-user-agent-browser": {
651 | "version": "3.709.0",
652 | "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.709.0.tgz",
653 | "integrity": "sha512-/rL2GasJzdTWUURCQKFldw2wqBtY4k4kCiA2tVZSKg3y4Ey7zO34SW8ebaeCE2/xoWOyLR2/etdKyphoo4Zrtg==",
654 | "license": "Apache-2.0",
655 | "dependencies": {
656 | "@aws-sdk/types": "3.709.0",
657 | "@smithy/types": "^3.7.2",
658 | "bowser": "^2.11.0",
659 | "tslib": "^2.6.2"
660 | }
661 | },
662 | "node_modules/@aws-sdk/util-user-agent-node": {
663 | "version": "3.709.0",
664 | "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.709.0.tgz",
665 | "integrity": "sha512-trBfzSCVWy7ILgqhEXgiuM7hfRCw4F4a8IK90tjk9YL0jgoJ6eJuOp7+DfCtHJaygoBxD3cdMFkOu+lluFmGBA==",
666 | "license": "Apache-2.0",
667 | "dependencies": {
668 | "@aws-sdk/middleware-user-agent": "3.709.0",
669 | "@aws-sdk/types": "3.709.0",
670 | "@smithy/node-config-provider": "^3.1.12",
671 | "@smithy/types": "^3.7.2",
672 | "tslib": "^2.6.2"
673 | },
674 | "engines": {
675 | "node": ">=16.0.0"
676 | },
677 | "peerDependencies": {
678 | "aws-crt": ">=1.0.0"
679 | },
680 | "peerDependenciesMeta": {
681 | "aws-crt": {
682 | "optional": true
683 | }
684 | }
685 | },
686 | "node_modules/@httptoolkit/websocket-stream": {
687 | "version": "6.0.1",
688 | "resolved": "https://registry.npmjs.org/@httptoolkit/websocket-stream/-/websocket-stream-6.0.1.tgz",
689 | "integrity": "sha512-A0NOZI+Glp3Xgcz6Na7i7o09+/+xm2m0UCU8gdtM2nIv6/cjLmhMZMqehSpTlgbx9omtLmV8LVqOskPEyWnmZQ==",
690 | "license": "BSD-2-Clause",
691 | "dependencies": {
692 | "@types/ws": "*",
693 | "duplexify": "^3.5.1",
694 | "inherits": "^2.0.1",
695 | "isomorphic-ws": "^4.0.1",
696 | "readable-stream": "^2.3.3",
697 | "safe-buffer": "^5.1.2",
698 | "ws": "*",
699 | "xtend": "^4.0.0"
700 | }
701 | },
702 | "node_modules/@httptoolkit/websocket-stream/node_modules/duplexify": {
703 | "version": "3.7.1",
704 | "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
705 | "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==",
706 | "license": "MIT",
707 | "dependencies": {
708 | "end-of-stream": "^1.0.0",
709 | "inherits": "^2.0.1",
710 | "readable-stream": "^2.0.0",
711 | "stream-shift": "^1.0.0"
712 | }
713 | },
714 | "node_modules/@httptoolkit/websocket-stream/node_modules/readable-stream": {
715 | "version": "2.3.8",
716 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
717 | "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
718 | "license": "MIT",
719 | "dependencies": {
720 | "core-util-is": "~1.0.0",
721 | "inherits": "~2.0.3",
722 | "isarray": "~1.0.0",
723 | "process-nextick-args": "~2.0.0",
724 | "safe-buffer": "~5.1.1",
725 | "string_decoder": "~1.1.1",
726 | "util-deprecate": "~1.0.1"
727 | }
728 | },
729 | "node_modules/@httptoolkit/websocket-stream/node_modules/safe-buffer": {
730 | "version": "5.1.2",
731 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
732 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
733 | "license": "MIT"
734 | },
735 | "node_modules/@httptoolkit/websocket-stream/node_modules/string_decoder": {
736 | "version": "1.1.1",
737 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
738 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
739 | "license": "MIT",
740 | "dependencies": {
741 | "safe-buffer": "~5.1.0"
742 | }
743 | },
744 | "node_modules/@smithy/abort-controller": {
745 | "version": "3.1.9",
746 | "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.9.tgz",
747 | "integrity": "sha512-yiW0WI30zj8ZKoSYNx90no7ugVn3khlyH/z5W8qtKBtVE6awRALbhSG+2SAHA1r6bO/6M9utxYKVZ3PCJ1rWxw==",
748 | "license": "Apache-2.0",
749 | "dependencies": {
750 | "@smithy/types": "^3.7.2",
751 | "tslib": "^2.6.2"
752 | },
753 | "engines": {
754 | "node": ">=16.0.0"
755 | }
756 | },
757 | "node_modules/@smithy/config-resolver": {
758 | "version": "3.0.13",
759 | "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.13.tgz",
760 | "integrity": "sha512-Gr/qwzyPaTL1tZcq8WQyHhTZREER5R1Wytmz4WnVGL4onA3dNk6Btll55c8Vr58pLdvWZmtG8oZxJTw3t3q7Jg==",
761 | "license": "Apache-2.0",
762 | "dependencies": {
763 | "@smithy/node-config-provider": "^3.1.12",
764 | "@smithy/types": "^3.7.2",
765 | "@smithy/util-config-provider": "^3.0.0",
766 | "@smithy/util-middleware": "^3.0.11",
767 | "tslib": "^2.6.2"
768 | },
769 | "engines": {
770 | "node": ">=16.0.0"
771 | }
772 | },
773 | "node_modules/@smithy/core": {
774 | "version": "2.5.5",
775 | "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.5.5.tgz",
776 | "integrity": "sha512-G8G/sDDhXA7o0bOvkc7bgai6POuSld/+XhNnWAbpQTpLv2OZPvyqQ58tLPPlz0bSNsXktldDDREIv1LczFeNEw==",
777 | "license": "Apache-2.0",
778 | "dependencies": {
779 | "@smithy/middleware-serde": "^3.0.11",
780 | "@smithy/protocol-http": "^4.1.8",
781 | "@smithy/types": "^3.7.2",
782 | "@smithy/util-body-length-browser": "^3.0.0",
783 | "@smithy/util-middleware": "^3.0.11",
784 | "@smithy/util-stream": "^3.3.2",
785 | "@smithy/util-utf8": "^3.0.0",
786 | "tslib": "^2.6.2"
787 | },
788 | "engines": {
789 | "node": ">=16.0.0"
790 | }
791 | },
792 | "node_modules/@smithy/credential-provider-imds": {
793 | "version": "3.2.8",
794 | "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.8.tgz",
795 | "integrity": "sha512-ZCY2yD0BY+K9iMXkkbnjo+08T2h8/34oHd0Jmh6BZUSZwaaGlGCyBT/3wnS7u7Xl33/EEfN4B6nQr3Gx5bYxgw==",
796 | "license": "Apache-2.0",
797 | "dependencies": {
798 | "@smithy/node-config-provider": "^3.1.12",
799 | "@smithy/property-provider": "^3.1.11",
800 | "@smithy/types": "^3.7.2",
801 | "@smithy/url-parser": "^3.0.11",
802 | "tslib": "^2.6.2"
803 | },
804 | "engines": {
805 | "node": ">=16.0.0"
806 | }
807 | },
808 | "node_modules/@smithy/fetch-http-handler": {
809 | "version": "4.1.2",
810 | "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-4.1.2.tgz",
811 | "integrity": "sha512-R7rU7Ae3ItU4rC0c5mB2sP5mJNbCfoDc8I5XlYjIZnquyUwec7fEo78F6DA3SmgJgkU1qTMcZJuGblxZsl10ZA==",
812 | "license": "Apache-2.0",
813 | "dependencies": {
814 | "@smithy/protocol-http": "^4.1.8",
815 | "@smithy/querystring-builder": "^3.0.11",
816 | "@smithy/types": "^3.7.2",
817 | "@smithy/util-base64": "^3.0.0",
818 | "tslib": "^2.6.2"
819 | }
820 | },
821 | "node_modules/@smithy/hash-node": {
822 | "version": "3.0.11",
823 | "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.11.tgz",
824 | "integrity": "sha512-emP23rwYyZhQBvklqTtwetkQlqbNYirDiEEwXl2v0GYWMnCzxst7ZaRAnWuy28njp5kAH54lvkdG37MblZzaHA==",
825 | "license": "Apache-2.0",
826 | "dependencies": {
827 | "@smithy/types": "^3.7.2",
828 | "@smithy/util-buffer-from": "^3.0.0",
829 | "@smithy/util-utf8": "^3.0.0",
830 | "tslib": "^2.6.2"
831 | },
832 | "engines": {
833 | "node": ">=16.0.0"
834 | }
835 | },
836 | "node_modules/@smithy/invalid-dependency": {
837 | "version": "3.0.11",
838 | "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.11.tgz",
839 | "integrity": "sha512-NuQmVPEJjUX6c+UELyVz8kUx8Q539EDeNwbRyu4IIF8MeV7hUtq1FB3SHVyki2u++5XLMFqngeMKk7ccspnNyQ==",
840 | "license": "Apache-2.0",
841 | "dependencies": {
842 | "@smithy/types": "^3.7.2",
843 | "tslib": "^2.6.2"
844 | }
845 | },
846 | "node_modules/@smithy/is-array-buffer": {
847 | "version": "3.0.0",
848 | "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz",
849 | "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==",
850 | "license": "Apache-2.0",
851 | "dependencies": {
852 | "tslib": "^2.6.2"
853 | },
854 | "engines": {
855 | "node": ">=16.0.0"
856 | }
857 | },
858 | "node_modules/@smithy/middleware-content-length": {
859 | "version": "3.0.13",
860 | "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.13.tgz",
861 | "integrity": "sha512-zfMhzojhFpIX3P5ug7jxTjfUcIPcGjcQYzB9t+rv0g1TX7B0QdwONW+ATouaLoD7h7LOw/ZlXfkq4xJ/g2TrIw==",
862 | "license": "Apache-2.0",
863 | "dependencies": {
864 | "@smithy/protocol-http": "^4.1.8",
865 | "@smithy/types": "^3.7.2",
866 | "tslib": "^2.6.2"
867 | },
868 | "engines": {
869 | "node": ">=16.0.0"
870 | }
871 | },
872 | "node_modules/@smithy/middleware-endpoint": {
873 | "version": "3.2.5",
874 | "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.2.5.tgz",
875 | "integrity": "sha512-VhJNs/s/lyx4weiZdXSloBgoLoS8osV0dKIain8nGmx7of3QFKu5BSdEuk1z/U8x9iwes1i+XCiNusEvuK1ijg==",
876 | "license": "Apache-2.0",
877 | "dependencies": {
878 | "@smithy/core": "^2.5.5",
879 | "@smithy/middleware-serde": "^3.0.11",
880 | "@smithy/node-config-provider": "^3.1.12",
881 | "@smithy/shared-ini-file-loader": "^3.1.12",
882 | "@smithy/types": "^3.7.2",
883 | "@smithy/url-parser": "^3.0.11",
884 | "@smithy/util-middleware": "^3.0.11",
885 | "tslib": "^2.6.2"
886 | },
887 | "engines": {
888 | "node": ">=16.0.0"
889 | }
890 | },
891 | "node_modules/@smithy/middleware-retry": {
892 | "version": "3.0.30",
893 | "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.30.tgz",
894 | "integrity": "sha512-6323RL2BvAR3VQpTjHpa52kH/iSHyxd/G9ohb2MkBk2Ucu+oMtRXT8yi7KTSIS9nb58aupG6nO0OlXnQOAcvmQ==",
895 | "license": "Apache-2.0",
896 | "dependencies": {
897 | "@smithy/node-config-provider": "^3.1.12",
898 | "@smithy/protocol-http": "^4.1.8",
899 | "@smithy/service-error-classification": "^3.0.11",
900 | "@smithy/smithy-client": "^3.5.0",
901 | "@smithy/types": "^3.7.2",
902 | "@smithy/util-middleware": "^3.0.11",
903 | "@smithy/util-retry": "^3.0.11",
904 | "tslib": "^2.6.2",
905 | "uuid": "^9.0.1"
906 | },
907 | "engines": {
908 | "node": ">=16.0.0"
909 | }
910 | },
911 | "node_modules/@smithy/middleware-serde": {
912 | "version": "3.0.11",
913 | "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.11.tgz",
914 | "integrity": "sha512-KzPAeySp/fOoQA82TpnwItvX8BBURecpx6ZMu75EZDkAcnPtO6vf7q4aH5QHs/F1s3/snQaSFbbUMcFFZ086Mw==",
915 | "license": "Apache-2.0",
916 | "dependencies": {
917 | "@smithy/types": "^3.7.2",
918 | "tslib": "^2.6.2"
919 | },
920 | "engines": {
921 | "node": ">=16.0.0"
922 | }
923 | },
924 | "node_modules/@smithy/middleware-stack": {
925 | "version": "3.0.11",
926 | "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.11.tgz",
927 | "integrity": "sha512-1HGo9a6/ikgOMrTrWL/WiN9N8GSVYpuRQO5kjstAq4CvV59bjqnh7TbdXGQ4vxLD3xlSjfBjq5t1SOELePsLnA==",
928 | "license": "Apache-2.0",
929 | "dependencies": {
930 | "@smithy/types": "^3.7.2",
931 | "tslib": "^2.6.2"
932 | },
933 | "engines": {
934 | "node": ">=16.0.0"
935 | }
936 | },
937 | "node_modules/@smithy/node-config-provider": {
938 | "version": "3.1.12",
939 | "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.12.tgz",
940 | "integrity": "sha512-O9LVEu5J/u/FuNlZs+L7Ikn3lz7VB9hb0GtPT9MQeiBmtK8RSY3ULmsZgXhe6VAlgTw0YO+paQx4p8xdbs43vQ==",
941 | "license": "Apache-2.0",
942 | "dependencies": {
943 | "@smithy/property-provider": "^3.1.11",
944 | "@smithy/shared-ini-file-loader": "^3.1.12",
945 | "@smithy/types": "^3.7.2",
946 | "tslib": "^2.6.2"
947 | },
948 | "engines": {
949 | "node": ">=16.0.0"
950 | }
951 | },
952 | "node_modules/@smithy/node-http-handler": {
953 | "version": "3.3.2",
954 | "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.3.2.tgz",
955 | "integrity": "sha512-t4ng1DAd527vlxvOfKFYEe6/QFBcsj7WpNlWTyjorwXXcKw3XlltBGbyHfSJ24QT84nF+agDha9tNYpzmSRZPA==",
956 | "license": "Apache-2.0",
957 | "dependencies": {
958 | "@smithy/abort-controller": "^3.1.9",
959 | "@smithy/protocol-http": "^4.1.8",
960 | "@smithy/querystring-builder": "^3.0.11",
961 | "@smithy/types": "^3.7.2",
962 | "tslib": "^2.6.2"
963 | },
964 | "engines": {
965 | "node": ">=16.0.0"
966 | }
967 | },
968 | "node_modules/@smithy/property-provider": {
969 | "version": "3.1.11",
970 | "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.11.tgz",
971 | "integrity": "sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==",
972 | "license": "Apache-2.0",
973 | "dependencies": {
974 | "@smithy/types": "^3.7.2",
975 | "tslib": "^2.6.2"
976 | },
977 | "engines": {
978 | "node": ">=16.0.0"
979 | }
980 | },
981 | "node_modules/@smithy/protocol-http": {
982 | "version": "4.1.8",
983 | "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.8.tgz",
984 | "integrity": "sha512-hmgIAVyxw1LySOwkgMIUN0kjN8TG9Nc85LJeEmEE/cNEe2rkHDUWhnJf2gxcSRFLWsyqWsrZGw40ROjUogg+Iw==",
985 | "license": "Apache-2.0",
986 | "dependencies": {
987 | "@smithy/types": "^3.7.2",
988 | "tslib": "^2.6.2"
989 | },
990 | "engines": {
991 | "node": ">=16.0.0"
992 | }
993 | },
994 | "node_modules/@smithy/querystring-builder": {
995 | "version": "3.0.11",
996 | "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.11.tgz",
997 | "integrity": "sha512-u+5HV/9uJaeLj5XTb6+IEF/dokWWkEqJ0XiaRRogyREmKGUgZnNecLucADLdauWFKUNbQfulHFEZEdjwEBjXRg==",
998 | "license": "Apache-2.0",
999 | "dependencies": {
1000 | "@smithy/types": "^3.7.2",
1001 | "@smithy/util-uri-escape": "^3.0.0",
1002 | "tslib": "^2.6.2"
1003 | },
1004 | "engines": {
1005 | "node": ">=16.0.0"
1006 | }
1007 | },
1008 | "node_modules/@smithy/querystring-parser": {
1009 | "version": "3.0.11",
1010 | "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.11.tgz",
1011 | "integrity": "sha512-Je3kFvCsFMnso1ilPwA7GtlbPaTixa3WwC+K21kmMZHsBEOZYQaqxcMqeFFoU7/slFjKDIpiiPydvdJm8Q/MCw==",
1012 | "license": "Apache-2.0",
1013 | "dependencies": {
1014 | "@smithy/types": "^3.7.2",
1015 | "tslib": "^2.6.2"
1016 | },
1017 | "engines": {
1018 | "node": ">=16.0.0"
1019 | }
1020 | },
1021 | "node_modules/@smithy/service-error-classification": {
1022 | "version": "3.0.11",
1023 | "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.11.tgz",
1024 | "integrity": "sha512-QnYDPkyewrJzCyaeI2Rmp7pDwbUETe+hU8ADkXmgNusO1bgHBH7ovXJiYmba8t0fNfJx75fE8dlM6SEmZxheog==",
1025 | "license": "Apache-2.0",
1026 | "dependencies": {
1027 | "@smithy/types": "^3.7.2"
1028 | },
1029 | "engines": {
1030 | "node": ">=16.0.0"
1031 | }
1032 | },
1033 | "node_modules/@smithy/shared-ini-file-loader": {
1034 | "version": "3.1.12",
1035 | "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.12.tgz",
1036 | "integrity": "sha512-1xKSGI+U9KKdbG2qDvIR9dGrw3CNx+baqJfyr0igKEpjbHL5stsqAesYBzHChYHlelWtb87VnLWlhvfCz13H8Q==",
1037 | "license": "Apache-2.0",
1038 | "dependencies": {
1039 | "@smithy/types": "^3.7.2",
1040 | "tslib": "^2.6.2"
1041 | },
1042 | "engines": {
1043 | "node": ">=16.0.0"
1044 | }
1045 | },
1046 | "node_modules/@smithy/signature-v4": {
1047 | "version": "4.2.4",
1048 | "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.2.4.tgz",
1049 | "integrity": "sha512-5JWeMQYg81TgU4cG+OexAWdvDTs5JDdbEZx+Qr1iPbvo91QFGzjy0IkXAKaXUHqmKUJgSHK0ZxnCkgZpzkeNTA==",
1050 | "license": "Apache-2.0",
1051 | "dependencies": {
1052 | "@smithy/is-array-buffer": "^3.0.0",
1053 | "@smithy/protocol-http": "^4.1.8",
1054 | "@smithy/types": "^3.7.2",
1055 | "@smithy/util-hex-encoding": "^3.0.0",
1056 | "@smithy/util-middleware": "^3.0.11",
1057 | "@smithy/util-uri-escape": "^3.0.0",
1058 | "@smithy/util-utf8": "^3.0.0",
1059 | "tslib": "^2.6.2"
1060 | },
1061 | "engines": {
1062 | "node": ">=16.0.0"
1063 | }
1064 | },
1065 | "node_modules/@smithy/smithy-client": {
1066 | "version": "3.5.0",
1067 | "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.5.0.tgz",
1068 | "integrity": "sha512-Y8FeOa7gbDfCWf7njrkoRATPa5eNLUEjlJS5z5rXatYuGkCb80LbHcu8AQR8qgAZZaNHCLyo2N+pxPsV7l+ivg==",
1069 | "license": "Apache-2.0",
1070 | "dependencies": {
1071 | "@smithy/core": "^2.5.5",
1072 | "@smithy/middleware-endpoint": "^3.2.5",
1073 | "@smithy/middleware-stack": "^3.0.11",
1074 | "@smithy/protocol-http": "^4.1.8",
1075 | "@smithy/types": "^3.7.2",
1076 | "@smithy/util-stream": "^3.3.2",
1077 | "tslib": "^2.6.2"
1078 | },
1079 | "engines": {
1080 | "node": ">=16.0.0"
1081 | }
1082 | },
1083 | "node_modules/@smithy/types": {
1084 | "version": "3.7.2",
1085 | "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.7.2.tgz",
1086 | "integrity": "sha512-bNwBYYmN8Eh9RyjS1p2gW6MIhSO2rl7X9QeLM8iTdcGRP+eDiIWDt66c9IysCc22gefKszZv+ubV9qZc7hdESg==",
1087 | "license": "Apache-2.0",
1088 | "dependencies": {
1089 | "tslib": "^2.6.2"
1090 | },
1091 | "engines": {
1092 | "node": ">=16.0.0"
1093 | }
1094 | },
1095 | "node_modules/@smithy/url-parser": {
1096 | "version": "3.0.11",
1097 | "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.11.tgz",
1098 | "integrity": "sha512-TmlqXkSk8ZPhfc+SQutjmFr5FjC0av3GZP4B/10caK1SbRwe/v+Wzu/R6xEKxoNqL+8nY18s1byiy6HqPG37Aw==",
1099 | "license": "Apache-2.0",
1100 | "dependencies": {
1101 | "@smithy/querystring-parser": "^3.0.11",
1102 | "@smithy/types": "^3.7.2",
1103 | "tslib": "^2.6.2"
1104 | }
1105 | },
1106 | "node_modules/@smithy/util-base64": {
1107 | "version": "3.0.0",
1108 | "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz",
1109 | "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==",
1110 | "license": "Apache-2.0",
1111 | "dependencies": {
1112 | "@smithy/util-buffer-from": "^3.0.0",
1113 | "@smithy/util-utf8": "^3.0.0",
1114 | "tslib": "^2.6.2"
1115 | },
1116 | "engines": {
1117 | "node": ">=16.0.0"
1118 | }
1119 | },
1120 | "node_modules/@smithy/util-body-length-browser": {
1121 | "version": "3.0.0",
1122 | "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz",
1123 | "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==",
1124 | "license": "Apache-2.0",
1125 | "dependencies": {
1126 | "tslib": "^2.6.2"
1127 | }
1128 | },
1129 | "node_modules/@smithy/util-body-length-node": {
1130 | "version": "3.0.0",
1131 | "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz",
1132 | "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==",
1133 | "license": "Apache-2.0",
1134 | "dependencies": {
1135 | "tslib": "^2.6.2"
1136 | },
1137 | "engines": {
1138 | "node": ">=16.0.0"
1139 | }
1140 | },
1141 | "node_modules/@smithy/util-buffer-from": {
1142 | "version": "3.0.0",
1143 | "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz",
1144 | "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==",
1145 | "license": "Apache-2.0",
1146 | "dependencies": {
1147 | "@smithy/is-array-buffer": "^3.0.0",
1148 | "tslib": "^2.6.2"
1149 | },
1150 | "engines": {
1151 | "node": ">=16.0.0"
1152 | }
1153 | },
1154 | "node_modules/@smithy/util-config-provider": {
1155 | "version": "3.0.0",
1156 | "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz",
1157 | "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==",
1158 | "license": "Apache-2.0",
1159 | "dependencies": {
1160 | "tslib": "^2.6.2"
1161 | },
1162 | "engines": {
1163 | "node": ">=16.0.0"
1164 | }
1165 | },
1166 | "node_modules/@smithy/util-defaults-mode-browser": {
1167 | "version": "3.0.30",
1168 | "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.30.tgz",
1169 | "integrity": "sha512-nLuGmgfcr0gzm64pqF2UT4SGWVG8UGviAdayDlVzJPNa6Z4lqvpDzdRXmLxtOdEjVlTOEdpZ9dd3ZMMu488mzg==",
1170 | "license": "Apache-2.0",
1171 | "dependencies": {
1172 | "@smithy/property-provider": "^3.1.11",
1173 | "@smithy/smithy-client": "^3.5.0",
1174 | "@smithy/types": "^3.7.2",
1175 | "bowser": "^2.11.0",
1176 | "tslib": "^2.6.2"
1177 | },
1178 | "engines": {
1179 | "node": ">= 10.0.0"
1180 | }
1181 | },
1182 | "node_modules/@smithy/util-defaults-mode-node": {
1183 | "version": "3.0.30",
1184 | "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.30.tgz",
1185 | "integrity": "sha512-OD63eWoH68vp75mYcfYyuVH+p7Li/mY4sYOROnauDrtObo1cS4uWfsy/zhOTW8F8ZPxQC1ZXZKVxoxvMGUv2Ow==",
1186 | "license": "Apache-2.0",
1187 | "dependencies": {
1188 | "@smithy/config-resolver": "^3.0.13",
1189 | "@smithy/credential-provider-imds": "^3.2.8",
1190 | "@smithy/node-config-provider": "^3.1.12",
1191 | "@smithy/property-provider": "^3.1.11",
1192 | "@smithy/smithy-client": "^3.5.0",
1193 | "@smithy/types": "^3.7.2",
1194 | "tslib": "^2.6.2"
1195 | },
1196 | "engines": {
1197 | "node": ">= 10.0.0"
1198 | }
1199 | },
1200 | "node_modules/@smithy/util-endpoints": {
1201 | "version": "2.1.7",
1202 | "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.1.7.tgz",
1203 | "integrity": "sha512-tSfcqKcN/Oo2STEYCABVuKgJ76nyyr6skGl9t15hs+YaiU06sgMkN7QYjo0BbVw+KT26zok3IzbdSOksQ4YzVw==",
1204 | "license": "Apache-2.0",
1205 | "dependencies": {
1206 | "@smithy/node-config-provider": "^3.1.12",
1207 | "@smithy/types": "^3.7.2",
1208 | "tslib": "^2.6.2"
1209 | },
1210 | "engines": {
1211 | "node": ">=16.0.0"
1212 | }
1213 | },
1214 | "node_modules/@smithy/util-hex-encoding": {
1215 | "version": "3.0.0",
1216 | "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz",
1217 | "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==",
1218 | "license": "Apache-2.0",
1219 | "dependencies": {
1220 | "tslib": "^2.6.2"
1221 | },
1222 | "engines": {
1223 | "node": ">=16.0.0"
1224 | }
1225 | },
1226 | "node_modules/@smithy/util-middleware": {
1227 | "version": "3.0.11",
1228 | "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.11.tgz",
1229 | "integrity": "sha512-dWpyc1e1R6VoXrwLoLDd57U1z6CwNSdkM69Ie4+6uYh2GC7Vg51Qtan7ITzczuVpqezdDTKJGJB95fFvvjU/ow==",
1230 | "license": "Apache-2.0",
1231 | "dependencies": {
1232 | "@smithy/types": "^3.7.2",
1233 | "tslib": "^2.6.2"
1234 | },
1235 | "engines": {
1236 | "node": ">=16.0.0"
1237 | }
1238 | },
1239 | "node_modules/@smithy/util-retry": {
1240 | "version": "3.0.11",
1241 | "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.11.tgz",
1242 | "integrity": "sha512-hJUC6W7A3DQgaee3Hp9ZFcOxVDZzmBIRBPlUAk8/fSOEl7pE/aX7Dci0JycNOnm9Mfr0KV2XjIlUOcGWXQUdVQ==",
1243 | "license": "Apache-2.0",
1244 | "dependencies": {
1245 | "@smithy/service-error-classification": "^3.0.11",
1246 | "@smithy/types": "^3.7.2",
1247 | "tslib": "^2.6.2"
1248 | },
1249 | "engines": {
1250 | "node": ">=16.0.0"
1251 | }
1252 | },
1253 | "node_modules/@smithy/util-stream": {
1254 | "version": "3.3.2",
1255 | "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.3.2.tgz",
1256 | "integrity": "sha512-sInAqdiVeisUGYAv/FrXpmJ0b4WTFmciTRqzhb7wVuem9BHvhIG7tpiYHLDWrl2stOokNZpTTGqz3mzB2qFwXg==",
1257 | "license": "Apache-2.0",
1258 | "dependencies": {
1259 | "@smithy/fetch-http-handler": "^4.1.2",
1260 | "@smithy/node-http-handler": "^3.3.2",
1261 | "@smithy/types": "^3.7.2",
1262 | "@smithy/util-base64": "^3.0.0",
1263 | "@smithy/util-buffer-from": "^3.0.0",
1264 | "@smithy/util-hex-encoding": "^3.0.0",
1265 | "@smithy/util-utf8": "^3.0.0",
1266 | "tslib": "^2.6.2"
1267 | },
1268 | "engines": {
1269 | "node": ">=16.0.0"
1270 | }
1271 | },
1272 | "node_modules/@smithy/util-uri-escape": {
1273 | "version": "3.0.0",
1274 | "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz",
1275 | "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==",
1276 | "license": "Apache-2.0",
1277 | "dependencies": {
1278 | "tslib": "^2.6.2"
1279 | },
1280 | "engines": {
1281 | "node": ">=16.0.0"
1282 | }
1283 | },
1284 | "node_modules/@smithy/util-utf8": {
1285 | "version": "3.0.0",
1286 | "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz",
1287 | "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==",
1288 | "license": "Apache-2.0",
1289 | "dependencies": {
1290 | "@smithy/util-buffer-from": "^3.0.0",
1291 | "tslib": "^2.6.2"
1292 | },
1293 | "engines": {
1294 | "node": ">=16.0.0"
1295 | }
1296 | },
1297 | "node_modules/@types/node": {
1298 | "version": "22.10.2",
1299 | "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz",
1300 | "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==",
1301 | "license": "MIT",
1302 | "dependencies": {
1303 | "undici-types": "~6.20.0"
1304 | }
1305 | },
1306 | "node_modules/@types/uuid": {
1307 | "version": "9.0.8",
1308 | "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz",
1309 | "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==",
1310 | "license": "MIT"
1311 | },
1312 | "node_modules/@types/ws": {
1313 | "version": "8.5.13",
1314 | "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz",
1315 | "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==",
1316 | "license": "MIT",
1317 | "dependencies": {
1318 | "@types/node": "*"
1319 | }
1320 | },
1321 | "node_modules/argparse": {
1322 | "version": "2.0.1",
1323 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
1324 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
1325 | },
1326 | "node_modules/aws-iot-device-sdk": {
1327 | "version": "2.2.15",
1328 | "resolved": "https://registry.npmjs.org/aws-iot-device-sdk/-/aws-iot-device-sdk-2.2.15.tgz",
1329 | "integrity": "sha512-JEnLUx288ttfuwy+ZJA/g9vFG+M3Mucyo1LXypWC8cNV1D8hGvAxeqHygs9TiinvjUazM7gcXwSA+s3E+tbx/g==",
1330 | "license": "Apache-2.0",
1331 | "dependencies": {
1332 | "@httptoolkit/websocket-stream": "^6.0.1",
1333 | "crypto-js": "4.2.0",
1334 | "minimist": "1.2.6",
1335 | "mqtt": "4.2.8"
1336 | },
1337 | "engines": {
1338 | "node": ">=8.17.0"
1339 | }
1340 | },
1341 | "node_modules/balanced-match": {
1342 | "version": "1.0.2",
1343 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
1344 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
1345 | },
1346 | "node_modules/base64-js": {
1347 | "version": "1.5.1",
1348 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
1349 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
1350 | "funding": [
1351 | {
1352 | "type": "github",
1353 | "url": "https://github.com/sponsors/feross"
1354 | },
1355 | {
1356 | "type": "patreon",
1357 | "url": "https://www.patreon.com/feross"
1358 | },
1359 | {
1360 | "type": "consulting",
1361 | "url": "https://feross.org/support"
1362 | }
1363 | ]
1364 | },
1365 | "node_modules/bl": {
1366 | "version": "4.1.0",
1367 | "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
1368 | "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
1369 | "dependencies": {
1370 | "buffer": "^5.5.0",
1371 | "inherits": "^2.0.4",
1372 | "readable-stream": "^3.4.0"
1373 | }
1374 | },
1375 | "node_modules/bowser": {
1376 | "version": "2.11.0",
1377 | "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz",
1378 | "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==",
1379 | "license": "MIT"
1380 | },
1381 | "node_modules/brace-expansion": {
1382 | "version": "1.1.11",
1383 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
1384 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
1385 | "dependencies": {
1386 | "balanced-match": "^1.0.0",
1387 | "concat-map": "0.0.1"
1388 | }
1389 | },
1390 | "node_modules/buffer": {
1391 | "version": "5.7.1",
1392 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
1393 | "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
1394 | "funding": [
1395 | {
1396 | "type": "github",
1397 | "url": "https://github.com/sponsors/feross"
1398 | },
1399 | {
1400 | "type": "patreon",
1401 | "url": "https://www.patreon.com/feross"
1402 | },
1403 | {
1404 | "type": "consulting",
1405 | "url": "https://feross.org/support"
1406 | }
1407 | ],
1408 | "dependencies": {
1409 | "base64-js": "^1.3.1",
1410 | "ieee754": "^1.1.13"
1411 | }
1412 | },
1413 | "node_modules/buffer-from": {
1414 | "version": "1.1.2",
1415 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
1416 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
1417 | },
1418 | "node_modules/commist": {
1419 | "version": "1.1.0",
1420 | "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz",
1421 | "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==",
1422 | "dependencies": {
1423 | "leven": "^2.1.0",
1424 | "minimist": "^1.1.0"
1425 | }
1426 | },
1427 | "node_modules/concat-map": {
1428 | "version": "0.0.1",
1429 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
1430 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
1431 | },
1432 | "node_modules/concat-stream": {
1433 | "version": "2.0.0",
1434 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
1435 | "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
1436 | "engines": [
1437 | "node >= 6.0"
1438 | ],
1439 | "dependencies": {
1440 | "buffer-from": "^1.0.0",
1441 | "inherits": "^2.0.3",
1442 | "readable-stream": "^3.0.2",
1443 | "typedarray": "^0.0.6"
1444 | }
1445 | },
1446 | "node_modules/core-util-is": {
1447 | "version": "1.0.3",
1448 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
1449 | "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
1450 | "license": "MIT"
1451 | },
1452 | "node_modules/crypto-js": {
1453 | "version": "4.2.0",
1454 | "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
1455 | "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
1456 | },
1457 | "node_modules/debug": {
1458 | "version": "4.3.4",
1459 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
1460 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
1461 | "dependencies": {
1462 | "ms": "2.1.2"
1463 | },
1464 | "engines": {
1465 | "node": ">=6.0"
1466 | },
1467 | "peerDependenciesMeta": {
1468 | "supports-color": {
1469 | "optional": true
1470 | }
1471 | }
1472 | },
1473 | "node_modules/duplexify": {
1474 | "version": "4.1.2",
1475 | "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz",
1476 | "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==",
1477 | "dependencies": {
1478 | "end-of-stream": "^1.4.1",
1479 | "inherits": "^2.0.3",
1480 | "readable-stream": "^3.1.1",
1481 | "stream-shift": "^1.0.0"
1482 | }
1483 | },
1484 | "node_modules/end-of-stream": {
1485 | "version": "1.4.4",
1486 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
1487 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
1488 | "dependencies": {
1489 | "once": "^1.4.0"
1490 | }
1491 | },
1492 | "node_modules/fast-xml-parser": {
1493 | "version": "4.4.1",
1494 | "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz",
1495 | "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==",
1496 | "funding": [
1497 | {
1498 | "type": "github",
1499 | "url": "https://github.com/sponsors/NaturalIntelligence"
1500 | },
1501 | {
1502 | "type": "paypal",
1503 | "url": "https://paypal.me/naturalintelligence"
1504 | }
1505 | ],
1506 | "license": "MIT",
1507 | "dependencies": {
1508 | "strnum": "^1.0.5"
1509 | },
1510 | "bin": {
1511 | "fxparser": "src/cli/cli.js"
1512 | }
1513 | },
1514 | "node_modules/fs.realpath": {
1515 | "version": "1.0.0",
1516 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
1517 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
1518 | },
1519 | "node_modules/glob": {
1520 | "version": "7.2.3",
1521 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
1522 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
1523 | "dependencies": {
1524 | "fs.realpath": "^1.0.0",
1525 | "inflight": "^1.0.4",
1526 | "inherits": "2",
1527 | "minimatch": "^3.1.1",
1528 | "once": "^1.3.0",
1529 | "path-is-absolute": "^1.0.0"
1530 | },
1531 | "engines": {
1532 | "node": "*"
1533 | },
1534 | "funding": {
1535 | "url": "https://github.com/sponsors/isaacs"
1536 | }
1537 | },
1538 | "node_modules/help-me": {
1539 | "version": "3.0.0",
1540 | "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz",
1541 | "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==",
1542 | "dependencies": {
1543 | "glob": "^7.1.6",
1544 | "readable-stream": "^3.6.0"
1545 | }
1546 | },
1547 | "node_modules/ieee754": {
1548 | "version": "1.2.1",
1549 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
1550 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
1551 | "funding": [
1552 | {
1553 | "type": "github",
1554 | "url": "https://github.com/sponsors/feross"
1555 | },
1556 | {
1557 | "type": "patreon",
1558 | "url": "https://www.patreon.com/feross"
1559 | },
1560 | {
1561 | "type": "consulting",
1562 | "url": "https://feross.org/support"
1563 | }
1564 | ]
1565 | },
1566 | "node_modules/inflight": {
1567 | "version": "1.0.6",
1568 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
1569 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
1570 | "dependencies": {
1571 | "once": "^1.3.0",
1572 | "wrappy": "1"
1573 | }
1574 | },
1575 | "node_modules/inherits": {
1576 | "version": "2.0.4",
1577 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
1578 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
1579 | },
1580 | "node_modules/isarray": {
1581 | "version": "1.0.0",
1582 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
1583 | "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
1584 | "license": "MIT"
1585 | },
1586 | "node_modules/isomorphic-ws": {
1587 | "version": "4.0.1",
1588 | "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz",
1589 | "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==",
1590 | "license": "MIT",
1591 | "peerDependencies": {
1592 | "ws": "*"
1593 | }
1594 | },
1595 | "node_modules/leven": {
1596 | "version": "2.1.0",
1597 | "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz",
1598 | "integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==",
1599 | "engines": {
1600 | "node": ">=0.10.0"
1601 | }
1602 | },
1603 | "node_modules/minimatch": {
1604 | "version": "3.1.2",
1605 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
1606 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
1607 | "dependencies": {
1608 | "brace-expansion": "^1.1.7"
1609 | },
1610 | "engines": {
1611 | "node": "*"
1612 | }
1613 | },
1614 | "node_modules/minimist": {
1615 | "version": "1.2.6",
1616 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
1617 | "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
1618 | },
1619 | "node_modules/mqtt": {
1620 | "version": "4.2.8",
1621 | "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.2.8.tgz",
1622 | "integrity": "sha512-DJYjlXODVXtSDecN8jnNzi6ItX3+ufGsEs9OB3YV24HtkRrh7kpx8L5M1LuyF0KzaiGtWr2PzDcMGAY60KGOSA==",
1623 | "dependencies": {
1624 | "commist": "^1.0.0",
1625 | "concat-stream": "^2.0.0",
1626 | "debug": "^4.1.1",
1627 | "duplexify": "^4.1.1",
1628 | "help-me": "^3.0.0",
1629 | "inherits": "^2.0.3",
1630 | "minimist": "^1.2.5",
1631 | "mqtt-packet": "^6.8.0",
1632 | "pump": "^3.0.0",
1633 | "readable-stream": "^3.6.0",
1634 | "reinterval": "^1.1.0",
1635 | "split2": "^3.1.0",
1636 | "ws": "^7.5.0",
1637 | "xtend": "^4.0.2"
1638 | },
1639 | "bin": {
1640 | "mqtt": "bin/mqtt.js",
1641 | "mqtt_pub": "bin/pub.js",
1642 | "mqtt_sub": "bin/sub.js"
1643 | },
1644 | "engines": {
1645 | "node": ">=10.0.0"
1646 | }
1647 | },
1648 | "node_modules/mqtt-packet": {
1649 | "version": "6.10.0",
1650 | "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz",
1651 | "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==",
1652 | "dependencies": {
1653 | "bl": "^4.0.2",
1654 | "debug": "^4.1.1",
1655 | "process-nextick-args": "^2.0.1"
1656 | }
1657 | },
1658 | "node_modules/ms": {
1659 | "version": "2.1.2",
1660 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
1661 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
1662 | },
1663 | "node_modules/once": {
1664 | "version": "1.4.0",
1665 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
1666 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
1667 | "dependencies": {
1668 | "wrappy": "1"
1669 | }
1670 | },
1671 | "node_modules/path-is-absolute": {
1672 | "version": "1.0.1",
1673 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
1674 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
1675 | "engines": {
1676 | "node": ">=0.10.0"
1677 | }
1678 | },
1679 | "node_modules/process-nextick-args": {
1680 | "version": "2.0.1",
1681 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
1682 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
1683 | },
1684 | "node_modules/pump": {
1685 | "version": "3.0.0",
1686 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
1687 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
1688 | "dependencies": {
1689 | "end-of-stream": "^1.1.0",
1690 | "once": "^1.3.1"
1691 | }
1692 | },
1693 | "node_modules/readable-stream": {
1694 | "version": "3.6.2",
1695 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
1696 | "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
1697 | "dependencies": {
1698 | "inherits": "^2.0.3",
1699 | "string_decoder": "^1.1.1",
1700 | "util-deprecate": "^1.0.1"
1701 | },
1702 | "engines": {
1703 | "node": ">= 6"
1704 | }
1705 | },
1706 | "node_modules/reinterval": {
1707 | "version": "1.1.0",
1708 | "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz",
1709 | "integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ=="
1710 | },
1711 | "node_modules/safe-buffer": {
1712 | "version": "5.2.1",
1713 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
1714 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
1715 | "funding": [
1716 | {
1717 | "type": "github",
1718 | "url": "https://github.com/sponsors/feross"
1719 | },
1720 | {
1721 | "type": "patreon",
1722 | "url": "https://www.patreon.com/feross"
1723 | },
1724 | {
1725 | "type": "consulting",
1726 | "url": "https://feross.org/support"
1727 | }
1728 | ]
1729 | },
1730 | "node_modules/split2": {
1731 | "version": "3.2.2",
1732 | "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz",
1733 | "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==",
1734 | "dependencies": {
1735 | "readable-stream": "^3.0.0"
1736 | }
1737 | },
1738 | "node_modules/stream-shift": {
1739 | "version": "1.0.2",
1740 | "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.2.tgz",
1741 | "integrity": "sha512-rV4Bovi9xx0BFzOb/X0B2GqoIjvqPCttZdu0Wgtx2Dxkj7ETyWl9gmqJ4EutWRLvtZWm8dxE+InQZX1IryZn/w=="
1742 | },
1743 | "node_modules/string_decoder": {
1744 | "version": "1.3.0",
1745 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
1746 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
1747 | "dependencies": {
1748 | "safe-buffer": "~5.2.0"
1749 | }
1750 | },
1751 | "node_modules/strnum": {
1752 | "version": "1.0.5",
1753 | "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
1754 | "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==",
1755 | "license": "MIT"
1756 | },
1757 | "node_modules/tslib": {
1758 | "version": "2.8.1",
1759 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
1760 | "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
1761 | "license": "0BSD"
1762 | },
1763 | "node_modules/typedarray": {
1764 | "version": "0.0.6",
1765 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
1766 | "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
1767 | },
1768 | "node_modules/undici-types": {
1769 | "version": "6.20.0",
1770 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
1771 | "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
1772 | "license": "MIT"
1773 | },
1774 | "node_modules/util-deprecate": {
1775 | "version": "1.0.2",
1776 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
1777 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
1778 | },
1779 | "node_modules/uuid": {
1780 | "version": "9.0.1",
1781 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
1782 | "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
1783 | "funding": [
1784 | "https://github.com/sponsors/broofa",
1785 | "https://github.com/sponsors/ctavan"
1786 | ],
1787 | "license": "MIT",
1788 | "bin": {
1789 | "uuid": "dist/bin/uuid"
1790 | }
1791 | },
1792 | "node_modules/wrappy": {
1793 | "version": "1.0.2",
1794 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
1795 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
1796 | },
1797 | "node_modules/ws": {
1798 | "version": "7.5.10",
1799 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
1800 | "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
1801 | "license": "MIT",
1802 | "engines": {
1803 | "node": ">=8.3.0"
1804 | },
1805 | "peerDependencies": {
1806 | "bufferutil": "^4.0.1",
1807 | "utf-8-validate": "^5.0.2"
1808 | },
1809 | "peerDependenciesMeta": {
1810 | "bufferutil": {
1811 | "optional": true
1812 | },
1813 | "utf-8-validate": {
1814 | "optional": true
1815 | }
1816 | }
1817 | },
1818 | "node_modules/xtend": {
1819 | "version": "4.0.2",
1820 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
1821 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
1822 | "engines": {
1823 | "node": ">=0.4"
1824 | }
1825 | }
1826 | }
1827 | }
1828 |
--------------------------------------------------------------------------------