tiny-oss is a tiny object storage SDK focused on uploading, with a functional API: every operation is a standalone function taking the client options as the first argument. Built-in entries: Aliyun OSS (default tiny-oss), Tencent Cloud COS, Huawei Cloud OBS, Volcano Engine TOS, AWS S3 (plus S3-compatible stores), Azure Blob Storage. Runs in browsers (XHR by default), Node.js/Service Workers (fetch transport) and WeChat mini programs (wx transport).
- Every operation is a factory over a
Protocol(src/protocol.ts).src/ops/holds one file per operation (createPut,createMultipartUpload, …); each entry (src/index.ts,src/cos|obs|tos|aws|azure/index.ts) binds a provider's protocol and exports the operations. - Network layer is injectable:
src/transport.ts(XHR default) +src/transports/(fetch, wx). - Public types live in
src/types.tsas top-level named exports (Options,BlobLike,PutOptions,SignatureUrlOptions, …); entries also exportsetTransport,getTransport,bindOptionsand all those types by name. putSymlinkis exported by the OSS and TOS entries; the Azure entry omitsabortMultipartUpload/listParts/listUploads/uploadPartCopy.
- Each signer must stay byte-identical to its official SDK — the oracle tests (
test/cos|obs|aws-signature.spec.ts,npm run test:azure-oracle) pin them. Never change a signer without those passing. - Entries must stay self-contained: keep provider-specific code in its own directory; shared modules must not reference unused signers (tree shaking depends on it).
- Commands live in
package.json; formatting/lint are handled by.editorconfigand.oxlintrc.json. - Integration specs (
test/*-integration.spec.ts) neednpm run servefirst (Hono server on :8080, credentials from.env); signature/unit specs don't. - Input data is
Blob | ArrayBuffer | Uint8Array | string; mini programs passArrayBuffer.
Conventional commits, and the type drives the user-facing CHANGELOG.md
(changelogen), so it must describe what a package consumer can observe:
feat/fix/perf— reaches users; only for changes to the published package's behaviour.docs— user-facing documentation (README.md,UPGRADING.md).chore(<area>)— repository maintenance no consumer sees: the loop host (scripts/loop/), CI workflows, the norms layer (this file,docs/norms/,skills/), tooling. Name the area:chore(loop),chore(ci),chore(norms).
Never use fix or refactor for maintenance work. Both are rendered in the
CHANGELOG — refactor additionally carries a patch semver — so internal
iteration would read to a user as a change to the package.
- Usage and per-provider options:
README.md; building a custom provider: README "Extension" section andsrc/provider.ts. - Domain docs:
docs/norms/domain.md(CONTEXT/ADR consumption, glossary usage).
This repo is operated by an autonomous loop system. If you are a loop run
(launched by .github/workflows/loop.yml), follow docs/norms/ops.md first.
- Issue tracker: GitHub, via the
ghCLI. Issues and PRs share one tracker and one label system — PRs ARE a triage surface. Seedocs/norms/issue-tracker.md. - Triage labels: five canonical roles —
needs-triage,needs-info,ready-for-agent,ready-for-human,wontfix. Exact semantics:docs/norms/triage-labels.md. - Release: the loop prepares and verifies; a human cuts the release with
pnpm releaseand publishes withpnpm build && pnpm publish. Seedocs/norms/release.md. - Skills:
skills/*/SKILL.md(triage, research, verify, review, sweep, retro) fix how each stage is done. Invoke them perops.md, never skip the opening/closing rituals. - State layer: task state, locks and metrics live in the loop's R2 state bucket
(synced into this checkout's
state/dir for the duration of your run — authoritative JSON +SUMMARY.md). Never keep cross-run state in your context or in comments only. - Norms layer changes (this file,
docs/norms/*,skills/*) are proposals: open a PR, never merge your own change. - You are the maker or the checker, never both for the same change.