@aurabase/aurabase-js 0.3.0 → 0.4.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/README.md +26 -795
- package/{packages/aurabase/dist/AuraClient-DAtDbfPB.d.ts → dist/AuraClient-BcFE8u1v.d.cts} +1 -1
- package/{packages/aurabase/dist/AuraClient-DAtDbfPB.d.cts → dist/AuraClient-BcFE8u1v.d.ts} +1 -1
- package/{packages/aurabase/dist → dist}/index.d.cts +1 -1
- package/{packages/aurabase/dist → dist}/index.d.ts +1 -1
- package/{packages/aurabase/dist → dist}/ssr.d.cts +1 -1
- package/{packages/aurabase/dist → dist}/ssr.d.ts +1 -1
- package/package.json +72 -82
- package/.changeset/config.json +0 -11
- package/CHANGELOG.md +0 -30
- package/packages/ai/LICENSE +0 -21
- package/packages/ai/README.md +0 -106
- package/packages/ai/dist/index.cjs +0 -229
- package/packages/ai/dist/index.d.cts +0 -139
- package/packages/ai/dist/index.d.ts +0 -139
- package/packages/ai/dist/index.js +0 -226
- 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/package.json +0 -61
- 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/LICENSE +0 -21
- package/packages/aurabase/README.md +0 -64
- 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/package.json +0 -80
- 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/aurabase/vitest.e2e.config.ts +0 -9
- package/packages/auth/LICENSE +0 -21
- package/packages/auth/README.md +0 -215
- package/packages/auth/dist/index.cjs +0 -1175
- package/packages/auth/dist/index.d.cts +0 -397
- package/packages/auth/dist/index.d.ts +0 -397
- package/packages/auth/dist/index.js +0 -1170
- 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/package.json +0 -61
- 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/LICENSE +0 -21
- package/packages/core/README.md +0 -132
- package/packages/core/dist/index.cjs +0 -695
- package/packages/core/dist/index.d.cts +0 -1137
- package/packages/core/dist/index.d.ts +0 -1137
- package/packages/core/dist/index.js +0 -673
- 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/package.json +0 -57
- 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/LICENSE +0 -21
- package/packages/db/README.md +0 -152
- package/packages/db/VENDORED.md +0 -93
- package/packages/db/dist/index.cjs +0 -544
- package/packages/db/dist/index.d.cts +0 -1111
- package/packages/db/dist/index.d.ts +0 -1111
- package/packages/db/dist/index.js +0 -541
- 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/package.json +0 -62
- 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/LICENSE +0 -21
- package/packages/functions/README.md +0 -96
- package/packages/functions/dist/index.cjs +0 -173
- package/packages/functions/dist/index.d.cts +0 -81
- package/packages/functions/dist/index.d.ts +0 -81
- package/packages/functions/dist/index.js +0 -168
- 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/package.json +0 -60
- 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/LICENSE +0 -21
- package/packages/gen/README.md +0 -84
- package/packages/gen/dist/cli.cjs +0 -334
- package/packages/gen/dist/cli.d.cts +0 -1
- package/packages/gen/dist/cli.d.ts +0 -1
- package/packages/gen/dist/cli.js +0 -332
- package/packages/gen/dist/index.cjs +0 -257
- package/packages/gen/dist/index.d.cts +0 -12
- package/packages/gen/dist/index.d.ts +0 -12
- package/packages/gen/dist/index.js +0 -255
- 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/package.json +0 -66
- 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/LICENSE +0 -21
- package/packages/notifications/README.md +0 -134
- package/packages/notifications/dist/index.cjs +0 -128
- package/packages/notifications/dist/index.d.cts +0 -81
- package/packages/notifications/dist/index.d.ts +0 -81
- package/packages/notifications/dist/index.js +0 -125
- 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/package.json +0 -60
- 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/LICENSE +0 -21
- package/packages/realtime/README.md +0 -183
- package/packages/realtime/dist/index.cjs +0 -977
- package/packages/realtime/dist/index.d.cts +0 -259
- package/packages/realtime/dist/index.d.ts +0 -259
- package/packages/realtime/dist/index.js +0 -973
- 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/package.json +0 -60
- 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/LICENSE +0 -21
- package/packages/storage/README.md +0 -141
- package/packages/storage/dist/index.cjs +0 -333
- package/packages/storage/dist/index.d.cts +0 -185
- package/packages/storage/dist/index.d.ts +0 -185
- package/packages/storage/dist/index.js +0 -329
- 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/package.json +0 -60
- 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
- /package/{packages/aurabase/dist → dist}/index.cjs +0 -0
- /package/{packages/aurabase/dist → dist}/index.js +0 -0
- /package/{packages/aurabase/dist → dist}/ssr.cjs +0 -0
- /package/{packages/aurabase/dist → dist}/ssr.js +0 -0
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// E2E réel de smoke des README (stack live) — Task 6 (chantier H, DX).
|
|
3
|
-
//
|
|
4
|
-
// Complément du compile-check statique (tests/types/docs-snippets.test-d.ts,
|
|
5
|
-
// preuve compile-time) : ce fichier exécute RÉELLEMENT, contre le déploiement
|
|
6
|
-
// Docker local (gateway :8080, control :8090), les exemples clés documentés
|
|
7
|
-
// dans packages/auth/README.md, packages/db/README.md et
|
|
8
|
-
// packages/storage/README.md — preuve runtime que la doc est fidèle au
|
|
9
|
-
// comportement observé, pas seulement à la signature TypeScript.
|
|
10
|
-
//
|
|
11
|
-
// Périmètre volontairement réduit à un flux « smoke » par domaine (pas une
|
|
12
|
-
// couverture exhaustive de chaque méthode documentée — c'est le rôle des
|
|
13
|
-
// suites unitaires par package) :
|
|
14
|
-
// - Auth : signUp → signInWithPassword → getUser (id/email cohérents) →
|
|
15
|
-
// signOut. Cleanup authAdmin.deleteUser en finally.
|
|
16
|
-
// - DB : table jetable créée via aura.db.sql() (CREATE TABLE + GRANT +
|
|
17
|
-
// reload schema PostgREST + délai de démarrage du reload, comme
|
|
18
|
-
// db-types-e2e.test.ts) → from(table).insert(...).select(...).single() →
|
|
19
|
-
// from(table).select(...).eq(...).single() → vérifie la forme
|
|
20
|
-
// réelle de la ligne retournée. Le reload de cache PostgREST étant
|
|
21
|
-
// asynchrone, insert/select rejouent sur 503 (reload en cours) ET
|
|
22
|
-
// 404 (cache pas encore rechargé) via retryReload, avec skip
|
|
23
|
-
// gracieux si le backend reste indisponible après retries.
|
|
24
|
-
// Cleanup DROP TABLE en finally.
|
|
25
|
-
// - Storage: createBucket (service_role) → upload → download (builder
|
|
26
|
-
// paresseux, .text() sur le Blob résolu) → remove →
|
|
27
|
-
// deleteBucket. Cleanup deleteBucket en finally.
|
|
28
|
-
//
|
|
29
|
-
// Gaté par RUN_E2E + credentials (identique à auth-e2e.test.ts /
|
|
30
|
-
// db-types-e2e.test.ts) : describe.runIf(RUN) SKIPPE proprement la suite
|
|
31
|
-
// entière (pas d'échec) quand les variables d'env manquent — vérifié sans
|
|
32
|
-
// RUN_E2E via `pnpm --filter aurabase test`.
|
|
33
|
-
// ---------------------------------------------------------------------------
|
|
34
|
-
|
|
35
|
-
import { describe, it, expect } from 'vitest'
|
|
36
|
-
import { createClient, createAdminClient } from '../src/index'
|
|
37
|
-
import type { AuraResponse } from '../src/index'
|
|
38
|
-
|
|
39
|
-
const URL = process.env.AURA_E2E_URL
|
|
40
|
-
const PROJECT = process.env.AURA_E2E_PROJECT
|
|
41
|
-
const ANON = process.env.AURA_E2E_ANON_KEY
|
|
42
|
-
const SERVICE = process.env.AURA_E2E_SERVICE_KEY
|
|
43
|
-
const RUN = Boolean(process.env.RUN_E2E && URL && PROJECT && ANON && SERVICE)
|
|
44
|
-
|
|
45
|
-
/** Statuts transitoires observés sur la stack locale (timeout gateway→service sous charge). */
|
|
46
|
-
const TRANSIENT_STATUS = new Set([408, 429, 502, 503, 504])
|
|
47
|
-
|
|
48
|
-
/** Rejoue une requête tant qu'elle renvoie un statut transitoire, borné (cf. auth-e2e.test.ts). */
|
|
49
|
-
async function retryTransient<T>(fn: () => Promise<AuraResponse<T>>): Promise<AuraResponse<T>> {
|
|
50
|
-
let res = await fn()
|
|
51
|
-
for (let i = 0; i < 10 && res.error && TRANSIENT_STATUS.has(res.error.status); i++) {
|
|
52
|
-
await new Promise((r) => setTimeout(r, 1000))
|
|
53
|
-
res = await fn()
|
|
54
|
-
}
|
|
55
|
-
return res
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/** Rejoue une requête tant qu'elle renvoie un statut transitoire (jeu complet
|
|
59
|
-
* TRANSIENT_STATUS : 408/429/502/503/504) OU 404 (cache pas encore rechargé — table
|
|
60
|
-
* inconnue de PostgREST), borné. Cf. db-types-e2e.test.ts : le reload de cache
|
|
61
|
-
* (pg_notify) est ASYNCHRONE — juste après la création d'une table via SQL brut,
|
|
62
|
-
* PostgREST peut d'abord renvoyer un 404 (POSTGREST_ERROR, cache pas encore rechargé)
|
|
63
|
-
* puis un 503 (reload en cours) avant d'être prêt. Sur stack locale saturée, peut aussi
|
|
64
|
-
* voir 408 (timeout gateway = transitoire). Réservé au flux db de setup ci-dessous
|
|
65
|
-
* (insert/select juste après CREATE TABLE) — ne pas réutiliser ce 404 élargi ailleurs,
|
|
66
|
-
* un 404 hors reload de schéma est une vraie erreur. */
|
|
67
|
-
async function retryReload<T>(fn: () => Promise<AuraResponse<T>>): Promise<AuraResponse<T>> {
|
|
68
|
-
let res = await fn()
|
|
69
|
-
for (let i = 0; i < 20 && (TRANSIENT_STATUS.has(res.error?.status) || res.error?.status === 404); i++) {
|
|
70
|
-
await new Promise((r) => setTimeout(r, 1000))
|
|
71
|
-
res = await fn()
|
|
72
|
-
}
|
|
73
|
-
return res
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
describe.runIf(RUN)('README smoke E2E réel (stack live) — auth / db / storage', () => {
|
|
77
|
-
it(
|
|
78
|
-
'auth : signUp → signInWithPassword → getUser (id/email cohérents) → signOut',
|
|
79
|
-
async () => {
|
|
80
|
-
const client = createClient(URL!, PROJECT!, ANON!)
|
|
81
|
-
const admin = createAdminClient(URL!, PROJECT!, SERVICE!)
|
|
82
|
-
const suffix = process.env.AURA_E2E_SUFFIX ?? Math.random().toString(36).slice(2, 8)
|
|
83
|
-
const email = `readme-smoke-auth-${suffix}@aurabase.dev`
|
|
84
|
-
const password = 'ReadmeSmokeAuth123!'
|
|
85
|
-
|
|
86
|
-
let userId: string | null = null
|
|
87
|
-
try {
|
|
88
|
-
// README auth § "Mot de passe"
|
|
89
|
-
const signUpRes = await retryTransient(() => client.auth.signUp({ email, password }))
|
|
90
|
-
expect(signUpRes.error).toBeNull()
|
|
91
|
-
|
|
92
|
-
const signInRes = await retryTransient(() => client.auth.signInWithPassword({ email, password }))
|
|
93
|
-
expect(signInRes.error).toBeNull()
|
|
94
|
-
const signInData = signInRes.data as { access_token: string; user: { id: string } }
|
|
95
|
-
expect(signInData.access_token).toBeTruthy()
|
|
96
|
-
userId = signInData.user.id
|
|
97
|
-
expect(userId).toBeTruthy()
|
|
98
|
-
|
|
99
|
-
// README auth § "Utilisateur, claims, mot de passe" — const { data: user } = await aura.auth.getUser()
|
|
100
|
-
const { data: user, error: userError } = await client.auth.getUser()
|
|
101
|
-
expect(userError).toBeNull()
|
|
102
|
-
expect(user).not.toBeNull()
|
|
103
|
-
expect(user!.id).toBe(userId)
|
|
104
|
-
expect(user!.email).toBe(email)
|
|
105
|
-
|
|
106
|
-
// README auth § "Mot de passe" — await aura.auth.signOut()
|
|
107
|
-
const signOutRes = await client.auth.signOut()
|
|
108
|
-
expect(signOutRes.error).toBeNull()
|
|
109
|
-
} finally {
|
|
110
|
-
if (userId) {
|
|
111
|
-
try {
|
|
112
|
-
await admin.authAdmin.deleteUser(userId)
|
|
113
|
-
} catch {
|
|
114
|
-
// best-effort cleanup
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
},
|
|
119
|
-
120_000,
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
it(
|
|
123
|
-
'db : from(table).insert(...).select(...).single() puis from(table).select(...).eq(...).single()',
|
|
124
|
-
async () => {
|
|
125
|
-
const client = createClient(URL!, PROJECT!, ANON!)
|
|
126
|
-
const suffix = process.env.AURA_E2E_SUFFIX ?? Math.random().toString(36).slice(2, 8)
|
|
127
|
-
const table = `e2e_readme_smoke_${suffix}`
|
|
128
|
-
|
|
129
|
-
// Table jetable — même mécanique que db-types-e2e.test.ts (SQL brut,
|
|
130
|
-
// GRANT large intentionnel, reload du cache de schéma PostgREST).
|
|
131
|
-
await client.db.sql(`DROP TABLE IF EXISTS ${table}`)
|
|
132
|
-
await client.db.sql(
|
|
133
|
-
`CREATE TABLE ${table} (id uuid PRIMARY KEY DEFAULT gen_random_uuid(), title text NOT NULL, published boolean NOT NULL DEFAULT false)`,
|
|
134
|
-
)
|
|
135
|
-
await client.db.sql(`GRANT ALL ON ${table} TO PUBLIC`)
|
|
136
|
-
await client.db.sql(`SELECT pg_notify('pgrst', 'reload schema')`)
|
|
137
|
-
// Laisse le reload asynchrone démarrer avant le premier appel — sans ce délai,
|
|
138
|
-
// le premier insert tombe quasi systématiquement en 404 (cache pas encore invalidé).
|
|
139
|
-
await new Promise((r) => setTimeout(r, 1500))
|
|
140
|
-
|
|
141
|
-
try {
|
|
142
|
-
// README db § "Mutations — update/delete ciblent par id"
|
|
143
|
-
const inserted = await retryReload(() =>
|
|
144
|
-
client.db.from(table).insert({ title: 'Hello Aurabase', published: true }).select('id').single(),
|
|
145
|
-
)
|
|
146
|
-
if (TRANSIENT_STATUS.has(inserted.error?.status) || inserted.error?.status === 404) {
|
|
147
|
-
// eslint-disable-next-line no-console
|
|
148
|
-
console.warn(
|
|
149
|
-
'[readme-smoke-e2e] SKIP db (infra: reload/503/404 persistant après retries sur insert) — ' +
|
|
150
|
-
'NON un succès : assertion runtime db ignorée, pas un défaut de la doc.',
|
|
151
|
-
)
|
|
152
|
-
return
|
|
153
|
-
}
|
|
154
|
-
expect(inserted.error).toBeNull()
|
|
155
|
-
const id = (inserted.data as { id: string } | null)?.id
|
|
156
|
-
expect(id).toBeTruthy()
|
|
157
|
-
|
|
158
|
-
// README db § "Select, filtres, embeds"
|
|
159
|
-
const selected = await retryReload(() =>
|
|
160
|
-
client.db.from(table).select('id,title,published').eq('id', id!).single(),
|
|
161
|
-
)
|
|
162
|
-
if (TRANSIENT_STATUS.has(selected.error?.status) || selected.error?.status === 404) {
|
|
163
|
-
// eslint-disable-next-line no-console
|
|
164
|
-
console.warn(
|
|
165
|
-
'[readme-smoke-e2e] SKIP db (infra: reload/503/404 persistant après retries sur select) — ' +
|
|
166
|
-
'NON un succès : assertion runtime db ignorée, pas un défaut de la doc.',
|
|
167
|
-
)
|
|
168
|
-
return
|
|
169
|
-
}
|
|
170
|
-
expect(selected.error).toBeNull()
|
|
171
|
-
const row = selected.data as { id: string; title: string; published: boolean }
|
|
172
|
-
expect(row.id).toBe(id)
|
|
173
|
-
expect(row.title).toBe('Hello Aurabase')
|
|
174
|
-
expect(row.published).toBe(true)
|
|
175
|
-
} finally {
|
|
176
|
-
await client.db.sql(`DROP TABLE IF EXISTS ${table}`)
|
|
177
|
-
}
|
|
178
|
-
},
|
|
179
|
-
120_000,
|
|
180
|
-
)
|
|
181
|
-
|
|
182
|
-
it(
|
|
183
|
-
'storage : createBucket (service_role) → upload → download → remove → deleteBucket',
|
|
184
|
-
async () => {
|
|
185
|
-
const admin = createAdminClient(URL!, PROJECT!, SERVICE!)
|
|
186
|
-
const suffix = process.env.AURA_E2E_SUFFIX ?? Math.random().toString(36).slice(2, 8)
|
|
187
|
-
const bucket = `e2e-readme-smoke-${suffix}`
|
|
188
|
-
const path = 'readme-smoke.txt'
|
|
189
|
-
const content = 'Aurabase README smoke E2E'
|
|
190
|
-
|
|
191
|
-
let created = false
|
|
192
|
-
try {
|
|
193
|
-
// README storage § "Buckets"
|
|
194
|
-
const createRes = await retryTransient(() => admin.storage.createBucket(bucket, { public: false }))
|
|
195
|
-
expect(createRes.error).toBeNull()
|
|
196
|
-
created = true
|
|
197
|
-
|
|
198
|
-
// README storage § "Upload, liste, métadonnées"
|
|
199
|
-
const uploadRes = await admin.storage.upload(
|
|
200
|
-
bucket,
|
|
201
|
-
path,
|
|
202
|
-
new Blob([content], { type: 'text/plain' }),
|
|
203
|
-
{ contentType: 'text/plain' },
|
|
204
|
-
)
|
|
205
|
-
expect(uploadRes.error).toBeNull()
|
|
206
|
-
const key = uploadRes.data!.key
|
|
207
|
-
expect(key).toBeTruthy()
|
|
208
|
-
|
|
209
|
-
// README storage § "Download — builder paresseux"
|
|
210
|
-
const { data: blob, error: downloadError } = await admin.storage.download(bucket, key)
|
|
211
|
-
expect(downloadError).toBeNull()
|
|
212
|
-
expect(blob).not.toBeNull()
|
|
213
|
-
const text = await blob!.text()
|
|
214
|
-
expect(text).toBe(content)
|
|
215
|
-
|
|
216
|
-
// README storage § "Copie, déplacement, suppression"
|
|
217
|
-
const removeRes = await admin.storage.remove(bucket, [key])
|
|
218
|
-
expect(removeRes.error).toBeNull()
|
|
219
|
-
} finally {
|
|
220
|
-
if (created) {
|
|
221
|
-
try {
|
|
222
|
-
await admin.storage.deleteBucket(bucket)
|
|
223
|
-
} catch {
|
|
224
|
-
// best-effort cleanup
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
},
|
|
229
|
-
120_000,
|
|
230
|
-
)
|
|
231
|
-
})
|
|
@@ -1,344 +0,0 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// E2E réel (stack live) — LOT A / Task A2 du plan
|
|
3
|
-
// docs/superpowers/plans/2026-07-13-realtime-column-filters.md.
|
|
4
|
-
//
|
|
5
|
-
// Prouve en conditions réelles que le filtre colonne serveur `aura-realtime`
|
|
6
|
-
// (protocol.rs::event_matches_filters, câblé handlers/websocket.rs:~1173) ne
|
|
7
|
-
// livre AU CALLBACK que les events postgres_changes dont le `record` (ou
|
|
8
|
-
// `old_record` pour DELETE) satisfait le prédicat `filter: 'col=op.value'`.
|
|
9
|
-
// Le Lot B (fallback client `columnFilter.ts`) n'est PAS encore implémenté à
|
|
10
|
-
// ce stade (AuraChannel._dispatchEvent ne vérifie que schema/table, jamais
|
|
11
|
-
// `filter` — cf. packages/realtime/src/AuraChannel.ts:~411-426) : ce test
|
|
12
|
-
// isole donc bien le comportement SERVEUR, seul en jeu ici.
|
|
13
|
-
//
|
|
14
|
-
// ── Mécanisme d'activation realtime d'une table (repéré dans le code) ──────
|
|
15
|
-
// Le CDC (`services/aura-realtime/src/cdc/postgres.rs`) ne route que les
|
|
16
|
-
// tables listées dans `{project_schema}_platform.realtime_tables WHERE
|
|
17
|
-
// enabled = true` (lu par `SubscriptionManager::get_active_realtime_tables`,
|
|
18
|
-
// rafraîchi toutes les 3s — `services/aura-realtime/src/cdc/postgres.rs:341`
|
|
19
|
-
// `filter_refresh_interval`). Il existe une route HTTP DÉDIÉE côté aura-db
|
|
20
|
-
// pour activer/désactiver ça proprement (pas besoin d'INSERT SQL manuel dans
|
|
21
|
-
// le schéma platform, verrouillé au master_pool) :
|
|
22
|
-
// PUT /v1/db/{project_id}/schema/tables/{table}/realtime
|
|
23
|
-
// body: { enabled: true }
|
|
24
|
-
// (service_role requis — `require_service_role` via header x-aura-role posé
|
|
25
|
-
// par le gateway à partir de la clé API service_role ; voir
|
|
26
|
-
// `services/aura-db/src/handlers/schema.rs::toggle_realtime`, routes
|
|
27
|
-
// enregistrées dans `services/aura-db/src/main.rs:783/983`)
|
|
28
|
-
// Cet endpoint fait aussi `ALTER TABLE ... REPLICA IDENTITY FULL`, nécessaire
|
|
29
|
-
// pour que `old_record` soit peuplé sur UPDATE/DELETE. Pas de méthode SDK
|
|
30
|
-
// dédiée (comme pour `/settings` storage) → fetch direct authentifié par la
|
|
31
|
-
// clé service_role, même pattern que storage-transform-e2e.test.ts.
|
|
32
|
-
//
|
|
33
|
-
// ── Piège trouvé et évité : `schema` dans le filtre postgres_changes ───────
|
|
34
|
-
// Le payload CDC (`build_payload`, cdc/postgres.rs:590-646) porte
|
|
35
|
-
// `"schema": change.schema` = le schéma PHYSIQUE `project_<uuid>` (PAS
|
|
36
|
-
// littéralement "public"). L'alias `db:public.{table}` (cdc/postgres.rs:528)
|
|
37
|
-
// n'est qu'un ALIAS DE ROUTAGE DE TOPIC (permet de s'abonner sans connaître
|
|
38
|
-
// le schéma interne) — il ne réécrit PAS le champ `schema` du payload livré.
|
|
39
|
-
// Si le filtre `.on('postgres_changes', { schema: 'public', ... })` était
|
|
40
|
-
// utilisé, la comparaison stricte `fs != schema` dans `event_matches_filters`
|
|
41
|
-
// (protocol.rs) EXCLURAIT alors TOUT event (fail-closed) puisque
|
|
42
|
-
// `"public" !== "project_<uuid>"` — et le fallback client (dispatch,
|
|
43
|
-
// AuraChannel.ts:423) ferait la même comparaison littérale en second rideau.
|
|
44
|
-
// Ce test omet donc volontairement `schema` dans le filtre (le champ est
|
|
45
|
-
// `Option<String>` côté serveur ET `schema?: string` côté SDK — absent ⇒
|
|
46
|
-
// check sauté, seuls `event`/`table`/`filter` s'appliquent), ce qui isole
|
|
47
|
-
// proprement le filtre COLONNE (objet de ce test) de ce défaut d'alias
|
|
48
|
-
// séparé (signalé ici, hors scope de A2 — potentiel suivi backlog).
|
|
49
|
-
//
|
|
50
|
-
// ── Auth WS ──────────────────────────────────────────────────────────────
|
|
51
|
-
// `GET /v1/realtime/ws` exige un VRAI JWT en query `?token=` (validate_jwt,
|
|
52
|
-
// handlers/websocket.rs:243-249) — une clé anon seule ne suffit pas. Le test
|
|
53
|
-
// signUp + signInWithPassword un utilisateur jetable via la clé anon pour
|
|
54
|
-
// peupler `authStore.token` avant `realtime.connect()`.
|
|
55
|
-
//
|
|
56
|
-
// Gaté par RUN_E2E + credentials (identique aux autres *-e2e.test.ts). Le
|
|
57
|
-
// run réel n'est PAS lancé ici (pas de creds dans cet environnement) — le
|
|
58
|
-
// contrôleur le fera après rebuild `aura-realtime`. Ce fichier doit
|
|
59
|
-
// seulement compiler et skip proprement (`describe.runIf`).
|
|
60
|
-
// ---------------------------------------------------------------------------
|
|
61
|
-
|
|
62
|
-
import { describe, it, expect } from 'vitest'
|
|
63
|
-
import { createClient, createAdminClient } from '../src/index'
|
|
64
|
-
import type { AuraResponse, RealtimeEvent, RealtimeSubscribeStatus } from '../src/index'
|
|
65
|
-
|
|
66
|
-
const URL = process.env.AURA_E2E_URL
|
|
67
|
-
const PROJECT = process.env.AURA_E2E_PROJECT
|
|
68
|
-
const ANON = process.env.AURA_E2E_ANON_KEY
|
|
69
|
-
const SERVICE = process.env.AURA_E2E_SERVICE_KEY
|
|
70
|
-
const RUN = Boolean(process.env.RUN_E2E && URL && PROJECT && ANON && SERVICE)
|
|
71
|
-
|
|
72
|
-
/** Statuts transitoires observés sur la stack locale (timeout gateway→service sous charge). */
|
|
73
|
-
const TRANSIENT_STATUS = new Set([408, 429, 502, 503, 504])
|
|
74
|
-
|
|
75
|
-
/** Rejoue une requête (AuraResponse) tant qu'elle renvoie un statut transitoire, borné. */
|
|
76
|
-
async function retryTransient<T>(fn: () => Promise<AuraResponse<T>>): Promise<AuraResponse<T>> {
|
|
77
|
-
let res = await fn()
|
|
78
|
-
for (let i = 0; i < 10 && res.error && TRANSIENT_STATUS.has(res.error.status); i++) {
|
|
79
|
-
await new Promise((r) => setTimeout(r, 1000))
|
|
80
|
-
res = await fn()
|
|
81
|
-
}
|
|
82
|
-
return res
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/** Rejoue un fetch() brut tant que le statut est transitoire, borné. */
|
|
86
|
-
async function retryFetchTransient(fn: () => Promise<Response>): Promise<Response> {
|
|
87
|
-
let res = await fn()
|
|
88
|
-
for (let i = 0; i < 10 && TRANSIENT_STATUS.has(res.status); i++) {
|
|
89
|
-
await new Promise((r) => setTimeout(r, 1000))
|
|
90
|
-
res = await fn()
|
|
91
|
-
}
|
|
92
|
-
return res
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function sleep(ms: number): Promise<void> {
|
|
96
|
-
return new Promise((r) => setTimeout(r, ms))
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
type CdcRecord = Record<string, unknown>
|
|
100
|
-
interface CdcPayload {
|
|
101
|
-
schema: string
|
|
102
|
-
table: string
|
|
103
|
-
type: 'INSERT' | 'UPDATE' | 'DELETE'
|
|
104
|
-
record: CdcRecord
|
|
105
|
-
old_record: CdcRecord | null
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Attend le PREMIER statut renvoyé par `channel.subscribe(cb)`, borné dans le temps.
|
|
110
|
-
* Retourne `'timeout'` si aucun statut n'arrive (WS/CDC pas prêt) — le test doit alors
|
|
111
|
-
* SKIPPER proprement plutôt que d'échouer sur une infra transitoire.
|
|
112
|
-
*/
|
|
113
|
-
function waitForSubscribeStatus(
|
|
114
|
-
doSubscribe: (cb: (status: RealtimeSubscribeStatus, err?: Error) => void) => void,
|
|
115
|
-
timeoutMs: number,
|
|
116
|
-
): Promise<{ status: RealtimeSubscribeStatus; err?: Error } | 'timeout'> {
|
|
117
|
-
return new Promise((resolve) => {
|
|
118
|
-
let done = false
|
|
119
|
-
const timer = setTimeout(() => {
|
|
120
|
-
if (!done) {
|
|
121
|
-
done = true
|
|
122
|
-
resolve('timeout')
|
|
123
|
-
}
|
|
124
|
-
}, timeoutMs)
|
|
125
|
-
doSubscribe((status, err) => {
|
|
126
|
-
if (done) return
|
|
127
|
-
done = true
|
|
128
|
-
clearTimeout(timer)
|
|
129
|
-
resolve({ status, err })
|
|
130
|
-
})
|
|
131
|
-
})
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
describe.runIf(RUN)('realtime filtre colonne E2E réel (stack live) — seuls les events matchant sont livrés', () => {
|
|
135
|
-
it(
|
|
136
|
-
'eq / gt / AND — le serveur ne délivre que les postgres_changes dont le record matche le filtre',
|
|
137
|
-
async () => {
|
|
138
|
-
const admin = createAdminClient(URL!, PROJECT!, SERVICE!)
|
|
139
|
-
const anon = createClient(URL!, PROJECT!, ANON!)
|
|
140
|
-
const suffix = process.env.AURA_E2E_SUFFIX ?? Math.random().toString(36).slice(2, 8)
|
|
141
|
-
const table = `rt_${suffix}`
|
|
142
|
-
// Le CDC calcule le RLS `allowed_sub_ids` sur le canal GÉNÉRIQUE au schéma
|
|
143
|
-
// PHYSIQUE (`project_<uuid>`), pas sur l'alias `db:public.*` (limite backend
|
|
144
|
-
// pré-existante : un abonné via l'alias public n'est jamais dans allowed_sub_ids).
|
|
145
|
-
// On s'abonne donc au canal générique pour recevoir les events.
|
|
146
|
-
const physicalSchema = `project_${PROJECT!.replace(/-/g, '_')}`
|
|
147
|
-
const channelName = `db:${physicalSchema}.${table}`
|
|
148
|
-
const email = `realtime-filter-e2e-${suffix}@aurabase.dev`
|
|
149
|
-
const password = 'EndUserPassword123!'
|
|
150
|
-
|
|
151
|
-
let tableCreated = false
|
|
152
|
-
let userId: string | null = null
|
|
153
|
-
|
|
154
|
-
try {
|
|
155
|
-
// -- 1. Setup service_role : table jetable + GRANT + reload PostgREST ----
|
|
156
|
-
await admin.db.sql(`DROP TABLE IF EXISTS ${table}`)
|
|
157
|
-
const createRes = await admin.db.sql(
|
|
158
|
-
`CREATE TABLE ${table} (
|
|
159
|
-
id serial PRIMARY KEY,
|
|
160
|
-
room_id int NOT NULL,
|
|
161
|
-
qty int NOT NULL DEFAULT 0,
|
|
162
|
-
name text NOT NULL DEFAULT '',
|
|
163
|
-
status text NOT NULL DEFAULT 'open'
|
|
164
|
-
)`,
|
|
165
|
-
)
|
|
166
|
-
if (createRes.error) {
|
|
167
|
-
// eslint-disable-next-line no-console
|
|
168
|
-
console.warn(
|
|
169
|
-
`[realtime-filter-e2e] SKIP (infra: CREATE TABLE a échoué — ${createRes.error.status} ` +
|
|
170
|
-
`${createRes.error.message ?? ''}) — table de test indisponible.`,
|
|
171
|
-
)
|
|
172
|
-
return
|
|
173
|
-
}
|
|
174
|
-
tableCreated = true
|
|
175
|
-
await admin.db.sql(`GRANT ALL ON ${table} TO PUBLIC`)
|
|
176
|
-
await admin.db.sql(`SELECT pg_notify('pgrst', 'reload schema')`)
|
|
177
|
-
|
|
178
|
-
// -- 2. Activer le realtime CDC pour cette table (service_role) ---------
|
|
179
|
-
const enableRes = await retryFetchTransient(() =>
|
|
180
|
-
fetch(`${admin.baseUrl}/v1/db/${admin.projectId}/schema/tables/${table}/realtime`, {
|
|
181
|
-
method: 'PUT',
|
|
182
|
-
headers: { apikey: SERVICE!, 'content-type': 'application/json' },
|
|
183
|
-
body: JSON.stringify({ enabled: true }),
|
|
184
|
-
}),
|
|
185
|
-
)
|
|
186
|
-
if (!enableRes.ok) {
|
|
187
|
-
// eslint-disable-next-line no-console
|
|
188
|
-
console.warn(
|
|
189
|
-
`[realtime-filter-e2e] SKIP (infra: PUT .../schema/tables/${table}/realtime → ` +
|
|
190
|
-
`${enableRes.status} — activation realtime indisponible dans ce contexte E2E).`,
|
|
191
|
-
)
|
|
192
|
-
return
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// -- 3. Utilisateur jetable (anon key) — le WS exige un vrai JWT --------
|
|
196
|
-
const signUpRes = await retryTransient(() => anon.auth.signUp({ email, password }))
|
|
197
|
-
if (signUpRes.error && TRANSIENT_STATUS.has(signUpRes.error.status)) {
|
|
198
|
-
// eslint-disable-next-line no-console
|
|
199
|
-
console.warn(
|
|
200
|
-
`[realtime-filter-e2e] SKIP (infra: signUp indisponible après retries — ` +
|
|
201
|
-
`${signUpRes.error.status} persistant).`,
|
|
202
|
-
)
|
|
203
|
-
return
|
|
204
|
-
}
|
|
205
|
-
expect(signUpRes.error).toBeNull()
|
|
206
|
-
|
|
207
|
-
const loginRes = await retryTransient(() => anon.auth.signInWithPassword({ email, password }))
|
|
208
|
-
if (loginRes.error && TRANSIENT_STATUS.has(loginRes.error.status)) {
|
|
209
|
-
// eslint-disable-next-line no-console
|
|
210
|
-
console.warn(
|
|
211
|
-
`[realtime-filter-e2e] SKIP (infra: signInWithPassword indisponible après retries — ` +
|
|
212
|
-
`${loginRes.error.status} persistant).`,
|
|
213
|
-
)
|
|
214
|
-
return
|
|
215
|
-
}
|
|
216
|
-
expect(loginRes.error).toBeNull()
|
|
217
|
-
const loginData = loginRes.data as { user: { id: string } } | null
|
|
218
|
-
userId = loginData?.user.id ?? null
|
|
219
|
-
|
|
220
|
-
// -- 4. Laisser le filtre CDC se rafraîchir (add-tables, ~3s) -----------
|
|
221
|
-
await sleep(4000)
|
|
222
|
-
|
|
223
|
-
// -- 5. Une seule connexion WS pour les 3 scénarios ---------------------
|
|
224
|
-
anon.realtime.connect()
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Un scénario = un channel FRAIS (même nom `db:public.<table>` — c'est
|
|
228
|
-
* l'alias de routage CDC, cf. commentaire en tête de fichier) avec UN SEUL
|
|
229
|
-
* listener `postgres_changes` (filtre isolé — pas de faux-négatif dû à un
|
|
230
|
-
* OR entre plusieurs filtres coexistant sur le même channel), un INSERT
|
|
231
|
-
* de deux lignes (une qui matche, une qui ne matche pas), une fenêtre de
|
|
232
|
-
* collecte bornée, puis une assertion stricte. Retourne `false` si le
|
|
233
|
-
* scénario doit SKIP (WS/CDC pas prêt) — auquel cas l'appelant arrête tout.
|
|
234
|
-
*/
|
|
235
|
-
async function runScenario(
|
|
236
|
-
label: string,
|
|
237
|
-
filter: string,
|
|
238
|
-
matchingRow: { room_id: number; qty: number; name: string; status: string },
|
|
239
|
-
nonMatchingRow: { room_id: number; qty: number; name: string; status: string },
|
|
240
|
-
): Promise<'ok' | 'skip'> {
|
|
241
|
-
const received: RealtimeEvent<CdcPayload>[] = []
|
|
242
|
-
const channel = anon.channel(channelName)
|
|
243
|
-
channel.on(
|
|
244
|
-
'postgres_changes',
|
|
245
|
-
// `schema` omis à dessein — voir commentaire en tête de fichier.
|
|
246
|
-
{ event: '*', table, filter },
|
|
247
|
-
(payload) => received.push(payload as RealtimeEvent<CdcPayload>),
|
|
248
|
-
)
|
|
249
|
-
|
|
250
|
-
const result = await waitForSubscribeStatus((cb) => channel.subscribe(cb), 15_000)
|
|
251
|
-
if (result === 'timeout' || result.status !== 'SUBSCRIBED') {
|
|
252
|
-
// eslint-disable-next-line no-console
|
|
253
|
-
console.warn(
|
|
254
|
-
`[realtime-filter-e2e] SKIP scénario ${label} (WS/CDC pas prêt — ` +
|
|
255
|
-
`${result === 'timeout' ? 'timeout attente SUBSCRIBED' : `statut ${result.status}`}).`,
|
|
256
|
-
)
|
|
257
|
-
anon.realtime.removeChannel(channelName)
|
|
258
|
-
return 'skip'
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
const insMatch = await admin.db.sql(
|
|
262
|
-
`INSERT INTO ${table} (room_id, qty, name, status) VALUES ($1, $2, $3, $4)`,
|
|
263
|
-
[matchingRow.room_id, matchingRow.qty, matchingRow.name, matchingRow.status],
|
|
264
|
-
)
|
|
265
|
-
expect(insMatch.error).toBeNull()
|
|
266
|
-
const insOther = await admin.db.sql(
|
|
267
|
-
`INSERT INTO ${table} (room_id, qty, name, status) VALUES ($1, $2, $3, $4)`,
|
|
268
|
-
[nonMatchingRow.room_id, nonMatchingRow.qty, nonMatchingRow.name, nonMatchingRow.status],
|
|
269
|
-
)
|
|
270
|
-
expect(insOther.error).toBeNull()
|
|
271
|
-
|
|
272
|
-
// Fenêtre de collecte CDC (poll WAL + refresh add-tables + latence pub/sub).
|
|
273
|
-
await sleep(8_000)
|
|
274
|
-
|
|
275
|
-
const matches = (r: CdcRecord | null | undefined, expected: typeof matchingRow): boolean =>
|
|
276
|
-
!!r && r.room_id === expected.room_id && r.qty === expected.qty
|
|
277
|
-
|
|
278
|
-
const gotMatching = received.some((e) => matches(e.payload.record, matchingRow))
|
|
279
|
-
const gotNonMatching = received.some((e) => matches(e.payload.record, nonMatchingRow))
|
|
280
|
-
|
|
281
|
-
expect(gotMatching).toBe(true)
|
|
282
|
-
expect(gotNonMatching).toBe(false)
|
|
283
|
-
|
|
284
|
-
anon.realtime.removeChannel(channelName)
|
|
285
|
-
return 'ok'
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// -- 6. Scénario eq : room_id=eq.42 --------------------------------------
|
|
289
|
-
const r1 = await runScenario(
|
|
290
|
-
'eq (room_id=eq.42)',
|
|
291
|
-
'room_id=eq.42',
|
|
292
|
-
{ room_id: 42, qty: 1, name: 'alpha', status: 'open' },
|
|
293
|
-
{ room_id: 7, qty: 1, name: 'beta', status: 'open' },
|
|
294
|
-
)
|
|
295
|
-
if (r1 === 'skip') return
|
|
296
|
-
|
|
297
|
-
// -- 7. Scénario gt : qty=gt.5 --------------------------------------------
|
|
298
|
-
const r2 = await runScenario(
|
|
299
|
-
'gt (qty=gt.5)',
|
|
300
|
-
'qty=gt.5',
|
|
301
|
-
{ room_id: 1, qty: 10, name: 'gamma', status: 'open' },
|
|
302
|
-
{ room_id: 1, qty: 1, name: 'delta', status: 'open' },
|
|
303
|
-
)
|
|
304
|
-
if (r2 === 'skip') return
|
|
305
|
-
|
|
306
|
-
// -- 8. Scénario AND : room_id=eq.42,qty=gt.5 -----------------------------
|
|
307
|
-
const r3 = await runScenario(
|
|
308
|
-
'AND (room_id=eq.42,qty=gt.5)',
|
|
309
|
-
'room_id=eq.42,qty=gt.5',
|
|
310
|
-
{ room_id: 42, qty: 10, name: 'epsilon', status: 'open' },
|
|
311
|
-
// Ne matche que la moitié du AND (room_id ok, qty non) — doit rester exclu.
|
|
312
|
-
{ room_id: 42, qty: 1, name: 'zeta', status: 'open' },
|
|
313
|
-
)
|
|
314
|
-
if (r3 === 'skip') return
|
|
315
|
-
} finally {
|
|
316
|
-
try {
|
|
317
|
-
anon.realtime.removeAllChannels()
|
|
318
|
-
} catch {
|
|
319
|
-
// best-effort cleanup
|
|
320
|
-
}
|
|
321
|
-
try {
|
|
322
|
-
anon.realtime.disconnect()
|
|
323
|
-
} catch {
|
|
324
|
-
// best-effort cleanup
|
|
325
|
-
}
|
|
326
|
-
if (userId) {
|
|
327
|
-
try {
|
|
328
|
-
await admin.authAdmin.deleteUser(userId)
|
|
329
|
-
} catch {
|
|
330
|
-
// best-effort cleanup
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
if (tableCreated) {
|
|
334
|
-
try {
|
|
335
|
-
await admin.db.sql(`DROP TABLE IF EXISTS ${table}`)
|
|
336
|
-
} catch {
|
|
337
|
-
// best-effort cleanup
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
},
|
|
342
|
-
120_000,
|
|
343
|
-
)
|
|
344
|
-
})
|