@sebbo2002/node-pyatv 4.1.1-develop.1 → 4.2.0-develop.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/CHANGELOG.md +7 -0
- package/dist/lib/device-events.js +7 -2
- package/dist/lib/device-events.js.map +1 -1
- package/dist/lib/device.js +10 -6
- package/dist/lib/device.js.map +1 -1
- package/dist/lib/tools.js +7 -0
- package/dist/lib/tools.js.map +1 -1
- package/dist/lib/types.d.ts +1 -0
- package/docs/coverage/cobertura-coverage.xml +525 -517
- package/docs/coverage/device-event.ts.html +1 -1
- package/docs/coverage/device-events.ts.html +99 -84
- package/docs/coverage/device.ts.html +38 -23
- package/docs/coverage/fake-spawn.ts.html +25 -25
- package/docs/coverage/index.html +24 -24
- package/docs/coverage/index.ts.html +1 -1
- package/docs/coverage/instance.ts.html +1 -1
- package/docs/coverage/tools.ts.html +131 -107
- package/docs/coverage/types.ts.html +5 -2
- package/docs/reference/assets/main.js +1 -1
- package/docs/reference/assets/style.css +4 -0
- package/docs/reference/classes/NodePyATVDeviceEvent.html +5 -5
- package/docs/reference/classes/default.html +10 -10
- package/docs/reference/enums/NodePyATVDeviceState.html +1 -1
- package/docs/reference/enums/NodePyATVKeys.html +1 -1
- package/docs/reference/enums/NodePyATVMediaType.html +1 -1
- package/docs/reference/enums/NodePyATVProtocol.html +1 -1
- package/docs/reference/enums/NodePyATVRepeatState.html +1 -1
- package/docs/reference/enums/NodePyATVShuffleState.html +1 -1
- package/docs/reference/index.html +1 -1
- package/docs/reference/interfaces/NodePyATVDeviceOptions.html +1 -1
- package/docs/reference/interfaces/NodePyATVFindAndInstanceOptions.html +1 -1
- package/docs/reference/interfaces/NodePyATVFindOptions.html +1 -1
- package/docs/reference/interfaces/NodePyATVGetStateOptions.html +1 -1
- package/docs/reference/interfaces/NodePyATVInstanceOptions.html +1 -1
- package/docs/reference/interfaces/NodePyATVState.html +1 -1
- package/docs/reference/interfaces/NodePyATVVersionResponse.html +1 -1
- package/docs/reference/modules.html +1 -1
- package/docs/tests/assets/app.css +1 -1
- package/docs/tests/assets/app.js +2 -2
- package/docs/tests/assets/app.js.LICENSE.txt +1 -1
- package/docs/tests/index.html +1 -1
- package/docs/tests/mochawesome.json +650 -593
- package/package.json +15 -15
- package/src/lib/device-events.ts +7 -2
- package/src/lib/device.ts +11 -6
- package/src/lib/tools.ts +8 -0
- package/src/lib/types.ts +1 -0
- package/test/device-events.ts +23 -0
- package/test/device.ts +18 -0
- package/test/tools.ts +15 -4
package/package.json
CHANGED
|
@@ -10,27 +10,27 @@
|
|
|
10
10
|
"description": "A lightweight wrapper around pyatv…",
|
|
11
11
|
"devDependencies": {
|
|
12
12
|
"@amanda-mitchell/semantic-release-npm-multiple": "^2.15.0",
|
|
13
|
-
"@qiwi/semantic-release-gh-pages-plugin": "^5.
|
|
14
|
-
"@semantic-release/changelog": "^6.0.
|
|
15
|
-
"@semantic-release/exec": "^6.0.
|
|
16
|
-
"@semantic-release/git": "^10.0.
|
|
13
|
+
"@qiwi/semantic-release-gh-pages-plugin": "^5.2.0",
|
|
14
|
+
"@semantic-release/changelog": "^6.0.1",
|
|
15
|
+
"@semantic-release/exec": "^6.0.2",
|
|
16
|
+
"@semantic-release/git": "^10.0.1",
|
|
17
17
|
"@types/mocha": "^9.0.0",
|
|
18
|
-
"@types/node": "^16.11.
|
|
18
|
+
"@types/node": "^16.11.9",
|
|
19
19
|
"@types/semver": "^7.3.9",
|
|
20
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
21
|
-
"@typescript-eslint/parser": "^5.
|
|
22
|
-
"eslint": "^8.0
|
|
23
|
-
"eslint-plugin-jsonc": "^
|
|
20
|
+
"@typescript-eslint/eslint-plugin": "^5.4.0",
|
|
21
|
+
"@typescript-eslint/parser": "^5.4.0",
|
|
22
|
+
"eslint": "^8.3.0",
|
|
23
|
+
"eslint-plugin-jsonc": "^2.0.0",
|
|
24
24
|
"license-checker": "^25.0.1",
|
|
25
25
|
"mocha": "^9.1.3",
|
|
26
|
-
"mochawesome": "^
|
|
26
|
+
"mochawesome": "^7.0.1",
|
|
27
27
|
"nyc": "^15.1.0",
|
|
28
28
|
"semantic-release": "^18.0.0",
|
|
29
29
|
"semantic-release-license": "^1.0.3",
|
|
30
|
-
"source-map-support": "^0.5.
|
|
31
|
-
"ts-node": "^10.
|
|
32
|
-
"typedoc": "^0.22.
|
|
33
|
-
"typescript": "^4.
|
|
30
|
+
"source-map-support": "^0.5.21",
|
|
31
|
+
"ts-node": "^10.4.0",
|
|
32
|
+
"typedoc": "^0.22.9",
|
|
33
|
+
"typescript": "^4.5.2"
|
|
34
34
|
},
|
|
35
35
|
"engines": {
|
|
36
36
|
"node": ">=12.0.0"
|
|
@@ -55,5 +55,5 @@
|
|
|
55
55
|
"postinstall": "./check.sh",
|
|
56
56
|
"test": "mocha"
|
|
57
57
|
},
|
|
58
|
-
"version": "4.
|
|
58
|
+
"version": "4.2.0-develop.1"
|
|
59
59
|
}
|
package/src/lib/device-events.ts
CHANGED
|
@@ -91,8 +91,13 @@ export default class NodePyATVDeviceEvents extends EventEmitter {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
private applyPushUpdate(update: NodePyATVInternalState, reqId: string): void {
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
try {
|
|
95
|
+
const newState = parseState(update, reqId, this.options);
|
|
96
|
+
this.applyStateAndEmitEvents(newState);
|
|
97
|
+
}
|
|
98
|
+
catch(error) {
|
|
99
|
+
this.emit('error', error);
|
|
100
|
+
}
|
|
96
101
|
}
|
|
97
102
|
|
|
98
103
|
private checkListener(): void {
|
package/src/lib/device.ts
CHANGED
|
@@ -148,14 +148,19 @@ export default class NodePyATVDevice implements EventEmitter{
|
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
const id = addRequestId();
|
|
151
|
-
const parameters = getParamters(this.options);
|
|
152
151
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
this.applyState(newState);
|
|
152
|
+
try {
|
|
153
|
+
const parameters = getParamters(this.options);
|
|
156
154
|
|
|
157
|
-
|
|
158
|
-
|
|
155
|
+
const result = await request(id, NodePyATVExecutableType.atvscript, [...parameters, 'playing'], this.options);
|
|
156
|
+
const newState = parseState(result, id, this.options);
|
|
157
|
+
|
|
158
|
+
this.applyState(newState);
|
|
159
|
+
return newState;
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
removeRequestId(id);
|
|
163
|
+
}
|
|
159
164
|
}
|
|
160
165
|
|
|
161
166
|
/**
|
package/src/lib/tools.ts
CHANGED
|
@@ -252,6 +252,14 @@ export function parseState(input: NodePyATVInternalState, id: string, options: N
|
|
|
252
252
|
if (!input || typeof input !== 'object') {
|
|
253
253
|
return result;
|
|
254
254
|
}
|
|
255
|
+
if(input.exception) {
|
|
256
|
+
let errorStr = 'Got pyatv Error: ' + input.exception;
|
|
257
|
+
if(input.stacktrace) {
|
|
258
|
+
errorStr += '\n\npyatv Stacktrace:\n' + input.stacktrace;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
throw new Error(errorStr);
|
|
262
|
+
}
|
|
255
263
|
|
|
256
264
|
// datetime
|
|
257
265
|
if (typeof input.datetime === 'string') {
|
package/src/lib/types.ts
CHANGED
package/test/device-events.ts
CHANGED
|
@@ -89,6 +89,29 @@ describe('NodePyATVDeviceEvents', function () {
|
|
|
89
89
|
|
|
90
90
|
assert.deepStrictEqual(sort, ['update:title', 'update']);
|
|
91
91
|
});
|
|
92
|
+
it('should emit error events on failures', async function () {
|
|
93
|
+
const device = new NodePyATVDevice({
|
|
94
|
+
name: 'My Testdevice',
|
|
95
|
+
host: '192.168.178.2',
|
|
96
|
+
spawn: createFakeSpawn(cp => {
|
|
97
|
+
cp.onStdIn(() => cp.end());
|
|
98
|
+
cp.stdout({
|
|
99
|
+
result: 'failure',
|
|
100
|
+
datetime: '2021-11-24T21:13:36.424576+03:00',
|
|
101
|
+
exception: 'invalid credentials: 321',
|
|
102
|
+
stacktrace: 'Traceback (most recent call last):\n File \"/Users/free/Library/Python/3.8/lib/python/site-packages/pyatv/scripts/atvscript.py\", line 302, in appstart\n print(args.output(await _handle_command(args, abort_sem, loop)), flush=True)\n File \"/Users/free/Library/Python/3.8/lib/python/site-packages/pyatv/scripts/atvscript.py\", line 196, in _handle_command\n atv = await connect(config, loop, protocol=Protocol.MRP)\n File \"/Users/free/Library/Python/3.8/lib/python/site-packages/pyatv/__init__.py\", line 96, in connect\n for setup_data in proto_methods.setup(\n File \"/Users/free/Library/Python/3.8/lib/python/site-packages/pyatv/protocols/airplay/__init__.py\", line 192, in setup\n stream = AirPlayStream(config, service)\n File \"/Users/free/Library/Python/3.8/lib/python/site-packages/pyatv/protocols/airplay/__init__.py\", line 79, in __init__\n self._credentials: HapCredentials = parse_credentials(self.service.credentials)\n File \"/Users/free/Library/Python/3.8/lib/python/site-packages/pyatv/auth/hap_pairing.py\", line 139, in parse_credentials\n raise exceptions.InvalidCredentialsError(\"invalid credentials: \" + detail_string)\npyatv.exceptions.InvalidCredentialsError: invalid credentials: 321\n'
|
|
103
|
+
});
|
|
104
|
+
})
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
await new Promise(cb => {
|
|
108
|
+
device.once('error', error => {
|
|
109
|
+
assert.ok(error instanceof Error);
|
|
110
|
+
assert.ok(error.toString().includes('invalid credentials: 321'));
|
|
111
|
+
cb(undefined);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
});
|
|
92
115
|
it('should not emit an update if new value is same as old one', async function () {
|
|
93
116
|
let spawnCounter = 0;
|
|
94
117
|
let eventCounter = 0;
|
package/test/device.ts
CHANGED
|
@@ -237,6 +237,24 @@ describe('NodePyATVDevice', function () {
|
|
|
237
237
|
powerState: null
|
|
238
238
|
});
|
|
239
239
|
});
|
|
240
|
+
it('should reject with error if pyatv fails', async function () {
|
|
241
|
+
const device = new NodePyATVDevice({
|
|
242
|
+
name: 'My Testdevice',
|
|
243
|
+
host: '192.168.178.2',
|
|
244
|
+
spawn: createFakeSpawn(cp => {
|
|
245
|
+
cp.end({
|
|
246
|
+
result: 'failure',
|
|
247
|
+
datetime: '2021-11-24T21:13:36.424576+03:00',
|
|
248
|
+
exception: 'invalid credentials: 321',
|
|
249
|
+
stacktrace: 'Traceback (most recent call last):\n File \"/Users/free/Library/Python/3.8/lib/python/site-packages/pyatv/scripts/atvscript.py\", line 302, in appstart\n print(args.output(await _handle_command(args, abort_sem, loop)), flush=True)\n File \"/Users/free/Library/Python/3.8/lib/python/site-packages/pyatv/scripts/atvscript.py\", line 196, in _handle_command\n atv = await connect(config, loop, protocol=Protocol.MRP)\n File \"/Users/free/Library/Python/3.8/lib/python/site-packages/pyatv/__init__.py\", line 96, in connect\n for setup_data in proto_methods.setup(\n File \"/Users/free/Library/Python/3.8/lib/python/site-packages/pyatv/protocols/airplay/__init__.py\", line 192, in setup\n stream = AirPlayStream(config, service)\n File \"/Users/free/Library/Python/3.8/lib/python/site-packages/pyatv/protocols/airplay/__init__.py\", line 79, in __init__\n self._credentials: HapCredentials = parse_credentials(self.service.credentials)\n File \"/Users/free/Library/Python/3.8/lib/python/site-packages/pyatv/auth/hap_pairing.py\", line 139, in parse_credentials\n raise exceptions.InvalidCredentialsError(\"invalid credentials: \" + detail_string)\npyatv.exceptions.InvalidCredentialsError: invalid credentials: 321\n'
|
|
250
|
+
});
|
|
251
|
+
})
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
assert.rejects(async () => {
|
|
255
|
+
await device.getState();
|
|
256
|
+
}, /Got pyatv Error: invalid credentials: 321/);
|
|
257
|
+
});
|
|
240
258
|
it('should cache requests for a bit', async function () {
|
|
241
259
|
let executions = 0;
|
|
242
260
|
const device = new NodePyATVDevice({
|
package/test/tools.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
import assert from 'assert';
|
|
4
|
-
import {addRequestId, debug, getExecutable, getParamters, parseState, removeRequestId} from '../src/lib/tools';
|
|
4
|
+
import { addRequestId, debug, getExecutable, getParamters, parseState, removeRequestId } from '../src/lib/tools';
|
|
5
5
|
import {
|
|
6
6
|
NodePyATVDeviceState,
|
|
7
7
|
NodePyATVExecutableType,
|
|
@@ -28,7 +28,7 @@ describe('Tools', function () {
|
|
|
28
28
|
debug('TEST', 'Hello World.', {});
|
|
29
29
|
});
|
|
30
30
|
it('should work with default logger', function () {
|
|
31
|
-
debug('TEST', 'Hello World.', {debug: true});
|
|
31
|
+
debug('TEST', 'Hello World.', { debug: true });
|
|
32
32
|
});
|
|
33
33
|
it('should work with custom logger', function () {
|
|
34
34
|
debug('TEST', 'Hello World.', {
|
|
@@ -39,7 +39,7 @@ describe('Tools', function () {
|
|
|
39
39
|
});
|
|
40
40
|
});
|
|
41
41
|
it('should work with colors disabled', function () {
|
|
42
|
-
debug('TEST', 'Hello World.', {noColors: true});
|
|
42
|
+
debug('TEST', 'Hello World.', { noColors: true });
|
|
43
43
|
});
|
|
44
44
|
it('should work with custom logger and colors disabled', function () {
|
|
45
45
|
debug('TEST', 'Hello World.', {
|
|
@@ -201,8 +201,19 @@ describe('Tools', function () {
|
|
|
201
201
|
powerState: null
|
|
202
202
|
});
|
|
203
203
|
});
|
|
204
|
+
it('should throw an error for pyatv exceptions', function () {
|
|
205
|
+
const input = {
|
|
206
|
+
result: 'failure',
|
|
207
|
+
datetime: '2021-11-24T21:13:36.424576+03:00',
|
|
208
|
+
exception: 'invalid credentials: 321',
|
|
209
|
+
stacktrace: 'Traceback (most recent call last):\n File \"/Users/free/Library/Python/3.8/lib/python/site-packages/pyatv/scripts/atvscript.py\", line 302, in appstart\n print(args.output(await _handle_command(args, abort_sem, loop)), flush=True)\n File \"/Users/free/Library/Python/3.8/lib/python/site-packages/pyatv/scripts/atvscript.py\", line 196, in _handle_command\n atv = await connect(config, loop, protocol=Protocol.MRP)\n File \"/Users/free/Library/Python/3.8/lib/python/site-packages/pyatv/__init__.py\", line 96, in connect\n for setup_data in proto_methods.setup(\n File \"/Users/free/Library/Python/3.8/lib/python/site-packages/pyatv/protocols/airplay/__init__.py\", line 192, in setup\n stream = AirPlayStream(config, service)\n File \"/Users/free/Library/Python/3.8/lib/python/site-packages/pyatv/protocols/airplay/__init__.py\", line 79, in __init__\n self._credentials: HapCredentials = parse_credentials(self.service.credentials)\n File \"/Users/free/Library/Python/3.8/lib/python/site-packages/pyatv/auth/hap_pairing.py\", line 139, in parse_credentials\n raise exceptions.InvalidCredentialsError(\"invalid credentials: \" + detail_string)\npyatv.exceptions.InvalidCredentialsError: invalid credentials: 321\n'
|
|
210
|
+
};
|
|
211
|
+
assert.throws(() => {
|
|
212
|
+
parseState(input, '', {});
|
|
213
|
+
}, /Got pyatv Error: invalid credentials: 321/);
|
|
214
|
+
});
|
|
204
215
|
it('should ignore date if it\'s an invalid date', function () {
|
|
205
|
-
const input = {datetime: 'today'};
|
|
216
|
+
const input = { datetime: 'today' };
|
|
206
217
|
const result = parseState(input, '', {});
|
|
207
218
|
assert.deepStrictEqual(result, {
|
|
208
219
|
dateTime: null,
|