@qmuse/cloud-client
v0.0.1-dev.3
Published
Narrow HTTP-style client for the single QMuse Cloud API Function
Downloads
395
Maintainers
Keywords
Readme
@qmuse/cloud-client
Unified Web/PC/mini-program client for QMuse Cloud services. Business APIs use
the single qmuse-cloud-api AppBase Function. File policy uses that Function as
its control plane while large file bytes use a platform-specific Storage data
plane inside this package.
The package intentionally does not expose AppBase clients, Functions, Storage,
TablesDB, endpoint, project ID, database ID, bucket ID, permissions, or a
platform-injection API to business modules. Platform implementations are fixed
by the /web and /miniapp package entry points.
The host initializes one client for the current JavaScript runtime before mounting the application. Web and mini-program hosts may load the public connection config differently while business modules always read the same singleton:
import { getQMuseClient } from '@qmuse/cloud-client';
import { initQMuseCloudClient } from '@qmuse/cloud-client/web';
await initQMuseCloudClient({
config: () => hostRuntime.appwrite,
});
const result = await getQMuseClient().request<{ data: Order }>({
method: 'GET',
path: '/api/orders/order_1',
});initQMuseCloudClient accepts a config object or a sync/async config loader. Calls
with the same normalized endpoint, projectId, and functionId are
idempotent and concurrent calls share the same initialization. Reinitializing
with different connection config is rejected.
Each generated application owns its own AppBase users, Sessions, roles and policies. The AppBase Session is the only application login state. It supplies Function runtime identity headers and Storage permissions; there is no second application access/refresh-token layer.
The selected package entry point supplies the AppBase Account capability. Login receives a
short-lived custom-token secret from the Function and exchanges it immediately;
the secret is never returned from login, persisted, logged or put in business
state.
import { getQMuseClient } from '@qmuse/cloud-client';
const cloudClient = getQMuseClient();
await cloudClient.auth.login({ username, password });
const currentUser = await cloudClient.auth.getCurrentUser();
await cloudClient.auth.logout();
// Or revoke every AppBase Session for this user:
await cloudClient.auth.logoutAll();The mini-program entry can acquire the platform authorization code and complete Alipay login without exposing provider details to business code:
import { initQMuseCloudClient } from '@qmuse/cloud-client/miniapp';
const cloudClient = await initQMuseCloudClient({
config: () => getMuseRuntime().appwrite,
});
await cloudClient.auth.loginWithMiniapp();On Alipay this calls my.getAuthCode({ scopes: ['auth_user'] }), invokes the
dedicated /api/auth/alipay/login Function route, and immediately exchanges the
returned custom token for the normal AppBase Session. A caller that already has
an authorization code may use
loginWithProvider({ provider: 'alipay', authCode }). WeChat remains a reserved
client type and currently fails with AUTH_PROVIDER_NOT_ENABLED before any
Function execution; non-mini-program environments fail with
AUTH_PLATFORM_UNSUPPORTED.
register creates the user without changing the current Session. login
exchanges the custom token internally. Session refresh is single-flight and is
performed before business requests when expiry is within five minutes. Web
hosts use AppBase's secure cookie; mini-program hosts persist AppBase fallback
Session headers in storage scoped by endpoint and project ID.
Business file operations use a logical resource, never a bucket ID:
const attachment = await cloudClient.files.upload({
resource: 'order-attachment',
file,
relation: { orderId },
onProgress: progress => console.log(progress.progress),
});
const preview = await cloudClient.files.createPreview({
fileId: attachment.id,
width: 640,
});
image.src = preview.url;
preview.dispose();The upload flow creates an intent through qmuse-cloud-api, uploads in 5 MiB
chunks through the injected Web or mini-program data-plane transport, then
completes the intent through the Function. Failures issue a best-effort cancel;
the backend must also expire abandoned intents. Preview/download access is
authorized by the Function and may return a short-lived File Token URL or an
authenticated URL that the Web transport converts to a disposable Blob URL.
The client intentionally exposes no file-list API; applications keep the file
IDs they attach to their own business records.
Initialization is available only from platform-specific entry points:
// Web build
import { initQMuseCloudClient } from '@qmuse/cloud-client/web';
await initQMuseCloudClient({
config: () => window.__MUSE__.appwrite,
});
// Taro mini-program build
import { initQMuseCloudClient } from '@qmuse/cloud-client/miniapp';
await initQMuseCloudClient({
config: () => getMuseRuntime().appwrite,
});The Web entry owns the Appwrite Web SDK and secure-cookie Session. The miniapp
entry owns Taro request, upload, storage, file-system and project-isolated
X-Fallback-Cookies Session handling. Both entries include the proven file
mechanics from the legacy @qmuse/appwrite implementation: Web File/Blob, Taro-style local paths, 5 MiB chunks,
Content-Range, X-Appwrite-ID continuation, progress, fallback Session
headers and mini-program temporary-file cleanup. They do not migrate TablesDB
CRUD or the legacy anonymous Role.any() update/delete permissions.
For Web hosts, initialization therefore stays small:
import { initQMuseCloudClient } from '@qmuse/cloud-client/web';
export const cloudClient = await initQMuseCloudClient({
config: () => window.__MUSE__.appwrite,
});functionId is the public physical Function ID assigned by the AppBase project.
It is fixed during initialization and is not supplied by business requests.
New applications should select one platform entry at build time and should not
depend on @qmuse/appwrite or @qmuse/appwrite-runtime-sdk.
Only /api paths and an allowlist of business headers are accepted. The client
uses synchronous Function execution, reads responseStatusCode, responseBody,
and responseHeaders, and maps non-2xx responses to QmuseCloudHttpError.
The client never replays a completed Function response, including a business
401, because replaying a write could duplicate side effects. The host adapter is
responsible for Session coordination and may retry createExecution once only
when the execution API request itself fails with a transport-level 401.
Direct Storage upload is an internal data-plane optimization, not a claim that
the bucket ID is secret on the network or that the protocol can only reach the
Function. Private buckets must be configured so client users can create files
but cannot read/update/delete them directly; reads and deletion are authorized
by the backend. The exact fileSecurity + File Token combination remains a
real AppBase E2E gate before production use.
Development
npm install
npm run ci
npm pack --dry-runPublishing
Set an unpublished semantic version in package.json, authenticate with the
public npm registry, and run:
npm login --registry https://registry.npmjs.org/
npm run publish:publicThe script defaults to the dev dist-tag and also supports latest. Before
publishing it checks the version, npm authentication, duplicate versions, the
full CI command, and package contents, then requires explicit confirmation. It
temporarily normalizes the public package name and registry and restores
package.json when publishing finishes or fails.
