Add BIM legacy share transform fallback
This commit is contained in:
parent
c242e364bb
commit
1a78dd0dc8
113
server/index.js
113
server/index.js
|
|
@ -1946,6 +1946,79 @@ const normalizeViewerSettings = (value) => (
|
||||||
: null
|
: null
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const viewerSettingsHaveTransforms = (settings) => {
|
||||||
|
const transforms = settings?.viewerState?.transforms;
|
||||||
|
return !!(
|
||||||
|
transforms &&
|
||||||
|
typeof transforms === "object" &&
|
||||||
|
!Array.isArray(transforms) &&
|
||||||
|
Object.keys(transforms).length
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const modelRecordMatchesShare = (model, share) => {
|
||||||
|
const meta = model?.meta && typeof model.meta === "object" ? model.meta : {};
|
||||||
|
if (share?.assetId && meta.assetId === share.assetId) {
|
||||||
|
if (share.projectId && meta.projectId && meta.projectId !== share.projectId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (share.versionId && meta.versionId && meta.versionId !== share.versionId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const haystack = [
|
||||||
|
model?.src,
|
||||||
|
meta.sourceSrc,
|
||||||
|
meta.settingsSrc,
|
||||||
|
meta.artifactSrc
|
||||||
|
].filter(Boolean).join("\n");
|
||||||
|
if (!haystack || !share?.assetId || !haystack.includes(share.assetId)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !share.versionId || haystack.includes(share.versionId);
|
||||||
|
};
|
||||||
|
|
||||||
|
const readProjectViewerSettingsForShare = async (share) => {
|
||||||
|
if (!share?.assetId) return null;
|
||||||
|
let entries = [];
|
||||||
|
try {
|
||||||
|
entries = await fs.readdir(DATA_DIR, {withFileTypes: true});
|
||||||
|
} catch (_err) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let best = null;
|
||||||
|
for (const entry of entries) {
|
||||||
|
if (!entry.isFile() || !entry.name.endsWith(".json") || entry.name === "index.json") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const projectPath = path.join(DATA_DIR, entry.name);
|
||||||
|
const project = await readJSONFile(projectPath).catch(() => null);
|
||||||
|
if (!project || !Array.isArray(project.models)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!project.models.some((model) => modelRecordMatchesShare(model, share))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const settings = normalizeViewerSettings({
|
||||||
|
version: 1,
|
||||||
|
updatedAt: project.updatedAt || project.createdAt || nowIso(),
|
||||||
|
viewerState: project.viewerState || {},
|
||||||
|
design: project.design || null
|
||||||
|
});
|
||||||
|
if (!viewerSettingsHaveTransforms(settings)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const updatedAtMs = Date.parse(settings.updatedAt || "") || 0;
|
||||||
|
if (!best || updatedAtMs >= best.updatedAtMs) {
|
||||||
|
best = {settings, updatedAtMs};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return best?.settings || null;
|
||||||
|
};
|
||||||
|
|
||||||
const readViewerSettingsForModelSrc = async (src) => {
|
const readViewerSettingsForModelSrc = async (src) => {
|
||||||
const manifestRef = await findManifestForModelSrc(src).catch(() => null);
|
const manifestRef = await findManifestForModelSrc(src).catch(() => null);
|
||||||
if (!manifestRef || !existsSync(manifestRef.manifestPath)) {
|
if (!manifestRef || !existsSync(manifestRef.manifestPath)) {
|
||||||
|
|
@ -1955,6 +2028,33 @@ const readViewerSettingsForModelSrc = async (src) => {
|
||||||
return normalizeViewerSettings(manifest?.viewerSettings);
|
return normalizeViewerSettings(manifest?.viewerSettings);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const mergeViewerSettingsTransforms = (base, fallback) => {
|
||||||
|
const normalizedBase = normalizeViewerSettings(base);
|
||||||
|
const normalizedFallback = normalizeViewerSettings(fallback);
|
||||||
|
if (!normalizedBase || viewerSettingsHaveTransforms(normalizedBase) || !viewerSettingsHaveTransforms(normalizedFallback)) {
|
||||||
|
return normalizedBase || normalizedFallback || null;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...normalizedBase,
|
||||||
|
viewerState: {
|
||||||
|
...(normalizedBase.viewerState || {}),
|
||||||
|
transforms: normalizedFallback.viewerState.transforms,
|
||||||
|
models: normalizedFallback.viewerState.models || normalizedBase.viewerState?.models || []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const resolveShareViewerSettings = async (share) => {
|
||||||
|
const shareSettings = normalizeViewerSettings(share?.viewerSettings);
|
||||||
|
const manifestSettings = await readViewerSettingsForModelSrc(share?.settingsSrc || share?.src);
|
||||||
|
const base = shareSettings || manifestSettings;
|
||||||
|
if (viewerSettingsHaveTransforms(base)) {
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
const projectSettings = await readProjectViewerSettingsForShare(share);
|
||||||
|
return mergeViewerSettingsTransforms(base, projectSettings);
|
||||||
|
};
|
||||||
|
|
||||||
const handleCreateShare = async (req, res) => {
|
const handleCreateShare = async (req, res) => {
|
||||||
const session = await getValidatedBimSession(req, res);
|
const session = await getValidatedBimSession(req, res);
|
||||||
if (BIM_AUTH_REQUIRED && !session) {
|
if (BIM_AUTH_REQUIRED && !session) {
|
||||||
|
|
@ -1988,8 +2088,14 @@ const handleCreateShare = async (req, res) => {
|
||||||
const name = typeof payload?.name === "string" && payload.name.trim()
|
const name = typeof payload?.name === "string" && payload.name.trim()
|
||||||
? payload.name.trim().slice(0, 240)
|
? payload.name.trim().slice(0, 240)
|
||||||
: path.basename(src);
|
: path.basename(src);
|
||||||
const viewerSettings = normalizeViewerSettings(payload?.viewerSettings)
|
const viewerSettings = await resolveShareViewerSettings({
|
||||||
|| await readViewerSettingsForModelSrc(settingsSrc || src);
|
...identity,
|
||||||
|
src,
|
||||||
|
settingsSrc,
|
||||||
|
versionId: typeof payload?.versionId === "string" ? payload.versionId : null,
|
||||||
|
selectedLod: stringOrNull(payload?.selectedLod),
|
||||||
|
viewerSettings: normalizeViewerSettings(payload?.viewerSettings)
|
||||||
|
});
|
||||||
const share = {
|
const share = {
|
||||||
token,
|
token,
|
||||||
access: "public-readonly",
|
access: "public-readonly",
|
||||||
|
|
@ -2072,8 +2178,7 @@ const handleGetShare = async (req, res, token) => {
|
||||||
projectId: share.projectId,
|
projectId: share.projectId,
|
||||||
assetId: share.assetId
|
assetId: share.assetId
|
||||||
}).catch(() => null);
|
}).catch(() => null);
|
||||||
const viewerSettings = normalizeViewerSettings(share.viewerSettings)
|
const viewerSettings = await resolveShareViewerSettings(share);
|
||||||
|| await readViewerSettingsForModelSrc(share.settingsSrc || share.src);
|
|
||||||
sendJSON(res, 200, {
|
sendJSON(res, 200, {
|
||||||
ok: true,
|
ok: true,
|
||||||
mode: authenticated ? "standard" : "guest",
|
mode: authenticated ? "standard" : "guest",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue