@tsln/max-api-types 0.0.0
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/LICENSE +21 -0
- package/README.md +57 -0
- package/index.d.ts +160 -0
- package/package.json +41 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mateo Murphy
|
|
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:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
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 THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# @tsln/max-api-types
|
|
2
|
+
|
|
3
|
+
Type declarations for `max-api`, the module Max's `[node.script]` object provides to the
|
|
4
|
+
Node.js process it runs (Node for Max), transcribed from the
|
|
5
|
+
[reference](https://docs.cycling74.com/apiref/nodeformax/).
|
|
6
|
+
|
|
7
|
+
This is the Node.js side of Max. For scripts in `[v8]`, `[js]` and their UI variants see
|
|
8
|
+
[`@tsln/max-types`](../max-types); the two declare globals of the same names and can't be
|
|
9
|
+
loaded together. A project with both kinds of script gives each its own folder and
|
|
10
|
+
`tsconfig.json`; the [repository README](../../README.md#using-the-v8-and-nodescript-types-in-one-project)
|
|
11
|
+
shows the layout.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npm install --save-dev @tsln/max-api-types @types/node
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`max-api` isn't a package to install: `[node.script]` injects it. The declarations are ambient,
|
|
20
|
+
so list the package in `types` and require the module as usual:
|
|
21
|
+
|
|
22
|
+
```jsonc
|
|
23
|
+
{
|
|
24
|
+
"compilerOptions": {
|
|
25
|
+
"types": ["node", "@tsln/max-api-types"]
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import maxAPI = require("max-api");
|
|
32
|
+
|
|
33
|
+
maxAPI.addHandlers({
|
|
34
|
+
bang: () => maxAPI.outletBang(),
|
|
35
|
+
number: (value) => maxAPI.outlet(value * 2), // value: number
|
|
36
|
+
list: (...values) => maxAPI.outlet(values.length), // values: (string | number)[]
|
|
37
|
+
dict: (dict) => maxAPI.post(dict.gain), // dict: JSONObject
|
|
38
|
+
gain: (db: number) => { ... }, // a message of the script's own: `gain -6`
|
|
39
|
+
[maxAPI.MESSAGE_TYPES.ALL]: (handled, ...args) => {
|
|
40
|
+
if (!handled) maxAPI.post("unhandled:", args, maxAPI.POST_LEVELS.WARN);
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Compared to `@types/max-api`
|
|
46
|
+
|
|
47
|
+
DefinitelyTyped has typings for the same module. These differ in two ways:
|
|
48
|
+
|
|
49
|
+
- The module is declared with `export =`, so `import maxAPI = require("max-api")` gives the API
|
|
50
|
+
directly, as it does at runtime, instead of an object with a `default` property.
|
|
51
|
+
- Handlers for the predefined selectors (`bang`, `number`, `list`, `dict`, `all`) are typed with
|
|
52
|
+
what they receive, through `addHandler` and `addHandlers` alike. Handlers for messages of the
|
|
53
|
+
script's own stay open, as `(...args: any[]) => void`.
|
|
54
|
+
|
|
55
|
+
`MAX_ENV`, `MESSAGE_TYPES` and `POST_LEVELS` are declared as the objects of strings they are at
|
|
56
|
+
runtime rather than as enums, so the plain strings work wherever the constants do.
|
|
57
|
+
`process.env.MAX_ENV` is typed with the `MAX_ENV` values.
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
// Type declarations for the "max-api" module that Max's [node.script] object provides to the
|
|
2
|
+
// Node.js process it runs. Transcribed from https://docs.cycling74.com/apiref/nodeformax/
|
|
3
|
+
//
|
|
4
|
+
// This is a Node.js API, not the [v8]/[js] one: it goes with @types/node, and must not be
|
|
5
|
+
// loaded together with @tsln/max-types, which declares globals of the same names.
|
|
6
|
+
|
|
7
|
+
declare module "max-api" {
|
|
8
|
+
// ---- values ----
|
|
9
|
+
|
|
10
|
+
/** A single Max atom, as they arrive in a list or a message. */
|
|
11
|
+
type Atom = string | number;
|
|
12
|
+
|
|
13
|
+
type JSONPrimitive = string | number | boolean | null;
|
|
14
|
+
type JSONArray = JSONValue[];
|
|
15
|
+
interface JSONObject {
|
|
16
|
+
[key: string]: JSONValue | undefined;
|
|
17
|
+
}
|
|
18
|
+
type JSONValue = JSONPrimitive | JSONArray | JSONObject;
|
|
19
|
+
|
|
20
|
+
/** What post() accepts: atoms, a list of atoms, or something JSON-like. */
|
|
21
|
+
type Anything = string | number | Atom[] | JSONObject | JSONArray;
|
|
22
|
+
|
|
23
|
+
// ---- constants ----
|
|
24
|
+
//
|
|
25
|
+
// The reference presents these as enums; at runtime they are plain objects of strings,
|
|
26
|
+
// which is how they are declared here so that the strings themselves can be used too.
|
|
27
|
+
|
|
28
|
+
/** Values Node for Max sets `process.env.MAX_ENV` to. */
|
|
29
|
+
const MAX_ENV: {
|
|
30
|
+
/** node.script running from within Max */
|
|
31
|
+
readonly MAX: "max";
|
|
32
|
+
/** node.script running from within Max for Live */
|
|
33
|
+
readonly MAX_FOR_LIVE: "maxforlive";
|
|
34
|
+
/** node.script running from within a standalone application */
|
|
35
|
+
readonly STANDALONE: "max:standalone";
|
|
36
|
+
};
|
|
37
|
+
type MaxEnv = (typeof MAX_ENV)[keyof typeof MAX_ENV];
|
|
38
|
+
|
|
39
|
+
/** The predefined selectors a handler can be registered for. */
|
|
40
|
+
const MESSAGE_TYPES: {
|
|
41
|
+
/** Every message, after the more specific handlers */
|
|
42
|
+
readonly ALL: "all";
|
|
43
|
+
/** A bang */
|
|
44
|
+
readonly BANG: "bang";
|
|
45
|
+
/** A dictionary */
|
|
46
|
+
readonly DICT: "dict";
|
|
47
|
+
/** A list (a message starting with a number) */
|
|
48
|
+
readonly LIST: "list";
|
|
49
|
+
/** A single number */
|
|
50
|
+
readonly NUMBER: "number";
|
|
51
|
+
};
|
|
52
|
+
type MessageType = (typeof MESSAGE_TYPES)[keyof typeof MESSAGE_TYPES];
|
|
53
|
+
|
|
54
|
+
/** Log levels for post(), given as its last argument. */
|
|
55
|
+
const POST_LEVELS: {
|
|
56
|
+
readonly ERROR: "error";
|
|
57
|
+
readonly INFO: "info";
|
|
58
|
+
readonly WARN: "warn";
|
|
59
|
+
};
|
|
60
|
+
type PostLevel = (typeof POST_LEVELS)[keyof typeof POST_LEVELS];
|
|
61
|
+
|
|
62
|
+
// ---- handlers ----
|
|
63
|
+
|
|
64
|
+
/** What a handler receives for each predefined selector. */
|
|
65
|
+
interface MessageHandlers {
|
|
66
|
+
/**
|
|
67
|
+
* Called for every message, after any more specific handler. `handled` says whether
|
|
68
|
+
* another handler already took the message; the rest is the message as received.
|
|
69
|
+
*/
|
|
70
|
+
all: (handled: boolean, ...args: any[]) => void;
|
|
71
|
+
bang: () => void;
|
|
72
|
+
/** The dictionary's contents. */
|
|
73
|
+
dict: (dict: JSONObject) => void;
|
|
74
|
+
/** The elements of the list. */
|
|
75
|
+
list: (...values: Atom[]) => void;
|
|
76
|
+
number: (value: number) => void;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** A handler for a message of the script's own, `selector arg1 arg2 ...`. */
|
|
80
|
+
type AnyHandler = (...args: any[]) => void;
|
|
81
|
+
|
|
82
|
+
/** Either a predefined selector or a message name of the script's own. */
|
|
83
|
+
type MaxFunctionSelector = MessageType | (string & {});
|
|
84
|
+
|
|
85
|
+
/** The handler type for a selector: typed for the predefined ones, open for the rest. */
|
|
86
|
+
type MaxFunctionHandler<S extends string = string> = S extends keyof MessageHandlers
|
|
87
|
+
? MessageHandlers[S]
|
|
88
|
+
: AnyHandler;
|
|
89
|
+
|
|
90
|
+
/** Handlers by selector, as addHandlers() takes them. */
|
|
91
|
+
interface HandlerMap extends Partial<MessageHandlers> {
|
|
92
|
+
[selector: string]: AnyHandler | undefined;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Registers a handler for a selector: a predefined MESSAGE_TYPES value, or the first
|
|
97
|
+
* word of a message of the script's own.
|
|
98
|
+
* @example
|
|
99
|
+
* maxAPI.addHandler("list", (...values) => maxAPI.outlet(values.length));
|
|
100
|
+
* maxAPI.addHandler("gain", (db: number) => { ... });
|
|
101
|
+
*/
|
|
102
|
+
function addHandler<S extends string>(selector: S, handler: MaxFunctionHandler<S>): void;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Registers several handlers at once, keyed by selector.
|
|
106
|
+
* @example
|
|
107
|
+
* maxAPI.addHandlers({
|
|
108
|
+
* bang: () => maxAPI.outletBang(),
|
|
109
|
+
* [maxAPI.MESSAGE_TYPES.ALL]: (handled, ...args) => { if (!handled) maxAPI.post(args); },
|
|
110
|
+
* });
|
|
111
|
+
*/
|
|
112
|
+
function addHandlers(handlers: HandlerMap): void;
|
|
113
|
+
|
|
114
|
+
/** Removes one handler previously registered for the selector. */
|
|
115
|
+
function removeHandler<S extends string>(selector: S, handler: MaxFunctionHandler<S>): void;
|
|
116
|
+
|
|
117
|
+
/** Removes every handler registered for the selector. */
|
|
118
|
+
function removeHandlers(selector: MaxFunctionSelector): void;
|
|
119
|
+
|
|
120
|
+
// ---- output ----
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Sends the values out of the [node.script] outlet: atoms as a message or list, arrays
|
|
124
|
+
* and objects as a dictionary. Resolves once Max has received them.
|
|
125
|
+
*/
|
|
126
|
+
function outlet(...args: JSONValue[]): Promise<void>;
|
|
127
|
+
|
|
128
|
+
/** Sends a bang out of the [node.script] outlet. */
|
|
129
|
+
function outletBang(): Promise<void>;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Posts to the Max console. A POST_LEVELS value as the last argument sets the level.
|
|
133
|
+
* @example
|
|
134
|
+
* maxAPI.post("something went wrong", maxAPI.POST_LEVELS.ERROR);
|
|
135
|
+
*/
|
|
136
|
+
function post(...args: (Anything | PostLevel)[]): Promise<void>;
|
|
137
|
+
|
|
138
|
+
// ---- dictionaries ----
|
|
139
|
+
|
|
140
|
+
/** Reads the contents of the named [dict]. */
|
|
141
|
+
function getDict(id: string): Promise<JSONObject>;
|
|
142
|
+
|
|
143
|
+
/** Replaces the contents of the named [dict], and resolves with the new contents. */
|
|
144
|
+
function setDict(id: string, dict: JSONObject): Promise<JSONObject>;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Sets one value in the named [dict] at a path such as `"a.b.c"` or `"items[2]"`, and
|
|
148
|
+
* resolves with the whole new contents.
|
|
149
|
+
*/
|
|
150
|
+
function updateDict(id: string, updatePath: string, updateValue: JSONValue): Promise<JSONObject>;
|
|
151
|
+
|
|
152
|
+
global {
|
|
153
|
+
namespace NodeJS {
|
|
154
|
+
interface ProcessEnv {
|
|
155
|
+
/** Set by Node for Max to say what the script is running inside; see MAX_ENV. */
|
|
156
|
+
MAX_ENV?: MaxEnv;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tsln/max-api-types",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Type declarations for the max-api module of Max's [node.script] object (Node for Max)",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Mateo Murphy",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/tsln-lab/max-packages.git",
|
|
10
|
+
"directory": "packages/max-api-types"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"max",
|
|
14
|
+
"msp",
|
|
15
|
+
"max-msp",
|
|
16
|
+
"node-for-max",
|
|
17
|
+
"node.script",
|
|
18
|
+
"max-api",
|
|
19
|
+
"cycling74",
|
|
20
|
+
"typescript",
|
|
21
|
+
"types"
|
|
22
|
+
],
|
|
23
|
+
"types": "./index.d.ts",
|
|
24
|
+
"files": [
|
|
25
|
+
"*.d.ts",
|
|
26
|
+
"README.md",
|
|
27
|
+
"CHANGELOG.md",
|
|
28
|
+
"LICENSE"
|
|
29
|
+
],
|
|
30
|
+
"sideEffects": false,
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^22.0.0",
|
|
36
|
+
"typescript": "7.0.2"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"typecheck": "tsc -p tsconfig.json"
|
|
40
|
+
}
|
|
41
|
+
}
|