npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@qmuse/cloud-client

v0.0.1-dev.3

Published

Narrow HTTP-style client for the single QMuse Cloud API Function

Downloads

395

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-run

Publishing

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:public

The 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.