@scaleflex/widget-core 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,256 @@
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
5
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
6
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
7
+ import { createSlice, isAnyOf } from '@reduxjs/toolkit';
8
+ import checkPermissions from '@scaleflex/widget-utils/lib/checkPermissions';
9
+ import createThunk from '@scaleflex/widget-utils/lib/createThunk';
10
+ import { AUTH_STATE, PERMISSIONS, PLUGINS_IDS } from '@scaleflex/widget-utils/lib/constants';
11
+ import { slicePropName as coreCommonSliceName } from './common.slice';
12
+
13
+ /**
14
+ * The order of the code in slice file is:
15
+ * 1. initialState (*No* export needed)
16
+ * 2. automated thunks functions -- uses createThunk API-- (export needed)
17
+ * 3. createSlice (*No* export needed)
18
+ * 4. actions exports
19
+ * 5. selectors (export needed)
20
+ * 6. default reducer export
21
+ *
22
+ */
23
+ var slicePropName = 'user';
24
+ var sliceName = "".concat(PLUGINS_IDS.CORE, "/").concat(slicePropName);
25
+ var sassKeyExpireDuration = 1170000; // 19.5 minutes
26
+
27
+ var initialState = {
28
+ sassKey: '',
29
+ authState: AUTH_STATE.ANONYMOUS,
30
+ permissions: {},
31
+ // userCheckedPermissions
32
+ securityData: {},
33
+ info: {} // possible to be empty, most probably won't be empty in-case of login mode.
34
+ };
35
+ export var generateUserKey = createThunk(async function (_, thunkApi) {
36
+ var _userAuthInfo$key_val, _userAuthInfo$key_val2, _filerobot$getPlugin$, _filerobot$getPlugin;
37
+ var _thunkApi$extra = thunkApi.extra,
38
+ filerobot = _thunkApi$extra.filerobot,
39
+ apiClient = _thunkApi$extra.apiClient;
40
+ var url = "".concat(filerobot.opts.apiEndpointWithContainer, "/key/").concat(filerobot.opts.securityTemplateId);
41
+
42
+ // Retrieve sassKey from server through security template id
43
+ var userAuthInfo = await apiClient.get(url, {
44
+ signal: thunkApi.signal,
45
+ noDefaultHeaders: true
46
+ });
47
+ var userAuthState = await thunkApi.dispatch(fetchUserAuthState({
48
+ userSassKey: userAuthInfo.key,
49
+ skipDispatch: true
50
+ }));
51
+
52
+ // Re-generate a new sassKey before the current one expires.
53
+ setTimeout(function () {
54
+ thunkApi.dispatch(generateUserKey());
55
+ }, (_userAuthInfo$key_val = (_userAuthInfo$key_val2 = userAuthInfo.key_validity) === null || _userAuthInfo$key_val2 === void 0 ? void 0 : _userAuthInfo$key_val2.expire_duration) !== null && _userAuthInfo$key_val !== void 0 ? _userAuthInfo$key_val : sassKeyExpireDuration);
56
+ filerobot.emit('sass-key-obtained', userAuthInfo.key);
57
+ var _ref = (_filerobot$getPlugin$ = (_filerobot$getPlugin = filerobot.getPlugin(PLUGINS_IDS.EXPLORER)) === null || _filerobot$getPlugin === void 0 ? void 0 : _filerobot$getPlugin.opts) !== null && _filerobot$getPlugin$ !== void 0 ? _filerobot$getPlugin$ : {},
58
+ useAssetsPicker = _ref.useAssetsPicker;
59
+
60
+ // Removed permissions from here, as we will always check the permissions in the userAuthState request.
61
+ return _objectSpread(_objectSpread({}, userAuthState), {}, {
62
+ useAssetsPicker: useAssetsPicker,
63
+ sassKey: userAuthInfo.key,
64
+ securityData: userAuthInfo
65
+ });
66
+ }, {
67
+ actionType: "".concat(sliceName, "/generateUserKey")
68
+ });
69
+ export var saveUserSassKey = createThunk(function (userSassKey, thunkApi) {
70
+ thunkApi.extra.filerobot.emit('sass-key-obtained', userSassKey);
71
+ var userSecurityData = selectUserSecurityData(thunkApi.getState());
72
+ return thunkApi.dispatch(userUpdated({
73
+ sassKey: userSassKey,
74
+ securityData: _objectSpread(_objectSpread({}, userSecurityData), {}, {
75
+ key: userSassKey
76
+ })
77
+ }));
78
+ });
79
+ export var fetchUserAuthState = createThunk(async function () {
80
+ var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
81
+ userSassKey = _ref2.userSassKey,
82
+ skipDispatch = _ref2.skipDispatch;
83
+ var thunkApi = arguments.length > 1 ? arguments[1] : undefined;
84
+ // We will have skipDispatch: true, when we call the fetchUserAuthState from the generateUserKey thunk,
85
+ // as we'll wait for the generateUserKey thunk & fetchUserAuthState thunk to finish then update the user state once,
86
+ // otherwise the user state should have skipDispatch: false, to update the user state after finishing its request.
87
+ if (skipDispatch) {
88
+ thunkApi.skipDispatch();
89
+ }
90
+ if (!userSassKey) {
91
+ thunkApi.skipDispatch();
92
+ return thunkApi.rejectWithValue('No sass key provided.');
93
+ }
94
+ var _thunkApi$extra2 = thunkApi.extra,
95
+ filerobot = _thunkApi$extra2.filerobot,
96
+ apiClient = _thunkApi$extra2.apiClient;
97
+ var _await$apiClient$get = await apiClient.get("".concat(filerobot.opts.apiEndpointWithContainer, "/v4/key/info?key=").concat(userSassKey), {
98
+ abortSignal: thunkApi.signal,
99
+ noDefaultHeaders: true
100
+ }),
101
+ isValidate = _await$apiClient$get.is_validate,
102
+ isUserInfoIncluded = _await$apiClient$get.is_user_info_included,
103
+ permissions = _await$apiClient$get.permissions;
104
+ var userAuthState = AUTH_STATE.ANONYMOUS;
105
+ if (isValidate) {
106
+ userAuthState = isUserInfoIncluded ? AUTH_STATE.AUTH : AUTH_STATE.UNAUTH;
107
+ }
108
+ // If no skipDispatch then emit the event, as this means no request is triggered for generating the sass key and sass key is provided from opts.
109
+ if (!skipDispatch) {
110
+ filerobot.emit('sass-key-obtained', userSassKey);
111
+ }
112
+ return {
113
+ sassKey: userSassKey,
114
+ authState: userAuthState,
115
+ permissions: checkPermissions(Array.isArray(permissions) && permissions.length > 0 ? permissions : filerobot.opts.userPermissions || permissions || [], Object.values(PERMISSIONS), true)
116
+ };
117
+ }, {
118
+ actionType: "".concat(sliceName, "/fetchUserAuthState"),
119
+ dismissGlobalAbort: true
120
+ });
121
+ export var userLogout = createThunk(function (_, thunkApi) {
122
+ var filerobot = thunkApi.extra.filerobot;
123
+ filerobot.emit('sass-key-obtained', undefined);
124
+ thunkApi.dispatch(userReset());
125
+ });
126
+ export var loginUserByCredentials = createThunk(async function (_ref3, thunkApi) {
127
+ var email = _ref3.email,
128
+ password = _ref3.password;
129
+ thunkApi.skipPendingDispatch();
130
+ var _thunkApi$extra3 = thunkApi.extra,
131
+ filerobot = _thunkApi$extra3.filerobot,
132
+ apiClient = _thunkApi$extra3.apiClient;
133
+ var token = filerobot.opts.container;
134
+ var response = await apiClient.postAdmin("login?token=".concat(token), {
135
+ data: {
136
+ login: {
137
+ email: email,
138
+ password: password
139
+ }
140
+ },
141
+ abortSignal: thunkApi.signal
142
+ });
143
+ var _ref4 = response || {},
144
+ userUuid = _ref4.user_uuid,
145
+ userEmail = _ref4.user_email,
146
+ sessionUuid = _ref4.session_uuid,
147
+ userPhotoUri = _ref4.user_photo_uri,
148
+ keychain = _ref4.keychain,
149
+ userName = _ref4.user_name;
150
+ // TODO: keyDuration is not supported from BE but added to be considered from their side once they add.
151
+ var _ref5 = (keychain === null || keychain === void 0 ? void 0 : keychain.tokens) || {},
152
+ userSassKey = _ref5.airstore_key,
153
+ permissions = _ref5.permissions;
154
+ if (userSassKey) {
155
+ filerobot.emit('sass-key-obtained', userSassKey);
156
+ if (filerobot.opts.sassKeyRenewerEnabled) {
157
+ // Send renew sass key request each hour
158
+ filerobot.sassKeyRenewer.subscribe();
159
+ }
160
+
161
+ // Expire the sass key if the duration is not 0, then the login page will show again.
162
+ // if (keyDuration !== 0) { // DEPRECATED! Not necessary according to new SassKeyRenewer logic
163
+ // setTimeout(() => {
164
+ // thunkApi.dispatch(userLogout())
165
+ // }, keyDuration)
166
+ // }
167
+ } else {
168
+ return thunkApi.rejectWithValue(new Error('No sass key generated, please try again later.'));
169
+ }
170
+ return {
171
+ sassKey: userSassKey,
172
+ authState: AUTH_STATE.AUTH,
173
+ permissions: checkPermissions(Array.isArray(permissions) && permissions.length > 0 ? permissions : filerobot.opts.userPermissions || permissions || [], Object.values(PERMISSIONS), true),
174
+ info: {
175
+ uuid: userUuid,
176
+ email: userEmail,
177
+ name: userName,
178
+ photo_uri: userPhotoUri,
179
+ sessionUuid: sessionUuid
180
+ }
181
+ };
182
+ }, {
183
+ actionType: "".concat(sliceName, "/loginUserByCredentials")
184
+ });
185
+ var userSlice = createSlice({
186
+ name: sliceName,
187
+ initialState: initialState,
188
+ reducers: {
189
+ userUpdated: function userUpdated(state, action) {
190
+ var newUserData = action.payload;
191
+ return _objectSpread(_objectSpread({}, state), newUserData);
192
+ },
193
+ userReset: function userReset(state) {
194
+ return _objectSpread(_objectSpread({}, state), initialState);
195
+ },
196
+ userInfoUpdated: function userInfoUpdated(state, action) {
197
+ return _objectSpread(_objectSpread({}, state), {}, {
198
+ info: _objectSpread(_objectSpread({}, state.info || {}), action.payload || {})
199
+ });
200
+ }
201
+ },
202
+ extraReducers: function extraReducers(builder) {
203
+ builder.addCase(generateUserKey.fulfilled, function (state, action) {
204
+ return _objectSpread(_objectSpread({}, state), action.payload);
205
+ }).addMatcher(isAnyOf(fetchUserAuthState.fulfilled, loginUserByCredentials.fulfilled), function (state, action) {
206
+ return _objectSpread(_objectSpread({}, state), action.payload);
207
+ });
208
+ }
209
+ });
210
+ var _userSlice$actions = userSlice.actions,
211
+ userUpdated = _userSlice$actions.userUpdated,
212
+ userInfoUpdated = _userSlice$actions.userInfoUpdated,
213
+ userReset = _userSlice$actions.userReset;
214
+ export { userUpdated, userInfoUpdated, userReset };
215
+ export var selectUser = function selectUser(state) {
216
+ return state[PLUGINS_IDS.CORE][slicePropName];
217
+ };
218
+ export var selectUserPermissions = function selectUserPermissions(state) {
219
+ return selectUser(state).permissions;
220
+ };
221
+
222
+ // `isDev` is used for enabling any feature requires user auth on dev. environment (in-case it is needed for some checking/improvements) and anyways it won't work from BE side as it requires the user auth.
223
+ export var selectIsUserAuth = function selectIsUserAuth(state) {
224
+ var _state$PLUGINS_IDS$CO, _state$PLUGINS_IDS$CO2;
225
+ return ((_state$PLUGINS_IDS$CO = state[PLUGINS_IDS.CORE]) === null || _state$PLUGINS_IDS$CO === void 0 ? void 0 : (_state$PLUGINS_IDS$CO2 = _state$PLUGINS_IDS$CO[coreCommonSliceName]) === null || _state$PLUGINS_IDS$CO2 === void 0 ? void 0 : _state$PLUGINS_IDS$CO2.isDevEnv) || selectUser(state).authState === AUTH_STATE.AUTH;
226
+ };
227
+ export var selectUserSecurityData = function selectUserSecurityData(state) {
228
+ return selectUser(state).securityData;
229
+ };
230
+ export var selectUserSassKey = function selectUserSassKey(state) {
231
+ return selectUser(state).sassKey;
232
+ };
233
+ export var selectUserInfo = function selectUserInfo(state) {
234
+ return selectUser(state).info;
235
+ };
236
+ export var selectUserSessionUuid = function selectUserSessionUuid(state) {
237
+ return selectUserInfo(state).sessionUuid;
238
+ };
239
+ export var selectIsUserPermittedTo = function selectIsUserPermittedTo(state, permissionToCheck) {
240
+ var userMustAuth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
241
+ var userPermissions = selectUserPermissions(state);
242
+ if (userMustAuth) {
243
+ var isUserAuth = selectIsUserAuth(state);
244
+ if (!isUserAuth) {
245
+ return false;
246
+ }
247
+ }
248
+ return Boolean(userPermissions[permissionToCheck]);
249
+ };
250
+ export var selectIsUserPermittedToShare = function selectIsUserPermittedToShare(state) {
251
+ return selectIsUserPermittedTo(state, PERMISSIONS.OBJECTS_SHARE_MANAGE, true);
252
+ };
253
+ export var selectIsUserPermittedToDisplayFile = function selectIsUserPermittedToDisplayFile(state) {
254
+ return selectIsUserPermittedTo(state, PERMISSIONS.DISPLAY);
255
+ };
256
+ export default userSlice.reducer;
package/lib/style.scss ADDED
@@ -0,0 +1,3 @@
1
+ @import './_variables.scss';
2
+ @import './_utils.scss';
3
+ @import './_common.scss';
@@ -0,0 +1,42 @@
1
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
2
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
3
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
4
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
5
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
6
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
7
+ // Edge 15.x does not fire 'progress' events on uploads.
8
+ // See https://github.com/transloadit/filerobot/issues/945
9
+ // And https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/12224510/
10
+ export default function supportsUploadProgress(userAgent) {
11
+ // Allow passing in userAgent for tests
12
+ if (userAgent == null) {
13
+ userAgent = typeof navigator !== 'undefined' ? navigator.userAgent : null;
14
+ }
15
+ // Assume it works because basically everything supports progress events.
16
+ if (!userAgent) return true;
17
+ var m = /Edge\/(\d+\.\d+)/.exec(userAgent);
18
+ if (!m) return true;
19
+ var edgeVersion = m[1];
20
+ var _edgeVersion$split = edgeVersion.split('.'),
21
+ _edgeVersion$split2 = _slicedToArray(_edgeVersion$split, 2),
22
+ major = _edgeVersion$split2[0],
23
+ minor = _edgeVersion$split2[1];
24
+ major = parseInt(major, 10);
25
+ minor = parseInt(minor, 10);
26
+
27
+ // Worked before:
28
+ // Edge 40.15063.0.0
29
+ // Microsoft EdgeHTML 15.15063
30
+ if (major < 15 || major === 15 && minor < 15063) {
31
+ return true;
32
+ }
33
+
34
+ // Fixed in:
35
+ // Microsoft EdgeHTML 18.18218
36
+ if (major > 18 || major === 18 && minor >= 18218) {
37
+ return true;
38
+ }
39
+
40
+ // other versions don't work.
41
+ return false;
42
+ }
@@ -0,0 +1,21 @@
1
+ import getBytesRemaining from '@scaleflex/widget-utils/lib/getBytesRemaining';
2
+ import getSpeed from '@scaleflex/widget-utils/lib/getSpeed';
3
+ var getTotalSpeed = function getTotalSpeed(files) {
4
+ return files.reduce(function (total, file) {
5
+ return total + getSpeed(file.progress);
6
+ }, 0);
7
+ };
8
+
9
+ // Eta (ETA) = Estimated Time of Arrival to finish operations in seconds
10
+ var calculateTotalEta = function calculateTotalEta(files) {
11
+ var totalSpeed = getTotalSpeed(files);
12
+ if (totalSpeed === 0) {
13
+ return 0;
14
+ }
15
+ var totalBytesRemaining = getBytesRemaining(files);
16
+ if (totalBytesRemaining && totalSpeed) {
17
+ // ETA = remainingDistance/Speed
18
+ return Math.round(totalBytesRemaining / totalSpeed * 10) / 10;
19
+ }
20
+ };
21
+ export default calculateTotalEta;
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@scaleflex/widget-core",
3
+ "description": "Core module for the extensible JavaScript file upload widget with support for drag&drop, resumable uploads, previews, restrictions, file processing/encoding, remote providers like Instagram, Dropbox, Google Drive, Box, One Drive, S3 and more.",
4
+ "version": "0.0.1",
5
+ "license": "MIT",
6
+ "main": "lib/index.js",
7
+ "style": "dist/style.min.css",
8
+ "types": "types/index.d.ts",
9
+ "files": [
10
+ "/dist",
11
+ "/lib",
12
+ "/types"
13
+ ],
14
+ "publishConfig": {
15
+ "access": "public"
16
+ },
17
+ "dependencies": {
18
+ "@reduxjs/toolkit": "^1.9.5",
19
+ "@scaleflex/icons": "^3.0.0-beta.11",
20
+ "@scaleflex/ui": "^3.0.0-beta.11",
21
+ "@scaleflex/widget-utils": "^0.0.1",
22
+ "@transloadit/prettier-bytes": "0.1.0",
23
+ "cuid": "^3.0.0",
24
+ "lodash.throttle": "^4.1.1",
25
+ "mime-match": "^1.0.2",
26
+ "namespace-emitter": "^2.0.1",
27
+ "react-redux": "^8.1.1"
28
+ },
29
+ "devDependencies": {
30
+ "react": "^19.0.0",
31
+ "react-dom": "^19.0.0"
32
+ },
33
+ "peerDependencies": {
34
+ "react": ">=19.0.0",
35
+ "react-dom": ">=19.0.0"
36
+ },
37
+ "gitHead": "64ea82e745b7deda36d6794863350e6671e9010d"
38
+ }
@@ -0,0 +1,301 @@
1
+ const FilerobotUtils = require("@scaleflex/widget-utils");
2
+
3
+ declare module Filerobot {
4
+ // Utility types
5
+ type OmitKey<T, Key> = Pick<T, Exclude<keyof T, Key>>;
6
+
7
+ // These are defined in @scaleflex/widget-utils instead of core so it can be used there without creating import cycles
8
+ export type FilerobotFile<
9
+ TMeta extends IndexedObject<any> = {},
10
+ TBody extends IndexedObject<any> = {}
11
+ > = FilerobotUtils.FilerobotFile<TMeta, TBody>;
12
+ export type Store = FilerobotUtils.Store;
13
+ export type InternalMetadata = FilerobotUtils.InternalMetadata;
14
+
15
+ interface IndexedObject<T> {
16
+ [key: string]: T;
17
+ [key: number]: T;
18
+ }
19
+
20
+ interface UploadedFilerobotFile<TMeta, TBody>
21
+ extends FilerobotFile<TMeta, TBody> {
22
+ uploadURL: string;
23
+ }
24
+
25
+ interface FailedFilerobotFile<TMeta, TBody>
26
+ extends FilerobotFile<TMeta, TBody> {
27
+ error: string;
28
+ }
29
+
30
+ // Replace the `meta` property type with one that allows omitting internal metadata; addFile() will add that
31
+ type FilerobotFileWithoutMeta<TMeta, TBody> = OmitKey<
32
+ FilerobotFile<TMeta, TBody>,
33
+ "meta"
34
+ >;
35
+ interface AddFileOptions<
36
+ TMeta = IndexedObject<any>,
37
+ TBody = IndexedObject<any>
38
+ > extends Partial<FilerobotFileWithoutMeta<TMeta, TBody>> {
39
+ // `.data` is the only required property here.
40
+ data: Blob | File;
41
+ meta?: Partial<InternalMetadata> & TMeta;
42
+ }
43
+
44
+ interface PluginOptions {
45
+ id?: string;
46
+ }
47
+ interface DefaultPluginOptions extends PluginOptions {
48
+ [prop: string]: any;
49
+ }
50
+
51
+ type PluginTarget = string | Element | typeof Plugin;
52
+
53
+ class Plugin<TOptions extends PluginOptions = DefaultPluginOptions> {
54
+ id: string;
55
+ filerobot: Filerobot;
56
+ type: string;
57
+ constructor(filerobot: Filerobot, opts?: TOptions);
58
+ setOptions(update: Partial<TOptions>): void;
59
+ getPluginState(): object;
60
+ setPluginState(update: IndexedObject<any>): object;
61
+ update(state?: object): void;
62
+ mount(target: PluginTarget, plugin: typeof Plugin): void;
63
+ render(state: object): void;
64
+ addTarget<TPlugin extends Plugin>(plugin: TPlugin): void;
65
+ unmount(): void;
66
+ install(): void;
67
+ uninstall(): void;
68
+ }
69
+
70
+ type LocaleStrings<TNames extends string> = {
71
+ [K in TNames]?: string | { [n: number]: string };
72
+ };
73
+ interface Locale<TNames extends string = string> {
74
+ strings: LocaleStrings<TNames>;
75
+ pluralize?: (n: number) => number;
76
+ }
77
+
78
+ interface Restrictions {
79
+ maxFileSize?: number | null;
80
+ maxNumberOfFiles?: number | null;
81
+ minNumberOfFiles?: number | null;
82
+ allowedFileTypes?: string[] | null;
83
+ maxItemsSizeForCompression: number | null;
84
+ }
85
+
86
+ interface FilerobotOptions<TMeta extends IndexedObject<any> = {}> {
87
+ container: string;
88
+ securityTemplateId?: string;
89
+ sassKey?: string;
90
+ dev?: boolean;
91
+ userInfo?: {
92
+ email: string;
93
+ name: string;
94
+ photo_uri: string;
95
+ uuid: string;
96
+ };
97
+ autoProceed?: boolean;
98
+ allowMultipleUploads?: boolean;
99
+ debug?: boolean;
100
+ restrictions?: Restrictions;
101
+ meta?: TMeta;
102
+ onBeforeFileAdded?: (
103
+ currentFile: FilerobotFile<TMeta>,
104
+ files: { [key: string]: FilerobotFile<TMeta> }
105
+ ) => FilerobotFile<TMeta> | boolean | undefined;
106
+ onBeforeUpload?: (files: {
107
+ [key: string]: FilerobotFile<TMeta>;
108
+ }) => { [key: string]: FilerobotFile<TMeta> } | boolean;
109
+ locale?: Locale;
110
+ store?: Store;
111
+ userPermissions?: string[];
112
+ userFoldersScope?: string[];
113
+ apiEndpoint?: string;
114
+ skipApiEndpointToken?: boolean;
115
+ adminApiEndpoint?: string;
116
+ shareApiEndpoint?: string;
117
+ }
118
+
119
+ interface UploadResult<
120
+ TMeta extends IndexedObject<any> = {},
121
+ TBody extends IndexedObject<any> = {}
122
+ > {
123
+ successful: UploadedFilerobotFile<TMeta, TBody>[];
124
+ failed: FailedFilerobotFile<TMeta, TBody>[];
125
+ }
126
+
127
+ interface State<
128
+ TMeta extends IndexedObject<any> = {},
129
+ TBody extends IndexedObject<any> = {}
130
+ > extends IndexedObject<any> {
131
+ capabilities?: { resumableUploads?: boolean };
132
+ currentUploads: {};
133
+ error?: string;
134
+ files: {
135
+ [key: string]:
136
+ | UploadedFilerobotFile<TMeta, TBody>
137
+ | FailedFilerobotFile<TMeta, TBody>;
138
+ };
139
+ info?: {
140
+ isHidden: boolean;
141
+ type: string;
142
+ message: string;
143
+ details: string;
144
+ };
145
+ plugins?: IndexedObject<any>;
146
+ totalProgress: number;
147
+ }
148
+
149
+ type LogLevel = "info" | "warning" | "error";
150
+
151
+ /** Enable the old, untyped `filerobot.use()` signature. */
152
+ type LooseTypes = "loose";
153
+ /** Disable the old, untyped `filerobot.use()` signature. */
154
+ type StrictTypes = "strict";
155
+ type TypeChecking = LooseTypes | StrictTypes;
156
+
157
+ // This hack accepts _any_ string for `Event`, but also tricks VSCode and friends into providing autocompletions
158
+ // for the names listed. https://github.com/microsoft/TypeScript/issues/29729#issuecomment-505826972
159
+ type LiteralUnion<T extends U, U = string> = T | (U & {});
160
+ type Event = LiteralUnion<
161
+ | "file-added"
162
+ | "file-removed"
163
+ | "upload"
164
+ | "upload-progress"
165
+ | "upload-success"
166
+ | "complete"
167
+ | "error"
168
+ | "upload-error"
169
+ | "upload-retry"
170
+ | "info-visible"
171
+ | "info-hidden"
172
+ | "cancel-uploads"
173
+ | "restriction-failed"
174
+ | "reset-progress"
175
+ >;
176
+
177
+ type UploadHandler = (fileIDs: string[]) => Promise<void>;
178
+
179
+ class Filerobot<TUseStrictTypes extends TypeChecking = TypeChecking> {
180
+ constructor(opts?: FilerobotOptions);
181
+ on<TMeta extends IndexedObject<any> = {}>(
182
+ event: "upload-success",
183
+ callback: (
184
+ file: FilerobotFile<TMeta>,
185
+ body: any,
186
+ uploadURL: string
187
+ ) => void
188
+ ): this;
189
+ on<TMeta extends IndexedObject<any> = {}>(
190
+ event: "complete",
191
+ callback: (result: UploadResult<TMeta>) => void
192
+ ): this;
193
+ on(event: Event, callback: (...args: any[]) => void): this;
194
+ off(event: Event, callback: (...args: any[]) => void): this;
195
+ /**
196
+ * For use by plugins only.
197
+ */
198
+ emit(event: Event, ...args: any[]): void;
199
+ updateAll(state: object): void;
200
+ setOptions(update: Partial<FilerobotOptions>): void;
201
+ setState(patch: object): void;
202
+ getState<TMeta extends IndexedObject<any> = {}>(): State<TMeta>;
203
+ readonly state: State;
204
+ addPreProcessor(fn: UploadHandler): void;
205
+ removePreProcessor(fn: UploadHandler): void;
206
+ addPostProcessor(fn: UploadHandler): void;
207
+ removePostProcessor(fn: UploadHandler): void;
208
+ addFilerobot(fn: UploadHandler): void;
209
+ removeFilerobot(fn: UploadHandler): void;
210
+ setMeta<TMeta extends IndexedObject<any> = {}>(data: TMeta): void;
211
+ setFileMeta<TMeta extends IndexedObject<any> = {}>(
212
+ fileID: string,
213
+ data: TMeta
214
+ ): void;
215
+ getFile<
216
+ TMeta extends IndexedObject<any> = {},
217
+ TBody extends IndexedObject<any> = {}
218
+ >(fileID: string): FilerobotFile<TMeta, TBody>;
219
+ getFiles<
220
+ TMeta extends IndexedObject<any> = {},
221
+ TBody extends IndexedObject<any> = {}
222
+ >(): Array<FilerobotFile<TMeta, TBody>>;
223
+ addFile<TMeta extends IndexedObject<any> = {}>(
224
+ file: AddFileOptions<TMeta>
225
+ ): void;
226
+ removeFile(fileID: string): void;
227
+ pauseResume(fileID: string): void;
228
+ cancelUploads(): void;
229
+ retryUpload<TMeta extends IndexedObject<any> = {}>(
230
+ fileID: string
231
+ ): Promise<UploadResult<TMeta>>;
232
+ pauseAll(): void;
233
+ resumeAll(): void;
234
+ retryAll<TMeta extends IndexedObject<any> = {}>(): Promise<
235
+ UploadResult<TMeta>
236
+ >;
237
+ cancelAll(): void;
238
+ getId(): string;
239
+ /**
240
+ * Add a plugin to this Filerobot instance.
241
+ */
242
+ use<TOptions, TInstance extends Plugin<TOptions>>(
243
+ pluginClass: new (filerobot: this, opts: TOptions) => TInstance,
244
+ opts?: TOptions
245
+ ): this;
246
+ /**
247
+ * Fallback `.use()` overload with unchecked plugin options.
248
+ *
249
+ * This does not validate that the options you pass in are correct.
250
+ * We recommend disabling this overload by using the `Filerobot<Filerobot.StrictTypes>` type, instead of the plain `Filerobot` type, to enforce strict typechecking.
251
+ * This overload will be removed in Filerobot 2.0.
252
+ */
253
+ use(
254
+ pluginClass: TUseStrictTypes extends StrictTypes
255
+ ? never
256
+ : new (filerobot: this, opts: any) => Plugin<any>,
257
+ opts?: object
258
+ ): this;
259
+ getPlugin(name: string): Plugin;
260
+ iteratePlugins(callback: (plugin: Plugin) => void): void;
261
+ removePlugin(instance: Plugin): void;
262
+ close(): void;
263
+ info(
264
+ message: string | { message: string; details: string },
265
+ type?: LogLevel,
266
+ duration?: number
267
+ ): void;
268
+ hideInfo(): void;
269
+ log(msg: string, type?: LogLevel): void;
270
+ /**
271
+ * Obsolete: do not use. This method does nothing and will be removed in a future release.
272
+ */
273
+ run(): this;
274
+ restore<TMeta extends IndexedObject<any> = {}>(
275
+ uploadID: string
276
+ ): Promise<UploadResult<TMeta>>;
277
+ addResultData(uploadID: string, data: object): void;
278
+ upload<TMeta extends IndexedObject<any> = {}>(): Promise<
279
+ UploadResult<TMeta>
280
+ >;
281
+ }
282
+ }
283
+
284
+ /**
285
+ * Create a filerobot instance.
286
+ *
287
+ * By default, Filerobot's `.use(Plugin, options)` method uses loose type checking.
288
+ * In Filerobot 2.0, the `.use()` method will get a stricter type signature. You can enable strict type checking of plugin classes and their options today by using:
289
+ * ```ts
290
+ * const filerobot = Filerobot<Filerobot.StrictTypes>()
291
+ * ```
292
+ * Make sure to also declare any variables and class properties with the `StrictTypes` parameter:
293
+ * ```ts
294
+ * private filerobot: Filerobot<Filerobot.StrictTypes>;
295
+ * ```
296
+ */
297
+ declare function Filerobot<
298
+ TUseStrictTypes extends Filerobot.TypeChecking = Filerobot.TypeChecking
299
+ >(opts?: Filerobot.FilerobotOptions): Filerobot.Filerobot<TUseStrictTypes>;
300
+
301
+ export = Filerobot;