diff --git a/.gitignore b/.gitignore index b7bdf70..777fa44 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ node_modules credentials.json -download_tests \ No newline at end of file +download_tests +dist \ No newline at end of file diff --git a/src/config.js b/src/config.js deleted file mode 100644 index d1b9c01..0000000 --- a/src/config.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Configures constants used in the other parts of this app - */ - -const dotenv = require('dotenv'); - -dotenv.config({path: '../.env'}); - -const ForgeAuthClient = require('forge-apis').AuthClientThreeLegged; - -const scopes = ['bucket:create', 'bucket:read', 'data:read', 'data:create', 'data:write']; - -const authClient = new ForgeAuthClient( - process.env.FORGE_CLIENT_ID, - process.env.FORGE_CLIENT_SECRET, - process.env.FORGE_CALLBACK_URL, - scopes, - true -); - -const folderIdMap = { - gantry: "GANTRY_FOLDER_ID", - lathe: "LATHE_FOLDER_ID", - mill: "MILL_FOLDER_ID", - waterjet: "WATERJET_FOLDER_ID" -}; - -module.exports = { - authClient: authClient, - scopes: scopes, - folderIdMap: folderIdMap, - port: process.env.PORT, - forgeClientId: process.env.FORGE_CLIENT_ID, - forgeClientSecret: process.env.FORGE_CLIENT_SECRET, - forgeCallbackURL: process.env.FORGE_CALLBACK_URL -} \ No newline at end of file diff --git a/src/config.ts b/src/config.ts index 184e30e..1ff8b44 100644 --- a/src/config.ts +++ b/src/config.ts @@ -23,39 +23,28 @@ export const authClient = new ForgeAuthClient( true ); -export const fileShareProjectID = "a.YnVzaW5lc3M6cHVyZHVlMjY5NiMyMDIxMTExNTQ2Njg0NTI1MQ"; +export const projectID = "a.YnVzaW5lc3M6cHVyZHVlMjY5NiMyMDIxMTExNTQ2Njg0NTI1MQ"; -export const folderMap = { +export const folderMap: any = { gantry: { fusionID: "urn:adsk.wipprod:fs.folder:co.IxiedfeBTOGg6NSIGQhXxQ", - local: "File Share/Gantry" + local: "../../File Share/Gantry" }, lathe: { fusionID: "urn:adsk.wipprod:fs.folder:co.FDWCeyBGQX2rv8xSNWo5lg", - local: "File Share/Lathe" + local: "../../File Share/Lathe" }, mill: { fusionID: "urn:adsk.wipprod:fs.folder:co.nEihcpHUSW-ZsVzU-__1iw", - local: "File Share/Mill" + local: "../../File Share/Mill" }, waterjet: { fusionID: "urn:adsk.wipprod:fs.folder:co.vJLXAKGbQQayeljr-nwztQ", - local: "File Share/Waterjet" + local: "../../File Share/Waterjet" } }; export const port = process.env.PORT; export const forgeClientId = process.env.FORGE_CLIENT_ID; export const forgeClientSecret = process.env.FORGE_CLIENT_SECRET; -export const forgeCallbackURL = process.env.FORGE_CALLBACK_URL; - -// export = { -// authClient: authClient, -// scopes: scopes, -// projectID: fileShareProjectID, -// folderMap: folderMap, -// port: process.env.PORT, -// forgeClientId: process.env.FORGE_CLIENT_ID, -// forgeClientSecret: process.env.FORGE_CLIENT_SECRET, -// forgeCallbackURL: process.env.FORGE_CALLBACK_URL -// } \ No newline at end of file +export const forgeCallbackURL = process.env.FORGE_CALLBACK_URL; \ No newline at end of file diff --git a/src/downloader.js b/src/downloader.ts similarity index 60% rename from src/downloader.js rename to src/downloader.ts index 35b3e2b..1d11fb5 100644 --- a/src/downloader.js +++ b/src/downloader.ts @@ -5,23 +5,23 @@ const config = require('./config'); const ObjectsApi = new ForgeSDK.ObjectsApi(); /** - * Kevin Pan | pan261@purdue.edu | Last Modified: 11/30/2021 + * Kevin Pan | pan261@purdue.edu | Last Modified: 12/2/2021 * * Downloads a file by using the Forge SDK to make a GET request * on the storageLocation and then saves the file as `filename` under the `destination` directory - * @param {String} storageLocation - * @param {String} fileName - * @param {String} destination + * @param {string} storageLocation + * @param {string} fileName + * @param {string} destination * @param {Object} credentials */ -exports.download = (storageLocation, fileName, destination, credentials) => { +exports.download = (storageLocation: string, fileName: string, destination: string, credentials: any) => { ObjectsApi.getObject('wip.dm.prod', storageLocation, {}, config.authClient, credentials) - .then((res) => { + .then((res: any) => { console.log(res) - fs.writeFile(`./${destination}/${fileName}`, res.body) + fs.writeFile(`${__dirname}/${destination}/${fileName}`, res.body) }) - .catch((err) => { + .catch((err: any) => { console.log("error while processing " + storageLocation); console.log(err); }); diff --git a/src/server.js b/src/server.js deleted file mode 100644 index fdaeb58..0000000 --- a/src/server.js +++ /dev/null @@ -1,129 +0,0 @@ -const express = require('express'); -const config = require('./config'); - -/** - * Kevin Pan | pan261@purdue.edu | Last Modified: 11/22/2021 - * - * Authentication server used to perform 3-legged auth through browser. - * - * Uses environment variables: - * - FORGE_CLIENT_ID - * - FORGE CLIENT_SECRET - * - FORGE_CALLBACK_URL - * - PORT (defaults to 3000) - * - * These are all configured in config.js - * - */ - -let credentials = null; -let refreshTime = null; -let intervalID = null; - -/** - * Creates server with three endpoints: - * 1. /auth - * - navigate to login in to Autodesk and begin auth process - * 2. /callback - * - after consent screen, auth API will redirect headers - * 3. /credentials - * - will return credentials JSON object or null if there isn't one - * @returns express server object - */ -const createServer = () => { - const app = express(); - const PORT = config.port || 3000; - - if (config.forgeClientId == null || config.forgeClientSecret == null) { - console.error('Missing FORGE_CLIENT_ID or FORGE_CLIENT_SECRET env. variables.'); - return; - } - - // Endpoint to begin authentication process - app.get('/auth', function (req, res) { - console.log( - '\x1b[96mserver.js::createServer:', - '\x1b[0m/auth endpoint called' - ); - res.redirect(config.authClient.generateAuthUrl()); - }); - - // Endpoint Forge redirects to after consent screen - app.get('/callback', function (req, res) { - config.authClient.getToken(req.query.code) - .then((creds) => { - credentials = creds; - refreshTime = creds.expires_in - 300; - res.send('Generated token: ' + credentials.access_token); - console.log( - '\x1b[92mserver.js::createServer:', - '\x1b[0m/callback reached, token generated' - ); - }) - .then(() => { - // sets refresh() function to run on an interval every 55 minutes - intervalID = setInterval(() => refresh(), refreshTime * 1000); // 55 seconds to ms - - // sets timeout for 13 days, before clearing refresh interval and clearing credentials - setTimeout(() => { - credentials = null; - clearInterval(intervalID); - console.log( - '\x1b[93mserver.js::createServer:', - '\x1b[0mRefresh token expiring, need to authenticate again' - ); - }, 13 * 24 * 3600 * 1000); // 13 days to ms - }) - .catch((err) => { - console.error(err); - res.send(err); - }); - }); - - // Endpoint for internal use, to get credentials from our auth server - app.get('/credentials', function (req, res) { - if (credentials) { - console.log( - '\x1b[96mserver.js::createServer:', - '\x1b[0m/credentials endpoint called, credentials returned' - ); - res.send(credentials); - } else { - console.log( - '\x1b[93mserver.js::createServer:', - '\x1b[0m/credentials endpoint called, no credentials found' - ); - res.send('Need to authenticate at localhost:3000/auth'); - } - }); - - // Default endpoint - app.use((err, req, res, next) => { - console.error(err); - res.status(err.statusCode).json(err); - }); - - const server = app.listen(config.port, () => { console.log(`Server listening on port ${PORT}`); }); - - return server; -} - -/** - * Used internally to refresh tokens automatically - */ -const refresh = () => { - config.authClient.refreshToken(credentials, config.scopes) - .then(creds => { - credentials = creds; - console.log( - '\x1b[92mserver.js::refresh:', - '\x1b[0mnew token generated from refresh token:' - ); - console.log(credentials); - }) - .catch(err => { - console.log(err); - }); -}; - -createServer(); \ No newline at end of file diff --git a/src/server.ts b/src/server.ts index 90909b9..2aa3001 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,9 +1,9 @@ -import * as express from 'express'; +import express = require('express'); import * as config from './config'; /** - * Kevin Pan | pan261@purdue.edu | Last Modified: 11/22/2021 + * Kevin Pan | pan261@purdue.edu | Last Modified: 12/2/2021 * * Authentication server used to perform 3-legged auth through browser. * diff --git a/src/taskRunner.js b/src/taskRunner.ts similarity index 76% rename from src/taskRunner.js rename to src/taskRunner.ts index acb9ecb..cbd950d 100644 --- a/src/taskRunner.js +++ b/src/taskRunner.ts @@ -1,10 +1,11 @@ const axios = require('axios'); const watcher = require('./watcher'); const downloader = require('./downloader'); -const config = require('./config'); +import * as config from './config'; + /** - * Kevin Pan | pan261@purdue.edu | Last Modified: 11/30/2021 + * Kevin Pan | pan261@purdue.edu | Last Modified: 12/2/2021 * * This file will be responsible for managing the watcher * as well as fetching the credentials from the server @@ -19,15 +20,17 @@ const projectID = "" // parse command line arguments from docker-compose to get folder ID -const folderID = config.folderIdMap[process.argv[2]]; -console.log(folderID); +const folderID = config.folderMap[process.argv[2]].fusionID; +const localDir = config.folderMap[process.argv[2]].local; + +console.log(folderID, localDir); -const adminProjectID = 'a.YnVzaW5lc3M6cHVyZHVlMjY5NiMyMDIxMTEwODQ2NDQzMzk3Ng'; -const adminProjectTopFolder = 'urn:adsk.wipprod:fs.folder:co.ltuYad4ZTtieJLm6j3MGuA'; +// const adminProjectID = 'a.YnVzaW5lc3M6cHVyZHVlMjY5NiMyMDIxMTEwODQ2NDQzMzk3Ng'; +// const adminProjectTopFolder = 'urn:adsk.wipprod:fs.folder:co.ltuYad4ZTtieJLm6j3MGuA'; -let credentials = null; -let initInterval = null; -let updateInterval = null; +let credentials: any = null; +let initInterval: any = null; +let updateInterval: any = null; /** * Sends GET request to get token from auth server @@ -41,7 +44,7 @@ const fetchToken = () => { method: 'GET', url: 'http://localhost:3000/credentials' }) - .then(res => { + .then((res: any) => { // console.log(res.data); if (Object.keys(res.data).length == 5) { credentials = res.data; @@ -57,7 +60,7 @@ const fetchToken = () => { ); } }) - .catch(err => { + .catch((err: any) => { console.log( '\x1b[91mtaskRunner.js::fetchToken:', '\x1b[0mError accessing localhost:3000/credentials' @@ -85,7 +88,7 @@ const getCredentials = () => { /** * Function to dispatch the watcher */ -const dispatchWatcher = async (interval) => { +const dispatchWatcher = async (interval: any) => { if (credentials === null) { console.log( '\x1b[93mtaskRunner.js::dispatchWatcher:', @@ -94,15 +97,15 @@ const dispatchWatcher = async (interval) => { return; } - const items = await watcher.watch(adminProjectID, adminProjectTopFolder, credentials, interval); + const items = await watcher.watch(config.projectID, folderID, credentials, interval); if (Object.keys(items).length == 0) { return; // no items to download } - for (index in items) { + for (var index in items) { // dispatch the downloader here - downloader.download(items[index].location, items[index].name, 'download_tests', credentials); + downloader.download(items[index].location, items[index].name, localDir, credentials); } }; diff --git a/src/watcher.js b/src/watcher.ts similarity index 88% rename from src/watcher.js rename to src/watcher.ts index a321e97..4824607 100644 --- a/src/watcher.js +++ b/src/watcher.ts @@ -1,19 +1,19 @@ const axios = require('axios'); /** - * Kevin Pan | pan261@purdue.edu | Last Modified: 11/30/2021 + * Kevin Pan | pan261@purdue.edu | Last Modified: 12/2/2021 * * Watches given folder id in the project, logs any files changed since * `interval` ms ago - * @param {String} projectId the project id - * @param {String} folderId the folder id + * @param {string} projectId the project id + * @param {string} folderId the folder id * @param {Object} credentials credentials for the call * @param {Integer} interval number of ms used to filter the date * if an interval is not passed, watcher will return all files in the given folder * * @return {Object} changedItems array of items changed that need to be downloaded */ -exports.watch = (projectID, folderID, credentials, interval) => { +exports.watch = (projectID: string, folderID: string, credentials: any, interval: any) => { let timeFilter = {}; if (interval) { @@ -34,10 +34,10 @@ exports.watch = (projectID, folderID, credentials, interval) => { }, params: timeFilter }) - .then(res => { + .then((res: any) => { return res.data.included; }) - .then(data => { + .then((data: any) => { if (data === undefined) { // no new files changed, return console.log( '\x1b[96mwatcher.js::watch:', @@ -45,7 +45,7 @@ exports.watch = (projectID, folderID, credentials, interval) => { return {}; } - let changedItems = {}; + let changedItems: any = {}; for (var index in data) { // console.log(data[index]); @@ -75,7 +75,7 @@ exports.watch = (projectID, folderID, credentials, interval) => { return changedItems; }) - .catch(err => { + .catch((err: any) => { console.log( '\x1b[91mwatcher.js::watch:', '\x1b[0mError accessing Forge folder contents API' diff --git a/tsconfig.json b/tsconfig.json index 5377628..3b05550 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -97,7 +97,7 @@ /* Completeness */ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ "skipLibCheck": true, /* Skip type checking all .d.ts files. */ - "outDir": "dist", + "outDir": "./src/dist", "sourceMap": true } }