@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,485 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
RealtimeEvent,
|
|
3
|
-
RealtimeListenType,
|
|
4
|
-
PostgresChangesFilter,
|
|
5
|
-
BroadcastFilter,
|
|
6
|
-
PresenceFilter,
|
|
7
|
-
SubscribeCallback,
|
|
8
|
-
BroadcastPayload,
|
|
9
|
-
PresenceState,
|
|
10
|
-
PresenceInfo,
|
|
11
|
-
ServerMessage,
|
|
12
|
-
ServerSubscribedMsg,
|
|
13
|
-
ServerEventMsg,
|
|
14
|
-
ServerPresenceStateMsg,
|
|
15
|
-
ServerErrorMsg,
|
|
16
|
-
ChannelConfig,
|
|
17
|
-
} from '@aurabase/core'
|
|
18
|
-
import { matchesColumnFilter } from './columnFilter'
|
|
19
|
-
|
|
20
|
-
// ─── Internal types ─────────────────────────────────────────────────────────
|
|
21
|
-
|
|
22
|
-
type ListenerCallback = (payload: RealtimeEvent | Record<string, unknown>) => void
|
|
23
|
-
|
|
24
|
-
type ListenerEntry = {
|
|
25
|
-
type: RealtimeListenType
|
|
26
|
-
filter: PostgresChangesFilter | BroadcastFilter | PresenceFilter
|
|
27
|
-
callback: ListenerCallback
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
type SendFn = (data: string) => void
|
|
31
|
-
|
|
32
|
-
// ─── AuraChannel ────────────────────────────────────────────────────────────
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* A realtime channel with Supabase-compatible chainable API.
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* ```ts
|
|
39
|
-
* const channel = aura.channel('room-1')
|
|
40
|
-
* .on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'messages' }, (payload) => {
|
|
41
|
-
* console.log('New message:', payload)
|
|
42
|
-
* })
|
|
43
|
-
* .on('broadcast', { event: 'cursor-pos' }, (payload) => {
|
|
44
|
-
* console.log('Cursor:', payload)
|
|
45
|
-
* })
|
|
46
|
-
* .on('presence', { event: 'sync' }, () => {
|
|
47
|
-
* console.log('Presence synced:', channel.presenceState())
|
|
48
|
-
* })
|
|
49
|
-
* .subscribe((status) => {
|
|
50
|
-
* if (status === 'SUBSCRIBED') console.log('Connected!')
|
|
51
|
-
* })
|
|
52
|
-
* ```
|
|
53
|
-
*/
|
|
54
|
-
export class AuraChannel {
|
|
55
|
-
readonly name: string
|
|
56
|
-
private readonly _projectId: string
|
|
57
|
-
private readonly _listeners: ListenerEntry[] = []
|
|
58
|
-
private _subscribed = false
|
|
59
|
-
private _sendFn: SendFn | null = null
|
|
60
|
-
private _subscribeCallback: SubscribeCallback | null = null
|
|
61
|
-
private _presenceState: PresenceState = {}
|
|
62
|
-
private _isPrivate = false
|
|
63
|
-
private _broadcastAck = false
|
|
64
|
-
private _broadcastSelf = false
|
|
65
|
-
private _presenceKey = ''
|
|
66
|
-
/** ID de subscription retourné par le serveur (utilisé pour le filtre RLS allowed_sub_ids) */
|
|
67
|
-
private _subscriptionId: string | null = null
|
|
68
|
-
/** Compteur pour générer des ref_id uniques par connexion */
|
|
69
|
-
private _refCounter = 0
|
|
70
|
-
/** Dernier event ID recu — utilise pour since_id au reconnect */
|
|
71
|
-
private _lastEventId: string | null = null
|
|
72
|
-
/** Pending ACK callbacks : ref_id → resolve */
|
|
73
|
-
private _pendingAcks = new Map<string, () => void>()
|
|
74
|
-
|
|
75
|
-
constructor(name: string, projectId: string, options?: ChannelConfig) {
|
|
76
|
-
this.name = name
|
|
77
|
-
this._projectId = projectId
|
|
78
|
-
this._isPrivate = options?.private ?? false
|
|
79
|
-
this._broadcastAck = options?.broadcast?.ack ?? false
|
|
80
|
-
this._broadcastSelf = options?.broadcast?.self ?? false
|
|
81
|
-
this._presenceKey = options?.config?.presence?.key ?? ''
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/** Génère un ref_id unique pour la corrélation request/response. */
|
|
85
|
-
private _nextRef(): string {
|
|
86
|
-
return `${this.fullName}:r${++this._refCounter}`
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/** Full channel name with project prefix (for server protocol) */
|
|
90
|
-
get fullName(): string {
|
|
91
|
-
return `${this._projectId}:${this.name}`
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// ─── Chainable .on() ────────────────────────────────────────────────────
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Register a listener for a specific event type.
|
|
98
|
-
* Returns `this` for chaining.
|
|
99
|
-
*/
|
|
100
|
-
on(
|
|
101
|
-
type: 'postgres_changes',
|
|
102
|
-
filter: PostgresChangesFilter,
|
|
103
|
-
callback: (payload: RealtimeEvent) => void,
|
|
104
|
-
): this
|
|
105
|
-
on(
|
|
106
|
-
type: 'broadcast',
|
|
107
|
-
filter: BroadcastFilter,
|
|
108
|
-
callback: (payload: RealtimeEvent) => void,
|
|
109
|
-
): this
|
|
110
|
-
on(
|
|
111
|
-
type: 'presence',
|
|
112
|
-
filter: PresenceFilter,
|
|
113
|
-
callback: (payload: any) => void,
|
|
114
|
-
): this
|
|
115
|
-
on(
|
|
116
|
-
type: RealtimeListenType,
|
|
117
|
-
filter: PostgresChangesFilter | BroadcastFilter | PresenceFilter,
|
|
118
|
-
callback: (payload: any) => void,
|
|
119
|
-
): this {
|
|
120
|
-
this._listeners.push({ type, filter, callback })
|
|
121
|
-
return this
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// ─── Subscribe ──────────────────────────────────────────────────────────
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Subscribe to the channel. Sends the Subscribe message to the server
|
|
128
|
-
* with the full config (postgres_changes, broadcast, presence).
|
|
129
|
-
*/
|
|
130
|
-
subscribe(callback?: SubscribeCallback): this {
|
|
131
|
-
this._subscribeCallback = callback ?? null
|
|
132
|
-
this._subscribed = true
|
|
133
|
-
|
|
134
|
-
// Si le WS est déjà connecté (canal créé après une connexion existante),
|
|
135
|
-
// s'abonner immédiatement. Sinon, RealtimeService appellera _bindSend()
|
|
136
|
-
// puis _doSubscribe() depuis son handler ws.onopen une fois connecté.
|
|
137
|
-
if (this._sendFn) {
|
|
138
|
-
this._doSubscribe()
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return this
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/** Called by RealtimeService once the WS connection is ready. */
|
|
145
|
-
_bindSend(sendFn: SendFn): void {
|
|
146
|
-
this._sendFn = sendFn
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/** Send the subscribe message to the server. */
|
|
150
|
-
_doSubscribe(): void {
|
|
151
|
-
if (!this._sendFn) return
|
|
152
|
-
|
|
153
|
-
// Build postgres_changes config from listeners
|
|
154
|
-
const pgFilters = this._listeners
|
|
155
|
-
.filter((l) => l.type === 'postgres_changes')
|
|
156
|
-
.map((l) => l.filter as PostgresChangesFilter)
|
|
157
|
-
|
|
158
|
-
const msg = {
|
|
159
|
-
type: 'subscribe',
|
|
160
|
-
channel: this.fullName,
|
|
161
|
-
ref_id: this._nextRef(),
|
|
162
|
-
since_id: this._lastEventId ?? undefined,
|
|
163
|
-
config: {
|
|
164
|
-
postgres_changes: pgFilters,
|
|
165
|
-
broadcast: {
|
|
166
|
-
self_broadcast: this._broadcastSelf, // ← depuis les options du channel
|
|
167
|
-
ack: this._broadcastAck, // ← depuis les options du channel
|
|
168
|
-
},
|
|
169
|
-
presence: { key: this._presenceKey }, // ← depuis les options du channel
|
|
170
|
-
private: this._isPrivate,
|
|
171
|
-
},
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
this._sendFn(JSON.stringify(msg))
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/** Unsubscribe from the channel. */
|
|
178
|
-
unsubscribe(): void {
|
|
179
|
-
if (this._sendFn) {
|
|
180
|
-
this._sendFn(JSON.stringify({ type: 'unsubscribe', channel: this.fullName }))
|
|
181
|
-
}
|
|
182
|
-
this._subscribed = false
|
|
183
|
-
this._listeners.length = 0
|
|
184
|
-
this._presenceState = {}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// ─── Broadcast ──────────────────────────────────────────────────────────
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Send a broadcast message to the channel.
|
|
191
|
-
* If broadcast.ack=true, returns a Promise that resolves when the server ACKs.
|
|
192
|
-
*
|
|
193
|
-
* @example
|
|
194
|
-
* ```ts
|
|
195
|
-
* // Without ACK (fire & forget)
|
|
196
|
-
* channel.send({ type: 'broadcast', event: 'cursor-pos', payload: { x: 100, y: 200 } })
|
|
197
|
-
*
|
|
198
|
-
* // With ACK (wait for server confirmation)
|
|
199
|
-
* await channel.send({ type: 'broadcast', event: 'cursor-pos', payload: { x: 100 } })
|
|
200
|
-
* ```
|
|
201
|
-
*/
|
|
202
|
-
send(message: BroadcastPayload): Promise<'ok' | 'timeout' | 'error'> {
|
|
203
|
-
return new Promise((resolve) => {
|
|
204
|
-
if (!this._sendFn) {
|
|
205
|
-
resolve('error')
|
|
206
|
-
return
|
|
207
|
-
}
|
|
208
|
-
const ref_id = message.ref_id ?? this._nextRef()
|
|
209
|
-
|
|
210
|
-
// Si ack demandé, enregistrer un callback en attente
|
|
211
|
-
if (this._broadcastAck) {
|
|
212
|
-
const timer = setTimeout(() => {
|
|
213
|
-
this._pendingAcks.delete(ref_id)
|
|
214
|
-
resolve('timeout')
|
|
215
|
-
}, 5000)
|
|
216
|
-
|
|
217
|
-
this._pendingAcks.set(ref_id, () => {
|
|
218
|
-
clearTimeout(timer)
|
|
219
|
-
resolve('ok')
|
|
220
|
-
})
|
|
221
|
-
} else {
|
|
222
|
-
resolve('ok')
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
this._sendFn(
|
|
226
|
-
JSON.stringify({
|
|
227
|
-
type: 'broadcast',
|
|
228
|
-
channel: this.fullName,
|
|
229
|
-
ref_id,
|
|
230
|
-
payload: { event: message.event, ...message.payload },
|
|
231
|
-
}),
|
|
232
|
-
)
|
|
233
|
-
})
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// ─── Presence ───────────────────────────────────────────────────────────
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Track presence state for this client.
|
|
240
|
-
* Returns a Promise that resolves with 'ok' once tracked (compatible Supabase).
|
|
241
|
-
*
|
|
242
|
-
* @example
|
|
243
|
-
* ```ts
|
|
244
|
-
* await channel.track({ user: 'user-1', online_at: new Date().toISOString() })
|
|
245
|
-
* ```
|
|
246
|
-
*/
|
|
247
|
-
async track(state: Record<string, unknown>): Promise<'ok' | 'error'> {
|
|
248
|
-
if (!this._sendFn) return 'error'
|
|
249
|
-
this._sendFn(
|
|
250
|
-
JSON.stringify({
|
|
251
|
-
type: 'presence_update',
|
|
252
|
-
channel: this.fullName,
|
|
253
|
-
meta: state,
|
|
254
|
-
}),
|
|
255
|
-
)
|
|
256
|
-
return 'ok'
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
/** Stop tracking presence. */
|
|
260
|
-
async untrack(): Promise<'ok' | 'error'> {
|
|
261
|
-
return this.track({})
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
/** Get the current presence state for this channel. */
|
|
265
|
-
presenceState(): PresenceState {
|
|
266
|
-
return { ...this._presenceState }
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
// ─── Internal: dispatch server messages ──────────────────────────────────
|
|
270
|
-
|
|
271
|
-
/** Called by RealtimeService when a server message arrives for this channel. */
|
|
272
|
-
_onMessage(msg: ServerMessage): void {
|
|
273
|
-
switch (msg.type) {
|
|
274
|
-
case 'subscribed': {
|
|
275
|
-
const subMsg = msg as ServerSubscribedMsg
|
|
276
|
-
if (subMsg.subscription_id) this._subscriptionId = subMsg.subscription_id
|
|
277
|
-
this._subscribeCallback?.('SUBSCRIBED')
|
|
278
|
-
break
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
case 'event': {
|
|
282
|
-
// Serde flatten : les champs de RealtimeEvent sont au top-level du JSON
|
|
283
|
-
// ServerEventMsg a les champs id, event, topic, payload, timestamp directement
|
|
284
|
-
const evtMsg = msg as ServerEventMsg
|
|
285
|
-
if (evtMsg.id) {
|
|
286
|
-
const event: RealtimeEvent = {
|
|
287
|
-
id: evtMsg.id,
|
|
288
|
-
event: evtMsg.event as RealtimeEvent['event'],
|
|
289
|
-
topic: evtMsg.topic,
|
|
290
|
-
payload: evtMsg.payload,
|
|
291
|
-
timestamp: evtMsg.timestamp,
|
|
292
|
-
allowed_sub_ids: evtMsg.allowed_sub_ids,
|
|
293
|
-
}
|
|
294
|
-
this._dispatchEvent(event)
|
|
295
|
-
}
|
|
296
|
-
break
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
case 'presence_state': {
|
|
300
|
-
const presMsg = msg as ServerPresenceStateMsg
|
|
301
|
-
if (presMsg.presences) {
|
|
302
|
-
this._presenceState = {}
|
|
303
|
-
for (const p of presMsg.presences) {
|
|
304
|
-
const key = p.user_id || p.client_id
|
|
305
|
-
if (!this._presenceState[key]) this._presenceState[key] = []
|
|
306
|
-
this._presenceState[key].push(p)
|
|
307
|
-
}
|
|
308
|
-
for (const l of this._listeners) {
|
|
309
|
-
if (l.type === 'presence' && (l.filter as PresenceFilter).event === 'sync') {
|
|
310
|
-
l.callback(this._presenceState)
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
break
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
case 'error': {
|
|
318
|
-
const errMsg = msg as ServerErrorMsg
|
|
319
|
-
this._subscribeCallback?.('CHANNEL_ERROR', new Error(errMsg.message ?? 'Unknown error'))
|
|
320
|
-
break
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
case 'token_refreshed':
|
|
324
|
-
break
|
|
325
|
-
|
|
326
|
-
case 'broadcast_ack': {
|
|
327
|
-
// Résoudre le pending ACK si ref_id présent
|
|
328
|
-
const ackMsg = msg as { type: 'broadcast_ack'; ref_id?: string; message_id?: string }
|
|
329
|
-
const refId = ackMsg.ref_id ?? ackMsg.message_id
|
|
330
|
-
if (refId) {
|
|
331
|
-
const resolve = this._pendingAcks.get(refId)
|
|
332
|
-
if (resolve) {
|
|
333
|
-
this._pendingAcks.delete(refId)
|
|
334
|
-
resolve()
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
break
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
/** Dispatch a RealtimeEvent to matching listeners. */
|
|
343
|
-
private _dispatchEvent(event: RealtimeEvent): void {
|
|
344
|
-
if (!event) return
|
|
345
|
-
|
|
346
|
-
// Tracker le dernier event ID pour since_id au reconnect
|
|
347
|
-
if (event.id) this._lastEventId = event.id
|
|
348
|
-
|
|
349
|
-
// Filtre RLS : si l'event a une liste allowed_sub_ids et que notre subscription_id
|
|
350
|
-
// n'y figure pas, ne pas dispatcher (defense-in-depth côté client)
|
|
351
|
-
const allowed = event.allowed_sub_ids
|
|
352
|
-
if (allowed && this._subscriptionId && !allowed.includes(this._subscriptionId)) {
|
|
353
|
-
return
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
const eventType = event.event // 'insert', 'update', 'delete', 'broadcast', 'presence'
|
|
357
|
-
|
|
358
|
-
// Mettre à jour l'état de présence local avant de notifier les écouteurs
|
|
359
|
-
if (eventType === 'presence') {
|
|
360
|
-
const payload = event.payload as Record<string, unknown>
|
|
361
|
-
const action = payload.action as string
|
|
362
|
-
const key = (payload.user_id || payload.client_id) as string
|
|
363
|
-
|
|
364
|
-
if (action === 'join') {
|
|
365
|
-
if (!this._presenceState[key]) this._presenceState[key] = []
|
|
366
|
-
if (!this._presenceState[key].some(p => p.client_id === payload.client_id)) {
|
|
367
|
-
const presenceInfo: PresenceInfo = {
|
|
368
|
-
client_id: payload.client_id as string,
|
|
369
|
-
user_id: (payload.user_id as string) ?? undefined,
|
|
370
|
-
metadata: (payload.metadata ?? payload.meta ?? {}) as Record<string, unknown>,
|
|
371
|
-
joined_at: new Date().toISOString(),
|
|
372
|
-
last_seen: new Date().toISOString(),
|
|
373
|
-
}
|
|
374
|
-
this._presenceState[key].push(presenceInfo)
|
|
375
|
-
}
|
|
376
|
-
} else if (action === 'leave') {
|
|
377
|
-
const arr = this._presenceState[key]
|
|
378
|
-
if (arr) {
|
|
379
|
-
const idx = arr.findIndex((p) => p.client_id === payload.client_id)
|
|
380
|
-
if (idx >= 0) arr.splice(idx, 1)
|
|
381
|
-
if (arr.length === 0) delete this._presenceState[key]
|
|
382
|
-
}
|
|
383
|
-
} else if (action === 'update') {
|
|
384
|
-
const arr = this._presenceState[key]
|
|
385
|
-
if (arr) {
|
|
386
|
-
const idx = arr.findIndex((p) => p.client_id === payload.client_id)
|
|
387
|
-
if (idx >= 0) {
|
|
388
|
-
arr[idx].metadata = (payload.metadata ?? payload.meta ?? {}) as Record<string, unknown>
|
|
389
|
-
arr[idx].last_seen = new Date().toISOString()
|
|
390
|
-
} else {
|
|
391
|
-
const presenceInfo: PresenceInfo = {
|
|
392
|
-
client_id: payload.client_id as string,
|
|
393
|
-
user_id: (payload.user_id as string) ?? undefined,
|
|
394
|
-
metadata: (payload.metadata ?? payload.meta ?? {}) as Record<string, unknown>,
|
|
395
|
-
joined_at: new Date().toISOString(),
|
|
396
|
-
last_seen: new Date().toISOString(),
|
|
397
|
-
}
|
|
398
|
-
this._presenceState[key].push(presenceInfo)
|
|
399
|
-
}
|
|
400
|
-
} else {
|
|
401
|
-
this._presenceState[key] = [{
|
|
402
|
-
client_id: payload.client_id as string,
|
|
403
|
-
user_id: (payload.user_id as string) ?? undefined,
|
|
404
|
-
metadata: (payload.metadata ?? payload.meta ?? {}) as Record<string, unknown>,
|
|
405
|
-
joined_at: new Date().toISOString(),
|
|
406
|
-
last_seen: new Date().toISOString(),
|
|
407
|
-
}]
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
for (const listener of this._listeners) {
|
|
413
|
-
if (listener.type === 'postgres_changes') {
|
|
414
|
-
const filter = listener.filter as PostgresChangesFilter
|
|
415
|
-
if (
|
|
416
|
-
eventType === 'insert' ||
|
|
417
|
-
eventType === 'update' ||
|
|
418
|
-
eventType === 'delete'
|
|
419
|
-
) {
|
|
420
|
-
const filterEvent = filter.event.toLowerCase()
|
|
421
|
-
if (filterEvent === '*' || filterEvent === eventType) {
|
|
422
|
-
// Check schema/table if specified
|
|
423
|
-
const payload = event.payload as Record<string, unknown>
|
|
424
|
-
if (filter.schema && payload.schema !== filter.schema) continue
|
|
425
|
-
if (filter.table && payload.table !== filter.table) continue
|
|
426
|
-
|
|
427
|
-
// Second rideau client (defense-in-depth) : le serveur a déjà filtré
|
|
428
|
-
// par colonne de façon autoritaire. DELETE -> old_record (record CDC
|
|
429
|
-
// vide) ; INSERT/UPDATE -> record. Si la cible est absente/non-objet,
|
|
430
|
-
// ne pas filtrer (éviter un faux négatif sur un payload sans record).
|
|
431
|
-
if (filter.filter) {
|
|
432
|
-
const target = eventType === 'delete' ? payload.old_record : payload.record
|
|
433
|
-
if (target && typeof target === 'object') {
|
|
434
|
-
if (!matchesColumnFilter(filter.filter, target as Record<string, unknown>)) {
|
|
435
|
-
continue
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
listener.callback(event)
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
} else if (listener.type === 'broadcast') {
|
|
444
|
-
if (eventType === 'broadcast') {
|
|
445
|
-
const filter = listener.filter as BroadcastFilter
|
|
446
|
-
const payload = event.payload as Record<string, unknown>
|
|
447
|
-
// Match broadcast event name if specified
|
|
448
|
-
if (!filter.event || payload.event === filter.event) {
|
|
449
|
-
listener.callback(event)
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
} else if (listener.type === 'presence') {
|
|
453
|
-
if (eventType === 'presence') {
|
|
454
|
-
const filter = listener.filter as PresenceFilter
|
|
455
|
-
const payload = event.payload as Record<string, unknown>
|
|
456
|
-
const action = payload.action as string
|
|
457
|
-
|
|
458
|
-
if (filter.event === 'join' && action === 'join') {
|
|
459
|
-
listener.callback({
|
|
460
|
-
key: payload.user_id || payload.client_id,
|
|
461
|
-
newPresences: [payload],
|
|
462
|
-
})
|
|
463
|
-
} else if (filter.event === 'leave' && action === 'leave') {
|
|
464
|
-
listener.callback({
|
|
465
|
-
key: payload.user_id || payload.client_id,
|
|
466
|
-
leftPresences: [payload],
|
|
467
|
-
})
|
|
468
|
-
} else if (filter.event === 'sync') {
|
|
469
|
-
listener.callback(this.presenceState())
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
/** Whether this channel has been subscribed. */
|
|
477
|
-
get isSubscribed(): boolean {
|
|
478
|
-
return this._subscribed
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
/** Get listeners (for re-subscribe after reconnect). */
|
|
482
|
-
_getListeners(): ListenerEntry[] {
|
|
483
|
-
return this._listeners
|
|
484
|
-
}
|
|
485
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HeartbeatManager — pings périodiques pour maintenir la connexion WS.
|
|
3
|
-
* Utilise un Worker dédié (anti-throttle des onglets en arrière-plan) ; fallback setInterval.
|
|
4
|
-
*/
|
|
5
|
-
export class HeartbeatManager {
|
|
6
|
-
private _worker: Worker | null = null
|
|
7
|
-
private _workerUrl: string | null = null
|
|
8
|
-
private _interval: ReturnType<typeof setInterval> | null = null
|
|
9
|
-
private _sendFn: (() => void) | null = null
|
|
10
|
-
|
|
11
|
-
start(sendPing: () => void, intervalMs = 25000): void {
|
|
12
|
-
this.stop()
|
|
13
|
-
this._sendFn = sendPing
|
|
14
|
-
|
|
15
|
-
if (typeof Worker !== 'undefined' && typeof URL !== 'undefined' && typeof URL.createObjectURL === 'function') {
|
|
16
|
-
try {
|
|
17
|
-
const code = `let i=null;onmessage=(e)=>{if(e.data.type==='start'){if(i)clearInterval(i);i=setInterval(()=>postMessage('ping'),e.data.interval||25000);}else if(e.data.type==='stop'){if(i){clearInterval(i);i=null;}}};`
|
|
18
|
-
const blob = new Blob([code], { type: 'application/javascript' })
|
|
19
|
-
this._workerUrl = URL.createObjectURL(blob)
|
|
20
|
-
this._worker = new Worker(this._workerUrl)
|
|
21
|
-
this._worker.onmessage = () => {
|
|
22
|
-
this._sendFn?.()
|
|
23
|
-
}
|
|
24
|
-
this._worker.postMessage({ type: 'start', interval: intervalMs })
|
|
25
|
-
return
|
|
26
|
-
} catch {
|
|
27
|
-
// Worker indispo/CSP → fallback
|
|
28
|
-
this._worker = null
|
|
29
|
-
if (this._workerUrl) {
|
|
30
|
-
try {
|
|
31
|
-
URL.revokeObjectURL(this._workerUrl)
|
|
32
|
-
} catch {
|
|
33
|
-
/* ignore */
|
|
34
|
-
}
|
|
35
|
-
this._workerUrl = null
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
this._interval = setInterval(() => {
|
|
41
|
-
this._sendFn?.()
|
|
42
|
-
}, intervalMs)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
stop(): void {
|
|
46
|
-
if (this._worker) {
|
|
47
|
-
try {
|
|
48
|
-
this._worker.postMessage({ type: 'stop' })
|
|
49
|
-
this._worker.terminate()
|
|
50
|
-
} catch {
|
|
51
|
-
/* ignore */
|
|
52
|
-
}
|
|
53
|
-
this._worker = null
|
|
54
|
-
}
|
|
55
|
-
if (this._workerUrl) {
|
|
56
|
-
try {
|
|
57
|
-
URL.revokeObjectURL(this._workerUrl)
|
|
58
|
-
} catch {
|
|
59
|
-
/* ignore */
|
|
60
|
-
}
|
|
61
|
-
this._workerUrl = null
|
|
62
|
-
}
|
|
63
|
-
if (this._interval) {
|
|
64
|
-
clearInterval(this._interval)
|
|
65
|
-
this._interval = null
|
|
66
|
-
}
|
|
67
|
-
this._sendFn = null
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
get isActive(): boolean {
|
|
71
|
-
return this._worker !== null || this._interval !== null
|
|
72
|
-
}
|
|
73
|
-
}
|