Skip to content

Commit

Permalink
Merge branch 'release/5.0.5'.
Browse files Browse the repository at this point in the history
  • Loading branch information
petrbroz committed Sep 11, 2024
2 parents b41f6e9 + 3947d7d commit 4a91cf7
Show file tree
Hide file tree
Showing 13 changed files with 59 additions and 69 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [5.0.5] - 2024-09-11

- Added
- SVF/F2D downloads can now be configured for different regions
- Fixed
- Bug in URN resolution on Windows (https://github.com/petrbroz/svf-utils/issues/84)

## [5.0.4] - 2024-09-10

- Added
Expand Down
4 changes: 2 additions & 2 deletions bin/svf-to-gltf.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const { ModelDerivativeClient} = require('@aps_sdk/model-derivative');
const { Scopes } = require('@aps_sdk/authentication');
const { SvfReader, GltfWriter, BasicAuthenticationProvider, TwoLeggedAuthenticationProvider } = require('../lib');

const { APS_CLIENT_ID, APS_CLIENT_SECRET, APS_ACCESS_TOKEN } = process.env;
const { APS_CLIENT_ID, APS_CLIENT_SECRET, APS_ACCESS_TOKEN, APS_REGION } = process.env;
let authenticationProvider = null;
if (APS_ACCESS_TOKEN) {
authenticationProvider = new BasicAuthenticationProvider(APS_ACCESS_TOKEN);
Expand Down Expand Up @@ -71,7 +71,7 @@ program
} else {
const modelDerivativeClient = new ModelDerivativeClient();
const accessToken = await authenticationProvider.getToken([Scopes.ViewablesRead]);
const manifest = await modelDerivativeClient.getManifest(urn, { accessToken });
const manifest = await modelDerivativeClient.getManifest(urn, { accessToken, region: APS_REGION });
const derivatives = [];
function traverse(derivative) {
if (derivative.type === 'resource' && derivative.role === 'graphics' && derivative.mime === 'application/autodesk-svf') {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "svf-utils",
"version": "5.0.4",
"version": "5.0.5",
"description": "Tools for working with the SVF format used by Autodesk Platform Services.",
"main": "lib/index.js",
"bin": {
Expand Down
5 changes: 3 additions & 2 deletions samples/custom-gltf-attribute.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* Usage:
* export APS_CLIENT_ID=<your client id>
* export APS_CLIENT_SECRET=<your client secret>
* export APS_REGION=<your region> # optional, can be one of the following: "US", "EMEA", "APAC"
* node custom-gltf-attribute.js <your model urn> <path to output folder>
*/

Expand Down Expand Up @@ -60,11 +61,11 @@ class CustomGltfWriter extends GltfWriter {
}
}

const { APS_CLIENT_ID, APS_CLIENT_SECRET } = process.env;
const { APS_CLIENT_ID, APS_CLIENT_SECRET, APS_REGION } = process.env;

async function run(urn, outputDir) {
try {
const derivatives = await getSvfDerivatives(urn, APS_CLIENT_ID, APS_CLIENT_SECRET);
const derivatives = await getSvfDerivatives(urn, APS_CLIENT_ID, APS_CLIENT_SECRET, APS_REGION);
const authenticationProvider = new TwoLeggedAuthenticationProvider(APS_CLIENT_ID, APS_CLIENT_SECRET);
const writer = new CustomGltfWriter({
deduplicate: false,
Expand Down
5 changes: 3 additions & 2 deletions samples/download-svf.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
* Usage:
* export APS_CLIENT_ID=<your client id>
* export APS_CLIENT_SECRET=<your client secret>
* export APS_REGION=<your region> # optional, can be one of the following: "US", "EMEA", "APAC"
* node download-svf.js <your model urn> <output folder>
*/

const { SvfDownloader, TwoLeggedAuthenticationProvider } = require('..');
const { APS_CLIENT_ID, APS_CLIENT_SECRET } = process.env;
const { APS_CLIENT_ID, APS_CLIENT_SECRET, APS_REGION } = process.env;

async function run(urn, outputDir = '.') {
const authenticationProvider = new TwoLeggedAuthenticationProvider(APS_CLIENT_ID, APS_CLIENT_SECRET);
const downloader = new SvfDownloader(authenticationProvider);
const download = downloader.download(urn, { outputDir, log: console.log });
const download = downloader.download(urn, { outputDir, log: console.log, region: APS_REGION });
await download.ready;
}

Expand Down
5 changes: 3 additions & 2 deletions samples/filter-by-area.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* npm install --save gl-matrix
* export APS_CLIENT_ID=<your client id>
* export APS_CLIENT_SECRET=<your client secret>
* export APS_REGION=<your region> # optional, can be one of the following: "US", "EMEA", "APAC"
* node filter-by-area.js <your model urn> <path to output folder>
*/

Expand Down Expand Up @@ -96,7 +97,7 @@ class AreaFilteredGltfWriter extends GltfWriter {
}
}

const { APS_CLIENT_ID, APS_CLIENT_SECRET } = process.env;
const { APS_CLIENT_ID, APS_CLIENT_SECRET, APS_REGION } = process.env;

async function run(urn, outputDir) {
const DefaultOptions = {
Expand All @@ -107,7 +108,7 @@ async function run(urn, outputDir) {
};

try {
const derivatives = await getSvfDerivatives(urn, APS_CLIENT_ID, APS_CLIENT_SECRET);
const derivatives = await getSvfDerivatives(urn, APS_CLIENT_ID, APS_CLIENT_SECRET, APS_REGION);
const authenticationProvider = new TwoLeggedAuthenticationProvider(APS_CLIENT_ID, APS_CLIENT_SECRET);
const writer = new AreaFilteredGltfWriter(Object.assign({}, DefaultOptions), [-25.0, -25.0, -25.0], [25.0, 25.0, 25.0]);
for (const derivative of derivatives) {
Expand Down
5 changes: 3 additions & 2 deletions samples/remote-svf-props.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
* Usage:
* export APS_CLIENT_ID=<your client id>
* export APS_CLIENT_SECRET=<your client secret>
* export APS_REGION=<your region> # optional, can be one of the following: "US", "EMEA", "APAC"
* node remote-svf-props.js <your model urn>
*/

const { getSvfDerivatives } = require('./shared.js');
const { SvfReader, TwoLeggedAuthenticationProvider } = require('..');

const { APS_CLIENT_ID, APS_CLIENT_SECRET } = process.env;
const { APS_CLIENT_ID, APS_CLIENT_SECRET, APS_REGION } = process.env;

async function run(urn) {
const derivatives = await getSvfDerivatives(urn, APS_CLIENT_ID, APS_CLIENT_SECRET);
const derivatives = await getSvfDerivatives(urn, APS_CLIENT_ID, APS_CLIENT_SECRET, APS_REGION);
const authenticationProvider = new TwoLeggedAuthenticationProvider(APS_CLIENT_ID, APS_CLIENT_SECRET);
for (const derivative of derivatives) {
const reader = await SvfReader.FromDerivativeService(urn, derivative.guid, authenticationProvider);
Expand Down
4 changes: 2 additions & 2 deletions samples/remote-svf-to-gltf.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ const path = require('path');
const { getSvfDerivatives } = require('./shared.js');
const { SvfReader, GltfWriter, TwoLeggedAuthenticationProvider } = require('..');

const { APS_CLIENT_ID, APS_CLIENT_SECRET } = process.env;
const { APS_CLIENT_ID, APS_CLIENT_SECRET, APS_REGION } = process.env;

async function run(urn, outputDir) {
try {
const derivatives = await getSvfDerivatives(urn, APS_CLIENT_ID, APS_CLIENT_SECRET);
const derivatives = await getSvfDerivatives(urn, APS_CLIENT_ID, APS_CLIENT_SECRET, APS_REGION);
const writer0 = new GltfWriter({ deduplicate: false, skipUnusedUvs: false, center: true, log: console.log });
const writer1 = new GltfWriter({ deduplicate: true, skipUnusedUvs: true, center: true, log: console.log });
const authenticationProvider = new TwoLeggedAuthenticationProvider(APS_CLIENT_ID, APS_CLIENT_SECRET);
Expand Down
4 changes: 2 additions & 2 deletions samples/serialize-msgpack.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ class MsgpackGltfWriter extends GltfWriter {
}
}

const { APS_CLIENT_ID, APS_CLIENT_SECRET } = process.env;
const { APS_CLIENT_ID, APS_CLIENT_SECRET, APS_REGION } = process.env;

async function run(urn, outputDir) {
try {
const derivatives = await getSvfDerivatives(urn, APS_CLIENT_ID, APS_CLIENT_SECRET);
const derivatives = await getSvfDerivatives(urn, APS_CLIENT_ID, APS_CLIENT_SECRET, APS_REGION);
const authenticationProvider = new TwoLeggedAuthenticationProvider(APS_CLIENT_ID, APS_CLIENT_SECRET);
const writer = new MsgpackGltfWriter({ deduplicate: true, center: true, log: console.log });
for (const derivative of derivatives) {
Expand Down
23 changes: 2 additions & 21 deletions samples/shared.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,12 @@
const axios = require('axios').default;
const { SdkManagerBuilder } = require('@aps_sdk/autodesk-sdkmanager');
const { AuthenticationClient, Scopes } = require('@aps_sdk/authentication');
const { ModelDerivativeClient } = require('@aps_sdk/model-derivative');

async function downloadDerivative(urn, derivativeUrn, clientId, clientSecret) {
const authenticationClient = new AuthenticationClient(SdkManagerBuilder.create().build());
const modelDerivativeClient = new ModelDerivativeClient();
try {
const credentials = await authenticationClient.getTwoLeggedToken(clientId, clientSecret, [Scopes.ViewablesRead]);
const downloadInfo = await modelDerivativeClient.getDerivativeUrl(derivativeUrn, urn, { accessToken: credentials.access_token });
const response = await axios.get(downloadInfo.url, { responseType: 'arraybuffer', decompress: false });
return response.data;
} catch (error) {
if (axios.isAxiosError(error)) {
throw new Error(`Could not download derivative ${derivativeUrn}: ${error.message}`);
} else {
throw error;
}
}
}

async function getSvfDerivatives(urn, clientId, clientSecret) {
async function getSvfDerivatives(urn, clientId, clientSecret, region) {
const authenticationClient = new AuthenticationClient(SdkManagerBuilder.create().build());
const modelDerivativeClient = new ModelDerivativeClient();
const credentials = await authenticationClient.getTwoLeggedToken(clientId, clientSecret, [Scopes.ViewablesRead]);
const manifest = await modelDerivativeClient.getManifest(urn, { accessToken: credentials.access_token });
const manifest = await modelDerivativeClient.getManifest(urn, { accessToken: credentials.access_token, region });
const derivatives = [];
function traverse(derivative) {
if (derivative.type === 'resource' && derivative.role === 'graphics' && derivative.mime === 'application/autodesk-svf') {
Expand All @@ -47,6 +29,5 @@ async function getSvfDerivatives(urn, clientId, clientSecret) {
}

module.exports = {
downloadDerivative,
getSvfDerivatives
};
25 changes: 12 additions & 13 deletions src/f2d/downloader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import * as path from 'path';
import * as zlib from 'zlib';
import * as fse from 'fs-extra';
import axios from 'axios';
import { ManifestResources, ModelDerivativeClient } from '@aps_sdk/model-derivative';
import { ManifestResources, ModelDerivativeClient, Region } from '@aps_sdk/model-derivative';
import { IAuthenticationProvider } from '../common/authentication-provider';
import { Scopes } from '@aps_sdk/authentication';

export interface IDownloadOptions {
region?: Region;
outputDir?: string;
log?: (message: string) => void;
failOnMissingAssets?: boolean;
Expand All @@ -25,11 +26,9 @@ interface IDownloadContext {
}

export class Downloader {
protected modelDerivativeClient: ModelDerivativeClient;
protected readonly modelDerivativeClient = new ModelDerivativeClient();

constructor(protected authenticationProvider: IAuthenticationProvider) {
this.modelDerivativeClient = new ModelDerivativeClient();
}
constructor(protected authenticationProvider: IAuthenticationProvider) {}

download(urn: string, options?: IDownloadOptions): IDownloadTask {
const context: IDownloadContext = {
Expand All @@ -39,15 +38,15 @@ export class Downloader {
failOnMissingAssets: !!options?.failOnMissingAssets
};
return {
ready: this._download(urn, context),
ready: this._download(urn, context, options?.region),
cancel: () => { context.cancelled = true; }
};
}

private async _downloadDerivative(urn: string, derivativeUrn: string) {
private async _downloadDerivative(urn: string, derivativeUrn: string, region?: Region) {
try {
const accessToken = await this.authenticationProvider.getToken([Scopes.ViewablesRead]);
const downloadInfo = await this.modelDerivativeClient.getDerivativeUrl(derivativeUrn, urn, { accessToken });
const downloadInfo = await this.modelDerivativeClient.getDerivativeUrl(derivativeUrn, urn, { accessToken, region });
const response = await axios.get(downloadInfo.url as string, { responseType: 'arraybuffer', decompress: false });
return response.data;
} catch (error) {
Expand All @@ -59,10 +58,10 @@ export class Downloader {
}
}

private async _download(urn: string, context: IDownloadContext): Promise<void> {
context.log(`Downloading derivative ${urn}`);
private async _download(urn: string, context: IDownloadContext, region?: Region): Promise<void> {
context.log(`Downloading derivative ${urn} (region: ${region || 'default'})`);
const accessToken = await this.authenticationProvider.getToken([Scopes.ViewablesRead]);
const manifest = await this.modelDerivativeClient.getManifest(urn, { accessToken });
const manifest = await this.modelDerivativeClient.getManifest(urn, { accessToken, region });
let derivatives: ManifestResources[] = [];
function collectDerivatives(derivative: ManifestResources) {
if (derivative.type === 'resource' && derivative.role === 'graphics' && (derivative as any).mime === 'application/autodesk-f2d') {
Expand Down Expand Up @@ -92,7 +91,7 @@ export class Downloader {
fse.ensureDirSync(guidDir);
const derivativeUrn = (derivative as any).urn;
const baseUrn = derivativeUrn.substr(0, derivativeUrn.lastIndexOf('/'));
const manifestGzip = await this._downloadDerivative(urn, baseUrn + '/manifest.json.gz');
const manifestGzip = await this._downloadDerivative(urn, baseUrn + '/manifest.json.gz', region);
fse.writeFileSync(path.join(guidDir, 'manifest.json.gz'), new Uint8Array(manifestGzip as Buffer));
const manifestGunzip = zlib.gunzipSync(manifestGzip);
const manifest = JSON.parse(manifestGunzip.toString());
Expand All @@ -102,7 +101,7 @@ export class Downloader {
}
context.log(`Downloading asset ${asset.URI}`);
try {
const assetData = await this._downloadDerivative(urn, baseUrn + '/' + asset.URI);
const assetData = await this._downloadDerivative(urn, baseUrn + '/' + asset.URI, region);
fse.writeFileSync(path.join(guidDir, asset.URI), new Uint8Array(assetData));
} catch (err) {
if (context.failOnMissingAssets) {
Expand Down
25 changes: 12 additions & 13 deletions src/svf/downloader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import * as fse from 'fs-extra';
import axios from 'axios';
import { SvfReader } from '..';
import { IAuthenticationProvider } from '../common/authentication-provider';
import { ManifestResources, ModelDerivativeClient } from '@aps_sdk/model-derivative';
import { ManifestResources, ModelDerivativeClient, Region } from '@aps_sdk/model-derivative';
import { Scopes } from '@aps_sdk/authentication';

export interface IDownloadOptions {
region?: Region
outputDir?: string;
log?: (message: string) => void;
failOnMissingAssets?: boolean;
Expand All @@ -25,11 +26,9 @@ interface IDownloadContext {
}

export class Downloader {
protected modelDerivativeClient: ModelDerivativeClient;
protected readonly modelDerivativeClient = new ModelDerivativeClient();

constructor(protected authenticationProvider: IAuthenticationProvider, host?: string, region?: string) {
this.modelDerivativeClient = new ModelDerivativeClient();
}
constructor(protected authenticationProvider: IAuthenticationProvider) {}

download(urn: string, options?: IDownloadOptions): IDownloadTask {
const context: IDownloadContext = {
Expand All @@ -39,15 +38,15 @@ export class Downloader {
failOnMissingAssets: !!options?.failOnMissingAssets
};
return {
ready: this._download(urn, context),
ready: this._download(urn, context, options?.region),
cancel: () => { context.cancelled = true; }
};
}

private async _downloadDerivative(urn: string, derivativeUrn: string) {
private async _downloadDerivative(urn: string, derivativeUrn: string, region?: Region) {
try {
const accessToken = await this.authenticationProvider.getToken([Scopes.ViewablesRead]);
const downloadInfo = await this.modelDerivativeClient.getDerivativeUrl(derivativeUrn, urn, { accessToken });
const downloadInfo = await this.modelDerivativeClient.getDerivativeUrl(derivativeUrn, urn, { accessToken, region });
const response = await axios.get(downloadInfo.url as string, { responseType: 'arraybuffer', decompress: false });
return response.data;
} catch (error) {
Expand All @@ -59,10 +58,10 @@ export class Downloader {
}
}

private async _download(urn: string, context: IDownloadContext): Promise<void> {
context.log(`Downloading derivative ${urn}`);
private async _download(urn: string, context: IDownloadContext, region?: Region): Promise<void> {
context.log(`Downloading derivative ${urn} (region: ${region || 'default'})`);
const accessToken = await this.authenticationProvider.getToken([Scopes.ViewablesRead]);
const manifest = await this.modelDerivativeClient.getManifest(urn, { accessToken });
const manifest = await this.modelDerivativeClient.getManifest(urn, { accessToken, region });
const urnDir = path.join(context.outputDir || '.', urn);

const derivatives: ManifestResources[] = [];
Expand Down Expand Up @@ -92,9 +91,9 @@ export class Downloader {
context.log(`Downloading viewable ${guid}`);
const guidDir = path.join(urnDir, guid);
fse.ensureDirSync(guidDir);
const svf = await this._downloadDerivative(urn, encodeURI((derivative as any).urn));
const svf = await this._downloadDerivative(urn, encodeURI((derivative as any).urn), region);
fse.writeFileSync(path.join(guidDir, 'output.svf'), new Uint8Array(svf));
const reader = await SvfReader.FromDerivativeService(urn, guid, this.authenticationProvider);
const reader = await SvfReader.FromDerivativeService(urn, guid, this.authenticationProvider, region);
const manifest = await reader.getManifest();
for (const asset of manifest.assets) {
if (context.cancelled) {
Expand Down
Loading

0 comments on commit 4a91cf7

Please sign in to comment.