@discord-player/plugin-host 8.0.0-dev.0 → 8.0.0-dev.2

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.
Files changed (60) hide show
  1. package/README.md +199 -29
  2. package/dist/compat/base-extractor.d.ts +6 -0
  3. package/dist/compat/base-extractor.js.map +1 -1
  4. package/dist/compat/extractor-execution-context.js.map +1 -1
  5. package/dist/compat/extractor-plugin.js +109 -68
  6. package/dist/compat/extractor-plugin.js.map +1 -1
  7. package/dist/compat/utils.js.map +1 -1
  8. package/dist/errors.d.ts +0 -2
  9. package/dist/errors.js +0 -2
  10. package/dist/errors.js.map +1 -1
  11. package/dist/host.d.ts +24 -3
  12. package/dist/host.js +198 -50
  13. package/dist/host.js.map +1 -1
  14. package/dist/index.d.ts +5 -0
  15. package/dist/index.js +2 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/legacy-player.d.ts +1 -1
  18. package/dist/lyrics.d.ts +56 -0
  19. package/dist/lyrics.js +110 -0
  20. package/dist/lyrics.js.map +1 -0
  21. package/dist/media.d.ts +15 -0
  22. package/dist/media.js +193 -0
  23. package/dist/media.js.map +1 -0
  24. package/dist/plugins/execution-options.d.ts +2 -0
  25. package/dist/plugins/operation-dispatch.js +30 -11
  26. package/dist/plugins/operation-dispatch.js.map +1 -1
  27. package/dist/plugins/plugin-error.js.map +1 -1
  28. package/dist/plugins/registry-internals.d.ts +2 -2
  29. package/dist/plugins/registry.d.ts +48 -6
  30. package/dist/plugins/registry.js +180 -18
  31. package/dist/plugins/registry.js.map +1 -1
  32. package/dist/plugins/stream-resolver.js +24 -4
  33. package/dist/plugins/stream-resolver.js.map +1 -1
  34. package/dist/plugins/types.d.ts +28 -23
  35. package/dist/plugins/types.js.map +1 -1
  36. package/dist/protocol.d.ts +43 -3
  37. package/dist/protocol.js +11 -1
  38. package/dist/protocol.js.map +1 -1
  39. package/dist/providers/lrclib.d.ts +120 -0
  40. package/dist/providers/lrclib.js +183 -0
  41. package/dist/providers/lrclib.js.map +1 -0
  42. package/dist/remote.d.ts +29 -0
  43. package/dist/remote.js +142 -0
  44. package/dist/remote.js.map +1 -0
  45. package/dist/runtime.d.ts +2 -8
  46. package/dist/runtime.js +42 -44
  47. package/dist/runtime.js.map +1 -1
  48. package/dist/structures/search-result.js.map +1 -1
  49. package/dist/structures/track-types.d.ts +7 -3
  50. package/dist/structures/track.d.ts +6 -11
  51. package/dist/structures/track.js +10 -10
  52. package/dist/structures/track.js.map +1 -1
  53. package/dist/types.d.ts +4 -4
  54. package/dist/utils/legacy-serialization-schemas.d.ts +12 -0
  55. package/dist/utils/serialization-schemas.d.ts +18 -0
  56. package/dist/utils/serialization-schemas.js +6 -1
  57. package/dist/utils/serialization-schemas.js.map +1 -1
  58. package/dist/utils/serialization.js.map +1 -1
  59. package/docs/remedia-contract.md +55 -0
  60. package/package.json +5 -4
package/dist/lyrics.js ADDED
@@ -0,0 +1,110 @@
1
+ import { z } from 'zod';
2
+ /** Validate provider-neutral records crossing a process boundary. @internal */
3
+ export const lyricsResultSchema = z.strictObject({
4
+ trackId: z.string().optional(),
5
+ provider: z.strictObject({ pluginId: z.string().min(1), hostId: z.string().optional(), data: z.json() }).optional(),
6
+ plain: z.discriminatedUnion('available', [
7
+ z.strictObject({ available: z.literal(false) }),
8
+ z.strictObject({ available: z.literal(true), text: z.string() }),
9
+ ]),
10
+ synced: z.discriminatedUnion('available', [
11
+ z.strictObject({ available: z.literal(false) }),
12
+ z.strictObject({
13
+ available: z.literal(true),
14
+ lines: z.array(z.strictObject({ timestampMs: z.number().nonnegative(), line: z.string() })),
15
+ }),
16
+ ]),
17
+ metadata: z.json().optional(),
18
+ });
19
+ /** Normalize and validate a lyrics record once, including sorted synchronized timestamps.
20
+ * @param result Provider record.
21
+ * @returns Validated record with duplicate timestamps resolved deterministically.
22
+ */
23
+ export function normalizeLyrics(result) {
24
+ const value = lyricsResultSchema.parse(result);
25
+ const normalized = {
26
+ plain: value.plain,
27
+ synced: value.synced,
28
+ ...(value.trackId === undefined ? {} : { trackId: value.trackId }),
29
+ ...(value.metadata === undefined ? {} : { metadata: value.metadata }),
30
+ ...(value.provider
31
+ ? {
32
+ provider: {
33
+ pluginId: value.provider.pluginId,
34
+ data: value.provider.data,
35
+ ...(value.provider.hostId === undefined ? {} : { hostId: value.provider.hostId }),
36
+ },
37
+ }
38
+ : {}),
39
+ };
40
+ if (!value.synced.available)
41
+ return normalized;
42
+ const lines = new Map(value.synced.lines.map((line) => [line.timestampMs, line.line]));
43
+ return {
44
+ ...normalized,
45
+ synced: {
46
+ available: true,
47
+ lines: [...lines].sort(([a], [b]) => a - b).map(([timestampMs, line]) => ({ timestampMs, line })),
48
+ },
49
+ };
50
+ }
51
+ /** Parse LRC once, including multiple timestamps and decimal-second fractions.
52
+ * @param text LRC text.
53
+ * @returns Sorted normalized lines, with the last line winning duplicate timestamps.
54
+ */
55
+ export function parseLyrics(text) {
56
+ const lines = new Map();
57
+ const offset = Number(/\[offset:([+-]?\d+)\]/i.exec(text)?.[1] ?? 0);
58
+ for (const row of text.split(/\r?\n/)) {
59
+ const matches = [...row.matchAll(/\[(\d+):(\d{2})(?:\.(\d{1,3}))?\]/g)];
60
+ const line = row.replace(/\[\d+:\d{2}(?:\.\d{1,3})?\]/g, '').trim();
61
+ for (const match of matches) {
62
+ const seconds = Number(match[2]);
63
+ if (seconds >= 60)
64
+ continue;
65
+ const timestampMs = Number(match[1]) * 60000 + seconds * 1000 + Number((match[3] ?? '').padEnd(3, '0')) + offset;
66
+ if (Number.isFinite(timestampMs) && timestampMs >= 0)
67
+ lines.set(timestampMs, line);
68
+ }
69
+ }
70
+ return [...lines].sort(([a], [b]) => a - b).map(([timestampMs, line]) => ({ timestampMs, line }));
71
+ }
72
+ /** Resolve lyrics through the same operation registry as source metadata.
73
+ * @param plugins Shared registry.
74
+ * @param input Track or raw query.
75
+ * @param signal Caller lifetime.
76
+ * @returns Results in provider priority order, preferring explicit and source affinity.
77
+ */
78
+ export async function searchLyrics(plugins, input, signal) {
79
+ signal?.throwIfAborted();
80
+ await plugins.ready();
81
+ const providers = plugins.providers('lyrics.search');
82
+ const preferred = typeof input === 'string' ? [] : [input.lyricsReference, input.sourceReference];
83
+ const ordered = [...providers];
84
+ for (const reference of preferred.reverse()) {
85
+ if (!reference)
86
+ continue;
87
+ const index = ordered.findIndex((provider) => provider.pluginId === reference.pluginId && (!reference.hostId || provider.hostId === reference.hostId));
88
+ if (index >= 0)
89
+ ordered.unshift(...ordered.splice(index, 1));
90
+ }
91
+ const results = [];
92
+ const seen = new Set();
93
+ for (const provider of ordered) {
94
+ const groups = await plugins.execute('lyrics.search', { input }, { pluginId: provider.pluginId, hostId: provider.hostId ?? null, signal });
95
+ for (const result of groups.flatMap((group) => group ?? [])) {
96
+ const normalized = normalizeLyrics({
97
+ ...result,
98
+ ...(typeof input === 'string' ? {} : { trackId: input.id }),
99
+ provider: { ...provider, data: result.provider?.data ?? null },
100
+ });
101
+ const key = JSON.stringify([normalized.plain, normalized.synced]);
102
+ if ((!normalized.plain.available && !normalized.synced.available) || seen.has(key))
103
+ continue;
104
+ seen.add(key);
105
+ results.push(normalized);
106
+ }
107
+ }
108
+ return results;
109
+ }
110
+ //# sourceMappingURL=lyrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lyrics.js","sourceRoot":"","sources":["../src/lyrics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /** Access limits for remote media materialization. Providers execute trusted code; this is not a plugin sandbox. */
2
+ export interface MediaAccessPolicy {
3
+ /** Permit private and loopback destinations, including redirects. Default false. */
4
+ allowPrivateNetworks?: boolean;
5
+ /** Optional exact hostname allowlist, also applied to redirects. */
6
+ allowedHosts?: readonly string[];
7
+ /** Authorized file roots. Default empty; roots and their parents must be administrator-owned. */
8
+ allowedFileRoots?: readonly string[];
9
+ /** Maximum encoded bytes per response. Default 512 MiB. */
10
+ maxBytes?: number;
11
+ /** Maximum simultaneous streams per host. Default 32. */
12
+ maxConcurrent?: number;
13
+ /** Whole-stream deadline in milliseconds, including DNS and connection. Default 30 minutes. */
14
+ timeoutMs?: number;
15
+ }
package/dist/media.js ADDED
@@ -0,0 +1,193 @@
1
+ import { lookup } from 'node:dns/promises';
2
+ import { request as httpRequest } from 'node:http';
3
+ import { request as httpsRequest } from 'node:https';
4
+ import { BlockList, isIP } from 'node:net';
5
+ import { open, realpath } from 'node:fs/promises';
6
+ import { relative, isAbsolute, sep } from 'node:path';
7
+ import { fileURLToPath } from 'node:url';
8
+ import { Readable, Transform, addAbortSignal, pipeline } from 'node:stream';
9
+ const active = new WeakMap();
10
+ const denied = new BlockList();
11
+ const deniedV6 = new BlockList();
12
+ deniedV6.addSubnet('2001::', 23, 'ipv6');
13
+ deniedV6.addSubnet('2001:db8::', 32, 'ipv6');
14
+ deniedV6.addSubnet('2002::', 16, 'ipv6');
15
+ deniedV6.addSubnet('3fff::', 20, 'ipv6');
16
+ for (const [address, prefix] of [
17
+ ['0.0.0.0', 8],
18
+ ['10.0.0.0', 8],
19
+ ['100.64.0.0', 10],
20
+ ['127.0.0.0', 8],
21
+ ['169.254.0.0', 16],
22
+ ['172.16.0.0', 12],
23
+ ['192.0.0.0', 24],
24
+ ['192.0.2.0', 24],
25
+ ['192.168.0.0', 16],
26
+ ['198.18.0.0', 15],
27
+ ['198.51.100.0', 24],
28
+ ['203.0.113.0', 24],
29
+ ['224.0.0.0', 3],
30
+ ])
31
+ denied.addSubnet(address, prefix);
32
+ function publicAddress(address) {
33
+ if (isIP(address) === 4)
34
+ return !denied.check(address, 'ipv4');
35
+ // Only global unicast IPv6; reject transition/mapped forms and documentation ranges.
36
+ return /^[23][0-9a-f]{3}:/i.test(address) && !deniedV6.check(address, 'ipv6');
37
+ }
38
+ function positive(value) {
39
+ if (!Number.isSafeInteger(value) || value < 1)
40
+ throw new RangeError('Invalid media resource limit');
41
+ return value;
42
+ }
43
+ /** Validate URL policy and resolve the exact address used for a connection.
44
+ * @internal
45
+ * @param url Provider URL.
46
+ * @param policy Host access policy.
47
+ * @param signal Caller lifetime.
48
+ * @returns Validated destination; callers opening sockets must pin this address.
49
+ */
50
+ export async function authorizeMediaURL(url, policy, signal) {
51
+ if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password)
52
+ throw new Error('Media requires an HTTP(S) URL without user credentials');
53
+ const hostname = url.hostname.replace(/^\[|\]$/g, '');
54
+ if (policy.allowedHosts && !policy.allowedHosts.includes(hostname))
55
+ throw new Error('Media hostname denied');
56
+ signal.throwIfAborted();
57
+ const addresses = await new Promise((resolve, reject) => {
58
+ const abort = () => reject(signal.reason);
59
+ signal.addEventListener('abort', abort, { once: true });
60
+ lookup(hostname, { all: true })
61
+ .then(resolve, reject)
62
+ .finally(() => signal.removeEventListener('abort', abort));
63
+ });
64
+ signal.throwIfAborted();
65
+ if (!addresses.length || (!policy.allowPrivateNetworks && addresses.some(({ address }) => !publicAddress(address))))
66
+ throw new Error('Media destination denied');
67
+ const selected = addresses[0];
68
+ return selected;
69
+ }
70
+ async function remote(url, policy, signal, redirects = 0) {
71
+ const selected = await authorizeMediaURL(url, policy, signal);
72
+ const response = await new Promise((resolve, reject) => {
73
+ const req = (url.protocol === 'https:' ? httpsRequest : httpRequest)(url, {
74
+ signal,
75
+ // Pin the checked address; keep the original Host and TLS server name. No second DNS lookup.
76
+ lookup: (_hostname, options, callback) => {
77
+ if (options.all)
78
+ callback(null, [selected]);
79
+ else
80
+ callback(null, selected.address, selected.family);
81
+ },
82
+ headers: { 'accept-encoding': 'identity' },
83
+ }, resolve);
84
+ req.once('error', reject);
85
+ req.setTimeout(30000, () => req.destroy(new Error('Media upstream idle timeout')));
86
+ req.end();
87
+ });
88
+ if ([301, 302, 303, 307, 308].includes(response.statusCode ?? 0)) {
89
+ const location = response.headers.location;
90
+ response.destroy();
91
+ if (!location || redirects >= 5)
92
+ throw new Error('Invalid media redirect');
93
+ const target = new URL(location, url);
94
+ if (url.protocol === 'https:' && target.protocol !== 'https:')
95
+ throw new Error('Media TLS downgrade denied');
96
+ return remote(target, policy, signal, redirects + 1);
97
+ }
98
+ if (response.statusCode !== 200) {
99
+ response.destroy();
100
+ throw new Error(`Media upstream returned ${response.statusCode}`);
101
+ }
102
+ return response;
103
+ }
104
+ /** Open bounded encoded media under a host policy. No whole-response buffering occurs.
105
+ * @internal
106
+ * @param source Trusted provider result, potentially containing an untrusted location.
107
+ * @param policy Host authorization and resource limits.
108
+ * @param signal Resolution/consumer lifetime.
109
+ * @returns Owned stream; close, abort, errors and deadlines release upstream resources.
110
+ */
111
+ export async function openMedia(source, policy, signal) {
112
+ const maxBytes = positive(policy.maxBytes ?? 512 * 1024 * 1024);
113
+ const maxConcurrent = positive(policy.maxConcurrent ?? 32);
114
+ const timeout = positive(policy.timeoutMs ?? 1800000);
115
+ const expiration = 'expiresAtMs' in source ? Number(source.expiresAtMs) : undefined;
116
+ if (expiration !== undefined && (!Number.isFinite(expiration) || expiration <= Date.now())) {
117
+ if ('stream' in source)
118
+ source.stream.destroy();
119
+ throw new Error('Media source credentials have expired; resolve the source again');
120
+ }
121
+ if ((active.get(policy) ?? 0) >= maxConcurrent) {
122
+ if ('stream' in source)
123
+ source.stream.destroy();
124
+ throw new Error('Media concurrency limit reached');
125
+ }
126
+ active.set(policy, (active.get(policy) ?? 0) + 1);
127
+ const controller = new AbortController();
128
+ const lifetime = signal ? AbortSignal.any([signal, controller.signal]) : controller.signal;
129
+ const timer = setTimeout(() => controller.abort(new Error('Media deadline exceeded')), timeout);
130
+ timer.unref();
131
+ let input;
132
+ let released = false;
133
+ const release = () => {
134
+ if (released)
135
+ return;
136
+ released = true;
137
+ clearTimeout(timer);
138
+ active.set(policy, (active.get(policy) ?? 1) - 1);
139
+ input?.destroy();
140
+ };
141
+ try {
142
+ lifetime.throwIfAborted();
143
+ if ('stream' in source)
144
+ input = source.stream;
145
+ else if ('buffer' in source)
146
+ input = Readable.from([source.buffer]);
147
+ else if ('file' in source) {
148
+ const path = await realpath(source.file.startsWith('file:') ? fileURLToPath(source.file) : source.file);
149
+ const roots = await Promise.all((policy.allowedFileRoots ?? []).map((root) => realpath(root)));
150
+ if (!roots.some((root) => {
151
+ const rel = relative(root, path);
152
+ return rel !== '..' && !rel.startsWith(`..${sep}`) && !isAbsolute(rel);
153
+ }))
154
+ throw new Error('Media file outside allowed roots');
155
+ const file = await open(path, 'r');
156
+ try {
157
+ if (!(await file.stat()).isFile())
158
+ throw new Error('Media path is not a regular file');
159
+ input = file.createReadStream();
160
+ }
161
+ catch (error) {
162
+ await file.close();
163
+ throw error;
164
+ }
165
+ }
166
+ else if ('url' in source)
167
+ input = await remote(new URL(source.url), policy, lifetime);
168
+ else
169
+ throw new Error('A source host cannot materialize another operation source');
170
+ lifetime.throwIfAborted();
171
+ let bytes = 0;
172
+ const output = new Transform({
173
+ destroy(error, callback) {
174
+ release();
175
+ callback(error);
176
+ },
177
+ transform(chunk, _encoding, callback) {
178
+ bytes += chunk.length;
179
+ callback(bytes > maxBytes ? new Error('Media byte limit exceeded') : null, chunk);
180
+ },
181
+ });
182
+ output.once('close', release);
183
+ addAbortSignal(lifetime, output);
184
+ pipeline(input, output, () => { });
185
+ return { stream: output, ...(expiration === undefined ? {} : { expiresAtMs: expiration }) };
186
+ }
187
+ catch (error) {
188
+ controller.abort();
189
+ release();
190
+ throw error;
191
+ }
192
+ }
193
+ //# sourceMappingURL=media.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media.js","sourceRoot":"","sources":["../src/media.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,8 @@ import type { MediaSource } from '@remedia/client';
3
3
  export interface ExecuteOptions {
4
4
  /** Restrict execution to one provider. */
5
5
  pluginId?: string;
6
+ /** Restrict deployment; null restricts execution to embedded registrations. */
7
+ hostId?: string | null;
6
8
  /** Caller cancellation. */
7
9
  signal?: AbortSignal;
8
10
  /** Disabled source IDs. */
@@ -1,5 +1,27 @@
1
1
  import { Readable } from 'node:stream';
2
2
  import { PluginError } from './plugin-error.js';
3
+ /** Select active, permitted handlers using the dispatcher's own routing rules.
4
+ * @internal
5
+ * @param operation Operation being inspected.
6
+ * @param input Routing input.
7
+ * @param options Provider targeting and block list.
8
+ * @param state Current registry state.
9
+ * @returns Ordered applicable subscriptions without invoking them.
10
+ */
11
+ export function selectHandlers(operation, input, options, state) {
12
+ return state.handlers
13
+ .filter((handler) => handler.operation === operation &&
14
+ handler.entry.active &&
15
+ (!options.pluginId || handler.entry.id === options.pluginId) &&
16
+ (options.hostId === undefined ||
17
+ (handler.entry.registration.definition.remoteHost?.hostId ?? null) === options.hostId) &&
18
+ !options.blocked?.includes(handler.entry.id) &&
19
+ !state.blocked().includes(handler.entry.id) &&
20
+ (!input.protocol ||
21
+ !handler.protocols?.length ||
22
+ handler.protocols?.includes(input.protocol)))
23
+ .sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0) || a.order - b.order);
24
+ }
3
25
  /** Dispatch a typed operation against initialized host state.
4
26
  * @internal
5
27
  * @param operation Operation name.
@@ -14,16 +36,7 @@ export async function dispatchOperation(operation, input, options, state, handle
14
36
  if (!policy) {
15
37
  throw new Error(`Undefined operation: ${operation}`);
16
38
  }
17
- const handlers = state.handlers
18
- .filter((handler) => handler.operation === operation &&
19
- handler.entry.active &&
20
- (!options.pluginId || handler.entry.id === options.pluginId) &&
21
- !options.blocked?.includes(handler.entry.id) &&
22
- !state.blocked().includes(handler.entry.id) &&
23
- (!input.protocol ||
24
- !handler.protocols?.length ||
25
- handler.protocols.includes(input.protocol)))
26
- .sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0) || a.order - b.order);
39
+ const handlers = selectHandlers(operation, input, options, state);
27
40
  const results = [];
28
41
  let value = input;
29
42
  for (const handler of handlers) {
@@ -70,7 +83,13 @@ export async function dispatchOperation(operation, input, options, state, handle
70
83
  }
71
84
  }
72
85
  if (operation === 'search.query.match' && result !== null) {
73
- result = { ...result, pluginId: handler.entry.id };
86
+ result = {
87
+ ...result,
88
+ pluginId: handler.entry.id,
89
+ ...(handler.entry.registration.definition.remoteHost
90
+ ? { hostId: handler.entry.registration.definition.remoteHost.hostId }
91
+ : {}),
92
+ };
74
93
  }
75
94
  if (policy === 'first') {
76
95
  let owner = handler.entry;
@@ -1 +1 @@
1
- {"version":3,"file":"operation-dispatch.js","sourceRoot":"","sources":["../../src/plugins/operation-dispatch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"operation-dispatch.js","sourceRoot":"","sources":["../../src/plugins/operation-dispatch.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-error.js","sourceRoot":"","sources":["../../src/plugins/plugin-error.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,MAAM,OAAO,WAAY,SAAQ,KAAK;IAQlB,QAAQ;IAER,SAAS;IAT3B;;;;OAIG;IACH;IACE,uCAAuC;IACvB,QAAgB;IAChC,2CAA2C;IAC3B,SAAiB,EACjC,KAAc;QAEd,KAAK,CAAC,UAAU,QAAQ,kBAAkB,SAAS,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE;YAChH,KAAK;SACN,CAAC,CAAC;wBAPa,QAAQ;yBAER,SAAS;QAOzB,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF"}
1
+ {"version":3,"file":"plugin-error.js","sourceRoot":"","sources":["../../src/plugins/plugin-error.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,MAAM,OAAO,WAAY,SAAQ,KAAK;IAQlB,QAAQ;IAGR,SAAS;IAV3B;;;;OAIG;IACH;IACE,uCAAuC;IACvB,QAAgB;IAEhC,2CAA2C;IAC3B,SAAiB,EAEjC,KAAc;QAEd,KAAK,CAAC,UAAU,QAAQ,kBAAkB,SAAS,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE;YAChH,KAAK;SACN,CAAC,CAAC;wBATa,QAAQ;yBAGR,SAAS;QAQzB,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF"}
@@ -1,4 +1,4 @@
1
- import type { DispatchPolicy, HandlerOptions, OperationInput, OperationContext, OperationName, OperationResult, PluginRegistration, SourcePluginContext } from './types.js';
1
+ import type { DispatchPolicy, HandlerOptions, OperationInput, OperationContext, OperationName, OperationResult, PluginRegistration, PluginContext } from './types.js';
2
2
  import type { ExecuteOptions } from './execution-options.js';
3
3
  /** Internal registration ownership record. */
4
4
  export type Entry = {
@@ -7,7 +7,7 @@ export type Entry = {
7
7
  /** Registration-local declaration and options. */
8
8
  registration: PluginRegistration<any>;
9
9
  /** Registration-local setup context. */
10
- context: SourcePluginContext<any>;
10
+ context: PluginContext<any>;
11
11
  /** Registration lifetime cancellation. */
12
12
  controller: AbortController;
13
13
  /** Owned cleanup callbacks in registration order. */
@@ -1,39 +1,80 @@
1
+ import { type RemotePluginHostOptions } from '../remote.js';
1
2
  import type { MediaSource } from '@remedia/client';
2
3
  import type { Track } from '../structures/track.js';
3
4
  import type { ExecuteOptions, StreamResolutionOptions } from './execution-options.js';
4
- import type { OperationInput, OperationName, OperationResult, PluginRegistration, SourceOperationMap } from './types.js';
5
+ import type { OperationInput, OperationName, OperationResult, PluginRegistration, ProviderReference, OperationMap } from './types.js';
5
6
  import type { LegacyPlayerContext } from '../legacy-player.js';
6
7
  export { PluginError } from './plugin-error.js';
7
8
  export type { ExecuteOptions, StreamResolutionOptions } from './execution-options.js';
8
- /** Context-owned source execution registry. Removal aborts and drains calls before teardown. */
9
+ /** Context-owned capability registry. Removal aborts and drains calls before teardown. */
9
10
  export declare class PluginRegistry {
10
11
  readonly player: LegacyPlayerContext;
11
12
  private readonly blocked;
13
+ private readonly hostId?;
14
+ private advertisements;
12
15
  private entries;
13
16
  private handlers;
14
17
  private order;
15
18
  private resultOwners;
16
19
  private destroyed;
20
+ private readonly lifetime;
17
21
  /** Create an independent host.
18
22
  * @param player Structural source context.
19
23
  * @param blocked Default disabled source IDs supplied by the owning Player.
24
+ * @param hostId Owning deployment, absent in ordinary embedded execution.
20
25
  */
21
- constructor(player: LegacyPlayerContext, blocked?: () => readonly string[]);
26
+ constructor(player: LegacyPlayerContext, blocked?: () => readonly string[], hostId?: string | undefined);
22
27
  private definitions;
23
28
  /** Define a declaration-merged operation before registering handlers.
24
29
  * @param name Operation name.
25
30
  * @param policy Dispatch policy matching its contract.
26
31
  */
27
- defineOperation<K extends OperationName>(name: K, policy: SourceOperationMap[K]['policy']): void;
32
+ defineOperation<K extends OperationName>(name: K, policy: OperationMap[K]['policy']): void;
28
33
  /** Whether an ID is reserved or active.
29
34
  * @param id Plugin ID.
35
+ * @param hostId Optional deployment constraint.
30
36
  */
31
- has(id: string): boolean;
37
+ has(id: string, hostId?: string): boolean;
38
+ /** List active provider/deployment references in priority and registration order.
39
+ * @param operation Capability to inspect.
40
+ * @returns Unique eligible provider/deployment references.
41
+ */
42
+ providers(operation: OperationName): ProviderReference[];
43
+ /** Check whether a deployment has an owned registration.
44
+ * @param hostId Deployment identity.
45
+ */
46
+ hasHost(hostId: string): boolean;
47
+ /** Advertise only actual local operation handlers.
48
+ * @returns Serializable provider capability descriptions.
49
+ */
50
+ describe(): {
51
+ id: string;
52
+ operations: (keyof OperationMap)[];
53
+ protocols: string[];
54
+ priorities: {
55
+ [k: string]: number;
56
+ };
57
+ }[];
58
+ /** Register all advertised providers from an existing HTTP deployment.
59
+ * @param host Existing deployment and authentication.
60
+ * @param signal Caller lifetime.
61
+ */
62
+ registerHost(host: RemotePluginHostOptions, signal?: AbortSignal): Promise<void>;
32
63
  /** Whether an active matching handler explicitly accepts a protocol.
33
64
  * @param protocol Query prefix without punctuation.
34
65
  * @param options Source targeting and block list.
35
66
  */
36
67
  supportsProtocol(protocol: string, options?: ExecuteOptions): boolean;
68
+ /** Ordered owners of a custom query protocol.
69
+ * @param protocol Registered protocol prefix.
70
+ * @param options Targeting and block list.
71
+ * @returns Eligible provider identities, in dispatch order.
72
+ */
73
+ protocolMatches(protocol: string, options?: ExecuteOptions): {
74
+ pluginId: string;
75
+ hostId: string | undefined;
76
+ score: number;
77
+ }[];
37
78
  /** Register and initialize a source descriptor, reserving its ID synchronously.
38
79
  * @param registration Descriptor produced by definePlugin.
39
80
  */
@@ -41,9 +82,10 @@ export declare class PluginRegistry {
41
82
  private cleanup;
42
83
  /** Abort new and active work, drain handlers, and release resources. Handlers must cooperate with cancellation.
43
84
  * @param id Plugin ID.
85
+ * @param hostId Optional deployment identity when the provider exists on multiple hosts.
44
86
  * @returns Whether the registration existed.
45
87
  */
46
- unregister(id: string): Promise<boolean>;
88
+ unregister(id: string, hostId?: string): Promise<boolean>;
47
89
  /** Initialize pending registrations before dispatch. */
48
90
  ready(): Promise<void>;
49
91
  /** Destroy all registrations, attempting every cleanup even when one fails. */