diff --git a/browser-client-react/package-lock.json b/browser-client-react/package-lock.json
index cee5a9f..4dbc398 100644
--- a/browser-client-react/package-lock.json
+++ b/browser-client-react/package-lock.json
@@ -8,8 +8,8 @@
"name": "browser-client-react",
"version": "3.2.0",
"dependencies": {
- "@interopio/browser": "^3.1.2",
- "@interopio/react-hooks": "^3.1.2",
+ "@interopio/browser": "^3.2.0",
+ "@interopio/react-hooks": "^3.2.0",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
@@ -2213,12 +2213,14 @@
}
},
"node_modules/@glue42/gateway-web": {
- "version": "3.0.18",
- "license": "MIT"
+ "version": "3.0.19",
+ "resolved": "https://registry.npmjs.org/@glue42/gateway-web/-/gateway-web-3.0.19.tgz",
+ "integrity": "sha512-k0s5C21jIF+3o1g+Sz5ZocfVUTSCuXFg21KB/wh5hqO0aFM4KCVHmWqazBmGpp16VfxoqoPHujcZDk8cK5Dl+g=="
},
"node_modules/@glue42/schemas": {
"version": "3.22.0",
- "license": "ISC",
+ "resolved": "https://registry.npmjs.org/@glue42/schemas/-/schemas-3.22.0.tgz",
+ "integrity": "sha512-4eC3oIci6o09DIPYwvGCHSaGHdNPqDDnqByh0XuiOw/lA6rlZii4HfamqbCYhytEZ58dqAdyTDqyqVNnEVBuQA==",
"dependencies": {
"ajv": "^6.12.6",
"ajv-keywords": "^3.4.1"
@@ -2233,20 +2235,31 @@
}
},
"node_modules/@glue42/server-api": {
- "version": "1.6.2",
- "license": "MIT",
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/@glue42/server-api/-/server-api-1.6.3.tgz",
+ "integrity": "sha512-UpHc8l1iNkg48k7JYLB9ofk8BmzG1sRxTLiu2l3pLldbzxS1xxcdRruUx45SSeSiM2juiahbi04iTDCsgQUVFg==",
"dependencies": {
"@glue42/schemas": "^3.18.0",
"@types/request": "^2.48.8",
"axios": "^1.6.2",
"form-data": "^4.0.0",
"jwt-decode": "^3.1.2",
+ "rimraf": "^5.0.5",
"typescript": "^4.2.4"
}
},
+ "node_modules/@glue42/server-api/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
"node_modules/@glue42/server-api/node_modules/form-data": {
"version": "4.0.0",
- "license": "MIT",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
@@ -2256,6 +2269,58 @@
"node": ">= 6"
}
},
+ "node_modules/@glue42/server-api/node_modules/glob": {
+ "version": "10.3.10",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
+ "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^2.3.5",
+ "minimatch": "^9.0.1",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
+ "path-scurry": "^1.10.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@glue42/server-api/node_modules/minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@glue42/server-api/node_modules/rimraf": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz",
+ "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==",
+ "dependencies": {
+ "glob": "^10.3.7"
+ },
+ "bin": {
+ "rimraf": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/@humanwhocodes/config-array": {
"version": "0.11.14",
"license": "Apache-2.0",
@@ -2284,14 +2349,15 @@
"license": "BSD-3-Clause"
},
"node_modules/@interopio/browser": {
- "version": "3.1.2",
- "license": "MIT",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@interopio/browser/-/browser-3.2.0.tgz",
+ "integrity": "sha512-B9Xv0vAdJtPnkZiy1Zbcy1TPaWkeQMyKL+H0UyNN54SXx/ksvoQCHvvP27OJFiKvNK962v8ju6cfw3oRcYqD1g==",
"dependencies": {
- "@interopio/core": "^6.1.0",
+ "@interopio/core": "^6.2.0",
"@interopio/desktop": "^6.0.1",
- "@interopio/search-api": "^2.1.0",
- "@interopio/utils": "^1.1.2",
- "@interopio/workspaces-api": "^3.1.0",
+ "@interopio/search-api": "^2.2.0",
+ "@interopio/utils": "^1.2.0",
+ "@interopio/workspaces-api": "^3.2.0",
"callback-registry": "^2.6.0",
"decoder-validate": "0.0.2",
"idb": "^7.1.1",
@@ -2300,17 +2366,18 @@
}
},
"node_modules/@interopio/browser-platform": {
- "version": "3.1.2",
- "license": "Commercial",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@interopio/browser-platform/-/browser-platform-3.2.0.tgz",
+ "integrity": "sha512-0dpIC7r/duBJrvXVvQaKoULC97De6qhPCA6fyFL9l+yCtZvvH3JeqmDkXsx+E7OHd8gQGRokb/Y/MOp620tY9Q==",
"dependencies": {
"@glue42/gateway-web": "^3.0.17",
- "@glue42/server-api": "^1.5.0",
- "@interopio/browser": "^3.1.2",
- "@interopio/core": "^6.1.0",
+ "@glue42/server-api": "^1.6.3",
+ "@interopio/browser": "^3.2.0",
+ "@interopio/core": "^6.2.0",
"@interopio/desktop": "^6.0.1",
- "@interopio/search-api": "^2.1.0",
- "@interopio/utils": "^1.1.2",
- "@interopio/workspaces-api": "^3.1.0",
+ "@interopio/search-api": "^2.2.0",
+ "@interopio/utils": "^1.2.0",
+ "@interopio/workspaces-api": "^3.2.0",
"callback-registry": "^2.7.1",
"decoder-validate": "0.0.2",
"deep-equal": "^2.1.0",
@@ -2325,13 +2392,14 @@
},
"node_modules/@interopio/browser-platform/node_modules/nanoid": {
"version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.2.tgz",
+ "integrity": "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
- "license": "MIT",
"bin": {
"nanoid": "bin/nanoid.js"
},
@@ -2341,13 +2409,14 @@
},
"node_modules/@interopio/browser/node_modules/nanoid": {
"version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.2.tgz",
+ "integrity": "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
- "license": "MIT",
"bin": {
"nanoid": "bin/nanoid.js"
},
@@ -2356,8 +2425,9 @@
}
},
"node_modules/@interopio/core": {
- "version": "6.1.0",
- "license": "MIT",
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/@interopio/core/-/core-6.2.0.tgz",
+ "integrity": "sha512-T+I6lymeJ7WbeFdM1+kdTSBOBH95d8qndK1LxVoAkVYKL3B952GXQhHTPBSq5uvARgvZmXlBc7jLVJo8cTDpNw==",
"dependencies": {
"callback-registry": "^2.7.2",
"shortid": "^2.2.16",
@@ -2366,7 +2436,8 @@
},
"node_modules/@interopio/core/node_modules/ws": {
"version": "8.16.0",
- "license": "MIT",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz",
+ "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==",
"engines": {
"node": ">=10.0.0"
},
@@ -2384,26 +2455,24 @@
}
},
"node_modules/@interopio/desktop": {
- "version": "6.1.0",
- "license": "MIT",
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/@interopio/desktop/-/desktop-6.2.2.tgz",
+ "integrity": "sha512-HzfhjU5PRQPZR7k9JYMLtsZ9TAntsRCoMQp/r2LuPdumG4eWh9SUEB5ScwyXuHlcYqJSdogDwmws8hsIsXvZVA==",
"dependencies": {
"@glue42/schemas": "^3.22.0",
- "@interopio/core": "^6.0.2",
+ "@interopio/core": "^6.1.0",
"@interopio/workspaces-api": "^3.1.0",
"callback-registry": "^2.7.1",
- "shortid": "2.2.8"
+ "nanoid": "^3.3.7"
}
},
- "node_modules/@interopio/desktop/node_modules/shortid": {
- "version": "2.2.8",
- "license": "MIT"
- },
"node_modules/@interopio/react-hooks": {
- "version": "3.1.2",
- "license": "MIT",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@interopio/react-hooks/-/react-hooks-3.2.0.tgz",
+ "integrity": "sha512-1jqquE7heNQObJdooqkoVCNRtg2SlON7P18lOLIlgHl3KIkbRwln1VyHxxrfuXohDJciIlWSq5JbY6IGf85odg==",
"dependencies": {
- "@interopio/browser": "^3.1.2",
- "@interopio/browser-platform": "^3.1.2",
+ "@interopio/browser": "^3.2.0",
+ "@interopio/browser-platform": "^3.2.0",
"@interopio/desktop": "^6.0.1",
"prop-types": "^15.7.2"
},
@@ -2421,10 +2490,11 @@
}
},
"node_modules/@interopio/search-api": {
- "version": "2.1.0",
- "license": "MIT",
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@interopio/search-api/-/search-api-2.2.0.tgz",
+ "integrity": "sha512-Q8CmDjDSBRie+pS9raklvFaL5ko1LpqzoEEaxD587lpgR+7gdMTdfv8BxazNd8iL/NeZmWbMWWk0GNNgSiaxYA==",
"dependencies": {
- "@interopio/core": "^6.1.0",
+ "@interopio/core": "^6.2.0",
"callback-registry": "^2.5.2",
"decoder-validate": "0.0.2",
"nanoid": "^4.0.0"
@@ -2432,13 +2502,14 @@
},
"node_modules/@interopio/search-api/node_modules/nanoid": {
"version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.2.tgz",
+ "integrity": "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
- "license": "MIT",
"bin": {
"nanoid": "bin/nanoid.js"
},
@@ -2447,17 +2518,19 @@
}
},
"node_modules/@interopio/utils": {
- "version": "1.1.2",
- "license": "ISC",
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@interopio/utils/-/utils-1.2.0.tgz",
+ "integrity": "sha512-Vn6QOX8IjuhpnpTNYGmfZ1VnIzIuRvwa3CIartDTcthvpHce/IlPCpMTr8uquzom8yzdONXcW4t0yLxRxMncBQ==",
"dependencies": {
"decoder-validate": "^0.0.2"
}
},
"node_modules/@interopio/workspaces-api": {
- "version": "3.1.0",
- "license": "MIT",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@interopio/workspaces-api/-/workspaces-api-3.2.0.tgz",
+ "integrity": "sha512-ShufjDByHfhn8T9qiOZ/NqczLzBy/7d0BLz+Jq8bMPutud8dsyNpIPHjzFi8jMNTA/y9fZPMp6SyMU0JS6C/uA==",
"dependencies": {
- "@interopio/core": "^6.1.0",
+ "@interopio/core": "^6.2.0",
"callback-registry": "^2.5.2",
"decoder-validate": "0.0.2",
"nanoid": "^4.0.0"
@@ -2465,13 +2538,14 @@
},
"node_modules/@interopio/workspaces-api/node_modules/nanoid": {
"version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.2.tgz",
+ "integrity": "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
- "license": "MIT",
"bin": {
"nanoid": "bin/nanoid.js"
},
@@ -3971,7 +4045,8 @@
},
"node_modules/@types/caseless": {
"version": "0.12.5",
- "license": "MIT"
+ "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz",
+ "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg=="
},
"node_modules/@types/connect": {
"version": "3.4.38",
@@ -4141,7 +4216,8 @@
},
"node_modules/@types/request": {
"version": "2.48.12",
- "license": "MIT",
+ "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.12.tgz",
+ "integrity": "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==",
"dependencies": {
"@types/caseless": "*",
"@types/node": "*",
@@ -4151,7 +4227,8 @@
},
"node_modules/@types/request/node_modules/form-data": {
"version": "2.5.1",
- "license": "MIT",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz",
+ "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.6",
@@ -4224,7 +4301,8 @@
},
"node_modules/@types/tough-cookie": {
"version": "4.0.5",
- "license": "MIT"
+ "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
+ "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA=="
},
"node_modules/@types/trusted-types": {
"version": "2.0.7",
@@ -5021,7 +5099,8 @@
},
"node_modules/axios": {
"version": "1.6.7",
- "license": "MIT",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz",
+ "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==",
"dependencies": {
"follow-redirects": "^1.15.4",
"form-data": "^4.0.0",
@@ -5030,7 +5109,8 @@
},
"node_modules/axios/node_modules/form-data": {
"version": "4.0.0",
- "license": "MIT",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
@@ -5502,7 +5582,8 @@
},
"node_modules/callback-registry": {
"version": "2.7.2",
- "license": "ISC"
+ "resolved": "https://registry.npmjs.org/callback-registry/-/callback-registry-2.7.2.tgz",
+ "integrity": "sha512-VVrtF21DaH0VHeNMkLDd4VGuxsYM3V3l3lwYneKVMU/6X3TRtcQszUwlAcqj2HrLcbP1NyS12LsanUwCykaz/Q=="
},
"node_modules/callsites": {
"version": "3.1.0",
@@ -6310,7 +6391,8 @@
},
"node_modules/decoder-validate": {
"version": "0.0.2",
- "license": "MIT"
+ "resolved": "https://registry.npmjs.org/decoder-validate/-/decoder-validate-0.0.2.tgz",
+ "integrity": "sha512-9BsqAH9Zq6CvlxKHkSrZrH2iYlhuhHcrh6uTnDvcsa9P5YEweEzt1ci+X/9STgSCE7b9BA7/QIiwhfUDDWmjxw=="
},
"node_modules/dedent": {
"version": "0.7.0",
@@ -11175,7 +11257,8 @@
},
"node_modules/jsrsasign": {
"version": "10.9.0",
- "license": "MIT",
+ "resolved": "https://registry.npmjs.org/jsrsasign/-/jsrsasign-10.9.0.tgz",
+ "integrity": "sha512-QWLUikj1SBJGuyGK8tjKSx3K7Y69KYJnrs/pQ1KZ6wvZIkHkWjZ1PJDpuvc1/28c1uP0KW9qn1eI1LzHQqDOwQ==",
"funding": {
"url": "https://github.com/kjur/jsrsasign#donations"
}
@@ -11195,7 +11278,8 @@
},
"node_modules/jwt-decode": {
"version": "3.1.2",
- "license": "MIT"
+ "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
+ "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
},
"node_modules/keyv": {
"version": "4.5.4",
@@ -13449,7 +13533,8 @@
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
- "license": "MIT"
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/psl": {
"version": "1.9.0",
@@ -14522,14 +14607,17 @@
},
"node_modules/shortid": {
"version": "2.2.16",
- "license": "MIT",
+ "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.16.tgz",
+ "integrity": "sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==",
+ "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
"dependencies": {
"nanoid": "^2.1.0"
}
},
"node_modules/shortid/node_modules/nanoid": {
"version": "2.1.11",
- "license": "MIT"
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz",
+ "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA=="
},
"node_modules/side-channel": {
"version": "1.0.4",
@@ -15599,6 +15687,8 @@
},
"node_modules/ua-parser-js": {
"version": "1.0.37",
+ "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz",
+ "integrity": "sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==",
"funding": [
{
"type": "opencollective",
@@ -15613,7 +15703,6 @@
"url": "https://github.com/sponsors/faisalman"
}
],
- "license": "MIT",
"engines": {
"node": "*"
}
@@ -17916,33 +18005,78 @@
"version": "8.56.0"
},
"@glue42/gateway-web": {
- "version": "3.0.18"
+ "version": "3.0.19",
+ "resolved": "https://registry.npmjs.org/@glue42/gateway-web/-/gateway-web-3.0.19.tgz",
+ "integrity": "sha512-k0s5C21jIF+3o1g+Sz5ZocfVUTSCuXFg21KB/wh5hqO0aFM4KCVHmWqazBmGpp16VfxoqoPHujcZDk8cK5Dl+g=="
},
"@glue42/schemas": {
"version": "3.22.0",
+ "resolved": "https://registry.npmjs.org/@glue42/schemas/-/schemas-3.22.0.tgz",
+ "integrity": "sha512-4eC3oIci6o09DIPYwvGCHSaGHdNPqDDnqByh0XuiOw/lA6rlZii4HfamqbCYhytEZ58dqAdyTDqyqVNnEVBuQA==",
"requires": {
"ajv": "^6.12.6",
"ajv-keywords": "^3.4.1"
}
},
"@glue42/server-api": {
- "version": "1.6.2",
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/@glue42/server-api/-/server-api-1.6.3.tgz",
+ "integrity": "sha512-UpHc8l1iNkg48k7JYLB9ofk8BmzG1sRxTLiu2l3pLldbzxS1xxcdRruUx45SSeSiM2juiahbi04iTDCsgQUVFg==",
"requires": {
"@glue42/schemas": "^3.18.0",
"@types/request": "^2.48.8",
"axios": "^1.6.2",
"form-data": "^4.0.0",
"jwt-decode": "^3.1.2",
+ "rimraf": "^5.0.5",
"typescript": "^4.2.4"
},
"dependencies": {
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
+ },
"form-data": {
"version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
+ },
+ "glob": {
+ "version": "10.3.10",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
+ "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
+ "requires": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^2.3.5",
+ "minimatch": "^9.0.1",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
+ "path-scurry": "^1.10.1"
+ }
+ },
+ "minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
+ },
+ "rimraf": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz",
+ "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==",
+ "requires": {
+ "glob": "^10.3.7"
+ }
}
}
},
@@ -17961,13 +18095,15 @@
"version": "2.0.2"
},
"@interopio/browser": {
- "version": "3.1.2",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@interopio/browser/-/browser-3.2.0.tgz",
+ "integrity": "sha512-B9Xv0vAdJtPnkZiy1Zbcy1TPaWkeQMyKL+H0UyNN54SXx/ksvoQCHvvP27OJFiKvNK962v8ju6cfw3oRcYqD1g==",
"requires": {
- "@interopio/core": "^6.1.0",
+ "@interopio/core": "^6.2.0",
"@interopio/desktop": "^6.0.1",
- "@interopio/search-api": "^2.1.0",
- "@interopio/utils": "^1.1.2",
- "@interopio/workspaces-api": "^3.1.0",
+ "@interopio/search-api": "^2.2.0",
+ "@interopio/utils": "^1.2.0",
+ "@interopio/workspaces-api": "^3.2.0",
"callback-registry": "^2.6.0",
"decoder-validate": "0.0.2",
"idb": "^7.1.1",
@@ -17976,21 +18112,25 @@
},
"dependencies": {
"nanoid": {
- "version": "4.0.2"
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.2.tgz",
+ "integrity": "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw=="
}
}
},
"@interopio/browser-platform": {
- "version": "3.1.2",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@interopio/browser-platform/-/browser-platform-3.2.0.tgz",
+ "integrity": "sha512-0dpIC7r/duBJrvXVvQaKoULC97De6qhPCA6fyFL9l+yCtZvvH3JeqmDkXsx+E7OHd8gQGRokb/Y/MOp620tY9Q==",
"requires": {
"@glue42/gateway-web": "^3.0.17",
- "@glue42/server-api": "^1.5.0",
- "@interopio/browser": "^3.1.2",
- "@interopio/core": "^6.1.0",
+ "@glue42/server-api": "^1.6.3",
+ "@interopio/browser": "^3.2.0",
+ "@interopio/core": "^6.2.0",
"@interopio/desktop": "^6.0.1",
- "@interopio/search-api": "^2.1.0",
- "@interopio/utils": "^1.1.2",
- "@interopio/workspaces-api": "^3.1.0",
+ "@interopio/search-api": "^2.2.0",
+ "@interopio/utils": "^1.2.0",
+ "@interopio/workspaces-api": "^3.2.0",
"callback-registry": "^2.7.1",
"decoder-validate": "0.0.2",
"deep-equal": "^2.1.0",
@@ -18004,12 +18144,16 @@
},
"dependencies": {
"nanoid": {
- "version": "4.0.2"
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.2.tgz",
+ "integrity": "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw=="
}
}
},
"@interopio/core": {
- "version": "6.1.0",
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/@interopio/core/-/core-6.2.0.tgz",
+ "integrity": "sha512-T+I6lymeJ7WbeFdM1+kdTSBOBH95d8qndK1LxVoAkVYKL3B952GXQhHTPBSq5uvARgvZmXlBc7jLVJo8cTDpNw==",
"requires": {
"callback-registry": "^2.7.2",
"shortid": "^2.2.16",
@@ -18018,65 +18162,76 @@
"dependencies": {
"ws": {
"version": "8.16.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz",
+ "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==",
"requires": {}
}
}
},
"@interopio/desktop": {
- "version": "6.1.0",
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/@interopio/desktop/-/desktop-6.2.2.tgz",
+ "integrity": "sha512-HzfhjU5PRQPZR7k9JYMLtsZ9TAntsRCoMQp/r2LuPdumG4eWh9SUEB5ScwyXuHlcYqJSdogDwmws8hsIsXvZVA==",
"requires": {
"@glue42/schemas": "^3.22.0",
- "@interopio/core": "^6.0.2",
+ "@interopio/core": "^6.1.0",
"@interopio/workspaces-api": "^3.1.0",
"callback-registry": "^2.7.1",
- "shortid": "2.2.8"
- },
- "dependencies": {
- "shortid": {
- "version": "2.2.8"
- }
+ "nanoid": "^3.3.7"
}
},
"@interopio/react-hooks": {
- "version": "3.1.2",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@interopio/react-hooks/-/react-hooks-3.2.0.tgz",
+ "integrity": "sha512-1jqquE7heNQObJdooqkoVCNRtg2SlON7P18lOLIlgHl3KIkbRwln1VyHxxrfuXohDJciIlWSq5JbY6IGf85odg==",
"requires": {
- "@interopio/browser": "^3.1.2",
- "@interopio/browser-platform": "^3.1.2",
+ "@interopio/browser": "^3.2.0",
+ "@interopio/browser-platform": "^3.2.0",
"@interopio/desktop": "^6.0.1",
"prop-types": "^15.7.2"
}
},
"@interopio/search-api": {
- "version": "2.1.0",
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@interopio/search-api/-/search-api-2.2.0.tgz",
+ "integrity": "sha512-Q8CmDjDSBRie+pS9raklvFaL5ko1LpqzoEEaxD587lpgR+7gdMTdfv8BxazNd8iL/NeZmWbMWWk0GNNgSiaxYA==",
"requires": {
- "@interopio/core": "^6.1.0",
+ "@interopio/core": "^6.2.0",
"callback-registry": "^2.5.2",
"decoder-validate": "0.0.2",
"nanoid": "^4.0.0"
},
"dependencies": {
"nanoid": {
- "version": "4.0.2"
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.2.tgz",
+ "integrity": "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw=="
}
}
},
"@interopio/utils": {
- "version": "1.1.2",
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@interopio/utils/-/utils-1.2.0.tgz",
+ "integrity": "sha512-Vn6QOX8IjuhpnpTNYGmfZ1VnIzIuRvwa3CIartDTcthvpHce/IlPCpMTr8uquzom8yzdONXcW4t0yLxRxMncBQ==",
"requires": {
"decoder-validate": "^0.0.2"
}
},
"@interopio/workspaces-api": {
- "version": "3.1.0",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@interopio/workspaces-api/-/workspaces-api-3.2.0.tgz",
+ "integrity": "sha512-ShufjDByHfhn8T9qiOZ/NqczLzBy/7d0BLz+Jq8bMPutud8dsyNpIPHjzFi8jMNTA/y9fZPMp6SyMU0JS6C/uA==",
"requires": {
- "@interopio/core": "^6.1.0",
+ "@interopio/core": "^6.2.0",
"callback-registry": "^2.5.2",
"decoder-validate": "0.0.2",
"nanoid": "^4.0.0"
},
"dependencies": {
"nanoid": {
- "version": "4.0.2"
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.2.tgz",
+ "integrity": "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw=="
}
}
},
@@ -18965,7 +19120,9 @@
}
},
"@types/caseless": {
- "version": "0.12.5"
+ "version": "0.12.5",
+ "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz",
+ "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg=="
},
"@types/connect": {
"version": "3.4.38",
@@ -19107,6 +19264,8 @@
},
"@types/request": {
"version": "2.48.12",
+ "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.12.tgz",
+ "integrity": "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==",
"requires": {
"@types/caseless": "*",
"@types/node": "*",
@@ -19116,6 +19275,8 @@
"dependencies": {
"form-data": {
"version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz",
+ "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.6",
@@ -19176,7 +19337,9 @@
}
},
"@types/tough-cookie": {
- "version": "4.0.5"
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
+ "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA=="
},
"@types/trusted-types": {
"version": "2.0.7"
@@ -19650,6 +19813,8 @@
},
"axios": {
"version": "1.6.7",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz",
+ "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==",
"requires": {
"follow-redirects": "^1.15.4",
"form-data": "^4.0.0",
@@ -19658,6 +19823,8 @@
"dependencies": {
"form-data": {
"version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
@@ -19963,7 +20130,9 @@
}
},
"callback-registry": {
- "version": "2.7.2"
+ "version": "2.7.2",
+ "resolved": "https://registry.npmjs.org/callback-registry/-/callback-registry-2.7.2.tgz",
+ "integrity": "sha512-VVrtF21DaH0VHeNMkLDd4VGuxsYM3V3l3lwYneKVMU/6X3TRtcQszUwlAcqj2HrLcbP1NyS12LsanUwCykaz/Q=="
},
"callsites": {
"version": "3.1.0"
@@ -20419,7 +20588,9 @@
"version": "10.4.3"
},
"decoder-validate": {
- "version": "0.0.2"
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/decoder-validate/-/decoder-validate-0.0.2.tgz",
+ "integrity": "sha512-9BsqAH9Zq6CvlxKHkSrZrH2iYlhuhHcrh6uTnDvcsa9P5YEweEzt1ci+X/9STgSCE7b9BA7/QIiwhfUDDWmjxw=="
},
"dedent": {
"version": "0.7.0"
@@ -23347,7 +23518,9 @@
"version": "5.0.1"
},
"jsrsasign": {
- "version": "10.9.0"
+ "version": "10.9.0",
+ "resolved": "https://registry.npmjs.org/jsrsasign/-/jsrsasign-10.9.0.tgz",
+ "integrity": "sha512-QWLUikj1SBJGuyGK8tjKSx3K7Y69KYJnrs/pQ1KZ6wvZIkHkWjZ1PJDpuvc1/28c1uP0KW9qn1eI1LzHQqDOwQ=="
},
"jsx-ast-utils": {
"version": "3.3.5",
@@ -23359,7 +23532,9 @@
}
},
"jwt-decode": {
- "version": "3.1.2"
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
+ "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
},
"keyv": {
"version": "4.5.4",
@@ -24535,7 +24710,9 @@
}
},
"proxy-from-env": {
- "version": "1.1.0"
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"psl": {
"version": "1.9.0"
@@ -25186,12 +25363,16 @@
},
"shortid": {
"version": "2.2.16",
+ "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.16.tgz",
+ "integrity": "sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==",
"requires": {
"nanoid": "^2.1.0"
},
"dependencies": {
"nanoid": {
- "version": "2.1.11"
+ "version": "2.1.11",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz",
+ "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA=="
}
}
},
@@ -25858,7 +26039,9 @@
"version": "4.9.5"
},
"ua-parser-js": {
- "version": "1.0.37"
+ "version": "1.0.37",
+ "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz",
+ "integrity": "sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ=="
},
"unbox-primitive": {
"version": "1.0.2",
diff --git a/browser-client-react/package.json b/browser-client-react/package.json
index f4d18b0..dbb7076 100644
--- a/browser-client-react/package.json
+++ b/browser-client-react/package.json
@@ -3,8 +3,8 @@
"version": "3.2.0",
"private": true,
"dependencies": {
- "@interopio/browser": "^3.1.2",
- "@interopio/react-hooks": "^3.1.2",
+ "@interopio/browser": "^3.2.0",
+ "@interopio/react-hooks": "^3.2.0",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
diff --git a/browser-client-vanilla-js/public/libs/browser.es.js b/browser-client-vanilla-js/public/libs/browser.es.js
index e709046..15e6bd3 100644
--- a/browser-client-vanilla-js/public/libs/browser.es.js
+++ b/browser-client-vanilla-js/public/libs/browser.es.js
@@ -73,10 +73,8 @@ const enterprise = (config) => {
libraries: (_a = config === null || config === void 0 ? void 0 : config.libraries) !== null && _a !== void 0 ? _a : [],
logger: (_c = (_b = config === null || config === void 0 ? void 0 : config.systemLogger) === null || _b === void 0 ? void 0 : _b.level) !== null && _c !== void 0 ? _c : "warn"
};
- if (window.glue42gd) {
- return window.Glue(enterpriseConfig);
- }
- return window.Glue(enterpriseConfig);
+ const injectedFactory = window.IODesktop || window.Glue;
+ return injectedFactory(enterpriseConfig);
};
/**
@@ -1800,7 +1798,7 @@ class FDC3Service {
isFdc3Definition(definition) {
const decodeRes = allDefinitionsDecoder.run(definition);
if (!decodeRes.ok) {
- return { isFdc3: false };
+ return { isFdc3: false, reason: parseDecoderErrorToStringMessage(decodeRes.error) };
}
if (definition.appId && definition.details) {
return { isFdc3: true, version: "2.0" };
@@ -1808,7 +1806,7 @@ class FDC3Service {
if (definition.manifest) {
return { isFdc3: true, version: "1.2" };
}
- return { isFdc3: false };
+ return { isFdc3: false, reason: "The passed definition is not FDC3" };
}
parseToBrowserBaseAppData(definition) {
var _a;
@@ -1979,9 +1977,27 @@ const decoders$1 = {
}
};
+var INTENTS_ERRORS;
+(function (INTENTS_ERRORS) {
+ INTENTS_ERRORS["USER_CANCELLED"] = "User Closed Intents Resolver UI without choosing a handler";
+ INTENTS_ERRORS["CALLER_NOT_DEFINED"] = "Caller Id is not defined";
+ INTENTS_ERRORS["TIMEOUT_HIT"] = "Timeout hit";
+ INTENTS_ERRORS["INTENT_NOT_FOUND"] = "Cannot find Intent";
+ INTENTS_ERRORS["HANDLER_NOT_FOUND"] = "Cannot find Intent Handler";
+ INTENTS_ERRORS["TARGET_INSTANCE_UNAVAILABLE"] = "Cannot start Target Instance";
+ INTENTS_ERRORS["INTENT_DELIVERY_FAILED"] = "Target Instance did not add a listener";
+ INTENTS_ERRORS["RESOLVER_UNAVAILABLE"] = "Intents Resolver UI unavailable";
+ INTENTS_ERRORS["RESOLVER_TIMEOUT"] = "User did not choose a handler";
+ INTENTS_ERRORS["INVALID_RESOLVER_RESPONSE"] = "Intents Resolver UI returned invalid response";
+ INTENTS_ERRORS["INTENT_HANDLER_REJECTION"] = "Intent Handler function processing the raised intent threw an error or rejected the promise it returned";
+})(INTENTS_ERRORS || (INTENTS_ERRORS = {}));
+
let IoC$1 = class IoC {
constructor() {
this._decoders = decoders$1;
+ this._errors = {
+ intents: INTENTS_ERRORS
+ };
}
get fdc3() {
if (!this._fdc3) {
@@ -1992,20 +2008,24 @@ let IoC$1 = class IoC {
get decoders() {
return this._decoders;
}
+ get errors() {
+ return this._errors;
+ }
};
const ioc = new IoC$1();
ioc.fdc3;
const decoders = ioc.decoders;
+ioc.errors;
const nonEmptyStringDecoder = string$1().where((s) => s.length > 0, "Expected a non-empty string");
const nonNegativeNumberDecoder = number$1().where((num) => num >= 0, "Expected a non-negative number");
const optionalNonEmptyStringDecoder = optional$1(nonEmptyStringDecoder);
-const libDomainDecoder = oneOf$1(constant$1("system"), constant$1("windows"), constant$1("appManager"), constant$1("layouts"), constant$1("intents"), constant$1("notifications"), constant$1("channels"), constant$1("extension"), constant$1("themes"));
+const libDomainDecoder = oneOf$1(constant$1("system"), constant$1("windows"), constant$1("appManager"), constant$1("layouts"), constant$1("intents"), constant$1("notifications"), constant$1("channels"), constant$1("extension"), constant$1("themes"), constant$1("prefs"));
const windowOperationTypesDecoder = oneOf$1(constant$1("openWindow"), constant$1("windowHello"), constant$1("windowAdded"), constant$1("windowRemoved"), constant$1("getBounds"), constant$1("getFrameBounds"), constant$1("getUrl"), constant$1("moveResize"), constant$1("focus"), constant$1("close"), constant$1("getTitle"), constant$1("setTitle"), constant$1("focusChange"), constant$1("getChannel"));
const appManagerOperationTypesDecoder = oneOf$1(constant$1("appHello"), constant$1("appDirectoryStateChange"), constant$1("instanceStarted"), constant$1("instanceStopped"), constant$1("applicationStart"), constant$1("instanceStop"), constant$1("clear"));
const layoutsOperationTypesDecoder = oneOf$1(constant$1("layoutAdded"), constant$1("layoutChanged"), constant$1("layoutRemoved"), constant$1("get"), constant$1("getAll"), constant$1("export"), constant$1("import"), constant$1("remove"), constant$1("clientSaveRequest"), constant$1("getGlobalPermissionState"), constant$1("checkGlobalActivated"), constant$1("requestGlobalPermission"), constant$1("getDefaultGlobal"), constant$1("setDefaultGlobal"), constant$1("clearDefaultGlobal"));
-const notificationsOperationTypesDecoder = oneOf$1(constant$1("raiseNotification"), constant$1("requestPermission"), constant$1("notificationShow"), constant$1("notificationClick"), constant$1("getPermission"), constant$1("list"), constant$1("notificationRaised"), constant$1("notificationClosed"), constant$1("click"), constant$1("clear"), constant$1("clearAll"));
+const notificationsOperationTypesDecoder = oneOf$1(constant$1("raiseNotification"), constant$1("requestPermission"), constant$1("notificationShow"), constant$1("notificationClick"), constant$1("getPermission"), constant$1("list"), constant$1("notificationRaised"), constant$1("notificationClosed"), constant$1("click"), constant$1("clear"), constant$1("clearAll"), constant$1("configure"), constant$1("getConfiguration"), constant$1("configurationChanged"), constant$1("setState"), constant$1("clearOld"), constant$1("activeCountChange"), constant$1("stateChange"));
const systemOperationTypesDecoder = oneOf$1(constant$1("getEnvironment"), constant$1("getBase"), constant$1("platformShutdown"));
const windowRelativeDirectionDecoder = oneOf$1(constant$1("top"), constant$1("left"), constant$1("right"), constant$1("bottom"));
const windowBoundsDecoder = object$1({
@@ -2406,10 +2426,11 @@ const intentResultDecoder = object$1({
const handlersFilterDecoder = object$1({
title: optional$1(nonEmptyStringDecoder),
openResolver: optional$1(boolean$1()),
- timeout: optional$1(number$1()),
+ timeout: optional$1(nonNegativeNumberDecoder),
intent: optional$1(nonEmptyStringDecoder),
contextTypes: optional$1(array$1(nonEmptyStringDecoder)),
resultType: optional$1(nonEmptyStringDecoder),
+ applicationNames: optional$1(array$1(nonEmptyStringDecoder))
});
const filterHandlersResultDecoder = object$1({
handlers: array$1(intentHandlerDecoder)
@@ -2427,6 +2448,17 @@ const AddIntentListenerRequestDecoder = object$1({
resultType: optional$1(string$1())
});
const AddIntentListenerDecoder = oneOf$1(nonEmptyStringDecoder, AddIntentListenerRequestDecoder);
+const intentInfoDecoder = object$1({
+ intent: nonEmptyStringDecoder,
+ contextTypes: optional$1(array$1(nonEmptyStringDecoder)),
+ description: optional$1(nonEmptyStringDecoder),
+ displayName: optional$1(nonEmptyStringDecoder),
+ icon: optional$1(nonEmptyStringDecoder),
+ resultType: optional$1(nonEmptyStringDecoder)
+});
+const getIntentsResultDecoder = object$1({
+ intents: array$1(intentInfoDecoder)
+});
const channelNameDecoder = (channelNames) => {
return nonEmptyStringDecoder.where(s => channelNames.includes(s), "Expected a valid channel name");
};
@@ -2441,6 +2473,10 @@ const glue42NotificationActionDecoder = object$1({
icon: optional$1(string$1()),
interop: optional$1(interopActionSettingsDecoder)
});
+const notificationStateDecoder = oneOf$1(constant$1("Active"), constant$1("Acknowledged"), constant$1("Seen"), constant$1("Closed"), constant$1("Stale"), constant$1("Snoozed"), constant$1("Processing"));
+const activeNotificationsCountChangeDecoder = object$1({
+ count: number$1()
+});
const notificationDefinitionDecoder = object$1({
badge: optional$1(string$1()),
body: optional$1(string$1()),
@@ -2476,7 +2512,12 @@ const glue42NotificationOptionsDecoder = object$1({
vibrate: optional$1(array$1(number$1())),
severity: optional$1(oneOf$1(constant$1("Low"), constant$1("None"), constant$1("Medium"), constant$1("High"), constant$1("Critical"))),
showToast: optional$1(boolean$1()),
- showInPanel: optional$1(boolean$1())
+ showInPanel: optional$1(boolean$1()),
+ state: optional$1(notificationStateDecoder)
+});
+const notificationSetStateRequestDecoder = object$1({
+ id: nonEmptyStringDecoder,
+ state: notificationStateDecoder
});
const channelContextDecoder = object$1({
name: nonEmptyStringDecoder,
@@ -2503,6 +2544,28 @@ const notificationEventPayloadDecoder = object$1({
action: optional$1(string$1()),
id: optional$1(nonEmptyStringDecoder)
});
+const notificationFilterDecoder = object$1({
+ allowed: optional$1(array$1(nonEmptyStringDecoder)),
+ blocked: optional$1(array$1(nonEmptyStringDecoder))
+});
+const notificationsConfigurationDecoder = object$1({
+ enable: optional$1(boolean$1()),
+ enableToasts: optional$1(boolean$1()),
+ sourceFilter: optional$1(notificationFilterDecoder),
+});
+const notificationsConfigurationProtocolDecoder = object$1({
+ configuration: notificationsConfigurationDecoder
+});
+const strictNotificationsConfigurationProtocolDecoder = object$1({
+ configuration: object$1({
+ enable: boolean$1(),
+ enableToasts: boolean$1(),
+ sourceFilter: object$1({
+ allowed: array$1(nonEmptyStringDecoder),
+ blocked: array$1(nonEmptyStringDecoder)
+ })
+ })
+});
const platformSaveRequestConfigDecoder = object$1({
layoutType: oneOf$1(constant$1("Global"), constant$1("Workspace")),
layoutName: nonEmptyStringDecoder,
@@ -2563,7 +2626,8 @@ const notificationsDataDecoder = object$1({
vibrate: optional$1(array$1(number$1())),
severity: optional$1(oneOf$1(constant$1("Low"), constant$1("None"), constant$1("Medium"), constant$1("High"), constant$1("Critical"))),
showToast: optional$1(boolean$1()),
- showInPanel: optional$1(boolean$1())
+ showInPanel: optional$1(boolean$1()),
+ state: optional$1(notificationStateDecoder)
});
const simpleNotificationDataDecoder = object$1({
notification: notificationsDataDecoder
@@ -2618,8 +2682,32 @@ const joinChannelDataDecoder = object$1({
const windowChannelResultDecoder = object$1({
channel: optional$1(nonEmptyStringDecoder),
});
+const prefsOperationTypesDecoder = oneOf$1(constant$1("clear"), constant$1("clearAll"), constant$1("get"), constant$1("getAll"), constant$1("set"), constant$1("update"), constant$1("prefsChanged"), constant$1("prefsHello"));
+const appPreferencesDecoder = object$1({
+ app: nonEmptyStringDecoder,
+ data: object$1(),
+ lastUpdate: optional$1(nonEmptyStringDecoder),
+});
+const basePrefsConfigDecoder = object$1({
+ app: nonEmptyStringDecoder,
+});
+const getPrefsResultDecoder = object$1({
+ prefs: appPreferencesDecoder,
+});
+const getAllPrefsResultDecoder = object$1({
+ all: array$1(appPreferencesDecoder),
+});
+const changePrefsDataDecoder = object$1({
+ app: nonEmptyStringDecoder,
+ data: object$1(),
+});
+const prefsHelloSuccessDecoder = object$1({
+ platform: object$1({
+ app: nonEmptyStringDecoder,
+ }),
+});
-const operations$8 = {
+const operations$9 = {
openWindow: { name: "openWindow", dataDecoder: openWindowConfigDecoder, resultDecoder: coreWindowDataDecoder },
windowHello: { name: "windowHello", dataDecoder: windowHelloDecoder, resultDecoder: helloSuccessDecoder },
windowAdded: { name: "windowAdded", dataDecoder: coreWindowDataDecoder },
@@ -2808,7 +2896,7 @@ class WebWindowModel {
}
getURL() {
return __awaiter$1(this, void 0, void 0, function* () {
- const result = yield this._bridge.send("windows", operations$8.getUrl, { windowId: this.id });
+ const result = yield this._bridge.send("windows", operations$9.getUrl, { windowId: this.id });
return result.url;
});
}
@@ -2822,7 +2910,7 @@ class WebWindowModel {
return __awaiter$1(this, void 0, void 0, function* () {
const targetBounds = boundsDecoder.runWithException(dimension);
const commandArgs = Object.assign({}, targetBounds, { windowId: this.id, relative: false });
- yield this._bridge.send("windows", operations$8.moveResize, commandArgs);
+ yield this._bridge.send("windows", operations$9.moveResize, commandArgs);
return this.me;
});
}
@@ -2838,7 +2926,7 @@ class WebWindowModel {
nonNegativeNumberDecoder.runWithException(height);
}
const commandArgs = Object.assign({}, { width, height }, { windowId: this.id, relative: true });
- yield this._bridge.send("windows", operations$8.moveResize, commandArgs);
+ yield this._bridge.send("windows", operations$9.moveResize, commandArgs);
return this.me;
});
}
@@ -2854,7 +2942,7 @@ class WebWindowModel {
number$1().runWithException(left);
}
const commandArgs = Object.assign({}, { top, left }, { windowId: this.id, relative: true });
- yield this._bridge.send("windows", operations$8.moveResize, commandArgs);
+ yield this._bridge.send("windows", operations$9.moveResize, commandArgs);
return this.me;
});
}
@@ -2864,33 +2952,33 @@ class WebWindowModel {
window.open(undefined, this.id);
}
else {
- yield this._bridge.send("windows", operations$8.focus, { windowId: this.id });
+ yield this._bridge.send("windows", operations$9.focus, { windowId: this.id });
}
return this.me;
});
}
close() {
return __awaiter$1(this, void 0, void 0, function* () {
- yield this._bridge.send("windows", operations$8.close, { windowId: this.id });
+ yield this._bridge.send("windows", operations$9.close, { windowId: this.id });
return this.me;
});
}
getTitle() {
return __awaiter$1(this, void 0, void 0, function* () {
- const result = yield this._bridge.send("windows", operations$8.getTitle, { windowId: this.id });
+ const result = yield this._bridge.send("windows", operations$9.getTitle, { windowId: this.id });
return result.title;
});
}
setTitle(title) {
return __awaiter$1(this, void 0, void 0, function* () {
const ttl = nonEmptyStringDecoder.runWithException(title);
- yield this._bridge.send("windows", operations$8.setTitle, { windowId: this.id, title: ttl });
+ yield this._bridge.send("windows", operations$9.setTitle, { windowId: this.id, title: ttl });
return this.me;
});
}
getBounds() {
return __awaiter$1(this, void 0, void 0, function* () {
- const result = yield this._bridge.send("windows", operations$8.getBounds, { windowId: this.id });
+ const result = yield this._bridge.send("windows", operations$9.getBounds, { windowId: this.id });
return result.bounds;
});
}
@@ -2925,7 +3013,7 @@ class WebWindowModel {
}
getChannel() {
return __awaiter$1(this, void 0, void 0, function* () {
- const result = yield this._bridge.send("windows", operations$8.getChannel, { windowId: this.id }, undefined, { includeOperationCheck: true });
+ const result = yield this._bridge.send("windows", operations$9.getChannel, { windowId: this.id }, undefined, { includeOperationCheck: true });
return result.channel;
});
}
@@ -3023,7 +3111,7 @@ class WindowsController {
return __awaiter$1(this, void 0, void 0, function* () {
yield this.platformRegistration;
const operationName = windowOperationTypesDecoder.runWithException(args.operation);
- const operation = operations$8[operationName];
+ const operation = operations$9[operationName];
if (!operation.execute) {
return;
}
@@ -3039,7 +3127,7 @@ class WindowsController {
nonEmptyStringDecoder.runWithException(name);
nonEmptyStringDecoder.runWithException(url);
const settings = windowOpenSettingsDecoder.runWithException(options);
- const windowSuccess = yield this.bridge.send("windows", operations$8.openWindow, { name, url, options: settings });
+ const windowSuccess = yield this.bridge.send("windows", operations$9.openWindow, { name, url, options: settings });
return this.waitForWindowAdded(windowSuccess.windowId);
});
}
@@ -3064,16 +3152,16 @@ class WindowsController {
};
}
addWindowOperationExecutors() {
- operations$8.focusChange.execute = this.handleFocusChangeEvent.bind(this);
- operations$8.windowAdded.execute = this.handleWindowAdded.bind(this);
- operations$8.windowRemoved.execute = this.handleWindowRemoved.bind(this);
- operations$8.getBounds.execute = this.handleGetBounds.bind(this);
- operations$8.getFrameBounds.execute = this.handleGetBounds.bind(this);
- operations$8.getTitle.execute = this.handleGetTitle.bind(this);
- operations$8.getUrl.execute = this.handleGetUrl.bind(this);
- operations$8.moveResize.execute = this.handleMoveResize.bind(this);
- operations$8.setTitle.execute = this.handleSetTitle.bind(this);
- operations$8.getChannel.execute = this.handleGetChannel.bind(this);
+ operations$9.focusChange.execute = this.handleFocusChangeEvent.bind(this);
+ operations$9.windowAdded.execute = this.handleWindowAdded.bind(this);
+ operations$9.windowRemoved.execute = this.handleWindowRemoved.bind(this);
+ operations$9.getBounds.execute = this.handleGetBounds.bind(this);
+ operations$9.getFrameBounds.execute = this.handleGetBounds.bind(this);
+ operations$9.getTitle.execute = this.handleGetTitle.bind(this);
+ operations$9.getUrl.execute = this.handleGetUrl.bind(this);
+ operations$9.moveResize.execute = this.handleMoveResize.bind(this);
+ operations$9.setTitle.execute = this.handleSetTitle.bind(this);
+ operations$9.getChannel.execute = this.handleGetChannel.bind(this);
}
my() {
return Object.assign({}, this.me);
@@ -3104,7 +3192,7 @@ class WindowsController {
}
sayHello() {
return __awaiter$1(this, void 0, void 0, function* () {
- const helloSuccess = yield this.bridge.send("windows", operations$8.windowHello, { windowId: this.publicWindowId });
+ const helloSuccess = yield this.bridge.send("windows", operations$9.windowHello, { windowId: this.publicWindowId });
return helloSuccess;
});
}
@@ -3270,7 +3358,7 @@ class WindowsController {
if (this.me) {
this.me.isFocused = hasFocus;
}
- yield this.bridge.send("windows", operations$8.focusChange, eventData);
+ yield this.bridge.send("windows", operations$9.focusChange, eventData);
});
}
defineEventListeners() {
@@ -3470,7 +3558,7 @@ class GlueBridge {
}
}
-const operations$7 = {
+const operations$8 = {
appHello: { name: "appHello", dataDecoder: windowHelloDecoder, resultDecoder: appHelloSuccessDecoder },
appDirectoryStateChange: { name: "appDirectoryStateChange", dataDecoder: appDirectoryStateChangeDecoder },
instanceStarted: { name: "instanceStarted", dataDecoder: instanceDataDecoder },
@@ -3518,7 +3606,7 @@ class AppManagerController {
return __awaiter$1(this, void 0, void 0, function* () {
yield this.platformRegistration;
const operationName = appManagerOperationTypesDecoder.runWithException(args.operation);
- const operation = operations$7[operationName];
+ const operation = operations$8[operationName];
if (!operation.execute) {
return;
}
@@ -3563,7 +3651,7 @@ class AppManagerController {
layoutComponentId: options === null || options === void 0 ? void 0 : options.layoutComponentId,
channelId: options === null || options === void 0 ? void 0 : options.channelId
};
- const openResult = yield this.bridge.send("appManager", operations$7.applicationStart, startOptions);
+ const openResult = yield this.bridge.send("appManager", operations$8.applicationStart, startOptions);
const app = this.applications.find((a) => a.name === openResult.applicationName);
return this.ioc.buildInstance(openResult, app);
});
@@ -3596,9 +3684,9 @@ class AppManagerController {
return api;
}
addOperationsExecutors() {
- operations$7.appDirectoryStateChange.execute = this.handleAppDirectoryStateChange.bind(this);
- operations$7.instanceStarted.execute = this.handleInstanceStartedMessage.bind(this);
- operations$7.instanceStopped.execute = this.handleInstanceStoppedMessage.bind(this);
+ operations$8.appDirectoryStateChange.execute = this.handleAppDirectoryStateChange.bind(this);
+ operations$8.instanceStarted.execute = this.handleInstanceStartedMessage.bind(this);
+ operations$8.instanceStopped.execute = this.handleInstanceStoppedMessage.bind(this);
}
handleAppDirectoryStateChange(data) {
return __awaiter$1(this, void 0, void 0, function* () {
@@ -3715,7 +3803,7 @@ class AppManagerController {
return soFar;
}, { valid: [], invalid: [] });
const responseTimeout = this.baseApplicationsTimeoutMS + this.appImportTimeoutMS * parseResult.valid.length;
- yield this.bridge.send("appManager", operations$7.import, { definitions: parseResult.valid, mode }, { methodResponseTimeoutMs: responseTimeout });
+ yield this.bridge.send("appManager", operations$8.import, { definitions: parseResult.valid, mode }, { methodResponseTimeoutMs: responseTimeout });
return {
imported: parseResult.valid.map((valid) => valid.name),
errors: parseResult.invalid
@@ -3725,17 +3813,17 @@ class AppManagerController {
remove(name) {
return __awaiter$1(this, void 0, void 0, function* () {
nonEmptyStringDecoder.runWithException(name);
- yield this.bridge.send("appManager", operations$7.remove, { name }, { methodResponseTimeoutMs: this.baseApplicationsTimeoutMS });
+ yield this.bridge.send("appManager", operations$8.remove, { name }, { methodResponseTimeoutMs: this.baseApplicationsTimeoutMS });
});
}
clear() {
return __awaiter$1(this, void 0, void 0, function* () {
- yield this.bridge.send("appManager", operations$7.clear, undefined, { methodResponseTimeoutMs: this.baseApplicationsTimeoutMS });
+ yield this.bridge.send("appManager", operations$8.clear, undefined, { methodResponseTimeoutMs: this.baseApplicationsTimeoutMS });
});
}
export() {
return __awaiter$1(this, void 0, void 0, function* () {
- const response = yield this.bridge.send("appManager", operations$7.export, undefined, { methodResponseTimeoutMs: this.baseApplicationsTimeoutMS });
+ const response = yield this.bridge.send("appManager", operations$8.export, undefined, { methodResponseTimeoutMs: this.baseApplicationsTimeoutMS });
return response.definitions;
});
}
@@ -3754,7 +3842,7 @@ class AppManagerController {
}
registerWithPlatform() {
return __awaiter$1(this, void 0, void 0, function* () {
- const result = yield this.bridge.send("appManager", operations$7.appHello, { windowId: this.publicWindowId }, { methodResponseTimeoutMs: this.baseApplicationsTimeoutMS });
+ const result = yield this.bridge.send("appManager", operations$8.appHello, { windowId: this.publicWindowId }, { methodResponseTimeoutMs: this.baseApplicationsTimeoutMS });
this.logger.trace("the platform responded to the hello message with a full list of apps");
this.applications = yield Promise.all(result.apps.map((app) => this.ioc.buildApplication(app, app.instances)));
this.instances = this.applications.reduce((instancesSoFar, app) => {
@@ -3807,7 +3895,7 @@ class InstanceModel {
}
stop() {
return __awaiter$1(this, void 0, void 0, function* () {
- yield this.bridge.send("appManager", operations$7.instanceStop, { id: this.data.id });
+ yield this.bridge.send("appManager", operations$8.instanceStop, { id: this.data.id });
});
}
}
@@ -3863,7 +3951,7 @@ class ApplicationModel {
}
}
-const operations$6 = {
+const operations$7 = {
layoutAdded: { name: "layoutAdded", dataDecoder: glueLayoutDecoder },
layoutChanged: { name: "layoutChanged", dataDecoder: glueLayoutDecoder },
layoutRemoved: { name: "layoutRemoved", dataDecoder: glueLayoutDecoder },
@@ -3906,7 +3994,7 @@ class LayoutsController {
handleBridgeMessage(args) {
return __awaiter$1(this, void 0, void 0, function* () {
const operationName = layoutsOperationTypesDecoder.runWithException(args.operation);
- const operation = operations$6[operationName];
+ const operation = operations$7[operationName];
if (!operation.execute) {
return;
}
@@ -3940,30 +4028,30 @@ class LayoutsController {
return Object.freeze(api);
}
addOperationsExecutors() {
- operations$6.layoutAdded.execute = this.handleOnAdded.bind(this);
- operations$6.layoutChanged.execute = this.handleOnChanged.bind(this);
- operations$6.layoutRemoved.execute = this.handleOnRemoved.bind(this);
- operations$6.clientSaveRequest.execute = this.handleSaveRequest.bind(this);
+ operations$7.layoutAdded.execute = this.handleOnAdded.bind(this);
+ operations$7.layoutChanged.execute = this.handleOnChanged.bind(this);
+ operations$7.layoutRemoved.execute = this.handleOnRemoved.bind(this);
+ operations$7.clientSaveRequest.execute = this.handleSaveRequest.bind(this);
}
get(name, type) {
return __awaiter$1(this, void 0, void 0, function* () {
nonEmptyStringDecoder.runWithException(name);
layoutTypeDecoder.runWithException(type);
- const result = yield this.bridge.send("layouts", operations$6.get, { name, type });
+ const result = yield this.bridge.send("layouts", operations$7.get, { name, type });
return result.layout;
});
}
getAll(type) {
return __awaiter$1(this, void 0, void 0, function* () {
layoutTypeDecoder.runWithException(type);
- const result = yield this.bridge.send("layouts", operations$6.getAll, { type });
+ const result = yield this.bridge.send("layouts", operations$7.getAll, { type });
return result.summaries;
});
}
export(type) {
return __awaiter$1(this, void 0, void 0, function* () {
layoutTypeDecoder.runWithException(type);
- const result = yield this.bridge.send("layouts", operations$6.export, { type });
+ const result = yield this.bridge.send("layouts", operations$7.export, { type });
return result.layouts;
});
}
@@ -3987,13 +4075,13 @@ class LayoutsController {
return soFar;
}, { valid: [] });
const layoutsToImport = layouts.filter((layout) => parseResult.valid.some((validLayout) => validLayout.name === layout.name));
- yield this.bridge.send("layouts", operations$6.import, { layouts: layoutsToImport, mode });
+ yield this.bridge.send("layouts", operations$7.import, { layouts: layoutsToImport, mode });
});
}
save(layout) {
return __awaiter$1(this, void 0, void 0, function* () {
newLayoutOptionsDecoder.runWithException(layout);
- const saveResult = yield this.bridge.send("layouts", operations$6.save, { layout });
+ const saveResult = yield this.bridge.send("layouts", operations$7.save, { layout });
return saveResult.layout;
});
}
@@ -4001,14 +4089,14 @@ class LayoutsController {
return __awaiter$1(this, void 0, void 0, function* () {
restoreOptionsDecoder.runWithException(options);
const invocationTimeout = options.timeout ? options.timeout * 2 : this.defaultLayoutRestoreTimeoutMS;
- yield this.bridge.send("layouts", operations$6.restore, { layout: options }, { methodResponseTimeoutMs: invocationTimeout });
+ yield this.bridge.send("layouts", operations$7.restore, { layout: options }, { methodResponseTimeoutMs: invocationTimeout });
});
}
remove(type, name) {
return __awaiter$1(this, void 0, void 0, function* () {
layoutTypeDecoder.runWithException(type);
nonEmptyStringDecoder.runWithException(name);
- yield this.bridge.send("layouts", operations$6.remove, { type, name });
+ yield this.bridge.send("layouts", operations$7.remove, { type, name });
});
}
handleSaveRequest(config) {
@@ -4028,7 +4116,7 @@ class LayoutsController {
}
getGlobalPermissionState() {
return __awaiter$1(this, void 0, void 0, function* () {
- const requestResult = yield this.bridge.send("layouts", operations$6.getGlobalPermissionState, undefined);
+ const requestResult = yield this.bridge.send("layouts", operations$7.getGlobalPermissionState, undefined);
return requestResult;
});
}
@@ -4047,43 +4135,43 @@ class LayoutsController {
if (myWindow.name !== "Platform" && !amIWorkspaceFrame) {
throw new Error("Cannot request permission for multi-window placement from any app other than the Platform.");
}
- const requestResult = yield this.bridge.send("layouts", operations$6.requestGlobalPermission, undefined, { methodResponseTimeoutMs: 180000 });
+ const requestResult = yield this.bridge.send("layouts", operations$7.requestGlobalPermission, undefined, { methodResponseTimeoutMs: 180000 });
return { permissionGranted: requestResult.isAvailable };
});
}
checkGlobalActivated() {
return __awaiter$1(this, void 0, void 0, function* () {
- const requestResult = yield this.bridge.send("layouts", operations$6.checkGlobalActivated, undefined);
+ const requestResult = yield this.bridge.send("layouts", operations$7.checkGlobalActivated, undefined);
return { activated: requestResult.isAvailable };
});
}
getDefaultGlobal() {
return __awaiter$1(this, void 0, void 0, function* () {
- const requestResult = yield this.bridge.send("layouts", operations$6.getDefaultGlobal, undefined, undefined, { includeOperationCheck: true });
+ const requestResult = yield this.bridge.send("layouts", operations$7.getDefaultGlobal, undefined, undefined, { includeOperationCheck: true });
return requestResult.layout;
});
}
setDefaultGlobal(name) {
return __awaiter$1(this, void 0, void 0, function* () {
nonEmptyStringDecoder.runWithException(name);
- yield this.bridge.send("layouts", operations$6.setDefaultGlobal, { name }, undefined, { includeOperationCheck: true });
+ yield this.bridge.send("layouts", operations$7.setDefaultGlobal, { name }, undefined, { includeOperationCheck: true });
});
}
clearDefaultGlobal() {
return __awaiter$1(this, void 0, void 0, function* () {
- yield this.bridge.send("layouts", operations$6.clearDefaultGlobal, undefined, undefined, { includeOperationCheck: true });
+ yield this.bridge.send("layouts", operations$7.clearDefaultGlobal, undefined, undefined, { includeOperationCheck: true });
});
}
onAdded(callback) {
this.export("Global").then((layouts) => layouts.forEach((layout) => callback(layout))).catch(() => { });
this.export("Workspace").then((layouts) => layouts.forEach((layout) => callback(layout))).catch(() => { });
- return this.registry.add(operations$6.layoutAdded.name, callback);
+ return this.registry.add(operations$7.layoutAdded.name, callback);
}
onChanged(callback) {
- return this.registry.add(operations$6.layoutChanged.name, callback);
+ return this.registry.add(operations$7.layoutChanged.name, callback);
}
onRemoved(callback) {
- return this.registry.add(operations$6.layoutRemoved.name, callback);
+ return this.registry.add(operations$7.layoutRemoved.name, callback);
}
subscribeOnSaveRequested(callback) {
if (typeof callback !== "function") {
@@ -4099,22 +4187,22 @@ class LayoutsController {
}
handleOnAdded(layout) {
return __awaiter$1(this, void 0, void 0, function* () {
- this.registry.execute(operations$6.layoutAdded.name, layout);
+ this.registry.execute(operations$7.layoutAdded.name, layout);
});
}
handleOnChanged(layout) {
return __awaiter$1(this, void 0, void 0, function* () {
- this.registry.execute(operations$6.layoutChanged.name, layout);
+ this.registry.execute(operations$7.layoutChanged.name, layout);
});
}
handleOnRemoved(layout) {
return __awaiter$1(this, void 0, void 0, function* () {
- this.registry.execute(operations$6.layoutRemoved.name, layout);
+ this.registry.execute(operations$7.layoutRemoved.name, layout);
});
}
}
-const operations$5 = {
+const operations$6 = {
raiseNotification: { name: "raiseNotification", dataDecoder: raiseNotificationDecoder, resultDecoder: raiseNotificationResultDecoder },
requestPermission: { name: "requestPermission", resultDecoder: permissionRequestResultDecoder },
notificationShow: { name: "notificationShow", dataDecoder: notificationEventPayloadDecoder },
@@ -4125,7 +4213,14 @@ const operations$5 = {
notificationClosed: { name: "notificationClosed", dataDecoder: simpleNotificationSelectDecoder },
click: { name: "click" },
clear: { name: "clear" },
- clearAll: { name: "clearAll" }
+ clearAll: { name: "clearAll" },
+ clearOld: { name: "clearOld" },
+ configure: { name: "configure", dataDecoder: notificationsConfigurationProtocolDecoder },
+ getConfiguration: { name: "getConfiguration", resultDecoder: strictNotificationsConfigurationProtocolDecoder },
+ configurationChanged: { name: "configurationChanged", resultDecoder: strictNotificationsConfigurationProtocolDecoder },
+ setState: { name: "setState", dataDecoder: notificationSetStateRequestDecoder },
+ activeCountChange: { name: "activeCountChange", resultDecoder: activeNotificationsCountChangeDecoder },
+ stateChange: { name: "stateChange", resultDecoder: notificationSetStateRequestDecoder }
};
var shortidExports$1 = {};
@@ -4502,7 +4597,7 @@ class NotificationsController {
handleBridgeMessage(args) {
return __awaiter$1(this, void 0, void 0, function* () {
const operationName = notificationsOperationTypesDecoder.runWithException(args.operation);
- const operation = operations$5[operationName];
+ const operation = operations$6[operationName];
if (!operation.execute) {
return;
}
@@ -4523,19 +4618,28 @@ class NotificationsController {
onClosed: this.onClosed.bind(this),
click: this.click.bind(this),
clear: this.clear.bind(this),
- clearAll: this.clearAll.bind(this)
+ clearAll: this.clearAll.bind(this),
+ clearOld: this.clearOld.bind(this),
+ configure: this.configure.bind(this),
+ getConfiguration: this.getConfiguration.bind(this),
+ getFilter: this.getFilter.bind(this),
+ setFilter: this.setFilter.bind(this),
+ setState: this.setState.bind(this),
+ onConfigurationChanged: this.onConfigurationChanged.bind(this),
+ onActiveCountChanged: this.onActiveCountChanged.bind(this),
+ onStateChanged: this.onStateChanged.bind(this)
};
return Object.freeze(api);
}
getPermission() {
return __awaiter$1(this, void 0, void 0, function* () {
- const queryResult = yield this.bridge.send("notifications", operations$5.getPermission, undefined);
+ const queryResult = yield this.bridge.send("notifications", operations$6.getPermission, undefined);
return queryResult.permission;
});
}
requestPermission() {
return __awaiter$1(this, void 0, void 0, function* () {
- const permissionResult = yield this.bridge.send("notifications", operations$5.requestPermission, undefined);
+ const permissionResult = yield this.bridge.send("notifications", operations$6.requestPermission, undefined);
return permissionResult.permissionGranted;
});
}
@@ -4549,7 +4653,7 @@ class NotificationsController {
throw new Error("Cannot raise the notification, because the user has declined the permission request");
}
const id = shortidExports$1.generate();
- const raiseResult = yield this.bridge.send("notifications", operations$5.raiseNotification, { settings, id });
+ const raiseResult = yield this.bridge.send("notifications", operations$6.raiseNotification, { settings, id });
const notification = this.buildNotificationFunc(raiseResult.settings, id);
this.notifications[id] = notification;
return notification;
@@ -4557,7 +4661,7 @@ class NotificationsController {
}
list() {
return __awaiter$1(this, void 0, void 0, function* () {
- const bridgeResponse = yield this.bridge.send("notifications", operations$5.list, undefined, undefined, { includeOperationCheck: true });
+ const bridgeResponse = yield this.bridge.send("notifications", operations$6.list, undefined, undefined, { includeOperationCheck: true });
return bridgeResponse.notifications;
});
}
@@ -4579,25 +4683,98 @@ class NotificationsController {
if (action) {
nonEmptyStringDecoder.runWithException(action);
}
- yield this.bridge.send("notifications", operations$5.click, { id, action }, undefined, { includeOperationCheck: true });
+ yield this.bridge.send("notifications", operations$6.click, { id, action }, undefined, { includeOperationCheck: true });
});
}
clear(id) {
return __awaiter$1(this, void 0, void 0, function* () {
nonEmptyStringDecoder.runWithException(id);
- yield this.bridge.send("notifications", operations$5.clear, { id }, undefined, { includeOperationCheck: true });
+ yield this.bridge.send("notifications", operations$6.clear, { id }, undefined, { includeOperationCheck: true });
});
}
clearAll() {
return __awaiter$1(this, void 0, void 0, function* () {
- yield this.bridge.send("notifications", operations$5.clearAll, undefined, undefined, { includeOperationCheck: true });
+ yield this.bridge.send("notifications", operations$6.clearAll, undefined, undefined, { includeOperationCheck: true });
+ });
+ }
+ clearOld() {
+ return __awaiter$1(this, void 0, void 0, function* () {
+ yield this.bridge.send("notifications", operations$6.clearOld, undefined, undefined, { includeOperationCheck: true });
+ });
+ }
+ configure(config) {
+ return __awaiter$1(this, void 0, void 0, function* () {
+ const verifiedConfig = notificationsConfigurationDecoder.runWithException(config);
+ yield this.bridge.send("notifications", operations$6.configure, { configuration: verifiedConfig }, undefined, { includeOperationCheck: true });
});
}
+ getConfiguration() {
+ return __awaiter$1(this, void 0, void 0, function* () {
+ const response = yield this.bridge.send("notifications", operations$6.getConfiguration, undefined, undefined, { includeOperationCheck: true });
+ return response.configuration;
+ });
+ }
+ getFilter() {
+ return __awaiter$1(this, void 0, void 0, function* () {
+ const response = yield this.bridge.send("notifications", operations$6.getConfiguration, undefined, undefined, { includeOperationCheck: true });
+ return response.configuration.sourceFilter;
+ });
+ }
+ setFilter(filter) {
+ return __awaiter$1(this, void 0, void 0, function* () {
+ const verifiedFilter = notificationFilterDecoder.runWithException(filter);
+ yield this.bridge.send("notifications", operations$6.configure, { configuration: { sourceFilter: verifiedFilter } }, undefined, { includeOperationCheck: true });
+ return verifiedFilter;
+ });
+ }
+ setState(id, state) {
+ return __awaiter$1(this, void 0, void 0, function* () {
+ nonEmptyStringDecoder.runWithException(id);
+ notificationStateDecoder.runWithException(state);
+ yield this.bridge.send("notifications", operations$6.setState, { id, state }, undefined, { includeOperationCheck: true });
+ });
+ }
+ onConfigurationChanged(callback) {
+ if (typeof callback !== "function") {
+ throw new Error("Cannot subscribe to configuration changed, because the provided callback is not a function!");
+ }
+ return this.registry.add("notifications-config-changed", callback);
+ }
+ onActiveCountChanged(callback) {
+ if (typeof callback !== "function") {
+ throw new Error("Cannot subscribe to onActiveCountChanged changed, because the provided callback is not a function!");
+ }
+ return this.registry.add("notifications-active-count-changed", callback);
+ }
+ onStateChanged(callback) {
+ if (typeof callback !== "function") {
+ throw new Error("Cannot subscribe to onStateChanged changed, because the provided callback is not a function!");
+ }
+ return this.registry.add("notification-state-changed", callback);
+ }
addOperationExecutors() {
- operations$5.notificationShow.execute = this.handleNotificationShow.bind(this);
- operations$5.notificationClick.execute = this.handleNotificationClick.bind(this);
- operations$5.notificationRaised.execute = this.handleNotificationRaised.bind(this);
- operations$5.notificationClosed.execute = this.handleNotificationClosed.bind(this);
+ operations$6.notificationShow.execute = this.handleNotificationShow.bind(this);
+ operations$6.notificationClick.execute = this.handleNotificationClick.bind(this);
+ operations$6.notificationRaised.execute = this.handleNotificationRaised.bind(this);
+ operations$6.notificationClosed.execute = this.handleNotificationClosed.bind(this);
+ operations$6.configurationChanged.execute = this.handleConfigurationChanged.bind(this);
+ operations$6.activeCountChange.execute = this.handleActiveCountChanged.bind(this);
+ operations$6.stateChange.execute = this.handleNotificationStateChanged.bind(this);
+ }
+ handleConfigurationChanged(data) {
+ return __awaiter$1(this, void 0, void 0, function* () {
+ this.registry.execute("notifications-config-changed", data.configuration);
+ });
+ }
+ handleActiveCountChanged(data) {
+ return __awaiter$1(this, void 0, void 0, function* () {
+ this.registry.execute("notifications-active-count-changed", data);
+ });
+ }
+ handleNotificationStateChanged(data) {
+ return __awaiter$1(this, void 0, void 0, function* () {
+ this.registry.execute("notification-state-changed", { id: data.id }, data.state);
+ });
}
handleNotificationShow(data) {
return __awaiter$1(this, void 0, void 0, function* () {
@@ -4642,12 +4819,13 @@ class NotificationsController {
}
}
-const operations$4 = {
+const operations$5 = {
getIntents: { name: "getIntents", resultDecoder: wrappedIntentsDecoder },
findIntent: { name: "findIntent", dataDecoder: wrappedIntentFilterDecoder, resultDecoder: wrappedIntentsDecoder },
raiseIntent: { name: "raiseIntent", dataDecoder: intentRequestDecoder, resultDecoder: intentResultDecoder },
raise: { name: "raise", dataDecoder: raiseIntentRequestDecoder, resultDecoder: intentResultDecoder },
- filterHandlers: { name: "filterHandlers", dataDecoder: filterHandlersWithResolverConfigDecoder, resultDecoder: filterHandlersResultDecoder }
+ filterHandlers: { name: "filterHandlers", dataDecoder: filterHandlersWithResolverConfigDecoder, resultDecoder: filterHandlersResultDecoder },
+ getIntentsByHandler: { name: "getIntentsByHandler", dataDecoder: intentHandlerDecoder, resultDecoder: getIntentsResultDecoder }
};
const GLUE42_FDC3_INTENTS_METHOD_PREFIX = "Tick42.FDC3.Intents.";
@@ -4686,7 +4864,7 @@ class IntentsController {
handleBridgeMessage(args) {
return __awaiter$1(this, void 0, void 0, function* () {
const operationName = intentsOperationTypesDecoder.runWithException(args.operation);
- const operation = operations$4[operationName];
+ const operation = operations$5[operationName];
if (!operation.execute) {
return;
}
@@ -4704,7 +4882,8 @@ class IntentsController {
addIntentListener: this.addIntentListener.bind(this),
register: this.register.bind(this),
find: this.find.bind(this),
- filterHandlers: this.filterHandlers.bind(this)
+ filterHandlers: this.filterHandlers.bind(this),
+ getIntents: this.getIntentsByHandler.bind(this)
};
return api;
}
@@ -4725,7 +4904,7 @@ class IntentsController {
const methodResponseTimeoutMs = intentRequest.waitUserResponseIndefinitely
? MAX_SET_TIMEOUT_DELAY
: (intentRequest.timeout || this.intentResolverResponseTimeout) + ADDITIONAL_BRIDGE_OPERATION_TIMEOUT;
- const response = yield this.bridge.send("intents", operations$4.raise, requestWithResolverInfo, { methodResponseTimeoutMs, waitTimeoutMs: methodResponseTimeoutMs });
+ const response = yield this.bridge.send("intents", operations$5.raise, requestWithResolverInfo, { methodResponseTimeoutMs, waitTimeoutMs: methodResponseTimeoutMs });
return response;
});
}
@@ -4765,7 +4944,7 @@ class IntentsController {
all() {
return __awaiter$1(this, void 0, void 0, function* () {
yield Promise.all(this.unregisterIntentPromises);
- const result = yield this.bridge.send("intents", operations$4.getIntents, undefined);
+ const result = yield this.bridge.send("intents", operations$5.getIntents, undefined);
return result.intents;
});
}
@@ -4863,7 +5042,7 @@ class IntentsController {
}
}
yield Promise.all(this.unregisterIntentPromises);
- const result = yield this.bridge.send("intents", operations$4.findIntent, data);
+ const result = yield this.bridge.send("intents", operations$5.findIntent, data);
return result.intents;
});
}
@@ -4904,20 +5083,29 @@ class IntentsController {
}
const methodResponseTimeoutMs = (handlerFilter.timeout || DEFAULT_PICK_HANDLER_BY_TIMEOUT) + ADDITIONAL_BRIDGE_OPERATION_TIMEOUT;
const filterHandlersRequestWithResolverConfig = { filterHandlersRequest: handlerFilter, resolverConfig: this.getResolverConfigByRequest({ handlerFilter }) };
- const result = yield this.bridge.send("intents", operations$4.filterHandlers, filterHandlersRequestWithResolverConfig, { methodResponseTimeoutMs, waitTimeoutMs: methodResponseTimeoutMs }, { includeOperationCheck: true });
- return result.handlers;
+ const result = yield this.bridge.send("intents", operations$5.filterHandlers, filterHandlersRequestWithResolverConfig, { methodResponseTimeoutMs, waitTimeoutMs: methodResponseTimeoutMs }, { includeOperationCheck: true });
+ return result;
});
}
checkIfAtLeastOneFilterIsPresent(filter) {
- const errorMsg = "Provide at least one filter criteria of the following: 'contextTypes' | 'intent' | 'resultType'";
+ const errorMsg = "Provide at least one filter criteria of the following: 'intent' | 'contextTypes' | 'resultType' | 'applicationNames'";
if (!Object.keys(filter).length) {
throw new Error(errorMsg);
}
- const { intent, resultType, contextTypes } = filter;
- if (!intent && !resultType && (!contextTypes || !contextTypes.length)) {
+ const { intent, resultType, contextTypes, applicationNames } = filter;
+ const existingValidContextTypes = contextTypes === null || contextTypes === void 0 ? void 0 : contextTypes.length;
+ const existingValidApplicationNames = applicationNames === null || applicationNames === void 0 ? void 0 : applicationNames.length;
+ if (!intent && !resultType && !existingValidContextTypes && !existingValidApplicationNames) {
throw new Error(errorMsg);
}
}
+ getIntentsByHandler(handler) {
+ return __awaiter$1(this, void 0, void 0, function* () {
+ intentHandlerDecoder.runWithException(handler);
+ const result = yield this.bridge.send("intents", operations$5.getIntentsByHandler, handler, undefined, { includeOperationCheck: true });
+ return result;
+ });
+ }
}
const Glue42CoreMessageTypes = {
@@ -4934,7 +5122,7 @@ const Glue42CoreMessageTypes = {
const webPlatformTransportName = "web-platform";
const latestFDC3Type = "latest_fdc3_type";
-const operations$3 = {
+const operations$4 = {
addChannel: { name: "addChannel", dataDecoder: channelContextDecoder },
getMyChannel: { name: "getMyChannel", resultDecoder: getMyChanelResultDecoder },
getWindowIdsOnChannel: { name: "getWindowIdsOnChannel", dataDecoder: getWindowIdsOnChannelDataDecoder, resultDecoder: getWindowIdsOnChannelResultDecoder },
@@ -4971,8 +5159,8 @@ class ChannelsController {
this.registry.clear();
}
addOperationsExecutors() {
- operations$3.getMyChannel.execute = this.handleGetMyChannel.bind(this);
- operations$3.joinChannel.execute = this.handleJoinChannel.bind(this);
+ operations$4.getMyChannel.execute = this.handleGetMyChannel.bind(this);
+ operations$4.joinChannel.execute = this.handleJoinChannel.bind(this);
}
start(coreGlue, ioc) {
return __awaiter$1(this, void 0, void 0, function* () {
@@ -4991,7 +5179,7 @@ class ChannelsController {
handleBridgeMessage(args) {
return __awaiter$1(this, void 0, void 0, function* () {
const operationName = channelsOperationTypesDecoder.runWithException(args.operation);
- const operation = operations$3[operationName];
+ const operation = operations$4[operationName];
if (!operation.execute) {
return;
}
@@ -5027,7 +5215,7 @@ class ChannelsController {
yield this.switchToChannel(name);
}
else {
- yield this.bridge.send("channels", operations$3.joinChannel, { channel: name, windowId }, undefined, { includeOperationCheck: true });
+ yield this.bridge.send("channels", operations$4.joinChannel, { channel: name, windowId }, undefined, { includeOperationCheck: true });
}
});
}
@@ -5198,7 +5386,7 @@ class ChannelsController {
if (channelWithSuchNameExists) {
throw new Error("There's an already existing channel with such name");
}
- yield this.bridge.send("channels", operations$3.addChannel, channelContext);
+ yield this.bridge.send("channels", operations$4.addChannel, channelContext);
return channelContext;
});
}
@@ -5214,7 +5402,7 @@ class ChannelsController {
return __awaiter$1(this, void 0, void 0, function* () {
const channelNames = this.getAllChannelNames();
channelNameDecoder(channelNames).runWithException(channel);
- const { windowIds } = yield this.bridge.send("channels", operations$3.getWindowIdsOnChannel, { channel }, undefined, { includeOperationCheck: true });
+ const { windowIds } = yield this.bridge.send("channels", operations$4.getWindowIdsOnChannel, { channel }, undefined, { includeOperationCheck: true });
const result = windowIds.reduce((windows, windowId) => {
const window = this.windowsController.findById(windowId);
return window ? [...windows, window] : windows;
@@ -5227,7 +5415,7 @@ class ChannelsController {
const operationData = filter !== undefined
? { filter: windowWithChannelFilterDecoder.runWithException(filter) }
: {};
- const { windowIdsWithChannels } = yield this.bridge.send("channels", operations$3.getWindowIdsWithChannels, operationData, undefined, { includeOperationCheck: true });
+ const { windowIdsWithChannels } = yield this.bridge.send("channels", operations$4.getWindowIdsWithChannels, operationData, undefined, { includeOperationCheck: true });
const result = windowIdsWithChannels.reduce((windowsWithChannels, { application, channel, windowId }) => {
const window = this.windowsController.findById(windowId);
return window ? [...windowsWithChannels, { application, channel, window }] : windowsWithChannels;
@@ -5237,7 +5425,7 @@ class ChannelsController {
}
}
-const operations$2 = {
+const operations$3 = {
getEnvironment: { name: "getEnvironment", resultDecoder: anyDecoder },
getBase: { name: "getBase", resultDecoder: anyDecoder },
platformShutdown: { name: "platformShutdown" }
@@ -5255,7 +5443,7 @@ class SystemController {
handleBridgeMessage(args) {
return __awaiter$1(this, void 0, void 0, function* () {
const operationName = systemOperationTypesDecoder.runWithException(args.operation);
- const operation = operations$2[operationName];
+ const operation = operations$3[operationName];
if (!operation.execute) {
return;
}
@@ -5276,8 +5464,8 @@ class SystemController {
}
setEnvironment() {
return __awaiter$1(this, void 0, void 0, function* () {
- const environment = yield this.bridge.send("system", operations$2.getEnvironment, undefined);
- const base = yield this.bridge.send("system", operations$2.getBase, undefined);
+ const environment = yield this.bridge.send("system", operations$3.getEnvironment, undefined);
+ const base = yield this.bridge.send("system", operations$3.getBase, undefined);
const globalNamespace = window.glue42core || window.iobrowser;
const globalNamespaceName = window.glue42core ? "glue42core" : "iobrowser";
const globalObj = Object.assign({}, globalNamespace, base, { environment });
@@ -5285,7 +5473,7 @@ class SystemController {
});
}
addOperationsExecutors() {
- operations$2.platformShutdown.execute = this.processPlatformShutdown.bind(this);
+ operations$3.platformShutdown.execute = this.processPlatformShutdown.bind(this);
}
}
@@ -5314,6 +5502,7 @@ class Notification {
this.severity = config.severity;
this.showToast = config.showToast;
this.showInPanel = config.showInPanel;
+ this.state = config.state;
}
}
@@ -5324,7 +5513,7 @@ const extensionConfigDecoder = object$1({
})
});
-const operations$1 = {
+const operations$2 = {
clientHello: { name: "clientHello", resultDecoder: extensionConfigDecoder }
};
@@ -5382,7 +5571,7 @@ class ExtController {
registerWithPlatform() {
return __awaiter$1(this, void 0, void 0, function* () {
this.logger.trace("registering with the platform");
- this.config = yield this.bridge.send("extension", operations$1.clientHello, { windowId: this.windowId });
+ this.config = yield this.bridge.send("extension", operations$2.clientHello, { windowId: this.windowId });
this.logger.trace("the platform responded to the hello message with a valid extension config");
});
}
@@ -5728,7 +5917,7 @@ class LegacyIntentsHelper {
});
}
invokeRaiseIntent(requestObj) {
- return this.bridge.send("intents", operations$4.raiseIntent, requestObj);
+ return this.bridge.send("intents", operations$5.raiseIntent, requestObj);
}
registerResponseMethod() {
return __awaiter$1(this, void 0, void 0, function* () {
@@ -5888,7 +6077,7 @@ class LegacyIntentsHelper {
}
}
-const operations = {
+const operations$1 = {
getCurrent: { name: "getCurrent", resultDecoder: simpleThemeResponseDecoder },
list: { name: "list", resultDecoder: allThemesResponseDecoder },
select: { name: "select", dataDecoder: selectThemeConfigDecoder }
@@ -5931,20 +6120,20 @@ class ThemesController {
}
getCurrent() {
return __awaiter$1(this, void 0, void 0, function* () {
- const bridgeResponse = yield this.bridge.send("themes", operations.getCurrent, undefined, undefined, { includeOperationCheck: true });
+ const bridgeResponse = yield this.bridge.send("themes", operations$1.getCurrent, undefined, undefined, { includeOperationCheck: true });
return bridgeResponse.theme;
});
}
list() {
return __awaiter$1(this, void 0, void 0, function* () {
- const bridgeResponse = yield this.bridge.send("themes", operations.list, undefined, undefined, { includeOperationCheck: true });
+ const bridgeResponse = yield this.bridge.send("themes", operations$1.list, undefined, undefined, { includeOperationCheck: true });
return bridgeResponse.themes;
});
}
select(name) {
return __awaiter$1(this, void 0, void 0, function* () {
nonEmptyStringDecoder.runWithException(name);
- yield this.bridge.send("themes", operations.select, { name }, undefined, { includeOperationCheck: true });
+ yield this.bridge.send("themes", operations$1.select, { name }, undefined, { includeOperationCheck: true });
});
}
onChanged(callback) {
@@ -6026,6 +6215,175 @@ class SessionStorageController {
}
}
+const operations = {
+ clear: { name: "clear", dataDecoder: basePrefsConfigDecoder },
+ clearAll: { name: "clearAll" },
+ get: { name: "get", dataDecoder: basePrefsConfigDecoder, resultDecoder: getPrefsResultDecoder },
+ getAll: { name: "getAll", resultDecoder: getAllPrefsResultDecoder },
+ set: { name: "set", dataDecoder: changePrefsDataDecoder },
+ update: { name: "update", dataDecoder: changePrefsDataDecoder },
+ prefsChanged: { name: "prefsChanged", dataDecoder: getPrefsResultDecoder },
+ prefsHello: { name: "prefsHello", resultDecoder: prefsHelloSuccessDecoder },
+};
+
+class PrefsController {
+ constructor() {
+ this.registry = lib$3();
+ }
+ handlePlatformShutdown() {
+ this.registry.clear();
+ }
+ start(coreGlue, ioc) {
+ return __awaiter$1(this, void 0, void 0, function* () {
+ this.logger = coreGlue.logger.subLogger("prefs.controller.web");
+ this.logger.trace("starting the web prefs controller");
+ this.addOperationsExecutors();
+ this.bridge = ioc.bridge;
+ this.config = ioc.config;
+ this.appManagerController = ioc.appManagerController;
+ try {
+ const prefsHelloSuccess = yield this.bridge.send("prefs", operations.prefsHello, undefined, undefined, { includeOperationCheck: true });
+ this.platformAppName = prefsHelloSuccess.platform.app;
+ }
+ catch (error) {
+ this.logger.warn("The platform of this client is outdated and does not support Prefs API.");
+ return;
+ }
+ this.logger.trace("no need for platform registration, attaching the prefs property to glue and returning");
+ const api = this.toApi();
+ coreGlue.prefs = api;
+ });
+ }
+ handleBridgeMessage(args) {
+ return __awaiter$1(this, void 0, void 0, function* () {
+ const operationName = prefsOperationTypesDecoder.runWithException(args.operation);
+ const operation = operations[operationName];
+ if (!operation.execute) {
+ return;
+ }
+ let operationData = args.data;
+ if (operation.dataDecoder) {
+ operationData = operation.dataDecoder.runWithException(args.data);
+ }
+ return yield operation.execute(operationData);
+ });
+ }
+ addOperationsExecutors() {
+ operations.prefsChanged.execute = this.handleOnChanged.bind(this);
+ }
+ toApi() {
+ const api = {
+ clear: this.clear.bind(this),
+ clearAll: this.clearAll.bind(this),
+ clearFor: this.clearFor.bind(this),
+ get: this.get.bind(this),
+ getAll: this.getAll.bind(this),
+ set: this.set.bind(this),
+ setFor: this.setFor.bind(this),
+ subscribe: this.subscribe.bind(this),
+ subscribeFor: this.subscribeFor.bind(this),
+ update: this.update.bind(this),
+ updateFor: this.updateFor.bind(this),
+ };
+ return api;
+ }
+ clear() {
+ return __awaiter$1(this, void 0, void 0, function* () {
+ const app = this.getMyAppName();
+ yield this.clearFor(app);
+ });
+ }
+ clearAll() {
+ return __awaiter$1(this, void 0, void 0, function* () {
+ yield this.bridge.send("prefs", operations.clearAll, undefined, undefined, { includeOperationCheck: true });
+ });
+ }
+ clearFor(app) {
+ return __awaiter$1(this, void 0, void 0, function* () {
+ const verifiedApp = nonEmptyStringDecoder.runWithException(app);
+ yield this.bridge.send("prefs", operations.clear, { app: verifiedApp }, undefined, { includeOperationCheck: true });
+ });
+ }
+ get(app) {
+ return __awaiter$1(this, void 0, void 0, function* () {
+ const verifiedApp = app === undefined || app === null ? this.getMyAppName() : nonEmptyStringDecoder.runWithException(app);
+ const { prefs } = yield this.bridge.send("prefs", operations.get, { app: verifiedApp }, undefined, { includeOperationCheck: true });
+ return prefs;
+ });
+ }
+ getAll() {
+ return __awaiter$1(this, void 0, void 0, function* () {
+ const result = yield this.bridge.send("prefs", operations.getAll, undefined, undefined, { includeOperationCheck: true });
+ return result;
+ });
+ }
+ set(data, options) {
+ var _a;
+ return __awaiter$1(this, void 0, void 0, function* () {
+ const verifiedOptions = optional$1(basePrefsConfigDecoder).runWithException(options);
+ const app = (_a = verifiedOptions === null || verifiedOptions === void 0 ? void 0 : verifiedOptions.app) !== null && _a !== void 0 ? _a : this.getMyAppName();
+ yield this.setFor(app, data);
+ });
+ }
+ setFor(app, data) {
+ return __awaiter$1(this, void 0, void 0, function* () {
+ const verifiedApp = nonEmptyStringDecoder.runWithException(app);
+ const verifiedData = object$1().runWithException(data);
+ yield this.bridge.send("prefs", operations.set, { app: verifiedApp, data: verifiedData }, undefined, { includeOperationCheck: true });
+ });
+ }
+ subscribe(callback) {
+ const app = this.getMyAppName();
+ return this.subscribeFor(app, callback);
+ }
+ subscribeFor(app, callback) {
+ const verifiedApp = nonEmptyStringDecoder.runWithException(app);
+ const applications = this.appManagerController.getApplications();
+ const isValidApp = verifiedApp === this.platformAppName || applications.some((application) => application.name === verifiedApp);
+ if (!isValidApp) {
+ throw new Error(`The provided app name "${app}" is not valid.`);
+ }
+ if (typeof callback !== "function") {
+ throw new Error("Cannot subscribe to prefs, because the provided callback is not a function!");
+ }
+ const subscriptionKey = this.getSubscriptionKey(verifiedApp);
+ this.get(verifiedApp).then(callback);
+ return this.registry.add(subscriptionKey, callback);
+ }
+ update(data, options) {
+ var _a;
+ return __awaiter$1(this, void 0, void 0, function* () {
+ const verifiedOptions = optional$1(basePrefsConfigDecoder).runWithException(options);
+ const app = (_a = verifiedOptions === null || verifiedOptions === void 0 ? void 0 : verifiedOptions.app) !== null && _a !== void 0 ? _a : this.getMyAppName();
+ yield this.updateFor(app, data);
+ });
+ }
+ updateFor(app, data) {
+ return __awaiter$1(this, void 0, void 0, function* () {
+ const verifiedApp = nonEmptyStringDecoder.runWithException(app);
+ const verifiedData = object$1().runWithException(data);
+ yield this.bridge.send("prefs", operations.update, { app: verifiedApp, data: verifiedData }, undefined, { includeOperationCheck: true });
+ });
+ }
+ getMyAppName() {
+ var _a;
+ const myAppName = this.config.isPlatformInternal ? this.platformAppName : (_a = this.appManagerController.me) === null || _a === void 0 ? void 0 : _a.application.name;
+ if (!myAppName) {
+ throw new Error("App Preferences operations can not be executed for windows that do not have app!");
+ }
+ return myAppName;
+ }
+ getSubscriptionKey(app) {
+ return `prefs-changed-${app}`;
+ }
+ handleOnChanged({ prefs }) {
+ return __awaiter$1(this, void 0, void 0, function* () {
+ const subscriptionKey = this.getSubscriptionKey(prefs.app);
+ this.registry.execute(subscriptionKey, prefs);
+ });
+ }
+}
+
class IoC {
constructor() {
this.controllers = {
@@ -6037,7 +6395,8 @@ class IoC {
channels: this.channelsController,
system: this.systemController,
extension: this.extensionController,
- themes: this.themesController
+ themes: this.themesController,
+ prefs: this.prefsController
};
}
get communicationId() {
@@ -6100,6 +6459,12 @@ class IoC {
}
return this._channelsControllerInstance;
}
+ get prefsController() {
+ if (!this._prefsControllerInstance) {
+ this._prefsControllerInstance = new PrefsController();
+ }
+ return this._prefsControllerInstance;
+ }
get extensionController() {
if (!this._extensionController) {
this._extensionController = new ExtController();
@@ -6165,7 +6530,7 @@ class IoC {
}
}
-var version$2 = "3.1.2";
+var version$2 = "3.2.0";
const createFactoryFunction = (coreFactoryFunction) => {
return (userConfig) => __awaiter$1(void 0, void 0, void 0, function* () {
@@ -9818,7 +10183,7 @@ var ContextMessageReplaySpec = {
}
};
-var version = "6.1.0";
+var version = "6.2.0";
function prepareConfig (configuration, ext, glue42gd) {
var _a, _b, _c, _d;
@@ -12094,7 +12459,7 @@ var GW3Bridge = (function () {
currentContext = _b.sent();
_b.label = 4;
case 4:
- calculatedDelta = this.protocolVersion === 2 ?
+ calculatedDelta = this.setPathSupported ?
this.calculateContextDeltaV2(currentContext, delta) :
this.calculateContextDeltaV1(currentContext, delta);
if (!Object.keys(calculatedDelta.added).length
diff --git a/browser-client-vanilla-js/public/libs/browser.es.js.map b/browser-client-vanilla-js/public/libs/browser.es.js.map
index 7c87a85..6f75b2f 100644
--- a/browser-client-vanilla-js/public/libs/browser.es.js.map
+++ b/browser-client-vanilla-js/public/libs/browser.es.js.map
@@ -1 +1 @@
-{"version":3,"file":"browser.es.js","sources":["../src/config/index.ts","../src/config/checkSingleton.ts","../src/enterprise/index.ts","../node_modules/decoder-validate/dist/index.es5.js","../../utils/dist/utils.es.js","../src/shared/decoders.ts","../src/windows/protocol.ts","../node_modules/callback-registry/lib/index.js","../src/windows/webWindow.ts","../src/shared/systemOperations.ts","../src/shared/promise-plus.ts","../src/windows/controller.ts","../src/communication/constants.ts","../src/communication/bridge.ts","../src/appManager/protocol.ts","../src/appManager/controller.ts","../src/appManager/instance.ts","../src/appManager/application.ts","../src/layouts/protocol.ts","../src/layouts/controller.ts","../src/notifications/protocol.ts","../node_modules/shortid/lib/random/random-from-seed.js","../node_modules/shortid/lib/alphabet.js","../node_modules/shortid/lib/random/random-byte-browser.js","../node_modules/shortid/node_modules/nanoid/format.browser.js","../node_modules/shortid/lib/generate.js","../node_modules/shortid/lib/build.js","../node_modules/shortid/lib/is-valid.js","../node_modules/shortid/lib/index.js","../node_modules/shortid/index.js","../src/notifications/controller.ts","../src/intents/protocol.ts","../src/intents/constants.ts","../src/intents/controller.ts","../src/shared/constants.ts","../src/channels/protocol.ts","../src/channels/controller.ts","../src/system/protocol.ts","../src/system/controller.ts","../src/notifications/notification.ts","../src/extension/decoders.ts","../src/extension/protocol.ts","../src/extension/controller.ts","../src/shared/dispatcher.ts","../src/communication/preferred.ts","../src/intents/legacyHelper.ts","../src/themes/protocol.ts","../src/themes/controller.ts","../src/storage/session.ts","../src/shared/ioc.ts","../src/web.ts","../../core/dist/core.es.js","../src/index.ts"],"sourcesContent":["import { IOConnectBrowser } from \"../../browser\";\r\nimport { ParsedConfig } from \"../shared/types\";\r\n\r\nconst defaultConfig = {\r\n logger: \"info\",\r\n gateway: { webPlatform: {} },\r\n libraries: [],\r\n exposeAPI: true\r\n};\r\n\r\n/* eslint-disable @typescript-eslint/no-explicit-any */\r\nexport const parseConfig = (config?: IOConnectBrowser.Config): ParsedConfig => {\r\n const isPlatformInternal = !!(config as any)?.gateway?.webPlatform?.port;\r\n\r\n const combined: ParsedConfig = Object.assign({}, defaultConfig, config, { isPlatformInternal });\r\n\r\n if (combined.systemLogger) {\r\n combined.logger = combined.systemLogger.level ?? \"info\";\r\n }\r\n\r\n return combined;\r\n};\r\n","/* eslint-disable @typescript-eslint/no-explicit-any */\r\nexport const checkSingleton = (): void => {\r\n const ioConnectBrowserNamespace = (window as any).glue42core || (window as any).iobrowser;\r\n\r\n if (ioConnectBrowserNamespace && ioConnectBrowserNamespace.webStarted) {\r\n throw new Error(\"IoConnect Browser has already been started for this application.\");\r\n }\r\n\r\n if (!ioConnectBrowserNamespace) {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n (window as any).iobrowser = { webStarted: true };\r\n return;\r\n }\r\n\r\n ioConnectBrowserNamespace.webStarted = true;\r\n};\r\n","/* eslint-disable @typescript-eslint/no-explicit-any */\r\n/* eslint-disable @typescript-eslint/no-unused-vars */\r\nimport { IOConnectDesktop } from \"@interopio/desktop\";\r\nimport { IOConnectBrowser } from \"../../browser\";\r\n\r\nexport const enterprise = (config?: IOConnectBrowser.Config): IOConnectDesktop.API => {\r\n const enterpriseConfig = {\r\n windows: true,\r\n layouts: \"full\",\r\n appManager: \"full\",\r\n channels: true,\r\n libraries: config?.libraries ?? [],\r\n logger: config?.systemLogger?.level ?? \"warn\"\r\n };\r\n\r\n if (window.glue42gd) {\r\n return (window as any).Glue(enterpriseConfig);\r\n }\r\n\r\n // TODO: here call the new interopio/desktop factory when it is ready\r\n return (window as any).Glue(enterpriseConfig);\r\n};","/**\r\n * Wraps values in an `Ok` type.\r\n *\r\n * Example: `ok(5) // => {ok: true, result: 5}`\r\n */\r\nvar ok = function (result) { return ({ ok: true, result: result }); };\r\n/**\r\n * Typeguard for `Ok`.\r\n */\r\nvar isOk = function (r) { return r.ok === true; };\r\n/**\r\n * Wraps errors in an `Err` type.\r\n *\r\n * Example: `err('on fire') // => {ok: false, error: 'on fire'}`\r\n */\r\nvar err = function (error) { return ({ ok: false, error: error }); };\r\n/**\r\n * Typeguard for `Err`.\r\n */\r\nvar isErr = function (r) { return r.ok === false; };\r\n/**\r\n * Create a `Promise` that either resolves with the result of `Ok` or rejects\r\n * with the error of `Err`.\r\n */\r\nvar asPromise = function (r) {\r\n return r.ok === true ? Promise.resolve(r.result) : Promise.reject(r.error);\r\n};\r\n/**\r\n * Unwraps a `Result` and returns either the result of an `Ok`, or\r\n * `defaultValue`.\r\n *\r\n * Example:\r\n * ```\r\n * Result.withDefault(5, number().run(json))\r\n * ```\r\n *\r\n * It would be nice if `Decoder` had an instance method that mirrored this\r\n * function. Such a method would look something like this:\r\n * ```\r\n * class Decoder {\r\n * runWithDefault = (defaultValue: A, json: any): A =>\r\n * Result.withDefault(defaultValue, this.run(json));\r\n * }\r\n *\r\n * number().runWithDefault(5, json)\r\n * ```\r\n * Unfortunately, the type of `defaultValue: A` on the method causes issues\r\n * with type inference on the `object` decoder in some situations. While these\r\n * inference issues can be solved by providing the optional type argument for\r\n * `object`s, the extra trouble and confusion doesn't seem worth it.\r\n */\r\nvar withDefault = function (defaultValue, r) {\r\n return r.ok === true ? r.result : defaultValue;\r\n};\r\n/**\r\n * Return the successful result, or throw an error.\r\n */\r\nvar withException = function (r) {\r\n if (r.ok === true) {\r\n return r.result;\r\n }\r\n else {\r\n throw r.error;\r\n }\r\n};\r\n/**\r\n * Given an array of `Result`s, return the successful values.\r\n */\r\nvar successes = function (results) {\r\n return results.reduce(function (acc, r) { return (r.ok === true ? acc.concat(r.result) : acc); }, []);\r\n};\r\n/**\r\n * Apply `f` to the result of an `Ok`, or pass the error through.\r\n */\r\nvar map = function (f, r) {\r\n return r.ok === true ? ok(f(r.result)) : r;\r\n};\r\n/**\r\n * Apply `f` to the result of two `Ok`s, or pass an error through. If both\r\n * `Result`s are errors then the first one is returned.\r\n */\r\nvar map2 = function (f, ar, br) {\r\n return ar.ok === false ? ar :\r\n br.ok === false ? br :\r\n ok(f(ar.result, br.result));\r\n};\r\n/**\r\n * Apply `f` to the error of an `Err`, or pass the success through.\r\n */\r\nvar mapError = function (f, r) {\r\n return r.ok === true ? r : err(f(r.error));\r\n};\r\n/**\r\n * Chain together a sequence of computations that may fail, similar to a\r\n * `Promise`. If the first computation fails then the error will propagate\r\n * through. If it succeeds, then `f` will be applied to the value, returning a\r\n * new `Result`.\r\n */\r\nvar andThen = function (f, r) {\r\n return r.ok === true ? f(r.result) : r;\r\n};\r\n\r\n\r\nvar result = Object.freeze({\r\n\tok: ok,\r\n\tisOk: isOk,\r\n\terr: err,\r\n\tisErr: isErr,\r\n\tasPromise: asPromise,\r\n\twithDefault: withDefault,\r\n\twithException: withException,\r\n\tsuccesses: successes,\r\n\tmap: map,\r\n\tmap2: map2,\r\n\tmapError: mapError,\r\n\tandThen: andThen\r\n});\r\n\r\n/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\n\r\n\r\nvar __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n };\r\n return __assign.apply(this, arguments);\r\n};\r\n\r\nfunction __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nfunction isEqual(a, b) {\r\n if (a === b) {\r\n return true;\r\n }\r\n if (a === null && b === null) {\r\n return true;\r\n }\r\n if (typeof (a) !== typeof (b)) {\r\n return false;\r\n }\r\n if (typeof (a) === 'object') {\r\n // Array\r\n if (Array.isArray(a)) {\r\n if (!Array.isArray(b)) {\r\n return false;\r\n }\r\n if (a.length !== b.length) {\r\n return false;\r\n }\r\n for (var i = 0; i < a.length; i++) {\r\n if (!isEqual(a[i], b[i])) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n // Hash table\r\n var keys = Object.keys(a);\r\n if (keys.length !== Object.keys(b).length) {\r\n return false;\r\n }\r\n for (var i = 0; i < keys.length; i++) {\r\n if (!b.hasOwnProperty(keys[i])) {\r\n return false;\r\n }\r\n if (!isEqual(a[keys[i]], b[keys[i]])) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n}\r\n/**\r\n * Type guard for `DecoderError`. One use case of the type guard is in the\r\n * `catch` of a promise. Typescript types the error argument of `catch` as\r\n * `any`, so when dealing with a decoder as a promise you may need to\r\n * distinguish between a `DecoderError` and an error string.\r\n */\r\nvar isDecoderError = function (a) {\r\n return a.kind === 'DecoderError' && typeof a.at === 'string' && typeof a.message === 'string';\r\n};\r\n/*\r\n * Helpers\r\n */\r\nvar isJsonArray = function (json) { return Array.isArray(json); };\r\nvar isJsonObject = function (json) {\r\n return typeof json === 'object' && json !== null && !isJsonArray(json);\r\n};\r\nvar typeString = function (json) {\r\n switch (typeof json) {\r\n case 'string':\r\n return 'a string';\r\n case 'number':\r\n return 'a number';\r\n case 'boolean':\r\n return 'a boolean';\r\n case 'undefined':\r\n return 'undefined';\r\n case 'object':\r\n if (json instanceof Array) {\r\n return 'an array';\r\n }\r\n else if (json === null) {\r\n return 'null';\r\n }\r\n else {\r\n return 'an object';\r\n }\r\n default:\r\n return JSON.stringify(json);\r\n }\r\n};\r\nvar expectedGot = function (expected, got) {\r\n return \"expected \" + expected + \", got \" + typeString(got);\r\n};\r\nvar printPath = function (paths) {\r\n return paths.map(function (path) { return (typeof path === 'string' ? \".\" + path : \"[\" + path + \"]\"); }).join('');\r\n};\r\nvar prependAt = function (newAt, _a) {\r\n var at = _a.at, rest = __rest(_a, [\"at\"]);\r\n return (__assign({ at: newAt + (at || '') }, rest));\r\n};\r\n/**\r\n * Decoders transform json objects with unknown structure into known and\r\n * verified forms. You can create objects of type `Decoder` with either the\r\n * primitive decoder functions, such as `boolean()` and `string()`, or by\r\n * applying higher-order decoders to the primitives, such as `array(boolean())`\r\n * or `dict(string())`.\r\n *\r\n * Each of the decoder functions are available both as a static method on\r\n * `Decoder` and as a function alias -- for example the string decoder is\r\n * defined at `Decoder.string()`, but is also aliased to `string()`. Using the\r\n * function aliases exported with the library is recommended.\r\n *\r\n * `Decoder` exposes a number of 'run' methods, which all decode json in the\r\n * same way, but communicate success and failure in different ways. The `map`\r\n * and `andThen` methods modify decoders without having to call a 'run' method.\r\n *\r\n * Alternatively, the main decoder `run()` method returns an object of type\r\n * `Result`. This library provides a number of helper\r\n * functions for dealing with the `Result` type, so you can do all the same\r\n * things with a `Result` as with the decoder methods.\r\n */\r\nvar Decoder = /** @class */ (function () {\r\n /**\r\n * The Decoder class constructor is kept private to separate the internal\r\n * `decode` function from the external `run` function. The distinction\r\n * between the two functions is that `decode` returns a\r\n * `Partial` on failure, which contains an unfinished error\r\n * report. When `run` is called on a decoder, the relevant series of `decode`\r\n * calls is made, and then on failure the resulting `Partial`\r\n * is turned into a `DecoderError` by filling in the missing information.\r\n *\r\n * While hiding the constructor may seem restrictive, leveraging the\r\n * provided decoder combinators and helper functions such as\r\n * `andThen` and `map` should be enough to build specialized decoders as\r\n * needed.\r\n */\r\n function Decoder(decode) {\r\n var _this = this;\r\n this.decode = decode;\r\n /**\r\n * Run the decoder and return a `Result` with either the decoded value or a\r\n * `DecoderError` containing the json input, the location of the error, and\r\n * the error message.\r\n *\r\n * Examples:\r\n * ```\r\n * number().run(12)\r\n * // => {ok: true, result: 12}\r\n *\r\n * string().run(9001)\r\n * // =>\r\n * // {\r\n * // ok: false,\r\n * // error: {\r\n * // kind: 'DecoderError',\r\n * // input: 9001,\r\n * // at: 'input',\r\n * // message: 'expected a string, got 9001'\r\n * // }\r\n * // }\r\n * ```\r\n */\r\n this.run = function (json) {\r\n return mapError(function (error) { return ({\r\n kind: 'DecoderError',\r\n input: json,\r\n at: 'input' + (error.at || ''),\r\n message: error.message || ''\r\n }); }, _this.decode(json));\r\n };\r\n /**\r\n * Run the decoder as a `Promise`.\r\n */\r\n this.runPromise = function (json) { return asPromise(_this.run(json)); };\r\n /**\r\n * Run the decoder and return the value on success, or throw an exception\r\n * with a formatted error string.\r\n */\r\n this.runWithException = function (json) { return withException(_this.run(json)); };\r\n /**\r\n * Construct a new decoder that applies a transformation to the decoded\r\n * result. If the decoder succeeds then `f` will be applied to the value. If\r\n * it fails the error will propagated through.\r\n *\r\n * Example:\r\n * ```\r\n * number().map(x => x * 5).run(10)\r\n * // => {ok: true, result: 50}\r\n * ```\r\n */\r\n this.map = function (f) {\r\n return new Decoder(function (json) { return map(f, _this.decode(json)); });\r\n };\r\n /**\r\n * Chain together a sequence of decoders. The first decoder will run, and\r\n * then the function will determine what decoder to run second. If the result\r\n * of the first decoder succeeds then `f` will be applied to the decoded\r\n * value. If it fails the error will propagate through.\r\n *\r\n * This is a very powerful method -- it can act as both the `map` and `where`\r\n * methods, can improve error messages for edge cases, and can be used to\r\n * make a decoder for custom types.\r\n *\r\n * Example of adding an error message:\r\n * ```\r\n * const versionDecoder = valueAt(['version'], number());\r\n * const infoDecoder3 = object({a: boolean()});\r\n *\r\n * const decoder = versionDecoder.andThen(version => {\r\n * switch (version) {\r\n * case 3:\r\n * return infoDecoder3;\r\n * default:\r\n * return fail(`Unable to decode info, version ${version} is not supported.`);\r\n * }\r\n * });\r\n *\r\n * decoder.run({version: 3, a: true})\r\n * // => {ok: true, result: {a: true}}\r\n *\r\n * decoder.run({version: 5, x: 'abc'})\r\n * // =>\r\n * // {\r\n * // ok: false,\r\n * // error: {... message: 'Unable to decode info, version 5 is not supported.'}\r\n * // }\r\n * ```\r\n *\r\n * Example of decoding a custom type:\r\n * ```\r\n * // nominal type for arrays with a length of at least one\r\n * type NonEmptyArray = T[] & { __nonEmptyArrayBrand__: void };\r\n *\r\n * const nonEmptyArrayDecoder = (values: Decoder): Decoder> =>\r\n * array(values).andThen(arr =>\r\n * arr.length > 0\r\n * ? succeed(createNonEmptyArray(arr))\r\n * : fail(`expected a non-empty array, got an empty array`)\r\n * );\r\n * ```\r\n */\r\n this.andThen = function (f) {\r\n return new Decoder(function (json) {\r\n return andThen(function (value) { return f(value).decode(json); }, _this.decode(json));\r\n });\r\n };\r\n /**\r\n * Add constraints to a decoder _without_ changing the resulting type. The\r\n * `test` argument is a predicate function which returns true for valid\r\n * inputs. When `test` fails on an input, the decoder fails with the given\r\n * `errorMessage`.\r\n *\r\n * ```\r\n * const chars = (length: number): Decoder =>\r\n * string().where(\r\n * (s: string) => s.length === length,\r\n * `expected a string of length ${length}`\r\n * );\r\n *\r\n * chars(5).run('12345')\r\n * // => {ok: true, result: '12345'}\r\n *\r\n * chars(2).run('HELLO')\r\n * // => {ok: false, error: {... message: 'expected a string of length 2'}}\r\n *\r\n * chars(12).run(true)\r\n * // => {ok: false, error: {... message: 'expected a string, got a boolean'}}\r\n * ```\r\n */\r\n this.where = function (test, errorMessage) {\r\n return _this.andThen(function (value) { return (test(value) ? Decoder.succeed(value) : Decoder.fail(errorMessage)); });\r\n };\r\n }\r\n /**\r\n * Decoder primitive that validates strings, and fails on all other input.\r\n */\r\n Decoder.string = function () {\r\n return new Decoder(function (json) {\r\n return typeof json === 'string'\r\n ? ok(json)\r\n : err({ message: expectedGot('a string', json) });\r\n });\r\n };\r\n /**\r\n * Decoder primitive that validates numbers, and fails on all other input.\r\n */\r\n Decoder.number = function () {\r\n return new Decoder(function (json) {\r\n return typeof json === 'number'\r\n ? ok(json)\r\n : err({ message: expectedGot('a number', json) });\r\n });\r\n };\r\n /**\r\n * Decoder primitive that validates booleans, and fails on all other input.\r\n */\r\n Decoder.boolean = function () {\r\n return new Decoder(function (json) {\r\n return typeof json === 'boolean'\r\n ? ok(json)\r\n : err({ message: expectedGot('a boolean', json) });\r\n });\r\n };\r\n Decoder.constant = function (value) {\r\n return new Decoder(function (json) {\r\n return isEqual(json, value)\r\n ? ok(value)\r\n : err({ message: \"expected \" + JSON.stringify(value) + \", got \" + JSON.stringify(json) });\r\n });\r\n };\r\n Decoder.object = function (decoders) {\r\n return new Decoder(function (json) {\r\n if (isJsonObject(json) && decoders) {\r\n var obj = {};\r\n for (var key in decoders) {\r\n if (decoders.hasOwnProperty(key)) {\r\n var r = decoders[key].decode(json[key]);\r\n if (r.ok === true) {\r\n // tslint:disable-next-line:strict-type-predicates\r\n if (r.result !== undefined) {\r\n obj[key] = r.result;\r\n }\r\n }\r\n else if (json[key] === undefined) {\r\n return err({ message: \"the key '\" + key + \"' is required but was not present\" });\r\n }\r\n else {\r\n return err(prependAt(\".\" + key, r.error));\r\n }\r\n }\r\n }\r\n return ok(obj);\r\n }\r\n else if (isJsonObject(json)) {\r\n return ok(json);\r\n }\r\n else {\r\n return err({ message: expectedGot('an object', json) });\r\n }\r\n });\r\n };\r\n Decoder.array = function (decoder) {\r\n return new Decoder(function (json) {\r\n if (isJsonArray(json) && decoder) {\r\n var decodeValue_1 = function (v, i) {\r\n return mapError(function (err$$1) { return prependAt(\"[\" + i + \"]\", err$$1); }, decoder.decode(v));\r\n };\r\n return json.reduce(function (acc, v, i) {\r\n return map2(function (arr, result) { return arr.concat([result]); }, acc, decodeValue_1(v, i));\r\n }, ok([]));\r\n }\r\n else if (isJsonArray(json)) {\r\n return ok(json);\r\n }\r\n else {\r\n return err({ message: expectedGot('an array', json) });\r\n }\r\n });\r\n };\r\n Decoder.tuple = function (decoders) {\r\n return new Decoder(function (json) {\r\n if (isJsonArray(json)) {\r\n if (json.length !== decoders.length) {\r\n return err({\r\n message: \"expected a tuple of length \" + decoders.length + \", got one of length \" + json.length\r\n });\r\n }\r\n var result = [];\r\n for (var i = 0; i < decoders.length; i++) {\r\n var nth = decoders[i].decode(json[i]);\r\n if (nth.ok) {\r\n result[i] = nth.result;\r\n }\r\n else {\r\n return err(prependAt(\"[\" + i + \"]\", nth.error));\r\n }\r\n }\r\n return ok(result);\r\n }\r\n else {\r\n return err({ message: expectedGot(\"a tuple of length \" + decoders.length, json) });\r\n }\r\n });\r\n };\r\n Decoder.union = function (ad, bd) {\r\n var decoders = [];\r\n for (var _i = 2; _i < arguments.length; _i++) {\r\n decoders[_i - 2] = arguments[_i];\r\n }\r\n return Decoder.oneOf.apply(Decoder, [ad, bd].concat(decoders));\r\n };\r\n Decoder.intersection = function (ad, bd) {\r\n var ds = [];\r\n for (var _i = 2; _i < arguments.length; _i++) {\r\n ds[_i - 2] = arguments[_i];\r\n }\r\n return new Decoder(function (json) {\r\n return [ad, bd].concat(ds).reduce(function (acc, decoder) { return map2(Object.assign, acc, decoder.decode(json)); }, ok({}));\r\n });\r\n };\r\n /**\r\n * Escape hatch to bypass validation. Always succeeds and types the result as\r\n * `any`. Useful for defining decoders incrementally, particularly for\r\n * complex objects.\r\n *\r\n * Example:\r\n * ```\r\n * interface User {\r\n * name: string;\r\n * complexUserData: ComplexType;\r\n * }\r\n *\r\n * const userDecoder: Decoder = object({\r\n * name: string(),\r\n * complexUserData: anyJson()\r\n * });\r\n * ```\r\n */\r\n Decoder.anyJson = function () { return new Decoder(function (json) { return ok(json); }); };\r\n /**\r\n * Decoder identity function which always succeeds and types the result as\r\n * `unknown`.\r\n */\r\n Decoder.unknownJson = function () {\r\n return new Decoder(function (json) { return ok(json); });\r\n };\r\n /**\r\n * Decoder for json objects where the keys are unknown strings, but the values\r\n * should all be of the same type.\r\n *\r\n * Example:\r\n * ```\r\n * dict(number()).run({chocolate: 12, vanilla: 10, mint: 37});\r\n * // => {ok: true, result: {chocolate: 12, vanilla: 10, mint: 37}}\r\n * ```\r\n */\r\n Decoder.dict = function (decoder) {\r\n return new Decoder(function (json) {\r\n if (isJsonObject(json)) {\r\n var obj = {};\r\n for (var key in json) {\r\n if (json.hasOwnProperty(key)) {\r\n var r = decoder.decode(json[key]);\r\n if (r.ok === true) {\r\n obj[key] = r.result;\r\n }\r\n else {\r\n return err(prependAt(\".\" + key, r.error));\r\n }\r\n }\r\n }\r\n return ok(obj);\r\n }\r\n else {\r\n return err({ message: expectedGot('an object', json) });\r\n }\r\n });\r\n };\r\n /**\r\n * Decoder for values that may be `undefined`. This is primarily helpful for\r\n * decoding interfaces with optional fields.\r\n *\r\n * Example:\r\n * ```\r\n * interface User {\r\n * id: number;\r\n * isOwner?: boolean;\r\n * }\r\n *\r\n * const decoder: Decoder = object({\r\n * id: number(),\r\n * isOwner: optional(boolean())\r\n * });\r\n * ```\r\n */\r\n Decoder.optional = function (decoder) {\r\n return new Decoder(function (json) { return (json === undefined || json === null ? ok(undefined) : decoder.decode(json)); });\r\n };\r\n /**\r\n * Decoder that attempts to run each decoder in `decoders` and either succeeds\r\n * with the first successful decoder, or fails after all decoders have failed.\r\n *\r\n * Note that `oneOf` expects the decoders to all have the same return type,\r\n * while `union` creates a decoder for the union type of all the input\r\n * decoders.\r\n *\r\n * Examples:\r\n * ```\r\n * oneOf(string(), number().map(String))\r\n * oneOf(constant('start'), constant('stop'), succeed('unknown'))\r\n * ```\r\n */\r\n Decoder.oneOf = function () {\r\n var decoders = [];\r\n for (var _i = 0; _i < arguments.length; _i++) {\r\n decoders[_i] = arguments[_i];\r\n }\r\n return new Decoder(function (json) {\r\n var errors = [];\r\n for (var i = 0; i < decoders.length; i++) {\r\n var r = decoders[i].decode(json);\r\n if (r.ok === true) {\r\n return r;\r\n }\r\n else {\r\n errors[i] = r.error;\r\n }\r\n }\r\n var errorsList = errors\r\n .map(function (error) { return \"at error\" + (error.at || '') + \": \" + error.message; })\r\n .join('\", \"');\r\n return err({\r\n message: \"expected a value matching one of the decoders, got the errors [\\\"\" + errorsList + \"\\\"]\"\r\n });\r\n });\r\n };\r\n /**\r\n * Decoder that always succeeds with either the decoded value, or a fallback\r\n * default value.\r\n */\r\n Decoder.withDefault = function (defaultValue, decoder) {\r\n return new Decoder(function (json) {\r\n return ok(withDefault(defaultValue, decoder.decode(json)));\r\n });\r\n };\r\n /**\r\n * Decoder that pulls a specific field out of a json structure, instead of\r\n * decoding and returning the full structure. The `paths` array describes the\r\n * object keys and array indices to traverse, so that values can be pulled out\r\n * of a nested structure.\r\n *\r\n * Example:\r\n * ```\r\n * const decoder = valueAt(['a', 'b', 0], string());\r\n *\r\n * decoder.run({a: {b: ['surprise!']}})\r\n * // => {ok: true, result: 'surprise!'}\r\n *\r\n * decoder.run({a: {x: 'cats'}})\r\n * // => {ok: false, error: {... at: 'input.a.b[0]' message: 'path does not exist'}}\r\n * ```\r\n *\r\n * Note that the `decoder` is ran on the value found at the last key in the\r\n * path, even if the last key is not found. This allows the `optional`\r\n * decoder to succeed when appropriate.\r\n * ```\r\n * const optionalDecoder = valueAt(['a', 'b', 'c'], optional(string()));\r\n *\r\n * optionalDecoder.run({a: {b: {c: 'surprise!'}}})\r\n * // => {ok: true, result: 'surprise!'}\r\n *\r\n * optionalDecoder.run({a: {b: 'cats'}})\r\n * // => {ok: false, error: {... at: 'input.a.b.c' message: 'expected an object, got \"cats\"'}\r\n *\r\n * optionalDecoder.run({a: {b: {z: 1}}})\r\n * // => {ok: true, result: undefined}\r\n * ```\r\n */\r\n Decoder.valueAt = function (paths, decoder) {\r\n return new Decoder(function (json) {\r\n var jsonAtPath = json;\r\n for (var i = 0; i < paths.length; i++) {\r\n if (jsonAtPath === undefined) {\r\n return err({\r\n at: printPath(paths.slice(0, i + 1)),\r\n message: 'path does not exist'\r\n });\r\n }\r\n else if (typeof paths[i] === 'string' && !isJsonObject(jsonAtPath)) {\r\n return err({\r\n at: printPath(paths.slice(0, i + 1)),\r\n message: expectedGot('an object', jsonAtPath)\r\n });\r\n }\r\n else if (typeof paths[i] === 'number' && !isJsonArray(jsonAtPath)) {\r\n return err({\r\n at: printPath(paths.slice(0, i + 1)),\r\n message: expectedGot('an array', jsonAtPath)\r\n });\r\n }\r\n else {\r\n jsonAtPath = jsonAtPath[paths[i]];\r\n }\r\n }\r\n return mapError(function (error) {\r\n return jsonAtPath === undefined\r\n ? { at: printPath(paths), message: 'path does not exist' }\r\n : prependAt(printPath(paths), error);\r\n }, decoder.decode(jsonAtPath));\r\n });\r\n };\r\n /**\r\n * Decoder that ignores the input json and always succeeds with `fixedValue`.\r\n */\r\n Decoder.succeed = function (fixedValue) {\r\n return new Decoder(function (json) { return ok(fixedValue); });\r\n };\r\n /**\r\n * Decoder that ignores the input json and always fails with `errorMessage`.\r\n */\r\n Decoder.fail = function (errorMessage) {\r\n return new Decoder(function (json) { return err({ message: errorMessage }); });\r\n };\r\n /**\r\n * Decoder that allows for validating recursive data structures. Unlike with\r\n * functions, decoders assigned to variables can't reference themselves\r\n * before they are fully defined. We can avoid prematurely referencing the\r\n * decoder by wrapping it in a function that won't be called until use, at\r\n * which point the decoder has been defined.\r\n *\r\n * Example:\r\n * ```\r\n * interface Comment {\r\n * msg: string;\r\n * replies: Comment[];\r\n * }\r\n *\r\n * const decoder: Decoder = object({\r\n * msg: string(),\r\n * replies: lazy(() => array(decoder))\r\n * });\r\n * ```\r\n */\r\n Decoder.lazy = function (mkDecoder) {\r\n return new Decoder(function (json) { return mkDecoder().decode(json); });\r\n };\r\n return Decoder;\r\n}());\r\n\r\n/* tslint:disable:variable-name */\r\n/** See `Decoder.string` */\r\nvar string = Decoder.string;\r\n/** See `Decoder.number` */\r\nvar number = Decoder.number;\r\n/** See `Decoder.boolean` */\r\nvar boolean = Decoder.boolean;\r\n/** See `Decoder.anyJson` */\r\nvar anyJson = Decoder.anyJson;\r\n/** See `Decoder.unknownJson` */\r\nvar unknownJson = Decoder.unknownJson;\r\n/** See `Decoder.constant` */\r\nvar constant = Decoder.constant;\r\n/** See `Decoder.object` */\r\nvar object = Decoder.object;\r\n/** See `Decoder.array` */\r\nvar array = Decoder.array;\r\n/** See `Decoder.tuple` */\r\nvar tuple = Decoder.tuple;\r\n/** See `Decoder.dict` */\r\nvar dict = Decoder.dict;\r\n/** See `Decoder.optional` */\r\nvar optional = Decoder.optional;\r\n/** See `Decoder.oneOf` */\r\nvar oneOf = Decoder.oneOf;\r\n/** See `Decoder.union` */\r\nvar union = Decoder.union;\r\n/** See `Decoder.intersection` */\r\nvar intersection = Decoder.intersection;\r\n/** See `Decoder.withDefault` */\r\nvar withDefault$1 = Decoder.withDefault;\r\n/** See `Decoder.valueAt` */\r\nvar valueAt = Decoder.valueAt;\r\n/** See `Decoder.succeed` */\r\nvar succeed = Decoder.succeed;\r\n/** See `Decoder.fail` */\r\nvar fail = Decoder.fail;\r\n/** See `Decoder.lazy` */\r\nvar lazy = Decoder.lazy;\r\n\r\nexport { result as Result, Decoder, isDecoderError, string, number, boolean, anyJson, unknownJson, constant, object, array, tuple, dict, optional, oneOf, union, intersection, withDefault$1 as withDefault, valueAt, succeed, fail, lazy };\r\n//# sourceMappingURL=index.es5.js.map\r\n","const connectBrowserAppProps = [\"name\", \"title\", \"version\", \"customProperties\", \"icon\", \"caption\", \"type\"];\nconst fdc3v2AppProps = [\"appId\", \"name\", \"type\", \"details\", \"version\", \"title\", \"tooltip\", \"lang\", \"description\", \"categories\", \"icons\", \"screenshots\", \"contactEmail\", \"moreInfo\", \"publisher\", \"customConfig\", \"hostManifests\", \"interop\", \"localizedVersions\"];\n\n/**\r\n * Wraps values in an `Ok` type.\r\n *\r\n * Example: `ok(5) // => {ok: true, result: 5}`\r\n */\r\nvar ok = function (result) { return ({ ok: true, result: result }); };\r\n/**\r\n * Wraps errors in an `Err` type.\r\n *\r\n * Example: `err('on fire') // => {ok: false, error: 'on fire'}`\r\n */\r\nvar err = function (error) { return ({ ok: false, error: error }); };\r\n/**\r\n * Create a `Promise` that either resolves with the result of `Ok` or rejects\r\n * with the error of `Err`.\r\n */\r\nvar asPromise = function (r) {\r\n return r.ok === true ? Promise.resolve(r.result) : Promise.reject(r.error);\r\n};\r\n/**\r\n * Unwraps a `Result` and returns either the result of an `Ok`, or\r\n * `defaultValue`.\r\n *\r\n * Example:\r\n * ```\r\n * Result.withDefault(5, number().run(json))\r\n * ```\r\n *\r\n * It would be nice if `Decoder` had an instance method that mirrored this\r\n * function. Such a method would look something like this:\r\n * ```\r\n * class Decoder {\r\n * runWithDefault = (defaultValue: A, json: any): A =>\r\n * Result.withDefault(defaultValue, this.run(json));\r\n * }\r\n *\r\n * number().runWithDefault(5, json)\r\n * ```\r\n * Unfortunately, the type of `defaultValue: A` on the method causes issues\r\n * with type inference on the `object` decoder in some situations. While these\r\n * inference issues can be solved by providing the optional type argument for\r\n * `object`s, the extra trouble and confusion doesn't seem worth it.\r\n */\r\nvar withDefault = function (defaultValue, r) {\r\n return r.ok === true ? r.result : defaultValue;\r\n};\r\n/**\r\n * Return the successful result, or throw an error.\r\n */\r\nvar withException = function (r) {\r\n if (r.ok === true) {\r\n return r.result;\r\n }\r\n else {\r\n throw r.error;\r\n }\r\n};\r\n/**\r\n * Apply `f` to the result of an `Ok`, or pass the error through.\r\n */\r\nvar map = function (f, r) {\r\n return r.ok === true ? ok(f(r.result)) : r;\r\n};\r\n/**\r\n * Apply `f` to the result of two `Ok`s, or pass an error through. If both\r\n * `Result`s are errors then the first one is returned.\r\n */\r\nvar map2 = function (f, ar, br) {\r\n return ar.ok === false ? ar :\r\n br.ok === false ? br :\r\n ok(f(ar.result, br.result));\r\n};\r\n/**\r\n * Apply `f` to the error of an `Err`, or pass the success through.\r\n */\r\nvar mapError = function (f, r) {\r\n return r.ok === true ? r : err(f(r.error));\r\n};\r\n/**\r\n * Chain together a sequence of computations that may fail, similar to a\r\n * `Promise`. If the first computation fails then the error will propagate\r\n * through. If it succeeds, then `f` will be applied to the value, returning a\r\n * new `Result`.\r\n */\r\nvar andThen = function (f, r) {\r\n return r.ok === true ? f(r.result) : r;\r\n};\r\n\r\n/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\n\r\n\r\nvar __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n };\r\n return __assign.apply(this, arguments);\r\n};\r\n\r\nfunction __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nfunction isEqual(a, b) {\r\n if (a === b) {\r\n return true;\r\n }\r\n if (a === null && b === null) {\r\n return true;\r\n }\r\n if (typeof (a) !== typeof (b)) {\r\n return false;\r\n }\r\n if (typeof (a) === 'object') {\r\n // Array\r\n if (Array.isArray(a)) {\r\n if (!Array.isArray(b)) {\r\n return false;\r\n }\r\n if (a.length !== b.length) {\r\n return false;\r\n }\r\n for (var i = 0; i < a.length; i++) {\r\n if (!isEqual(a[i], b[i])) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n // Hash table\r\n var keys = Object.keys(a);\r\n if (keys.length !== Object.keys(b).length) {\r\n return false;\r\n }\r\n for (var i = 0; i < keys.length; i++) {\r\n if (!b.hasOwnProperty(keys[i])) {\r\n return false;\r\n }\r\n if (!isEqual(a[keys[i]], b[keys[i]])) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n}\r\n/*\r\n * Helpers\r\n */\r\nvar isJsonArray = function (json) { return Array.isArray(json); };\r\nvar isJsonObject = function (json) {\r\n return typeof json === 'object' && json !== null && !isJsonArray(json);\r\n};\r\nvar typeString = function (json) {\r\n switch (typeof json) {\r\n case 'string':\r\n return 'a string';\r\n case 'number':\r\n return 'a number';\r\n case 'boolean':\r\n return 'a boolean';\r\n case 'undefined':\r\n return 'undefined';\r\n case 'object':\r\n if (json instanceof Array) {\r\n return 'an array';\r\n }\r\n else if (json === null) {\r\n return 'null';\r\n }\r\n else {\r\n return 'an object';\r\n }\r\n default:\r\n return JSON.stringify(json);\r\n }\r\n};\r\nvar expectedGot = function (expected, got) {\r\n return \"expected \" + expected + \", got \" + typeString(got);\r\n};\r\nvar printPath = function (paths) {\r\n return paths.map(function (path) { return (typeof path === 'string' ? \".\" + path : \"[\" + path + \"]\"); }).join('');\r\n};\r\nvar prependAt = function (newAt, _a) {\r\n var at = _a.at, rest = __rest(_a, [\"at\"]);\r\n return (__assign({ at: newAt + (at || '') }, rest));\r\n};\r\n/**\r\n * Decoders transform json objects with unknown structure into known and\r\n * verified forms. You can create objects of type `Decoder` with either the\r\n * primitive decoder functions, such as `boolean()` and `string()`, or by\r\n * applying higher-order decoders to the primitives, such as `array(boolean())`\r\n * or `dict(string())`.\r\n *\r\n * Each of the decoder functions are available both as a static method on\r\n * `Decoder` and as a function alias -- for example the string decoder is\r\n * defined at `Decoder.string()`, but is also aliased to `string()`. Using the\r\n * function aliases exported with the library is recommended.\r\n *\r\n * `Decoder` exposes a number of 'run' methods, which all decode json in the\r\n * same way, but communicate success and failure in different ways. The `map`\r\n * and `andThen` methods modify decoders without having to call a 'run' method.\r\n *\r\n * Alternatively, the main decoder `run()` method returns an object of type\r\n * `Result`. This library provides a number of helper\r\n * functions for dealing with the `Result` type, so you can do all the same\r\n * things with a `Result` as with the decoder methods.\r\n */\r\nvar Decoder = /** @class */ (function () {\r\n /**\r\n * The Decoder class constructor is kept private to separate the internal\r\n * `decode` function from the external `run` function. The distinction\r\n * between the two functions is that `decode` returns a\r\n * `Partial` on failure, which contains an unfinished error\r\n * report. When `run` is called on a decoder, the relevant series of `decode`\r\n * calls is made, and then on failure the resulting `Partial`\r\n * is turned into a `DecoderError` by filling in the missing information.\r\n *\r\n * While hiding the constructor may seem restrictive, leveraging the\r\n * provided decoder combinators and helper functions such as\r\n * `andThen` and `map` should be enough to build specialized decoders as\r\n * needed.\r\n */\r\n function Decoder(decode) {\r\n var _this = this;\r\n this.decode = decode;\r\n /**\r\n * Run the decoder and return a `Result` with either the decoded value or a\r\n * `DecoderError` containing the json input, the location of the error, and\r\n * the error message.\r\n *\r\n * Examples:\r\n * ```\r\n * number().run(12)\r\n * // => {ok: true, result: 12}\r\n *\r\n * string().run(9001)\r\n * // =>\r\n * // {\r\n * // ok: false,\r\n * // error: {\r\n * // kind: 'DecoderError',\r\n * // input: 9001,\r\n * // at: 'input',\r\n * // message: 'expected a string, got 9001'\r\n * // }\r\n * // }\r\n * ```\r\n */\r\n this.run = function (json) {\r\n return mapError(function (error) { return ({\r\n kind: 'DecoderError',\r\n input: json,\r\n at: 'input' + (error.at || ''),\r\n message: error.message || ''\r\n }); }, _this.decode(json));\r\n };\r\n /**\r\n * Run the decoder as a `Promise`.\r\n */\r\n this.runPromise = function (json) { return asPromise(_this.run(json)); };\r\n /**\r\n * Run the decoder and return the value on success, or throw an exception\r\n * with a formatted error string.\r\n */\r\n this.runWithException = function (json) { return withException(_this.run(json)); };\r\n /**\r\n * Construct a new decoder that applies a transformation to the decoded\r\n * result. If the decoder succeeds then `f` will be applied to the value. If\r\n * it fails the error will propagated through.\r\n *\r\n * Example:\r\n * ```\r\n * number().map(x => x * 5).run(10)\r\n * // => {ok: true, result: 50}\r\n * ```\r\n */\r\n this.map = function (f) {\r\n return new Decoder(function (json) { return map(f, _this.decode(json)); });\r\n };\r\n /**\r\n * Chain together a sequence of decoders. The first decoder will run, and\r\n * then the function will determine what decoder to run second. If the result\r\n * of the first decoder succeeds then `f` will be applied to the decoded\r\n * value. If it fails the error will propagate through.\r\n *\r\n * This is a very powerful method -- it can act as both the `map` and `where`\r\n * methods, can improve error messages for edge cases, and can be used to\r\n * make a decoder for custom types.\r\n *\r\n * Example of adding an error message:\r\n * ```\r\n * const versionDecoder = valueAt(['version'], number());\r\n * const infoDecoder3 = object({a: boolean()});\r\n *\r\n * const decoder = versionDecoder.andThen(version => {\r\n * switch (version) {\r\n * case 3:\r\n * return infoDecoder3;\r\n * default:\r\n * return fail(`Unable to decode info, version ${version} is not supported.`);\r\n * }\r\n * });\r\n *\r\n * decoder.run({version: 3, a: true})\r\n * // => {ok: true, result: {a: true}}\r\n *\r\n * decoder.run({version: 5, x: 'abc'})\r\n * // =>\r\n * // {\r\n * // ok: false,\r\n * // error: {... message: 'Unable to decode info, version 5 is not supported.'}\r\n * // }\r\n * ```\r\n *\r\n * Example of decoding a custom type:\r\n * ```\r\n * // nominal type for arrays with a length of at least one\r\n * type NonEmptyArray = T[] & { __nonEmptyArrayBrand__: void };\r\n *\r\n * const nonEmptyArrayDecoder = (values: Decoder): Decoder> =>\r\n * array(values).andThen(arr =>\r\n * arr.length > 0\r\n * ? succeed(createNonEmptyArray(arr))\r\n * : fail(`expected a non-empty array, got an empty array`)\r\n * );\r\n * ```\r\n */\r\n this.andThen = function (f) {\r\n return new Decoder(function (json) {\r\n return andThen(function (value) { return f(value).decode(json); }, _this.decode(json));\r\n });\r\n };\r\n /**\r\n * Add constraints to a decoder _without_ changing the resulting type. The\r\n * `test` argument is a predicate function which returns true for valid\r\n * inputs. When `test` fails on an input, the decoder fails with the given\r\n * `errorMessage`.\r\n *\r\n * ```\r\n * const chars = (length: number): Decoder =>\r\n * string().where(\r\n * (s: string) => s.length === length,\r\n * `expected a string of length ${length}`\r\n * );\r\n *\r\n * chars(5).run('12345')\r\n * // => {ok: true, result: '12345'}\r\n *\r\n * chars(2).run('HELLO')\r\n * // => {ok: false, error: {... message: 'expected a string of length 2'}}\r\n *\r\n * chars(12).run(true)\r\n * // => {ok: false, error: {... message: 'expected a string, got a boolean'}}\r\n * ```\r\n */\r\n this.where = function (test, errorMessage) {\r\n return _this.andThen(function (value) { return (test(value) ? Decoder.succeed(value) : Decoder.fail(errorMessage)); });\r\n };\r\n }\r\n /**\r\n * Decoder primitive that validates strings, and fails on all other input.\r\n */\r\n Decoder.string = function () {\r\n return new Decoder(function (json) {\r\n return typeof json === 'string'\r\n ? ok(json)\r\n : err({ message: expectedGot('a string', json) });\r\n });\r\n };\r\n /**\r\n * Decoder primitive that validates numbers, and fails on all other input.\r\n */\r\n Decoder.number = function () {\r\n return new Decoder(function (json) {\r\n return typeof json === 'number'\r\n ? ok(json)\r\n : err({ message: expectedGot('a number', json) });\r\n });\r\n };\r\n /**\r\n * Decoder primitive that validates booleans, and fails on all other input.\r\n */\r\n Decoder.boolean = function () {\r\n return new Decoder(function (json) {\r\n return typeof json === 'boolean'\r\n ? ok(json)\r\n : err({ message: expectedGot('a boolean', json) });\r\n });\r\n };\r\n Decoder.constant = function (value) {\r\n return new Decoder(function (json) {\r\n return isEqual(json, value)\r\n ? ok(value)\r\n : err({ message: \"expected \" + JSON.stringify(value) + \", got \" + JSON.stringify(json) });\r\n });\r\n };\r\n Decoder.object = function (decoders) {\r\n return new Decoder(function (json) {\r\n if (isJsonObject(json) && decoders) {\r\n var obj = {};\r\n for (var key in decoders) {\r\n if (decoders.hasOwnProperty(key)) {\r\n var r = decoders[key].decode(json[key]);\r\n if (r.ok === true) {\r\n // tslint:disable-next-line:strict-type-predicates\r\n if (r.result !== undefined) {\r\n obj[key] = r.result;\r\n }\r\n }\r\n else if (json[key] === undefined) {\r\n return err({ message: \"the key '\" + key + \"' is required but was not present\" });\r\n }\r\n else {\r\n return err(prependAt(\".\" + key, r.error));\r\n }\r\n }\r\n }\r\n return ok(obj);\r\n }\r\n else if (isJsonObject(json)) {\r\n return ok(json);\r\n }\r\n else {\r\n return err({ message: expectedGot('an object', json) });\r\n }\r\n });\r\n };\r\n Decoder.array = function (decoder) {\r\n return new Decoder(function (json) {\r\n if (isJsonArray(json) && decoder) {\r\n var decodeValue_1 = function (v, i) {\r\n return mapError(function (err$$1) { return prependAt(\"[\" + i + \"]\", err$$1); }, decoder.decode(v));\r\n };\r\n return json.reduce(function (acc, v, i) {\r\n return map2(function (arr, result) { return arr.concat([result]); }, acc, decodeValue_1(v, i));\r\n }, ok([]));\r\n }\r\n else if (isJsonArray(json)) {\r\n return ok(json);\r\n }\r\n else {\r\n return err({ message: expectedGot('an array', json) });\r\n }\r\n });\r\n };\r\n Decoder.tuple = function (decoders) {\r\n return new Decoder(function (json) {\r\n if (isJsonArray(json)) {\r\n if (json.length !== decoders.length) {\r\n return err({\r\n message: \"expected a tuple of length \" + decoders.length + \", got one of length \" + json.length\r\n });\r\n }\r\n var result = [];\r\n for (var i = 0; i < decoders.length; i++) {\r\n var nth = decoders[i].decode(json[i]);\r\n if (nth.ok) {\r\n result[i] = nth.result;\r\n }\r\n else {\r\n return err(prependAt(\"[\" + i + \"]\", nth.error));\r\n }\r\n }\r\n return ok(result);\r\n }\r\n else {\r\n return err({ message: expectedGot(\"a tuple of length \" + decoders.length, json) });\r\n }\r\n });\r\n };\r\n Decoder.union = function (ad, bd) {\r\n var decoders = [];\r\n for (var _i = 2; _i < arguments.length; _i++) {\r\n decoders[_i - 2] = arguments[_i];\r\n }\r\n return Decoder.oneOf.apply(Decoder, [ad, bd].concat(decoders));\r\n };\r\n Decoder.intersection = function (ad, bd) {\r\n var ds = [];\r\n for (var _i = 2; _i < arguments.length; _i++) {\r\n ds[_i - 2] = arguments[_i];\r\n }\r\n return new Decoder(function (json) {\r\n return [ad, bd].concat(ds).reduce(function (acc, decoder) { return map2(Object.assign, acc, decoder.decode(json)); }, ok({}));\r\n });\r\n };\r\n /**\r\n * Escape hatch to bypass validation. Always succeeds and types the result as\r\n * `any`. Useful for defining decoders incrementally, particularly for\r\n * complex objects.\r\n *\r\n * Example:\r\n * ```\r\n * interface User {\r\n * name: string;\r\n * complexUserData: ComplexType;\r\n * }\r\n *\r\n * const userDecoder: Decoder = object({\r\n * name: string(),\r\n * complexUserData: anyJson()\r\n * });\r\n * ```\r\n */\r\n Decoder.anyJson = function () { return new Decoder(function (json) { return ok(json); }); };\r\n /**\r\n * Decoder identity function which always succeeds and types the result as\r\n * `unknown`.\r\n */\r\n Decoder.unknownJson = function () {\r\n return new Decoder(function (json) { return ok(json); });\r\n };\r\n /**\r\n * Decoder for json objects where the keys are unknown strings, but the values\r\n * should all be of the same type.\r\n *\r\n * Example:\r\n * ```\r\n * dict(number()).run({chocolate: 12, vanilla: 10, mint: 37});\r\n * // => {ok: true, result: {chocolate: 12, vanilla: 10, mint: 37}}\r\n * ```\r\n */\r\n Decoder.dict = function (decoder) {\r\n return new Decoder(function (json) {\r\n if (isJsonObject(json)) {\r\n var obj = {};\r\n for (var key in json) {\r\n if (json.hasOwnProperty(key)) {\r\n var r = decoder.decode(json[key]);\r\n if (r.ok === true) {\r\n obj[key] = r.result;\r\n }\r\n else {\r\n return err(prependAt(\".\" + key, r.error));\r\n }\r\n }\r\n }\r\n return ok(obj);\r\n }\r\n else {\r\n return err({ message: expectedGot('an object', json) });\r\n }\r\n });\r\n };\r\n /**\r\n * Decoder for values that may be `undefined`. This is primarily helpful for\r\n * decoding interfaces with optional fields.\r\n *\r\n * Example:\r\n * ```\r\n * interface User {\r\n * id: number;\r\n * isOwner?: boolean;\r\n * }\r\n *\r\n * const decoder: Decoder = object({\r\n * id: number(),\r\n * isOwner: optional(boolean())\r\n * });\r\n * ```\r\n */\r\n Decoder.optional = function (decoder) {\r\n return new Decoder(function (json) { return (json === undefined || json === null ? ok(undefined) : decoder.decode(json)); });\r\n };\r\n /**\r\n * Decoder that attempts to run each decoder in `decoders` and either succeeds\r\n * with the first successful decoder, or fails after all decoders have failed.\r\n *\r\n * Note that `oneOf` expects the decoders to all have the same return type,\r\n * while `union` creates a decoder for the union type of all the input\r\n * decoders.\r\n *\r\n * Examples:\r\n * ```\r\n * oneOf(string(), number().map(String))\r\n * oneOf(constant('start'), constant('stop'), succeed('unknown'))\r\n * ```\r\n */\r\n Decoder.oneOf = function () {\r\n var decoders = [];\r\n for (var _i = 0; _i < arguments.length; _i++) {\r\n decoders[_i] = arguments[_i];\r\n }\r\n return new Decoder(function (json) {\r\n var errors = [];\r\n for (var i = 0; i < decoders.length; i++) {\r\n var r = decoders[i].decode(json);\r\n if (r.ok === true) {\r\n return r;\r\n }\r\n else {\r\n errors[i] = r.error;\r\n }\r\n }\r\n var errorsList = errors\r\n .map(function (error) { return \"at error\" + (error.at || '') + \": \" + error.message; })\r\n .join('\", \"');\r\n return err({\r\n message: \"expected a value matching one of the decoders, got the errors [\\\"\" + errorsList + \"\\\"]\"\r\n });\r\n });\r\n };\r\n /**\r\n * Decoder that always succeeds with either the decoded value, or a fallback\r\n * default value.\r\n */\r\n Decoder.withDefault = function (defaultValue, decoder) {\r\n return new Decoder(function (json) {\r\n return ok(withDefault(defaultValue, decoder.decode(json)));\r\n });\r\n };\r\n /**\r\n * Decoder that pulls a specific field out of a json structure, instead of\r\n * decoding and returning the full structure. The `paths` array describes the\r\n * object keys and array indices to traverse, so that values can be pulled out\r\n * of a nested structure.\r\n *\r\n * Example:\r\n * ```\r\n * const decoder = valueAt(['a', 'b', 0], string());\r\n *\r\n * decoder.run({a: {b: ['surprise!']}})\r\n * // => {ok: true, result: 'surprise!'}\r\n *\r\n * decoder.run({a: {x: 'cats'}})\r\n * // => {ok: false, error: {... at: 'input.a.b[0]' message: 'path does not exist'}}\r\n * ```\r\n *\r\n * Note that the `decoder` is ran on the value found at the last key in the\r\n * path, even if the last key is not found. This allows the `optional`\r\n * decoder to succeed when appropriate.\r\n * ```\r\n * const optionalDecoder = valueAt(['a', 'b', 'c'], optional(string()));\r\n *\r\n * optionalDecoder.run({a: {b: {c: 'surprise!'}}})\r\n * // => {ok: true, result: 'surprise!'}\r\n *\r\n * optionalDecoder.run({a: {b: 'cats'}})\r\n * // => {ok: false, error: {... at: 'input.a.b.c' message: 'expected an object, got \"cats\"'}\r\n *\r\n * optionalDecoder.run({a: {b: {z: 1}}})\r\n * // => {ok: true, result: undefined}\r\n * ```\r\n */\r\n Decoder.valueAt = function (paths, decoder) {\r\n return new Decoder(function (json) {\r\n var jsonAtPath = json;\r\n for (var i = 0; i < paths.length; i++) {\r\n if (jsonAtPath === undefined) {\r\n return err({\r\n at: printPath(paths.slice(0, i + 1)),\r\n message: 'path does not exist'\r\n });\r\n }\r\n else if (typeof paths[i] === 'string' && !isJsonObject(jsonAtPath)) {\r\n return err({\r\n at: printPath(paths.slice(0, i + 1)),\r\n message: expectedGot('an object', jsonAtPath)\r\n });\r\n }\r\n else if (typeof paths[i] === 'number' && !isJsonArray(jsonAtPath)) {\r\n return err({\r\n at: printPath(paths.slice(0, i + 1)),\r\n message: expectedGot('an array', jsonAtPath)\r\n });\r\n }\r\n else {\r\n jsonAtPath = jsonAtPath[paths[i]];\r\n }\r\n }\r\n return mapError(function (error) {\r\n return jsonAtPath === undefined\r\n ? { at: printPath(paths), message: 'path does not exist' }\r\n : prependAt(printPath(paths), error);\r\n }, decoder.decode(jsonAtPath));\r\n });\r\n };\r\n /**\r\n * Decoder that ignores the input json and always succeeds with `fixedValue`.\r\n */\r\n Decoder.succeed = function (fixedValue) {\r\n return new Decoder(function (json) { return ok(fixedValue); });\r\n };\r\n /**\r\n * Decoder that ignores the input json and always fails with `errorMessage`.\r\n */\r\n Decoder.fail = function (errorMessage) {\r\n return new Decoder(function (json) { return err({ message: errorMessage }); });\r\n };\r\n /**\r\n * Decoder that allows for validating recursive data structures. Unlike with\r\n * functions, decoders assigned to variables can't reference themselves\r\n * before they are fully defined. We can avoid prematurely referencing the\r\n * decoder by wrapping it in a function that won't be called until use, at\r\n * which point the decoder has been defined.\r\n *\r\n * Example:\r\n * ```\r\n * interface Comment {\r\n * msg: string;\r\n * replies: Comment[];\r\n * }\r\n *\r\n * const decoder: Decoder = object({\r\n * msg: string(),\r\n * replies: lazy(() => array(decoder))\r\n * });\r\n * ```\r\n */\r\n Decoder.lazy = function (mkDecoder) {\r\n return new Decoder(function (json) { return mkDecoder().decode(json); });\r\n };\r\n return Decoder;\r\n}());\r\n\r\n/* tslint:disable:variable-name */\r\n/** See `Decoder.string` */\r\nvar string = Decoder.string;\r\n/** See `Decoder.number` */\r\nvar number = Decoder.number;\r\n/** See `Decoder.boolean` */\r\nvar boolean = Decoder.boolean;\r\n/** See `Decoder.anyJson` */\r\nvar anyJson = Decoder.anyJson;\r\n/** See `Decoder.unknownJson` */\r\nDecoder.unknownJson;\r\n/** See `Decoder.constant` */\r\nvar constant = Decoder.constant;\r\n/** See `Decoder.object` */\r\nvar object = Decoder.object;\r\n/** See `Decoder.array` */\r\nvar array = Decoder.array;\r\n/** See `Decoder.tuple` */\r\nDecoder.tuple;\r\n/** See `Decoder.dict` */\r\nvar dict = Decoder.dict;\r\n/** See `Decoder.optional` */\r\nvar optional = Decoder.optional;\r\n/** See `Decoder.oneOf` */\r\nvar oneOf = Decoder.oneOf;\r\n/** See `Decoder.union` */\r\nDecoder.union;\r\n/** See `Decoder.intersection` */\r\nDecoder.intersection;\r\n/** See `Decoder.withDefault` */\r\nDecoder.withDefault;\r\n/** See `Decoder.valueAt` */\r\nDecoder.valueAt;\r\n/** See `Decoder.succeed` */\r\nDecoder.succeed;\r\n/** See `Decoder.fail` */\r\nDecoder.fail;\r\n/** See `Decoder.lazy` */\r\nDecoder.lazy;\n\nconst nonEmptyStringDecoder = string().where((s) => s.length > 0, \"Expected a non-empty string\");\nconst nonNegativeNumberDecoder = number().where((num) => num >= 0, \"Expected a non-negative number\");\n\nconst intentDefinitionDecoder = object({\n name: nonEmptyStringDecoder,\n displayName: optional(string()),\n contexts: optional(array(string())),\n customConfig: optional(object())\n});\nconst v2TypeDecoder = oneOf(constant(\"web\"), constant(\"native\"), constant(\"citrix\"), constant(\"onlineNative\"), constant(\"other\"));\nconst v2DetailsDecoder = object({\n url: nonEmptyStringDecoder\n});\nconst v2IconDecoder = object({\n src: nonEmptyStringDecoder,\n size: optional(nonEmptyStringDecoder),\n type: optional(nonEmptyStringDecoder)\n});\nconst v2ScreenshotDecoder = object({\n src: nonEmptyStringDecoder,\n size: optional(nonEmptyStringDecoder),\n type: optional(nonEmptyStringDecoder),\n label: optional(nonEmptyStringDecoder)\n});\nconst v2ListensForIntentDecoder = object({\n contexts: array(nonEmptyStringDecoder),\n displayName: optional(nonEmptyStringDecoder),\n resultType: optional(nonEmptyStringDecoder),\n customConfig: optional(anyJson())\n});\nconst v2IntentsDecoder = object({\n listensFor: optional(dict(v2ListensForIntentDecoder)),\n raises: optional(dict(array(nonEmptyStringDecoder)))\n});\nconst v2UserChannelDecoder = object({\n broadcasts: optional(array(nonEmptyStringDecoder)),\n listensFor: optional(array(nonEmptyStringDecoder))\n});\nconst v2AppChannelDecoder = object({\n name: nonEmptyStringDecoder,\n description: optional(nonEmptyStringDecoder),\n broadcasts: optional(array(nonEmptyStringDecoder)),\n listensFor: optional(array(nonEmptyStringDecoder))\n});\nconst v2InteropDecoder = object({\n intents: optional(v2IntentsDecoder),\n userChannels: optional(v2UserChannelDecoder),\n appChannels: optional(array(v2AppChannelDecoder))\n});\nconst glue42ApplicationDetailsDecoder = object({\n url: nonEmptyStringDecoder,\n top: optional(number()),\n left: optional(number()),\n width: optional(nonNegativeNumberDecoder),\n height: optional(nonNegativeNumberDecoder)\n});\nconst glue42HostManifestsBrowserDecoder = object({\n name: optional(nonEmptyStringDecoder),\n type: optional(nonEmptyStringDecoder.where((s) => s === \"window\", \"Expected a value of window\")),\n title: optional(nonEmptyStringDecoder),\n version: optional(nonEmptyStringDecoder),\n customProperties: optional(anyJson()),\n icon: optional(string()),\n caption: optional(string()),\n details: optional(glue42ApplicationDetailsDecoder),\n intents: optional(array(intentDefinitionDecoder)),\n hidden: optional(boolean())\n});\nconst hostManifestsBrowserDecoder = oneOf(object({\n \"Glue42\": oneOf(glue42HostManifestsBrowserDecoder, anyJson())\n}), anyJson());\nconst v1DefinitionDecoder = object({\n name: nonEmptyStringDecoder,\n appId: nonEmptyStringDecoder,\n title: optional(nonEmptyStringDecoder),\n version: optional(nonEmptyStringDecoder),\n manifest: nonEmptyStringDecoder,\n manifestType: nonEmptyStringDecoder,\n tooltip: optional(nonEmptyStringDecoder),\n description: optional(nonEmptyStringDecoder),\n contactEmail: optional(nonEmptyStringDecoder),\n supportEmail: optional(nonEmptyStringDecoder),\n publisher: optional(nonEmptyStringDecoder),\n images: optional(array(object({ url: optional(nonEmptyStringDecoder) }))),\n icons: optional(array(object({ icon: optional(nonEmptyStringDecoder) }))),\n customConfig: anyJson(),\n intents: optional(array(intentDefinitionDecoder))\n});\nconst v2LocalizedDefinitionDecoder = object({\n appId: optional(nonEmptyStringDecoder),\n name: optional(nonEmptyStringDecoder),\n details: optional(v2DetailsDecoder),\n version: optional(nonEmptyStringDecoder),\n title: optional(nonEmptyStringDecoder),\n tooltip: optional(nonEmptyStringDecoder),\n lang: optional(nonEmptyStringDecoder),\n description: optional(nonEmptyStringDecoder),\n categories: optional(array(nonEmptyStringDecoder)),\n icons: optional(array(v2IconDecoder)),\n screenshots: optional(array(v2ScreenshotDecoder)),\n contactEmail: optional(nonEmptyStringDecoder),\n supportEmail: optional(nonEmptyStringDecoder),\n moreInfo: optional(nonEmptyStringDecoder),\n publisher: optional(nonEmptyStringDecoder),\n customConfig: optional(array(anyJson())),\n hostManifests: optional(hostManifestsBrowserDecoder),\n interop: optional(v2InteropDecoder)\n});\nconst v2DefinitionDecoder = object({\n appId: nonEmptyStringDecoder,\n name: nonEmptyStringDecoder,\n type: v2TypeDecoder,\n details: v2DetailsDecoder,\n version: optional(nonEmptyStringDecoder),\n title: optional(nonEmptyStringDecoder),\n tooltip: optional(nonEmptyStringDecoder),\n lang: optional(nonEmptyStringDecoder),\n description: optional(nonEmptyStringDecoder),\n categories: optional(array(nonEmptyStringDecoder)),\n icons: optional(array(v2IconDecoder)),\n screenshots: optional(array(v2ScreenshotDecoder)),\n contactEmail: optional(nonEmptyStringDecoder),\n supportEmail: optional(nonEmptyStringDecoder),\n moreInfo: optional(nonEmptyStringDecoder),\n publisher: optional(nonEmptyStringDecoder),\n customConfig: optional(array(anyJson())),\n hostManifests: optional(hostManifestsBrowserDecoder),\n interop: optional(v2InteropDecoder),\n localizedVersions: optional(dict(v2LocalizedDefinitionDecoder))\n});\nconst allDefinitionsDecoder = oneOf(v1DefinitionDecoder, v2DefinitionDecoder);\n\nconst parseDecoderErrorToStringMessage = (error) => {\n return `${error.kind} at ${error.at}: ${JSON.stringify(error.input)}. Reason - ${error.message}`;\n};\n\nclass FDC3Service {\n constructor() {\n this.fdc3ToDesktopDefinitionType = {\n web: \"window\",\n native: \"exe\",\n citrix: \"citrix\",\n onlineNative: \"clickonce\",\n other: \"window\"\n };\n }\n toApi() {\n return {\n isFdc3Definition: this.isFdc3Definition.bind(this),\n parseToBrowserBaseAppData: this.parseToBrowserBaseAppData.bind(this),\n parseToDesktopAppConfig: this.parseToDesktopAppConfig.bind(this)\n };\n }\n isFdc3Definition(definition) {\n const decodeRes = allDefinitionsDecoder.run(definition);\n if (!decodeRes.ok) {\n return { isFdc3: false };\n }\n if (definition.appId && definition.details) {\n return { isFdc3: true, version: \"2.0\" };\n }\n if (definition.manifest) {\n return { isFdc3: true, version: \"1.2\" };\n }\n return { isFdc3: false };\n }\n parseToBrowserBaseAppData(definition) {\n var _a;\n const { isFdc3, version } = this.isFdc3Definition(definition);\n if (!isFdc3) {\n throw new Error(\"The passed definition is not FDC3\");\n }\n const decodeRes = allDefinitionsDecoder.run(definition);\n if (!decodeRes.ok) {\n throw new Error(`Invalid FDC3 ${version} definition. Error: ${parseDecoderErrorToStringMessage(decodeRes.error)}`);\n }\n const userProperties = this.getUserPropertiesFromDefinition(definition, version);\n const createOptions = { url: this.getUrl(definition, version) };\n let baseApplicationData = {\n name: definition.appId,\n type: \"window\",\n createOptions,\n userProperties: Object.assign(Object.assign({}, userProperties), { intents: version === \"1.2\"\n ? userProperties.intents\n : this.getIntentsFromV2AppDefinition(definition), details: createOptions }),\n title: definition.title,\n version: definition.version,\n icon: this.getIconFromDefinition(definition, version),\n caption: definition.description,\n fdc3: version === \"2.0\" ? Object.assign(Object.assign({}, definition), { definitionVersion: \"2.0\" }) : undefined,\n };\n if ((_a = definition.hostManifests) === null || _a === void 0 ? void 0 : _a[\"Glue42\"]) {\n const decodeRes = glue42HostManifestsBrowserDecoder.run(definition.hostManifests[\"Glue42\"]);\n if (!decodeRes.ok) {\n throw new Error(`Invalid FDC3 ${version} definition. Error: ${parseDecoderErrorToStringMessage(decodeRes.error)}`);\n }\n if (!Object.keys(decodeRes.result).length) {\n throw new Error(\"Invalid 'hostManifests['Glue42]' key\");\n }\n baseApplicationData = this.mergeBaseAppDataWithGlueManifest(baseApplicationData, decodeRes.result);\n }\n return baseApplicationData;\n }\n parseToDesktopAppConfig(definition) {\n var _a, _b, _c;\n const { isFdc3, version } = this.isFdc3Definition(definition);\n if (!isFdc3) {\n throw new Error(\"The passed definition is not FDC3\");\n }\n const decodeRes = allDefinitionsDecoder.run(definition);\n if (!decodeRes.ok) {\n throw new Error(`Invalid FDC3 ${version} definition. Error: ${parseDecoderErrorToStringMessage(decodeRes.error)}`);\n }\n if (version === \"1.2\") {\n const fdc3v1Definition = definition;\n return {\n name: fdc3v1Definition.appId,\n type: \"window\",\n details: {\n url: this.getUrl(definition, version)\n },\n version: fdc3v1Definition.version,\n title: fdc3v1Definition.title,\n tooltip: fdc3v1Definition.tooltip,\n caption: fdc3v1Definition.description,\n icon: (_a = fdc3v1Definition.icons) === null || _a === void 0 ? void 0 : _a[0].icon,\n intents: fdc3v1Definition.intents,\n customProperties: {\n manifestType: fdc3v1Definition.manifestType,\n images: fdc3v1Definition.images,\n contactEmail: fdc3v1Definition.contactEmail,\n supportEmail: fdc3v1Definition.supportEmail,\n publisher: fdc3v1Definition.publisher,\n icons: fdc3v1Definition.icons,\n customConfig: fdc3v1Definition.customConfig\n }\n };\n }\n const fdc3v2Definition = definition;\n let desktopDefinition = {\n name: fdc3v2Definition.appId,\n type: this.fdc3ToDesktopDefinitionType[fdc3v2Definition.type],\n details: fdc3v2Definition.details,\n version: fdc3v2Definition.version,\n title: fdc3v2Definition.title,\n tooltip: fdc3v2Definition.tooltip,\n caption: fdc3v2Definition.description,\n icon: this.getIconFromDefinition(fdc3v2Definition, \"2.0\"),\n intents: this.getIntentsFromV2AppDefinition(fdc3v2Definition),\n fdc3: Object.assign(Object.assign({}, fdc3v2Definition), { definitionVersion: \"2.0\" })\n };\n if ((_b = fdc3v2Definition.hostManifests) === null || _b === void 0 ? void 0 : _b[\"Glue42\"]) {\n if (typeof fdc3v2Definition.hostManifests[\"Glue42\"] !== \"object\" || Array.isArray(fdc3v2Definition.hostManifests[\"Glue42\"])) {\n throw new Error(\"Invalid 'hostManifests['Glue42]' key\");\n }\n desktopDefinition = this.mergeDesktopConfigWithGlueManifest(desktopDefinition, (_c = fdc3v2Definition.hostManifests) === null || _c === void 0 ? void 0 : _c[\"Glue42\"]);\n }\n return desktopDefinition;\n }\n getUserPropertiesFromDefinition(definition, version) {\n if (version === \"1.2\") {\n return Object.fromEntries(Object.entries(definition).filter(([key]) => !connectBrowserAppProps.includes(key)));\n }\n return Object.fromEntries(Object.entries(definition).filter(([key]) => !connectBrowserAppProps.includes(key) && !fdc3v2AppProps.includes(key)));\n }\n getUrl(definition, version) {\n var _a, _b;\n let url;\n if (version === \"1.2\") {\n const parsedManifest = JSON.parse(definition.manifest);\n url = ((_a = parsedManifest.details) === null || _a === void 0 ? void 0 : _a.url) || parsedManifest.url;\n }\n else {\n url = (_b = definition.details) === null || _b === void 0 ? void 0 : _b.url;\n }\n if (!url || typeof url !== \"string\") {\n throw new Error(`Invalid FDC3 ${version} definition. Provide valid 'url' under '${version === \"1.2\" ? \"manifest\" : \"details\"}' key`);\n }\n return url;\n }\n getIntentsFromV2AppDefinition(definition) {\n var _a, _b;\n const fdc3Intents = (_b = (_a = definition.interop) === null || _a === void 0 ? void 0 : _a.intents) === null || _b === void 0 ? void 0 : _b.listensFor;\n if (!fdc3Intents) {\n return;\n }\n const intents = Object.entries(fdc3Intents).map((fdc3Intent) => {\n const [intentName, intentData] = fdc3Intent;\n return Object.assign({ name: intentName }, intentData);\n });\n return intents;\n }\n getIconFromDefinition(definition, version) {\n var _a, _b, _c, _d;\n if (version === \"1.2\") {\n return ((_b = (_a = definition.icons) === null || _a === void 0 ? void 0 : _a.find((iconDef) => iconDef.icon)) === null || _b === void 0 ? void 0 : _b.icon) || undefined;\n }\n return ((_d = (_c = definition.icons) === null || _c === void 0 ? void 0 : _c.find((iconDef) => iconDef.src)) === null || _d === void 0 ? void 0 : _d.src) || undefined;\n }\n mergeBaseAppDataWithGlueManifest(baseAppData, hostManifestDefinition) {\n let baseApplicationDefinition = baseAppData;\n if (hostManifestDefinition.details) {\n const details = Object.assign(Object.assign({}, baseAppData.createOptions), hostManifestDefinition.details);\n baseApplicationDefinition.createOptions = details;\n baseApplicationDefinition.userProperties.details = details;\n }\n if (Array.isArray(hostManifestDefinition.intents)) {\n baseApplicationDefinition.userProperties.intents = (baseApplicationDefinition.userProperties.intents || []).concat(hostManifestDefinition.intents);\n }\n baseApplicationDefinition = Object.assign(Object.assign({}, baseApplicationDefinition), hostManifestDefinition);\n delete baseApplicationDefinition.details;\n delete baseApplicationDefinition.intents;\n return baseApplicationDefinition;\n }\n mergeDesktopConfigWithGlueManifest(config, desktopDefinition) {\n const appConfig = Object.assign({}, config, desktopDefinition, { details: Object.assign(Object.assign({}, config.details), desktopDefinition.details) });\n if (Array.isArray(desktopDefinition.intents)) {\n appConfig.intents = (config.intents || []).concat(desktopDefinition.intents);\n }\n return appConfig;\n }\n}\n\nconst decoders$1 = {\n common: {\n nonEmptyStringDecoder,\n nonNegativeNumberDecoder\n },\n fdc3: {\n allDefinitionsDecoder,\n v1DefinitionDecoder,\n v2DefinitionDecoder\n }\n};\n\nclass IoC {\n constructor() {\n this._decoders = decoders$1;\n }\n get fdc3() {\n if (!this._fdc3) {\n this._fdc3 = new FDC3Service().toApi();\n }\n return this._fdc3;\n }\n get decoders() {\n return this._decoders;\n }\n}\n\nconst ioc = new IoC();\nconst fdc3 = ioc.fdc3;\nconst decoders = ioc.decoders;\n\nexport { decoders, fdc3 };\n//# sourceMappingURL=utils.es.js.map\n","import { IOConnectWorkspaces } from \"@interopio/workspaces-api\";\r\nimport { decoders } from \"@interopio/utils\";\r\nimport { Decoder, string, number, object, constant, oneOf, optional, array, boolean, anyJson, lazy } from \"decoder-validate\";\r\nimport { IOConnectBrowser } from \"../../browser\";\r\nimport { AppsImportOperation, AppHelloSuccess, ApplicationData, ApplicationStartConfig, AppManagerOperationTypes, AppRemoveConfig, BaseApplicationData, BasicInstanceData, InstanceData, AppsExportOperation, FDC3Definition, AppDirectoryStateChange } from \"../appManager/protocol\";\r\nimport { AllLayoutsFullConfig, AllLayoutsSummariesResult, GetAllLayoutsConfig, LayoutsImportConfig, LayoutsOperationTypes, OptionalSimpleLayoutResult, RestoreLayoutConfig, SaveLayoutConfig, SaveRequestClientResponse, PlatformSaveRequestConfig, SimpleLayoutConfig, SimpleLayoutResult, PermissionStateResult, SimpleAvailabilityResult, SetDefaultGlobalConfig } from \"../layouts/protocol\";\r\nimport { HelloSuccess, OpenWindowConfig, CoreWindowData, WindowHello, WindowOperationTypes, SimpleWindowCommand, WindowTitleConfig, WindowBoundsResult, WindowMoveResizeConfig, WindowUrlResult, FrameWindowBoundsResult, FocusEventData, WindowChannelResult } from \"../windows/protocol\";\r\nimport { IntentsOperationTypes, WrappedIntentFilter, WrappedIntents } from \"../intents/protocol\";\r\nimport { LibDomains, OperationCheckConfig, OperationCheckResult, SimpleItemIdRequest, WorkspaceFrameBoundsResult } from \"./types\";\r\nimport { AllNotificationsData, NotificationEventPayload, NotificationsOperationTypes, PermissionQueryResult, PermissionRequestResult, RaiseNotification, RaiseNotificationResult, SimpleNotificationData, SimpleNotificationSelect } from \"../notifications/protocol\";\r\nimport { AllThemesResponse, SelectThemeConfig, SimpleThemeResponse } from \"../themes/protocol\";\r\nimport { SystemOperationTypes } from \"../system/protocol\";\r\nimport { WindowIdsOnChannelData, ChannelOperationTypes, WrappedWindowWithChannelFilter, WindowIdsWithChannelsData, MyChannelData, JoinChannelData } from \"../channels/protocol\";\r\nimport { FilterHandlersReturnResult, FilterHandlersWithResolverConfig, IntentRequestWithResolverConfig, IntentResolverResponse, ResolverConfig } from \"../intents/types\";\r\n\r\nexport const nonEmptyStringDecoder: Decoder = string().where((s) => s.length > 0, \"Expected a non-empty string\");\r\nexport const nonNegativeNumberDecoder: Decoder = number().where((num) => num >= 0, \"Expected a non-negative number\");\r\nexport const optionalNonEmptyStringDecoder: Decoder = optional(nonEmptyStringDecoder);\r\n\r\nexport const libDomainDecoder: Decoder = oneOf<\"system\" | \"windows\" | \"appManager\" | \"layouts\" | \"intents\" | \"notifications\" | \"channels\" | \"extension\" | \"themes\">(\r\n constant(\"system\"),\r\n constant(\"windows\"),\r\n constant(\"appManager\"),\r\n constant(\"layouts\"),\r\n constant(\"intents\"),\r\n constant(\"notifications\"),\r\n constant(\"channels\"),\r\n constant(\"extension\"),\r\n constant(\"themes\")\r\n);\r\n\r\nexport const windowOperationTypesDecoder: Decoder = oneOf<\"openWindow\" | \"getBounds\" | \"getFrameBounds\" | \"windowHello\" | \"windowAdded\" | \"windowRemoved\" | \"getUrl\" | \"moveResize\" | \"focus\" | \"close\" | \"getTitle\" | \"setTitle\" | \"focusChange\" | \"getChannel\">(\r\n constant(\"openWindow\"),\r\n constant(\"windowHello\"),\r\n constant(\"windowAdded\"),\r\n constant(\"windowRemoved\"),\r\n constant(\"getBounds\"),\r\n constant(\"getFrameBounds\"),\r\n constant(\"getUrl\"),\r\n constant(\"moveResize\"),\r\n constant(\"focus\"),\r\n constant(\"close\"),\r\n constant(\"getTitle\"),\r\n constant(\"setTitle\"),\r\n constant(\"focusChange\"),\r\n constant(\"getChannel\"),\r\n);\r\n\r\nexport const appManagerOperationTypesDecoder: Decoder = oneOf<\"appHello\" | \"appDirectoryStateChange\" | \"instanceStarted\" | \"instanceStopped\" | \"applicationStart\" | \"instanceStop\" | \"clear\">(\r\n constant(\"appHello\"),\r\n constant(\"appDirectoryStateChange\"),\r\n constant(\"instanceStarted\"),\r\n constant(\"instanceStopped\"),\r\n constant(\"applicationStart\"),\r\n constant(\"instanceStop\"),\r\n constant(\"clear\")\r\n);\r\n\r\nexport const layoutsOperationTypesDecoder: Decoder = oneOf<\"layoutAdded\" | \"layoutChanged\" | \"layoutRemoved\" | \"get\" | \"getAll\" | \"export\" | \"import\" | \"remove\" | \"clientSaveRequest\" | \"getGlobalPermissionState\" | \"requestGlobalPermission\" | \"checkGlobalActivated\" | \"getDefaultGlobal\" | \"setDefaultGlobal\" | \"clearDefaultGlobal\">(\r\n constant(\"layoutAdded\"),\r\n constant(\"layoutChanged\"),\r\n constant(\"layoutRemoved\"),\r\n constant(\"get\"),\r\n constant(\"getAll\"),\r\n constant(\"export\"),\r\n constant(\"import\"),\r\n constant(\"remove\"),\r\n constant(\"clientSaveRequest\"),\r\n constant(\"getGlobalPermissionState\"),\r\n constant(\"checkGlobalActivated\"),\r\n constant(\"requestGlobalPermission\"),\r\n constant(\"getDefaultGlobal\"),\r\n constant(\"setDefaultGlobal\"),\r\n constant(\"clearDefaultGlobal\")\r\n);\r\n\r\nexport const notificationsOperationTypesDecoder: Decoder = oneOf<\"raiseNotification\" | \"requestPermission\" | \"notificationShow\" | \"notificationClick\" | \"getPermission\" | \"list\" | \"notificationRaised\" | \"notificationClosed\" | \"click\" | \"clear\" | \"clearAll\">(\r\n constant(\"raiseNotification\"),\r\n constant(\"requestPermission\"),\r\n constant(\"notificationShow\"),\r\n constant(\"notificationClick\"),\r\n constant(\"getPermission\"),\r\n constant(\"list\"),\r\n constant(\"notificationRaised\"),\r\n constant(\"notificationClosed\"),\r\n constant(\"click\"),\r\n constant(\"clear\"),\r\n constant(\"clearAll\")\r\n);\r\n\r\nexport const systemOperationTypesDecoder: Decoder = oneOf<\"getEnvironment\" | \"getBase\" | \"platformShutdown\">(\r\n constant(\"getEnvironment\"),\r\n constant(\"getBase\"),\r\n constant(\"platformShutdown\")\r\n);\r\n\r\nexport const windowRelativeDirectionDecoder: Decoder = oneOf<\"top\" | \"left\" | \"right\" | \"bottom\">(\r\n constant(\"top\"),\r\n constant(\"left\"),\r\n constant(\"right\"),\r\n constant(\"bottom\")\r\n);\r\n\r\nexport const windowBoundsDecoder: Decoder = object({\r\n top: number(),\r\n left: number(),\r\n width: nonNegativeNumberDecoder,\r\n height: nonNegativeNumberDecoder\r\n});\r\n\r\nexport const windowOpenSettingsDecoder: Decoder = optional(object({\r\n top: optional(number()),\r\n left: optional(number()),\r\n width: optional(nonNegativeNumberDecoder),\r\n height: optional(nonNegativeNumberDecoder),\r\n context: optional(anyJson()),\r\n relativeTo: optional(nonEmptyStringDecoder),\r\n relativeDirection: optional(windowRelativeDirectionDecoder),\r\n windowId: optional(nonEmptyStringDecoder),\r\n layoutComponentId: optional(nonEmptyStringDecoder)\r\n}));\r\n\r\nexport const openWindowConfigDecoder: Decoder = object({\r\n name: nonEmptyStringDecoder,\r\n url: nonEmptyStringDecoder,\r\n options: windowOpenSettingsDecoder\r\n});\r\n\r\nexport const windowHelloDecoder: Decoder = object({\r\n windowId: optional(nonEmptyStringDecoder)\r\n});\r\n\r\nexport const coreWindowDataDecoder: Decoder = object({\r\n windowId: nonEmptyStringDecoder,\r\n name: nonEmptyStringDecoder\r\n});\r\n\r\nexport const simpleWindowDecoder: Decoder = object({\r\n windowId: nonEmptyStringDecoder\r\n});\r\n\r\nexport const helloSuccessDecoder: Decoder = object({\r\n windows: array(coreWindowDataDecoder),\r\n isWorkspaceFrame: boolean()\r\n});\r\n\r\n\r\nexport const windowTitleConfigDecoder: Decoder = object({\r\n windowId: nonEmptyStringDecoder,\r\n title: string()\r\n});\r\n\r\nexport const focusEventDataDecoder: Decoder = object({\r\n windowId: nonEmptyStringDecoder,\r\n hasFocus: boolean()\r\n});\r\n\r\nexport const windowMoveResizeConfigDecoder: Decoder = object({\r\n windowId: nonEmptyStringDecoder,\r\n top: optional(number()),\r\n left: optional(number()),\r\n width: optional(nonNegativeNumberDecoder),\r\n height: optional(nonNegativeNumberDecoder),\r\n relative: optional(boolean())\r\n});\r\n\r\nexport const windowBoundsResultDecoder: Decoder = object({\r\n windowId: nonEmptyStringDecoder,\r\n bounds: object({\r\n top: number(),\r\n left: number(),\r\n width: nonNegativeNumberDecoder,\r\n height: nonNegativeNumberDecoder\r\n })\r\n});\r\n\r\nexport const frameWindowBoundsResultDecoder: Decoder = object({\r\n bounds: object({\r\n top: number(),\r\n left: number(),\r\n width: nonNegativeNumberDecoder,\r\n height: nonNegativeNumberDecoder\r\n })\r\n});\r\n\r\nexport const windowUrlResultDecoder: Decoder = object({\r\n windowId: nonEmptyStringDecoder,\r\n url: nonEmptyStringDecoder\r\n});\r\n\r\nexport const anyDecoder: Decoder = anyJson();\r\n\r\nexport const boundsDecoder: Decoder> = object({\r\n top: optional(number()),\r\n left: optional(number()),\r\n width: optional(nonNegativeNumberDecoder),\r\n height: optional(nonNegativeNumberDecoder)\r\n});\r\n\r\nexport const instanceDataDecoder: Decoder = object({\r\n id: nonEmptyStringDecoder,\r\n applicationName: nonEmptyStringDecoder\r\n});\r\n\r\nexport const applicationDetailsDecoder: Decoder = object({\r\n url: nonEmptyStringDecoder,\r\n top: optional(number()),\r\n left: optional(number()),\r\n width: optional(nonNegativeNumberDecoder),\r\n height: optional(nonNegativeNumberDecoder)\r\n});\r\n\r\nexport const intentDefinitionDecoder: Decoder = object({\r\n name: nonEmptyStringDecoder,\r\n displayName: optional(string()),\r\n contexts: optional(array(string())),\r\n customConfig: optional(object())\r\n});\r\n\r\nexport const fdc3AppDefinitionDecoder: Decoder = object({\r\n name: nonEmptyStringDecoder,\r\n title: optional(nonEmptyStringDecoder),\r\n version: optional(nonEmptyStringDecoder),\r\n appId: optional(nonEmptyStringDecoder),\r\n manifest: nonEmptyStringDecoder,\r\n manifestType: nonEmptyStringDecoder,\r\n tooltip: optional(nonEmptyStringDecoder),\r\n description: optional(nonEmptyStringDecoder),\r\n contactEmail: optional(nonEmptyStringDecoder),\r\n supportEmail: optional(nonEmptyStringDecoder),\r\n publisher: optional(nonEmptyStringDecoder),\r\n images: optional(array(object({ url: optional(nonEmptyStringDecoder) }))),\r\n icons: optional(array(object({ icon: optional(nonEmptyStringDecoder) }))),\r\n customConfig: anyJson(),\r\n intents: optional(array(intentDefinitionDecoder))\r\n});\r\n\r\nexport const applicationDefinitionDecoder: Decoder = object({\r\n name: nonEmptyStringDecoder,\r\n type: nonEmptyStringDecoder.where((s) => s === \"window\", \"Expected a value of window\"),\r\n title: optional(nonEmptyStringDecoder),\r\n version: optional(nonEmptyStringDecoder),\r\n customProperties: optional(anyJson()),\r\n icon: optional(string()),\r\n caption: optional(string()),\r\n details: applicationDetailsDecoder,\r\n intents: optional(array(intentDefinitionDecoder)),\r\n hidden: optional(boolean()),\r\n fdc3: optional(decoders.fdc3.v2DefinitionDecoder)\r\n});\r\n\r\nexport const allApplicationDefinitionsDecoder: Decoder = oneOf(\r\n applicationDefinitionDecoder,\r\n decoders.fdc3.v2DefinitionDecoder,\r\n decoders.fdc3.v1DefinitionDecoder\r\n);\r\n\r\nexport const appsImportOperationDecoder: Decoder = object({\r\n definitions: array(allApplicationDefinitionsDecoder),\r\n mode: oneOf<\"replace\" | \"merge\">(\r\n constant(\"replace\"),\r\n constant(\"merge\")\r\n )\r\n});\r\n\r\nexport const appRemoveConfigDecoder: Decoder = object({\r\n name: nonEmptyStringDecoder\r\n});\r\n\r\nexport const appsExportOperationDecoder: Decoder = object({\r\n definitions: array(applicationDefinitionDecoder)\r\n});\r\n\r\nexport const applicationDataDecoder: Decoder = object({\r\n name: nonEmptyStringDecoder,\r\n type: nonEmptyStringDecoder.where((s) => s === \"window\", \"Expected a value of window\"),\r\n instances: array(instanceDataDecoder),\r\n userProperties: optional(anyJson()),\r\n title: optional(nonEmptyStringDecoder),\r\n version: optional(nonEmptyStringDecoder),\r\n icon: optional(nonEmptyStringDecoder),\r\n caption: optional(nonEmptyStringDecoder)\r\n});\r\n\r\nexport const baseApplicationDataDecoder: Decoder = object({\r\n name: nonEmptyStringDecoder,\r\n type: nonEmptyStringDecoder.where((s) => s === \"window\", \"Expected a value of window\"),\r\n userProperties: anyJson(),\r\n title: optional(nonEmptyStringDecoder),\r\n version: optional(nonEmptyStringDecoder),\r\n icon: optional(nonEmptyStringDecoder),\r\n caption: optional(nonEmptyStringDecoder)\r\n});\r\n\r\nexport const appDirectoryStateChangeDecoder: Decoder = object({\r\n appsAdded: array(baseApplicationDataDecoder),\r\n appsChanged: array(baseApplicationDataDecoder),\r\n appsRemoved: array(baseApplicationDataDecoder)\r\n});\r\n\r\nexport const appHelloSuccessDecoder: Decoder = object({\r\n apps: array(applicationDataDecoder),\r\n initialChannelId: optional(nonEmptyStringDecoder)\r\n});\r\n\r\nexport const basicInstanceDataDecoder: Decoder = object({\r\n id: nonEmptyStringDecoder\r\n});\r\n\r\nexport const applicationStartConfigDecoder: Decoder = object({\r\n name: nonEmptyStringDecoder,\r\n waitForAGMReady: boolean(),\r\n id: optional(nonEmptyStringDecoder),\r\n context: optional(anyJson()),\r\n top: optional(number()),\r\n left: optional(number()),\r\n width: optional(nonNegativeNumberDecoder),\r\n height: optional(nonNegativeNumberDecoder),\r\n relativeTo: optional(nonEmptyStringDecoder),\r\n relativeDirection: optional(windowRelativeDirectionDecoder),\r\n forceChromeTab: optional(boolean()),\r\n layoutComponentId: optional(nonEmptyStringDecoder),\r\n channelId: optional(nonEmptyStringDecoder)\r\n});\r\n\r\nexport const layoutTypeDecoder: Decoder = oneOf<\"Global\" | \"Activity\" | \"ApplicationDefault\" | \"Swimlane\" | \"Workspace\">(\r\n constant(\"Global\"),\r\n constant(\"Activity\"),\r\n constant(\"ApplicationDefault\"),\r\n constant(\"Swimlane\"),\r\n constant(\"Workspace\")\r\n);\r\n\r\nexport const componentTypeDecoder: Decoder = oneOf<\"application\" | \"activity\">(\r\n constant(\"application\"),\r\n constant(\"activity\")\r\n);\r\n\r\nexport const windowComponentStateDecoder: Decoder = object({\r\n context: optional(anyJson()),\r\n bounds: windowBoundsDecoder,\r\n createArgs: object({\r\n name: optional(nonEmptyStringDecoder),\r\n url: optional(nonEmptyStringDecoder),\r\n context: optional(anyJson())\r\n }),\r\n windowState: optional(nonEmptyStringDecoder),\r\n restoreState: optional(nonEmptyStringDecoder),\r\n instanceId: nonEmptyStringDecoder,\r\n isCollapsed: optional(boolean()),\r\n isSticky: optional(boolean()),\r\n restoreSettings: object({\r\n groupId: optional(nonEmptyStringDecoder),\r\n groupZOrder: optional(number())\r\n })\r\n});\r\n\r\nexport const windowLayoutComponentDecoder: Decoder = object({\r\n type: constant(\"window\"),\r\n componentType: optional(componentTypeDecoder),\r\n application: nonEmptyStringDecoder,\r\n state: windowComponentStateDecoder\r\n});\r\n\r\nexport const windowLayoutItemDecoder: Decoder = object({\r\n type: constant(\"window\"),\r\n config: object({\r\n appName: nonEmptyStringDecoder,\r\n url: optional(nonEmptyStringDecoder),\r\n title: optional(string()),\r\n allowExtract: optional(boolean()),\r\n allowReorder: optional(boolean()),\r\n showCloseButton: optional(boolean()),\r\n isMaximized: optional(boolean())\r\n })\r\n});\r\n\r\nexport const groupLayoutItemDecoder: Decoder = object({\r\n type: constant(\"group\"),\r\n config: anyJson(),\r\n children: array(oneOf(\r\n windowLayoutItemDecoder\r\n ))\r\n});\r\n\r\nexport const columnLayoutItemDecoder: Decoder = object({\r\n type: constant(\"column\"),\r\n config: anyJson(),\r\n children: array(oneOf(\r\n groupLayoutItemDecoder,\r\n windowLayoutItemDecoder,\r\n lazy(() => columnLayoutItemDecoder),\r\n // eslint-disable-next-line @typescript-eslint/no-use-before-define\r\n lazy(() => rowLayoutItemDecoder)\r\n ))\r\n});\r\n\r\nexport const rowLayoutItemDecoder: Decoder = object({\r\n type: constant(\"row\"),\r\n config: anyJson(),\r\n children: array(oneOf(\r\n columnLayoutItemDecoder,\r\n groupLayoutItemDecoder,\r\n windowLayoutItemDecoder,\r\n lazy(() => rowLayoutItemDecoder)\r\n ))\r\n});\r\n\r\nexport const workspaceLayoutComponentStateDecoder: Decoder = object({\r\n config: anyJson(),\r\n context: anyJson(),\r\n children: array(oneOf(\r\n rowLayoutItemDecoder,\r\n columnLayoutItemDecoder,\r\n groupLayoutItemDecoder,\r\n windowLayoutItemDecoder\r\n ))\r\n});\r\n\r\nexport const workspaceLayoutComponentDecoder: Decoder = object({\r\n type: constant(\"Workspace\"),\r\n application: optional(nonEmptyStringDecoder),\r\n state: workspaceLayoutComponentStateDecoder\r\n});\r\n\r\nexport const workspaceFrameComponentStateDecoder: Decoder = object({\r\n bounds: windowBoundsDecoder,\r\n instanceId: nonEmptyStringDecoder,\r\n selectedWorkspace: nonNegativeNumberDecoder,\r\n workspaces: array(workspaceLayoutComponentStateDecoder),\r\n windowState: optional(nonEmptyStringDecoder),\r\n restoreState: optional(nonEmptyStringDecoder),\r\n context: optional(anyJson())\r\n});\r\n\r\nexport const workspaceFrameComponentDecoder: Decoder = object({\r\n type: constant<\"workspaceFrame\">(\"workspaceFrame\"),\r\n application: nonEmptyStringDecoder,\r\n componentType: optional(componentTypeDecoder),\r\n state: workspaceFrameComponentStateDecoder\r\n});\r\n\r\nexport const glueLayoutDecoder: Decoder = object({\r\n name: nonEmptyStringDecoder,\r\n type: layoutTypeDecoder,\r\n components: array(oneOf(\r\n windowLayoutComponentDecoder,\r\n workspaceLayoutComponentDecoder,\r\n workspaceFrameComponentDecoder\r\n )),\r\n context: optional(anyJson()),\r\n metadata: optional(anyJson()),\r\n version: optional(number())\r\n});\r\n\r\nexport const newLayoutOptionsDecoder: Decoder = object({\r\n name: nonEmptyStringDecoder,\r\n context: optional(anyJson()),\r\n metadata: optional(anyJson()),\r\n instances: optional(array(nonEmptyStringDecoder)),\r\n ignoreInstances: optional(array(nonEmptyStringDecoder))\r\n});\r\n\r\nexport const restoreOptionsDecoder: Decoder = object({\r\n name: nonEmptyStringDecoder,\r\n context: optional(anyJson()),\r\n closeRunningInstance: optional(boolean()),\r\n closeMe: optional(boolean()),\r\n timeout: optional(nonNegativeNumberDecoder)\r\n});\r\n\r\nexport const layoutSummaryDecoder: Decoder = object({\r\n name: nonEmptyStringDecoder,\r\n type: layoutTypeDecoder,\r\n context: optional(anyJson()),\r\n metadata: optional(anyJson())\r\n});\r\n\r\nexport const simpleLayoutConfigDecoder: Decoder = object({\r\n name: nonEmptyStringDecoder,\r\n type: layoutTypeDecoder\r\n});\r\n\r\nexport const saveLayoutConfigDecoder: Decoder = object({\r\n layout: newLayoutOptionsDecoder\r\n});\r\n\r\nexport const restoreLayoutConfigDecoder: Decoder = object({\r\n layout: restoreOptionsDecoder\r\n});\r\n\r\nexport const getAllLayoutsConfigDecoder: Decoder = object({\r\n type: layoutTypeDecoder\r\n});\r\n\r\nexport const allLayoutsFullConfigDecoder: Decoder = object({\r\n layouts: array(glueLayoutDecoder)\r\n});\r\n\r\nexport const importModeDecoder: Decoder<\"replace\" | \"merge\"> = oneOf<\"replace\" | \"merge\">(\r\n constant(\"replace\"),\r\n constant(\"merge\")\r\n);\r\n\r\nexport const layoutsImportConfigDecoder: Decoder = object({\r\n layouts: array(glueLayoutDecoder),\r\n mode: importModeDecoder,\r\n isManagerOperation: optional(boolean())\r\n});\r\n\r\nexport const allLayoutsSummariesResultDecoder: Decoder = object({\r\n summaries: array(layoutSummaryDecoder)\r\n});\r\n\r\nexport const simpleLayoutResultDecoder: Decoder = object({\r\n layout: glueLayoutDecoder\r\n});\r\n\r\nexport const optionalSimpleLayoutResult: Decoder = object({\r\n layout: optional(glueLayoutDecoder)\r\n});\r\n\r\nexport const setDefaultGlobalConfigDecoder: Decoder = object({\r\n name: nonEmptyStringDecoder\r\n});\r\n\r\nexport const intentsOperationTypesDecoder: Decoder = oneOf<\"findIntent\" | \"getIntents\" | \"raiseIntent\" | \"raise\" | \"filterHandlers\">(\r\n constant(\"findIntent\"),\r\n constant(\"getIntents\"),\r\n constant(\"raiseIntent\"),\r\n constant(\"raise\"),\r\n constant(\"filterHandlers\")\r\n);\r\n\r\nconst intentHandlerDecoder: Decoder = object({\r\n applicationName: nonEmptyStringDecoder,\r\n applicationTitle: optional(string()),\r\n applicationDescription: optional(string()),\r\n applicationIcon: optional(string()),\r\n type: oneOf<\"app\" | \"instance\">(constant(\"app\"), constant(\"instance\")),\r\n displayName: optional(string()),\r\n contextTypes: optional(array(nonEmptyStringDecoder)),\r\n instanceId: optional(string()),\r\n instanceTitle: optional(string()),\r\n resultType: optional(string())\r\n});\r\n\r\nexport const resolverIntentHandlerDecoder = object({\r\n applicationName: string(),\r\n applicationIcon: optional(string()),\r\n instanceId: optional(string()),\r\n});\r\n\r\nexport const intentResolverResponseDecoder: Decoder = object({\r\n intent: nonEmptyStringDecoder,\r\n handler: intentHandlerDecoder\r\n});\r\n\r\nconst intentDecoder: Decoder = object({\r\n name: nonEmptyStringDecoder,\r\n handlers: array(intentHandlerDecoder)\r\n});\r\n\r\nconst intentTargetDecoder: Decoder<\"startNew\" | \"reuse\" | { app?: string; instance?: string }> = oneOf<\"startNew\" | \"reuse\" | { app?: string; instance?: string }>(\r\n constant(\"startNew\"),\r\n constant(\"reuse\"),\r\n object({\r\n app: optional(nonEmptyStringDecoder),\r\n instance: optional(nonEmptyStringDecoder)\r\n })\r\n);\r\n\r\nconst intentContextDecoder: Decoder = object({\r\n type: optional(nonEmptyStringDecoder),\r\n data: optional(anyJson())\r\n});\r\n\r\nexport const intentsDecoder: Decoder = array(intentDecoder);\r\n\r\nexport const wrappedIntentsDecoder: Decoder = object({\r\n intents: intentsDecoder\r\n});\r\n\r\nexport const intentFilterDecoder: Decoder = object({\r\n name: optional(nonEmptyStringDecoder),\r\n contextType: optional(nonEmptyStringDecoder),\r\n resultType: optional(nonEmptyStringDecoder)\r\n});\r\n\r\nexport const findFilterDecoder: Decoder = oneOf(\r\n nonEmptyStringDecoder,\r\n intentFilterDecoder\r\n);\r\n\r\nexport const wrappedIntentFilterDecoder: Decoder = object({\r\n filter: optional(intentFilterDecoder)\r\n});\r\n\r\nexport const intentRequestDecoder: Decoder = object({\r\n intent: nonEmptyStringDecoder,\r\n target: optional(intentTargetDecoder),\r\n context: optional(intentContextDecoder),\r\n options: optional(windowOpenSettingsDecoder),\r\n handlers: optional(array(intentHandlerDecoder)),\r\n timeout: optional(nonNegativeNumberDecoder),\r\n waitUserResponseIndefinitely: optional(boolean())\r\n});\r\n\r\nexport const raiseRequestDecoder: Decoder = oneOf(\r\n nonEmptyStringDecoder,\r\n intentRequestDecoder\r\n);\r\n\r\nexport const resolverConfigDecoder: Decoder = object({\r\n enabled: boolean(),\r\n appName: nonEmptyStringDecoder,\r\n waitResponseTimeout: number()\r\n});\r\n\r\nexport const raiseIntentRequestDecoder: Decoder = object({\r\n intentRequest: intentRequestDecoder,\r\n resolverConfig: resolverConfigDecoder\r\n});\r\n\r\nexport const intentResultDecoder: Decoder = object({\r\n request: intentRequestDecoder,\r\n handler: intentHandlerDecoder,\r\n result: anyJson()\r\n});\r\n\r\nexport const handlersFilterDecoder: Decoder = object({\r\n title: optional(nonEmptyStringDecoder),\r\n openResolver: optional(boolean()),\r\n timeout: optional(number()),\r\n intent: optional(nonEmptyStringDecoder),\r\n contextTypes: optional(array(nonEmptyStringDecoder)),\r\n resultType: optional(nonEmptyStringDecoder),\r\n});\r\n\r\nexport const filterHandlersResultDecoder: Decoder = object({\r\n handlers: array(intentHandlerDecoder)\r\n});\r\n\r\nexport const filterHandlersWithResolverConfigDecoder: Decoder = object({\r\n filterHandlersRequest: handlersFilterDecoder,\r\n resolverConfig: resolverConfigDecoder\r\n});\r\n\r\nexport const AddIntentListenerRequestDecoder: Decoder = object({\r\n intent: nonEmptyStringDecoder,\r\n contextTypes: optional(array(nonEmptyStringDecoder)),\r\n displayName: optional(string()),\r\n icon: optional(string()),\r\n description: optional(string()),\r\n resultType: optional(string())\r\n});\r\n\r\nexport const AddIntentListenerDecoder: Decoder = oneOf(\r\n nonEmptyStringDecoder,\r\n AddIntentListenerRequestDecoder\r\n);\r\n\r\nexport const channelNameDecoder = (channelNames: string[]): Decoder => {\r\n return nonEmptyStringDecoder.where(s => channelNames.includes(s), \"Expected a valid channel name\");\r\n};\r\n\r\nexport const interopActionSettingsDecoder: Decoder = object({\r\n method: nonEmptyStringDecoder,\r\n arguments: optional(anyJson()),\r\n target: optional(oneOf<\"all\" | \"best\">(\r\n constant(\"all\"),\r\n constant(\"best\")\r\n ))\r\n});\r\n\r\nexport const glue42NotificationActionDecoder: Decoder = object({\r\n action: string(),\r\n title: nonEmptyStringDecoder,\r\n icon: optional(string()),\r\n interop: optional(interopActionSettingsDecoder)\r\n});\r\n\r\nexport const notificationDefinitionDecoder: Decoder = object({\r\n badge: optional(string()),\r\n body: optional(string()),\r\n data: optional(anyJson()),\r\n dir: optional(oneOf<\"auto\" | \"ltr\" | \"rtl\">(\r\n constant(\"auto\"),\r\n constant(\"ltr\"),\r\n constant(\"rtl\")\r\n )),\r\n icon: optional(string()),\r\n image: optional(string()),\r\n lang: optional(string()),\r\n renotify: optional(boolean()),\r\n requireInteraction: optional(boolean()),\r\n silent: optional(boolean()),\r\n tag: optional(string()),\r\n timestamp: optional(nonNegativeNumberDecoder),\r\n vibrate: optional(array(number()))\r\n});\r\n\r\nexport const glue42NotificationOptionsDecoder: Decoder = object({\r\n title: nonEmptyStringDecoder,\r\n clickInterop: optional(interopActionSettingsDecoder),\r\n actions: optional(array(glue42NotificationActionDecoder)),\r\n focusPlatformOnDefaultClick: optional(boolean()),\r\n badge: optional(string()),\r\n body: optional(string()),\r\n data: optional(anyJson()),\r\n dir: optional(oneOf<\"auto\" | \"ltr\" | \"rtl\">(\r\n constant(\"auto\"),\r\n constant(\"ltr\"),\r\n constant(\"rtl\")\r\n )),\r\n icon: optional(string()),\r\n image: optional(string()),\r\n lang: optional(string()),\r\n renotify: optional(boolean()),\r\n requireInteraction: optional(boolean()),\r\n silent: optional(boolean()),\r\n tag: optional(string()),\r\n timestamp: optional(nonNegativeNumberDecoder),\r\n vibrate: optional(array(number())),\r\n severity: optional(oneOf<\"Low\" | \"Medium\" | \"High\" | \"Critical\" | \"None\">(\r\n constant(\"Low\"),\r\n constant(\"None\"),\r\n constant(\"Medium\"),\r\n constant(\"High\"),\r\n constant(\"Critical\")\r\n )),\r\n showToast: optional(boolean()),\r\n showInPanel: optional(boolean())\r\n});\r\n\r\nexport const channelContextDecoder: Decoder = object({\r\n name: nonEmptyStringDecoder,\r\n meta: object({\r\n color: nonEmptyStringDecoder\r\n }),\r\n data: optional(object()),\r\n});\r\n\r\n\r\nexport const raiseNotificationDecoder: Decoder = object({\r\n settings: glue42NotificationOptionsDecoder,\r\n id: nonEmptyStringDecoder\r\n});\r\n\r\nexport const raiseNotificationResultDecoder: Decoder = object({\r\n settings: glue42NotificationOptionsDecoder\r\n});\r\n\r\nexport const permissionRequestResultDecoder: Decoder = object({\r\n permissionGranted: boolean()\r\n});\r\n\r\nexport const permissionQueryResultDecoder: Decoder = object({\r\n permission: oneOf<\"default\" | \"granted\" | \"denied\">(\r\n constant(\"default\"),\r\n constant(\"granted\"),\r\n constant(\"denied\")\r\n )\r\n});\r\n\r\nexport const notificationEventPayloadDecoder: Decoder = object({\r\n definition: notificationDefinitionDecoder,\r\n action: optional(string()),\r\n id: optional(nonEmptyStringDecoder)\r\n});\r\n\r\nexport const platformSaveRequestConfigDecoder: Decoder = object({\r\n layoutType: oneOf<\"Global\" | \"Workspace\">(\r\n constant(\"Global\"),\r\n constant(\"Workspace\")\r\n ),\r\n layoutName: nonEmptyStringDecoder,\r\n context: optional(anyJson())\r\n});\r\n\r\nexport const saveRequestClientResponseDecoder: Decoder = object({\r\n windowContext: optional(anyJson()),\r\n});\r\n\r\nexport const permissionStateResultDecoder: Decoder = object({\r\n state: oneOf<\"prompt\" | \"granted\" | \"denied\">(\r\n constant(\"prompt\"),\r\n constant(\"denied\"),\r\n constant(\"granted\")\r\n )\r\n});\r\n\r\nexport const simpleAvailabilityResultDecoder: Decoder = object({\r\n isAvailable: boolean()\r\n});\r\n\r\nexport const simpleItemIdDecoder: Decoder = object({\r\n itemId: nonEmptyStringDecoder\r\n});\r\n\r\nexport const operationCheckResultDecoder: Decoder = object({\r\n isSupported: boolean()\r\n});\r\n\r\nexport const operationCheckConfigDecoder: Decoder = object({\r\n operation: nonEmptyStringDecoder\r\n});\r\n\r\nexport const workspaceFrameBoundsResultDecoder: Decoder = object({\r\n bounds: windowBoundsDecoder\r\n});\r\n\r\nexport const themeDecoder: Decoder = object({\r\n displayName: nonEmptyStringDecoder,\r\n name: nonEmptyStringDecoder\r\n});\r\n\r\nexport const simpleThemeResponseDecoder: Decoder = object({\r\n theme: themeDecoder\r\n});\r\n\r\nexport const allThemesResponseDecoder: Decoder = object({\r\n themes: array(themeDecoder)\r\n});\r\n\r\nexport const selectThemeConfigDecoder: Decoder = object({\r\n name: nonEmptyStringDecoder\r\n});\r\n\r\nexport const notificationsDataDecoder: Decoder = object({\r\n id: nonEmptyStringDecoder,\r\n title: nonEmptyStringDecoder,\r\n clickInterop: optional(interopActionSettingsDecoder),\r\n actions: optional(array(glue42NotificationActionDecoder)),\r\n focusPlatformOnDefaultClick: optional(boolean()),\r\n badge: optional(string()),\r\n body: optional(string()),\r\n data: optional(anyJson()),\r\n dir: optional(oneOf<\"auto\" | \"ltr\" | \"rtl\">(\r\n constant(\"auto\"),\r\n constant(\"ltr\"),\r\n constant(\"rtl\")\r\n )),\r\n icon: optional(string()),\r\n image: optional(string()),\r\n lang: optional(string()),\r\n renotify: optional(boolean()),\r\n requireInteraction: optional(boolean()),\r\n silent: optional(boolean()),\r\n tag: optional(string()),\r\n timestamp: optional(nonNegativeNumberDecoder),\r\n vibrate: optional(array(number())),\r\n severity: optional(oneOf<\"Low\" | \"Medium\" | \"High\" | \"Critical\" | \"None\">(\r\n constant(\"Low\"),\r\n constant(\"None\"),\r\n constant(\"Medium\"),\r\n constant(\"High\"),\r\n constant(\"Critical\")\r\n )),\r\n showToast: optional(boolean()),\r\n showInPanel: optional(boolean())\r\n});\r\n\r\nexport const simpleNotificationDataDecoder: Decoder = object({\r\n notification: notificationsDataDecoder\r\n});\r\n\r\nexport const allNotificationsDataDecoder: Decoder = object({\r\n notifications: array(notificationsDataDecoder)\r\n});\r\n\r\nexport const simpleNotificationSelectDecoder: Decoder = object({\r\n id: nonEmptyStringDecoder\r\n});\r\n\r\nexport const getWindowIdsOnChannelDataDecoder: Decoder<{ channel: string }> = object({\r\n channel: nonEmptyStringDecoder\r\n});\r\n\r\nexport const getWindowIdsOnChannelResultDecoder: Decoder = object({\r\n windowIds: array(nonEmptyStringDecoder)\r\n});\r\n\r\nexport const channelsOperationTypesDecoder: Decoder = oneOf<\"addChannel\" | \"getMyChannel\" | \"getWindowIdsOnChannel\" | \"getWindowIdsWithChannels\" | \"joinChannel\">(\r\n constant(\"addChannel\"),\r\n constant(\"getMyChannel\"),\r\n constant(\"getWindowIdsOnChannel\"),\r\n constant(\"getWindowIdsWithChannels\"),\r\n constant(\"joinChannel\"),\r\n);\r\n\r\nexport const getMyChanelResultDecoder: Decoder = object({\r\n channel: optional(nonEmptyStringDecoder)\r\n});\r\n\r\nexport const windowWithChannelFilterDecoder: Decoder = object({\r\n application: optional(nonEmptyStringDecoder),\r\n channels: optional(array(nonEmptyStringDecoder)),\r\n windowIds: optional(array(nonEmptyStringDecoder))\r\n});\r\n\r\nexport const wrappedWindowWithChannelFilterDecoder: Decoder = object({\r\n filter: optional(windowWithChannelFilterDecoder)\r\n});\r\n\r\nexport const getWindowIdsWithChannelsResultDecoder: Decoder = object({\r\n windowIdsWithChannels: array(object({\r\n application: nonEmptyStringDecoder,\r\n channel: optional(nonEmptyStringDecoder),\r\n windowId: nonEmptyStringDecoder\r\n }))\r\n});\r\nexport const startApplicationContextDecoder = optional(anyJson());\r\n\r\nexport const startApplicationOptionsDecoder: Decoder = optional(object({\r\n top: optional(number()),\r\n left: optional(number()),\r\n width: optional(nonNegativeNumberDecoder),\r\n height: optional(nonNegativeNumberDecoder),\r\n relativeTo: optional(nonEmptyStringDecoder),\r\n relativeDirection: optional(windowRelativeDirectionDecoder),\r\n waitForAGMReady: optional(boolean()),\r\n channelId: optional(nonEmptyStringDecoder),\r\n reuseId: optional(nonEmptyStringDecoder),\r\n}));\r\n\r\nexport const joinChannelDataDecoder: Decoder = object({\r\n channel: nonEmptyStringDecoder,\r\n windowId: nonEmptyStringDecoder\r\n});\r\n\r\nexport const windowChannelResultDecoder: Decoder = object({\r\n channel: optional(nonEmptyStringDecoder),\r\n});\r\n","import { IOConnectBrowser } from \"../../browser\";\r\nimport { openWindowConfigDecoder, coreWindowDataDecoder, windowHelloDecoder, helloSuccessDecoder, simpleWindowDecoder, windowBoundsResultDecoder, windowUrlResultDecoder, windowMoveResizeConfigDecoder, windowTitleConfigDecoder, frameWindowBoundsResultDecoder, focusEventDataDecoder, windowChannelResultDecoder } from \"../shared/decoders\";\r\nimport { BridgeOperation } from \"../shared/types\";\r\nimport { WebWindowModel } from \"./webWindow\";\r\n\r\nexport type WindowOperationTypes = \"openWindow\" | \"getBounds\" | \"getFrameBounds\" |\r\n \"windowHello\" | \"windowAdded\" | \"windowRemoved\" | \"getUrl\" |\r\n \"moveResize\" | \"focus\" | \"close\" | \"getTitle\" | \"setTitle\" | \"focusChange\" |\r\n \"getChannel\";\r\n\r\nexport const operations: { [key in WindowOperationTypes]: BridgeOperation } = {\r\n openWindow: { name: \"openWindow\", dataDecoder: openWindowConfigDecoder, resultDecoder: coreWindowDataDecoder },\r\n windowHello: { name: \"windowHello\", dataDecoder: windowHelloDecoder, resultDecoder: helloSuccessDecoder },\r\n windowAdded: { name: \"windowAdded\", dataDecoder: coreWindowDataDecoder },\r\n windowRemoved: { name: \"windowRemoved\", dataDecoder: simpleWindowDecoder },\r\n getBounds: { name: \"getBounds\", dataDecoder: simpleWindowDecoder, resultDecoder: windowBoundsResultDecoder },\r\n getFrameBounds: { name: \"getFrameBounds\", dataDecoder: simpleWindowDecoder, resultDecoder: frameWindowBoundsResultDecoder },\r\n getUrl: { name: \"getUrl\", dataDecoder: simpleWindowDecoder, resultDecoder: windowUrlResultDecoder },\r\n moveResize: { name: \"moveResize\", dataDecoder: windowMoveResizeConfigDecoder },\r\n focus: { name: \"focus\", dataDecoder: simpleWindowDecoder },\r\n close: { name: \"close\", dataDecoder: simpleWindowDecoder },\r\n getTitle: { name: \"getTitle\", dataDecoder: simpleWindowDecoder, resultDecoder: windowTitleConfigDecoder },\r\n setTitle: { name: \"setTitle\", dataDecoder: windowTitleConfigDecoder },\r\n focusChange: { name: \"focusChange\", dataDecoder: focusEventDataDecoder },\r\n getChannel: { name: \"getChannel\", dataDecoder: simpleWindowDecoder, resultDecoder: windowChannelResultDecoder },\r\n};\r\n\r\nexport interface WindowProjection {\r\n id: string;\r\n model: WebWindowModel;\r\n api: IOConnectBrowser.Windows.WebWindow;\r\n}\r\n\r\nexport interface WindowHello {\r\n windowId?: string;\r\n}\r\n\r\nexport interface OpenWindowConfig {\r\n name: string;\r\n url: string;\r\n options?: IOConnectBrowser.Windows.Settings;\r\n}\r\n\r\nexport interface FocusEventData {\r\n windowId: string;\r\n hasFocus: boolean;\r\n}\r\n\r\nexport interface SimpleWindowCommand {\r\n windowId: string;\r\n}\r\n\r\nexport interface WindowTitleConfig {\r\n windowId: string;\r\n title: string;\r\n}\r\n\r\nexport interface WindowMoveResizeConfig {\r\n windowId: string;\r\n top?: number;\r\n left?: number;\r\n width?: number;\r\n height?: number;\r\n relative?: boolean;\r\n}\r\n\r\nexport interface HelloSuccess {\r\n windows: CoreWindowData[];\r\n isWorkspaceFrame: boolean;\r\n}\r\n\r\nexport interface CoreWindowData {\r\n windowId: string;\r\n name: string;\r\n}\r\n\r\nexport interface WindowBoundsResult {\r\n windowId: string;\r\n bounds: IOConnectBrowser.Windows.Bounds;\r\n}\r\n\r\nexport interface FrameWindowBoundsResult {\r\n bounds: IOConnectBrowser.Windows.Bounds;\r\n}\r\n\r\nexport interface WindowUrlResult {\r\n windowId: string;\r\n url: string;\r\n}\r\n\r\nexport interface WindowChannelResult {\r\n channel?: string;\r\n}\r\n","\"use strict\";\nfunction createRegistry(options) {\n if (options && options.errorHandling\n && typeof options.errorHandling !== \"function\"\n && options.errorHandling !== \"log\"\n && options.errorHandling !== \"silent\"\n && options.errorHandling !== \"throw\") {\n throw new Error(\"Invalid options passed to createRegistry. Prop errorHandling should be [\\\"log\\\" | \\\"silent\\\" | \\\"throw\\\" | (err) => void], but \" + typeof options.errorHandling + \" was passed\");\n }\n var _userErrorHandler = options && typeof options.errorHandling === \"function\" && options.errorHandling;\n var callbacks = {};\n function add(key, callback, replayArgumentsArr) {\n var callbacksForKey = callbacks[key];\n if (!callbacksForKey) {\n callbacksForKey = [];\n callbacks[key] = callbacksForKey;\n }\n callbacksForKey.push(callback);\n if (replayArgumentsArr) {\n setTimeout(function () {\n replayArgumentsArr.forEach(function (replayArgument) {\n var _a;\n if ((_a = callbacks[key]) === null || _a === void 0 ? void 0 : _a.includes(callback)) {\n try {\n if (Array.isArray(replayArgument)) {\n callback.apply(undefined, replayArgument);\n }\n else {\n callback.apply(undefined, [replayArgument]);\n }\n }\n catch (err) {\n _handleError(err, key);\n }\n }\n });\n }, 0);\n }\n return function () {\n var allForKey = callbacks[key];\n if (!allForKey) {\n return;\n }\n allForKey = allForKey.reduce(function (acc, element, index) {\n if (!(element === callback && acc.length === index)) {\n acc.push(element);\n }\n return acc;\n }, []);\n if (allForKey.length === 0) {\n delete callbacks[key];\n }\n else {\n callbacks[key] = allForKey;\n }\n };\n }\n function execute(key) {\n var argumentsArr = [];\n for (var _i = 1; _i < arguments.length; _i++) {\n argumentsArr[_i - 1] = arguments[_i];\n }\n var callbacksForKey = callbacks[key];\n if (!callbacksForKey || callbacksForKey.length === 0) {\n return [];\n }\n var results = [];\n callbacksForKey.forEach(function (callback) {\n try {\n var result = callback.apply(undefined, argumentsArr);\n results.push(result);\n }\n catch (err) {\n results.push(undefined);\n _handleError(err, key);\n }\n });\n return results;\n }\n function _handleError(exceptionArtifact, key) {\n var errParam = exceptionArtifact instanceof Error ? exceptionArtifact : new Error(exceptionArtifact);\n if (_userErrorHandler) {\n _userErrorHandler(errParam);\n return;\n }\n var msg = \"[ERROR] callback-registry: User callback for key \\\"\" + key + \"\\\" failed: \" + errParam.stack;\n if (options) {\n switch (options.errorHandling) {\n case \"log\":\n return console.error(msg);\n case \"silent\":\n return;\n case \"throw\":\n throw new Error(msg);\n }\n }\n console.error(msg);\n }\n function clear() {\n callbacks = {};\n }\n function clearKey(key) {\n var callbacksForKey = callbacks[key];\n if (!callbacksForKey) {\n return;\n }\n delete callbacks[key];\n }\n return {\n add: add,\n execute: execute,\n clear: clear,\n clearKey: clearKey\n };\n}\n;\ncreateRegistry.default = createRegistry;\nmodule.exports = createRegistry;\n//# sourceMappingURL=index.js.map","/* eslint-disable @typescript-eslint/no-explicit-any */\r\nimport { number } from \"decoder-validate\";\r\nimport { IOConnectBrowser } from \"../../browser\";\r\nimport { GlueBridge } from \"../communication/bridge\";\r\nimport { anyDecoder, boundsDecoder, nonEmptyStringDecoder, nonNegativeNumberDecoder } from \"../shared/decoders\";\r\nimport { operations, SimpleWindowCommand, WindowBoundsResult, WindowChannelResult, WindowMoveResizeConfig, WindowTitleConfig, WindowUrlResult } from \"./protocol\";\r\nimport {\r\n default as CallbackRegistryFactory,\r\n CallbackRegistry,\r\n UnsubscribeFunction,\r\n} from \"callback-registry\";\r\n\r\nexport class WebWindowModel {\r\n private readonly registry: CallbackRegistry = CallbackRegistryFactory();\r\n private readonly myCtxKey: string;\r\n private ctxUnsubscribe: UnsubscribeFunction | undefined;\r\n private me!: IOConnectBrowser.Windows.WebWindow;\r\n\r\n constructor(private readonly _id: string, private readonly _name: string, private readonly _bridge: GlueBridge) {\r\n this.myCtxKey = `___window___${this.id}`;\r\n }\r\n\r\n public get id(): string {\r\n return this._id.slice();\r\n }\r\n\r\n public get name(): string {\r\n return this._name.slice();\r\n }\r\n\r\n public clean(): void {\r\n if (this.ctxUnsubscribe) {\r\n this.ctxUnsubscribe();\r\n }\r\n }\r\n\r\n public processSelfFocusEvent(hasFocus: boolean): void {\r\n this.me.isFocused = hasFocus;\r\n\r\n this.registry.execute(\"focus-change\", this.me);\r\n }\r\n\r\n public async toApi(): Promise {\r\n\r\n this.ctxUnsubscribe = await this._bridge.contextLib.subscribe(this.myCtxKey, (data) => this.registry.execute(\"context-updated\", data));\r\n\r\n this.me = {\r\n id: this.id,\r\n name: this.name,\r\n isFocused: false,\r\n getURL: this.getURL.bind(this),\r\n moveResize: this.moveResize.bind(this),\r\n resizeTo: this.resizeTo.bind(this),\r\n moveTo: this.moveTo.bind(this),\r\n focus: this.focus.bind(this),\r\n close: this.close.bind(this),\r\n getTitle: this.getTitle.bind(this),\r\n setTitle: this.setTitle.bind(this),\r\n getBounds: this.getBounds.bind(this),\r\n getContext: this.getContext.bind(this),\r\n updateContext: this.updateContext.bind(this),\r\n setContext: this.setContext.bind(this),\r\n onContextUpdated: this.onContextUpdated.bind(this),\r\n onFocusChanged: this.onFocusChanged.bind(this),\r\n getChannel: this.getChannel.bind(this),\r\n };\r\n\r\n return this.me;\r\n }\r\n\r\n private async getURL(): Promise {\r\n const result = await this._bridge.send(\"windows\", operations.getUrl, { windowId: this.id });\r\n return result.url;\r\n }\r\n\r\n private onFocusChanged(callback: (window: IOConnectBrowser.Windows.WebWindow) => void): UnsubscribeFunction {\r\n if (typeof callback !== \"function\") {\r\n throw new Error(\"Cannot subscribe to context changes, because the provided callback is not a function!\");\r\n }\r\n\r\n return this.registry.add(\"focus-change\", callback);\r\n }\r\n\r\n private async moveResize(dimension: Partial): Promise {\r\n const targetBounds = boundsDecoder.runWithException(dimension);\r\n\r\n const commandArgs = Object.assign({}, targetBounds, { windowId: this.id, relative: false });\r\n\r\n await this._bridge.send(\"windows\", operations.moveResize, commandArgs);\r\n\r\n return this.me;\r\n }\r\n\r\n private async resizeTo(width?: number, height?: number): Promise {\r\n if (typeof width === \"undefined\" && typeof height === \"undefined\") {\r\n return this.me;\r\n }\r\n\r\n if (typeof width !== \"undefined\") {\r\n nonNegativeNumberDecoder.runWithException(width);\r\n }\r\n\r\n if (typeof height !== \"undefined\") {\r\n nonNegativeNumberDecoder.runWithException(height);\r\n }\r\n\r\n const commandArgs = Object.assign({}, { width, height }, { windowId: this.id, relative: true });\r\n\r\n await this._bridge.send(\"windows\", operations.moveResize, commandArgs);\r\n\r\n return this.me;\r\n }\r\n\r\n private async moveTo(top?: number, left?: number): Promise {\r\n if (typeof top === \"undefined\" && typeof left === \"undefined\") {\r\n return this.me;\r\n }\r\n\r\n if (typeof top !== \"undefined\") {\r\n number().runWithException(top);\r\n }\r\n\r\n if (typeof left !== \"undefined\") {\r\n number().runWithException(left);\r\n }\r\n\r\n const commandArgs = Object.assign({}, { top, left }, { windowId: this.id, relative: true });\r\n\r\n await this._bridge.send(\"windows\", operations.moveResize, commandArgs);\r\n\r\n return this.me;\r\n }\r\n\r\n private async focus(): Promise {\r\n if (this.name === \"Platform\") {\r\n window.open(undefined, this.id);\r\n } else {\r\n await this._bridge.send(\"windows\", operations.focus, { windowId: this.id });\r\n }\r\n\r\n return this.me;\r\n }\r\n\r\n private async close(): Promise {\r\n await this._bridge.send(\"windows\", operations.close, { windowId: this.id });\r\n\r\n return this.me;\r\n }\r\n\r\n private async getTitle(): Promise {\r\n const result = await this._bridge.send(\"windows\", operations.getTitle, { windowId: this.id });\r\n\r\n return result.title;\r\n }\r\n\r\n private async setTitle(title: string): Promise {\r\n const ttl = nonEmptyStringDecoder.runWithException(title);\r\n\r\n await this._bridge.send(\"windows\", operations.setTitle, { windowId: this.id, title: ttl });\r\n\r\n return this.me;\r\n }\r\n\r\n private async getBounds(): Promise {\r\n const result = await this._bridge.send(\"windows\", operations.getBounds, { windowId: this.id });\r\n\r\n return result.bounds;\r\n }\r\n\r\n private async getContext(): Promise {\r\n const ctx = await this._bridge.contextLib.get(this.myCtxKey);\r\n return ctx;\r\n }\r\n\r\n private async updateContext(context: any): Promise {\r\n const ctx = anyDecoder.runWithException(context);\r\n\r\n await this._bridge.contextLib.update(this.myCtxKey, ctx);\r\n\r\n return this.me;\r\n }\r\n\r\n private async setContext(context: any): Promise {\r\n const ctx = anyDecoder.runWithException(context);\r\n\r\n await this._bridge.contextLib.set(this.myCtxKey, ctx);\r\n\r\n return this.me;\r\n }\r\n\r\n private onContextUpdated(callback: (context: any, window: IOConnectBrowser.Windows.WebWindow) => void): UnsubscribeFunction {\r\n if (typeof callback !== \"function\") {\r\n throw new Error(\"Cannot subscribe to context changes, because the provided callback is not a function!\");\r\n }\r\n\r\n const wrappedCallback = (data: any): void => {\r\n callback(data, this.me);\r\n };\r\n\r\n return this.registry.add(\"context-updated\", wrappedCallback);\r\n }\r\n\r\n private async getChannel(): Promise {\r\n const result = await this._bridge.send(\"windows\", operations.getChannel, { windowId: this.id }, undefined, { includeOperationCheck: true });\r\n\r\n return result.channel as string;\r\n }\r\n}\r\n","import { operationCheckConfigDecoder, operationCheckResultDecoder, simpleItemIdDecoder, workspaceFrameBoundsResultDecoder } from \"./decoders\";\r\nimport { BridgeOperation } from \"./types\";\r\n\r\nexport type SystemOperationTypes = \"operationCheck\" | \"getWorkspaceWindowFrameBounds\";\r\n\r\nexport const systemOperations: { [key in SystemOperationTypes]: BridgeOperation } = {\r\n operationCheck: { name: \"operationCheck\", dataDecoder: operationCheckConfigDecoder, resultDecoder: operationCheckResultDecoder },\r\n getWorkspaceWindowFrameBounds: { name: \"getWorkspaceWindowFrameBounds\", resultDecoder: workspaceFrameBoundsResultDecoder, dataDecoder: simpleItemIdDecoder }\r\n};\r\n","/* eslint-disable @typescript-eslint/no-explicit-any */\r\n\r\nexport const PromiseWrap = (promise: () => Promise, timeoutMilliseconds: number, timeoutMessage?: string): Promise => {\r\n return new Promise((resolve, reject) => {\r\n\r\n let promiseActive = true;\r\n\r\n const timeout = setTimeout(() => {\r\n if (!promiseActive) {\r\n return;\r\n }\r\n promiseActive = false;\r\n const message = timeoutMessage || `Promise timeout hit: ${timeoutMilliseconds}`;\r\n\r\n reject(message);\r\n }, timeoutMilliseconds);\r\n\r\n promise()\r\n .then((result) => {\r\n if (!promiseActive) {\r\n return;\r\n }\r\n promiseActive = false;\r\n clearTimeout(timeout);\r\n resolve(result);\r\n })\r\n .catch((error) => {\r\n if (!promiseActive) {\r\n return;\r\n }\r\n promiseActive = false;\r\n clearTimeout(timeout);\r\n reject(error);\r\n });\r\n });\r\n};\r\n\r\nexport const PromisePlus = (executor: (resolve: (value: T | PromiseLike) => void, reject: (reason?: any) => void) => void, timeoutMilliseconds: number, timeoutMessage?: string): Promise => {\r\n\r\n return new Promise((resolve, reject) => {\r\n const timeout = setTimeout(() => {\r\n\r\n const message = timeoutMessage || `Promise timeout hit: ${timeoutMilliseconds}`;\r\n\r\n reject(message);\r\n }, timeoutMilliseconds);\r\n\r\n const providedPromise = new Promise(executor);\r\n\r\n providedPromise\r\n .then((result) => {\r\n clearTimeout(timeout);\r\n resolve(result);\r\n })\r\n .catch((error) => {\r\n clearTimeout(timeout);\r\n reject(error);\r\n });\r\n });\r\n\r\n};\r\n","/* eslint-disable @typescript-eslint/no-non-null-assertion */\r\n/* eslint-disable @typescript-eslint/no-explicit-any */\r\nimport { IOConnectCore } from \"@interopio/core\";\r\nimport { IOConnectBrowser } from \"../../browser\";\r\nimport { GlueBridge } from \"../communication/bridge\";\r\nimport { nonEmptyStringDecoder, windowOpenSettingsDecoder, windowOperationTypesDecoder } from \"../shared/decoders\";\r\nimport { LibController, OperationCheckConfig, OperationCheckResult } from \"../shared/types\";\r\nimport { HelloSuccess, OpenWindowConfig, CoreWindowData, WindowHello, operations, WindowBoundsResult, WindowTitleConfig, WindowUrlResult, WindowMoveResizeConfig, WindowProjection, FocusEventData, WindowChannelResult } from \"./protocol\";\r\nimport {\r\n default as CallbackRegistryFactory,\r\n CallbackRegistry,\r\n UnsubscribeFunction,\r\n} from \"callback-registry\";\r\nimport { IoC } from \"../shared/ioc\";\r\nimport { systemOperations } from \"../shared/systemOperations\";\r\nimport { PromisePlus } from \"../shared/promise-plus\";\r\nimport { ChannelsController } from \"../channels/controller\";\r\n\r\nexport class WindowsController implements LibController {\r\n\r\n private focusEventHandler?: () => void;\r\n private readonly registry: CallbackRegistry = CallbackRegistryFactory();\r\n private platformRegistration!: Promise;\r\n private ioc!: IoC;\r\n private bridge!: GlueBridge;\r\n private publicWindowId!: string;\r\n private allWindowProjections: WindowProjection[] = [];\r\n private me?: IOConnectBrowser.Windows.WebWindow;\r\n private logger!: IOConnectBrowser.Logger.API;\r\n private isWorkspaceFrame?: boolean;\r\n private instanceId!: string;\r\n private channelsController!: ChannelsController;\r\n\r\n public async start(coreGlue: IOConnectCore.API, ioc: IoC): Promise {\r\n\r\n this.logger = coreGlue.logger.subLogger(\"windows.controller.web\");\r\n\r\n this.logger.trace(\"starting the web windows controller\");\r\n\r\n this.publicWindowId = ioc.publicWindowId;\r\n\r\n this.addWindowOperationExecutors();\r\n\r\n this.ioc = ioc;\r\n this.bridge = ioc.bridge;\r\n this.instanceId = coreGlue.interop.instance.instance as string;\r\n\r\n this.channelsController = ioc.channelsController;\r\n\r\n this.logger.trace(`set the public window id: ${this.publicWindowId}, set the bridge operations and ioc, registering with the platform now`);\r\n\r\n this.platformRegistration = this.registerWithPlatform();\r\n\r\n await this.platformRegistration;\r\n\r\n await this.initializeFocusTracking();\r\n\r\n this.logger.trace(\"registration with the platform successful, attaching the windows property to glue and returning\");\r\n\r\n const api = this.toApi();\r\n\r\n (coreGlue as IOConnectBrowser.API).windows = api;\r\n }\r\n\r\n public handlePlatformShutdown(): void {\r\n this.registry.clear();\r\n this.allWindowProjections = [];\r\n\r\n if (!this.focusEventHandler) {\r\n return;\r\n }\r\n\r\n document.removeEventListener(\"visibilityChange\", this.focusEventHandler);\r\n window.removeEventListener(\"focus\", this.focusEventHandler);\r\n window.removeEventListener(\"blur\", this.focusEventHandler);\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n public async handleBridgeMessage(args: any): Promise {\r\n await this.platformRegistration;\r\n\r\n const operationName = windowOperationTypesDecoder.runWithException(args.operation);\r\n\r\n const operation = operations[operationName];\r\n\r\n if (!operation.execute) {\r\n return;\r\n }\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n let operationData: any = args.data;\r\n\r\n if (operation.dataDecoder) {\r\n operationData = operation.dataDecoder.runWithException(args.data);\r\n }\r\n\r\n return await operation.execute(operationData);\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n private async open(name: string, url: string, options?: IOConnectBrowser.Windows.Settings): Promise {\r\n nonEmptyStringDecoder.runWithException(name);\r\n nonEmptyStringDecoder.runWithException(url);\r\n // layoutComponentId is a hidden property for global layouts\r\n const settings = windowOpenSettingsDecoder.runWithException(options);\r\n\r\n const windowSuccess = await this.bridge.send(\"windows\", operations.openWindow, { name, url, options: settings });\r\n\r\n return this.waitForWindowAdded(windowSuccess.windowId);\r\n }\r\n\r\n private list(): IOConnectBrowser.Windows.WebWindow[] {\r\n return this.allWindowProjections.map((projection) => projection.api);\r\n }\r\n\r\n public findById(id: string): IOConnectBrowser.Windows.WebWindow | undefined {\r\n nonEmptyStringDecoder.runWithException(id);\r\n\r\n return this.allWindowProjections.find((projection) => projection.id === id)?.api;\r\n }\r\n\r\n private toApi(): IOConnectBrowser.Windows.API {\r\n return {\r\n open: this.open.bind(this),\r\n my: this.my.bind(this),\r\n list: this.list.bind(this),\r\n findById: this.findById.bind(this),\r\n onWindowAdded: this.onWindowAdded.bind(this),\r\n onWindowRemoved: this.onWindowRemoved.bind(this),\r\n onWindowGotFocus: this.onWindowGotFocus.bind(this),\r\n onWindowLostFocus: this.onWindowLostFocus.bind(this)\r\n };\r\n }\r\n\r\n private addWindowOperationExecutors(): void {\r\n operations.focusChange.execute = this.handleFocusChangeEvent.bind(this);\r\n operations.windowAdded.execute = this.handleWindowAdded.bind(this);\r\n operations.windowRemoved.execute = this.handleWindowRemoved.bind(this);\r\n operations.getBounds.execute = this.handleGetBounds.bind(this);\r\n operations.getFrameBounds.execute = this.handleGetBounds.bind(this);\r\n operations.getTitle.execute = this.handleGetTitle.bind(this);\r\n operations.getUrl.execute = this.handleGetUrl.bind(this);\r\n operations.moveResize.execute = this.handleMoveResize.bind(this);\r\n operations.setTitle.execute = this.handleSetTitle.bind(this);\r\n operations.getChannel.execute = this.handleGetChannel.bind(this);\r\n }\r\n\r\n public my(): IOConnectBrowser.Windows.WebWindow {\r\n return Object.assign({}, this.me);\r\n }\r\n\r\n private onWindowAdded(callback: (window: IOConnectBrowser.Windows.WebWindow) => void): UnsubscribeFunction {\r\n if (typeof callback !== \"function\") {\r\n throw new Error(\"Cannot subscribe to window added, because the provided callback is not a function!\");\r\n }\r\n\r\n return this.registry.add(\"window-added\", callback);\r\n }\r\n\r\n private onWindowRemoved(callback: (window: IOConnectBrowser.Windows.WebWindow) => void): UnsubscribeFunction {\r\n if (typeof callback !== \"function\") {\r\n throw new Error(\"Cannot subscribe to window removed, because the provided callback is not a function!\");\r\n }\r\n\r\n return this.registry.add(\"window-removed\", callback);\r\n }\r\n\r\n private onWindowGotFocus(callback: (window: IOConnectBrowser.Windows.WebWindow) => void): UnsubscribeFunction {\r\n if (typeof callback !== \"function\") {\r\n throw new Error(\"Cannot subscribe to onWindowGotFocus, because the provided callback is not a function!\");\r\n }\r\n\r\n return this.registry.add(\"window-got-focus\", callback);\r\n }\r\n\r\n private onWindowLostFocus(callback: (window: IOConnectBrowser.Windows.WebWindow) => void): UnsubscribeFunction {\r\n if (typeof callback !== \"function\") {\r\n throw new Error(\"Cannot subscribe to onWindowLostFocus, because the provided callback is not a function!\");\r\n }\r\n\r\n return this.registry.add(\"window-lost-focus\", callback);\r\n }\r\n\r\n private async sayHello(): Promise {\r\n const helloSuccess = await this.bridge.send(\"windows\", operations.windowHello, { windowId: this.publicWindowId });\r\n\r\n return helloSuccess;\r\n }\r\n\r\n private async registerWithPlatform(): Promise {\r\n\r\n const { windows, isWorkspaceFrame } = await this.sayHello();\r\n\r\n this.isWorkspaceFrame = isWorkspaceFrame;\r\n\r\n this.logger.trace(\"the platform responded to the hello message\");\r\n\r\n // if I am an iframe, I am not considered a Glue Window\r\n if (!this.isWorkspaceFrame && this.publicWindowId) {\r\n this.logger.trace(\"i am not treated as a workspace frame, setting my window\");\r\n\r\n const myWindow = windows.find((w) => w.windowId === this.publicWindowId);\r\n\r\n if (!myWindow) {\r\n throw new Error(\"Cannot initialize the window library, because I received no information about me from the platform\");\r\n }\r\n\r\n const myProjection = await this.ioc.buildWebWindow(this.publicWindowId, myWindow.name);\r\n\r\n this.me = myProjection.api;\r\n\r\n this.allWindowProjections.push(myProjection);\r\n }\r\n\r\n const currentWindows = await Promise.all(windows\r\n .filter((w) => w.windowId !== this.publicWindowId)\r\n .map((w) => this.ioc.buildWebWindow(w.windowId, w.name))\r\n );\r\n\r\n this.logger.trace(\"all windows projections are completed, building the list collection\");\r\n\r\n this.allWindowProjections.push(...currentWindows);\r\n }\r\n\r\n private async handleFocusChangeEvent(focusData: FocusEventData): Promise {\r\n const foundProjection = this.allWindowProjections.find((projection) => projection.id === focusData.windowId);\r\n\r\n if (!foundProjection) {\r\n return;\r\n }\r\n\r\n foundProjection.model.processSelfFocusEvent(focusData.hasFocus);\r\n\r\n const keyToExecute = focusData.hasFocus ? \"window-got-focus\" : \"window-lost-focus\";\r\n\r\n this.registry.execute(keyToExecute, foundProjection.api);\r\n }\r\n\r\n private async handleWindowAdded(data: CoreWindowData): Promise {\r\n if (this.allWindowProjections.some((projection) => projection.id === data.windowId)) {\r\n return;\r\n }\r\n\r\n const webWindowProjection = await this.ioc.buildWebWindow(data.windowId, data.name);\r\n this.allWindowProjections.push(webWindowProjection);\r\n\r\n this.registry.execute(\"window-added\", webWindowProjection.api);\r\n }\r\n\r\n private async handleWindowRemoved(data: CoreWindowData): Promise {\r\n const removed = this.allWindowProjections.find((w) => w.id === data.windowId);\r\n\r\n if (!removed) {\r\n return;\r\n }\r\n\r\n this.allWindowProjections = this.allWindowProjections.filter((w) => w.id !== data.windowId);\r\n\r\n removed.model.clean();\r\n\r\n this.registry.execute(\"window-removed\", removed.api);\r\n }\r\n\r\n private async handleGetBounds(): Promise {\r\n\r\n if (!this.me && !this.isWorkspaceFrame) {\r\n throw new Error(\"This window cannot report it's bounds, because it is not a Glue Window, most likely because it is an iframe\");\r\n }\r\n\r\n // this.me is optional, because this handler responds to a workspace frame bounds request and the frame is not a regular GD window\r\n return {\r\n windowId: this.isWorkspaceFrame ? \"noop\" : this.me!.id,\r\n bounds: {\r\n top: window.screenTop,\r\n left: window.screenLeft,\r\n width: window.innerWidth,\r\n height: window.innerHeight\r\n }\r\n };\r\n }\r\n\r\n private async handleGetTitle(): Promise {\r\n\r\n if (!this.me) {\r\n throw new Error(\"This window cannot report it's title, because it is not a Glue Window, most likely because it is an iframe\");\r\n }\r\n\r\n return {\r\n windowId: this.me.id,\r\n title: document.title\r\n };\r\n }\r\n\r\n private async handleGetUrl(): Promise {\r\n\r\n if (!this.me) {\r\n throw new Error(\"This window cannot report it's url, because it is not a Glue Window, most likely because it is an iframe\");\r\n }\r\n\r\n return {\r\n windowId: this.me.id,\r\n url: window.location.href\r\n };\r\n }\r\n\r\n private async handleMoveResize(config: WindowMoveResizeConfig): Promise {\r\n\r\n const targetTop = typeof config.top === \"number\" ? config.top :\r\n config.relative ? 0 : window.screenTop;\r\n\r\n const targetLeft = typeof config.left === \"number\" ? config.left :\r\n config.relative ? 0 : window.screenLeft;\r\n\r\n const targetHeight = typeof config.height === \"number\" ? config.height :\r\n config.relative ? 0 : window.innerHeight;\r\n\r\n const targetWidth = typeof config.width === \"number\" ? config.width :\r\n config.relative ? 0 : window.innerWidth;\r\n\r\n const moveMethod = config.relative ? window.moveBy : window.moveTo;\r\n const resizeMethod = config.relative ? window.resizeBy : window.resizeTo;\r\n\r\n moveMethod(targetLeft, targetTop);\r\n resizeMethod(targetWidth, targetHeight);\r\n }\r\n\r\n private async handleSetTitle(config: WindowTitleConfig): Promise {\r\n document.title = config.title;\r\n }\r\n\r\n private async initializeFocusTracking(): Promise {\r\n\r\n if (this.isWorkspaceFrame) {\r\n this.logger.trace(\"Ignoring the focus tracking, because this client is a workspace frame\");\r\n return;\r\n }\r\n\r\n try {\r\n await this.bridge.send(\"windows\", systemOperations.operationCheck, { operation: \"focusChange\" });\r\n } catch (error) {\r\n this.logger.warn(\"The platform of this client is outdated and does not support focus tracking, disabling focus events for this client.\");\r\n return;\r\n }\r\n\r\n const hasFocus = document.hasFocus();\r\n\r\n // every window when opened gaines focus\r\n await this.transmitFocusChange(true);\r\n\r\n if (!hasFocus) {\r\n // manual focus lost announce in case focus was lost while Web was initializing\r\n await this.transmitFocusChange(false);\r\n }\r\n\r\n this.defineEventListeners();\r\n }\r\n\r\n private processFocusEvent(): void {\r\n const hasFocus = document.hasFocus();\r\n\r\n this.transmitFocusChange(hasFocus);\r\n }\r\n\r\n private waitForWindowAdded(windowId: string): Promise {\r\n\r\n const foundWindow = this.allWindowProjections.find((projection) => projection.id === windowId);\r\n\r\n if (foundWindow) {\r\n return Promise.resolve(foundWindow.api);\r\n }\r\n\r\n return PromisePlus((resolve) => {\r\n const unsubscribe = this.onWindowAdded((addedWindow) => {\r\n if (addedWindow.id === windowId) {\r\n unsubscribe();\r\n resolve(addedWindow);\r\n }\r\n });\r\n }, 30000, `Timed out waiting for ${windowId} to be announced`);\r\n }\r\n\r\n private async transmitFocusChange(hasFocus: boolean): Promise {\r\n\r\n const eventData: FocusEventData = {\r\n windowId: this.me?.id || `iframe-${this.instanceId}`,\r\n hasFocus\r\n };\r\n\r\n if (this.me) {\r\n this.me.isFocused = hasFocus;\r\n }\r\n\r\n await this.bridge.send(\"windows\", operations.focusChange, eventData);\r\n }\r\n\r\n private defineEventListeners(): void {\r\n\r\n this.focusEventHandler = this.processFocusEvent.bind(this);\r\n\r\n document.addEventListener(\"visibilityChange\", this.focusEventHandler);\r\n window.addEventListener(\"focus\", this.focusEventHandler);\r\n window.addEventListener(\"blur\", this.focusEventHandler);\r\n }\r\n\r\n private async handleGetChannel(): Promise {\r\n\r\n if (!this.me) {\r\n throw new Error(\"This window cannot report it's channel, because it is not a Glue Window, most likely because it is an iframe\");\r\n }\r\n\r\n const channel = this.channelsController.my();\r\n\r\n return {\r\n ...(channel ? { channel } : {}),\r\n };\r\n }\r\n}\r\n","export const GlueWebPlatformControlName = \"T42.Web.Platform.Control\";\r\n\r\nexport const GlueWebPlatformStreamName = \"T42.Web.Platform.Stream\";\r\n\r\nexport const GlueClientControlName = \"T42.Web.Client.Control\";\r\n\r\nexport const GlueCorePlusThemesStream = \"T42.Core.Plus.Themes.Stream\";","/* eslint-disable @typescript-eslint/no-explicit-any */\r\nimport { IOConnectCore } from \"@interopio/core\";\r\nimport { libDomainDecoder } from \"../shared/decoders\";\r\nimport { PromisePlus } from \"../shared/promise-plus\";\r\nimport { systemOperations } from \"../shared/systemOperations\";\r\nimport { BridgeOperation, LibController, LibDomains, OperationCheckConfig, OperationCheckResult } from \"../shared/types\";\r\nimport { GlueClientControlName, GlueCorePlusThemesStream, GlueWebPlatformControlName, GlueWebPlatformStreamName } from \"./constants\";\r\n\r\nexport class GlueBridge {\r\n private readonly platformMethodTimeoutMs = 10000;\r\n private controllers!: { [key in LibDomains]: LibController };\r\n private sub!: IOConnectCore.AGM.Subscription;\r\n private running?: boolean;\r\n\r\n constructor(private readonly coreGlue: IOConnectCore.API, private readonly communicationId: string) {}\r\n\r\n public get contextLib(): IOConnectCore.Contexts.API {\r\n return this.coreGlue.contexts;\r\n }\r\n\r\n public get interopInstance(): string | undefined {\r\n return this.coreGlue.interop.instance.instance;\r\n }\r\n\r\n public async stop(): Promise {\r\n this.running = false;\r\n this.sub.close();\r\n await this.coreGlue.interop.unregister(GlueClientControlName);\r\n }\r\n\r\n public async start(controllers: { [key in LibDomains]: LibController }): Promise {\r\n this.running = true;\r\n this.controllers = controllers;\r\n\r\n await Promise.all([\r\n this.checkWaitMethod(GlueWebPlatformControlName),\r\n this.checkWaitMethod(GlueWebPlatformStreamName)\r\n ]);\r\n\r\n // this systemId will be missing if the platform is older than 1.12.X\r\n const systemId = this.communicationId;\r\n\r\n const [sub] = await Promise.all([\r\n this.coreGlue.interop.subscribe(GlueWebPlatformStreamName, systemId ? { target: { instance: this.communicationId } } : undefined),\r\n this.coreGlue.interop.registerAsync(GlueClientControlName, (args, _, success, error) => this.passMessageController(args, success, error))\r\n ]);\r\n\r\n this.sub = sub;\r\n\r\n this.sub.onData((pkg) => this.passMessageController(pkg.data));\r\n }\r\n\r\n public getInteropInstance(windowId: string): IOConnectCore.Interop.Instance {\r\n const result = this.coreGlue.interop.servers().find((s) => s.windowId && s.windowId === windowId);\r\n\r\n return {\r\n application: result?.application,\r\n applicationName: result?.applicationName,\r\n peerId: result?.peerId,\r\n instance: result?.instance,\r\n windowId: result?.windowId\r\n };\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n public async send(domain: LibDomains, operation: BridgeOperation, operationData: OutBound, options?: IOConnectCore.AGM.InvokeOptions, webOptions?: { includeOperationCheck?: boolean }): Promise {\r\n\r\n if (operation.dataDecoder) {\r\n try {\r\n operation.dataDecoder.runWithException(operationData);\r\n } catch (error: any) {\r\n throw new Error(`Unexpected Web->Platform outgoing validation error: ${error.message}, for operation: ${operation.name} and input: ${JSON.stringify(error.input)}`);\r\n }\r\n }\r\n\r\n const operationSupported = webOptions?.includeOperationCheck ? \r\n (await this.checkOperationSupported(domain, operation)).isSupported :\r\n true;\r\n\r\n if (!operationSupported) {\r\n throw new Error(`Cannot complete operation: ${operation.name} for domain: ${domain} because this client is connected to a platform which does not support it`);\r\n }\r\n\r\n try {\r\n const operationResult = await this.transmitMessage(domain, operation, operationData, options);\r\n\r\n if (operation.resultDecoder) {\r\n operation.resultDecoder.runWithException(operationResult);\r\n }\r\n\r\n return operationResult;\r\n\r\n } catch (error: any) {\r\n if (error.kind) {\r\n throw new Error(`Unexpected Web<-Platform incoming validation error: ${error.message}, for operation: ${operation.name} and input: ${JSON.stringify(error.input)}`);\r\n }\r\n throw new Error(error.message);\r\n }\r\n }\r\n\r\n public async createNotificationsSteam(): Promise {\r\n const streamExists = this.coreGlue.interop.methods().some((method) => method.name === GlueCorePlusThemesStream);\r\n\r\n if (!streamExists) {\r\n throw new Error(\"Cannot subscribe to theme changes, because the underlying interop stream does not exist. Most likely this is the case when this client is not connected to Core Plus.\");\r\n }\r\n\r\n return this.coreGlue.interop.subscribe(GlueCorePlusThemesStream, this.communicationId ? { target: { instance: this.communicationId } } : undefined);\r\n }\r\n\r\n private async checkOperationSupported(domain: LibDomains, operation: BridgeOperation): Promise {\r\n try {\r\n const result = await this.send(domain, systemOperations.operationCheck, { operation: operation.name });\r\n\r\n return result;\r\n } catch (error) {\r\n return { isSupported: false };\r\n }\r\n }\r\n\r\n private checkWaitMethod(name: string): Promise {\r\n return PromisePlus((resolve) => {\r\n\r\n const hasMethod = this.coreGlue.interop.methods().some((method) => {\r\n const nameMatch = method.name === name;\r\n\r\n const serverMatch = this.communicationId ?\r\n method.getServers().some((server) => server.instance === this.communicationId) :\r\n true;\r\n\r\n return nameMatch && serverMatch;\r\n });\r\n\r\n if (hasMethod) {\r\n return resolve();\r\n }\r\n\r\n const unSub = this.coreGlue.interop.serverMethodAdded((data) => {\r\n const method = data.method;\r\n const server = data.server;\r\n\r\n const serverMatch = this.communicationId ?\r\n server.instance === this.communicationId :\r\n true;\r\n\r\n if (method.name === name && serverMatch) {\r\n unSub();\r\n resolve();\r\n }\r\n });\r\n\r\n }, this.platformMethodTimeoutMs, `Cannot initiate Glue Web, because a system method's discovery timed out: ${name}`);\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n private passMessageController(args: any, success?: (args?: any) => void, error?: (error?: string | object | undefined) => void): void {\r\n const decodeResult = libDomainDecoder.run(args.domain);\r\n\r\n if (!decodeResult.ok) {\r\n if (error) {\r\n error(`Cannot execute this client control, because of domain validation error: ${JSON.stringify(decodeResult.error)}`);\r\n }\r\n return;\r\n }\r\n\r\n const domain = decodeResult.result;\r\n\r\n this.controllers[domain]\r\n .handleBridgeMessage(args)\r\n .then((resolutionData: unknown) => {\r\n if (success) {\r\n success(resolutionData);\r\n }\r\n })\r\n .catch((err: string | object | undefined) => {\r\n if (error) {\r\n error(err);\r\n }\r\n console.warn(err);\r\n });\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n private async transmitMessage(domain: string, operation: BridgeOperation, data: any, options?: IOConnectCore.AGM.InvokeOptions): Promise {\r\n\r\n const messageData = { domain, data, operation: operation.name };\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n let invocationResult: IOConnectCore.Interop.InvocationResult;\r\n\r\n const baseErrorMessage = `Internal Platform Communication Error. Attempted operation: ${JSON.stringify(operation.name)} with data: ${JSON.stringify(data)}. `;\r\n\r\n const systemId = this.communicationId;\r\n\r\n try {\r\n\r\n if (!this.running) {\r\n throw new Error(\"Cannot send a control message, because the platform shut down\");\r\n }\r\n\r\n invocationResult = await this.coreGlue.interop.invoke(GlueWebPlatformControlName, messageData, systemId ? { instance: this.communicationId } : undefined, options);\r\n\r\n if (!invocationResult) {\r\n throw new Error(\"Received unsupported result from the platform - empty result\");\r\n }\r\n\r\n if (!Array.isArray(invocationResult.all_return_values) || invocationResult.all_return_values.length === 0) {\r\n throw new Error(\"Received unsupported result from the platform - empty values collection\");\r\n }\r\n\r\n } catch (error: any) {\r\n if (error && error.all_errors && error.all_errors.length) {\r\n // IMPORTANT: Do NOT change the `Inner message:` string, because it is used by other programs to extract the inner message of a communication error\r\n const invocationErrorMessage = error.all_errors[0].message;\r\n throw new Error(`${baseErrorMessage} -> Inner message: ${invocationErrorMessage}`);\r\n\r\n }\r\n // IMPORTANT: Do NOT change the `Inner message:` string, because it is used by other programs to extract the inner message of a communication error\r\n throw new Error(`${baseErrorMessage} -> Inner message: ${error.message}`);\r\n }\r\n\r\n return invocationResult.all_return_values[0].returned;\r\n }\r\n}\r\n","/* eslint-disable @typescript-eslint/no-explicit-any */\r\nimport { IOConnectBrowser } from \"../../browser\";\r\nimport { appDirectoryStateChangeDecoder, appHelloSuccessDecoder, applicationStartConfigDecoder, appRemoveConfigDecoder, appsExportOperationDecoder, basicInstanceDataDecoder, instanceDataDecoder, windowHelloDecoder } from \"../shared/decoders\";\r\nimport { BridgeOperation } from \"../shared/types\";\r\n\r\nexport type AppManagerOperationTypes = \"appHello\" | \"appDirectoryStateChange\" | \"instanceStarted\" | \"instanceStopped\" |\r\n \"applicationStart\" | \"instanceStop\" | \"import\" | \"remove\" | \"export\" | \"clear\";\r\n\r\nexport const operations: { [key in AppManagerOperationTypes]: BridgeOperation } = {\r\n appHello: { name: \"appHello\", dataDecoder: windowHelloDecoder, resultDecoder: appHelloSuccessDecoder },\r\n appDirectoryStateChange: { name: \"appDirectoryStateChange\", dataDecoder: appDirectoryStateChangeDecoder },\r\n instanceStarted: { name: \"instanceStarted\", dataDecoder: instanceDataDecoder },\r\n instanceStopped: { name: \"instanceStopped\", dataDecoder: instanceDataDecoder },\r\n applicationStart: { name: \"applicationStart\", dataDecoder: applicationStartConfigDecoder, resultDecoder: instanceDataDecoder },\r\n instanceStop: { name: \"instanceStop\", dataDecoder: basicInstanceDataDecoder },\r\n import: { name: \"import\" },\r\n remove: { name: \"remove\", dataDecoder: appRemoveConfigDecoder },\r\n export: { name: \"export\", resultDecoder: appsExportOperationDecoder },\r\n clear: { name: \"clear\" }\r\n};\r\n\r\nexport interface InstanceData {\r\n id: string;\r\n applicationName: string;\r\n}\r\n\r\nexport interface BaseApplicationData {\r\n name: string;\r\n type: string;\r\n userProperties: any;\r\n title?: string;\r\n version?: string;\r\n icon?: string;\r\n caption?: string;\r\n}\r\n\r\nexport interface ApplicationData extends BaseApplicationData {\r\n instances: InstanceData[];\r\n}\r\n\r\nexport interface AppDirectoryStateChange {\r\n appsAdded: BaseApplicationData[];\r\n appsChanged: BaseApplicationData[];\r\n appsRemoved: BaseApplicationData[];\r\n}\r\n\r\nexport interface AppRemoveConfig {\r\n name: string;\r\n}\r\n\r\nexport interface AppsExportOperation {\r\n definitions: IOConnectBrowser.AppManager.Definition[];\r\n}\r\n\r\nexport interface AppsImportOperation {\r\n definitions: Array;\r\n mode: \"replace\" | \"merge\";\r\n}\r\n\r\nexport interface AppHelloSuccess {\r\n apps: ApplicationData[];\r\n initialChannelId?: string;\r\n}\r\n\r\nexport interface ApplicationStartConfig {\r\n name: string;\r\n waitForAGMReady: boolean;\r\n id?: string;\r\n context?: any;\r\n top?: number;\r\n left?: number;\r\n width?: number;\r\n height?: number;\r\n relativeTo?: string;\r\n relativeDirection?: \"top\" | \"left\" | \"right\" | \"bottom\";\r\n forceChromeTab?: boolean;\r\n layoutComponentId?: string;\r\n channelId?: string;\r\n}\r\n\r\nexport interface BasicInstanceData {\r\n id: string;\r\n}\r\n\r\nexport interface FDC3Definition {\r\n name: string;\r\n title?: string;\r\n version?: string;\r\n appId?: string;\r\n manifest: string;\r\n manifestType: string;\r\n tooltip?: string;\r\n description?: string;\r\n contactEmail?: string;\r\n supportEmail?: string;\r\n publisher?: string;\r\n images?: Array<{ url?: string }>;\r\n icons?: Array<{ icon?: string }>;\r\n customConfig?: any;\r\n intents?: Intent[];\r\n}\r\n\r\nexport interface Intent {\r\n name: string;\r\n displayName?: string;\r\n contexts?: string[];\r\n customConfig?: any;\r\n}\r\n\r\nexport interface DefinitionParseResult {\r\n valid: IOConnectBrowser.AppManager.Definition[];\r\n invalid: Array<{ app: string; error: string }>;\r\n}\r\n","/* eslint-disable @typescript-eslint/no-unused-vars */\r\n/* eslint-disable @typescript-eslint/no-explicit-any */\r\nimport { IOConnectCore } from \"@interopio/core\";\r\nimport { IOConnectBrowser } from \"../../browser\";\r\nimport { GlueBridge } from \"../communication/bridge\";\r\nimport { allApplicationDefinitionsDecoder, appManagerOperationTypesDecoder, importModeDecoder, nonEmptyStringDecoder } from \"../shared/decoders\";\r\nimport { IoC } from \"../shared/ioc\";\r\nimport { LibController } from \"../shared/types\";\r\nimport { WindowHello } from \"../windows/protocol\";\r\nimport { AppsImportOperation, AppHelloSuccess, ApplicationStartConfig, AppRemoveConfig, InstanceData, operations, BaseApplicationData, AppsExportOperation, DefinitionParseResult, AppDirectoryStateChange } from \"./protocol\";\r\nimport {\r\n default as CallbackRegistryFactory,\r\n CallbackRegistry,\r\n UnsubscribeFunction,\r\n} from \"callback-registry\";\r\nimport { ChannelsController } from \"../channels/controller\";\r\nimport { SessionStorageController } from \"../storage/session\";\r\n\r\nexport class AppManagerController implements LibController {\r\n private baseApplicationsTimeoutMS = 60000;\r\n private appImportTimeoutMS = 20;\r\n private readonly registry: CallbackRegistry = CallbackRegistryFactory();\r\n private ioc!: IoC;\r\n private bridge!: GlueBridge;\r\n private publicWindowId!: string;\r\n private me: IOConnectBrowser.AppManager.Instance | undefined;\r\n private applications: IOConnectBrowser.AppManager.Application[] = [];\r\n private instances: IOConnectBrowser.AppManager.Instance[] = [];\r\n private platformRegistration!: Promise;\r\n private logger!: IOConnectBrowser.Logger.API;\r\n private channelsController!: ChannelsController;\r\n private sessionController!: SessionStorageController;\r\n\r\n public handlePlatformShutdown(): void {\r\n this.registry.clear();\r\n this.applications = [];\r\n this.instances = [];\r\n delete this.me;\r\n }\r\n\r\n public async start(coreGlue: IOConnectCore.API, ioc: IoC): Promise {\r\n this.logger = coreGlue.logger.subLogger(\"appManger.controller.web\");\r\n\r\n this.logger.trace(\"starting the web appManager controller\");\r\n\r\n this.publicWindowId = ioc.publicWindowId;\r\n\r\n this.addOperationsExecutors();\r\n\r\n this.ioc = ioc;\r\n this.bridge = ioc.bridge;\r\n this.channelsController = ioc.channelsController;\r\n this.sessionController = ioc.sessionController;\r\n\r\n this.platformRegistration = this.registerWithPlatform();\r\n\r\n await this.platformRegistration;\r\n\r\n this.logger.trace(\"registration with the platform successful, attaching the appManager property to glue and returning\");\r\n\r\n const api = this.toApi();\r\n\r\n (coreGlue as IOConnectBrowser.API).appManager = api;\r\n }\r\n\r\n public async handleBridgeMessage(args: any): Promise {\r\n await this.platformRegistration;\r\n\r\n const operationName = appManagerOperationTypesDecoder.runWithException(args.operation);\r\n\r\n const operation = operations[operationName];\r\n\r\n if (!operation.execute) {\r\n return;\r\n }\r\n\r\n let operationData: any = args.data;\r\n\r\n if (operation.dataDecoder) {\r\n operationData = operation.dataDecoder.runWithException(args.data);\r\n }\r\n\r\n return await operation.execute(operationData);\r\n }\r\n\r\n public onInstanceStarted(callback: (instance: IOConnectBrowser.AppManager.Instance) => any): UnsubscribeFunction {\r\n if (typeof callback !== \"function\") {\r\n throw new Error(\"onInstanceStarted requires a single argument of type function\");\r\n }\r\n\r\n return this.registry.add(\"instance-started\", callback, this.instances);\r\n }\r\n\r\n public onInstanceStopped(callback: (instance: IOConnectBrowser.AppManager.Instance) => any): UnsubscribeFunction {\r\n if (typeof callback !== \"function\") {\r\n throw new Error(\"onInstanceStopped requires a single argument of type function\");\r\n }\r\n\r\n return this.registry.add(\"instance-stopped\", callback);\r\n }\r\n\r\n public async startApplication(appName: string, context?: object, options?: IOConnectBrowser.AppManager.ApplicationStartOptions): Promise {\r\n const channels = await this.channelsController.all();\r\n\r\n if (options?.channelId && !channels.includes(options.channelId)) {\r\n throw new Error(`The channel with name \"${options.channelId}\" doesn't exist!`);\r\n }\r\n \r\n // reuseId is a hidden property for workspaces-only use\r\n // layoutComponentId is a hidden property for global layouts\r\n // forceChromeTab is a hidden property for extension use only\r\n const startOptions: ApplicationStartConfig = {\r\n name: appName,\r\n waitForAGMReady: options?.waitForAGMReady ?? true,\r\n context,\r\n top: options?.top,\r\n left: options?.left,\r\n width: options?.width,\r\n height: options?.height,\r\n relativeTo: options?.relativeTo,\r\n relativeDirection: options?.relativeDirection,\r\n id: (options as any)?.reuseId,\r\n forceChromeTab: (options as any)?.forceTab,\r\n layoutComponentId: (options as any)?.layoutComponentId,\r\n channelId: options?.channelId\r\n };\r\n\r\n const openResult = await this.bridge.send(\"appManager\", operations.applicationStart, startOptions);\r\n\r\n const app = this.applications.find((a) => a.name === openResult.applicationName) as IOConnectBrowser.AppManager.Application;\r\n\r\n return this.ioc.buildInstance(openResult, app);\r\n }\r\n\r\n public getApplication(name: string): IOConnectBrowser.AppManager.Application {\r\n const verifiedName = nonEmptyStringDecoder.runWithException(name);\r\n\r\n return this.applications.find((app) => app.name === verifiedName) as IOConnectBrowser.AppManager.Application;\r\n }\r\n\r\n public getInstances(): IOConnectBrowser.AppManager.Instance[] {\r\n return this.instances.slice();\r\n }\r\n\r\n private toApi(): IOConnectBrowser.AppManager.API {\r\n const api: IOConnectBrowser.AppManager.API = {\r\n myInstance: this.me as unknown as IOConnectBrowser.AppManager.Instance,\r\n inMemory: {\r\n import: this.import.bind(this),\r\n remove: this.remove.bind(this),\r\n export: this.export.bind(this),\r\n clear: this.clear.bind(this)\r\n },\r\n application: this.getApplication.bind(this),\r\n applications: this.getApplications.bind(this),\r\n instances: this.getInstances.bind(this),\r\n onAppAdded: this.onAppAdded.bind(this),\r\n onAppChanged: this.onAppChanged.bind(this),\r\n onAppRemoved: this.onAppRemoved.bind(this),\r\n onInstanceStarted: this.onInstanceStarted.bind(this),\r\n onInstanceStopped: this.onInstanceStopped.bind(this)\r\n };\r\n\r\n return api;\r\n }\r\n\r\n private addOperationsExecutors(): void {\r\n operations.appDirectoryStateChange.execute = this.handleAppDirectoryStateChange.bind(this);\r\n operations.instanceStarted.execute = this.handleInstanceStartedMessage.bind(this);\r\n operations.instanceStopped.execute = this.handleInstanceStoppedMessage.bind(this);\r\n }\r\n\r\n private async handleAppDirectoryStateChange(data: AppDirectoryStateChange): Promise {\r\n data.appsAdded.forEach(this.handleApplicationAddedMessage.bind(this));\r\n data.appsChanged.forEach(this.handleApplicationChangedMessage.bind(this));\r\n data.appsRemoved.forEach(this.handleApplicationRemovedMessage.bind(this));\r\n }\r\n\r\n private onAppAdded(callback: (app: IOConnectBrowser.AppManager.Application) => any): UnsubscribeFunction {\r\n if (typeof callback !== \"function\") {\r\n throw new Error(\"onAppAdded requires a single argument of type function\");\r\n }\r\n\r\n return this.registry.add(\"application-added\", callback, this.applications);\r\n }\r\n\r\n private onAppRemoved(callback: (app: IOConnectBrowser.AppManager.Application) => any): UnsubscribeFunction {\r\n if (typeof callback !== \"function\") {\r\n throw new Error(\"onAppRemoved requires a single argument of type function\");\r\n }\r\n\r\n return this.registry.add(\"application-removed\", callback);\r\n }\r\n\r\n private onAppChanged(callback: (app: IOConnectBrowser.AppManager.Application) => any): UnsubscribeFunction {\r\n if (typeof callback !== \"function\") {\r\n throw new Error(\"onAppChanged requires a single argument of type function\");\r\n }\r\n\r\n return this.registry.add(\"application-changed\", callback);\r\n }\r\n\r\n private async handleApplicationAddedMessage(appData: BaseApplicationData): Promise {\r\n\r\n if (this.applications.some((app) => app.name === appData.name)) {\r\n return;\r\n }\r\n\r\n const app = await this.ioc.buildApplication(appData, []);\r\n\r\n const instances = this.instances.filter((instance) => instance.application.name === app.name);\r\n\r\n app.instances.push(...instances);\r\n\r\n this.applications.push(app);\r\n\r\n this.registry.execute(\"application-added\", app);\r\n }\r\n\r\n private async handleApplicationRemovedMessage(appData: BaseApplicationData): Promise {\r\n const appIndex = this.applications.findIndex((app) => app.name === appData.name);\r\n\r\n if (appIndex < 0) {\r\n return;\r\n }\r\n\r\n const app = this.applications[appIndex];\r\n\r\n this.applications.splice(appIndex, 1);\r\n\r\n this.registry.execute(\"application-removed\", app);\r\n }\r\n\r\n private async handleApplicationChangedMessage(appData: BaseApplicationData): Promise {\r\n const app = this.applications.find((app) => app.name === appData.name);\r\n\r\n if (!app) {\r\n return this.handleApplicationAddedMessage(appData);\r\n }\r\n\r\n app.title = appData.title as string;\r\n app.version = appData.version as string;\r\n app.icon = appData.icon as string;\r\n app.caption = appData.caption as string;\r\n app.userProperties = appData.userProperties;\r\n\r\n this.registry.execute(\"application-changed\", app);\r\n }\r\n\r\n private async handleInstanceStartedMessage(instanceData: InstanceData): Promise {\r\n if (this.instances.some((instance) => instance.id === instanceData.id)) {\r\n return;\r\n }\r\n\r\n const application = this.applications.find((app) => app.name === instanceData.applicationName);\r\n\r\n if (!application) {\r\n throw new Error(`Cannot add instance: ${instanceData.id}, because there is no application definition associated with it`);\r\n }\r\n\r\n const instance = this.ioc.buildInstance(instanceData, application);\r\n\r\n this.instances.push(instance);\r\n application.instances.push(instance);\r\n\r\n this.registry.execute(\"instance-started\", instance);\r\n }\r\n\r\n private async handleInstanceStoppedMessage(instanceData: InstanceData): Promise {\r\n const instance = this.instances.find((i) => i.id === instanceData.id);\r\n\r\n if (instance) {\r\n const instIdx = this.instances.findIndex((inst) => inst.id === instanceData.id);\r\n this.instances.splice(instIdx, 1);\r\n }\r\n\r\n const application = this.applications.find((app) => app.instances.some((inst) => inst.id === instanceData.id));\r\n\r\n if (application) {\r\n const instIdxApps = application.instances.findIndex((inst) => inst.id === instanceData.id);\r\n application.instances.splice(instIdxApps, 1);\r\n }\r\n\r\n if (!instance) {\r\n return;\r\n }\r\n\r\n this.registry.execute(\"instance-stopped\", instance);\r\n }\r\n\r\n private async import(definitions: IOConnectBrowser.AppManager.Definition[], mode: \"replace\" | \"merge\" = \"replace\"): Promise {\r\n importModeDecoder.runWithException(mode);\r\n\r\n if (!Array.isArray(definitions)) {\r\n throw new Error(\"Import must be called with an array of definitions\");\r\n }\r\n\r\n if (definitions.length > 10000) {\r\n throw new Error(\"Cannot import more than 10000 app definitions in Glue42 Core.\");\r\n }\r\n\r\n const parseResult = definitions.reduce((soFar, definition) => {\r\n\r\n const decodeResult = allApplicationDefinitionsDecoder.run(definition);\r\n\r\n if (!decodeResult.ok) {\r\n soFar.invalid.push({ app: definition?.name, error: JSON.stringify(decodeResult.error) });\r\n } else {\r\n soFar.valid.push(definition);\r\n }\r\n\r\n return soFar;\r\n }, { valid: [], invalid: [] });\r\n\r\n const responseTimeout = this.baseApplicationsTimeoutMS + this.appImportTimeoutMS * parseResult.valid.length;\r\n\r\n await this.bridge.send(\"appManager\", operations.import, { definitions: parseResult.valid, mode }, { methodResponseTimeoutMs: responseTimeout });\r\n\r\n return {\r\n imported: parseResult.valid.map((valid) => valid.name),\r\n errors: parseResult.invalid\r\n };\r\n }\r\n\r\n private async remove(name: string): Promise {\r\n nonEmptyStringDecoder.runWithException(name);\r\n\r\n await this.bridge.send(\"appManager\", operations.remove, { name }, { methodResponseTimeoutMs: this.baseApplicationsTimeoutMS });\r\n }\r\n\r\n private async clear(): Promise {\r\n await this.bridge.send(\"appManager\", operations.clear, undefined, { methodResponseTimeoutMs: this.baseApplicationsTimeoutMS });\r\n }\r\n\r\n private async export(): Promise {\r\n\r\n const response = await this.bridge.send(\"appManager\", operations.export, undefined, { methodResponseTimeoutMs: this.baseApplicationsTimeoutMS });\r\n\r\n return response.definitions;\r\n }\r\n\r\n public getApplications(): IOConnectBrowser.AppManager.Application[] {\r\n return this.applications.slice();\r\n }\r\n\r\n private async joinInitialChannel(initialChannelId: string): Promise {\r\n try {\r\n await this.channelsController.join(initialChannelId);\r\n } catch (error) {\r\n this.logger.warn(`Application instance ${this.me} was unable to join the ${initialChannelId} channel. Reason: ${JSON.stringify(error)}`);\r\n }\r\n }\r\n\r\n private async registerWithPlatform(): Promise {\r\n const result = await this.bridge.send(\"appManager\", operations.appHello, { windowId: this.publicWindowId }, { methodResponseTimeoutMs: this.baseApplicationsTimeoutMS });\r\n\r\n this.logger.trace(\"the platform responded to the hello message with a full list of apps\");\r\n\r\n this.applications = await Promise.all(result.apps.map((app) => this.ioc.buildApplication(app, app.instances)));\r\n\r\n this.instances = this.applications.reduce((instancesSoFar, app) => {\r\n\r\n instancesSoFar.push(...app.instances);\r\n\r\n return instancesSoFar;\r\n }, []);\r\n\r\n this.me = this.findMyInstance();\r\n\r\n this.logger.trace(`all applications were parsed and saved. I am ${this.me ? \"NOT a\" : \"a\"} valid instance`);\r\n\r\n const { channels: channelsStorageData } = this.sessionController.getWindowData();\r\n const channel = channelsStorageData ? channelsStorageData.currentName : result.initialChannelId;\r\n \r\n if (channel) {\r\n await this.joinInitialChannel(channel);\r\n }\r\n }\r\n\r\n private findMyInstance(): IOConnectBrowser.AppManager.Instance | undefined {\r\n for (const app of this.applications) {\r\n const foundInstance = app.instances.find((instance) => instance.id === this.publicWindowId);\r\n\r\n if (foundInstance) {\r\n return foundInstance;\r\n }\r\n }\r\n\r\n // this satisfies the TS \"noImplicitReturns\" true flag\r\n return undefined;\r\n }\r\n}\r\n","import { IOConnectBrowser } from \"../../browser\";\r\nimport { GlueBridge } from \"../communication/bridge\";\r\nimport { BasicInstanceData, InstanceData, operations } from \"./protocol\";\r\n\r\nexport class InstanceModel {\r\n private me!: IOConnectBrowser.AppManager.Instance;\r\n private readonly myCtxKey: string;\r\n\r\n constructor(private readonly data: InstanceData, private readonly bridge: GlueBridge, private readonly application: IOConnectBrowser.AppManager.Application) {\r\n this.myCtxKey = `___instance___${this.data.id}`;\r\n }\r\n\r\n public toApi(): IOConnectBrowser.AppManager.Instance {\r\n const agm = this.bridge.getInteropInstance(this.data.id);\r\n\r\n const api: IOConnectBrowser.AppManager.Instance = {\r\n id: this.data.id,\r\n agm,\r\n application: this.application,\r\n stop: this.stop.bind(this),\r\n getContext: this.getContext.bind(this)\r\n };\r\n\r\n this.me = Object.freeze(api);\r\n\r\n return this.me;\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n private async getContext(): Promise {\r\n return this.bridge.contextLib.get(this.myCtxKey);\r\n }\r\n\r\n private async stop(): Promise {\r\n await this.bridge.send(\"appManager\", operations.instanceStop, { id: this.data.id });\r\n }\r\n}","/* eslint-disable @typescript-eslint/no-explicit-any */\r\nimport { UnsubscribeFunction } from \"callback-registry\";\r\nimport { IOConnectBrowser } from \"../../browser\";\r\nimport { AppManagerController } from \"./controller\";\r\nimport { BaseApplicationData } from \"./protocol\";\r\nimport { startApplicationContextDecoder, startApplicationOptionsDecoder } from \"../shared/decoders\";\r\n\r\nexport class ApplicationModel {\r\n private me!: IOConnectBrowser.AppManager.Application;\r\n\r\n constructor(\r\n private readonly data: BaseApplicationData,\r\n private readonly instances: IOConnectBrowser.AppManager.Instance[],\r\n private readonly controller: AppManagerController,\r\n ) { }\r\n\r\n public toApi(): IOConnectBrowser.AppManager.Application {\r\n const api: IOConnectBrowser.AppManager.Application = {\r\n name: this.data.name,\r\n title: this.data.title as string,\r\n version: this.data.version as string,\r\n icon: this.data.icon as string,\r\n caption: this.data.caption as string,\r\n userProperties: this.data.userProperties,\r\n instances: this.instances,\r\n start: this.start.bind(this),\r\n onInstanceStarted: this.onInstanceStarted.bind(this),\r\n onInstanceStopped: this.onInstanceStopped.bind(this)\r\n };\r\n\r\n this.me = api;\r\n\r\n return this.me;\r\n }\r\n\r\n private onInstanceStarted(callback: (instance: IOConnectBrowser.AppManager.Instance) => any): UnsubscribeFunction {\r\n\r\n if (typeof callback !== \"function\") {\r\n throw new Error(\"OnInstanceStarted requires a single argument of type function\");\r\n }\r\n\r\n return this.controller.onInstanceStarted((instance) => {\r\n if (instance.application.name === this.data.name) {\r\n callback(instance);\r\n }\r\n });\r\n }\r\n\r\n private onInstanceStopped(callback: (instance: IOConnectBrowser.AppManager.Instance) => any): UnsubscribeFunction {\r\n if (typeof callback !== \"function\") {\r\n throw new Error(\"OnInstanceStarted requires a single argument of type function\");\r\n }\r\n\r\n return this.controller.onInstanceStopped((instance) => {\r\n if (instance.application.name === this.data.name) {\r\n callback(instance);\r\n }\r\n });\r\n }\r\n\r\n private async start(context?: any, options?: IOConnectBrowser.AppManager.ApplicationStartOptions): Promise {\r\n const verifiedContext = startApplicationContextDecoder.runWithException(context);\r\n const verifiedOptions = startApplicationOptionsDecoder.runWithException(options);\r\n\r\n return this.controller.startApplication(this.data.name, verifiedContext, verifiedOptions);\r\n }\r\n}","import { IOConnectBrowser } from \"../../browser\";\r\nimport { allLayoutsFullConfigDecoder, allLayoutsSummariesResultDecoder, getAllLayoutsConfigDecoder, glueLayoutDecoder, layoutsImportConfigDecoder, optionalSimpleLayoutResult, restoreLayoutConfigDecoder, saveLayoutConfigDecoder, saveRequestClientResponseDecoder, platformSaveRequestConfigDecoder, simpleLayoutConfigDecoder, simpleLayoutResultDecoder, simpleAvailabilityResultDecoder, permissionStateResultDecoder, setDefaultGlobalConfigDecoder } from \"../shared/decoders\";\r\nimport { BridgeOperation } from \"../shared/types\";\r\n\r\nexport type LayoutsOperationTypes = \"layoutAdded\" | \"layoutChanged\" | \"layoutRemoved\" |\r\n \"get\" | \"getAll\" | \"export\" | \"import\" | \"remove\" | \"save\" | \"restore\" | \"clientSaveRequest\" |\r\n \"getGlobalPermissionState\" | \"requestGlobalPermission\" | \"checkGlobalActivated\" | \"getDefaultGlobal\" | \"setDefaultGlobal\" | \"clearDefaultGlobal\";\r\n\r\nexport const operations: { [key in LayoutsOperationTypes]: BridgeOperation } = {\r\n layoutAdded: { name: \"layoutAdded\", dataDecoder: glueLayoutDecoder },\r\n layoutChanged: { name: \"layoutChanged\", dataDecoder: glueLayoutDecoder },\r\n layoutRemoved: { name: \"layoutRemoved\", dataDecoder: glueLayoutDecoder },\r\n get: { name: \"get\", dataDecoder: simpleLayoutConfigDecoder, resultDecoder: optionalSimpleLayoutResult },\r\n getAll: { name: \"getAll\", dataDecoder: getAllLayoutsConfigDecoder, resultDecoder: allLayoutsSummariesResultDecoder },\r\n export: { name: \"export\", dataDecoder: getAllLayoutsConfigDecoder, resultDecoder: allLayoutsFullConfigDecoder },\r\n import: { name: \"import\", dataDecoder: layoutsImportConfigDecoder },\r\n remove: { name: \"remove\", dataDecoder: simpleLayoutConfigDecoder },\r\n save: { name: \"save\", dataDecoder: saveLayoutConfigDecoder, resultDecoder: simpleLayoutResultDecoder },\r\n restore: { name: \"restore\", dataDecoder: restoreLayoutConfigDecoder },\r\n clientSaveRequest: { name: \"clientSaveRequest\", dataDecoder: platformSaveRequestConfigDecoder, resultDecoder: saveRequestClientResponseDecoder },\r\n getGlobalPermissionState: { name: \"getGlobalPermissionState\", resultDecoder: permissionStateResultDecoder },\r\n requestGlobalPermission: { name: \"requestGlobalPermission\", resultDecoder: simpleAvailabilityResultDecoder },\r\n checkGlobalActivated: { name: \"checkGlobalActivated\", resultDecoder: simpleAvailabilityResultDecoder },\r\n getDefaultGlobal: { name: \"getDefaultGlobal\", resultDecoder: optionalSimpleLayoutResult },\r\n setDefaultGlobal: { name: \"setDefaultGlobal\", dataDecoder: setDefaultGlobalConfigDecoder },\r\n clearDefaultGlobal: { name: \"clearDefaultGlobal\" }\r\n};\r\n\r\nexport interface SimpleLayoutConfig {\r\n name: string;\r\n type: IOConnectBrowser.Layouts.LayoutType;\r\n}\r\n\r\nexport interface SaveLayoutConfig {\r\n layout: IOConnectBrowser.Layouts.NewLayoutOptions;\r\n}\r\n\r\nexport interface RestoreLayoutConfig {\r\n layout: IOConnectBrowser.Layouts.RestoreOptions;\r\n}\r\n\r\nexport interface GetAllLayoutsConfig {\r\n type: IOConnectBrowser.Layouts.LayoutType;\r\n}\r\n\r\nexport interface LayoutsImportConfig {\r\n layouts: IOConnectBrowser.Layouts.Layout[];\r\n mode: \"replace\" | \"merge\";\r\n isManagerOperation?: boolean;\r\n}\r\n\r\nexport interface AllLayoutsFullConfig {\r\n layouts: IOConnectBrowser.Layouts.Layout[];\r\n}\r\n\r\nexport interface AllLayoutsSummariesResult {\r\n summaries: IOConnectBrowser.Layouts.LayoutSummary[];\r\n}\r\n\r\nexport interface SimpleLayoutResult {\r\n layout: IOConnectBrowser.Layouts.Layout;\r\n}\r\n\r\nexport interface OptionalSimpleLayoutResult {\r\n layout?: IOConnectBrowser.Layouts.Layout;\r\n}\r\n\r\nexport interface LayoutParseResult {\r\n valid: IOConnectBrowser.Layouts.Layout[];\r\n}\r\n\r\nexport interface PlatformSaveRequestConfig {\r\n layoutType: \"Global\" | \"Workspace\";\r\n layoutName: string;\r\n context?: any;\r\n}\r\n\r\nexport interface SaveRequestClientResponse {\r\n windowContext?: any;\r\n}\r\n\r\nexport interface PermissionStateResult {\r\n state: \"prompt\" | \"granted\" | \"denied\";\r\n}\r\n\r\nexport interface SimpleAvailabilityResult {\r\n isAvailable: boolean;\r\n}\r\n\r\nexport interface SetDefaultGlobalConfig {\r\n name: string;\r\n}","/* eslint-disable @typescript-eslint/no-explicit-any */\r\nimport { IOConnectCore } from \"@interopio/core\";\r\nimport { IoC } from \"../shared/ioc\";\r\nimport { LibController } from \"../shared/types\";\r\nimport {\r\n default as CallbackRegistryFactory,\r\n CallbackRegistry,\r\n UnsubscribeFunction,\r\n} from \"callback-registry\";\r\nimport { IOConnectBrowser } from \"../../browser\";\r\nimport { GlueBridge } from \"../communication/bridge\";\r\nimport { glueLayoutDecoder, importModeDecoder, layoutsOperationTypesDecoder, layoutTypeDecoder, newLayoutOptionsDecoder, nonEmptyStringDecoder, restoreOptionsDecoder } from \"../shared/decoders\";\r\nimport { AllLayoutsFullConfig, AllLayoutsSummariesResult, GetAllLayoutsConfig, LayoutParseResult, LayoutsImportConfig, operations, OptionalSimpleLayoutResult, RestoreLayoutConfig, SaveLayoutConfig, SaveRequestClientResponse, PlatformSaveRequestConfig, SimpleLayoutConfig, SimpleLayoutResult, PermissionStateResult, SimpleAvailabilityResult, SetDefaultGlobalConfig } from \"./protocol\";\r\nimport { WindowsController } from \"../windows/controller\";\r\n\r\nexport class LayoutsController implements LibController {\r\n private readonly defaultLayoutRestoreTimeoutMS = 120000;\r\n private readonly registry: CallbackRegistry = CallbackRegistryFactory();\r\n private bridge!: GlueBridge;\r\n private logger!: IOConnectBrowser.Logger.API;\r\n private windowsController!: WindowsController;\r\n private saveRequestSubscription?: (info?: IOConnectBrowser.Layouts.SaveRequestContext) => IOConnectBrowser.Layouts.SaveRequestResponse;\r\n\r\n public handlePlatformShutdown(): void {\r\n this.registry.clear();\r\n }\r\n\r\n public async start(coreGlue: IOConnectCore.API, ioc: IoC): Promise {\r\n this.logger = coreGlue.logger.subLogger(\"layouts.controller.web\");\r\n\r\n this.logger.trace(\"starting the web layouts controller\");\r\n\r\n this.bridge = ioc.bridge;\r\n\r\n this.windowsController = ioc.windowsController;\r\n\r\n this.addOperationsExecutors();\r\n\r\n const api = this.toApi();\r\n\r\n this.logger.trace(\"no need for platform registration, attaching the layouts property to glue and returning\");\r\n\r\n (coreGlue as IOConnectBrowser.API).layouts = api;\r\n }\r\n\r\n public async handleBridgeMessage(args: any): Promise {\r\n const operationName = layoutsOperationTypesDecoder.runWithException(args.operation);\r\n\r\n const operation = operations[operationName];\r\n\r\n if (!operation.execute) {\r\n return;\r\n }\r\n\r\n let operationData: any = args.data;\r\n\r\n if (operation.dataDecoder) {\r\n operationData = operation.dataDecoder.runWithException(args.data);\r\n }\r\n\r\n return await operation.execute(operationData);\r\n }\r\n\r\n private toApi(): IOConnectBrowser.Layouts.API {\r\n const api: IOConnectBrowser.Layouts.API = {\r\n get: this.get.bind(this),\r\n getAll: this.getAll.bind(this),\r\n export: this.export.bind(this),\r\n import: this.import.bind(this),\r\n save: this.save.bind(this),\r\n restore: this.restore.bind(this),\r\n remove: this.remove.bind(this),\r\n onAdded: this.onAdded.bind(this),\r\n onChanged: this.onChanged.bind(this),\r\n onRemoved: this.onRemoved.bind(this),\r\n onSaveRequested: this.subscribeOnSaveRequested.bind(this),\r\n getMultiScreenPermissionState: this.getGlobalPermissionState.bind(this),\r\n requestMultiScreenPermission: this.requestGlobalPermission.bind(this),\r\n getGlobalTypeState: this.checkGlobalActivated.bind(this),\r\n getDefaultGlobal: this.getDefaultGlobal.bind(this),\r\n setDefaultGlobal: this.setDefaultGlobal.bind(this),\r\n clearDefaultGlobal: this.clearDefaultGlobal.bind(this)\r\n };\r\n\r\n return Object.freeze(api);\r\n }\r\n\r\n private addOperationsExecutors(): void {\r\n operations.layoutAdded.execute = this.handleOnAdded.bind(this);\r\n operations.layoutChanged.execute = this.handleOnChanged.bind(this);\r\n operations.layoutRemoved.execute = this.handleOnRemoved.bind(this);\r\n operations.clientSaveRequest.execute = this.handleSaveRequest.bind(this);\r\n }\r\n\r\n private async get(name: string, type: IOConnectBrowser.Layouts.LayoutType): Promise {\r\n nonEmptyStringDecoder.runWithException(name);\r\n layoutTypeDecoder.runWithException(type);\r\n\r\n const result = await this.bridge.send(\"layouts\", operations.get, { name, type });\r\n\r\n return result.layout;\r\n }\r\n\r\n private async getAll(type: IOConnectBrowser.Layouts.LayoutType): Promise