Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: webserver: fusion apps service migration #806

Merged
merged 51 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
0269357
Implement catch-all proxy for new Fusion Apps service
kjetilhau Sep 26, 2024
94da947
.
kjetilhau Sep 26, 2024
0890beb
Update radixconfig
kjetilhau Sep 26, 2024
ba7856c
Merge branch 'main' into feature/fusion-apps-service-migration
kjetilhau Sep 26, 2024
4b3487a
.
kjetilhau Sep 26, 2024
c0875bb
Remove unused portalConfig elements for frontend
kjetilhau Sep 27, 2024
3dbc90b
Clean up and remove unused code
kjetilhau Sep 27, 2024
154dd29
Merge branch 'main' into feature/fusion-apps-service-migration
kjetilhau Sep 30, 2024
6523dde
Add proxy route constants
kjetilhau Sep 30, 2024
b688b94
Remove unused httpClient
kjetilhau Sep 30, 2024
0e682bd
Update packages
kjetilhau Sep 30, 2024
00e8f7f
chore: create pr-806-2098564848.md
kjetilhau Sep 30, 2024
642e2e7
Add initial cors config
kjetilhau Oct 1, 2024
cc45b27
.
kjetilhau Oct 1, 2024
a3c64d6
Los order muy importante
kjetilhau Oct 1, 2024
1ca13a3
feat: new apps loading form new app service
Noggling Oct 3, 2024
0cbfd8d
chore: move legacy app loader and fix loading
Noggling Oct 3, 2024
663b0aa
chore: update use-app-loader to fit new app loader
Noggling Oct 3, 2024
e67559d
core: build legacy app loader in docker on publish
Noggling Oct 3, 2024
2f00a1d
fix: docker and pkg build form right directory
Noggling Oct 3, 2024
9cf817f
chore: move app loader
Noggling Oct 3, 2024
c07c716
Add .gitignore to legacyAppLoader
Noggling Oct 3, 2024
bc70038
merge from main
kjetilhau Oct 8, 2024
7e0f184
Remove CORS config again
kjetilhau Oct 8, 2024
3eb5cd4
feat:app loading
Noggling Oct 14, 2024
b28ec81
refactor: move legacyAppLoader files and configurations
Noggling Oct 14, 2024
af7bb96
Refactor Dockerfile to separate app loading and legacyAppLoader builds
Noggling Oct 14, 2024
348def9
Merge branch 'feature/fusion-apps-service-migration' of https://githu…
kjetilhau Oct 15, 2024
edd42dc
Refactor app loading configuration and mocks
Noggling Oct 15, 2024
01e46b7
Refactor legacyAppLoader and use-legacy-app-loader hooks
Noggling Oct 15, 2024
bf9daae
Refactor package.json dependencies for legacyAppLoader and client
Noggling Oct 15, 2024
4a3088a
Refactor package.json dependencies for legacyAppLoader and client
Noggling Oct 15, 2024
72edbb2
Ignore specific vulnerabilities related to appKey configuration in ap…
Noggling Oct 15, 2024
96edbd0
Refactor app loading configuration and mocks
Noggling Oct 15, 2024
b709d24
Refactor .snyk to ignore hard-coded appKey in app.config.ts
Noggling Oct 15, 2024
257be58
Refactor .snyk to ignore hard-coded appKey in app.config.ts
Noggling Oct 15, 2024
234def0
Refactor .snyk to ignore hard-coded appKey in app.config.ts
Noggling Oct 15, 2024
4bfb8f4
Refactor document title in main.tsx
Noggling Oct 15, 2024
503f943
Merge branch 'main' into feature/fusion-apps-service-migration
Noggling Oct 15, 2024
d5abfc2
Refactor .snyk to remove hard-coded appKey in app.config.ts
Noggling Oct 15, 2024
06457dd
Refactor .snyk to ignore hard-coded appKey in app.config.ts
Noggling Oct 16, 2024
61b1235
Fix appSettings typo
kjetilhau Oct 16, 2024
6653c89
Merge branch 'feature/fusion-apps-service-migration' of https://githu…
kjetilhau Oct 16, 2024
0bab744
chore: revert to use key for now sins we are not hooked up tp new api…
Noggling Oct 16, 2024
b3ba68c
chore: Refactor useAppLoader to remove unused code
Noggling Oct 16, 2024
eef4909
Refactor useAppLoader to remove unused code
Noggling Oct 16, 2024
6c2c255
Merge branch 'main' into feature/fusion-apps-service-migration
Noggling Oct 16, 2024
8dbe5a5
chore: fix is pinned typing
Noggling Oct 16, 2024
865dcce
core: Refactor useFavorites to handle null values in app key
Noggling Oct 16, 2024
5d14504
core: Refactor AllApps component to remove console.log statement and …
Noggling Oct 16, 2024
62bd9c7
chore: update pr-806-2098564848.md
Noggling Oct 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .changeset/pr-806-2098564848.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

---
"fusion-project-portal": major
---
- BREAKING CHANGE: The previous proxy endpoint: `/bundles/apps/{appKey}/resources/{*resourcePath}` is no more. Instead use `/fusion-apps/{*wildcard*}` to make proxy calls against the whole Fusion Apps API. See Fusion Apps API Swagger documentation for more information about routes.
- Migrated proxy from Fusion Portal to Fusion Apps API
- Updated packages to latest version
- Refactored and simplified code
- Removed unused Project Portal variables in frontend
- Update frontend to use the new proxy endpoints
- Make frontend client use the new types provided by fusion core
- Update the legacy app loader to use the new proxy endpoints and and fix types
- Move legacy app code to apps folder for cleaner repository
- Setup build of legacy app loader in build pipeline for constant build an deployment.
- Update all Fusion dependencies for frontend client
7 changes: 0 additions & 7 deletions .snyk

This file was deleted.

2 changes: 2 additions & 0 deletions client/apps/legacyAppLoader/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

node_modules
File renamed without changes.
24 changes: 24 additions & 0 deletions client/apps/legacyAppLoader/app.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { mergeAppConfigs, defineAppConfig } from '@equinor/fusion-framework-cli';
export default defineAppConfig((_env, { base }) =>
mergeAppConfigs(
{},
{
environment: {
endpoints: {
client: {
baseUri: 'https://backend-fusion-project-portal-test.radix.equinor.com',
defaultScopes: ['api://02f3484c-cad0-4d1d-853d-3a9e604b38f3/access_as_user'],
},
portal: {
baseUri: 'https://fusion-s-portal-ci.azurewebsites.net',
defaultScopes: ['5a842df8-3238-415d-b168-9f16a6a6031b/.default'],
},
},
fusionEnv: 'ci',
loadingText: 'Loading',
appKey: 'handover-garden',
basename: 'localhost:3000/apps/handover-garden/',
},
}
)
);
7 changes: 7 additions & 0 deletions client/apps/legacyAppLoader/app.manifest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { defineAppManifest, mergeManifests } from '@equinor/fusion-framework-cli';

export default defineAppManifest((env, { base }) => {
return mergeManifests(base, {
name: 'App-loader',
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,28 @@
"type": "module",
"main": "src/index.ts",
"scripts": {
"prebuild": "rm -f ../client/packages/portal-client/src/assets/appLegacyLoader.js",
"build": "fusion-framework-cli app build && mv ./dist/app-bundle.js ../client/packages/portal-client/src/assets/appLegacyLoader.js",
"prebuild": "rm -f ../../packages/portal-client/src/assets/appLegacyLoader.js",
"build:appLoader": "fusion-framework-cli app build && mv ./dist/app-bundle.js ../../packages/portal-client/src/assets/appLegacyLoader.js",
"build:resources": "tsc && vite build",
"dev": "fusion-framework-cli app dev -c vite.config.js",
"dev:appLoader": "fusion-framework-cli app dev -c vite.config.js",
"docker": "cd .. && sh docker-script.sh app-react",
"update:fusion": "ncu -i -f /fusion/"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@equinor/fusion": "^3.4.13",
"@equinor/eds-core-react": "^0.42.0",
"@equinor/fusion": "^3.4.16",
"@equinor/fusion-components": "^2.12.0",
"@equinor/fusion-framework-cli": "^7.0.12",
"@equinor/fusion-framework-module-http": "^5.1.1",
"@equinor/fusion-framework-module-navigation": "^3.0.6",
"@equinor/fusion-framework-react": "^5.3.2",
"@equinor/fusion-framework-react-app": "^4.1.9",
"@equinor/fusion-observable": "^8.1.2",
"@equinor/fusion-react-styles": "^0.5.11",
"@equinor/fusion-framework-app": "^9.1.10",
"@equinor/fusion-framework-module-app": "^6.0.0",
"@equinor/fusion-framework-module-http": "^6.2.0",
"@equinor/fusion-framework-module-navigation": "^4.0.7",
"@equinor/fusion-framework-react": "^7.3.0",
"@equinor/fusion-framework-react-app": "^5.2.10",
"@equinor/fusion-observable": "^8.4.1",
"@equinor/fusion-react-styles": "^0.6.2",
"@types/react": "^17.0.70",
"@types/react-dom": "^17.0.25",
"react": "^17.0.1",
Expand All @@ -39,6 +41,7 @@
"vite-tsconfig-paths": "^4.2.0"
},
"devDependencies": {
"@equinor/fusion-framework-cli": "^10.0.0",
"@types/react-router-dom": "^5.3.3",
"vite-plugin-static-copy": "^0.17.0"
}
Expand Down
57 changes: 57 additions & 0 deletions client/apps/legacyAppLoader/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { NavigationModule } from '@equinor/fusion-framework-module-navigation';
import { LegacyFusionWrapper } from './app-loader';
import { AppModuleLoader } from './app-loader/components/AppModuleLoader';

import { AppModule } from '@equinor/fusion-framework-module-app';
import { Fusion, useFramework } from '@equinor/fusion-framework-react';

import { ComponentRenderArgs, makeComponent, useAppModules } from '@equinor/fusion-framework-react-app';

import { ProgressLoader } from './app-loader/components/ProgressLoader';

import { addGlobalDependencies } from './globalResources';
import { Suspense, createElement } from 'react';
import configure from './config';

addGlobalDependencies();

export const App = (props: {
fusion: Fusion;
env: {
config: {
environment: { appKey: string; fusionEnv: string; loadingText?: string };
};
};
}) => {
const fusion = useFramework<[AppModule, NavigationModule]>();
const appFramework = useAppModules<[AppModule]>();
return (
<LegacyFusionWrapper
framework={fusion}
options={{
loadBundlesFromDisk: false,
environment: {
env: props.env.config.environment.fusionEnv,
},
}}
loader={<ProgressLoader title={props.env.config.environment.loadingText || 'Loading'} />}
appFramework={appFramework}
>
<AppModuleLoader appKey={props.env?.config.environment.appKey} />
</LegacyFusionWrapper>
);
};

const appComponent = (args: any) => createElement(App, args);

/** create React render root component */
export const createApp = (args: ComponentRenderArgs) => makeComponent(appComponent(args), args, configure as any);

export const AppComponent = (args: ComponentRenderArgs) => {
const AppComponent = createApp(args);
return (
<Suspense fallback={<></>}>
<AppComponent />
</Suspense>
);
};
61 changes: 61 additions & 0 deletions client/apps/legacyAppLoader/src/app-loader/components/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { NavigationModule } from '@equinor/fusion-framework-module-navigation';
import { LegacyFusionWrapper } from './app-loader';
import { AppModuleLoader } from './app-loader/components/AppModuleLoader';

import { AppModule } from '@equinor/fusion-framework-module-app';
import { Fusion, useFramework } from '@equinor/fusion-framework-react';

import { ComponentRenderArgs, makeComponent, useAppModules } from '@equinor/fusion-framework-react-app';

import { ProgressLoader } from './app-loader/components/ProgressLoader';

import { addGlobalDependencies } from './globalResources';
import { Suspense, createElement } from 'react';
import configure from './config';

addGlobalDependencies();

export const App = (props: {
fusion: Fusion;
env: {
config: {
environment: { appKey: string; env: string; loadingText?: string };
};
};
}) => {
const fusion = useFramework<[AppModule, NavigationModule]>();
const appFramework = useAppModules<[AppModule]>();

return (
<LegacyFusionWrapper
framework={fusion}
options={{
loadBundlesFromDisk: false,
environment: {
env: props.env.config.environment.env,
},
}}
loader={<ProgressLoader title={props.env.config.environment.loadingText || 'Loading'} />}
appFramework={appFramework}
>
<AppModuleLoader appKey={props.env?.config.environment.appKey} />
</LegacyFusionWrapper>
);
};

const appComponent = (args: any) => createElement(App, args);

/** create React render root component */
export const createApp = (args: ComponentRenderArgs) => {
return makeComponent(appComponent(args), args, configure as any);
};

export const AppComponent = (args: ComponentRenderArgs) => {
const AppComponent = createApp(args);
return 'hello';
return (
<Suspense fallback={<></>}>
<AppComponent />
</Suspense>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { lazy } from 'react';
import AppWrapperLegacy, { getLegacyFusion } from './LegacyAppWrapper';

import { AppConfig } from '@equinor/fusion-framework-module-app';
import { AppManifest as LegacyAppManifest } from '@equinor/fusion';

import LegacyAppContainer from '../legacy-interopt/LegacyAppContainer';
import { MessagePage } from './MessagePage';
export type LegacyEnv = {
basename: string;
config: AppConfig;
manifest: LegacyAppManifest;
};

export const createLegacyAppLoader = (appKey: string) =>
lazy(async () => {
const appContainer = getLegacyFusion().app.container as LegacyAppContainer;
const [basename] = window.location.pathname.match(/\/?apps\/[a-z|-]+\//) ?? [''];

if (Object.keys(appContainer.allApps).length === 0) {
await appContainer.getAllAsync();
}

const config = await appContainer.setCurrentAppAsync(appKey);

if (!config) {
return {
default: () => <MessagePage type="Warning" title="No config" />,
};
}

const env = {
basename,
config,
manifest: { ...appContainer.currentApp } as LegacyAppManifest,
};

return {
default: () => (
<>
<AppWrapperLegacy appKey={appKey} env={env} />
</>
),
};
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Suspense, useMemo } from 'react';

import { useFramework } from '@equinor/fusion-framework-react';

import { GLOBAL_FUSION_CONTEXT_KEY } from '../legacy-interopt/static';
import { createLegacyRender } from '../legacy-interopt';

import { MessagePage } from './MessagePage';
import { ProgressLoader } from './ProgressLoader';

import { LegacyEnv } from './LegacyAppLoader';

const DEBUG_LOG = false;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
export const getLegacyFusion = () => window[GLOBAL_FUSION_CONTEXT_KEY];
/**
* Legacy wrapper element
* this should be removed in future when applications are moved over to ESM
*/

export const AppWrapperLegacy = (props: { appKey: string; env: LegacyEnv }): JSX.Element => {
const { appKey, env } = props;
const fusion = useFramework();
const legacyFusion = getLegacyFusion();
const manifest = getLegacyFusion().app.container.get(appKey) || null;

const AppComponent = useMemo(() => {
if (!manifest) {
console.warn('🌍❗️ Portal Legacy:', 'missing application manifest');
return null;
}

/** sanity check if the `registerApp` has been loaded */
if (!manifest.render && !manifest.AppComponent) {
DEBUG_LOG &&
console.warn('🌍❗️ Portal Legacy:', 'no render or component, make sure app script is loading');
return null;
}

DEBUG_LOG && console.debug('🌍 Portal:', 'creating application component', manifest);

const render = manifest.render ?? createLegacyRender(manifest, legacyFusion);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return render(fusion, env);
}, [fusion, legacyFusion, manifest, env]);

if (!AppComponent) {
return (
<MessagePage title="Loader Error">
<p>Failed to render application, missing app component</p>
</MessagePage>
);
}
return (
<Suspense fallback={<ProgressLoader title="Loading" />}>
<AppComponent />
</Suspense>
);
};

export default AppWrapperLegacy;
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useFramework } from '@equinor/fusion-framework-react';
import { PropsWithChildren } from 'react';

import { AppModule } from '@equinor/fusion-framework-module-app';
import { NavigationModule } from '@equinor/fusion-framework-module-navigation';
import { LegacyFusionWrapper } from '../legacy-interopt/components';
import { useAppModules } from '@equinor/fusion-framework-react-app';
import { ProgressLoader } from './ProgressLoader';

export const LegacyWrapper = ({ children }: PropsWithChildren<unknown>) => {
const framework = useFramework<[AppModule, NavigationModule]>();
const appFramework = useAppModules<[AppModule]>();

return (
<LegacyFusionWrapper
framework={framework}
loader={<ProgressLoader title="Loading" />}
appFramework={appFramework}
>
{children}
</LegacyFusionWrapper>
);
};
Loading