fix(acc): check if ready before import

This commit is contained in:
Chuck Driesler
2025-07-25 09:20:55 +01:00
parent 2752fead21
commit 8fbe2fe9ca
4 changed files with 165 additions and 1 deletions
@@ -0,0 +1,60 @@
import type { ModelDerivativeServiceDesignManifest } from '@/modules/acc/domain/types'
const invokeRequest = async <T>(params: {
url: string
token: string
method?: RequestInit['method']
body?: URLSearchParams
}) => {
const { url, method = 'get', body, token } = params
const response = await fetch(url, {
method,
headers: {
'Content-Type':
body && body instanceof URLSearchParams
? 'application/x-www-form-urlencoded'
: 'application/json',
Authorization: `Bearer ${token}`
},
body
})
return (await response.json()) as T
}
export const getManifestByUrn = async (
urn: string
): Promise<ModelDerivativeServiceDesignManifest> => {
const clientId = '5Y2LzxsL3usaD1xAMyElBY8mcN6XKyfHfulZDV3up0jfhN5Y'
const clientSecret =
'qHyGqaP4zCWLyS2lp04qBDOC1giIupPzJPmLFKGFHKZrPYYpan27zF8vlhQr1RYL'
const token = Buffer.from(`${clientId}:${clientSecret}`, 'utf8').toString('base64')
const tokens = await fetch(
'https://developer.api.autodesk.com/authentication/v2/token',
{
method: 'POST',
body: new URLSearchParams({
/* eslint-disable-next-line */
grant_type: 'client_credentials',
scope: 'data:read account:read viewables:read'
}),
headers: {
Authorization: `Basic ${token}`,
Accept: 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
}
}
)
const data = await tokens.json()
const { access_token: accessToken } = data
return await invokeRequest({
url: `https://developer.api.autodesk.com/modelderivative/v2/regions/eu/designdata/${urn}/manifest`,
token: accessToken,
method: 'GET'
})
}
@@ -0,0 +1,12 @@
import type { ModelDerivativeServiceDesignManifest } from '@/modules/acc/domain/types'
export const isReadyForImport = (
manifest: ModelDerivativeServiceDesignManifest
): boolean => {
return (
manifest.derivatives?.some(
({ status, outputType, overrideOutputType }) =>
[outputType, overrideOutputType].includes('svf2') && status === 'success'
) ?? false
)
}
@@ -27,3 +27,30 @@ export type AccSyncItemStatus =
| 'FAILED'
| 'PAUSED'
| 'SUCCEEDED'
export type ModelDerivativeServiceDesignManifest = {
type: 'manifest'
region: string
/* special base64 encoded */
urn: string
derivatives?: ModelDerivativeServiceDesignManifestDerivative[]
}
export type ModelDerivativeServiceDesignManifestDerivative = {
name?: string
status: 'pending' | 'inprogress' | 'success' | 'failed' | 'timeout'
progress: 'complete' | `${number}%`
outputType:
| 'dwg'
| 'fbx'
| 'ifc'
| 'iges'
| 'obj'
| 'step'
| 'stl'
| 'svf'
| 'svf2'
| 'thumbnail'
/** Sometimes `outputType` is "svf" and `overrideOutputType` is "svf2" */
overrideOutputType?: string
}
+66 -1
View File
@@ -16,7 +16,10 @@ import {
import { Scopes, TIME_MS } from '@speckle/shared'
import type { ScheduleExecution } from '@/modules/core/domain/scheduledTasks/operations'
import { AccSyncItems } from '@/modules/acc/dbSchema'
import type { AccSyncItem } from '@/modules/acc/domain/types'
import type {
AccSyncItem,
ModelDerivativeServiceDesignManifest
} from '@/modules/acc/domain/types'
import type { InsertableAutomationRun } from '@/modules/automate/repositories/automations'
import {
getAutomationFactory,
@@ -38,6 +41,8 @@ import {
import { TokenResourceIdentifierType } from '@/modules/core/graph/generated/graphql'
import { getServerOrigin } from '@/modules/shared/helpers/envHelper'
import type { VersionCreatedTriggerManifest } from '@/modules/automate/helpers/types'
import { getManifestByUrn } from '@/modules/acc/clients/autodesk'
import { isReadyForImport } from '@/modules/acc/domain/logic'
export default function accRestApi(app: Express) {
const sessionMiddleware = sessionMiddlewareFactory()
@@ -137,6 +142,57 @@ export default function accRestApi(app: Express) {
}
})
app.get('/acc/download', sessionMiddleware, async (req, res) => {
const clientId = '5Y2LzxsL3usaD1xAMyElBY8mcN6XKyfHfulZDV3up0jfhN5Y'
const clientSecret =
'qHyGqaP4zCWLyS2lp04qBDOC1giIupPzJPmLFKGFHKZrPYYpan27zF8vlhQr1RYL'
console.log('AAAAAA')
const token = Buffer.from(`${clientId}:${clientSecret}`, 'utf8').toString('base64')
const tokens = await fetch(
'https://developer.api.autodesk.com/authentication/v2/token',
{
method: 'POST',
body: new URLSearchParams({
grant_type: 'client_credentials',
scope: 'data:read account:read viewables:read'
}),
headers: {
Authorization: `Basic ${token}`,
Accept: 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
}
}
)
const data = await tokens.json()
console.log(data)
const { access_token } = data
// https://developer.api.autodesk.com/modelderivative/v2/designdata/{urn}/manifest
// (EMEA) https://developer.api.autodesk.com/modelderivative/v2/regions/eu/designdata/{urn}/manifest
const urn =
'dXJuOmFkc2sud2lwZW1lYTpmcy5maWxlOnZmLjVORWw3ajZJVF9PSmRDdjVDWFNHTlE_dmVyc2lvbj0xNA'
const response = await fetch(
`https://developer.api.autodesk.com/modelderivative/v2/regions/eu/designdata/${urn}/manifest`,
{
method: 'GET',
headers: {
Authorization: `Bearer ${access_token}`
}
}
)
const manifest: ModelDerivativeServiceDesignManifest = await response.json()
console.log(manifest)
res.status(200).send('OK')
})
app.post('/acc/sync-item-created', sessionMiddleware, async (req, res) => {
const { accHubUrn } = req.body
@@ -217,6 +273,15 @@ const schedulePendingAccSyncItemsPoll = () => {
const projectDb = await getProjectDbClient({ projectId: syncItem.projectId })
const manifest = await getManifestByUrn(syncItem.accFileVersionUrn)
console.log(manifest)
if (!isReadyForImport(manifest)) {
console.log('NOT READY')
continue
}
await projectDb.table<AccSyncItem>(AccSyncItems.name).update({
status: 'SYNCING'
})