Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
36 changes: 35 additions & 1 deletion src/components/utils/remoteUniverse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,46 @@ export const buildRemoteMetisResourceUri = (universeSlug: string, metisScope?: s
return `${normalizedBaseUrl}/api/remote-universe/${encodeURIComponent(universeSlug)}/metis${scopePath}`;
};

export const buildRemoteMetisProxyPath = (universeSlug: string, metisScope?: string, baseUrl?: string) => {
export type RemoteMetisFocusQuery = {
currentMetamodelRef?: string;
currentModelRef?: string;
currentModelviewRef?: string;
currentTargetMetamodelRef?: string;
currentTargetModelRef?: string;
currentTargetModelviewRef?: string;
modelScope?: string;
revision?: string;
};

const appendRemoteMetisFocusQuery = (query: URLSearchParams, focusQuery?: RemoteMetisFocusQuery) => {
if (!focusQuery) return;
([
"currentMetamodelRef",
"currentModelRef",
"currentModelviewRef",
"currentTargetMetamodelRef",
"currentTargetModelRef",
"currentTargetModelviewRef",
"modelScope",
"revision",
] as const).forEach(key => {
const value = focusQuery[key];
if (typeof value === "string" && value.trim()) query.set(key, value.trim());
});
};

export const buildRemoteMetisProxyPath = (
universeSlug: string,
metisScope?: string,
baseUrl?: string,
focusQuery?: RemoteMetisFocusQuery,
) => {
const query = new URLSearchParams();
query.set("baseUrl", normalizeRemoteUniverseBaseUrl(baseUrl));
if (metisScope) {
query.set("scope", metisScope);
}
appendRemoteMetisFocusQuery(query, focusQuery);
return `/api/remote-universe/${encodeURIComponent(universeSlug)}/metis?${query.toString()}`;
};

Expand Down
20 changes: 19 additions & 1 deletion src/pages/api/remote-universe/[universeSlug]/metis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,24 @@ const readRawBaseUrl = (req: NextApiRequest) => {
return typeof bodyValue === 'string' ? bodyValue : readSingleQueryValue(queryValue);
};

const buildScopedRemoteMetisUri = (req: NextApiRequest, universeSlug: string, scope: string, baseUrl: string) => {
const url = new URL(buildRemoteMetisResourceUri(universeSlug, scope, baseUrl));
[
'currentMetamodelRef',
'currentModelRef',
'currentModelviewRef',
'currentTargetMetamodelRef',
'currentTargetModelRef',
'currentTargetModelviewRef',
'modelScope',
'revision',
].forEach((key) => {
const value = readSingleQueryValue(req.query[key]);
if (value) url.searchParams.set(key, value);
});
return url.toString();
};

const asRecord = (value: any) => (value && typeof value === 'object' ? value : {});

const isMetisRecord = (value: any) => {
Expand Down Expand Up @@ -115,7 +133,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
try {
const baseUrl = readBaseUrl(req);
const scope = readSingleQueryValue(req.query.scope);
const response = await fetch(buildRemoteMetisResourceUri(universeSlug, scope, baseUrl));
const response = await fetch(buildScopedRemoteMetisUri(req, universeSlug, scope, baseUrl));
const { payload, text } = await readRemoteJsonLike(response);

if (!response.ok || !payload) {
Expand Down
62 changes: 54 additions & 8 deletions src/pages/model.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@ import { searchGithub } from '../components/githubServices/githubService';
import { InitialState } from '../reducers/reducer';
import { normalizeGithubSource, readShareQueryValue } from '../components/utils/focusShare';
import { readJsonResponse, readJsonResponseError } from '../components/utils/httpResponse';
import { buildRemoteMetisProxyPath, buildRemoteMetisResourceUri, normalizeRemoteUniverseBaseUrl, readRemoteUniverseId, readRemoteUniverseSlug } from '../components/utils/remoteUniverse';
import {
buildRemoteMetisProxyPath,
buildRemoteMetisResourceUri,
normalizeRemoteUniverseBaseUrl,
readRemoteUniverseId,
readRemoteUniverseSlug,
type RemoteMetisFocusQuery,
} from '../components/utils/remoteUniverse';
import { buildMimrisStateFromWorkspaceSnapshot, getWorkspaceSnapshotMeta, isWorkspaceUniverseSnapshot } from '../components/utils/workspaceUniverseAdapter';
import { saveRemoteUniverseProject } from '../components/utils/remoteUniverseProject';
import { describeMetisAvailability, normalizeMetisScope, setActiveMetisScope } from '../components/utils/workspaceMetisResolver.js';
Expand Down Expand Up @@ -86,7 +93,30 @@ const page = (props: any) => {
return '';
}
};
const buildModelRoute = (options: { universeId?: string; universeSlug?: string; baseUrl?: string; metisScope?: string }) => {
const hasRequestedRemoteMetisFocus = (focusQuery?: RemoteMetisFocusQuery) =>
Boolean(
focusQuery?.modelScope === 'current' ||
focusQuery?.currentModelRef ||
focusQuery?.currentModelviewRef ||
focusQuery?.currentMetamodelRef,
);
Comment on lines +96 to +102
const appendRemoteMetisFocusRouteParams = (params: URLSearchParams, focusQuery?: RemoteMetisFocusQuery) => {
if (!focusQuery) return;
([
'currentMetamodelRef',
'currentModelRef',
'currentModelviewRef',
'currentTargetMetamodelRef',
'currentTargetModelRef',
'currentTargetModelviewRef',
'modelScope',
'revision',
] as const).forEach(key => {
const value = focusQuery[key];
if (typeof value === 'string' && value.trim()) params.set(key, value.trim());
});
};
const buildModelRoute = (options: { universeId?: string; universeSlug?: string; baseUrl?: string; metisScope?: string; focusQuery?: RemoteMetisFocusQuery }) => {
const params = new URLSearchParams();
const normalizedBaseUrl = options.baseUrl ? normalizeRemoteUniverseBaseUrl(options.baseUrl) : '';
if (options.universeId) {
Expand All @@ -100,15 +130,17 @@ const page = (props: any) => {
if (options.metisScope) {
params.set('metisScope', normalizeMetisScope(options.metisScope));
}
appendRemoteMetisFocusRouteParams(params, options.focusQuery);
return `/model?${params.toString()}`;
};
const updateModelRoute = (options: { universeId?: string; universeSlug?: string; baseUrl?: string; metisScope?: string }) => {
const updateModelRoute = (options: { universeId?: string; universeSlug?: string; baseUrl?: string; metisScope?: string; focusQuery?: RemoteMetisFocusQuery }) => {
const nextRoute = buildModelRoute(options);
const currentPath = typeof window !== 'undefined' ? `${window.location.pathname}${window.location.search}` : router.asPath;
if (currentPath === nextRoute) return;
router.replace(nextRoute, undefined, { shallow: true, scroll: false });
};
Comment on lines +136 to 141
const loadLocalMemoryState = () => {
const loadLocalMemoryState = (focusQuery?: RemoteMetisFocusQuery) => {
if (hasRequestedRemoteMetisFocus(focusQuery)) return false;
try {
const stored = window.localStorage.getItem('memorystate');
const parsed = stored ? JSON.parse(stored) : null;
Expand Down Expand Up @@ -207,9 +239,9 @@ const page = (props: any) => {
return '';
}
};
const loadExplicitRemoteMetisScope = async (options: { universeSlug: string; universeId?: string; baseUrl: string; metisScope: string }) => {
const loadExplicitRemoteMetisScope = async (options: { universeSlug: string; universeId?: string; baseUrl: string; metisScope: string; focusQuery?: RemoteMetisFocusQuery }) => {
const remoteUri = buildRemoteMetisResourceUri(options.universeSlug, options.metisScope, options.baseUrl);
const response = await fetch(buildRemoteMetisProxyPath(options.universeSlug, options.metisScope, options.baseUrl));
const response = await fetch(buildRemoteMetisProxyPath(options.universeSlug, options.metisScope, options.baseUrl, options.focusQuery));
const { payload, text } = await readJsonResponse(response);
if (!response.ok || payload?.error || !payload?.payload) {
try {
Expand Down Expand Up @@ -239,6 +271,7 @@ const page = (props: any) => {
universeSlug: options.universeSlug,
baseUrl: options.baseUrl,
metisScope: options.metisScope,
focusQuery: options.focusQuery,
});
dispatch({
type: 'SET_FOCUS_REFRESH',
Expand Down Expand Up @@ -288,6 +321,7 @@ const page = (props: any) => {
universeSlug: options.universeSlug,
baseUrl: options.baseUrl,
metisScope: options.metisScope,
focusQuery: options.focusQuery,
});
dispatch({
type: 'SET_FOCUS_REFRESH',
Expand Down Expand Up @@ -418,6 +452,16 @@ const page = (props: any) => {
const universeSlug = readShareQueryValue(query.universeSlug);
const universeApi = readShareQueryValue(query.universeApi);
const requestedMetisScope = normalizeMetisScope(readShareQueryValue(query.metisScope));
const focusQuery: RemoteMetisFocusQuery = {
currentMetamodelRef: readShareQueryValue(query.currentMetamodelRef),
currentModelRef: readShareQueryValue(query.currentModelRef),
currentModelviewRef: readShareQueryValue(query.currentModelviewRef),
currentTargetMetamodelRef: readShareQueryValue(query.currentTargetMetamodelRef),
currentTargetModelRef: readShareQueryValue(query.currentTargetModelRef),
currentTargetModelviewRef: readShareQueryValue(query.currentTargetModelviewRef),
modelScope: readShareQueryValue(query.modelScope),
revision: readShareQueryValue(query.revision),
};
const projectId = readShareQueryValue(query.project);
const org = readShareQueryValue(query.org);
const repo = readShareQueryValue(query.repo);
Expand Down Expand Up @@ -454,6 +498,7 @@ const page = (props: any) => {
universeId,
baseUrl,
metisScope: requestedMetisScope,
focusQuery,
});
setIsLoading(false);
return;
Expand Down Expand Up @@ -484,6 +529,7 @@ const page = (props: any) => {
universeId: resolvedId,
baseUrl,
metisScope: requestedMetisScope,
focusQuery,
});
} catch (error: any) {
console.error('Error loading remote universe library entry:', error);
Expand Down Expand Up @@ -534,15 +580,15 @@ const page = (props: any) => {
dispatchLoadedState(nextData);
} catch (error: any) {
console.error('Error loading shared model:', error);
if (!loadLocalMemoryState()) {
if (!loadLocalMemoryState(focusQuery)) {
setLoadError(error?.message || 'Unable to load shared model file.');
}
}
setIsLoading(false);
return;
}

const hasLocalState = loadLocalMemoryState();
const hasLocalState = loadLocalMemoryState(focusQuery);
if (!hasLocalState) {
setLoadError('Unable to load shared model file.');
}
Expand Down