Add node-datachannel stub with polyfill subpath for next build

@libp2p/webrtc imports @ipshipyard/node-datachannel/polyfill which
requires native C++ compilation. Stub provides ESM+CJS exports for
both main and polyfill subpaths with no-op WebRTC classes. Also
ignores pnpm-lock.yaml in cspell and copies stubs dir in Dockerfiles.
This commit is contained in:
2026-02-24 18:07:34 -08:00
parent 7049344343
commit cda4e3c4e8
10 changed files with 159 additions and 145 deletions
+1
View File
@@ -11,6 +11,7 @@ RUN corepack enable && corepack prepare [email protected] --activate
# Install dependencies
WORKDIR /app
COPY package.json pnpm-lock.yaml .npmrc ./
COPY stubs ./stubs
COPY tsconfig.json ./
COPY types ./types
COPY lib ./lib
+1
View File
@@ -8,6 +8,7 @@ WORKDIR /app
# Copy package files
COPY package.json pnpm-lock.yaml .npmrc ./
COPY stubs ./stubs
COPY tsconfig.json ./
COPY next.config.js ./
+2 -1
View File
@@ -14,7 +14,8 @@
"playwright/fixtures/rewards.ts",
"public/static/capybara/index.js",
"ui/showcases/utils.ts",
"ui/tx/TxExternalTxs.pw.tsx"
"ui/tx/TxExternalTxs.pw.tsx",
"pnpm-lock.yaml"
],
"enableGlobDot": true,
"ignoreRandomStrings": true,
+2 -1
View File
@@ -208,7 +208,8 @@
"node-forge": "1.3.2",
"brace-expansion": "1.1.12",
"js-yaml": "4.1.1",
"@noble/hashes": "1.8.0"
"@noble/hashes": "1.8.0",
"@ipshipyard/node-datachannel": "link:./stubs/node-datachannel"
}
},
"packageManager": "[email protected]"
+2 -143
View File
@@ -12,6 +12,7 @@ overrides:
brace-expansion: 1.1.12
js-yaml: 4.1.1
'@noble/hashes': 1.8.0
'@ipshipyard/node-datachannel': link:./stubs/node-datachannel
importers:
@@ -2522,10 +2523,6 @@ packages:
'@ipshipyard/[email protected]':
resolution: {integrity: sha512-wV1smnqbg3xUCHmPB8KWFuP8G9MKlx8KDuiJvhCWPi7B03xJq2FMybMDPI8tM9boa9sHD+5+NFu+Teo3Lz76fw==}
'@ipshipyard/[email protected]':
resolution: {integrity: sha512-70HdhYMyAGXEMuCUq9ATO1Rx/JmiENM5LrGN94KT/q/Et2VsMjJpOWbyFzgodtkQJjDG5saNXTOiQpYZ1AnvEg==}
engines: {node: '>=18.20.0'}
'@isaacs/[email protected]':
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
engines: {node: '>=12'}
@@ -6539,9 +6536,6 @@ packages:
[email protected]:
resolution: {integrity: sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==}
[email protected]:
resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
[email protected]:
resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==}
@@ -6606,9 +6600,6 @@ packages:
[email protected]:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
[email protected]:
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
[email protected]:
resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==}
@@ -6701,9 +6692,6 @@ packages:
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
engines: {node: '>= 8.10.0'}
[email protected]:
resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
[email protected]:
resolution: {integrity: sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==}
engines: {node: '>=12.13.0'}
@@ -7266,10 +7254,6 @@ packages:
resolution: {integrity: sha512-oj7KWToJuuxlPr7VV0vabvxEIiqNMo+q0NueIiL3XhtwC6FVOX7Hr1c0C4eD0bmf7Zr+S/dSf2xvkH3Ad6sU3Q==}
engines: {node: '>=20'}
[email protected]:
resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
engines: {node: '>=10'}
[email protected]:
resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==}
engines: {node: '>=4.0.0'}
@@ -7810,10 +7794,6 @@ packages:
resolution: {integrity: sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
[email protected]:
resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==}
engines: {node: '>=6'}
[email protected]:
resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==}
engines: {node: '>=12.0.0'}
@@ -8042,9 +8022,6 @@ packages:
[email protected]:
resolution: {integrity: sha512-VBE7f5OVnYwdgB3LHa+Qo29h8qVpxhVO9Trlc+AWm+/XNAgks1tAwMFHb33mjeiof77GglsJzeYF7OqXrROP/A==}
[email protected]:
resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
[email protected]:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
@@ -8141,9 +8118,6 @@ packages:
resolution: {integrity: sha512-mKZj9JLQrwMBtj5wxi6MH8Z5eSKaERpAwjg43dPtlGI1ZVEgH/qC7T8/6R2OBSUA+zzHBZgICsVJaEIV2tKTDA==}
engines: {node: '>=6.0'}
[email protected]:
resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==}
[email protected]:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
@@ -9388,10 +9362,6 @@ packages:
resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
engines: {node: '>=12'}
[email protected]:
resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
engines: {node: '>=10'}
[email protected]:
resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@@ -9439,9 +9409,6 @@ packages:
[email protected]:
resolution: {integrity: sha512-LudY4eRIkvjEpAlIAg10i2T2mbtiKZ4XlMGbTyF1kcAhEqMa9JhEEdEcjxYPwiKhuMVSBM3RVkNCZaNqcnE4ww==}
[email protected]:
resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
[email protected]:
resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
engines: {node: '>=10'}
@@ -9516,9 +9483,6 @@ packages:
engines: {node: ^18 || >=20}
hasBin: true
[email protected]:
resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==}
[email protected]:
resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==}
@@ -9572,10 +9536,6 @@ packages:
peerDependencies:
next: '*'
[email protected]:
resolution: {integrity: sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==}
engines: {node: '>=10'}
[email protected]:
resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==}
@@ -10192,12 +10152,6 @@ packages:
[email protected]:
resolution: {integrity: sha512-u1/ixq/lVQI0CakKNvLDEcW5zfCjUQfZdK9qqWuIJtsezuyG6pk9TWj75GMuI/EzRSZB/VAE43sNWWZfiy8psw==}
[email protected]:
resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==}
engines: {node: '>=10'}
deprecated: No longer maintained. Please contact the author of the relevant native addon; alternatives are available.
hasBin: true
[email protected]:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
@@ -10969,12 +10923,6 @@ packages:
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
engines: {node: '>=14'}
[email protected]:
resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==}
[email protected]:
resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==}
[email protected]:
resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
@@ -11309,13 +11257,6 @@ packages:
resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==}
engines: {node: '>=6'}
[email protected]:
resolution: {integrity: sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==}
[email protected]:
resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==}
engines: {node: '>=6'}
[email protected]:
resolution: {integrity: sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==}
@@ -11552,9 +11493,6 @@ packages:
resolution: {integrity: sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==}
engines: {node: '>= 6.0.0'}
[email protected]:
resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
[email protected]:
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
engines: {node: '>= 0.8.0'}
@@ -15389,10 +15327,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@ipshipyard/[email protected]':
dependencies:
prebuild-install: 7.1.3
'@isaacs/[email protected]':
dependencies:
string-width: 5.1.2
@@ -15852,7 +15786,7 @@ snapshots:
dependencies:
'@chainsafe/is-ip': 2.0.2
'@chainsafe/libp2p-noise': 16.1.3
'@ipshipyard/node-datachannel': 0.26.6
'@ipshipyard/node-datachannel': link:stubs/node-datachannel
'@libp2p/crypto': 5.1.1
'@libp2p/interface': 2.9.0
'@libp2p/interface-internal': 2.3.11
@@ -22390,12 +22324,6 @@ snapshots:
[email protected]: {}
[email protected]:
dependencies:
buffer: 5.7.1
inherits: 2.0.4
readable-stream: 3.6.2
[email protected]:
dependencies:
buffer: 6.0.3
@@ -22478,11 +22406,6 @@ snapshots:
[email protected]: {}
[email protected]:
dependencies:
base64-js: 1.5.1
ieee754: 1.2.1
[email protected]:
dependencies:
base64-js: 1.5.1
@@ -22580,8 +22503,6 @@ snapshots:
optionalDependencies:
fsevents: 2.3.3
[email protected]: {}
[email protected]:
dependencies:
'@types/node': 20.16.7
@@ -23213,10 +23134,6 @@ snapshots:
dependencies:
mimic-response: 4.0.0
[email protected]:
dependencies:
mimic-response: 3.1.0
[email protected]: {}
[email protected]: {}
@@ -23931,8 +23848,6 @@ snapshots:
signal-exit: 3.0.7
strip-final-newline: 3.0.0
[email protected]: {}
[email protected]: {}
[email protected]: {}
@@ -24143,8 +24058,6 @@ snapshots:
[email protected]: {}
[email protected]: {}
[email protected]: {}
[email protected]:
@@ -24242,8 +24155,6 @@ snapshots:
dependencies:
isobject: 3.0.1
[email protected]: {}
[email protected]:
dependencies:
is-glob: 4.0.3
@@ -25842,8 +25753,6 @@ snapshots:
[email protected]: {}
[email protected]: {}
[email protected]: {}
[email protected]:
@@ -25882,8 +25791,6 @@ snapshots:
dependencies:
rrweb: 2.0.0-alpha.18
[email protected]: {}
[email protected]: {}
[email protected]:
@@ -25940,8 +25847,6 @@ snapshots:
[email protected]: {}
[email protected]: {}
[email protected]: {}
[email protected]: {}
@@ -25989,10 +25894,6 @@ snapshots:
chokidar: 3.6.0
next: 15.5.10(@babel/[email protected])(@opentelemetry/[email protected])(@playwright/[email protected])([email protected]([email protected]))([email protected])
[email protected]:
dependencies:
semver: 7.7.4
[email protected]: {}
[email protected]: {}
@@ -26651,21 +26552,6 @@ snapshots:
[email protected]: {}
[email protected]:
dependencies:
detect-libc: 2.1.2
expand-template: 2.0.3
github-from-package: 0.0.0
minimist: 1.2.8
mkdirp-classic: 0.5.3
napi-build-utils: 2.0.0
node-abi: 3.75.0
pump: 3.0.0
rc: 1.2.8
simple-get: 4.0.1
tar-fs: 2.1.4
tunnel-agent: 0.6.0
[email protected]: {}
[email protected]: {}
@@ -27611,14 +27497,6 @@ snapshots:
[email protected]: {}
[email protected]: {}
[email protected]:
dependencies:
decompress-response: 6.0.0
once: 1.4.0
simple-concat: 1.0.1
[email protected]:
dependencies:
is-arrayish: 0.3.2
@@ -28018,21 +27896,6 @@ snapshots:
[email protected]: {}
[email protected]:
dependencies:
chownr: 1.1.4
mkdirp-classic: 0.5.3
pump: 3.0.0
tar-stream: 2.2.0
[email protected]:
dependencies:
bl: 4.1.0
end-of-stream: 1.4.4
fs-constants: 1.0.0
inherits: 2.0.4
readable-stream: 3.6.2
[email protected]:
dependencies:
bintrees: 1.0.2
@@ -28250,10 +28113,6 @@ snapshots:
dependencies:
tslib: 1.14.1
[email protected]:
dependencies:
safe-buffer: 5.2.1
[email protected]:
dependencies:
prelude-ls: 1.2.1
+14
View File
@@ -0,0 +1,14 @@
// Stub for @ipshipyard/node-datachannel (CJS)
class PeerConnection {
constructor() {}
close() {}
setLocalDescription() {}
setRemoteDescription() {}
addRemoteCandidate() {}
createDataChannel() { return {}; }
}
class IceUdpMuxListener {
constructor() {}
close() {}
}
module.exports = { PeerConnection, IceUdpMuxListener };
+24
View File
@@ -0,0 +1,24 @@
// Stub for @ipshipyard/node-datachannel
// Native WebRTC module not needed for Lux blockchain explorer
class PeerConnection {
close() {}
setLocalDescription() {}
setRemoteDescription() {}
addRemoteCandidate() {}
createDataChannel() {
return {};
}
onLocalDescription() {}
onLocalCandidate() {}
onStateChange() {}
onGatheringStateChange() {}
onDataChannel() {}
}
class IceUdpMuxListener {
close() {}
}
export { PeerConnection, IceUdpMuxListener };
export default {};
+19
View File
@@ -0,0 +1,19 @@
{
"name": "@ipshipyard/node-datachannel",
"version": "0.26.6",
"description": "Stub — native WebRTC module not needed for Lux explorer",
"main": "index.js",
"type": "module",
"exports": {
".": {
"require": "./index.cjs",
"import": "./index.js",
"default": "./index.js"
},
"./polyfill": {
"require": "./polyfill.cjs",
"import": "./polyfill.js",
"default": "./polyfill.js"
}
}
}
+30
View File
@@ -0,0 +1,30 @@
// Stub polyfill for @ipshipyard/node-datachannel/polyfill (CJS)
class RTCPeerConnection {
constructor() {}
close() {}
createDataChannel() { return new RTCDataChannel(); }
createOffer() { return Promise.resolve({}); }
createAnswer() { return Promise.resolve({}); }
setLocalDescription() { return Promise.resolve(); }
setRemoteDescription() { return Promise.resolve(); }
addIceCandidate() { return Promise.resolve(); }
addEventListener() {}
removeEventListener() {}
}
class RTCSessionDescription {
constructor(init) { this.type = init?.type ?? ''; this.sdp = init?.sdp ?? ''; }
}
class RTCIceCandidate {
constructor(init) { this.candidate = init?.candidate ?? ''; this.sdpMid = init?.sdpMid ?? null; this.sdpMLineIndex = init?.sdpMLineIndex ?? null; }
}
class RTCDataChannel {
constructor() { this.readyState = 'closed'; }
close() {}
send() {}
addEventListener() {}
removeEventListener() {}
}
class RTCDataChannelEvent {
constructor(type, init) { this.type = type; this.channel = init?.channel ?? null; }
}
module.exports = { RTCPeerConnection, RTCSessionDescription, RTCIceCandidate, RTCDataChannel, RTCDataChannelEvent };
+64
View File
@@ -0,0 +1,64 @@
// Stub polyfill for @ipshipyard/node-datachannel/polyfill
// Provides no-op WebRTC classes for environments where native WebRTC is not needed
class RTCPeerConnection {
close() {}
createDataChannel() {
return new RTCDataChannel();
}
createOffer() {
return Promise.resolve({});
}
createAnswer() {
return Promise.resolve({});
}
setLocalDescription() {
return Promise.resolve();
}
setRemoteDescription() {
return Promise.resolve();
}
addIceCandidate() {
return Promise.resolve();
}
addEventListener() {}
removeEventListener() {}
}
class RTCSessionDescription {
constructor(init) {
this.type = init?.type ?? '';
this.sdp = init?.sdp ?? '';
}
}
class RTCIceCandidate {
constructor(init) {
this.candidate = init?.candidate ?? '';
this.sdpMid = init?.sdpMid ?? null;
this.sdpMLineIndex = init?.sdpMLineIndex ?? null;
}
}
class RTCDataChannel {
readyState = 'closed';
close() {}
send() {}
addEventListener() {}
removeEventListener() {}
}
class RTCDataChannelEvent {
constructor(type, init) {
this.type = type;
this.channel = init?.channel ?? null;
}
}
export {
RTCPeerConnection,
RTCSessionDescription,
RTCIceCandidate,
RTCDataChannel,
RTCDataChannelEvent,
};