@knime/utils 1.1.1 → 1.1.2

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @knime/utils
2
2
 
3
+ ## 1.1.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 15a4479: add utilities for file extensions
8
+
3
9
  ## 1.1.1
4
10
 
5
11
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knime/utils",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "Internal utility functions and constants shared across @knime packages.",
5
5
  "homepage": "https://knime.github.io/webapps-common/",
6
6
  "license": "GPL 3 and Additional Permissions according to Sec. 7 (SEE the file LICENSE)",
@@ -0,0 +1,68 @@
1
+ export const getFileExtension = (nameOrPath: string) => {
2
+ const basename = nameOrPath.split(/[\\/]/).pop();
3
+ const position = basename?.lastIndexOf(".") as number;
4
+
5
+ if (basename === "" || position < 1) {
6
+ return "";
7
+ }
8
+
9
+ return basename?.slice(position + 1);
10
+ };
11
+
12
+ /**
13
+ * Metadata for .knar files, which corresponds to exported KNIME Workflow Groups
14
+ * or Components
15
+ */
16
+ const KNAR = Object.freeze({
17
+ extension: "knar",
18
+ mimeType: "application/vnd.knime.workflow-group+zip",
19
+ matches(file: File) {
20
+ const extension = getFileExtension(file.name);
21
+ return extension === this.extension;
22
+ },
23
+ });
24
+
25
+ /**
26
+ * Metadata for .knwf files, which corresponds to exported KNIME Workflows
27
+ */
28
+ const KNWF = Object.freeze({
29
+ extension: "knwf",
30
+ mimeType: "application/vnd.knime.workflow+zip",
31
+ matches(file: File) {
32
+ const extension = getFileExtension(file.name);
33
+ return extension === this.extension;
34
+ },
35
+ });
36
+
37
+ export const knimeFileFormats = { KNAR, KNWF };
38
+
39
+ /**
40
+ * Gets the mime type from a given file. Defaults to `application/octet-stream`
41
+ * if mimeType cannot be detected
42
+ * @param file File
43
+ * @returns mimeType
44
+ */
45
+ export const getFileMimeType = (file: File): string => {
46
+ const DEFAULT_MIMETYPE = "application/octet-stream";
47
+
48
+ const extension = getFileExtension(file.name);
49
+
50
+ if (!extension) {
51
+ return DEFAULT_MIMETYPE;
52
+ }
53
+
54
+ if (KNWF.matches(file)) {
55
+ return KNWF.mimeType;
56
+ }
57
+
58
+ if (KNAR.matches(file)) {
59
+ return KNAR.mimeType;
60
+ }
61
+
62
+ // file has extension but unrecognizable mime type
63
+ if (!file.type) {
64
+ return DEFAULT_MIMETYPE;
65
+ }
66
+
67
+ return file.type;
68
+ };
package/src/index.ts CHANGED
@@ -45,6 +45,8 @@ export namespace UploadManagerNS {
45
45
  export type UploadStateName = _UploadStateName;
46
46
  }
47
47
 
48
+ export * from "./fileExtensions";
49
+
48
50
  export {
49
51
  uploadManager,
50
52
  promise,
@@ -56,12 +56,22 @@ const uploadChunkWithProgress = (params: {
56
56
  // https://datatracker.ietf.org/doc/html/rfc7232#section-2.3
57
57
  resolve({ partId: etag.replace(/^(?:W\/)?"|"$/g, "") });
58
58
  } else {
59
- reject(new Error(`Failed to upload chunk ${chunkIndex}`));
59
+ consola.error("Failed or unexpected XHR response", {
60
+ xhrStatus: xhr.status,
61
+ xhrResponse: xhr.response,
62
+ chunkIndex,
63
+ });
64
+ reject(new Error("Failed to upload file"));
60
65
  }
61
66
  };
62
67
 
63
- xhr.onerror = () =>
64
- reject(new Error(`Failed to upload chunk ${chunkIndex}`));
68
+ xhr.onerror = (event) => {
69
+ consola.error("Failed to upload chunk", {
70
+ xhrErrorEvent: event,
71
+ chunkIndex,
72
+ });
73
+ reject(new Error("Failed to upload file"));
74
+ };
65
75
 
66
76
  xhr.send(chunk);
67
77
  });