@abstractframework/continuum 0.3.0 → 0.3.1

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 (67) hide show
  1. package/README.md +38 -19
  2. package/bin/cli.js +157 -32
  3. package/bin/hub_proxy.js +37 -17
  4. package/bin/settings.js +511 -0
  5. package/dist/assets/{abnfDiagram-VRR7QNED-CS1wi4Y3.js → abnfDiagram-VRR7QNED-DkP5u0Ku.js} +2 -2
  6. package/dist/assets/{arc-DYoB4bu2.js → arc-vxPq5BjA.js} +2 -2
  7. package/dist/assets/{architectureDiagram-ZJ3FMSHR-DoNVXIHa.js → architectureDiagram-ZJ3FMSHR-ku0NT7zM.js} +2 -2
  8. package/dist/assets/{blockDiagram-677ZJIJ3-CeP5oeQE.js → blockDiagram-677ZJIJ3-DXQQcNdo.js} +2 -2
  9. package/dist/assets/{c4Diagram-LMCZKHZV-BEGwHMwG.js → c4Diagram-LMCZKHZV-DuZ33cED.js} +2 -2
  10. package/dist/assets/channel-tvH0KUyT.js +2 -0
  11. package/dist/assets/{chunk-2Q5K7J3B-jW9ElN5d.js → chunk-2Q5K7J3B-BGWsS7uu.js} +2 -2
  12. package/dist/assets/{chunk-32BRIVSS-BS6et1PP.js → chunk-32BRIVSS-BgokockY.js} +2 -2
  13. package/dist/assets/{chunk-5VM5RSS4-DQ9hLs-B.js → chunk-5VM5RSS4-OLY5jTMg.js} +2 -2
  14. package/dist/assets/{chunk-EX3LRPZG-Wp68VufQ.js → chunk-EX3LRPZG-BWHQVZSz.js} +2 -2
  15. package/dist/assets/{chunk-JWPE2WC7-DYSRWrFH.js → chunk-JWPE2WC7-CuM7Hcrw.js} +2 -2
  16. package/dist/assets/{chunk-MOJQB5TN-8cwmjmPr.js → chunk-MOJQB5TN-DI56DwNK.js} +2 -2
  17. package/dist/assets/{chunk-RYQCIY6F--F4n2CLl.js → chunk-RYQCIY6F-phvbPmeC.js} +2 -2
  18. package/dist/assets/{chunk-V7JOEXUC-vx1HHblG.js → chunk-V7JOEXUC-Cv7eW1t4.js} +2 -2
  19. package/dist/assets/{chunk-VR4S4FIN-BWDfVdfu.js → chunk-VR4S4FIN-D8k2SzA3.js} +2 -2
  20. package/dist/assets/{chunk-XXDRQBXY-tmf9giTR.js → chunk-XXDRQBXY-DZy8Plz8.js} +2 -2
  21. package/dist/assets/classDiagram-OUVF2IWQ-C0x6Ou39.js +2 -0
  22. package/dist/assets/classDiagram-v2-EOCWNBFH-C0x6Ou39.js +2 -0
  23. package/dist/assets/{cose-bilkent-JH36ORCC-D4pA4Uis.js → cose-bilkent-JH36ORCC-CiwWaVUb.js} +2 -2
  24. package/dist/assets/{cynefin-VYW2F7L2-fqThC73D.js → cynefin-VYW2F7L2-Cz79Fwdx.js} +2 -2
  25. package/dist/assets/{cynefinDiagram-TSTJHNR4-xKZSOndK.js → cynefinDiagram-TSTJHNR4-DYlkii-x.js} +2 -2
  26. package/dist/assets/{dagre-VKFMJZFB-DckpxAkb.js → dagre-VKFMJZFB-Cumo7o1R.js} +2 -2
  27. package/dist/assets/{diagram-FQU43EPY-GJNsMViq.js → diagram-FQU43EPY-Dorm69_e.js} +2 -2
  28. package/dist/assets/{diagram-G47NLZAW-BAx3mWlA.js → diagram-G47NLZAW-Bhtzc4JU.js} +2 -2
  29. package/dist/assets/{diagram-NH7WQ7WH-BvAd2Vow.js → diagram-NH7WQ7WH-DJF-iHCK.js} +2 -2
  30. package/dist/assets/{diagram-OA4YK3LP-DxDd3CWT.js → diagram-OA4YK3LP-8mQ4915-.js} +2 -2
  31. package/dist/assets/{diagram-WEI45ONY-C3s99ME6.js → diagram-WEI45ONY-C4Bv6dbm.js} +2 -2
  32. package/dist/assets/{ebnfDiagram-CCIWWBDH-DwY_zzL5.js → ebnfDiagram-CCIWWBDH-DzagnQVX.js} +2 -2
  33. package/dist/assets/{erDiagram-Q63AITRT-ByyDRAIk.js → erDiagram-Q63AITRT-BbkYElA6.js} +2 -2
  34. package/dist/assets/{flowDiagram-23GEKE2U-nzwsYkxG.js → flowDiagram-23GEKE2U-OcR4vkjk.js} +2 -2
  35. package/dist/assets/{ganttDiagram-NO4QXBWP-xjthVT1C.js → ganttDiagram-NO4QXBWP-DyAPiIdB.js} +2 -2
  36. package/dist/assets/{gitGraphDiagram-IHSO6WYX-BhwlJJX_.js → gitGraphDiagram-IHSO6WYX-pymEefZi.js} +2 -2
  37. package/dist/assets/{index-B90p5t5R.js → index-DTn9k-3t.js} +48 -48
  38. package/dist/assets/{infoDiagram-FWYZ7A6U-lgB-aUlU.js → infoDiagram-FWYZ7A6U-Dh41Som-.js} +2 -2
  39. package/dist/assets/{ishikawaDiagram-FXEZZL3T--cMGxagK.js → ishikawaDiagram-FXEZZL3T-Xc9vuvPV.js} +2 -2
  40. package/dist/assets/{journeyDiagram-5HDEW3XC-ZGXAX-J5.js → journeyDiagram-5HDEW3XC-bJ0gK8bC.js} +2 -2
  41. package/dist/assets/{kanban-definition-HUTT4EX6-Y4tnA7YW.js → kanban-definition-HUTT4EX6-Cu1Zn3KW.js} +2 -2
  42. package/dist/assets/{linear-DNPBmvUz.js → linear-DrGsraGo.js} +2 -2
  43. package/dist/assets/{mermaid.core-WQuHCSR5.js → mermaid.core-CkQqPHPZ.js} +5 -5
  44. package/dist/assets/{mindmap-definition-LN4V7U3C-BqOKjeA8.js → mindmap-definition-LN4V7U3C-ZCEP6XWH.js} +2 -2
  45. package/dist/assets/{pegDiagram-2B236MQR-DoKnv3Ez.js → pegDiagram-2B236MQR-DjDrn07n.js} +2 -2
  46. package/dist/assets/{pieDiagram-ENE6RG2P-CK7u0YoT.js → pieDiagram-ENE6RG2P-oD3ciEy7.js} +2 -2
  47. package/dist/assets/{quadrantDiagram-ABIIQ3AL-pZ2BrTn4.js → quadrantDiagram-ABIIQ3AL-CYbDYNM7.js} +2 -2
  48. package/dist/assets/{railroadDiagram-RFXS5EU6-B8uTEagG.js → railroadDiagram-RFXS5EU6-DMcO7O0d.js} +2 -2
  49. package/dist/assets/{requirementDiagram-TGXJPOKE-vkNASsjm.js → requirementDiagram-TGXJPOKE-DeeSIVn-.js} +2 -2
  50. package/dist/assets/{sankeyDiagram-HTMAVEWB-Bhql_cld.js → sankeyDiagram-HTMAVEWB-C43xzNvP.js} +2 -2
  51. package/dist/assets/{sequenceDiagram-DBY2YBRQ-CHd_hwoo.js → sequenceDiagram-DBY2YBRQ-d3lj6z8y.js} +2 -2
  52. package/dist/assets/{sizeCapture-X5ZJPWSS-DP6WJWOP.js → sizeCapture-X5ZJPWSS-D4UyeLsX.js} +2 -2
  53. package/dist/assets/{stateDiagram-2N3HPSRC-DJtFU8bY.js → stateDiagram-2N3HPSRC-Cq4YMMP1.js} +2 -2
  54. package/dist/assets/stateDiagram-v2-6OUMAXLB-DMVYrQgX.js +2 -0
  55. package/dist/assets/{swimlanes-5IMT3BWC-6-t4XS8A.js → swimlanes-5IMT3BWC-CRbkVLoI.js} +3 -3
  56. package/dist/assets/swimlanesDiagram-G3AALYLV-Bzg2g7oq.js +9 -0
  57. package/dist/assets/{timeline-definition-FHXFAJF6-8natOnn8.js → timeline-definition-FHXFAJF6-BN8oLdvs.js} +2 -2
  58. package/dist/assets/{vennDiagram-L72KCM5P-BgwY6aTt.js → vennDiagram-L72KCM5P-BqAHS4HE.js} +2 -2
  59. package/dist/assets/{wardleyDiagram-EHGQE667-BRA-hXqX.js → wardleyDiagram-EHGQE667-D2aA14yL.js} +2 -2
  60. package/dist/assets/{xychartDiagram-FW5EYKEG-Bps4vnDY.js → xychartDiagram-FW5EYKEG-BkrnnKWS.js} +2 -2
  61. package/dist/index.html +1 -1
  62. package/package.json +2 -2
  63. package/dist/assets/channel-CGvEfjJ_.js +0 -2
  64. package/dist/assets/classDiagram-OUVF2IWQ-Bs-9E6z7.js +0 -2
  65. package/dist/assets/classDiagram-v2-EOCWNBFH-Bs-9E6z7.js +0 -2
  66. package/dist/assets/stateDiagram-v2-6OUMAXLB-DmsSVvZs.js +0 -2
  67. package/dist/assets/swimlanesDiagram-G3AALYLV-DVV8zrk-.js +0 -9
@@ -0,0 +1,511 @@
1
+ /**
2
+ * Continuum server settings: one registry, one precedence rule.
3
+ *
4
+ * Every setting an operator may need is reachable three ways, and exactly
5
+ * one function decides which wins (operator rule 2026-09-25: settings and
6
+ * --flags, not environment variables):
7
+ *
8
+ * launch flag > settings file > environment (legacy) > default
9
+ *
10
+ * - Launch flags: `abstractcontinuum --hub-seat <seat>` (one run).
11
+ * - Settings file: `~/.abstractcontinuum/settings.json`, written by
12
+ * `abstractcontinuum config set <key> <value>` and by the Settings page
13
+ * (hub seat). Owner-only permissions: it may hold the hub token.
14
+ * - Environment: read only as a legacy fallback and reported as such; no
15
+ * help text or UI instructs it.
16
+ *
17
+ * Consumers: bin/cli.js (the server and `config`), vite.config.ts (dev
18
+ * server), bin/hub_proxy.js (through getters the server hands it) and the
19
+ * /api/continuum/settings route below (the Settings page).
20
+ */
21
+
22
+ import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, statSync, writeFileSync } from 'fs';
23
+ import { homedir } from 'os';
24
+ import { dirname, join } from 'path';
25
+
26
+ const TRUE_VALUES = new Set(['1', 'true', 'yes', 'y', 'on']);
27
+ const FALSE_VALUES = new Set(['0', 'false', 'no', 'n', 'off']);
28
+
29
+ /** The registry. `key` is the settings-file key, `flag` the launch flag,
30
+ * `env` the legacy fallback names (first non-empty wins). */
31
+ export const SETTINGS = [
32
+ {
33
+ key: 'port',
34
+ flag: '--port',
35
+ type: 'port',
36
+ default: 3002,
37
+ env: ['PORT'],
38
+ metavar: '<n>',
39
+ help: 'HTTP port',
40
+ },
41
+ {
42
+ key: 'host',
43
+ flag: '--host',
44
+ type: 'string',
45
+ default: '127.0.0.1',
46
+ env: ['HOST'],
47
+ metavar: '<address>',
48
+ help: 'bind address (wider only behind access control)',
49
+ },
50
+ {
51
+ key: 'gateway_url',
52
+ flag: '--gateway-url',
53
+ type: 'url',
54
+ default: 'http://127.0.0.1:8080',
55
+ env: ['ABSTRACTCONTINUUM_GATEWAY_URL', 'ABSTRACTGATEWAY_URL'],
56
+ metavar: '<url>',
57
+ help: 'gateway this deployment talks to',
58
+ },
59
+ {
60
+ key: 'hub_url',
61
+ flag: '--hub-url',
62
+ type: 'url',
63
+ default: 'http://127.0.0.1:8765',
64
+ env: ['ABSTRACTCONTINUUM_HUB_URL', 'AGORA_HUB_URL'],
65
+ metavar: '<url>',
66
+ help: 'agora hub for the Team page',
67
+ },
68
+ {
69
+ key: 'hub_seat',
70
+ flag: '--hub-seat',
71
+ type: 'seat',
72
+ default: 'operator',
73
+ env: ['ABSTRACTCONTINUUM_HUB_SEAT'],
74
+ metavar: '<seat>',
75
+ help: 'your hub seat: the Team page reads and posts as it',
76
+ },
77
+ {
78
+ key: 'hub_token',
79
+ flag: '--hub-token',
80
+ type: 'string',
81
+ default: '',
82
+ env: ['ABSTRACTCONTINUUM_HUB_KEY'],
83
+ secret: true,
84
+ metavar: '<token>',
85
+ help: 'hub API key for the seat; overrides the key store',
86
+ },
87
+ {
88
+ key: 'hub_keys',
89
+ flag: '--hub-keys',
90
+ type: 'string',
91
+ default: '~/.agora/keys.json',
92
+ env: ['ABSTRACTCONTINUUM_HUB_KEYS'],
93
+ metavar: '<path>',
94
+ help: 'hub key store (entry "<hub_url>::<seat>")',
95
+ },
96
+ {
97
+ key: 'hub_allow_remote',
98
+ flag: '--hub-allow-remote',
99
+ type: 'bool',
100
+ default: false,
101
+ env: ['ABSTRACTCONTINUUM_HUB_ALLOW_REMOTE'],
102
+ help: 'let other machines use the hub proxy',
103
+ },
104
+ {
105
+ key: 'allow_remote_gateway_config',
106
+ flag: '--allow-remote-gateway-config',
107
+ type: 'bool',
108
+ default: false,
109
+ env: ['ABSTRACTCONTINUUM_ALLOW_REMOTE_BROWSER_GATEWAY_CONFIG', 'ABSTRACTGATEWAY_ALLOW_REMOTE_BROWSER_GATEWAY_CONFIG'],
110
+ help: 'let other machines change the gateway URL at sign-in',
111
+ gate: true,
112
+ },
113
+ {
114
+ key: 'allow_gateway_url_cookie',
115
+ flag: '--allow-gateway-url-cookie',
116
+ type: 'bool',
117
+ default: false,
118
+ env: ['ABSTRACTCONTINUUM_ALLOW_BROWSER_GATEWAY_URL_COOKIE'],
119
+ help: 'honor a browser gateway-URL cookie off loopback',
120
+ gate: true,
121
+ },
122
+ {
123
+ key: 'trust_proxy_headers',
124
+ flag: '--trust-proxy-headers',
125
+ type: 'bool',
126
+ default: false,
127
+ env: ['ABSTRACTCONTINUUM_TRUST_PROXY_HEADERS', 'ABSTRACTGATEWAY_TRUST_PROXY_HEADERS'],
128
+ help: 'trust x-forwarded-host (behind your own proxy only)',
129
+ gate: true,
130
+ },
131
+ ];
132
+
133
+ /** Settings the Continuum Settings page may change through the server. */
134
+ export const UI_WRITABLE_KEYS = ['hub_seat'];
135
+
136
+ const BY_KEY = new Map(SETTINGS.map((s) => [s.key, s]));
137
+ const BY_FLAG = new Map(SETTINGS.map((s) => [s.flag, s]));
138
+
139
+ export function setting_spec(key) {
140
+ return BY_KEY.get(key) || null;
141
+ }
142
+
143
+ export function default_settings_path() {
144
+ return join(homedir(), '.abstractcontinuum', 'settings.json');
145
+ }
146
+
147
+ /** `~/…` → absolute (the key store default and user-typed paths). */
148
+ export function expand_home(p) {
149
+ const s = String(p || '');
150
+ if (s === '~') return homedir();
151
+ if (s.startsWith('~/')) return join(homedir(), s.slice(2));
152
+ return s;
153
+ }
154
+
155
+ /**
156
+ * Parse one raw value for a setting. Returns the typed value; throws an
157
+ * Error naming the setting on invalid input (the CLI and the route both
158
+ * report it verbatim).
159
+ */
160
+ export function coerce(spec, raw) {
161
+ const name = spec.key;
162
+ if (spec.type === 'bool') {
163
+ if (typeof raw === 'boolean') return raw;
164
+ const s = String(raw ?? '').trim().toLowerCase();
165
+ if (TRUE_VALUES.has(s)) return true;
166
+ if (FALSE_VALUES.has(s)) return false;
167
+ throw new Error(`${name}: expected on/off (got "${raw}")`);
168
+ }
169
+ if (spec.type === 'port') {
170
+ const s = String(raw ?? '').trim();
171
+ const n = Number(s);
172
+ if (!/^\d+$/.test(s) || !Number.isInteger(n) || n < 1 || n > 65535) throw new Error(`${name}: expected a port number 1-65535 (got "${raw}")`);
173
+ return n;
174
+ }
175
+ const s = String(raw ?? '').trim();
176
+ if (spec.type === 'url') {
177
+ const v = s.replace(/^['"]|['"]$/g, '').replace(/\/+$/, '');
178
+ let u;
179
+ try {
180
+ u = new URL(v);
181
+ } catch {
182
+ throw new Error(`${name}: expected an http(s) URL (got "${raw}")`);
183
+ }
184
+ if (u.protocol !== 'http:' && u.protocol !== 'https:') throw new Error(`${name}: expected an http(s) URL (got "${raw}")`);
185
+ return v;
186
+ }
187
+ if (spec.type === 'seat') {
188
+ if (!/^[A-Za-z0-9_.-]{1,64}$/.test(s)) throw new Error(`${name}: expected a seat name (letters, digits, "_", "-", "."; got "${raw}")`);
189
+ return s;
190
+ }
191
+ if (!s && !spec.secret) throw new Error(`${name}: expected a value`);
192
+ return s;
193
+ }
194
+
195
+ /**
196
+ * THE precedence function: flag > settings file > environment (legacy) >
197
+ * default, per key. Returns `{ [key]: { value, source } }` with source one
198
+ * of "flag" | "setting" | "env" | "default". An invalid file or env value
199
+ * is skipped (reported in `problems`) so one bad entry cannot stop the
200
+ * server; an invalid FLAG never reaches here (parse_args refuses it).
201
+ */
202
+ export function resolve_settings({ flags = {}, file = {}, env = {} } = {}) {
203
+ const out = {};
204
+ const problems = [];
205
+ for (const spec of SETTINGS) {
206
+ const k = spec.key;
207
+ let picked = null;
208
+ if (Object.prototype.hasOwnProperty.call(flags, k) && flags[k] !== undefined) {
209
+ picked = { value: flags[k], source: 'flag' };
210
+ }
211
+ if (!picked && file && Object.prototype.hasOwnProperty.call(file, k) && file[k] !== null && file[k] !== undefined) {
212
+ try {
213
+ picked = { value: coerce(spec, file[k]), source: 'setting' };
214
+ } catch (e) {
215
+ problems.push(`settings file: ${e.message}`);
216
+ }
217
+ }
218
+ if (!picked) {
219
+ for (const name of spec.env) {
220
+ const raw = env[name];
221
+ if (typeof raw !== 'string' || !raw.trim()) continue;
222
+ try {
223
+ picked = { value: coerce(spec, raw), source: 'env' };
224
+ } catch (e) {
225
+ problems.push(`environment ${name}: ${e.message}`);
226
+ }
227
+ break;
228
+ }
229
+ }
230
+ if (!picked) picked = { value: spec.default, source: 'default' };
231
+ out[k] = picked;
232
+ }
233
+ return { settings: out, problems };
234
+ }
235
+
236
+ /** Read the settings file; missing → {}. Invalid JSON throws (the CLI
237
+ * reports it; the server refuses to start on a corrupt file rather than
238
+ * silently running on defaults). */
239
+ export function read_settings_file(path) {
240
+ if (!existsSync(path)) return {};
241
+ const text = readFileSync(path, 'utf8');
242
+ if (!text.trim()) return {};
243
+ const obj = JSON.parse(text);
244
+ if (!obj || typeof obj !== 'object' || Array.isArray(obj)) throw new Error(`${path}: expected a JSON object`);
245
+ return obj;
246
+ }
247
+
248
+ /** Write atomically with owner-only permissions (0600 file, 0700 dir):
249
+ * the file may hold the hub token. */
250
+ export function write_settings_file(path, obj) {
251
+ const dir = dirname(path);
252
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true, mode: 0o700 });
253
+ const tmp = `${path}.${process.pid}.tmp`;
254
+ writeFileSync(tmp, JSON.stringify(obj, null, 2) + '\n', { mode: 0o600 });
255
+ chmodSync(tmp, 0o600);
256
+ renameSync(tmp, path);
257
+ chmodSync(path, 0o600);
258
+ }
259
+
260
+ /** Set (value !== null) or unset (value === null) one key in the file. */
261
+ export function update_settings_file(path, key, value) {
262
+ const spec = setting_spec(key);
263
+ if (!spec) throw new Error(`unknown setting "${key}"`);
264
+ const cur = read_settings_file(path);
265
+ if (value === null || value === undefined) delete cur[key];
266
+ else cur[key] = coerce(spec, value);
267
+ write_settings_file(path, cur);
268
+ return cur;
269
+ }
270
+
271
+ /** Display form of a resolved value (secrets never printed). */
272
+ export function display_value(spec, value) {
273
+ if (spec.secret) return value ? '(set, hidden)' : '(not set)';
274
+ if (value === '' || value === null || value === undefined) return '(not set)';
275
+ if (typeof value === 'boolean') return value ? 'on' : 'off';
276
+ return String(value);
277
+ }
278
+
279
+ export const SOURCE_WORDS = { flag: 'launch flag', setting: 'setting', env: 'environment (legacy)', default: 'default' };
280
+
281
+ /**
282
+ * Parse argv. Shapes:
283
+ * abstractcontinuum [serve] [--flag value | --flag=value | --bool-flag]...
284
+ * abstractcontinuum config get [key] | set <key> <value> | set hub_token --from-file <path> | unset <key> | path
285
+ * Returns { command, flags, settings_file, config, error }.
286
+ */
287
+ export function parse_args(argv) {
288
+ const out = { command: 'serve', flags: {}, settings_file: '', config: null, error: '' };
289
+ const rest = [];
290
+ const args = [...argv];
291
+ let i = 0;
292
+ const fail = (msg) => ({ ...out, error: msg });
293
+ while (i < args.length) {
294
+ const a = args[i];
295
+ if (a === '--help' || a === '-h') return { ...out, command: 'help' };
296
+ if (a === '--version' || a === '-v') return { ...out, command: 'version' };
297
+ if (a.startsWith('--')) {
298
+ const eq = a.indexOf('=');
299
+ const name = eq >= 0 ? a.slice(0, eq) : a;
300
+ const inline = eq >= 0 ? a.slice(eq + 1) : undefined;
301
+ const take = () => {
302
+ if (inline !== undefined) return inline;
303
+ if (i + 1 >= args.length || args[i + 1].startsWith('--')) throw new Error(`${name} needs a value`);
304
+ i += 1;
305
+ return args[i];
306
+ };
307
+ try {
308
+ if (name === '--settings-file') {
309
+ out.settings_file = expand_home(take());
310
+ } else if (name === '--hub-token-file') {
311
+ const p = expand_home(take());
312
+ let text;
313
+ try {
314
+ text = readFileSync(p, 'utf8');
315
+ } catch (e) {
316
+ throw new Error(`--hub-token-file: cannot read ${p} (${e.code || e.message})`);
317
+ }
318
+ const token = text.trim();
319
+ if (!token) throw new Error(`--hub-token-file: ${p} is empty`);
320
+ out.flags.hub_token = token;
321
+ } else if (name === '--from-file') {
322
+ out.from_file = expand_home(take());
323
+ } else if (name.startsWith('--no-') && BY_FLAG.get('--' + name.slice(5))?.type === 'bool' && inline === undefined) {
324
+ out.flags[BY_FLAG.get('--' + name.slice(5)).key] = false;
325
+ } else if (BY_FLAG.has(name)) {
326
+ const spec = BY_FLAG.get(name);
327
+ if (spec.type === 'bool') {
328
+ out.flags[spec.key] = inline === undefined ? true : coerce(spec, inline);
329
+ } else {
330
+ out.flags[spec.key] = coerce(spec, take());
331
+ }
332
+ } else {
333
+ throw new Error(`unknown option ${name} (see --help)`);
334
+ }
335
+ } catch (e) {
336
+ return fail(e.message);
337
+ }
338
+ i += 1;
339
+ continue;
340
+ }
341
+ rest.push(a);
342
+ i += 1;
343
+ }
344
+ if (rest[0] === 'serve') rest.shift();
345
+ if (rest[0] === 'config') {
346
+ const [, action, key, value] = rest;
347
+ if (!['get', 'set', 'unset', 'path'].includes(action || '')) return fail('config: expected get, set, unset or path');
348
+ if ((action === 'set' || action === 'unset') && !key) return fail(`config ${action}: name a setting`);
349
+ if (key && !BY_KEY.has(key)) return fail(`config: unknown setting "${key}" (known: ${SETTINGS.map((s) => s.key).join(', ')})`);
350
+ if (action === 'set' && value === undefined && !out.from_file) return fail(`config set ${key}: give a value${BY_KEY.get(key)?.secret ? ' or --from-file <path>' : ''}`);
351
+ if (rest.length > (action === 'set' ? 4 : 3)) return fail(`config ${action}: unexpected "${rest.slice(action === 'set' ? 4 : 3).join(' ')}"`);
352
+ return { ...out, command: 'config', config: { action, key: key || '', value } };
353
+ }
354
+ if (rest.length) return fail(`unexpected "${rest.join(' ')}" (see --help)`);
355
+ if (out.from_file) return fail('--from-file only applies to `config set`');
356
+ return out;
357
+ }
358
+
359
+ /**
360
+ * Bridge to @abstractframework/app-server's session proxy, which reads its
361
+ * three hardening gates from environment names only. The resolved value
362
+ * (flag > setting > environment > default) is made the ONLY one it can
363
+ * see: every legacy name is removed, then the app's own name is set when
364
+ * the resolved gate is on. Without this a legacy variable would beat an
365
+ * explicit `--no-trust-proxy-headers`.
366
+ */
367
+ export function apply_session_proxy_gates(settings, env) {
368
+ for (const spec of SETTINGS) {
369
+ if (!spec.gate) continue;
370
+ for (const name of spec.env) delete env[name];
371
+ if (settings[spec.key]?.value === true) env[spec.env[0]] = '1';
372
+ }
373
+ }
374
+
375
+ /**
376
+ * Live settings: flags are fixed at launch; the file is re-read when it
377
+ * changes on disk (so `abstractcontinuum config set hub_seat …` in a
378
+ * terminal and a save on the Settings page both apply to the Team page
379
+ * without a restart). Port, host, gateway URL and the sign-in gates are
380
+ * read once at start.
381
+ */
382
+ export function createLiveSettings({ flags = {}, settingsPath, env = process.env, onProblem = () => {} }) {
383
+ let stamp = '';
384
+ let file = {};
385
+ let resolved = null;
386
+ function refresh(force = false) {
387
+ let next = '';
388
+ try {
389
+ const st = statSync(settingsPath);
390
+ next = `${st.mtimeMs}:${st.size}`;
391
+ } catch {
392
+ next = 'missing';
393
+ }
394
+ if (!force && resolved && next === stamp) return resolved;
395
+ stamp = next;
396
+ try {
397
+ file = read_settings_file(settingsPath);
398
+ } catch (e) {
399
+ onProblem(`settings file ${settingsPath}: ${e.message}`);
400
+ }
401
+ const r = resolve_settings({ flags, file, env });
402
+ for (const p of r.problems) onProblem(p);
403
+ resolved = r.settings;
404
+ return resolved;
405
+ }
406
+ refresh(true);
407
+ return {
408
+ settingsPath,
409
+ flags,
410
+ get: () => refresh(),
411
+ value: (key) => refresh()[key].value,
412
+ set(key, value) {
413
+ update_settings_file(settingsPath, key, value);
414
+ return refresh(true);
415
+ },
416
+ };
417
+ }
418
+
419
+ function send_json(res, status, body) {
420
+ res.writeHead(status, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });
421
+ res.end(JSON.stringify(body));
422
+ }
423
+
424
+ function is_loopback_peer(req) {
425
+ const peer = String(req.socket && req.socket.remoteAddress ? req.socket.remoteAddress : '');
426
+ return peer === '127.0.0.1' || peer === '::1' || peer === '::ffff:127.0.0.1' || peer === '';
427
+ }
428
+
429
+ function same_origin(req) {
430
+ const origin = String((req.headers && req.headers.origin) || '').trim();
431
+ if (!origin) return true;
432
+ try {
433
+ return new URL(origin).host.toLowerCase() === String((req.headers && req.headers.host) || '').trim().toLowerCase();
434
+ } catch {
435
+ return false;
436
+ }
437
+ }
438
+
439
+ /** Public view: every setting with its source; secrets as presence only. */
440
+ export function settings_view(live, extra = {}) {
441
+ const s = live.get();
442
+ const settings = {};
443
+ for (const spec of SETTINGS) {
444
+ const { value, source } = s[spec.key];
445
+ settings[spec.key] = spec.secret ? { set: Boolean(value), source } : { value, source };
446
+ }
447
+ return { settings, writable: UI_WRITABLE_KEYS, settings_file: live.settingsPath, ...extra };
448
+ }
449
+
450
+ /**
451
+ * GET/PUT /api/continuum/settings — the Settings page's door to this
452
+ * server's own settings. Local only: the socket peer must be loopback
453
+ * (the same gate as the hub proxy, which this seat setting steers) and a
454
+ * browser Origin must match the Host. PUT takes `{ hub_seat: "<seat>" }`
455
+ * or `{ hub_seat: null }` (back to the default) and persists to the
456
+ * settings file.
457
+ */
458
+ export const SETTINGS_ROUTE = '/api/continuum/settings';
459
+
460
+ export function createSettingsRoute({ live, extra = () => ({}) }) {
461
+ return {
462
+ path: SETTINGS_ROUTE,
463
+ handle(req, res, pathname) {
464
+ if (pathname !== SETTINGS_ROUTE) return false;
465
+ if (!is_loopback_peer(req)) {
466
+ send_json(res, 403, { error: 'settings_non_loopback', detail: "Continuum's settings can only be changed from the computer it runs on." });
467
+ return true;
468
+ }
469
+ if (!same_origin(req)) {
470
+ send_json(res, 403, { error: 'settings_cross_origin', detail: 'Cross-origin requests to the settings route are refused.' });
471
+ return true;
472
+ }
473
+ if (req.method === 'GET') {
474
+ send_json(res, 200, settings_view(live, extra()));
475
+ return true;
476
+ }
477
+ if (req.method !== 'PUT') {
478
+ send_json(res, 405, { error: 'method_not_allowed' });
479
+ return true;
480
+ }
481
+ const ctype = String((req.headers && req.headers['content-type']) || '').toLowerCase();
482
+ if (!ctype.startsWith('application/json')) {
483
+ send_json(res, 415, { error: 'expected_json' });
484
+ return true;
485
+ }
486
+ void (async () => {
487
+ let text = '';
488
+ try {
489
+ for await (const chunk of req) {
490
+ text += chunk;
491
+ if (text.length > 16384) throw new Error('body too large');
492
+ }
493
+ const body = JSON.parse(text || '{}');
494
+ if (!body || typeof body !== 'object' || Array.isArray(body)) throw new Error('expected a JSON object');
495
+ const keys = Object.keys(body);
496
+ if (!keys.length) throw new Error('no setting given');
497
+ for (const k of keys) {
498
+ if (!UI_WRITABLE_KEYS.includes(k)) throw new Error(`"${k}" cannot be changed here (use \`abstractcontinuum config set ${k} …\`)`);
499
+ // Validate every key before writing any.
500
+ if (body[k] !== null) coerce(setting_spec(k), body[k]);
501
+ }
502
+ for (const k of keys) live.set(k, body[k]);
503
+ send_json(res, 200, settings_view(live, extra()));
504
+ } catch (e) {
505
+ send_json(res, 400, { error: 'invalid_setting', detail: String(e && e.message ? e.message : e) });
506
+ }
507
+ })();
508
+ return true;
509
+ },
510
+ };
511
+ }
@@ -1,2 +1,2 @@
1
- import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-8cwmjmPr.js";import{p as f}from"./chunk-JWPE2WC7-DYSRWrFH.js";import{_ as n,l as o}from"./mermaid.core-WQuHCSR5.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-fqThC73D.js";import"./index-B90p5t5R.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
2
- //# sourceMappingURL=abnfDiagram-VRR7QNED-CS1wi4Y3.js.map
1
+ import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-DI56DwNK.js";import{p as f}from"./chunk-JWPE2WC7-CuM7Hcrw.js";import{_ as n,l as o}from"./mermaid.core-CkQqPHPZ.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-Cz79Fwdx.js";import"./index-DTn9k-3t.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
2
+ //# sourceMappingURL=abnfDiagram-VRR7QNED-DkP5u0Ku.js.map
@@ -1,2 +1,2 @@
1
- import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-WQuHCSR5.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,z,a){var O=I-l,i=D-h,n=z-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function U(l,h,I,D,v,A,z){var a=l-I,O=h-D,i=(z?A:-A)/J(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,B=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*J(on(0,T*T*R-P*P)),Y=(P*g-m*S)/R,$=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=Y-B,e=$-t,r=w-B,C=p-t;return x*x+e*e>r*r+C*C&&(Y=w,$=p),{cx:Y,cy:$,x01:-n,y01:-d,x11:Y*(v/T-1),y11:$*(v/T-1)}}function hn(){var l=cn,h=yn,I=j(0),D=null,v=gn,A=dn,z=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,B=rn(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(B>tn-y)a.moveTo(s*F(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*F(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=B,S=B,Y=z.apply(this,arguments)/2,$=Y>y&&(D?+D.apply(this,arguments):J(u*u+s*s)),w=_(rn(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if($>y){var C=sn($/u*q(Y)),K=sn($/s*q(Y));(P-=C*2)>y?(C*=t?1:-1,R+=C,T-=C):(P=0,R=T=(f+c)/2),(S-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(S=0,m=g=(f+c)/2)}var G=s*F(m),H=s*q(m),L=u*F(T),M=u*q(T);if(w>y){var N=s*F(g),Q=s*q(g),V=u*F(R),W=u*q(R),E;if(B<an)if(E=pn(G,H,V,W,N,Q,L,M)){var X=G-E[0],Z=H-E[1],b=N-E[0],k=Q-E[1],nn=1/q(fn((X*b+Z*k)/(J(X*X+Z*Z)*J(b*b+k*k)))/2),en=J(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=U(V,W,G,H,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(G,H),a.arc(0,0,s,m,g,!t)):a.moveTo(G,H),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(G,H,V,W,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[F(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:j(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:j(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:j(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:j(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:j(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:j(+n),i):A},i.padAngle=function(n){return arguments.length?(z=typeof n=="function"?n:j(+n),i):z},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
2
- //# sourceMappingURL=arc-DYoB4bu2.js.map
1
+ import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-CkQqPHPZ.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,z,a){var O=I-l,i=D-h,n=z-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function U(l,h,I,D,v,A,z){var a=l-I,O=h-D,i=(z?A:-A)/J(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,B=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*J(on(0,T*T*R-P*P)),Y=(P*g-m*S)/R,$=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=Y-B,e=$-t,r=w-B,C=p-t;return x*x+e*e>r*r+C*C&&(Y=w,$=p),{cx:Y,cy:$,x01:-n,y01:-d,x11:Y*(v/T-1),y11:$*(v/T-1)}}function hn(){var l=cn,h=yn,I=j(0),D=null,v=gn,A=dn,z=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,B=rn(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(B>tn-y)a.moveTo(s*F(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*F(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=B,S=B,Y=z.apply(this,arguments)/2,$=Y>y&&(D?+D.apply(this,arguments):J(u*u+s*s)),w=_(rn(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if($>y){var C=sn($/u*q(Y)),K=sn($/s*q(Y));(P-=C*2)>y?(C*=t?1:-1,R+=C,T-=C):(P=0,R=T=(f+c)/2),(S-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(S=0,m=g=(f+c)/2)}var G=s*F(m),H=s*q(m),L=u*F(T),M=u*q(T);if(w>y){var N=s*F(g),Q=s*q(g),V=u*F(R),W=u*q(R),E;if(B<an)if(E=pn(G,H,V,W,N,Q,L,M)){var X=G-E[0],Z=H-E[1],b=N-E[0],k=Q-E[1],nn=1/q(fn((X*b+Z*k)/(J(X*X+Z*Z)*J(b*b+k*k)))/2),en=J(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=U(V,W,G,H,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(G,H),a.arc(0,0,s,m,g,!t)):a.moveTo(G,H),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(G,H,V,W,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[F(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:j(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:j(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:j(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:j(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:j(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:j(+n),i):A},i.padAngle=function(n){return arguments.length?(z=typeof n=="function"?n:j(+n),i):z},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
2
+ //# sourceMappingURL=arc-vxPq5BjA.js.map