@qmuse/cloud-client 0.0.1-dev.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/LEGAL.md +7 -0
- package/README.md +158 -0
- package/dist/adapters.d.ts +18 -0
- package/dist/adapters.d.ts.map +1 -0
- package/dist/adapters.js +43 -0
- package/dist/adapters.js.map +1 -0
- package/dist/auth.d.ts +9 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +157 -0
- package/dist/auth.js.map +1 -0
- package/dist/client.d.ts +5 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +157 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +15 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +19 -0
- package/dist/errors.js.map +1 -0
- package/dist/files.d.ts +5 -0
- package/dist/files.d.ts.map +1 -0
- package/dist/files.js +149 -0
- package/dist/files.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/miniapp.d.ts +60 -0
- package/dist/miniapp.d.ts.map +1 -0
- package/dist/miniapp.js +161 -0
- package/dist/miniapp.js.map +1 -0
- package/dist/types.d.ts +184 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/web.d.ts +11 -0
- package/dist/web.d.ts.map +1 -0
- package/dist/web.js +146 -0
- package/dist/web.js.map +1 -0
- package/package.json +55 -0
package/LEGAL.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Legal Disclaimer
|
|
2
|
+
|
|
3
|
+
Within this source code, the comments in Chinese shall be the original, governing version. Any comment in other languages are for reference only. In the event of any conflict between the Chinese language version comments and other language version comments, the Chinese language version shall prevail.
|
|
4
|
+
|
|
5
|
+
法律免责声明
|
|
6
|
+
|
|
7
|
+
关于代码注释部分,中文注释为官方版本,其它语言注释仅做参考。中文注释可能与其它语言注释存在不一致,当中文注释与其它语言注释存在不一致时,请以中文注释为准。
|
package/README.md
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# @qmuse/cloud-client
|
|
2
|
+
|
|
3
|
+
Unified Web/PC/mini-program client for QMuse Cloud services. Business APIs use
|
|
4
|
+
the single `qmuse-cloud-api` AppBase Function. File policy uses that Function as
|
|
5
|
+
its control plane while large file bytes use a platform-specific Storage data
|
|
6
|
+
plane inside this package.
|
|
7
|
+
|
|
8
|
+
The package intentionally does not expose AppBase clients, Functions, Storage,
|
|
9
|
+
TablesDB, endpoint, project ID, database ID, bucket ID, or permissions to
|
|
10
|
+
business modules. A QMuse host adapter supplies narrow execution, Session and
|
|
11
|
+
file transport capabilities.
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { createQmuseCloudClient } from '@qmuse/cloud-client';
|
|
15
|
+
|
|
16
|
+
export const cloudClient = createQmuseCloudClient({
|
|
17
|
+
execute: input => runtime.executeCloudFunction(input),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const result = await cloudClient.request<{ data: Order }>({
|
|
21
|
+
method: 'GET',
|
|
22
|
+
path: '/api/orders/order_1',
|
|
23
|
+
});
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Each generated application owns its own users, credentials, sessions, roles,
|
|
27
|
+
and policies. It does not reuse the QMuse platform login. AppBase Auth is only
|
|
28
|
+
an internal shadow transport identity used for Function runtime headers and
|
|
29
|
+
Storage permissions.
|
|
30
|
+
|
|
31
|
+
The host supplies an application credential store and the two narrow AppBase
|
|
32
|
+
Account operations needed to establish/remove that shadow Session:
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
export const cloudClient = createQmuseCloudClient({
|
|
36
|
+
execute: input => runtime.executeCloudFunction(input),
|
|
37
|
+
auth: {
|
|
38
|
+
credentialStore: secureCredentialStore,
|
|
39
|
+
shadowSession: {
|
|
40
|
+
createSession: input => account.createSession(input),
|
|
41
|
+
deleteCurrentSession: () => account.deleteSession({ sessionId: 'current' }),
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
await cloudClient.auth.login({ email, password });
|
|
47
|
+
const currentUser = await cloudClient.auth.getCurrentUser();
|
|
48
|
+
await cloudClient.auth.logout();
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`login/register/refresh` receive a one-time shadow Custom Token from Hono and
|
|
52
|
+
exchange it internally. The token secret is never persisted in the application
|
|
53
|
+
credential store. Refresh is single-flight, rotates application credentials,
|
|
54
|
+
and replaces the current shadow Session. Hosts must back `credentialStore` with
|
|
55
|
+
their platform's secure storage policy; this package does not default refresh
|
|
56
|
+
tokens to `localStorage`.
|
|
57
|
+
|
|
58
|
+
Business file operations use a logical resource, never a bucket ID:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
const attachment = await cloudClient.files.upload({
|
|
62
|
+
resource: 'order-attachment',
|
|
63
|
+
file,
|
|
64
|
+
relation: { orderId },
|
|
65
|
+
onProgress: progress => console.log(progress.progress),
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const preview = await cloudClient.files.createPreview({
|
|
69
|
+
fileId: attachment.id,
|
|
70
|
+
width: 640,
|
|
71
|
+
});
|
|
72
|
+
image.src = preview.url;
|
|
73
|
+
preview.dispose();
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The upload flow creates an intent through `qmuse-cloud-api`, uploads in 5 MiB
|
|
77
|
+
chunks through the injected Web or mini-program data-plane transport, then
|
|
78
|
+
completes the intent through the Function. Failures issue a best-effort cancel;
|
|
79
|
+
the backend must also expire abandoned intents. Preview/download access is
|
|
80
|
+
authorized by the Function and may return a short-lived File Token URL or an
|
|
81
|
+
authenticated URL that the Web transport converts to a disposable Blob URL.
|
|
82
|
+
|
|
83
|
+
Platform transports are separate package entry points:
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
import { createWebFileTransport } from '@qmuse/cloud-client/web';
|
|
87
|
+
import { createMiniappFileTransport } from '@qmuse/cloud-client/miniapp';
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
They migrate the proven file mechanics from the legacy `@qmuse/appwrite`
|
|
91
|
+
implementation: Web `File`/`Blob`, Taro-style local paths, 5 MiB chunks,
|
|
92
|
+
`Content-Range`, `X-Appwrite-ID` continuation, progress, fallback Session
|
|
93
|
+
headers and mini-program temporary-file cleanup. They do not migrate TablesDB
|
|
94
|
+
CRUD or the legacy anonymous `Role.any()` update/delete permissions.
|
|
95
|
+
|
|
96
|
+
For Web hosts, bind an initialized `Functions` instance without exposing it to
|
|
97
|
+
business modules:
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
import { createAppBaseWebCloudClient } from '@qmuse/cloud-client';
|
|
101
|
+
|
|
102
|
+
export const cloudClient = createAppBaseWebCloudClient(functions, {
|
|
103
|
+
refreshSession,
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
The legacy portable adapter remains available during migration:
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
import { createPortableCloudClient } from '@qmuse/cloud-client';
|
|
111
|
+
|
|
112
|
+
export const cloudClient = createPortableCloudClient(appwrite);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
New applications should bind Function, Session and file capabilities directly
|
|
116
|
+
at their host bootstrap and should not depend on `@qmuse/appwrite` or
|
|
117
|
+
`@qmuse/appwrite-runtime-sdk`. The portable adapter only translates this
|
|
118
|
+
package's `path` field to the legacy `xpath` field for staged migration.
|
|
119
|
+
|
|
120
|
+
Only `/api` paths and an allowlist of business headers are accepted. The client
|
|
121
|
+
uses synchronous Function execution, reads `responseStatusCode`, `responseBody`,
|
|
122
|
+
and `responseHeaders`, and maps non-2xx responses to `QmuseCloudHttpError`.
|
|
123
|
+
|
|
124
|
+
The client never replays a completed Function response, including a business
|
|
125
|
+
401, because replaying a write could duplicate side effects. The host adapter is
|
|
126
|
+
responsible for Session coordination and may retry `createExecution` once only
|
|
127
|
+
when the execution API request itself fails with a transport-level 401.
|
|
128
|
+
|
|
129
|
+
Direct Storage upload is an internal data-plane optimization, not a claim that
|
|
130
|
+
the bucket ID is secret on the network or that the protocol can only reach the
|
|
131
|
+
Function. Private buckets must be configured so client users can create files
|
|
132
|
+
but cannot read/update/delete them directly; reads and deletion are authorized
|
|
133
|
+
by the backend. The exact `fileSecurity` + File Token combination remains a
|
|
134
|
+
real AppBase E2E gate before production use.
|
|
135
|
+
|
|
136
|
+
## Development
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
npm install
|
|
140
|
+
npm run ci
|
|
141
|
+
npm pack --dry-run
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Publishing
|
|
145
|
+
|
|
146
|
+
Set an unpublished semantic version in `package.json`, authenticate with the
|
|
147
|
+
public npm registry, and run:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
npm login --registry https://registry.npmjs.org/
|
|
151
|
+
npm run publish:public
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The script defaults to the `dev` dist-tag and also supports `latest`. Before
|
|
155
|
+
publishing it checks the version, npm authentication, duplicate versions, the
|
|
156
|
+
full CI command, and package contents, then requires explicit confirmation. It
|
|
157
|
+
temporarily normalizes the public package name and registry and restores
|
|
158
|
+
`package.json` when publishing finishes or fails.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CloudAuthOptions, CloudExecution, CloudExecutionInput, CloudFileTransport, QmuseCloudClient } from './types.js';
|
|
2
|
+
export interface AppBaseFunctionsCapability {
|
|
3
|
+
createExecution(input: CloudExecutionInput): Promise<CloudExecution>;
|
|
4
|
+
}
|
|
5
|
+
export interface PortableExecutionInput extends Omit<CloudExecutionInput, 'path'> {
|
|
6
|
+
xpath: string;
|
|
7
|
+
}
|
|
8
|
+
export interface PortableAppwriteCapability {
|
|
9
|
+
executeFunction(input: PortableExecutionInput): Promise<CloudExecution>;
|
|
10
|
+
}
|
|
11
|
+
export interface HostAdapterOptions<FileSource = never> {
|
|
12
|
+
refreshSession?(): Promise<void>;
|
|
13
|
+
auth?: CloudAuthOptions;
|
|
14
|
+
fileTransport?: CloudFileTransport<FileSource>;
|
|
15
|
+
}
|
|
16
|
+
export declare function createAppBaseWebCloudClient<FileSource = never>(functions: AppBaseFunctionsCapability, options?: HostAdapterOptions<FileSource>): QmuseCloudClient<FileSource>;
|
|
17
|
+
export declare function createPortableCloudClient<FileSource = never>(appwrite: PortableAppwriteCapability, options?: HostAdapterOptions<FileSource>): QmuseCloudClient<FileSource>;
|
|
18
|
+
//# sourceMappingURL=adapters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapters.d.ts","sourceRoot":"","sources":["../src/adapters.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAYpB,MAAM,WAAW,0BAA0B;IACzC,eAAe,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CACtE;AAED,MAAM,WAAW,sBAAuB,SAAQ,IAAI,CAAC,mBAAmB,EAAE,MAAM,CAAC;IAC/E,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,0BAA0B;IACzC,eAAe,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CACzE;AAED,MAAM,WAAW,kBAAkB,CAAC,UAAU,GAAG,KAAK;IACpD,cAAc,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,aAAa,CAAC,EAAE,kBAAkB,CAAC,UAAU,CAAC,CAAC;CAChD;AAsBD,wBAAgB,2BAA2B,CAAC,UAAU,GAAG,KAAK,EAC5D,SAAS,EAAE,0BAA0B,EACrC,OAAO,GAAE,kBAAkB,CAAC,UAAU,CAAM,GAC3C,gBAAgB,CAAC,UAAU,CAAC,CAY9B;AAED,wBAAgB,yBAAyB,CAAC,UAAU,GAAG,KAAK,EAC1D,QAAQ,EAAE,0BAA0B,EACpC,OAAO,GAAE,kBAAkB,CAAC,UAAU,CAAM,GAC3C,gBAAgB,CAAC,UAAU,CAAC,CAe9B"}
|
package/dist/adapters.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { createQmuseCloudClient } from './client.js';
|
|
2
|
+
function isTransportUnauthorized(error) {
|
|
3
|
+
if (!error || typeof error !== 'object')
|
|
4
|
+
return false;
|
|
5
|
+
const value = error;
|
|
6
|
+
return [value.code, value.status, value.statusCode, value.response?.status, value.response?.statusCode]
|
|
7
|
+
.some(code => Number(code) === 401);
|
|
8
|
+
}
|
|
9
|
+
async function withTransportRetry(operation, refreshSession) {
|
|
10
|
+
try {
|
|
11
|
+
return await operation();
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
if (!refreshSession || !isTransportUnauthorized(error))
|
|
15
|
+
throw error;
|
|
16
|
+
await refreshSession();
|
|
17
|
+
return operation();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export function createAppBaseWebCloudClient(functions, options = {}) {
|
|
21
|
+
if (!functions || typeof functions.createExecution !== 'function') {
|
|
22
|
+
throw new TypeError('An AppBase Functions capability is required');
|
|
23
|
+
}
|
|
24
|
+
return createQmuseCloudClient({
|
|
25
|
+
execute: input => withTransportRetry(() => functions.createExecution(input), options.refreshSession),
|
|
26
|
+
...(options.auth ? { auth: options.auth } : {}),
|
|
27
|
+
...(options.fileTransport ? { fileTransport: options.fileTransport } : {}),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
export function createPortableCloudClient(appwrite, options = {}) {
|
|
31
|
+
if (!appwrite || typeof appwrite.executeFunction !== 'function') {
|
|
32
|
+
throw new TypeError('A portable Appwrite execution capability is required');
|
|
33
|
+
}
|
|
34
|
+
return createQmuseCloudClient({
|
|
35
|
+
execute: input => {
|
|
36
|
+
const { path, ...portableInput } = input;
|
|
37
|
+
return withTransportRetry(() => appwrite.executeFunction({ ...portableInput, xpath: path }), options.refreshSession);
|
|
38
|
+
},
|
|
39
|
+
...(options.auth ? { auth: options.auth } : {}),
|
|
40
|
+
...(options.fileTransport ? { fileTransport: options.fileTransport } : {}),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=adapters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapters.js","sourceRoot":"","sources":["../src/adapters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAqCrD,SAAS,uBAAuB,CAAC,KAAc;IAC7C,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,KAAK,GAAG,KAA2B,CAAC;IAC1C,OAAO,CAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAE;SACtG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;AACxC,CAAC;AAED,KAAK,UAAU,kBAAkB,CAC/B,SAA2B,EAC3B,cAAoC;IAEpC,IAAI,CAAC;QACH,OAAO,MAAM,SAAS,EAAE,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,cAAc,IAAI,CAAC,uBAAuB,CAAC,KAAK,CAAC;YAAE,MAAM,KAAK,CAAC;QACpE,MAAM,cAAc,EAAE,CAAC;QACvB,OAAO,SAAS,EAAE,CAAC;IACrB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,2BAA2B,CACzC,SAAqC,EACrC,UAA0C,EAAE;IAE5C,IAAI,CAAC,SAAS,IAAI,OAAO,SAAS,CAAC,eAAe,KAAK,UAAU,EAAE,CAAC;QAClE,MAAM,IAAI,SAAS,CAAC,6CAA6C,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,sBAAsB,CAAC;QAC5B,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAClC,GAAG,EAAE,CAAC,SAAS,CAAC,eAAe,CAAC,KAAK,CAAC,EACtC,OAAO,CAAC,cAAc,CACvB;QACD,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/C,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC3E,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,QAAoC,EACpC,UAA0C,EAAE;IAE5C,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,CAAC,eAAe,KAAK,UAAU,EAAE,CAAC;QAChE,MAAM,IAAI,SAAS,CAAC,sDAAsD,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,sBAAsB,CAAC;QAC5B,OAAO,EAAE,KAAK,CAAC,EAAE;YACf,MAAM,EAAE,IAAI,EAAE,GAAG,aAAa,EAAE,GAAG,KAAK,CAAC;YACzC,OAAO,kBAAkB,CACvB,GAAG,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,GAAG,aAAa,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EACjE,OAAO,CAAC,cAAc,CACvB,CAAC;QACJ,CAAC;QACD,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/C,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC3E,CAAC,CAAC;AACL,CAAC"}
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CloudAuthOptions, CloudRequest, CloudResponse, QmuseCloudAuth } from './types.js';
|
|
2
|
+
type AuthRequest = <T>(request: CloudRequest, accessToken?: string) => Promise<CloudResponse<T>>;
|
|
3
|
+
export type CloudAuthRuntime = QmuseCloudAuth & {
|
|
4
|
+
accessToken(): Promise<string | undefined>;
|
|
5
|
+
};
|
|
6
|
+
export declare function createUnavailableCloudAuth(): CloudAuthRuntime;
|
|
7
|
+
export declare function createCloudAuth(options: CloudAuthOptions, request: AuthRequest): CloudAuthRuntime;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,gBAAgB,EAKhB,YAAY,EACZ,aAAa,EACb,cAAc,EACf,MAAM,YAAY,CAAC;AAEpB,KAAK,WAAW,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AAEjG,MAAM,MAAM,gBAAgB,GAAG,cAAc,GAAG;IAAE,WAAW,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;CAAE,CAAC;AAqC/F,wBAAgB,0BAA0B,IAAI,gBAAgB,CAa7D;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,WAAW,GAAG,gBAAgB,CA4GjG"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { QmuseCloudError } from './errors.js';
|
|
2
|
+
function validCredentials(value) {
|
|
3
|
+
if (!value || typeof value !== 'object')
|
|
4
|
+
return false;
|
|
5
|
+
const item = value;
|
|
6
|
+
return typeof item.accessToken === 'string' && item.accessToken.length > 0 &&
|
|
7
|
+
typeof item.refreshToken === 'string' && item.refreshToken.length > 0 &&
|
|
8
|
+
typeof item.accessTokenExpiresAt === 'string' && item.accessTokenExpiresAt.length > 0 &&
|
|
9
|
+
!!item.user && typeof item.user === 'object' && typeof item.user.id === 'string' && item.user.id.length > 0;
|
|
10
|
+
}
|
|
11
|
+
function validSessionResult(value) {
|
|
12
|
+
if (!value || typeof value !== 'object')
|
|
13
|
+
return false;
|
|
14
|
+
const item = value;
|
|
15
|
+
const shadow = item.shadowSession;
|
|
16
|
+
return validCredentials(item.credentials) && !!shadow && typeof shadow === 'object' &&
|
|
17
|
+
typeof shadow.userId === 'string' && shadow.userId === item.credentials.user.id &&
|
|
18
|
+
typeof shadow.secret === 'string' && shadow.secret.length > 0 &&
|
|
19
|
+
typeof shadow.expire === 'string' && shadow.expire.length > 0;
|
|
20
|
+
}
|
|
21
|
+
function sessionResult(response) {
|
|
22
|
+
const value = response.data?.data;
|
|
23
|
+
if (!validSessionResult(value)) {
|
|
24
|
+
throw new QmuseCloudError('Cloud API returned an invalid authentication response', 'AUTH_RESPONSE_INVALID');
|
|
25
|
+
}
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
export function createUnavailableCloudAuth() {
|
|
29
|
+
const unavailable = async () => {
|
|
30
|
+
throw new QmuseCloudError('Cloud Auth is not configured', 'AUTH_UNAVAILABLE');
|
|
31
|
+
};
|
|
32
|
+
return {
|
|
33
|
+
register: unavailable,
|
|
34
|
+
login: unavailable,
|
|
35
|
+
refresh: unavailable,
|
|
36
|
+
restore: async () => null,
|
|
37
|
+
logout: async () => undefined,
|
|
38
|
+
getCurrentUser: async () => null,
|
|
39
|
+
accessToken: async () => undefined,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export function createCloudAuth(options, request) {
|
|
43
|
+
if (!options || typeof options.credentialStore?.load !== 'function' ||
|
|
44
|
+
typeof options.credentialStore.save !== 'function' || typeof options.credentialStore.clear !== 'function') {
|
|
45
|
+
throw new TypeError('Cloud Auth requires a credential store');
|
|
46
|
+
}
|
|
47
|
+
if (typeof options.shadowSession?.createSession !== 'function' ||
|
|
48
|
+
typeof options.shadowSession.deleteCurrentSession !== 'function') {
|
|
49
|
+
throw new TypeError('Cloud Auth requires a shadow Session capability');
|
|
50
|
+
}
|
|
51
|
+
let loaded = false;
|
|
52
|
+
let credentials = null;
|
|
53
|
+
let refreshFlight = null;
|
|
54
|
+
const load = async () => {
|
|
55
|
+
if (loaded)
|
|
56
|
+
return credentials;
|
|
57
|
+
const stored = await options.credentialStore.load();
|
|
58
|
+
credentials = validCredentials(stored) ? stored : null;
|
|
59
|
+
loaded = true;
|
|
60
|
+
if (stored && !credentials)
|
|
61
|
+
await options.credentialStore.clear();
|
|
62
|
+
return credentials;
|
|
63
|
+
};
|
|
64
|
+
const clear = async () => {
|
|
65
|
+
credentials = null;
|
|
66
|
+
loaded = true;
|
|
67
|
+
await options.credentialStore.clear();
|
|
68
|
+
};
|
|
69
|
+
const establish = async (result) => {
|
|
70
|
+
await options.shadowSession.createSession({
|
|
71
|
+
userId: result.shadowSession.userId,
|
|
72
|
+
secret: result.shadowSession.secret,
|
|
73
|
+
});
|
|
74
|
+
try {
|
|
75
|
+
await options.credentialStore.save(result.credentials);
|
|
76
|
+
credentials = result.credentials;
|
|
77
|
+
loaded = true;
|
|
78
|
+
return result.credentials.user;
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
await options.shadowSession.deleteCurrentSession().catch(() => undefined);
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
const authenticate = async (path, body) => {
|
|
86
|
+
await options.shadowSession.deleteCurrentSession().catch(() => undefined);
|
|
87
|
+
return establish(sessionResult(await request({ method: 'POST', path, body })));
|
|
88
|
+
};
|
|
89
|
+
const refresh = async () => {
|
|
90
|
+
if (refreshFlight)
|
|
91
|
+
return refreshFlight;
|
|
92
|
+
refreshFlight = (async () => {
|
|
93
|
+
const current = await load();
|
|
94
|
+
if (!current)
|
|
95
|
+
throw new QmuseCloudError('No application session is available', 'AUTH_SESSION_MISSING');
|
|
96
|
+
await options.shadowSession.deleteCurrentSession().catch(() => undefined);
|
|
97
|
+
const response = await request({
|
|
98
|
+
method: 'POST',
|
|
99
|
+
path: '/api/auth/refresh',
|
|
100
|
+
body: { refreshToken: current.refreshToken },
|
|
101
|
+
});
|
|
102
|
+
return establish(sessionResult(response));
|
|
103
|
+
})();
|
|
104
|
+
try {
|
|
105
|
+
return await refreshFlight;
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
refreshFlight = null;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
return {
|
|
112
|
+
register: input => authenticate('/api/auth/register', input),
|
|
113
|
+
login: input => authenticate('/api/auth/login', input),
|
|
114
|
+
refresh,
|
|
115
|
+
async restore() {
|
|
116
|
+
if (!await load())
|
|
117
|
+
return null;
|
|
118
|
+
try {
|
|
119
|
+
return await refresh();
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
await clear();
|
|
123
|
+
await options.shadowSession.deleteCurrentSession().catch(() => undefined);
|
|
124
|
+
throw error;
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
async logout() {
|
|
128
|
+
const current = await load();
|
|
129
|
+
try {
|
|
130
|
+
if (current) {
|
|
131
|
+
await request({ method: 'POST', path: '/api/auth/logout' }, current.accessToken);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
await options.shadowSession.deleteCurrentSession().catch(() => undefined);
|
|
136
|
+
await clear();
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
async getCurrentUser() {
|
|
140
|
+
const current = await load();
|
|
141
|
+
if (!current)
|
|
142
|
+
return null;
|
|
143
|
+
const response = await request({ method: 'GET', path: '/api/auth/me' }, current.accessToken);
|
|
144
|
+
const user = response.data?.data;
|
|
145
|
+
if (!user || typeof user !== 'object' || typeof user.id !== 'string') {
|
|
146
|
+
throw new QmuseCloudError('Cloud API returned an invalid current user', 'AUTH_USER_INVALID');
|
|
147
|
+
}
|
|
148
|
+
credentials = { ...current, user };
|
|
149
|
+
await options.credentialStore.save(credentials);
|
|
150
|
+
return user;
|
|
151
|
+
},
|
|
152
|
+
async accessToken() {
|
|
153
|
+
return (await load())?.accessToken;
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { QmuseCloudClient, QmuseCloudClientOptions, CloudFileTransport } from './types.js';
|
|
2
|
+
export declare function createQmuseCloudClient<FileSource = never>(options: Omit<QmuseCloudClientOptions, 'fileTransport'> & {
|
|
3
|
+
fileTransport?: CloudFileTransport<FileSource>;
|
|
4
|
+
}): QmuseCloudClient<FileSource>;
|
|
5
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAKV,gBAAgB,EAChB,uBAAuB,EACvB,kBAAkB,EACnB,MAAM,YAAY,CAAC;AA+GpB,wBAAgB,sBAAsB,CAAC,UAAU,GAAG,KAAK,EACvD,OAAO,EAAE,IAAI,CAAC,uBAAuB,EAAE,eAAe,CAAC,GAAG;IAAE,aAAa,CAAC,EAAE,kBAAkB,CAAC,UAAU,CAAC,CAAA;CAAE,GAC3G,gBAAgB,CAAC,UAAU,CAAC,CA+C9B"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { QmuseCloudError, QmuseCloudHttpError } from './errors.js';
|
|
2
|
+
import { createCloudAuth, createUnavailableCloudAuth } from './auth.js';
|
|
3
|
+
import { createCloudFiles } from './files.js';
|
|
4
|
+
const functionId = 'qmuse-cloud-api';
|
|
5
|
+
const allowedHeaders = new Set([
|
|
6
|
+
'accept',
|
|
7
|
+
'content-type',
|
|
8
|
+
'idempotency-key',
|
|
9
|
+
'if-match',
|
|
10
|
+
'if-none-match',
|
|
11
|
+
'x-request-id',
|
|
12
|
+
]);
|
|
13
|
+
function encodeQueryValue(value) {
|
|
14
|
+
return value === null ? '' : String(value);
|
|
15
|
+
}
|
|
16
|
+
function buildPath(path, query) {
|
|
17
|
+
if (!path.startsWith('/api/') && path !== '/api') {
|
|
18
|
+
throw new TypeError('Cloud API path must be /api or start with /api/');
|
|
19
|
+
}
|
|
20
|
+
if (path.includes('?') || path.includes('#') || path.includes('://')) {
|
|
21
|
+
throw new TypeError('Cloud API path must not contain a query, fragment, or URL scheme');
|
|
22
|
+
}
|
|
23
|
+
if (!query)
|
|
24
|
+
return path;
|
|
25
|
+
const params = new URLSearchParams();
|
|
26
|
+
for (const key of Object.keys(query).sort()) {
|
|
27
|
+
const value = query[key];
|
|
28
|
+
if (value !== undefined)
|
|
29
|
+
params.append(key, encodeQueryValue(value));
|
|
30
|
+
}
|
|
31
|
+
const encoded = params.toString();
|
|
32
|
+
return encoded ? `${path}?${encoded}` : path;
|
|
33
|
+
}
|
|
34
|
+
function normalizeRequestHeaders(headers, hasBody, accessToken) {
|
|
35
|
+
const normalized = { accept: 'application/json' };
|
|
36
|
+
for (const [rawName, value] of Object.entries(headers ?? {})) {
|
|
37
|
+
const name = rawName.trim().toLowerCase();
|
|
38
|
+
if (!allowedHeaders.has(name)) {
|
|
39
|
+
throw new TypeError(`Cloud API header is not allowed: ${rawName}`);
|
|
40
|
+
}
|
|
41
|
+
normalized[name] = value;
|
|
42
|
+
}
|
|
43
|
+
if (hasBody && !normalized['content-type'])
|
|
44
|
+
normalized['content-type'] = 'application/json';
|
|
45
|
+
if (accessToken)
|
|
46
|
+
normalized.authorization = `Bearer ${accessToken}`;
|
|
47
|
+
return normalized;
|
|
48
|
+
}
|
|
49
|
+
function normalizeResponseHeaders(value) {
|
|
50
|
+
if (!value)
|
|
51
|
+
return {};
|
|
52
|
+
if (!Array.isArray(value)) {
|
|
53
|
+
return Object.fromEntries(Object.entries(value).map(([name, headerValue]) => [name.toLowerCase(), headerValue]));
|
|
54
|
+
}
|
|
55
|
+
const headers = {};
|
|
56
|
+
for (const header of value)
|
|
57
|
+
headers[header.name.toLowerCase()] = header.value;
|
|
58
|
+
return headers;
|
|
59
|
+
}
|
|
60
|
+
function parseBody(body) {
|
|
61
|
+
if (!body)
|
|
62
|
+
return null;
|
|
63
|
+
try {
|
|
64
|
+
return JSON.parse(body);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return body;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function readHttpError(status, payload) {
|
|
71
|
+
let code = `HTTP_${status}`;
|
|
72
|
+
let message = `Cloud API request failed with status ${status}`;
|
|
73
|
+
let details;
|
|
74
|
+
if (payload && typeof payload === 'object' && 'error' in payload) {
|
|
75
|
+
const error = payload.error;
|
|
76
|
+
if (error && typeof error === 'object') {
|
|
77
|
+
const record = error;
|
|
78
|
+
if (typeof record.code === 'string' && record.code)
|
|
79
|
+
code = record.code;
|
|
80
|
+
if (typeof record.message === 'string' && record.message)
|
|
81
|
+
message = record.message;
|
|
82
|
+
details = record.details;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return new QmuseCloudHttpError({ status, code, message, details });
|
|
86
|
+
}
|
|
87
|
+
function isTransportUnauthorized(error) {
|
|
88
|
+
if (error instanceof QmuseCloudHttpError || !error || typeof error !== 'object')
|
|
89
|
+
return false;
|
|
90
|
+
const value = error;
|
|
91
|
+
return [value.code, value.status, value.statusCode, value.response?.status, value.response?.statusCode]
|
|
92
|
+
.some(code => Number(code) === 401);
|
|
93
|
+
}
|
|
94
|
+
function serializeBody(request) {
|
|
95
|
+
if (request.method === 'GET' || request.method === 'DELETE') {
|
|
96
|
+
if (request.body !== undefined)
|
|
97
|
+
throw new TypeError(`${request.method} requests must not contain a body`);
|
|
98
|
+
return '';
|
|
99
|
+
}
|
|
100
|
+
if (request.body === undefined)
|
|
101
|
+
return '';
|
|
102
|
+
try {
|
|
103
|
+
return JSON.stringify(request.body);
|
|
104
|
+
}
|
|
105
|
+
catch (cause) {
|
|
106
|
+
throw new QmuseCloudError('Cloud API request body is not JSON serializable', 'BODY_NOT_SERIALIZABLE', { cause });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
export function createQmuseCloudClient(options) {
|
|
110
|
+
if (!options || typeof options.execute !== 'function') {
|
|
111
|
+
throw new TypeError('A Cloud API execution capability is required');
|
|
112
|
+
}
|
|
113
|
+
const execute = async (request, accessToken) => {
|
|
114
|
+
const body = serializeBody(request);
|
|
115
|
+
const execution = await options.execute({
|
|
116
|
+
functionId,
|
|
117
|
+
body,
|
|
118
|
+
async: false,
|
|
119
|
+
path: buildPath(request.path, request.query),
|
|
120
|
+
method: request.method,
|
|
121
|
+
headers: normalizeRequestHeaders(request.headers, body.length > 0, accessToken),
|
|
122
|
+
});
|
|
123
|
+
if (execution.status !== 'completed') {
|
|
124
|
+
throw new QmuseCloudError('Cloud API Function execution did not complete', 'EXECUTION_NOT_COMPLETED');
|
|
125
|
+
}
|
|
126
|
+
const status = execution.responseStatusCode;
|
|
127
|
+
if (!Number.isInteger(status) || status < 100 || status > 599) {
|
|
128
|
+
throw new QmuseCloudError('Cloud API Function returned an invalid status', 'EXECUTION_STATUS_INVALID');
|
|
129
|
+
}
|
|
130
|
+
const data = parseBody(execution.responseBody);
|
|
131
|
+
if (status < 200 || status >= 300)
|
|
132
|
+
throw readHttpError(status, data);
|
|
133
|
+
return {
|
|
134
|
+
status,
|
|
135
|
+
headers: normalizeResponseHeaders(execution.responseHeaders),
|
|
136
|
+
data: data,
|
|
137
|
+
};
|
|
138
|
+
};
|
|
139
|
+
const auth = options.auth ? createCloudAuth(options.auth, execute) : createUnavailableCloudAuth();
|
|
140
|
+
const authenticatedExecute = async (request) => {
|
|
141
|
+
try {
|
|
142
|
+
return await execute(request, await auth.accessToken());
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
if (!options.auth || !isTransportUnauthorized(error))
|
|
146
|
+
throw error;
|
|
147
|
+
await auth.restore();
|
|
148
|
+
return execute(request, await auth.accessToken());
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
return {
|
|
152
|
+
request: (request) => authenticatedExecute(request),
|
|
153
|
+
auth,
|
|
154
|
+
files: createCloudFiles(authenticatedExecute, options.fileTransport),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare class QmuseCloudError extends Error {
|
|
2
|
+
readonly code: string;
|
|
3
|
+
constructor(message: string, code: string, options?: ErrorOptions);
|
|
4
|
+
}
|
|
5
|
+
export declare class QmuseCloudHttpError extends QmuseCloudError {
|
|
6
|
+
readonly status: number;
|
|
7
|
+
readonly details: unknown;
|
|
8
|
+
constructor(input: {
|
|
9
|
+
status: number;
|
|
10
|
+
code: string;
|
|
11
|
+
message: string;
|
|
12
|
+
details?: unknown;
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAKlE;AAED,qBAAa,mBAAoB,SAAQ,eAAe;IACtD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;gBAEd,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE;CAMxF"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export class QmuseCloudError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
constructor(message, code, options) {
|
|
4
|
+
super(message, options);
|
|
5
|
+
this.name = 'QmuseCloudError';
|
|
6
|
+
this.code = code;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export class QmuseCloudHttpError extends QmuseCloudError {
|
|
10
|
+
status;
|
|
11
|
+
details;
|
|
12
|
+
constructor(input) {
|
|
13
|
+
super(input.message, input.code);
|
|
14
|
+
this.name = 'QmuseCloudHttpError';
|
|
15
|
+
this.status = input.status;
|
|
16
|
+
this.details = input.details;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAC/B,IAAI,CAAS;IAEtB,YAAY,OAAe,EAAE,IAAY,EAAE,OAAsB;QAC/D,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,MAAM,OAAO,mBAAoB,SAAQ,eAAe;IAC7C,MAAM,CAAS;IACf,OAAO,CAAU;IAE1B,YAAY,KAA2E;QACrF,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC3B,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC/B,CAAC;CACF"}
|
package/dist/files.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { CloudFileTransport, CloudRequest, CloudResponse, QmuseCloudFiles } from './types.js';
|
|
2
|
+
type RequestCloud = <T>(request: CloudRequest) => Promise<CloudResponse<T>>;
|
|
3
|
+
export declare function createCloudFiles<FileSource>(request: RequestCloud, transport?: CloudFileTransport<FileSource>): QmuseCloudFiles<FileSource>;
|
|
4
|
+
export {};
|
|
5
|
+
//# sourceMappingURL=files.d.ts.map
|