diff --git a/package-lock.json b/package-lock.json index 6766051..444e72b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,10 @@ "workspaces": [ "packages/hack", "packages/cdk", - "packages/foo" + "packages/foo", + "packages/process", + "packages/create", + "packages/poll" ], "dependencies": { "conventional-changelog-eslint": "^6.0.0", @@ -434,6 +437,147 @@ "node": ">=20.0.0" } }, + "node_modules/@aws-sdk/client-dynamodb": { + "version": "3.986.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.986.0.tgz", + "integrity": "sha512-4SPBE+QzRl8Yi8mSHDahwE+rKgCB1RhiIYoeqfwpkiocXnMaBQsNSEaJaschLTbC6cOPs2RqM1/oIF50do/OvA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.973.7", + "@aws-sdk/credential-provider-node": "^3.972.6", + "@aws-sdk/dynamodb-codec": "^3.972.8", + "@aws-sdk/middleware-endpoint-discovery": "^3.972.3", + "@aws-sdk/middleware-host-header": "^3.972.3", + "@aws-sdk/middleware-logger": "^3.972.3", + "@aws-sdk/middleware-recursion-detection": "^3.972.3", + "@aws-sdk/middleware-user-agent": "^3.972.7", + "@aws-sdk/region-config-resolver": "^3.972.3", + "@aws-sdk/types": "^3.973.1", + "@aws-sdk/util-endpoints": "3.986.0", + "@aws-sdk/util-user-agent-browser": "^3.972.3", + "@aws-sdk/util-user-agent-node": "^3.972.5", + "@smithy/config-resolver": "^4.4.6", + "@smithy/core": "^3.22.1", + "@smithy/fetch-http-handler": "^5.3.9", + "@smithy/hash-node": "^4.2.8", + "@smithy/invalid-dependency": "^4.2.8", + "@smithy/middleware-content-length": "^4.2.8", + "@smithy/middleware-endpoint": "^4.4.13", + "@smithy/middleware-retry": "^4.4.30", + "@smithy/middleware-serde": "^4.2.9", + "@smithy/middleware-stack": "^4.2.8", + "@smithy/node-config-provider": "^4.3.8", + "@smithy/node-http-handler": "^4.4.9", + "@smithy/protocol-http": "^5.3.8", + "@smithy/smithy-client": "^4.11.2", + "@smithy/types": "^4.12.0", + "@smithy/url-parser": "^4.2.8", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.29", + "@smithy/util-defaults-mode-node": "^4.2.32", + "@smithy/util-endpoints": "^3.2.8", + "@smithy/util-middleware": "^4.2.8", + "@smithy/util-retry": "^4.2.8", + "@smithy/util-utf8": "^4.2.0", + "@smithy/util-waiter": "^4.2.8", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/util-endpoints": { + "version": "3.986.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.986.0.tgz", + "integrity": "sha512-Mqi79L38qi1gCG3adlVdbNrSxvcm1IPDLiJPA3OBypY5ewxUyWbaA3DD4goG+EwET6LSFgZJcRSIh6KBNpP5pA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.1", + "@smithy/types": "^4.12.0", + "@smithy/url-parser": "^4.2.8", + "@smithy/util-endpoints": "^3.2.8", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda": { + "version": "3.986.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.986.0.tgz", + "integrity": "sha512-R0VrqSH622b0MmIULLCNbupyU9qqEn+vofIeKng+ALPJY6U7pq7MG0p+bbxLCGztLl0u2vmO237SPZYcFm3hCQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.973.7", + "@aws-sdk/credential-provider-node": "^3.972.6", + "@aws-sdk/middleware-host-header": "^3.972.3", + "@aws-sdk/middleware-logger": "^3.972.3", + "@aws-sdk/middleware-recursion-detection": "^3.972.3", + "@aws-sdk/middleware-user-agent": "^3.972.7", + "@aws-sdk/region-config-resolver": "^3.972.3", + "@aws-sdk/types": "^3.973.1", + "@aws-sdk/util-endpoints": "3.986.0", + "@aws-sdk/util-user-agent-browser": "^3.972.3", + "@aws-sdk/util-user-agent-node": "^3.972.5", + "@smithy/config-resolver": "^4.4.6", + "@smithy/core": "^3.22.1", + "@smithy/eventstream-serde-browser": "^4.2.8", + "@smithy/eventstream-serde-config-resolver": "^4.3.8", + "@smithy/eventstream-serde-node": "^4.2.8", + "@smithy/fetch-http-handler": "^5.3.9", + "@smithy/hash-node": "^4.2.8", + "@smithy/invalid-dependency": "^4.2.8", + "@smithy/middleware-content-length": "^4.2.8", + "@smithy/middleware-endpoint": "^4.4.13", + "@smithy/middleware-retry": "^4.4.30", + "@smithy/middleware-serde": "^4.2.9", + "@smithy/middleware-stack": "^4.2.8", + "@smithy/node-config-provider": "^4.3.8", + "@smithy/node-http-handler": "^4.4.9", + "@smithy/protocol-http": "^5.3.8", + "@smithy/smithy-client": "^4.11.2", + "@smithy/types": "^4.12.0", + "@smithy/url-parser": "^4.2.8", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.29", + "@smithy/util-defaults-mode-node": "^4.2.32", + "@smithy/util-endpoints": "^3.2.8", + "@smithy/util-middleware": "^4.2.8", + "@smithy/util-retry": "^4.2.8", + "@smithy/util-stream": "^4.5.11", + "@smithy/util-utf8": "^4.2.0", + "@smithy/util-waiter": "^4.2.8", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/util-endpoints": { + "version": "3.986.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.986.0.tgz", + "integrity": "sha512-Mqi79L38qi1gCG3adlVdbNrSxvcm1IPDLiJPA3OBypY5ewxUyWbaA3DD4goG+EwET6LSFgZJcRSIh6KBNpP5pA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.1", + "@smithy/types": "^4.12.0", + "@smithy/url-parser": "^4.2.8", + "@smithy/util-endpoints": "^3.2.8", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/@aws-sdk/client-route-53": { "version": "3.984.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-route-53/-/client-route-53-3.984.0.tgz", @@ -553,44 +697,44 @@ } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.982.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.982.0.tgz", - "integrity": "sha512-qJrIiivmvujdGqJ0ldSUvhN3k3N7GtPesoOI1BSt0fNXovVnMz4C/JmnkhZihU7hJhDvxJaBROLYTU+lpild4w==", + "version": "3.985.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.985.0.tgz", + "integrity": "sha512-81J8iE8MuXhdbMfIz4sWFj64Pe41bFi/uqqmqOC5SlGv+kwoyLsyKS/rH2tW2t5buih4vTUxskRjxlqikTD4oQ==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.6", + "@aws-sdk/core": "^3.973.7", "@aws-sdk/middleware-host-header": "^3.972.3", "@aws-sdk/middleware-logger": "^3.972.3", "@aws-sdk/middleware-recursion-detection": "^3.972.3", - "@aws-sdk/middleware-user-agent": "^3.972.6", + "@aws-sdk/middleware-user-agent": "^3.972.7", "@aws-sdk/region-config-resolver": "^3.972.3", "@aws-sdk/types": "^3.973.1", - "@aws-sdk/util-endpoints": "3.982.0", + "@aws-sdk/util-endpoints": "3.985.0", "@aws-sdk/util-user-agent-browser": "^3.972.3", - "@aws-sdk/util-user-agent-node": "^3.972.4", + "@aws-sdk/util-user-agent-node": "^3.972.5", "@smithy/config-resolver": "^4.4.6", - "@smithy/core": "^3.22.0", + "@smithy/core": "^3.22.1", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/hash-node": "^4.2.8", "@smithy/invalid-dependency": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", - "@smithy/middleware-endpoint": "^4.4.12", - "@smithy/middleware-retry": "^4.4.29", + "@smithy/middleware-endpoint": "^4.4.13", + "@smithy/middleware-retry": "^4.4.30", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", - "@smithy/node-http-handler": "^4.4.8", + "@smithy/node-http-handler": "^4.4.9", "@smithy/protocol-http": "^5.3.8", - "@smithy/smithy-client": "^4.11.1", + "@smithy/smithy-client": "^4.11.2", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.28", - "@smithy/util-defaults-mode-node": "^4.2.31", + "@smithy/util-defaults-mode-browser": "^4.3.29", + "@smithy/util-defaults-mode-node": "^4.2.32", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", @@ -602,9 +746,9 @@ } }, "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/util-endpoints": { - "version": "3.982.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.982.0.tgz", - "integrity": "sha512-M27u8FJP7O0Of9hMWX5dipp//8iglmV9jr7R8SR8RveU+Z50/8TqH68Tu6wUWBGMfXjzbVwn1INIAO5lZrlxXQ==", + "version": "3.985.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.985.0.tgz", + "integrity": "sha512-vth7UfGSUR3ljvaq8V4Rc62FsM7GUTH/myxPWkaEgOrprz1/Pc72EgTXxj+cPPPDAfHFIpjhkB7T7Td0RJx+BA==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "^3.973.1", @@ -618,19 +762,19 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.973.6", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.973.6.tgz", - "integrity": "sha512-pz4ZOw3BLG0NdF25HoB9ymSYyPbMiIjwQJ2aROXRhAzt+b+EOxStfFv8s5iZyP6Kiw7aYhyWxj5G3NhmkoOTKw==", + "version": "3.973.7", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.973.7.tgz", + "integrity": "sha512-wNZZQQNlJ+hzD49cKdo+PY6rsTDElO8yDImnrI69p2PLBa7QomeUKAJWYp9xnaR38nlHqWhMHZuYLCQ3oSX+xg==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "^3.973.1", "@aws-sdk/xml-builder": "^3.972.4", - "@smithy/core": "^3.22.0", + "@smithy/core": "^3.22.1", "@smithy/node-config-provider": "^4.3.8", "@smithy/property-provider": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/signature-v4": "^5.3.8", - "@smithy/smithy-client": "^4.11.1", + "@smithy/smithy-client": "^4.11.2", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-middleware": "^4.2.8", @@ -655,12 +799,12 @@ } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.972.4", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.4.tgz", - "integrity": "sha512-/8dnc7+XNMmViEom2xsNdArQxQPSgy4Z/lm6qaFPTrMFesT1bV3PsBhb19n09nmxHdrtQskYmViddUIjUQElXg==", + "version": "3.972.5", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.5.tgz", + "integrity": "sha512-LxJ9PEO4gKPXzkufvIESUysykPIdrV7+Ocb9yAhbhJLE4TiAYqbCVUE+VuKP1leGR1bBfjWjYgSV5MxprlX3mQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.6", + "@aws-sdk/core": "^3.973.7", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/types": "^4.12.0", @@ -671,20 +815,20 @@ } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.972.6", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.6.tgz", - "integrity": "sha512-5ERWqRljiZv44AIdvIRQ3k+EAV0Sq2WeJHvXuK7gL7bovSxOf8Al7MLH7Eh3rdovH4KHFnlIty7J71mzvQBl5Q==", + "version": "3.972.7", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.7.tgz", + "integrity": "sha512-L2uOGtvp2x3bTcxFTpSM+GkwFIPd8pHfGWO1764icMbo7e5xJh0nfhx1UwkXLnwvocTNEf8A7jISZLYjUSNaTg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.6", + "@aws-sdk/core": "^3.973.7", "@aws-sdk/types": "^3.973.1", "@smithy/fetch-http-handler": "^5.3.9", - "@smithy/node-http-handler": "^4.4.8", + "@smithy/node-http-handler": "^4.4.9", "@smithy/property-provider": "^4.2.8", "@smithy/protocol-http": "^5.3.8", - "@smithy/smithy-client": "^4.11.1", + "@smithy/smithy-client": "^4.11.2", "@smithy/types": "^4.12.0", - "@smithy/util-stream": "^4.5.10", + "@smithy/util-stream": "^4.5.11", "tslib": "^2.6.2" }, "engines": { @@ -692,19 +836,19 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.972.4", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.4.tgz", - "integrity": "sha512-eRUg+3HaUKuXWn/lEMirdiA5HOKmEl8hEHVuszIDt2MMBUKgVX5XNGmb3XmbgU17h6DZ+RtjbxQpjhz3SbTjZg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.973.6", - "@aws-sdk/credential-provider-env": "^3.972.4", - "@aws-sdk/credential-provider-http": "^3.972.6", - "@aws-sdk/credential-provider-login": "^3.972.4", - "@aws-sdk/credential-provider-process": "^3.972.4", - "@aws-sdk/credential-provider-sso": "^3.972.4", - "@aws-sdk/credential-provider-web-identity": "^3.972.4", - "@aws-sdk/nested-clients": "3.982.0", + "version": "3.972.5", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.5.tgz", + "integrity": "sha512-SdDTYE6jkARzOeL7+kudMIM4DaFnP5dZVeatzw849k4bSXDdErDS188bgeNzc/RA2WGrlEpsqHUKP6G7sVXhZg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.7", + "@aws-sdk/credential-provider-env": "^3.972.5", + "@aws-sdk/credential-provider-http": "^3.972.7", + "@aws-sdk/credential-provider-login": "^3.972.5", + "@aws-sdk/credential-provider-process": "^3.972.5", + "@aws-sdk/credential-provider-sso": "^3.972.5", + "@aws-sdk/credential-provider-web-identity": "^3.972.5", + "@aws-sdk/nested-clients": "3.985.0", "@aws-sdk/types": "^3.973.1", "@smithy/credential-provider-imds": "^4.2.8", "@smithy/property-provider": "^4.2.8", @@ -717,13 +861,13 @@ } }, "node_modules/@aws-sdk/credential-provider-login": { - "version": "3.972.4", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.4.tgz", - "integrity": "sha512-nLGjXuvWWDlQAp505xIONI7Gam0vw2p7Qu3P6on/W2q7rjJXtYjtpHbcsaOjJ/pAju3eTvEQuSuRedcRHVQIAQ==", + "version": "3.972.5", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.5.tgz", + "integrity": "sha512-uYq1ILyTSI6ZDCMY5+vUsRM0SOCVI7kaW4wBrehVVkhAxC6y+e9rvGtnoZqCOWL1gKjTMouvsf4Ilhc5NCg1Aw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.6", - "@aws-sdk/nested-clients": "3.982.0", + "@aws-sdk/core": "^3.973.7", + "@aws-sdk/nested-clients": "3.985.0", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/protocol-http": "^5.3.8", @@ -736,17 +880,17 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.972.5", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.5.tgz", - "integrity": "sha512-VWXKgSISQCI2GKN3zakTNHSiZ0+mux7v6YHmmbLQp/o3fvYUQJmKGcLZZzg2GFA+tGGBStplra9VFNf/WwxpYg==", + "version": "3.972.6", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.6.tgz", + "integrity": "sha512-DZ3CnAAtSVtVz+G+ogqecaErMLgzph4JH5nYbHoBMgBkwTUV+SUcjsjOJwdBJTHu3Dm6l5LBYekZoU2nDqQk2A==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "^3.972.4", - "@aws-sdk/credential-provider-http": "^3.972.6", - "@aws-sdk/credential-provider-ini": "^3.972.4", - "@aws-sdk/credential-provider-process": "^3.972.4", - "@aws-sdk/credential-provider-sso": "^3.972.4", - "@aws-sdk/credential-provider-web-identity": "^3.972.4", + "@aws-sdk/credential-provider-env": "^3.972.5", + "@aws-sdk/credential-provider-http": "^3.972.7", + "@aws-sdk/credential-provider-ini": "^3.972.5", + "@aws-sdk/credential-provider-process": "^3.972.5", + "@aws-sdk/credential-provider-sso": "^3.972.5", + "@aws-sdk/credential-provider-web-identity": "^3.972.5", "@aws-sdk/types": "^3.973.1", "@smithy/credential-provider-imds": "^4.2.8", "@smithy/property-provider": "^4.2.8", @@ -759,12 +903,12 @@ } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.972.4", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.4.tgz", - "integrity": "sha512-TCZpWUnBQN1YPk6grvd5x419OfXjHvhj5Oj44GYb84dOVChpg/+2VoEj+YVA4F4E/6huQPNnX7UYbTtxJqgihw==", + "version": "3.972.5", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.5.tgz", + "integrity": "sha512-HDKF3mVbLnuqGg6dMnzBf1VUOywE12/N286msI9YaK9mEIzdsGCtLTvrDhe3Up0R9/hGFbB+9l21/TwF5L1C6g==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.6", + "@aws-sdk/core": "^3.973.7", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", @@ -776,14 +920,14 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.972.4", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.4.tgz", - "integrity": "sha512-wzsGwv9mKlwJ3vHLyembBvGE/5nPUIwRR2I51B1cBV4Cb4ql9nIIfpmHzm050XYTY5fqTOKJQnhLj7zj89VG8g==", + "version": "3.972.5", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.5.tgz", + "integrity": "sha512-8urj3AoeNeQisjMmMBhFeiY2gxt6/7wQQbEGun0YV/OaOOiXrIudTIEYF8ZfD+NQI6X1FY5AkRsx6O/CaGiybA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-sso": "3.982.0", - "@aws-sdk/core": "^3.973.6", - "@aws-sdk/token-providers": "3.982.0", + "@aws-sdk/client-sso": "3.985.0", + "@aws-sdk/core": "^3.973.7", + "@aws-sdk/token-providers": "3.985.0", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", @@ -795,13 +939,13 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.972.4", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.4.tgz", - "integrity": "sha512-hIzw2XzrG8jzsUSEatehmpkd5rWzASg5IHUfA+m01k/RtvfAML7ZJVVohuKdhAYx+wV2AThLiQJVzqn7F0khrw==", + "version": "3.972.5", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.5.tgz", + "integrity": "sha512-OK3cULuJl6c+RcDZfPpaK5o3deTOnKZbxm7pzhFNGA3fI2hF9yDih17fGRazJzGGWaDVlR9ejZrpDef4DJCEsw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.6", - "@aws-sdk/nested-clients": "3.982.0", + "@aws-sdk/core": "^3.973.7", + "@aws-sdk/nested-clients": "3.985.0", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", @@ -812,6 +956,36 @@ "node": ">=20.0.0" } }, + "node_modules/@aws-sdk/dynamodb-codec": { + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/dynamodb-codec/-/dynamodb-codec-3.972.8.tgz", + "integrity": "sha512-5ngfn6fQPSNc7G9LlingK4SXfzcJtv5pOP++erc7HmCq0LcDj//0pcpLgxpDII0sBTh0FcR/iw9i4fBZwSJ2Cg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.7", + "@smithy/core": "^3.22.1", + "@smithy/smithy-client": "^4.11.2", + "@smithy/types": "^4.12.0", + "@smithy/util-base64": "^4.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/endpoint-cache": { + "version": "3.972.2", + "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.972.2.tgz", + "integrity": "sha512-3L7mwqSLJ6ouZZKtCntoNF0HTYDNs1FDQqkGjoPWXcv1p0gnLotaDmLq1rIDqfu4ucOit0Re3ioLyYDUTpSroA==", + "license": "Apache-2.0", + "dependencies": { + "mnemonist": "0.38.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/@aws-sdk/middleware-bucket-endpoint": { "version": "3.972.3", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.972.3.tgz", @@ -830,6 +1004,23 @@ "node": ">=20.0.0" } }, + "node_modules/@aws-sdk/middleware-endpoint-discovery": { + "version": "3.972.3", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.972.3.tgz", + "integrity": "sha512-xAxA8/TOygQmMrzcw9CrlpTHCGWSG/lvzrHCySfSZpDN4/yVSfXO+gUwW9WxeskBmuv9IIFATOVpzc9EzfTZ0Q==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/endpoint-cache": "^3.972.2", + "@aws-sdk/types": "^3.973.1", + "@smithy/node-config-provider": "^4.3.8", + "@smithy/protocol-http": "^5.3.8", + "@smithy/types": "^4.12.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/@aws-sdk/middleware-expect-continue": { "version": "3.972.3", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.972.3.tgz", @@ -983,15 +1174,15 @@ } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.972.6", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.6.tgz", - "integrity": "sha512-TehLN8W/kivl0U9HcS+keryElEWORROpghDXZBLfnb40DXM7hx/i+7OOjkogXQOF3QtUraJVRkHQ07bPhrWKlw==", + "version": "3.972.7", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.7.tgz", + "integrity": "sha512-HUD+geASjXSCyL/DHPQc/Ua7JhldTcIglVAoCV8kiVm99IaFSlAbTvEnyhZwdE6bdFyTL+uIaWLaCFSRsglZBQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.6", + "@aws-sdk/core": "^3.973.7", "@aws-sdk/types": "^3.973.1", - "@aws-sdk/util-endpoints": "3.982.0", - "@smithy/core": "^3.22.0", + "@aws-sdk/util-endpoints": "3.985.0", + "@smithy/core": "^3.22.1", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" @@ -1001,9 +1192,9 @@ } }, "node_modules/@aws-sdk/middleware-user-agent/node_modules/@aws-sdk/util-endpoints": { - "version": "3.982.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.982.0.tgz", - "integrity": "sha512-M27u8FJP7O0Of9hMWX5dipp//8iglmV9jr7R8SR8RveU+Z50/8TqH68Tu6wUWBGMfXjzbVwn1INIAO5lZrlxXQ==", + "version": "3.985.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.985.0.tgz", + "integrity": "sha512-vth7UfGSUR3ljvaq8V4Rc62FsM7GUTH/myxPWkaEgOrprz1/Pc72EgTXxj+cPPPDAfHFIpjhkB7T7Td0RJx+BA==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "^3.973.1", @@ -1017,44 +1208,44 @@ } }, "node_modules/@aws-sdk/nested-clients": { - "version": "3.982.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.982.0.tgz", - "integrity": "sha512-VVkaH27digrJfdVrT64rjkllvOp4oRiZuuJvrylLXAKl18ujToJR7AqpDldL/LS63RVne3QWIpkygIymxFtliQ==", + "version": "3.985.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.985.0.tgz", + "integrity": "sha512-TsWwKzb/2WHafAY0CE7uXgLj0FmnkBTgfioG9HO+7z/zCPcl1+YU+i7dW4o0y+aFxFgxTMG+ExBQpqT/k2ao8g==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.6", + "@aws-sdk/core": "^3.973.7", "@aws-sdk/middleware-host-header": "^3.972.3", "@aws-sdk/middleware-logger": "^3.972.3", "@aws-sdk/middleware-recursion-detection": "^3.972.3", - "@aws-sdk/middleware-user-agent": "^3.972.6", + "@aws-sdk/middleware-user-agent": "^3.972.7", "@aws-sdk/region-config-resolver": "^3.972.3", "@aws-sdk/types": "^3.973.1", - "@aws-sdk/util-endpoints": "3.982.0", + "@aws-sdk/util-endpoints": "3.985.0", "@aws-sdk/util-user-agent-browser": "^3.972.3", - "@aws-sdk/util-user-agent-node": "^3.972.4", + "@aws-sdk/util-user-agent-node": "^3.972.5", "@smithy/config-resolver": "^4.4.6", - "@smithy/core": "^3.22.0", + "@smithy/core": "^3.22.1", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/hash-node": "^4.2.8", "@smithy/invalid-dependency": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", - "@smithy/middleware-endpoint": "^4.4.12", - "@smithy/middleware-retry": "^4.4.29", + "@smithy/middleware-endpoint": "^4.4.13", + "@smithy/middleware-retry": "^4.4.30", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", - "@smithy/node-http-handler": "^4.4.8", + "@smithy/node-http-handler": "^4.4.9", "@smithy/protocol-http": "^5.3.8", - "@smithy/smithy-client": "^4.11.1", + "@smithy/smithy-client": "^4.11.2", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.28", - "@smithy/util-defaults-mode-node": "^4.2.31", + "@smithy/util-defaults-mode-browser": "^4.3.29", + "@smithy/util-defaults-mode-node": "^4.2.32", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", @@ -1066,9 +1257,9 @@ } }, "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/util-endpoints": { - "version": "3.982.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.982.0.tgz", - "integrity": "sha512-M27u8FJP7O0Of9hMWX5dipp//8iglmV9jr7R8SR8RveU+Z50/8TqH68Tu6wUWBGMfXjzbVwn1INIAO5lZrlxXQ==", + "version": "3.985.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.985.0.tgz", + "integrity": "sha512-vth7UfGSUR3ljvaq8V4Rc62FsM7GUTH/myxPWkaEgOrprz1/Pc72EgTXxj+cPPPDAfHFIpjhkB7T7Td0RJx+BA==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "^3.973.1", @@ -1115,13 +1306,13 @@ } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.982.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.982.0.tgz", - "integrity": "sha512-v3M0KYp2TVHYHNBT7jHD9lLTWAdS9CaWJ2jboRKt0WAB65bA7iUEpR+k4VqKYtpQN4+8kKSc4w+K6kUNZkHKQw==", + "version": "3.985.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.985.0.tgz", + "integrity": "sha512-+hwpHZyEq8k+9JL2PkE60V93v2kNhUIv7STFt+EAez1UJsJOQDhc5LpzEX66pNjclI5OTwBROs/DhJjC/BtMjQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.6", - "@aws-sdk/nested-clients": "3.982.0", + "@aws-sdk/core": "^3.973.7", + "@aws-sdk/nested-clients": "3.985.0", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", @@ -1198,12 +1389,12 @@ } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.972.4", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.972.4.tgz", - "integrity": "sha512-3WFCBLiM8QiHDfosQq3Py+lIMgWlFWwFQliUHUqwEiRqLnKyhgbU3AKa7AWJF7lW2Oc/2kFNY4MlAYVnVc0i8A==", + "version": "3.972.5", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.972.5.tgz", + "integrity": "sha512-GsUDF+rXyxDZkkJxUsDxnA67FG+kc5W1dnloCFLl6fWzceevsCYzJpASBzT+BPjwUgREE6FngfJYYYMQUY5fZQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-user-agent": "^3.972.6", + "@aws-sdk/middleware-user-agent": "^3.972.7", "@aws-sdk/types": "^3.973.1", "@smithy/node-config-provider": "^4.3.8", "@smithy/types": "^4.12.0", @@ -3344,7 +3535,6 @@ "resolved": "https://registry.npmjs.org/@middy/core/-/core-7.0.2.tgz", "integrity": "sha512-C4PEJxMjWFneqfQzsbWQ9BZ7Bfds9oqw74/fTuEeunI/0PA1KtGfbHDuU1SQH6lZ3rOp+VUIYh4YDho8qmc2Rg==", "license": "MIT", - "peer": true, "engines": { "node": ">=22" }, @@ -7305,6 +7495,10 @@ "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", "license": "MIT" }, + "node_modules/create": { + "resolved": "packages/create", + "link": true + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -11443,6 +11637,15 @@ "node": ">=10" } }, + "node_modules/mnemonist": { + "version": "0.38.3", + "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.3.tgz", + "integrity": "sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==", + "license": "MIT", + "dependencies": { + "obliterator": "^1.6.1" + } + }, "node_modules/morgan": { "version": "1.10.1", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.1.tgz", @@ -11789,6 +11992,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obliterator": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-1.6.1.tgz", + "integrity": "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==", + "license": "MIT" + }, "node_modules/obug": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", @@ -12225,6 +12434,10 @@ "pathe": "^2.0.3" } }, + "node_modules/poll": { + "resolved": "packages/poll", + "link": true + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -12332,6 +12545,10 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/process": { + "resolved": "packages/process", + "link": true + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -15207,6 +15424,24 @@ "vite": "^7.3.1" } }, + "packages/create": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "@aws-lambda-powertools/commons": "^2.30.2", + "@aws-lambda-powertools/logger": "^2.30.2", + "@aws-lambda-powertools/parameters": "^2.30.2", + "@aws-sdk/client-lambda": "^3.986.0", + "@middy/core": "^7.0.2", + "@middy/input-output-logger": "^7.0.2", + "@nhs/fhir-middy-error-handler": "^2.1.71", + "@nhsdigital/eps-spine-client": "^2.1.78" + }, + "devDependencies": { + "axios-mock-adapter": "^2.1.0", + "esbuild": "^0.27.2" + } + }, "packages/foo": { "name": "status", "version": "1.0.0", @@ -15523,6 +15758,41 @@ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" + }, + "packages/poll": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "@aws-lambda-powertools/commons": "^2.30.2", + "@aws-lambda-powertools/logger": "^2.30.2", + "@aws-lambda-powertools/parameters": "^2.30.2", + "@aws-sdk/client-dynamodb": "^3.986.0", + "@middy/core": "^7.0.2", + "@middy/input-output-logger": "^7.0.2", + "@nhs/fhir-middy-error-handler": "^2.1.71", + "@nhsdigital/eps-spine-client": "^2.1.78" + }, + "devDependencies": { + "axios-mock-adapter": "^2.1.0", + "esbuild": "^0.27.2" + } + }, + "packages/process": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "@aws-lambda-powertools/commons": "^2.30.2", + "@aws-lambda-powertools/logger": "^2.30.2", + "@aws-lambda-powertools/parameters": "^2.30.2", + "@middy/core": "^7.0.2", + "@middy/input-output-logger": "^7.0.2", + "@nhs/fhir-middy-error-handler": "^2.1.71", + "@nhsdigital/eps-spine-client": "^2.1.78" + }, + "devDependencies": { + "axios-mock-adapter": "^2.1.0", + "esbuild": "^0.27.2" + } } } } diff --git a/package.json b/package.json index 544ae6b..43a4c50 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,10 @@ "workspaces": [ "packages/hack", "packages/cdk", - "packages/foo" + "packages/foo", + "packages/process", + "packages/create", + "packages/poll" ], "devDependencies": { "@eslint/js": "^9.38.0", diff --git a/packages/cdk/resources/CloudfrontBehaviors.ts b/packages/cdk/resources/CloudfrontBehaviors.ts index 7286d45..f725625 100644 --- a/packages/cdk/resources/CloudfrontBehaviors.ts +++ b/packages/cdk/resources/CloudfrontBehaviors.ts @@ -31,7 +31,7 @@ export interface CloudfrontBehaviorsProps { * Any rewrites for cloudfront requests should go here */ -export class CloudfrontBehaviors extends Construct{ +export class CloudfrontBehaviors extends Construct { public readonly additionalBehaviors: Record public readonly s3404UriRewriteFunction: CloudfrontFunction public readonly s3404ModifyStatusCodeFunction: CloudfrontFunction @@ -40,31 +40,33 @@ export class CloudfrontBehaviors extends Construct{ public readonly keyValueStore: KeyValueStore public readonly fullCognitoDomain: string - public constructor(scope: Construct, id: string, props: CloudfrontBehaviorsProps){ + public constructor(scope: Construct, id: string, props: CloudfrontBehaviorsProps) { super(scope, id) // Resources const keyValueStore = new KeyValueStore(this, "FunctionsStore", { comment: `${props.serviceName}-KeyValueStore`, - source: ImportSource.fromInline(JSON.stringify({data: [ - { - key: "404_rewrite", - value: "404.html" - }, - { - key: "500_rewrite", - value: "500.html" - }, - { - key: "site_basePath", - value: "/site" - }, - { - key: "api_path", - value: "/api" - } - ]})) + source: ImportSource.fromInline(JSON.stringify({ + data: [ + { + key: "404_rewrite", + value: "404.html" + }, + { + key: "500_rewrite", + value: "500.html" + }, + { + key: "site_basePath", + value: "/site" + }, + { + key: "api_path", + value: "/api" + } + ] + })) }) // Workaround for CF KVS tag issues in latest cdk/cf, see: https://github.com/aws/aws-cdk/issues/36765 const cfnKeyValueStore = keyValueStore.node.defaultChild as CfnKeyValueStore diff --git a/packages/cdk/resources/DynamoDb.ts b/packages/cdk/resources/DynamoDb.ts new file mode 100644 index 0000000..4958105 --- /dev/null +++ b/packages/cdk/resources/DynamoDb.ts @@ -0,0 +1,141 @@ +import {Construct} from "constructs" + +import { + AttributeType, + Billing, + TableEncryptionV2, + TableV2 +} from "aws-cdk-lib/aws-dynamodb" +import { + AccountRootPrincipal, + AnyPrincipal, + Effect, + ManagedPolicy, + PolicyDocument, + PolicyStatement +} from "aws-cdk-lib/aws-iam" +import {Key} from "aws-cdk-lib/aws-kms" +import {Duration, RemovalPolicy} from "aws-cdk-lib" + +export interface DynamodbProps { + readonly stackName: string +} + +/** + * Dynamodb tables used for user state information + */ +export class Dynamodb extends Construct { + public readonly processStatus: TableV2 + public readonly useProcessStatusKmsKeyPolicy: ManagedPolicy + public readonly processStatusTableWritePolicy: ManagedPolicy + public readonly processStatusTableReadPolicy: ManagedPolicy + // + + public constructor(scope: Construct, id: string, props: DynamodbProps) { + super(scope, id) + + // KMS key for token mapping table + const processStatusKey = new Key(this, "processStatusKey", { + removalPolicy: RemovalPolicy.DESTROY, + pendingWindow: Duration.days(7), + alias: `${props.stackName}-processStatusKey`, + description: `${props.stackName}-processStatusKey`, + enableKeyRotation: true, + policy: new PolicyDocument({ + statements: [ + new PolicyStatement({ + sid: "Enable IAM User Permissions", + effect: Effect.ALLOW, + actions: [ + "kms:*" + ], + principals: [ + new AccountRootPrincipal + ], + resources: ["*"] + }) + ] + }) + }) + + // Process Status Table + const processStatusTable = new TableV2(this, "processStatusTable", { + partitionKey: { + name: "actionId", + type: AttributeType.STRING + }, + tableName: `${props.stackName}-processStatus`, + removalPolicy: RemovalPolicy.DESTROY, + pointInTimeRecoverySpecification: { + pointInTimeRecoveryEnabled: true + }, + encryption: TableEncryptionV2.customerManagedKey(processStatusKey), + billing: Billing.onDemand(), + timeToLiveAttribute: "ExpiryTime" + }) + + // Policy to use token mapping KMS key + const useProcessStatusKmsKey = new ManagedPolicy(this, "UseProcessStatusKMSKeyPolicy", { + statements: [ + new PolicyStatement({ + actions: [ + "kms:DescribeKey", + "kms:GenerateDataKey", + "kms:Encrypt", + "kms:ReEncryptFrom", + "kms:ReEncryptTo", + "kms:Decrypt" + ], + resources: [ + processStatusKey.keyArn + ] + }) + ] + }) + + const processStatusReadPolicy = new ManagedPolicy(this, "ProcessStatusReadManagedPolicy", { + statements: [ + new PolicyStatement({ + actions: [ + "dynamodb:GetItem", + "dynamodb:BatchGetItem", + "dynamodb:Scan", + "dynamodb:Query", + "dynamodb:ConditionCheckItem", + "dynamodb:DescribeTable" + ], + resources: [ + processStatusTable.tableArn, + `${processStatusTable.tableArn}/index/*` + ] + }) + ] + }) + + const processStatusWritePolicy = new ManagedPolicy(this, "ProcessStatusWriteManagedPolicy", { + statements: [ + new PolicyStatement({ + actions: [ + "dynamodb:PutItem", + "dynamodb:BatchWriteItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem" + ], + resources: [ + processStatusTable.tableArn, + `${processStatusTable.tableArn}/index/*` + ] + }) + ] + }) + + + // Outputs: assign the created resources to the class properties + this.processStatus = processStatusTable + this.useProcessStatusKmsKeyPolicy = useProcessStatusKmsKey + this.processStatusTableWritePolicy = processStatusWritePolicy + this.processStatusTableReadPolicy = processStatusReadPolicy + + + } +} diff --git a/packages/cdk/resources/Functions.ts b/packages/cdk/resources/Functions.ts index 3c22a45..cdf8f47 100644 --- a/packages/cdk/resources/Functions.ts +++ b/packages/cdk/resources/Functions.ts @@ -1,6 +1,7 @@ import {Construct} from "constructs" import {TypescriptLambdaFunction} from "@nhsdigital/eps-cdk-constructs" -import { resolve } from "node:path" +import {resolve} from "node:path" +import {Dynamodb} from "./DynamoDb" const baseDir = resolve(__dirname, "../../..") // Interface for properties needed to create API functions export interface ApiFunctionsProps { @@ -8,6 +9,7 @@ export interface ApiFunctionsProps { readonly stackName: string readonly version: string readonly commitId: string + readonly processingStatusTable: Dynamodb } /** @@ -15,6 +17,9 @@ export interface ApiFunctionsProps { */ export class ApiFunctions extends Construct { public readonly fooLambda: TypescriptLambdaFunction + public readonly createLambda: TypescriptLambdaFunction + public readonly processLambda: TypescriptLambdaFunction + public readonly pollLambda: TypescriptLambdaFunction public constructor(scope: Construct, id: string, props: ApiFunctionsProps) { super(scope, id) @@ -29,7 +34,57 @@ export class ApiFunctions extends Construct { version: props.version, commitId: props.commitId }) + + const processLambda = new TypescriptLambdaFunction(this, "ProcessLambda", { + functionName: `${props.stackName}-ProcessLambda`, + projectBaseDir: baseDir, + packageBasePath: "packages/process", + entryPoint: "src/handler.ts", + environmentVariables: {}, + logRetentionInDays: 30, + logLevel: "DEBUG", + version: props.version, + commitId: props.commitId + }) + + const createLambda = new TypescriptLambdaFunction(this, "CreateLambda", { + functionName: `${props.stackName}-CreateLambda`, + projectBaseDir: baseDir, + packageBasePath: "packages/create", + entryPoint: "src/handler.ts", + environmentVariables: { + PROCESSING_LAMBDA_NAME: processLambda.function.functionName + }, + logRetentionInDays: 30, + logLevel: "DEBUG", + version: props.version, + commitId: props.commitId, + additionalPolicies: [ + processLambda.executionPolicy + ] + }) + + const pollLambda = new TypescriptLambdaFunction(this, "PollLambda", { + functionName: `${props.stackName}-PollLambda`, + projectBaseDir: baseDir, + packageBasePath: "packages/poll", + entryPoint: "src/handler.ts", + environmentVariables: { + PROCESSING_STATUS_TABLE_NAME: props.processingStatusTable.processStatus.tableName + }, + logRetentionInDays: 30, + logLevel: "DEBUG", + version: props.version, + commitId: props.commitId, + additionalPolicies: [ + props.processingStatusTable.processStatusTableReadPolicy, + ] + }) + // Outputs this.fooLambda = fooLambda + this.createLambda = createLambda + this.processLambda = processLambda + this.pollLambda = pollLambda } } diff --git a/packages/cdk/resources/RestApiGateway/RestApiGatewayMethods.ts b/packages/cdk/resources/RestApiGateway/RestApiGatewayMethods.ts index fb6e8fa..1e0ae54 100644 --- a/packages/cdk/resources/RestApiGateway/RestApiGatewayMethods.ts +++ b/packages/cdk/resources/RestApiGateway/RestApiGatewayMethods.ts @@ -5,7 +5,7 @@ import { RestApi } from "aws-cdk-lib/aws-apigateway" import {Construct} from "constructs" -import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs" +import {NodejsFunction} from "aws-cdk-lib/aws-lambda-nodejs" // import {NodejsFunction} from "aws-cdk-lib/aws-lambda-nodejs" export interface RestApiGatewayMethodsProps { @@ -13,6 +13,8 @@ export interface RestApiGatewayMethodsProps { readonly restAPiGatewayRole: IRole readonly restApiGateway: RestApi readonly fooLambda: NodejsFunction + readonly createLambda: NodejsFunction + readonly pollLambda: NodejsFunction } /** @@ -35,11 +37,24 @@ export class RestApiGatewayMethods extends Construct { const prescriptionDetailsLambdaResource = props.restApiGateway.root.addResource("foo") prescriptionDetailsLambdaResource.addMethod("GET", new LambdaIntegration(props.fooLambda, { - credentialsRole: props.restAPiGatewayRole - }), { - authorizationType: AuthorizationType.NONE, - }) - + credentialsRole: props.restAPiGatewayRole + }), { + authorizationType: AuthorizationType.NONE, + }) + + const createPrescriptionLambdaResource = props.restApiGateway.root.addResource("create") + createPrescriptionLambdaResource.addMethod("GET", new LambdaIntegration(props.createLambda, { + credentialsRole: props.restAPiGatewayRole + }), { + authorizationType: AuthorizationType.NONE, + }) + + const pollPrescriptionLambdaResource = props.restApiGateway.root.addResource("poll") + pollPrescriptionLambdaResource.addMethod("POST", new LambdaIntegration(props.pollLambda, { + credentialsRole: props.restAPiGatewayRole + }), { + authorizationType: AuthorizationType.NONE, + }) //Outputs } diff --git a/packages/cdk/stacks/HackStack.ts b/packages/cdk/stacks/HackStack.ts index 2d9174e..d3dfec5 100644 --- a/packages/cdk/stacks/HackStack.ts +++ b/packages/cdk/stacks/HackStack.ts @@ -11,18 +11,19 @@ import {StaticContentBucket} from "../resources/StaticContentBucket" import {Certificate} from "aws-cdk-lib/aws-certificatemanager" import {Role} from "aws-cdk-lib/aws-iam" import {HostedZone} from "aws-cdk-lib/aws-route53" -import { Key } from "aws-cdk-lib/aws-kms" -import { Stream } from "aws-cdk-lib/aws-kinesis" -import { ukRegionLogGroups } from "../resources/ukRegionLogGroups" -import { RestApiGateway } from "../resources/RestApiGateway" -import { RestApiGatewayMethods } from "../resources/RestApiGateway/RestApiGatewayMethods" -import { RestApiOrigin, S3BucketOrigin } from "aws-cdk-lib/aws-cloudfront-origins" -import { AccessLevel, AllowedMethods, FunctionEventType, OriginRequestCookieBehavior, OriginRequestHeaderBehavior, OriginRequestPolicy, OriginRequestQueryStringBehavior, ViewerProtocolPolicy } from "aws-cdk-lib/aws-cloudfront" -import { CloudfrontBehaviors } from "../resources/CloudfrontBehaviors" -import { CloudfrontDistribution } from "../resources/CloudfrontDistribution" -import { getConfigFromEnvVar } from "@nhsdigital/eps-cdk-constructs" -import { ApiFunctions } from "../resources/Functions" -import { addNagSuppressions } from "./nagSuppression" +import {Key} from "aws-cdk-lib/aws-kms" +import {Stream} from "aws-cdk-lib/aws-kinesis" +import {ukRegionLogGroups} from "../resources/ukRegionLogGroups" +import {RestApiGateway} from "../resources/RestApiGateway" +import {RestApiGatewayMethods} from "../resources/RestApiGateway/RestApiGatewayMethods" +import {RestApiOrigin, S3BucketOrigin} from "aws-cdk-lib/aws-cloudfront-origins" +import {AccessLevel, AllowedMethods, FunctionEventType, OriginRequestCookieBehavior, OriginRequestHeaderBehavior, OriginRequestPolicy, OriginRequestQueryStringBehavior, ViewerProtocolPolicy} from "aws-cdk-lib/aws-cloudfront" +import {CloudfrontBehaviors} from "../resources/CloudfrontBehaviors" +import {CloudfrontDistribution} from "../resources/CloudfrontDistribution" +import {getConfigFromEnvVar} from "@nhsdigital/eps-cdk-constructs" +import {ApiFunctions} from "../resources/Functions" +import {addNagSuppressions} from "./nagSuppression" +import {Dynamodb} from "../resources/DynamoDb" export interface HackStackProps extends StackProps { readonly serviceName: string @@ -37,7 +38,7 @@ export interface HackStackProps extends StackProps { */ export class HackStack extends Stack { - public constructor(scope: App, id: string, props: HackStackProps){ + public constructor(scope: App, id: string, props: HackStackProps) { super(scope, id, props) // Context @@ -93,6 +94,9 @@ export class HackStack extends Stack { wafLogGroupName: `aws-waf-logs-${props.serviceName}-apigw`, stackName: this.stackName }) + const dyna = new Dynamodb(this, "Dynamodb", { + stackName: props.stackName + }) const apiGateway = new RestApiGateway(this, "ApiGateway", { serviceName: props.serviceName, stackName: props.stackName, @@ -106,15 +110,20 @@ export class HackStack extends Stack { serviceName: props.serviceName, stackName: props.stackName, version: "1.0.0", - commitId: "abc123" + commitId: "abc123", + processingStatusTable: dyna }) const apiMethods = new RestApiGatewayMethods(this, "RestApiGatewayMethods", { executePolices: [ - functions.fooLambda.executionPolicy + functions.fooLambda.executionPolicy, + functions.createLambda.executionPolicy, + functions.pollLambda.executionPolicy ], restAPiGatewayRole: apiGateway.apiGatewayRole, restApiGateway: apiGateway.apiGateway, - fooLambda: functions.fooLambda.function + fooLambda: functions.fooLambda.function, + createLambda: functions.createLambda.function, + pollLambda: functions.pollLambda.function, }) const staticContentBucketOrigin = S3BucketOrigin.withOriginAccessControl( staticContentBucket.bucket, @@ -141,7 +150,7 @@ export class HackStack extends Stack { apiGatewayRequestPolicy: apiGatewayRequestPolicy, staticContentBucketOrigin: staticContentBucketOrigin, }) - + // --- Distribution const cloudfrontDistribution = new CloudfrontDistribution(this, "CloudfrontDistribution", { serviceName: props.serviceName, @@ -176,6 +185,7 @@ export class HackStack extends Stack { ] }) + // Outputs // Exports diff --git a/packages/cdk/stacks/nagSuppression.ts b/packages/cdk/stacks/nagSuppression.ts index 82bd4a7..fbf28ed 100644 --- a/packages/cdk/stacks/nagSuppression.ts +++ b/packages/cdk/stacks/nagSuppression.ts @@ -84,6 +84,66 @@ export const addNagSuppressions = (stack: Stack) => { } ] ) + safeAddNagSuppression( + stack, + "/HackStack/Dynamodb/ProcessStatusWriteManagedPolicy/Resource", + [ + { + id: "AwsSolutions-IAM5", + reason: "this is for hack day stack" + } + ] + ) + safeAddNagSuppression( + stack, + "/HackStack/Dynamodb/ProcessStatusReadManagedPolicy/Resource", + [ + { + id: "AwsSolutions-IAM5", + reason: "this is for hack day stack" + } + ] + ) + safeAddNagSuppression( + stack, + "/HackStack/ApiGateway/ApiGateway/Default/create/GET/Resource", + [ + { + id: "AwsSolutions-APIG4", + reason: "this is for hack day stack - no auth is fine (for now)" + } + ] + ) + safeAddNagSuppression( + stack, + "/HackStack/ApiGateway/ApiGateway/Default/create/GET/Resource", + [ + { + id: "AwsSolutions-COG4", + reason: "this is for hack day stack - no auth is fine" + } + ] + ) + safeAddNagSuppression( + stack, + "/HackStack/ApiGateway/ApiGateway/Default/poll/GET/Resource", + [ + { + id: "AwsSolutions-APIG4", + reason: "this is for hack day stack - no auth is fine (for now)" + } + ] + ) + safeAddNagSuppression( + stack, + "/HackStack/ApiGateway/ApiGateway/Default/poll/GET/Resource", + [ + { + id: "AwsSolutions-COG4", + reason: "this is for hack day stack - no auth is fine" + } + ] + ) } diff --git a/packages/create/package.json b/packages/create/package.json new file mode 100644 index 0000000..ae40f08 --- /dev/null +++ b/packages/create/package.json @@ -0,0 +1,29 @@ +{ + "name": "create", + "version": "1.0.0", + "description": "Lambda of the create endpoint", + "main": "handler.js", + "author": "NHS Digital", + "license": "MIT", + "scripts": { + "unit": "POWERTOOLS_DEV=true NODE_OPTIONS=--experimental-vm-modules jest --no-cache --coverage", + "lint": "eslint --max-warnings 0 --fix --config ../../eslint.config.mjs .", + "compile": "tsc --build", + "test": "npm run compile && npm run unit", + "check-licenses": "license-checker --failOn GPL --failOn LGPL --start ../.." + }, + "dependencies": { + "@aws-lambda-powertools/commons": "^2.30.2", + "@aws-lambda-powertools/logger": "^2.30.2", + "@aws-lambda-powertools/parameters": "^2.30.2", + "@aws-sdk/client-lambda": "^3.986.0", + "@middy/core": "^7.0.2", + "@middy/input-output-logger": "^7.0.2", + "@nhs/fhir-middy-error-handler": "^2.1.71", + "@nhsdigital/eps-spine-client": "^2.1.78" + }, + "devDependencies": { + "axios-mock-adapter": "^2.1.0", + "esbuild": "^0.27.2" + } +} diff --git a/packages/create/src/handler.ts b/packages/create/src/handler.ts new file mode 100644 index 0000000..4665a4f --- /dev/null +++ b/packages/create/src/handler.ts @@ -0,0 +1,59 @@ +import {Logger} from "@aws-lambda-powertools/logger" +import {InvokeCommand, LambdaClient, LogType} from "@aws-sdk/client-lambda" +import {injectLambdaContext} from "@aws-lambda-powertools/logger/middleware" +import middy from "@middy/core" +import inputOutputLogger from "@middy/input-output-logger" +import errorHandler from "@nhs/fhir-middy-error-handler" + +import {randomUUID, UUID} from "node:crypto" + +const logger = new Logger({serviceName: "create"}) + +const invoke = async (funcName: string, payload: any) => { + const client = new LambdaClient({}); + const command = new InvokeCommand({ + FunctionName: funcName, + InvocationType: "Event", // asynchronous invocation + Payload: JSON.stringify(payload) + }); + + await client.send(command) +}; + +const lambdaHandler = async (event: any): Promise => { + logger.appendKeys({ + "nhsd-correlation-id": event.headers["nhsd-correlation-id"], + "x-request-id": event.headers["x-request-id"], + "nhsd-request-id": event.headers["nhsd-request-id"], + "x-correlation-id": event.headers["x-correlation-id"], + "apigw-request-id": event.requestContext.requestId + }) + + // Create an empty record in dynamo with a new uuid + const uuid: UUID = randomUUID() + logger.info("invoking processing lambda", {processingLambdaName: process.env.PROCESSING_LAMBDA_NAME, id: uuid}) + await invoke(process.env.PROCESSING_LAMBDA_NAME!, {id: uuid}) + + // immediately return 200 and the newly created ID + const createBody = {id: uuid} + + return { + statusCode: 200, + body: JSON.stringify(createBody), + headers: { + "Content-Type": "application/health+json", + "Cache-Control": "no-cache" + } + } +} + +export const handler = middy(lambdaHandler) + .use(injectLambdaContext(logger, {clearState: true})) + .use( + inputOutputLogger({ + logger: (request) => { + logger.info(request) + } + }) + ) + .use(errorHandler({logger: logger})) diff --git a/packages/create/tsconfig.json b/packages/create/tsconfig.json new file mode 100644 index 0000000..d26c8f0 --- /dev/null +++ b/packages/create/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.defaults.json", + "compilerOptions": { + "rootDir": ".", + "outDir": "lib" + }, + "include": ["src/**/*", "tests/**/*"], + "exclude": ["node_modules"] +} \ No newline at end of file diff --git a/packages/poll/package.json b/packages/poll/package.json new file mode 100644 index 0000000..bf7efb9 --- /dev/null +++ b/packages/poll/package.json @@ -0,0 +1,29 @@ +{ + "name": "poll", + "version": "1.0.0", + "description": "Lambda of the poll endpoint", + "main": "handler.js", + "author": "NHS Digital", + "license": "MIT", + "scripts": { + "unit": "POWERTOOLS_DEV=true NODE_OPTIONS=--experimental-vm-modules jest --no-cache --coverage", + "lint": "eslint --max-warnings 0 --fix --config ../../eslint.config.mjs .", + "compile": "tsc --build", + "test": "npm run compile && npm run unit", + "check-licenses": "license-checker --failOn GPL --failOn LGPL --start ../.." + }, + "dependencies": { + "@aws-lambda-powertools/commons": "^2.30.2", + "@aws-lambda-powertools/logger": "^2.30.2", + "@aws-lambda-powertools/parameters": "^2.30.2", + "@aws-sdk/client-dynamodb": "^3.986.0", + "@middy/core": "^7.0.2", + "@middy/input-output-logger": "^7.0.2", + "@nhs/fhir-middy-error-handler": "^2.1.71", + "@nhsdigital/eps-spine-client": "^2.1.78" + }, + "devDependencies": { + "axios-mock-adapter": "^2.1.0", + "esbuild": "^0.27.2" + } +} diff --git a/packages/poll/src/dynamo.ts b/packages/poll/src/dynamo.ts new file mode 100644 index 0000000..936cd1d --- /dev/null +++ b/packages/poll/src/dynamo.ts @@ -0,0 +1,40 @@ +import {Logger} from "@aws-lambda-powertools/logger" +import {DynamoDBClient, GetItemCommand, GetItemCommandInput} from "@aws-sdk/client-dynamodb" + +const client = new DynamoDBClient() +const tableName = process.env.PROCESSING_STATUS_TABLE_NAME! + +export async function queryActionState( + actionID: string, + logger: Logger +): Promise> { + const query: GetItemCommandInput = { + TableName: tableName, + Key: { + actionId: {S: actionID} + } + } + + logger.info("Getting DynamoDB item for action ID", { + actionID, + tableName, + }) + + try { + const result = await client.send(new GetItemCommand(query)) + const items = result.Item ? [result.Item] : [] + + logger.info("Retrieved records from DynamoDB", { + actionID, + recordCount: items.length + }) + + return items + } catch (err) { + logger.error("Error getting DynamoDB item for existing prescription records", { + actionID, + error: err + }) + throw err + } +} diff --git a/packages/poll/src/handler.ts b/packages/poll/src/handler.ts new file mode 100644 index 0000000..496773f --- /dev/null +++ b/packages/poll/src/handler.ts @@ -0,0 +1,57 @@ +import {Logger} from "@aws-lambda-powertools/logger" +import {injectLambdaContext} from "@aws-lambda-powertools/logger/middleware" +import middy from "@middy/core" +import inputOutputLogger from "@middy/input-output-logger" +import errorHandler from "@nhs/fhir-middy-error-handler" + +import {queryActionState} from "./dynamo" + +const logger = new Logger({serviceName: "poll"}) + +const lambdaHandler = async (event: any): Promise => { + logger.appendKeys({ + "nhsd-correlation-id": event.headers["nhsd-correlation-id"], + "x-request-id": event.headers["x-request-id"], + "nhsd-request-id": event.headers["nhsd-request-id"], + "x-correlation-id": event.headers["x-correlation-id"], + "apigw-request-id": event.requestContext.requestId + }) + + // take the action ID from the body and use it to query the DynamoDB table for any existing records with that action ID + const body = event.body ? JSON.parse(event.body) : null + + if (!body || !body.actionid) { + logger.warn("No action ID provided in request body") + return { + statusCode: 400, + body: JSON.stringify({message: "Missing required body parameter: actionid"}), + headers: { + "Content-Type": "application/json", + "Cache-Control": "no-cache" + } + } + } + + const actionID = body.actionid + const result = await queryActionState(actionID, logger) + + return { + statusCode: 200, + body: JSON.stringify(result), + headers: { + "Content-Type": "application/health+json", + "Cache-Control": "no-cache" + } + } +} + +export const handler = middy(lambdaHandler) + .use(injectLambdaContext(logger, {clearState: true})) + .use( + inputOutputLogger({ + logger: (request) => { + logger.info(request) + } + }) + ) + .use(errorHandler({logger: logger})) diff --git a/packages/poll/tsconfig.json b/packages/poll/tsconfig.json new file mode 100644 index 0000000..d26c8f0 --- /dev/null +++ b/packages/poll/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.defaults.json", + "compilerOptions": { + "rootDir": ".", + "outDir": "lib" + }, + "include": ["src/**/*", "tests/**/*"], + "exclude": ["node_modules"] +} \ No newline at end of file diff --git a/packages/process/package.json b/packages/process/package.json new file mode 100644 index 0000000..b711ae3 --- /dev/null +++ b/packages/process/package.json @@ -0,0 +1,28 @@ +{ + "name": "process", + "version": "1.0.0", + "description": "Lambda of the procss endpoint", + "main": "status.js", + "author": "NHS Digital", + "license": "MIT", + "scripts": { + "unit": "POWERTOOLS_DEV=true NODE_OPTIONS=--experimental-vm-modules jest --no-cache --coverage", + "lint": "eslint --max-warnings 0 --fix --config ../../eslint.config.mjs .", + "compile": "tsc --build", + "test": "npm run compile && npm run unit", + "check-licenses": "license-checker --failOn GPL --failOn LGPL --start ../.." + }, + "dependencies": { + "@aws-lambda-powertools/commons": "^2.30.2", + "@aws-lambda-powertools/logger": "^2.30.2", + "@aws-lambda-powertools/parameters": "^2.30.2", + "@middy/core": "^7.0.2", + "@middy/input-output-logger": "^7.0.2", + "@nhs/fhir-middy-error-handler": "^2.1.71", + "@nhsdigital/eps-spine-client": "^2.1.78" + }, + "devDependencies": { + "axios-mock-adapter": "^2.1.0", + "esbuild": "^0.27.2" + } +} \ No newline at end of file diff --git a/packages/process/src/handler.ts b/packages/process/src/handler.ts new file mode 100644 index 0000000..a70e521 --- /dev/null +++ b/packages/process/src/handler.ts @@ -0,0 +1,59 @@ +import {Logger} from "@aws-lambda-powertools/logger" +import {injectLambdaContext} from "@aws-lambda-powertools/logger/middleware" +import middy from "@middy/core" +import inputOutputLogger from "@middy/input-output-logger" +import errorHandler from "@nhs/fhir-middy-error-handler" +import crypto from "crypto" + +const logger = new Logger({serviceName: "process"}) + +const generateUuid = (): string => { + if (typeof crypto.randomUUID === "function") { + return crypto.randomUUID() + } + + const bytes = crypto.randomBytes(16) + bytes[6] = (bytes[6] & 0x0f) | 0x40 + bytes[8] = (bytes[8] & 0x3f) | 0x80 + const hex = bytes.toString("hex") + return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}` +} + + +const lambdaHandler = async (event: any): Promise => { + const requestId = event.headers["x-request-id"] ?? generateUuid() + + logger.appendKeys({ + "nhsd-correlation-id": event.headers["nhsd-correlation-id"], + "x-request-id": requestId, + "nhsd-request-id": event.headers["nhsd-request-id"], + "x-correlation-id": event.headers["x-correlation-id"], + "apigw-request-id": event.requestContext.requestId + }) + + const commitId = process.env.COMMIT_ID + const versionNumber = process.env.VERSION_NUMBER + + + const statusBody = {commitId: commitId, versionNumber: versionNumber} + + return { + statusCode: 200, + body: JSON.stringify(statusBody), + headers: { + "Content-Type": "application/health+json", + "Cache-Control": "no-cache" + } + } +} + +export const handler = middy(lambdaHandler) + .use(injectLambdaContext(logger, {clearState: true})) + .use( + inputOutputLogger({ + logger: (request) => { + logger.info(request) + } + }) + ) + .use(errorHandler({logger: logger})) diff --git a/packages/process/tsconfig.json b/packages/process/tsconfig.json new file mode 100644 index 0000000..d26c8f0 --- /dev/null +++ b/packages/process/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.defaults.json", + "compilerOptions": { + "rootDir": ".", + "outDir": "lib" + }, + "include": ["src/**/*", "tests/**/*"], + "exclude": ["node_modules"] +} \ No newline at end of file