@aicloud360/dsh-cloud-disk-api-provider 0.1.1-alpha.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.
package/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # @aicloud360/dsh-cloud-disk-api-provider
2
+
3
+ English | [中文](README.zh.md)
4
+
5
+ Host-side direct 360 CloudDisk OpenAPI provider. It exchanges a Host-held user credential for an access token, signs directory and search requests with a separate Host-held application secret, and returns only normalized CloudDisk values.
6
+
7
+ ## Configuration
8
+
9
+ `DirectCloudDiskProviderOptions` requires these Host-only values:
10
+
11
+ | Field | Meaning |
12
+ |---|---|
13
+ | `credentialRef` | User API-key reference. |
14
+ | `signingSecretRef` | Application signing-secret reference. |
15
+ | `endpoint` | Audited OpenAPI endpoint. |
16
+ | `clientEnv`, `clientSource`, `subChannel` | Deployment identity sent during authentication. |
17
+ | `credentials`, `http` | Host credential and HTTP providers. |
18
+ | `timeoutMs`, `maxRetries` | Per-attempt timeout and retry limit. |
19
+
20
+ The user key, access token, qid, signing secret, request headers, and raw API responses must never reach a browser, Session, model, URL, log, or diagnostic.
21
+
22
+ ## Read operations
23
+
24
+ `getUser()` exchanges the user credential and reads the current user. `list()` maps `File.getList` pages; listed directory ids are resolved to their path only within the current credential generation. `search()` maps form-encoded `File.searchList` pages. Both cursors are opaque source-page numbers.
25
+
26
+ The provider rejects a missing user credential or signing secret before a signed request. A credential change clears the in-memory directory-path map. Caller cancellation is not retried; retryable transport failures and retryable HTTP statuses are bounded by `maxRetries`.
27
+
28
+ ## Deployment prerequisite
29
+
30
+ The signing secret needs an approved, rotatable Host-only source. Do not copy signing material from an MCP reference project or commit it to source, fixtures, Bundle YAML, or client configuration. The package includes a production fetch transport, but remains a tested Provider implementation until that secret source and Provider registration are composed into the Bundle.
31
+
32
+ ## Known Limitations and Deferred Work
33
+
34
+ - The Provider implements only user lookup, directory listing, and search. It has no upload, download, mutation, sharing, or transfer API.
35
+ - One configured Provider serves one Host process. Multi-account switching and remote change observation are not implemented.
36
+ - Signing material remains a user-managed Host credential in this release; a managed distribution or rotation service is not part of this package.
package/README.zh.md ADDED
@@ -0,0 +1,36 @@
1
+ # @aicloud360/dsh-cloud-disk-api-provider
2
+
3
+ [English](README.md) | 中文
4
+
5
+ Host 侧直连 360 云盘 OpenAPI Provider。它用 Host 保存的用户凭据交换 access token,用另一份 Host 保存的应用签名密钥签名目录和搜索请求,只返回标准化的 CloudDisk 值。
6
+
7
+ ## 配置
8
+
9
+ `DirectCloudDiskProviderOptions` 需要以下 Host-only 值:
10
+
11
+ | 字段 | 含义 |
12
+ |---|---|
13
+ | `credentialRef` | 用户 API key 引用。 |
14
+ | `signingSecretRef` | 应用签名密钥引用。 |
15
+ | `endpoint` | 已审计的 OpenAPI endpoint。 |
16
+ | `clientEnv`、`clientSource`、`subChannel` | 鉴权时发送的部署身份。 |
17
+ | `credentials`、`http` | Host 凭据和 HTTP Provider。 |
18
+ | `timeoutMs`、`maxRetries` | 单次超时和重试上限。 |
19
+
20
+ 用户 key、access token、qid、签名密钥、请求头和原始 API 响应不得进入浏览器、Session、模型、URL、日志或诊断。
21
+
22
+ ## 只读操作
23
+
24
+ `getUser()` 交换用户凭据并读取当前用户。`list()` 映射 `File.getList` 分页;已列出的目录 id 仅在当前凭据代次内解析为路径。`search()` 映射表单编码的 `File.searchList` 分页。两种 cursor 都是不透明的源页码。
25
+
26
+ 缺少用户凭据或签名密钥时,Provider 会在发出签名请求前拒绝。凭据变化会清除内存目录路径映射。调用方取消不会重试;可重试的传输失败和 HTTP 状态由 `maxRetries` 限制。
27
+
28
+ ## 部署前提
29
+
30
+ 签名密钥需要经过批准、可轮换的 Host-only 来源。不得从 MCP 参考项目复制签名材料,也不得将其提交到源码、fixture、Bundle YAML 或客户端配置。本包已包含生产 fetch transport;但在该来源与 Provider 注册被组合到 Bundle 前,它只是经过测试的 Provider 实现,不是已部署集成。
31
+
32
+ ## 已知限制与暂缓事项
33
+
34
+ - Provider 只实现用户查询、目录列表和搜索;不提供上传、下载、变更、分享或传输 API。
35
+ - 一个已配置的 Provider 服务于一个 Host 进程,尚未实现多账户切换和远端变更观察。
36
+ - 本发布中的签名材料仍是用户自管的 Host 凭据;本包不提供托管分发或轮换服务。
package/lib/index.js ADDED
@@ -0,0 +1,326 @@
1
+ import { createHash } from "node:crypto";
2
+ import z from "@deepseek-ai/schemastery";
3
+ import { credentialRef } from "@deepseek-ai/dsh-credentials";
4
+ import CloudDiskRuntime, { CloudDiskError } from "@aicloud360/dsh-cloud-disk";
5
+ //#region lib/types/index.js
6
+ /** Direct Host-side adapter for the audited 360 CloudDisk OpenAPI. */
7
+ /** Cordis loader name for the direct CloudDisk Provider plugin. */
8
+ const name = "cloud-disk-api-provider";
9
+ /** Host services required to register and operate the direct Provider. */
10
+ const inject = ["cloudDisk", "credentials"];
11
+ /** Runtime schema for the complete, explicit Provider configuration. */
12
+ const Config = z.object({
13
+ endpoint: z.string().required(),
14
+ apiKeyRef: z.string().required(),
15
+ signingSecretRef: z.string().required(),
16
+ clientEnv: z.string().required(),
17
+ clientSource: z.string().required(),
18
+ subChannel: z.string().required(),
19
+ timeoutMs: z.number().required(),
20
+ maxRetries: z.number().required()
21
+ });
22
+ /**
23
+ * Create the production fetch transport used by the Host-side Provider.
24
+ * @param fetchImpl - Host fetch implementation; injectable only for tests.
25
+ * @returns A transport that parses JSON without logging sensitive request data.
26
+ */
27
+ function createFetchCloudDiskHttpClient(fetchImpl = fetch) {
28
+ return { async request(input) {
29
+ const response = await fetchImpl(input.url, {
30
+ method: input.method,
31
+ headers: input.headers,
32
+ ...input.body === void 0 ? {} : { body: input.body },
33
+ ...input.signal === void 0 ? {} : { signal: input.signal }
34
+ });
35
+ let json;
36
+ try {
37
+ json = await response.json();
38
+ } catch {
39
+ json = void 0;
40
+ }
41
+ return {
42
+ status: response.status,
43
+ json
44
+ };
45
+ } };
46
+ }
47
+ /** Provider that keeps API key, token, and signing material on the Host. */
48
+ var DirectCloudDiskProvider = class {
49
+ options;
50
+ id = "360-http";
51
+ parentPaths = /* @__PURE__ */ new Map();
52
+ credentialFingerprint;
53
+ constructor(options) {
54
+ this.options = options;
55
+ if (!Number.isInteger(options.timeoutMs) || options.timeoutMs <= 0) throw new TypeError("timeoutMs must be a positive integer");
56
+ if (!Number.isInteger(options.maxRetries) || options.maxRetries < 0) throw new TypeError("maxRetries must be a non-negative integer");
57
+ }
58
+ /** Report that the Provider is configured; each operation verifies its credentials. */
59
+ available() {
60
+ return true;
61
+ }
62
+ /**
63
+ * Read the authenticated user without exposing credential or token fields.
64
+ * @param signal - Cancels the request.
65
+ * @returns Normalized user information.
66
+ */
67
+ async getUser(signal) {
68
+ const auth = await this.authenticate(signal);
69
+ const result = await this.call(this.getInput({
70
+ method: "User.getUserDetail",
71
+ access_token: auth.accessToken,
72
+ qid: auth.qid,
73
+ sign: "",
74
+ sub_channel: this.options.subChannel
75
+ }, auth.accessToken), signal);
76
+ const data = this.data(result, "user");
77
+ if (!isRecord(data) || typeof data.qid !== "string") throw invalidResponse("user");
78
+ const displayName = [
79
+ data.nickname,
80
+ data.nickName,
81
+ data.nick,
82
+ data.userName,
83
+ data.name
84
+ ].find((value) => typeof value === "string" && value.trim().length > 0);
85
+ return {
86
+ id: data.qid,
87
+ ...displayName === void 0 ? {} : { displayName: displayName.trim() }
88
+ };
89
+ }
90
+ /**
91
+ * List one directory page.
92
+ * @param request - Stable parent id and opaque cursor.
93
+ * @param signal - Cancels the request.
94
+ * @returns Normalized remote nodes.
95
+ */
96
+ async list(request, signal) {
97
+ const path = request.parentId === void 0 ? "/" : this.parentPaths.get(request.parentId);
98
+ if (path === void 0) throw new CloudDiskError("CloudDisk directory is no longer available in this Provider generation", "CLOUD_DISK_INVALID_REQUEST");
99
+ const page = pageNumber(request.cursor, 0);
100
+ const limit = request.limit ?? 50;
101
+ const auth = await this.authenticate(signal);
102
+ const params = await this.signed(auth, "File.getList", {
103
+ path,
104
+ page: String(page),
105
+ page_size: String(limit)
106
+ });
107
+ const result = await this.call(this.getInput(params, auth.accessToken), signal);
108
+ return this.page(this.data(result, "directory page"), path, request.parentId, page);
109
+ }
110
+ /** Search remote nodes. @param request - Query and opaque cursor. @param signal - Cancels the request. @returns Normalized matches. */
111
+ async search(request, signal) {
112
+ const page = pageNumber(request.cursor, 1);
113
+ const limit = request.limit ?? 20;
114
+ const auth = await this.authenticate(signal);
115
+ const params = await this.signed(auth, "File.searchList", {
116
+ file_category: "-1",
117
+ key: request.query,
118
+ page: String(page),
119
+ page_size: String(limit)
120
+ });
121
+ const result = await this.call(this.postInput(params, auth.accessToken), signal);
122
+ return this.page(this.data(result, "search page"), void 0, void 0, page);
123
+ }
124
+ async authenticate(signal) {
125
+ const credential = await this.options.credentials.resolve(this.options.credentialRef);
126
+ if (credential === void 0) throw credentialMissing();
127
+ const fingerprint = createHash("sha256").update(credential.value, "utf8").digest("hex");
128
+ if (this.credentialFingerprint !== fingerprint) {
129
+ this.parentPaths.clear();
130
+ this.credentialFingerprint = fingerprint;
131
+ }
132
+ const params = {
133
+ method: "Oauth.getAccessTokenByApiKeyOrQT",
134
+ client_env: this.options.clientEnv,
135
+ client_src: this.options.clientSource,
136
+ grant_type: "authorization_code",
137
+ sub_channel: this.options.subChannel,
138
+ api_key: credential.value
139
+ };
140
+ const result = await this.call({
141
+ method: "GET",
142
+ url: queryUrl(this.options.endpoint, params),
143
+ headers: {
144
+ accept: "application/json",
145
+ api_key: credential.value
146
+ }
147
+ }, signal);
148
+ const data = this.data(result, "authentication");
149
+ if (!isRecord(data) || typeof data.access_token !== "string" || typeof data.qid !== "string") throw invalidResponse("authentication");
150
+ return {
151
+ accessToken: data.access_token,
152
+ qid: data.qid
153
+ };
154
+ }
155
+ async signed(auth, method, extra) {
156
+ const secret = await this.options.credentials.resolve(this.options.signingSecretRef);
157
+ if (secret === void 0) throw signingSecretMissing();
158
+ const input = {
159
+ access_token: auth.accessToken,
160
+ method,
161
+ qid: auth.qid,
162
+ ...extra
163
+ };
164
+ return {
165
+ ...input,
166
+ sign: sign(input, secret.value),
167
+ sub_channel: this.options.subChannel
168
+ };
169
+ }
170
+ getInput(params, accessToken) {
171
+ return {
172
+ method: "GET",
173
+ url: queryUrl(this.options.endpoint, params),
174
+ headers: { "access-token": accessToken }
175
+ };
176
+ }
177
+ postInput(params, accessToken) {
178
+ return {
179
+ method: "POST",
180
+ url: this.options.endpoint,
181
+ headers: {
182
+ "access-token": accessToken,
183
+ "content-type": "application/x-www-form-urlencoded"
184
+ },
185
+ body: new URLSearchParams(params).toString()
186
+ };
187
+ }
188
+ async call(input, parent) {
189
+ for (let attempt = 0;; attempt += 1) {
190
+ const deadline = deadlineSignal(parent, this.options.timeoutMs);
191
+ try {
192
+ const response = await this.options.http.request({
193
+ ...input,
194
+ signal: deadline.signal
195
+ });
196
+ if (response.status < 200 || response.status >= 300) {
197
+ if (retryableStatus(response.status) && attempt < this.options.maxRetries) continue;
198
+ throw response.status === 401 || response.status === 403 ? authenticationFailed() : failed(`CloudDisk API request failed with HTTP ${String(response.status)}`);
199
+ }
200
+ if (!isRecord(response.json)) throw invalidResponse("API envelope");
201
+ return response.json;
202
+ } catch (error) {
203
+ if (parent?.aborted) throw parent.reason;
204
+ if (error instanceof CloudDiskError) throw error;
205
+ if (attempt >= this.options.maxRetries) throw networkFailed();
206
+ } finally {
207
+ deadline.dispose();
208
+ }
209
+ }
210
+ }
211
+ data(result, subject) {
212
+ if (result.errno !== 0) throw failed(`CloudDisk ${subject} failed`);
213
+ return result.data;
214
+ }
215
+ page(value, path, parentId, page) {
216
+ if (!isRecord(value) || !Array.isArray(value.node_list) || typeof value.has_next_page !== "boolean") throw invalidResponse("page");
217
+ return {
218
+ nodes: value.node_list.map((node, index) => this.node(node, path, parentId, index)),
219
+ ...value.has_next_page ? { nextCursor: String(page + 1) } : {}
220
+ };
221
+ }
222
+ node(value, parentPath, parentId, index) {
223
+ if (!isRecord(value) || typeof value.nid !== "string" || typeof value.name !== "string") throw invalidResponse(`page.node_list[${String(index)}]`);
224
+ const directory = value.type === 1 || value.type === "1" || value.type === "dir" || value.is_dir === 1 || value.is_dir === "1";
225
+ const id = value.nid;
226
+ if (directory && parentPath !== void 0) this.parentPaths.set(id, childPath(parentPath, value.name));
227
+ const parent = parentId === void 0 ? {} : { parentId };
228
+ const size = typeof value.count_size === "string" && /^\d+$/.test(value.count_size) ? { size: Number(value.count_size) } : {};
229
+ const updatedAt = typeof value.modify_time === "string" ? { updatedAt: value.modify_time } : {};
230
+ return {
231
+ id,
232
+ kind: directory ? "directory" : "file",
233
+ name: value.name,
234
+ ...parent,
235
+ ...size,
236
+ ...updatedAt
237
+ };
238
+ }
239
+ };
240
+ /**
241
+ * Register a direct Provider and return its disposer.
242
+ * @param ctx - CloudDisk service owner.
243
+ * @param options - Host-only Provider configuration.
244
+ * @returns Registration disposer.
245
+ */
246
+ function applyDirectCloudDiskProvider(ctx, options) {
247
+ return ctx.cloudDisk.registerProvider(new DirectCloudDiskProvider(options));
248
+ }
249
+ /**
250
+ * Register the production fetch Provider from a profile's explicit credential references.
251
+ * @param ctx - Host context that owns the CloudDisk and credential services.
252
+ * @param config - Complete direct-Provider configuration from the profile Bundle.
253
+ */
254
+ function apply(ctx, config) {
255
+ applyDirectCloudDiskProvider(ctx, {
256
+ endpoint: config.endpoint,
257
+ credentialRef: credentialRef(config.apiKeyRef),
258
+ signingSecretRef: credentialRef(config.signingSecretRef),
259
+ clientEnv: config.clientEnv,
260
+ clientSource: config.clientSource,
261
+ subChannel: config.subChannel,
262
+ credentials: ctx.credentials,
263
+ http: createFetchCloudDiskHttpClient(),
264
+ timeoutMs: config.timeoutMs,
265
+ maxRetries: config.maxRetries
266
+ });
267
+ }
268
+ function isRecord(value) {
269
+ return value !== null && typeof value === "object" && !Array.isArray(value);
270
+ }
271
+ function credentialMissing() {
272
+ return new CloudDiskError("CloudDisk credential is not configured", "CLOUD_DISK_CREDENTIAL_MISSING");
273
+ }
274
+ function signingSecretMissing() {
275
+ return new CloudDiskError("CloudDisk signing secret is not configured", "CLOUD_DISK_SIGNING_SECRET_MISSING");
276
+ }
277
+ function authenticationFailed() {
278
+ return new CloudDiskError("CloudDisk authentication failed", "CLOUD_DISK_AUTHENTICATION_FAILED");
279
+ }
280
+ function networkFailed() {
281
+ return new CloudDiskError("CloudDisk network request failed", "CLOUD_DISK_NETWORK_FAILED");
282
+ }
283
+ function failed(message) {
284
+ return new CloudDiskError(message, "CLOUD_DISK_PROVIDER_FAILED");
285
+ }
286
+ function invalidResponse(subject) {
287
+ return failed(`CloudDisk ${subject} response is invalid`);
288
+ }
289
+ function retryableStatus(status) {
290
+ return status === 408 || status === 425 || status === 429 || status >= 500;
291
+ }
292
+ function queryUrl(endpoint, params) {
293
+ const url = new URL(endpoint);
294
+ for (const [key, value] of Object.entries(params)) url.searchParams.set(key, value);
295
+ return url.toString();
296
+ }
297
+ function pageNumber(cursor, initial) {
298
+ if (cursor === void 0) return initial;
299
+ if (!/^\d+$/.test(cursor)) throw new CloudDiskError("CloudDisk cursor is invalid", "CLOUD_DISK_INVALID_REQUEST");
300
+ return Number(cursor);
301
+ }
302
+ function childPath(parent, name) {
303
+ const path = name.startsWith("/") ? name : `${parent}${name}`;
304
+ return path.endsWith("/") ? path : `${path}/`;
305
+ }
306
+ function phpEncode(value) {
307
+ return encodeURIComponent(value).replace(/%20/g, "+").replace(/[!'()*~]/g, (char) => `%${char.charCodeAt(0).toString(16).toUpperCase()}`);
308
+ }
309
+ function sign(params, secret) {
310
+ return createHash("md5").update(`${Object.keys(params).sort().map((key) => `${key}=${phpEncode(params[key])}`).join("&")}${secret}`, "utf8").digest("hex");
311
+ }
312
+ function deadlineSignal(parent, timeoutMs) {
313
+ const controller = new AbortController();
314
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
315
+ const abort = () => controller.abort(parent?.reason);
316
+ parent?.addEventListener("abort", abort, { once: true });
317
+ return {
318
+ signal: controller.signal,
319
+ dispose: () => {
320
+ clearTimeout(timer);
321
+ parent?.removeEventListener("abort", abort);
322
+ }
323
+ };
324
+ }
325
+ //#endregion
326
+ export { CloudDiskRuntime, Config, DirectCloudDiskProvider, apply, applyDirectCloudDiskProvider, createFetchCloudDiskHttpClient, inject, name };
@@ -0,0 +1,20 @@
1
+ //#region lib/types/invariant.js
2
+ /**
3
+ * Package-owned invariant companion for `@aicloud360/dsh-cloud-disk-api-provider`.
4
+ * @module @aicloud360/dsh-cloud-disk-api-provider/invariant
5
+ */
6
+ const PACKAGE_NAME = "@aicloud360/dsh-cloud-disk-api-provider";
7
+ /** Cordis companion plugin name. */
8
+ const name = "cloud-disk-api-provider-invariant";
9
+ /** Service required before the companion can reserve package ownership. */
10
+ const inject = ["invariants"];
11
+ /** No runtime invariant: provider behavior is enforced at operation time and routed through stable `CloudDiskError` codes. */
12
+ const install = () => {};
13
+ /**
14
+ * Register this package's invariant companion.
15
+ * @param ctx - Cordis context carrying the invariant service.
16
+ * @returns the installed registration's disposer.
17
+ */
18
+ const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
19
+ //#endregion
20
+ export { apply, inject, name };
@@ -0,0 +1,110 @@
1
+ /** Direct Host-side adapter for the audited 360 CloudDisk OpenAPI. */
2
+ import type { Context } from '@deepseek-ai/cordis';
3
+ import z from '@deepseek-ai/schemastery';
4
+ import { type CredentialProvider, type CredentialRef } from '@deepseek-ai/dsh-credentials';
5
+ import CloudDiskRuntime, { type CloudDiskListRequest, type CloudDiskPage, type CloudDiskProvider, type CloudDiskProviderConfig, type CloudDiskSearchRequest, type CloudDiskUser } from '@aicloud360/dsh-cloud-disk';
6
+ /** Cordis loader name for the direct CloudDisk Provider plugin. */
7
+ export declare const name = "cloud-disk-api-provider";
8
+ /** Host services required to register and operate the direct Provider. */
9
+ export declare const inject: string[];
10
+ /** Loader configuration for the direct CloudDisk Provider. */
11
+ export interface Config {
12
+ /** OpenAPI endpoint URL. */
13
+ endpoint: string;
14
+ /** Credential reference containing the user API key. */
15
+ apiKeyRef: string;
16
+ /** Credential reference containing the server-side request-signing secret. */
17
+ signingSecretRef: string;
18
+ /** 360 client environment identifier. */
19
+ clientEnv: string;
20
+ /** 360 client source identifier. */
21
+ clientSource: string;
22
+ /** 360 sub-channel identifier. */
23
+ subChannel: string;
24
+ /** Maximum duration of one HTTP attempt in milliseconds. */
25
+ timeoutMs: number;
26
+ /** Number of retry attempts after the initial HTTP attempt. */
27
+ maxRetries: number;
28
+ }
29
+ /** Runtime schema for the complete, explicit Provider configuration. */
30
+ export declare const Config: z<Config>;
31
+ /** Response returned by the Provider's injectable Host HTTP transport. */
32
+ export interface CloudDiskHttpResponse {
33
+ readonly status: number;
34
+ readonly json: unknown;
35
+ }
36
+ /** Host HTTP transport. It must not log request headers or response bodies. */
37
+ export interface CloudDiskHttpClient {
38
+ request(input: {
39
+ readonly method: 'GET' | 'POST';
40
+ readonly url: string;
41
+ readonly headers: Readonly<Record<string, string>>;
42
+ readonly body?: string;
43
+ readonly signal?: AbortSignal;
44
+ }): Promise<CloudDiskHttpResponse>;
45
+ }
46
+ /**
47
+ * Create the production fetch transport used by the Host-side Provider.
48
+ * @param fetchImpl - Host fetch implementation; injectable only for tests.
49
+ * @returns A transport that parses JSON without logging sensitive request data.
50
+ */
51
+ export declare function createFetchCloudDiskHttpClient(fetchImpl?: typeof fetch): CloudDiskHttpClient;
52
+ /** Host-only configuration for the audited direct 360 OpenAPI Provider. */
53
+ export interface DirectCloudDiskProviderOptions extends CloudDiskProviderConfig {
54
+ readonly signingSecretRef: CredentialRef;
55
+ readonly clientEnv: string;
56
+ readonly clientSource: string;
57
+ readonly subChannel: string;
58
+ readonly credentials: CredentialProvider;
59
+ readonly http: CloudDiskHttpClient;
60
+ readonly timeoutMs: number;
61
+ readonly maxRetries: number;
62
+ }
63
+ /** Provider that keeps API key, token, and signing material on the Host. */
64
+ export declare class DirectCloudDiskProvider implements CloudDiskProvider {
65
+ private readonly options;
66
+ readonly id = "360-http";
67
+ private readonly parentPaths;
68
+ private credentialFingerprint;
69
+ constructor(options: DirectCloudDiskProviderOptions);
70
+ /** Report that the Provider is configured; each operation verifies its credentials. */
71
+ available(): boolean;
72
+ /**
73
+ * Read the authenticated user without exposing credential or token fields.
74
+ * @param signal - Cancels the request.
75
+ * @returns Normalized user information.
76
+ */
77
+ getUser(signal?: AbortSignal): Promise<CloudDiskUser>;
78
+ /**
79
+ * List one directory page.
80
+ * @param request - Stable parent id and opaque cursor.
81
+ * @param signal - Cancels the request.
82
+ * @returns Normalized remote nodes.
83
+ */
84
+ list(request: CloudDiskListRequest, signal?: AbortSignal): Promise<CloudDiskPage>;
85
+ /** Search remote nodes. @param request - Query and opaque cursor. @param signal - Cancels the request. @returns Normalized matches. */
86
+ search(request: CloudDiskSearchRequest, signal?: AbortSignal): Promise<CloudDiskPage>;
87
+ private authenticate;
88
+ private signed;
89
+ private getInput;
90
+ private postInput;
91
+ private call;
92
+ private data;
93
+ private page;
94
+ private node;
95
+ }
96
+ /**
97
+ * Register a direct Provider and return its disposer.
98
+ * @param ctx - CloudDisk service owner.
99
+ * @param options - Host-only Provider configuration.
100
+ * @returns Registration disposer.
101
+ */
102
+ export declare function applyDirectCloudDiskProvider(ctx: Context, options: DirectCloudDiskProviderOptions): () => void;
103
+ /**
104
+ * Register the production fetch Provider from a profile's explicit credential references.
105
+ * @param ctx - Host context that owns the CloudDisk and credential services.
106
+ * @param config - Complete direct-Provider configuration from the profile Bundle.
107
+ */
108
+ export declare function apply(ctx: Context, config: Config): void;
109
+ export { CloudDiskRuntime };
110
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Package-owned invariant companion for `@aicloud360/dsh-cloud-disk-api-provider`.
3
+ * @module @aicloud360/dsh-cloud-disk-api-provider/invariant
4
+ */
5
+ import type { Context } from '@deepseek-ai/cordis';
6
+ /** Cordis companion plugin name. */
7
+ export declare const name = "cloud-disk-api-provider-invariant";
8
+ /** Service required before the companion can reserve package ownership. */
9
+ export declare const inject: string[];
10
+ /**
11
+ * Register this package's invariant companion.
12
+ * @param ctx - Cordis context carrying the invariant service.
13
+ * @returns the installed registration's disposer.
14
+ */
15
+ export declare const apply: (ctx: Context) => Promise<() => void>;
16
+ //# sourceMappingURL=invariant.d.ts.map
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@aicloud360/dsh-cloud-disk-api-provider",
3
+ "description": "Direct Host-side HTTP provider adapter for the native CloudDisk capability seam",
4
+ "version": "0.1.1-alpha.1",
5
+ "publishConfig": {
6
+ "access": "public",
7
+ "registry": "https://registry.npmjs.org"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/yifangyun/dsh-cloud-disk.git",
12
+ "directory": "packages/dsh-cloud-disk-api-provider"
13
+ },
14
+ "type": "module",
15
+ "main": "lib/index.js",
16
+ "types": "lib/types/index.d.ts",
17
+ "files": [
18
+ "lib/index.js",
19
+ "lib/invariant.js",
20
+ "lib/types/**/*.d.ts"
21
+ ],
22
+ "license": "MIT",
23
+ "peerDependencies": {
24
+ "@deepseek-ai/dsh-credentials": "0.1.1-rc.2",
25
+ "@deepseek-ai/dsh-invariants": "0.1.1-rc.2",
26
+ "@deepseek-ai/schemastery": "^3.18.1",
27
+ "@deepseek-ai/cordis": "^4.0.1"
28
+ },
29
+ "exports": {
30
+ ".": {
31
+ "types": "./lib/types/index.d.ts",
32
+ "default": "./lib/index.js"
33
+ },
34
+ "./invariant": {
35
+ "types": "./lib/types/invariant.d.ts",
36
+ "default": "./lib/invariant.js"
37
+ },
38
+ "./package.json": "./package.json"
39
+ },
40
+ "dependencies": {
41
+ "@aicloud360/dsh-cloud-disk": "0.1.1-alpha.1"
42
+ }
43
+ }