homebridge-plugin-utils 2.0.0 → 2.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/dist/backpressure.d.ts +1 -1
- package/dist/backpressure.js +4 -4
- package/dist/backpressure.js.map +1 -1
- package/dist/cli/index.d.ts +73 -2
- package/dist/cli/index.js +221 -25
- package/dist/cli/index.js.map +1 -1
- package/dist/clock-double.js +2 -2
- package/dist/clock-double.js.map +1 -1
- package/dist/disposable-stack.d.ts +59 -0
- package/dist/disposable-stack.js +155 -0
- package/dist/disposable-stack.js.map +1 -0
- package/dist/docChrome.d.ts +260 -0
- package/dist/docChrome.js +361 -0
- package/dist/docChrome.js.map +1 -0
- package/dist/featureOptions-docs.d.ts +2 -2
- package/dist/featureOptions-docs.js +1 -1
- package/dist/featureOptions.d.ts +5 -5
- package/dist/featureOptions.js +6 -6
- package/dist/ffmpeg/exec.d.ts +2 -2
- package/dist/ffmpeg/exec.js +2 -2
- package/dist/ffmpeg/mp4-assembler.d.ts +45 -4
- package/dist/ffmpeg/mp4-assembler.js +45 -8
- package/dist/ffmpeg/mp4-assembler.js.map +1 -1
- package/dist/ffmpeg/mp4-parser.d.ts +1 -1
- package/dist/ffmpeg/mp4-parser.js +1 -1
- package/dist/ffmpeg/options.js +3 -3
- package/dist/ffmpeg/options.js.map +1 -1
- package/dist/ffmpeg/process.d.ts +1 -1
- package/dist/ffmpeg/process.js +4 -4
- package/dist/ffmpeg/process.js.map +1 -1
- package/dist/ffmpeg/record.d.ts +26 -1
- package/dist/ffmpeg/record.js +12 -0
- package/dist/ffmpeg/record.js.map +1 -1
- package/dist/ffmpeg/recording-process-double.d.ts +13 -0
- package/dist/ffmpeg/recording-process-double.js +22 -0
- package/dist/ffmpeg/recording-process-double.js.map +1 -1
- package/dist/ffmpeg/rtp-parser.d.ts +1 -1
- package/dist/ffmpeg/rtp-parser.js +1 -1
- package/dist/ffmpeg/rtp.d.ts +4 -4
- package/dist/ffmpeg/rtp.js +7 -6
- package/dist/ffmpeg/rtp.js.map +1 -1
- package/dist/ffmpeg/stream.js +1 -1
- package/dist/ffmpeg/stream.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/logclient/auth.d.ts +3 -3
- package/dist/logclient/auth.js +2 -2
- package/dist/logclient/auth.js.map +1 -1
- package/dist/logclient/cli-run.js +2 -2
- package/dist/logclient/cli-run.js.map +1 -1
- package/dist/logclient/cli.js +2 -2
- package/dist/logclient/client.js +2 -2
- package/dist/logclient/client.js.map +1 -1
- package/dist/logclient/rest.js +1 -1
- package/dist/logclient/socket-double.d.ts +1 -1
- package/dist/logclient/socket-double.js +1 -1
- package/dist/logclient/socket.js +5 -5
- package/dist/logclient/socket.js.map +1 -1
- package/dist/logclient/time-window.d.ts +1 -1
- package/dist/mqttClient.d.ts +1 -1
- package/dist/mqttClient.js +3 -3
- package/dist/mqttClient.js.map +1 -1
- package/dist/ui/featureOptions.js +6 -6
- package/dist/ui/pluginConfigSession.mjs +1 -1
- package/dist/ui/webUi-featureOptions/effects/persist.mjs +2 -2
- package/dist/ui/webUi-featureOptions/effects/theme.mjs +1 -1
- package/dist/ui/webUi-featureOptions/effects/tokens.mjs +1 -1
- package/dist/ui/webUi-featureOptions/rendering.mjs +2 -2
- package/dist/ui/webUi-featureOptions/selectors.mjs +3 -3
- package/dist/ui/webUi-featureOptions/state.mjs +6 -6
- package/dist/ui/webUi-featureOptions/store.mjs +1 -1
- package/dist/ui/webUi-featureOptions/utils.mjs +14 -1
- package/dist/ui/webUi-featureOptions/views/connectionError.mjs +1 -1
- package/dist/ui/webUi-featureOptions/views/nav.mjs +42 -28
- package/dist/ui/webUi-featureOptions/views/options.mjs +2 -2
- package/dist/ui/webUi-featureOptions/views/search.mjs +2 -2
- package/dist/ui/webUi-featureOptions.mjs +57 -32
- package/dist/ui/webUi.mjs +43 -11
- package/dist/util.d.ts +89 -12
- package/dist/util.js +62 -14
- package/dist/util.js.map +1 -1
- package/package.json +9 -9
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
/* Copyright(C) 2017-2026, HJD (https://github.com/hjdhjd). All rights reserved.
|
|
2
|
+
*
|
|
3
|
+
* docChrome.ts: Pure, isomorphic renderers that project a per-plugin documentation-chrome manifest into the masthead, navigation index, dashboard badges, and project
|
|
4
|
+
* list that every family plugin repeats by hand across its README, its docs, and its webUI.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* The opening marker of the auto-generated masthead region. See {@link renderMasthead}. The text doubles as an in-document warning not to edit the region by hand.
|
|
8
|
+
*
|
|
9
|
+
* @category Doc Chrome
|
|
10
|
+
*/
|
|
11
|
+
export const MASTHEAD_BEGIN = "<!-- MASTHEAD:BEGIN - Auto-generated by homebridge-plugin-utils. Do not edit this region by hand. -->";
|
|
12
|
+
/**
|
|
13
|
+
* The closing marker of the auto-generated masthead region. See {@link MASTHEAD_BEGIN}.
|
|
14
|
+
*
|
|
15
|
+
* @category Doc Chrome
|
|
16
|
+
*/
|
|
17
|
+
export const MASTHEAD_END = "<!-- MASTHEAD:END -->";
|
|
18
|
+
/**
|
|
19
|
+
* The opening marker of the auto-generated documentation-index region, used in the README's documentation section, each content doc's footer, and the webUI's Support
|
|
20
|
+
* tab. See {@link renderDocIndex}.
|
|
21
|
+
*
|
|
22
|
+
* @category Doc Chrome
|
|
23
|
+
*/
|
|
24
|
+
export const DOCUMENTATION_BEGIN = "<!-- DOCUMENTATION:BEGIN - Auto-generated by homebridge-plugin-utils. Do not edit this region by hand. -->";
|
|
25
|
+
/**
|
|
26
|
+
* The closing marker of the auto-generated documentation-index region. See {@link DOCUMENTATION_BEGIN}.
|
|
27
|
+
*
|
|
28
|
+
* @category Doc Chrome
|
|
29
|
+
*/
|
|
30
|
+
export const DOCUMENTATION_END = "<!-- DOCUMENTATION:END -->";
|
|
31
|
+
/**
|
|
32
|
+
* The opening marker of the auto-generated development-dashboard badge region (README only). See {@link renderDevBadges}.
|
|
33
|
+
*
|
|
34
|
+
* @category Doc Chrome
|
|
35
|
+
*/
|
|
36
|
+
export const DEV_BADGES_BEGIN = "<!-- DEV BADGES:BEGIN - Auto-generated by homebridge-plugin-utils. Do not edit this region by hand. -->";
|
|
37
|
+
/**
|
|
38
|
+
* The closing marker of the auto-generated development-dashboard badge region. See {@link DEV_BADGES_BEGIN}.
|
|
39
|
+
*
|
|
40
|
+
* @category Doc Chrome
|
|
41
|
+
*/
|
|
42
|
+
export const DEV_BADGES_END = "<!-- DEV BADGES:END -->";
|
|
43
|
+
/**
|
|
44
|
+
* The opening marker of the auto-generated project-list region (webUI only). See {@link renderProjects}.
|
|
45
|
+
*
|
|
46
|
+
* @category Doc Chrome
|
|
47
|
+
*/
|
|
48
|
+
export const PROJECTS_BEGIN = "<!-- PROJECTS:BEGIN - Auto-generated by homebridge-plugin-utils. Do not edit this region by hand. -->";
|
|
49
|
+
/**
|
|
50
|
+
* The closing marker of the auto-generated project-list region. See {@link PROJECTS_BEGIN}.
|
|
51
|
+
*
|
|
52
|
+
* @category Doc Chrome
|
|
53
|
+
*/
|
|
54
|
+
export const PROJECTS_END = "<!-- PROJECTS:END -->";
|
|
55
|
+
// Escape text destined for an HTML text node. We neutralize "&", "<", and ">" so a blurb containing any of them renders as literal text rather than being parsed as
|
|
56
|
+
// markup. "&" is replaced first so the entities we introduce are not themselves re-escaped. This applies only to the webUI (HTML) surface; the markdown surfaces embed
|
|
57
|
+
// author-owned prose verbatim, matching the hand-authored source the renderer reproduces.
|
|
58
|
+
function escapeHtmlText(text) {
|
|
59
|
+
return text.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
60
|
+
}
|
|
61
|
+
// Escape a value destined for a double-quoted HTML attribute (an href). It builds on the text-node escaping - the shared single source of truth for the "&"/"<"/">"
|
|
62
|
+
// entities - and adds the double quote that would otherwise terminate the attribute early. The quote substitution runs after the text escaping, so the "&" it introduces
|
|
63
|
+
// is not itself re-escaped.
|
|
64
|
+
function escapeHtmlAttr(value) {
|
|
65
|
+
return escapeHtmlText(value).replaceAll("\"", """);
|
|
66
|
+
}
|
|
67
|
+
// The absolute GitHub blob base for a repository, the prefix every non-local navigation href is built on.
|
|
68
|
+
function blobBaseUrl(repo) {
|
|
69
|
+
return "https://github.com/" + repo.owner + "/" + repo.name + "/blob/" + repo.branch;
|
|
70
|
+
}
|
|
71
|
+
// Render a single badge as a linked markdown image, the shape both the masthead and the dashboard badges share.
|
|
72
|
+
function renderBadge(badge) {
|
|
73
|
+
return "[](" + badge.link + ")";
|
|
74
|
+
}
|
|
75
|
+
// Derive the href for a documentation entry on a given surface. On the README itself a `readme-anchor` entry is an in-page anchor; viewed from anywhere else it must
|
|
76
|
+
// resolve to the README's absolute blob URL. A `doc` entry is always an absolute blob URL to its file, identical on every surface - which is what collapses the
|
|
77
|
+
// per-surface href drift the hand-maintained lists suffer from.
|
|
78
|
+
function docEntryHref(entry, repo, local) {
|
|
79
|
+
if (entry.kind === "readme-anchor") {
|
|
80
|
+
return local ? ("#" + entry.anchor) : (blobBaseUrl(repo) + "/README.md#" + entry.anchor);
|
|
81
|
+
}
|
|
82
|
+
return blobBaseUrl(repo) + "/" + entry.file;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Render the masthead - the centered logo, the H1 title, the ordered badge row, and the H2 tagline - as the markdown/HTML block a plugin embeds at the top of its README
|
|
86
|
+
* and every content doc. The block is identical across those surfaces, so a single manifest drives all of them and the hand-copied mastheads collapse to one.
|
|
87
|
+
*
|
|
88
|
+
* @param manifest - The documentation-chrome manifest.
|
|
89
|
+
*
|
|
90
|
+
* @returns The rendered masthead block.
|
|
91
|
+
*
|
|
92
|
+
* @category Doc Chrome
|
|
93
|
+
*/
|
|
94
|
+
export function renderMasthead(manifest) {
|
|
95
|
+
const { badges, logo, tagline, title } = manifest.masthead;
|
|
96
|
+
// Assemble the block line by line: the centering wrapper, the linked logo image, the title, one linked badge image per badge, and the tagline. A pushed empty string
|
|
97
|
+
// is a blank line, keeping the vertical rhythm explicit rather than threading "\n\n" through concatenations.
|
|
98
|
+
const lines = [
|
|
99
|
+
"<SPAN ALIGN=\"CENTER\" STYLE=\"text-align:center\">",
|
|
100
|
+
"<DIV ALIGN=\"CENTER\" STYLE=\"text-align:center\">",
|
|
101
|
+
"",
|
|
102
|
+
"[](" + logo.href + ")",
|
|
103
|
+
"",
|
|
104
|
+
"# " + title,
|
|
105
|
+
"",
|
|
106
|
+
...badges.map(renderBadge),
|
|
107
|
+
"",
|
|
108
|
+
"## " + tagline,
|
|
109
|
+
"</DIV>",
|
|
110
|
+
"</SPAN>"
|
|
111
|
+
];
|
|
112
|
+
return lines.join("\n");
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Render the development-dashboard badges - the README-only badge row (license, build status, dependencies, and the like) that sits apart from the masthead. Returns an
|
|
116
|
+
* empty string when the manifest declares no dashboard badges.
|
|
117
|
+
*
|
|
118
|
+
* @param manifest - The documentation-chrome manifest.
|
|
119
|
+
*
|
|
120
|
+
* @returns The rendered badge rows, one badge per line.
|
|
121
|
+
*
|
|
122
|
+
* @category Doc Chrome
|
|
123
|
+
*/
|
|
124
|
+
export function renderDevBadges(manifest) {
|
|
125
|
+
return (manifest.devBadges ?? []).map(renderBadge).join("\n");
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Render the documentation index for a surface. On the markdown surfaces (`"readme"`, `"doc-footer"`) the output is one bullet per section with a nested bullet per
|
|
129
|
+
* entry; on `"webui"` it is one `<h5>` heading and `<ul>` per section. Href derivation follows the surface: in-README anchors on `"readme"`, absolute blob URLs
|
|
130
|
+
* elsewhere. A `"doc-footer"` render omits the current document (via `currentFile`) and drops any section left empty by that omission, so a doc's own footer never links
|
|
131
|
+
* back to itself.
|
|
132
|
+
*
|
|
133
|
+
* @param input
|
|
134
|
+
* @param input.currentFile - The doc file being rendered into, relative to the plugin root. Only consulted for the `"doc-footer"` surface, to omit the self-link.
|
|
135
|
+
* @param input.manifest - The documentation-chrome manifest.
|
|
136
|
+
* @param input.surface - The surface to render for.
|
|
137
|
+
*
|
|
138
|
+
* @returns The rendered documentation index.
|
|
139
|
+
*
|
|
140
|
+
* @category Doc Chrome
|
|
141
|
+
*/
|
|
142
|
+
export function renderDocIndex({ currentFile, manifest, surface }) {
|
|
143
|
+
if (surface === "webui") {
|
|
144
|
+
// The webUI surface renders HTML and never omits a self-link (it is not itself a doc). Each entry links to an absolute blob URL.
|
|
145
|
+
const sections = manifest.nav.map((section) => {
|
|
146
|
+
const items = section.entries.map((entry) => {
|
|
147
|
+
return " <li><a target=\"_blank\" href=\"" + escapeHtmlAttr(docEntryHref(entry, manifest.repo, false)) + "\">" + escapeHtmlText(entry.title) + "</a>: " +
|
|
148
|
+
escapeHtmlText(entry.blurb) + "</li>";
|
|
149
|
+
});
|
|
150
|
+
return "<h5>" + escapeHtmlText(section.title) + "</h5>\n<ul dir=\"auto\">\n" + items.join("\n") + "\n</ul>";
|
|
151
|
+
});
|
|
152
|
+
return sections.join("\n\n");
|
|
153
|
+
}
|
|
154
|
+
// The markdown surfaces. `"readme"` uses in-page anchors for anchor entries; `"doc-footer"` uses absolute URLs and omits the current doc.
|
|
155
|
+
const local = surface === "readme";
|
|
156
|
+
const omitFile = (surface === "doc-footer") ? currentFile : undefined;
|
|
157
|
+
const sections = [];
|
|
158
|
+
for (const section of manifest.nav) {
|
|
159
|
+
const bullets = section.entries
|
|
160
|
+
.filter((entry) => !((entry.kind === "doc") && (entry.file === omitFile)))
|
|
161
|
+
.map((entry) => " * [" + entry.title + "](" + docEntryHref(entry, manifest.repo, local) + "): " + entry.blurb);
|
|
162
|
+
// Drop a section that the self-omission emptied, so a footer never renders a heading with no entries beneath it.
|
|
163
|
+
if (bullets.length === 0) {
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
sections.push(["* " + section.title, ...bullets].join("\n"));
|
|
167
|
+
}
|
|
168
|
+
return sections.join("\n\n");
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Render the webUI project list - the "other projects" links - as an HTML `<ul>`. The CLI resolves the manifest's project source (inline, local file, or remote URL) to
|
|
172
|
+
* this array before calling; the renderer never performs I/O. Entries are rendered in alphabetical order by title, so the list reads predictably no matter what order the
|
|
173
|
+
* source - often a shared, remotely-fetched file every plugin points at - happens to hold. Each entry's link text is `{title}: {blurb}`.
|
|
174
|
+
*
|
|
175
|
+
* @param projects - The resolved project entries. Their order is not significant; the renderer sorts them by title.
|
|
176
|
+
*
|
|
177
|
+
* @returns The rendered project list.
|
|
178
|
+
*
|
|
179
|
+
* @category Doc Chrome
|
|
180
|
+
*/
|
|
181
|
+
export function renderProjects(projects) {
|
|
182
|
+
// Sort a copy by lowercased title so the output is alphabetical and consistent regardless of the source order, without disturbing the caller's array. We compare
|
|
183
|
+
// lowercased titles directly rather than through localeCompare so the ordering is identical on every build machine, independent of the host's locale.
|
|
184
|
+
const ordered = projects.toSorted((left, right) => {
|
|
185
|
+
const leftTitle = left.title.toLowerCase();
|
|
186
|
+
const rightTitle = right.title.toLowerCase();
|
|
187
|
+
if (leftTitle < rightTitle) {
|
|
188
|
+
return -1;
|
|
189
|
+
}
|
|
190
|
+
if (leftTitle > rightTitle) {
|
|
191
|
+
return 1;
|
|
192
|
+
}
|
|
193
|
+
return 0;
|
|
194
|
+
});
|
|
195
|
+
const items = ordered.map((project) => {
|
|
196
|
+
return " <li><a target=\"_blank\" href=\"" + escapeHtmlAttr(project.href) + "\">" + escapeHtmlText(project.title) + ": " +
|
|
197
|
+
escapeHtmlText(project.blurb) + "</a></li>";
|
|
198
|
+
});
|
|
199
|
+
return "<ul dir=\"auto\">\n" + items.join("\n") + "\n</ul>";
|
|
200
|
+
}
|
|
201
|
+
// Throw a uniformly framed validation error naming the manifest source and the offending path, mirroring the diagnostics the catalog validation in the CLI produces.
|
|
202
|
+
function fail(source, detail) {
|
|
203
|
+
throw new Error("Doc-chrome manifest " + source + " " + detail + ".");
|
|
204
|
+
}
|
|
205
|
+
// Assert that a value is a non-empty string at a named path, else fail with a framed diagnostic.
|
|
206
|
+
function assertString(value, path, source) {
|
|
207
|
+
if ((typeof value !== "string") || (value.length === 0)) {
|
|
208
|
+
fail(source, "field `" + path + "` must be a non-empty string");
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// Validate a badge's shape. Shared by the masthead badges and the optional dashboard badges.
|
|
212
|
+
function assertBadge(value, path, source) {
|
|
213
|
+
if ((typeof value !== "object") || (value === null)) {
|
|
214
|
+
fail(source, "field `" + path + "` must be an object");
|
|
215
|
+
}
|
|
216
|
+
const badge = value;
|
|
217
|
+
assertString(badge.alt, path + ".alt", source);
|
|
218
|
+
assertString(badge.image, path + ".image", source);
|
|
219
|
+
assertString(badge.link, path + ".link", source);
|
|
220
|
+
}
|
|
221
|
+
// Validate one documentation entry. The `kind` tag selects which additional field is required.
|
|
222
|
+
function assertDocEntry(value, path, source) {
|
|
223
|
+
if ((typeof value !== "object") || (value === null)) {
|
|
224
|
+
fail(source, "field `" + path + "` must be an object");
|
|
225
|
+
}
|
|
226
|
+
const entry = value;
|
|
227
|
+
assertString(entry.title, path + ".title", source);
|
|
228
|
+
assertString(entry.blurb, path + ".blurb", source);
|
|
229
|
+
switch (entry.kind) {
|
|
230
|
+
case "doc": {
|
|
231
|
+
assertString(entry.file, path + ".file", source);
|
|
232
|
+
if ((entry.masthead !== undefined) && (typeof entry.masthead !== "boolean")) {
|
|
233
|
+
fail(source, "field `" + path + ".masthead` must be a boolean when present");
|
|
234
|
+
}
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
case "readme-anchor": {
|
|
238
|
+
assertString(entry.anchor, path + ".anchor", source);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
default: {
|
|
242
|
+
fail(source, "field `" + path + ".kind` must be \"doc\" or \"readme-anchor\"");
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Validate a loaded value and return it typed as a well-formed {@link DocChromeManifest}, failing fast with a framed diagnostic that names the manifest source and the
|
|
248
|
+
* offending field rather than surfacing an opaque error deep inside a renderer or a bare `resolve()` type error in the CLI. Validates every field the renderer or the
|
|
249
|
+
* CLI consumes - `masthead`, `nav`, `repo`, and the optional `devBadges` and `surfaces`. The project source is validated separately at resolution time, since it may be
|
|
250
|
+
* a remote reference rather than inline data.
|
|
251
|
+
*
|
|
252
|
+
* @param value - The loaded manifest value, untrusted until validated.
|
|
253
|
+
* @param source - The manifest's path or module specifier, for diagnostics.
|
|
254
|
+
*
|
|
255
|
+
* @returns The same value, now typed as a validated {@link DocChromeManifest}.
|
|
256
|
+
*
|
|
257
|
+
* @category Doc Chrome
|
|
258
|
+
*/
|
|
259
|
+
export function parseDocChromeManifest(value, source) {
|
|
260
|
+
if ((typeof value !== "object") || (value === null)) {
|
|
261
|
+
fail(source, "must export a manifest object");
|
|
262
|
+
}
|
|
263
|
+
const manifest = value;
|
|
264
|
+
// The masthead and its nested logo and badge row.
|
|
265
|
+
if ((typeof manifest.masthead !== "object") || (manifest.masthead === null)) {
|
|
266
|
+
fail(source, "field `masthead` must be an object");
|
|
267
|
+
}
|
|
268
|
+
const masthead = manifest.masthead;
|
|
269
|
+
assertString(masthead.title, "masthead.title", source);
|
|
270
|
+
assertString(masthead.tagline, "masthead.tagline", source);
|
|
271
|
+
if ((typeof masthead.logo !== "object") || (masthead.logo === null)) {
|
|
272
|
+
fail(source, "field `masthead.logo` must be an object");
|
|
273
|
+
}
|
|
274
|
+
const logo = masthead.logo;
|
|
275
|
+
assertString(logo.alt, "masthead.logo.alt", source);
|
|
276
|
+
assertString(logo.href, "masthead.logo.href", source);
|
|
277
|
+
assertString(logo.src, "masthead.logo.src", source);
|
|
278
|
+
if (!Array.isArray(masthead.badges)) {
|
|
279
|
+
fail(source, "field `masthead.badges` must be an array");
|
|
280
|
+
}
|
|
281
|
+
for (const [index, badge] of masthead.badges.entries()) {
|
|
282
|
+
assertBadge(badge, "masthead.badges[" + String(index) + "]", source);
|
|
283
|
+
}
|
|
284
|
+
// The repository coordinates.
|
|
285
|
+
if ((typeof manifest.repo !== "object") || (manifest.repo === null)) {
|
|
286
|
+
fail(source, "field `repo` must be an object");
|
|
287
|
+
}
|
|
288
|
+
const repo = manifest.repo;
|
|
289
|
+
assertString(repo.branch, "repo.branch", source);
|
|
290
|
+
assertString(repo.name, "repo.name", source);
|
|
291
|
+
assertString(repo.owner, "repo.owner", source);
|
|
292
|
+
// The navigation sections and their entries.
|
|
293
|
+
if (!Array.isArray(manifest.nav)) {
|
|
294
|
+
fail(source, "field `nav` must be an array");
|
|
295
|
+
}
|
|
296
|
+
for (const [sectionIndex, section] of manifest.nav.entries()) {
|
|
297
|
+
if ((typeof section !== "object") || (section === null)) {
|
|
298
|
+
fail(source, "field `nav[" + String(sectionIndex) + "]` must be an object");
|
|
299
|
+
}
|
|
300
|
+
const navSection = section;
|
|
301
|
+
assertString(navSection.title, "nav[" + String(sectionIndex) + "].title", source);
|
|
302
|
+
if (!Array.isArray(navSection.entries)) {
|
|
303
|
+
fail(source, "field `nav[" + String(sectionIndex) + "].entries` must be an array");
|
|
304
|
+
}
|
|
305
|
+
for (const [entryIndex, entry] of navSection.entries.entries()) {
|
|
306
|
+
assertDocEntry(entry, "nav[" + String(sectionIndex) + "].entries[" + String(entryIndex) + "]", source);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
// The optional dashboard badges.
|
|
310
|
+
if (manifest.devBadges !== undefined) {
|
|
311
|
+
if (!Array.isArray(manifest.devBadges)) {
|
|
312
|
+
fail(source, "field `devBadges` must be an array when present");
|
|
313
|
+
}
|
|
314
|
+
for (const [index, badge] of manifest.devBadges.entries()) {
|
|
315
|
+
assertBadge(badge, "devBadges[" + String(index) + "]", source);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
// The optional per-surface path overrides. These are consumed by the CLI's `resolve()` calls, so validating them here keeps the framed-diagnostic guarantee whole for
|
|
319
|
+
// a JSON-authored manifest that could otherwise smuggle a non-string path past the type system.
|
|
320
|
+
if (manifest.surfaces !== undefined) {
|
|
321
|
+
if ((typeof manifest.surfaces !== "object") || (manifest.surfaces === null)) {
|
|
322
|
+
fail(source, "field `surfaces` must be an object when present");
|
|
323
|
+
}
|
|
324
|
+
const surfaces = manifest.surfaces;
|
|
325
|
+
if ((surfaces.readme !== undefined) && ((typeof surfaces.readme !== "string") || (surfaces.readme.length === 0))) {
|
|
326
|
+
fail(source, "field `surfaces.readme` must be a non-empty string when present");
|
|
327
|
+
}
|
|
328
|
+
if ((surfaces.webui !== undefined) && ((typeof surfaces.webui !== "string") || (surfaces.webui.length === 0))) {
|
|
329
|
+
fail(source, "field `surfaces.webui` must be a non-empty string when present");
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return value;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Validate a resolved project source and return it typed as an array of {@link ProjectEntry}. The CLI calls this after resolving the manifest's project source - which
|
|
336
|
+
* may be inline data, a local file, or a remote URL - so a malformed external list fails fast with a framed diagnostic naming the source rather than rendering broken
|
|
337
|
+
* markup.
|
|
338
|
+
*
|
|
339
|
+
* @param value - The resolved project value, untrusted until validated.
|
|
340
|
+
* @param source - The project source (a path or URL) for diagnostics.
|
|
341
|
+
*
|
|
342
|
+
* @returns The same value, now typed as a validated array of {@link ProjectEntry}.
|
|
343
|
+
*
|
|
344
|
+
* @category Doc Chrome
|
|
345
|
+
*/
|
|
346
|
+
export function parseProjectEntries(value, source) {
|
|
347
|
+
if (!Array.isArray(value)) {
|
|
348
|
+
fail(source, "project source must resolve to an array of project entries");
|
|
349
|
+
}
|
|
350
|
+
for (const [index, entry] of value.entries()) {
|
|
351
|
+
if ((typeof entry !== "object") || (entry === null)) {
|
|
352
|
+
fail(source, "project entry [" + String(index) + "] must be an object");
|
|
353
|
+
}
|
|
354
|
+
const project = entry;
|
|
355
|
+
assertString(project.blurb, "project entry [" + String(index) + "].blurb", source);
|
|
356
|
+
assertString(project.href, "project entry [" + String(index) + "].href", source);
|
|
357
|
+
assertString(project.title, "project entry [" + String(index) + "].title", source);
|
|
358
|
+
}
|
|
359
|
+
return value;
|
|
360
|
+
}
|
|
361
|
+
//# sourceMappingURL=docChrome.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docChrome.js","sourceRoot":"","sources":["../src/docChrome.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Every plugin in the family used to ship a near-duplicate `*-gendocs.ts` script that walked its feature-options catalog and printed a markdown category index plus
|
|
5
5
|
* per-category option tables, then pasted the result into its `docs/FeatureOptions.md` by hand. ~95% of each script was identical, and each hand-rolled the dotted-key
|
|
6
|
-
* construction and the value-vs-toggle
|
|
6
|
+
* construction and the value-vs-toggle distinction that this library already owns as single-source-of-truth helpers. This module collapses all of that into one
|
|
7
7
|
* elegant renderer so the documentation becomes a pure projection of the live catalog.
|
|
8
8
|
*
|
|
9
9
|
* The module exports two pure string functions:
|
|
@@ -75,7 +75,7 @@ export declare function renderFeatureOptionsReference<TOptionMeta = unknown, TCa
|
|
|
75
75
|
* `writeFile` around it.
|
|
76
76
|
*
|
|
77
77
|
* The replacement inserts a newline before and after `content`, so a marker pair on its own lines stays on its own lines and the rendered fragment is cleanly framed.
|
|
78
|
-
* The operation is
|
|
78
|
+
* The operation is repeatable: splicing the same `content` into an already-spliced document reproduces it byte-for-byte. Each marker may be overridden through the
|
|
79
79
|
* options object for documents that use a different convention, though the defaults match what every plugin in the family embeds.
|
|
80
80
|
*
|
|
81
81
|
* @param source - The full document text.
|
|
@@ -149,7 +149,7 @@ export function renderFeatureOptionsReference(input) {
|
|
|
149
149
|
* `writeFile` around it.
|
|
150
150
|
*
|
|
151
151
|
* The replacement inserts a newline before and after `content`, so a marker pair on its own lines stays on its own lines and the rendered fragment is cleanly framed.
|
|
152
|
-
* The operation is
|
|
152
|
+
* The operation is repeatable: splicing the same `content` into an already-spliced document reproduces it byte-for-byte. Each marker may be overridden through the
|
|
153
153
|
* options object for documents that use a different convention, though the defaults match what every plugin in the family embeds.
|
|
154
154
|
*
|
|
155
155
|
* @param source - The full document text.
|
package/dist/featureOptions.d.ts
CHANGED
|
@@ -26,7 +26,7 @@ import type { HomebridgePluginLogging, Nullable } from "./util.ts";
|
|
|
26
26
|
* available for bespoke needs that the registry does not cover.
|
|
27
27
|
*
|
|
28
28
|
* The set targets the unit categories that recur across plugin catalogs: bitrate (in either of the two common storage conventions), data size, percentages, and
|
|
29
|
-
* durations. Extend the union when a new
|
|
29
|
+
* durations. Extend the union when a new format is genuinely shared across multiple plugins. Resist adding a formatter speculatively - the function escape
|
|
30
30
|
* hatch already covers one-off needs, and an unused formatter is dead surface that downstream plugins still see in their IDE autocomplete.
|
|
31
31
|
*
|
|
32
32
|
* @category Feature Options
|
|
@@ -43,7 +43,7 @@ export type FeatureOptionFormatter = "bps" | "bytes" | "kbps" | "ms" | "percent"
|
|
|
43
43
|
* @property meta - Optional. An opaque, plugin-private annotation channel the core never interprets. HBPU's types deliberately cannot see inside `TMeta`;
|
|
44
44
|
* the value is carried verbatim through the catalog and forwarded to the documentation renderer's closures (the only surface that knows its
|
|
45
45
|
* concrete shape). This mirrors the OpenAPI `x-*` extension discipline, made type-safe: a plugin parameterizes the entry with its own
|
|
46
|
-
* annotation type, the core treats it as `unknown`, and the round-trip stays structurally
|
|
46
|
+
* annotation type, the core treats it as `unknown`, and the round-trip stays structurally unchanged rather than a naming convention.
|
|
47
47
|
* @property name - Name of the feature option (used in option strings).
|
|
48
48
|
* @property render - Optional. Maps the raw stored value of a value-centric option to a display string. Either a {@link FeatureOptionFormatter} string naming
|
|
49
49
|
* a built-in formatter (preferred when the format already exists in the registry, since this keeps the enclosing catalog JSON-serializable
|
|
@@ -105,7 +105,7 @@ export interface ResolvedOptionEntry {
|
|
|
105
105
|
* Immutable derived index over the catalog inputs ({@link FeatureCategoryEntry}[] + the options map). Every field except `categories` / `options` is derived from
|
|
106
106
|
* those two; the index bundles them with their derivations so a single value carries everything any caller needs to make catalog-level decisions in O(1).
|
|
107
107
|
*
|
|
108
|
-
* The index is built once per catalog at {@link buildCatalogIndex}; it is
|
|
108
|
+
* The index is built once per catalog at {@link buildCatalogIndex}; it is unchanged across configured-options mutations, so a consumer that holds a stable
|
|
109
109
|
* reference can rely on its query results until the catalog itself changes. The {@link FeatureOptions} class holds one internally; consumers driving reducers
|
|
110
110
|
* directly hold it as state and reuse it across every dispatch that does not touch the catalog.
|
|
111
111
|
*
|
|
@@ -188,7 +188,7 @@ export declare function expandOption(category: FeatureCategoryEntry | string, op
|
|
|
188
188
|
* name on a `render` declaration does not resolve, surfacing the misconfiguration at load time rather than silently degrading the log-emission path.
|
|
189
189
|
*
|
|
190
190
|
* The index is the catalog-side input to every other pure helper in this module. Build it once per catalog; reuse it across every configured-options mutation
|
|
191
|
-
* because the catalog is
|
|
191
|
+
* because the catalog is unchanged across those mutations. Categories without an entry in the options map are skipped silently (a plugin defines a category for
|
|
192
192
|
* future expansion before any option has migrated into it).
|
|
193
193
|
*
|
|
194
194
|
* @param categories - The raw category list.
|
|
@@ -557,7 +557,7 @@ export declare class FeatureOptions {
|
|
|
557
557
|
*
|
|
558
558
|
* Callers express intent ("forget any configuration for option X at scope Y") and the model owns the entry-format end-to-end. The match is value-aware: for
|
|
559
559
|
* value-centric options it covers both the bare scoped entry and any entry carrying a single trailing value segment, so a subsequent {@link setOption} cleanly
|
|
560
|
-
* replaces whatever was there. No-op when no entry addresses the target scope, so callers can treat this as
|
|
560
|
+
* replaces whatever was there. No-op when no entry addresses the target scope, so callers can treat this as a repeatable reset.
|
|
561
561
|
*
|
|
562
562
|
* @param args - The addressing intent: option key and optional scope id. See {@link ClearOptionArgs}.
|
|
563
563
|
*
|
package/dist/featureOptions.js
CHANGED
|
@@ -136,7 +136,7 @@ function entryAddressesScope({ catalog, rawEntry, target }) {
|
|
|
136
136
|
* name on a `render` declaration does not resolve, surfacing the misconfiguration at load time rather than silently degrading the log-emission path.
|
|
137
137
|
*
|
|
138
138
|
* The index is the catalog-side input to every other pure helper in this module. Build it once per catalog; reuse it across every configured-options mutation
|
|
139
|
-
* because the catalog is
|
|
139
|
+
* because the catalog is unchanged across those mutations. Categories without an entry in the options map are skipped silently (a plugin defines a category for
|
|
140
140
|
* future expansion before any option has migrated into it).
|
|
141
141
|
*
|
|
142
142
|
* @param categories - The raw category list.
|
|
@@ -681,7 +681,7 @@ export class FeatureOptions {
|
|
|
681
681
|
*
|
|
682
682
|
* Callers express intent ("forget any configuration for option X at scope Y") and the model owns the entry-format end-to-end. The match is value-aware: for
|
|
683
683
|
* value-centric options it covers both the bare scoped entry and any entry carrying a single trailing value segment, so a subsequent {@link setOption} cleanly
|
|
684
|
-
* replaces whatever was there. No-op when no entry addresses the target scope, so callers can treat this as
|
|
684
|
+
* replaces whatever was there. No-op when no entry addresses the target scope, so callers can treat this as a repeatable reset.
|
|
685
685
|
*
|
|
686
686
|
* @param args - The addressing intent: option key and optional scope id. See {@link ClearOptionArgs}.
|
|
687
687
|
*
|
|
@@ -700,7 +700,7 @@ export class FeatureOptions {
|
|
|
700
700
|
return;
|
|
701
701
|
}
|
|
702
702
|
this.#configuredOptions = next;
|
|
703
|
-
// Only the index depends on the configured-options array; the catalog-derived state is
|
|
703
|
+
// Only the index depends on the configured-options array; the catalog-derived state is unchanged across config mutations and need not be touched here.
|
|
704
704
|
this.#configIndex = buildConfigIndex(this.#catalog, this.#configuredOptions);
|
|
705
705
|
}
|
|
706
706
|
/**
|
|
@@ -725,7 +725,7 @@ export class FeatureOptions {
|
|
|
725
725
|
*/
|
|
726
726
|
setOption(args) {
|
|
727
727
|
this.#configuredOptions = applySetOption({ args, catalog: this.#catalog, configuredOptions: this.#configuredOptions });
|
|
728
|
-
// Only the index depends on the configured-options array; the catalog-derived state is
|
|
728
|
+
// Only the index depends on the configured-options array; the catalog-derived state is unchanged across config mutations and need not be touched here.
|
|
729
729
|
this.#configIndex = buildConfigIndex(this.#catalog, this.#configuredOptions);
|
|
730
730
|
}
|
|
731
731
|
/**
|
|
@@ -791,7 +791,7 @@ export class FeatureOptions {
|
|
|
791
791
|
* @returns Returns the current list of available feature option categories.
|
|
792
792
|
*/
|
|
793
793
|
get categories() {
|
|
794
|
-
// The catalog stores the categories as readonly to encode the immutability
|
|
794
|
+
// The catalog stores the categories as readonly to encode the immutability guarantee the pure functional core relies on. The public getter returns the
|
|
795
795
|
// historical mutable type for backward compatibility - the array is the same identity the caller passed at construction (or via the setter), so consumers
|
|
796
796
|
// mutating it would be mutating the catalog regardless of the return type. The readonly annotation is the discipline, not a runtime enforcement.
|
|
797
797
|
return this.#catalog.categories;
|
|
@@ -823,7 +823,7 @@ export class FeatureOptions {
|
|
|
823
823
|
*/
|
|
824
824
|
set configuredOptions(options) {
|
|
825
825
|
this.#configuredOptions = options ?? [];
|
|
826
|
-
// The catalog-derived state is
|
|
826
|
+
// The catalog-derived state is unchanged across config mutations; only the lookup index needs rebuilding.
|
|
827
827
|
this.#configIndex = buildConfigIndex(this.#catalog, this.#configuredOptions);
|
|
828
828
|
}
|
|
829
829
|
/**
|
package/dist/ffmpeg/exec.d.ts
CHANGED
|
@@ -98,7 +98,7 @@ export declare class FfmpegExec extends FfmpegProcess {
|
|
|
98
98
|
* path does not normally produce a stream error, so an aborted run yields whatever bytes happened to arrive before the kill landed - which may be all of them, some
|
|
99
99
|
* of them, or none of them.
|
|
100
100
|
*
|
|
101
|
-
* This promise is the data channel only. To
|
|
101
|
+
* This promise is the data channel only. To distinguish "the child wrote nothing" from "the run was aborted before the child could write anything," consult
|
|
102
102
|
* {@link FfmpegExec.exited} (`exitCode` / `exitSignal`) and {@link FfmpegProcess.signal} (`signal.reason`). Those are the single source of truth for process
|
|
103
103
|
* disposition; an empty buffer carries no disposition meaning on its own.
|
|
104
104
|
*/
|
|
@@ -117,7 +117,7 @@ export declare class FfmpegExec extends FfmpegProcess {
|
|
|
117
117
|
* Await the process to completion and return the bundled result.
|
|
118
118
|
*
|
|
119
119
|
* Resolves once both the stdout collector and the base class's `exited` promise settle. Rejects with the same reason `exited` would reject with (today, only when
|
|
120
|
-
* the child never spawned - e.g., ENOENT). On any normal exit, including non-zero exit codes, this method resolves; callers
|
|
120
|
+
* the child never spawned - e.g., ENOENT). On any normal exit, including non-zero exit codes, this method resolves; callers distinguish outcomes by inspecting
|
|
121
121
|
* `exitCode` and `exitSignal` in the result, or the derived `hasError` getter on the instance.
|
|
122
122
|
*
|
|
123
123
|
* @returns A promise resolving to an {@link ExecResult} bundling stdout, exit code, exit signal, and the accumulated stderr log.
|
package/dist/ffmpeg/exec.js
CHANGED
|
@@ -47,7 +47,7 @@ export class FfmpegExec extends FfmpegProcess {
|
|
|
47
47
|
* path does not normally produce a stream error, so an aborted run yields whatever bytes happened to arrive before the kill landed - which may be all of them, some
|
|
48
48
|
* of them, or none of them.
|
|
49
49
|
*
|
|
50
|
-
* This promise is the data channel only. To
|
|
50
|
+
* This promise is the data channel only. To distinguish "the child wrote nothing" from "the run was aborted before the child could write anything," consult
|
|
51
51
|
* {@link FfmpegExec.exited} (`exitCode` / `exitSignal`) and {@link FfmpegProcess.signal} (`signal.reason`). Those are the single source of truth for process
|
|
52
52
|
* disposition; an empty buffer carries no disposition meaning on its own.
|
|
53
53
|
*/
|
|
@@ -88,7 +88,7 @@ export class FfmpegExec extends FfmpegProcess {
|
|
|
88
88
|
* Await the process to completion and return the bundled result.
|
|
89
89
|
*
|
|
90
90
|
* Resolves once both the stdout collector and the base class's `exited` promise settle. Rejects with the same reason `exited` would reject with (today, only when
|
|
91
|
-
* the child never spawned - e.g., ENOENT). On any normal exit, including non-zero exit codes, this method resolves; callers
|
|
91
|
+
* the child never spawned - e.g., ENOENT). On any normal exit, including non-zero exit codes, this method resolves; callers distinguish outcomes by inspecting
|
|
92
92
|
* `exitCode` and `exitSignal` in the result, or the derived `hasError` getter on the instance.
|
|
93
93
|
*
|
|
94
94
|
* @returns A promise resolving to an {@link ExecResult} bundling stdout, exit code, exit signal, and the accumulated stderr log.
|
|
@@ -14,6 +14,28 @@ export interface Mp4SegmentAssemblerInit {
|
|
|
14
14
|
segmentTimeout?: number;
|
|
15
15
|
signal?: AbortSignal;
|
|
16
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* The kind of a segment yielded by {@link Mp4SegmentAssembler.stream}. `"init"` is the one-shot initialization segment; `"media"` is a continuous media fragment. A
|
|
19
|
+
* consumer that paces or forwards every item uniformly can read {@link Mp4Segment.bytes} without branching; a consumer that must treat the init segment specially
|
|
20
|
+
* branches on this field.
|
|
21
|
+
*
|
|
22
|
+
* @category FFmpeg
|
|
23
|
+
*/
|
|
24
|
+
export type Mp4SegmentKind = "init" | "media";
|
|
25
|
+
/**
|
|
26
|
+
* A single fMP4 segment yielded by {@link Mp4SegmentAssembler.stream}, tagged with its kind so a consumer can tell the one-shot initialization segment apart from the
|
|
27
|
+
* media fragments that follow it without relying on positional ordering.
|
|
28
|
+
*
|
|
29
|
+
* @property bytes - The complete segment bytes: for `"init"`, the concatenated initialization boxes (typically `ftyp` + `moov`); for `"media"`, a concatenated
|
|
30
|
+
* `moof` + `mdat` pair.
|
|
31
|
+
* @property kind - `"init"` for the single leading initialization segment, `"media"` for each subsequent media fragment.
|
|
32
|
+
*
|
|
33
|
+
* @category FFmpeg
|
|
34
|
+
*/
|
|
35
|
+
export interface Mp4Segment {
|
|
36
|
+
bytes: Buffer;
|
|
37
|
+
kind: Mp4SegmentKind;
|
|
38
|
+
}
|
|
17
39
|
/**
|
|
18
40
|
* AsyncDisposable fMP4 segment assembler that converts a Readable byte source into an init segment promise and a media-segment async generator.
|
|
19
41
|
*
|
|
@@ -88,7 +110,7 @@ export declare class Mp4SegmentAssembler implements AsyncDisposable {
|
|
|
88
110
|
get aborted(): boolean;
|
|
89
111
|
/**
|
|
90
112
|
* `true` when the abort reason indicates a timeout. Matches both the canonical `HbpuAbortError("timeout")` emitted by the inter-segment watchdog and the platform
|
|
91
|
-
* `TimeoutError` emitted by `AbortSignal.timeout()`. The
|
|
113
|
+
* `TimeoutError` emitted by `AbortSignal.timeout()`. The branching lives in {@link isTimeoutReason} so this getter stays a one-line delegation and every
|
|
92
114
|
* resource class in the library shares one definition of "timeout."
|
|
93
115
|
*/
|
|
94
116
|
get isTimedOut(): boolean;
|
|
@@ -105,9 +127,9 @@ export declare class Mp4SegmentAssembler implements AsyncDisposable {
|
|
|
105
127
|
* ends, the assembler aborts, or the optional caller signal aborts; in every case the queue is drained before the generator returns, so a consumer never loses a
|
|
106
128
|
* segment that was already assembled before teardown.
|
|
107
129
|
*
|
|
108
|
-
* **Single-consumer only.** The internal parked-waiter slot is single-writer; calling `segments()` concurrently with another consumer on the same assembler
|
|
109
|
-
* unsupported and will hang one of the consumers when the producer's wake-up
|
|
110
|
-
* replicating each yielded Buffer into per-consumer queues external to the assembler.
|
|
130
|
+
* **Single-consumer only.** The internal parked-waiter slot is single-writer; calling `segments()` concurrently with another consumer on the same assembler - including
|
|
131
|
+
* the {@link Mp4SegmentAssembler.stream} view, which drives this generator internally - is unsupported and will hang one of the consumers when the producer's wake-up
|
|
132
|
+
* resolves only the later parker. If fan-out is needed, tee at the consumer side by replicating each yielded Buffer into per-consumer queues external to the assembler.
|
|
111
133
|
*
|
|
112
134
|
* @param init - Optional init options. `signal` composes with the assembler's own signal - aborting it terminates only this generator call, not the assembler.
|
|
113
135
|
*
|
|
@@ -116,5 +138,24 @@ export declare class Mp4SegmentAssembler implements AsyncDisposable {
|
|
|
116
138
|
segments(init?: {
|
|
117
139
|
signal?: AbortSignal;
|
|
118
140
|
}): AsyncGenerator<Buffer>;
|
|
141
|
+
/**
|
|
142
|
+
* Async generator yielding the whole segment stream as a kind-tagged sequence: exactly one {@link Mp4Segment} of kind `"init"` carrying the initialization bytes,
|
|
143
|
+
* followed by one of kind `"media"` per completed media fragment. This is a third view over the same single-pass pipeline, composed from {@link initSegment} and
|
|
144
|
+
* {@link segments} - it lets a consumer forward the init segment and the media segments through a single loop without tracking which item is which by position.
|
|
145
|
+
*
|
|
146
|
+
* Terminates cleanly on the same conditions as {@link segments}: the source ends, the assembler aborts, or the optional caller signal aborts; queued media drains
|
|
147
|
+
* before the generator returns, so no assembled segment is lost. If the assembler is aborted before the initialization segment arrives, the generator returns without
|
|
148
|
+
* yielding anything.
|
|
149
|
+
*
|
|
150
|
+
* **Single-consumer only.** `stream()` drives {@link segments} internally, so it shares the one parked-waiter slot. Use `stream()` OR the {@link initSegment} /
|
|
151
|
+
* {@link segments} pair on a single assembler, never both concurrently - mixing them competes for the same drain and hangs one consumer.
|
|
152
|
+
*
|
|
153
|
+
* @param init - Optional init options. `signal` composes with the assembler's own signal - aborting it terminates only this generator call, not the assembler.
|
|
154
|
+
*
|
|
155
|
+
* @returns An async generator yielding one `"init"` segment followed by `"media"` segments in stream order.
|
|
156
|
+
*/
|
|
157
|
+
stream(init?: {
|
|
158
|
+
signal?: AbortSignal;
|
|
159
|
+
}): AsyncGenerator<Mp4Segment>;
|
|
119
160
|
}
|
|
120
161
|
//# sourceMappingURL=mp4-assembler.d.ts.map
|