@camstack/core 0.1.36 → 0.1.38
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/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.d.ts +7 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.d.ts.map +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +46 -56
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js.map +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +47 -57
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs.map +1 -1
- package/dist/index.js +89 -143
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +89 -143
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -37
- package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.d.ts +0 -8
- package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.d.ts.map +0 -1
- package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.js +0 -75
- package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.js.map +0 -1
- package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.mjs +0 -69
- package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.mjs.map +0 -1
- package/dist/builtins/auth-orchestrator/index.d.ts +0 -2
- package/dist/builtins/auth-orchestrator/index.d.ts.map +0 -1
- package/dist/builtins/auth-orchestrator/index.js +0 -7
- package/dist/builtins/auth-orchestrator/index.mjs +0 -2
- package/dist/builtins/mesh-orchestrator/index.d.ts +0 -2
- package/dist/builtins/mesh-orchestrator/index.d.ts.map +0 -1
- package/dist/builtins/mesh-orchestrator/index.js +0 -7
- package/dist/builtins/mesh-orchestrator/index.mjs +0 -2
- package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.d.ts +0 -9
- package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.d.ts.map +0 -1
- package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.js +0 -113
- package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.js.map +0 -1
- package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.mjs +0 -107
- package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.mjs.map +0 -1
- package/dist/builtins/turn-orchestrator/index.d.ts +0 -2
- package/dist/builtins/turn-orchestrator/index.d.ts.map +0 -1
- package/dist/builtins/turn-orchestrator/index.js +0 -7
- package/dist/builtins/turn-orchestrator/index.mjs +0 -2
- package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.d.ts +0 -34
- package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.d.ts.map +0 -1
- package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.js +0 -126
- package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.js.map +0 -1
- package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.mjs +0 -120
- package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.mjs.map +0 -1
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
Object.defineProperties(exports, {
|
|
2
|
-
__esModule: { value: true },
|
|
3
|
-
[Symbol.toStringTag]: { value: "Module" }
|
|
4
|
-
});
|
|
5
|
-
require("../../chunk-C13QxCFV.js");
|
|
6
|
-
let _camstack_types = require("@camstack/types");
|
|
7
|
-
//#region src/builtins/turn-orchestrator/turn-orchestrator.addon.ts
|
|
8
|
-
/**
|
|
9
|
-
* TURN orchestrator — singleton facade over the `turn-provider`
|
|
10
|
-
* collection (Cloudflare TURN, coturn, Twilio, …). Mirrors the
|
|
11
|
-
* remote-access-orchestrator persistence + autostart contract:
|
|
12
|
-
* - `enabledProviders: string[]` in addon-store is the operator's
|
|
13
|
-
* intent. Boot reads it back; the Enable/Disable toggle in the
|
|
14
|
-
* admin UI writes it.
|
|
15
|
-
* - `getAllServers()` (consumed by the WebRTC layer) aggregates ICE
|
|
16
|
-
* servers ONLY from enabled providers.
|
|
17
|
-
* - `listProviders()` surfaces the persisted `enabled` flag so the
|
|
18
|
-
* UI can render the correct toggle state on first paint.
|
|
19
|
-
*
|
|
20
|
-
* Provides:
|
|
21
|
-
* - listProviders() — admin UI inventory
|
|
22
|
-
* - getAllServers() — combined ICE server list across enabled providers
|
|
23
|
-
* - setProviderEnabled() — toggle a provider on/off (persisted)
|
|
24
|
-
*/
|
|
25
|
-
var TurnOrchestratorAddon = class extends _camstack_types.BaseAddon {
|
|
26
|
-
constructor() {
|
|
27
|
-
super({
|
|
28
|
-
enabledProviders: [],
|
|
29
|
-
enabledProvidersSeeded: false
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
async onInitialize() {
|
|
33
|
-
const provider = {
|
|
34
|
-
listProviders: async () => this.listProviders(),
|
|
35
|
-
getAllServers: async () => this.getAllServers(),
|
|
36
|
-
setProviderEnabled: async ({ addonId, enabled }) => {
|
|
37
|
-
await this.markEnabled(addonId, enabled);
|
|
38
|
-
return { success: true };
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
this.ctx.logger.info("TURN orchestrator initialized", { meta: {
|
|
42
|
-
enabledCount: this.config.enabledProviders.length,
|
|
43
|
-
seeded: this.config.enabledProvidersSeeded
|
|
44
|
-
} });
|
|
45
|
-
return [{
|
|
46
|
-
capability: _camstack_types.turnOrchestratorCapability,
|
|
47
|
-
provider
|
|
48
|
-
}];
|
|
49
|
-
}
|
|
50
|
-
getEntries() {
|
|
51
|
-
return this.capabilities?.getCollectionEntries("turn-provider") ?? [];
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Operator-effective enabled set. Before the first toggle, default
|
|
55
|
-
* to "every registered provider is enabled" so a fresh install of a
|
|
56
|
-
* TURN addon participates without manual intervention. After the
|
|
57
|
-
* operator clicks anything, the persisted list is authoritative.
|
|
58
|
-
*/
|
|
59
|
-
effectivelyEnabled() {
|
|
60
|
-
if (this.config.enabledProvidersSeeded) return new Set(this.config.enabledProviders);
|
|
61
|
-
return new Set(this.getEntries().map(([id]) => id));
|
|
62
|
-
}
|
|
63
|
-
async markEnabled(addonId, enabled) {
|
|
64
|
-
const current = this.effectivelyEnabled();
|
|
65
|
-
const wasEnabled = current.has(addonId);
|
|
66
|
-
if (enabled) current.add(addonId);
|
|
67
|
-
else current.delete(addonId);
|
|
68
|
-
if (wasEnabled === enabled && this.config.enabledProvidersSeeded) return;
|
|
69
|
-
await this.updateGlobalSettings({
|
|
70
|
-
enabledProviders: [...current],
|
|
71
|
-
enabledProvidersSeeded: true
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
async listProviders() {
|
|
75
|
-
const enabled = this.effectivelyEnabled();
|
|
76
|
-
const out = [];
|
|
77
|
-
for (const [addonId, impl] of this.getEntries()) {
|
|
78
|
-
let serverCount = 0;
|
|
79
|
-
let urls = [];
|
|
80
|
-
let error;
|
|
81
|
-
const isEnabled = enabled.has(addonId);
|
|
82
|
-
if (isEnabled && impl.getTurnServers) try {
|
|
83
|
-
const servers = await impl.getTurnServers();
|
|
84
|
-
serverCount = servers.length;
|
|
85
|
-
const flat = [];
|
|
86
|
-
for (const s of servers) if (Array.isArray(s.urls)) flat.push(...s.urls);
|
|
87
|
-
else if (typeof s.urls === "string") flat.push(s.urls);
|
|
88
|
-
urls = flat;
|
|
89
|
-
} catch (err) {
|
|
90
|
-
error = err instanceof Error ? err.message : String(err);
|
|
91
|
-
}
|
|
92
|
-
out.push({
|
|
93
|
-
addonId,
|
|
94
|
-
displayName: impl.displayName ?? addonId,
|
|
95
|
-
enabled: isEnabled,
|
|
96
|
-
serverCount,
|
|
97
|
-
urls,
|
|
98
|
-
...error !== void 0 ? { error } : {}
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
return out;
|
|
102
|
-
}
|
|
103
|
-
async getAllServers() {
|
|
104
|
-
const enabled = this.effectivelyEnabled();
|
|
105
|
-
const out = [];
|
|
106
|
-
for (const [addonId, impl] of this.getEntries()) {
|
|
107
|
-
if (!enabled.has(addonId)) continue;
|
|
108
|
-
if (!impl.getTurnServers) continue;
|
|
109
|
-
try {
|
|
110
|
-
const servers = await impl.getTurnServers();
|
|
111
|
-
out.push(...servers);
|
|
112
|
-
} catch (err) {
|
|
113
|
-
this.ctx.logger.warn("TURN provider failed to enumerate servers", { meta: {
|
|
114
|
-
addonId,
|
|
115
|
-
error: err instanceof Error ? err.message : String(err)
|
|
116
|
-
} });
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
return out;
|
|
120
|
-
}
|
|
121
|
-
};
|
|
122
|
-
//#endregion
|
|
123
|
-
exports.TurnOrchestratorAddon = TurnOrchestratorAddon;
|
|
124
|
-
exports.default = TurnOrchestratorAddon;
|
|
125
|
-
|
|
126
|
-
//# sourceMappingURL=turn-orchestrator.addon.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"turn-orchestrator.addon.js","names":[],"sources":["../../../src/builtins/turn-orchestrator/turn-orchestrator.addon.ts"],"sourcesContent":["/**\n * TURN orchestrator — singleton facade over the `turn-provider`\n * collection (Cloudflare TURN, coturn, Twilio, …). Mirrors the\n * remote-access-orchestrator persistence + autostart contract:\n * - `enabledProviders: string[]` in addon-store is the operator's\n * intent. Boot reads it back; the Enable/Disable toggle in the\n * admin UI writes it.\n * - `getAllServers()` (consumed by the WebRTC layer) aggregates ICE\n * servers ONLY from enabled providers.\n * - `listProviders()` surfaces the persisted `enabled` flag so the\n * UI can render the correct toggle state on first paint.\n *\n * Provides:\n * - listProviders() — admin UI inventory\n * - getAllServers() — combined ICE server list across enabled providers\n * - setProviderEnabled() — toggle a provider on/off (persisted)\n */\nimport {\n BaseAddon,\n turnOrchestratorCapability,\n type ITurnOrchestratorProvider,\n type TurnProviderInfo,\n type ProviderRegistration,\n} from '@camstack/types'\n\ninterface TurnProviderLike {\n getTurnServers?: () => Promise<readonly { urls: string | string[]; username?: string; credential?: string }[]>\n readonly displayName?: string\n}\n\ninterface TurnOrchestratorConfig {\n /**\n * addonIds the operator has explicitly enabled. Persisted in the\n * addon-store; first-launch defaults to \"every provider enabled\" so\n * a freshly-installed TURN addon participates immediately (the\n * operator can disable from the UI). See `effectivelyEnabled`.\n */\n readonly enabledProviders: readonly string[]\n /**\n * Sentinel: true after `enabledProviders` has been written at least\n * once. Distinguishes \"operator hasn't touched the toggles yet —\n * default-enable all\" from \"operator cleared the list — keep it\n * empty\". Same shape as local-network's bootSeeded.\n */\n readonly enabledProvidersSeeded: boolean\n}\n\nexport class TurnOrchestratorAddon extends BaseAddon<TurnOrchestratorConfig> {\n constructor() {\n super({ enabledProviders: [], enabledProvidersSeeded: false })\n }\n\n protected async onInitialize(): Promise<ProviderRegistration[]> {\n const provider: ITurnOrchestratorProvider = {\n listProviders: async () => this.listProviders(),\n getAllServers: async () => this.getAllServers(),\n setProviderEnabled: async ({ addonId, enabled }) => {\n await this.markEnabled(addonId, enabled)\n return { success: true as const }\n },\n }\n this.ctx.logger.info('TURN orchestrator initialized', {\n meta: {\n enabledCount: this.config.enabledProviders.length,\n seeded: this.config.enabledProvidersSeeded,\n },\n })\n return [{ capability: turnOrchestratorCapability, provider }]\n }\n\n private getEntries(): readonly (readonly [string, TurnProviderLike])[] {\n return this.capabilities?.getCollectionEntries<TurnProviderLike>('turn-provider') ?? []\n }\n\n /**\n * Operator-effective enabled set. Before the first toggle, default\n * to \"every registered provider is enabled\" so a fresh install of a\n * TURN addon participates without manual intervention. After the\n * operator clicks anything, the persisted list is authoritative.\n */\n private effectivelyEnabled(): Set<string> {\n if (this.config.enabledProvidersSeeded) {\n return new Set(this.config.enabledProviders)\n }\n return new Set(this.getEntries().map(([id]) => id))\n }\n\n private async markEnabled(addonId: string, enabled: boolean): Promise<void> {\n const current = this.effectivelyEnabled()\n const wasEnabled = current.has(addonId)\n if (enabled) current.add(addonId); else current.delete(addonId)\n // Always persist with seeded=true so the operator's choice locks in.\n if (wasEnabled === enabled && this.config.enabledProvidersSeeded) return\n await this.updateGlobalSettings({\n enabledProviders: [...current],\n enabledProvidersSeeded: true,\n })\n }\n\n private async listProviders(): Promise<readonly TurnProviderInfo[]> {\n const enabled = this.effectivelyEnabled()\n const out: TurnProviderInfo[] = []\n for (const [addonId, impl] of this.getEntries()) {\n let serverCount = 0\n let urls: readonly string[] = []\n let error: string | undefined\n const isEnabled = enabled.has(addonId)\n // Only fetch live server count for enabled providers — disabled\n // providers shouldn't be making outbound API calls just to render\n // an admin row.\n if (isEnabled && impl.getTurnServers) {\n try {\n const servers = await impl.getTurnServers()\n serverCount = servers.length\n // Flatten the urls field of every ICE-server entry into one\n // list — `{ urls: ['stun:a', 'stun:b'] }` becomes `['stun:a',\n // 'stun:b']`; `{ urls: 'turn:x' }` becomes `['turn:x']`. The\n // admin UI's compact per-provider chip list iterates this.\n const flat: string[] = []\n for (const s of servers) {\n if (Array.isArray(s.urls)) flat.push(...s.urls)\n else if (typeof s.urls === 'string') flat.push(s.urls)\n }\n urls = flat\n } catch (err) {\n error = err instanceof Error ? err.message : String(err)\n }\n }\n out.push({\n addonId,\n displayName: impl.displayName ?? addonId,\n enabled: isEnabled,\n serverCount,\n urls,\n ...(error !== undefined ? { error } : {}),\n })\n }\n return out\n }\n\n private async getAllServers(): Promise<readonly { urls: string | string[]; username?: string; credential?: string }[]> {\n const enabled = this.effectivelyEnabled()\n const out: { urls: string | string[]; username?: string; credential?: string }[] = []\n for (const [addonId, impl] of this.getEntries()) {\n if (!enabled.has(addonId)) continue\n if (!impl.getTurnServers) continue\n try {\n const servers = await impl.getTurnServers()\n out.push(...servers)\n } catch (err) {\n this.ctx.logger.warn('TURN provider failed to enumerate servers', {\n meta: { addonId, error: err instanceof Error ? err.message : String(err) },\n })\n }\n }\n return out\n }\n}\n\nexport default TurnOrchestratorAddon\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA+CA,IAAa,wBAAb,cAA2C,gBAAA,UAAkC;CAC3E,cAAc;EACZ,MAAM;GAAE,kBAAkB,EAAE;GAAE,wBAAwB;GAAO,CAAC;;CAGhE,MAAgB,eAAgD;EAC9D,MAAM,WAAsC;GAC1C,eAAe,YAAY,KAAK,eAAe;GAC/C,eAAe,YAAY,KAAK,eAAe;GAC/C,oBAAoB,OAAO,EAAE,SAAS,cAAc;IAClD,MAAM,KAAK,YAAY,SAAS,QAAQ;IACxC,OAAO,EAAE,SAAS,MAAe;;GAEpC;EACD,KAAK,IAAI,OAAO,KAAK,iCAAiC,EACpD,MAAM;GACJ,cAAc,KAAK,OAAO,iBAAiB;GAC3C,QAAQ,KAAK,OAAO;GACrB,EACF,CAAC;EACF,OAAO,CAAC;GAAE,YAAY,gBAAA;GAA4B;GAAU,CAAC;;CAG/D,aAAuE;EACrE,OAAO,KAAK,cAAc,qBAAuC,gBAAgB,IAAI,EAAE;;;;;;;;CASzF,qBAA0C;EACxC,IAAI,KAAK,OAAO,wBACd,OAAO,IAAI,IAAI,KAAK,OAAO,iBAAiB;EAE9C,OAAO,IAAI,IAAI,KAAK,YAAY,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC;;CAGrD,MAAc,YAAY,SAAiB,SAAiC;EAC1E,MAAM,UAAU,KAAK,oBAAoB;EACzC,MAAM,aAAa,QAAQ,IAAI,QAAQ;EACvC,IAAI,SAAS,QAAQ,IAAI,QAAQ;OAAO,QAAQ,OAAO,QAAQ;EAE/D,IAAI,eAAe,WAAW,KAAK,OAAO,wBAAwB;EAClE,MAAM,KAAK,qBAAqB;GAC9B,kBAAkB,CAAC,GAAG,QAAQ;GAC9B,wBAAwB;GACzB,CAAC;;CAGJ,MAAc,gBAAsD;EAClE,MAAM,UAAU,KAAK,oBAAoB;EACzC,MAAM,MAA0B,EAAE;EAClC,KAAK,MAAM,CAAC,SAAS,SAAS,KAAK,YAAY,EAAE;GAC/C,IAAI,cAAc;GAClB,IAAI,OAA0B,EAAE;GAChC,IAAI;GACJ,MAAM,YAAY,QAAQ,IAAI,QAAQ;GAItC,IAAI,aAAa,KAAK,gBACpB,IAAI;IACF,MAAM,UAAU,MAAM,KAAK,gBAAgB;IAC3C,cAAc,QAAQ;IAKtB,MAAM,OAAiB,EAAE;IACzB,KAAK,MAAM,KAAK,SACd,IAAI,MAAM,QAAQ,EAAE,KAAK,EAAE,KAAK,KAAK,GAAG,EAAE,KAAK;SAC1C,IAAI,OAAO,EAAE,SAAS,UAAU,KAAK,KAAK,EAAE,KAAK;IAExD,OAAO;YACA,KAAK;IACZ,QAAQ,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;;GAG5D,IAAI,KAAK;IACP;IACA,aAAa,KAAK,eAAe;IACjC,SAAS;IACT;IACA;IACA,GAAI,UAAU,KAAA,IAAY,EAAE,OAAO,GAAG,EAAE;IACzC,CAAC;;EAEJ,OAAO;;CAGT,MAAc,gBAAyG;EACrH,MAAM,UAAU,KAAK,oBAAoB;EACzC,MAAM,MAA6E,EAAE;EACrF,KAAK,MAAM,CAAC,SAAS,SAAS,KAAK,YAAY,EAAE;GAC/C,IAAI,CAAC,QAAQ,IAAI,QAAQ,EAAE;GAC3B,IAAI,CAAC,KAAK,gBAAgB;GAC1B,IAAI;IACF,MAAM,UAAU,MAAM,KAAK,gBAAgB;IAC3C,IAAI,KAAK,GAAG,QAAQ;YACb,KAAK;IACZ,KAAK,IAAI,OAAO,KAAK,6CAA6C,EAChE,MAAM;KAAE;KAAS,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;KAAE,EAC3E,CAAC;;;EAGN,OAAO"}
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import { BaseAddon, turnOrchestratorCapability } from "@camstack/types";
|
|
2
|
-
//#region src/builtins/turn-orchestrator/turn-orchestrator.addon.ts
|
|
3
|
-
/**
|
|
4
|
-
* TURN orchestrator — singleton facade over the `turn-provider`
|
|
5
|
-
* collection (Cloudflare TURN, coturn, Twilio, …). Mirrors the
|
|
6
|
-
* remote-access-orchestrator persistence + autostart contract:
|
|
7
|
-
* - `enabledProviders: string[]` in addon-store is the operator's
|
|
8
|
-
* intent. Boot reads it back; the Enable/Disable toggle in the
|
|
9
|
-
* admin UI writes it.
|
|
10
|
-
* - `getAllServers()` (consumed by the WebRTC layer) aggregates ICE
|
|
11
|
-
* servers ONLY from enabled providers.
|
|
12
|
-
* - `listProviders()` surfaces the persisted `enabled` flag so the
|
|
13
|
-
* UI can render the correct toggle state on first paint.
|
|
14
|
-
*
|
|
15
|
-
* Provides:
|
|
16
|
-
* - listProviders() — admin UI inventory
|
|
17
|
-
* - getAllServers() — combined ICE server list across enabled providers
|
|
18
|
-
* - setProviderEnabled() — toggle a provider on/off (persisted)
|
|
19
|
-
*/
|
|
20
|
-
var TurnOrchestratorAddon = class extends BaseAddon {
|
|
21
|
-
constructor() {
|
|
22
|
-
super({
|
|
23
|
-
enabledProviders: [],
|
|
24
|
-
enabledProvidersSeeded: false
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
async onInitialize() {
|
|
28
|
-
const provider = {
|
|
29
|
-
listProviders: async () => this.listProviders(),
|
|
30
|
-
getAllServers: async () => this.getAllServers(),
|
|
31
|
-
setProviderEnabled: async ({ addonId, enabled }) => {
|
|
32
|
-
await this.markEnabled(addonId, enabled);
|
|
33
|
-
return { success: true };
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
this.ctx.logger.info("TURN orchestrator initialized", { meta: {
|
|
37
|
-
enabledCount: this.config.enabledProviders.length,
|
|
38
|
-
seeded: this.config.enabledProvidersSeeded
|
|
39
|
-
} });
|
|
40
|
-
return [{
|
|
41
|
-
capability: turnOrchestratorCapability,
|
|
42
|
-
provider
|
|
43
|
-
}];
|
|
44
|
-
}
|
|
45
|
-
getEntries() {
|
|
46
|
-
return this.capabilities?.getCollectionEntries("turn-provider") ?? [];
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Operator-effective enabled set. Before the first toggle, default
|
|
50
|
-
* to "every registered provider is enabled" so a fresh install of a
|
|
51
|
-
* TURN addon participates without manual intervention. After the
|
|
52
|
-
* operator clicks anything, the persisted list is authoritative.
|
|
53
|
-
*/
|
|
54
|
-
effectivelyEnabled() {
|
|
55
|
-
if (this.config.enabledProvidersSeeded) return new Set(this.config.enabledProviders);
|
|
56
|
-
return new Set(this.getEntries().map(([id]) => id));
|
|
57
|
-
}
|
|
58
|
-
async markEnabled(addonId, enabled) {
|
|
59
|
-
const current = this.effectivelyEnabled();
|
|
60
|
-
const wasEnabled = current.has(addonId);
|
|
61
|
-
if (enabled) current.add(addonId);
|
|
62
|
-
else current.delete(addonId);
|
|
63
|
-
if (wasEnabled === enabled && this.config.enabledProvidersSeeded) return;
|
|
64
|
-
await this.updateGlobalSettings({
|
|
65
|
-
enabledProviders: [...current],
|
|
66
|
-
enabledProvidersSeeded: true
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
async listProviders() {
|
|
70
|
-
const enabled = this.effectivelyEnabled();
|
|
71
|
-
const out = [];
|
|
72
|
-
for (const [addonId, impl] of this.getEntries()) {
|
|
73
|
-
let serverCount = 0;
|
|
74
|
-
let urls = [];
|
|
75
|
-
let error;
|
|
76
|
-
const isEnabled = enabled.has(addonId);
|
|
77
|
-
if (isEnabled && impl.getTurnServers) try {
|
|
78
|
-
const servers = await impl.getTurnServers();
|
|
79
|
-
serverCount = servers.length;
|
|
80
|
-
const flat = [];
|
|
81
|
-
for (const s of servers) if (Array.isArray(s.urls)) flat.push(...s.urls);
|
|
82
|
-
else if (typeof s.urls === "string") flat.push(s.urls);
|
|
83
|
-
urls = flat;
|
|
84
|
-
} catch (err) {
|
|
85
|
-
error = err instanceof Error ? err.message : String(err);
|
|
86
|
-
}
|
|
87
|
-
out.push({
|
|
88
|
-
addonId,
|
|
89
|
-
displayName: impl.displayName ?? addonId,
|
|
90
|
-
enabled: isEnabled,
|
|
91
|
-
serverCount,
|
|
92
|
-
urls,
|
|
93
|
-
...error !== void 0 ? { error } : {}
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
return out;
|
|
97
|
-
}
|
|
98
|
-
async getAllServers() {
|
|
99
|
-
const enabled = this.effectivelyEnabled();
|
|
100
|
-
const out = [];
|
|
101
|
-
for (const [addonId, impl] of this.getEntries()) {
|
|
102
|
-
if (!enabled.has(addonId)) continue;
|
|
103
|
-
if (!impl.getTurnServers) continue;
|
|
104
|
-
try {
|
|
105
|
-
const servers = await impl.getTurnServers();
|
|
106
|
-
out.push(...servers);
|
|
107
|
-
} catch (err) {
|
|
108
|
-
this.ctx.logger.warn("TURN provider failed to enumerate servers", { meta: {
|
|
109
|
-
addonId,
|
|
110
|
-
error: err instanceof Error ? err.message : String(err)
|
|
111
|
-
} });
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
return out;
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
//#endregion
|
|
118
|
-
export { TurnOrchestratorAddon, TurnOrchestratorAddon as default };
|
|
119
|
-
|
|
120
|
-
//# sourceMappingURL=turn-orchestrator.addon.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"turn-orchestrator.addon.mjs","names":[],"sources":["../../../src/builtins/turn-orchestrator/turn-orchestrator.addon.ts"],"sourcesContent":["/**\n * TURN orchestrator — singleton facade over the `turn-provider`\n * collection (Cloudflare TURN, coturn, Twilio, …). Mirrors the\n * remote-access-orchestrator persistence + autostart contract:\n * - `enabledProviders: string[]` in addon-store is the operator's\n * intent. Boot reads it back; the Enable/Disable toggle in the\n * admin UI writes it.\n * - `getAllServers()` (consumed by the WebRTC layer) aggregates ICE\n * servers ONLY from enabled providers.\n * - `listProviders()` surfaces the persisted `enabled` flag so the\n * UI can render the correct toggle state on first paint.\n *\n * Provides:\n * - listProviders() — admin UI inventory\n * - getAllServers() — combined ICE server list across enabled providers\n * - setProviderEnabled() — toggle a provider on/off (persisted)\n */\nimport {\n BaseAddon,\n turnOrchestratorCapability,\n type ITurnOrchestratorProvider,\n type TurnProviderInfo,\n type ProviderRegistration,\n} from '@camstack/types'\n\ninterface TurnProviderLike {\n getTurnServers?: () => Promise<readonly { urls: string | string[]; username?: string; credential?: string }[]>\n readonly displayName?: string\n}\n\ninterface TurnOrchestratorConfig {\n /**\n * addonIds the operator has explicitly enabled. Persisted in the\n * addon-store; first-launch defaults to \"every provider enabled\" so\n * a freshly-installed TURN addon participates immediately (the\n * operator can disable from the UI). See `effectivelyEnabled`.\n */\n readonly enabledProviders: readonly string[]\n /**\n * Sentinel: true after `enabledProviders` has been written at least\n * once. Distinguishes \"operator hasn't touched the toggles yet —\n * default-enable all\" from \"operator cleared the list — keep it\n * empty\". Same shape as local-network's bootSeeded.\n */\n readonly enabledProvidersSeeded: boolean\n}\n\nexport class TurnOrchestratorAddon extends BaseAddon<TurnOrchestratorConfig> {\n constructor() {\n super({ enabledProviders: [], enabledProvidersSeeded: false })\n }\n\n protected async onInitialize(): Promise<ProviderRegistration[]> {\n const provider: ITurnOrchestratorProvider = {\n listProviders: async () => this.listProviders(),\n getAllServers: async () => this.getAllServers(),\n setProviderEnabled: async ({ addonId, enabled }) => {\n await this.markEnabled(addonId, enabled)\n return { success: true as const }\n },\n }\n this.ctx.logger.info('TURN orchestrator initialized', {\n meta: {\n enabledCount: this.config.enabledProviders.length,\n seeded: this.config.enabledProvidersSeeded,\n },\n })\n return [{ capability: turnOrchestratorCapability, provider }]\n }\n\n private getEntries(): readonly (readonly [string, TurnProviderLike])[] {\n return this.capabilities?.getCollectionEntries<TurnProviderLike>('turn-provider') ?? []\n }\n\n /**\n * Operator-effective enabled set. Before the first toggle, default\n * to \"every registered provider is enabled\" so a fresh install of a\n * TURN addon participates without manual intervention. After the\n * operator clicks anything, the persisted list is authoritative.\n */\n private effectivelyEnabled(): Set<string> {\n if (this.config.enabledProvidersSeeded) {\n return new Set(this.config.enabledProviders)\n }\n return new Set(this.getEntries().map(([id]) => id))\n }\n\n private async markEnabled(addonId: string, enabled: boolean): Promise<void> {\n const current = this.effectivelyEnabled()\n const wasEnabled = current.has(addonId)\n if (enabled) current.add(addonId); else current.delete(addonId)\n // Always persist with seeded=true so the operator's choice locks in.\n if (wasEnabled === enabled && this.config.enabledProvidersSeeded) return\n await this.updateGlobalSettings({\n enabledProviders: [...current],\n enabledProvidersSeeded: true,\n })\n }\n\n private async listProviders(): Promise<readonly TurnProviderInfo[]> {\n const enabled = this.effectivelyEnabled()\n const out: TurnProviderInfo[] = []\n for (const [addonId, impl] of this.getEntries()) {\n let serverCount = 0\n let urls: readonly string[] = []\n let error: string | undefined\n const isEnabled = enabled.has(addonId)\n // Only fetch live server count for enabled providers — disabled\n // providers shouldn't be making outbound API calls just to render\n // an admin row.\n if (isEnabled && impl.getTurnServers) {\n try {\n const servers = await impl.getTurnServers()\n serverCount = servers.length\n // Flatten the urls field of every ICE-server entry into one\n // list — `{ urls: ['stun:a', 'stun:b'] }` becomes `['stun:a',\n // 'stun:b']`; `{ urls: 'turn:x' }` becomes `['turn:x']`. The\n // admin UI's compact per-provider chip list iterates this.\n const flat: string[] = []\n for (const s of servers) {\n if (Array.isArray(s.urls)) flat.push(...s.urls)\n else if (typeof s.urls === 'string') flat.push(s.urls)\n }\n urls = flat\n } catch (err) {\n error = err instanceof Error ? err.message : String(err)\n }\n }\n out.push({\n addonId,\n displayName: impl.displayName ?? addonId,\n enabled: isEnabled,\n serverCount,\n urls,\n ...(error !== undefined ? { error } : {}),\n })\n }\n return out\n }\n\n private async getAllServers(): Promise<readonly { urls: string | string[]; username?: string; credential?: string }[]> {\n const enabled = this.effectivelyEnabled()\n const out: { urls: string | string[]; username?: string; credential?: string }[] = []\n for (const [addonId, impl] of this.getEntries()) {\n if (!enabled.has(addonId)) continue\n if (!impl.getTurnServers) continue\n try {\n const servers = await impl.getTurnServers()\n out.push(...servers)\n } catch (err) {\n this.ctx.logger.warn('TURN provider failed to enumerate servers', {\n meta: { addonId, error: err instanceof Error ? err.message : String(err) },\n })\n }\n }\n return out\n }\n}\n\nexport default TurnOrchestratorAddon\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA+CA,IAAa,wBAAb,cAA2C,UAAkC;CAC3E,cAAc;EACZ,MAAM;GAAE,kBAAkB,EAAE;GAAE,wBAAwB;GAAO,CAAC;;CAGhE,MAAgB,eAAgD;EAC9D,MAAM,WAAsC;GAC1C,eAAe,YAAY,KAAK,eAAe;GAC/C,eAAe,YAAY,KAAK,eAAe;GAC/C,oBAAoB,OAAO,EAAE,SAAS,cAAc;IAClD,MAAM,KAAK,YAAY,SAAS,QAAQ;IACxC,OAAO,EAAE,SAAS,MAAe;;GAEpC;EACD,KAAK,IAAI,OAAO,KAAK,iCAAiC,EACpD,MAAM;GACJ,cAAc,KAAK,OAAO,iBAAiB;GAC3C,QAAQ,KAAK,OAAO;GACrB,EACF,CAAC;EACF,OAAO,CAAC;GAAE,YAAY;GAA4B;GAAU,CAAC;;CAG/D,aAAuE;EACrE,OAAO,KAAK,cAAc,qBAAuC,gBAAgB,IAAI,EAAE;;;;;;;;CASzF,qBAA0C;EACxC,IAAI,KAAK,OAAO,wBACd,OAAO,IAAI,IAAI,KAAK,OAAO,iBAAiB;EAE9C,OAAO,IAAI,IAAI,KAAK,YAAY,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC;;CAGrD,MAAc,YAAY,SAAiB,SAAiC;EAC1E,MAAM,UAAU,KAAK,oBAAoB;EACzC,MAAM,aAAa,QAAQ,IAAI,QAAQ;EACvC,IAAI,SAAS,QAAQ,IAAI,QAAQ;OAAO,QAAQ,OAAO,QAAQ;EAE/D,IAAI,eAAe,WAAW,KAAK,OAAO,wBAAwB;EAClE,MAAM,KAAK,qBAAqB;GAC9B,kBAAkB,CAAC,GAAG,QAAQ;GAC9B,wBAAwB;GACzB,CAAC;;CAGJ,MAAc,gBAAsD;EAClE,MAAM,UAAU,KAAK,oBAAoB;EACzC,MAAM,MAA0B,EAAE;EAClC,KAAK,MAAM,CAAC,SAAS,SAAS,KAAK,YAAY,EAAE;GAC/C,IAAI,cAAc;GAClB,IAAI,OAA0B,EAAE;GAChC,IAAI;GACJ,MAAM,YAAY,QAAQ,IAAI,QAAQ;GAItC,IAAI,aAAa,KAAK,gBACpB,IAAI;IACF,MAAM,UAAU,MAAM,KAAK,gBAAgB;IAC3C,cAAc,QAAQ;IAKtB,MAAM,OAAiB,EAAE;IACzB,KAAK,MAAM,KAAK,SACd,IAAI,MAAM,QAAQ,EAAE,KAAK,EAAE,KAAK,KAAK,GAAG,EAAE,KAAK;SAC1C,IAAI,OAAO,EAAE,SAAS,UAAU,KAAK,KAAK,EAAE,KAAK;IAExD,OAAO;YACA,KAAK;IACZ,QAAQ,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;;GAG5D,IAAI,KAAK;IACP;IACA,aAAa,KAAK,eAAe;IACjC,SAAS;IACT;IACA;IACA,GAAI,UAAU,KAAA,IAAY,EAAE,OAAO,GAAG,EAAE;IACzC,CAAC;;EAEJ,OAAO;;CAGT,MAAc,gBAAyG;EACrH,MAAM,UAAU,KAAK,oBAAoB;EACzC,MAAM,MAA6E,EAAE;EACrF,KAAK,MAAM,CAAC,SAAS,SAAS,KAAK,YAAY,EAAE;GAC/C,IAAI,CAAC,QAAQ,IAAI,QAAQ,EAAE;GAC3B,IAAI,CAAC,KAAK,gBAAgB;GAC1B,IAAI;IACF,MAAM,UAAU,MAAM,KAAK,gBAAgB;IAC3C,IAAI,KAAK,GAAG,QAAQ;YACb,KAAK;IACZ,KAAK,IAAI,OAAO,KAAK,6CAA6C,EAChE,MAAM;KAAE;KAAS,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;KAAE,EAC3E,CAAC;;;EAGN,OAAO"}
|