@aurabase/aurabase-js 0.3.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/.changeset/config.json +11 -0
- package/CHANGELOG.md +30 -0
- package/LICENSE +21 -0
- package/README.md +833 -0
- package/package.json +90 -0
- package/packages/ai/LICENSE +21 -0
- package/packages/ai/README.md +106 -0
- package/packages/ai/dist/index.cjs +229 -0
- package/packages/ai/dist/index.d.cts +139 -0
- package/packages/ai/dist/index.d.ts +139 -0
- package/packages/ai/dist/index.js +226 -0
- package/packages/ai/node_modules/.bin/esbuild +19 -0
- package/packages/ai/node_modules/.bin/tsc +22 -0
- package/packages/ai/node_modules/.bin/tsserver +22 -0
- package/packages/ai/node_modules/.bin/tsup +22 -0
- package/packages/ai/node_modules/.bin/tsup-node +22 -0
- package/packages/ai/node_modules/.bin/vite +22 -0
- package/packages/ai/node_modules/.bin/vitest +22 -0
- package/packages/ai/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/packages/ai/package.json +61 -0
- package/packages/ai/src/AiService.ts +226 -0
- package/packages/ai/src/index.ts +18 -0
- package/packages/ai/src/sse.ts +141 -0
- package/packages/ai/src/types.ts +30 -0
- package/packages/ai/tests/chat-stream.test.ts +151 -0
- package/packages/ai/tests/rag-namespaces.test.ts +54 -0
- package/packages/ai/tests/sse.test.ts +69 -0
- package/packages/ai/tsconfig.json +5 -0
- package/packages/ai/tsup.config.ts +11 -0
- package/packages/aurabase/LICENSE +21 -0
- package/packages/aurabase/README.md +64 -0
- package/packages/aurabase/dist/AuraClient-DAtDbfPB.d.cts +77 -0
- package/packages/aurabase/dist/AuraClient-DAtDbfPB.d.ts +77 -0
- package/packages/aurabase/dist/index.cjs +237 -0
- package/packages/aurabase/dist/index.d.cts +46 -0
- package/packages/aurabase/dist/index.d.ts +46 -0
- package/packages/aurabase/dist/index.js +177 -0
- package/packages/aurabase/dist/ssr.cjs +224 -0
- package/packages/aurabase/dist/ssr.d.cts +65 -0
- package/packages/aurabase/dist/ssr.d.ts +65 -0
- package/packages/aurabase/dist/ssr.js +214 -0
- package/packages/aurabase/node_modules/.bin/esbuild +19 -0
- package/packages/aurabase/node_modules/.bin/tsc +22 -0
- package/packages/aurabase/node_modules/.bin/tsserver +22 -0
- package/packages/aurabase/node_modules/.bin/tsup +22 -0
- package/packages/aurabase/node_modules/.bin/tsup-node +22 -0
- package/packages/aurabase/node_modules/.bin/vite +22 -0
- package/packages/aurabase/node_modules/.bin/vitest +22 -0
- package/packages/aurabase/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/packages/aurabase/package.json +80 -0
- package/packages/aurabase/src/AuraClient.ts +237 -0
- package/packages/aurabase/src/index.ts +152 -0
- package/packages/aurabase/src/ssr.ts +156 -0
- package/packages/aurabase/tests/ai-streaming-rag-e2e.test.ts +82 -0
- package/packages/aurabase/tests/ai.test.ts +111 -0
- package/packages/aurabase/tests/auth-admin.test.ts +515 -0
- package/packages/aurabase/tests/auth-e2e.test.ts +135 -0
- package/packages/aurabase/tests/auth-hardening.test.ts +206 -0
- package/packages/aurabase/tests/auth.test.ts +947 -0
- package/packages/aurabase/tests/database.test.ts +230 -0
- package/packages/aurabase/tests/db-types-e2e.test.ts +217 -0
- package/packages/aurabase/tests/dispose.test.ts +23 -0
- package/packages/aurabase/tests/foreign-token.e2e.test.ts +129 -0
- package/packages/aurabase/tests/functions.test.ts +107 -0
- package/packages/aurabase/tests/integration.test.ts +413 -0
- package/packages/aurabase/tests/live-production-validation.js +241 -0
- package/packages/aurabase/tests/live-sdk-production-validation.js +293 -0
- package/packages/aurabase/tests/mocks.ts +139 -0
- package/packages/aurabase/tests/notifications.test.ts +314 -0
- package/packages/aurabase/tests/observability-backup.test.ts +186 -0
- package/packages/aurabase/tests/observability-hook.test.ts +130 -0
- package/packages/aurabase/tests/production-robustness.test.ts +268 -0
- package/packages/aurabase/tests/public-api-surface.test.ts +53 -0
- package/packages/aurabase/tests/query-builder.test.ts +329 -0
- package/packages/aurabase/tests/readme-smoke-e2e.test.ts +231 -0
- package/packages/aurabase/tests/realtime-filter-e2e.test.ts +344 -0
- package/packages/aurabase/tests/refresh-locks.test.ts +210 -0
- package/packages/aurabase/tests/retry-option.test.ts +17 -0
- package/packages/aurabase/tests/rpc-e2e.test.ts +254 -0
- package/packages/aurabase/tests/rs256-local-e2e.test.ts +114 -0
- package/packages/aurabase/tests/rt-alias-public-e2e.test.ts +235 -0
- package/packages/aurabase/tests/rt-http-broadcast-e2e.test.ts +124 -0
- package/packages/aurabase/tests/service-role-guard.test.ts +99 -0
- package/packages/aurabase/tests/ssr.test.ts +91 -0
- package/packages/aurabase/tests/storage-backend-e2e.test.ts +481 -0
- package/packages/aurabase/tests/storage-sdk-parity-e2e.test.ts +104 -0
- package/packages/aurabase/tests/storage-transform-e2e.test.ts +684 -0
- package/packages/aurabase/tests/storage.test.ts +55 -0
- package/packages/aurabase/tests/types/client-generic.test-d.ts +79 -0
- package/packages/aurabase/tests/types/docs-snippets.test-d.ts +571 -0
- package/packages/aurabase/tests/types/error-code.test-d.ts +53 -0
- package/packages/aurabase/tsconfig.json +5 -0
- package/packages/aurabase/tsconfig.test-d.json +5 -0
- package/packages/aurabase/tsup.config.ts +11 -0
- package/packages/aurabase/vitest.config.ts +16 -0
- package/packages/aurabase/vitest.e2e.config.ts +9 -0
- package/packages/auth/LICENSE +21 -0
- package/packages/auth/README.md +215 -0
- package/packages/auth/dist/index.cjs +1175 -0
- package/packages/auth/dist/index.d.cts +397 -0
- package/packages/auth/dist/index.d.ts +397 -0
- package/packages/auth/dist/index.js +1170 -0
- package/packages/auth/node_modules/.bin/esbuild +19 -0
- package/packages/auth/node_modules/.bin/tsc +22 -0
- package/packages/auth/node_modules/.bin/tsserver +22 -0
- package/packages/auth/node_modules/.bin/tsup +22 -0
- package/packages/auth/node_modules/.bin/tsup-node +22 -0
- package/packages/auth/node_modules/.bin/vite +22 -0
- package/packages/auth/node_modules/.bin/vitest +22 -0
- package/packages/auth/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/packages/auth/package.json +61 -0
- package/packages/auth/src/AuthAdminService.ts +149 -0
- package/packages/auth/src/AuthService.ts +1166 -0
- package/packages/auth/src/SessionManager.ts +92 -0
- package/packages/auth/src/index.ts +17 -0
- package/packages/auth/src/jwks.ts +337 -0
- package/packages/auth/src/pkce.ts +27 -0
- package/packages/auth/src/types.ts +89 -0
- package/packages/auth/tests/auth-lifecycle.test.ts +149 -0
- package/packages/auth/tests/detect-session.test.ts +361 -0
- package/packages/auth/tests/getclaims.test.ts +780 -0
- package/packages/auth/tests/is-mfa-challenge.test.ts +27 -0
- package/packages/auth/tests/password-recovery.test.ts +124 -0
- package/packages/auth/tests/pkce.test.ts +192 -0
- package/packages/auth/tests/session-manager.test.ts +103 -0
- package/packages/auth/tests/set-session.test.ts +139 -0
- package/packages/auth/tests/verify-otp.test.ts +153 -0
- package/packages/auth/tsconfig.json +5 -0
- package/packages/auth/tsup.config.ts +11 -0
- package/packages/core/LICENSE +21 -0
- package/packages/core/README.md +132 -0
- package/packages/core/dist/index.cjs +695 -0
- package/packages/core/dist/index.d.cts +1137 -0
- package/packages/core/dist/index.d.ts +1137 -0
- package/packages/core/dist/index.js +673 -0
- package/packages/core/node_modules/.bin/esbuild +22 -0
- package/packages/core/node_modules/.bin/tsc +22 -0
- package/packages/core/node_modules/.bin/tsserver +22 -0
- package/packages/core/node_modules/.bin/tsup +22 -0
- package/packages/core/node_modules/.bin/tsup-node +22 -0
- package/packages/core/node_modules/.bin/vite +22 -0
- package/packages/core/node_modules/.bin/vitest +22 -0
- package/packages/core/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/packages/core/package.json +57 -0
- package/packages/core/src/AuraError.ts +89 -0
- package/packages/core/src/BaseService.ts +44 -0
- package/packages/core/src/client.ts +34 -0
- package/packages/core/src/cookie-utils.ts +42 -0
- package/packages/core/src/fetch.ts +435 -0
- package/packages/core/src/index.ts +22 -0
- package/packages/core/src/retry.ts +63 -0
- package/packages/core/src/serialize.ts +6 -0
- package/packages/core/src/stores/BaseAuthStore.ts +164 -0
- package/packages/core/src/stores/LocalAuthStore.ts +199 -0
- package/packages/core/src/types.ts +1042 -0
- package/packages/core/tests/auth-store.test.ts +300 -0
- package/packages/core/tests/error-code.test.ts +61 -0
- package/packages/core/tests/error.test.ts +24 -0
- package/packages/core/tests/fetch.test.ts +286 -0
- package/packages/core/tests/mocks.ts +139 -0
- package/packages/core/tests/observability.test.ts +86 -0
- package/packages/core/tests/refresh-hardening.test.ts +164 -0
- package/packages/core/tests/refresh-observability.test.ts +111 -0
- package/packages/core/tests/retry.test.ts +106 -0
- package/packages/core/tests/serialize.test.ts +12 -0
- package/packages/core/tests/timeout.test.ts +79 -0
- package/packages/core/tsconfig.json +5 -0
- package/packages/core/tsup.config.ts +11 -0
- package/packages/db/LICENSE +21 -0
- package/packages/db/README.md +152 -0
- package/packages/db/VENDORED.md +93 -0
- package/packages/db/dist/index.cjs +544 -0
- package/packages/db/dist/index.d.cts +1111 -0
- package/packages/db/dist/index.d.ts +1111 -0
- package/packages/db/dist/index.js +541 -0
- package/packages/db/node_modules/.bin/esbuild +19 -0
- package/packages/db/node_modules/.bin/tsc +22 -0
- package/packages/db/node_modules/.bin/tsserver +22 -0
- package/packages/db/node_modules/.bin/tsup +22 -0
- package/packages/db/node_modules/.bin/tsup-node +22 -0
- package/packages/db/node_modules/.bin/vite +22 -0
- package/packages/db/node_modules/.bin/vitest +22 -0
- package/packages/db/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/packages/db/package.json +62 -0
- package/packages/db/src/DatabaseService.ts +170 -0
- package/packages/db/src/QueryBuilder.ts +830 -0
- package/packages/db/src/index.ts +2 -0
- package/packages/db/src/pgrst-types/common/common.ts +86 -0
- package/packages/db/src/pgrst-types/common/rpc.ts +151 -0
- package/packages/db/src/pgrst-types/feature-flags.ts +20 -0
- package/packages/db/src/pgrst-types/types.ts +134 -0
- package/packages/db/src/select-query-parser/parser.ts +479 -0
- package/packages/db/src/select-query-parser/result.ts +553 -0
- package/packages/db/src/select-query-parser/types.ts +132 -0
- package/packages/db/src/select-query-parser/utils.ts +707 -0
- package/packages/db/tests/filters.test.ts +81 -0
- package/packages/db/tests/mutations-filtered.e2e.test.ts +132 -0
- package/packages/db/tests/mutations-filtered.test.ts +188 -0
- package/packages/db/tests/order.test.ts +45 -0
- package/packages/db/tests/rpc.test.ts +41 -0
- package/packages/db/tests/scale/build-large-schema.ts +94 -0
- package/packages/db/tests/scale/scale-compile.test.ts +167 -0
- package/packages/db/tests/schema.test.ts +77 -0
- package/packages/db/tests/single-accept.e2e.test.ts +123 -0
- package/packages/db/tests/single.test.ts +211 -0
- package/packages/db/tests/types/filters.test-d.ts +52 -0
- package/packages/db/tests/types/fixtures.ts +40 -0
- package/packages/db/tests/types/from-views.test-d.ts +18 -0
- package/packages/db/tests/types/mutations.test-d.ts +23 -0
- package/packages/db/tests/types/rpc.test-d.ts +60 -0
- package/packages/db/tests/types/schema-shape.test-d.ts +8 -0
- package/packages/db/tests/types/select-inference.test-d.ts +38 -0
- package/packages/db/tests/vendored/fixtures.ts +83 -0
- package/packages/db/tests/vendored/get-result.test-d.ts +75 -0
- package/packages/db/tsconfig.json +5 -0
- package/packages/db/tsconfig.test-d.json +5 -0
- package/packages/db/tsup.config.ts +11 -0
- package/packages/db/vitest.config.ts +8 -0
- package/packages/functions/LICENSE +21 -0
- package/packages/functions/README.md +96 -0
- package/packages/functions/dist/index.cjs +173 -0
- package/packages/functions/dist/index.d.cts +81 -0
- package/packages/functions/dist/index.d.ts +81 -0
- package/packages/functions/dist/index.js +168 -0
- package/packages/functions/node_modules/.bin/esbuild +19 -0
- package/packages/functions/node_modules/.bin/tsc +22 -0
- package/packages/functions/node_modules/.bin/tsserver +22 -0
- package/packages/functions/node_modules/.bin/tsup +22 -0
- package/packages/functions/node_modules/.bin/tsup-node +22 -0
- package/packages/functions/node_modules/.bin/vite +22 -0
- package/packages/functions/node_modules/.bin/vitest +22 -0
- package/packages/functions/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/packages/functions/package.json +60 -0
- package/packages/functions/src/FunctionsService.ts +188 -0
- package/packages/functions/src/errors.ts +70 -0
- package/packages/functions/src/index.ts +6 -0
- package/packages/functions/tests/invoke.test.ts +97 -0
- package/packages/functions/tests/response-type-errors.test.ts +135 -0
- package/packages/functions/tsconfig.json +5 -0
- package/packages/functions/tsup.config.ts +11 -0
- package/packages/gen/LICENSE +21 -0
- package/packages/gen/README.md +84 -0
- package/packages/gen/dist/cli.cjs +334 -0
- package/packages/gen/dist/cli.d.cts +1 -0
- package/packages/gen/dist/cli.d.ts +1 -0
- package/packages/gen/dist/cli.js +332 -0
- package/packages/gen/dist/index.cjs +257 -0
- package/packages/gen/dist/index.d.cts +12 -0
- package/packages/gen/dist/index.d.ts +12 -0
- package/packages/gen/dist/index.js +255 -0
- package/packages/gen/node_modules/.bin/esbuild +19 -0
- package/packages/gen/node_modules/.bin/tsc +22 -0
- package/packages/gen/node_modules/.bin/tsserver +22 -0
- package/packages/gen/node_modules/.bin/tsup +22 -0
- package/packages/gen/node_modules/.bin/tsup-node +22 -0
- package/packages/gen/node_modules/.bin/vite +22 -0
- package/packages/gen/node_modules/.bin/vitest +22 -0
- package/packages/gen/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/packages/gen/package.json +66 -0
- package/packages/gen/src/cli.ts +67 -0
- package/packages/gen/src/generate.ts +0 -0
- package/packages/gen/src/index.ts +2 -0
- package/packages/gen/tests/compile.test.ts +213 -0
- package/packages/gen/tests/e2e.test.ts +130 -0
- package/packages/gen/tests/generate.test.ts +396 -0
- package/packages/gen/tsconfig.json +5 -0
- package/packages/gen/tsup.config.ts +11 -0
- package/packages/notifications/LICENSE +21 -0
- package/packages/notifications/README.md +134 -0
- package/packages/notifications/dist/index.cjs +128 -0
- package/packages/notifications/dist/index.d.cts +81 -0
- package/packages/notifications/dist/index.d.ts +81 -0
- package/packages/notifications/dist/index.js +125 -0
- package/packages/notifications/node_modules/.bin/esbuild +19 -0
- package/packages/notifications/node_modules/.bin/tsc +22 -0
- package/packages/notifications/node_modules/.bin/tsserver +22 -0
- package/packages/notifications/node_modules/.bin/tsup +22 -0
- package/packages/notifications/node_modules/.bin/tsup-node +22 -0
- package/packages/notifications/node_modules/.bin/vite +22 -0
- package/packages/notifications/node_modules/.bin/vitest +22 -0
- package/packages/notifications/package.json +60 -0
- package/packages/notifications/src/NotificationsService.ts +230 -0
- package/packages/notifications/src/index.ts +19 -0
- package/packages/notifications/tsconfig.json +5 -0
- package/packages/notifications/tsup.config.ts +11 -0
- package/packages/realtime/LICENSE +21 -0
- package/packages/realtime/README.md +183 -0
- package/packages/realtime/dist/index.cjs +977 -0
- package/packages/realtime/dist/index.d.cts +259 -0
- package/packages/realtime/dist/index.d.ts +259 -0
- package/packages/realtime/dist/index.js +973 -0
- package/packages/realtime/node_modules/.bin/esbuild +19 -0
- package/packages/realtime/node_modules/.bin/tsc +22 -0
- package/packages/realtime/node_modules/.bin/tsserver +22 -0
- package/packages/realtime/node_modules/.bin/tsup +22 -0
- package/packages/realtime/node_modules/.bin/tsup-node +22 -0
- package/packages/realtime/node_modules/.bin/vite +22 -0
- package/packages/realtime/node_modules/.bin/vitest +22 -0
- package/packages/realtime/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/packages/realtime/package.json +60 -0
- package/packages/realtime/src/AuraChannel.ts +485 -0
- package/packages/realtime/src/HeartbeatManager.ts +73 -0
- package/packages/realtime/src/RealtimeService.ts +505 -0
- package/packages/realtime/src/columnFilter.ts +301 -0
- package/packages/realtime/src/index.ts +4 -0
- package/packages/realtime/tests/ack-routing.test.ts +81 -0
- package/packages/realtime/tests/column-filter.test.ts +144 -0
- package/packages/realtime/tests/dispatch.test.ts +191 -0
- package/packages/realtime/tests/heartbeat.test.ts +67 -0
- package/packages/realtime/tests/http-broadcast.test.ts +68 -0
- package/packages/realtime/tests/realtime-token.test.ts +43 -0
- package/packages/realtime/tests/reconnect-race.test.ts +149 -0
- package/packages/realtime/tests/ref-id.test.ts +34 -0
- package/packages/realtime/tests/set-auth.test.ts +70 -0
- package/packages/realtime/tsconfig.json +5 -0
- package/packages/realtime/tsup.config.ts +11 -0
- package/packages/storage/LICENSE +21 -0
- package/packages/storage/README.md +141 -0
- package/packages/storage/dist/index.cjs +333 -0
- package/packages/storage/dist/index.d.cts +185 -0
- package/packages/storage/dist/index.d.ts +185 -0
- package/packages/storage/dist/index.js +329 -0
- package/packages/storage/node_modules/.bin/esbuild +19 -0
- package/packages/storage/node_modules/.bin/tsc +22 -0
- package/packages/storage/node_modules/.bin/tsserver +22 -0
- package/packages/storage/node_modules/.bin/tsup +22 -0
- package/packages/storage/node_modules/.bin/tsup-node +22 -0
- package/packages/storage/node_modules/.bin/vite +22 -0
- package/packages/storage/node_modules/.bin/vitest +22 -0
- package/packages/storage/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/packages/storage/package.json +60 -0
- package/packages/storage/src/DownloadBuilder.ts +60 -0
- package/packages/storage/src/StorageService.ts +323 -0
- package/packages/storage/src/index.ts +2 -0
- package/packages/storage/src/path.ts +35 -0
- package/packages/storage/src/transform.ts +15 -0
- package/packages/storage/tests/download.test.ts +64 -0
- package/packages/storage/tests/parity.test.ts +154 -0
- package/packages/storage/tests/path.test.ts +87 -0
- package/packages/storage/tests/transform.test.ts +79 -0
- package/packages/storage/tsconfig.json +5 -0
- package/packages/storage/tsup.config.ts +11 -0
- package/pnpm-workspace.yaml +24 -0
- package/tsconfig.base.json +15 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# @aurabase/storage
|
|
2
|
+
|
|
3
|
+
Service de stockage objet du SDK Aurabase : buckets, upload/download, copie/déplacement intra-bucket et URLs signées.
|
|
4
|
+
|
|
5
|
+
 
|
|
6
|
+
|
|
7
|
+
> Pre-release — pas encore publié sur npm.
|
|
8
|
+
|
|
9
|
+
Fait partie du SDK **[aurabase](../aurabase)**. Installé automatiquement avec `aurabase` ; ce package est publié séparément pour un usage ciblé / tree-shaking.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm i @aurabase/storage
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
> Dépend de `@aurabase/core`. Déjà inclus si vous utilisez le package `aurabase` — cette installation ciblée sert à composer votre propre client ou à limiter la taille du bundle.
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
`StorageService` est exposé par le client principal sous `aura.storage`.
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { createClient } from 'aurabase'
|
|
25
|
+
|
|
26
|
+
const aura = createClient('http://localhost:8080', 'my-project', 'aura_anon_xxx')
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Buckets
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
const buckets = await aura.storage.listBuckets()
|
|
33
|
+
|
|
34
|
+
await aura.storage.createBucket('avatars', {
|
|
35
|
+
public: true,
|
|
36
|
+
fileSizeLimit: 5 * 1024 * 1024,
|
|
37
|
+
allowedMimeTypes: ['image/png', 'image/jpeg'],
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
const bucket = await aura.storage.getBucket('avatars')
|
|
41
|
+
await aura.storage.deleteBucket('avatars')
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Upload, liste, métadonnées
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
declare const file: File
|
|
48
|
+
|
|
49
|
+
// Le serveur génère la clé (`<uuid>.<ext>`) — réutilisez data.key directement pour download/remove/copy/move.
|
|
50
|
+
const { data } = await aura.storage.upload('avatars', 'photo.png', file, {
|
|
51
|
+
contentType: 'image/png',
|
|
52
|
+
upsert: true,
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
const files = await aura.storage.list('avatars', { prefix: 'users/', limit: 100 })
|
|
56
|
+
|
|
57
|
+
const metadata = await aura.storage.getMetadata('avatars', data!.key)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Download — builder paresseux
|
|
61
|
+
|
|
62
|
+
`download()` ne fait pas de requête tant qu'il n'est pas `await`é ; par défaut il résout un `Blob`. `.asStream()` bascule sur un `ReadableStream`.
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
// Déclenche le fetch et résout { data: Blob, error }
|
|
66
|
+
const { data: blob } = await aura.storage.download('avatars', 'photo.png')
|
|
67
|
+
|
|
68
|
+
// Variante flux : { data: ReadableStream<Uint8Array>, error }
|
|
69
|
+
const { data: stream } = await aura.storage.download('avatars', 'photo.png').asStream()
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Copie, déplacement, suppression (intra-bucket)
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
await aura.storage.copy('avatars', 'photo.png', 'archive/photo.png')
|
|
76
|
+
await aura.storage.move('avatars', 'archive/photo.png', 'photo.png')
|
|
77
|
+
await aura.storage.remove('avatars', ['photo.png'])
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### URLs signées et URL publique
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
const signedDownload = await aura.storage.createSignedUrl('avatars', 'photo.png', 600)
|
|
84
|
+
const signedUpload = await aura.storage.createSignedUploadUrl('avatars', 'photo.png', 300)
|
|
85
|
+
|
|
86
|
+
// Attention : cette URL EXIGE quand même une clé API — voir Limitations.
|
|
87
|
+
const url = aura.storage.getPublicUrl('avatars', 'photo.png')
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Transformations d'image
|
|
91
|
+
|
|
92
|
+
`getPublicUrl()`, `download()` et `createSignedUrl()` acceptent une option `{ transform: ImageTransform }` qui déclenche un rendu à la volée côté backend (redimensionnement, recadrage, ré-encodage) :
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
// Redimensionnement + recadrage (fit "cover").
|
|
96
|
+
const thumbnail = aura.storage.getPublicUrl('avatars', 'photo.png', {
|
|
97
|
+
transform: { width: 200, resize: 'cover' },
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
// Download d'un dérivé redimensionné, qualité JPEG réduite.
|
|
101
|
+
const { data: blob } = await aura.storage.download('avatars', 'photo.png', {
|
|
102
|
+
transform: { width: 800, height: 300, quality: 75 },
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
// URL signée pointant vers un dérivé WebP.
|
|
106
|
+
const signed = await aura.storage.createSignedUrl('avatars', 'photo.png', 600, {
|
|
107
|
+
transform: { width: 200, format: 'webp' },
|
|
108
|
+
})
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
`ImageTransform` (`@aurabase/core`) :
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
interface ImageTransform {
|
|
115
|
+
width?: number
|
|
116
|
+
height?: number
|
|
117
|
+
resize?: 'cover' | 'contain' | 'fill'
|
|
118
|
+
quality?: number
|
|
119
|
+
format?: 'origin' | 'jpeg' | 'png' | 'webp' | 'gif'
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
À savoir avant d'activer les transforms en production :
|
|
124
|
+
|
|
125
|
+
- **Flag projet** : le rendu est **activé par défaut** ; un projet peut le **désactiver** via le paramètre `img_transform_enabled`. Sur un projet où il est désactivé, toute requête avec `transform` échoue en `403` (`image_transform_disabled`).
|
|
126
|
+
- **`quality` ne s'applique qu'au JPEG** : la bibliothèque de rendu backend actuelle ne propose pas d'encodeur WebP *lossy* paramétrable (le WebP produit est *lossless*) ; `quality` est silencieusement ignoré pour `webp`/`png`/`gif` (pas d'erreur).
|
|
127
|
+
- **Borne de dimension** : `width`/`height` sont plafonnés à 2500px côté backend. Au-delà, la requête échoue en `400` (`image_transform_dimension_too_large`).
|
|
128
|
+
- **Cache serveur des dérivés** : chaque combinaison `(fichier, params de transform)` est rendue une fois puis mise en cache côté serveur. La réponse porte un header `x-aura-cache: HIT` (dérivé servi depuis le cache) ou `MISS` (rendu effectué à cette requête) — présent uniquement sur les réponses avec `transform` (ou `Range`), pas sur un download brut sans transform.
|
|
129
|
+
- **Invalidation = limite connue** : le cache des dérivés est purgé seulement lors d'une **suppression définitive** de l'original (purge permanente côté backend). Un **overwrite** (`upload(..., { upsert: true })`) sur la même clé ne purge PAS les dérivés déjà en cache : d'anciens dérivés peuvent continuer à être servis après un upsert tant qu'aucune suppression définitive n'a eu lieu entretemps.
|
|
130
|
+
|
|
131
|
+
## Limitations
|
|
132
|
+
|
|
133
|
+
- Pas d'upload résumable / protocole TUS ; `upload()` fait un envoi `multipart/form-data` unique.
|
|
134
|
+
- Pas de `updateBucket()` ni de `emptyBucket()`.
|
|
135
|
+
- `copy()`/`move()` sont **intra-bucket uniquement** (pas de copie/déplacement entre deux buckets différents).
|
|
136
|
+
- Options d'upload limitées à `contentType` et `upsert` (pas de métadonnées personnalisées ni de cache-control).
|
|
137
|
+
- **`getPublicUrl()` ne rend pas le fichier accessible sans authentification** : le gateway exige une clé API (`apikey`/`x-api-key`) sur toutes les routes storage, y compris pour un bucket créé avec `public: true`. Pour un accès partageable sans clé API, utilisez `createSignedUrl()`.
|
|
138
|
+
|
|
139
|
+
## Documentation
|
|
140
|
+
|
|
141
|
+
Référence complète du SDK (tous les services, types partagés, SSR) : [README racine](../../README.md).
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@aurabase/core');
|
|
4
|
+
|
|
5
|
+
// src/StorageService.ts
|
|
6
|
+
async function runDownload(fn, extract) {
|
|
7
|
+
let res;
|
|
8
|
+
try {
|
|
9
|
+
res = await fn();
|
|
10
|
+
} catch (err) {
|
|
11
|
+
return {
|
|
12
|
+
data: null,
|
|
13
|
+
error: new core.AuraError(0, { error: { code: "network_error", message: err instanceof Error ? err.message : "Download failed" } })
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
if (!res.ok) return { data: null, error: new core.AuraError(res.status) };
|
|
17
|
+
return { data: await extract(res), error: null };
|
|
18
|
+
}
|
|
19
|
+
var BlobDownloadBuilder = class {
|
|
20
|
+
constructor(_fn) {
|
|
21
|
+
this._fn = _fn;
|
|
22
|
+
}
|
|
23
|
+
_fn;
|
|
24
|
+
_promise = null;
|
|
25
|
+
asStream() {
|
|
26
|
+
return new StreamDownloadBuilder(this._fn);
|
|
27
|
+
}
|
|
28
|
+
_run() {
|
|
29
|
+
if (!this._promise) this._promise = runDownload(this._fn, (r) => r.blob());
|
|
30
|
+
return this._promise;
|
|
31
|
+
}
|
|
32
|
+
then(onfulfilled, onrejected) {
|
|
33
|
+
return this._run().then(onfulfilled, onrejected);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
var StreamDownloadBuilder = class {
|
|
37
|
+
constructor(_fn) {
|
|
38
|
+
this._fn = _fn;
|
|
39
|
+
}
|
|
40
|
+
_fn;
|
|
41
|
+
_promise = null;
|
|
42
|
+
_run() {
|
|
43
|
+
if (!this._promise) {
|
|
44
|
+
this._promise = runDownload(this._fn, (r) => r.body);
|
|
45
|
+
}
|
|
46
|
+
return this._promise;
|
|
47
|
+
}
|
|
48
|
+
then(onfulfilled, onrejected) {
|
|
49
|
+
return this._run().then(onfulfilled, onrejected);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
function encodeObjectPath(path) {
|
|
53
|
+
const trimmed = path.replace(/^\/+/, "");
|
|
54
|
+
const segments = trimmed.split("/");
|
|
55
|
+
for (const seg of segments) {
|
|
56
|
+
if (seg === "..") {
|
|
57
|
+
throw new core.AuraError(0, {
|
|
58
|
+
error: {
|
|
59
|
+
code: "invalid_path",
|
|
60
|
+
message: 'Path traversal ("..") is not allowed in storage object paths'
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return segments.map((s) => encodeURIComponent(s)).join("/");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// src/transform.ts
|
|
69
|
+
function renderTransformParams(t) {
|
|
70
|
+
const p = new URLSearchParams();
|
|
71
|
+
if (Number.isFinite(t.width)) p.set("width", String(Math.max(1, Math.floor(t.width))));
|
|
72
|
+
if (Number.isFinite(t.height)) p.set("height", String(Math.max(1, Math.floor(t.height))));
|
|
73
|
+
if (t.resize) p.set("fit", t.resize);
|
|
74
|
+
if (Number.isFinite(t.quality)) p.set("quality", String(Math.min(100, Math.max(20, Math.floor(t.quality)))));
|
|
75
|
+
if (t.format && t.format !== "origin") p.set("format", t.format);
|
|
76
|
+
return p;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// src/StorageService.ts
|
|
80
|
+
var StorageService = class extends core.BaseService {
|
|
81
|
+
constructor(client) {
|
|
82
|
+
super(client);
|
|
83
|
+
}
|
|
84
|
+
get prefix() {
|
|
85
|
+
return `/v1/storage/${this.client.projectId}`;
|
|
86
|
+
}
|
|
87
|
+
// -- Buckets ----------------------------------------------------------------
|
|
88
|
+
async listBuckets() {
|
|
89
|
+
return this.request("GET", `${this.prefix}/buckets`);
|
|
90
|
+
}
|
|
91
|
+
async getBucket(id) {
|
|
92
|
+
return this.request("GET", `${this.prefix}/buckets/${id}`);
|
|
93
|
+
}
|
|
94
|
+
async createBucket(name, options) {
|
|
95
|
+
return this.request("POST", `${this.prefix}/buckets`, {
|
|
96
|
+
name,
|
|
97
|
+
public: options?.public ?? false,
|
|
98
|
+
file_size_limit: options?.fileSizeLimit,
|
|
99
|
+
allowed_mime_types: options?.allowedMimeTypes
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Met à jour un bucket existant (mise à jour PARTIELLE : seuls les champs
|
|
104
|
+
* fournis sont envoyés). Mapping identique à `createBucket`
|
|
105
|
+
* (`public`/`file_size_limit`/`allowed_mime_types`).
|
|
106
|
+
*
|
|
107
|
+
* Backend route: PATCH /v1/storage/{project_id}/buckets/{id}
|
|
108
|
+
*/
|
|
109
|
+
async updateBucket(id, options) {
|
|
110
|
+
const body = {};
|
|
111
|
+
if (options?.public !== void 0) body.public = options.public;
|
|
112
|
+
if (options?.fileSizeLimit !== void 0) body.file_size_limit = options.fileSizeLimit;
|
|
113
|
+
if (options?.allowedMimeTypes !== void 0) body.allowed_mime_types = options.allowedMimeTypes;
|
|
114
|
+
return this.request("PATCH", `${this.prefix}/buckets/${id}`, body);
|
|
115
|
+
}
|
|
116
|
+
async deleteBucket(id) {
|
|
117
|
+
return this.request("DELETE", `${this.prefix}/buckets/${id}`);
|
|
118
|
+
}
|
|
119
|
+
// -- Objects ----------------------------------------------------------------
|
|
120
|
+
/**
|
|
121
|
+
* Upload a file to a bucket.
|
|
122
|
+
*
|
|
123
|
+
* Le serveur génère une clé unique `<uuid>.<ext>` (relative au bucket).
|
|
124
|
+
* Réutilisez directement `data.key` pour download(), remove(), copy(), etc.
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* const { data } = await client.storage.upload('avatars', 'photo.png', file)
|
|
128
|
+
* await client.storage.download('avatars', data!.key) // fonctionne directement
|
|
129
|
+
*
|
|
130
|
+
* Backend route: POST /v1/storage/{project_id}/{bucket}
|
|
131
|
+
*/
|
|
132
|
+
async upload(bucketId, path, file, options) {
|
|
133
|
+
const formData = new FormData();
|
|
134
|
+
const blob = file instanceof Blob ? file : new Blob([file], { type: options?.contentType ?? "application/octet-stream" });
|
|
135
|
+
formData.append("file", blob, path);
|
|
136
|
+
if (options?.upsert) formData.append("upsert", "true");
|
|
137
|
+
if (options?.metadata) {
|
|
138
|
+
for (const [k, v] of Object.entries(options.metadata)) formData.append(k, v);
|
|
139
|
+
}
|
|
140
|
+
return this.request("POST", `${this.prefix}/${bucketId}`, formData);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Download paresseux d'un fichier. Renvoie un builder (Blob par défaut, `.asStream()` pour
|
|
144
|
+
* le flux) ; la requête part à l'`await`. Refresh proactif du token avant la requête.
|
|
145
|
+
* `options?.transform` (image) : appende `renderTransformParams(...)` à l'URL — figée à
|
|
146
|
+
* l'appel, le builder reste inchangé.
|
|
147
|
+
* Backend route: GET /v1/storage/{project_id}/{bucket}/{*key}
|
|
148
|
+
*/
|
|
149
|
+
download(bucketId, path, options) {
|
|
150
|
+
let url = this.url(`${this.prefix}/${encodeURIComponent(bucketId)}/${encodeObjectPath(path)}`);
|
|
151
|
+
if (options?.transform) {
|
|
152
|
+
const qs = renderTransformParams(options.transform).toString();
|
|
153
|
+
if (qs) url = `${url}?${qs}`;
|
|
154
|
+
}
|
|
155
|
+
const client = this.client;
|
|
156
|
+
const downloadFn = async () => {
|
|
157
|
+
const store = client.authStore;
|
|
158
|
+
if (store.token && store.refreshToken && core.isTokenExpired(store.token, 30)) {
|
|
159
|
+
await core.refreshOnce(client);
|
|
160
|
+
}
|
|
161
|
+
const headers = {};
|
|
162
|
+
if (store.token) headers["Authorization"] = `Bearer ${store.token}`;
|
|
163
|
+
if (client.apiKey) headers["apikey"] = client.apiKey;
|
|
164
|
+
return client.fetchFn(url, { headers });
|
|
165
|
+
};
|
|
166
|
+
return new BlobDownloadBuilder(downloadFn);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* List files in a bucket.
|
|
170
|
+
*
|
|
171
|
+
* ⚠️ `offset` n'est PAS supporté par le backend (`ListQuery` ne connaît que
|
|
172
|
+
* `prefix`+`limit`) : le paramètre est accepté pour compatibilité ascendante
|
|
173
|
+
* mais IGNORÉ (jamais envoyé au serveur). Pour restreindre les résultats,
|
|
174
|
+
* utilisez `prefix`. La vraie pagination (continuation token) relève du backend.
|
|
175
|
+
*
|
|
176
|
+
* Backend route: GET /v1/storage/{project_id}/{bucket}
|
|
177
|
+
*/
|
|
178
|
+
async list(bucketId, options) {
|
|
179
|
+
const params = new URLSearchParams();
|
|
180
|
+
if (options?.prefix) params.set("prefix", options.prefix);
|
|
181
|
+
if (options?.limit !== void 0) params.set("limit", String(options.limit));
|
|
182
|
+
const qs = params.toString();
|
|
183
|
+
const sep = qs ? "?" : "";
|
|
184
|
+
return this.request("GET", `${this.prefix}/${bucketId}${sep}${qs}`);
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Delete one or more files from a bucket.
|
|
188
|
+
* Backend route: DELETE /v1/storage/{project_id}/{bucket}/{*key}
|
|
189
|
+
* Note: for single file deletion, paths[0] is used. Multi-delete is done in sequence.
|
|
190
|
+
*/
|
|
191
|
+
async remove(bucketId, paths) {
|
|
192
|
+
let keys;
|
|
193
|
+
try {
|
|
194
|
+
keys = paths.map((p) => encodeObjectPath(p));
|
|
195
|
+
} catch (e) {
|
|
196
|
+
return { data: null, error: e };
|
|
197
|
+
}
|
|
198
|
+
const b = encodeURIComponent(bucketId);
|
|
199
|
+
if (keys.length === 1) {
|
|
200
|
+
return this.request("DELETE", `${this.prefix}/${b}/${keys[0]}`);
|
|
201
|
+
}
|
|
202
|
+
const results = await Promise.all(
|
|
203
|
+
keys.map((k) => this.request("DELETE", `${this.prefix}/${b}/${k}`))
|
|
204
|
+
);
|
|
205
|
+
const failed = results.find((r) => r.error);
|
|
206
|
+
if (failed) return failed;
|
|
207
|
+
return { data: null, error: null };
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Copy a file within a bucket.
|
|
211
|
+
*
|
|
212
|
+
* `fromPath`/`toPath` sont relatifs au bucket (cohérent avec `download`/
|
|
213
|
+
* `remove`/`upload`) — le SDK les préfixe par `bucketId` pour produire les
|
|
214
|
+
* clés MinIO complètes attendues par le backend.
|
|
215
|
+
*
|
|
216
|
+
* Backend route: POST /v1/storage/{project_id}/{bucket}/copy
|
|
217
|
+
*/
|
|
218
|
+
async copy(bucketId, fromPath, toPath) {
|
|
219
|
+
return this.request("POST", `${this.prefix}/${bucketId}/copy`, {
|
|
220
|
+
src_key: `${bucketId}/${fromPath}`,
|
|
221
|
+
dst_key: `${bucketId}/${toPath}`
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Move/rename a file within a bucket.
|
|
226
|
+
*
|
|
227
|
+
* `fromPath`/`toPath` sont relatifs au bucket (cohérent avec `download`/
|
|
228
|
+
* `remove`/`upload`) — le SDK les préfixe par `bucketId` pour produire les
|
|
229
|
+
* clés MinIO complètes attendues par le backend.
|
|
230
|
+
*
|
|
231
|
+
* Backend route: POST /v1/storage/{project_id}/{bucket}/move
|
|
232
|
+
*/
|
|
233
|
+
async move(bucketId, fromPath, toPath) {
|
|
234
|
+
return this.request("POST", `${this.prefix}/${bucketId}/move`, {
|
|
235
|
+
src_key: `${bucketId}/${fromPath}`,
|
|
236
|
+
dst_key: `${bucketId}/${toPath}`
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Get file metadata.
|
|
241
|
+
* Backend route: GET /v1/storage/{project_id}/{bucket}/meta/{*key}
|
|
242
|
+
*/
|
|
243
|
+
async getMetadata(bucketId, path) {
|
|
244
|
+
let key;
|
|
245
|
+
try {
|
|
246
|
+
key = encodeObjectPath(path);
|
|
247
|
+
} catch (e) {
|
|
248
|
+
return { data: null, error: e };
|
|
249
|
+
}
|
|
250
|
+
return this.request("GET", `${this.prefix}/${encodeURIComponent(bucketId)}/meta/${key}`);
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Generate a signed (temporary) download URL.
|
|
254
|
+
*
|
|
255
|
+
* `options?.transform` (image) : dérisqué en réel (stack live) — les params transform
|
|
256
|
+
* sont HORS HMAC (le backend ne les couvre pas dans la signature), donc on les appende
|
|
257
|
+
* à l'URL signée APRÈS réception de `{ url, expires_in }`, sans toucher à la requête
|
|
258
|
+
* `signed-url` elle-même.
|
|
259
|
+
* Backend route: GET /v1/storage/{project_id}/{bucket}/signed-url?key=...&ttl_secs=...
|
|
260
|
+
*/
|
|
261
|
+
async createSignedUrl(bucketId, path, expiresInSeconds = 3600, options) {
|
|
262
|
+
const params = new URLSearchParams({ key: path, ttl_secs: String(expiresInSeconds) });
|
|
263
|
+
const res = await this.request(
|
|
264
|
+
"GET",
|
|
265
|
+
`${this.prefix}/${bucketId}/signed-url?${params.toString()}`
|
|
266
|
+
);
|
|
267
|
+
if (res.data && options?.transform) {
|
|
268
|
+
const qs = renderTransformParams(options.transform).toString();
|
|
269
|
+
if (qs) {
|
|
270
|
+
const sep = res.data.url.includes("?") ? "&" : "?";
|
|
271
|
+
res.data = { ...res.data, url: `${res.data.url}${sep}${qs}` };
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return res;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Génère plusieurs URLs signées en une passe (batch).
|
|
278
|
+
*
|
|
279
|
+
* Il n'existe pas d'endpoint batch côté backend : l'implémentation fait un
|
|
280
|
+
* fan-out `Promise.all` sur `createSignedUrl` (même patron que `remove()`),
|
|
281
|
+
* RÉSILIENT PAR-ITEM — chaque entrée est soit `{ path, url, expires_in }`
|
|
282
|
+
* (succès), soit `{ path, error }` (échec), sans faire échouer les autres.
|
|
283
|
+
*
|
|
284
|
+
* @example
|
|
285
|
+
* const { data } = await client.storage.createSignedUrls('avatars', ['a.png', 'b.png'])
|
|
286
|
+
* data?.forEach((r) => 'url' in r ? use(r.url) : console.warn(r.path, r.error))
|
|
287
|
+
*/
|
|
288
|
+
async createSignedUrls(bucketId, paths, expiresInSeconds = 3600, options) {
|
|
289
|
+
const results = await Promise.all(
|
|
290
|
+
paths.map(async (path) => {
|
|
291
|
+
const res = await this.createSignedUrl(bucketId, path, expiresInSeconds, options);
|
|
292
|
+
if (res.error || !res.data) {
|
|
293
|
+
return { path, error: res.error ?? new core.AuraError(0, { error: { code: "unknown", message: "No data" } }) };
|
|
294
|
+
}
|
|
295
|
+
return { path, url: res.data.url, expires_in: res.data.expires_in };
|
|
296
|
+
})
|
|
297
|
+
);
|
|
298
|
+
return { data: results, error: null };
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Generate a signed upload URL (presigned POST/PUT).
|
|
302
|
+
* Backend route: GET /v1/storage/{project_id}/{bucket}/upload-url?key=...&ttl_secs=...
|
|
303
|
+
*/
|
|
304
|
+
async createSignedUploadUrl(bucketId, path, expiresInSeconds = 3600) {
|
|
305
|
+
const params = new URLSearchParams({ key: path, ttl_secs: String(expiresInSeconds) });
|
|
306
|
+
return this.request("GET", `${this.prefix}/${bucketId}/upload-url?${params.toString()}`);
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Construit une URL vers un fichier d'un bucket.
|
|
310
|
+
*
|
|
311
|
+
* ⚠️ Cette URL N'EST PAS accessible sans authentification : le gateway exige
|
|
312
|
+
* une clé API (`apikey`/`x-api-key`) sur toutes les routes storage, y compris
|
|
313
|
+
* pour les buckets créés avec `public: true` (ce flag n'est actuellement pas
|
|
314
|
+
* vérifié côté gateway — une requête non authentifiée renvoie 401). Pour
|
|
315
|
+
* partager un fichier sans authentification, utilisez `createSignedUrl()`,
|
|
316
|
+
* qui génère une URL signée HMAC vérifiée côté serveur sans clé API.
|
|
317
|
+
*
|
|
318
|
+
* `options?.transform` (image) : appende `renderTransformParams(...)` en query string.
|
|
319
|
+
* Backend route: GET /v1/storage/{project_id}/{bucket}/{*key} (clé API requise)
|
|
320
|
+
*/
|
|
321
|
+
getPublicUrl(bucketId, path, options) {
|
|
322
|
+
const base = this.url(`${this.prefix}/${encodeURIComponent(bucketId)}/${encodeObjectPath(path)}`);
|
|
323
|
+
if (options?.transform) {
|
|
324
|
+
const qs = renderTransformParams(options.transform).toString();
|
|
325
|
+
if (qs) return `${base}?${qs}`;
|
|
326
|
+
}
|
|
327
|
+
return base;
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
exports.BlobDownloadBuilder = BlobDownloadBuilder;
|
|
332
|
+
exports.StorageService = StorageService;
|
|
333
|
+
exports.StreamDownloadBuilder = StreamDownloadBuilder;
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { AuraResponse, BaseService, AuraClientLike, StorageBucket, UploadResult, ImageTransform, FileEntry, ObjectMeta, AuraError } from '@aurabase/core';
|
|
2
|
+
|
|
3
|
+
type DownloadFn = () => Promise<Response>;
|
|
4
|
+
/** Download paresseux (Blob par défaut). La requête ne part qu'à l'await ; résultat mémoïsé. */
|
|
5
|
+
declare class BlobDownloadBuilder implements PromiseLike<AuraResponse<Blob>> {
|
|
6
|
+
private readonly _fn;
|
|
7
|
+
private _promise;
|
|
8
|
+
constructor(_fn: DownloadFn);
|
|
9
|
+
asStream(): StreamDownloadBuilder;
|
|
10
|
+
private _run;
|
|
11
|
+
then<TR1 = AuraResponse<Blob>, TR2 = never>(onfulfilled?: ((v: AuraResponse<Blob>) => TR1 | PromiseLike<TR1>) | null, onrejected?: ((e: unknown) => TR2 | PromiseLike<TR2>) | null): Promise<TR1 | TR2>;
|
|
12
|
+
}
|
|
13
|
+
/** Variante flux — `res.body` (ReadableStream). */
|
|
14
|
+
declare class StreamDownloadBuilder implements PromiseLike<AuraResponse<ReadableStream<Uint8Array>>> {
|
|
15
|
+
private readonly _fn;
|
|
16
|
+
private _promise;
|
|
17
|
+
constructor(_fn: DownloadFn);
|
|
18
|
+
private _run;
|
|
19
|
+
then<TR1 = AuraResponse<ReadableStream<Uint8Array>>, TR2 = never>(onfulfilled?: ((v: AuraResponse<ReadableStream<Uint8Array>>) => TR1 | PromiseLike<TR1>) | null, onrejected?: ((e: unknown) => TR2 | PromiseLike<TR2>) | null): Promise<TR1 | TR2>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
declare class StorageService extends BaseService {
|
|
23
|
+
constructor(client: AuraClientLike);
|
|
24
|
+
private get prefix();
|
|
25
|
+
listBuckets(): Promise<AuraResponse<StorageBucket[]>>;
|
|
26
|
+
getBucket(id: string): Promise<AuraResponse<StorageBucket>>;
|
|
27
|
+
createBucket(name: string, options?: {
|
|
28
|
+
public?: boolean;
|
|
29
|
+
fileSizeLimit?: number;
|
|
30
|
+
allowedMimeTypes?: string[];
|
|
31
|
+
}): Promise<AuraResponse<StorageBucket>>;
|
|
32
|
+
/**
|
|
33
|
+
* Met à jour un bucket existant (mise à jour PARTIELLE : seuls les champs
|
|
34
|
+
* fournis sont envoyés). Mapping identique à `createBucket`
|
|
35
|
+
* (`public`/`file_size_limit`/`allowed_mime_types`).
|
|
36
|
+
*
|
|
37
|
+
* Backend route: PATCH /v1/storage/{project_id}/buckets/{id}
|
|
38
|
+
*/
|
|
39
|
+
updateBucket(id: string, options?: {
|
|
40
|
+
public?: boolean;
|
|
41
|
+
fileSizeLimit?: number;
|
|
42
|
+
allowedMimeTypes?: string[];
|
|
43
|
+
}): Promise<AuraResponse<StorageBucket>>;
|
|
44
|
+
deleteBucket(id: string): Promise<AuraResponse<null>>;
|
|
45
|
+
/**
|
|
46
|
+
* Upload a file to a bucket.
|
|
47
|
+
*
|
|
48
|
+
* Le serveur génère une clé unique `<uuid>.<ext>` (relative au bucket).
|
|
49
|
+
* Réutilisez directement `data.key` pour download(), remove(), copy(), etc.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* const { data } = await client.storage.upload('avatars', 'photo.png', file)
|
|
53
|
+
* await client.storage.download('avatars', data!.key) // fonctionne directement
|
|
54
|
+
*
|
|
55
|
+
* Backend route: POST /v1/storage/{project_id}/{bucket}
|
|
56
|
+
*/
|
|
57
|
+
upload(bucketId: string, path: string, file: Blob | File | ArrayBuffer, options?: {
|
|
58
|
+
contentType?: string;
|
|
59
|
+
upsert?: boolean;
|
|
60
|
+
metadata?: Record<string, string>;
|
|
61
|
+
}): Promise<AuraResponse<UploadResult>>;
|
|
62
|
+
/**
|
|
63
|
+
* Download paresseux d'un fichier. Renvoie un builder (Blob par défaut, `.asStream()` pour
|
|
64
|
+
* le flux) ; la requête part à l'`await`. Refresh proactif du token avant la requête.
|
|
65
|
+
* `options?.transform` (image) : appende `renderTransformParams(...)` à l'URL — figée à
|
|
66
|
+
* l'appel, le builder reste inchangé.
|
|
67
|
+
* Backend route: GET /v1/storage/{project_id}/{bucket}/{*key}
|
|
68
|
+
*/
|
|
69
|
+
download(bucketId: string, path: string, options?: {
|
|
70
|
+
transform?: ImageTransform;
|
|
71
|
+
}): BlobDownloadBuilder;
|
|
72
|
+
/**
|
|
73
|
+
* List files in a bucket.
|
|
74
|
+
*
|
|
75
|
+
* ⚠️ `offset` n'est PAS supporté par le backend (`ListQuery` ne connaît que
|
|
76
|
+
* `prefix`+`limit`) : le paramètre est accepté pour compatibilité ascendante
|
|
77
|
+
* mais IGNORÉ (jamais envoyé au serveur). Pour restreindre les résultats,
|
|
78
|
+
* utilisez `prefix`. La vraie pagination (continuation token) relève du backend.
|
|
79
|
+
*
|
|
80
|
+
* Backend route: GET /v1/storage/{project_id}/{bucket}
|
|
81
|
+
*/
|
|
82
|
+
list(bucketId: string, options?: {
|
|
83
|
+
prefix?: string;
|
|
84
|
+
limit?: number;
|
|
85
|
+
offset?: number;
|
|
86
|
+
}): Promise<AuraResponse<FileEntry[]>>;
|
|
87
|
+
/**
|
|
88
|
+
* Delete one or more files from a bucket.
|
|
89
|
+
* Backend route: DELETE /v1/storage/{project_id}/{bucket}/{*key}
|
|
90
|
+
* Note: for single file deletion, paths[0] is used. Multi-delete is done in sequence.
|
|
91
|
+
*/
|
|
92
|
+
remove(bucketId: string, paths: string[]): Promise<AuraResponse<null>>;
|
|
93
|
+
/**
|
|
94
|
+
* Copy a file within a bucket.
|
|
95
|
+
*
|
|
96
|
+
* `fromPath`/`toPath` sont relatifs au bucket (cohérent avec `download`/
|
|
97
|
+
* `remove`/`upload`) — le SDK les préfixe par `bucketId` pour produire les
|
|
98
|
+
* clés MinIO complètes attendues par le backend.
|
|
99
|
+
*
|
|
100
|
+
* Backend route: POST /v1/storage/{project_id}/{bucket}/copy
|
|
101
|
+
*/
|
|
102
|
+
copy(bucketId: string, fromPath: string, toPath: string): Promise<AuraResponse<{
|
|
103
|
+
key: string;
|
|
104
|
+
}>>;
|
|
105
|
+
/**
|
|
106
|
+
* Move/rename a file within a bucket.
|
|
107
|
+
*
|
|
108
|
+
* `fromPath`/`toPath` sont relatifs au bucket (cohérent avec `download`/
|
|
109
|
+
* `remove`/`upload`) — le SDK les préfixe par `bucketId` pour produire les
|
|
110
|
+
* clés MinIO complètes attendues par le backend.
|
|
111
|
+
*
|
|
112
|
+
* Backend route: POST /v1/storage/{project_id}/{bucket}/move
|
|
113
|
+
*/
|
|
114
|
+
move(bucketId: string, fromPath: string, toPath: string): Promise<AuraResponse<{
|
|
115
|
+
key: string;
|
|
116
|
+
}>>;
|
|
117
|
+
/**
|
|
118
|
+
* Get file metadata.
|
|
119
|
+
* Backend route: GET /v1/storage/{project_id}/{bucket}/meta/{*key}
|
|
120
|
+
*/
|
|
121
|
+
getMetadata(bucketId: string, path: string): Promise<AuraResponse<ObjectMeta>>;
|
|
122
|
+
/**
|
|
123
|
+
* Generate a signed (temporary) download URL.
|
|
124
|
+
*
|
|
125
|
+
* `options?.transform` (image) : dérisqué en réel (stack live) — les params transform
|
|
126
|
+
* sont HORS HMAC (le backend ne les couvre pas dans la signature), donc on les appende
|
|
127
|
+
* à l'URL signée APRÈS réception de `{ url, expires_in }`, sans toucher à la requête
|
|
128
|
+
* `signed-url` elle-même.
|
|
129
|
+
* Backend route: GET /v1/storage/{project_id}/{bucket}/signed-url?key=...&ttl_secs=...
|
|
130
|
+
*/
|
|
131
|
+
createSignedUrl(bucketId: string, path: string, expiresInSeconds?: number, options?: {
|
|
132
|
+
transform?: ImageTransform;
|
|
133
|
+
}): Promise<AuraResponse<{
|
|
134
|
+
url: string;
|
|
135
|
+
expires_in: number;
|
|
136
|
+
}>>;
|
|
137
|
+
/**
|
|
138
|
+
* Génère plusieurs URLs signées en une passe (batch).
|
|
139
|
+
*
|
|
140
|
+
* Il n'existe pas d'endpoint batch côté backend : l'implémentation fait un
|
|
141
|
+
* fan-out `Promise.all` sur `createSignedUrl` (même patron que `remove()`),
|
|
142
|
+
* RÉSILIENT PAR-ITEM — chaque entrée est soit `{ path, url, expires_in }`
|
|
143
|
+
* (succès), soit `{ path, error }` (échec), sans faire échouer les autres.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* const { data } = await client.storage.createSignedUrls('avatars', ['a.png', 'b.png'])
|
|
147
|
+
* data?.forEach((r) => 'url' in r ? use(r.url) : console.warn(r.path, r.error))
|
|
148
|
+
*/
|
|
149
|
+
createSignedUrls(bucketId: string, paths: string[], expiresInSeconds?: number, options?: {
|
|
150
|
+
transform?: ImageTransform;
|
|
151
|
+
}): Promise<AuraResponse<Array<{
|
|
152
|
+
path: string;
|
|
153
|
+
url: string;
|
|
154
|
+
expires_in: number;
|
|
155
|
+
} | {
|
|
156
|
+
path: string;
|
|
157
|
+
error: AuraError;
|
|
158
|
+
}>>>;
|
|
159
|
+
/**
|
|
160
|
+
* Generate a signed upload URL (presigned POST/PUT).
|
|
161
|
+
* Backend route: GET /v1/storage/{project_id}/{bucket}/upload-url?key=...&ttl_secs=...
|
|
162
|
+
*/
|
|
163
|
+
createSignedUploadUrl(bucketId: string, path: string, expiresInSeconds?: number): Promise<AuraResponse<{
|
|
164
|
+
url: string;
|
|
165
|
+
expires_in: number;
|
|
166
|
+
}>>;
|
|
167
|
+
/**
|
|
168
|
+
* Construit une URL vers un fichier d'un bucket.
|
|
169
|
+
*
|
|
170
|
+
* ⚠️ Cette URL N'EST PAS accessible sans authentification : le gateway exige
|
|
171
|
+
* une clé API (`apikey`/`x-api-key`) sur toutes les routes storage, y compris
|
|
172
|
+
* pour les buckets créés avec `public: true` (ce flag n'est actuellement pas
|
|
173
|
+
* vérifié côté gateway — une requête non authentifiée renvoie 401). Pour
|
|
174
|
+
* partager un fichier sans authentification, utilisez `createSignedUrl()`,
|
|
175
|
+
* qui génère une URL signée HMAC vérifiée côté serveur sans clé API.
|
|
176
|
+
*
|
|
177
|
+
* `options?.transform` (image) : appende `renderTransformParams(...)` en query string.
|
|
178
|
+
* Backend route: GET /v1/storage/{project_id}/{bucket}/{*key} (clé API requise)
|
|
179
|
+
*/
|
|
180
|
+
getPublicUrl(bucketId: string, path: string, options?: {
|
|
181
|
+
transform?: ImageTransform;
|
|
182
|
+
}): string;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export { BlobDownloadBuilder, StorageService, StreamDownloadBuilder };
|