@kmlckj/licos-platform-sdk 0.5.0 → 0.6.0
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/README.md +13 -21
- package/package.json +2 -2
- package/src/browser.d.ts +0 -47
- package/src/browser.js +0 -38
- package/src/index.d.ts +0 -48
- package/src/index.js +0 -52
- package/src/shared.js +2 -161
package/README.md
CHANGED
|
@@ -1,47 +1,39 @@
|
|
|
1
1
|
# @kmlckj/licos-platform-sdk
|
|
2
2
|
|
|
3
|
-
LICOS
|
|
3
|
+
LICOS 平台对象存储预览 / 下载 SDK,兼容前端和后端调用。
|
|
4
4
|
|
|
5
5
|
## 后端模式
|
|
6
6
|
|
|
7
|
-
- `baseUrl` / `token`
|
|
7
|
+
- `baseUrl` / `token` 不传时,会回退读取 `LICOS_*` 环境变量
|
|
8
8
|
- 后端默认读取 `LICOS_ORCHESTRATOR_API_BASE_URL`
|
|
9
|
-
- 这些存储接口实际挂在调度器 `/api/v1/
|
|
10
|
-
- `uploadUser` / `uploadProject` 支持直接传本地文件路径
|
|
9
|
+
- 这些存储接口实际挂在调度器 `/api/v1/public/storage/*`
|
|
11
10
|
- `download(url, outputPath)` 会把文件写到本地路径
|
|
12
|
-
-
|
|
11
|
+
- 预览 / 下载都要求鉴权;`download(...)` 会自动带上 `token` 或 `LICOS_RUNTIME_TOKEN`
|
|
13
12
|
|
|
14
13
|
```js
|
|
15
|
-
import {
|
|
14
|
+
import { download, downloadUrl } from '@kmlckj/licos-platform-sdk';
|
|
16
15
|
|
|
17
|
-
const
|
|
18
|
-
await download(
|
|
16
|
+
const url = downloadUrl('demo-bucket', 'folder/report.pdf');
|
|
17
|
+
await download(url, '/tmp/report-downloaded.pdf');
|
|
19
18
|
```
|
|
20
19
|
|
|
21
20
|
## 前端模式
|
|
22
21
|
|
|
23
22
|
- 默认走同源相对地址;也可以显式传 `baseUrl`
|
|
24
|
-
- 上传支持 `File` / `Blob` / `ArrayBuffer` / TypedArray / `{ data, fileName, contentType }`
|
|
25
23
|
- `download(url)` 返回 `Blob`
|
|
26
24
|
- TypeScript 前端可显式导入浏览器入口 `@kmlckj/licos-platform-sdk/browser`,拿到浏览器专用类型
|
|
27
25
|
- 预览 / 下载接口同样要求传 `token`
|
|
28
26
|
|
|
29
27
|
```js
|
|
30
|
-
import {
|
|
28
|
+
import { download, previewUrl } from '@kmlckj/licos-platform-sdk';
|
|
31
29
|
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
const blob = await download(uploaded.download_url, { token: userJwt });
|
|
30
|
+
const url = previewUrl('demo-bucket', 'images/demo.png');
|
|
31
|
+
const blob = await download(url, { token: runtimeToken });
|
|
37
32
|
```
|
|
38
33
|
|
|
39
34
|
```ts
|
|
40
|
-
import {
|
|
41
|
-
|
|
42
|
-
const uploaded = await uploadUser(fileInput.files![0], {
|
|
43
|
-
token: userJwt,
|
|
44
|
-
});
|
|
35
|
+
import { download, previewUrl } from '@kmlckj/licos-platform-sdk/browser';
|
|
45
36
|
|
|
46
|
-
const
|
|
37
|
+
const url = previewUrl('demo-bucket', 'images/demo.png');
|
|
38
|
+
const blob = await download(url, { token: runtimeToken });
|
|
47
39
|
```
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kmlckj/licos-platform-sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "LICOS platform SDK for storage
|
|
3
|
+
"version": "0.6.0",
|
|
4
|
+
"description": "LICOS platform SDK for storage download and preview in browser and Node runtimes",
|
|
5
5
|
"author": "kmlckj",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./src/index.js",
|
package/src/browser.d.ts
CHANGED
|
@@ -1,48 +1,11 @@
|
|
|
1
|
-
export interface UploadResult {
|
|
2
|
-
bucket: string;
|
|
3
|
-
object_key: string;
|
|
4
|
-
file_name: string;
|
|
5
|
-
content_type: string;
|
|
6
|
-
size_bytes: number;
|
|
7
|
-
preview_url: string;
|
|
8
|
-
download_url: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface BlobLike {
|
|
12
|
-
arrayBuffer(): Promise<ArrayBuffer>;
|
|
13
|
-
readonly size?: number;
|
|
14
|
-
readonly type?: string;
|
|
15
|
-
readonly name?: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface UploadBinaryDescriptor {
|
|
19
|
-
data?: ArrayBuffer | ArrayBufferView | BlobLike;
|
|
20
|
-
file?: ArrayBuffer | ArrayBufferView | BlobLike;
|
|
21
|
-
fileName?: string;
|
|
22
|
-
contentType?: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export type UploadSource =
|
|
26
|
-
| ArrayBuffer
|
|
27
|
-
| ArrayBufferView
|
|
28
|
-
| BlobLike
|
|
29
|
-
| UploadBinaryDescriptor;
|
|
30
|
-
|
|
31
1
|
export interface StorageClientOptions {
|
|
32
2
|
baseUrl?: string;
|
|
33
3
|
token?: string;
|
|
34
|
-
userId?: string;
|
|
35
|
-
projectId?: string;
|
|
36
4
|
fetch?: typeof fetch;
|
|
37
5
|
headers?: HeadersInit;
|
|
38
6
|
credentials?: RequestCredentials;
|
|
39
7
|
}
|
|
40
8
|
|
|
41
|
-
export interface UploadProjectOptions extends StorageClientOptions {
|
|
42
|
-
userId?: string;
|
|
43
|
-
projectId?: string;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
9
|
export class PlatformSdkError extends Error {
|
|
47
10
|
status?: number;
|
|
48
11
|
code?: number;
|
|
@@ -56,8 +19,6 @@ export class StorageClient {
|
|
|
56
19
|
constructor(options?: StorageClientOptions);
|
|
57
20
|
previewUrl(bucket: string, objectKey: string): string;
|
|
58
21
|
downloadUrl(bucket: string, objectKey: string): string;
|
|
59
|
-
uploadUser(file: UploadSource): Promise<UploadResult>;
|
|
60
|
-
uploadProject(file: UploadSource, options?: UploadProjectOptions): Promise<UploadResult>;
|
|
61
22
|
download(url: string): Promise<Blob>;
|
|
62
23
|
}
|
|
63
24
|
|
|
@@ -71,12 +32,4 @@ export function downloadUrl(
|
|
|
71
32
|
objectKey: string,
|
|
72
33
|
options?: StorageClientOptions,
|
|
73
34
|
): string;
|
|
74
|
-
export function uploadUser(
|
|
75
|
-
file: UploadSource,
|
|
76
|
-
options?: StorageClientOptions,
|
|
77
|
-
): Promise<UploadResult>;
|
|
78
|
-
export function uploadProject(
|
|
79
|
-
file: UploadSource,
|
|
80
|
-
options?: UploadProjectOptions,
|
|
81
|
-
): Promise<UploadResult>;
|
|
82
35
|
export function download(url: string, options?: StorageClientOptions): Promise<Blob>;
|
package/src/browser.js
CHANGED
|
@@ -6,17 +6,12 @@ import {
|
|
|
6
6
|
encodeObjectKey,
|
|
7
7
|
encodeStorageSegment,
|
|
8
8
|
normalizeBaseUrl,
|
|
9
|
-
resolveProjectId,
|
|
10
|
-
resolveUserId,
|
|
11
|
-
uploadFile,
|
|
12
9
|
} from './shared.js';
|
|
13
10
|
|
|
14
11
|
export class StorageClient {
|
|
15
12
|
constructor(options = {}) {
|
|
16
13
|
this.baseUrl = options.baseUrl;
|
|
17
14
|
this.token = options.token;
|
|
18
|
-
this.userId = options.userId;
|
|
19
|
-
this.projectId = options.projectId;
|
|
20
15
|
this.fetchImpl = options.fetch ?? fetch;
|
|
21
16
|
this.headers = options.headers;
|
|
22
17
|
this.credentials = options.credentials;
|
|
@@ -31,31 +26,6 @@ export class StorageClient {
|
|
|
31
26
|
return `${this.previewUrl(bucket, objectKey)}?download=1`;
|
|
32
27
|
}
|
|
33
28
|
|
|
34
|
-
async uploadUser(file) {
|
|
35
|
-
const baseUrl = normalizeBaseUrl(this.baseUrl);
|
|
36
|
-
return uploadFile(this.fetchImpl, `${baseUrl}/api/v1/storage/upload/user`, file, {
|
|
37
|
-
token: this.token,
|
|
38
|
-
headers: this.headers,
|
|
39
|
-
credentials: this.credentials,
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async uploadProject(file, options = {}) {
|
|
44
|
-
const baseUrl = normalizeBaseUrl(this.baseUrl);
|
|
45
|
-
const userId = resolveUserId(options.userId ?? this.userId);
|
|
46
|
-
const projectId = resolveProjectId(options.projectId ?? this.projectId);
|
|
47
|
-
return uploadFile(
|
|
48
|
-
this.fetchImpl,
|
|
49
|
-
`${baseUrl}/api/v1/storage/upload/project/${encodeStorageSegment(userId)}/${encodeStorageSegment(projectId)}`,
|
|
50
|
-
file,
|
|
51
|
-
{
|
|
52
|
-
token: this.token,
|
|
53
|
-
headers: this.headers,
|
|
54
|
-
credentials: this.credentials,
|
|
55
|
-
},
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
29
|
async download(url, outputPath) {
|
|
60
30
|
if (outputPath !== undefined) {
|
|
61
31
|
throw new ConfigurationError(
|
|
@@ -82,14 +52,6 @@ export function downloadUrl(bucket, objectKey, options = {}) {
|
|
|
82
52
|
return defaultClient(options).downloadUrl(bucket, objectKey);
|
|
83
53
|
}
|
|
84
54
|
|
|
85
|
-
export async function uploadUser(file, options = {}) {
|
|
86
|
-
return defaultClient(options).uploadUser(file);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export async function uploadProject(file, options = {}) {
|
|
90
|
-
return defaultClient(options).uploadProject(file, options);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
55
|
export async function download(url, outputPathOrOptions, maybeOptions = {}) {
|
|
94
56
|
if (typeof outputPathOrOptions === 'string') {
|
|
95
57
|
throw new ConfigurationError(
|
package/src/index.d.ts
CHANGED
|
@@ -1,49 +1,11 @@
|
|
|
1
|
-
export interface UploadResult {
|
|
2
|
-
bucket: string;
|
|
3
|
-
object_key: string;
|
|
4
|
-
file_name: string;
|
|
5
|
-
content_type: string;
|
|
6
|
-
size_bytes: number;
|
|
7
|
-
preview_url: string;
|
|
8
|
-
download_url: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface BlobLike {
|
|
12
|
-
arrayBuffer(): Promise<ArrayBuffer>;
|
|
13
|
-
readonly size?: number;
|
|
14
|
-
readonly type?: string;
|
|
15
|
-
readonly name?: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface UploadBinaryDescriptor {
|
|
19
|
-
data?: ArrayBuffer | ArrayBufferView | BlobLike;
|
|
20
|
-
file?: ArrayBuffer | ArrayBufferView | BlobLike;
|
|
21
|
-
fileName?: string;
|
|
22
|
-
contentType?: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export type UploadSource =
|
|
26
|
-
| string
|
|
27
|
-
| ArrayBuffer
|
|
28
|
-
| ArrayBufferView
|
|
29
|
-
| BlobLike
|
|
30
|
-
| UploadBinaryDescriptor;
|
|
31
|
-
|
|
32
1
|
export interface StorageClientOptions {
|
|
33
2
|
baseUrl?: string;
|
|
34
3
|
token?: string;
|
|
35
|
-
userId?: string;
|
|
36
|
-
projectId?: string;
|
|
37
4
|
fetch?: typeof fetch;
|
|
38
5
|
headers?: HeadersInit;
|
|
39
6
|
credentials?: RequestCredentials;
|
|
40
7
|
}
|
|
41
8
|
|
|
42
|
-
export interface UploadProjectOptions extends StorageClientOptions {
|
|
43
|
-
userId?: string;
|
|
44
|
-
projectId?: string;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
9
|
export class PlatformSdkError extends Error {
|
|
48
10
|
status?: number;
|
|
49
11
|
code?: number;
|
|
@@ -57,8 +19,6 @@ export class StorageClient {
|
|
|
57
19
|
constructor(options?: StorageClientOptions);
|
|
58
20
|
previewUrl(bucket: string, objectKey: string): string;
|
|
59
21
|
downloadUrl(bucket: string, objectKey: string): string;
|
|
60
|
-
uploadUser(file: UploadSource): Promise<UploadResult>;
|
|
61
|
-
uploadProject(file: UploadSource, options?: UploadProjectOptions): Promise<UploadResult>;
|
|
62
22
|
download(url: string): Promise<Blob>;
|
|
63
23
|
download(url: string, outputPath: string): Promise<string>;
|
|
64
24
|
}
|
|
@@ -73,14 +33,6 @@ export function downloadUrl(
|
|
|
73
33
|
objectKey: string,
|
|
74
34
|
options?: StorageClientOptions,
|
|
75
35
|
): string;
|
|
76
|
-
export function uploadUser(
|
|
77
|
-
file: UploadSource,
|
|
78
|
-
options?: StorageClientOptions,
|
|
79
|
-
): Promise<UploadResult>;
|
|
80
|
-
export function uploadProject(
|
|
81
|
-
file: UploadSource,
|
|
82
|
-
options?: UploadProjectOptions,
|
|
83
|
-
): Promise<UploadResult>;
|
|
84
36
|
export function download(url: string, options?: StorageClientOptions): Promise<Blob>;
|
|
85
37
|
export function download(
|
|
86
38
|
url: string,
|
package/src/index.js
CHANGED
|
@@ -8,20 +8,13 @@ import {
|
|
|
8
8
|
downloadBlob,
|
|
9
9
|
encodeObjectKey,
|
|
10
10
|
encodeStorageSegment,
|
|
11
|
-
fileNameFromPath,
|
|
12
|
-
guessContentType,
|
|
13
11
|
normalizeBaseUrl,
|
|
14
|
-
resolveProjectId,
|
|
15
|
-
resolveUserId,
|
|
16
|
-
uploadFile,
|
|
17
12
|
} from './shared.js';
|
|
18
13
|
|
|
19
14
|
export class StorageClient {
|
|
20
15
|
constructor(options = {}) {
|
|
21
16
|
this.baseUrl = options.baseUrl;
|
|
22
17
|
this.token = options.token;
|
|
23
|
-
this.userId = options.userId;
|
|
24
|
-
this.projectId = options.projectId;
|
|
25
18
|
this.fetchImpl = options.fetch ?? fetch;
|
|
26
19
|
this.headers = options.headers;
|
|
27
20
|
this.credentials = options.credentials;
|
|
@@ -36,21 +29,6 @@ export class StorageClient {
|
|
|
36
29
|
return `${this.previewUrl(bucket, objectKey)}?download=1`;
|
|
37
30
|
}
|
|
38
31
|
|
|
39
|
-
async uploadUser(file) {
|
|
40
|
-
const baseUrl = normalizeBaseUrl(this.baseUrl);
|
|
41
|
-
return this.#upload(`${baseUrl}/api/v1/storage/upload/user`, file);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
async uploadProject(file, options = {}) {
|
|
45
|
-
const baseUrl = normalizeBaseUrl(this.baseUrl);
|
|
46
|
-
const userId = resolveUserId(options.userId ?? this.userId);
|
|
47
|
-
const projectId = resolveProjectId(options.projectId ?? this.projectId);
|
|
48
|
-
return this.#upload(
|
|
49
|
-
`${baseUrl}/api/v1/storage/upload/project/${encodeStorageSegment(userId)}/${encodeStorageSegment(projectId)}`,
|
|
50
|
-
file,
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
32
|
async download(url, outputPath) {
|
|
55
33
|
const blob = await downloadBlob(this.fetchImpl, url, {
|
|
56
34
|
token: this.token,
|
|
@@ -66,28 +44,6 @@ export class StorageClient {
|
|
|
66
44
|
return outputPath;
|
|
67
45
|
}
|
|
68
46
|
|
|
69
|
-
async #upload(url, file) {
|
|
70
|
-
return uploadFile(
|
|
71
|
-
this.fetchImpl,
|
|
72
|
-
url,
|
|
73
|
-
file,
|
|
74
|
-
{
|
|
75
|
-
token: this.token,
|
|
76
|
-
headers: this.headers,
|
|
77
|
-
credentials: this.credentials,
|
|
78
|
-
},
|
|
79
|
-
async (filePath) => {
|
|
80
|
-
const fileBuffer = await fs.readFile(filePath);
|
|
81
|
-
const fileName = fileNameFromPath(filePath);
|
|
82
|
-
const contentType = guessContentType(fileName);
|
|
83
|
-
return {
|
|
84
|
-
fileName,
|
|
85
|
-
contentType,
|
|
86
|
-
blob: new Blob([fileBuffer], { type: contentType }),
|
|
87
|
-
};
|
|
88
|
-
},
|
|
89
|
-
);
|
|
90
|
-
}
|
|
91
47
|
}
|
|
92
48
|
|
|
93
49
|
function defaultClient(options = {}) {
|
|
@@ -102,14 +58,6 @@ export function downloadUrl(bucket, objectKey, options = {}) {
|
|
|
102
58
|
return defaultClient(options).downloadUrl(bucket, objectKey);
|
|
103
59
|
}
|
|
104
60
|
|
|
105
|
-
export async function uploadUser(filePath, options = {}) {
|
|
106
|
-
return defaultClient(options).uploadUser(filePath);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export async function uploadProject(filePath, options = {}) {
|
|
110
|
-
return defaultClient(options).uploadProject(filePath, options);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
61
|
export async function download(url, outputPathOrOptions, maybeOptions = {}) {
|
|
114
62
|
if (typeof outputPathOrOptions === 'string') {
|
|
115
63
|
return defaultClient(maybeOptions).download(url, outputPathOrOptions);
|
package/src/shared.js
CHANGED
|
@@ -23,14 +23,6 @@ function readEnv(name) {
|
|
|
23
23
|
return value ? value : undefined;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
export function requireEnv(name) {
|
|
27
|
-
const value = readEnv(name);
|
|
28
|
-
if (value) {
|
|
29
|
-
return value;
|
|
30
|
-
}
|
|
31
|
-
throw new ConfigurationError(`Missing required environment variable: ${name}`);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
26
|
export function normalizeBaseUrl(baseUrl) {
|
|
35
27
|
if (typeof baseUrl === 'string') {
|
|
36
28
|
return baseUrl.replace(/\/+$/, '');
|
|
@@ -50,14 +42,6 @@ export function normalizeBaseUrl(baseUrl) {
|
|
|
50
42
|
);
|
|
51
43
|
}
|
|
52
44
|
|
|
53
|
-
export function resolveUserId(userId) {
|
|
54
|
-
return userId ?? requireEnv('LICOS_USER_ID');
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export function resolveProjectId(projectId) {
|
|
58
|
-
return projectId ?? requireEnv('LICOS_PROJECT_ID');
|
|
59
|
-
}
|
|
60
|
-
|
|
61
45
|
export function encodeStorageSegment(value) {
|
|
62
46
|
return encodeURIComponent(value);
|
|
63
47
|
}
|
|
@@ -66,112 +50,6 @@ export function encodeObjectKey(value) {
|
|
|
66
50
|
return value.split('/').map(encodeStorageSegment).join('/');
|
|
67
51
|
}
|
|
68
52
|
|
|
69
|
-
export function fileNameFromPath(filePath) {
|
|
70
|
-
const parts = String(filePath).split(/[\\/]/);
|
|
71
|
-
const fileName = parts[parts.length - 1];
|
|
72
|
-
return fileName || 'upload.bin';
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function guessContentType(fileName) {
|
|
76
|
-
const ext = /\.[^./\\]+$/.exec(String(fileName).toLowerCase())?.[0] ?? '';
|
|
77
|
-
switch (ext) {
|
|
78
|
-
case '.txt':
|
|
79
|
-
return 'text/plain';
|
|
80
|
-
case '.json':
|
|
81
|
-
return 'application/json';
|
|
82
|
-
case '.pdf':
|
|
83
|
-
return 'application/pdf';
|
|
84
|
-
case '.png':
|
|
85
|
-
return 'image/png';
|
|
86
|
-
case '.jpg':
|
|
87
|
-
case '.jpeg':
|
|
88
|
-
return 'image/jpeg';
|
|
89
|
-
case '.gif':
|
|
90
|
-
return 'image/gif';
|
|
91
|
-
case '.webp':
|
|
92
|
-
return 'image/webp';
|
|
93
|
-
case '.svg':
|
|
94
|
-
return 'image/svg+xml';
|
|
95
|
-
case '.md':
|
|
96
|
-
return 'text/markdown';
|
|
97
|
-
default:
|
|
98
|
-
return 'application/octet-stream';
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function isBlobLike(value) {
|
|
103
|
-
return !!value && typeof value === 'object' && typeof value.arrayBuffer === 'function';
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function isBinaryDescriptor(value) {
|
|
107
|
-
if (!value || typeof value !== 'object' || isBlobLike(value)) {
|
|
108
|
-
return false;
|
|
109
|
-
}
|
|
110
|
-
return 'data' in value || 'file' in value;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function toUint8Array(data) {
|
|
114
|
-
if (data instanceof Uint8Array) {
|
|
115
|
-
return data;
|
|
116
|
-
}
|
|
117
|
-
if (ArrayBuffer.isView(data)) {
|
|
118
|
-
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
119
|
-
}
|
|
120
|
-
return new Uint8Array(data);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
async function normalizeBinaryPayload(data, overrides = {}) {
|
|
124
|
-
if (isBlobLike(data)) {
|
|
125
|
-
const fileName =
|
|
126
|
-
overrides.fileName ??
|
|
127
|
-
(typeof data.name === 'string' && data.name ? data.name : undefined) ??
|
|
128
|
-
'upload.bin';
|
|
129
|
-
const contentType =
|
|
130
|
-
overrides.contentType ??
|
|
131
|
-
(typeof data.type === 'string' && data.type ? data.type : undefined) ??
|
|
132
|
-
guessContentType(fileName);
|
|
133
|
-
return {
|
|
134
|
-
fileName,
|
|
135
|
-
contentType,
|
|
136
|
-
blob: new Blob([await data.arrayBuffer()], { type: contentType }),
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) {
|
|
141
|
-
const fileName = overrides.fileName ?? 'upload.bin';
|
|
142
|
-
const contentType = overrides.contentType ?? guessContentType(fileName);
|
|
143
|
-
return {
|
|
144
|
-
fileName,
|
|
145
|
-
contentType,
|
|
146
|
-
blob: new Blob([toUint8Array(data)], { type: contentType }),
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
throw new ConfigurationError(
|
|
151
|
-
'Unsupported upload input. Use a file path string, Blob/File, ArrayBuffer, TypedArray, or { data, fileName }.',
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
export async function normalizeUploadSource(source, readPathSource) {
|
|
156
|
-
if (typeof source === 'string') {
|
|
157
|
-
if (!readPathSource) {
|
|
158
|
-
throw new ConfigurationError(
|
|
159
|
-
'Front-end mode does not support filesystem path uploads. Pass File, Blob, ArrayBuffer, TypedArray, or { data, fileName } instead.',
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
|
-
return readPathSource(source);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
if (isBinaryDescriptor(source)) {
|
|
166
|
-
return normalizeBinaryPayload(source.data ?? source.file, {
|
|
167
|
-
fileName: source.fileName,
|
|
168
|
-
contentType: source.contentType,
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return normalizeBinaryPayload(source);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
53
|
function headersFromInit(headersInit) {
|
|
176
54
|
return new Headers(headersInit ?? undefined);
|
|
177
55
|
}
|
|
@@ -179,12 +57,12 @@ function headersFromInit(headersInit) {
|
|
|
179
57
|
export function buildRequestHeaders(options = {}, { authenticated = false } = {}) {
|
|
180
58
|
const headers = headersFromInit(options.headers);
|
|
181
59
|
if (authenticated && !headers.has('Authorization')) {
|
|
182
|
-
const resolvedToken = options.token ?? readEnv('
|
|
60
|
+
const resolvedToken = options.token ?? readEnv('LICOS_RUNTIME_TOKEN');
|
|
183
61
|
if (resolvedToken) {
|
|
184
62
|
headers.set('Authorization', `Bearer ${resolvedToken}`);
|
|
185
63
|
} else if (isNodeRuntime()) {
|
|
186
64
|
throw new ConfigurationError(
|
|
187
|
-
'Missing authentication token. Pass options.token, provide an Authorization header, or set
|
|
65
|
+
'Missing authentication token. Pass options.token, provide an Authorization header, or set LICOS_RUNTIME_TOKEN.',
|
|
188
66
|
);
|
|
189
67
|
}
|
|
190
68
|
}
|
|
@@ -199,27 +77,6 @@ export function buildRequestInit(options = {}, init = {}) {
|
|
|
199
77
|
return requestInit;
|
|
200
78
|
}
|
|
201
79
|
|
|
202
|
-
export async function readJsonEnvelope(response) {
|
|
203
|
-
let payload;
|
|
204
|
-
try {
|
|
205
|
-
payload = await response.json();
|
|
206
|
-
} catch (error) {
|
|
207
|
-
throw new ApiError('Platform API returned non-JSON response', {
|
|
208
|
-
status: response.status,
|
|
209
|
-
details: error instanceof Error ? error.message : String(error),
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
if (!response.ok || payload?.code !== 0) {
|
|
214
|
-
throw new ApiError(payload?.message ?? `Platform API failed: HTTP ${response.status}`, {
|
|
215
|
-
status: response.status,
|
|
216
|
-
code: payload?.code,
|
|
217
|
-
details: payload?.data ?? payload,
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
return payload.data;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
80
|
export async function downloadBlob(fetchImpl, url, options = {}) {
|
|
224
81
|
const response = await fetchImpl(
|
|
225
82
|
url,
|
|
@@ -240,19 +97,3 @@ export async function downloadBlob(fetchImpl, url, options = {}) {
|
|
|
240
97
|
type: response.headers.get('content-type') ?? undefined,
|
|
241
98
|
});
|
|
242
99
|
}
|
|
243
|
-
|
|
244
|
-
export async function uploadFile(fetchImpl, url, source, options = {}, readPathSource) {
|
|
245
|
-
const normalized = await normalizeUploadSource(source, readPathSource);
|
|
246
|
-
const formData = new FormData();
|
|
247
|
-
formData.append('file', normalized.blob, normalized.fileName);
|
|
248
|
-
|
|
249
|
-
const response = await fetchImpl(
|
|
250
|
-
url,
|
|
251
|
-
buildRequestInit(options, {
|
|
252
|
-
method: 'POST',
|
|
253
|
-
headers: buildRequestHeaders(options, { authenticated: true }),
|
|
254
|
-
body: formData,
|
|
255
|
-
}),
|
|
256
|
-
);
|
|
257
|
-
return readJsonEnvelope(response);
|
|
258
|
-
}
|