Add TypeScript mixxx controls definitions#15441
Conversation
|
I attempted to add the deprecated controls with a note, but currently, JSDoc deprecation warnings do not display for union types. Therefore, I believe it is best to only document the up-to-date types by this. |
res/controllers/mixxx-controls.d.ts
Outdated
| | 'PeakIndicator' | ||
| | 'PeakIndicatorL' | ||
| | 'PeakIndicatorR' |
There was a problem hiding this comment.
FYI these and VuMeter controls have been moved/renamed to the [Main] group.
mixxxdj/manual#798
|
I appreciate the contribution, but I'm a little skeptical that this improves the developer experience enough to warrant the additional maintenance overhead this causes. Wdyt @JoergAtGithub |
|
I personaly like it. But maintaining two parallel descriptions is of course additional maintenance effort. |
|
I also think that it's only worthwhile if it one of the parts can be generated. Without knowing too much about C++ or the Mixxx code base itself, is it also possible to generate the types straight from the Mixxx-Code? The controls must surely be registered somewhere. If, for example, they could be read out as a dictionary with group and control, the path to Typescript types could not be that long. |
Checking for undefined controls should be possible for JS and TS files via TS compiler prehook, at least as long as “as any” has not been passed by the developer in TS. In JS, you could at least check this with the tsconfig setting “checkJS”: true if the string was written directly into the function call in JS. I could test that too. |
|
@Serveny This PR is your first contribution to Mixxx: |
Done! :) |
Fixed that, now group/control type check is disabled if group is just But I have one more question: The d.ts formatting seems inconsistent so far, for example, only sometimes using a semicolon and with an unknown tab or maximum line width. What are the usual code formatting guidelines for TS/JS? I found a .prettierrc.yaml file in the project. Is that intended for auto formatting the JS/TS code with prettier? tabWidth: 2
singleQuote: false |
|
I think not all variants of the ControlPotMeter controls are represented: https://manual.mixxx.org/2.6/en/chapters/appendix/mixxx_controls.html#controlpotmeter-controls |
|
What do you think about seperated type groups for writeable and readonly controls? To hide the read-only COs from setValue etc. |
|
@JoergAtGithub I think I was able to resolve your points:
Known limitation:
|
|
If I use the auto-completion in VS-Code and select a control from the suggestion list, it place the closing quotation mark before the cursor. Do you have an idea, if this can be fixed: Aufzeichnung.2025-10-12.200742.mp4 |
Cursor inside string after suggestion is the default vscode behaivior, but there is (just vscode things 😄) an extension for tab to jump out of the string or brackets: https://marketplace.visualstudio.com/items?itemName=albert.TabOut Alternatively, you can also set a script to {
"key": "enter",
"command": "runCommands",
"args": {
"commands": [
"acceptSelectedSuggestion",
"cursorRight"
]
},
"when": "suggestWidgetVisible && textInputFocus"
}EDIT: |
|
This is LGTM now! But what are your ideas to prevent double maintenance of the list of COs? |
Cool :) Hmm, there are various good ways to achieve that:
Conclusion: If we can read out the controls informations about groups, control name, read-only & isDeprecated I would prefer option 1, if not option 2. |
|
I'd go with 1. generate from c++ code base (though that's not trivial afaict) and maintain the manual by hand. Because 2. generate the controls documentation from TS types with TS doc comments is not really a time safer. |
|
I created a little Python prototype how we could generate the types:
@ronso0 Do you think this is the right path, or is there a better way than extracting the controls from the C++ code via Python and clang package? EDIT: I tried this with Python and clang, but it was very slow and I couldn't find the right tokens (probably because the imports still need to be linked somehow, idk). |
dcd93ff to
497fb8d
Compare
|
I built a workflow like the What it should do:
The trigger inside the manual repo could look like this: name: Generate TypeScript Control Types
on:
push:
branches:
- '**'
paths:
- 'source/chapters/appendix/mixxx_controls.rst'
permissions: {}
jobs:
trigger-ts-control-types-update:
name: Trigger mixxx-types.ts update on Mixxx repository
needs: build
runs-on: ubuntu-latest
steps:
- name: Start workflow run on Mixxx repository
uses: peter-evans/repository-dispatch@v4
if: env.MIXXXBOT_TOKEN != null
with:
token: ${{ env.MIXXXBOT_TOKEN }}
repository: mixxxdj/mixxx
event-type: update-ts-crtl-types
client-payload: '{"branch": "${{ github.ref_name }}", "ref": "${{ github.ref }}", "sha": "${{ github.sha }}"}'
env:
MIXXXBOT_TOKEN: ${{ secrets.MIXXXBOT_TS_TYPES_AUTOUPDATER_PAT }}I'm a little bit unshure if this is the right way, because we have to pull and build the manual every time. Is it possible to run the Python script when |
|
Could you please move -- |
|
@JoergAtGithub All right, yes, that makes more sense. Then I'll move the |
353582d to
62222d4
Compare
393f3b9 to
3cc299c
Compare
|
Hi, another quick (final?) update:
For documentation, I wrote a little instruction how to use these types: New Type Definitions & Usage GuideProject SetupAdd the new definition files to your {
"compilerOptions": { ... },
"include": [
"/path/to/your/mixxx/controllers/mixxx-controls.d.ts",
"/path/to/your/mixxx/controllers/script-api.d.ts"
]
}
Enhanced Documentation (Optional)To see full control documentation and suggestions in your editor's "Quick Info," use TS Union Docs.
Warning Do not install both the extension and the plugin simultaneously, as this will result in duplicate documentation tooltips. Enabling Strict Type CheckingBy default, these types are permissive (they won't complain if you pass a generic string). To enforce strict checking for groups and controls, create a declare namespace MixxxControls {
interface Config {
strict: true;
}
}Implementation ExampleYou can use these types to build your own typesafe abstractions in TypeScript. Here is an example of a typesafe class Button<TGroup extends MixxxControls.Group> {
constructor(
public group: TGroup,
public inKey: MixxxControls.CtrlRW<TGroup>, // Read or Write controls
public outKey: MixxxControls.Ctrl<TGroup> // Read and Write controls
) {}
enable(): void {
script.triggerControl(this.group, this.inKey);
}
read(): number {
return engine.getValue(this.group, this.outKey);
}
}
// Usage
const playBtn = new Button('[Channel2]', 'play', 'play_indicator'); |
Could you explain why we need a declaration for this one JavaScript-Library only? Until now, we just included the Library-File itself in the |
@JoergAtGithub Yes, because several functions in this library interact with Mixxx Controls. By using a function toggleControl<TGroup extends MixxxControls.Group>(group: TGroup, control: MixxxControls.CtrlRW<TGroup>): void;
function triggerControl<TGroup extends MixxxControls.Group>(group: TGroup, control: MixxxControls.CtrlRW<TGroup>, delay?: number): void;
It’s entirely optional. If you include the declaration file in your The reason I added that is because I use strict types it in my controller mapping that I'm working on, and I thought it might be interesting for others as well. The only disadvantage is that if changes are made to the JS library API, the type definitions would have to be updated accordingly. |
|
from the dev discussion: this is low risk and we'd like to get this in if we can |
Cool, if there is anything else I need to adjust or document further, please let me know :) |
|
@acolombier @daschuer any notes for @Serveny ? |
|
I will test this again this weekend! |
|
I tried and getting it to work with the devcontainer setup but couldn't get it to load unfortunately. Would you be able to help here? I assume I must be missing something... |
|
We should also consider that we published the following setup for mapping developers: https://mixxx.org/news/2024-08-18-controller-api-declartions/ |
@acolombier Hmm, so the problem is you listed the extension in
@JoergAtGithub Yes, developers would mainly need to be informed about the new entries in ts/js-config and about the (optional) plugin. I think what I have written here covers everything. |
|
The |
|
@acolombier That's because the js/ts compiler must be informed that there are definitions. You could add a {
"compilerOptions": {
"allowJs": true,
"checkJs": false,
"noEmit": true
},
"include": [
"*.js",
"*.d.ts"
]
} |
|
Ah indeed, this was the needed fix. Should we add this file in the repo? Or do we think documenting the need for it is enough? |
|
No, the jsconfig.js must always be user specific. It should only list the files, the user really uses in his project.(listed in the mappings XML file) otherwise you see symbols of files you haven't included. |
acolombier
left a comment
There was a problem hiding this comment.
LGTM!
Tested and this provide much better intelisense. It isn't perfect, but it remains a net improvement so let's merge and start from there.



Exact TypeScript type definitions for the Mixxx controls available in JavaScript/TypeScript for full autocompletion and type-checking in your IDE. The editor shows you exactly which controls and groups are available and validates which controls are allowed within a group.
Forum post
Demonstration:
