Skip to content

Commit

Permalink
Merge pull request #162 from svrooij/beta
Browse files Browse the repository at this point in the history
feat: 2022Q2 release
  • Loading branch information
svrooij authored Jun 16, 2022
2 parents 25d4a6f + cebaa47 commit 322a36d
Show file tree
Hide file tree
Showing 111 changed files with 3,791 additions and 1,411 deletions.
23 changes: 23 additions & 0 deletions .deepsource.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
version = 1

test_patterns = [
"tests/**/*.test.ts",
"tests/*.test.ts"
]

exclude_patterns = [
"tests/test-helpers.ts",
"tests/helpers/legacy-helpers.js",
"docs/**",
"examples/**",
"jest.config.js",
".eslintrc.js"
]

[[analyzers]]
name = "secrets"
enabled = true

[[analyzers]]
name = "javascript"
enabled = true
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,4 @@ module.exports = {
}
}
]
};
};
20 changes: 20 additions & 0 deletions .generator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Sonos generator

A lot of files in this library are generated, you can use the [@svrooij/sonos-docs](https://github.com/svrooij/sonos-api-docs/tree/main/generator/sonos-docs) generator.
With the template in the [./.generator/ts/](ts/) folder.

## (Re)generate files

```bash
# from root of repository!

# Generate the combined.json file (from online source), this is a combination of manual documentation and generated services.
npx @svrooij/sonos-docs combine

# Generate files in this library
npx @svrooij/sonos-docs generate ./.generator/ts/ ./

# Shortcut
npm run generate

```
23 changes: 23 additions & 0 deletions .generator/ts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Sonos Typescript template

This folder contains the template files for [sonos-ts](://svrooij.io/node-sonos-ts/).

## Folder content

| File | Description | Remarks |
|:-----|:------------|:--------|
| [docs-index](./docs-index.hbs) | Documentation Index | |
| [docs-service](./docs-service.hbs) | Service documentation | |
| [service-export](./service-export.hbs) | Service export | Exporting all the services to be available for one import |
| [service](./service.hbs) | Single service | Strong type service template, see [details](#sonos-service) |
| [sonos-base](./sonos-base.hbs) | Sonos base device | To enable generating a single class **SonosDevice** with a generated base |
| [sonos-upnp-errors](./sonos-upnp-errors.hbs) | All errors | Default sonos UPNP errors |

## Sonos Service

The [service file](./service.hbs) uses some extra handlebarjs handlers to get it to generate the correct file.

Handlebars is used to generate the service but it doesn't support special `if` conditions, for instance to only add a piece of code when the variable is equal to something else. Since we want some pieces of code to only be added to specific services, the generator adds some special handlers.

- **are_equal** is used like `{{#if (are_equal variable_name value)}}` sample `{{#if (are_equal serviceName 'AlarmClockService')}}`
- **or** is used like `{{#if (or (are_equal name 'Volume') (are_equal name 'Mute'))}}`
26 changes: 26 additions & 0 deletions .generator/ts/docs-index.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
layout: default
title: Services
parent: Sonos device
nav_order: 4
has_children: true
has_toc: false
---

# Sonos SOAP Services
{: .no_toc }

Every sonos speaker has several soap services. Each service has one or more actions you can call.

## All services
{: .no_toc }

| Service | Description |
|:--------|:------------|
{{#each services}}
| [**{{name}} service**]({{kebabName}}-service.html) | {{description}} |
{{/each}}

---
This file is automatically generated with [@svrooij/sonos-docs](https://github.com/svrooij/sonos-api-docs/tree/main/generator/sonos-docs), do not edit manually.
95 changes: 95 additions & 0 deletions .generator/ts/docs-service.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
---
layout: default
title: {{name}}
parent: Services
grand_parent: Sonos device
---
# {{name}} service
{: .no_toc }
{{#if description}}

{{description}}
{{/if}}
{{#if availableAt}}

The {{name}} service is available on these models: {{#each availableAt}}`{{this}}`{{#unless @last}} / {{/unless}}{{/each}}.
{{/if}}

```js
const SonosDevice = require('@svrooij/sonos').SonosDevice
const sonos = new SonosDevice('192.168.x.x')
sonos.{{serviceName}}.OneOfTheMethodsBelow({...})
```

All actions that require input expect an object with the specified parameters, even if it only requires one parameter.

1. TOC
{:toc}

---
{{#each actions}}
### {{name}}
{{#if description}}
{{description}}
{{/if}}
{{#if inputs}}
```js
const result = await sonos.{{../serviceName}}.{{name}}({ {{#each inputs}}{{name}}:...{{#unless @last}}, {{/unless}}{{/each}} });
```
Input object:
| property | type | description |
|:----------|:-----|:------------|
{{#each inputs}}
| **{{name}}** | `{{{relatedStateVariable.dataType}}}` | {{{description}}}{{#if relatedStateVariable.allowedValues}} Allowed values: {{#each relatedStateVariable.allowedValues}}`{{this}}`{{#unless @last}} / {{/unless}}{{/each}}{{/if}} |
{{/each}}
{{else}}
```js
const result = await sonos.{{../serviceName}}.{{name}}();
```
{{/if}}
{{#if outputs}}
Output object:
| property | type | description |
|:----------|:-----|:------------|
{{#each outputs}}
| **{{name}}** | `{{{relatedStateVariable.dataType}}}` | {{{description}}}{{#if relatedStateVariable.allowedValues}} Possible values: {{#each relatedStateVariable.allowedValues}}`{{this}}`{{#unless @last}} / {{/unless}}{{/each}}{{/if}} |
{{/each}}
{{else}}
This actions returns a boolean whether or not the requests succeeded.
{{/if}}
{{#if remarks}}
**Remarks** {{{remarks}}}
{{/if}}
{{/each}}
{{#if eventVariables}}
## {{serviceName}} event
```js
const SonosDevice = require('@svrooij/sonos').SonosDevice
const sonos = new SonosDevice('192.168.x.x')
sonos.{{serviceName}}.Events('serviceEvent', (data) => {
console.log(data);
});
```
The **{{serviceName}}** emits events with these properties. Not all properties are emitted every time.
| parameter | type | possible values |
|:----------|:-----|:----------------|
{{#each eventVariables}}
| **{{name}}** | `{{{dataType}}}` | {{#each allowedValues}}`{{this}}`{{#unless @last}} / {{/unless}}{{/each}} |
{{/each}}
{{/if}}
This file is automatically generated with [@svrooij/sonos-docs](https://github.com/svrooij/sonos-api-docs/tree/main/generator/sonos-docs), do not edit manually.
14 changes: 14 additions & 0 deletions .generator/ts/service-export.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* All sonos services exported as one file for easy access.
*
* Stephan van Rooij
* https://svrooij.io/sonos-api-docs
*
* This file is generated, do not edit manually.
*/
{{#each services}}
export * from './{{kebabName}}.service';
{{#if data.extended}}
export * from './{{kebabName}}.service.extension';
{{/if}}
{{/each}}
141 changes: 141 additions & 0 deletions .generator/ts/service.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/**
* Sonos {{name}} service
*
* Stephan van Rooij
* https://svrooij.io
*
* This file is generated, do not edit manually. https://svrooij.io/sonos-api-docs
*/
{{#if data.importUrl}}
import { URL } from 'url';
{{/if}}
import BaseService from './base-service';
import { SonosUpnpError } from '../models/sonos-upnp-error';
import SonosUpnpErrors from './sonos-upnp-errors';
{{#if data.imports}}
import {
{{#each data.imports}}{{this}},{{#unless @last}} {{/unless}}{{/each}}
} from '../models';
{{/if}}

{{#if description}}
/**
* {{description}}
*
* @export
* @class {{serviceName}}{{#if data.extended}}Base{{/if}}
* @extends {BaseService}
*/
{{/if}}
export class {{serviceName}}{{#if data.extended}}Base{{/if}} extends BaseService{{#if eventVariables}}<{{serviceName}}Event>{{else}}<undefined>{{/if}} {
readonly serviceNane: string = '{{name}}';

readonly controlUrl: string = '{{controlURL}}';

readonly eventSubUrl: string = '{{eventSubURL}}';

readonly scpUrl: string = '{{discoveryUri}}';

{{#if errors}}
/**
* Default errors and service specific errors
*
* @type {SonosUpnpError[]}
* @remarks See https://svrooij.io/sonos-api-docs/#manual-documentation-file
*/
readonly errors: SonosUpnpError[] = [
...SonosUpnpErrors.defaultErrors,
{{#each errors}}
{ code: {{code}}, description: '{{description}}' },
{{/each}}
];
{{else}}
readonly errors: SonosUpnpError[] = SonosUpnpErrors.defaultErrors;
{{/if}}

// #region actions
{{#each actions}}
{{#if description}}
/**
* {{description}}
{{#if inputs}}
*
{{/if}}
{{#each inputs}}
* @param { {{~ relatedStateVariable.dataType ~}} } input.{{name}}{{#if description}} - {{{description}}}{{/if}}{{#if relatedStateVariable.allowedValues}} [ {{#each relatedStateVariable.allowedValues}}'{{this}}'{{#unless @last}} / {{/unless}}{{/each}} ]{{/if}}
{{/each}}
{{#if remarks}}
* @remarks {{{remarks}}}
{{/if}}
*/
{{/if}}
{{#if inputs}}
async {{name}}(input: { {{#each inputs}}{{name}}: {{relatedStateVariable.dataType}}{{#unless @last}}; {{/unless}}{{/each}} }{{{sonos_if_only_instance_id inputs ' = { InstanceID: 0 }'}}}):
{{#if outputs}}
Promise<{{name}}Response> { return await this.SoapRequestWithBody<typeof input, {{name}}Response>('{{name}}', input); }
{{else}}
Promise<boolean> { return await this.SoapRequestWithBodyNoResponse<typeof input>('{{name}}', input); }
{{/if}}
{{else}}
async {{name}}():
{{#if outputs}}
Promise<{{name}}Response> { return await this.SoapRequest<{{name}}Response>('{{name}}'); }
{{else}}
Promise<boolean> { return await this.SoapRequestNoResponse('{{name}}'); }
{{/if}}
{{/if}}
{{#unless @last}}

{{/unless}}
{{/each}}
// #endregion
{{#if outputVariables}}

protected responseProperties(): {[key: string]: string} {
return {
{{#each outputVariables}}
{{@key}}: '{{{this}}}',
{{/each}}
};
}
{{/if}}
{{#if eventVariables}}

// Event properties from service description.
protected eventProperties(): {[key: string]: string} {
return {
{{#each eventVariables}}
{{name}}: '{{#if (or (are_equal name 'Volume') (are_equal name 'Mute'))}}{{#if (are_equal name 'Mute')}}ChannelValue<boolean>{{else}}ChannelValue<number>{{/if}}{{else}}{{{dataType}}}{{/if}}',
{{/each}}
};
}
{{else}}

// No properties in service description, throw error on retrieval.
protected eventProperties(): {[key: string]: string} {
throw new Error('No event properties in service definition');
}
{{/if}}
}

// Generated responses
{{#each actions}}
{{#if outputs}}
{{#unless (are_equal name 'Browse')}}
export interface {{name}}Response {
{{#each outputs}}
{{name}}: {{{relatedStateVariable.dataType}}};
{{/each}}
}

{{/unless}}
{{/if}}
{{/each}}
{{#if eventVariables}}
// Strong type event
export interface {{serviceName}}Event {
{{#each eventVariables}}
{{name}}?: {{#if (or (are_equal name 'Volume') (are_equal name 'Mute'))}}{{#if (are_equal name 'Mute')}}ChannelValue<boolean>{{else}}ChannelValue<number>{{/if}}{{else}}{{{dataType}}}{{/if}};
{{/each}}
}
{{/if}}
Loading

0 comments on commit 322a36d

Please sign in to comment.