From 56a1960fffe541b69b1bd9af59dec965c501699d Mon Sep 17 00:00:00 2001 From: Saad Jutt Date: Sun, 30 May 2021 05:58:17 +0500 Subject: [PATCH 1/4] feat: create file resource while deploying service pack for viya --- src/SASViyaApiClient.ts | 50 +++++++++++++++++++++++++++++++++++++++++ src/SASjs.ts | 45 +++++++++++++++++++++++++++++++++++++ src/types/File.ts | 8 +++++++ src/types/index.ts | 1 + 4 files changed, 104 insertions(+) create mode 100644 src/types/File.ts diff --git a/src/SASViyaApiClient.ts b/src/SASViyaApiClient.ts index 72e9fa6..f7f2856 100644 --- a/src/SASViyaApiClient.ts +++ b/src/SASViyaApiClient.ts @@ -12,6 +12,7 @@ import { Context, ContextAllAttributes, Folder, + File, EditContextInput, JobDefinition, PollOptions @@ -532,6 +533,55 @@ export class SASViyaApiClient { .then((res) => res.result) } + /** + * Creates a file. Path to or URI of the parent folder is required. + * @param fileName - the name of the new file. + * @param content - the content of the new file. + * @param parentFolderPath - the full path to the parent folder. If not + * provided, the parentFolderUri must be provided. + * @param parentFolderUri - the URI (eg /folders/folders/UUID) of the parent + * folder. If not provided, the parentFolderPath must be provided. + * @param accessToken - an access token for authorizing the request. + */ + public async createFile( + fileName: string, + content: string = '', + parentFolderPath?: string, + parentFolderUri?: string, + accessToken?: string + ): Promise { + if (!parentFolderPath && !parentFolderUri) { + throw new Error('Path or URI of the parent folder is required.') + } + + if (!parentFolderUri && parentFolderPath) { + parentFolderUri = await this.getFolderUri(parentFolderPath, accessToken) + } + + const headers = { + Accept: 'application/vnd.sas.file+json', + 'Content-Disposition': `filename="${fileName}";` + } + + const mimeType = /.html$/.test(fileName) + ? 'text/html' + : /.css$/.test(fileName) + ? 'text/css' + : /.js/.test(fileName) + ? 'text/javascript' + : 'text/plain' + + return ( + await this.requestClient.post( + `/files/files?parentFolderUri=${parentFolderUri}&typeDefName=file#rawUpload`, + content, + accessToken, + mimeType, + headers + ) + ).result + } + /** * Creates a folder. Path to or URI of the parent folder is required. * @param folderName - the name of the new folder. diff --git a/src/SASjs.ts b/src/SASjs.ts index 4d9c71c..df5c515 100644 --- a/src/SASjs.ts +++ b/src/SASjs.ts @@ -299,6 +299,41 @@ export default class SASjs { ) } + /** + * Creates a file at SAS file system. + * @param fileName - name of the file to be created. + * @param content - content of the file to be created. + * @param parentFolderPath - the full path (eg `/Public/example/myFolder`) of the parent folder. + * @param parentFolderUri - the URI of the parent folder. + * @param accessToken - the access token to authorizing the request. + * @param sasApiClient - a client for interfacing with SAS API. + * @param isForced - flag that indicates if target folder already exists, it and all subfolders have to be deleted. Applicable for SAS VIYA only. + */ + public async createFile( + fileName: string, + content: string, + parentFolderPath: string, + parentFolderUri?: string, + accessToken?: string, + sasApiClient?: SASViyaApiClient + ) { + if (sasApiClient) + return await sasApiClient.createFile( + fileName, + content, + parentFolderPath, + parentFolderUri, + accessToken + ) + return await this.sasViyaApiClient!.createFile( + fileName, + content, + parentFolderPath, + parentFolderUri, + accessToken + ) + } + /** * Fetches a folder from the SAS file system. * @param folderPath - path of the folder to be fetched. @@ -867,6 +902,16 @@ export default class SASjs { isForced ) break + case 'file': + await this.createFile( + member.name, + member.code, + parentFolder, + undefined, + accessToken, + sasApiClient + ) + break case 'service': await this.createJobDefinition( member.name, diff --git a/src/types/File.ts b/src/types/File.ts new file mode 100644 index 0000000..a1afe32 --- /dev/null +++ b/src/types/File.ts @@ -0,0 +1,8 @@ +import { Link } from './Link' + +export interface File { + id: string + name: string + parentUri: string + links: Link[] +} diff --git a/src/types/index.ts b/src/types/index.ts index 36ee543..313aef2 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,6 +1,7 @@ export * from './Context' export * from './CsrfToken' export * from './Folder' +export * from './File' export * from './Job' export * from './JobDefinition' export * from './JobResult' From c5824a8a8d7787fe3aa07cbd11c14043296981ff Mon Sep 17 00:00:00 2001 From: Saad Jutt Date: Sun, 30 May 2021 23:47:31 +0500 Subject: [PATCH 2/4] fix: using mime package to determine content-type --- package-lock.json | 245 +++++++++++++++------------------------- package.json | 2 + src/SASViyaApiClient.ts | 10 +- 3 files changed, 97 insertions(+), 160 deletions(-) diff --git a/package-lock.json b/package-lock.json index d82b8f5..744c297 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "hasInstallScript": true, "license": "ISC", "dependencies": { - "@sasjs/utils": "^2.10.2", + "@sasjs/utils": "^2.14.0", "axios": "^0.21.1", "axios-cookiejar-support": "^1.0.1", "form-data": "^4.0.0", @@ -18,11 +18,13 @@ }, "devDependencies": { "@types/jest": "^26.0.22", + "@types/mime": "^2.0.3", "@types/tough-cookie": "^4.0.0", "cp": "^0.2.0", "dotenv": "^8.2.0", "jest": "^26.6.3", "jest-extended": "^0.11.5", + "mime": "^2.5.2", "path": "^0.12.7", "rimraf": "^3.0.2", "semantic-release": "^17.4.2", @@ -31,7 +33,7 @@ "ts-loader": "^9.1.2", "tslint": "^6.1.3", "tslint-config-prettier": "^1.18.0", - "typedoc": "^0.20.35", + "typedoc": "^0.20.36", "typedoc-neo-theme": "^1.1.0", "typedoc-plugin-external-module-name": "^4.0.6", "typescript": "^3.9.9", @@ -933,16 +935,33 @@ } }, "node_modules/@sasjs/utils": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.10.2.tgz", - "integrity": "sha512-N5nIsz7NUs1Yt0Am0QGs9UXDkN396ialCIfIRsNR9h4VtQRzvOwjXrsLnr3AUAAV9Z8h9CtadkC3W6MAzrQaOg==", + "version": "2.15.5", + "resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.15.5.tgz", + "integrity": "sha512-5HSWX5fy8D0Zy+Le+LgeRZG4vb5quLqhNiHw3dl0MS2hpsWACSRKia060jZk9LNHayKwBuusjlz5Ba0SyyaiEQ==", + "hasInstallScript": true, "dependencies": { - "@types/prompts": "^2.0.10", + "@types/prompts": "^2.0.11", + "chalk": "^4.1.1", + "cli-table": "^0.3.6", "consola": "^2.15.0", + "fs-extra": "^10.0.0", "prompts": "^2.4.1", "valid-url": "^1.0.9" } }, + "node_modules/@sasjs/utils/node_modules/fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@sasjs/utils/node_modules/prompts": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.1.tgz", @@ -1324,6 +1343,12 @@ "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", "dev": true }, + "node_modules/@types/mime": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz", + "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==", + "dev": true + }, "node_modules/@types/minimist": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.1.tgz", @@ -1354,9 +1379,9 @@ "dev": true }, "node_modules/@types/prompts": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/prompts/-/prompts-2.0.10.tgz", - "integrity": "sha512-W3PEl3l4vmxdgfY6LUG7ysh+mLJOTOFYmSpiLe6MCo1OdEm8b5s6ZJfuTQgEpYNwcMiiaRzJespPS5Py2tqLlQ==", + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@types/prompts/-/prompts-2.0.12.tgz", + "integrity": "sha512-Hr6osqfNg3IcQT3pJDXCsSnb0KnldY/hXeJCKJriwbZLnedN9n1e8kcZwLc25GIWULDb6h5aEyOBbf33XpZBXQ==", "dependencies": { "@types/node": "*" } @@ -1687,7 +1712,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -2114,12 +2138,6 @@ "url": "https://opencollective.com/browserslist" } }, - "node_modules/browserslist/node_modules/colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", - "dev": true - }, "node_modules/bs-logger": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", @@ -2302,16 +2320,18 @@ "dev": true }, "node_modules/chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/char-regex": { @@ -2393,7 +2413,6 @@ "version": "0.3.6", "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.6.tgz", "integrity": "sha512-ZkNZbnZjKERTY5NwC2SeMeLeifSPq/pubeRoTpdr3WchLlnZg6hEgvHkK5zL7KNFdd9PmHN8lxrENUwI3cE8vQ==", - "dev": true, "dependencies": { "colors": "1.0.3" }, @@ -2405,7 +2424,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", - "dev": true, "engines": { "node": ">=0.1.90" } @@ -2468,7 +2486,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -2479,8 +2496,7 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/colorette": { "version": "1.2.2", @@ -3956,8 +3972,7 @@ "node_modules/graceful-fs": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" }, "node_modules/growly": { "version": "1.3.0", @@ -4034,7 +4049,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -5980,7 +5994,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, "dependencies": { "graceful-fs": "^4.1.6", "universalify": "^2.0.0" @@ -6265,9 +6278,9 @@ } }, "node_modules/marked": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-2.0.1.tgz", - "integrity": "sha512-5+/fKgMv2hARmMW7DOpykr2iLhl0NgjyELk5yn92iE7z8Se1IS9n3UsFm86hFXIkvMBmVxki8+ckcpjBeyo/hw==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/marked/-/marked-2.0.6.tgz", + "integrity": "sha512-S2mYj0FzTQa0dLddssqwRVW4EOJOVJ355Xm2Vcbm+LU7GQRGWvwbO5K87OaPSOux2AwTSgtPPaXmc8sDPrhn2A==", "dev": true, "bin": { "marked": "bin/marked" @@ -6423,19 +6436,19 @@ } }, "node_modules/mime-db": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", - "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", + "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.28", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", - "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", + "version": "2.1.30", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", + "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", "dependencies": { - "mime-db": "1.45.0" + "mime-db": "1.47.0" }, "engines": { "node": ">= 0.6" @@ -11899,7 +11912,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -12045,20 +12057,6 @@ "node": ">= 10.13.0" } }, - "node_modules/terser-webpack-plugin/node_modules/jest-worker": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", - "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, "node_modules/terser-webpack-plugin/node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -12522,9 +12520,9 @@ } }, "node_modules/typedoc": { - "version": "0.20.35", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.20.35.tgz", - "integrity": "sha512-7sNca19LXg2hgyGHq3b33tQ1YFApmd8aBDEzWQ2ry4VDkw/NdFWkysGiGRY1QckDCB0gVH8+MlXA4K71IB3azg==", + "version": "0.20.36", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.20.36.tgz", + "integrity": "sha512-qFU+DWMV/hifQ9ZAlTjdFO9wbUIHuUBpNXzv68ZyURAP9pInjZiO4+jCPeAzHVcaBCHER9WL/+YzzTt6ZlN/Nw==", "dev": true, "dependencies": { "colors": "^1.4.0", @@ -12532,18 +12530,21 @@ "handlebars": "^4.7.7", "lodash": "^4.17.21", "lunr": "^2.3.9", - "marked": "^2.0.1", + "marked": "^2.0.3", "minimatch": "^3.0.0", "progress": "^2.0.3", "shelljs": "^0.8.4", "shiki": "^0.9.3", - "typedoc-default-themes": "^0.12.9" + "typedoc-default-themes": "^0.12.10" }, "bin": { "typedoc": "bin/typedoc" }, "engines": { "node": ">= 10.8.0" + }, + "peerDependencies": { + "typescript": "3.9.x || 4.0.x || 4.1.x || 4.2.x" } }, "node_modules/typedoc-default-themes": { @@ -12674,7 +12675,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, "engines": { "node": ">= 10.0.0" } @@ -13150,19 +13150,6 @@ "node": ">=0.4.0" } }, - "node_modules/webpack/node_modules/enhanced-resolve": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.7.0.tgz", - "integrity": "sha512-6njwt/NsZFUKhM6j9U8hzVyD4E4r0x7NQzhTCbcWOJ0IQjNSAoalWmb0AE51Wn+fwan5qVESWi7t2ToBxs9vrw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/webpack/node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -13175,15 +13162,6 @@ "node": ">=10" } }, - "node_modules/webpack/node_modules/tapable": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.0.tgz", - "integrity": "sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/webpack/node_modules/terser-webpack-plugin": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.1.1.tgz", @@ -14232,25 +14210,27 @@ } }, "@sasjs/utils": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.14.0.tgz", - "integrity": "sha512-5g42spg+7WpSAtIMeCt4HguCBh8w3Y1laN3rT+IXdG/twubQK6ty8TYb89bfwCVY8dH3PY2QfWikXkZm3HpYbg==", + "version": "2.15.5", + "resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.15.5.tgz", + "integrity": "sha512-5HSWX5fy8D0Zy+Le+LgeRZG4vb5quLqhNiHw3dl0MS2hpsWACSRKia060jZk9LNHayKwBuusjlz5Ba0SyyaiEQ==", "requires": { "@types/prompts": "^2.0.11", "chalk": "^4.1.1", "cli-table": "^0.3.6", "consola": "^2.15.0", + "fs-extra": "^10.0.0", "prompts": "^2.4.1", "valid-url": "^1.0.9" }, "dependencies": { - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" } }, "prompts": { @@ -14586,6 +14566,12 @@ "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", "dev": true }, + "@types/mime": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz", + "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==", + "dev": true + }, "@types/minimist": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.1.tgz", @@ -15267,14 +15253,6 @@ "electron-to-chromium": "^1.3.723", "escalade": "^3.1.1", "node-releases": "^1.1.71" - }, - "dependencies": { - "colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", - "dev": true - } } }, "bs-logger": { @@ -15424,10 +15402,9 @@ "dev": true }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -16748,8 +16725,7 @@ "graceful-fs": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" }, "growly": { "version": "1.3.0", @@ -18381,7 +18357,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, "requires": { "graceful-fs": "^4.1.6", "universalify": "^2.0.0" @@ -18614,9 +18589,9 @@ } }, "marked": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-2.0.1.tgz", - "integrity": "sha512-5+/fKgMv2hARmMW7DOpykr2iLhl0NgjyELk5yn92iE7z8Se1IS9n3UsFm86hFXIkvMBmVxki8+ckcpjBeyo/hw==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/marked/-/marked-2.0.6.tgz", + "integrity": "sha512-S2mYj0FzTQa0dLddssqwRVW4EOJOVJ355Xm2Vcbm+LU7GQRGWvwbO5K87OaPSOux2AwTSgtPPaXmc8sDPrhn2A==", "dev": true }, "marked-terminal": { @@ -18735,16 +18710,16 @@ "dev": true }, "mime-db": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", - "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==" + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", + "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==" }, "mime-types": { - "version": "2.1.28", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", - "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", + "version": "2.1.30", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", + "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", "requires": { - "mime-db": "1.45.0" + "mime-db": "1.47.0" } }, "mimic-fn": { @@ -22893,17 +22868,6 @@ "webpack-sources": "^1.4.3" }, "dependencies": { - "jest-worker": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", - "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - } - }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -23286,14 +23250,6 @@ "shelljs": "^0.8.4", "shiki": "^0.9.3", "typedoc-default-themes": "^0.12.10" - }, - "dependencies": { - "marked": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/marked/-/marked-2.0.5.tgz", - "integrity": "sha512-yfCEUXmKhBPLOzEC7c+tc4XZdIeTdGoRCZakFMkCxodr7wDXqoapIME4wjcpBPJLNyUnKJ3e8rb8wlAgnLnaDw==", - "dev": true - } } }, "typedoc-default-themes": { @@ -23394,8 +23350,7 @@ "universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" }, "unset-value": { "version": "1.0.0", @@ -23647,16 +23602,6 @@ "integrity": "sha512-xYiIVjNuqtKXMxlRMDc6mZUhXehod4a3gbZ1qRlM7icK4EbxUFNLhWoPblCvFtB2Y9CIqHP3CF/rdxLItaQv8g==", "dev": true }, - "enhanced-resolve": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.7.0.tgz", - "integrity": "sha512-6njwt/NsZFUKhM6j9U8hzVyD4E4r0x7NQzhTCbcWOJ0IQjNSAoalWmb0AE51Wn+fwan5qVESWi7t2ToBxs9vrw==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -23666,12 +23611,6 @@ "yocto-queue": "^0.1.0" } }, - "tapable": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.0.tgz", - "integrity": "sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==", - "dev": true - }, "terser-webpack-plugin": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.1.1.tgz", diff --git a/package.json b/package.json index 256ce31..e5c619b 100644 --- a/package.json +++ b/package.json @@ -39,11 +39,13 @@ "license": "ISC", "devDependencies": { "@types/jest": "^26.0.22", + "@types/mime": "^2.0.3", "@types/tough-cookie": "^4.0.0", "cp": "^0.2.0", "dotenv": "^8.2.0", "jest": "^26.6.3", "jest-extended": "^0.11.5", + "mime": "^2.5.2", "path": "^0.12.7", "rimraf": "^3.0.2", "semantic-release": "^17.4.2", diff --git a/src/SASViyaApiClient.ts b/src/SASViyaApiClient.ts index f7f2856..878a073 100644 --- a/src/SASViyaApiClient.ts +++ b/src/SASViyaApiClient.ts @@ -31,6 +31,7 @@ import { isAuthorizeFormRequired } from './auth/isAuthorizeFormRequired' import { RequestClient } from './request/RequestClient' import { SasAuthResponse } from '@sasjs/utils/types' import { prefixMessage } from '@sasjs/utils/error' +import * as mime from 'mime' /** * A client for interfacing with the SAS Viya REST API. @@ -563,13 +564,8 @@ export class SASViyaApiClient { 'Content-Disposition': `filename="${fileName}";` } - const mimeType = /.html$/.test(fileName) - ? 'text/html' - : /.css$/.test(fileName) - ? 'text/css' - : /.js/.test(fileName) - ? 'text/javascript' - : 'text/plain' + const mimeType = + mime.getType(fileName.match(/\.[0-9a-z]+$/i)?.[0] || '') ?? 'text/plain' return ( await this.requestClient.post( From 22445d12682f359d210d6c0810b8e8361396fa8d Mon Sep 17 00:00:00 2001 From: Saad Jutt Date: Thu, 10 Jun 2021 16:49:20 +0500 Subject: [PATCH 3/4] fix: uploading file Buffer with FormData --- src/SASViyaApiClient.ts | 9 ++++++--- src/SASjs.ts | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/SASViyaApiClient.ts b/src/SASViyaApiClient.ts index 878a073..3ed3fbe 100644 --- a/src/SASViyaApiClient.ts +++ b/src/SASViyaApiClient.ts @@ -546,7 +546,7 @@ export class SASViyaApiClient { */ public async createFile( fileName: string, - content: string = '', + contentBuffer: Buffer, parentFolderPath?: string, parentFolderUri?: string, accessToken?: string @@ -564,15 +564,18 @@ export class SASViyaApiClient { 'Content-Disposition': `filename="${fileName}";` } + const formData = new NodeFormData() + formData.append('file', contentBuffer, fileName) + const mimeType = mime.getType(fileName.match(/\.[0-9a-z]+$/i)?.[0] || '') ?? 'text/plain' return ( await this.requestClient.post( `/files/files?parentFolderUri=${parentFolderUri}&typeDefName=file#rawUpload`, - content, + formData, accessToken, - mimeType, + 'multipart/form-data; boundary=' + (formData as any)._boundary, headers ) ).result diff --git a/src/SASjs.ts b/src/SASjs.ts index df5c515..3e10b92 100644 --- a/src/SASjs.ts +++ b/src/SASjs.ts @@ -311,7 +311,7 @@ export default class SASjs { */ public async createFile( fileName: string, - content: string, + content: Buffer, parentFolderPath: string, parentFolderUri?: string, accessToken?: string, From c5e995f8d67b6480cd17d52bf782b96d30b899c1 Mon Sep 17 00:00:00 2001 From: Saad Jutt Date: Sun, 13 Jun 2021 16:25:04 +0500 Subject: [PATCH 4/4] chore: TSDoc comments updated --- src/SASViyaApiClient.ts | 2 +- src/SASjs.ts | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/SASViyaApiClient.ts b/src/SASViyaApiClient.ts index 0022b6a..bb629bf 100644 --- a/src/SASViyaApiClient.ts +++ b/src/SASViyaApiClient.ts @@ -541,7 +541,7 @@ export class SASViyaApiClient { /** * Creates a file. Path to or URI of the parent folder is required. * @param fileName - the name of the new file. - * @param content - the content of the new file. + * @param contentBuffer - the content of the new file in Buffer. * @param parentFolderPath - the full path to the parent folder. If not * provided, the parentFolderUri must be provided. * @param parentFolderUri - the URI (eg /folders/folders/UUID) of the parent diff --git a/src/SASjs.ts b/src/SASjs.ts index 410c143..1057aaf 100644 --- a/src/SASjs.ts +++ b/src/SASjs.ts @@ -267,7 +267,7 @@ export default class SASjs { } /** - * Creates a folder at SAS file system. + * Creates a folder in the logical SAS folder tree * @param folderName - name of the folder to be created. * @param parentFolderPath - the full path (eg `/Public/example/myFolder`) of the parent folder. * @param parentFolderUri - the URI of the parent folder. @@ -300,14 +300,13 @@ export default class SASjs { } /** - * Creates a file at SAS file system. + * Creates a file in the logical SAS folder tree * @param fileName - name of the file to be created. * @param content - content of the file to be created. * @param parentFolderPath - the full path (eg `/Public/example/myFolder`) of the parent folder. * @param parentFolderUri - the URI of the parent folder. * @param accessToken - the access token to authorizing the request. * @param sasApiClient - a client for interfacing with SAS API. - * @param isForced - flag that indicates if target folder already exists, it and all subfolders have to be deleted. Applicable for SAS VIYA only. */ public async createFile( fileName: string,