@middy/ssm 6.1.6 → 6.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/index.d.ts +36 -30
  2. package/index.js +190 -188
  3. package/package.json +71 -74
package/index.d.ts CHANGED
@@ -1,40 +1,46 @@
1
- import middy from '@middy/core'
2
- import { Options as MiddyOptions } from '@middy/util'
3
- import { Context as LambdaContext } from 'aws-lambda'
4
- import { SSMClient, SSMClientConfig } from '@aws-sdk/client-ssm'
1
+ import type { SSMClient, SSMClientConfig } from "@aws-sdk/client-ssm";
2
+ import type middy from "@middy/core";
3
+ import type { Options as MiddyOptions } from "@middy/util";
4
+ import type { Context as LambdaContext } from "aws-lambda";
5
5
 
6
- export type ParamType<T> = string & { __returnType?: T }
7
- export declare function ssmParam<T> (path: string): ParamType<T>
6
+ export type ParamType<T> = string & { __returnType?: T };
7
+ export declare function ssmParam<T>(path: string): ParamType<T>;
8
8
 
9
9
  export interface SSMOptions<AwsSSMClient = SSMClient>
10
- extends Omit<MiddyOptions<AwsSSMClient, SSMClientConfig>, 'fetchData'> {
11
- fetchData?: { [key: string]: string | ParamType<unknown> }
10
+ extends Omit<MiddyOptions<AwsSSMClient, SSMClientConfig>, "fetchData"> {
11
+ fetchData?: { [key: string]: string | ParamType<unknown> };
12
12
  }
13
13
 
14
14
  export type Context<TOptions extends SSMOptions | undefined> =
15
- TOptions extends { setToContext: true }
16
- ? TOptions extends { fetchData: infer TFetchData }
17
- ? LambdaContext & {
18
- [Key in keyof TFetchData]: TFetchData[Key] extends ParamType<infer T>
19
- ? T
20
- : unknown
21
- }
22
- : never
23
- : LambdaContext
15
+ TOptions extends { setToContext: true }
16
+ ? TOptions extends { fetchData: infer TFetchData }
17
+ ? LambdaContext & {
18
+ [Key in keyof TFetchData]: TFetchData[Key] extends ParamType<infer T>
19
+ ? T
20
+ : unknown;
21
+ }
22
+ : never
23
+ : LambdaContext;
24
24
 
25
25
  export type Internal<TOptions extends SSMOptions | undefined> =
26
- TOptions extends SSMOptions
27
- ? TOptions extends { fetchData: infer TFetchData }
28
- ? {
29
- [Key in keyof TFetchData]: TFetchData[Key] extends ParamType<infer T>
30
- ? T
31
- : unknown
32
- }
33
- : {}
34
- : {}
26
+ TOptions extends SSMOptions
27
+ ? TOptions extends { fetchData: infer TFetchData }
28
+ ? {
29
+ [Key in keyof TFetchData]: TFetchData[Key] extends ParamType<infer T>
30
+ ? T
31
+ : unknown;
32
+ }
33
+ : {}
34
+ : {};
35
35
 
36
- declare function ssm<TOptions extends SSMOptions> (
37
- options?: TOptions
38
- ): middy.MiddlewareObj<unknown, any, Error, Context<TOptions>, Internal<TOptions>>
36
+ declare function ssm<TOptions extends SSMOptions>(
37
+ options?: TOptions,
38
+ ): middy.MiddlewareObj<
39
+ unknown,
40
+ any,
41
+ Error,
42
+ Context<TOptions>,
43
+ Internal<TOptions>
44
+ >;
39
45
 
40
- export default ssm
46
+ export default ssm;
package/index.js CHANGED
@@ -1,196 +1,198 @@
1
1
  import {
2
- canPrefetch,
3
- createPrefetchClient,
4
- createClient,
5
- processCache,
6
- getCache,
7
- modifyCache,
8
- jsonSafeParse,
9
- getInternal,
10
- sanitizeKey,
11
- catchInvalidSignatureException
12
- } from '../util/index.js'
2
+ GetParametersByPathCommand,
3
+ GetParametersCommand,
4
+ SSMClient,
5
+ } from "@aws-sdk/client-ssm";
13
6
  import {
14
- SSMClient,
15
- GetParametersCommand,
16
- GetParametersByPathCommand
17
- } from '@aws-sdk/client-ssm'
18
-
19
- const awsRequestLimit = 10
7
+ canPrefetch,
8
+ catchInvalidSignatureException,
9
+ createClient,
10
+ createPrefetchClient,
11
+ getCache,
12
+ getInternal,
13
+ jsonSafeParse,
14
+ modifyCache,
15
+ processCache,
16
+ sanitizeKey,
17
+ } from "../util/index.js";
18
+
19
+ const awsRequestLimit = 10;
20
20
  const defaults = {
21
- AwsClient: SSMClient, // Allow for XRay
22
- awsClientOptions: {},
23
- awsClientAssumeRole: undefined,
24
- awsClientCapture: undefined,
25
- fetchData: {}, // { contextKey: fetchKey, contextPrefix: fetchPath/ }
26
- disablePrefetch: false,
27
- cacheKey: 'ssm',
28
- cacheKeyExpiry: {},
29
- cacheExpiry: -1,
30
- setToContext: false
31
- }
21
+ AwsClient: SSMClient, // Allow for XRay
22
+ awsClientOptions: {},
23
+ awsClientAssumeRole: undefined,
24
+ awsClientCapture: undefined,
25
+ fetchData: {}, // { contextKey: fetchKey, contextPrefix: fetchPath/ }
26
+ disablePrefetch: false,
27
+ cacheKey: "ssm",
28
+ cacheKeyExpiry: {},
29
+ cacheExpiry: -1,
30
+ setToContext: false,
31
+ };
32
32
 
33
33
  const ssmMiddleware = (opts = {}) => {
34
- const options = { ...defaults, ...opts }
35
-
36
- const fetchRequest = (request, cachedValues) => {
37
- return {
38
- ...fetchSingleRequest(request, cachedValues),
39
- ...fetchByPathRequest(request, cachedValues)
40
- }
41
- }
42
-
43
- const fetchSingleRequest = (request, cachedValues = {}) => {
44
- const values = {}
45
- let batchReq = null
46
- let batchInternalKeys = []
47
- let batchFetchKeys = []
48
- const namedKeys = []
49
-
50
- const internalKeys = Object.keys(options.fetchData)
51
- const fetchKeys = Object.values(options.fetchData)
52
- for (const internalKey of internalKeys) {
53
- if (cachedValues[internalKey]) continue
54
- if (options.fetchData[internalKey].substr(-1) === '/') continue // Skip path passed in
55
- namedKeys.push(internalKey)
56
- }
57
-
58
- for (const [idx, internalKey] of namedKeys.entries()) {
59
- const fetchKey = options.fetchData[internalKey]
60
- batchInternalKeys.push(internalKey)
61
- batchFetchKeys.push(fetchKey)
62
- // from the first to the batch size skip, unless it's the last entry
63
- if (
64
- (!idx || (idx + 1) % awsRequestLimit !== 0) &&
65
- !(idx + 1 === namedKeys.length)
66
- ) {
67
- continue
68
- }
69
-
70
- const command = new GetParametersCommand({
71
- Names: batchFetchKeys,
72
- WithDecryption: true
73
- })
74
- batchReq = client
75
- .send(command)
76
- .catch((e) => catchInvalidSignatureException(e, client, command))
77
- .then((resp) => {
78
- // Don't sanitize key, mapped to set value in options
79
- return Object.assign(
80
- ...(resp.InvalidParameters ?? []).map((fetchKey) => {
81
- return {
82
- [fetchKey]: new Promise(() => {
83
- const internalKey = internalKeys[fetchKeys.indexOf(fetchKey)]
84
- const value = getCache(options.cacheKey).value ?? {}
85
- value[internalKey] = undefined
86
- modifyCache(options.cacheKey, value)
87
- throw new Error('InvalidParameter ' + fetchKey, {
88
- cause: { package: '@middy/ssm' }
89
- })
90
- })
91
- }
92
- }),
93
- ...(resp.Parameters ?? []).map((param) => {
94
- return { [param.Name]: parseValue(param) }
95
- })
96
- )
97
- })
98
- .catch((e) => {
99
- const value = getCache(options.cacheKey).value ?? {}
100
- value[internalKey] = undefined
101
- modifyCache(options.cacheKey, value)
102
- throw e
103
- })
104
-
105
- for (const internalKey of batchInternalKeys) {
106
- values[internalKey] = batchReq.then((params) => {
107
- return params[options.fetchData[internalKey]]
108
- })
109
- }
110
-
111
- batchInternalKeys = []
112
- batchFetchKeys = []
113
- batchReq = null
114
- }
115
- return values
116
- }
117
-
118
- const fetchByPathRequest = (request, cachedValues = {}) => {
119
- const values = {}
120
- for (const internalKey in options.fetchData) {
121
- if (cachedValues[internalKey]) continue
122
- const fetchKey = options.fetchData[internalKey]
123
- if (fetchKey.substr(-1) !== '/') continue // Skip not path passed in
124
- values[internalKey] = fetchPathRequest(fetchKey).catch((e) => {
125
- const value = getCache(options.cacheKey).value ?? {}
126
- value[internalKey] = undefined
127
- modifyCache(options.cacheKey, value)
128
- throw e
129
- })
130
- }
131
- return values
132
- }
133
-
134
- const fetchPathRequest = (path, nextToken, values = {}) => {
135
- const command = new GetParametersByPathCommand({
136
- Path: path,
137
- NextToken: nextToken,
138
- Recursive: true,
139
- WithDecryption: true
140
- })
141
- return client
142
- .send(command)
143
- .catch((e) => catchInvalidSignatureException(e, client, command))
144
- .then((resp) => {
145
- Object.assign(
146
- values,
147
- ...resp.Parameters.map((param) => {
148
- return {
149
- [sanitizeKey(param.Name.replace(path, ''))]: parseValue(param)
150
- }
151
- })
152
- )
153
- if (resp.NextToken) { return fetchPathRequest(path, resp.NextToken, values) }
154
- return values
155
- })
156
- }
157
-
158
- const parseValue = (param) => {
159
- if (param.Type === 'StringList') {
160
- return param.Value.split(',')
161
- }
162
- return jsonSafeParse(param.Value)
163
- }
164
-
165
- let client
166
- if (canPrefetch(options)) {
167
- client = createPrefetchClient(options)
168
- processCache(options, fetchRequest)
169
- }
170
-
171
- const ssmMiddlewareBefore = async (request) => {
172
- if (!client) {
173
- client = await createClient(options, request)
174
- }
175
-
176
- const { value } = processCache(options, fetchRequest, request)
177
-
178
- Object.assign(request.internal, value)
179
-
180
- if (options.setToContext) {
181
- const data = await getInternal(Object.keys(options.fetchData), request)
182
- Object.assign(request.context, data)
183
- }
184
- }
185
-
186
- return {
187
- before: ssmMiddlewareBefore
188
- }
189
- }
190
-
191
- export default ssmMiddleware
34
+ const options = { ...defaults, ...opts };
35
+
36
+ const fetchRequest = (request, cachedValues) => {
37
+ return {
38
+ ...fetchSingleRequest(request, cachedValues),
39
+ ...fetchByPathRequest(request, cachedValues),
40
+ };
41
+ };
42
+
43
+ const fetchSingleRequest = (request, cachedValues = {}) => {
44
+ const values = {};
45
+ let batchReq = null;
46
+ let batchInternalKeys = [];
47
+ let batchFetchKeys = [];
48
+ const namedKeys = [];
49
+
50
+ const internalKeys = Object.keys(options.fetchData);
51
+ const fetchKeys = Object.values(options.fetchData);
52
+ for (const internalKey of internalKeys) {
53
+ if (cachedValues[internalKey]) continue;
54
+ if (options.fetchData[internalKey].substr(-1) === "/") continue; // Skip path passed in
55
+ namedKeys.push(internalKey);
56
+ }
57
+
58
+ for (const [idx, internalKey] of namedKeys.entries()) {
59
+ const fetchKey = options.fetchData[internalKey];
60
+ batchInternalKeys.push(internalKey);
61
+ batchFetchKeys.push(fetchKey);
62
+ // from the first to the batch size skip, unless it's the last entry
63
+ if (
64
+ (!idx || (idx + 1) % awsRequestLimit !== 0) &&
65
+ !(idx + 1 === namedKeys.length)
66
+ ) {
67
+ continue;
68
+ }
69
+
70
+ const command = new GetParametersCommand({
71
+ Names: batchFetchKeys,
72
+ WithDecryption: true,
73
+ });
74
+ batchReq = client
75
+ .send(command)
76
+ .catch((e) => catchInvalidSignatureException(e, client, command))
77
+ .then((resp) => {
78
+ // Don't sanitize key, mapped to set value in options
79
+ return Object.assign(
80
+ ...(resp.InvalidParameters ?? []).map((fetchKey) => {
81
+ return {
82
+ [fetchKey]: new Promise(() => {
83
+ const internalKey = internalKeys[fetchKeys.indexOf(fetchKey)];
84
+ const value = getCache(options.cacheKey).value ?? {};
85
+ value[internalKey] = undefined;
86
+ modifyCache(options.cacheKey, value);
87
+ throw new Error(`InvalidParameter ${fetchKey}`, {
88
+ cause: { package: "@middy/ssm" },
89
+ });
90
+ }),
91
+ };
92
+ }),
93
+ ...(resp.Parameters ?? []).map((param) => {
94
+ return { [param.Name]: parseValue(param) };
95
+ }),
96
+ );
97
+ })
98
+ .catch((e) => {
99
+ const value = getCache(options.cacheKey).value ?? {};
100
+ value[internalKey] = undefined;
101
+ modifyCache(options.cacheKey, value);
102
+ throw e;
103
+ });
104
+
105
+ for (const internalKey of batchInternalKeys) {
106
+ values[internalKey] = batchReq.then((params) => {
107
+ return params[options.fetchData[internalKey]];
108
+ });
109
+ }
110
+
111
+ batchInternalKeys = [];
112
+ batchFetchKeys = [];
113
+ batchReq = null;
114
+ }
115
+ return values;
116
+ };
117
+
118
+ const fetchByPathRequest = (request, cachedValues = {}) => {
119
+ const values = {};
120
+ for (const internalKey in options.fetchData) {
121
+ if (cachedValues[internalKey]) continue;
122
+ const fetchKey = options.fetchData[internalKey];
123
+ if (fetchKey.substr(-1) !== "/") continue; // Skip not path passed in
124
+ values[internalKey] = fetchPathRequest(fetchKey).catch((e) => {
125
+ const value = getCache(options.cacheKey).value ?? {};
126
+ value[internalKey] = undefined;
127
+ modifyCache(options.cacheKey, value);
128
+ throw e;
129
+ });
130
+ }
131
+ return values;
132
+ };
133
+
134
+ const fetchPathRequest = (path, nextToken, values = {}) => {
135
+ const command = new GetParametersByPathCommand({
136
+ Path: path,
137
+ NextToken: nextToken,
138
+ Recursive: true,
139
+ WithDecryption: true,
140
+ });
141
+ return client
142
+ .send(command)
143
+ .catch((e) => catchInvalidSignatureException(e, client, command))
144
+ .then((resp) => {
145
+ Object.assign(
146
+ values,
147
+ ...resp.Parameters.map((param) => {
148
+ return {
149
+ [sanitizeKey(param.Name.replace(path, ""))]: parseValue(param),
150
+ };
151
+ }),
152
+ );
153
+ if (resp.NextToken) {
154
+ return fetchPathRequest(path, resp.NextToken, values);
155
+ }
156
+ return values;
157
+ });
158
+ };
159
+
160
+ const parseValue = (param) => {
161
+ if (param.Type === "StringList") {
162
+ return param.Value.split(",");
163
+ }
164
+ return jsonSafeParse(param.Value);
165
+ };
166
+
167
+ let client;
168
+ if (canPrefetch(options)) {
169
+ client = createPrefetchClient(options);
170
+ processCache(options, fetchRequest);
171
+ }
172
+
173
+ const ssmMiddlewareBefore = async (request) => {
174
+ if (!client) {
175
+ client = await createClient(options, request);
176
+ }
177
+
178
+ const { value } = processCache(options, fetchRequest, request);
179
+
180
+ Object.assign(request.internal, value);
181
+
182
+ if (options.setToContext) {
183
+ const data = await getInternal(Object.keys(options.fetchData), request);
184
+ Object.assign(request.context, data);
185
+ }
186
+ };
187
+
188
+ return {
189
+ before: ssmMiddlewareBefore,
190
+ };
191
+ };
192
+
193
+ export default ssmMiddleware;
192
194
 
193
195
  // used for TS type inference (see index.d.ts)
194
- export function ssmParam (name) {
195
- return name
196
+ export function ssmParam(name) {
197
+ return name;
196
198
  }
package/package.json CHANGED
@@ -1,76 +1,73 @@
1
1
  {
2
- "name": "@middy/ssm",
3
- "version": "6.1.6",
4
- "description": "SSM (EC2 Systems Manager) parameters middleware for the middy framework",
5
- "type": "module",
6
- "engines": {
7
- "node": ">=20"
8
- },
9
- "engineStrict": true,
10
- "publishConfig": {
11
- "access": "public"
12
- },
13
- "module": "./index.js",
14
- "exports": {
15
- ".": {
16
- "import": {
17
- "types": "./index.d.ts",
18
- "default": "./index.js"
19
- },
20
- "require": {
21
- "default": "./index.js"
22
- }
23
- }
24
- },
25
- "types": "index.d.ts",
26
- "files": [
27
- "index.js",
28
- "index.d.ts"
29
- ],
30
- "scripts": {
31
- "test": "npm run test:unit && npm run test:fuzz",
32
- "test:unit": "node --test __tests__/index.js",
33
- "test:fuzz": "node --test __tests__/fuzz.js",
34
- "test:benchmark": "node __benchmarks__/index.js"
35
- },
36
- "license": "MIT",
37
- "keywords": [
38
- "Lambda",
39
- "Middleware",
40
- "Serverless",
41
- "Framework",
42
- "AWS",
43
- "AWS Lambda",
44
- "Middy",
45
- "SSM",
46
- "EC2 Systems Manager",
47
- "Parameters"
48
- ],
49
- "author": {
50
- "name": "Middy contributors",
51
- "url": "https://github.com/middyjs/middy/graphs/contributors"
52
- },
53
- "repository": {
54
- "type": "git",
55
- "url": "git+https://github.com/middyjs/middy.git",
56
- "directory": "packages/ssm"
57
- },
58
- "bugs": {
59
- "url": "https://github.com/middyjs/middy/issues"
60
- },
61
- "homepage": "https://middy.js.org",
62
- "funding": {
63
- "type": "github",
64
- "url": "https://github.com/sponsors/willfarrell"
65
- },
66
- "dependencies": {
67
- "@middy/util": "6.1.6"
68
- },
69
- "devDependencies": {
70
- "@aws-sdk/client-ssm": "^3.0.0",
71
- "@middy/core": "6.1.6",
72
- "@types/aws-lambda": "^8.10.101",
73
- "aws-xray-sdk": "^3.3.3"
74
- },
75
- "gitHead": "7a6c0fbb8ab71d6a2171e678697de9f237568431"
2
+ "name": "@middy/ssm",
3
+ "version": "6.2.0",
4
+ "description": "SSM (EC2 Systems Manager) parameters middleware for the middy framework",
5
+ "type": "module",
6
+ "engines": {
7
+ "node": ">=20"
8
+ },
9
+ "engineStrict": true,
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "module": "./index.js",
14
+ "exports": {
15
+ ".": {
16
+ "import": {
17
+ "types": "./index.d.ts",
18
+ "default": "./index.js"
19
+ },
20
+ "require": {
21
+ "default": "./index.js"
22
+ }
23
+ }
24
+ },
25
+ "types": "index.d.ts",
26
+ "files": ["index.js", "index.d.ts"],
27
+ "scripts": {
28
+ "test": "npm run test:unit && npm run test:fuzz",
29
+ "test:unit": "node --test",
30
+ "test:fuzz": "node --test index.fuzz.js",
31
+ "test:perf": "node --test index.perf.js"
32
+ },
33
+ "license": "MIT",
34
+ "keywords": [
35
+ "Lambda",
36
+ "Middleware",
37
+ "Serverless",
38
+ "Framework",
39
+ "AWS",
40
+ "AWS Lambda",
41
+ "Middy",
42
+ "SSM",
43
+ "EC2 Systems Manager",
44
+ "Parameters"
45
+ ],
46
+ "author": {
47
+ "name": "Middy contributors",
48
+ "url": "https://github.com/middyjs/middy/graphs/contributors"
49
+ },
50
+ "repository": {
51
+ "type": "git",
52
+ "url": "git+https://github.com/middyjs/middy.git",
53
+ "directory": "packages/ssm"
54
+ },
55
+ "bugs": {
56
+ "url": "https://github.com/middyjs/middy/issues"
57
+ },
58
+ "homepage": "https://middy.js.org",
59
+ "funding": {
60
+ "type": "github",
61
+ "url": "https://github.com/sponsors/willfarrell"
62
+ },
63
+ "dependencies": {
64
+ "@middy/util": "6.2.0"
65
+ },
66
+ "devDependencies": {
67
+ "@aws-sdk/client-ssm": "^3.0.0",
68
+ "@middy/core": "6.2.0",
69
+ "@types/aws-lambda": "^8.10.101",
70
+ "aws-xray-sdk": "^3.3.3"
71
+ },
72
+ "gitHead": "7a6c0fbb8ab71d6a2171e678697de9f237568431"
76
73
  }