presidium 3.2.0 → 3.3.1

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/DynamoDBStream.js CHANGED
@@ -467,15 +467,18 @@ class DynamoDBStream {
467
467
  let exists = false
468
468
  while (!exists) {
469
469
  await sleep(100)
470
- const streamData = await this.describe().catch(error => {
470
+
471
+ try {
472
+ const streamData = await this.describe()
473
+ if (streamData.TableStatus == 'ACTIVE') {
474
+ exists = true
475
+ }
476
+ } catch (error) {
471
477
  if (error.message == `DynamoDB Stream for ${this.table} not found.`) {
472
- // return
478
+ // continue
473
479
  } else {
474
480
  throw error
475
481
  }
476
- })
477
- if (streamData.TableStatus == 'ACTIVE') {
478
- exists = true
479
482
  }
480
483
  }
481
484
  }
@@ -178,38 +178,6 @@ class GoogleChromeDevToolsPage {
178
178
  }
179
179
  }
180
180
 
181
- /**
182
- * @name Event: DOM.attributeModified
183
- */
184
-
185
- /**
186
- * @name Event: DOM.attributeRemoved
187
- */
188
-
189
- /**
190
- * @name Event: DOM.characterDataModified
191
- */
192
-
193
- /**
194
- * @name Event: DOM.childNodeCountUpdated
195
- */
196
-
197
- /**
198
- * @name Event: DOM.childNodeInserted
199
- */
200
-
201
- /**
202
- * @name Event: DOM.childNodeRemoved
203
- */
204
-
205
- /**
206
- * @name Event: DOM.documentUpdated
207
- */
208
-
209
- /**
210
- * @name Event: DOM.setChildNodes
211
- */
212
-
213
181
  class GoogleChromeDevToolsDOM {
214
182
  constructor(websocket) {
215
183
  this.websocket = websocket
@@ -497,8 +465,179 @@ class GoogleChromeDevToolsDOM {
497
465
  return _Method.call(this, 'DOM.focus', options)
498
466
  }
499
467
 
468
+ /**
469
+ * @name Event: DOM.attributeModified
470
+ *
471
+ * @docs
472
+ * ```coffeescript [specscript]
473
+ * emit('DOM.attributeModified', data {
474
+ * nodeId: string,
475
+ * name: string,
476
+ * value: string,
477
+ * })
478
+ * ```
479
+ *
480
+ * The `DOM.attributeModified` event. Emitted when an attribute of an element is modified.
481
+ *
482
+ * Event Data:
483
+ * `data`
484
+ * * `nodeId` - the ID of the element or node.
485
+ * * `name` - the name of the modified attribute.
486
+ * * `value` - the value of the modified attribute.
487
+ *
488
+ * ```javascript
489
+ * googleChromeDevTools.on('DOM.attributeModified', data => {
490
+ * console.log('attribute modified:', data)
491
+ * })
492
+ * ```
493
+ */
494
+
495
+ /**
496
+ * @name Event: DOM.attributeRemoved
497
+ *
498
+ * @docs
499
+ * ```coffeescript [specscript]
500
+ * emit('DOM.attributeRemoved', data {
501
+ * nodeId: string,
502
+ * name: string,
503
+ * })
504
+ * ```
505
+ *
506
+ * The `DOM.attributeRemoved` event. Emitted when an attribute of an element is removed.
507
+ *
508
+ * Event Data:
509
+ * * `data`
510
+ * * `nodeId` - the ID of the element or node.
511
+ * * `name` - the name of the removed attribute.
512
+ *
513
+ * ```javascript
514
+ * googleChromeDevTools.on('DOM.attributeModified', data => {
515
+ * console.log('attribute removed:', data)
516
+ * })
517
+ * ```
518
+ */
519
+
520
+ /**
521
+ * @name Event: DOM.characterDataModified
522
+ *
523
+ * @docs
524
+ * ```coffeescript [specscript]
525
+ * emit('DOM.characterDataModified', data {
526
+ * nodeId: string,
527
+ * childNodeCount: number,
528
+ * })
529
+ * ```
530
+ *
531
+ * The `DOM.characterDataModified` event. Emitted when a text node is modified.
532
+ *
533
+ * Event Data:
534
+ * * `data`
535
+ * * `nodeId` - the ID of the element or node.
536
+ * * `characterData` - the new text value.
537
+ *
538
+ * ```javascript
539
+ * googleChromeDevTools.on('DOM.characterDataModified', data => {
540
+ * console.log('text modified:', data)
541
+ * })
542
+ * ```
543
+ */
544
+
545
+ /**
546
+ * @name Event: DOM.childNodeCountUpdated
547
+ *
548
+ * @docs
549
+ * ```coffeescript [specscript]
550
+ * emit('DOM.childNodeCountUpdated', data {
551
+ * nodeId: string,
552
+ * childNodeCount: number,
553
+ * })
554
+ * ```
555
+ *
556
+ * The `DOM.childNodeCountUpdated` event. Emitted when the child node count of a node is updated.
557
+ *
558
+ * Event Data:
559
+ * * `data`
560
+ * * `nodeId` - the ID of the element or node.
561
+ * * `childNodeCount` - the updated count of child nodes.
562
+ *
563
+ * ```javascript
564
+ * googleChromeDevTools.on('DOM.childNodeCountUpdated', data => {
565
+ * console.log('child node count updated:', data)
566
+ * })
567
+ * ```
568
+ */
569
+
570
+ /**
571
+ * @name Event: DOM.childNodeInserted
572
+ *
573
+ * @docs
574
+ * ```javascript
575
+ * module CDPDOM 'https://chromedevtools.github.io/devtools-protocol/tot/DOM/'
576
+ *
577
+ * emit('DOM.childNodeInserted', data {
578
+ * parentNodeId: string,
579
+ * previousNodeId: string,
580
+ * node: CDPDOM.Node,
581
+ * })
582
+ * ```
583
+ *
584
+ * The `DOM.childNodeInserted` event. Emitted when a node is inserted into the DOM as a child of another node.
585
+ *
586
+ * Event Data:
587
+ * * `data`
588
+ * * `parentNodeId` - the id of the parent node.
589
+ * * `previousNodeId` - the id of the node immediately preceding the inserted node.
590
+ * * `node` - [`CDPDOM.Node`](https://chromedevtools.github.io/devtools-protocol/tot/DOM/#type-Node) - data about the inserted node.
591
+ */
592
+
593
+ /**
594
+ * @name Event: DOM.childNodeRemoved
595
+ *
596
+ * @docs
597
+ * ```javascript
598
+ * emit('DOM.childNodeRemoved', data {
599
+ * parentNodeId: string,
600
+ * nodeId: string,
601
+ * })
602
+ * ```
603
+ *
604
+ * The `DOM.childNodeRemoved` event. Emitted when a node is removed from the DOM as a child of another node.
605
+ *
606
+ * Event Data:
607
+ * * `data`
608
+ * * `parentNodeId` - the id of the parent node.
609
+ * * `nodeId` - the id of the removed node.
610
+ *
611
+ * ```javascript
612
+ * googleChromeDevTools.on('DOM.childNodeRemoved', data => {
613
+ * console.log('child node removed:', data.nodeId)
614
+ * })
615
+ * ```
616
+ */
617
+
618
+ /**
619
+ * @name Event: DOM.documentUpdated
620
+ *
621
+ * @docs
622
+ * ```coffeescript [specscript]
623
+ * emit('DOM.documentUpdated')
624
+ * ```
625
+ *
626
+ * The `DOM.documentUpdated` event. Emitted when the `Document` object has been totally updated and node IDs are no longer valid.
627
+ *
628
+ * Event Data:
629
+ * * (none)
630
+ *
631
+ * ```javascript
632
+ * googleChromeDevTools.on('DOM.documentUpdated', () => {
633
+ * console.log('Document updated')
634
+ * })
635
+ * ```
636
+ */
637
+
500
638
  }
501
639
 
640
+
502
641
  class GoogleChromeDevToolsInput {
503
642
  constructor(websocket) {
504
643
  this.websocket = websocket
@@ -849,24 +988,20 @@ class GoogleChromeDevToolsRuntime {
849
988
  * Supported platforms:
850
989
  * * `mac-arm64`
851
990
  * * `linux64`
991
+ * * `win64`
852
992
  *
853
993
  * ## Further Installation
854
994
  * Some further installation may be required for Linux platforms.
855
995
  *
856
- * ### Install headless dependencies for Amazon Linux 2023
996
+ * ### Install headless dependencies for Amazon Linux 2023 / Red Hat
857
997
  * ```sh
858
998
  * sudo dnf install -y cairo pango nss nspr atk at-spi2-atk cups-libs libdrm libxkbcommon libXcomposite libXdamage libXfixes libXrandr mesa-libgbm alsa-lib
859
999
  * ```
860
1000
  *
861
- * ### Install headless dependencies for Ubuntu
1001
+ * ### Install headless dependencies for Ubuntu / Debian
862
1002
  * ```sh
863
1003
  * sudo apt-get update && sudo apt-get install -y libcairo2 libpango-1.0-0 libnss3 libnspr4 libatk1.0-0 libatk-bridge2.0-0 libatspi2.0-0 libcups2 libdrm-dev libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm-dev libasound2-dev
864
- *
865
- * # disable AppArmor unprivileged security restriction
866
- * echo "kernel.apparmor_restrict_unprivileged_userns=0" | sudo tee /etc/sysctl.d/60-apparmor-namespace.conf
867
- * sudo sysctl -p /etc/sysctl.d/60-apparmor-namespace.conf
868
1004
  * ```
869
- *
870
1005
  */
871
1006
  class GoogleChromeDevTools extends EventEmitter {
872
1007
  constructor(options = {}) {
@@ -921,7 +1056,11 @@ class GoogleChromeDevTools extends EventEmitter {
921
1056
  offerPerMessageDeflate: false,
922
1057
  })
923
1058
  this.websocket.on('error', error => {
924
- throw error
1059
+ if (this.closed && error.code == 'ECONNRESET') {
1060
+ console.error('Reset after close:', error)
1061
+ } else {
1062
+ throw error
1063
+ }
925
1064
  })
926
1065
 
927
1066
  this.websocket.on('message', message => {
@@ -995,10 +1134,37 @@ class GoogleChromeDevTools extends EventEmitter {
995
1134
  * ```
996
1135
  */
997
1136
  close() {
1137
+ this.closed = true
998
1138
  this.websocket.sendClose()
999
- this.websocket.close()
1000
- this.googleChromeForTesting.close()
1139
+ this.websocket.on('close', () => {
1140
+ this.googleChromeForTesting.cmd.on('close', () => {
1141
+ this.emit('close')
1142
+ })
1143
+ this.googleChromeForTesting.close()
1144
+ })
1001
1145
  }
1146
+
1147
+ /**
1148
+ * @name Event: close
1149
+ *
1150
+ * @docs
1151
+ * ```coffeescript [specscript]
1152
+ * emit('close')
1153
+ * ```
1154
+ *
1155
+ * The `close` event. Emitted when the websocket connection to the DevTools server is closed and the Google Chrome for Testing process is terminated.
1156
+ *
1157
+ * Event Data:
1158
+ * * (none)
1159
+ *
1160
+ * ```javascript
1161
+ * googleChromeForTesting.on('close', () => {
1162
+ * console.log('WebSocket connection closed and Google Chrome for Testing process terminated.')
1163
+ * })
1164
+ * ```
1165
+ */
1166
+
1002
1167
  }
1003
1168
 
1169
+
1004
1170
  module.exports = GoogleChromeDevTools
@@ -18,7 +18,7 @@ async function getChromeVersions() {
18
18
  return data
19
19
  }
20
20
 
21
- function updateConsoleLog(message) {
21
+ function updateConsoleLog(message, platform) {
22
22
  readline.cursorTo(process.stdout, 0, undefined);
23
23
  readline.clearLine(process.stdout, 0);
24
24
  process.stdout.write(message);
@@ -33,7 +33,11 @@ function getPlatform() {
33
33
 
34
34
  if (platform == 'mac') {
35
35
  platform = `${platform}-${arch}`
36
- } else {
36
+ }
37
+ else if (platform == 'win32') {
38
+ platform = `win${arch.slice(1)}`
39
+ }
40
+ else {
37
41
  platform = `${platform}${arch.slice(1)}`
38
42
  }
39
43
 
@@ -58,13 +62,26 @@ async function getChromeUrl() {
58
62
  }
59
63
 
60
64
  async function installChrome() {
65
+ const platform = getPlatform()
66
+ const delimiter = platform.startsWith('win') ? '\\' : '/'
61
67
  const url = await getChromeUrl.call(this)
62
- let filepath = `${this.chromeDir}/${url.replace('https://storage.googleapis.com/chrome-for-testing-public/', '')}`
63
- if (!filepath.startsWith('/')) {
68
+
69
+ let filepath = `${this.chromeDir}${delimiter}${url.replace('https://storage.googleapis.com/chrome-for-testing-public/', '')}`
70
+ if (platform.startsWith('win')) {
71
+ filepath = filepath.replace(/\//g, '\\')
72
+ if (!filepath.startsWith(`${__dirname[0]}:`)) {
73
+ filepath = path.join(process.cwd(), filepath)
74
+ }
75
+ } else if (!filepath.startsWith('/')) {
64
76
  filepath = path.join(process.cwd(), filepath)
65
77
  }
66
- let parentDir = `${filepath.split('/').slice(0, -1).join('/')}`
67
- if (!parentDir.startsWith('/')) {
78
+
79
+ let parentDir = `${filepath.split(delimiter).slice(0, -1).join(delimiter)}`
80
+ if (platform.startsWith('win')) {
81
+ if (!filepath.startsWith(`${__dirname[0]}:`)) {
82
+ parentDir = path.join(process.cwd(), parentDir)
83
+ }
84
+ } else if (!parentDir.startsWith('/')) {
68
85
  parentDir = path.join(process.cwd(), parentDir)
69
86
  }
70
87
  await fs.promises.mkdir(parentDir, { recursive: true })
@@ -81,9 +98,9 @@ async function installChrome() {
81
98
  response.on('data', chunk => {
82
99
  downloadedLength += chunk.length
83
100
  if (downloadedLength == contentLength) {
84
- updateConsoleLog(`Downloading ${url} (${downloadedLength} / ${contentLength} bytes)\n`)
101
+ updateConsoleLog(`Downloading ${url} (${downloadedLength} / ${contentLength} bytes)\n`, platform)
85
102
  } else {
86
- updateConsoleLog(`Downloading ${url} (${downloadedLength} / ${contentLength} bytes)`)
103
+ updateConsoleLog(`Downloading ${url} (${downloadedLength} / ${contentLength} bytes)`, platform)
87
104
  }
88
105
 
89
106
  fileStream.write(chunk)
@@ -98,10 +115,11 @@ async function installChrome() {
98
115
  })
99
116
  await promise
100
117
 
118
+ console.log('Extracting', filepath)
101
119
  try {
102
120
  await extract(filepath, { dir: parentDir })
103
- } catch {
104
- await sleep(100)
121
+ } catch (_error) {
122
+ await sleep(1000)
105
123
  await extract(filepath, { dir: parentDir })
106
124
  }
107
125
  }
@@ -113,14 +131,21 @@ async function getChromeFilepath() {
113
131
  const parentDir = `${filepath.split('/').slice(0, -1).join('/')}`
114
132
 
115
133
  try {
134
+ const dirents = await fs.promises.readdir(parentDir)
135
+ if (dirents.length <= 1) {
136
+ await installChrome.call(this)
137
+ }
138
+
116
139
  for await (const filepath of walk(parentDir)) {
117
- console.log(filepath)
118
140
  if (platform.startsWith('mac') && filepath.endsWith('Google Chrome for Testing')) {
119
141
  return filepath
120
142
  }
121
143
  if (platform.startsWith('linux') && filepath.endsWith('chrome')) {
122
144
  return filepath
123
145
  }
146
+ if (platform.startsWith('win') && filepath.endsWith('chrome.exe')) {
147
+ return filepath
148
+ }
124
149
  }
125
150
  } catch (error) {
126
151
  if (error.code == 'ENOENT') {
@@ -173,6 +198,7 @@ async function getChromeFilepath() {
173
198
  * Supported platforms:
174
199
  * * `mac-arm64`
175
200
  * * `linux64`
201
+ * * `win64`
176
202
  *
177
203
  * ## Further Installation
178
204
  * Some further installation may be required for Linux platforms.
@@ -185,10 +211,6 @@ async function getChromeFilepath() {
185
211
  * ### Install headless dependencies for Ubuntu / Debian
186
212
  * ```sh
187
213
  * sudo apt-get update && sudo apt-get install -y libcairo2 libpango-1.0-0 libnss3 libnspr4 libatk1.0-0 libatk-bridge2.0-0 libatspi2.0-0 libcups2 libdrm-dev libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm-dev libasound2-dev
188
- *
189
- * # disable AppArmor unprivileged security restriction
190
- * echo "kernel.apparmor_restrict_unprivileged_userns=0" | sudo tee /etc/sysctl.d/60-apparmor-namespace.conf
191
- * sudo sysctl -p /etc/sysctl.d/60-apparmor-namespace.conf
192
214
  * ```
193
215
  */
194
216
  class GoogleChromeForTesting {
@@ -236,6 +258,7 @@ class GoogleChromeForTesting {
236
258
  `--user-data-dir=${this.userDataDir}`,
237
259
  ...this.headless ? ['--headless'] : [],
238
260
  ...this.useMockKeychain ? ['--use-mock-keychain'] : [],
261
+ '--no-sandbox',
239
262
  ])
240
263
  cmd.stdout.pipe(process.stdout)
241
264
  cmd.stderr.pipe(process.stderr)
@@ -288,6 +311,18 @@ class GoogleChromeForTesting {
288
311
  * ```coffeescript [specscript]
289
312
  * close() -> undefined
290
313
  * ```
314
+ *
315
+ * Terminates the Google Chrome for Testing process.
316
+ *
317
+ * Arguments:
318
+ * * (none)
319
+ *
320
+ * Return:
321
+ * * `undefined`
322
+ *
323
+ * ```javascript
324
+ * googleChromeForTesting.close()
325
+ * ```
291
326
  */
292
327
  close() {
293
328
  this.cmd.kill('SIGKILL')
package/LICENSE CHANGED
@@ -1,21 +1,9 @@
1
- The MIT License (MIT)
1
+ The CLOUT Free and Open Source Software License (CFOSS)
2
2
 
3
- Copyright (c) 2026 Richard Tong
3
+ © Richard Yufei Tong, King of Software
4
4
 
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
11
6
 
12
- The above copyright notice and this permission notice shall be included in
13
- all copies or substantial portions of the Software.
7
+ 1. This permission notice is included in all copies or substantial portions of the Software.
14
8
 
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- THE SOFTWARE.
9
+ THE SOFTWARE IS PROVIDED AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE, OR IN THE USE OF OR OTHER DEALINGS OF THE SOFTWARE.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "presidium",
3
- "version": "3.2.0",
3
+ "version": "3.3.1",
4
4
  "description": "A library for creating web services",
5
5
  "author": "Richard Tong",
6
6
  "license": "MIT",