@textmode/runner-protocol 0.1.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 +122 -0
- package/README.md +121 -0
- package/dist/capabilities.d.ts +39 -0
- package/dist/capabilities.js +21 -0
- package/dist/exports.d.ts +120 -0
- package/dist/exports.js +1 -0
- package/dist/guards.d.ts +26 -0
- package/dist/guards.internal.d.ts +17 -0
- package/dist/guards.internal.js +64 -0
- package/dist/guards.js +116 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +15 -0
- package/dist/messages.d.ts +300 -0
- package/dist/messages.js +1 -0
- package/dist/playback.d.ts +21 -0
- package/dist/playback.js +1 -0
- package/dist/runtime.d.ts +15 -0
- package/dist/runtime.js +1 -0
- package/package.json +32 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
Creative Commons Legal Code
|
|
2
|
+
|
|
3
|
+
CC0 1.0 Universal
|
|
4
|
+
|
|
5
|
+
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
|
6
|
+
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
|
7
|
+
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
|
8
|
+
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
|
9
|
+
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
|
10
|
+
HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF
|
|
11
|
+
THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER.
|
|
12
|
+
|
|
13
|
+
Statement of Purpose
|
|
14
|
+
|
|
15
|
+
The laws of most jurisdictions throughout the world automatically confer
|
|
16
|
+
exclusive Copyright and Related Rights (defined below) upon the creator
|
|
17
|
+
and subsequent owner(s) (each and all, an "owner") of an original work of
|
|
18
|
+
authorship and/or a database (each, a "Work").
|
|
19
|
+
|
|
20
|
+
Certain owners wish to permanently relinquish those rights to a Work for
|
|
21
|
+
the purpose of contributing to a commons of creative, cultural and
|
|
22
|
+
scientific works ("Commons") that the public can reliably and without
|
|
23
|
+
fear of later claims of infringement build upon, modify, incorporate in
|
|
24
|
+
other works, reuse and redistribute as freely as possible in any form
|
|
25
|
+
whatsoever and for any purposes, including without limitation commercial
|
|
26
|
+
purposes. These owners may contribute to the Commons to promote the ideal
|
|
27
|
+
of a free culture and the further production of creative, cultural and
|
|
28
|
+
scientific works, or to gain reputation or greater distribution for their
|
|
29
|
+
Work in part through the use and efforts of others.
|
|
30
|
+
|
|
31
|
+
For these and/or other purposes and motivations, and without any
|
|
32
|
+
expectation of additional consideration or compensation, the person
|
|
33
|
+
associating CC0 with a Work (the "Affirmer"), to the extent that he or
|
|
34
|
+
she is an owner of Copyright and Related Rights in the Work, voluntarily
|
|
35
|
+
elects to apply CC0 to the Work and publicly distribute the Work under
|
|
36
|
+
its terms, with knowledge of his or her Copyright and Related Rights in
|
|
37
|
+
the Work and the meaning and intended legal effect of CC0 on those
|
|
38
|
+
rights.
|
|
39
|
+
|
|
40
|
+
1. Copyright and Related Rights. A Work made available under CC0 may be
|
|
41
|
+
protected by copyright and related or neighboring rights ("Copyright and
|
|
42
|
+
Related Rights"). Copyright and Related Rights include, but are not
|
|
43
|
+
limited to, the following:
|
|
44
|
+
|
|
45
|
+
i. the right to reproduce, adapt, distribute, perform, display,
|
|
46
|
+
communicate, and translate a Work;
|
|
47
|
+
ii. moral rights retained by the original author(s) and/or performer(s);
|
|
48
|
+
iii. publicity and privacy rights pertaining to a person's image or
|
|
49
|
+
likeness depicted in a Work;
|
|
50
|
+
iv. rights protecting against unfair competition in regards to a Work,
|
|
51
|
+
subject to the limitations in paragraph 4(a), below;
|
|
52
|
+
v. rights protecting the extraction, dissemination, use and reuse of
|
|
53
|
+
data in a Work;
|
|
54
|
+
vi. database rights (such as those arising under Directive 96/9/EC of
|
|
55
|
+
the European Parliament and of the Council of 11 March 1996 on the
|
|
56
|
+
legal protection of databases, and under any national implementation
|
|
57
|
+
thereof, including any amended or successor version of such
|
|
58
|
+
directive); and
|
|
59
|
+
vii. other similar, equivalent or corresponding rights throughout the
|
|
60
|
+
world based on applicable law or treaty, and any national
|
|
61
|
+
implementations thereof.
|
|
62
|
+
|
|
63
|
+
2. Waiver. To the greatest extent permitted by, but not in contravention
|
|
64
|
+
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
|
65
|
+
irrevocably and unconditionally waives, abandons, and surrenders all of
|
|
66
|
+
Affirmer's Copyright and Related Rights and associated claims and causes
|
|
67
|
+
of action, whether now known or unknown (including existing as well as
|
|
68
|
+
future claims and causes of action), in the Work (i) in all territories
|
|
69
|
+
worldwide, (ii) for the maximum duration provided by applicable law or
|
|
70
|
+
treaty (including future time extensions), (iii) in any current or future
|
|
71
|
+
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
|
72
|
+
including without limitation commercial, advertising or promotional
|
|
73
|
+
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of
|
|
74
|
+
each member of the public at large and to the detriment of Affirmer's
|
|
75
|
+
heirs and successors, fully intending that such Waiver shall not be
|
|
76
|
+
subject to revocation, rescission, cancellation, termination, or any
|
|
77
|
+
other legal or equitable action to disrupt the quiet enjoyment of the
|
|
78
|
+
Work by the public as contemplated by Affirmer's express Statement of
|
|
79
|
+
Purpose.
|
|
80
|
+
|
|
81
|
+
3. Public License Fallback. Should any part of the Waiver for any reason
|
|
82
|
+
be judged legally invalid or ineffective under applicable law, then the
|
|
83
|
+
Waiver shall be preserved to the maximum extent permitted taking into
|
|
84
|
+
account Affirmer's express Statement of Purpose. In addition, to the
|
|
85
|
+
extent the Waiver is so judged Affirmer hereby grants to each affected
|
|
86
|
+
person a royalty-free, non transferable, non sublicensable, non
|
|
87
|
+
exclusive, irrevocable and unconditional license to exercise Affirmer's
|
|
88
|
+
Copyright and Related Rights in the Work (i) in all territories
|
|
89
|
+
worldwide, (ii) for the maximum duration provided by applicable law or
|
|
90
|
+
treaty (including future time extensions), (iii) in any current or future
|
|
91
|
+
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
|
92
|
+
including without limitation commercial, advertising or promotional
|
|
93
|
+
purposes (the "License"). The License shall be deemed effective as of the
|
|
94
|
+
date CC0 was applied by Affirmer to the Work. Should any part of the
|
|
95
|
+
License for any reason be judged legally invalid or ineffective under
|
|
96
|
+
applicable law, such partial invalidity or ineffectiveness shall not
|
|
97
|
+
invalidate the remainder of the License, and in such case Affirmer hereby
|
|
98
|
+
affirms that he or she will not (i) exercise any of his or her remaining
|
|
99
|
+
Copyright and Related Rights in the Work or (ii) assert any associated
|
|
100
|
+
claims and causes of action with respect to the Work, in either case
|
|
101
|
+
contrary to Affirmer's express Statement of Purpose.
|
|
102
|
+
|
|
103
|
+
4. Limitations and Disclaimers.
|
|
104
|
+
|
|
105
|
+
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
|
106
|
+
surrendered, licensed or otherwise affected by this document.
|
|
107
|
+
b. Affirmer offers the Work as-is and makes no representations or
|
|
108
|
+
warranties of any kind concerning the Work, express, implied,
|
|
109
|
+
statutory or otherwise, including without limitation warranties of
|
|
110
|
+
title, merchantability, fitness for a particular purpose, non
|
|
111
|
+
infringement, or the absence of latent or other defects, accuracy, or
|
|
112
|
+
the present or absence of errors, whether or not discoverable, all to
|
|
113
|
+
the greatest extent permissible under applicable law.
|
|
114
|
+
c. Affirmer disclaims responsibility for clearing rights of other
|
|
115
|
+
persons that may apply to the Work or any use thereof, including
|
|
116
|
+
without limitation any person's Copyright and Related Rights in the
|
|
117
|
+
Work. Further, Affirmer disclaims responsibility for obtaining any
|
|
118
|
+
necessary consents, permissions or other rights required for any use
|
|
119
|
+
of the Work.
|
|
120
|
+
d. Affirmer understands and acknowledges that Creative Commons is not a
|
|
121
|
+
party to this document and has no duty or obligation with respect to
|
|
122
|
+
this CC0 or use of the Work.
|
package/README.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# @textmode/runner-protocol
|
|
2
|
+
|
|
3
|
+
Shared TypeScript message contract for the hosted textmode runner iframe.
|
|
4
|
+
|
|
5
|
+
This package is the single source of truth for the wire messages exchanged by
|
|
6
|
+
the runner and browser host apps in the textmode.js ecosystem.
|
|
7
|
+
It contains the public message types, capability model, runtime settings,
|
|
8
|
+
export/playback/font payloads, and runtime validators used on both sides of the
|
|
9
|
+
iframe boundary.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
npm install @textmode/runner-protocol
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import {
|
|
21
|
+
createRunnerCapabilities,
|
|
22
|
+
isParentMessage,
|
|
23
|
+
isRunnerMessage,
|
|
24
|
+
type ParentToRunnerMessage,
|
|
25
|
+
type RunnerToParentMessage,
|
|
26
|
+
} from '@textmode/runner-protocol';
|
|
27
|
+
|
|
28
|
+
const capabilities = createRunnerCapabilities();
|
|
29
|
+
|
|
30
|
+
function handleParentMessage(message: unknown): void {
|
|
31
|
+
if (!isParentMessage(message)) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
runMessage(message);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function sendRunnerMessage(message: RunnerToParentMessage): void {
|
|
39
|
+
if (isRunnerMessage(message)) {
|
|
40
|
+
port.postMessage(message);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function runMessage(message: ParentToRunnerMessage): void {
|
|
45
|
+
switch (message.type) {
|
|
46
|
+
case 'RUN_CODE':
|
|
47
|
+
runCode(message.code, message.requestId);
|
|
48
|
+
break;
|
|
49
|
+
case 'PING':
|
|
50
|
+
port.postMessage({ type: 'PONG', nonce: message.nonce, timestamp: Date.now() });
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Public API
|
|
57
|
+
|
|
58
|
+
Import from the package root only:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { isRunnerMessage, type RuntimeSettings } from '@textmode/runner-protocol';
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Public subpath imports are intentionally not supported. This keeps the protocol
|
|
65
|
+
package free to reorganize internal modules without breaking consumers.
|
|
66
|
+
|
|
67
|
+
The main exports are grouped around:
|
|
68
|
+
|
|
69
|
+
- capabilities: `RunnerCapabilities`, `ExportFormat`,
|
|
70
|
+
`createRunnerCapabilities`
|
|
71
|
+
- runtime settings: `RuntimeSettings`
|
|
72
|
+
- exports: image, SVG, TXT, GIF, and WebM option/result/progress types
|
|
73
|
+
- playback: `PlaybackAction`, `PlaybackState`
|
|
74
|
+
- messages: `InitMessage`, `ParentToRunnerMessage`, `RunnerToParentMessage`,
|
|
75
|
+
`Message`
|
|
76
|
+
- guards: `isInitMessage`, `isParentMessage`, `isRunnerMessage`,
|
|
77
|
+
`isRunnerCapabilities`
|
|
78
|
+
|
|
79
|
+
## Protocol Model
|
|
80
|
+
|
|
81
|
+
The runner protocol has one current message shape. Runtime protocol version
|
|
82
|
+
negotiation is intentionally absent: npm package semver describes source
|
|
83
|
+
compatibility, while runner feature availability is described through
|
|
84
|
+
capabilities.
|
|
85
|
+
|
|
86
|
+
The initial window message is generic for every host app:
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
{ type: 'INIT' }
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
After a successful handshake, the runner responds with:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
{ type: 'READY', capabilities: RunnerCapabilities }
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Messages sent after that point use the `ParentToRunnerMessage` and
|
|
99
|
+
`RunnerToParentMessage` unions.
|
|
100
|
+
|
|
101
|
+
## Validation
|
|
102
|
+
|
|
103
|
+
The exported guards are strict runtime validators for untrusted `postMessage`
|
|
104
|
+
payloads. Use them before dispatching messages across the iframe boundary:
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
if (!isRunnerMessage(event.data)) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The guards reject retired app-identity and protocol-version fields such as
|
|
113
|
+
`client`, `v`, `clients`, and `protocolVersions`.
|
|
114
|
+
|
|
115
|
+
## API Docs
|
|
116
|
+
|
|
117
|
+
Generated TypeDoc Markdown lives in [`api/runner-protocol`](./api/runner-protocol/index.md).
|
|
118
|
+
|
|
119
|
+
## License
|
|
120
|
+
|
|
121
|
+
CC0-1.0. See [LICENSE](./LICENSE).
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Export families supported by the current runner.
|
|
3
|
+
*
|
|
4
|
+
* @category Capabilities
|
|
5
|
+
*/
|
|
6
|
+
export declare const EXPORT_FORMATS: readonly ["image", "svg", "txt", "gif", "webm"];
|
|
7
|
+
/**
|
|
8
|
+
* Export format advertised by runner capabilities and export messages.
|
|
9
|
+
*
|
|
10
|
+
* @category Capabilities
|
|
11
|
+
*/
|
|
12
|
+
export type ExportFormat = (typeof EXPORT_FORMATS)[number];
|
|
13
|
+
/**
|
|
14
|
+
* Feature flags advertised by a ready runner iframe.
|
|
15
|
+
*
|
|
16
|
+
* Capabilities describe feature availability only. They are not a runtime
|
|
17
|
+
* protocol version negotiation mechanism.
|
|
18
|
+
*
|
|
19
|
+
* @category Capabilities
|
|
20
|
+
*/
|
|
21
|
+
export interface RunnerCapabilities {
|
|
22
|
+
/** Whether fixed runtime settings can be configured before execution. */
|
|
23
|
+
runtimeConfig: boolean;
|
|
24
|
+
/** Export formats available through the runner. */
|
|
25
|
+
exports: ExportFormat[];
|
|
26
|
+
/** Whether host apps can load fonts into the runner. */
|
|
27
|
+
fonts: boolean;
|
|
28
|
+
/** Whether playback controls and state reporting are available. */
|
|
29
|
+
playback: boolean;
|
|
30
|
+
/** Whether the runner responds to heartbeat pings. */
|
|
31
|
+
heartbeat: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Creates the capability set for the current hosted runner implementation.
|
|
35
|
+
*
|
|
36
|
+
* @returns The current runner capability set.
|
|
37
|
+
* @category Capabilities
|
|
38
|
+
*/
|
|
39
|
+
export declare function createRunnerCapabilities(): RunnerCapabilities;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Export families supported by the current runner.
|
|
3
|
+
*
|
|
4
|
+
* @category Capabilities
|
|
5
|
+
*/
|
|
6
|
+
export const EXPORT_FORMATS = ['image', 'svg', 'txt', 'gif', 'webm'];
|
|
7
|
+
/**
|
|
8
|
+
* Creates the capability set for the current hosted runner implementation.
|
|
9
|
+
*
|
|
10
|
+
* @returns The current runner capability set.
|
|
11
|
+
* @category Capabilities
|
|
12
|
+
*/
|
|
13
|
+
export function createRunnerCapabilities() {
|
|
14
|
+
return {
|
|
15
|
+
runtimeConfig: true,
|
|
16
|
+
exports: [...EXPORT_FORMATS],
|
|
17
|
+
fonts: true,
|
|
18
|
+
playback: true,
|
|
19
|
+
heartbeat: true,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import type { ExportFormat } from './capabilities';
|
|
2
|
+
/**
|
|
3
|
+
* Raster image export file format.
|
|
4
|
+
*
|
|
5
|
+
* @category Exports
|
|
6
|
+
*/
|
|
7
|
+
export type ImageExportFormat = 'png' | 'jpg' | 'webp';
|
|
8
|
+
/**
|
|
9
|
+
* Options for raster image exports.
|
|
10
|
+
*
|
|
11
|
+
* @category Exports
|
|
12
|
+
*/
|
|
13
|
+
export interface ImageExportOptions {
|
|
14
|
+
/** Output image format. */
|
|
15
|
+
format?: ImageExportFormat;
|
|
16
|
+
/** Export scale multiplier. */
|
|
17
|
+
scale?: number;
|
|
18
|
+
/** Encoder quality for lossy image formats. */
|
|
19
|
+
quality?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Options for SVG exports.
|
|
23
|
+
*
|
|
24
|
+
* @category Exports
|
|
25
|
+
*/
|
|
26
|
+
export interface SvgExportOptions {
|
|
27
|
+
/** Whether to include background rectangles in the SVG output. */
|
|
28
|
+
includeBackgroundRectangles?: boolean;
|
|
29
|
+
/** SVG drawing mode for text geometry. */
|
|
30
|
+
drawMode?: 'fill' | 'stroke';
|
|
31
|
+
/** Stroke width used when `drawMode` is `stroke`. */
|
|
32
|
+
strokeWidth?: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Options for plain text exports.
|
|
36
|
+
*
|
|
37
|
+
* @category Exports
|
|
38
|
+
*/
|
|
39
|
+
export interface TxtExportOptions {
|
|
40
|
+
/** Whether trailing spaces should be preserved. */
|
|
41
|
+
preserveTrailingSpaces?: boolean;
|
|
42
|
+
/** Line ending style for generated text. */
|
|
43
|
+
lineEnding?: 'lf' | 'crlf';
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Options for animated GIF exports.
|
|
47
|
+
*
|
|
48
|
+
* @category Exports
|
|
49
|
+
*/
|
|
50
|
+
export interface GifExportOptions {
|
|
51
|
+
/** Suggested filename without requiring the runner to initiate a download. */
|
|
52
|
+
filename?: string;
|
|
53
|
+
/** Number of frames to record. */
|
|
54
|
+
frameCount?: number;
|
|
55
|
+
/** Capture frame rate. */
|
|
56
|
+
frameRate?: number;
|
|
57
|
+
/** Export scale multiplier. */
|
|
58
|
+
scale?: number;
|
|
59
|
+
/** GIF repeat count. */
|
|
60
|
+
repeat?: number;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Options for WebM exports.
|
|
64
|
+
*
|
|
65
|
+
* @category Exports
|
|
66
|
+
*/
|
|
67
|
+
export interface WebmExportOptions {
|
|
68
|
+
/** Suggested filename without requiring the runner to initiate a download. */
|
|
69
|
+
filename?: string;
|
|
70
|
+
/** Number of frames to record. */
|
|
71
|
+
frameCount?: number;
|
|
72
|
+
/** Capture frame rate. */
|
|
73
|
+
frameRate?: number;
|
|
74
|
+
/** Encoder quality hint. */
|
|
75
|
+
quality?: number;
|
|
76
|
+
/** Whether the export should preserve transparency when supported. */
|
|
77
|
+
transparent?: boolean;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Typed export request payload grouped by export format.
|
|
81
|
+
*
|
|
82
|
+
* @category Exports
|
|
83
|
+
*/
|
|
84
|
+
export type ExportRequest = {
|
|
85
|
+
format: 'image';
|
|
86
|
+
options?: ImageExportOptions;
|
|
87
|
+
} | {
|
|
88
|
+
format: 'svg';
|
|
89
|
+
options?: SvgExportOptions;
|
|
90
|
+
} | {
|
|
91
|
+
format: 'txt';
|
|
92
|
+
options?: TxtExportOptions;
|
|
93
|
+
} | {
|
|
94
|
+
format: 'gif';
|
|
95
|
+
options?: GifExportOptions;
|
|
96
|
+
} | {
|
|
97
|
+
format: 'webm';
|
|
98
|
+
options?: WebmExportOptions;
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Progress payload emitted while recording multi-frame exports.
|
|
102
|
+
*
|
|
103
|
+
* @category Exports
|
|
104
|
+
*/
|
|
105
|
+
export interface ExportProgress {
|
|
106
|
+
/** Export lifecycle state reported by the runner. */
|
|
107
|
+
state: string;
|
|
108
|
+
/** Zero-based frame currently being recorded, when applicable. */
|
|
109
|
+
frameIndex?: number;
|
|
110
|
+
/** Total frame count for the export, when known. */
|
|
111
|
+
totalFrames?: number;
|
|
112
|
+
/** Optional human-readable progress detail. */
|
|
113
|
+
message?: string;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Export format used by the protocol.
|
|
117
|
+
*
|
|
118
|
+
* @category Exports
|
|
119
|
+
*/
|
|
120
|
+
export type ProtocolExportFormat = ExportFormat;
|
package/dist/exports.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/guards.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { RunnerCapabilities } from './capabilities';
|
|
2
|
+
import type { InitMessage, ParentToRunnerMessage, RunnerToParentMessage } from './messages';
|
|
3
|
+
/**
|
|
4
|
+
* Checks whether a value is a valid current runner-to-host message.
|
|
5
|
+
*
|
|
6
|
+
* @category Guards
|
|
7
|
+
*/
|
|
8
|
+
export declare function isRunnerMessage(msg: unknown): msg is RunnerToParentMessage;
|
|
9
|
+
/**
|
|
10
|
+
* Checks whether a value is a valid current host-to-runner MessagePort message.
|
|
11
|
+
*
|
|
12
|
+
* @category Guards
|
|
13
|
+
*/
|
|
14
|
+
export declare function isParentMessage(msg: unknown): msg is ParentToRunnerMessage;
|
|
15
|
+
/**
|
|
16
|
+
* Checks whether a value is a valid current runner iframe initialization message.
|
|
17
|
+
*
|
|
18
|
+
* @category Guards
|
|
19
|
+
*/
|
|
20
|
+
export declare function isInitMessage(msg: unknown): msg is InitMessage;
|
|
21
|
+
/**
|
|
22
|
+
* Checks whether a value is a valid current runner capability set.
|
|
23
|
+
*
|
|
24
|
+
* @category Guards
|
|
25
|
+
*/
|
|
26
|
+
export declare function isRunnerCapabilities(value: unknown): value is RunnerCapabilities;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type ExportFormat } from './capabilities';
|
|
2
|
+
import type { ExportProgress } from './exports';
|
|
3
|
+
import type { PlaybackAction, PlaybackState } from './playback';
|
|
4
|
+
import type { RuntimeSettings } from './runtime';
|
|
5
|
+
export declare function isMessageRecord(value: unknown): value is Record<string, unknown> & {
|
|
6
|
+
type?: unknown;
|
|
7
|
+
};
|
|
8
|
+
export declare function isFiniteNumber(value: unknown): value is number;
|
|
9
|
+
export declare function isOptionalString(value: unknown): value is string | undefined;
|
|
10
|
+
export declare function isOptionalFiniteNumber(value: unknown): value is number | undefined;
|
|
11
|
+
export declare function isOptionalBlob(value: unknown): value is Blob | undefined;
|
|
12
|
+
export declare function isRuntimeSettings(value: unknown): value is RuntimeSettings;
|
|
13
|
+
export declare function isPartialRuntimeSettings(value: unknown): value is Partial<RuntimeSettings>;
|
|
14
|
+
export declare function isExportFormat(value: unknown): value is ExportFormat;
|
|
15
|
+
export declare function isPlaybackAction(value: unknown): value is PlaybackAction;
|
|
16
|
+
export declare function isPlaybackState(value: unknown): value is PlaybackState;
|
|
17
|
+
export declare function isExportProgress(value: unknown): value is ExportProgress;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { EXPORT_FORMATS } from './capabilities';
|
|
2
|
+
export function isMessageRecord(value) {
|
|
3
|
+
return typeof value === 'object' && value !== null;
|
|
4
|
+
}
|
|
5
|
+
export function isFiniteNumber(value) {
|
|
6
|
+
return typeof value === 'number' && Number.isFinite(value);
|
|
7
|
+
}
|
|
8
|
+
export function isOptionalString(value) {
|
|
9
|
+
return value === undefined || typeof value === 'string';
|
|
10
|
+
}
|
|
11
|
+
export function isOptionalFiniteNumber(value) {
|
|
12
|
+
return value === undefined || isFiniteNumber(value);
|
|
13
|
+
}
|
|
14
|
+
export function isOptionalBlob(value) {
|
|
15
|
+
return value === undefined || (typeof Blob !== 'undefined' && value instanceof Blob);
|
|
16
|
+
}
|
|
17
|
+
export function isRuntimeSettings(value) {
|
|
18
|
+
if (!isMessageRecord(value))
|
|
19
|
+
return false;
|
|
20
|
+
return (isPositiveFiniteNumber(value.width) &&
|
|
21
|
+
isPositiveFiniteNumber(value.height) &&
|
|
22
|
+
isPositiveFiniteNumber(value.fontSize) &&
|
|
23
|
+
isPositiveFiniteNumber(value.frameRate));
|
|
24
|
+
}
|
|
25
|
+
export function isPartialRuntimeSettings(value) {
|
|
26
|
+
if (!isMessageRecord(value))
|
|
27
|
+
return false;
|
|
28
|
+
return ((value.width === undefined || isPositiveFiniteNumber(value.width)) &&
|
|
29
|
+
(value.height === undefined || isPositiveFiniteNumber(value.height)) &&
|
|
30
|
+
(value.fontSize === undefined || isPositiveFiniteNumber(value.fontSize)) &&
|
|
31
|
+
(value.frameRate === undefined || isPositiveFiniteNumber(value.frameRate)));
|
|
32
|
+
}
|
|
33
|
+
export function isExportFormat(value) {
|
|
34
|
+
return EXPORT_FORMATS.includes(value);
|
|
35
|
+
}
|
|
36
|
+
export function isPlaybackAction(value) {
|
|
37
|
+
return (value === 'play' ||
|
|
38
|
+
value === 'pause' ||
|
|
39
|
+
value === 'stop' ||
|
|
40
|
+
value === 'seek' ||
|
|
41
|
+
value === 'next' ||
|
|
42
|
+
value === 'previous' ||
|
|
43
|
+
value === 'setMaxFrames' ||
|
|
44
|
+
value === 'state');
|
|
45
|
+
}
|
|
46
|
+
export function isPlaybackState(value) {
|
|
47
|
+
if (!isMessageRecord(value))
|
|
48
|
+
return false;
|
|
49
|
+
return (typeof value.isPlaying === 'boolean' &&
|
|
50
|
+
isFiniteNumber(value.frame) &&
|
|
51
|
+
isFiniteNumber(value.maxFrames) &&
|
|
52
|
+
(value.fps === undefined || isFiniteNumber(value.fps)));
|
|
53
|
+
}
|
|
54
|
+
export function isExportProgress(value) {
|
|
55
|
+
if (!isMessageRecord(value))
|
|
56
|
+
return false;
|
|
57
|
+
return (typeof value.state === 'string' &&
|
|
58
|
+
isOptionalFiniteNumber(value.frameIndex) &&
|
|
59
|
+
isOptionalFiniteNumber(value.totalFrames) &&
|
|
60
|
+
isOptionalString(value.message));
|
|
61
|
+
}
|
|
62
|
+
function isPositiveFiniteNumber(value) {
|
|
63
|
+
return isFiniteNumber(value) && value > 0;
|
|
64
|
+
}
|
package/dist/guards.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { isExportFormat, isExportProgress, isFiniteNumber, isMessageRecord, isOptionalBlob, isOptionalFiniteNumber, isOptionalString, isPartialRuntimeSettings, isPlaybackAction, isPlaybackState, isRuntimeSettings, } from './guards.internal';
|
|
2
|
+
/**
|
|
3
|
+
* Checks whether a value is a valid current runner-to-host message.
|
|
4
|
+
*
|
|
5
|
+
* @category Guards
|
|
6
|
+
*/
|
|
7
|
+
export function isRunnerMessage(msg) {
|
|
8
|
+
if (!isMessageRecord(msg))
|
|
9
|
+
return false;
|
|
10
|
+
switch (msg.type) {
|
|
11
|
+
case 'READY':
|
|
12
|
+
return !('v' in msg) && isRunnerCapabilities(msg.capabilities);
|
|
13
|
+
case 'TOGGLE_UI':
|
|
14
|
+
case 'USER_INTERACTION':
|
|
15
|
+
return true;
|
|
16
|
+
case 'RUN_OK':
|
|
17
|
+
return isFiniteNumber(msg.timestamp) && isOptionalString(msg.requestId);
|
|
18
|
+
case 'RUN_ERROR':
|
|
19
|
+
return (typeof msg.message === 'string' &&
|
|
20
|
+
isOptionalString(msg.stack) &&
|
|
21
|
+
isOptionalFiniteNumber(msg.line) &&
|
|
22
|
+
isOptionalFiniteNumber(msg.column) &&
|
|
23
|
+
isOptionalString(msg.requestId));
|
|
24
|
+
case 'SYNTH_ERROR':
|
|
25
|
+
return typeof msg.message === 'string' && isOptionalString(msg.uniformName);
|
|
26
|
+
case 'EXPORT_RESULT':
|
|
27
|
+
return (typeof msg.requestId === 'string' &&
|
|
28
|
+
isExportFormat(msg.format) &&
|
|
29
|
+
isOptionalBlob(msg.blob) &&
|
|
30
|
+
isOptionalString(msg.text) &&
|
|
31
|
+
isOptionalString(msg.filename) &&
|
|
32
|
+
isOptionalString(msg.mimeType));
|
|
33
|
+
case 'EXPORT_PROGRESS':
|
|
34
|
+
return (typeof msg.requestId === 'string' &&
|
|
35
|
+
(msg.format === 'gif' || msg.format === 'webm') &&
|
|
36
|
+
isExportProgress(msg.progress));
|
|
37
|
+
case 'FONT_LOADED':
|
|
38
|
+
return (typeof msg.requestId === 'string' &&
|
|
39
|
+
(msg.familyName === null || typeof msg.familyName === 'string') &&
|
|
40
|
+
Array.isArray(msg.characters) &&
|
|
41
|
+
msg.characters.every((entry) => typeof entry === 'string'));
|
|
42
|
+
case 'FONT_ERROR':
|
|
43
|
+
return typeof msg.requestId === 'string' && typeof msg.message === 'string';
|
|
44
|
+
case 'PLAYBACK_STATE':
|
|
45
|
+
return isOptionalString(msg.requestId) && isPlaybackState(msg.state);
|
|
46
|
+
case 'PONG':
|
|
47
|
+
return isOptionalString(msg.nonce) && isFiniteNumber(msg.timestamp);
|
|
48
|
+
default:
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Checks whether a value is a valid current host-to-runner MessagePort message.
|
|
54
|
+
*
|
|
55
|
+
* @category Guards
|
|
56
|
+
*/
|
|
57
|
+
export function isParentMessage(msg) {
|
|
58
|
+
if (!isMessageRecord(msg))
|
|
59
|
+
return false;
|
|
60
|
+
switch (msg.type) {
|
|
61
|
+
case 'RUN_CODE':
|
|
62
|
+
case 'SOFT_RESET':
|
|
63
|
+
return typeof msg.code === 'string' && isOptionalString(msg.requestId);
|
|
64
|
+
case 'DISPOSE':
|
|
65
|
+
return true;
|
|
66
|
+
case 'CONFIGURE_RUNTIME':
|
|
67
|
+
return isRuntimeSettings(msg.settings) && isOptionalString(msg.requestId);
|
|
68
|
+
case 'SET_SETTINGS':
|
|
69
|
+
return isPartialRuntimeSettings(msg.settings) && isOptionalString(msg.requestId);
|
|
70
|
+
case 'EXPORT':
|
|
71
|
+
return (typeof msg.requestId === 'string' &&
|
|
72
|
+
isExportFormat(msg.format) &&
|
|
73
|
+
(msg.options === undefined || isMessageRecord(msg.options)));
|
|
74
|
+
case 'LOAD_FONT':
|
|
75
|
+
return (typeof msg.requestId === 'string' &&
|
|
76
|
+
typeof msg.fileName === 'string' &&
|
|
77
|
+
isOptionalString(msg.mimeType) &&
|
|
78
|
+
msg.buffer instanceof ArrayBuffer);
|
|
79
|
+
case 'PLAYBACK':
|
|
80
|
+
return (isOptionalString(msg.requestId) &&
|
|
81
|
+
isPlaybackAction(msg.action) &&
|
|
82
|
+
isOptionalFiniteNumber(msg.frame) &&
|
|
83
|
+
isOptionalFiniteNumber(msg.maxFrames));
|
|
84
|
+
case 'PING':
|
|
85
|
+
return isOptionalString(msg.nonce);
|
|
86
|
+
default:
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Checks whether a value is a valid current runner iframe initialization message.
|
|
92
|
+
*
|
|
93
|
+
* @category Guards
|
|
94
|
+
*/
|
|
95
|
+
export function isInitMessage(msg) {
|
|
96
|
+
return isMessageRecord(msg) && msg.type === 'INIT' && Object.keys(msg).length === 1;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Checks whether a value is a valid current runner capability set.
|
|
100
|
+
*
|
|
101
|
+
* @category Guards
|
|
102
|
+
*/
|
|
103
|
+
export function isRunnerCapabilities(value) {
|
|
104
|
+
if (!isMessageRecord(value))
|
|
105
|
+
return false;
|
|
106
|
+
if ('protocolVersions' in value)
|
|
107
|
+
return false;
|
|
108
|
+
if ('clients' in value)
|
|
109
|
+
return false;
|
|
110
|
+
return (typeof value.runtimeConfig === 'boolean' &&
|
|
111
|
+
Array.isArray(value.exports) &&
|
|
112
|
+
value.exports.every(isExportFormat) &&
|
|
113
|
+
typeof value.fonts === 'boolean' &&
|
|
114
|
+
typeof value.playback === 'boolean' &&
|
|
115
|
+
typeof value.heartbeat === 'boolean');
|
|
116
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
*
|
|
4
|
+
* Shared message protocol for the textmode runner iframe.
|
|
5
|
+
*
|
|
6
|
+
* `@textmode/runner-protocol` is the single source of truth for the wire
|
|
7
|
+
* contract used by the hosted runner and browser host apps.
|
|
8
|
+
* Runtime protocol version negotiation is intentionally absent: package semver
|
|
9
|
+
* describes source compatibility, while this package describes the one current
|
|
10
|
+
* message shape. Feature availability is advertised through capabilities.
|
|
11
|
+
*
|
|
12
|
+
* @module @textmode/runner-protocol
|
|
13
|
+
*/
|
|
14
|
+
export { EXPORT_FORMATS, createRunnerCapabilities, type ExportFormat, type RunnerCapabilities, } from './capabilities';
|
|
15
|
+
export { type ExportProgress, type ExportRequest, type GifExportOptions, type ImageExportFormat, type ImageExportOptions, type SvgExportOptions, type TxtExportOptions, type WebmExportOptions, } from './exports';
|
|
16
|
+
export { isInitMessage, isParentMessage, isRunnerCapabilities, isRunnerMessage, } from './guards';
|
|
17
|
+
export { type ConfigureRuntimeMessage, type DisposeMessage, type ExportMessage, type ExportProgressMessage, type ExportResultMessage, type FontErrorMessage, type FontLoadedMessage, type InitMessage, type LoadFontMessage, type Message, type ParentToRunnerMessage, type PingMessage, type PlaybackMessage, type PlaybackStateMessage, type PongMessage, type ReadyMessage, type RunCodeMessage, type RunErrorMessage, type RunOkMessage, type RunnerToParentMessage, type SetSettingsMessage, type SoftResetMessage, type SynthErrorMessage, type ToggleUIMessage, type UserInteractionMessage, type WindowToRunnerMessage, } from './messages';
|
|
18
|
+
export { type PlaybackAction, type PlaybackState } from './playback';
|
|
19
|
+
export { type RuntimeSettings } from './runtime';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
*
|
|
4
|
+
* Shared message protocol for the textmode runner iframe.
|
|
5
|
+
*
|
|
6
|
+
* `@textmode/runner-protocol` is the single source of truth for the wire
|
|
7
|
+
* contract used by the hosted runner and browser host apps.
|
|
8
|
+
* Runtime protocol version negotiation is intentionally absent: package semver
|
|
9
|
+
* describes source compatibility, while this package describes the one current
|
|
10
|
+
* message shape. Feature availability is advertised through capabilities.
|
|
11
|
+
*
|
|
12
|
+
* @module @textmode/runner-protocol
|
|
13
|
+
*/
|
|
14
|
+
export { EXPORT_FORMATS, createRunnerCapabilities, } from './capabilities';
|
|
15
|
+
export { isInitMessage, isParentMessage, isRunnerCapabilities, isRunnerMessage, } from './guards';
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import type { RunnerCapabilities } from './capabilities';
|
|
2
|
+
import type { ExportProgress, ExportRequest } from './exports';
|
|
3
|
+
import type { PlaybackAction, PlaybackState } from './playback';
|
|
4
|
+
import type { RuntimeSettings } from './runtime';
|
|
5
|
+
/**
|
|
6
|
+
* Initial window message sent by a host app to the runner iframe.
|
|
7
|
+
*
|
|
8
|
+
* @category Messages
|
|
9
|
+
*/
|
|
10
|
+
export interface InitMessage {
|
|
11
|
+
type: 'INIT';
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Runner readiness message sent after a successful iframe handshake.
|
|
15
|
+
*
|
|
16
|
+
* @category Messages
|
|
17
|
+
*/
|
|
18
|
+
export interface ReadyMessage {
|
|
19
|
+
type: 'READY';
|
|
20
|
+
/** Feature set supported by this runner. */
|
|
21
|
+
capabilities: RunnerCapabilities;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Successful code execution result.
|
|
25
|
+
*
|
|
26
|
+
* @category Messages
|
|
27
|
+
*/
|
|
28
|
+
export interface RunOkMessage {
|
|
29
|
+
type: 'RUN_OK';
|
|
30
|
+
/** Runner-side completion timestamp. */
|
|
31
|
+
timestamp: number;
|
|
32
|
+
/** Request identifier when the run was initiated by a request/response host. */
|
|
33
|
+
requestId?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Code execution failure result.
|
|
37
|
+
*
|
|
38
|
+
* @category Messages
|
|
39
|
+
*/
|
|
40
|
+
export interface RunErrorMessage {
|
|
41
|
+
type: 'RUN_ERROR';
|
|
42
|
+
/** Human-readable error message. */
|
|
43
|
+
message: string;
|
|
44
|
+
/** Optional stack trace. */
|
|
45
|
+
stack?: string;
|
|
46
|
+
/** Optional 1-based source line. */
|
|
47
|
+
line?: number;
|
|
48
|
+
/** Optional 1-based source column. */
|
|
49
|
+
column?: number;
|
|
50
|
+
/** Request identifier when the failure belongs to a request/response call. */
|
|
51
|
+
requestId?: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Shader synth parameter error reported by the runner.
|
|
55
|
+
*
|
|
56
|
+
* @category Messages
|
|
57
|
+
*/
|
|
58
|
+
export interface SynthErrorMessage {
|
|
59
|
+
type: 'SYNTH_ERROR';
|
|
60
|
+
/** Human-readable error message. */
|
|
61
|
+
message: string;
|
|
62
|
+
/** Uniform name associated with the error, when available. */
|
|
63
|
+
uniformName?: string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Runner-originated shortcut event requesting host UI visibility changes.
|
|
67
|
+
*
|
|
68
|
+
* @category Messages
|
|
69
|
+
*/
|
|
70
|
+
export interface ToggleUIMessage {
|
|
71
|
+
type: 'TOGGLE_UI';
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Runner-originated user interaction event.
|
|
75
|
+
*
|
|
76
|
+
* @category Messages
|
|
77
|
+
*/
|
|
78
|
+
export interface UserInteractionMessage {
|
|
79
|
+
type: 'USER_INTERACTION';
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Export completion payload.
|
|
83
|
+
*
|
|
84
|
+
* @category Messages
|
|
85
|
+
*/
|
|
86
|
+
export interface ExportResultMessage {
|
|
87
|
+
type: 'EXPORT_RESULT';
|
|
88
|
+
/** Request identifier for the export call. */
|
|
89
|
+
requestId: string;
|
|
90
|
+
/** Completed export format. */
|
|
91
|
+
format: ExportRequest['format'];
|
|
92
|
+
/** Binary export result for blob-based formats. */
|
|
93
|
+
blob?: Blob;
|
|
94
|
+
/** Text export result for text-based formats. */
|
|
95
|
+
text?: string;
|
|
96
|
+
/** Suggested filename, when provided by the runner. */
|
|
97
|
+
filename?: string;
|
|
98
|
+
/** MIME type for the export result. */
|
|
99
|
+
mimeType?: string;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Progress payload for multi-frame exports.
|
|
103
|
+
*
|
|
104
|
+
* @category Messages
|
|
105
|
+
*/
|
|
106
|
+
export interface ExportProgressMessage {
|
|
107
|
+
type: 'EXPORT_PROGRESS';
|
|
108
|
+
/** Request identifier for the export call. */
|
|
109
|
+
requestId: string;
|
|
110
|
+
/** Streaming export format. */
|
|
111
|
+
format: 'gif' | 'webm';
|
|
112
|
+
/** Current progress snapshot. */
|
|
113
|
+
progress: ExportProgress;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Successful font load result.
|
|
117
|
+
*
|
|
118
|
+
* @category Messages
|
|
119
|
+
*/
|
|
120
|
+
export interface FontLoadedMessage {
|
|
121
|
+
type: 'FONT_LOADED';
|
|
122
|
+
/** Request identifier for the font load call. */
|
|
123
|
+
requestId: string;
|
|
124
|
+
/** Font family name detected by the runner. */
|
|
125
|
+
familyName: string | null;
|
|
126
|
+
/** Characters available in the loaded font. */
|
|
127
|
+
characters: string[];
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Font load failure result.
|
|
131
|
+
*
|
|
132
|
+
* @category Messages
|
|
133
|
+
*/
|
|
134
|
+
export interface FontErrorMessage {
|
|
135
|
+
type: 'FONT_ERROR';
|
|
136
|
+
/** Request identifier for the font load call. */
|
|
137
|
+
requestId: string;
|
|
138
|
+
/** Human-readable error message. */
|
|
139
|
+
message: string;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Playback state response or event.
|
|
143
|
+
*
|
|
144
|
+
* @category Messages
|
|
145
|
+
*/
|
|
146
|
+
export interface PlaybackStateMessage {
|
|
147
|
+
type: 'PLAYBACK_STATE';
|
|
148
|
+
/** Request identifier when the state belongs to a playback request. */
|
|
149
|
+
requestId?: string;
|
|
150
|
+
/** Current playback state. */
|
|
151
|
+
state: PlaybackState;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Heartbeat response from the runner.
|
|
155
|
+
*
|
|
156
|
+
* @category Messages
|
|
157
|
+
*/
|
|
158
|
+
export interface PongMessage {
|
|
159
|
+
type: 'PONG';
|
|
160
|
+
/** Echoed heartbeat nonce. */
|
|
161
|
+
nonce?: string;
|
|
162
|
+
/** Runner-side response timestamp. */
|
|
163
|
+
timestamp: number;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Messages sent from the runner iframe to a host app.
|
|
167
|
+
*
|
|
168
|
+
* @category Messages
|
|
169
|
+
*/
|
|
170
|
+
export type RunnerToParentMessage = ReadyMessage | RunOkMessage | RunErrorMessage | SynthErrorMessage | ToggleUIMessage | UserInteractionMessage | ExportResultMessage | ExportProgressMessage | FontLoadedMessage | FontErrorMessage | PlaybackStateMessage | PongMessage;
|
|
171
|
+
/**
|
|
172
|
+
* Request to execute code in the runner.
|
|
173
|
+
*
|
|
174
|
+
* @category Messages
|
|
175
|
+
*/
|
|
176
|
+
export interface RunCodeMessage {
|
|
177
|
+
type: 'RUN_CODE';
|
|
178
|
+
/** Source code to execute. */
|
|
179
|
+
code: string;
|
|
180
|
+
/** Optional request identifier for result routing. */
|
|
181
|
+
requestId?: string;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Request to reset frame state and execute code.
|
|
185
|
+
*
|
|
186
|
+
* @category Messages
|
|
187
|
+
*/
|
|
188
|
+
export interface SoftResetMessage {
|
|
189
|
+
type: 'SOFT_RESET';
|
|
190
|
+
/** Source code to execute after soft reset. */
|
|
191
|
+
code: string;
|
|
192
|
+
/** Optional request identifier for result routing. */
|
|
193
|
+
requestId?: string;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Request to dispose the runner runtime.
|
|
197
|
+
*
|
|
198
|
+
* @category Messages
|
|
199
|
+
*/
|
|
200
|
+
export interface DisposeMessage {
|
|
201
|
+
type: 'DISPOSE';
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Request to initialize or reconfigure fixed runtime settings.
|
|
205
|
+
*
|
|
206
|
+
* @category Messages
|
|
207
|
+
*/
|
|
208
|
+
export interface ConfigureRuntimeMessage {
|
|
209
|
+
type: 'CONFIGURE_RUNTIME';
|
|
210
|
+
/** Complete runtime settings. */
|
|
211
|
+
settings: RuntimeSettings;
|
|
212
|
+
/** Optional request identifier for result routing. */
|
|
213
|
+
requestId?: string;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Request to update part of the current runtime settings.
|
|
217
|
+
*
|
|
218
|
+
* @category Messages
|
|
219
|
+
*/
|
|
220
|
+
export interface SetSettingsMessage {
|
|
221
|
+
type: 'SET_SETTINGS';
|
|
222
|
+
/** Partial runtime settings to apply. */
|
|
223
|
+
settings: Partial<RuntimeSettings>;
|
|
224
|
+
/** Optional request identifier for result routing. */
|
|
225
|
+
requestId?: string;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Request to export the current runner output.
|
|
229
|
+
*
|
|
230
|
+
* @category Messages
|
|
231
|
+
*/
|
|
232
|
+
export interface ExportMessage {
|
|
233
|
+
type: 'EXPORT';
|
|
234
|
+
/** Request identifier for result routing. */
|
|
235
|
+
requestId: string;
|
|
236
|
+
/** Requested export format. */
|
|
237
|
+
format: ExportRequest['format'];
|
|
238
|
+
/** Export options matching the requested format. */
|
|
239
|
+
options?: ExportRequest['options'];
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Request to load a font file into the runner.
|
|
243
|
+
*
|
|
244
|
+
* @category Messages
|
|
245
|
+
*/
|
|
246
|
+
export interface LoadFontMessage {
|
|
247
|
+
type: 'LOAD_FONT';
|
|
248
|
+
/** Request identifier for result routing. */
|
|
249
|
+
requestId: string;
|
|
250
|
+
/** Original file name. */
|
|
251
|
+
fileName: string;
|
|
252
|
+
/** Browser-reported MIME type, when available. */
|
|
253
|
+
mimeType?: string;
|
|
254
|
+
/** Font file bytes. */
|
|
255
|
+
buffer: ArrayBuffer;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Request to control or inspect playback.
|
|
259
|
+
*
|
|
260
|
+
* @category Messages
|
|
261
|
+
*/
|
|
262
|
+
export interface PlaybackMessage {
|
|
263
|
+
type: 'PLAYBACK';
|
|
264
|
+
/** Optional request identifier for result routing. */
|
|
265
|
+
requestId?: string;
|
|
266
|
+
/** Playback action to perform. */
|
|
267
|
+
action: PlaybackAction;
|
|
268
|
+
/** Target frame for seek-like actions. */
|
|
269
|
+
frame?: number;
|
|
270
|
+
/** Maximum frame count for playback range updates. */
|
|
271
|
+
maxFrames?: number;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Heartbeat request sent by a host app.
|
|
275
|
+
*
|
|
276
|
+
* @category Messages
|
|
277
|
+
*/
|
|
278
|
+
export interface PingMessage {
|
|
279
|
+
type: 'PING';
|
|
280
|
+
/** Optional nonce echoed by the runner. */
|
|
281
|
+
nonce?: string;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Messages sent from a host app to the runner after handshake.
|
|
285
|
+
*
|
|
286
|
+
* @category Messages
|
|
287
|
+
*/
|
|
288
|
+
export type ParentToRunnerMessage = RunCodeMessage | SoftResetMessage | DisposeMessage | ConfigureRuntimeMessage | SetSettingsMessage | ExportMessage | LoadFontMessage | PlaybackMessage | PingMessage;
|
|
289
|
+
/**
|
|
290
|
+
* Messages sent to the runner iframe window before MessagePort attachment.
|
|
291
|
+
*
|
|
292
|
+
* @category Messages
|
|
293
|
+
*/
|
|
294
|
+
export type WindowToRunnerMessage = InitMessage;
|
|
295
|
+
/**
|
|
296
|
+
* Any message in the runner protocol.
|
|
297
|
+
*
|
|
298
|
+
* @category Messages
|
|
299
|
+
*/
|
|
300
|
+
export type Message = RunnerToParentMessage | ParentToRunnerMessage | WindowToRunnerMessage;
|
package/dist/messages.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Playback command accepted by the runner.
|
|
3
|
+
*
|
|
4
|
+
* @category Playback
|
|
5
|
+
*/
|
|
6
|
+
export type PlaybackAction = 'play' | 'pause' | 'stop' | 'seek' | 'next' | 'previous' | 'setMaxFrames' | 'state';
|
|
7
|
+
/**
|
|
8
|
+
* Playback state snapshot emitted by the runner.
|
|
9
|
+
*
|
|
10
|
+
* @category Playback
|
|
11
|
+
*/
|
|
12
|
+
export interface PlaybackState {
|
|
13
|
+
/** Whether playback is actively advancing frames. */
|
|
14
|
+
isPlaying: boolean;
|
|
15
|
+
/** Current frame index. */
|
|
16
|
+
frame: number;
|
|
17
|
+
/** Maximum frame count used by playback controls. */
|
|
18
|
+
maxFrames: number;
|
|
19
|
+
/** Optional measured or configured frames per second. */
|
|
20
|
+
fps?: number;
|
|
21
|
+
}
|
package/dist/playback.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fixed runtime dimensions and timing used by configurable runner hosts.
|
|
3
|
+
*
|
|
4
|
+
* @category Runtime
|
|
5
|
+
*/
|
|
6
|
+
export interface RuntimeSettings {
|
|
7
|
+
/** Canvas width in CSS pixels. */
|
|
8
|
+
width: number;
|
|
9
|
+
/** Canvas height in CSS pixels. */
|
|
10
|
+
height: number;
|
|
11
|
+
/** Textmode font size in CSS pixels. */
|
|
12
|
+
fontSize: number;
|
|
13
|
+
/** Target animation frame rate. */
|
|
14
|
+
frameRate: number;
|
|
15
|
+
}
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@textmode/runner-protocol",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Shared message protocol and validators for the hosted textmode runner iframe.",
|
|
5
|
+
"license": "CC0-1.0",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist/**/*.d.ts",
|
|
21
|
+
"dist/**/*.js"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "tsc -b",
|
|
25
|
+
"check-types": "tsc -p tsconfig.json --noEmit",
|
|
26
|
+
"lint": "eslint .",
|
|
27
|
+
"test": "vitest run --passWithNoTests",
|
|
28
|
+
"build:docs": "typedoc --options typedoc.json",
|
|
29
|
+
"dev:docs": "typedoc --options typedoc.json --watch",
|
|
30
|
+
"prepare": "npm run build"
|
|
31
|
+
}
|
|
32
|
+
}
|