├── .gitignore ├── .npmignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── index.js ├── package-lock.json └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | gulpfile.js 3 | tests 4 | .vscode -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/) 5 | and this project adheres to [Semantic Versioning](http://semver.org/). 6 | 7 | ## [1.5.9] - 2018-08-18 8 | ### Security 9 | - Fixed 5 moderate security issues, by updating the request package 10 | 11 | ## [1.5.8] - 2018-08-18 12 | ### Fix 13 | - Update to documentation 14 | 15 | ## [1.5.7] - 2018-08-18 16 | ### Fix 17 | - Update to documentation 18 | 19 | ## [1.5.6] - 2017-08-25 20 | ### Fix 21 | - Bug fix when uploading more than 15 files. 22 | 23 | ## [1.5.5] - 2017-02-03 24 | ### Added 25 | - A new setting called `libraryPath`. This setting, specifies which library to upload the files from. 26 | 27 | ### Changed 28 | - Updated dependencies 29 | 30 | ## [1.5.4] - 2016-09-07 31 | ### Added 32 | - CHANGELOG.md 33 | - Updated through2 to 2.0.1 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2018 Wictor Wilén 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gulp-spsync 2 | Gulp plugin for synchronizing local files with a SharePoint library 3 | 4 | # Features 5 | 6 | * Gulp plugin 7 | * Copies local files to a SharePoint Document libraries and galleries 8 | 9 | # How to use 10 | 11 | 1. Prepare SharePoint by registering a SharePoint app using appregnew.aspx. Eg go to https://contoso.sharepoint.com/sites/site/_layouts/15/appregnew.aspx 12 | 2. Click on Generate for both Client Id and Client Secret. For Title, App Domain and Redirect URI, write something you don't care about. Then click on Create 13 | 3. Note down the Client Id and Client Secret, you will need it later 14 | 4. Navigate to appinv.aspx, https://contoso.sharepoint.com/sites/site/_layouts/15/appinv.aspx, enter the client ID in the App Id box and press Lookup 15 | 5. In the Permission Request XML text box enter the following XML and click Create (Note: `FullControl` is required to update assets in the Master Page gallery) 16 | ```xml 17 | 18 | 21 | 22 | ``` 23 | 6. In the following consent screen choose to trust the App by clicking on Trust It! 24 | 7. Open a folder using Visual studio code 25 | 8. Run `npm install gulp` to install the Gulp task runner 26 | 9. Run `npm install gulp-spsync` to install to install the gulp-spsync 27 | 10. Press Ctrl-Shift-P, type Task and choose to Configure Task Runner 28 | 11. In the tasks.json file that is being created replace the contents with the following: 29 | ```json 30 | { 31 | "version": "0.1.0", 32 | "command": "gulp", 33 | "isShellCommand": true, 34 | "tasks": [ 35 | { 36 | "taskName": "default", 37 | "isBuildCommand": true, 38 | "showOutput": "silent" 39 | } 40 | ] 41 | } 42 | ``` 43 | 12. Create a new file in the root of your folder called `gulpfile.js`, and modify it as follows. This task will monitor all files in the `Src` folder 44 | ```javascript 45 | var gulp = require('gulp') 46 | var sp = require('gulp-spsync') 47 | gulp.task('default', function() { 48 | return gulp.src('src/**/*.*'). 49 | pipe(sp({ 50 | "client_id":"3d271647-2e12-4ae5-9271-04b3aa67dcd3", 51 | "client_secret":"Zk9ORywN0gaGljrtlxfp+s5vh7ZyWV4dRpOXCLjtl8U=", 52 | "realm" : "", 53 | "site" : "https://contoso.sharepoint.com/sites/site", 54 | "verbose": "true" 55 | })). 56 | pipe(gulp.dest('build')) 57 | }) 58 | ``` 59 | 13. Replace the client_id and client_secret parameters with the value for the App you just created 60 | 14. Replace the site URL with your site URL 61 | 15. Create a folder called `Src` (you can call it whatever you want, but the tasks above/below uses `Src`) 62 | 16. Create sub folders to the `Src` folder where each Subfolder represents a Library in a site. You can alos create a subfolder called `_catalogs` and 63 | add a subfolder to that one called `masterpage` if you want to sync files to the Master Page Gallery. 64 | 17. Add files as you want to these folders 65 | 18. Press Ctrl-Shift-B to Build and let Gulp and gulp-spsync upload the files to SharePoint 66 | 67 | # Using Gulp watchers 68 | 69 | You can use Gulp watchers (gulp-watch) to upload files as they are changed. 70 | The following `gulpfile.js` shows how to upload all files on build and then upload files incrementally when changed and saved. 71 | 72 | You need to run `npm install gulp-watch` to install the Gulp watcher 73 | 74 | ```javascript 75 | var gulp = require('gulp') 76 | var sp = require('gulp-spsync') 77 | var watch = require('gulp-watch') 78 | 79 | var settings = { 80 | "client_id":"...", 81 | "client_secret":"...", 82 | "realm" : "", 83 | "site" : "https://contoso.sharepoint.com/sites/site", 84 | "verbose": "true", 85 | "watch": true 86 | }; 87 | gulp.task('default', function() { 88 | return gulp.src('src/**/*.*') 89 | .pipe(watch('src/**/*.*')) 90 | .pipe(sp(settings)) 91 | .pipe(gulp.dest('build')) 92 | }) 93 | 94 | ``` 95 | # Setting metadata for files 96 | If you're files require metadata to be set when they are uploaded, you can pass in a metadata options (update_metadata, files_metadata). 97 | 98 | **Example:** 99 | ```javascript 100 | var fileMetadata = [ 101 | { 102 | name: 'Item_Minimal.js', 103 | metadata: { 104 | "__metadata": { type: "SP.Data.OData__x005f_catalogs_x002f_masterpageItem" }, 105 | Title: 'Item Minimal Template (via GULP)', 106 | MasterPageDescription: 'This is a display template added via gulp.', 107 | ManagedPropertyMapping: "'Path','Title':'Title'", 108 | ContentTypeId: '0x0101002039C03B61C64EC4A04F5361F38510660500A0383064C59087438E649B7323C95AF6', 109 | DisplayTemplateLevel: 'Item', 110 | TargetControlType: { 111 | "__metadata": { 112 | "type": "Collection(Edm.String)" 113 | }, 114 | "results": [ 115 | "SearchResults", 116 | "Content Web Parts" 117 | ] 118 | } 119 | } 120 | }, 121 | { 122 | name: 'Control_Minimal.js', 123 | metadata: { 124 | "__metadata": { type: "SP.Data.OData__x005f_catalogs_x002f_masterpageItem" }, 125 | Title: 'Control Minimal Template (via GULP)', 126 | MasterPageDescription: 'This is a display template added via gulp.', 127 | ContentTypeId: '0x0101002039C03B61C64EC4A04F5361F38510660500A0383064C59087438E649B7323C95AF6', 128 | DisplayTemplateLevel: 'Control', 129 | TargetControlType: { 130 | "__metadata": { 131 | "type": "Collection(Edm.String)" 132 | }, 133 | "results": [ 134 | "SearchResults", 135 | "Content Web Parts" 136 | ] 137 | } 138 | } 139 | } 140 | ]; 141 | 142 | var settings = { 143 | "client_id":"...", 144 | "client_secret":"...", 145 | "realm" : "", 146 | "site" : "https://contoso.sharepoint.com/sites/site", 147 | "verbose": true, 148 | "update_metadata": true, 149 | "files_metadata": fileMetadata 150 | }; 151 | ``` 152 | 153 | # Publishing files 154 | By setting the **publish** setting, you can specify to publish your files when they are uploaded to the site. 155 | 156 | ```json 157 | var settings = { 158 | "client_id":"...", 159 | "client_secret":"...", 160 | "realm" : "", 161 | "site" : "https://contoso.sharepoint.com/sites/site", 162 | "verbose": true, 163 | "publish": true 164 | }; 165 | ``` 166 | 167 | # Using nested folders (new in 1.4.0) 168 | 169 | If you're using nested folders or deep structures, you can choose the name of the "start folder", using the `startFolder` option. 170 | Assume you have your SharePoint files under `src/template1/_sp/_catalogs` and `src/template2/_sp/_catalogs/` then you can use `"startFolder"="_sp"` to make sure that the first folder names are stripped. 171 | 172 | ```javascript 173 | var gulp = require('gulp') 174 | var sp = require('gulp-spsync') 175 | 176 | var settings = { 177 | "client_id":"...", 178 | "client_secret":"...", 179 | "realm" : "", 180 | "site" : "https://contoso.sharepoint.com/sites/site", 181 | "verbose": "true", 182 | "startFolder":"_sp" 183 | }; 184 | gulp.task('default', function() { 185 | return gulp.src('src/**/_sp/**/*.*') 186 | .pipe(sp(settings)) 187 | }) 188 | 189 | ``` 190 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var through = require('through2') 3 | var rp = require('request-promise'); 4 | var u = require('url') 5 | var gutil = require('gulp-util'); 6 | var path = require('path'); 7 | var util = require("util"); 8 | 9 | module.exports = function(args){ 10 | var options = { 11 | client_id: "", 12 | client_secret: "", 13 | realm: "", 14 | site: "", 15 | verbose: false, 16 | watch: false, 17 | update_metadata: false, 18 | files_metadata: [], 19 | publish: false, 20 | libraryPath: "" 21 | } 22 | 23 | if(!args){ 24 | throw "options required" 25 | } 26 | if(!args.client_id){ 27 | throw "The client_id options parameter is required" 28 | } 29 | if(!args.client_secret){ 30 | throw "The client_secret options parameter is required" 31 | } 32 | if(!args.site){ 33 | throw "The site options parameter is required" 34 | } 35 | 36 | if (args) { 37 | // Required properties 38 | options.client_id = args.client_id; 39 | options.client_secret = args.client_secret; 40 | options.site = args.site; 41 | // Default properties or configured via the gulp script 42 | options.realm = args.realm || options.realm; 43 | options.verbose = args.verbose || options.verbose; 44 | if (typeof (options.verbose) === 'string') { 45 | options.verbose = options.verbose === 'true'; 46 | } 47 | if (options.verbose) { 48 | gutil.log('Verbose logging on!') 49 | } 50 | options.watch = args.watch || options.watch; 51 | options.update_metadata = args.update_metadata || options.update_metadata; 52 | options.files_metadata = args.files_metadata || options.files_metadata; 53 | options.publish = args.publish || options.publish; 54 | options.startFolder = args.startFolder || ""; 55 | options.libraryPath = args.libraryPath || ""; 56 | } 57 | 58 | var getFormattedPrincipal = function (principalName, hostName, realm){ 59 | var resource = principalName 60 | if(hostName != null && hostName != "" ) { 61 | resource += "/" + hostName 62 | } 63 | resource += "@" + realm 64 | return resource 65 | } 66 | 67 | var toDateFromEpoch = function(epoch){ 68 | var tmp = parseInt(epoch); 69 | if(tmp<10000000000) tmp *= 1000; 70 | var d = new Date() 71 | d.setTime(tmp) 72 | return d; 73 | } 74 | var now = function() { 75 | return new Date() 76 | } 77 | var globalEndPointPrefix = "accounts"; 78 | var acsHostUrl = "accesscontrol.windows.net"; 79 | var acsMetadataEndPointRelativeUrl = "/metadata/json/1"; 80 | var S2SProtocol = "OAuth2" 81 | var sharePointPrincipal = "00000003-0000-0ff1-ce00-000000000000" 82 | var bearer = "Bearer realm=\"" 83 | var https ="https://" 84 | var clientsvc = "/vti_bin/client.svc" 85 | var tokens = null 86 | 87 | var getStsUrl = function(realm){ 88 | if(options.verbose){ 89 | gutil.log('Locating STS Url for ' + realm) 90 | } 91 | var url = https + globalEndPointPrefix + "." + acsHostUrl + acsMetadataEndPointRelativeUrl + "?realm=" + realm 92 | return rp 93 | .get(url) 94 | .then(function(data){ 95 | var endpoints =JSON.parse(data).endpoints 96 | for(var i in endpoints){ 97 | if(endpoints[i].protocol == S2SProtocol ) 98 | { 99 | if(options.verbose){ 100 | gutil.log('STS Endpoint found ' + endpoints[i].location) 101 | } 102 | return endpoints[i].location 103 | } 104 | } 105 | throw "ACS endpoint not found" 106 | }); 107 | } 108 | var getRealmFromTargetUrl = function(targetUrl){ 109 | if(options.verbose){ 110 | gutil.log('Locating realm for ' + targetUrl) 111 | } 112 | 113 | return rp.post( targetUrl + clientsvc,{ 114 | headers: { 115 | "Authorization": "Bearer " 116 | }, 117 | resolveWithFullResponse: true 118 | }).then(function(response){ 119 | throw "Unexpected" 120 | }).catch(function(err){ 121 | if(err.name== 'RequestError'){ 122 | throw "Request error" 123 | } 124 | var headers = err.response.headers 125 | var data = headers["www-authenticate"] 126 | var ix = data.indexOf(bearer) + bearer.length 127 | data = data.substring(ix, ix+36) 128 | if(options.verbose){ 129 | gutil.log('Realm is ' + data) 130 | } 131 | return data; 132 | }); 133 | } 134 | var getAppOnlyAccessToken = function( 135 | targetPrincipalName, 136 | targetHost, 137 | targetRealm){ 138 | 139 | var resource = getFormattedPrincipal(targetPrincipalName, targetHost, targetRealm) 140 | var clientId = getFormattedPrincipal(options.client_id, "", targetRealm) 141 | 142 | var httpOptions = { 143 | headers: { 144 | "Content-Type": "application/x-www-form-urlencoded" 145 | }, 146 | form: { 147 | "grant_type": "client_credentials", 148 | "client_id": clientId, 149 | "client_secret": options.client_secret, 150 | "resource": resource 151 | } 152 | }; 153 | 154 | if(options.verbose){ 155 | gutil.log('Retreiving access token for ' + clientId) 156 | } 157 | return getStsUrl(options.realm) 158 | .then(function(stsUrl){ 159 | return rp.post(stsUrl, httpOptions) 160 | .then(function(data){ 161 | return JSON.parse(data) 162 | }) 163 | }); 164 | } 165 | 166 | var updateFileMetadata = function(file, resolve, reject) { 167 | if (options.update_metadata) { 168 | if (options.files_metadata.length <= 0) { 169 | resolve(true); 170 | } 171 | // Get file context 172 | var fileCtx = getFileContext(file); 173 | var library = fileCtx.library; 174 | var filename = fileCtx.filename; 175 | // Check if the filename is in the array with metadata 176 | var fileMetadata = options.files_metadata.filter(function (fm) { 177 | if (fm.name === filename) { 178 | return fm; 179 | } 180 | }); 181 | // Check if metadata has been retrieved for the file 182 | if (fileMetadata.length > 0) { 183 | var metadata = fileMetadata[0].metadata; 184 | var metadataHeader = { 185 | "headers":{ 186 | "Authorization": "Bearer " + tokens.access_token, 187 | "content-type":"application/json;odata=verbose", 188 | "X-HTTP-Method": "PATCH", 189 | "If-Match": "*" 190 | }, 191 | "body": JSON.stringify(metadata) 192 | }; 193 | rp.post( 194 | options.site + "/_api/web/GetFolderByServerRelativeUrl('" + library +"')/Files('"+filename +"')/listitemallfields", 195 | metadataHeader 196 | ).then(function(postData) { 197 | gutil.log(gutil.colors.green('Metadata updated successful')); 198 | resolve(postData); 199 | }).catch(function(err){ 200 | gutil.log(gutil.colors.red("Unable to update metadata of the file")); 201 | reject(err); 202 | }); 203 | } else { 204 | // Nothing to do, no metadata for the file 205 | resolve(true); 206 | } 207 | } else { 208 | resolve(true); 209 | } 210 | } 211 | 212 | var publishFile = function (file, resolve, reject) { 213 | // Get file context 214 | var fileCtx = getFileContext(file); 215 | var library = fileCtx.library; 216 | var filename = fileCtx.filename; 217 | if (options.publish) { 218 | var publishHeader = { 219 | "headers":{ 220 | "Authorization": "Bearer " + tokens.access_token, 221 | "content-type":"application/json;odata=verbose" 222 | } 223 | }; 224 | // First check out the file 225 | rp.post( 226 | options.site + "/_api/web/GetFolderByServerRelativeUrl('" + library +"')/Files('"+filename +"')/CheckOut()", 227 | publishHeader 228 | ).then(function(result){ 229 | // Check in major version 230 | rp.post( 231 | options.site + "/_api/web/GetFolderByServerRelativeUrl('" + library +"')/Files('"+filename +"')/CheckIn(comment='Checked in via GULP', checkintype=1)", 232 | publishHeader 233 | ).then(function (result) { 234 | gutil.log(gutil.colors.green('Published file')); 235 | resolve(result); 236 | }) 237 | }).catch(function(err){ 238 | gutil.log(gutil.colors.red("Unable to publish file")); 239 | reject(err); 240 | }); 241 | } else { 242 | resolve(true); 243 | } 244 | } 245 | 246 | var getFileContext = function(file) { 247 | var ix = file.relative.lastIndexOf(path.sep) 248 | var ix2 = 0; 249 | if(options.startFolder) { 250 | ix2 = file.relative.indexOf(options.startFolder) + options.startFolder.length + 1 251 | if(ix2 == -1) { 252 | ix2 = 0 253 | } 254 | } 255 | var library = file.relative.substring(ix2,ix) 256 | if(options.verbose){ 257 | gutil.log('Using library: ' + library) 258 | } 259 | var filename = file.relative.substring(ix+1) 260 | return { 261 | library: options.libraryPath !== "" ? options.libraryPath + path.sep + library : library, 262 | filename: filename 263 | }; 264 | } 265 | 266 | var uploadFile = function(file, content){ 267 | var headers = { 268 | "headers":{ 269 | "Authorization": "Bearer " + tokens.access_token, 270 | "content-type":"application/json;odata=verbose", 271 | "accept":"application/json;odata=verbose" 272 | }, 273 | "body": content 274 | }; 275 | 276 | var fileCtx = getFileContext(file); 277 | var library = fileCtx.library; 278 | var filename = fileCtx.filename; 279 | 280 | if(path.sep == "\\"){ 281 | library = library.replace(/\\/g, "/") 282 | } 283 | 284 | return checkFoldersAndCreateIfNotExist(library, filename, options, tokens).then(function() { 285 | return new Promise(function (resolve, reject) { 286 | rp.post( 287 | options.site + "/_api/web/GetFolderByServerRelativeUrl('" + 288 | library +"')/Files/add(url='"+ 289 | filename +"',overwrite=true)", 290 | headers 291 | ) 292 | .then(function(success) { 293 | gutil.log(gutil.colors.green('Upload successful')); 294 | resolve(success); 295 | }) 296 | .catch(function(err){ 297 | switch(err.statusCode){ 298 | case 423: 299 | gutil.log(gutil.colors.red("Unable to upload file, it might be checked out to someone")) 300 | break; 301 | default: 302 | gutil.log(gutil.colors.red("Unable to upload file, it might be checked out to someone")) 303 | break; 304 | } 305 | reject(err); 306 | }); 307 | }); 308 | }).then(function() { 309 | // Update file metadata 310 | return new Promise(function (resolve, reject) { 311 | updateFileMetadata(file, resolve, reject); 312 | }); 313 | }).then(function(){ 314 | // Publish file 315 | return new Promise(function (resolve, reject) { 316 | publishFile(file, resolve, reject) 317 | }); 318 | }); 319 | } 320 | 321 | var checkFoldersAndCreateIfNotExist = function(library, filename, options, tokens) { 322 | var foldersArray = getFolderPathsArray(library); 323 | var proms = []; 324 | foldersArray.forEach(function (val, index) { 325 | proms.push(checkFolderExists(val)); 326 | }); 327 | 328 | return Promise.all(proms) 329 | .then(function(data) { 330 | var erroredIndexes = data.map(function (val, index) { 331 | if (val.error) { 332 | return index; 333 | } 334 | }).filter(function (x) { return x != undefined }); 335 | var pathArray = []; 336 | erroredIndexes.forEach(function (val, index) { 337 | var path = foldersArray[val]; 338 | pathArray.push(path); 339 | }) 340 | if (pathArray.length > 0) { 341 | return createPathRecursive(pathArray, library, filename, options, tokens); 342 | } 343 | } 344 | ); 345 | } 346 | 347 | var checkFolderExists = function(folderName) { 348 | var getFolderUrl = util.format("/_api/web/GetFolderByServerRelativeUrl(@FolderName)" + 349 | "?@FolderName='%s'", encodeURIComponent(folderName)); 350 | var opts = { 351 | headers: { 352 | "Accept": "application/json;odata=verbose", 353 | "Authorization": "Bearer " + tokens.access_token, 354 | "content-type":"application/json;odata=verbose" 355 | }, 356 | json: true 357 | }; 358 | var endPoint = options.site + getFolderUrl; 359 | if(options.verbose){ 360 | gutil.log("Checking folder exists " + endPoint); 361 | } 362 | return rp.get(endPoint, opts) 363 | .then(function (success) { 364 | if(options.verbose){ 365 | gutil.log('Folder ' + folderName + ' exists'); 366 | } 367 | return success; 368 | }) 369 | .catch(function(err) { 370 | gutil.log("INFO: Folder '" + folderName + "' doesn't exist and will be created"); 371 | return err; 372 | }); 373 | } 374 | 375 | var createPathRecursive = function(path, library, filename, options, tokens) { 376 | if(options.verbose){ 377 | gutil.log("Creating path " + path[0]); 378 | } 379 | var setFolder = util.format("/_api/web/folders"); 380 | var body = "{'__metadata': {'type': 'SP.Folder'}, 'ServerRelativeUrl': '" + path[0] + "'}"; 381 | var opts = { 382 | headers: { 383 | "Accept": "application/json;odata=verbose", 384 | "Authorization": "Bearer " + tokens.access_token, 385 | "content-type": "application/json;odata=verbose", 386 | "content-length": Buffer.byteLength(body) 387 | }, 388 | body: body 389 | }; 390 | 391 | return new Promise(function (resolve) { 392 | rp.post(options.site + setFolder, opts) 393 | .then(function (res) { 394 | resolve(path.slice(1, path.length)); 395 | }) 396 | .catch(function(err) { 397 | gutil.log("ERR: " + err); 398 | return err; 399 | }); 400 | }) 401 | .then(function (path) { 402 | if (path.length > 0) { 403 | return createPathRecursive(path, library, filename, options, tokens); 404 | } 405 | return true; 406 | }); 407 | } 408 | 409 | var getFolderPathsArray = function (folder) { 410 | if (endsWith(folder, "/") && folder !== "/") { 411 | folder = folder.slice(0, -1); 412 | } 413 | 414 | var folderNamesArray = folder.split('/'); 415 | var foldersArray = []; 416 | for (var i = 0; i < folderNamesArray.length; i++) { 417 | var pathArray = []; 418 | for (var r = 0; r <= i; r++) { 419 | pathArray.push(folderNamesArray[r]); 420 | } 421 | foldersArray.push(pathArray.join('/')); 422 | } 423 | return foldersArray; 424 | } 425 | 426 | var endsWith = function(str, suffix) { 427 | return str.indexOf(suffix, str.length - suffix.length) !== -1; 428 | } 429 | 430 | return through.obj(function(file, enc, cb){ 431 | // If watch is set to true, only upload the changed files 432 | if (options.watch && file.event !== "change") { 433 | if(options.verbose){ 434 | gutil.log("Skipping:", gutil.colors.yellow(file.relative)) 435 | } 436 | cb(null,file) 437 | return; 438 | } 439 | 440 | var fileDone = function(parameter) { 441 | cb() 442 | } 443 | 444 | if(file.isNull()){ 445 | cb() 446 | return; 447 | } 448 | if (file.isStream()) { 449 | cb(new gutil.PluginError("gulp-spsync", 'Streaming not supported')); 450 | return; 451 | } 452 | 453 | var content = file.contents; 454 | if (file.contents == null || file.contents.length === 0) { 455 | content = ''; 456 | } 457 | 458 | gutil.log('Uploading ' + file.relative) 459 | 460 | if(tokens == null || now() > toDateFromEpoch(tokens.expires_on) ){ 461 | getRealmFromTargetUrl(options.site).then(function(realm){ 462 | return getAppOnlyAccessToken( 463 | sharePointPrincipal, 464 | u.parse(options.site).hostname, 465 | realm) 466 | .then(function(token){ 467 | tokens = token 468 | return uploadFile(file, content).then(fileDone) 469 | }) 470 | }).catch(function(err){ 471 | cb(new gutil.PluginError("gulp-spsync", err)); 472 | }); 473 | } else { 474 | return uploadFile(file, content).then(fileDone) 475 | } 476 | },function(cb){ 477 | if(options.verbose){ 478 | gutil.log("And we're done...") 479 | } 480 | cb(); 481 | }) 482 | } -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gulp-spsync", 3 | "version": "1.5.9", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "ajv": { 8 | "version": "5.5.2", 9 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", 10 | "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", 11 | "requires": { 12 | "co": "^4.6.0", 13 | "fast-deep-equal": "^1.0.0", 14 | "fast-json-stable-stringify": "^2.0.0", 15 | "json-schema-traverse": "^0.3.0" 16 | } 17 | }, 18 | "ansi-gray": { 19 | "version": "0.1.1", 20 | "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", 21 | "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", 22 | "requires": { 23 | "ansi-wrap": "0.1.0" 24 | } 25 | }, 26 | "ansi-regex": { 27 | "version": "2.1.1", 28 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 29 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" 30 | }, 31 | "ansi-styles": { 32 | "version": "2.2.1", 33 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 34 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" 35 | }, 36 | "ansi-wrap": { 37 | "version": "0.1.0", 38 | "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", 39 | "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=" 40 | }, 41 | "array-differ": { 42 | "version": "1.0.0", 43 | "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", 44 | "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" 45 | }, 46 | "array-uniq": { 47 | "version": "1.0.3", 48 | "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", 49 | "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" 50 | }, 51 | "asn1": { 52 | "version": "0.2.4", 53 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", 54 | "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", 55 | "requires": { 56 | "safer-buffer": "~2.1.0" 57 | } 58 | }, 59 | "assert-plus": { 60 | "version": "1.0.0", 61 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 62 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 63 | }, 64 | "asynckit": { 65 | "version": "0.4.0", 66 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 67 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 68 | }, 69 | "aws-sign2": { 70 | "version": "0.7.0", 71 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 72 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" 73 | }, 74 | "aws4": { 75 | "version": "1.8.0", 76 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", 77 | "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" 78 | }, 79 | "bcrypt-pbkdf": { 80 | "version": "1.0.2", 81 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 82 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", 83 | "optional": true, 84 | "requires": { 85 | "tweetnacl": "^0.14.3" 86 | } 87 | }, 88 | "beeper": { 89 | "version": "1.1.1", 90 | "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", 91 | "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=" 92 | }, 93 | "bluebird": { 94 | "version": "3.5.1", 95 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", 96 | "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" 97 | }, 98 | "caseless": { 99 | "version": "0.12.0", 100 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 101 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" 102 | }, 103 | "chalk": { 104 | "version": "1.1.3", 105 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 106 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 107 | "requires": { 108 | "ansi-styles": "^2.2.1", 109 | "escape-string-regexp": "^1.0.2", 110 | "has-ansi": "^2.0.0", 111 | "strip-ansi": "^3.0.0", 112 | "supports-color": "^2.0.0" 113 | } 114 | }, 115 | "clone": { 116 | "version": "1.0.4", 117 | "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", 118 | "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" 119 | }, 120 | "clone-stats": { 121 | "version": "0.0.1", 122 | "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", 123 | "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=" 124 | }, 125 | "co": { 126 | "version": "4.6.0", 127 | "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", 128 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" 129 | }, 130 | "color-support": { 131 | "version": "1.1.3", 132 | "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", 133 | "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" 134 | }, 135 | "combined-stream": { 136 | "version": "1.0.6", 137 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", 138 | "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", 139 | "requires": { 140 | "delayed-stream": "~1.0.0" 141 | } 142 | }, 143 | "core-util-is": { 144 | "version": "1.0.2", 145 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 146 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 147 | }, 148 | "dashdash": { 149 | "version": "1.14.1", 150 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 151 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 152 | "requires": { 153 | "assert-plus": "^1.0.0" 154 | } 155 | }, 156 | "dateformat": { 157 | "version": "2.2.0", 158 | "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", 159 | "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=" 160 | }, 161 | "delayed-stream": { 162 | "version": "1.0.0", 163 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 164 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 165 | }, 166 | "duplexer2": { 167 | "version": "0.0.2", 168 | "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", 169 | "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", 170 | "requires": { 171 | "readable-stream": "~1.1.9" 172 | } 173 | }, 174 | "ecc-jsbn": { 175 | "version": "0.1.2", 176 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 177 | "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", 178 | "optional": true, 179 | "requires": { 180 | "jsbn": "~0.1.0", 181 | "safer-buffer": "^2.1.0" 182 | } 183 | }, 184 | "escape-string-regexp": { 185 | "version": "1.0.5", 186 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 187 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 188 | }, 189 | "extend": { 190 | "version": "3.0.2", 191 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 192 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 193 | }, 194 | "extsprintf": { 195 | "version": "1.3.0", 196 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 197 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" 198 | }, 199 | "fancy-log": { 200 | "version": "1.3.2", 201 | "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", 202 | "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", 203 | "requires": { 204 | "ansi-gray": "^0.1.1", 205 | "color-support": "^1.1.3", 206 | "time-stamp": "^1.0.0" 207 | } 208 | }, 209 | "fast-deep-equal": { 210 | "version": "1.1.0", 211 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", 212 | "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" 213 | }, 214 | "fast-json-stable-stringify": { 215 | "version": "2.0.0", 216 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", 217 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" 218 | }, 219 | "forever-agent": { 220 | "version": "0.6.1", 221 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 222 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" 223 | }, 224 | "form-data": { 225 | "version": "2.3.2", 226 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", 227 | "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", 228 | "requires": { 229 | "asynckit": "^0.4.0", 230 | "combined-stream": "1.0.6", 231 | "mime-types": "^2.1.12" 232 | } 233 | }, 234 | "getpass": { 235 | "version": "0.1.7", 236 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 237 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 238 | "requires": { 239 | "assert-plus": "^1.0.0" 240 | } 241 | }, 242 | "glogg": { 243 | "version": "1.0.1", 244 | "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", 245 | "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", 246 | "requires": { 247 | "sparkles": "^1.0.0" 248 | } 249 | }, 250 | "gulp-util": { 251 | "version": "3.0.8", 252 | "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", 253 | "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", 254 | "requires": { 255 | "array-differ": "^1.0.0", 256 | "array-uniq": "^1.0.2", 257 | "beeper": "^1.0.0", 258 | "chalk": "^1.0.0", 259 | "dateformat": "^2.0.0", 260 | "fancy-log": "^1.1.0", 261 | "gulplog": "^1.0.0", 262 | "has-gulplog": "^0.1.0", 263 | "lodash._reescape": "^3.0.0", 264 | "lodash._reevaluate": "^3.0.0", 265 | "lodash._reinterpolate": "^3.0.0", 266 | "lodash.template": "^3.0.0", 267 | "minimist": "^1.1.0", 268 | "multipipe": "^0.1.2", 269 | "object-assign": "^3.0.0", 270 | "replace-ext": "0.0.1", 271 | "through2": "^2.0.0", 272 | "vinyl": "^0.5.0" 273 | } 274 | }, 275 | "gulplog": { 276 | "version": "1.0.0", 277 | "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", 278 | "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", 279 | "requires": { 280 | "glogg": "^1.0.0" 281 | } 282 | }, 283 | "har-schema": { 284 | "version": "2.0.0", 285 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 286 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" 287 | }, 288 | "har-validator": { 289 | "version": "5.1.0", 290 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", 291 | "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", 292 | "requires": { 293 | "ajv": "^5.3.0", 294 | "har-schema": "^2.0.0" 295 | } 296 | }, 297 | "has-ansi": { 298 | "version": "2.0.0", 299 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", 300 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", 301 | "requires": { 302 | "ansi-regex": "^2.0.0" 303 | } 304 | }, 305 | "has-gulplog": { 306 | "version": "0.1.0", 307 | "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", 308 | "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", 309 | "requires": { 310 | "sparkles": "^1.0.0" 311 | } 312 | }, 313 | "http-signature": { 314 | "version": "1.2.0", 315 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 316 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 317 | "requires": { 318 | "assert-plus": "^1.0.0", 319 | "jsprim": "^1.2.2", 320 | "sshpk": "^1.7.0" 321 | } 322 | }, 323 | "inherits": { 324 | "version": "2.0.3", 325 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 326 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 327 | }, 328 | "is-typedarray": { 329 | "version": "1.0.0", 330 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 331 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" 332 | }, 333 | "isarray": { 334 | "version": "0.0.1", 335 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 336 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" 337 | }, 338 | "isstream": { 339 | "version": "0.1.2", 340 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 341 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" 342 | }, 343 | "jsbn": { 344 | "version": "0.1.1", 345 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 346 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", 347 | "optional": true 348 | }, 349 | "json-schema": { 350 | "version": "0.2.3", 351 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 352 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" 353 | }, 354 | "json-schema-traverse": { 355 | "version": "0.3.1", 356 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", 357 | "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" 358 | }, 359 | "json-stringify-safe": { 360 | "version": "5.0.1", 361 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 362 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" 363 | }, 364 | "jsprim": { 365 | "version": "1.4.1", 366 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 367 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 368 | "requires": { 369 | "assert-plus": "1.0.0", 370 | "extsprintf": "1.3.0", 371 | "json-schema": "0.2.3", 372 | "verror": "1.10.0" 373 | } 374 | }, 375 | "lodash": { 376 | "version": "4.17.10", 377 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", 378 | "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" 379 | }, 380 | "lodash._basecopy": { 381 | "version": "3.0.1", 382 | "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", 383 | "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=" 384 | }, 385 | "lodash._basetostring": { 386 | "version": "3.0.1", 387 | "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", 388 | "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=" 389 | }, 390 | "lodash._basevalues": { 391 | "version": "3.0.0", 392 | "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", 393 | "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=" 394 | }, 395 | "lodash._getnative": { 396 | "version": "3.9.1", 397 | "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", 398 | "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" 399 | }, 400 | "lodash._isiterateecall": { 401 | "version": "3.0.9", 402 | "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", 403 | "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=" 404 | }, 405 | "lodash._reescape": { 406 | "version": "3.0.0", 407 | "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", 408 | "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=" 409 | }, 410 | "lodash._reevaluate": { 411 | "version": "3.0.0", 412 | "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", 413 | "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=" 414 | }, 415 | "lodash._reinterpolate": { 416 | "version": "3.0.0", 417 | "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", 418 | "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" 419 | }, 420 | "lodash._root": { 421 | "version": "3.0.1", 422 | "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", 423 | "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=" 424 | }, 425 | "lodash.escape": { 426 | "version": "3.2.0", 427 | "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", 428 | "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", 429 | "requires": { 430 | "lodash._root": "^3.0.0" 431 | } 432 | }, 433 | "lodash.isarguments": { 434 | "version": "3.1.0", 435 | "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", 436 | "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" 437 | }, 438 | "lodash.isarray": { 439 | "version": "3.0.4", 440 | "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", 441 | "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" 442 | }, 443 | "lodash.keys": { 444 | "version": "3.1.2", 445 | "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", 446 | "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", 447 | "requires": { 448 | "lodash._getnative": "^3.0.0", 449 | "lodash.isarguments": "^3.0.0", 450 | "lodash.isarray": "^3.0.0" 451 | } 452 | }, 453 | "lodash.restparam": { 454 | "version": "3.6.1", 455 | "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", 456 | "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=" 457 | }, 458 | "lodash.template": { 459 | "version": "3.6.2", 460 | "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", 461 | "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", 462 | "requires": { 463 | "lodash._basecopy": "^3.0.0", 464 | "lodash._basetostring": "^3.0.0", 465 | "lodash._basevalues": "^3.0.0", 466 | "lodash._isiterateecall": "^3.0.0", 467 | "lodash._reinterpolate": "^3.0.0", 468 | "lodash.escape": "^3.0.0", 469 | "lodash.keys": "^3.0.0", 470 | "lodash.restparam": "^3.0.0", 471 | "lodash.templatesettings": "^3.0.0" 472 | } 473 | }, 474 | "lodash.templatesettings": { 475 | "version": "3.1.1", 476 | "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", 477 | "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", 478 | "requires": { 479 | "lodash._reinterpolate": "^3.0.0", 480 | "lodash.escape": "^3.0.0" 481 | } 482 | }, 483 | "mime-db": { 484 | "version": "1.35.0", 485 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.35.0.tgz", 486 | "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==" 487 | }, 488 | "mime-types": { 489 | "version": "2.1.19", 490 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.19.tgz", 491 | "integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==", 492 | "requires": { 493 | "mime-db": "~1.35.0" 494 | } 495 | }, 496 | "minimist": { 497 | "version": "1.2.0", 498 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", 499 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" 500 | }, 501 | "multipipe": { 502 | "version": "0.1.2", 503 | "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", 504 | "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", 505 | "requires": { 506 | "duplexer2": "0.0.2" 507 | } 508 | }, 509 | "oauth-sign": { 510 | "version": "0.9.0", 511 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 512 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" 513 | }, 514 | "object-assign": { 515 | "version": "3.0.0", 516 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", 517 | "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=" 518 | }, 519 | "performance-now": { 520 | "version": "2.1.0", 521 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 522 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" 523 | }, 524 | "process-nextick-args": { 525 | "version": "2.0.0", 526 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", 527 | "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" 528 | }, 529 | "psl": { 530 | "version": "1.1.29", 531 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", 532 | "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" 533 | }, 534 | "punycode": { 535 | "version": "1.4.1", 536 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 537 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" 538 | }, 539 | "qs": { 540 | "version": "6.5.2", 541 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 542 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" 543 | }, 544 | "querystring": { 545 | "version": "0.2.0", 546 | "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", 547 | "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" 548 | }, 549 | "readable-stream": { 550 | "version": "1.1.14", 551 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", 552 | "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", 553 | "requires": { 554 | "core-util-is": "~1.0.0", 555 | "inherits": "~2.0.1", 556 | "isarray": "0.0.1", 557 | "string_decoder": "~0.10.x" 558 | } 559 | }, 560 | "replace-ext": { 561 | "version": "0.0.1", 562 | "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", 563 | "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" 564 | }, 565 | "request": { 566 | "version": "2.88.0", 567 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", 568 | "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", 569 | "requires": { 570 | "aws-sign2": "~0.7.0", 571 | "aws4": "^1.8.0", 572 | "caseless": "~0.12.0", 573 | "combined-stream": "~1.0.6", 574 | "extend": "~3.0.2", 575 | "forever-agent": "~0.6.1", 576 | "form-data": "~2.3.2", 577 | "har-validator": "~5.1.0", 578 | "http-signature": "~1.2.0", 579 | "is-typedarray": "~1.0.0", 580 | "isstream": "~0.1.2", 581 | "json-stringify-safe": "~5.0.1", 582 | "mime-types": "~2.1.19", 583 | "oauth-sign": "~0.9.0", 584 | "performance-now": "^2.1.0", 585 | "qs": "~6.5.2", 586 | "safe-buffer": "^5.1.2", 587 | "tough-cookie": "~2.4.3", 588 | "tunnel-agent": "^0.6.0", 589 | "uuid": "^3.3.2" 590 | } 591 | }, 592 | "request-promise": { 593 | "version": "4.1.1", 594 | "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.1.1.tgz", 595 | "integrity": "sha1-JgIeT29W/Uwwn2vx69jJepWsH7U=", 596 | "requires": { 597 | "bluebird": "^3.4.1", 598 | "request-promise-core": "1.1.1", 599 | "stealthy-require": "^1.0.0" 600 | } 601 | }, 602 | "request-promise-core": { 603 | "version": "1.1.1", 604 | "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", 605 | "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", 606 | "requires": { 607 | "lodash": "^4.13.1" 608 | } 609 | }, 610 | "safe-buffer": { 611 | "version": "5.1.2", 612 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 613 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 614 | }, 615 | "safer-buffer": { 616 | "version": "2.1.2", 617 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 618 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 619 | }, 620 | "sparkles": { 621 | "version": "1.0.1", 622 | "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", 623 | "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==" 624 | }, 625 | "sshpk": { 626 | "version": "1.14.2", 627 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", 628 | "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", 629 | "requires": { 630 | "asn1": "~0.2.3", 631 | "assert-plus": "^1.0.0", 632 | "bcrypt-pbkdf": "^1.0.0", 633 | "dashdash": "^1.12.0", 634 | "ecc-jsbn": "~0.1.1", 635 | "getpass": "^0.1.1", 636 | "jsbn": "~0.1.0", 637 | "safer-buffer": "^2.0.2", 638 | "tweetnacl": "~0.14.0" 639 | } 640 | }, 641 | "stealthy-require": { 642 | "version": "1.1.1", 643 | "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", 644 | "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" 645 | }, 646 | "string_decoder": { 647 | "version": "0.10.31", 648 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 649 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" 650 | }, 651 | "strip-ansi": { 652 | "version": "3.0.1", 653 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 654 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 655 | "requires": { 656 | "ansi-regex": "^2.0.0" 657 | } 658 | }, 659 | "supports-color": { 660 | "version": "2.0.0", 661 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 662 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" 663 | }, 664 | "through2": { 665 | "version": "2.0.3", 666 | "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", 667 | "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", 668 | "requires": { 669 | "readable-stream": "^2.1.5", 670 | "xtend": "~4.0.1" 671 | }, 672 | "dependencies": { 673 | "isarray": { 674 | "version": "1.0.0", 675 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 676 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 677 | }, 678 | "readable-stream": { 679 | "version": "2.3.6", 680 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", 681 | "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", 682 | "requires": { 683 | "core-util-is": "~1.0.0", 684 | "inherits": "~2.0.3", 685 | "isarray": "~1.0.0", 686 | "process-nextick-args": "~2.0.0", 687 | "safe-buffer": "~5.1.1", 688 | "string_decoder": "~1.1.1", 689 | "util-deprecate": "~1.0.1" 690 | } 691 | }, 692 | "string_decoder": { 693 | "version": "1.1.1", 694 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 695 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 696 | "requires": { 697 | "safe-buffer": "~5.1.0" 698 | } 699 | } 700 | } 701 | }, 702 | "time-stamp": { 703 | "version": "1.1.0", 704 | "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", 705 | "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=" 706 | }, 707 | "tough-cookie": { 708 | "version": "2.4.3", 709 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", 710 | "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", 711 | "requires": { 712 | "psl": "^1.1.24", 713 | "punycode": "^1.4.1" 714 | } 715 | }, 716 | "tunnel-agent": { 717 | "version": "0.6.0", 718 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 719 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 720 | "requires": { 721 | "safe-buffer": "^5.0.1" 722 | } 723 | }, 724 | "tweetnacl": { 725 | "version": "0.14.5", 726 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 727 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", 728 | "optional": true 729 | }, 730 | "url": { 731 | "version": "0.11.0", 732 | "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", 733 | "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", 734 | "requires": { 735 | "punycode": "1.3.2", 736 | "querystring": "0.2.0" 737 | }, 738 | "dependencies": { 739 | "punycode": { 740 | "version": "1.3.2", 741 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", 742 | "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" 743 | } 744 | } 745 | }, 746 | "util": { 747 | "version": "0.10.3", 748 | "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", 749 | "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", 750 | "requires": { 751 | "inherits": "2.0.1" 752 | }, 753 | "dependencies": { 754 | "inherits": { 755 | "version": "2.0.1", 756 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", 757 | "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" 758 | } 759 | } 760 | }, 761 | "util-deprecate": { 762 | "version": "1.0.2", 763 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 764 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 765 | }, 766 | "uuid": { 767 | "version": "3.3.2", 768 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", 769 | "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" 770 | }, 771 | "verror": { 772 | "version": "1.10.0", 773 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 774 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 775 | "requires": { 776 | "assert-plus": "^1.0.0", 777 | "core-util-is": "1.0.2", 778 | "extsprintf": "^1.2.0" 779 | } 780 | }, 781 | "vinyl": { 782 | "version": "0.5.3", 783 | "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", 784 | "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", 785 | "requires": { 786 | "clone": "^1.0.0", 787 | "clone-stats": "^0.0.1", 788 | "replace-ext": "0.0.1" 789 | } 790 | }, 791 | "xtend": { 792 | "version": "4.0.1", 793 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", 794 | "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" 795 | } 796 | } 797 | } 798 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gulp-spsync", 3 | "version": "1.5.9", 4 | "description": "Gulp plugin that syncs with a library in SharePoint Online", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "test" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/wictorwilen/gulp-spsync.git" 12 | }, 13 | "keywords": [ 14 | "gulp", 15 | "sharepoint", 16 | "sync", 17 | "file", 18 | "tool", 19 | "office365" 20 | ], 21 | "dependencies": { 22 | "gulp-util": "3.0.8", 23 | "request": "^2.88.0", 24 | "request-promise": "4.1.1", 25 | "through2": "2.0.3", 26 | "url": "0.11.0", 27 | "util": "0.10.3" 28 | }, 29 | "author": "Wictor Wilén", 30 | "license": "MIT", 31 | "bugs": { 32 | "url": "https://github.com/wictorwilen/gulp-spsync/issues" 33 | }, 34 | "homepage": "https://github.com/wictorwilen/gulp-spsync", 35 | "maintainers": [ 36 | { 37 | "name": "wictor", 38 | "email": "wictor@wictorwilen.se" 39 | } 40 | ], 41 | "devDependencies": {} 42 | } 43 | --------------------------------------------------------------------------------