@strapi-community/plugin-io 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1411 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const React = require("react");
5
+ const designSystem = require("@strapi/design-system");
6
+ const icons = require("@strapi/icons");
7
+ const admin = require("@strapi/strapi/admin");
8
+ const index = require("./index-DkTxsEqL.js");
9
+ const styled = require("styled-components");
10
+ const index$1 = require("./index-BVQ20t1c.js");
11
+ const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
12
+ const styled__default = /* @__PURE__ */ _interopDefault(styled);
13
+ const ResponsiveMain = styled__default.default(designSystem.Main)`
14
+ & > div {
15
+ padding: 16px !important;
16
+
17
+ @media (min-width: 768px) {
18
+ padding: 32px !important;
19
+ }
20
+ }
21
+ `;
22
+ const ResponsiveHeader = styled__default.default(designSystem.Box)`
23
+ padding-bottom: 16px !important;
24
+
25
+ @media (min-width: 768px) {
26
+ padding-bottom: 32px !important;
27
+ }
28
+ `;
29
+ const ResponsiveTitle = styled__default.default(designSystem.Typography)`
30
+ font-size: 1.25rem !important;
31
+
32
+ @media (min-width: 768px) {
33
+ font-size: 2rem !important;
34
+ }
35
+ `;
36
+ const ResponsiveSubtitle = styled__default.default(designSystem.Typography)`
37
+ font-size: 0.875rem !important;
38
+
39
+ @media (min-width: 768px) {
40
+ font-size: 1rem !important;
41
+ }
42
+ `;
43
+ const ResponsiveCard = styled__default.default(designSystem.Box)`
44
+ padding: 16px !important;
45
+
46
+ @media (min-width: 768px) {
47
+ padding: 24px !important;
48
+ }
49
+ `;
50
+ const ResponsiveSection = styled__default.default(designSystem.Box)`
51
+ padding-bottom: 16px !important;
52
+
53
+ @media (min-width: 768px) {
54
+ padding-bottom: 24px !important;
55
+ }
56
+ `;
57
+ const ResponsiveSectionTitle = styled__default.default(designSystem.Typography)`
58
+ font-size: 1.125rem !important;
59
+ margin-bottom: 8px !important;
60
+
61
+ @media (min-width: 768px) {
62
+ font-size: 1.5rem !important;
63
+ margin-bottom: 12px !important;
64
+ }
65
+ `;
66
+ const ResponsiveButtonGroup = styled__default.default(designSystem.Flex)`
67
+ flex-direction: column;
68
+ gap: 8px;
69
+ width: 100%;
70
+
71
+ @media (min-width: 640px) {
72
+ flex-direction: row;
73
+ width: auto;
74
+ }
75
+
76
+ button {
77
+ width: 100%;
78
+ justify-content: center;
79
+
80
+ @media (min-width: 640px) {
81
+ width: auto;
82
+ }
83
+ }
84
+ `;
85
+ const InputWrapper = styled__default.default.div`
86
+ width: 100%;
87
+
88
+ input, textarea, select {
89
+ width: 100% !important;
90
+ min-height: 48px !important;
91
+ font-size: 16px !important;
92
+ padding: 14px 16px !important;
93
+ box-sizing: border-box !important;
94
+
95
+ @media (min-width: 768px) {
96
+ min-height: 44px !important;
97
+ font-size: 15px !important;
98
+ padding: 12px 16px !important;
99
+ }
100
+ }
101
+
102
+ /* Number Input specific - remove ALL spinners */
103
+ input[type="number"] {
104
+ width: 100% !important;
105
+ min-height: 48px !important;
106
+ font-size: 16px !important;
107
+
108
+ /* Remove native browser spinner arrows */
109
+ -moz-appearance: textfield;
110
+
111
+ &::-webkit-outer-spin-button,
112
+ &::-webkit-inner-spin-button {
113
+ -webkit-appearance: none;
114
+ margin: 0;
115
+ }
116
+
117
+ @media (min-width: 768px) {
118
+ min-height: 44px !important;
119
+ font-size: 15px !important;
120
+ }
121
+ }
122
+
123
+ /* Strapi Input Component Override */
124
+ > div {
125
+ width: 100% !important;
126
+
127
+ > div {
128
+ width: 100% !important;
129
+
130
+ input {
131
+ width: 100% !important;
132
+ }
133
+ }
134
+ }
135
+
136
+ /* Strapi NumberInput Component - ALWAYS hide increment/decrement buttons */
137
+ button[aria-label="Increment"],
138
+ button[aria-label="Decrement"],
139
+ div button[aria-label="Increment"],
140
+ div button[aria-label="Decrement"],
141
+ & button[aria-label="Increment"],
142
+ & button[aria-label="Decrement"] {
143
+ display: none !important;
144
+ visibility: hidden !important;
145
+ opacity: 0 !important;
146
+ width: 0 !important;
147
+ height: 0 !important;
148
+ overflow: hidden !important;
149
+ pointer-events: none !important;
150
+ }
151
+
152
+ /* NumberInput Container - proper alignment */
153
+ > div {
154
+ display: flex !important;
155
+ align-items: center !important;
156
+ width: 100% !important;
157
+
158
+ /* Input field container */
159
+ > div:first-child {
160
+ flex: 1 !important;
161
+ min-width: 0 !important;
162
+ margin-right: 0 !important;
163
+
164
+ input {
165
+ width: 100% !important;
166
+ padding-right: 12px !important;
167
+ }
168
+ }
169
+
170
+ /* Spinner Buttons Container - ALWAYS HIDDEN */
171
+ > div:last-child {
172
+ display: none !important;
173
+ visibility: hidden !important;
174
+ width: 0 !important;
175
+ height: 0 !important;
176
+ overflow: hidden !important;
177
+ }
178
+ }
179
+ `;
180
+ const ResponsiveField = styled__default.default(designSystem.Field.Root)`
181
+ width: 100%;
182
+
183
+ label {
184
+ font-size: 15px !important;
185
+ margin-bottom: 10px !important;
186
+ font-weight: 600 !important;
187
+ display: block !important;
188
+
189
+ @media (min-width: 768px) {
190
+ font-size: 14px !important;
191
+ margin-bottom: 8px !important;
192
+ }
193
+ }
194
+
195
+ /* Field hint */
196
+ > span:last-child {
197
+ font-size: 14px !important;
198
+ margin-top: 8px !important;
199
+
200
+ @media (min-width: 768px) {
201
+ font-size: 13px !important;
202
+ margin-top: 6px !important;
203
+ }
204
+ }
205
+ `;
206
+ const SettingsPage = () => {
207
+ const { get, put } = admin.useFetchClient();
208
+ const { toggleNotification } = admin.useNotification();
209
+ const { formatMessage } = index.useIntl();
210
+ const t = (id, defaultMessage) => formatMessage({ id: `${index$1.PLUGIN_ID}.${id}`, defaultMessage });
211
+ const [isLoading, setIsLoading] = React.useState(true);
212
+ const [isSaving, setIsSaving] = React.useState(false);
213
+ const [hasChanges, setHasChanges] = React.useState(false);
214
+ const [settings, setSettings] = React.useState({
215
+ enabled: true,
216
+ cors: {
217
+ origins: ["http://localhost:3000"]
218
+ },
219
+ connection: {
220
+ maxConnections: 1e3,
221
+ pingTimeout: 2e4,
222
+ pingInterval: 25e3,
223
+ connectionTimeout: 45e3
224
+ },
225
+ security: {
226
+ requireAuthentication: false,
227
+ rateLimiting: {
228
+ enabled: false,
229
+ maxEventsPerSecond: 10
230
+ },
231
+ ipWhitelist: [],
232
+ ipBlacklist: []
233
+ },
234
+ events: {
235
+ customEventNames: false,
236
+ includeRelations: false,
237
+ excludeFields: [],
238
+ onlyPublished: false
239
+ },
240
+ rooms: {
241
+ autoJoinByRole: {},
242
+ enablePrivateRooms: false
243
+ },
244
+ redis: {
245
+ enabled: false,
246
+ url: "redis://localhost:6379"
247
+ },
248
+ namespaces: {
249
+ enabled: false,
250
+ list: {}
251
+ },
252
+ middleware: {
253
+ enabled: false,
254
+ handlers: []
255
+ },
256
+ monitoring: {
257
+ enableConnectionLogging: true,
258
+ enableEventLogging: false,
259
+ maxEventLogSize: 100
260
+ },
261
+ entitySubscriptions: {
262
+ enabled: true,
263
+ maxSubscriptionsPerSocket: 100,
264
+ requireVerification: true,
265
+ allowedContentTypes: [],
266
+ enableMetrics: true
267
+ }
268
+ });
269
+ const [availableContentTypes, setAvailableContentTypes] = React.useState([]);
270
+ const [availableRoles, setAvailableRoles] = React.useState([]);
271
+ const fileInputRef = React.useRef(null);
272
+ const validateSettings = (settingsToValidate) => {
273
+ const errors = [];
274
+ settingsToValidate.cors?.origins?.forEach((origin) => {
275
+ try {
276
+ new URL(origin);
277
+ } catch {
278
+ errors.push(t("validation.invalidOrigin", `Invalid origin: ${origin}`));
279
+ }
280
+ });
281
+ if (settingsToValidate.connection?.pingTimeout <= 0) {
282
+ errors.push(t("validation.pingTimeoutPositive", "Ping timeout must be positive"));
283
+ }
284
+ if (settingsToValidate.connection?.pingInterval <= 0) {
285
+ errors.push(t("validation.pingIntervalPositive", "Ping interval must be positive"));
286
+ }
287
+ if (settingsToValidate.connection?.connectionTimeout <= 0) {
288
+ errors.push(t("validation.connectionTimeoutPositive", "Connection timeout must be positive"));
289
+ }
290
+ if (settingsToValidate.connection?.maxConnections <= 0) {
291
+ errors.push(t("validation.maxConnectionsPositive", "Max connections must be positive"));
292
+ }
293
+ if (settingsToValidate.redis?.enabled && !settingsToValidate.redis?.url) {
294
+ errors.push(t("validation.redisUrlRequired", "Redis URL is required when Redis is enabled"));
295
+ }
296
+ return errors;
297
+ };
298
+ const exportSettings = () => {
299
+ const dataStr = JSON.stringify(settings, null, 2);
300
+ const dataUri = "data:application/json;charset=utf-8," + encodeURIComponent(dataStr);
301
+ const exportFileDefaultName = `socket-io-settings-${Date.now()}.json`;
302
+ const linkElement = document.createElement("a");
303
+ linkElement.setAttribute("href", dataUri);
304
+ linkElement.setAttribute("download", exportFileDefaultName);
305
+ linkElement.click();
306
+ toggleNotification({
307
+ type: "success",
308
+ message: t("settings.exported", "Settings exported successfully!")
309
+ });
310
+ };
311
+ const importSettings = (event) => {
312
+ const file = event.target.files[0];
313
+ if (!file) return;
314
+ const reader = new FileReader();
315
+ reader.onload = (e) => {
316
+ try {
317
+ const imported = JSON.parse(e.target.result);
318
+ const errors = validateSettings(imported);
319
+ if (errors.length > 0) {
320
+ toggleNotification({
321
+ type: "danger",
322
+ message: `${t("settings.importError", "Import failed")}: ${errors.join(", ")}`
323
+ });
324
+ return;
325
+ }
326
+ updateSettings(imported);
327
+ toggleNotification({
328
+ type: "success",
329
+ message: t("settings.imported", "Settings imported successfully!")
330
+ });
331
+ } catch {
332
+ toggleNotification({
333
+ type: "danger",
334
+ message: t("settings.invalidJson", "Invalid settings file!")
335
+ });
336
+ }
337
+ };
338
+ reader.readAsText(file);
339
+ event.target.value = null;
340
+ };
341
+ const enableAllContentTypes = (roleType) => {
342
+ updateSettings((prev) => {
343
+ const contentTypes = {};
344
+ availableContentTypes.forEach((ct) => {
345
+ contentTypes[ct.uid] = { create: true, update: true, delete: true };
346
+ });
347
+ return {
348
+ ...prev,
349
+ rolePermissions: {
350
+ ...prev.rolePermissions,
351
+ [roleType]: {
352
+ ...prev.rolePermissions?.[roleType],
353
+ contentTypes
354
+ }
355
+ }
356
+ };
357
+ });
358
+ };
359
+ const disableAllContentTypes = (roleType) => {
360
+ updateSettings((prev) => ({
361
+ ...prev,
362
+ rolePermissions: {
363
+ ...prev.rolePermissions,
364
+ [roleType]: {
365
+ ...prev.rolePermissions?.[roleType],
366
+ contentTypes: {}
367
+ }
368
+ }
369
+ }));
370
+ };
371
+ React.useEffect(() => {
372
+ const fetchData = async () => {
373
+ try {
374
+ const [settingsRes, contentTypesRes, rolesRes] = await Promise.all([
375
+ get(`/${index$1.PLUGIN_ID}/settings`),
376
+ get(`/${index$1.PLUGIN_ID}/content-types`),
377
+ get(`/${index$1.PLUGIN_ID}/roles`)
378
+ ]);
379
+ if (settingsRes.data?.data) {
380
+ setSettings(settingsRes.data.data);
381
+ }
382
+ if (contentTypesRes.data?.data) {
383
+ setAvailableContentTypes(contentTypesRes.data.data);
384
+ }
385
+ if (rolesRes.data?.data) {
386
+ setAvailableRoles(rolesRes.data.data);
387
+ }
388
+ } catch (err) {
389
+ console.error("Error loading settings:", err);
390
+ toggleNotification({
391
+ type: "danger",
392
+ message: t("settings.loadError", "Error loading settings")
393
+ });
394
+ } finally {
395
+ setIsLoading(false);
396
+ }
397
+ };
398
+ fetchData();
399
+ }, [get, toggleNotification]);
400
+ const handleSave = async () => {
401
+ const errors = validateSettings(settings);
402
+ if (errors.length > 0) {
403
+ toggleNotification({
404
+ type: "danger",
405
+ message: `${t("validation.errors", "Validation errors")}: ${errors.join(", ")}`
406
+ });
407
+ return;
408
+ }
409
+ setIsSaving(true);
410
+ try {
411
+ await put(`/${index$1.PLUGIN_ID}/settings`, settings);
412
+ setHasChanges(false);
413
+ toggleNotification({
414
+ type: "success",
415
+ message: t("settings.success", "Settings saved successfully!")
416
+ });
417
+ } catch (err) {
418
+ console.error("Error saving settings:", err);
419
+ toggleNotification({
420
+ type: "danger",
421
+ message: t("settings.error", "Error saving settings")
422
+ });
423
+ } finally {
424
+ setIsSaving(false);
425
+ }
426
+ };
427
+ const updateSettings = (updater) => {
428
+ setSettings(updater);
429
+ setHasChanges(true);
430
+ };
431
+ const httpMethods = ["GET", "POST", "PUT", "DELETE", "PATCH"];
432
+ const [newOrigin, setNewOrigin] = React.useState("");
433
+ const [newNamespace, setNewNamespace] = React.useState("");
434
+ const addOrigin = () => {
435
+ if (newOrigin && !settings.cors?.origins?.includes(newOrigin)) {
436
+ updateSettings((prev) => ({
437
+ ...prev,
438
+ cors: {
439
+ ...prev.cors,
440
+ origins: [...prev.cors?.origins || [], newOrigin]
441
+ }
442
+ }));
443
+ setNewOrigin("");
444
+ }
445
+ };
446
+ const removeOrigin = (origin) => {
447
+ updateSettings((prev) => ({
448
+ ...prev,
449
+ cors: {
450
+ ...prev.cors,
451
+ origins: prev.cors?.origins?.filter((o) => o !== origin) || []
452
+ }
453
+ }));
454
+ };
455
+ const updateConnection = (key, value) => {
456
+ updateSettings((prev) => ({
457
+ ...prev,
458
+ connection: {
459
+ ...prev.connection,
460
+ [key]: parseInt(value) || 0
461
+ }
462
+ }));
463
+ };
464
+ const updateSecurity = (key, value) => {
465
+ updateSettings((prev) => ({
466
+ ...prev,
467
+ security: {
468
+ ...prev.security,
469
+ [key]: value
470
+ }
471
+ }));
472
+ };
473
+ const updateEvents = (key, value) => {
474
+ updateSettings((prev) => ({
475
+ ...prev,
476
+ events: {
477
+ ...prev.events,
478
+ [key]: value
479
+ }
480
+ }));
481
+ };
482
+ const updateMonitoring = (key, value) => {
483
+ updateSettings((prev) => ({
484
+ ...prev,
485
+ monitoring: {
486
+ ...prev.monitoring,
487
+ [key]: value
488
+ }
489
+ }));
490
+ };
491
+ const updateEntitySubscriptions = (key, value) => {
492
+ updateSettings((prev) => ({
493
+ ...prev,
494
+ entitySubscriptions: {
495
+ ...prev.entitySubscriptions,
496
+ [key]: value
497
+ }
498
+ }));
499
+ };
500
+ const updateRedis = (key, value) => {
501
+ updateSettings((prev) => ({
502
+ ...prev,
503
+ redis: {
504
+ ...prev.redis,
505
+ [key]: value
506
+ }
507
+ }));
508
+ };
509
+ const updateNamespaces = (key, value) => {
510
+ updateSettings((prev) => ({
511
+ ...prev,
512
+ namespaces: {
513
+ ...prev.namespaces,
514
+ [key]: value
515
+ }
516
+ }));
517
+ };
518
+ const addNamespace = () => {
519
+ const trimmed = newNamespace.trim();
520
+ console.log("addNamespace called, newNamespace:", trimmed);
521
+ console.log("current list:", settings.namespaces?.list);
522
+ if (!trimmed) {
523
+ console.log("Empty namespace name");
524
+ return;
525
+ }
526
+ const currentList = settings.namespaces?.list || {};
527
+ if (currentList[trimmed]) {
528
+ console.log("Namespace already exists");
529
+ return;
530
+ }
531
+ updateSettings((prev) => ({
532
+ ...prev,
533
+ namespaces: {
534
+ enabled: prev.namespaces?.enabled || false,
535
+ list: {
536
+ ...currentList,
537
+ [trimmed]: { requireAuth: false }
538
+ }
539
+ }
540
+ }));
541
+ setNewNamespace("");
542
+ console.log("Namespace added:", trimmed);
543
+ };
544
+ const removeNamespace = (namespace) => {
545
+ updateSettings((prev) => {
546
+ const newList = { ...prev.namespaces?.list };
547
+ delete newList[namespace];
548
+ return {
549
+ ...prev,
550
+ namespaces: {
551
+ ...prev.namespaces,
552
+ list: newList
553
+ }
554
+ };
555
+ });
556
+ };
557
+ if (isLoading) {
558
+ return /* @__PURE__ */ jsxRuntime.jsx(ResponsiveMain, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 8, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: "Loading..." }) }) });
559
+ }
560
+ return /* @__PURE__ */ jsxRuntime.jsx(ResponsiveMain, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 8, background: "neutral100", children: [
561
+ /* @__PURE__ */ jsxRuntime.jsx(ResponsiveHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: { base: "column", tablet: "row" }, justifyContent: "space-between", alignItems: { base: "flex-start", tablet: "center" }, gap: 3, children: [
562
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
563
+ /* @__PURE__ */ jsxRuntime.jsxs(ResponsiveTitle, { variant: "alpha", as: "h1", children: [
564
+ t("plugin.name", "Socket.IO"),
565
+ " ",
566
+ t("settings.title", "Settings")
567
+ ] }),
568
+ /* @__PURE__ */ jsxRuntime.jsx(ResponsiveSubtitle, { variant: "epsilon", textColor: "neutral600", children: t("settings.description", "Configure the Socket.IO connection for real-time events") })
569
+ ] }),
570
+ /* @__PURE__ */ jsxRuntime.jsxs(ResponsiveButtonGroup, { children: [
571
+ /* @__PURE__ */ jsxRuntime.jsx(
572
+ designSystem.Button,
573
+ {
574
+ variant: "secondary",
575
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Download, {}),
576
+ onClick: exportSettings,
577
+ size: "S",
578
+ children: t("settings.export", "Export")
579
+ }
580
+ ),
581
+ /* @__PURE__ */ jsxRuntime.jsx(
582
+ designSystem.Button,
583
+ {
584
+ variant: "secondary",
585
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Upload, {}),
586
+ onClick: () => fileInputRef.current?.click(),
587
+ size: "S",
588
+ children: t("settings.import", "Import")
589
+ }
590
+ ),
591
+ /* @__PURE__ */ jsxRuntime.jsx(
592
+ "input",
593
+ {
594
+ ref: fileInputRef,
595
+ type: "file",
596
+ accept: ".json",
597
+ onChange: importSettings,
598
+ style: { display: "none" }
599
+ }
600
+ ),
601
+ /* @__PURE__ */ jsxRuntime.jsx(
602
+ designSystem.Button,
603
+ {
604
+ onClick: handleSave,
605
+ loading: isSaving,
606
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Check, {}),
607
+ disabled: !hasChanges,
608
+ size: "S",
609
+ children: hasChanges ? t("settings.saveAndApply", "Save & Apply") : t("settings.saved", "Saved")
610
+ }
611
+ )
612
+ ] })
613
+ ] }) }),
614
+ /* @__PURE__ */ jsxRuntime.jsxs(ResponsiveCard, { background: "neutral0", shadow: "filterShadow", hasRadius: true, children: [
615
+ /* @__PURE__ */ jsxRuntime.jsxs(ResponsiveSection, { children: [
616
+ /* @__PURE__ */ jsxRuntime.jsx(ResponsiveSectionTitle, { variant: "delta", as: "h2", children: t("cors.title", "CORS Origins") }),
617
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t("cors.description", "Configure which frontend URLs are allowed to connect") })
618
+ ] }),
619
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Root, { gap: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(ResponsiveField, { children: [
620
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t("cors.origins", "Allowed Origins") }),
621
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: { base: "column", tablet: "row" }, gap: 2, paddingBottom: 2, children: [
622
+ /* @__PURE__ */ jsxRuntime.jsx(InputWrapper, { style: { flex: 1, width: "100%" }, children: /* @__PURE__ */ jsxRuntime.jsx(
623
+ designSystem.TextInput,
624
+ {
625
+ placeholder: "http://localhost:3000",
626
+ value: newOrigin,
627
+ onChange: (e) => setNewOrigin(e.target.value),
628
+ onKeyPress: (e) => e.key === "Enter" && addOrigin()
629
+ }
630
+ ) }),
631
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: addOrigin, size: "L", style: { width: "100%", maxWidth: "200px", minHeight: "44px" }, children: t("cors.add", "Add") })
632
+ ] }),
633
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, wrap: "wrap", paddingTop: 2, children: settings.cors?.origins?.map((origin) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { onClick: () => removeOrigin(origin), style: { cursor: "pointer", fontSize: "13px", padding: "6px 12px" }, children: [
634
+ origin,
635
+ " ✕"
636
+ ] }, origin)) }),
637
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, { children: t("cors.originsHint", "Add multiple frontend URLs that can connect") })
638
+ ] }) }) }),
639
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 4, paddingBottom: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, {}) }),
640
+ /* @__PURE__ */ jsxRuntime.jsxs(ResponsiveSection, { children: [
641
+ /* @__PURE__ */ jsxRuntime.jsx(ResponsiveSectionTitle, { variant: "delta", as: "h2", children: t("connection.title", "Connection Settings") }),
642
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t("connection.description", "Configure connection limits and timeouts") })
643
+ ] }),
644
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { gap: 3, children: [
645
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(ResponsiveField, { children: [
646
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t("connection.maxConnections", "Max Connections") }),
647
+ /* @__PURE__ */ jsxRuntime.jsx(InputWrapper, { children: /* @__PURE__ */ jsxRuntime.jsx(
648
+ designSystem.NumberInput,
649
+ {
650
+ value: settings.connection?.maxConnections || 1e3,
651
+ onValueChange: (value) => updateConnection("maxConnections", value)
652
+ }
653
+ ) })
654
+ ] }) }),
655
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(ResponsiveField, { children: [
656
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t("connection.pingTimeout", "Ping Timeout (ms)") }),
657
+ /* @__PURE__ */ jsxRuntime.jsx(InputWrapper, { children: /* @__PURE__ */ jsxRuntime.jsx(
658
+ designSystem.NumberInput,
659
+ {
660
+ value: settings.connection?.pingTimeout || 2e4,
661
+ onValueChange: (value) => updateConnection("pingTimeout", value)
662
+ }
663
+ ) })
664
+ ] }) }),
665
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(ResponsiveField, { children: [
666
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t("connection.pingInterval", "Ping Interval (ms)") }),
667
+ /* @__PURE__ */ jsxRuntime.jsx(InputWrapper, { children: /* @__PURE__ */ jsxRuntime.jsx(
668
+ designSystem.NumberInput,
669
+ {
670
+ value: settings.connection?.pingInterval || 25e3,
671
+ onValueChange: (value) => updateConnection("pingInterval", value)
672
+ }
673
+ ) })
674
+ ] }) }),
675
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(ResponsiveField, { children: [
676
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t("connection.connectionTimeout", "Connection Timeout (ms)") }),
677
+ /* @__PURE__ */ jsxRuntime.jsx(InputWrapper, { children: /* @__PURE__ */ jsxRuntime.jsx(
678
+ designSystem.NumberInput,
679
+ {
680
+ value: settings.connection?.connectionTimeout || 45e3,
681
+ onValueChange: (value) => updateConnection("connectionTimeout", value)
682
+ }
683
+ ) })
684
+ ] }) })
685
+ ] }),
686
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 4, paddingBottom: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, {}) }),
687
+ /* @__PURE__ */ jsxRuntime.jsxs(ResponsiveSection, { children: [
688
+ /* @__PURE__ */ jsxRuntime.jsx(ResponsiveSectionTitle, { variant: "delta", as: "h2", children: t("security.title", "Security Settings") }),
689
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t("security.description", "Configure authentication and rate limiting") })
690
+ ] }),
691
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { gap: 3, children: [
692
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxRuntime.jsx(
693
+ designSystem.Box,
694
+ {
695
+ padding: 4,
696
+ background: settings.security?.requireAuthentication ? "success100" : "neutral0",
697
+ hasRadius: true,
698
+ style: {
699
+ cursor: "pointer",
700
+ border: `2px solid ${settings.security?.requireAuthentication ? "#5cb176" : "#dcdce4"}`,
701
+ transition: "all 0.2s ease",
702
+ minHeight: "110px",
703
+ display: "flex",
704
+ alignItems: "center"
705
+ },
706
+ onClick: () => updateSecurity("requireAuthentication", !settings.security?.requireAuthentication),
707
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "center", style: { width: "100%" }, children: [
708
+ /* @__PURE__ */ jsxRuntime.jsx(
709
+ designSystem.Toggle,
710
+ {
711
+ checked: settings.security?.requireAuthentication || false,
712
+ onChange: (e) => updateSecurity("requireAuthentication", e.target.checked)
713
+ }
714
+ ),
715
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", gap: 1, children: [
716
+ /* @__PURE__ */ jsxRuntime.jsx(
717
+ designSystem.Typography,
718
+ {
719
+ variant: "omega",
720
+ fontWeight: settings.security?.requireAuthentication ? "bold" : "normal",
721
+ textColor: settings.security?.requireAuthentication ? "success700" : "neutral800",
722
+ children: t("security.requireAuth", "Require Authentication")
723
+ }
724
+ ),
725
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "12px" }, children: settings.security?.requireAuthentication ? "✓ Active" : "Inactive" })
726
+ ] })
727
+ ] })
728
+ }
729
+ ) }),
730
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsxRuntime.jsx(
731
+ designSystem.Box,
732
+ {
733
+ padding: 4,
734
+ background: settings.security?.rateLimiting?.enabled ? "warning100" : "neutral0",
735
+ hasRadius: true,
736
+ style: {
737
+ cursor: "pointer",
738
+ border: `2px solid ${settings.security?.rateLimiting?.enabled ? "#f59e0b" : "#dcdce4"}`,
739
+ transition: "all 0.2s ease",
740
+ minHeight: "110px",
741
+ display: "flex",
742
+ alignItems: "center"
743
+ },
744
+ onClick: () => updateSecurity("rateLimiting", { ...settings.security?.rateLimiting, enabled: !settings.security?.rateLimiting?.enabled }),
745
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "center", style: { width: "100%" }, children: [
746
+ /* @__PURE__ */ jsxRuntime.jsx(
747
+ designSystem.Toggle,
748
+ {
749
+ checked: settings.security?.rateLimiting?.enabled || false,
750
+ onChange: (e) => updateSecurity("rateLimiting", { ...settings.security?.rateLimiting, enabled: e.target.checked })
751
+ }
752
+ ),
753
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", gap: 1, children: [
754
+ /* @__PURE__ */ jsxRuntime.jsx(
755
+ designSystem.Typography,
756
+ {
757
+ variant: "omega",
758
+ fontWeight: settings.security?.rateLimiting?.enabled ? "bold" : "normal",
759
+ textColor: settings.security?.rateLimiting?.enabled ? "warning700" : "neutral800",
760
+ children: t("security.rateLimiting", "Enable Rate Limiting")
761
+ }
762
+ ),
763
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "12px" }, children: settings.security?.rateLimiting?.enabled ? "✓ Active" : "Inactive" })
764
+ ] })
765
+ ] })
766
+ }
767
+ ) }),
768
+ settings.security?.rateLimiting?.enabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxRuntime.jsx(
769
+ designSystem.NumberInput,
770
+ {
771
+ label: t("security.maxEventsPerSecond", "Max Events/Second"),
772
+ value: settings.security?.rateLimiting?.maxEventsPerSecond || 10,
773
+ onValueChange: (value) => updateSecurity("rateLimiting", { ...settings.security?.rateLimiting, maxEventsPerSecond: value })
774
+ }
775
+ ) })
776
+ ] }),
777
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 4, paddingBottom: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, {}) }),
778
+ /* @__PURE__ */ jsxRuntime.jsxs(ResponsiveSection, { children: [
779
+ /* @__PURE__ */ jsxRuntime.jsx(ResponsiveSectionTitle, { variant: "delta", as: "h2", children: t("events.title", "Event Configuration") }),
780
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t("events.description", "Global event settings") })
781
+ ] }),
782
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { gap: 3, children: [
783
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsxRuntime.jsx(
784
+ designSystem.Box,
785
+ {
786
+ padding: 4,
787
+ background: settings.events?.customEventNames ? "primary100" : "neutral0",
788
+ hasRadius: true,
789
+ style: {
790
+ cursor: "pointer",
791
+ border: `2px solid ${settings.events?.customEventNames ? "#4945ff" : "#dcdce4"}`,
792
+ transition: "all 0.2s ease",
793
+ minHeight: "110px",
794
+ display: "flex",
795
+ alignItems: "center"
796
+ },
797
+ onClick: () => updateEvents("customEventNames", !settings.events?.customEventNames),
798
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "center", style: { width: "100%" }, children: [
799
+ /* @__PURE__ */ jsxRuntime.jsx(
800
+ designSystem.Toggle,
801
+ {
802
+ checked: settings.events?.customEventNames || false,
803
+ onChange: (e) => updateEvents("customEventNames", e.target.checked)
804
+ }
805
+ ),
806
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", gap: 1, children: [
807
+ /* @__PURE__ */ jsxRuntime.jsx(
808
+ designSystem.Typography,
809
+ {
810
+ variant: "omega",
811
+ fontWeight: settings.events?.customEventNames ? "bold" : "normal",
812
+ textColor: settings.events?.customEventNames ? "primary700" : "neutral800",
813
+ children: t("events.customNames", "Use Custom Event Names")
814
+ }
815
+ ),
816
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "12px" }, children: settings.events?.customEventNames ? "✓ Active" : "Inactive" })
817
+ ] })
818
+ ] })
819
+ }
820
+ ) }),
821
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsxRuntime.jsx(
822
+ designSystem.Box,
823
+ {
824
+ padding: 4,
825
+ background: settings.events?.includeRelations ? "primary100" : "neutral0",
826
+ hasRadius: true,
827
+ style: {
828
+ cursor: "pointer",
829
+ border: `2px solid ${settings.events?.includeRelations ? "#4945ff" : "#dcdce4"}`,
830
+ transition: "all 0.2s ease",
831
+ minHeight: "110px",
832
+ display: "flex",
833
+ alignItems: "center"
834
+ },
835
+ onClick: () => updateEvents("includeRelations", !settings.events?.includeRelations),
836
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "center", style: { width: "100%" }, children: [
837
+ /* @__PURE__ */ jsxRuntime.jsx(
838
+ designSystem.Toggle,
839
+ {
840
+ checked: settings.events?.includeRelations || false,
841
+ onChange: (e) => updateEvents("includeRelations", e.target.checked)
842
+ }
843
+ ),
844
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", gap: 1, children: [
845
+ /* @__PURE__ */ jsxRuntime.jsx(
846
+ designSystem.Typography,
847
+ {
848
+ variant: "omega",
849
+ fontWeight: settings.events?.includeRelations ? "bold" : "normal",
850
+ textColor: settings.events?.includeRelations ? "primary700" : "neutral800",
851
+ children: t("events.includeRelations", "Include Relations")
852
+ }
853
+ ),
854
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "12px" }, children: settings.events?.includeRelations ? "✓ Active" : "Inactive" })
855
+ ] })
856
+ ] })
857
+ }
858
+ ) }),
859
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsxRuntime.jsx(
860
+ designSystem.Box,
861
+ {
862
+ padding: 4,
863
+ background: settings.events?.onlyPublished ? "primary100" : "neutral0",
864
+ hasRadius: true,
865
+ style: {
866
+ cursor: "pointer",
867
+ border: `2px solid ${settings.events?.onlyPublished ? "#4945ff" : "#dcdce4"}`,
868
+ transition: "all 0.2s ease",
869
+ minHeight: "110px",
870
+ display: "flex",
871
+ alignItems: "center"
872
+ },
873
+ onClick: () => updateEvents("onlyPublished", !settings.events?.onlyPublished),
874
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "center", style: { width: "100%" }, children: [
875
+ /* @__PURE__ */ jsxRuntime.jsx(
876
+ designSystem.Toggle,
877
+ {
878
+ checked: settings.events?.onlyPublished || false,
879
+ onChange: (e) => updateEvents("onlyPublished", e.target.checked)
880
+ }
881
+ ),
882
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", gap: 1, children: [
883
+ /* @__PURE__ */ jsxRuntime.jsx(
884
+ designSystem.Typography,
885
+ {
886
+ variant: "omega",
887
+ fontWeight: settings.events?.onlyPublished ? "bold" : "normal",
888
+ textColor: settings.events?.onlyPublished ? "primary700" : "neutral800",
889
+ children: t("events.onlyPublished", "Only Published Content")
890
+ }
891
+ ),
892
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "12px" }, children: settings.events?.onlyPublished ? "✓ Active" : "Inactive" })
893
+ ] })
894
+ ] })
895
+ }
896
+ ) })
897
+ ] }),
898
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 4, paddingBottom: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, {}) }),
899
+ /* @__PURE__ */ jsxRuntime.jsxs(ResponsiveSection, { children: [
900
+ /* @__PURE__ */ jsxRuntime.jsx(ResponsiveSectionTitle, { variant: "delta", as: "h2", children: t("permissions.title", "Role Permissions") }),
901
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t("permissions.description", "Configure Socket.IO permissions per user role") })
902
+ ] }),
903
+ availableRoles.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Root, { children: availableRoles.map((role) => {
904
+ const rolePerms = settings.rolePermissions?.[role.type] || {};
905
+ const canConnect = rolePerms.canConnect ?? true;
906
+ const enabledContentTypes = Object.entries(rolePerms.contentTypes || {}).filter(
907
+ ([uid, actions]) => actions.create || actions.update || actions.delete
908
+ ).length;
909
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Accordion.Item, { value: role.type, children: [
910
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", width: "100%", paddingRight: 4, alignItems: "flex-start", children: [
911
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", gap: 1, children: [
912
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", children: role.name }),
913
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: [
914
+ "(",
915
+ enabledContentTypes,
916
+ " ",
917
+ t("permissions.contentTypesEnabled", "content types enabled"),
918
+ ")"
919
+ ] })
920
+ ] }),
921
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { active: canConnect, children: canConnect ? t("permissions.canConnect", "Can Connect") : t("permissions.blocked", "Blocked") })
922
+ ] }) }) }),
923
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Content, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 4, background: "neutral100", children: [
924
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingBottom: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "center", children: [
925
+ /* @__PURE__ */ jsxRuntime.jsx(
926
+ designSystem.Checkbox,
927
+ {
928
+ checked: canConnect,
929
+ onCheckedChange: (checked) => updateSettings((prev) => ({
930
+ ...prev,
931
+ rolePermissions: {
932
+ ...prev.rolePermissions,
933
+ [role.type]: {
934
+ ...prev.rolePermissions?.[role.type],
935
+ canConnect: checked
936
+ }
937
+ }
938
+ }))
939
+ }
940
+ ),
941
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", gap: 1, children: [
942
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", children: t("permissions.allowConnection", "Allow Connection") }),
943
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t("permissions.allowConnectionHint", "Users with this role can connect to Socket.IO") })
944
+ ] })
945
+ ] }) }),
946
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingBottom: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "center", children: [
947
+ /* @__PURE__ */ jsxRuntime.jsx(
948
+ designSystem.Checkbox,
949
+ {
950
+ checked: rolePerms.allowCredentials ?? true,
951
+ onCheckedChange: (checked) => updateSettings((prev) => ({
952
+ ...prev,
953
+ rolePermissions: {
954
+ ...prev.rolePermissions,
955
+ [role.type]: {
956
+ ...prev.rolePermissions?.[role.type],
957
+ allowCredentials: checked
958
+ }
959
+ }
960
+ }))
961
+ }
962
+ ),
963
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", gap: 1, children: [
964
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", children: t("permissions.allowCredentials", "Allow Credentials") }),
965
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t("permissions.allowCredentialsHint", "Allow cookies and auth headers") })
966
+ ] })
967
+ ] }) }),
968
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { paddingBottom: 4, children: [
969
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", paddingBottom: 2, children: t("permissions.allowedMethods", "Allowed HTTP Methods") }),
970
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, wrap: "wrap", children: httpMethods.map((method) => /* @__PURE__ */ jsxRuntime.jsx(
971
+ designSystem.Box,
972
+ {
973
+ padding: 2,
974
+ paddingLeft: 3,
975
+ paddingRight: 3,
976
+ background: rolePerms.allowedMethods?.includes(method) ? "primary100" : "neutral100",
977
+ hasRadius: true,
978
+ style: {
979
+ cursor: "pointer",
980
+ border: `1px solid ${rolePerms.allowedMethods?.includes(method) ? "#4945ff" : "#dcdce4"}`
981
+ },
982
+ onClick: () => {
983
+ const current = rolePerms.allowedMethods || [];
984
+ const updated = current.includes(method) ? current.filter((m) => m !== method) : [...current, method];
985
+ updateSettings((prev) => ({
986
+ ...prev,
987
+ rolePermissions: {
988
+ ...prev.rolePermissions,
989
+ [role.type]: {
990
+ ...prev.rolePermissions?.[role.type],
991
+ allowedMethods: updated
992
+ }
993
+ }
994
+ }));
995
+ },
996
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", children: [
997
+ /* @__PURE__ */ jsxRuntime.jsx(
998
+ designSystem.Checkbox,
999
+ {
1000
+ checked: rolePerms.allowedMethods?.includes(method) || false,
1001
+ onCheckedChange: () => {
1002
+ }
1003
+ }
1004
+ ),
1005
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", children: method })
1006
+ ] })
1007
+ },
1008
+ method
1009
+ )) })
1010
+ ] }),
1011
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, {}),
1012
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { paddingTop: 4, children: [
1013
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", paddingBottom: 3, children: [
1014
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", children: t("permissions.contentTypePermissions", "Content Type Permissions") }),
1015
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
1016
+ /* @__PURE__ */ jsxRuntime.jsx(
1017
+ designSystem.Button,
1018
+ {
1019
+ size: "S",
1020
+ variant: "secondary",
1021
+ onClick: () => enableAllContentTypes(role.type),
1022
+ children: t("permissions.enableAll", "Enable All")
1023
+ }
1024
+ ),
1025
+ /* @__PURE__ */ jsxRuntime.jsx(
1026
+ designSystem.Button,
1027
+ {
1028
+ size: "S",
1029
+ variant: "tertiary",
1030
+ onClick: () => disableAllContentTypes(role.type),
1031
+ children: t("permissions.disableAll", "Disable All")
1032
+ }
1033
+ )
1034
+ ] })
1035
+ ] }),
1036
+ availableContentTypes.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { background: "neutral0", hasRadius: true, style: { border: "1px solid #dcdce4" }, children: [
1037
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 2, background: "neutral100", style: { borderBottom: "1px solid #dcdce4" }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { children: [
1038
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", children: t("events.contentType", "CONTENT TYPE") }) }),
1039
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", children: t("events.create", "CREATE") }) }) }),
1040
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", children: t("events.update", "UPDATE") }) }) }),
1041
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", children: t("events.delete", "DELETE") }) }) }),
1042
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "sigma", textColor: "neutral600", children: [
1043
+ t("entitySubscriptions.allow", "ENTITIES"),
1044
+ " 🆕"
1045
+ ] }) }) })
1046
+ ] }) }),
1047
+ availableContentTypes.map((ct, idx) => {
1048
+ const hasAnyPermission = rolePerms.contentTypes?.[ct.uid]?.create || rolePerms.contentTypes?.[ct.uid]?.update || rolePerms.contentTypes?.[ct.uid]?.delete;
1049
+ settings.entitySubscriptions?.allowedContentTypes?.includes(ct.uid) || settings.entitySubscriptions?.allowedContentTypes?.length === 0;
1050
+ return /* @__PURE__ */ jsxRuntime.jsx(
1051
+ designSystem.Box,
1052
+ {
1053
+ padding: 2,
1054
+ style: {
1055
+ borderBottom: idx < availableContentTypes.length - 1 ? "1px solid #dcdce4" : "none",
1056
+ opacity: hasAnyPermission ? 1 : 0.5
1057
+ },
1058
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { children: [
1059
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", children: ct.displayName }) }),
1060
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(
1061
+ designSystem.Checkbox,
1062
+ {
1063
+ checked: rolePerms.contentTypes?.[ct.uid]?.create || false,
1064
+ onCheckedChange: (checked) => updateSettings((prev) => ({
1065
+ ...prev,
1066
+ rolePermissions: {
1067
+ ...prev.rolePermissions,
1068
+ [role.type]: {
1069
+ ...prev.rolePermissions?.[role.type],
1070
+ contentTypes: {
1071
+ ...prev.rolePermissions?.[role.type]?.contentTypes,
1072
+ [ct.uid]: {
1073
+ ...prev.rolePermissions?.[role.type]?.contentTypes?.[ct.uid],
1074
+ create: checked
1075
+ }
1076
+ }
1077
+ }
1078
+ }
1079
+ }))
1080
+ }
1081
+ ) }) }),
1082
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(
1083
+ designSystem.Checkbox,
1084
+ {
1085
+ checked: rolePerms.contentTypes?.[ct.uid]?.update || false,
1086
+ onCheckedChange: (checked) => updateSettings((prev) => ({
1087
+ ...prev,
1088
+ rolePermissions: {
1089
+ ...prev.rolePermissions,
1090
+ [role.type]: {
1091
+ ...prev.rolePermissions?.[role.type],
1092
+ contentTypes: {
1093
+ ...prev.rolePermissions?.[role.type]?.contentTypes,
1094
+ [ct.uid]: {
1095
+ ...prev.rolePermissions?.[role.type]?.contentTypes?.[ct.uid],
1096
+ update: checked
1097
+ }
1098
+ }
1099
+ }
1100
+ }
1101
+ }))
1102
+ }
1103
+ ) }) }),
1104
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(
1105
+ designSystem.Checkbox,
1106
+ {
1107
+ checked: rolePerms.contentTypes?.[ct.uid]?.delete || false,
1108
+ onCheckedChange: (checked) => updateSettings((prev) => ({
1109
+ ...prev,
1110
+ rolePermissions: {
1111
+ ...prev.rolePermissions,
1112
+ [role.type]: {
1113
+ ...prev.rolePermissions?.[role.type],
1114
+ contentTypes: {
1115
+ ...prev.rolePermissions?.[role.type]?.contentTypes,
1116
+ [ct.uid]: {
1117
+ ...prev.rolePermissions?.[role.type]?.contentTypes?.[ct.uid],
1118
+ delete: checked
1119
+ }
1120
+ }
1121
+ }
1122
+ }
1123
+ }))
1124
+ }
1125
+ ) }) }),
1126
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: settings.entitySubscriptions?.enabled ? /* @__PURE__ */ jsxRuntime.jsx(
1127
+ designSystem.Checkbox,
1128
+ {
1129
+ checked: hasAnyPermission && (settings.entitySubscriptions?.allowedContentTypes?.length === 0 || settings.entitySubscriptions?.allowedContentTypes?.includes(ct.uid)),
1130
+ disabled: !hasAnyPermission,
1131
+ onCheckedChange: (checked) => {
1132
+ if (!hasAnyPermission) return;
1133
+ const current = settings.entitySubscriptions?.allowedContentTypes || [];
1134
+ let updated;
1135
+ if (current.length === 0) {
1136
+ if (!checked) {
1137
+ updated = availableContentTypes.filter((t2) => t2.uid !== ct.uid).map((t2) => t2.uid);
1138
+ } else {
1139
+ updated = [];
1140
+ }
1141
+ } else {
1142
+ if (checked) {
1143
+ updated = [...current, ct.uid];
1144
+ } else {
1145
+ updated = current.filter((uid) => uid !== ct.uid);
1146
+ }
1147
+ }
1148
+ updateEntitySubscriptions("allowedContentTypes", updated);
1149
+ }
1150
+ }
1151
+ ) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Checkbox, { checked: false, disabled: true }) }) })
1152
+ ] })
1153
+ },
1154
+ ct.uid
1155
+ );
1156
+ })
1157
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 4, background: "neutral100", hasRadius: true, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: t("events.noContentTypes", "No content types found") }) })
1158
+ ] })
1159
+ ] }) })
1160
+ ] }, role.id);
1161
+ }) }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 4, background: "neutral100", hasRadius: true, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: t("permissions.noRoles", "No roles found") }) }),
1162
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 6, paddingBottom: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, {}) }),
1163
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { paddingBottom: 4, children: [
1164
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", as: "h2", children: t("redis.title", "Redis Adapter") }),
1165
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t("redis.description", "Enable Redis for multi-server scaling") })
1166
+ ] }),
1167
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { gap: 4, children: [
1168
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsxRuntime.jsx(
1169
+ designSystem.Box,
1170
+ {
1171
+ padding: 4,
1172
+ background: settings.redis?.enabled ? "danger100" : "neutral0",
1173
+ hasRadius: true,
1174
+ style: {
1175
+ cursor: "pointer",
1176
+ border: `2px solid ${settings.redis?.enabled ? "#dc2626" : "#dcdce4"}`,
1177
+ transition: "all 0.2s ease",
1178
+ minHeight: "110px",
1179
+ display: "flex",
1180
+ alignItems: "center"
1181
+ },
1182
+ onClick: () => updateRedis("enabled", !settings.redis?.enabled),
1183
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "center", style: { width: "100%" }, children: [
1184
+ /* @__PURE__ */ jsxRuntime.jsx(
1185
+ designSystem.Toggle,
1186
+ {
1187
+ checked: settings.redis?.enabled || false,
1188
+ onChange: (e) => updateRedis("enabled", e.target.checked)
1189
+ }
1190
+ ),
1191
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", gap: 1, children: [
1192
+ /* @__PURE__ */ jsxRuntime.jsx(
1193
+ designSystem.Typography,
1194
+ {
1195
+ variant: "omega",
1196
+ fontWeight: settings.redis?.enabled ? "bold" : "normal",
1197
+ textColor: settings.redis?.enabled ? "danger700" : "neutral800",
1198
+ children: t("redis.enable", "Enable Redis Adapter")
1199
+ }
1200
+ ),
1201
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "12px" }, children: settings.redis?.enabled ? "✓ Active" : "Inactive" })
1202
+ ] })
1203
+ ] })
1204
+ }
1205
+ ) }),
1206
+ settings.redis?.enabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(ResponsiveField, { children: [
1207
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t("redis.url", "Redis URL") }),
1208
+ /* @__PURE__ */ jsxRuntime.jsx(InputWrapper, { children: /* @__PURE__ */ jsxRuntime.jsx(
1209
+ designSystem.TextInput,
1210
+ {
1211
+ value: settings.redis?.url || "redis://localhost:6379",
1212
+ onChange: (e) => updateRedis("url", e.target.value),
1213
+ placeholder: "redis://localhost:6379"
1214
+ }
1215
+ ) })
1216
+ ] }) })
1217
+ ] }),
1218
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 4, paddingBottom: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, {}) }),
1219
+ /* @__PURE__ */ jsxRuntime.jsxs(ResponsiveSection, { children: [
1220
+ /* @__PURE__ */ jsxRuntime.jsx(ResponsiveSectionTitle, { variant: "delta", as: "h2", children: t("namespaces.title", "Namespaces") }),
1221
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t("namespaces.description", "Create separate Socket.IO endpoints") })
1222
+ ] }),
1223
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { gap: 3, children: [
1224
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxRuntime.jsx(
1225
+ designSystem.Box,
1226
+ {
1227
+ padding: 4,
1228
+ background: settings.namespaces?.enabled ? "secondary100" : "neutral0",
1229
+ hasRadius: true,
1230
+ style: {
1231
+ cursor: "pointer",
1232
+ border: `2px solid ${settings.namespaces?.enabled ? "#a855f7" : "#dcdce4"}`,
1233
+ transition: "all 0.2s ease",
1234
+ minHeight: "110px",
1235
+ display: "flex",
1236
+ alignItems: "center"
1237
+ },
1238
+ onClick: () => updateNamespaces("enabled", !settings.namespaces?.enabled),
1239
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "center", style: { width: "100%" }, children: [
1240
+ /* @__PURE__ */ jsxRuntime.jsx(
1241
+ designSystem.Toggle,
1242
+ {
1243
+ checked: settings.namespaces?.enabled || false,
1244
+ onChange: (e) => updateNamespaces("enabled", e.target.checked)
1245
+ }
1246
+ ),
1247
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", gap: 1, children: [
1248
+ /* @__PURE__ */ jsxRuntime.jsx(
1249
+ designSystem.Typography,
1250
+ {
1251
+ variant: "omega",
1252
+ fontWeight: settings.namespaces?.enabled ? "bold" : "normal",
1253
+ textColor: settings.namespaces?.enabled ? "secondary700" : "neutral800",
1254
+ children: t("namespaces.enable", "Enable Namespaces")
1255
+ }
1256
+ ),
1257
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "12px" }, children: settings.namespaces?.enabled ? "✓ Active" : "Inactive" })
1258
+ ] })
1259
+ ] })
1260
+ }
1261
+ ) }),
1262
+ settings.namespaces?.enabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(ResponsiveField, { children: [
1263
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t("namespaces.list", "Namespaces") }),
1264
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: { base: "column", tablet: "row" }, gap: 2, paddingBottom: 2, children: [
1265
+ /* @__PURE__ */ jsxRuntime.jsx(InputWrapper, { style: { flex: 1, width: "100%" }, children: /* @__PURE__ */ jsxRuntime.jsx(
1266
+ designSystem.TextInput,
1267
+ {
1268
+ placeholder: "admin",
1269
+ value: newNamespace,
1270
+ onChange: (e) => setNewNamespace(e.target.value),
1271
+ onKeyPress: (e) => e.key === "Enter" && addNamespace()
1272
+ }
1273
+ ) }),
1274
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: addNamespace, size: "L", style: { width: "100%", maxWidth: "200px", minHeight: "44px" }, children: t("namespaces.add", "Add") })
1275
+ ] }),
1276
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, wrap: "wrap", paddingTop: 2, children: Object.entries(settings.namespaces?.list || {}).map(([ns, config]) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 1, alignItems: "center", children: [
1277
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { children: [
1278
+ "/",
1279
+ ns,
1280
+ config.requireAuth && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { marginLeft: "4px" }, children: "🔒" }),
1281
+ /* @__PURE__ */ jsxRuntime.jsx(
1282
+ designSystem.Button,
1283
+ {
1284
+ variant: "ghost",
1285
+ size: "S",
1286
+ onClick: () => removeNamespace(ns),
1287
+ style: { marginLeft: "8px", padding: "0 4px" },
1288
+ children: "×"
1289
+ }
1290
+ )
1291
+ ] }),
1292
+ config.requireAuth && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", style: { fontSize: "11px" }, children: t("namespaces.authRequired", "Auth required") })
1293
+ ] }, ns)) }),
1294
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", children: t("namespaces.hint", "Examples: admin, chat, notifications") }) })
1295
+ ] }) })
1296
+ ] }),
1297
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 4, paddingBottom: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, {}) }),
1298
+ /* @__PURE__ */ jsxRuntime.jsx(ResponsiveSection, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", children: [
1299
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
1300
+ /* @__PURE__ */ jsxRuntime.jsxs(ResponsiveSectionTitle, { variant: "delta", as: "h2", children: [
1301
+ t("entitySubscriptions.title", "Entity Subscriptions"),
1302
+ " 🆕"
1303
+ ] }),
1304
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t("entitySubscriptions.description", "Allow clients to subscribe to specific entities") })
1305
+ ] }),
1306
+ /* @__PURE__ */ jsxRuntime.jsx(
1307
+ designSystem.Toggle,
1308
+ {
1309
+ checked: settings.entitySubscriptions?.enabled ?? true,
1310
+ onChange: (e) => updateEntitySubscriptions("enabled", e.target.checked)
1311
+ }
1312
+ )
1313
+ ] }) }),
1314
+ settings.entitySubscriptions?.enabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 3, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { gap: 3, children: [
1315
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(ResponsiveField, { children: [
1316
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t("entitySubscriptions.maxPerSocket", "Max Per Socket") }),
1317
+ /* @__PURE__ */ jsxRuntime.jsx(InputWrapper, { children: /* @__PURE__ */ jsxRuntime.jsx(
1318
+ designSystem.NumberInput,
1319
+ {
1320
+ value: settings.entitySubscriptions?.maxSubscriptionsPerSocket ?? 100,
1321
+ onValueChange: (value) => updateEntitySubscriptions("maxSubscriptionsPerSocket", value)
1322
+ }
1323
+ ) })
1324
+ ] }) }),
1325
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", paddingTop: 6, children: [
1326
+ /* @__PURE__ */ jsxRuntime.jsx(
1327
+ designSystem.Checkbox,
1328
+ {
1329
+ checked: settings.entitySubscriptions?.requireVerification ?? true,
1330
+ onCheckedChange: (checked) => updateEntitySubscriptions("requireVerification", checked)
1331
+ }
1332
+ ),
1333
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", children: t("entitySubscriptions.verify", "Verify Entity Exists") })
1334
+ ] }) }),
1335
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", paddingTop: 6, children: [
1336
+ /* @__PURE__ */ jsxRuntime.jsx(
1337
+ designSystem.Checkbox,
1338
+ {
1339
+ checked: settings.entitySubscriptions?.enableMetrics ?? true,
1340
+ onCheckedChange: (checked) => updateEntitySubscriptions("enableMetrics", checked)
1341
+ }
1342
+ ),
1343
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", children: t("entitySubscriptions.metrics", "Track Metrics") })
1344
+ ] }) })
1345
+ ] }) }),
1346
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 4, paddingBottom: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, {}) }),
1347
+ /* @__PURE__ */ jsxRuntime.jsx(ResponsiveSection, { children: /* @__PURE__ */ jsxRuntime.jsx(ResponsiveSectionTitle, { variant: "delta", as: "h2", children: t("monitoring.title", "Monitoring & Logging") }) }),
1348
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { gap: 3, children: [
1349
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxRuntime.jsx(
1350
+ designSystem.Box,
1351
+ {
1352
+ padding: 4,
1353
+ background: settings.monitoring?.enableConnectionLogging ? "primary100" : "neutral0",
1354
+ hasRadius: true,
1355
+ style: { cursor: "pointer", border: `1px solid ${settings.monitoring?.enableConnectionLogging ? "#4945ff" : "#dcdce4"}` },
1356
+ onClick: () => updateMonitoring("enableConnectionLogging", !settings.monitoring?.enableConnectionLogging),
1357
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "center", children: [
1358
+ /* @__PURE__ */ jsxRuntime.jsx(
1359
+ designSystem.Checkbox,
1360
+ {
1361
+ checked: settings.monitoring?.enableConnectionLogging || false,
1362
+ onCheckedChange: (checked) => updateMonitoring("enableConnectionLogging", checked)
1363
+ }
1364
+ ),
1365
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", gap: 1, children: [
1366
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", children: t("monitoring.connectionLogging", "Connection Logging") }),
1367
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t("monitoring.connectionLoggingHint", "Log client connections") })
1368
+ ] })
1369
+ ] })
1370
+ }
1371
+ ) }),
1372
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsxRuntime.jsx(
1373
+ designSystem.Box,
1374
+ {
1375
+ padding: 4,
1376
+ background: settings.monitoring?.enableEventLogging ? "primary100" : "neutral0",
1377
+ hasRadius: true,
1378
+ style: { cursor: "pointer", border: `1px solid ${settings.monitoring?.enableEventLogging ? "#4945ff" : "#dcdce4"}` },
1379
+ onClick: () => updateMonitoring("enableEventLogging", !settings.monitoring?.enableEventLogging),
1380
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "center", children: [
1381
+ /* @__PURE__ */ jsxRuntime.jsx(
1382
+ designSystem.Checkbox,
1383
+ {
1384
+ checked: settings.monitoring?.enableEventLogging || false,
1385
+ onCheckedChange: (checked) => updateMonitoring("enableEventLogging", checked)
1386
+ }
1387
+ ),
1388
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", gap: 1, children: [
1389
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", children: t("monitoring.eventLogging", "Event Logging") }),
1390
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t("monitoring.eventLoggingHint", "Log all events for debugging") })
1391
+ ] })
1392
+ ] })
1393
+ }
1394
+ ) }),
1395
+ settings.monitoring?.enableEventLogging && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 12, s: 12, children: /* @__PURE__ */ jsxRuntime.jsx(ResponsiveField, { children: /* @__PURE__ */ jsxRuntime.jsx(InputWrapper, { children: /* @__PURE__ */ jsxRuntime.jsx(
1396
+ designSystem.NumberInput,
1397
+ {
1398
+ label: t("monitoring.maxLogSize", "Max Log Size"),
1399
+ value: settings.monitoring?.maxEventLogSize || 100,
1400
+ onValueChange: (value) => updateMonitoring("maxEventLogSize", value)
1401
+ }
1402
+ ) }) }) })
1403
+ ] })
1404
+ ] }),
1405
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 3, padding: 3, background: "success100", hasRadius: true, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", children: [
1406
+ /* @__PURE__ */ jsxRuntime.jsx(icons.Check, {}),
1407
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", style: { fontSize: "13px" }, children: t("settings.noRestart", "Changes are applied immediately – no restart required!") })
1408
+ ] }) })
1409
+ ] }) });
1410
+ };
1411
+ exports.SettingsPage = SettingsPage;