├── .gitignore
├── css
└── custom.style.css
├── index.html
├── js
├── OneDrive.Debug.js
└── markdown-editor.js
├── license.txt
├── readme.md
└── start-iis.bat
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | artifacts/
46 |
47 | *_i.c
48 | *_p.c
49 | *_i.h
50 | *.ilk
51 | *.meta
52 | *.obj
53 | *.pch
54 | *.pdb
55 | *.pgc
56 | *.pgd
57 | *.rsp
58 | *.sbr
59 | *.tlb
60 | *.tli
61 | *.tlh
62 | *.tmp
63 | *.tmp_proj
64 | *.log
65 | *.vspscc
66 | *.vssscc
67 | .builds
68 | *.pidb
69 | *.svclog
70 | *.scc
71 |
72 | # Chutzpah Test files
73 | _Chutzpah*
74 |
75 | # Visual C++ cache files
76 | ipch/
77 | *.aps
78 | *.ncb
79 | *.opendb
80 | *.opensdf
81 | *.sdf
82 | *.cachefile
83 |
84 | # Visual Studio profiler
85 | *.psess
86 | *.vsp
87 | *.vspx
88 | *.sap
89 |
90 | # TFS 2012 Local Workspace
91 | $tf/
92 |
93 | # Guidance Automation Toolkit
94 | *.gpState
95 |
96 | # ReSharper is a .NET coding add-in
97 | _ReSharper*/
98 | *.[Rr]e[Ss]harper
99 | *.DotSettings.user
100 |
101 | # JustCode is a .NET coding add-in
102 | .JustCode
103 |
104 | # TeamCity is a build add-in
105 | _TeamCity*
106 |
107 | # DotCover is a Code Coverage Tool
108 | *.dotCover
109 |
110 | # NCrunch
111 | _NCrunch_*
112 | .*crunch*.local.xml
113 | nCrunchTemp_*
114 |
115 | # MightyMoose
116 | *.mm.*
117 | AutoTest.Net/
118 |
119 | # Web workbench (sass)
120 | .sass-cache/
121 |
122 | # Installshield output folder
123 | [Ee]xpress/
124 |
125 | # DocProject is a documentation generator add-in
126 | DocProject/buildhelp/
127 | DocProject/Help/*.HxT
128 | DocProject/Help/*.HxC
129 | DocProject/Help/*.hhc
130 | DocProject/Help/*.hhk
131 | DocProject/Help/*.hhp
132 | DocProject/Help/Html2
133 | DocProject/Help/html
134 |
135 | # Click-Once directory
136 | publish/
137 |
138 | # Publish Web Output
139 | *.[Pp]ublish.xml
140 | *.azurePubxml
141 | # TODO: Comment the next line if you want to checkin your web deploy settings
142 | # but database connection strings (with potential passwords) will be unencrypted
143 | *.pubxml
144 | *.publishproj
145 |
146 | # NuGet Packages
147 | *.nupkg
148 | # The packages folder can be ignored because of Package Restore
149 | **/packages/*
150 | # except build/, which is used as an MSBuild target.
151 | !**/packages/build/
152 | # Uncomment if necessary however generally it will be regenerated when needed
153 | #!**/packages/repositories.config
154 | # NuGet v3's project.json files produces more ignoreable files
155 | *.nuget.props
156 | *.nuget.targets
157 |
158 | # Microsoft Azure Build Output
159 | csx/
160 | *.build.csdef
161 |
162 | # Microsoft Azure Emulator
163 | ecf/
164 | rcf/
165 |
166 | # Microsoft Azure ApplicationInsights config file
167 | ApplicationInsights.config
168 |
169 | # Windows Store app package directory
170 | AppPackages/
171 | BundleArtifacts/
172 |
173 | # Visual Studio cache files
174 | # files ending in .cache can be ignored
175 | *.[Cc]ache
176 | # but keep track of directories ending in .cache
177 | !*.[Cc]ache/
178 |
179 | # Others
180 | ClientBin/
181 | ~$*
182 | *~
183 | *.dbmdl
184 | *.dbproj.schemaview
185 | *.pfx
186 | *.publishsettings
187 | node_modules/
188 | orleans.codegen.cs
189 |
190 | # RIA/Silverlight projects
191 | Generated_Code/
192 |
193 | # Backup & report files from converting an old project file
194 | # to a newer Visual Studio version. Backup files are not needed,
195 | # because we have git ;-)
196 | _UpgradeReport_Files/
197 | Backup*/
198 | UpgradeLog*.XML
199 | UpgradeLog*.htm
200 |
201 | # SQL Server files
202 | *.mdf
203 | *.ldf
204 |
205 | # Business Intelligence projects
206 | *.rdl.data
207 | *.bim.layout
208 | *.bim_*.settings
209 |
210 | # Microsoft Fakes
211 | FakesAssemblies/
212 |
213 | # GhostDoc plugin setting file
214 | *.GhostDoc.xml
215 |
216 | # Node.js Tools for Visual Studio
217 | .ntvs_analysis.dat
218 |
219 | # Visual Studio 6 build log
220 | *.plg
221 |
222 | # Visual Studio 6 workspace options file
223 | *.opt
224 |
225 | # Visual Studio LightSwitch build output
226 | **/*.HTMLClient/GeneratedArtifacts
227 | **/*.DesktopClient/GeneratedArtifacts
228 | **/*.DesktopClient/ModelManifest.xml
229 | **/*.Server/GeneratedArtifacts
230 | **/*.Server/ModelManifest.xml
231 | _Pvt_Extensions
232 |
233 | # Paket dependency manager
234 | .paket/paket.exe
235 |
236 | # FAKE - F# Make
237 | .fake/
238 |
--------------------------------------------------------------------------------
/css/custom.style.css:
--------------------------------------------------------------------------------
1 | body {
2 | height: 100%;
3 | }
4 |
5 | div.textEditor {
6 | position: absolute;
7 | left: 10px;
8 | right: 10px;
9 | width: auto;
10 | height: auto;
11 | top: 60px;
12 | bottom: 10px;
13 | box-sizing: border-box;
14 | -moz-box-sizing: border-box;
15 | -webkit-box-sizing: border-box;
16 | }
17 |
18 | textarea#canvas {
19 | font-family: Consolas;
20 | font-size: 12pt;
21 | width: 100%;
22 | height: 100%;
23 | box-sizing: border-box;
24 | -moz-box-sizing: border-box;
25 | -webkit-box-sizing: border-box;
26 | resize: none;
27 | }
28 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | OneDrive Markdown Editor Sample
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
28 |
29 |
30 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/js/OneDrive.Debug.js:
--------------------------------------------------------------------------------
1 | //! Copyright (c) Microsoft Corporation. All rights reserved.
2 | var __extends = (this && this.__extends) || function (d, b) {for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];function __() { this.constructor = d; }__.prototype = b.prototype;d.prototype = new __();};
3 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.OneDrive = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o ACCESS_TOKEN_LIFESPAN;
593 | }
594 | exports.loginHintExpired = loginHintExpired;
595 | function updateLoginHint(clientId, idToken, invokerOptions) {
596 | var loginHint;
597 | var domainHint;
598 | var endpointHint;
599 | var apiEndpoint;
600 | switch (invokerOptions.endpointHint) {
601 | case DomainHint_1.default.aad:
602 | var idTokenObj = this.parseIdToken(idToken);
603 | loginHint = idTokenObj.preferredUserName;
604 | if (idTokenObj.tid === Constants_1.default.CUSTOMER_TID) {
605 | apiEndpoint = ApiEndpoint_1.default.graph_odc;
606 | domainHint = "consumers";
607 | } else {
608 | apiEndpoint = ApiEndpoint_1.default.graph_odb;
609 | domainHint = "organizations";
610 | }
611 | endpointHint = DomainHint_1.default.aad;
612 | break;
613 | case DomainHint_1.default.msa:
614 | apiEndpoint = ApiEndpoint_1.default.msa;
615 | endpointHint = DomainHint_1.default.msa;
616 | loginHint = invokerOptions.loginHint;
617 | domainHint = "consumers";
618 | break;
619 | case DomainHint_1.default.tenant:
620 | apiEndpoint = ApiEndpoint_1.default.filesV2;
621 | endpointHint = DomainHint_1.default.tenant;
622 | loginHint = invokerOptions.loginHint;
623 | domainHint = "organizations";
624 | break;
625 | }
626 | var newLoginHint = {
627 | apiEndpoint: apiEndpoint,
628 | loginHint: loginHint,
629 | domainHint: domainHint,
630 | endpointHint: endpointHint,
631 | timeStamp: new Date().getTime()
632 | };
633 | var loginCache = Cache_1.getCacheItem(LOGINHINT_KEY) || {};
634 | loginCache[LOGINHINT_ITEM_PREFIX + clientId] = newLoginHint;
635 | Cache_1.setCacheItem(LOGINHINT_KEY, loginCache);
636 | return newLoginHint;
637 | }
638 | exports.updateLoginHint = updateLoginHint;
639 | function parseIdToken(idToken) {
640 | if (!idToken) {
641 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.badResponse, 'id_token is missing in oauth response'));
642 | }
643 | var userInfoPart = idToken.split('.')[1];
644 | var urlFriendlyValue = userInfoPart.replace('-', '+').replace('_', '/');
645 | var userInfo = ObjectUtilities_1.deserializeJSON(atob(urlFriendlyValue));
646 | if (!userInfo[ID_TOKEN_TID]) {
647 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.badResponse, 'tid is missing in id_token response'));
648 | }
649 | if (!userInfo[ID_TOKEN_PREFERRED_USERNAME]) {
650 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.badResponse, 'preferred_username is missing in id_token response'));
651 | }
652 | return {
653 | tid: userInfo[ID_TOKEN_TID],
654 | preferredUserName: userInfo[ID_TOKEN_PREFERRED_USERNAME]
655 | };
656 | }
657 | exports.parseIdToken = parseIdToken;
658 | }(require, exports, require('../models/ApiEndpoint'), require('../utilities/Cache'), require('../Constants'), require('../models/DomainHint'), require('../utilities/ErrorHandler'), require('../models/ErrorType'), require('../models/OneDriveSdkError'), require('../utilities/ObjectUtilities')));
659 | },{"../Constants":1,"../models/ApiEndpoint":11,"../models/DomainHint":12,"../models/ErrorType":13,"../models/OneDriveSdkError":16,"../utilities/Cache":22,"../utilities/ErrorHandler":26,"../utilities/ObjectUtilities":28}],7:[function(require,module,exports){
660 | (function (require, exports, Channel_1, DomainHint_1, DomUtilities_1, ErrorHandler_1, ErrorType_1, LoginCache_1, OauthEndpoint_1, OneDriveSdkError_1, es6_promise_1, UrlUtilities_1) {
661 | 'use strict';
662 | var PARAM_ACCESS_TOKEN = 'access_token';
663 | var PARAM_ERROR = 'error';
664 | var PARAM_ERROR_DESCRIPTION = 'error_description';
665 | var PARAM_ID_TOKEN = 'id_token';
666 | var PARAM_OAUTH_CONFIG = 'oauth';
667 | var PARAM_STATE = 'state';
668 | var AAD_OAUTH_ENDPOINT = 'https://login.microsoftonline.com/common/oauth2/authorize';
669 | var AADV2_OAUTH_ENDPOINT = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize';
670 | var MSA_OAUTH_ENDPONT = 'https://login.live.com/oauth20_authorize.srf';
671 | var OAUTH_RESPONSE_HEADER = '[OneDriveSDK-OauthResponse]';
672 | function onAuth() {
673 | DomUtilities_1.onDocumentReady(function () {
674 | var redirResults = UrlUtilities_1.readCurrentUrlParameters();
675 | var isOauth = redirResults[PARAM_OAUTH_CONFIG] || redirResults[PARAM_ERROR] || redirResults[PARAM_ACCESS_TOKEN];
676 | if (isOauth && window.opener) {
677 | handleOauth(redirResults, new Channel_1.default(window.opener));
678 | }
679 | });
680 | }
681 | exports.onAuth = onAuth;
682 | function handleOauth(redirResults, channel) {
683 | DomUtilities_1.displayOverlay();
684 | if (redirResults[PARAM_OAUTH_CONFIG]) {
685 | redirectToOauthPage(JSON.parse(redirResults[PARAM_OAUTH_CONFIG]));
686 | } else if (redirResults[PARAM_ERROR]) {
687 | sendResponseToParent(generateErrorResponse(redirResults), channel);
688 | } else if (redirResults[PARAM_ACCESS_TOKEN]) {
689 | sendResponseToParent(generateSuccessResponse(redirResults), channel);
690 | }
691 | }
692 | exports.handleOauth = handleOauth;
693 | function generateErrorResponse(redirResults) {
694 | var error = new OneDriveSdkError_1.default(ErrorType_1.default.badResponse, redirResults[PARAM_ERROR_DESCRIPTION]);
695 | return {
696 | type: 'error',
697 | error: error,
698 | state: redirResults[PARAM_STATE]
699 | };
700 | }
701 | function generateSuccessResponse(redirResults) {
702 | return {
703 | type: 'success',
704 | accessToken: redirResults[PARAM_ACCESS_TOKEN],
705 | idToken: redirResults[PARAM_ID_TOKEN],
706 | state: redirResults[PARAM_STATE]
707 | };
708 | }
709 | function sendResponseToParent(response, channel) {
710 | if (response.state) {
711 | var responseFragment = response.state.split('_');
712 | if (responseFragment.length !== 2) {
713 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.badResponse, 'received bad state parameter from Oauth endpoint, state received: ' + response.state)).exposeToPublic();
714 | }
715 | var origin = responseFragment[0];
716 | if (channel) {
717 | channel.send(OAUTH_RESPONSE_HEADER + JSON.stringify(response), origin);
718 | } else {
719 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.popupOpen, 'opener is not defined')).exposeToPublic();
720 | }
721 | } else {
722 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.badResponse, 'missing state parameter from Oauth redirect')).exposeToPublic();
723 | }
724 | }
725 | function redirectToOauthPage(oauthConfig) {
726 | var url;
727 | switch (oauthConfig.endpoint) {
728 | case OauthEndpoint_1.default.AAD:
729 | url = buildAADOauthUrl(oauthConfig);
730 | break;
731 | case OauthEndpoint_1.default.AADv2:
732 | url = buildAADOauthV2Url(oauthConfig);
733 | break;
734 | case OauthEndpoint_1.default.MSA:
735 | url = buildMSAOauthUrl(oauthConfig);
736 | break;
737 | default:
738 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.badResponse, 'received bad oauth endpoint, endpoint value is: ' + oauthConfig.endpoint));
739 | break;
740 | }
741 | if (oauthConfig.switchAccount) {
742 | url = UrlUtilities_1.appendQueryString(url, 'prompt', 'select_account');
743 | } else if (oauthConfig.loginHint) {
744 | url = UrlUtilities_1.appendQueryString(url, 'login_hint', oauthConfig.loginHint);
745 | if (oauthConfig.domainHint) {
746 | url = UrlUtilities_1.appendQueryString(url, 'domain_hint', oauthConfig.domainHint);
747 | }
748 | }
749 |
750 | UrlUtilities_1.redirect(url);
751 | }
752 | function buildAADOauthUrl(config) {
753 | return UrlUtilities_1.appendQueryStrings(AAD_OAUTH_ENDPOINT, {
754 | redirect_uri: config.redirectUri,
755 | client_id: config.clientId,
756 | response_type: 'token',
757 | state: config.state,
758 | resource: config.origin
759 | });
760 | }
761 | function buildAADOauthV2Url(config) {
762 | var scope = 'profile openid https://graph.microsoft.com/User.Read ' + config.scopes.map(function (s) {
763 | return 'https://graph.microsoft.com/' + s;
764 | }).join(' ');
765 | var url = UrlUtilities_1.appendQueryStrings(AADV2_OAUTH_ENDPOINT, {
766 | redirect_uri: config.redirectUri,
767 | client_id: config.clientId,
768 | scope: scope,
769 | response_mode: 'fragment',
770 | state: config.state,
771 | nonce: UrlUtilities_1.generateNonce()
772 | });
773 | url += '&response_type=id_token+token';
774 | return url;
775 | }
776 | function buildMSAOauthUrl(config) {
777 | var needWritePermission = false;
778 | for (var _i = 0, _a = config.scopes; _i < _a.length; _i++) {
779 | var scope = _a[_i];
780 | needWritePermission = needWritePermission || scope.toLowerCase().indexOf('readwrite') > 1;
781 | }
782 | return UrlUtilities_1.appendQueryStrings(MSA_OAUTH_ENDPONT, {
783 | redirect_uri: config.redirectUri,
784 | client_id: config.clientId,
785 | response_type: 'token',
786 | state: config.state,
787 | scope: 'onedrive.' + (needWritePermission ? 'readwrite' : 'readonly')
788 | });
789 | }
790 | function auth(config, popupView) {
791 | var state = document.location.origin + '_' + UrlUtilities_1.generateNonce();
792 | config.state = state;
793 | return new es6_promise_1.Promise(function (resolve, reject) {
794 | var listenerId = DomUtilities_1.onMessage(function (event) {
795 | if (event.data && event.data.indexOf(OAUTH_RESPONSE_HEADER) === 0) {
796 | var responseData = JSON.parse(event.data.substring(OAUTH_RESPONSE_HEADER.length));
797 | if (responseData.state === state && event.source === popupView.getPopupWindow()) {
798 | DomUtilities_1.removeMessageListener(listenerId);
799 | if (responseData.type === 'error' || responseData.error) {
800 | var errorCode = ErrorType_1.default[responseData.error.errorCode];
801 | reject(new OneDriveSdkError_1.default(errorCode, responseData.error.message));
802 | } else {
803 | resolve(responseData);
804 | }
805 | } else {
806 | reject(new OneDriveSdkError_1.default(ErrorType_1.default.popupOpen, 'Another popup is already opened.'));
807 | }
808 | }
809 | });
810 | return popupView.openPopup(config.redirectUri + '?' + PARAM_OAUTH_CONFIG + '=' + JSON.stringify(config)).then(function () {
811 | resolve({
812 | type: 'cancel',
813 | state: state
814 | });
815 | });
816 | });
817 | }
818 | exports.auth = auth;
819 | function buildOauthConfig(invokerOptions, switchAccount) {
820 | var endpoint;
821 | switch (invokerOptions.endpointHint) {
822 | case DomainHint_1.default.aad:
823 | endpoint = OauthEndpoint_1.default.AADv2;
824 | break;
825 | case DomainHint_1.default.msa:
826 | endpoint = OauthEndpoint_1.default.MSA;
827 | break;
828 | case DomainHint_1.default.tenant:
829 | endpoint = OauthEndpoint_1.default.AAD;
830 | break;
831 | }
832 | var loginHint = LoginCache_1.getLoginHint(invokerOptions);
833 | var scopes = invokerOptions.scopes.map(function (s) {
834 | return s + (s.indexOf('Files.') > -1 && invokerOptions.needSharePointPermission ? '.All' : '');
835 | });
836 | return {
837 | clientId: invokerOptions.clientId,
838 | endpoint: endpoint,
839 | scopes: scopes,
840 | loginHint: invokerOptions.loginHint || (loginHint ? loginHint.loginHint : null),
841 | domainHint: invokerOptions.domainHint || (loginHint ? loginHint.domainHint : null),
842 | origin: window.location.origin,
843 | redirectUri: invokerOptions.redirectUri,
844 | switchAccount: switchAccount
845 | };
846 | }
847 | exports.buildOauthConfig = buildOauthConfig;
848 | }(require, exports, require('../utilities/Channel'), require('../models/DomainHint'), require('../utilities/DomUtilities'), require('../utilities/ErrorHandler'), require('../models/ErrorType'), require('./LoginCache'), require('../models/OauthEndpoint'), require('../models/OneDriveSdkError'), require('es6-promise'), require('../utilities/UrlUtilities')));
849 | },{"../models/DomainHint":12,"../models/ErrorType":13,"../models/OauthEndpoint":15,"../models/OneDriveSdkError":16,"../utilities/Channel":24,"../utilities/DomUtilities":25,"../utilities/ErrorHandler":26,"../utilities/UrlUtilities":32,"./LoginCache":6,"es6-promise":34}],8:[function(require,module,exports){
850 | (function (require, exports, ApiEndpoint_1, ApiRequest_1, Constants_1, Invoker_1, ObjectUtilities_1, PickerOptions_1, PickerActionType_1, StringUtilities_1, UrlUtilities_1) {
851 | 'use strict';
852 | var Picker = function (_super) {
853 | __extends(Picker, _super);
854 | function Picker(options) {
855 | var clonedOptions = ObjectUtilities_1.shallowClone(options);
856 | var pickerOptions = new PickerOptions_1.default(clonedOptions);
857 | _super.call(this, pickerOptions);
858 | }
859 | Picker.prototype.launchPicker = function () {
860 | return _super.prototype.launchInvoker.call(this);
861 | };
862 | Picker.prototype.buildPickerUXConfig = function (pickerOptions) {
863 | var pickerUXConfig = {
864 | applicationId: pickerOptions.clientId,
865 | accessLevel: Picker.ACCESS_LEVEL,
866 | filter: pickerOptions.filter,
867 | id: UrlUtilities_1.generateNonce(),
868 | navEnabled: pickerOptions.navEnabled,
869 | origin: window.location.origin,
870 | parentDiv: pickerOptions.parentDiv,
871 | redirectUri: pickerOptions.redirectUri,
872 | selectionMode: pickerOptions.multiSelect ? 'multiple' : 'single',
873 | viewType: Picker.VIEW_TYPE
874 | };
875 | return pickerUXConfig;
876 | };
877 | Picker.prototype.makeApiRequest = function (files) {
878 | if (this.invokerOptions.action === PickerActionType_1.default.share) {
879 | return this.shareItems(files);
880 | } else {
881 | var isDownload = this.invokerOptions.action === PickerActionType_1.default.download;
882 | return this.queryItems(files, isDownload);
883 | }
884 | };
885 | Picker.prototype.queryItems = function (files, isDownload) {
886 | var itemQuery = this.invokerOptions.queryParameters || Constants_1.default.DEFAULT_QUERY_ITEM_PARAMETER;
887 | if (isDownload) {
888 | itemQuery = StringUtilities_1.format('{0}{1}{2}', itemQuery, itemQuery.indexOf('select') === -1 ? '&select=' : ',', 'name,size,@content.downloadUrl');
889 | }
890 | return ApiRequest_1.getItems(files, this.getApiRequestConfig(), itemQuery);
891 | };
892 | Picker.prototype.shareItems = function (files) {
893 | var _this = this;
894 | var pickerOptions = this.invokerOptions;
895 | var createLinkParameters = pickerOptions.createLinkParameters || this.getDefaultSharingConfig();
896 | return ApiRequest_1.getItems(files, this.getApiRequestConfig()).then(function (files) {
897 | return ApiRequest_1.shareItems(files, _this.getApiRequestConfig(), createLinkParameters);
898 | });
899 | };
900 | Picker.prototype.getDefaultSharingConfig = function () {
901 | var createLinkParameters = { 'type': 'view' };
902 | if (this.getApiRequestConfig().apiEndpoint === ApiEndpoint_1.default.graph_odc || this.getApiRequestConfig().apiEndpoint === ApiEndpoint_1.default.msa) {
903 | return createLinkParameters;
904 | }
905 | createLinkParameters['scope'] = 'organization';
906 | return createLinkParameters;
907 | };
908 | Picker.ACCESS_LEVEL = 'read';
909 | Picker.VIEW_TYPE = 'files';
910 | return Picker;
911 | }(Invoker_1.default);
912 | Object.defineProperty(exports, '__esModule', { value: true });
913 | exports.default = Picker;
914 | }(require, exports, require('../models/ApiEndpoint'), require('./ApiRequest'), require('../Constants'), require('./Invoker'), require('../utilities/ObjectUtilities'), require('../models/PickerOptions'), require('../models/PickerActionType'), require('../utilities/StringUtilities'), require('../utilities/UrlUtilities')));
915 | },{"../Constants":1,"../models/ApiEndpoint":11,"../models/PickerActionType":17,"../models/PickerOptions":18,"../utilities/ObjectUtilities":28,"../utilities/StringUtilities":30,"../utilities/UrlUtilities":32,"./ApiRequest":4,"./Invoker":5}],9:[function(require,module,exports){
916 | (function (require, exports, ApiEndpoint_1, Channel_1, DomUtilities_1, ErrorHandler_1, ErrorType_1, Logging_1, OneDriveSdkError_1, UrlUtilities_1, es6_promise_1, Constants_1) {
917 | 'use strict';
918 | var CUSTOMER_PICKER_BASE_URL = 'https://onedrive.live.com/';
919 | var RESPONSE_PREFIX = '[OneDrive-FromPicker]';
920 | var MESSAGE_PREFIX = '[OneDrive-ToPicker]';
921 | var INITIALIZE_RESPONSE = 'initialize';
922 | function generatePickerUX(apiEndpoint, tenantUrl) {
923 | return new PickerUX(apiEndpoint, tenantUrl);
924 | }
925 | exports.generatePickerUX = generatePickerUX;
926 | var PickerUX = function () {
927 | function PickerUX(apiEndpoint, tenantUrl) {
928 | if (apiEndpoint === ApiEndpoint_1.default.graph_odc || apiEndpoint === ApiEndpoint_1.default.msa) {
929 | this.url = UrlUtilities_1.appendQueryStrings(CUSTOMER_PICKER_BASE_URL, { 'v': '2' });
930 | } else if (apiEndpoint === ApiEndpoint_1.default.graph_odb || apiEndpoint === ApiEndpoint_1.default.filesV2) {
931 | if (!tenantUrl) {
932 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'the site url must be specified')).exposeToPublic();
933 | }
934 | UrlUtilities_1.validateUrlProtocol(tenantUrl, ['HTTPS']);
935 | if (apiEndpoint === ApiEndpoint_1.default.graph_odb) {
936 | tenantUrl = UrlUtilities_1.appendToPath(tenantUrl, '_layouts/onedrive.aspx');
937 | }
938 | this.url = UrlUtilities_1.appendQueryString(tenantUrl, 'p', '2');
939 | }
940 | }
941 | PickerUX.prototype.invokePickerUX = function (uxConfig, popupView) {
942 | var _this = this;
943 | var receivedResponse = false;
944 | var pickerUXPromise = new es6_promise_1.Promise(function (resolve, reject) {
945 | var channelId = DomUtilities_1.onMessage(function (event) {
946 | var urlParts = _this.url.split('/');
947 | var channel = new Channel_1.default(_this.iframe ? _this.iframe.contentWindow : popupView.getPopupWindow());
948 | if (event.origin === urlParts[0] + '//' + urlParts[2]) {
949 | var message = '' + (event.data || '');
950 | if (message.indexOf(RESPONSE_PREFIX) === 0 && event.source === channel.getReceiver()) {
951 | var response = JSON.parse(message.substring(RESPONSE_PREFIX.length));
952 | var pickerId = response.pickerId, conversationId = response.conversationId, type = response.type;
953 | if (pickerId === uxConfig.id) {
954 | if (type === INITIALIZE_RESPONSE) {
955 | channel.send(MESSAGE_PREFIX + JSON.stringify({
956 | pickerId: pickerId,
957 | conversationId: conversationId,
958 | type: 'activate'
959 | }), event.origin);
960 | } else {
961 | receivedResponse = true;
962 | resolve(response);
963 | DomUtilities_1.removeMessageListener(channelId);
964 | }
965 | }
966 | } else {
967 | reject(new OneDriveSdkError_1.default(ErrorType_1.default.badResponse, 'received invalid response from picker UI'));
968 | }
969 | }
970 | });
971 | var pickerOption = {
972 | aid: uxConfig.applicationId,
973 | a: uxConfig.accessLevel,
974 | id: uxConfig.id,
975 | l: uxConfig.linkType,
976 | ln: uxConfig.navEnabled,
977 | s: uxConfig.selectionMode,
978 | f: uxConfig.filter,
979 | v: uxConfig.viewType,
980 | ru: uxConfig.redirectUri,
981 | o: uxConfig.origin,
982 | sdk: Constants_1.default.SDK_VERSION_NUMBER,
983 | e: uxConfig.entryLocation,
984 | st: uxConfig.sourceTypes,
985 | sn: !uxConfig.parentDiv,
986 | ss: !uxConfig.parentDiv
987 | };
988 | var pickerUrl = UrlUtilities_1.appendQueryString(_this.url, 'picker', JSON.stringify(pickerOption));
989 | Logging_1.default.logMessage('invoke picker with url: ' + pickerUrl);
990 | if (uxConfig.parentDiv) {
991 | popupView.close();
992 | var iframe = document.createElement('iframe');
993 | iframe.id = 'odpicker' + new Date().getTime();
994 | iframe.style.position = 'relative';
995 | iframe.style.width = '100%';
996 | iframe.style.height = '100%';
997 | iframe.src = pickerUrl;
998 | uxConfig.parentDiv.appendChild(iframe);
999 | _this.iframe = iframe;
1000 | } else {
1001 | return popupView.openPopup(pickerUrl).then(function () {
1002 | resolve({ type: 'cancel' });
1003 | });
1004 | }
1005 | });
1006 | return pickerUXPromise;
1007 | };
1008 | PickerUX.prototype.removeIFrame = function () {
1009 | if (this.iframe) {
1010 | this.iframe.parentNode.removeChild(this.iframe);
1011 | this.iframe = null;
1012 | }
1013 | };
1014 | return PickerUX;
1015 | }();
1016 | Object.defineProperty(exports, '__esModule', { value: true });
1017 | exports.default = PickerUX;
1018 | }(require, exports, require('../models/ApiEndpoint'), require('../utilities/Channel'), require('../utilities/DomUtilities'), require('../utilities/ErrorHandler'), require('../models/ErrorType'), require('../utilities/Logging'), require('../models/OneDriveSdkError'), require('../utilities/UrlUtilities'), require('es6-promise'), require('../Constants')));
1019 | },{"../Constants":1,"../models/ApiEndpoint":11,"../models/ErrorType":13,"../models/OneDriveSdkError":16,"../utilities/Channel":24,"../utilities/DomUtilities":25,"../utilities/ErrorHandler":26,"../utilities/Logging":27,"../utilities/UrlUtilities":32,"es6-promise":34}],10:[function(require,module,exports){
1020 | (function (require, exports, ApiRequest_1, Constants_1, Invoker_1, ObjectUtilities_1, SaverActionType_1, SaverOptions_1, UploadType_1, UrlUtilities_1) {
1021 | 'use strict';
1022 | var ACCESS_LEVEL = 'readwrite';
1023 | var VIEW_TYPE = 'folders';
1024 | var SELECTION_MODE = 'single';
1025 | var Saver = function (_super) {
1026 | __extends(Saver, _super);
1027 | function Saver(options) {
1028 | var clonedOptions = ObjectUtilities_1.shallowClone(options);
1029 | var saverOptions = new SaverOptions_1.default(clonedOptions);
1030 | _super.call(this, saverOptions);
1031 | }
1032 | Saver.prototype.launchSaver = function () {
1033 | return _super.prototype.launchInvoker.call(this);
1034 | };
1035 | Saver.prototype.buildPickerUXConfig = function (saverOptions) {
1036 | return {
1037 | applicationId: saverOptions.clientId,
1038 | accessLevel: ACCESS_LEVEL,
1039 | id: UrlUtilities_1.generateNonce(),
1040 | navEnabled: saverOptions.navEnabled,
1041 | filter: saverOptions.filter,
1042 | origin: window.location.origin,
1043 | parentDiv: saverOptions.parentDiv,
1044 | redirectUri: saverOptions.redirectUri,
1045 | selectionMode: SELECTION_MODE,
1046 | viewType: VIEW_TYPE
1047 | };
1048 | };
1049 | Saver.prototype.makeApiRequest = function (files) {
1050 | var saverOptions = this.invokerOptions;
1051 | if (this.invokerOptions.action === SaverActionType_1.default.query) {
1052 | var itemQuery = this.invokerOptions.queryParameters || Constants_1.default.DEFAULT_QUERY_ITEM_PARAMETER;
1053 | return ApiRequest_1.getItems(files, this.apiRequestConfig, itemQuery);
1054 | } else if (saverOptions.uploadType === UploadType_1.default.dataUrl || saverOptions.uploadType === UploadType_1.default.url) {
1055 | var uploadItemDescription = { name: saverOptions.fileName };
1056 | return ApiRequest_1.saveItemByUriUpload(files.value[0], uploadItemDescription, saverOptions.sourceUri, this.apiRequestConfig);
1057 | } else if (saverOptions.uploadType === UploadType_1.default.form) {
1058 | var uploadItemDescription = {
1059 | name: saverOptions.fileName,
1060 | '@name.conflictBehavior': saverOptions.nameConflictBehavior
1061 | };
1062 | return ApiRequest_1.saveItemByFormUpload(files.value[0], uploadItemDescription, saverOptions.fileInput, this.apiRequestConfig, saverOptions.progress);
1063 | }
1064 | };
1065 | return Saver;
1066 | }(Invoker_1.default);
1067 | Object.defineProperty(exports, '__esModule', { value: true });
1068 | exports.default = Saver;
1069 | }(require, exports, require('./ApiRequest'), require('../Constants'), require('./Invoker'), require('../utilities/ObjectUtilities'), require('../models/SaverActionType'), require('../models/SaverOptions'), require('../models/UploadType'), require('../utilities/UrlUtilities')));
1070 | },{"../Constants":1,"../models/SaverActionType":19,"../models/SaverOptions":20,"../models/UploadType":21,"../utilities/ObjectUtilities":28,"../utilities/UrlUtilities":32,"./ApiRequest":4,"./Invoker":5}],11:[function(require,module,exports){
1071 | (function (require, exports) {
1072 | 'use strict';
1073 | var ApiEndpoint;
1074 | (function (ApiEndpoint) {
1075 | ApiEndpoint[ApiEndpoint['filesV2'] = 0] = 'filesV2';
1076 | ApiEndpoint[ApiEndpoint['graph_odc'] = 1] = 'graph_odc';
1077 | ApiEndpoint[ApiEndpoint['graph_odb'] = 2] = 'graph_odb';
1078 | ApiEndpoint[ApiEndpoint['msa'] = 3] = 'msa';
1079 | }(ApiEndpoint || (ApiEndpoint = {})));
1080 | Object.defineProperty(exports, '__esModule', { value: true });
1081 | exports.default = ApiEndpoint;
1082 | }(require, exports));
1083 | },{}],12:[function(require,module,exports){
1084 | (function (require, exports) {
1085 | 'use strict';
1086 | var DomainHint;
1087 | (function (DomainHint) {
1088 | DomainHint[DomainHint['aad'] = 0] = 'aad';
1089 | DomainHint[DomainHint['msa'] = 1] = 'msa';
1090 | DomainHint[DomainHint['tenant'] = 2] = 'tenant';
1091 | }(DomainHint || (DomainHint = {})));
1092 | Object.defineProperty(exports, '__esModule', { value: true });
1093 | exports.default = DomainHint;
1094 | }(require, exports));
1095 | },{}],13:[function(require,module,exports){
1096 | (function (require, exports) {
1097 | 'use strict';
1098 | var ErrorType;
1099 | (function (ErrorType) {
1100 | ErrorType[ErrorType['badResponse'] = 0] = 'badResponse';
1101 | ErrorType[ErrorType['fileReaderFailure'] = 1] = 'fileReaderFailure';
1102 | ErrorType[ErrorType['popupOpen'] = 2] = 'popupOpen';
1103 | ErrorType[ErrorType['unknown'] = 3] = 'unknown';
1104 | ErrorType[ErrorType['unsupportedFeature'] = 4] = 'unsupportedFeature';
1105 | ErrorType[ErrorType['webRequestFailure'] = 5] = 'webRequestFailure';
1106 | ErrorType[ErrorType['internalError'] = 6] = 'internalError';
1107 | ErrorType[ErrorType['optionsError'] = 7] = 'optionsError';
1108 | ErrorType[ErrorType['typeError'] = 8] = 'typeError';
1109 | ErrorType[ErrorType['popupClosed'] = 9] = 'popupClosed';
1110 | }(ErrorType || (ErrorType = {})));
1111 | Object.defineProperty(exports, '__esModule', { value: true });
1112 | exports.default = ErrorType;
1113 | }(require, exports));
1114 | },{}],14:[function(require,module,exports){
1115 | (function (require, exports, CallbackInvoker_1, Constants_1, DomainHint_1, ErrorHandler_1, ErrorType_1, Logging_1, OneDriveSdkError_1, StringUtilities_1, TypeValidators_1, UrlUtilities_1) {
1116 | 'use strict';
1117 | var AAD_APPID_PATTERN = new RegExp('^[a-fA-F\\d]{8}-([a-fA-F\\d]{4}-){3}[a-fA-F\\d]{12}$');
1118 | var InvokerOptions = function () {
1119 | function InvokerOptions(options) {
1120 | this.navEnabled = true;
1121 | this.needSharePointPermission = true;
1122 | this.clientId = TypeValidators_1.validateType(options.clientId, Constants_1.default.TYPE_STRING);
1123 | var cancelCallback = TypeValidators_1.validateCallback(options.cancel, true);
1124 | this.cancel = function () {
1125 | Logging_1.default.logMessage('user cancelled operation');
1126 | if (cancelCallback) {
1127 | CallbackInvoker_1.invokeAppCallback(cancelCallback, true);
1128 | }
1129 | };
1130 | var errorCallback = TypeValidators_1.validateCallback(options.error, true);
1131 | this.error = function (error) {
1132 | if (errorCallback) {
1133 | CallbackInvoker_1.invokeAppCallback(errorCallback, true, error);
1134 | } else {
1135 | throw error;
1136 | }
1137 | };
1138 | this.parseAdvancedOptions(options);
1139 | this.redirectUri = this.redirectUri || UrlUtilities_1.trimUrlQuery(window.location.href);
1140 | this.endpointHint = this.endpointHint || DomainHint_1.default.aad;
1141 | InvokerOptions.checkClientId(this.clientId);
1142 | }
1143 | InvokerOptions.checkClientId = function (clientId) {
1144 | if (clientId) {
1145 | if (AAD_APPID_PATTERN.test(clientId)) {
1146 | Logging_1.default.logMessage('parsed client id: ' + clientId);
1147 | } else {
1148 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.unknown, StringUtilities_1.format('invalid format for client id \'{0}\' - AAD: 32 characters (HEX) GUID', clientId)));
1149 | }
1150 | } else {
1151 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.unknown, 'client id is missing in options'));
1152 | }
1153 | };
1154 | InvokerOptions.prototype.needOauth = function () {
1155 | return this.needAPICall() && !this.accessToken || this.endpointHint === DomainHint_1.default.aad;
1156 | };
1157 | InvokerOptions.prototype.parseAdvancedOptions = function (options) {
1158 | if (options.advanced) {
1159 | if (!!options.advanced.redirectUri) {
1160 | UrlUtilities_1.validateRedirectUrlHost(options.advanced.redirectUri);
1161 | this.redirectUri = options.advanced.redirectUri;
1162 | }
1163 | if (!!options.advanced.queryParameters) {
1164 | var itemQueries = UrlUtilities_1.readUrlParameters('?' + options.advanced.queryParameters);
1165 | for (var key in itemQueries) {
1166 | if (key.toLowerCase() !== 'select' && key.toLowerCase() !== 'expand') {
1167 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, StringUtilities_1.format('unexpected query key: {0} is found in advanced.queryParameters', key)));
1168 | }
1169 | }
1170 | var selectQuery = itemQueries['select'];
1171 | var expandQuery = itemQueries['expand'];
1172 | if (selectQuery && expandQuery) {
1173 | this.queryParameters = StringUtilities_1.format('expand={0}&select={1}', expandQuery, selectQuery);
1174 | } else if (expandQuery) {
1175 | this.queryParameters = StringUtilities_1.format('expand={0}', expandQuery);
1176 | } else if (selectQuery) {
1177 | if ('select=' + selectQuery.split(',').sort().join(',') !== Constants_1.default.DEFAULT_QUERY_ITEM_PARAMETER) {
1178 | this.queryParameters = StringUtilities_1.format('select={0}', selectQuery);
1179 | }
1180 | }
1181 | }
1182 | if (!!options.advanced.endpointHint) {
1183 | if (options.advanced.endpointHint.toLowerCase() === Constants_1.default.VROOM_ENDPOINT_HINT) {
1184 | this.endpointHint = DomainHint_1.default.msa;
1185 | } else {
1186 | var domainHint = TypeValidators_1.validateType(options.advanced.endpointHint, 'string', false);
1187 | UrlUtilities_1.validateUrlProtocol(domainHint);
1188 | this.endpointHint = DomainHint_1.default.tenant;
1189 | this.siteUrl = domainHint;
1190 | }
1191 | if (!!options.advanced.accessToken) {
1192 | this.accessToken = options.advanced.accessToken;
1193 | }
1194 | }
1195 | if (!!options.advanced.iframeParentDiv) {
1196 | if (!options.advanced.iframeParentDiv.nodeName || options.advanced.iframeParentDiv.nodeName.toLowerCase() !== 'div') {
1197 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'the iframe\'s parent div element is not a DOM object')).exposeToPublic();
1198 | }
1199 | this.parentDiv = options.advanced.iframeParentDiv;
1200 | }
1201 | if (!!options.advanced.scopes) {
1202 | if (typeof options.advanced.scopes === 'string') {
1203 | this.scopes = [options.advanced.scopes];
1204 | } else if (options.advanced.scopes instanceof Array) {
1205 | this.scopes = options.advanced.scopes;
1206 | }
1207 | }
1208 | this.linkType = options.advanced.linkType;
1209 | this.parseNavigationOptions(options.advanced.navigation);
1210 | this.loginHint = options.advanced.loginHint;
1211 | this.filter = options.advanced.filter;
1212 | }
1213 | };
1214 | InvokerOptions.prototype.parseNavigationOptions = function (navigation) {
1215 | if (navigation) {
1216 | var entryLocation = navigation.entryLocation;
1217 | if (entryLocation) {
1218 | var _a = entryLocation.sharePoint, sitePath = _a.sitePath, listPath = _a.listPath;
1219 | if (sitePath) {
1220 | UrlUtilities_1.validateUrlProtocol(sitePath, ['HTTPS']);
1221 | }
1222 | if (listPath) {
1223 | UrlUtilities_1.validateUrlProtocol(listPath, ['HTTPS']);
1224 | }
1225 | this.navEntryLocation = entryLocation;
1226 | }
1227 | var sourceTypes = navigation.sourceTypes instanceof Array ? navigation.sourceTypes : navigation.sourceTypes ? [navigation.sourceTypes] : null;
1228 | if (!!sourceTypes) {
1229 | this.needSharePointPermission = !(sourceTypes.length === 1 && sourceTypes[0].toLowerCase() === 'onedrive');
1230 | this.navSourceTypes = sourceTypes;
1231 | }
1232 | this.navEnabled = !navigation.disable;
1233 | }
1234 | };
1235 | return InvokerOptions;
1236 | }();
1237 | Object.defineProperty(exports, '__esModule', { value: true });
1238 | exports.default = InvokerOptions;
1239 | }(require, exports, require('../utilities/CallbackInvoker'), require('../Constants'), require('./DomainHint'), require('../utilities/ErrorHandler'), require('./ErrorType'), require('../utilities/Logging'), require('./OneDriveSdkError'), require('../utilities/StringUtilities'), require('../utilities/TypeValidators'), require('../utilities/UrlUtilities')));
1240 | },{"../Constants":1,"../utilities/CallbackInvoker":23,"../utilities/ErrorHandler":26,"../utilities/Logging":27,"../utilities/StringUtilities":30,"../utilities/TypeValidators":31,"../utilities/UrlUtilities":32,"./DomainHint":12,"./ErrorType":13,"./OneDriveSdkError":16}],15:[function(require,module,exports){
1241 | (function (require, exports) {
1242 | 'use strict';
1243 | var OauthEndpoint;
1244 | (function (OauthEndpoint) {
1245 | OauthEndpoint[OauthEndpoint['AAD'] = 0] = 'AAD';
1246 | OauthEndpoint[OauthEndpoint['AADv2'] = 1] = 'AADv2';
1247 | OauthEndpoint[OauthEndpoint['MSA'] = 2] = 'MSA';
1248 | }(OauthEndpoint || (OauthEndpoint = {})));
1249 | Object.defineProperty(exports, '__esModule', { value: true });
1250 | exports.default = OauthEndpoint;
1251 | }(require, exports));
1252 | },{}],16:[function(require,module,exports){
1253 | (function (require, exports, ErrorType_1, StringUtilities_1) {
1254 | 'use strict';
1255 | var OneDriveSdkError = function (_super) {
1256 | __extends(OneDriveSdkError, _super);
1257 | function OneDriveSdkError(errorCode, message) {
1258 | _super.call(this, message);
1259 | this.errorCode = ErrorType_1.default[errorCode];
1260 | this.message = message;
1261 | }
1262 | OneDriveSdkError.prototype.toString = function () {
1263 | return StringUtilities_1.format('[OneDriveSDK Error] errorType: {0}, message: {1}', this.errorCode, this.message);
1264 | };
1265 | return OneDriveSdkError;
1266 | }(Error);
1267 | Object.defineProperty(exports, '__esModule', { value: true });
1268 | exports.default = OneDriveSdkError;
1269 | }(require, exports, require('../models/ErrorType'), require('../utilities/StringUtilities')));
1270 | },{"../models/ErrorType":13,"../utilities/StringUtilities":30}],17:[function(require,module,exports){
1271 | (function (require, exports) {
1272 | 'use strict';
1273 | var PickerActionType;
1274 | (function (PickerActionType) {
1275 | PickerActionType[PickerActionType['download'] = 0] = 'download';
1276 | PickerActionType[PickerActionType['query'] = 1] = 'query';
1277 | PickerActionType[PickerActionType['share'] = 2] = 'share';
1278 | }(PickerActionType || (PickerActionType = {})));
1279 | Object.defineProperty(exports, '__esModule', { value: true });
1280 | exports.default = PickerActionType;
1281 | }(require, exports));
1282 | },{}],18:[function(require,module,exports){
1283 | (function (require, exports, CallbackInvoker_1, Constants_1, InvokerOptions_1, Logging_1, PickerActionType_1, TypeValidators_1) {
1284 | 'use strict';
1285 | var PickerOptions = function (_super) {
1286 | __extends(PickerOptions, _super);
1287 | function PickerOptions(options) {
1288 | _super.call(this, options);
1289 | var successCallback = TypeValidators_1.validateCallback(options.success, false);
1290 | this.success = function (files) {
1291 | Logging_1.default.logMessage('picker operation succeeded');
1292 | CallbackInvoker_1.invokeAppCallback(successCallback, true, files);
1293 | };
1294 | this.multiSelect = TypeValidators_1.validateType(options.multiSelect, Constants_1.default.TYPE_BOOLEAN, true, false);
1295 | var actionName = TypeValidators_1.validateType(options.action, Constants_1.default.TYPE_STRING, true, PickerActionType_1.default[PickerActionType_1.default.query]);
1296 | this.action = PickerActionType_1.default[actionName];
1297 | if (options.advanced) {
1298 | this.createLinkParameters = options.advanced.createLinkParameters;
1299 | }
1300 | if (!this.scopes) {
1301 | this.scopes = [this.action === PickerActionType_1.default.share ? 'Files.ReadWrite' : 'Files.Read'];
1302 | }
1303 | }
1304 | PickerOptions.prototype.needAPICall = function () {
1305 | return !!this.queryParameters || this.action !== PickerActionType_1.default.query;
1306 | };
1307 | return PickerOptions;
1308 | }(InvokerOptions_1.default);
1309 | Object.defineProperty(exports, '__esModule', { value: true });
1310 | exports.default = PickerOptions;
1311 | }(require, exports, require('../utilities/CallbackInvoker'), require('../Constants'), require('./InvokerOptions'), require('../utilities/Logging'), require('./PickerActionType'), require('../utilities/TypeValidators')));
1312 | },{"../Constants":1,"../utilities/CallbackInvoker":23,"../utilities/Logging":27,"../utilities/TypeValidators":31,"./InvokerOptions":14,"./PickerActionType":17}],19:[function(require,module,exports){
1313 | (function (require, exports) {
1314 | 'use strict';
1315 | var SaverActionType;
1316 | (function (SaverActionType) {
1317 | SaverActionType[SaverActionType['save'] = 0] = 'save';
1318 | SaverActionType[SaverActionType['query'] = 1] = 'query';
1319 | }(SaverActionType || (SaverActionType = {})));
1320 | Object.defineProperty(exports, '__esModule', { value: true });
1321 | exports.default = SaverActionType;
1322 | }(require, exports));
1323 | },{}],20:[function(require,module,exports){
1324 | (function (require, exports, CallbackInvoker_1, Constants_1, DomUtilities_1, ErrorHandler_1, ErrorType_1, InvokerOptions_1, Logging_1, OneDriveSdkError_1, SaverActionType_1, StringUtilities_1, TypeValidators_1, UploadType_1, UrlUtilities_1) {
1325 | 'use strict';
1326 | var SaverOptions = function (_super) {
1327 | __extends(SaverOptions, _super);
1328 | function SaverOptions(options) {
1329 | _super.call(this, options);
1330 | var successCallback = TypeValidators_1.validateCallback(options.success, false);
1331 | this.success = function (folder) {
1332 | Logging_1.default.logMessage('saver operation succeeded');
1333 | CallbackInvoker_1.invokeAppCallback(successCallback, true, folder);
1334 | };
1335 | var progressCallback = TypeValidators_1.validateCallback(options.progress, true);
1336 | this.progress = function (percentage) {
1337 | Logging_1.default.logMessage(StringUtilities_1.format('upload progress: {0}%', percentage));
1338 | if (progressCallback) {
1339 | CallbackInvoker_1.invokeAppCallback(progressCallback, false, percentage);
1340 | }
1341 | };
1342 | var actionName = TypeValidators_1.validateType(options.action, Constants_1.default.TYPE_STRING, true, SaverActionType_1.default[SaverActionType_1.default.query]);
1343 | this.action = SaverActionType_1.default[actionName];
1344 | if (this.action === SaverActionType_1.default.save) {
1345 | this._setFileInfo(options);
1346 | }
1347 | this.nameConflictBehavior = TypeValidators_1.validateType(options.nameConflictBehavior, Constants_1.default.TYPE_STRING, true, 'rename');
1348 | if (!this.scopes) {
1349 | this.scopes = ['Files.ReadWrite'];
1350 | }
1351 | }
1352 | SaverOptions.prototype.needAPICall = function () {
1353 | return !!this.queryParameters || this.action === SaverActionType_1.default.save;
1354 | };
1355 | SaverOptions.prototype._setFileInfo = function (options) {
1356 | if (options.sourceInputElementId && options.sourceUri) {
1357 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'sourceUri and sourceInputElementId' + ' are provided, only one is required.'));
1358 | }
1359 | this.sourceInputElementId = options.sourceInputElementId;
1360 | this.sourceUri = options.sourceUri;
1361 | var fileName = TypeValidators_1.validateType(options.fileName, Constants_1.default.TYPE_STRING, true, null);
1362 | if (this.sourceUri) {
1363 | if (UrlUtilities_1.isPathFullUrl(this.sourceUri)) {
1364 | this.uploadType = UploadType_1.default.url;
1365 | this.fileName = fileName || UrlUtilities_1.getFileNameFromUrl(this.sourceUri);
1366 | if (!this.fileName) {
1367 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'must supply a file name or a URL that ends with a file name'));
1368 | }
1369 | } else if (UrlUtilities_1.isPathDataUrl(this.sourceUri)) {
1370 | this.uploadType = UploadType_1.default.dataUrl;
1371 | this.fileName = fileName;
1372 | if (!this.fileName) {
1373 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'must supply a file name for data URL uploads'));
1374 | }
1375 | }
1376 | } else if (this.sourceInputElementId) {
1377 | this.uploadType = UploadType_1.default.form;
1378 | this.fileInput = DomUtilities_1.getFileInput(this.sourceInputElementId);
1379 | this.fileName = fileName || this.fileInput.name;
1380 | } else {
1381 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'please specified one type of resource to save'));
1382 | }
1383 | };
1384 | return SaverOptions;
1385 | }(InvokerOptions_1.default);
1386 | Object.defineProperty(exports, '__esModule', { value: true });
1387 | exports.default = SaverOptions;
1388 | }(require, exports, require('../utilities/CallbackInvoker'), require('../Constants'), require('../utilities/DomUtilities'), require('../utilities/ErrorHandler'), require('./ErrorType'), require('./InvokerOptions'), require('../utilities/Logging'), require('./OneDriveSdkError'), require('./SaverActionType'), require('../utilities/StringUtilities'), require('../utilities/TypeValidators'), require('./UploadType'), require('../utilities/UrlUtilities')));
1389 | },{"../Constants":1,"../utilities/CallbackInvoker":23,"../utilities/DomUtilities":25,"../utilities/ErrorHandler":26,"../utilities/Logging":27,"../utilities/StringUtilities":30,"../utilities/TypeValidators":31,"../utilities/UrlUtilities":32,"./ErrorType":13,"./InvokerOptions":14,"./OneDriveSdkError":16,"./SaverActionType":19,"./UploadType":21}],21:[function(require,module,exports){
1390 | (function (require, exports) {
1391 | 'use strict';
1392 | var UploadType;
1393 | (function (UploadType) {
1394 | UploadType[UploadType['dataUrl'] = 0] = 'dataUrl';
1395 | UploadType[UploadType['form'] = 1] = 'form';
1396 | UploadType[UploadType['url'] = 2] = 'url';
1397 | }(UploadType || (UploadType = {})));
1398 | Object.defineProperty(exports, '__esModule', { value: true });
1399 | exports.default = UploadType;
1400 | }(require, exports));
1401 | },{}],22:[function(require,module,exports){
1402 | (function (require, exports, ErrorType_1, ErrorHandler_1, OneDriveSdkError_1) {
1403 | 'use strict';
1404 | var CACHE_NAME = 'odpickerv7cache';
1405 | function getCacheItem(key) {
1406 | var cache = getCache();
1407 | return cache[key];
1408 | }
1409 | exports.getCacheItem = getCacheItem;
1410 | function setCacheItem(key, object) {
1411 | var cache = getCache();
1412 | cache[key] = object;
1413 | setCache(cache);
1414 | }
1415 | exports.setCacheItem = setCacheItem;
1416 | function removeCacheItem(key) {
1417 | var cache = getCache();
1418 | var deletedItem = cache[key];
1419 | delete cache[key];
1420 | setCache(cache);
1421 | return deletedItem;
1422 | }
1423 | exports.removeCacheItem = removeCacheItem;
1424 | function getCache() {
1425 | if (Storage) {
1426 | var cacheString = localStorage.getItem(CACHE_NAME);
1427 | var cache = JSON.parse(cacheString || '{}');
1428 | return cache;
1429 | } else {
1430 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.unsupportedFeature, 'cache based on Storage is not supported in this browser'));
1431 | }
1432 | }
1433 | function setCache(cache) {
1434 | if (Storage) {
1435 | localStorage.setItem(CACHE_NAME, JSON.stringify(cache));
1436 | } else {
1437 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.unsupportedFeature, 'cache based on Storage is not supported in this browser'));
1438 | }
1439 | }
1440 | }(require, exports, require('../models/ErrorType'), require('./ErrorHandler'), require('../models/OneDriveSdkError')));
1441 | },{"../models/ErrorType":13,"../models/OneDriveSdkError":16,"./ErrorHandler":26}],23:[function(require,module,exports){
1442 | (function (require, exports, Constants_1) {
1443 | 'use strict';
1444 | function invokeAppCallback(callback, isFinalCallback) {
1445 | var args = [];
1446 | for (var _i = 2; _i < arguments.length; _i++) {
1447 | args[_i - 2] = arguments[_i];
1448 | }
1449 | if (typeof callback === Constants_1.default.TYPE_FUNCTION) {
1450 | callback.apply(null, args);
1451 | }
1452 | }
1453 | exports.invokeAppCallback = invokeAppCallback;
1454 | function invokeCallbackAsynchronous(callback) {
1455 | var args = [];
1456 | for (var _i = 1; _i < arguments.length; _i++) {
1457 | args[_i - 1] = arguments[_i];
1458 | }
1459 | window.setTimeout(function () {
1460 | callback.apply(null, args);
1461 | }, 0);
1462 | }
1463 | exports.invokeCallbackAsynchronous = invokeCallbackAsynchronous;
1464 | }(require, exports, require('../Constants')));
1465 | },{"../Constants":1}],24:[function(require,module,exports){
1466 | (function (require, exports) {
1467 | 'use strict';
1468 | var Channel = function () {
1469 | function Channel(receiver) {
1470 | this.receiver = receiver;
1471 | }
1472 | Channel.prototype.send = function (data, origin) {
1473 | if (this.receiver) {
1474 | this.receiver.postMessage(data, origin);
1475 | }
1476 | };
1477 | Channel.prototype.getReceiver = function () {
1478 | return this.receiver;
1479 | };
1480 | return Channel;
1481 | }();
1482 | Object.defineProperty(exports, '__esModule', { value: true });
1483 | exports.default = Channel;
1484 | }(require, exports));
1485 | },{}],25:[function(require,module,exports){
1486 | (function (require, exports, ErrorHandler_1, ErrorType_1, OneDriveSdkError_1, UrlUtilities_1) {
1487 | 'use strict';
1488 | var FORM_UPLOAD_SIZE_LIMIT = 104857600;
1489 | var FORM_UPLOAD_SIZE_LIMIT_STRING = '100 MB';
1490 | var MESSAGE_LISTENERS = {};
1491 | function getElementById(id) {
1492 | return document.getElementById(id);
1493 | }
1494 | exports.getElementById = getElementById;
1495 | function onDocumentReady(callback) {
1496 | if (document.readyState === 'interactive' || document.readyState === 'complete') {
1497 | callback();
1498 | } else {
1499 | document.addEventListener('DOMContentLoaded', callback, false);
1500 | }
1501 | }
1502 | exports.onDocumentReady = onDocumentReady;
1503 | function onMessage(callback) {
1504 | var id = UrlUtilities_1.generateNonce() + '_' + new Date().getMilliseconds();
1505 | window.addEventListener('message', callback);
1506 | MESSAGE_LISTENERS[id] = callback;
1507 | return id;
1508 | }
1509 | exports.onMessage = onMessage;
1510 | function removeMessageListener(id) {
1511 | var callback = MESSAGE_LISTENERS[id];
1512 | if (callback) {
1513 | window.removeEventListener('message', callback);
1514 | }
1515 | }
1516 | exports.removeMessageListener = removeMessageListener;
1517 | function getFileInput(elementId) {
1518 | var fileInputElement = getElementById(elementId);
1519 | if (fileInputElement instanceof HTMLInputElement) {
1520 | if (fileInputElement.type !== 'file') {
1521 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'input elemenet must be of type \'file\''));
1522 | }
1523 | if (!fileInputElement.value) {
1524 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'please a file to upload'));
1525 | return null;
1526 | }
1527 | var files = fileInputElement.files;
1528 | if (!files || !window['FileReader']) {
1529 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.unsupportedFeature, 'browser does not support Files API'));
1530 | }
1531 | if (files.length !== 1) {
1532 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.unsupportedFeature, 'can not upload more than one file at a time'));
1533 | }
1534 | var fileInput = files[0];
1535 | if (!fileInput) {
1536 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'missing file input'));
1537 | }
1538 | if (fileInput.size > FORM_UPLOAD_SIZE_LIMIT) {
1539 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'the user has selected a file larger than ' + FORM_UPLOAD_SIZE_LIMIT_STRING));
1540 | return null;
1541 | }
1542 | return fileInput;
1543 | } else {
1544 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.unknown, 'element was not an instance of an HTMLInputElement'));
1545 | }
1546 | }
1547 | exports.getFileInput = getFileInput;
1548 | function displayOverlay() {
1549 | var overlay = document.createElement('div');
1550 | var overlayStyle = [
1551 | 'position: fixed',
1552 | 'width: 100%',
1553 | 'height: 100%',
1554 | 'top: 0px',
1555 | 'left: 0px',
1556 | 'background-color: white',
1557 | 'opacity: 1',
1558 | 'z-index: 10000',
1559 | 'min-width: 40px',
1560 | 'min-height: 40px'
1561 | ];
1562 | overlay.id = 'od-overlay';
1563 | overlay.style.cssText = overlayStyle.join(';');
1564 | var spinner = document.createElement('img');
1565 | var spinnerStyle = [
1566 | 'position: absolute',
1567 | 'margin: auto',
1568 | 'top: 0',
1569 | 'left: 0',
1570 | 'right: 0',
1571 | 'bottom: 0'
1572 | ];
1573 | spinner.id = 'od-spinner';
1574 | spinner.src = 'https://p.sfx.ms/common/spinner_grey_40_transparent.gif';
1575 | spinner.style.cssText = spinnerStyle.join(';');
1576 | overlay.appendChild(spinner);
1577 | var hiddenStyle = document.createElement('style');
1578 | hiddenStyle.type = 'text/css';
1579 | hiddenStyle.innerHTML = 'body { visibility: hidden !important; }';
1580 | document.head.appendChild(hiddenStyle);
1581 | onDocumentReady(function () {
1582 | var documentBody = document.body;
1583 | if (documentBody !== null) {
1584 | documentBody.insertBefore(overlay, documentBody.firstChild);
1585 | } else {
1586 | document.createElement('body').appendChild(overlay);
1587 | }
1588 | document.head.removeChild(hiddenStyle);
1589 | });
1590 | }
1591 | exports.displayOverlay = displayOverlay;
1592 | }(require, exports, require('./ErrorHandler'), require('../models/ErrorType'), require('../models/OneDriveSdkError'), require('./UrlUtilities')));
1593 | },{"../models/ErrorType":13,"../models/OneDriveSdkError":16,"./ErrorHandler":26,"./UrlUtilities":32}],26:[function(require,module,exports){
1594 | (function (require, exports, ErrorType_1) {
1595 | 'use strict';
1596 | var ERROR_HANDLERS = [];
1597 | function registerErrorObserver(callback) {
1598 | ERROR_HANDLERS.push(callback);
1599 | }
1600 | exports.registerErrorObserver = registerErrorObserver;
1601 | function throwError(sdkError) {
1602 | if (sdkError.errorCode !== ErrorType_1.default[ErrorType_1.default.unknown]) {
1603 | for (var _i = 0, ERROR_HANDLERS_1 = ERROR_HANDLERS; _i < ERROR_HANDLERS_1.length; _i++) {
1604 | var callback = ERROR_HANDLERS_1[_i];
1605 | callback(sdkError);
1606 | }
1607 | return {
1608 | exposeToPublic: function () {
1609 | throw sdkError;
1610 | }
1611 | };
1612 | } else {
1613 | throw sdkError;
1614 | }
1615 | }
1616 | exports.throwError = throwError;
1617 | }(require, exports, require('../models/ErrorType')));
1618 | },{"../models/ErrorType":13}],27:[function(require,module,exports){
1619 | (function (require, exports) {
1620 | 'use strict';
1621 | var ENABLE_LOGGING = 'onedrive_enable_logging';
1622 | var LOG_PREFIX = '[OneDriveSDK] ';
1623 | var Logging = function () {
1624 | function Logging() {
1625 | }
1626 | Logging.logError = function (message) {
1627 | var objects = [];
1628 | for (var _i = 1; _i < arguments.length; _i++) {
1629 | objects[_i - 1] = arguments[_i];
1630 | }
1631 | Logging._log(message, true, objects);
1632 | };
1633 | Logging.logMessage = function (message) {
1634 | Logging._log(message, false);
1635 | };
1636 | Logging._log = function (message, isError) {
1637 | var objects = [];
1638 | for (var _i = 2; _i < arguments.length; _i++) {
1639 | objects[_i - 2] = arguments[_i];
1640 | }
1641 | if (isError || Logging.loggingEnabled || window[ENABLE_LOGGING]) {
1642 | console.log(LOG_PREFIX + message, objects);
1643 | }
1644 | };
1645 | Logging.loggingEnabled = false;
1646 | return Logging;
1647 | }();
1648 | Object.defineProperty(exports, '__esModule', { value: true });
1649 | exports.default = Logging;
1650 | }(require, exports));
1651 | },{}],28:[function(require,module,exports){
1652 | (function (require, exports, Constants_1, Logging_1) {
1653 | 'use strict';
1654 | function shallowClone(object) {
1655 | if (typeof object !== Constants_1.default.TYPE_OBJECT || !object) {
1656 | return null;
1657 | }
1658 | var clonedObject = {};
1659 | for (var key in object) {
1660 | if (object.hasOwnProperty(key)) {
1661 | clonedObject[key] = object[key];
1662 | }
1663 | }
1664 | return clonedObject;
1665 | }
1666 | exports.shallowClone = shallowClone;
1667 | function deserializeJSON(text) {
1668 | var deserializedObject = null;
1669 | try {
1670 | deserializedObject = JSON.parse(text);
1671 | } catch (error) {
1672 | Logging_1.default.logError('deserialization error' + error);
1673 | }
1674 | if (typeof deserializedObject !== Constants_1.default.TYPE_OBJECT || deserializedObject === null) {
1675 | deserializedObject = {};
1676 | }
1677 | return deserializedObject;
1678 | }
1679 | exports.deserializeJSON = deserializeJSON;
1680 | function serializeJSON(value) {
1681 | return JSON.stringify(value);
1682 | }
1683 | exports.serializeJSON = serializeJSON;
1684 | }(require, exports, require('../Constants'), require('./Logging')));
1685 | },{"../Constants":1,"./Logging":27}],29:[function(require,module,exports){
1686 | (function (require, exports, ErrorHandler_1, ErrorType_1, Logging_1, OneDriveSdkError_1, UrlUtilities_1) {
1687 | 'use strict';
1688 | var POPUP_WIDTH = 1024;
1689 | var POPUP_HEIGHT = 650;
1690 | exports.POPUP_PINGER_INTERVAL = 500;
1691 | var Popup = function () {
1692 | function Popup() {
1693 | }
1694 | Popup.getCurrentPopup = function () {
1695 | return Popup._currentPopup || new Popup();
1696 | };
1697 | Popup.setCurrentPopup = function (popup) {
1698 | Popup._currentPopup = popup;
1699 | };
1700 | Popup.createPopupFeatures = function () {
1701 | var left = window.screenX + Math.max(window.outerWidth - POPUP_WIDTH, 0) / 2;
1702 | var top = window.screenY + Math.max(window.outerHeight - POPUP_HEIGHT, 0) / 2;
1703 | var features = [
1704 | 'width=' + POPUP_WIDTH,
1705 | 'height=' + POPUP_HEIGHT,
1706 | 'top=' + top,
1707 | 'left=' + left,
1708 | 'status=no',
1709 | 'resizable=yes',
1710 | 'toolbar=no',
1711 | 'menubar=no',
1712 | 'scrollbars=yes'
1713 | ];
1714 | return features.join(',');
1715 | };
1716 | Popup.prototype.close = function () {
1717 | if (Popup.getCurrentPopup().isPopupOpen()) {
1718 | Popup.getCurrentPopup()._popup.close();
1719 | Popup.setCurrentPopup(null);
1720 | }
1721 | };
1722 | Popup.prototype.openPopup = function (url) {
1723 | var _this = this;
1724 | UrlUtilities_1.validateUrlProtocol(url);
1725 | if (Popup.getCurrentPopup().isPopupOpen()) {
1726 | Logging_1.default.logMessage('leaving current url: ' + this._url);
1727 | this._url = url;
1728 | Popup.getCurrentPopup().getPopupWindow().location.href = url;
1729 | } else {
1730 | this._url = url;
1731 | this._popup = window.open(url, '_blank', Popup.createPopupFeatures());
1732 | if (!this._popup) {
1733 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.popupOpen, 'popup window is disconnected')).exposeToPublic();
1734 | } else {
1735 | this._popup.focus();
1736 | }
1737 | Popup.setCurrentPopup(this);
1738 | }
1739 | return new Promise(function (resolve, reject) {
1740 | var interval = setInterval(function () {
1741 | if (!_this.isPopupOpen()) {
1742 | window.clearInterval(interval);
1743 | resolve();
1744 | }
1745 | }, exports.POPUP_PINGER_INTERVAL);
1746 | });
1747 | };
1748 | Popup.prototype.getPopupWindow = function () {
1749 | return this._popup;
1750 | };
1751 | Popup.prototype.getCurrentUrl = function () {
1752 | return this._url;
1753 | };
1754 | Popup.prototype.isPopupOpen = function () {
1755 | return !!this._popup && !this._popup.closed;
1756 | };
1757 | return Popup;
1758 | }();
1759 | Object.defineProperty(exports, '__esModule', { value: true });
1760 | exports.default = Popup;
1761 | }(require, exports, require('./ErrorHandler'), require('../models/ErrorType'), require('./Logging'), require('../models/OneDriveSdkError'), require('../utilities/UrlUtilities')));
1762 | },{"../models/ErrorType":13,"../models/OneDriveSdkError":16,"../utilities/UrlUtilities":32,"./ErrorHandler":26,"./Logging":27}],30:[function(require,module,exports){
1763 | (function (require, exports) {
1764 | 'use strict';
1765 | var FORMAT_ARGS_REGEX = /[\{\}]/g;
1766 | var FORMAT_REGEX = /\{\d+\}/g;
1767 | function format(str) {
1768 | var values = [];
1769 | for (var _i = 1; _i < arguments.length; _i++) {
1770 | values[_i - 1] = arguments[_i];
1771 | }
1772 | var replacer = function (match) {
1773 | var replacement = values[match.replace(FORMAT_ARGS_REGEX, '')];
1774 | if (replacement === null) {
1775 | replacement = '';
1776 | }
1777 | return replacement;
1778 | };
1779 | return str.replace(FORMAT_REGEX, replacer);
1780 | }
1781 | exports.format = format;
1782 | }(require, exports));
1783 | },{}],31:[function(require,module,exports){
1784 | (function (require, exports, Constants_1, ErrorHandler_1, ErrorType_1, Logging_1, ObjectUtilities_1, OneDriveSdkError_1, StringUtilities_1) {
1785 | 'use strict';
1786 | function validateType(object, expectedType, optional, defaultValue, validValues) {
1787 | if (optional === void 0) {
1788 | optional = false;
1789 | }
1790 | if (object === undefined) {
1791 | if (optional) {
1792 | if (defaultValue !== undefined) {
1793 | Logging_1.default.logMessage('applying default value: ' + defaultValue);
1794 | return defaultValue;
1795 | }
1796 | } else {
1797 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.typeError, 'object was missing and not optional'));
1798 | }
1799 | return null;
1800 | }
1801 | var objectType = typeof object;
1802 | if (objectType !== expectedType) {
1803 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.typeError, StringUtilities_1.format('expected object type: \'{0}\', actual object type: \'{1}\'', expectedType, objectType)));
1804 | return null;
1805 | }
1806 | if (!isValidValue(object, validValues)) {
1807 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.typeError, StringUtilities_1.format('object does not match any valid values {0}', ObjectUtilities_1.serializeJSON(validValues))));
1808 | return null;
1809 | }
1810 | return object;
1811 | }
1812 | exports.validateType = validateType;
1813 | function validateCallback(functionOption, optional) {
1814 | if (optional === void 0) {
1815 | optional = false;
1816 | }
1817 | if (functionOption === undefined) {
1818 | if (!optional) {
1819 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.typeError, 'function was missing and not optional'));
1820 | }
1821 | return null;
1822 | }
1823 | var functionType = typeof functionOption;
1824 | if (functionType !== Constants_1.default.TYPE_FUNCTION) {
1825 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.typeError, StringUtilities_1.format('expected function type: function | string, actual type: {0}', functionType)));
1826 | }
1827 | return functionOption;
1828 | }
1829 | exports.validateCallback = validateCallback;
1830 | function isValidValue(object, validValues) {
1831 | if (!Array.isArray(validValues)) {
1832 | return true;
1833 | }
1834 | for (var index in validValues) {
1835 | if (object === validValues[index]) {
1836 | return true;
1837 | }
1838 | }
1839 | return false;
1840 | }
1841 | }(require, exports, require('../Constants'), require('./ErrorHandler'), require('../models/ErrorType'), require('./Logging'), require('./ObjectUtilities'), require('../models/OneDriveSdkError'), require('./StringUtilities')));
1842 | },{"../Constants":1,"../models/ErrorType":13,"../models/OneDriveSdkError":16,"./ErrorHandler":26,"./Logging":27,"./ObjectUtilities":28,"./StringUtilities":30}],32:[function(require,module,exports){
1843 | (function (require, exports, Constants_1, ErrorHandler_1, ErrorType_1, OneDriveSdkError_1, StringUtilities_1) {
1844 | 'use strict';
1845 | var PROTOCOL_HTTP = 'HTTP';
1846 | var PROTOCOL_HTTPS = 'HTTPS';
1847 | function appendToPath(baseUrl, path) {
1848 | return baseUrl + (baseUrl.charAt(baseUrl.length - 1) !== '/' ? '/' : '') + path;
1849 | }
1850 | exports.appendToPath = appendToPath;
1851 | function appendQueryString(baseUrl, queryKey, queryValue) {
1852 | return appendQueryStrings(baseUrl, (_a = {}, _a[queryKey] = queryValue, _a));
1853 | var _a;
1854 | }
1855 | exports.appendQueryString = appendQueryString;
1856 | function appendQueryStrings(baseUrl, queryParameters, isAspx) {
1857 | if (!queryParameters || Object.keys(queryParameters).length === 0) {
1858 | return baseUrl;
1859 | }
1860 | if (isAspx) {
1861 | baseUrl += '#';
1862 | } else if (baseUrl.indexOf('?') === -1) {
1863 | baseUrl += '?';
1864 | } else if (baseUrl.charAt(baseUrl.length - 1) !== '&') {
1865 | baseUrl += '&';
1866 | }
1867 | var queryString = '';
1868 | for (var key in queryParameters) {
1869 | queryString += (queryString.length ? '&' : '') + StringUtilities_1.format('{0}={1}', encodeURIComponent(key), encodeURIComponent(queryParameters[key]));
1870 | }
1871 | return baseUrl + queryString;
1872 | }
1873 | exports.appendQueryStrings = appendQueryStrings;
1874 | function readCurrentUrlParameters() {
1875 | return readUrlParameters(window.location.href);
1876 | }
1877 | exports.readCurrentUrlParameters = readCurrentUrlParameters;
1878 | function readUrlParameters(url) {
1879 | var queryParamters = {};
1880 | var queryStart = url.indexOf('?') + 1;
1881 | var hashStart = url.indexOf('#') + 1;
1882 | if (queryStart > 0) {
1883 | var queryEnd = hashStart > queryStart ? hashStart - 1 : url.length;
1884 | deserializeParameters(url.substring(queryStart, queryEnd), queryParamters);
1885 | }
1886 | if (hashStart > 0) {
1887 | deserializeParameters(url.substring(hashStart), queryParamters);
1888 | }
1889 | return queryParamters;
1890 | }
1891 | exports.readUrlParameters = readUrlParameters;
1892 | function redirect(url) {
1893 | validateUrlProtocol(url);
1894 | window.location.replace(url);
1895 | }
1896 | exports.redirect = redirect;
1897 | function trimUrlQuery(url) {
1898 | var separators = [
1899 | '?',
1900 | '#'
1901 | ];
1902 | for (var index in separators) {
1903 | var charIndex = url.indexOf(separators[index]);
1904 | if (charIndex > 0) {
1905 | url = url.substring(0, charIndex);
1906 | }
1907 | }
1908 | return url;
1909 | }
1910 | exports.trimUrlQuery = trimUrlQuery;
1911 | function getFileNameFromUrl(url) {
1912 | var trimmedUrl = trimUrlQuery(url);
1913 | return trimmedUrl.substr(trimmedUrl.lastIndexOf('/') + 1);
1914 | }
1915 | exports.getFileNameFromUrl = getFileNameFromUrl;
1916 | function getOrigin(url) {
1917 | return appendToPath(url.replace(/^((\w+:)?\/\/[^\/]+\/?).*$/, '$1'), '');
1918 | }
1919 | exports.getOrigin = getOrigin;
1920 | function isPathFullUrl(path) {
1921 | return path.indexOf('https://') === 0 || path.indexOf('http://') === 0;
1922 | }
1923 | exports.isPathFullUrl = isPathFullUrl;
1924 | function isPathDataUrl(path) {
1925 | return path.indexOf('data:') === 0;
1926 | }
1927 | exports.isPathDataUrl = isPathDataUrl;
1928 | function generateNonce() {
1929 | var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
1930 | var text = '';
1931 | for (var i = 0; i < Constants_1.default.NONCE_LENGTH; i++) {
1932 | text += possible.charAt(Math.floor(Math.random() * possible.length));
1933 | }
1934 | return text;
1935 | }
1936 | exports.generateNonce = generateNonce;
1937 | function validateUrlProtocol(url, protocols) {
1938 | protocols = protocols ? protocols : [
1939 | PROTOCOL_HTTP,
1940 | PROTOCOL_HTTPS
1941 | ];
1942 | for (var _i = 0, protocols_1 = protocols; _i < protocols_1.length; _i++) {
1943 | var protocol = protocols_1[_i];
1944 | if (url.toUpperCase().indexOf(protocol) === 0) {
1945 | return;
1946 | }
1947 | }
1948 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, StringUtilities_1.format('uri {0} does not match protocol(s): ' + protocols, url))).exposeToPublic();
1949 | }
1950 | exports.validateUrlProtocol = validateUrlProtocol;
1951 | function validateRedirectUrlHost(url) {
1952 | validateUrlProtocol(url);
1953 | if (url.indexOf('://') > -1) {
1954 | var domain = url.split('/')[2];
1955 | if (domain !== window.location.host) {
1956 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'redirect uri is not in the same domain as picker sdk')).exposeToPublic();
1957 | }
1958 | } else {
1959 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'redirect uri is not an absolute url')).exposeToPublic();
1960 | }
1961 | }
1962 | exports.validateRedirectUrlHost = validateRedirectUrlHost;
1963 | function deserializeParameters(query, queryParameters) {
1964 | var properties = query.split('&');
1965 | for (var i = 0; i < properties.length; i++) {
1966 | var property = properties[i].split('=');
1967 | if (property.length === 2) {
1968 | queryParameters[decodeURIComponent(property[0])] = decodeURIComponent(property[1]);
1969 | }
1970 | }
1971 | }
1972 | }(require, exports, require('../Constants'), require('./ErrorHandler'), require('../models/ErrorType'), require('../models/OneDriveSdkError'), require('./StringUtilities')));
1973 | },{"../Constants":1,"../models/ErrorType":13,"../models/OneDriveSdkError":16,"./ErrorHandler":26,"./StringUtilities":30}],33:[function(require,module,exports){
1974 | (function (require, exports, ApiEndpoint_1, Constants_1, ErrorHandler_1, ErrorType_1, Logging_1, OneDriveSdkError_1, StringUtilities_1) {
1975 | 'use strict';
1976 | var REQUEST_TIMEOUT = 30000;
1977 | var EXCEPTION_STATUS = -1;
1978 | var TIMEOUT_STATUS = -2;
1979 | var ABORT_STATUS = -3;
1980 | var LEGACY_MSA_APPID_PATTERN = new RegExp('^([a-fA-F0-9]){16}$');
1981 | var XHR = function () {
1982 | function XHR(options) {
1983 | this._url = options.url;
1984 | this._json = options.json;
1985 | this._headers = options.headers || {};
1986 | this._method = options.method;
1987 | this._clientId = options.clientId;
1988 | this._apiEndpoint = options.apiEndpoint || ApiEndpoint_1.default.msa;
1989 | ErrorHandler_1.registerErrorObserver(this._abortRequest);
1990 | }
1991 | XHR.statusCodeToString = function (statusCode) {
1992 | switch (statusCode) {
1993 | case -1:
1994 | return 'EXCEPTION';
1995 | case -2:
1996 | return 'TIMEOUT';
1997 | case -3:
1998 | return 'REQUEST ABORTED';
1999 | default:
2000 | return statusCode.toString();
2001 | }
2002 | };
2003 | XHR.prototype.start = function (successCallback, failureCallback) {
2004 | var _this = this;
2005 | try {
2006 | this._successCallback = successCallback;
2007 | this._failureCallback = failureCallback;
2008 | this._request = new XMLHttpRequest();
2009 | this._request.ontimeout = this._onTimeout;
2010 | this._request.onload = function () {
2011 | var status = _this._request.status;
2012 | if (status < 400 && status > 0) {
2013 | _this._callSuccessCallback(status);
2014 | } else {
2015 | _this._callFailureCallback(status);
2016 | }
2017 | };
2018 | if (!this._method) {
2019 | this._method = this._json ? XHR.HTTP_POST : XHR.HTTP_GET;
2020 | }
2021 | this._request.open(this._method, this._url, true);
2022 | this._request.timeout = REQUEST_TIMEOUT;
2023 | this._setHeaders();
2024 | Logging_1.default.logMessage('starting request to: ' + this._url);
2025 | this._request.send(this._json);
2026 | } catch (error) {
2027 | this._callFailureCallback(EXCEPTION_STATUS, error);
2028 | }
2029 | };
2030 | XHR.prototype.upload = function (data, successCallback, failureCallback, progressCallback) {
2031 | var _this = this;
2032 | try {
2033 | this._successCallback = successCallback;
2034 | this._progressCallback = progressCallback;
2035 | this._failureCallback = failureCallback;
2036 | this._request = new XMLHttpRequest();
2037 | this._request.ontimeout = this._onTimeout;
2038 | this._method = XHR.HTTP_PUT;
2039 | this._request.open(this._method, this._url, true);
2040 | this._setHeaders();
2041 | this._request.onload = function (event) {
2042 | _this._completed = true;
2043 | var status = _this._request.status;
2044 | if (status === 200 || status === 201 || status === 202) {
2045 | _this._callSuccessCallback(status);
2046 | } else {
2047 | _this._callFailureCallback(status, event);
2048 | }
2049 | };
2050 | this._request.onerror = function (event) {
2051 | _this._completed = true;
2052 | _this._callFailureCallback(_this._request.status, event);
2053 | };
2054 | this._request.upload.onprogress = function (event) {
2055 | if (event.lengthComputable) {
2056 | var uploadProgress = {
2057 | bytesTransferred: event.loaded,
2058 | totalBytes: event.total,
2059 | progressPercentage: event.total === 0 ? 0 : event.loaded / event.total * 100
2060 | };
2061 | _this._callProgressCallback(uploadProgress);
2062 | }
2063 | };
2064 | Logging_1.default.logMessage('starting upload to: ' + this._url);
2065 | this._request.send(data);
2066 | } catch (error) {
2067 | this._callFailureCallback(EXCEPTION_STATUS, error);
2068 | }
2069 | };
2070 | XHR.prototype._callSuccessCallback = function (status) {
2071 | Logging_1.default.logMessage('calling xhr success callback, status: ' + XHR.statusCodeToString(status));
2072 | this._successCallback(this._request, status, this._url);
2073 | };
2074 | XHR.prototype._callFailureCallback = function (status, error) {
2075 | Logging_1.default.logError('calling xhr failure callback, status: ' + XHR.statusCodeToString(status), this._request, error);
2076 | this._failureCallback(this._request, status, status === TIMEOUT_STATUS);
2077 | };
2078 | XHR.prototype._callProgressCallback = function (uploadProgress) {
2079 | Logging_1.default.logMessage('calling xhr upload progress callback');
2080 | this._progressCallback(this._request, uploadProgress);
2081 | };
2082 | XHR.prototype._abortRequest = function () {
2083 | if (this && !this._completed) {
2084 | this._completed = true;
2085 | if (this._request) {
2086 | try {
2087 | this._request.abort();
2088 | } catch (error) {
2089 | }
2090 | }
2091 | this._callFailureCallback(ABORT_STATUS);
2092 | }
2093 | };
2094 | XHR.prototype._onTimeout = function () {
2095 | if (!this._completed) {
2096 | this._completed = true;
2097 | this._callFailureCallback(TIMEOUT_STATUS);
2098 | }
2099 | };
2100 | XHR.prototype._setHeaders = function () {
2101 | for (var x in this._headers) {
2102 | this._request.setRequestHeader(x, this._headers[x]);
2103 | }
2104 | if (this._clientId) {
2105 | var idToRecord = this._clientId;
2106 | if (LEGACY_MSA_APPID_PATTERN.test(this._clientId)) {
2107 | idToRecord = '0x' + this._clientId;
2108 | }
2109 | this._request.setRequestHeader('Application', '0x' + idToRecord);
2110 | }
2111 | var sdkVersion = StringUtilities_1.format('{0}={1}', 'SDK-Version', Constants_1.default.SDK_VERSION);
2112 | switch (this._apiEndpoint) {
2113 | case ApiEndpoint_1.default.graph_odb:
2114 | case ApiEndpoint_1.default.filesV2:
2115 | this._request.setRequestHeader('X-ClientService-ClientTag', sdkVersion);
2116 | break;
2117 | case ApiEndpoint_1.default.graph_odc:
2118 | case ApiEndpoint_1.default.msa:
2119 | this._request.setRequestHeader('X-RequestStats', sdkVersion);
2120 | break;
2121 | default:
2122 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.internalError, 'invalid API endpoint: ' + this._apiEndpoint));
2123 | }
2124 | if (this._method === XHR.HTTP_POST) {
2125 | this._request.setRequestHeader('Content-Type', this._json ? 'application/json' : 'text/plain');
2126 | }
2127 | };
2128 | XHR.HTTP_GET = 'GET';
2129 | XHR.HTTP_POST = 'POST';
2130 | XHR.HTTP_PUT = 'PUT';
2131 | return XHR;
2132 | }();
2133 | Object.defineProperty(exports, '__esModule', { value: true });
2134 | exports.default = XHR;
2135 | }(require, exports, require('../models/ApiEndpoint'), require('../Constants'), require('./ErrorHandler'), require('../models/ErrorType'), require('./Logging'), require('../models/OneDriveSdkError'), require('./StringUtilities')));
2136 | },{"../Constants":1,"../models/ApiEndpoint":11,"../models/ErrorType":13,"../models/OneDriveSdkError":16,"./ErrorHandler":26,"./Logging":27,"./StringUtilities":30}],34:[function(require,module,exports){
2137 | /*!
2138 | * @overview es6-promise - a tiny implementation of Promises/A+.
2139 | * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
2140 | * @license Licensed under MIT license
2141 | * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE
2142 | * @version 3.3.1
2143 | */
2144 |
2145 | (function (global, factory) {
2146 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
2147 | typeof define === 'function' && define.amd ? define(factory) :
2148 | (global.ES6Promise = factory());
2149 | }(this, (function () { 'use strict';
2150 |
2151 | function objectOrFunction(x) {
2152 | return typeof x === 'function' || typeof x === 'object' && x !== null;
2153 | }
2154 |
2155 | function isFunction(x) {
2156 | return typeof x === 'function';
2157 | }
2158 |
2159 | var _isArray = undefined;
2160 | if (!Array.isArray) {
2161 | _isArray = function (x) {
2162 | return Object.prototype.toString.call(x) === '[object Array]';
2163 | };
2164 | } else {
2165 | _isArray = Array.isArray;
2166 | }
2167 |
2168 | var isArray = _isArray;
2169 |
2170 | var len = 0;
2171 | var vertxNext = undefined;
2172 | var customSchedulerFn = undefined;
2173 |
2174 | var asap = function asap(callback, arg) {
2175 | queue[len] = callback;
2176 | queue[len + 1] = arg;
2177 | len += 2;
2178 | if (len === 2) {
2179 | // If len is 2, that means that we need to schedule an async flush.
2180 | // If additional callbacks are queued before the queue is flushed, they
2181 | // will be processed by this flush that we are scheduling.
2182 | if (customSchedulerFn) {
2183 | customSchedulerFn(flush);
2184 | } else {
2185 | scheduleFlush();
2186 | }
2187 | }
2188 | };
2189 |
2190 | function setScheduler(scheduleFn) {
2191 | customSchedulerFn = scheduleFn;
2192 | }
2193 |
2194 | function setAsap(asapFn) {
2195 | asap = asapFn;
2196 | }
2197 |
2198 | var browserWindow = typeof window !== 'undefined' ? window : undefined;
2199 | var browserGlobal = browserWindow || {};
2200 | var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
2201 | var isNode = typeof self === 'undefined' && typeof process !== 'undefined' && ({}).toString.call(process) === '[object process]';
2202 |
2203 | // test for web worker but not in IE10
2204 | var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined';
2205 |
2206 | // node
2207 | function useNextTick() {
2208 | // node version 0.10.x displays a deprecation warning when nextTick is used recursively
2209 | // see https://github.com/cujojs/when/issues/410 for details
2210 | return function () {
2211 | return process.nextTick(flush);
2212 | };
2213 | }
2214 |
2215 | // vertx
2216 | function useVertxTimer() {
2217 | return function () {
2218 | vertxNext(flush);
2219 | };
2220 | }
2221 |
2222 | function useMutationObserver() {
2223 | var iterations = 0;
2224 | var observer = new BrowserMutationObserver(flush);
2225 | var node = document.createTextNode('');
2226 | observer.observe(node, { characterData: true });
2227 |
2228 | return function () {
2229 | node.data = iterations = ++iterations % 2;
2230 | };
2231 | }
2232 |
2233 | // web worker
2234 | function useMessageChannel() {
2235 | var channel = new MessageChannel();
2236 | channel.port1.onmessage = flush;
2237 | return function () {
2238 | return channel.port2.postMessage(0);
2239 | };
2240 | }
2241 |
2242 | function useSetTimeout() {
2243 | // Store setTimeout reference so es6-promise will be unaffected by
2244 | // other code modifying setTimeout (like sinon.useFakeTimers())
2245 | var globalSetTimeout = setTimeout;
2246 | return function () {
2247 | return globalSetTimeout(flush, 1);
2248 | };
2249 | }
2250 |
2251 | var queue = new Array(1000);
2252 | function flush() {
2253 | for (var i = 0; i < len; i += 2) {
2254 | var callback = queue[i];
2255 | var arg = queue[i + 1];
2256 |
2257 | callback(arg);
2258 |
2259 | queue[i] = undefined;
2260 | queue[i + 1] = undefined;
2261 | }
2262 |
2263 | len = 0;
2264 | }
2265 |
2266 | function attemptVertx() {
2267 | try {
2268 | var r = require;
2269 | var vertx = r('vertx');
2270 | vertxNext = vertx.runOnLoop || vertx.runOnContext;
2271 | return useVertxTimer();
2272 | } catch (e) {
2273 | return useSetTimeout();
2274 | }
2275 | }
2276 |
2277 | var scheduleFlush = undefined;
2278 | // Decide what async method to use to triggering processing of queued callbacks:
2279 | if (isNode) {
2280 | scheduleFlush = useNextTick();
2281 | } else if (BrowserMutationObserver) {
2282 | scheduleFlush = useMutationObserver();
2283 | } else if (isWorker) {
2284 | scheduleFlush = useMessageChannel();
2285 | } else if (browserWindow === undefined && typeof require === 'function') {
2286 | scheduleFlush = attemptVertx();
2287 | } else {
2288 | scheduleFlush = useSetTimeout();
2289 | }
2290 |
2291 | function then(onFulfillment, onRejection) {
2292 | var _arguments = arguments;
2293 |
2294 | var parent = this;
2295 |
2296 | var child = new this.constructor(noop);
2297 |
2298 | if (child[PROMISE_ID] === undefined) {
2299 | makePromise(child);
2300 | }
2301 |
2302 | var _state = parent._state;
2303 |
2304 | if (_state) {
2305 | (function () {
2306 | var callback = _arguments[_state - 1];
2307 | asap(function () {
2308 | return invokeCallback(_state, child, callback, parent._result);
2309 | });
2310 | })();
2311 | } else {
2312 | subscribe(parent, child, onFulfillment, onRejection);
2313 | }
2314 |
2315 | return child;
2316 | }
2317 |
2318 | /**
2319 | `Promise.resolve` returns a promise that will become resolved with the
2320 | passed `value`. It is shorthand for the following:
2321 |
2322 | ```javascript
2323 | let promise = new Promise(function(resolve, reject){
2324 | resolve(1);
2325 | });
2326 |
2327 | promise.then(function(value){
2328 | // value === 1
2329 | });
2330 | ```
2331 |
2332 | Instead of writing the above, your code now simply becomes the following:
2333 |
2334 | ```javascript
2335 | let promise = Promise.resolve(1);
2336 |
2337 | promise.then(function(value){
2338 | // value === 1
2339 | });
2340 | ```
2341 |
2342 | @method resolve
2343 | @static
2344 | @param {Any} value value that the returned promise will be resolved with
2345 | Useful for tooling.
2346 | @return {Promise} a promise that will become fulfilled with the given
2347 | `value`
2348 | */
2349 | function resolve(object) {
2350 | /*jshint validthis:true */
2351 | var Constructor = this;
2352 |
2353 | if (object && typeof object === 'object' && object.constructor === Constructor) {
2354 | return object;
2355 | }
2356 |
2357 | var promise = new Constructor(noop);
2358 | _resolve(promise, object);
2359 | return promise;
2360 | }
2361 |
2362 | var PROMISE_ID = Math.random().toString(36).substring(16);
2363 |
2364 | function noop() {}
2365 |
2366 | var PENDING = void 0;
2367 | var FULFILLED = 1;
2368 | var REJECTED = 2;
2369 |
2370 | var GET_THEN_ERROR = new ErrorObject();
2371 |
2372 | function selfFulfillment() {
2373 | return new TypeError("You cannot resolve a promise with itself");
2374 | }
2375 |
2376 | function cannotReturnOwn() {
2377 | return new TypeError('A promises callback cannot return that same promise.');
2378 | }
2379 |
2380 | function getThen(promise) {
2381 | try {
2382 | return promise.then;
2383 | } catch (error) {
2384 | GET_THEN_ERROR.error = error;
2385 | return GET_THEN_ERROR;
2386 | }
2387 | }
2388 |
2389 | function tryThen(then, value, fulfillmentHandler, rejectionHandler) {
2390 | try {
2391 | then.call(value, fulfillmentHandler, rejectionHandler);
2392 | } catch (e) {
2393 | return e;
2394 | }
2395 | }
2396 |
2397 | function handleForeignThenable(promise, thenable, then) {
2398 | asap(function (promise) {
2399 | var sealed = false;
2400 | var error = tryThen(then, thenable, function (value) {
2401 | if (sealed) {
2402 | return;
2403 | }
2404 | sealed = true;
2405 | if (thenable !== value) {
2406 | _resolve(promise, value);
2407 | } else {
2408 | fulfill(promise, value);
2409 | }
2410 | }, function (reason) {
2411 | if (sealed) {
2412 | return;
2413 | }
2414 | sealed = true;
2415 |
2416 | _reject(promise, reason);
2417 | }, 'Settle: ' + (promise._label || ' unknown promise'));
2418 |
2419 | if (!sealed && error) {
2420 | sealed = true;
2421 | _reject(promise, error);
2422 | }
2423 | }, promise);
2424 | }
2425 |
2426 | function handleOwnThenable(promise, thenable) {
2427 | if (thenable._state === FULFILLED) {
2428 | fulfill(promise, thenable._result);
2429 | } else if (thenable._state === REJECTED) {
2430 | _reject(promise, thenable._result);
2431 | } else {
2432 | subscribe(thenable, undefined, function (value) {
2433 | return _resolve(promise, value);
2434 | }, function (reason) {
2435 | return _reject(promise, reason);
2436 | });
2437 | }
2438 | }
2439 |
2440 | function handleMaybeThenable(promise, maybeThenable, then$$) {
2441 | if (maybeThenable.constructor === promise.constructor && then$$ === then && maybeThenable.constructor.resolve === resolve) {
2442 | handleOwnThenable(promise, maybeThenable);
2443 | } else {
2444 | if (then$$ === GET_THEN_ERROR) {
2445 | _reject(promise, GET_THEN_ERROR.error);
2446 | } else if (then$$ === undefined) {
2447 | fulfill(promise, maybeThenable);
2448 | } else if (isFunction(then$$)) {
2449 | handleForeignThenable(promise, maybeThenable, then$$);
2450 | } else {
2451 | fulfill(promise, maybeThenable);
2452 | }
2453 | }
2454 | }
2455 |
2456 | function _resolve(promise, value) {
2457 | if (promise === value) {
2458 | _reject(promise, selfFulfillment());
2459 | } else if (objectOrFunction(value)) {
2460 | handleMaybeThenable(promise, value, getThen(value));
2461 | } else {
2462 | fulfill(promise, value);
2463 | }
2464 | }
2465 |
2466 | function publishRejection(promise) {
2467 | if (promise._onerror) {
2468 | promise._onerror(promise._result);
2469 | }
2470 |
2471 | publish(promise);
2472 | }
2473 |
2474 | function fulfill(promise, value) {
2475 | if (promise._state !== PENDING) {
2476 | return;
2477 | }
2478 |
2479 | promise._result = value;
2480 | promise._state = FULFILLED;
2481 |
2482 | if (promise._subscribers.length !== 0) {
2483 | asap(publish, promise);
2484 | }
2485 | }
2486 |
2487 | function _reject(promise, reason) {
2488 | if (promise._state !== PENDING) {
2489 | return;
2490 | }
2491 | promise._state = REJECTED;
2492 | promise._result = reason;
2493 |
2494 | asap(publishRejection, promise);
2495 | }
2496 |
2497 | function subscribe(parent, child, onFulfillment, onRejection) {
2498 | var _subscribers = parent._subscribers;
2499 | var length = _subscribers.length;
2500 |
2501 | parent._onerror = null;
2502 |
2503 | _subscribers[length] = child;
2504 | _subscribers[length + FULFILLED] = onFulfillment;
2505 | _subscribers[length + REJECTED] = onRejection;
2506 |
2507 | if (length === 0 && parent._state) {
2508 | asap(publish, parent);
2509 | }
2510 | }
2511 |
2512 | function publish(promise) {
2513 | var subscribers = promise._subscribers;
2514 | var settled = promise._state;
2515 |
2516 | if (subscribers.length === 0) {
2517 | return;
2518 | }
2519 |
2520 | var child = undefined,
2521 | callback = undefined,
2522 | detail = promise._result;
2523 |
2524 | for (var i = 0; i < subscribers.length; i += 3) {
2525 | child = subscribers[i];
2526 | callback = subscribers[i + settled];
2527 |
2528 | if (child) {
2529 | invokeCallback(settled, child, callback, detail);
2530 | } else {
2531 | callback(detail);
2532 | }
2533 | }
2534 |
2535 | promise._subscribers.length = 0;
2536 | }
2537 |
2538 | function ErrorObject() {
2539 | this.error = null;
2540 | }
2541 |
2542 | var TRY_CATCH_ERROR = new ErrorObject();
2543 |
2544 | function tryCatch(callback, detail) {
2545 | try {
2546 | return callback(detail);
2547 | } catch (e) {
2548 | TRY_CATCH_ERROR.error = e;
2549 | return TRY_CATCH_ERROR;
2550 | }
2551 | }
2552 |
2553 | function invokeCallback(settled, promise, callback, detail) {
2554 | var hasCallback = isFunction(callback),
2555 | value = undefined,
2556 | error = undefined,
2557 | succeeded = undefined,
2558 | failed = undefined;
2559 |
2560 | if (hasCallback) {
2561 | value = tryCatch(callback, detail);
2562 |
2563 | if (value === TRY_CATCH_ERROR) {
2564 | failed = true;
2565 | error = value.error;
2566 | value = null;
2567 | } else {
2568 | succeeded = true;
2569 | }
2570 |
2571 | if (promise === value) {
2572 | _reject(promise, cannotReturnOwn());
2573 | return;
2574 | }
2575 | } else {
2576 | value = detail;
2577 | succeeded = true;
2578 | }
2579 |
2580 | if (promise._state !== PENDING) {
2581 | // noop
2582 | } else if (hasCallback && succeeded) {
2583 | _resolve(promise, value);
2584 | } else if (failed) {
2585 | _reject(promise, error);
2586 | } else if (settled === FULFILLED) {
2587 | fulfill(promise, value);
2588 | } else if (settled === REJECTED) {
2589 | _reject(promise, value);
2590 | }
2591 | }
2592 |
2593 | function initializePromise(promise, resolver) {
2594 | try {
2595 | resolver(function resolvePromise(value) {
2596 | _resolve(promise, value);
2597 | }, function rejectPromise(reason) {
2598 | _reject(promise, reason);
2599 | });
2600 | } catch (e) {
2601 | _reject(promise, e);
2602 | }
2603 | }
2604 |
2605 | var id = 0;
2606 | function nextId() {
2607 | return id++;
2608 | }
2609 |
2610 | function makePromise(promise) {
2611 | promise[PROMISE_ID] = id++;
2612 | promise._state = undefined;
2613 | promise._result = undefined;
2614 | promise._subscribers = [];
2615 | }
2616 |
2617 | function Enumerator(Constructor, input) {
2618 | this._instanceConstructor = Constructor;
2619 | this.promise = new Constructor(noop);
2620 |
2621 | if (!this.promise[PROMISE_ID]) {
2622 | makePromise(this.promise);
2623 | }
2624 |
2625 | if (isArray(input)) {
2626 | this._input = input;
2627 | this.length = input.length;
2628 | this._remaining = input.length;
2629 |
2630 | this._result = new Array(this.length);
2631 |
2632 | if (this.length === 0) {
2633 | fulfill(this.promise, this._result);
2634 | } else {
2635 | this.length = this.length || 0;
2636 | this._enumerate();
2637 | if (this._remaining === 0) {
2638 | fulfill(this.promise, this._result);
2639 | }
2640 | }
2641 | } else {
2642 | _reject(this.promise, validationError());
2643 | }
2644 | }
2645 |
2646 | function validationError() {
2647 | return new Error('Array Methods must be provided an Array');
2648 | };
2649 |
2650 | Enumerator.prototype._enumerate = function () {
2651 | var length = this.length;
2652 | var _input = this._input;
2653 |
2654 | for (var i = 0; this._state === PENDING && i < length; i++) {
2655 | this._eachEntry(_input[i], i);
2656 | }
2657 | };
2658 |
2659 | Enumerator.prototype._eachEntry = function (entry, i) {
2660 | var c = this._instanceConstructor;
2661 | var resolve$$ = c.resolve;
2662 |
2663 | if (resolve$$ === resolve) {
2664 | var _then = getThen(entry);
2665 |
2666 | if (_then === then && entry._state !== PENDING) {
2667 | this._settledAt(entry._state, i, entry._result);
2668 | } else if (typeof _then !== 'function') {
2669 | this._remaining--;
2670 | this._result[i] = entry;
2671 | } else if (c === Promise) {
2672 | var promise = new c(noop);
2673 | handleMaybeThenable(promise, entry, _then);
2674 | this._willSettleAt(promise, i);
2675 | } else {
2676 | this._willSettleAt(new c(function (resolve$$) {
2677 | return resolve$$(entry);
2678 | }), i);
2679 | }
2680 | } else {
2681 | this._willSettleAt(resolve$$(entry), i);
2682 | }
2683 | };
2684 |
2685 | Enumerator.prototype._settledAt = function (state, i, value) {
2686 | var promise = this.promise;
2687 |
2688 | if (promise._state === PENDING) {
2689 | this._remaining--;
2690 |
2691 | if (state === REJECTED) {
2692 | _reject(promise, value);
2693 | } else {
2694 | this._result[i] = value;
2695 | }
2696 | }
2697 |
2698 | if (this._remaining === 0) {
2699 | fulfill(promise, this._result);
2700 | }
2701 | };
2702 |
2703 | Enumerator.prototype._willSettleAt = function (promise, i) {
2704 | var enumerator = this;
2705 |
2706 | subscribe(promise, undefined, function (value) {
2707 | return enumerator._settledAt(FULFILLED, i, value);
2708 | }, function (reason) {
2709 | return enumerator._settledAt(REJECTED, i, reason);
2710 | });
2711 | };
2712 |
2713 | /**
2714 | `Promise.all` accepts an array of promises, and returns a new promise which
2715 | is fulfilled with an array of fulfillment values for the passed promises, or
2716 | rejected with the reason of the first passed promise to be rejected. It casts all
2717 | elements of the passed iterable to promises as it runs this algorithm.
2718 |
2719 | Example:
2720 |
2721 | ```javascript
2722 | let promise1 = resolve(1);
2723 | let promise2 = resolve(2);
2724 | let promise3 = resolve(3);
2725 | let promises = [ promise1, promise2, promise3 ];
2726 |
2727 | Promise.all(promises).then(function(array){
2728 | // The array here would be [ 1, 2, 3 ];
2729 | });
2730 | ```
2731 |
2732 | If any of the `promises` given to `all` are rejected, the first promise
2733 | that is rejected will be given as an argument to the returned promises's
2734 | rejection handler. For example:
2735 |
2736 | Example:
2737 |
2738 | ```javascript
2739 | let promise1 = resolve(1);
2740 | let promise2 = reject(new Error("2"));
2741 | let promise3 = reject(new Error("3"));
2742 | let promises = [ promise1, promise2, promise3 ];
2743 |
2744 | Promise.all(promises).then(function(array){
2745 | // Code here never runs because there are rejected promises!
2746 | }, function(error) {
2747 | // error.message === "2"
2748 | });
2749 | ```
2750 |
2751 | @method all
2752 | @static
2753 | @param {Array} entries array of promises
2754 | @param {String} label optional string for labeling the promise.
2755 | Useful for tooling.
2756 | @return {Promise} promise that is fulfilled when all `promises` have been
2757 | fulfilled, or rejected if any of them become rejected.
2758 | @static
2759 | */
2760 | function all(entries) {
2761 | return new Enumerator(this, entries).promise;
2762 | }
2763 |
2764 | /**
2765 | `Promise.race` returns a new promise which is settled in the same way as the
2766 | first passed promise to settle.
2767 |
2768 | Example:
2769 |
2770 | ```javascript
2771 | let promise1 = new Promise(function(resolve, reject){
2772 | setTimeout(function(){
2773 | resolve('promise 1');
2774 | }, 200);
2775 | });
2776 |
2777 | let promise2 = new Promise(function(resolve, reject){
2778 | setTimeout(function(){
2779 | resolve('promise 2');
2780 | }, 100);
2781 | });
2782 |
2783 | Promise.race([promise1, promise2]).then(function(result){
2784 | // result === 'promise 2' because it was resolved before promise1
2785 | // was resolved.
2786 | });
2787 | ```
2788 |
2789 | `Promise.race` is deterministic in that only the state of the first
2790 | settled promise matters. For example, even if other promises given to the
2791 | `promises` array argument are resolved, but the first settled promise has
2792 | become rejected before the other promises became fulfilled, the returned
2793 | promise will become rejected:
2794 |
2795 | ```javascript
2796 | let promise1 = new Promise(function(resolve, reject){
2797 | setTimeout(function(){
2798 | resolve('promise 1');
2799 | }, 200);
2800 | });
2801 |
2802 | let promise2 = new Promise(function(resolve, reject){
2803 | setTimeout(function(){
2804 | reject(new Error('promise 2'));
2805 | }, 100);
2806 | });
2807 |
2808 | Promise.race([promise1, promise2]).then(function(result){
2809 | // Code here never runs
2810 | }, function(reason){
2811 | // reason.message === 'promise 2' because promise 2 became rejected before
2812 | // promise 1 became fulfilled
2813 | });
2814 | ```
2815 |
2816 | An example real-world use case is implementing timeouts:
2817 |
2818 | ```javascript
2819 | Promise.race([ajax('foo.json'), timeout(5000)])
2820 | ```
2821 |
2822 | @method race
2823 | @static
2824 | @param {Array} promises array of promises to observe
2825 | Useful for tooling.
2826 | @return {Promise} a promise which settles in the same way as the first passed
2827 | promise to settle.
2828 | */
2829 | function race(entries) {
2830 | /*jshint validthis:true */
2831 | var Constructor = this;
2832 |
2833 | if (!isArray(entries)) {
2834 | return new Constructor(function (_, reject) {
2835 | return reject(new TypeError('You must pass an array to race.'));
2836 | });
2837 | } else {
2838 | return new Constructor(function (resolve, reject) {
2839 | var length = entries.length;
2840 | for (var i = 0; i < length; i++) {
2841 | Constructor.resolve(entries[i]).then(resolve, reject);
2842 | }
2843 | });
2844 | }
2845 | }
2846 |
2847 | /**
2848 | `Promise.reject` returns a promise rejected with the passed `reason`.
2849 | It is shorthand for the following:
2850 |
2851 | ```javascript
2852 | let promise = new Promise(function(resolve, reject){
2853 | reject(new Error('WHOOPS'));
2854 | });
2855 |
2856 | promise.then(function(value){
2857 | // Code here doesn't run because the promise is rejected!
2858 | }, function(reason){
2859 | // reason.message === 'WHOOPS'
2860 | });
2861 | ```
2862 |
2863 | Instead of writing the above, your code now simply becomes the following:
2864 |
2865 | ```javascript
2866 | let promise = Promise.reject(new Error('WHOOPS'));
2867 |
2868 | promise.then(function(value){
2869 | // Code here doesn't run because the promise is rejected!
2870 | }, function(reason){
2871 | // reason.message === 'WHOOPS'
2872 | });
2873 | ```
2874 |
2875 | @method reject
2876 | @static
2877 | @param {Any} reason value that the returned promise will be rejected with.
2878 | Useful for tooling.
2879 | @return {Promise} a promise rejected with the given `reason`.
2880 | */
2881 | function reject(reason) {
2882 | /*jshint validthis:true */
2883 | var Constructor = this;
2884 | var promise = new Constructor(noop);
2885 | _reject(promise, reason);
2886 | return promise;
2887 | }
2888 |
2889 | function needsResolver() {
2890 | throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
2891 | }
2892 |
2893 | function needsNew() {
2894 | throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
2895 | }
2896 |
2897 | /**
2898 | Promise objects represent the eventual result of an asynchronous operation. The
2899 | primary way of interacting with a promise is through its `then` method, which
2900 | registers callbacks to receive either a promise's eventual value or the reason
2901 | why the promise cannot be fulfilled.
2902 |
2903 | Terminology
2904 | -----------
2905 |
2906 | - `promise` is an object or function with a `then` method whose behavior conforms to this specification.
2907 | - `thenable` is an object or function that defines a `then` method.
2908 | - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
2909 | - `exception` is a value that is thrown using the throw statement.
2910 | - `reason` is a value that indicates why a promise was rejected.
2911 | - `settled` the final resting state of a promise, fulfilled or rejected.
2912 |
2913 | A promise can be in one of three states: pending, fulfilled, or rejected.
2914 |
2915 | Promises that are fulfilled have a fulfillment value and are in the fulfilled
2916 | state. Promises that are rejected have a rejection reason and are in the
2917 | rejected state. A fulfillment value is never a thenable.
2918 |
2919 | Promises can also be said to *resolve* a value. If this value is also a
2920 | promise, then the original promise's settled state will match the value's
2921 | settled state. So a promise that *resolves* a promise that rejects will
2922 | itself reject, and a promise that *resolves* a promise that fulfills will
2923 | itself fulfill.
2924 |
2925 |
2926 | Basic Usage:
2927 | ------------
2928 |
2929 | ```js
2930 | let promise = new Promise(function(resolve, reject) {
2931 | // on success
2932 | resolve(value);
2933 |
2934 | // on failure
2935 | reject(reason);
2936 | });
2937 |
2938 | promise.then(function(value) {
2939 | // on fulfillment
2940 | }, function(reason) {
2941 | // on rejection
2942 | });
2943 | ```
2944 |
2945 | Advanced Usage:
2946 | ---------------
2947 |
2948 | Promises shine when abstracting away asynchronous interactions such as
2949 | `XMLHttpRequest`s.
2950 |
2951 | ```js
2952 | function getJSON(url) {
2953 | return new Promise(function(resolve, reject){
2954 | let xhr = new XMLHttpRequest();
2955 |
2956 | xhr.open('GET', url);
2957 | xhr.onreadystatechange = handler;
2958 | xhr.responseType = 'json';
2959 | xhr.setRequestHeader('Accept', 'application/json');
2960 | xhr.send();
2961 |
2962 | function handler() {
2963 | if (this.readyState === this.DONE) {
2964 | if (this.status === 200) {
2965 | resolve(this.response);
2966 | } else {
2967 | reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));
2968 | }
2969 | }
2970 | };
2971 | });
2972 | }
2973 |
2974 | getJSON('/posts.json').then(function(json) {
2975 | // on fulfillment
2976 | }, function(reason) {
2977 | // on rejection
2978 | });
2979 | ```
2980 |
2981 | Unlike callbacks, promises are great composable primitives.
2982 |
2983 | ```js
2984 | Promise.all([
2985 | getJSON('/posts'),
2986 | getJSON('/comments')
2987 | ]).then(function(values){
2988 | values[0] // => postsJSON
2989 | values[1] // => commentsJSON
2990 |
2991 | return values;
2992 | });
2993 | ```
2994 |
2995 | @class Promise
2996 | @param {function} resolver
2997 | Useful for tooling.
2998 | @constructor
2999 | */
3000 | function Promise(resolver) {
3001 | this[PROMISE_ID] = nextId();
3002 | this._result = this._state = undefined;
3003 | this._subscribers = [];
3004 |
3005 | if (noop !== resolver) {
3006 | typeof resolver !== 'function' && needsResolver();
3007 | this instanceof Promise ? initializePromise(this, resolver) : needsNew();
3008 | }
3009 | }
3010 |
3011 | Promise.all = all;
3012 | Promise.race = race;
3013 | Promise.resolve = resolve;
3014 | Promise.reject = reject;
3015 | Promise._setScheduler = setScheduler;
3016 | Promise._setAsap = setAsap;
3017 | Promise._asap = asap;
3018 |
3019 | Promise.prototype = {
3020 | constructor: Promise,
3021 |
3022 | /**
3023 | The primary way of interacting with a promise is through its `then` method,
3024 | which registers callbacks to receive either a promise's eventual value or the
3025 | reason why the promise cannot be fulfilled.
3026 |
3027 | ```js
3028 | findUser().then(function(user){
3029 | // user is available
3030 | }, function(reason){
3031 | // user is unavailable, and you are given the reason why
3032 | });
3033 | ```
3034 |
3035 | Chaining
3036 | --------
3037 |
3038 | The return value of `then` is itself a promise. This second, 'downstream'
3039 | promise is resolved with the return value of the first promise's fulfillment
3040 | or rejection handler, or rejected if the handler throws an exception.
3041 |
3042 | ```js
3043 | findUser().then(function (user) {
3044 | return user.name;
3045 | }, function (reason) {
3046 | return 'default name';
3047 | }).then(function (userName) {
3048 | // If `findUser` fulfilled, `userName` will be the user's name, otherwise it
3049 | // will be `'default name'`
3050 | });
3051 |
3052 | findUser().then(function (user) {
3053 | throw new Error('Found user, but still unhappy');
3054 | }, function (reason) {
3055 | throw new Error('`findUser` rejected and we're unhappy');
3056 | }).then(function (value) {
3057 | // never reached
3058 | }, function (reason) {
3059 | // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
3060 | // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
3061 | });
3062 | ```
3063 | If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
3064 |
3065 | ```js
3066 | findUser().then(function (user) {
3067 | throw new PedagogicalException('Upstream error');
3068 | }).then(function (value) {
3069 | // never reached
3070 | }).then(function (value) {
3071 | // never reached
3072 | }, function (reason) {
3073 | // The `PedgagocialException` is propagated all the way down to here
3074 | });
3075 | ```
3076 |
3077 | Assimilation
3078 | ------------
3079 |
3080 | Sometimes the value you want to propagate to a downstream promise can only be
3081 | retrieved asynchronously. This can be achieved by returning a promise in the
3082 | fulfillment or rejection handler. The downstream promise will then be pending
3083 | until the returned promise is settled. This is called *assimilation*.
3084 |
3085 | ```js
3086 | findUser().then(function (user) {
3087 | return findCommentsByAuthor(user);
3088 | }).then(function (comments) {
3089 | // The user's comments are now available
3090 | });
3091 | ```
3092 |
3093 | If the assimliated promise rejects, then the downstream promise will also reject.
3094 |
3095 | ```js
3096 | findUser().then(function (user) {
3097 | return findCommentsByAuthor(user);
3098 | }).then(function (comments) {
3099 | // If `findCommentsByAuthor` fulfills, we'll have the value here
3100 | }, function (reason) {
3101 | // If `findCommentsByAuthor` rejects, we'll have the reason here
3102 | });
3103 | ```
3104 |
3105 | Simple Example
3106 | --------------
3107 |
3108 | Synchronous Example
3109 |
3110 | ```javascript
3111 | let result;
3112 |
3113 | try {
3114 | result = findResult();
3115 | // success
3116 | } catch(reason) {
3117 | // failure
3118 | }
3119 | ```
3120 |
3121 | Errback Example
3122 |
3123 | ```js
3124 | findResult(function(result, err){
3125 | if (err) {
3126 | // failure
3127 | } else {
3128 | // success
3129 | }
3130 | });
3131 | ```
3132 |
3133 | Promise Example;
3134 |
3135 | ```javascript
3136 | findResult().then(function(result){
3137 | // success
3138 | }, function(reason){
3139 | // failure
3140 | });
3141 | ```
3142 |
3143 | Advanced Example
3144 | --------------
3145 |
3146 | Synchronous Example
3147 |
3148 | ```javascript
3149 | let author, books;
3150 |
3151 | try {
3152 | author = findAuthor();
3153 | books = findBooksByAuthor(author);
3154 | // success
3155 | } catch(reason) {
3156 | // failure
3157 | }
3158 | ```
3159 |
3160 | Errback Example
3161 |
3162 | ```js
3163 |
3164 | function foundBooks(books) {
3165 |
3166 | }
3167 |
3168 | function failure(reason) {
3169 |
3170 | }
3171 |
3172 | findAuthor(function(author, err){
3173 | if (err) {
3174 | failure(err);
3175 | // failure
3176 | } else {
3177 | try {
3178 | findBoooksByAuthor(author, function(books, err) {
3179 | if (err) {
3180 | failure(err);
3181 | } else {
3182 | try {
3183 | foundBooks(books);
3184 | } catch(reason) {
3185 | failure(reason);
3186 | }
3187 | }
3188 | });
3189 | } catch(error) {
3190 | failure(err);
3191 | }
3192 | // success
3193 | }
3194 | });
3195 | ```
3196 |
3197 | Promise Example;
3198 |
3199 | ```javascript
3200 | findAuthor().
3201 | then(findBooksByAuthor).
3202 | then(function(books){
3203 | // found books
3204 | }).catch(function(reason){
3205 | // something went wrong
3206 | });
3207 | ```
3208 |
3209 | @method then
3210 | @param {Function} onFulfilled
3211 | @param {Function} onRejected
3212 | Useful for tooling.
3213 | @return {Promise}
3214 | */
3215 | then: then,
3216 |
3217 | /**
3218 | `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
3219 | as the catch block of a try/catch statement.
3220 |
3221 | ```js
3222 | function findAuthor(){
3223 | throw new Error('couldn't find that author');
3224 | }
3225 |
3226 | // synchronous
3227 | try {
3228 | findAuthor();
3229 | } catch(reason) {
3230 | // something went wrong
3231 | }
3232 |
3233 | // async with promises
3234 | findAuthor().catch(function(reason){
3235 | // something went wrong
3236 | });
3237 | ```
3238 |
3239 | @method catch
3240 | @param {Function} onRejection
3241 | Useful for tooling.
3242 | @return {Promise}
3243 | */
3244 | 'catch': function _catch(onRejection) {
3245 | return this.then(null, onRejection);
3246 | }
3247 | };
3248 |
3249 | function polyfill() {
3250 | var local = undefined;
3251 |
3252 | if (typeof global !== 'undefined') {
3253 | local = global;
3254 | } else if (typeof self !== 'undefined') {
3255 | local = self;
3256 | } else {
3257 | try {
3258 | local = Function('return this')();
3259 | } catch (e) {
3260 | throw new Error('polyfill failed because global object is unavailable in this environment');
3261 | }
3262 | }
3263 |
3264 | var P = local.Promise;
3265 |
3266 | if (P) {
3267 | var promiseToString = null;
3268 | try {
3269 | promiseToString = Object.prototype.toString.call(P.resolve());
3270 | } catch (e) {
3271 | // silently ignored
3272 | }
3273 |
3274 | if (promiseToString === '[object Promise]' && !P.cast) {
3275 | return;
3276 | }
3277 | }
3278 |
3279 | local.Promise = Promise;
3280 | }
3281 |
3282 | polyfill();
3283 | // Strange compat..
3284 | Promise.polyfill = polyfill;
3285 | Promise.Promise = Promise;
3286 |
3287 | return Promise;
3288 |
3289 | })));
3290 |
3291 | },{}]},{},[2])(2)
3292 | });
--------------------------------------------------------------------------------
/js/markdown-editor.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE in the project root for license information.
2 |
3 | var markdownEditor = {
4 | applicationId: "5fc58006-b25f-4eaf-8f30-527c6fa7e5f5",
5 | defaultFileName: "MD file.md",
6 | microsoftGraphApiRoot: "https://graph.microsoft.com/v1.0/",
7 |
8 | /************ Open *************/
9 |
10 | // Open a new file by invoking the picker to select a file from OneDrive.
11 | openFile: function () {
12 | var editor = this;
13 |
14 | // Build the options that we pass to the picker
15 | var options = {
16 | // Specify the options for the picker (we want download links and only one file).
17 | clientId: editor.applicationId,
18 | action: "download",
19 | multiSelect: false,
20 | advanced: {
21 | /* Filter the files that are available for selection */
22 | filter: ".md,.mdown,.txt",
23 | /* Request a few additional properties */
24 | queryParameters: "select=*,name,size",
25 | /* Request a read-write scope for the access token */
26 | scopes: ["Files.ReadWrite"]
27 | },
28 | success: function (files) {
29 | // Update our state to remember how we can use the API to write back to this file.
30 | editor.accessToken = files.accessToken;
31 |
32 | // Get the first selected file (since we're not doing multi-select) and open it
33 | var selectedFile = files.value[0];
34 | editor.openItemInEditor(selectedFile);
35 | },
36 | error: function (e) { editor.showError("Error occurred while picking a file: " + e, e); },
37 | };
38 | OneDrive.open(options);
39 | },
40 |
41 | // Method used to open the picked file into the editor. Resets local state and downloads the file from OneDrive.
42 | openItemInEditor: function (fileItem) {
43 | var editor = this;
44 | editor.lastSelectedFile = fileItem;
45 | // Retrieve the contents of the file and load it into our editor
46 | var downloadLink = fileItem["@microsoft.graph.downloadUrl"];
47 |
48 | // Use JQuery AJAX to download the file
49 | $.ajax(downloadLink, {
50 | success: function (data, status, xhr) {
51 |
52 | // load the file into the editor
53 | editor.setEditorBody(xhr.responseText);
54 | editor.setFilename(fileItem.name);
55 | $("#canvas").attr("disabled", false);
56 | editor.openFileID = fileItem.id;
57 | },
58 | error: function(xhr, status, err) {
59 | editor.showError(err);
60 | }
61 | });
62 | },
63 |
64 | /************ Save As *************/
65 |
66 | // Save the contents of the editor back to the server using a new filename. Invokes
67 | // the picker to allow the user to select a folder where the file should be saved.
68 | saveAsFile: function () {
69 | var editor = this;
70 | var filename = "";
71 |
72 | // Ensure we have a valid filename for the file
73 | if (editor.lastSelectedFile) {
74 | filename = editor.lastSelectedFile.name;
75 | }
76 | if (!filename || filename == "") {
77 | filename = editor.defaultFileName;
78 | }
79 |
80 | // Build the picker options to query for a folder where the file should be saved.
81 | var options = {
82 | clientId: editor.applicationId,
83 | action: "query",
84 | advanced: {
85 | // Request additional parameters when we save the file
86 | queryParameters: "select=id,name,parentReference"
87 | },
88 | success: function (selection) {
89 | // The return here is the folder where we need to upload the item
90 | var folder = selection.value[0];
91 |
92 |
93 | if (!editor.lastSelectedFile) {
94 | // Remember the details of the file we just created
95 | editor.lastSelectedFile = {
96 | id: null,
97 | name: filename,
98 | parentReference: {
99 | driveId: folder.parentReference.driveId,
100 | id: folder.id
101 | }
102 | }
103 | } else {
104 | // Update the lastSelectedFile item with the details of the new destination folder
105 | editor.lastSelectedFile.parentReference.driveId = folder.parentReference.driveId;
106 | editor.lastSelectedFile.parentReference.id = folder.id
107 | }
108 |
109 | // Store the access token from the file picker, so we don't need to get a new one
110 | editor.accessToken = selection.accessToken;
111 |
112 | // Call the saveFileWithToken method, which will write this file back with Microsoft Graph
113 | editor.saveFileWithAPI( { uploadIntoParentFolder: true });
114 | },
115 | error: function (e) { editor.showError("An error occurred while saving the file: " + e, e); }
116 | };
117 |
118 | // Launch the picker
119 | OneDrive.save(options);
120 | },
121 |
122 | /************ Save *************/
123 |
124 | // Save the contents of the editor back to the file that was opened. If no file was
125 | // currently open, the saveAsFile method is invoked.
126 | saveFile: function () {
127 | var editor = this;
128 | // Check to see if we know about an open file. If not, revert to the save as flow.
129 | if (editor.openFileID == "") {
130 | editor.saveAsFile();
131 | return;
132 | }
133 |
134 | // Since we're using the API to write back changes, make sure we have a valid
135 | // access_token and then invoke saveFileWithToken.
136 | editor.saveFileWithAPI();
137 | },
138 |
139 | // Save the contents of the editor back to a target drive item. Requires an access token
140 | // and a parent reference in the state object.
141 | saveFileWithAPI: function (state) {
142 | var editor = this;
143 | if (editor.accessToken == null) {
144 | // An error occurred and we don't have a token available to save.
145 | editor.showError("Unable to save file due to an authentication error. Try using Save As instead.");
146 | return;
147 | }
148 |
149 | // This method uses the REST API directly instead of the file picker,
150 | // using some values that we stored from the picker when we opened the item.
151 | var url = editor.generateGraphUrl(editor.lastSelectedFile, (state && state.uploadIntoParentFolder) ? true : false, "/content");
152 |
153 | var bodyContent = $("#canvas").val().replace(/\r\n|\r|\n/g, "\r\n");
154 |
155 | // Call the REST API to PUT the text value to the contents of the file.
156 | $.ajax(url, {
157 | method: "PUT",
158 | contentType: "application/octet-stream",
159 | data: bodyContent,
160 | processData: false,
161 | headers: { Authorization: "Bearer" + editor.accessToken },
162 | success: function(data, status, xhr) {
163 | if (data && data.name && data.parentReference) {
164 | editor.lastSelectedFile = data;
165 | editor.showSuccessMessage("File was saved.");
166 | }
167 | },
168 | error: function(xhr, status, err) {
169 | editor.showError(err);
170 | }
171 | });
172 | },
173 |
174 |
175 | /************ Rename File *************/
176 |
177 | // Rename the currently open file by providing a new name for the file via an input
178 | // dialog
179 | renameFile: function () {
180 | var editor = this;
181 |
182 | var oldFilename = (editor.lastSelectedFile && editor.lastSelectedFile.name) ? editor.lastSelectedFile.name : editor.defaultFileName;
183 | var newFilename = window.prompt("Rename file", oldFilename);
184 | if (!newFilename) return;
185 |
186 | editor.setFilename(newFilename);
187 |
188 | if (editor.lastSelectedFile && editor.lastSelectedFile.id) {
189 | // Patch the file to rename it in real time.
190 | editor.lastSelectedFile.name = newFilename;
191 | editor.patchDriveItemWithAPI({ propertyList: [ "name" ]} );
192 | } else {
193 | // The file hasn't been saved yet, so the rename is just local
194 | }
195 | },
196 |
197 | // Patch a DriveItem via the Microsoft Graph. Expects an access token and the state
198 | // parameter to have a driveItem, propertyList, and parent (reference to this object) properties.
199 | // driveItem is the item to update, which needs to have its id and parentReference.driveId property set to the item to patch.
200 | // propertyList is an array of properties on the driveItem that will be submitted as the patch. These must be top-level properties of the driveItem
201 | patchDriveItemWithAPI: function(state) {
202 | var editor = this;
203 | if (editor.accessToken == null) {
204 | // An error occurred and we don't have a token available to save.
205 | editor.showError("Unable to save file due to an authentication error. Try using Save As instead.");
206 | return;
207 | }
208 |
209 | if (state == null) {
210 | editor.showError("The state parameter is required for this method.");
211 | return;
212 | }
213 |
214 | var item = editor.lastSelectedFile;
215 | var propList = state.propertyList;
216 |
217 | // For PATCH we don't invoke the picker, we're going to use the REST API directly
218 | var url = editor.generateGraphUrl(item, false, null);
219 |
220 | // Copy the values into patchData from the driveItem, based on names of properties in propertyList
221 | var patchData = { };
222 | for(var i=0, len = propList.length; i < len; i++)
223 | {
224 | patchData[propList[i]] = item[propList[i]];
225 | }
226 |
227 | $.ajax(url, {
228 | method: "PATCH",
229 | contentType: "application/json; charset=UTF-8",
230 | data: JSON.stringify(patchData),
231 | headers: { Authorization: "Bearer" + editor.accessToken },
232 | success: function(data, status, xhr) {
233 | if (data && data.name && data.parentReference) {
234 | editor.showSuccessMessage("File was updated successfully.");
235 | editor.lastSelectedFile = data;
236 | }
237 | },
238 | error: function(xhr, status, err) {
239 | editor.showError("Unable to patch file metadata: " + err);
240 | }
241 | });
242 | },
243 |
244 | /***************** Share File ***************/
245 | shareFile: function () {
246 | var editor = this;
247 | // Make a request to Microsoft Graph to retrieve a default sharing URL for the file.
248 | if (!editor.lastSelectedFile || !editor.lastSelectedFile.id)
249 | {
250 | editor.showError("You need to save the file first before you can share it.");
251 | return;
252 | }
253 |
254 | editor.getSharingLinkWithAPI();
255 | },
256 |
257 | getSharingLinkWithAPI: function() {
258 | var editor = this;
259 | var driveItem = editor.lastSelectedFile;
260 |
261 | var url = editor.generateGraphUrl(driveItem, false, "/createLink");
262 | var requestBody = { type: "view" };
263 |
264 | $.ajax(url, {
265 | method: "POST",
266 | contentType: "application/json; charset=UTF-8",
267 | data: JSON.stringify(requestBody),
268 | headers: { Authorization: "Bearer" + editor.accessToken },
269 | success: function(data, status, xhr) {
270 | if (data && data.link && data.link.webUrl) {
271 | window.prompt("View-only sharing link", data.link.webUrl);
272 | } else {
273 | editor.showError("Unable to retrieve a sharing link for this file.");
274 | }
275 | },
276 | error: function(xhr, status, err) {
277 | editor.showError("Unable to retrieve a sharing link for this file.");
278 | }
279 | });
280 | },
281 |
282 | // Used to generate the Microsoft Graph URL for a target item, with a few parameters
283 | // uploadIntoParentFolder: bool, indicates that we should be targeting the parent folder + filename instead of the item itself
284 | // targetContentStream: bool, indicates we should append /content to the item URL
285 | generateGraphUrl: function(driveItem, targetParentFolder, itemRelativeApiPath) {
286 | var url = this.microsoftGraphApiRoot;
287 | if (targetParentFolder)
288 | {
289 | url += "drives/" + driveItem.parentReference.driveId + "/items/" +driveItem.parentReference.id + "/children/" + driveItem.name;
290 | } else {
291 | url += "drives/" + driveItem.parentReference.driveId + "/items/" + driveItem.id;
292 | }
293 |
294 | if (itemRelativeApiPath) {
295 | url += itemRelativeApiPath;
296 | }
297 | return url;
298 | },
299 |
300 |
301 | /************ Create New File *************/
302 |
303 | // Clear the current editor buffer and reset any local state so we don't
304 | // overwrite an existing file by mistake.
305 | createNewFile: function () {
306 | this.lastSelectedFile = null;
307 | this.openFileID = "";
308 | this.setFilename(this.defaultFileName);
309 | $("#canvas").attr("disabled", false);
310 | this.setEditorBody("");
311 | },
312 |
313 |
314 | /************ Utility functions *************/
315 |
316 | // Update the state of the editor with a new filename.
317 | setFilename: function (filename) {
318 | var btnRename = this.buttons["rename"];
319 | if (btnRename) {
320 | $(btnRename).text(filename);
321 | }
322 | },
323 |
324 | // Set the contents of the editor to a new value.
325 | setEditorBody: function (text) {
326 | $("#canvas").val(text);
327 | },
328 |
329 | // State and function to connect elements in the HTML page to actions in the markdown editor.
330 | buttons: {},
331 | wireUpCommandButton: function(element, cmd)
332 | {
333 | this.buttons[cmd] = element;
334 | switch(cmd) {
335 | case "new":
336 | element.onclick = function () { markdownEditor.createNewFile(); return false; }
337 | break;
338 | case "open":
339 | element.onclick = function () { markdownEditor.openFile(); return false; }
340 | break;
341 | case "save":
342 | element.onclick = function () { markdownEditor.saveFile(); return false; }
343 | break;
344 | case "saveAs":
345 | element.onclick = function () { markdownEditor.saveAsFile(); return false; }
346 | break;
347 | case "rename":
348 | element.onclick = function () { markdownEditor.renameFile(); return false; }
349 | break;
350 | case "share":
351 | element.onclick = function () { markdownEditor.shareFile(); return false; }
352 | break;
353 | }
354 | },
355 |
356 | // Handle displaying errors to the user
357 | showError: function (msg, e) {
358 | window.alert(msg);
359 | },
360 |
361 | showSuccessMessage: function(msg) {
362 | window.alert(msg);
363 | },
364 |
365 | // An object representing the currently selected file
366 | lastSelectedFile: null,
367 |
368 | // The access_token returned from the picker so we can make API calls again.
369 | accessToken: null,
370 |
371 | user: {
372 | id: "nouser@contoso.com",
373 | domain: "organizations"
374 | }
375 | }
376 |
377 | $("#canvas").attr("disabled", true);
378 |
--------------------------------------------------------------------------------
/license.txt:
--------------------------------------------------------------------------------
1 | OneDrive Text Editor - Sample Code
2 | Copyright (c) Microsoft Corporation
3 | All rights reserved.
4 |
5 | MIT License
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy of
8 | this software and associated documentation files (the ""Software""), to deal in
9 | the Software without restriction, including without limitation the rights to use,
10 | copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
11 | Software, and to permit persons to whom the Software is furnished to do so,
12 | subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
18 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
19 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # OneDrive Text Editor Sample
2 |
3 | This sample application provides a simple markdown (text) editor experience for files stored in OneDrive.
4 |
5 | It demonstrates the following:
6 |
7 | * Using the OneDrive file picker to select files from OneDrive personal and OneDrive for Business.
8 | * Downloading the contents of a file from OneDrive
9 | * Saving a file back to OneDrive
10 | * Using the Microsoft Graph to retrieve a sharing link
11 |
12 | This is written as a single-page JavaScript application and can be hosted on any HTTPS compatible server.
13 |
14 | ## App Registration
15 |
16 | To register an app to use the [v7 OneDrive Picker](https://dev.onedrive.com/sdk/js-v7/js-picker-overview.htm) visit the [Microsoft Apps Registration Page](https://apps.dev.microsoft.com).
17 |
--------------------------------------------------------------------------------
/start-iis.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | "%programfiles%\IIS Express\iisexpress.exe" /path:"%CD%" /port:9999
3 |
--------------------------------------------------------------------------------