Design as decided 2026-10-21 (replaces the raw-JSON egress editor idea): the forwarding form lives on the inbound, and the entry agent's egress entries are compiled from it on every config pull — never snapshotted. - model: Inbound.Forwarding (JSON text) via AutoMigrate; panel-side metadata only, never reaches xray itself - service/forwarding.go: ForwardingSpec (mode direct/forward; landing managed|manual), save-time validation (managed target must exist and be a SOCKS-family landing — the fork's SK5 inbound is 'mixed'; no self-forward; manual endpoint/protocol sanity), live resolution (managed: concrete listen IP wins, else hosting node's address; credentials from the target's first account), and the compiler that appends one socks/http outbound (tag fwd-<inboundId>) plus a prepended inboundTag rule per forwarding inbound - buildXrayConfig agent path: compile runs after applyAgentEgress, so entries ride on the live template (or stored egress override) and template edits keep flowing; unresolvable entries skip with a warning instead of failing the whole config - UpdateInbound's field-merge now carries Forwarding (its absence was caught by the smoke: adds worked, updates silently kept the old spec) - GET /panel/api/inbounds/forwardTargets: managed-landing candidates (id/remark/tag/listen/port/node name) — credentials never exposed - frontend: new Forwarding tab in the inbound form (mode, landing type, managed picker, manual endpoint with link import incl. base64 form), adapter round-trips the spec as a JSON string like settings; en/zh strings; generated API types refreshed Acceptance: unit tests for parse/validate/resolve/compile incl. the dynamic-recompile proof (template edit + spec edit both reflected), and an end-to-end smoke (real binary, two agent nodes, all inbound writes in browser form-urlencoded format): 22/22 PASS — see P9-REPORT.md.
707 lines
14 KiB
TypeScript
707 lines
14 KiB
TypeScript
// Code generated by tools/openapigen. DO NOT EDIT.
|
|
export const EXAMPLES: Record<string, unknown> = {
|
|
"AllSetting": {
|
|
"datepicker": "",
|
|
"expireDiff": 0,
|
|
"ipLimitAllowlist": "",
|
|
"outboundDownThreshold": 1,
|
|
"pageSize": 0,
|
|
"panelOutbound": "",
|
|
"remarkTemplate": "",
|
|
"restartXrayOnClientDisable": false,
|
|
"sessionMaxAge": 1,
|
|
"subAnnounce": "",
|
|
"subCertFile": "",
|
|
"subClashAutoDetect": false,
|
|
"subClashEnable": false,
|
|
"subClashPath": "",
|
|
"subClashURI": "",
|
|
"subClashUserAgentRegex": "",
|
|
"subDomain": "",
|
|
"subEnable": false,
|
|
"subEncrypt": false,
|
|
"subHideSettings": false,
|
|
"subJsonAlwaysArray": false,
|
|
"subJsonAutoDetect": false,
|
|
"subJsonEnable": false,
|
|
"subJsonFinalMask": "",
|
|
"subJsonMux": "",
|
|
"subJsonObservatory": "",
|
|
"subJsonPath": "",
|
|
"subJsonURI": "",
|
|
"subJsonUserAgentRegex": "",
|
|
"subKeyFile": "",
|
|
"subListen": "",
|
|
"subPath": "",
|
|
"subPort": 0,
|
|
"subProfileUrl": "",
|
|
"subShowIdentityOnAllLinks": false,
|
|
"subSupportUrl": "",
|
|
"subThemeDir": "",
|
|
"subTitle": "",
|
|
"subURI": "",
|
|
"subUpdates": 0,
|
|
"tgBotAPIServer": "",
|
|
"tgBotBackup": false,
|
|
"tgBotChatId": "",
|
|
"tgBotEnable": false,
|
|
"tgBotProxy": "",
|
|
"tgBotToken": "",
|
|
"tgCpu": 0,
|
|
"tgEnabledEvents": "",
|
|
"tgLang": "",
|
|
"tgMemory": 0,
|
|
"tgRunTime": "",
|
|
"timeLocation": "",
|
|
"trafficDiff": 0,
|
|
"trustedProxyCIDRs": "",
|
|
"warpUpdateInterval": 0,
|
|
"webBasePath": "",
|
|
"webCertFile": "",
|
|
"webDomain": "",
|
|
"webKeyFile": "",
|
|
"webListen": "",
|
|
"webPort": 1
|
|
},
|
|
"AllSettingView": {
|
|
"datepicker": "",
|
|
"expireDiff": 0,
|
|
"hasApiToken": false,
|
|
"hasNordSecret": false,
|
|
"hasTgBotToken": false,
|
|
"hasWarpSecret": false,
|
|
"ipLimitAllowlist": "",
|
|
"outboundDownThreshold": 1,
|
|
"pageSize": 0,
|
|
"panelOutbound": "",
|
|
"remarkTemplate": "",
|
|
"restartXrayOnClientDisable": false,
|
|
"sessionMaxAge": 1,
|
|
"subAnnounce": "",
|
|
"subCertFile": "",
|
|
"subClashAutoDetect": false,
|
|
"subClashEnable": false,
|
|
"subClashPath": "",
|
|
"subClashURI": "",
|
|
"subClashUserAgentRegex": "",
|
|
"subDomain": "",
|
|
"subEnable": false,
|
|
"subEncrypt": false,
|
|
"subHideSettings": false,
|
|
"subJsonAlwaysArray": false,
|
|
"subJsonAutoDetect": false,
|
|
"subJsonEnable": false,
|
|
"subJsonFinalMask": "",
|
|
"subJsonMux": "",
|
|
"subJsonObservatory": "",
|
|
"subJsonPath": "",
|
|
"subJsonURI": "",
|
|
"subJsonUserAgentRegex": "",
|
|
"subKeyFile": "",
|
|
"subListen": "",
|
|
"subPath": "",
|
|
"subPort": 0,
|
|
"subProfileUrl": "",
|
|
"subShowIdentityOnAllLinks": false,
|
|
"subSupportUrl": "",
|
|
"subThemeDir": "",
|
|
"subTitle": "",
|
|
"subURI": "",
|
|
"subUpdates": 0,
|
|
"tgBotAPIServer": "",
|
|
"tgBotBackup": false,
|
|
"tgBotChatId": "",
|
|
"tgBotEnable": false,
|
|
"tgBotProxy": "",
|
|
"tgBotToken": "",
|
|
"tgCpu": 0,
|
|
"tgEnabledEvents": "",
|
|
"tgLang": "",
|
|
"tgMemory": 0,
|
|
"tgRunTime": "",
|
|
"timeLocation": "",
|
|
"trafficDiff": 0,
|
|
"trustedProxyCIDRs": "",
|
|
"warpUpdateInterval": 0,
|
|
"webBasePath": "",
|
|
"webCertFile": "",
|
|
"webDomain": "",
|
|
"webKeyFile": "",
|
|
"webListen": "",
|
|
"webPort": 1
|
|
},
|
|
"ApiToken": {
|
|
"createdAt": 0,
|
|
"enabled": false,
|
|
"expiresAt": 0,
|
|
"id": 0,
|
|
"name": "",
|
|
"scope": "",
|
|
"token": ""
|
|
},
|
|
"ApiTokenView": {
|
|
"createdAt": 1736000000,
|
|
"enabled": true,
|
|
"expiresAt": 0,
|
|
"id": 2,
|
|
"name": "central-panel-a",
|
|
"scope": "admin",
|
|
"token": "new-token-string"
|
|
},
|
|
"Client": {
|
|
"adTag": "0123456789abcdef0123456789abcdef",
|
|
"allowedIPs": [
|
|
""
|
|
],
|
|
"allowedIPsByInbound": {},
|
|
"auth": "",
|
|
"comment": "",
|
|
"created_at": 0,
|
|
"email": "",
|
|
"enable": false,
|
|
"expiryTime": 0,
|
|
"flow": "",
|
|
"forwardedPorts": "",
|
|
"group": "",
|
|
"id": "",
|
|
"keepAlive": 0,
|
|
"limitIp": 0,
|
|
"password": "",
|
|
"preSharedKey": "",
|
|
"privateKey": "",
|
|
"publicKey": "",
|
|
"reset": 0,
|
|
"resetDay": 0,
|
|
"resetMax": 0,
|
|
"reverse": null,
|
|
"secret": "ee1234567890abcdef1234567890abcd7777772e636c6f7564666c6172652e636f6d",
|
|
"security": "",
|
|
"subId": "",
|
|
"tgId": 0,
|
|
"totalGB": 0,
|
|
"trafficReset": "never",
|
|
"trafficResetDay": 1,
|
|
"updated_at": 0
|
|
},
|
|
"ClientInbound": {
|
|
"clientId": 0,
|
|
"createdAt": 0,
|
|
"flowOverride": "",
|
|
"inboundId": 0
|
|
},
|
|
"ClientRecord": {
|
|
"adTag": "",
|
|
"allowedIPs": "",
|
|
"auth": "",
|
|
"comment": "",
|
|
"createdAt": 0,
|
|
"email": "",
|
|
"enable": false,
|
|
"expiryTime": 0,
|
|
"flow": "",
|
|
"forwardedPorts": "",
|
|
"group": "",
|
|
"id": 0,
|
|
"keepAlive": 0,
|
|
"limitHwid": 0,
|
|
"limitIp": 0,
|
|
"password": "",
|
|
"preSharedKey": "",
|
|
"privateKey": "",
|
|
"publicKey": "",
|
|
"reset": 0,
|
|
"resetDay": 0,
|
|
"resetMax": 0,
|
|
"reverse": null,
|
|
"secret": "",
|
|
"security": "",
|
|
"subId": "",
|
|
"tgId": 0,
|
|
"totalGB": 0,
|
|
"trafficReset": "",
|
|
"trafficResetDay": 0,
|
|
"updatedAt": 0,
|
|
"uuid": ""
|
|
},
|
|
"ClientReverse": {
|
|
"tag": ""
|
|
},
|
|
"ClientTraffic": {
|
|
"down": 2097152,
|
|
"email": "user1",
|
|
"enable": true,
|
|
"expiryTime": 1735689600000,
|
|
"id": 14825,
|
|
"inboundId": 1,
|
|
"lastOnline": 1735680000000,
|
|
"lastSubFetch": 1735680000000,
|
|
"reset": 0,
|
|
"resetCount": 0,
|
|
"resetDay": 0,
|
|
"resetMax": 0,
|
|
"subId": "i7tvdpeffi0hvvf1",
|
|
"total": 10737418240,
|
|
"up": 1048576,
|
|
"uuid": "e18c9a96-71bf-48d4-933f-8b9a46d4290c"
|
|
},
|
|
"FallbackParentInfo": {
|
|
"masterId": 0,
|
|
"path": ""
|
|
},
|
|
"GeoCategory": {
|
|
"attributes": [
|
|
"ads",
|
|
"cn"
|
|
],
|
|
"code": "google",
|
|
"entries": 1284
|
|
},
|
|
"GeoCategoryPage": {
|
|
"items": [
|
|
{
|
|
"attributes": [
|
|
"ads",
|
|
"cn"
|
|
],
|
|
"code": "google",
|
|
"entries": 1284
|
|
}
|
|
],
|
|
"total": 1043
|
|
},
|
|
"GeoEntry": {
|
|
"kind": "domain",
|
|
"value": "google.com"
|
|
},
|
|
"GeoEntryPage": {
|
|
"items": [
|
|
{
|
|
"kind": "domain",
|
|
"value": "google.com"
|
|
}
|
|
],
|
|
"total": 1284
|
|
},
|
|
"GeoFile": {
|
|
"categories": 1043,
|
|
"error": "",
|
|
"kind": "site",
|
|
"modifiedAt": 1769558400000,
|
|
"name": "geosite.dat",
|
|
"size": 1467392
|
|
},
|
|
"GeodataTokenIssue": {
|
|
"code": "blabla",
|
|
"file": "geosite.dat",
|
|
"reason": "categoryMissing",
|
|
"token": "geosite:blabla"
|
|
},
|
|
"HistoryOfSeeders": {
|
|
"id": 0,
|
|
"seederName": ""
|
|
},
|
|
"Host": {
|
|
"address": "cdn.example.com",
|
|
"allowInsecure": false,
|
|
"alpn": [
|
|
""
|
|
],
|
|
"createdAt": 0,
|
|
"echConfigList": "",
|
|
"excludeFromSubTypes": [
|
|
""
|
|
],
|
|
"finalMask": "",
|
|
"fingerprint": "",
|
|
"groupId": "",
|
|
"hostHeader": "",
|
|
"id": 1,
|
|
"inboundId": 1,
|
|
"isDisabled": false,
|
|
"isHidden": false,
|
|
"keepSniBlank": false,
|
|
"mihomoIpVersion": "dual",
|
|
"mihomoX25519": false,
|
|
"muxParams": null,
|
|
"nodeGuids": [
|
|
""
|
|
],
|
|
"overrideSniFromAddress": false,
|
|
"path": "",
|
|
"pinnedPeerCertSha256": [
|
|
""
|
|
],
|
|
"port": 8443,
|
|
"remark": "cdn-front",
|
|
"security": "same",
|
|
"serverDescription": "",
|
|
"shuffleHost": false,
|
|
"sni": "",
|
|
"sockoptParams": null,
|
|
"sortOrder": 0,
|
|
"tags": [
|
|
""
|
|
],
|
|
"updatedAt": 0,
|
|
"verifyPeerCertByName": "",
|
|
"vlessRoute": "443"
|
|
},
|
|
"HostGroup": {
|
|
"allowInsecure": false,
|
|
"alpn": [
|
|
""
|
|
],
|
|
"echConfigList": "",
|
|
"excludeFromSubTypes": [
|
|
""
|
|
],
|
|
"finalMask": "",
|
|
"fingerprint": "",
|
|
"groupId": "",
|
|
"hostHeader": "",
|
|
"hosts": [
|
|
""
|
|
],
|
|
"inboundIds": [
|
|
0
|
|
],
|
|
"isDisabled": false,
|
|
"isHidden": false,
|
|
"keepSniBlank": false,
|
|
"mihomoIpVersion": "dual",
|
|
"mihomoX25519": false,
|
|
"muxParams": "",
|
|
"nodeGuids": [
|
|
""
|
|
],
|
|
"overrideSniFromAddress": false,
|
|
"path": "",
|
|
"pinnedPeerCertSha256": [
|
|
""
|
|
],
|
|
"port": 0,
|
|
"remark": "",
|
|
"security": "same",
|
|
"serverDescription": "",
|
|
"shuffleHost": false,
|
|
"sni": "",
|
|
"sockoptParams": "",
|
|
"sortOrder": 0,
|
|
"tags": [
|
|
""
|
|
],
|
|
"verifyPeerCertByName": "",
|
|
"vlessRoute": ""
|
|
},
|
|
"Inbound": {
|
|
"clientStats": [
|
|
{
|
|
"down": 2097152,
|
|
"email": "user1",
|
|
"enable": true,
|
|
"expiryTime": 1735689600000,
|
|
"id": 14825,
|
|
"inboundId": 1,
|
|
"lastOnline": 1735680000000,
|
|
"lastSubFetch": 1735680000000,
|
|
"reset": 0,
|
|
"resetCount": 0,
|
|
"resetDay": 0,
|
|
"resetMax": 0,
|
|
"subId": "i7tvdpeffi0hvvf1",
|
|
"total": 10737418240,
|
|
"up": 1048576,
|
|
"uuid": "e18c9a96-71bf-48d4-933f-8b9a46d4290c"
|
|
}
|
|
],
|
|
"disableFlow": false,
|
|
"down": 0,
|
|
"enable": true,
|
|
"expiryTime": 0,
|
|
"fallbackParent": null,
|
|
"forwarding": "",
|
|
"id": 1,
|
|
"lastTrafficResetTime": 0,
|
|
"listen": "",
|
|
"nodeId": null,
|
|
"originNodeGuid": "",
|
|
"port": 443,
|
|
"protocol": "vless",
|
|
"remark": "VLESS-443",
|
|
"settings": null,
|
|
"shareAddr": "",
|
|
"shareAddrStrategy": "node",
|
|
"sniffing": null,
|
|
"streamSettings": null,
|
|
"subSortIndex": 1,
|
|
"tag": "in-443-tcp",
|
|
"total": 0,
|
|
"trafficReset": "never",
|
|
"trafficResetDay": 1,
|
|
"up": 0
|
|
},
|
|
"InboundClientIps": {
|
|
"clientEmail": "",
|
|
"id": 0,
|
|
"ips": null
|
|
},
|
|
"InboundFallback": {
|
|
"alpn": "",
|
|
"childId": 0,
|
|
"dest": "",
|
|
"id": 0,
|
|
"masterId": 0,
|
|
"name": "",
|
|
"path": "",
|
|
"sortOrder": 0,
|
|
"xver": 0
|
|
},
|
|
"InboundOption": {
|
|
"awgServer": null,
|
|
"enable": true,
|
|
"id": 1,
|
|
"listen": "",
|
|
"mtprotoDomain": "",
|
|
"nodeAddress": "",
|
|
"nodeId": null,
|
|
"port": 443,
|
|
"protocol": "vless",
|
|
"remark": "VLESS-443",
|
|
"shareAddr": "",
|
|
"shareAddrStrategy": "",
|
|
"ssMethod": "",
|
|
"tag": "in-443-tcp",
|
|
"tlsFlowCapable": true,
|
|
"wgDns": "",
|
|
"wgMtu": 0,
|
|
"wgPublicKey": ""
|
|
},
|
|
"Msg": {
|
|
"msg": "",
|
|
"obj": null,
|
|
"success": false
|
|
},
|
|
"Node": {
|
|
"activeCount": 23,
|
|
"address": "node1.example.com",
|
|
"allowPrivateAddress": false,
|
|
"basePath": "/",
|
|
"clientCount": 27,
|
|
"configDirty": false,
|
|
"configDirtyAt": 0,
|
|
"cpuPct": 23.5,
|
|
"createdAt": 1700000000,
|
|
"depletedCount": 1,
|
|
"disabledCount": 3,
|
|
"enable": true,
|
|
"guid": "",
|
|
"id": 1,
|
|
"inboundCount": 5,
|
|
"inboundSyncMode": "all",
|
|
"inboundTags": [
|
|
""
|
|
],
|
|
"lastError": "",
|
|
"lastHeartbeat": 1700000000,
|
|
"latencyMs": 42,
|
|
"memPct": 45.1,
|
|
"name": "de-fra-1",
|
|
"netDown": 2097152,
|
|
"netUp": 1048576,
|
|
"onlineCount": 3,
|
|
"outboundTag": "",
|
|
"panelVersion": "v3.x.x",
|
|
"parentGuid": "",
|
|
"pinnedCertSha256": "",
|
|
"port": 2053,
|
|
"remark": "",
|
|
"scheme": "https",
|
|
"status": "online",
|
|
"tlsVerifyMode": "verify",
|
|
"transitive": false,
|
|
"updatedAt": 1700000000,
|
|
"uptimeSecs": 86400,
|
|
"xrayError": "",
|
|
"xrayState": "",
|
|
"xrayVersion": "25.10.31"
|
|
},
|
|
"NodeMutationRequest": {
|
|
"address": "",
|
|
"allowPrivateAddress": false,
|
|
"apiToken": null,
|
|
"basePath": "",
|
|
"clearApiToken": false,
|
|
"enable": false,
|
|
"id": 0,
|
|
"inboundSyncMode": "all",
|
|
"inboundTags": [
|
|
""
|
|
],
|
|
"name": "",
|
|
"nodeType": "traditional",
|
|
"outboundTag": "",
|
|
"pinnedCertSha256": "",
|
|
"port": 0,
|
|
"remark": "",
|
|
"scheme": "http",
|
|
"tlsVerifyMode": "verify"
|
|
},
|
|
"NodeView": {
|
|
"activeCount": 20,
|
|
"address": "node.example.com",
|
|
"allowPrivateAddress": false,
|
|
"basePath": "/",
|
|
"clientCount": 25,
|
|
"configDirty": false,
|
|
"configDirtyAt": 0,
|
|
"cpuPct": 12.5,
|
|
"createdAt": 1700000000,
|
|
"depletedCount": 1,
|
|
"disabledCount": 2,
|
|
"enable": true,
|
|
"guid": "node-guid",
|
|
"hasApiToken": true,
|
|
"id": 1,
|
|
"inboundCount": 3,
|
|
"inboundSyncMode": "all",
|
|
"inboundTags": [
|
|
"in-443-tcp"
|
|
],
|
|
"lastError": "",
|
|
"lastHeartbeat": 1700000000,
|
|
"latencyMs": 42,
|
|
"memPct": 45.2,
|
|
"name": "edge-1",
|
|
"netDown": 1048576,
|
|
"netUp": 2097152,
|
|
"nodeType": "traditional",
|
|
"onlineCount": 5,
|
|
"outboundTag": "direct",
|
|
"panelVersion": "v3.x.x",
|
|
"parentGuid": "",
|
|
"pinnedCertSha256": "",
|
|
"port": 2053,
|
|
"remark": "Primary edge",
|
|
"scheme": "https",
|
|
"status": "online",
|
|
"tlsVerifyMode": "verify",
|
|
"transitive": false,
|
|
"updatedAt": 1700003600,
|
|
"uptimeSecs": 86400,
|
|
"xrayError": "",
|
|
"xrayState": "running",
|
|
"xrayVersion": "25.10.31"
|
|
},
|
|
"OutboundTraffics": {
|
|
"down": 0,
|
|
"id": 0,
|
|
"tag": "",
|
|
"total": 0,
|
|
"up": 0
|
|
},
|
|
"PanelUpdateStatus": {
|
|
"exitCode": 0,
|
|
"finishedAt": 1735689612,
|
|
"runId": "1735689600123456789",
|
|
"state": "success"
|
|
},
|
|
"ProbeResultUI": {
|
|
"cpuPct": 12.5,
|
|
"error": "",
|
|
"latencyMs": 42,
|
|
"memPct": 45.2,
|
|
"panelVersion": "v3.x.x",
|
|
"status": "online",
|
|
"uptimeSecs": 86400,
|
|
"xrayError": "",
|
|
"xrayState": "",
|
|
"xrayVersion": "25.10.31"
|
|
},
|
|
"RealityScanResult": {
|
|
"alpn": "h2",
|
|
"certChainValid": true,
|
|
"certIssuer": "Google Trust Services",
|
|
"certSubject": "cloudflare.com",
|
|
"certValid": true,
|
|
"curveID": "X25519",
|
|
"feasible": true,
|
|
"h2": true,
|
|
"host": "www.cloudflare.com",
|
|
"ip": "104.16.124.96",
|
|
"latencyMs": 180,
|
|
"notAfter": "2026-08-01T00:00:00Z",
|
|
"port": 443,
|
|
"privateTarget": false,
|
|
"reason": "",
|
|
"serverNames": [
|
|
""
|
|
],
|
|
"target": "www.cloudflare.com:443",
|
|
"tls13": true,
|
|
"tlsVersion": "1.3",
|
|
"x25519": true
|
|
},
|
|
"ServerSettings": {
|
|
"contentPaddingAddition": "",
|
|
"disableCookies": false,
|
|
"externalInterface": "",
|
|
"h1": "",
|
|
"h2": "",
|
|
"h3": "",
|
|
"h4": "",
|
|
"headerProtectionKey": "",
|
|
"i1": "",
|
|
"i2": "",
|
|
"i3": "",
|
|
"i4": "",
|
|
"i5": "",
|
|
"ipv6Enabled": false,
|
|
"ipv6ExternalInterface": "",
|
|
"ipv6Subnet": "",
|
|
"jc": 0,
|
|
"jmax": 0,
|
|
"jmin": 0,
|
|
"keepaliveTimeout": "",
|
|
"maxHandshakeAttempts": "",
|
|
"mtu": 0,
|
|
"primaryDns": "",
|
|
"privateKey": "",
|
|
"publicKey": "",
|
|
"randomTrailers": false,
|
|
"rejectAfterTime": "",
|
|
"rekeyAfterTime": "",
|
|
"rekeyTimeout": "",
|
|
"routeThroughXray": false,
|
|
"s1": 0,
|
|
"s2": 0,
|
|
"s3": 0,
|
|
"s4": 0,
|
|
"secondaryDns": "",
|
|
"subnetCidr": 0,
|
|
"subnetIp": ""
|
|
},
|
|
"Setting": {
|
|
"id": 0,
|
|
"key": "",
|
|
"value": ""
|
|
},
|
|
"SubBalancer": {
|
|
"createdAt": 1710000000000,
|
|
"enabled": true,
|
|
"id": 1,
|
|
"inboundIds": [
|
|
1,
|
|
3
|
|
],
|
|
"remark": "auto-fastest",
|
|
"sortOrder": 1,
|
|
"strategy": "random",
|
|
"updatedAt": 1710000000000
|
|
},
|
|
"User": {
|
|
"id": 0,
|
|
"password": "",
|
|
"username": ""
|
|
}
|
|
};
|