diff --git a/services/user/CommonSys/common/messaging/index.ts b/services/user/CommonSys/common/messaging/index.ts index b073bfb96..76f5bbfab 100644 --- a/services/user/CommonSys/common/messaging/index.ts +++ b/services/user/CommonSys/common/messaging/index.ts @@ -25,3 +25,8 @@ export { buildFunctionCallResponse, } from "./supervisor/FunctionCallResponse"; export { generateRandomString } from "./generateRandomString"; +export { + type PreLoadServicesRequest, + buildPreLoadServicesRequest, + isPreLoadServicesRequest, +} from "./supervisor/PreLoadServicesRequest"; diff --git a/services/user/CommonSys/common/messaging/supervisor.ts b/services/user/CommonSys/common/messaging/supervisor.ts index 12d87cd56..7af54255a 100644 --- a/services/user/CommonSys/common/messaging/supervisor.ts +++ b/services/user/CommonSys/common/messaging/supervisor.ts @@ -1,4 +1,5 @@ import { generateRandomString } from "./generateRandomString"; +import { buildPreLoadServicesRequest } from "./supervisor/PreLoadServicesRequest"; import { isIFrameInitialized, isFunctionCallResponse, @@ -54,6 +55,8 @@ export class Supervisor { reject: (result: unknown) => void; }[] = []; + private onLoadPromise?: (value?: unknown) => void; + constructor(public options?: Options) { const supervisorSrc = options?.supervisorSrc || getSupervisorHref(); this.listenToRawMessages(); @@ -78,6 +81,9 @@ export class Supervisor { onSupervisorInitialized() { console.log("Supervisor successfully initialized. 🔥"); this.isSupervisorInitialized = true; + if (this.onLoadPromise) { + this.onLoadPromise(); + } } onFunctionCallResponse(response: FunctionCallResponse) { @@ -93,21 +99,24 @@ export class Supervisor { } } - functionCall(args: FunctionCallArgs) { + private getSupervisorIframe(): HTMLIFrameElement { if (!this.isSupervisorInitialized) throw new Error(`Supervisor is not initialized`); + const iframe = document.getElementById( + SupervisorIFrameId + ) as HTMLIFrameElement; + if (!iframe) throw new Error(`Failed to find supervisor-sys iframe`); + if (!iframe.contentWindow) + throw new Error(`Failed to access iframe contentWindow`); + return iframe; + } + + functionCall(args: FunctionCallArgs) { const id = generateId(); - console.log(this.pendingRequests, "pending requests."); + const iframe = this.getSupervisorIframe(); return new Promise((resolve, reject) => { this.pendingRequests.push({ id, resolve, reject }); - const iframe = document.getElementById( - SupervisorIFrameId - ) as HTMLIFrameElement; - if (!iframe) - throw new Error(`Failed to find supervisor-sys iframe`); - if (!iframe.contentWindow) - throw new Error(`Failed to access iframe contentWindow`); const message: FunctionCallRequest = { type: "FUNCTION_CALL_REQUEST", payload: { @@ -115,7 +124,28 @@ export class Supervisor { args, }, }; - iframe.contentWindow.postMessage(message, "*"); + if (iframe.contentWindow) { + iframe.contentWindow.postMessage(message, "*"); + } else { + reject("Failed to get supervisor iframe"); + } }); } + + public async onLoaded() { + if (this.isSupervisorInitialized) return; + return new Promise((resolve) => { + this.onLoadPromise = resolve; + }); + } + + preLoadServices(services: string[]) { + const message = buildPreLoadServicesRequest(services); + const iframe = this.getSupervisorIframe(); + if (!iframe.contentWindow) + throw new Error( + `Failed to get content window from supervisor iframe` + ); + iframe.contentWindow.postMessage(message, "*"); + } } diff --git a/services/user/CommonSys/common/messaging/supervisor/PreLoadServicesRequest.ts b/services/user/CommonSys/common/messaging/supervisor/PreLoadServicesRequest.ts new file mode 100644 index 000000000..85695e0c8 --- /dev/null +++ b/services/user/CommonSys/common/messaging/supervisor/PreLoadServicesRequest.ts @@ -0,0 +1,22 @@ +const PRE_LOAD_SERVICES_REQUEST = "PRE_LOAD_SERVICES_REQUEST" as const; + +export interface PreLoadServicesRequest { + type: typeof PRE_LOAD_SERVICES_REQUEST; + payload: { + services: string[]; + }; +} + +export const isPreLoadServicesRequest = ( + data: any +): data is PreLoadServicesRequest => + data && data.type == PRE_LOAD_SERVICES_REQUEST; + +export const buildPreLoadServicesRequest = ( + services: string[] +): PreLoadServicesRequest => ({ + type: PRE_LOAD_SERVICES_REQUEST, + payload: { + services, + }, +}); diff --git a/services/user/DemoApp1/ui/package.json b/services/user/DemoApp1/ui/package.json index 776b3c35c..63694220d 100644 --- a/services/user/DemoApp1/ui/package.json +++ b/services/user/DemoApp1/ui/package.json @@ -14,6 +14,7 @@ "react-dom": "^18.2.0" }, "devDependencies": { + "@types/node": "^20.11.19", "@types/react": "^18.2.43", "@types/react-dom": "^18.2.17", "@typescript-eslint/eslint-plugin": "^6.14.0", diff --git a/services/user/DemoApp1/ui/src/App.tsx b/services/user/DemoApp1/ui/src/App.tsx index 401623b44..6f32eb0a7 100644 --- a/services/user/DemoApp1/ui/src/App.tsx +++ b/services/user/DemoApp1/ui/src/App.tsx @@ -1,23 +1,32 @@ -import "./App.css"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { Supervisor } from "@messaging"; +import "./App.css"; + const supervisor = new Supervisor(); function App() { const [res, setRes] = useState("Empty"); + const init = async () => { + await supervisor.onLoaded(); + supervisor.preLoadServices(["demoapp2"]); + }; + + useEffect(() => { + init(); + }, []); + const run = async () => { console.info("DemoApp1 connected to Supervisor"); console.log("calling demoapp2.callintoplugin"); - const _res = await supervisor.functionCall({ + const res = await supervisor.functionCall({ service: "demoapp2", method: "callintoplugin", params: [], }); - console.log("demosapp2.callintoplugin() returned:", _res); setRes(res as string); }; diff --git a/services/user/DemoApp1/ui/tsconfig.json b/services/user/DemoApp1/ui/tsconfig.json index 967df01ef..11f203f48 100644 --- a/services/user/DemoApp1/ui/tsconfig.json +++ b/services/user/DemoApp1/ui/tsconfig.json @@ -2,11 +2,7 @@ "compilerOptions": { "target": "ES2020", "useDefineForClassFields": true, - "lib": [ - "ES2020", - "DOM", - "DOM.Iterable" - ], + "lib": ["ES2020", "DOM", "DOM.Iterable"], "module": "ESNext", "skipLibCheck": true, /* Bundler mode */ @@ -22,20 +18,14 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "paths": { - "@messaging": [ - "../../CommonSys/common/messaging" - ], - "/common": [ - "../../CommonSys/common" - ] - }, + "@messaging": ["../../CommonSys/common/messaging"], + "/common": ["../../CommonSys/common"] + } }, - "include": [ - "src" - ], + "include": ["./src"], "references": [ { "path": "./tsconfig.node.json" } ] -} \ No newline at end of file +} diff --git a/services/user/DemoApp1/ui/vite.config.ts b/services/user/DemoApp1/ui/vite.config.ts index a0e94bc48..8fe31cdb6 100644 --- a/services/user/DemoApp1/ui/vite.config.ts +++ b/services/user/DemoApp1/ui/vite.config.ts @@ -8,7 +8,7 @@ export default defineConfig({ resolve: { alias: { "@messaging": path.resolve( - "../../../user/CommonSys/common/messaging" + "../../CommonSys/common/messaging" ), }, }, diff --git a/services/user/DemoApp1/ui/yarn.lock b/services/user/DemoApp1/ui/yarn.lock index 2bdbb4186..e5b9c6d29 100644 --- a/services/user/DemoApp1/ui/yarn.lock +++ b/services/user/DemoApp1/ui/yarn.lock @@ -465,6 +465,13 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== +"@types/node@^20.11.19": + version "20.11.19" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.19.tgz#b466de054e9cb5b3831bee38938de64ac7f81195" + integrity sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ== + dependencies: + undici-types "~5.26.4" + "@types/prop-types@*": version "15.7.11" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.11.tgz#2596fb352ee96a1379c657734d4b913a613ad563" @@ -1523,6 +1530,11 @@ typescript@^5.2.2: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + update-browserslist-db@^1.0.13: version "1.0.13" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" diff --git a/services/user/PsiSpaceSys/ui/yarn.lock b/services/user/PsiSpaceSys/ui/yarn.lock index d9c0b0bc2..37c3fc203 100644 --- a/services/user/PsiSpaceSys/ui/yarn.lock +++ b/services/user/PsiSpaceSys/ui/yarn.lock @@ -492,20 +492,6 @@ dependencies: mini-svg-data-uri "^1.2.3" -"@types/bn.js@*": - version "5.1.5" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.5.tgz#2e0dacdcce2c0f16b905d20ff87aedbc6f7b4bf0" - integrity sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A== - dependencies: - "@types/node" "*" - -"@types/elliptic@^6.4.18": - version "6.4.18" - resolved "https://registry.yarnpkg.com/@types/elliptic/-/elliptic-6.4.18.tgz#bc96e26e1ccccbabe8b6f0e409c85898635482e1" - integrity sha512-UseG6H5vjRiNpQvrhy4VF/JXdA3V/Fp5amvveaL+fs28BZ6xIKJBPnUPRlEaZpysD9MbpfaLi8lbl7PGUAkpWw== - dependencies: - "@types/bn.js" "*" - "@types/estree@^1.0.0": version "1.0.5" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" @@ -521,13 +507,6 @@ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.4.tgz#2198ac274de6017b44d941e00261d5bc6a0e0a45" integrity sha512-iJt33IQnVRkqeqC7PzBHPTC6fDlRNRW8vjrgqtScAhrmMwe8c4Eo7+fUGTa+XdWrpEgpyKWMYmi2dIwMAYRzPw== -"@types/node@*": - version "20.11.17" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.17.tgz#cdd642d0e62ef3a861f88ddbc2b61e32578a9292" - integrity sha512-QmgQZGWu1Yw9TDyAP9ZzpFJKynYNeOvwMJmaxABfieQoVoiVOS6MN1WSpqpRcbeA5+RW82kraAVxCCJg+780Qw== - dependencies: - undici-types "~5.26.4" - "@types/node@^18.7.7": version "18.19.14" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.14.tgz#1880ff1b3ac913f3877f711588e5ed227da01886" @@ -763,11 +742,6 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== -bn.js@^4.11.9: - version "4.12.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" - integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -790,11 +764,6 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" -brorand@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== - browserslist@^4.22.2: version "4.22.3" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.3.tgz#299d11b7e947a6b843981392721169e27d60c5a6" @@ -1013,19 +982,6 @@ electron-to-chromium@^1.4.648: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.658.tgz#cfa99cb02539125ffba420f6715face7cbce1241" integrity sha512-LGkxndHz7OEv6ipmL95E83SOZmK96PHk6Njw0nf5UaOLbvPxxJhejlBWl4esuU6JHMiCjysLhKRQmLTd5s2ZPw== -elliptic@^6.5.4: - version "6.5.4" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== - dependencies: - bn.js "^4.11.9" - brorand "^1.1.0" - hash.js "^1.0.0" - hmac-drbg "^1.0.1" - inherits "^2.0.4" - minimalistic-assert "^1.0.1" - minimalistic-crypto-utils "^1.0.1" - emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -1667,14 +1623,6 @@ has-tostringtag@^1.0.0, has-tostringtag@^1.0.1: dependencies: has-symbols "^1.0.3" -hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - hasown@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" @@ -1682,15 +1630,6 @@ hasown@^2.0.0: dependencies: function-bind "^1.1.2" -hmac-drbg@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - ignore@^5.2.0: version "5.3.1" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" @@ -1722,7 +1661,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: +inherits@2, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -2058,16 +1997,6 @@ mini-svg-data-uri@^1.2.3: resolved "https://registry.yarnpkg.com/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz#8ab0aabcdf8c29ad5693ca595af19dd2ead09939" integrity sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg== -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== - minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" diff --git a/services/user/SupervisorSys/ui/src/main.ts b/services/user/SupervisorSys/ui/src/main.ts index a042b6e0e..980ef423e 100644 --- a/services/user/SupervisorSys/ui/src/main.ts +++ b/services/user/SupervisorSys/ui/src/main.ts @@ -11,6 +11,8 @@ import { generateRandomString, buildPluginCallRequest, buildFunctionCallResponse, + isPreLoadServicesRequest, + PreLoadServicesRequest, } from "@messaging"; document.querySelector("#app")!.innerHTML = ` @@ -216,6 +218,12 @@ const onPluginCallRequest = (message: PluginCallRequest) => { pendingFunctionCalls.forEach(addToPendingFunctionCall); }; +const onPreloadServicesRequest = ({ + payload, +}: PreLoadServicesRequest): void => { + payload.services.forEach(getLoader); +}; + const onRawEvent = (message: MessageEvent) => { if (isFunctionCallRequest(message.data)) { // TODO Assert origin of supervisor-sys @@ -226,6 +234,8 @@ const onRawEvent = (message: MessageEvent) => { } else if (isPluginCallRequest(message.data)) { // TODO Assert origin of plugin call request onPluginCallRequest(message.data); + } else if (isPreLoadServicesRequest(message.data)) { + onPreloadServicesRequest(message.data); } };