presidium 0.16.15 → 0.16.17

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.
package/.eslintrc.js CHANGED
@@ -210,7 +210,7 @@ module.exports = {
210
210
  'no-sequences': 'off',
211
211
  'no-shadow': 'off',
212
212
  'no-spaced-func': 'error',
213
- 'no-sync': 'error',
213
+ 'no-sync': 'off',
214
214
  'no-tabs': 'error',
215
215
  'no-template-curly-in-string': 'error',
216
216
  'no-ternary': 'off',
@@ -269,7 +269,7 @@ module.exports = {
269
269
  'single'
270
270
  ],
271
271
  'radix': 'error',
272
- 'require-atomic-updates': 'error',
272
+ 'require-atomic-updates': 'off',
273
273
  'require-await': 'off',
274
274
  'require-jsdoc': 'error',
275
275
  'require-unicode-regexp': 'off',
@@ -0,0 +1,61 @@
1
+ require('rubico/global')
2
+ const fs = require('fs')
3
+ const nodePath = require('path')
4
+ const pathResolve = require('./internal/pathResolve')
5
+
6
+ /**
7
+ * @name AwsCredentials
8
+ *
9
+ * @synopsis
10
+ * ```coffeescript [specscript]
11
+ * AwsCredentials(options {
12
+ * profile?: string,
13
+ * credentialsFileDir?: string,
14
+ * }) -> awsCreds {
15
+ * accessKeyId: string,
16
+ * secretAccessKey: string,
17
+ * }
18
+ *
19
+ * AwsCredentials(profile string) -> awsCreds {
20
+ * accessKeyId: string,
21
+ * secretAccessKey: string,
22
+ * }
23
+ * ```
24
+ */
25
+
26
+ const AwsCredentials = async function (options = {}) {
27
+ const profile = (
28
+ typeof options == 'string' ? options : options.profile
29
+ ) ?? 'default'
30
+
31
+ let credentialsFileDir =
32
+ options.credentialsFileDir ?? pathResolve(process.cwd())
33
+ let lines = ''
34
+ while (credentialsFileDir != '/') {
35
+ const credentialsFilePath =
36
+ pathResolve(credentialsFileDir, '.aws/credentials')
37
+ if (fs.existsSync(credentialsFilePath)) {
38
+ lines = await (
39
+ fs.promises.readFile(credentialsFilePath)
40
+ .then(buffer => `${buffer}`.split('\n'))
41
+ )
42
+ break
43
+ }
44
+ credentialsFileDir = pathResolve(credentialsFileDir, '..')
45
+ }
46
+
47
+ const startingLineNumber = lines.findIndex(line => line == `[${profile}]`)
48
+
49
+ const accessKeyId = lines.find(
50
+ (line, index) => index > startingLineNumber
51
+ && line.startsWith('aws_access_key_id')
52
+ ).split(' = ')[1]
53
+ const secretAccessKey = lines.find(
54
+ (line, index) => index > startingLineNumber
55
+ && line.startsWith('aws_secret_access_key')
56
+ ).split(' = ')[1]
57
+
58
+ return { accessKeyId, secretAccessKey }
59
+ }
60
+
61
+ module.exports = AwsCredentials
@@ -0,0 +1,45 @@
1
+ const Test = require('thunk-test')
2
+ const assert = require('assert')
3
+ const fs = require('fs')
4
+ const AwsCredentials = require('./AwsCredentials')
5
+
6
+ const test = new Test('AwsCredentials', async function () {
7
+ try {
8
+ await fs.promises.mkdir(`${__dirname}/.aws`)
9
+ } catch {
10
+ await fs.promises.rm(`${__dirname}/.aws`, { recursive: true })
11
+ await fs.promises.mkdir(`${__dirname}/.aws`)
12
+ }
13
+
14
+ await fs.promises.writeFile(`${__dirname}/.aws/credentials`, `
15
+ [default]
16
+ aws_access_key_id = AAA
17
+ aws_secret_access_key = FFF
18
+ `.trim())
19
+
20
+ {
21
+ const awsCreds = await AwsCredentials('default')
22
+ assert.equal(awsCreds.accessKeyId, 'AAA')
23
+ assert.equal(awsCreds.secretAccessKey, 'FFF')
24
+ }
25
+
26
+ {
27
+ const awsCreds = await AwsCredentials({ profile: 'default' })
28
+ assert.equal(awsCreds.accessKeyId, 'AAA')
29
+ assert.equal(awsCreds.secretAccessKey, 'FFF')
30
+ }
31
+
32
+ {
33
+ const awsCreds = await AwsCredentials()
34
+ assert.equal(awsCreds.accessKeyId, 'AAA')
35
+ assert.equal(awsCreds.secretAccessKey, 'FFF')
36
+ }
37
+
38
+ await fs.promises.rm(`${__dirname}/.aws`, { recursive: true })
39
+ }).case()
40
+
41
+ if (process.argv[1] == __filename) {
42
+ test()
43
+ }
44
+
45
+ module.exports = test
package/DynamoStream.js CHANGED
@@ -150,7 +150,16 @@ DynamoStream.prototype.getRecords = async function* getRecords(
150
150
  let records = await this.client.getRecords({
151
151
  ShardIterator: startingShardIterator,
152
152
  Limit: this.getRecordsLimit
153
- }).promise()
153
+ }).promise().catch(error => {
154
+ if (error.retryable) {
155
+ return this.client.getRecords({
156
+ ShardIterator: startingShardIterator,
157
+ Limit: this.getRecordsLimit
158
+ }).promise()
159
+ }
160
+ throw error
161
+ })
162
+
154
163
  if (records.Records.length > 0) {
155
164
  yield* records.Records.map(assign({
156
165
  table: always(this.table),
@@ -163,7 +172,16 @@ DynamoStream.prototype.getRecords = async function* getRecords(
163
172
  records = await this.client.getRecords({
164
173
  ShardIterator: records.NextShardIterator,
165
174
  Limit: this.getRecordsLimit
166
- }).promise()
175
+ }).promise().catch(error => {
176
+ if (error.retryable) {
177
+ return this.client.getRecords({
178
+ ShardIterator: records.NextShardIterator,
179
+ Limit: this.getRecordsLimit
180
+ }).promise()
181
+ }
182
+ throw error
183
+ })
184
+
167
185
  if (records.Records.length > 0) {
168
186
  yield* records.Records.map(assign({
169
187
  table: always(this.table),
@@ -38,6 +38,7 @@ const test = Test('DynamoStream', DynamoStream)
38
38
  table: 'my-table',
39
39
  endpoint: 'http://localhost:8000',
40
40
  shardIteratorType: 'TRIM_HORIZON',
41
+ shardUpdatePeriod: 1000,
41
42
  }, async function (myStream) {
42
43
  await myStream.ready
43
44
 
@@ -83,7 +84,7 @@ const test = Test('DynamoStream', DynamoStream)
83
84
  endpoint: 'http://localhost:8000',
84
85
  getRecordsLimit: 1,
85
86
  getRecordsInterval: 1000,
86
- shardUpdatePeriod: 5000,
87
+ shardUpdatePeriod: 1000,
87
88
  shardIteratorType: 'TRIM_HORIZON',
88
89
  }, async function (myStream) {
89
90
  await myStream.ready
@@ -129,6 +130,7 @@ const test = Test('DynamoStream', DynamoStream)
129
130
  table: 'my-table',
130
131
  endpoint: 'http://localhost:8000',
131
132
  getRecordsLimit: 1,
133
+ shardUpdatePeriod: 1000,
132
134
  shardIteratorType: 'TRIM_HORIZON',
133
135
  }, async function (myStream) {
134
136
  await myStream.ready
@@ -183,6 +185,7 @@ const test = Test('DynamoStream', DynamoStream)
183
185
  listStreamsLimit: 1,
184
186
  shardIteratorType: 'TRIM_HORIZON',
185
187
  debug: true,
188
+ shardUpdatePeriod: 1000,
186
189
  }, async function (myStream) {
187
190
  await myStream.ready
188
191
 
@@ -223,6 +226,82 @@ const test = Test('DynamoStream', DynamoStream)
223
226
  myStream.close()
224
227
  })
225
228
 
229
+ .case({
230
+ table: 'my-table',
231
+ endpoint: 'http://localhost:8000',
232
+ listStreamsLimit: 1,
233
+ shardIteratorType: 'TRIM_HORIZON',
234
+ debug: true,
235
+ shardUpdatePeriod: 1000,
236
+ }, async function (myStream) {
237
+ await myStream.ready
238
+
239
+ const originalClient = myStream.client
240
+ const alternatingErrorClient = {
241
+ listStreams(options) {
242
+ return originalClient.listStreams(options)
243
+ },
244
+ describeStream(options) {
245
+ return originalClient.describeStream(options)
246
+ },
247
+ getShardIterator(options) {
248
+ return originalClient.getShardIterator(options)
249
+ },
250
+ getRecordsCount: 0,
251
+ getRecords(options) {
252
+ return {
253
+ async promise() {
254
+ if (alternatingErrorClient.getRecordsCount % 2 == 0) {
255
+ const error = new Error('stub error')
256
+ error.retryable = true
257
+ alternatingErrorClient.getRecordsCount += 1
258
+ throw error
259
+ }
260
+ alternatingErrorClient.getRecordsCount += 1
261
+ return originalClient.getRecords(options).promise()
262
+ },
263
+ }
264
+ },
265
+ }
266
+ myStream.client = alternatingErrorClient
267
+
268
+ const table = this.table
269
+ await table.putItem({
270
+ id: '1',
271
+ status: 'waitlist',
272
+ createTime: 1000,
273
+ name: 'George',
274
+ })
275
+ await table.putItem({
276
+ id: '2',
277
+ status: 'waitlist',
278
+ createTime: 1001,
279
+ name: 'geo',
280
+ })
281
+ await table.putItem({
282
+ id: '3',
283
+ status: 'waitlist',
284
+ createTime: 1002,
285
+ name: 'john',
286
+ })
287
+ await table.putItem({
288
+ id: '4',
289
+ status: 'approved',
290
+ createTime: 1003,
291
+ name: 'sally',
292
+ })
293
+ await table.putItem({
294
+ id: '5',
295
+ status: 'approved',
296
+ createTime: 1004,
297
+ name: 'sally',
298
+ })
299
+
300
+ const first5 = await asyncIterableTake(5)(myStream)
301
+ assert.strictEqual(first5.length, 5)
302
+ myStream.close()
303
+ })
304
+
226
305
  .case({
227
306
  table: 'my-table',
228
307
  endpoint: 'http://localhost:8000',
package/SecretsManager.js CHANGED
@@ -52,7 +52,7 @@ client.getSecretValue({SecretId: secretName}, function(err, data) {
52
52
  decodedBinarySecret = buff.toString('ascii');
53
53
  }
54
54
  }
55
-
56
- // Your code goes here.
55
+
56
+ // Your code goes here.
57
57
  });
58
58
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "presidium",
3
- "version": "0.16.15",
3
+ "version": "0.16.17",
4
4
  "description": "A library for creating web services",
5
5
  "author": "Richard Tong",
6
6
  "license": "MIT",