@aurabase/aurabase-js 0.3.0 → 0.3.1
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/package.json +4 -4
- package/packages/ai/node_modules/.bin/esbuild +0 -19
- package/packages/ai/node_modules/.bin/tsc +0 -22
- package/packages/ai/node_modules/.bin/tsserver +0 -22
- package/packages/ai/node_modules/.bin/tsup +0 -22
- package/packages/ai/node_modules/.bin/tsup-node +0 -22
- package/packages/ai/node_modules/.bin/vite +0 -22
- package/packages/ai/node_modules/.bin/vitest +0 -22
- package/packages/ai/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
- package/packages/ai/src/AiService.ts +0 -226
- package/packages/ai/src/index.ts +0 -18
- package/packages/ai/src/sse.ts +0 -141
- package/packages/ai/src/types.ts +0 -30
- package/packages/ai/tests/chat-stream.test.ts +0 -151
- package/packages/ai/tests/rag-namespaces.test.ts +0 -54
- package/packages/ai/tests/sse.test.ts +0 -69
- package/packages/ai/tsconfig.json +0 -5
- package/packages/ai/tsup.config.ts +0 -11
- package/packages/aurabase/node_modules/.bin/esbuild +0 -19
- package/packages/aurabase/node_modules/.bin/tsc +0 -22
- package/packages/aurabase/node_modules/.bin/tsserver +0 -22
- package/packages/aurabase/node_modules/.bin/tsup +0 -22
- package/packages/aurabase/node_modules/.bin/tsup-node +0 -22
- package/packages/aurabase/node_modules/.bin/vite +0 -22
- package/packages/aurabase/node_modules/.bin/vitest +0 -22
- package/packages/aurabase/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
- package/packages/aurabase/src/AuraClient.ts +0 -237
- package/packages/aurabase/src/index.ts +0 -152
- package/packages/aurabase/src/ssr.ts +0 -156
- package/packages/aurabase/tests/ai-streaming-rag-e2e.test.ts +0 -82
- package/packages/aurabase/tests/ai.test.ts +0 -111
- package/packages/aurabase/tests/auth-admin.test.ts +0 -515
- package/packages/aurabase/tests/auth-e2e.test.ts +0 -135
- package/packages/aurabase/tests/auth-hardening.test.ts +0 -206
- package/packages/aurabase/tests/auth.test.ts +0 -947
- package/packages/aurabase/tests/database.test.ts +0 -230
- package/packages/aurabase/tests/db-types-e2e.test.ts +0 -217
- package/packages/aurabase/tests/dispose.test.ts +0 -23
- package/packages/aurabase/tests/foreign-token.e2e.test.ts +0 -129
- package/packages/aurabase/tests/functions.test.ts +0 -107
- package/packages/aurabase/tests/integration.test.ts +0 -413
- package/packages/aurabase/tests/live-production-validation.js +0 -241
- package/packages/aurabase/tests/live-sdk-production-validation.js +0 -293
- package/packages/aurabase/tests/mocks.ts +0 -139
- package/packages/aurabase/tests/notifications.test.ts +0 -314
- package/packages/aurabase/tests/observability-backup.test.ts +0 -186
- package/packages/aurabase/tests/observability-hook.test.ts +0 -130
- package/packages/aurabase/tests/production-robustness.test.ts +0 -268
- package/packages/aurabase/tests/public-api-surface.test.ts +0 -53
- package/packages/aurabase/tests/query-builder.test.ts +0 -329
- package/packages/aurabase/tests/readme-smoke-e2e.test.ts +0 -231
- package/packages/aurabase/tests/realtime-filter-e2e.test.ts +0 -344
- package/packages/aurabase/tests/refresh-locks.test.ts +0 -210
- package/packages/aurabase/tests/retry-option.test.ts +0 -17
- package/packages/aurabase/tests/rpc-e2e.test.ts +0 -254
- package/packages/aurabase/tests/rs256-local-e2e.test.ts +0 -114
- package/packages/aurabase/tests/rt-alias-public-e2e.test.ts +0 -235
- package/packages/aurabase/tests/rt-http-broadcast-e2e.test.ts +0 -124
- package/packages/aurabase/tests/service-role-guard.test.ts +0 -99
- package/packages/aurabase/tests/ssr.test.ts +0 -91
- package/packages/aurabase/tests/storage-backend-e2e.test.ts +0 -481
- package/packages/aurabase/tests/storage-sdk-parity-e2e.test.ts +0 -104
- package/packages/aurabase/tests/storage-transform-e2e.test.ts +0 -684
- package/packages/aurabase/tests/storage.test.ts +0 -55
- package/packages/aurabase/tests/types/client-generic.test-d.ts +0 -79
- package/packages/aurabase/tests/types/docs-snippets.test-d.ts +0 -571
- package/packages/aurabase/tests/types/error-code.test-d.ts +0 -53
- package/packages/aurabase/tsconfig.json +0 -5
- package/packages/aurabase/tsconfig.test-d.json +0 -5
- package/packages/aurabase/tsup.config.ts +0 -11
- package/packages/aurabase/vitest.config.ts +0 -16
- package/packages/auth/node_modules/.bin/esbuild +0 -19
- package/packages/auth/node_modules/.bin/tsc +0 -22
- package/packages/auth/node_modules/.bin/tsserver +0 -22
- package/packages/auth/node_modules/.bin/tsup +0 -22
- package/packages/auth/node_modules/.bin/tsup-node +0 -22
- package/packages/auth/node_modules/.bin/vite +0 -22
- package/packages/auth/node_modules/.bin/vitest +0 -22
- package/packages/auth/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
- package/packages/auth/src/AuthAdminService.ts +0 -149
- package/packages/auth/src/AuthService.ts +0 -1166
- package/packages/auth/src/SessionManager.ts +0 -92
- package/packages/auth/src/index.ts +0 -17
- package/packages/auth/src/jwks.ts +0 -337
- package/packages/auth/src/pkce.ts +0 -27
- package/packages/auth/src/types.ts +0 -89
- package/packages/auth/tests/auth-lifecycle.test.ts +0 -149
- package/packages/auth/tests/detect-session.test.ts +0 -361
- package/packages/auth/tests/getclaims.test.ts +0 -780
- package/packages/auth/tests/is-mfa-challenge.test.ts +0 -27
- package/packages/auth/tests/password-recovery.test.ts +0 -124
- package/packages/auth/tests/pkce.test.ts +0 -192
- package/packages/auth/tests/session-manager.test.ts +0 -103
- package/packages/auth/tests/set-session.test.ts +0 -139
- package/packages/auth/tests/verify-otp.test.ts +0 -153
- package/packages/auth/tsconfig.json +0 -5
- package/packages/auth/tsup.config.ts +0 -11
- package/packages/core/node_modules/.bin/esbuild +0 -22
- package/packages/core/node_modules/.bin/tsc +0 -22
- package/packages/core/node_modules/.bin/tsserver +0 -22
- package/packages/core/node_modules/.bin/tsup +0 -22
- package/packages/core/node_modules/.bin/tsup-node +0 -22
- package/packages/core/node_modules/.bin/vite +0 -22
- package/packages/core/node_modules/.bin/vitest +0 -22
- package/packages/core/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
- package/packages/core/src/AuraError.ts +0 -89
- package/packages/core/src/BaseService.ts +0 -44
- package/packages/core/src/client.ts +0 -34
- package/packages/core/src/cookie-utils.ts +0 -42
- package/packages/core/src/fetch.ts +0 -435
- package/packages/core/src/index.ts +0 -22
- package/packages/core/src/retry.ts +0 -63
- package/packages/core/src/serialize.ts +0 -6
- package/packages/core/src/stores/BaseAuthStore.ts +0 -164
- package/packages/core/src/stores/LocalAuthStore.ts +0 -199
- package/packages/core/src/types.ts +0 -1042
- package/packages/core/tests/auth-store.test.ts +0 -300
- package/packages/core/tests/error-code.test.ts +0 -61
- package/packages/core/tests/error.test.ts +0 -24
- package/packages/core/tests/fetch.test.ts +0 -286
- package/packages/core/tests/mocks.ts +0 -139
- package/packages/core/tests/observability.test.ts +0 -86
- package/packages/core/tests/refresh-hardening.test.ts +0 -164
- package/packages/core/tests/refresh-observability.test.ts +0 -111
- package/packages/core/tests/retry.test.ts +0 -106
- package/packages/core/tests/serialize.test.ts +0 -12
- package/packages/core/tests/timeout.test.ts +0 -79
- package/packages/core/tsconfig.json +0 -5
- package/packages/core/tsup.config.ts +0 -11
- package/packages/db/node_modules/.bin/esbuild +0 -19
- package/packages/db/node_modules/.bin/tsc +0 -22
- package/packages/db/node_modules/.bin/tsserver +0 -22
- package/packages/db/node_modules/.bin/tsup +0 -22
- package/packages/db/node_modules/.bin/tsup-node +0 -22
- package/packages/db/node_modules/.bin/vite +0 -22
- package/packages/db/node_modules/.bin/vitest +0 -22
- package/packages/db/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
- package/packages/db/src/DatabaseService.ts +0 -170
- package/packages/db/src/QueryBuilder.ts +0 -830
- package/packages/db/src/index.ts +0 -2
- package/packages/db/src/pgrst-types/common/common.ts +0 -86
- package/packages/db/src/pgrst-types/common/rpc.ts +0 -151
- package/packages/db/src/pgrst-types/feature-flags.ts +0 -20
- package/packages/db/src/pgrst-types/types.ts +0 -134
- package/packages/db/src/select-query-parser/parser.ts +0 -479
- package/packages/db/src/select-query-parser/result.ts +0 -553
- package/packages/db/src/select-query-parser/types.ts +0 -132
- package/packages/db/src/select-query-parser/utils.ts +0 -707
- package/packages/db/tests/filters.test.ts +0 -81
- package/packages/db/tests/mutations-filtered.e2e.test.ts +0 -132
- package/packages/db/tests/mutations-filtered.test.ts +0 -188
- package/packages/db/tests/order.test.ts +0 -45
- package/packages/db/tests/rpc.test.ts +0 -41
- package/packages/db/tests/scale/build-large-schema.ts +0 -94
- package/packages/db/tests/scale/scale-compile.test.ts +0 -167
- package/packages/db/tests/schema.test.ts +0 -77
- package/packages/db/tests/single-accept.e2e.test.ts +0 -123
- package/packages/db/tests/single.test.ts +0 -211
- package/packages/db/tests/types/filters.test-d.ts +0 -52
- package/packages/db/tests/types/fixtures.ts +0 -40
- package/packages/db/tests/types/from-views.test-d.ts +0 -18
- package/packages/db/tests/types/mutations.test-d.ts +0 -23
- package/packages/db/tests/types/rpc.test-d.ts +0 -60
- package/packages/db/tests/types/schema-shape.test-d.ts +0 -8
- package/packages/db/tests/types/select-inference.test-d.ts +0 -38
- package/packages/db/tests/vendored/fixtures.ts +0 -83
- package/packages/db/tests/vendored/get-result.test-d.ts +0 -75
- package/packages/db/tsconfig.json +0 -5
- package/packages/db/tsconfig.test-d.json +0 -5
- package/packages/db/tsup.config.ts +0 -11
- package/packages/db/vitest.config.ts +0 -8
- package/packages/functions/node_modules/.bin/esbuild +0 -19
- package/packages/functions/node_modules/.bin/tsc +0 -22
- package/packages/functions/node_modules/.bin/tsserver +0 -22
- package/packages/functions/node_modules/.bin/tsup +0 -22
- package/packages/functions/node_modules/.bin/tsup-node +0 -22
- package/packages/functions/node_modules/.bin/vite +0 -22
- package/packages/functions/node_modules/.bin/vitest +0 -22
- package/packages/functions/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
- package/packages/functions/src/FunctionsService.ts +0 -188
- package/packages/functions/src/errors.ts +0 -70
- package/packages/functions/src/index.ts +0 -6
- package/packages/functions/tests/invoke.test.ts +0 -97
- package/packages/functions/tests/response-type-errors.test.ts +0 -135
- package/packages/functions/tsconfig.json +0 -5
- package/packages/functions/tsup.config.ts +0 -11
- package/packages/gen/node_modules/.bin/esbuild +0 -19
- package/packages/gen/node_modules/.bin/tsc +0 -22
- package/packages/gen/node_modules/.bin/tsserver +0 -22
- package/packages/gen/node_modules/.bin/tsup +0 -22
- package/packages/gen/node_modules/.bin/tsup-node +0 -22
- package/packages/gen/node_modules/.bin/vite +0 -22
- package/packages/gen/node_modules/.bin/vitest +0 -22
- package/packages/gen/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
- package/packages/gen/src/cli.ts +0 -67
- package/packages/gen/src/generate.ts +0 -0
- package/packages/gen/src/index.ts +0 -2
- package/packages/gen/tests/compile.test.ts +0 -213
- package/packages/gen/tests/e2e.test.ts +0 -130
- package/packages/gen/tests/generate.test.ts +0 -396
- package/packages/gen/tsconfig.json +0 -5
- package/packages/gen/tsup.config.ts +0 -11
- package/packages/notifications/node_modules/.bin/esbuild +0 -19
- package/packages/notifications/node_modules/.bin/tsc +0 -22
- package/packages/notifications/node_modules/.bin/tsserver +0 -22
- package/packages/notifications/node_modules/.bin/tsup +0 -22
- package/packages/notifications/node_modules/.bin/tsup-node +0 -22
- package/packages/notifications/node_modules/.bin/vite +0 -22
- package/packages/notifications/node_modules/.bin/vitest +0 -22
- package/packages/notifications/src/NotificationsService.ts +0 -230
- package/packages/notifications/src/index.ts +0 -19
- package/packages/notifications/tsconfig.json +0 -5
- package/packages/notifications/tsup.config.ts +0 -11
- package/packages/realtime/node_modules/.bin/esbuild +0 -19
- package/packages/realtime/node_modules/.bin/tsc +0 -22
- package/packages/realtime/node_modules/.bin/tsserver +0 -22
- package/packages/realtime/node_modules/.bin/tsup +0 -22
- package/packages/realtime/node_modules/.bin/tsup-node +0 -22
- package/packages/realtime/node_modules/.bin/vite +0 -22
- package/packages/realtime/node_modules/.bin/vitest +0 -22
- package/packages/realtime/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
- package/packages/realtime/src/AuraChannel.ts +0 -485
- package/packages/realtime/src/HeartbeatManager.ts +0 -73
- package/packages/realtime/src/RealtimeService.ts +0 -505
- package/packages/realtime/src/columnFilter.ts +0 -301
- package/packages/realtime/src/index.ts +0 -4
- package/packages/realtime/tests/ack-routing.test.ts +0 -81
- package/packages/realtime/tests/column-filter.test.ts +0 -144
- package/packages/realtime/tests/dispatch.test.ts +0 -191
- package/packages/realtime/tests/heartbeat.test.ts +0 -67
- package/packages/realtime/tests/http-broadcast.test.ts +0 -68
- package/packages/realtime/tests/realtime-token.test.ts +0 -43
- package/packages/realtime/tests/reconnect-race.test.ts +0 -149
- package/packages/realtime/tests/ref-id.test.ts +0 -34
- package/packages/realtime/tests/set-auth.test.ts +0 -70
- package/packages/realtime/tsconfig.json +0 -5
- package/packages/realtime/tsup.config.ts +0 -11
- package/packages/storage/node_modules/.bin/esbuild +0 -19
- package/packages/storage/node_modules/.bin/tsc +0 -22
- package/packages/storage/node_modules/.bin/tsserver +0 -22
- package/packages/storage/node_modules/.bin/tsup +0 -22
- package/packages/storage/node_modules/.bin/tsup-node +0 -22
- package/packages/storage/node_modules/.bin/vite +0 -22
- package/packages/storage/node_modules/.bin/vitest +0 -22
- package/packages/storage/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
- package/packages/storage/src/DownloadBuilder.ts +0 -60
- package/packages/storage/src/StorageService.ts +0 -323
- package/packages/storage/src/index.ts +0 -2
- package/packages/storage/src/path.ts +0 -35
- package/packages/storage/src/transform.ts +0 -15
- package/packages/storage/tests/download.test.ts +0 -64
- package/packages/storage/tests/parity.test.ts +0 -154
- package/packages/storage/tests/path.test.ts +0 -87
- package/packages/storage/tests/transform.test.ts +0 -79
- package/packages/storage/tsconfig.json +0 -5
- package/packages/storage/tsup.config.ts +0 -11
- package/pnpm-workspace.yaml +0 -24
- package/tsconfig.base.json +0 -15
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
#!/bin/sh
|
|
2
|
-
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
3
|
-
|
|
4
|
-
case `uname` in
|
|
5
|
-
*CYGWIN*|*MINGW*|*MSYS*)
|
|
6
|
-
if command -v cygpath > /dev/null 2>&1; then
|
|
7
|
-
basedir=`cygpath -w "$basedir"`
|
|
8
|
-
fi
|
|
9
|
-
;;
|
|
10
|
-
esac
|
|
11
|
-
|
|
12
|
-
if [ -z "$NODE_PATH" ]; then
|
|
13
|
-
export NODE_PATH="/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/typescript@5.9.3/node_modules:/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/node_modules"
|
|
14
|
-
else
|
|
15
|
-
export NODE_PATH="/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/typescript@5.9.3/node_modules:/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
16
|
-
fi
|
|
17
|
-
if [ -x "$basedir/node" ]; then
|
|
18
|
-
exec "$basedir/node" "$basedir/../typescript/bin/tsserver" "$@"
|
|
19
|
-
else
|
|
20
|
-
exec node "$basedir/../typescript/bin/tsserver" "$@"
|
|
21
|
-
fi
|
|
22
|
-
# cmd-shim-target=/Users/affanedaylami/aurabase/aurabase-js/packages/storage/node_modules/typescript/bin/tsserver
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
#!/bin/sh
|
|
2
|
-
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
3
|
-
|
|
4
|
-
case `uname` in
|
|
5
|
-
*CYGWIN*|*MINGW*|*MSYS*)
|
|
6
|
-
if command -v cygpath > /dev/null 2>&1; then
|
|
7
|
-
basedir=`cygpath -w "$basedir"`
|
|
8
|
-
fi
|
|
9
|
-
;;
|
|
10
|
-
esac
|
|
11
|
-
|
|
12
|
-
if [ -z "$NODE_PATH" ]; then
|
|
13
|
-
export NODE_PATH="/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/tsup@8.5.1_postcss@8.5.16_typescript@5.9.3/node_modules/tsup/node_modules:/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/tsup@8.5.1_postcss@8.5.16_typescript@5.9.3/node_modules:/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/node_modules"
|
|
14
|
-
else
|
|
15
|
-
export NODE_PATH="/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/tsup@8.5.1_postcss@8.5.16_typescript@5.9.3/node_modules/tsup/node_modules:/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/tsup@8.5.1_postcss@8.5.16_typescript@5.9.3/node_modules:/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
16
|
-
fi
|
|
17
|
-
if [ -x "$basedir/node" ]; then
|
|
18
|
-
exec "$basedir/node" "$basedir/../tsup/dist/cli-default.js" "$@"
|
|
19
|
-
else
|
|
20
|
-
exec node "$basedir/../tsup/dist/cli-default.js" "$@"
|
|
21
|
-
fi
|
|
22
|
-
# cmd-shim-target=/Users/affanedaylami/aurabase/aurabase-js/packages/storage/node_modules/tsup/dist/cli-default.js
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
#!/bin/sh
|
|
2
|
-
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
3
|
-
|
|
4
|
-
case `uname` in
|
|
5
|
-
*CYGWIN*|*MINGW*|*MSYS*)
|
|
6
|
-
if command -v cygpath > /dev/null 2>&1; then
|
|
7
|
-
basedir=`cygpath -w "$basedir"`
|
|
8
|
-
fi
|
|
9
|
-
;;
|
|
10
|
-
esac
|
|
11
|
-
|
|
12
|
-
if [ -z "$NODE_PATH" ]; then
|
|
13
|
-
export NODE_PATH="/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/tsup@8.5.1_postcss@8.5.16_typescript@5.9.3/node_modules/tsup/node_modules:/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/tsup@8.5.1_postcss@8.5.16_typescript@5.9.3/node_modules:/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/node_modules"
|
|
14
|
-
else
|
|
15
|
-
export NODE_PATH="/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/tsup@8.5.1_postcss@8.5.16_typescript@5.9.3/node_modules/tsup/node_modules:/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/tsup@8.5.1_postcss@8.5.16_typescript@5.9.3/node_modules:/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
16
|
-
fi
|
|
17
|
-
if [ -x "$basedir/node" ]; then
|
|
18
|
-
exec "$basedir/node" "$basedir/../tsup/dist/cli-node.js" "$@"
|
|
19
|
-
else
|
|
20
|
-
exec node "$basedir/../tsup/dist/cli-node.js" "$@"
|
|
21
|
-
fi
|
|
22
|
-
# cmd-shim-target=/Users/affanedaylami/aurabase/aurabase-js/packages/storage/node_modules/tsup/dist/cli-node.js
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
#!/bin/sh
|
|
2
|
-
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
3
|
-
|
|
4
|
-
case `uname` in
|
|
5
|
-
*CYGWIN*|*MINGW*|*MSYS*)
|
|
6
|
-
if command -v cygpath > /dev/null 2>&1; then
|
|
7
|
-
basedir=`cygpath -w "$basedir"`
|
|
8
|
-
fi
|
|
9
|
-
;;
|
|
10
|
-
esac
|
|
11
|
-
|
|
12
|
-
if [ -z "$NODE_PATH" ]; then
|
|
13
|
-
export NODE_PATH="/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/vite@8.1.3_@types+node@20.14.15_esbuild@0.27.7/node_modules/vite/node_modules:/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/vite@8.1.3_@types+node@20.14.15_esbuild@0.27.7/node_modules:/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/node_modules"
|
|
14
|
-
else
|
|
15
|
-
export NODE_PATH="/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/vite@8.1.3_@types+node@20.14.15_esbuild@0.27.7/node_modules/vite/node_modules:/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/vite@8.1.3_@types+node@20.14.15_esbuild@0.27.7/node_modules:/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
16
|
-
fi
|
|
17
|
-
if [ -x "$basedir/node" ]; then
|
|
18
|
-
exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/vite@8.1.3_@types+node@20.14.15_esbuild@0.27.7/node_modules/vite/bin/vite.js" "$@"
|
|
19
|
-
else
|
|
20
|
-
exec node "$basedir/../../../../node_modules/.pnpm/vite@8.1.3_@types+node@20.14.15_esbuild@0.27.7/node_modules/vite/bin/vite.js" "$@"
|
|
21
|
-
fi
|
|
22
|
-
# cmd-shim-target=/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/vite@8.1.3_@types+node@20.14.15_esbuild@0.27.7/node_modules/vite/bin/vite.js
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
#!/bin/sh
|
|
2
|
-
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
3
|
-
|
|
4
|
-
case `uname` in
|
|
5
|
-
*CYGWIN*|*MINGW*|*MSYS*)
|
|
6
|
-
if command -v cygpath > /dev/null 2>&1; then
|
|
7
|
-
basedir=`cygpath -w "$basedir"`
|
|
8
|
-
fi
|
|
9
|
-
;;
|
|
10
|
-
esac
|
|
11
|
-
|
|
12
|
-
if [ -z "$NODE_PATH" ]; then
|
|
13
|
-
export NODE_PATH="/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/vitest@4.1.9_@types+node@20.14.15_vite@8.1.3_@types+node@20.14.15_esbuild@0.27.7_/node_modules/vitest/node_modules:/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/vitest@4.1.9_@types+node@20.14.15_vite@8.1.3_@types+node@20.14.15_esbuild@0.27.7_/node_modules:/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/node_modules"
|
|
14
|
-
else
|
|
15
|
-
export NODE_PATH="/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/vitest@4.1.9_@types+node@20.14.15_vite@8.1.3_@types+node@20.14.15_esbuild@0.27.7_/node_modules/vitest/node_modules:/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/vitest@4.1.9_@types+node@20.14.15_vite@8.1.3_@types+node@20.14.15_esbuild@0.27.7_/node_modules:/Users/affanedaylami/aurabase/aurabase-js/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
16
|
-
fi
|
|
17
|
-
if [ -x "$basedir/node" ]; then
|
|
18
|
-
exec "$basedir/node" "$basedir/../vitest/vitest.mjs" "$@"
|
|
19
|
-
else
|
|
20
|
-
exec node "$basedir/../vitest/vitest.mjs" "$@"
|
|
21
|
-
fi
|
|
22
|
-
# cmd-shim-target=/Users/affanedaylami/aurabase/aurabase-js/packages/storage/node_modules/vitest/vitest.mjs
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":"4.1.9","results":[[":tests/download.test.ts",{"duration":383.5393750000003,"failed":false}],[":tests/path.test.ts",{"duration":285.0919170000002,"failed":false}],[":tests/transform.test.ts",{"duration":522.0009580000005,"failed":false}],[":tests/parity.test.ts",{"duration":719.0756669999996,"failed":false}]]}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { AuraError } from '@aurabase/core'
|
|
2
|
-
import type { AuraResponse } from '@aurabase/core'
|
|
3
|
-
|
|
4
|
-
type DownloadFn = () => Promise<Response>
|
|
5
|
-
|
|
6
|
-
async function runDownload<T>(fn: DownloadFn, extract: (r: Response) => T | Promise<T>): Promise<AuraResponse<T>> {
|
|
7
|
-
let res: Response
|
|
8
|
-
try {
|
|
9
|
-
res = await fn()
|
|
10
|
-
} catch (err) {
|
|
11
|
-
return {
|
|
12
|
-
data: null,
|
|
13
|
-
error: new 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 AuraError(res.status) }
|
|
17
|
-
return { data: await extract(res), error: null }
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/** Download paresseux (Blob par défaut). La requête ne part qu'à l'await ; résultat mémoïsé. */
|
|
21
|
-
export class BlobDownloadBuilder implements PromiseLike<AuraResponse<Blob>> {
|
|
22
|
-
private _promise: Promise<AuraResponse<Blob>> | null = null
|
|
23
|
-
constructor(private readonly _fn: DownloadFn) {}
|
|
24
|
-
|
|
25
|
-
asStream(): StreamDownloadBuilder {
|
|
26
|
-
return new StreamDownloadBuilder(this._fn)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
private _run(): Promise<AuraResponse<Blob>> {
|
|
30
|
-
if (!this._promise) this._promise = runDownload(this._fn, (r) => r.blob())
|
|
31
|
-
return this._promise
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
then<TR1 = AuraResponse<Blob>, TR2 = never>(
|
|
35
|
-
onfulfilled?: ((v: AuraResponse<Blob>) => TR1 | PromiseLike<TR1>) | null,
|
|
36
|
-
onrejected?: ((e: unknown) => TR2 | PromiseLike<TR2>) | null,
|
|
37
|
-
): Promise<TR1 | TR2> {
|
|
38
|
-
return this._run().then(onfulfilled, onrejected)
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/** Variante flux — `res.body` (ReadableStream). */
|
|
43
|
-
export class StreamDownloadBuilder implements PromiseLike<AuraResponse<ReadableStream<Uint8Array>>> {
|
|
44
|
-
private _promise: Promise<AuraResponse<ReadableStream<Uint8Array>>> | null = null
|
|
45
|
-
constructor(private readonly _fn: DownloadFn) {}
|
|
46
|
-
|
|
47
|
-
private _run(): Promise<AuraResponse<ReadableStream<Uint8Array>>> {
|
|
48
|
-
if (!this._promise) {
|
|
49
|
-
this._promise = runDownload(this._fn, (r) => r.body as ReadableStream<Uint8Array>)
|
|
50
|
-
}
|
|
51
|
-
return this._promise
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
then<TR1 = AuraResponse<ReadableStream<Uint8Array>>, TR2 = never>(
|
|
55
|
-
onfulfilled?: ((v: AuraResponse<ReadableStream<Uint8Array>>) => TR1 | PromiseLike<TR1>) | null,
|
|
56
|
-
onrejected?: ((e: unknown) => TR2 | PromiseLike<TR2>) | null,
|
|
57
|
-
): Promise<TR1 | TR2> {
|
|
58
|
-
return this._run().then(onfulfilled, onrejected)
|
|
59
|
-
}
|
|
60
|
-
}
|
|
@@ -1,323 +0,0 @@
|
|
|
1
|
-
import { BaseService } from '@aurabase/core'
|
|
2
|
-
import { isTokenExpired, refreshOnce, AuraError } from '@aurabase/core'
|
|
3
|
-
import type {
|
|
4
|
-
AuraResponse,
|
|
5
|
-
FileEntry,
|
|
6
|
-
ImageTransform,
|
|
7
|
-
ObjectMeta,
|
|
8
|
-
StorageBucket,
|
|
9
|
-
UploadResult,
|
|
10
|
-
} from '@aurabase/core'
|
|
11
|
-
import type { AuraClientLike } from '@aurabase/core'
|
|
12
|
-
import { BlobDownloadBuilder } from './DownloadBuilder'
|
|
13
|
-
import { encodeObjectPath } from './path'
|
|
14
|
-
import { renderTransformParams } from './transform'
|
|
15
|
-
|
|
16
|
-
export class StorageService extends BaseService {
|
|
17
|
-
constructor(client: AuraClientLike) {
|
|
18
|
-
super(client)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
private get prefix(): string {
|
|
22
|
-
return `/v1/storage/${this.client.projectId}`
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// -- Buckets ----------------------------------------------------------------
|
|
26
|
-
|
|
27
|
-
async listBuckets(): Promise<AuraResponse<StorageBucket[]>> {
|
|
28
|
-
return this.request('GET', `${this.prefix}/buckets`)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async getBucket(id: string): Promise<AuraResponse<StorageBucket>> {
|
|
32
|
-
return this.request('GET', `${this.prefix}/buckets/${id}`)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async createBucket(
|
|
36
|
-
name: string,
|
|
37
|
-
options?: { public?: boolean; fileSizeLimit?: number; allowedMimeTypes?: string[] },
|
|
38
|
-
): Promise<AuraResponse<StorageBucket>> {
|
|
39
|
-
return this.request('POST', `${this.prefix}/buckets`, {
|
|
40
|
-
name,
|
|
41
|
-
public: options?.public ?? false,
|
|
42
|
-
file_size_limit: options?.fileSizeLimit,
|
|
43
|
-
allowed_mime_types: options?.allowedMimeTypes,
|
|
44
|
-
})
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Met à jour un bucket existant (mise à jour PARTIELLE : seuls les champs
|
|
49
|
-
* fournis sont envoyés). Mapping identique à `createBucket`
|
|
50
|
-
* (`public`/`file_size_limit`/`allowed_mime_types`).
|
|
51
|
-
*
|
|
52
|
-
* Backend route: PATCH /v1/storage/{project_id}/buckets/{id}
|
|
53
|
-
*/
|
|
54
|
-
async updateBucket(
|
|
55
|
-
id: string,
|
|
56
|
-
options?: { public?: boolean; fileSizeLimit?: number; allowedMimeTypes?: string[] },
|
|
57
|
-
): Promise<AuraResponse<StorageBucket>> {
|
|
58
|
-
const body: Record<string, unknown> = {}
|
|
59
|
-
if (options?.public !== undefined) body.public = options.public
|
|
60
|
-
if (options?.fileSizeLimit !== undefined) body.file_size_limit = options.fileSizeLimit
|
|
61
|
-
if (options?.allowedMimeTypes !== undefined) body.allowed_mime_types = options.allowedMimeTypes
|
|
62
|
-
return this.request('PATCH', `${this.prefix}/buckets/${id}`, body)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async deleteBucket(id: string): Promise<AuraResponse<null>> {
|
|
66
|
-
return this.request('DELETE', `${this.prefix}/buckets/${id}`)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// -- Objects ----------------------------------------------------------------
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Upload a file to a bucket.
|
|
73
|
-
*
|
|
74
|
-
* Le serveur génère une clé unique `<uuid>.<ext>` (relative au bucket).
|
|
75
|
-
* Réutilisez directement `data.key` pour download(), remove(), copy(), etc.
|
|
76
|
-
*
|
|
77
|
-
* @example
|
|
78
|
-
* const { data } = await client.storage.upload('avatars', 'photo.png', file)
|
|
79
|
-
* await client.storage.download('avatars', data!.key) // fonctionne directement
|
|
80
|
-
*
|
|
81
|
-
* Backend route: POST /v1/storage/{project_id}/{bucket}
|
|
82
|
-
*/
|
|
83
|
-
async upload(
|
|
84
|
-
bucketId: string,
|
|
85
|
-
path: string,
|
|
86
|
-
file: Blob | File | ArrayBuffer,
|
|
87
|
-
options?: { contentType?: string; upsert?: boolean; metadata?: Record<string, string> },
|
|
88
|
-
): Promise<AuraResponse<UploadResult>> {
|
|
89
|
-
const formData = new FormData()
|
|
90
|
-
const blob =
|
|
91
|
-
file instanceof Blob
|
|
92
|
-
? file
|
|
93
|
-
: new Blob([file], { type: options?.contentType ?? 'application/octet-stream' })
|
|
94
|
-
formData.append('file', blob, path)
|
|
95
|
-
if (options?.upsert) formData.append('upsert', 'true')
|
|
96
|
-
// Métadonnées objet : tout champ multipart ≠ `file`/`upsert` est rangé par le
|
|
97
|
-
// backend dans `custom_meta` → métadonnées S3 relues par `getMetadata`.
|
|
98
|
-
if (options?.metadata) {
|
|
99
|
-
for (const [k, v] of Object.entries(options.metadata)) formData.append(k, v)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return this.request('POST', `${this.prefix}/${bucketId}`, formData as unknown)
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Download paresseux d'un fichier. Renvoie un builder (Blob par défaut, `.asStream()` pour
|
|
107
|
-
* le flux) ; la requête part à l'`await`. Refresh proactif du token avant la requête.
|
|
108
|
-
* `options?.transform` (image) : appende `renderTransformParams(...)` à l'URL — figée à
|
|
109
|
-
* l'appel, le builder reste inchangé.
|
|
110
|
-
* Backend route: GET /v1/storage/{project_id}/{bucket}/{*key}
|
|
111
|
-
*/
|
|
112
|
-
download(bucketId: string, path: string, options?: { transform?: ImageTransform }): BlobDownloadBuilder {
|
|
113
|
-
// Encodage anti-traversal + neutralisation des caractères d'URL. Lève
|
|
114
|
-
// synchroniquement (AuraError) sur un segment `..`.
|
|
115
|
-
let url = this.url(`${this.prefix}/${encodeURIComponent(bucketId)}/${encodeObjectPath(path)}`)
|
|
116
|
-
if (options?.transform) {
|
|
117
|
-
const qs = renderTransformParams(options.transform).toString()
|
|
118
|
-
if (qs) url = `${url}?${qs}`
|
|
119
|
-
}
|
|
120
|
-
const client = this.client
|
|
121
|
-
const downloadFn = async (): Promise<Response> => {
|
|
122
|
-
const store = client.authStore
|
|
123
|
-
if (store.token && store.refreshToken && isTokenExpired(store.token, 30)) {
|
|
124
|
-
await refreshOnce(client)
|
|
125
|
-
}
|
|
126
|
-
const headers: Record<string, string> = {}
|
|
127
|
-
if (store.token) headers['Authorization'] = `Bearer ${store.token}`
|
|
128
|
-
if (client.apiKey) headers['apikey'] = client.apiKey
|
|
129
|
-
return client.fetchFn(url, { headers })
|
|
130
|
-
}
|
|
131
|
-
return new BlobDownloadBuilder(downloadFn)
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* List files in a bucket.
|
|
136
|
-
*
|
|
137
|
-
* ⚠️ `offset` n'est PAS supporté par le backend (`ListQuery` ne connaît que
|
|
138
|
-
* `prefix`+`limit`) : le paramètre est accepté pour compatibilité ascendante
|
|
139
|
-
* mais IGNORÉ (jamais envoyé au serveur). Pour restreindre les résultats,
|
|
140
|
-
* utilisez `prefix`. La vraie pagination (continuation token) relève du backend.
|
|
141
|
-
*
|
|
142
|
-
* Backend route: GET /v1/storage/{project_id}/{bucket}
|
|
143
|
-
*/
|
|
144
|
-
async list(bucketId: string, options?: { prefix?: string; limit?: number; offset?: number }): Promise<AuraResponse<FileEntry[]>> {
|
|
145
|
-
const params = new URLSearchParams()
|
|
146
|
-
if (options?.prefix) params.set('prefix', options.prefix)
|
|
147
|
-
if (options?.limit !== undefined) params.set('limit', String(options.limit))
|
|
148
|
-
// `offset` volontairement NON transmis : ignoré par le backend (cf. JSDoc).
|
|
149
|
-
const qs = params.toString()
|
|
150
|
-
const sep = qs ? '?' : ''
|
|
151
|
-
return this.request('GET', `${this.prefix}/${bucketId}${sep}${qs}`)
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Delete one or more files from a bucket.
|
|
156
|
-
* Backend route: DELETE /v1/storage/{project_id}/{bucket}/{*key}
|
|
157
|
-
* Note: for single file deletion, paths[0] is used. Multi-delete is done in sequence.
|
|
158
|
-
*/
|
|
159
|
-
async remove(bucketId: string, paths: string[]): Promise<AuraResponse<null>> {
|
|
160
|
-
// Encodage anti-traversal de chaque clé (never-throw : on renvoie l'erreur).
|
|
161
|
-
let keys: string[]
|
|
162
|
-
try {
|
|
163
|
-
keys = paths.map((p) => encodeObjectPath(p))
|
|
164
|
-
} catch (e) {
|
|
165
|
-
return { data: null, error: e as AuraError }
|
|
166
|
-
}
|
|
167
|
-
const b = encodeURIComponent(bucketId)
|
|
168
|
-
// Backend supports single file deletion per request
|
|
169
|
-
// For multiple files, call sequentially
|
|
170
|
-
if (keys.length === 1) {
|
|
171
|
-
return this.request('DELETE', `${this.prefix}/${b}/${keys[0]}`)
|
|
172
|
-
}
|
|
173
|
-
// Multi-delete: fire all in parallel, return success if all succeed
|
|
174
|
-
const results = await Promise.all(
|
|
175
|
-
keys.map((k) => this.request('DELETE', `${this.prefix}/${b}/${k}`)),
|
|
176
|
-
)
|
|
177
|
-
const failed = results.find((r) => r.error)
|
|
178
|
-
if (failed) return failed as AuraResponse<null>
|
|
179
|
-
return { data: null, error: null }
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Copy a file within a bucket.
|
|
184
|
-
*
|
|
185
|
-
* `fromPath`/`toPath` sont relatifs au bucket (cohérent avec `download`/
|
|
186
|
-
* `remove`/`upload`) — le SDK les préfixe par `bucketId` pour produire les
|
|
187
|
-
* clés MinIO complètes attendues par le backend.
|
|
188
|
-
*
|
|
189
|
-
* Backend route: POST /v1/storage/{project_id}/{bucket}/copy
|
|
190
|
-
*/
|
|
191
|
-
async copy(bucketId: string, fromPath: string, toPath: string): Promise<AuraResponse<{ key: string }>> {
|
|
192
|
-
return this.request('POST', `${this.prefix}/${bucketId}/copy`, {
|
|
193
|
-
src_key: `${bucketId}/${fromPath}`,
|
|
194
|
-
dst_key: `${bucketId}/${toPath}`,
|
|
195
|
-
})
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Move/rename a file within a bucket.
|
|
200
|
-
*
|
|
201
|
-
* `fromPath`/`toPath` sont relatifs au bucket (cohérent avec `download`/
|
|
202
|
-
* `remove`/`upload`) — le SDK les préfixe par `bucketId` pour produire les
|
|
203
|
-
* clés MinIO complètes attendues par le backend.
|
|
204
|
-
*
|
|
205
|
-
* Backend route: POST /v1/storage/{project_id}/{bucket}/move
|
|
206
|
-
*/
|
|
207
|
-
async move(bucketId: string, fromPath: string, toPath: string): Promise<AuraResponse<{ key: string }>> {
|
|
208
|
-
return this.request('POST', `${this.prefix}/${bucketId}/move`, {
|
|
209
|
-
src_key: `${bucketId}/${fromPath}`,
|
|
210
|
-
dst_key: `${bucketId}/${toPath}`,
|
|
211
|
-
})
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Get file metadata.
|
|
216
|
-
* Backend route: GET /v1/storage/{project_id}/{bucket}/meta/{*key}
|
|
217
|
-
*/
|
|
218
|
-
async getMetadata(bucketId: string, path: string): Promise<AuraResponse<ObjectMeta>> {
|
|
219
|
-
let key: string
|
|
220
|
-
try {
|
|
221
|
-
key = encodeObjectPath(path)
|
|
222
|
-
} catch (e) {
|
|
223
|
-
return { data: null, error: e as AuraError }
|
|
224
|
-
}
|
|
225
|
-
return this.request('GET', `${this.prefix}/${encodeURIComponent(bucketId)}/meta/${key}`)
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Generate a signed (temporary) download URL.
|
|
230
|
-
*
|
|
231
|
-
* `options?.transform` (image) : dérisqué en réel (stack live) — les params transform
|
|
232
|
-
* sont HORS HMAC (le backend ne les couvre pas dans la signature), donc on les appende
|
|
233
|
-
* à l'URL signée APRÈS réception de `{ url, expires_in }`, sans toucher à la requête
|
|
234
|
-
* `signed-url` elle-même.
|
|
235
|
-
* Backend route: GET /v1/storage/{project_id}/{bucket}/signed-url?key=...&ttl_secs=...
|
|
236
|
-
*/
|
|
237
|
-
async createSignedUrl(
|
|
238
|
-
bucketId: string,
|
|
239
|
-
path: string,
|
|
240
|
-
expiresInSeconds = 3600,
|
|
241
|
-
options?: { transform?: ImageTransform },
|
|
242
|
-
): Promise<AuraResponse<{ url: string; expires_in: number }>> {
|
|
243
|
-
const params = new URLSearchParams({ key: path, ttl_secs: String(expiresInSeconds) })
|
|
244
|
-
const res = await this.request<{ url: string; expires_in: number }>(
|
|
245
|
-
'GET',
|
|
246
|
-
`${this.prefix}/${bucketId}/signed-url?${params.toString()}`,
|
|
247
|
-
)
|
|
248
|
-
if (res.data && options?.transform) {
|
|
249
|
-
const qs = renderTransformParams(options.transform).toString()
|
|
250
|
-
if (qs) {
|
|
251
|
-
const sep = res.data.url.includes('?') ? '&' : '?'
|
|
252
|
-
res.data = { ...res.data, url: `${res.data.url}${sep}${qs}` }
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
return res
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* Génère plusieurs URLs signées en une passe (batch).
|
|
260
|
-
*
|
|
261
|
-
* Il n'existe pas d'endpoint batch côté backend : l'implémentation fait un
|
|
262
|
-
* fan-out `Promise.all` sur `createSignedUrl` (même patron que `remove()`),
|
|
263
|
-
* RÉSILIENT PAR-ITEM — chaque entrée est soit `{ path, url, expires_in }`
|
|
264
|
-
* (succès), soit `{ path, error }` (échec), sans faire échouer les autres.
|
|
265
|
-
*
|
|
266
|
-
* @example
|
|
267
|
-
* const { data } = await client.storage.createSignedUrls('avatars', ['a.png', 'b.png'])
|
|
268
|
-
* data?.forEach((r) => 'url' in r ? use(r.url) : console.warn(r.path, r.error))
|
|
269
|
-
*/
|
|
270
|
-
async createSignedUrls(
|
|
271
|
-
bucketId: string,
|
|
272
|
-
paths: string[],
|
|
273
|
-
expiresInSeconds = 3600,
|
|
274
|
-
options?: { transform?: ImageTransform },
|
|
275
|
-
): Promise<AuraResponse<Array<{ path: string; url: string; expires_in: number } | { path: string; error: AuraError }>>> {
|
|
276
|
-
const results = await Promise.all(
|
|
277
|
-
paths.map(async (path) => {
|
|
278
|
-
const res = await this.createSignedUrl(bucketId, path, expiresInSeconds, options)
|
|
279
|
-
if (res.error || !res.data) {
|
|
280
|
-
return { path, error: res.error ?? new AuraError(0, { error: { code: 'unknown', message: 'No data' } }) }
|
|
281
|
-
}
|
|
282
|
-
return { path, url: res.data.url, expires_in: res.data.expires_in }
|
|
283
|
-
}),
|
|
284
|
-
)
|
|
285
|
-
return { data: results, error: null }
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* Generate a signed upload URL (presigned POST/PUT).
|
|
290
|
-
* Backend route: GET /v1/storage/{project_id}/{bucket}/upload-url?key=...&ttl_secs=...
|
|
291
|
-
*/
|
|
292
|
-
async createSignedUploadUrl(
|
|
293
|
-
bucketId: string,
|
|
294
|
-
path: string,
|
|
295
|
-
expiresInSeconds = 3600,
|
|
296
|
-
): Promise<AuraResponse<{ url: string; expires_in: number }>> {
|
|
297
|
-
const params = new URLSearchParams({ key: path, ttl_secs: String(expiresInSeconds) })
|
|
298
|
-
return this.request('GET', `${this.prefix}/${bucketId}/upload-url?${params.toString()}`)
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* Construit une URL vers un fichier d'un bucket.
|
|
303
|
-
*
|
|
304
|
-
* ⚠️ Cette URL N'EST PAS accessible sans authentification : le gateway exige
|
|
305
|
-
* une clé API (`apikey`/`x-api-key`) sur toutes les routes storage, y compris
|
|
306
|
-
* pour les buckets créés avec `public: true` (ce flag n'est actuellement pas
|
|
307
|
-
* vérifié côté gateway — une requête non authentifiée renvoie 401). Pour
|
|
308
|
-
* partager un fichier sans authentification, utilisez `createSignedUrl()`,
|
|
309
|
-
* qui génère une URL signée HMAC vérifiée côté serveur sans clé API.
|
|
310
|
-
*
|
|
311
|
-
* `options?.transform` (image) : appende `renderTransformParams(...)` en query string.
|
|
312
|
-
* Backend route: GET /v1/storage/{project_id}/{bucket}/{*key} (clé API requise)
|
|
313
|
-
*/
|
|
314
|
-
getPublicUrl(bucketId: string, path: string, options?: { transform?: ImageTransform }): string {
|
|
315
|
-
// Lève synchroniquement (AuraError) sur un segment `..`.
|
|
316
|
-
const base = this.url(`${this.prefix}/${encodeURIComponent(bucketId)}/${encodeObjectPath(path)}`)
|
|
317
|
-
if (options?.transform) {
|
|
318
|
-
const qs = renderTransformParams(options.transform).toString()
|
|
319
|
-
if (qs) return `${base}?${qs}`
|
|
320
|
-
}
|
|
321
|
-
return base
|
|
322
|
-
}
|
|
323
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { AuraError } from '@aurabase/core'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Encode un chemin d'objet storage pour interpolation SÛRE dans un path d'URL.
|
|
5
|
-
*
|
|
6
|
-
* Deux protections :
|
|
7
|
-
* 1. **Anti-traversal** — rejette tout segment `..`. Sans ça, un `../` non
|
|
8
|
-
* neutralisé serait normalisé par `fetch`/le navigateur AVANT l'envoi
|
|
9
|
-
* (`/storage/proj/bucketA/../../bucketB/x` → `/storage/proj/bucketB/x`),
|
|
10
|
-
* permettant un accès cross-bucket. Le backend traite les clés S3 de façon
|
|
11
|
-
* littérale et ne filtre pas `..` : la défense doit donc être ici aussi.
|
|
12
|
-
* 2. **Encodage per-segment** — `encodeURIComponent` sur chaque segment
|
|
13
|
-
* (les `/` séparateurs sont préservés pour garder la structure de dossiers).
|
|
14
|
-
* Neutralise `?`, `#`, `%`, espaces… qui casseraient l'URL ou injecteraient
|
|
15
|
-
* une query string. Le double-décodage est évité (`%2E%2E` reste littéral).
|
|
16
|
-
*
|
|
17
|
-
* @throws {AuraError} code `invalid_path` si un segment `..` est présent.
|
|
18
|
-
*/
|
|
19
|
-
export function encodeObjectPath(path: string): string {
|
|
20
|
-
// Retire les slashes de tête : le préfixe bucket est ajouté séparément, et un
|
|
21
|
-
// path absolu (`/x`) ne doit pas produire `bucket//x`.
|
|
22
|
-
const trimmed = path.replace(/^\/+/, '')
|
|
23
|
-
const segments = trimmed.split('/')
|
|
24
|
-
for (const seg of segments) {
|
|
25
|
-
if (seg === '..') {
|
|
26
|
-
throw new AuraError(0, {
|
|
27
|
-
error: {
|
|
28
|
-
code: 'invalid_path',
|
|
29
|
-
message: 'Path traversal ("..") is not allowed in storage object paths',
|
|
30
|
-
},
|
|
31
|
-
})
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
return segments.map((s) => encodeURIComponent(s)).join('/')
|
|
35
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { ImageTransform } from '@aurabase/core'
|
|
2
|
-
|
|
3
|
-
/** Mappe une ImageTransform (vocabulaire Supabase) vers les query params du backend
|
|
4
|
-
* de rendu Aurabase (`fit`, `format`, `quality`, `width`, `height`). */
|
|
5
|
-
export function renderTransformParams(t: ImageTransform): URLSearchParams {
|
|
6
|
-
const p = new URLSearchParams()
|
|
7
|
-
// Garde `Number.isFinite` : un NaN/Infinity (calcul amont non vérifié) est de type
|
|
8
|
-
// 'number' mais produirait `width=NaN` → 400 backend ; on l'ignore silencieusement.
|
|
9
|
-
if (Number.isFinite(t.width)) p.set('width', String(Math.max(1, Math.floor(t.width as number))))
|
|
10
|
-
if (Number.isFinite(t.height)) p.set('height', String(Math.max(1, Math.floor(t.height as number))))
|
|
11
|
-
if (t.resize) p.set('fit', t.resize) // cover/contain/fill : mêmes valeurs backend
|
|
12
|
-
if (Number.isFinite(t.quality)) p.set('quality', String(Math.min(100, Math.max(20, Math.floor(t.quality as number)))))
|
|
13
|
-
if (t.format && t.format !== 'origin') p.set('format', t.format)
|
|
14
|
-
return p
|
|
15
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest'
|
|
2
|
-
import { StorageService } from '../src/StorageService'
|
|
3
|
-
import { BaseAuthStore } from '@aurabase/core'
|
|
4
|
-
import type { AuraClientLike } from '@aurabase/core'
|
|
5
|
-
|
|
6
|
-
function b64url(o: unknown) { return btoa(JSON.stringify(o)).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '') }
|
|
7
|
-
function expiredJwt() { return `${b64url({ alg: 'HS256' })}.${b64url({ exp: Math.floor(Date.now() / 1000) - 60 })}.s` }
|
|
8
|
-
function validJwt() { return `${b64url({ alg: 'HS256' })}.${b64url({ exp: Math.floor(Date.now() / 1000) + 3600 })}.s` }
|
|
9
|
-
function fakeUser() { return { id: 'u', email: null, role: 'authenticated', email_verified: true, is_banned: false, is_anonymous: false, mfa_enabled: false, user_metadata: {}, app_metadata: {}, created_at: '2025-01-01T00:00:00Z' } }
|
|
10
|
-
|
|
11
|
-
function make(responder: (url: string) => Response, store = new BaseAuthStore()) {
|
|
12
|
-
const calls: string[] = []
|
|
13
|
-
const client: AuraClientLike = {
|
|
14
|
-
baseUrl: 'http://x', projectId: 'p', apiKey: 'k', authStore: store,
|
|
15
|
-
fetchFn: (async (url: string) => { calls.push(String(url)); return responder(String(url)) }) as unknown as typeof globalThis.fetch,
|
|
16
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
|
-
auth: { refreshSession: async () => ({ data: null, error: null }) as any },
|
|
18
|
-
}
|
|
19
|
-
return { storage: new StorageService(client), calls }
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
describe('storage.download — builder paresseux', () => {
|
|
23
|
-
it('Blob par défaut', async () => {
|
|
24
|
-
const { storage } = make(() => new Response(new Blob(['hello']), { status: 200 }))
|
|
25
|
-
const { data, error } = await storage.download('b', 'k.png')
|
|
26
|
-
expect(error).toBeNull()
|
|
27
|
-
expect(data).toBeInstanceOf(Blob)
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
it('mémoïsé : une seule requête même sur double await', async () => {
|
|
31
|
-
const { storage, calls } = make(() => new Response(new Blob(['x']), { status: 200 }))
|
|
32
|
-
const dl = storage.download('b', 'k.png')
|
|
33
|
-
await dl
|
|
34
|
-
await dl
|
|
35
|
-
expect(calls.length).toBe(1)
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
it('.asStream() → ReadableStream', async () => {
|
|
39
|
-
const { storage } = make(() => new Response(new Blob(['x']), { status: 200 }))
|
|
40
|
-
const { data } = await storage.download('b', 'k.png').asStream()
|
|
41
|
-
expect(data).toBeInstanceOf(ReadableStream)
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
it('!ok → erreur status', async () => {
|
|
45
|
-
const { storage } = make(() => new Response(null, { status: 404 }))
|
|
46
|
-
const { data, error } = await storage.download('b', 'missing')
|
|
47
|
-
expect(data).toBeNull()
|
|
48
|
-
expect(error?.status).toBe(404)
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
it('refresh proactif si token expiré (refresh AVANT download)', async () => {
|
|
52
|
-
const store = new BaseAuthStore()
|
|
53
|
-
store.save(expiredJwt(), 'rt', fakeUser())
|
|
54
|
-
const { storage, calls } = make((url) => {
|
|
55
|
-
if (url.includes('/v1/auth/')) {
|
|
56
|
-
return new Response(JSON.stringify({ access_token: validJwt(), refresh_token: 'rt2', token_type: 'bearer', expires_in: 3600, user: fakeUser() }), { status: 200, headers: { 'Content-Type': 'application/json' } })
|
|
57
|
-
}
|
|
58
|
-
return new Response(new Blob(['x']), { status: 200 })
|
|
59
|
-
}, store)
|
|
60
|
-
await storage.download('b', 'k.png')
|
|
61
|
-
expect(calls[0]).toContain('/v1/auth/p/refresh')
|
|
62
|
-
expect(calls[1]).toContain('/b/k.png')
|
|
63
|
-
})
|
|
64
|
-
})
|