@zshannon/streamstore 0.22.3
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/LICENSE +21 -0
- package/README.md +93 -0
- package/dist/cjs/accessTokens.d.ts +51 -0
- package/dist/cjs/accessTokens.d.ts.map +1 -0
- package/dist/cjs/accessTokens.js +127 -0
- package/dist/cjs/accessTokens.js.map +1 -0
- package/dist/cjs/auth/biscuit.d.ts +42 -0
- package/dist/cjs/auth/biscuit.d.ts.map +1 -0
- package/dist/cjs/auth/biscuit.js +72 -0
- package/dist/cjs/auth/biscuit.js.map +1 -0
- package/dist/cjs/auth/index.d.ts +5 -0
- package/dist/cjs/auth/index.d.ts.map +1 -0
- package/dist/cjs/auth/index.js +14 -0
- package/dist/cjs/auth/index.js.map +1 -0
- package/dist/cjs/auth/pki-auth.d.ts +60 -0
- package/dist/cjs/auth/pki-auth.d.ts.map +1 -0
- package/dist/cjs/auth/pki-auth.js +102 -0
- package/dist/cjs/auth/pki-auth.js.map +1 -0
- package/dist/cjs/auth/sign.d.ts +39 -0
- package/dist/cjs/auth/sign.d.ts.map +1 -0
- package/dist/cjs/auth/sign.js +128 -0
- package/dist/cjs/auth/sign.js.map +1 -0
- package/dist/cjs/auth/signing-key.d.ts +42 -0
- package/dist/cjs/auth/signing-key.d.ts.map +1 -0
- package/dist/cjs/auth/signing-key.js +66 -0
- package/dist/cjs/auth/signing-key.js.map +1 -0
- package/dist/cjs/basin.d.ts +33 -0
- package/dist/cjs/basin.d.ts.map +1 -0
- package/dist/cjs/basin.js +54 -0
- package/dist/cjs/basin.js.map +1 -0
- package/dist/cjs/basins.d.ts +62 -0
- package/dist/cjs/basins.d.ts.map +1 -0
- package/dist/cjs/basins.js +201 -0
- package/dist/cjs/basins.js.map +1 -0
- package/dist/cjs/batch-transform.d.ts +60 -0
- package/dist/cjs/batch-transform.d.ts.map +1 -0
- package/dist/cjs/batch-transform.js +171 -0
- package/dist/cjs/batch-transform.js.map +1 -0
- package/dist/cjs/common.d.ts +156 -0
- package/dist/cjs/common.d.ts.map +1 -0
- package/dist/cjs/common.js +54 -0
- package/dist/cjs/common.js.map +1 -0
- package/dist/cjs/endpoints.d.ts +63 -0
- package/dist/cjs/endpoints.d.ts.map +1 -0
- package/dist/cjs/endpoints.js +120 -0
- package/dist/cjs/endpoints.js.map +1 -0
- package/dist/cjs/error.d.ts +119 -0
- package/dist/cjs/error.d.ts.map +1 -0
- package/dist/cjs/error.js +373 -0
- package/dist/cjs/error.js.map +1 -0
- package/dist/cjs/generated/client/client.gen.d.ts +3 -0
- package/dist/cjs/generated/client/client.gen.d.ts.map +1 -0
- package/dist/cjs/generated/client/client.gen.js +209 -0
- package/dist/cjs/generated/client/client.gen.js.map +1 -0
- package/dist/cjs/generated/client/index.d.ts +9 -0
- package/dist/cjs/generated/client/index.d.ts.map +1 -0
- package/dist/cjs/generated/client/index.js +18 -0
- package/dist/cjs/generated/client/index.js.map +1 -0
- package/dist/cjs/generated/client/types.gen.d.ts +125 -0
- package/dist/cjs/generated/client/types.gen.d.ts.map +1 -0
- package/dist/cjs/generated/client/types.gen.js +4 -0
- package/dist/cjs/generated/client/types.gen.js.map +1 -0
- package/dist/cjs/generated/client/utils.gen.d.ts +34 -0
- package/dist/cjs/generated/client/utils.gen.d.ts.map +1 -0
- package/dist/cjs/generated/client/utils.gen.js +243 -0
- package/dist/cjs/generated/client/utils.gen.js.map +1 -0
- package/dist/cjs/generated/client.gen.d.ts +13 -0
- package/dist/cjs/generated/client.gen.d.ts.map +1 -0
- package/dist/cjs/generated/client.gen.js +9 -0
- package/dist/cjs/generated/client.gen.js.map +1 -0
- package/dist/cjs/generated/core/auth.gen.d.ts +19 -0
- package/dist/cjs/generated/core/auth.gen.d.ts.map +1 -0
- package/dist/cjs/generated/core/auth.gen.js +19 -0
- package/dist/cjs/generated/core/auth.gen.js.map +1 -0
- package/dist/cjs/generated/core/bodySerializer.gen.d.ts +26 -0
- package/dist/cjs/generated/core/bodySerializer.gen.d.ts.map +1 -0
- package/dist/cjs/generated/core/bodySerializer.gen.js +61 -0
- package/dist/cjs/generated/core/bodySerializer.gen.js.map +1 -0
- package/dist/cjs/generated/core/params.gen.d.ts +44 -0
- package/dist/cjs/generated/core/params.gen.d.ts.map +1 -0
- package/dist/cjs/generated/core/params.gen.js +105 -0
- package/dist/cjs/generated/core/params.gen.js.map +1 -0
- package/dist/cjs/generated/core/pathSerializer.gen.d.ts +34 -0
- package/dist/cjs/generated/core/pathSerializer.gen.d.ts.map +1 -0
- package/dist/cjs/generated/core/pathSerializer.gen.js +124 -0
- package/dist/cjs/generated/core/pathSerializer.gen.js.map +1 -0
- package/dist/cjs/generated/core/queryKeySerializer.gen.d.ts +19 -0
- package/dist/cjs/generated/core/queryKeySerializer.gen.d.ts.map +1 -0
- package/dist/cjs/generated/core/queryKeySerializer.gen.js +106 -0
- package/dist/cjs/generated/core/queryKeySerializer.gen.js.map +1 -0
- package/dist/cjs/generated/core/serverSentEvents.gen.d.ts +72 -0
- package/dist/cjs/generated/core/serverSentEvents.gen.d.ts.map +1 -0
- package/dist/cjs/generated/core/serverSentEvents.gen.js +140 -0
- package/dist/cjs/generated/core/serverSentEvents.gen.js.map +1 -0
- package/dist/cjs/generated/core/types.gen.d.ts +79 -0
- package/dist/cjs/generated/core/types.gen.d.ts.map +1 -0
- package/dist/cjs/generated/core/types.gen.js +4 -0
- package/dist/cjs/generated/core/types.gen.js.map +1 -0
- package/dist/cjs/generated/core/utils.gen.d.ts +20 -0
- package/dist/cjs/generated/core/utils.gen.d.ts.map +1 -0
- package/dist/cjs/generated/core/utils.gen.js +94 -0
- package/dist/cjs/generated/core/utils.gen.js.map +1 -0
- package/dist/cjs/generated/index.d.ts +3 -0
- package/dist/cjs/generated/index.d.ts.map +1 -0
- package/dist/cjs/generated/index.js +19 -0
- package/dist/cjs/generated/index.js.map +1 -0
- package/dist/cjs/generated/proto/s2.d.ts +250 -0
- package/dist/cjs/generated/proto/s2.d.ts.map +1 -0
- package/dist/cjs/generated/proto/s2.js +426 -0
- package/dist/cjs/generated/proto/s2.js.map +1 -0
- package/dist/cjs/generated/sdk.gen.d.ts +100 -0
- package/dist/cjs/generated/sdk.gen.d.ts.map +1 -0
- package/dist/cjs/generated/sdk.gen.js +374 -0
- package/dist/cjs/generated/sdk.gen.js.map +1 -0
- package/dist/cjs/generated/types.gen.d.ts +1064 -0
- package/dist/cjs/generated/types.gen.d.ts.map +1 -0
- package/dist/cjs/generated/types.gen.js +4 -0
- package/dist/cjs/generated/types.gen.js.map +1 -0
- package/dist/cjs/index.d.ts +42 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +81 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/internal/case-transform.d.ts +59 -0
- package/dist/cjs/internal/case-transform.d.ts.map +1 -0
- package/dist/cjs/internal/case-transform.js +80 -0
- package/dist/cjs/internal/case-transform.js.map +1 -0
- package/dist/cjs/internal/mappers.d.ts +51 -0
- package/dist/cjs/internal/mappers.d.ts.map +1 -0
- package/dist/cjs/internal/mappers.js +225 -0
- package/dist/cjs/internal/mappers.js.map +1 -0
- package/dist/cjs/internal/sdk-types.d.ts +127 -0
- package/dist/cjs/internal/sdk-types.d.ts.map +1 -0
- package/dist/cjs/internal/sdk-types.js +9 -0
- package/dist/cjs/internal/sdk-types.js.map +1 -0
- package/dist/cjs/lib/base64.d.ts +12 -0
- package/dist/cjs/lib/base64.d.ts.map +1 -0
- package/dist/cjs/lib/base64.js +172 -0
- package/dist/cjs/lib/base64.js.map +1 -0
- package/dist/cjs/lib/event-stream.d.ts +26 -0
- package/dist/cjs/lib/event-stream.d.ts.map +1 -0
- package/dist/cjs/lib/event-stream.js +154 -0
- package/dist/cjs/lib/event-stream.js.map +1 -0
- package/dist/cjs/lib/paginate.d.ts +61 -0
- package/dist/cjs/lib/paginate.d.ts.map +1 -0
- package/dist/cjs/lib/paginate.js +51 -0
- package/dist/cjs/lib/paginate.js.map +1 -0
- package/dist/cjs/lib/redacted.d.ts +17 -0
- package/dist/cjs/lib/redacted.d.ts.map +1 -0
- package/dist/cjs/lib/redacted.js +34 -0
- package/dist/cjs/lib/redacted.js.map +1 -0
- package/dist/cjs/lib/result.d.ts +57 -0
- package/dist/cjs/lib/result.d.ts.map +1 -0
- package/dist/cjs/lib/result.js +43 -0
- package/dist/cjs/lib/result.js.map +1 -0
- package/dist/cjs/lib/retry.d.ts +167 -0
- package/dist/cjs/lib/retry.d.ts.map +1 -0
- package/dist/cjs/lib/retry.js +1011 -0
- package/dist/cjs/lib/retry.js.map +1 -0
- package/dist/cjs/lib/stream/factory.d.ts +14 -0
- package/dist/cjs/lib/stream/factory.d.ts.map +1 -0
- package/dist/cjs/lib/stream/factory.js +35 -0
- package/dist/cjs/lib/stream/factory.js.map +1 -0
- package/dist/cjs/lib/stream/runtime.d.ts +27 -0
- package/dist/cjs/lib/stream/runtime.d.ts.map +1 -0
- package/dist/cjs/lib/stream/runtime.js +70 -0
- package/dist/cjs/lib/stream/runtime.js.map +1 -0
- package/dist/cjs/lib/stream/transport/fetch/index.d.ts +64 -0
- package/dist/cjs/lib/stream/transport/fetch/index.d.ts.map +1 -0
- package/dist/cjs/lib/stream/transport/fetch/index.js +462 -0
- package/dist/cjs/lib/stream/transport/fetch/index.js.map +1 -0
- package/dist/cjs/lib/stream/transport/fetch/shared.d.ts +11 -0
- package/dist/cjs/lib/stream/transport/fetch/shared.d.ts.map +1 -0
- package/dist/cjs/lib/stream/transport/fetch/shared.js +118 -0
- package/dist/cjs/lib/stream/transport/fetch/shared.js.map +1 -0
- package/dist/cjs/lib/stream/transport/proto.d.ts +9 -0
- package/dist/cjs/lib/stream/transport/proto.d.ts.map +1 -0
- package/dist/cjs/lib/stream/transport/proto.js +118 -0
- package/dist/cjs/lib/stream/transport/proto.js.map +1 -0
- package/dist/cjs/lib/stream/transport/s2s/framing.d.ts +47 -0
- package/dist/cjs/lib/stream/transport/s2s/framing.d.ts.map +1 -0
- package/dist/cjs/lib/stream/transport/s2s/framing.js +123 -0
- package/dist/cjs/lib/stream/transport/s2s/framing.js.map +1 -0
- package/dist/cjs/lib/stream/transport/s2s/index.d.ts +24 -0
- package/dist/cjs/lib/stream/transport/s2s/index.d.ts.map +1 -0
- package/dist/cjs/lib/stream/transport/s2s/index.js +823 -0
- package/dist/cjs/lib/stream/transport/s2s/index.js.map +1 -0
- package/dist/cjs/lib/stream/types.d.ts +199 -0
- package/dist/cjs/lib/stream/types.d.ts.map +1 -0
- package/dist/cjs/lib/stream/types.js +21 -0
- package/dist/cjs/lib/stream/types.js.map +1 -0
- package/dist/cjs/metrics.d.ts +46 -0
- package/dist/cjs/metrics.d.ts.map +1 -0
- package/dist/cjs/metrics.js +127 -0
- package/dist/cjs/metrics.js.map +1 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/producer.d.ts +82 -0
- package/dist/cjs/producer.d.ts.map +1 -0
- package/dist/cjs/producer.js +305 -0
- package/dist/cjs/producer.js.map +1 -0
- package/dist/cjs/s2.d.ts +41 -0
- package/dist/cjs/s2.d.ts.map +1 -0
- package/dist/cjs/s2.js +119 -0
- package/dist/cjs/s2.js.map +1 -0
- package/dist/cjs/stream.d.ts +78 -0
- package/dist/cjs/stream.d.ts.map +1 -0
- package/dist/cjs/stream.js +176 -0
- package/dist/cjs/stream.js.map +1 -0
- package/dist/cjs/streams.d.ts +61 -0
- package/dist/cjs/streams.d.ts.map +1 -0
- package/dist/cjs/streams.js +201 -0
- package/dist/cjs/streams.js.map +1 -0
- package/dist/cjs/types.d.ts +633 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +129 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/cjs/utils.d.ts +25 -0
- package/dist/cjs/utils.d.ts.map +1 -0
- package/dist/cjs/utils.js +108 -0
- package/dist/cjs/utils.js.map +1 -0
- package/dist/cjs/version.d.ts +8 -0
- package/dist/cjs/version.d.ts.map +1 -0
- package/dist/cjs/version.js +11 -0
- package/dist/cjs/version.js.map +1 -0
- package/dist/esm/accessTokens.d.ts +51 -0
- package/dist/esm/accessTokens.d.ts.map +1 -0
- package/dist/esm/accessTokens.js +123 -0
- package/dist/esm/accessTokens.js.map +1 -0
- package/dist/esm/auth/biscuit.d.ts +42 -0
- package/dist/esm/auth/biscuit.d.ts.map +1 -0
- package/dist/esm/auth/biscuit.js +68 -0
- package/dist/esm/auth/biscuit.js.map +1 -0
- package/dist/esm/auth/index.d.ts +5 -0
- package/dist/esm/auth/index.d.ts.map +1 -0
- package/dist/esm/auth/index.js +5 -0
- package/dist/esm/auth/index.js.map +1 -0
- package/dist/esm/auth/pki-auth.d.ts +60 -0
- package/dist/esm/auth/pki-auth.d.ts.map +1 -0
- package/dist/esm/auth/pki-auth.js +99 -0
- package/dist/esm/auth/pki-auth.js.map +1 -0
- package/dist/esm/auth/sign.d.ts +39 -0
- package/dist/esm/auth/sign.d.ts.map +1 -0
- package/dist/esm/auth/sign.js +125 -0
- package/dist/esm/auth/sign.js.map +1 -0
- package/dist/esm/auth/signing-key.d.ts +42 -0
- package/dist/esm/auth/signing-key.d.ts.map +1 -0
- package/dist/esm/auth/signing-key.js +62 -0
- package/dist/esm/auth/signing-key.js.map +1 -0
- package/dist/esm/basin.d.ts +33 -0
- package/dist/esm/basin.d.ts.map +1 -0
- package/dist/esm/basin.js +50 -0
- package/dist/esm/basin.js.map +1 -0
- package/dist/esm/basins.d.ts +62 -0
- package/dist/esm/basins.d.ts.map +1 -0
- package/dist/esm/basins.js +197 -0
- package/dist/esm/basins.js.map +1 -0
- package/dist/esm/batch-transform.d.ts +60 -0
- package/dist/esm/batch-transform.d.ts.map +1 -0
- package/dist/esm/batch-transform.js +167 -0
- package/dist/esm/batch-transform.js.map +1 -0
- package/dist/esm/common.d.ts +156 -0
- package/dist/esm/common.d.ts.map +1 -0
- package/dist/esm/common.js +49 -0
- package/dist/esm/common.js.map +1 -0
- package/dist/esm/endpoints.d.ts +63 -0
- package/dist/esm/endpoints.d.ts.map +1 -0
- package/dist/esm/endpoints.js +115 -0
- package/dist/esm/endpoints.js.map +1 -0
- package/dist/esm/error.d.ts +119 -0
- package/dist/esm/error.d.ts.map +1 -0
- package/dist/esm/error.js +358 -0
- package/dist/esm/error.js.map +1 -0
- package/dist/esm/generated/client/client.gen.d.ts +3 -0
- package/dist/esm/generated/client/client.gen.d.ts.map +1 -0
- package/dist/esm/generated/client/client.gen.js +205 -0
- package/dist/esm/generated/client/client.gen.js.map +1 -0
- package/dist/esm/generated/client/index.d.ts +9 -0
- package/dist/esm/generated/client/index.d.ts.map +1 -0
- package/dist/esm/generated/client/index.js +7 -0
- package/dist/esm/generated/client/index.js.map +1 -0
- package/dist/esm/generated/client/types.gen.d.ts +125 -0
- package/dist/esm/generated/client/types.gen.d.ts.map +1 -0
- package/dist/esm/generated/client/types.gen.js +3 -0
- package/dist/esm/generated/client/types.gen.js.map +1 -0
- package/dist/esm/generated/client/utils.gen.d.ts +34 -0
- package/dist/esm/generated/client/utils.gen.d.ts.map +1 -0
- package/dist/esm/generated/client/utils.gen.js +232 -0
- package/dist/esm/generated/client/utils.gen.js.map +1 -0
- package/dist/esm/generated/client.gen.d.ts +13 -0
- package/dist/esm/generated/client.gen.d.ts.map +1 -0
- package/dist/esm/generated/client.gen.js +6 -0
- package/dist/esm/generated/client.gen.js.map +1 -0
- package/dist/esm/generated/core/auth.gen.d.ts +19 -0
- package/dist/esm/generated/core/auth.gen.d.ts.map +1 -0
- package/dist/esm/generated/core/auth.gen.js +15 -0
- package/dist/esm/generated/core/auth.gen.js.map +1 -0
- package/dist/esm/generated/core/bodySerializer.gen.d.ts +26 -0
- package/dist/esm/generated/core/bodySerializer.gen.d.ts.map +1 -0
- package/dist/esm/generated/core/bodySerializer.gen.js +58 -0
- package/dist/esm/generated/core/bodySerializer.gen.js.map +1 -0
- package/dist/esm/generated/core/params.gen.d.ts +44 -0
- package/dist/esm/generated/core/params.gen.d.ts.map +1 -0
- package/dist/esm/generated/core/params.gen.js +101 -0
- package/dist/esm/generated/core/params.gen.js.map +1 -0
- package/dist/esm/generated/core/pathSerializer.gen.d.ts +34 -0
- package/dist/esm/generated/core/pathSerializer.gen.d.ts.map +1 -0
- package/dist/esm/generated/core/pathSerializer.gen.js +115 -0
- package/dist/esm/generated/core/pathSerializer.gen.js.map +1 -0
- package/dist/esm/generated/core/queryKeySerializer.gen.d.ts +19 -0
- package/dist/esm/generated/core/queryKeySerializer.gen.d.ts.map +1 -0
- package/dist/esm/generated/core/queryKeySerializer.gen.js +100 -0
- package/dist/esm/generated/core/queryKeySerializer.gen.js.map +1 -0
- package/dist/esm/generated/core/serverSentEvents.gen.d.ts +72 -0
- package/dist/esm/generated/core/serverSentEvents.gen.d.ts.map +1 -0
- package/dist/esm/generated/core/serverSentEvents.gen.js +136 -0
- package/dist/esm/generated/core/serverSentEvents.gen.js.map +1 -0
- package/dist/esm/generated/core/types.gen.d.ts +79 -0
- package/dist/esm/generated/core/types.gen.d.ts.map +1 -0
- package/dist/esm/generated/core/types.gen.js +3 -0
- package/dist/esm/generated/core/types.gen.js.map +1 -0
- package/dist/esm/generated/core/utils.gen.d.ts +20 -0
- package/dist/esm/generated/core/utils.gen.d.ts.map +1 -0
- package/dist/esm/generated/core/utils.gen.js +88 -0
- package/dist/esm/generated/core/utils.gen.js.map +1 -0
- package/dist/esm/generated/index.d.ts +3 -0
- package/dist/esm/generated/index.d.ts.map +1 -0
- package/dist/esm/generated/index.js +3 -0
- package/dist/esm/generated/index.js.map +1 -0
- package/dist/esm/generated/proto/s2.d.ts +250 -0
- package/dist/esm/generated/proto/s2.d.ts.map +1 -0
- package/dist/esm/generated/proto/s2.js +423 -0
- package/dist/esm/generated/proto/s2.js.map +1 -0
- package/dist/esm/generated/sdk.gen.d.ts +100 -0
- package/dist/esm/generated/sdk.gen.d.ts.map +1 -0
- package/dist/esm/generated/sdk.gen.js +350 -0
- package/dist/esm/generated/sdk.gen.js.map +1 -0
- package/dist/esm/generated/types.gen.d.ts +1064 -0
- package/dist/esm/generated/types.gen.d.ts.map +1 -0
- package/dist/esm/generated/types.gen.js +3 -0
- package/dist/esm/generated/types.gen.js.map +1 -0
- package/dist/esm/index.d.ts +42 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +47 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/internal/case-transform.d.ts +59 -0
- package/dist/esm/internal/case-transform.d.ts.map +1 -0
- package/dist/esm/internal/case-transform.js +76 -0
- package/dist/esm/internal/case-transform.js.map +1 -0
- package/dist/esm/internal/mappers.d.ts +51 -0
- package/dist/esm/internal/mappers.d.ts.map +1 -0
- package/dist/esm/internal/mappers.js +218 -0
- package/dist/esm/internal/mappers.js.map +1 -0
- package/dist/esm/internal/sdk-types.d.ts +127 -0
- package/dist/esm/internal/sdk-types.d.ts.map +1 -0
- package/dist/esm/internal/sdk-types.js +8 -0
- package/dist/esm/internal/sdk-types.js.map +1 -0
- package/dist/esm/lib/base64.d.ts +12 -0
- package/dist/esm/lib/base64.d.ts.map +1 -0
- package/dist/esm/lib/base64.js +165 -0
- package/dist/esm/lib/base64.js.map +1 -0
- package/dist/esm/lib/event-stream.d.ts +26 -0
- package/dist/esm/lib/event-stream.d.ts.map +1 -0
- package/dist/esm/lib/event-stream.js +150 -0
- package/dist/esm/lib/event-stream.js.map +1 -0
- package/dist/esm/lib/paginate.d.ts +61 -0
- package/dist/esm/lib/paginate.d.ts.map +1 -0
- package/dist/esm/lib/paginate.js +48 -0
- package/dist/esm/lib/paginate.js.map +1 -0
- package/dist/esm/lib/redacted.d.ts +17 -0
- package/dist/esm/lib/redacted.d.ts.map +1 -0
- package/dist/esm/lib/redacted.js +28 -0
- package/dist/esm/lib/redacted.js.map +1 -0
- package/dist/esm/lib/result.d.ts +57 -0
- package/dist/esm/lib/result.d.ts.map +1 -0
- package/dist/esm/lib/result.js +37 -0
- package/dist/esm/lib/result.js.map +1 -0
- package/dist/esm/lib/retry.d.ts +167 -0
- package/dist/esm/lib/retry.d.ts.map +1 -0
- package/dist/esm/lib/retry.js +1003 -0
- package/dist/esm/lib/retry.js.map +1 -0
- package/dist/esm/lib/stream/factory.d.ts +14 -0
- package/dist/esm/lib/stream/factory.d.ts.map +1 -0
- package/dist/esm/lib/stream/factory.js +32 -0
- package/dist/esm/lib/stream/factory.js.map +1 -0
- package/dist/esm/lib/stream/runtime.d.ts +27 -0
- package/dist/esm/lib/stream/runtime.d.ts.map +1 -0
- package/dist/esm/lib/stream/runtime.js +71 -0
- package/dist/esm/lib/stream/runtime.js.map +1 -0
- package/dist/esm/lib/stream/transport/fetch/index.d.ts +64 -0
- package/dist/esm/lib/stream/transport/fetch/index.d.ts.map +1 -0
- package/dist/esm/lib/stream/transport/fetch/index.js +456 -0
- package/dist/esm/lib/stream/transport/fetch/index.js.map +1 -0
- package/dist/esm/lib/stream/transport/fetch/shared.d.ts +11 -0
- package/dist/esm/lib/stream/transport/fetch/shared.d.ts.map +1 -0
- package/dist/esm/lib/stream/transport/fetch/shared.js +114 -0
- package/dist/esm/lib/stream/transport/fetch/shared.js.map +1 -0
- package/dist/esm/lib/stream/transport/proto.d.ts +9 -0
- package/dist/esm/lib/stream/transport/proto.d.ts.map +1 -0
- package/dist/esm/lib/stream/transport/proto.js +110 -0
- package/dist/esm/lib/stream/transport/proto.js.map +1 -0
- package/dist/esm/lib/stream/transport/s2s/framing.d.ts +47 -0
- package/dist/esm/lib/stream/transport/s2s/framing.d.ts.map +1 -0
- package/dist/esm/lib/stream/transport/s2s/framing.js +118 -0
- package/dist/esm/lib/stream/transport/s2s/framing.js.map +1 -0
- package/dist/esm/lib/stream/transport/s2s/index.d.ts +24 -0
- package/dist/esm/lib/stream/transport/s2s/index.d.ts.map +1 -0
- package/dist/esm/lib/stream/transport/s2s/index.js +819 -0
- package/dist/esm/lib/stream/transport/s2s/index.js.map +1 -0
- package/dist/esm/lib/stream/types.d.ts +199 -0
- package/dist/esm/lib/stream/types.d.ts.map +1 -0
- package/dist/esm/lib/stream/types.js +18 -0
- package/dist/esm/lib/stream/types.js.map +1 -0
- package/dist/esm/metrics.d.ts +46 -0
- package/dist/esm/metrics.d.ts.map +1 -0
- package/dist/esm/metrics.js +122 -0
- package/dist/esm/metrics.js.map +1 -0
- package/dist/esm/producer.d.ts +82 -0
- package/dist/esm/producer.d.ts.map +1 -0
- package/dist/esm/producer.js +300 -0
- package/dist/esm/producer.js.map +1 -0
- package/dist/esm/s2.d.ts +41 -0
- package/dist/esm/s2.d.ts.map +1 -0
- package/dist/esm/s2.js +115 -0
- package/dist/esm/s2.js.map +1 -0
- package/dist/esm/stream.d.ts +78 -0
- package/dist/esm/stream.d.ts.map +1 -0
- package/dist/esm/stream.js +172 -0
- package/dist/esm/stream.js.map +1 -0
- package/dist/esm/streams.d.ts +61 -0
- package/dist/esm/streams.d.ts.map +1 -0
- package/dist/esm/streams.js +197 -0
- package/dist/esm/streams.js.map +1 -0
- package/dist/esm/types.d.ts +633 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +126 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/utils.d.ts +25 -0
- package/dist/esm/utils.d.ts.map +1 -0
- package/dist/esm/utils.js +103 -0
- package/dist/esm/utils.js.map +1 -0
- package/dist/esm/version.d.ts +8 -0
- package/dist/esm/version.d.ts.map +1 -0
- package/dist/esm/version.js +8 -0
- package/dist/esm/version.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1,823 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* S2S HTTP/2 transport for Node.js
|
|
4
|
+
* Uses the s2s binary protocol over HTTP/2 for efficient streaming
|
|
5
|
+
*
|
|
6
|
+
* This file should only be imported in Node.js environments
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.S2STransport = void 0;
|
|
10
|
+
const debug_1 = require("debug");
|
|
11
|
+
const error_js_1 = require("../../../../error.js");
|
|
12
|
+
const Proto = require("../../../../generated/proto/s2.js");
|
|
13
|
+
const result_js_1 = require("../../../result.js");
|
|
14
|
+
const retry_js_1 = require("../../../retry.js");
|
|
15
|
+
const runtime_js_1 = require("../../runtime.js");
|
|
16
|
+
const proto_js_1 = require("../proto.js");
|
|
17
|
+
const framing_js_1 = require("./framing.js");
|
|
18
|
+
/**
|
|
19
|
+
* Gets the auth token from an auth provider.
|
|
20
|
+
*/
|
|
21
|
+
async function getAuthToken(authProvider) {
|
|
22
|
+
if (authProvider.type === "pki") {
|
|
23
|
+
return authProvider.context.getToken();
|
|
24
|
+
}
|
|
25
|
+
return authProvider.token;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Signs headers if using PKI auth.
|
|
29
|
+
*/
|
|
30
|
+
async function signHeadersIfPki(authProvider, headers, method, url, body) {
|
|
31
|
+
if (authProvider.type === "pki") {
|
|
32
|
+
await authProvider.context.signHeaders({ method, url, headers, body });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const debug = (0, debug_1.default)("s2:s2s");
|
|
36
|
+
let http2ModulePromise;
|
|
37
|
+
async function loadHttp2() {
|
|
38
|
+
// Hint bundlers to skip bundling node:http2 while keeping the specifier static for type inference.
|
|
39
|
+
if (!http2ModulePromise) {
|
|
40
|
+
http2ModulePromise = Promise.resolve().then(() => require(
|
|
41
|
+
/* webpackIgnore: true */
|
|
42
|
+
/* @vite-ignore */
|
|
43
|
+
"node:http2"));
|
|
44
|
+
}
|
|
45
|
+
return http2ModulePromise;
|
|
46
|
+
}
|
|
47
|
+
class S2STransport {
|
|
48
|
+
transportConfig;
|
|
49
|
+
connection;
|
|
50
|
+
connectionPromise;
|
|
51
|
+
closingPromise;
|
|
52
|
+
constructor(config) {
|
|
53
|
+
this.transportConfig = config;
|
|
54
|
+
}
|
|
55
|
+
async makeAppendSession(stream, sessionOptions, requestOptions) {
|
|
56
|
+
return retry_js_1.RetryAppendSession.create((myOptions) => {
|
|
57
|
+
return S2SAppendSession.create(this.transportConfig.baseUrl, this.transportConfig.authProvider, stream, () => this.getConnection(), this.transportConfig.basinName, myOptions, requestOptions);
|
|
58
|
+
}, sessionOptions, this.transportConfig.retry, stream);
|
|
59
|
+
}
|
|
60
|
+
async makeReadSession(stream, args, options) {
|
|
61
|
+
return retry_js_1.RetryReadSession.create((myArgs) => {
|
|
62
|
+
return S2SReadSession.create(this.transportConfig.baseUrl, this.transportConfig.authProvider, stream, myArgs, options, () => this.getConnection(), this.transportConfig.basinName);
|
|
63
|
+
}, args, this.transportConfig.retry);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get or create HTTP/2 connection (one per transport)
|
|
67
|
+
*/
|
|
68
|
+
async getConnection() {
|
|
69
|
+
if (this.connection &&
|
|
70
|
+
!this.connection.closed &&
|
|
71
|
+
!this.connection.destroyed) {
|
|
72
|
+
return this.connection;
|
|
73
|
+
}
|
|
74
|
+
// If connection is in progress, wait for it
|
|
75
|
+
if (this.connectionPromise) {
|
|
76
|
+
return this.connectionPromise;
|
|
77
|
+
}
|
|
78
|
+
// Create new connection
|
|
79
|
+
this.connectionPromise = this.createConnection();
|
|
80
|
+
try {
|
|
81
|
+
this.connection = await this.connectionPromise;
|
|
82
|
+
return this.connection;
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
this.connectionPromise = undefined;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
async createConnection() {
|
|
89
|
+
const http2 = await loadHttp2();
|
|
90
|
+
const url = new URL(this.transportConfig.baseUrl);
|
|
91
|
+
const client = http2.connect(url.origin, {
|
|
92
|
+
// Use HTTPS settings
|
|
93
|
+
...(url.protocol === "https:"
|
|
94
|
+
? {
|
|
95
|
+
// TLS options can go here if needed
|
|
96
|
+
}
|
|
97
|
+
: {}),
|
|
98
|
+
settings: {
|
|
99
|
+
initialWindowSize: 10 * 1024 * 1024, // 10 MB
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
const connectPromise = new Promise((resolve, reject) => {
|
|
103
|
+
client.once("connect", () => {
|
|
104
|
+
// Guard against session being destroyed before connect fires
|
|
105
|
+
if (client.destroyed)
|
|
106
|
+
return;
|
|
107
|
+
client.setLocalWindowSize(10 * 1024 * 1024);
|
|
108
|
+
resolve(client);
|
|
109
|
+
});
|
|
110
|
+
client.once("error", (err) => {
|
|
111
|
+
reject(err);
|
|
112
|
+
});
|
|
113
|
+
// Handle connection close
|
|
114
|
+
client.once("close", () => {
|
|
115
|
+
if (this.connection === client) {
|
|
116
|
+
this.connection = undefined;
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
// Apply connection timeout if configured
|
|
121
|
+
const connectionTimeout = this.transportConfig.connectionTimeoutMillis ?? 3000;
|
|
122
|
+
let timeoutId;
|
|
123
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
124
|
+
timeoutId = setTimeout(() => {
|
|
125
|
+
// Destroy the client on timeout
|
|
126
|
+
if (!client.closed && !client.destroyed) {
|
|
127
|
+
client.destroy();
|
|
128
|
+
}
|
|
129
|
+
reject(new error_js_1.S2Error({
|
|
130
|
+
message: `Connection timeout after ${connectionTimeout}ms`,
|
|
131
|
+
status: 408,
|
|
132
|
+
code: "CONNECTION_TIMEOUT",
|
|
133
|
+
origin: "sdk",
|
|
134
|
+
}));
|
|
135
|
+
}, connectionTimeout);
|
|
136
|
+
});
|
|
137
|
+
try {
|
|
138
|
+
return await Promise.race([connectPromise, timeoutPromise]);
|
|
139
|
+
}
|
|
140
|
+
finally {
|
|
141
|
+
if (timeoutId) {
|
|
142
|
+
clearTimeout(timeoutId);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
async close() {
|
|
147
|
+
if (this.closingPromise) {
|
|
148
|
+
return this.closingPromise;
|
|
149
|
+
}
|
|
150
|
+
this.closingPromise = (async () => {
|
|
151
|
+
const connection = this.connection ??
|
|
152
|
+
(await this.connectionPromise?.catch(() => undefined));
|
|
153
|
+
if (connection && !connection.closed && !connection.destroyed) {
|
|
154
|
+
await new Promise((resolve) => {
|
|
155
|
+
connection.close(() => resolve());
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
this.connection = undefined;
|
|
159
|
+
})();
|
|
160
|
+
try {
|
|
161
|
+
await this.closingPromise;
|
|
162
|
+
}
|
|
163
|
+
finally {
|
|
164
|
+
this.closingPromise = undefined;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
exports.S2STransport = S2STransport;
|
|
169
|
+
class S2SReadSession extends ReadableStream {
|
|
170
|
+
streamName;
|
|
171
|
+
args;
|
|
172
|
+
authProvider;
|
|
173
|
+
url;
|
|
174
|
+
options;
|
|
175
|
+
getConnection;
|
|
176
|
+
basinName;
|
|
177
|
+
http2Stream;
|
|
178
|
+
_lastReadPosition;
|
|
179
|
+
_nextReadPosition;
|
|
180
|
+
_lastObservedTail;
|
|
181
|
+
parser = new framing_js_1.S2SFrameParser();
|
|
182
|
+
static async create(baseUrl, authProvider, streamName, args, options, getConnection, basinName) {
|
|
183
|
+
const url = new URL(baseUrl);
|
|
184
|
+
return new S2SReadSession(streamName, args, authProvider, url, options, getConnection, basinName);
|
|
185
|
+
}
|
|
186
|
+
constructor(streamName, args, authProvider, url, options, getConnection, basinName) {
|
|
187
|
+
// Initialize parser and textDecoder before super() call
|
|
188
|
+
const parser = new framing_js_1.S2SFrameParser();
|
|
189
|
+
const textDecoder = new TextDecoder();
|
|
190
|
+
let http2Stream;
|
|
191
|
+
let lastReadPosition;
|
|
192
|
+
// Track timeout for detecting when server stops sending data
|
|
193
|
+
const TAIL_TIMEOUT_MS = 20000; // 20 seconds
|
|
194
|
+
let timeoutTimer;
|
|
195
|
+
super({
|
|
196
|
+
start: async (controller) => {
|
|
197
|
+
let controllerClosed = false;
|
|
198
|
+
let responseCode;
|
|
199
|
+
const safeClose = () => {
|
|
200
|
+
if (!controllerClosed) {
|
|
201
|
+
controllerClosed = true;
|
|
202
|
+
if (timeoutTimer) {
|
|
203
|
+
clearTimeout(timeoutTimer);
|
|
204
|
+
timeoutTimer = undefined;
|
|
205
|
+
}
|
|
206
|
+
try {
|
|
207
|
+
controller.close();
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
// Controller may already be closed, ignore
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
const safeError = (err) => {
|
|
215
|
+
if (!controllerClosed) {
|
|
216
|
+
controllerClosed = true;
|
|
217
|
+
if (timeoutTimer) {
|
|
218
|
+
clearTimeout(timeoutTimer);
|
|
219
|
+
timeoutTimer = undefined;
|
|
220
|
+
}
|
|
221
|
+
// Convert error to S2Error and enqueue as error result
|
|
222
|
+
controller.enqueue({ ok: false, error: (0, error_js_1.s2Error)(err) });
|
|
223
|
+
controller.close();
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
// Helper to start/reset the timeout timer
|
|
227
|
+
// Resets on every tail received, fires only if no tail for 20s
|
|
228
|
+
const resetTimeoutTimer = () => {
|
|
229
|
+
if (timeoutTimer) {
|
|
230
|
+
clearTimeout(timeoutTimer);
|
|
231
|
+
}
|
|
232
|
+
timeoutTimer = setTimeout(() => {
|
|
233
|
+
const timeoutError = new error_js_1.S2Error({
|
|
234
|
+
message: `No tail received for ${TAIL_TIMEOUT_MS / 1000}s`,
|
|
235
|
+
status: 408, // Request Timeout
|
|
236
|
+
code: "TIMEOUT",
|
|
237
|
+
});
|
|
238
|
+
debug("tail timeout detected");
|
|
239
|
+
safeError(timeoutError);
|
|
240
|
+
}, TAIL_TIMEOUT_MS);
|
|
241
|
+
};
|
|
242
|
+
try {
|
|
243
|
+
// Start the timeout timer - will fire in 20s if no tail received
|
|
244
|
+
resetTimeoutTimer();
|
|
245
|
+
const connection = await getConnection();
|
|
246
|
+
// Build query string
|
|
247
|
+
const queryParams = new URLSearchParams();
|
|
248
|
+
const { as, ...readParams } = args ?? {};
|
|
249
|
+
if (readParams.seq_num !== undefined)
|
|
250
|
+
queryParams.set("seq_num", readParams.seq_num.toString());
|
|
251
|
+
if (readParams.timestamp !== undefined)
|
|
252
|
+
queryParams.set("timestamp", readParams.timestamp.toString());
|
|
253
|
+
if (readParams.tail_offset !== undefined)
|
|
254
|
+
queryParams.set("tail_offset", readParams.tail_offset.toString());
|
|
255
|
+
if (readParams.count !== undefined)
|
|
256
|
+
queryParams.set("count", readParams.count.toString());
|
|
257
|
+
if (readParams.bytes !== undefined)
|
|
258
|
+
queryParams.set("bytes", readParams.bytes.toString());
|
|
259
|
+
if (readParams.wait !== undefined)
|
|
260
|
+
queryParams.set("wait", readParams.wait.toString());
|
|
261
|
+
if (typeof readParams.until === "number") {
|
|
262
|
+
queryParams.set("until", readParams.until.toString());
|
|
263
|
+
}
|
|
264
|
+
const queryString = queryParams.toString();
|
|
265
|
+
const path = `${url.pathname}/streams/${encodeURIComponent(streamName)}/records${queryString ? `?${queryString}` : ""}`;
|
|
266
|
+
const fullUrl = `${url.protocol}//${url.host}${path}`;
|
|
267
|
+
// Get auth token
|
|
268
|
+
const token = await getAuthToken(authProvider);
|
|
269
|
+
// Build headers
|
|
270
|
+
// Note: We include both :authority (HTTP/2 pseudo-header) and host (for proxy compatibility)
|
|
271
|
+
const headers = {
|
|
272
|
+
":method": "GET",
|
|
273
|
+
":path": path,
|
|
274
|
+
":scheme": url.protocol.slice(0, -1),
|
|
275
|
+
":authority": url.host,
|
|
276
|
+
host: url.host, // Some proxies (like Fly.io) may need this for proper forwarding
|
|
277
|
+
"user-agent": runtime_js_1.DEFAULT_USER_AGENT,
|
|
278
|
+
authorization: `Bearer ${token}`,
|
|
279
|
+
accept: "application/protobuf",
|
|
280
|
+
"content-type": "s2s/proto",
|
|
281
|
+
...(basinName ? { "s2-basin": basinName } : {}),
|
|
282
|
+
};
|
|
283
|
+
// Sign headers if using PKI auth
|
|
284
|
+
await signHeadersIfPki(authProvider, headers, "GET", fullUrl);
|
|
285
|
+
const stream = connection.request(headers);
|
|
286
|
+
http2Stream = stream;
|
|
287
|
+
options?.signal?.addEventListener("abort", () => {
|
|
288
|
+
if (!stream.closed) {
|
|
289
|
+
stream.close();
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
stream.on("response", (headers) => {
|
|
293
|
+
// Cache the status.
|
|
294
|
+
// This informs whether we should attempt to parse s2s frames in the "data" handler.
|
|
295
|
+
responseCode = headers[":status"] ?? 500;
|
|
296
|
+
});
|
|
297
|
+
connection.on("goaway", (errorCode, lastStreamID, opaqueData) => {
|
|
298
|
+
debug("received GOAWAY from server");
|
|
299
|
+
});
|
|
300
|
+
stream.on("error", (err) => {
|
|
301
|
+
safeError(err);
|
|
302
|
+
});
|
|
303
|
+
stream.on("data", (chunk) => {
|
|
304
|
+
try {
|
|
305
|
+
const status = responseCode ?? 500;
|
|
306
|
+
if (status >= 400) {
|
|
307
|
+
const errorText = textDecoder.decode(chunk);
|
|
308
|
+
debug("error response: status=%d body=%s", status, errorText);
|
|
309
|
+
if (status === 416) {
|
|
310
|
+
try {
|
|
311
|
+
const errorJson = JSON.parse(errorText);
|
|
312
|
+
safeError(new error_js_1.RangeNotSatisfiableError({
|
|
313
|
+
status,
|
|
314
|
+
code: errorJson.code,
|
|
315
|
+
tail: errorJson.tail,
|
|
316
|
+
}));
|
|
317
|
+
}
|
|
318
|
+
catch {
|
|
319
|
+
safeError(new error_js_1.RangeNotSatisfiableError({ status }));
|
|
320
|
+
}
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
try {
|
|
324
|
+
const errorJson = JSON.parse(errorText);
|
|
325
|
+
safeError(new error_js_1.S2Error({
|
|
326
|
+
message: errorJson.message ?? "Unknown error",
|
|
327
|
+
code: errorJson.code,
|
|
328
|
+
status,
|
|
329
|
+
origin: "server",
|
|
330
|
+
}));
|
|
331
|
+
}
|
|
332
|
+
catch {
|
|
333
|
+
safeError(new error_js_1.S2Error({
|
|
334
|
+
message: errorText || "Unknown error",
|
|
335
|
+
status,
|
|
336
|
+
origin: "server",
|
|
337
|
+
}));
|
|
338
|
+
}
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
// Buffer already extends Uint8Array in Node.js, no need to convert
|
|
342
|
+
parser.push(chunk);
|
|
343
|
+
let frame = parser.parseFrame();
|
|
344
|
+
while (frame) {
|
|
345
|
+
if (frame.terminal) {
|
|
346
|
+
if (frame.statusCode && frame.statusCode >= 400) {
|
|
347
|
+
const errorText = textDecoder.decode(frame.body);
|
|
348
|
+
try {
|
|
349
|
+
const errorJson = JSON.parse(errorText);
|
|
350
|
+
const status = frame.statusCode ?? 500;
|
|
351
|
+
// Map known read errors
|
|
352
|
+
if (status === 416) {
|
|
353
|
+
safeError(new error_js_1.RangeNotSatisfiableError({
|
|
354
|
+
status,
|
|
355
|
+
code: errorJson.code,
|
|
356
|
+
tail: errorJson.tail,
|
|
357
|
+
}));
|
|
358
|
+
}
|
|
359
|
+
else {
|
|
360
|
+
safeError((0, error_js_1.makeServerError)({ status, statusText: undefined }, errorJson));
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
catch {
|
|
364
|
+
safeError((0, error_js_1.makeServerError)({
|
|
365
|
+
status: frame.statusCode ?? 500,
|
|
366
|
+
statusText: undefined,
|
|
367
|
+
}, errorText));
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
else {
|
|
371
|
+
safeClose();
|
|
372
|
+
}
|
|
373
|
+
stream.close();
|
|
374
|
+
}
|
|
375
|
+
else {
|
|
376
|
+
// Parse ReadBatch
|
|
377
|
+
try {
|
|
378
|
+
const protoBatch = Proto.ReadBatch.fromBinary(frame.body);
|
|
379
|
+
resetTimeoutTimer();
|
|
380
|
+
// Update tail from batch
|
|
381
|
+
if (protoBatch.tail) {
|
|
382
|
+
const tail = convertStreamPosition(protoBatch.tail);
|
|
383
|
+
lastReadPosition = tail;
|
|
384
|
+
this._lastReadPosition = tail;
|
|
385
|
+
this._lastObservedTail = tail;
|
|
386
|
+
debug("received tail");
|
|
387
|
+
}
|
|
388
|
+
// Enqueue each record and track next position
|
|
389
|
+
for (const record of protoBatch.records) {
|
|
390
|
+
const converted = this.convertRecord(record, as ?? "string", textDecoder);
|
|
391
|
+
controller.enqueue({ ok: true, value: converted });
|
|
392
|
+
// Update next read position to after this record
|
|
393
|
+
if (record.seqNum !== undefined) {
|
|
394
|
+
this._nextReadPosition = {
|
|
395
|
+
seq_num: Number(record.seqNum) + 1,
|
|
396
|
+
timestamp: Number(record.timestamp ?? 0n),
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
catch (err) {
|
|
402
|
+
safeError(new error_js_1.S2Error({
|
|
403
|
+
message: `Failed to parse ReadBatch: ${err}`,
|
|
404
|
+
status: 500,
|
|
405
|
+
origin: "sdk",
|
|
406
|
+
}));
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
frame = parser.parseFrame();
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
catch (error) {
|
|
413
|
+
safeError(error instanceof error_js_1.S2Error
|
|
414
|
+
? error
|
|
415
|
+
: new error_js_1.S2Error({
|
|
416
|
+
message: `Failed to process read data: ${error}`,
|
|
417
|
+
status: 500,
|
|
418
|
+
origin: "sdk",
|
|
419
|
+
}));
|
|
420
|
+
}
|
|
421
|
+
});
|
|
422
|
+
stream.on("end", () => {
|
|
423
|
+
if (stream.rstCode != 0) {
|
|
424
|
+
debug("stream reset code=%d", stream.rstCode);
|
|
425
|
+
safeError(new error_js_1.S2Error({
|
|
426
|
+
message: `Stream ended with error: ${stream.rstCode}`,
|
|
427
|
+
status: 500,
|
|
428
|
+
code: "stream reset",
|
|
429
|
+
origin: "sdk",
|
|
430
|
+
}));
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
stream.on("close", () => {
|
|
434
|
+
if (parser.hasData()) {
|
|
435
|
+
safeError(new error_js_1.S2Error({
|
|
436
|
+
message: "Stream closed with unparsed data remaining",
|
|
437
|
+
status: 500,
|
|
438
|
+
code: "STREAM_CLOSED_PREMATURELY",
|
|
439
|
+
origin: "sdk",
|
|
440
|
+
}));
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
safeClose();
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
catch (err) {
|
|
448
|
+
safeError(err);
|
|
449
|
+
}
|
|
450
|
+
},
|
|
451
|
+
cancel: async () => {
|
|
452
|
+
if (http2Stream && !http2Stream.closed) {
|
|
453
|
+
http2Stream.close();
|
|
454
|
+
}
|
|
455
|
+
},
|
|
456
|
+
});
|
|
457
|
+
this.streamName = streamName;
|
|
458
|
+
this.args = args;
|
|
459
|
+
this.authProvider = authProvider;
|
|
460
|
+
this.url = url;
|
|
461
|
+
this.options = options;
|
|
462
|
+
this.getConnection = getConnection;
|
|
463
|
+
this.basinName = basinName;
|
|
464
|
+
// Assign parser to instance property after super() completes
|
|
465
|
+
this.parser = parser;
|
|
466
|
+
this.http2Stream = http2Stream;
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Convert a protobuf SequencedRecord to the requested format
|
|
470
|
+
*/
|
|
471
|
+
convertRecord(record, format, textDecoder) {
|
|
472
|
+
if (format === "bytes") {
|
|
473
|
+
return {
|
|
474
|
+
seq_num: Number(record.seqNum),
|
|
475
|
+
timestamp: Number(record.timestamp),
|
|
476
|
+
headers: record.headers?.map((h) => [h.name ?? new Uint8Array(), h.value ?? new Uint8Array()]),
|
|
477
|
+
body: record.body,
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
else {
|
|
481
|
+
// Convert to string format with object headers
|
|
482
|
+
const headerEntries = record.headers?.map((h) => [
|
|
483
|
+
h.name ? textDecoder.decode(h.name) : "",
|
|
484
|
+
h.value ? textDecoder.decode(h.value) : "",
|
|
485
|
+
]);
|
|
486
|
+
return {
|
|
487
|
+
seq_num: Number(record.seqNum),
|
|
488
|
+
timestamp: Number(record.timestamp),
|
|
489
|
+
headers: headerEntries ? Object.fromEntries(headerEntries) : undefined,
|
|
490
|
+
body: record.body ? textDecoder.decode(record.body) : undefined,
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
async [Symbol.asyncDispose]() {
|
|
495
|
+
await this.cancel("disposed");
|
|
496
|
+
}
|
|
497
|
+
// Polyfill for older browsers / Node.js environments
|
|
498
|
+
[Symbol.asyncIterator]() {
|
|
499
|
+
const proto = ReadableStream.prototype;
|
|
500
|
+
const fn = proto[Symbol.asyncIterator];
|
|
501
|
+
if (typeof fn === "function")
|
|
502
|
+
return fn.call(this);
|
|
503
|
+
const reader = this.getReader();
|
|
504
|
+
return {
|
|
505
|
+
next: async () => {
|
|
506
|
+
const r = await reader.read();
|
|
507
|
+
if (r.done) {
|
|
508
|
+
reader.releaseLock();
|
|
509
|
+
return { done: true, value: undefined };
|
|
510
|
+
}
|
|
511
|
+
return { done: false, value: r.value };
|
|
512
|
+
},
|
|
513
|
+
throw: async (e) => {
|
|
514
|
+
await reader.cancel(e);
|
|
515
|
+
reader.releaseLock();
|
|
516
|
+
return { done: true, value: undefined };
|
|
517
|
+
},
|
|
518
|
+
return: async () => {
|
|
519
|
+
await reader.cancel("done");
|
|
520
|
+
reader.releaseLock();
|
|
521
|
+
return { done: true, value: undefined };
|
|
522
|
+
},
|
|
523
|
+
[Symbol.asyncIterator]() {
|
|
524
|
+
return this;
|
|
525
|
+
},
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
nextReadPosition() {
|
|
529
|
+
return this._nextReadPosition;
|
|
530
|
+
}
|
|
531
|
+
lastObservedTail() {
|
|
532
|
+
return this._lastObservedTail;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* AcksStream for S2S append session
|
|
537
|
+
*/
|
|
538
|
+
// Removed S2SAcksStream - transport sessions no longer expose streams
|
|
539
|
+
/**
|
|
540
|
+
* S2S-based transport session for appending records via HTTP/2.
|
|
541
|
+
* Pipelined: multiple requests can be in-flight simultaneously.
|
|
542
|
+
* No backpressure, no retry logic, no streams - just submit/close with value-encoded errors.
|
|
543
|
+
*/
|
|
544
|
+
class S2SAppendSession {
|
|
545
|
+
baseUrl;
|
|
546
|
+
authProvider;
|
|
547
|
+
streamName;
|
|
548
|
+
getConnection;
|
|
549
|
+
basinName;
|
|
550
|
+
options;
|
|
551
|
+
http2Stream;
|
|
552
|
+
parser = new framing_js_1.S2SFrameParser();
|
|
553
|
+
closed = false;
|
|
554
|
+
pendingAcks = [];
|
|
555
|
+
initPromise;
|
|
556
|
+
static async create(baseUrl, authProvider, streamName, getConnection, basinName, sessionOptions, requestOptions) {
|
|
557
|
+
return new S2SAppendSession(baseUrl, authProvider, streamName, getConnection, basinName, sessionOptions, requestOptions);
|
|
558
|
+
}
|
|
559
|
+
constructor(baseUrl, authProvider, streamName, getConnection, basinName, sessionOptions, options) {
|
|
560
|
+
this.baseUrl = baseUrl;
|
|
561
|
+
this.authProvider = authProvider;
|
|
562
|
+
this.streamName = streamName;
|
|
563
|
+
this.getConnection = getConnection;
|
|
564
|
+
this.basinName = basinName;
|
|
565
|
+
this.options = options;
|
|
566
|
+
// No stream setup
|
|
567
|
+
// Initialization happens lazily on first submit
|
|
568
|
+
}
|
|
569
|
+
async initializeStream() {
|
|
570
|
+
const url = new URL(this.baseUrl);
|
|
571
|
+
const connection = await this.getConnection();
|
|
572
|
+
const path = `${url.pathname}/streams/${encodeURIComponent(this.streamName)}/records`;
|
|
573
|
+
const fullUrl = `${url.protocol}//${url.host}${path}`;
|
|
574
|
+
// Get auth token
|
|
575
|
+
const token = await getAuthToken(this.authProvider);
|
|
576
|
+
// Build headers
|
|
577
|
+
// Note: We include both :authority (HTTP/2 pseudo-header) and host (for proxy compatibility)
|
|
578
|
+
const headers = {
|
|
579
|
+
":method": "POST",
|
|
580
|
+
":path": path,
|
|
581
|
+
":scheme": url.protocol.slice(0, -1),
|
|
582
|
+
":authority": url.host,
|
|
583
|
+
host: url.host, // Some proxies (like Fly.io) may need this for proper forwarding
|
|
584
|
+
"user-agent": runtime_js_1.DEFAULT_USER_AGENT,
|
|
585
|
+
authorization: `Bearer ${token}`,
|
|
586
|
+
"content-type": "s2s/proto",
|
|
587
|
+
accept: "application/protobuf",
|
|
588
|
+
...(this.basinName ? { "s2-basin": this.basinName } : {}),
|
|
589
|
+
};
|
|
590
|
+
// Sign headers if using PKI auth
|
|
591
|
+
await signHeadersIfPki(this.authProvider, headers, "POST", fullUrl);
|
|
592
|
+
const stream = connection.request(headers);
|
|
593
|
+
this.http2Stream = stream;
|
|
594
|
+
this.options?.signal?.addEventListener("abort", () => {
|
|
595
|
+
if (!stream.closed) {
|
|
596
|
+
stream.close();
|
|
597
|
+
}
|
|
598
|
+
});
|
|
599
|
+
const textDecoder = new TextDecoder();
|
|
600
|
+
let responseCode;
|
|
601
|
+
const safeError = (error) => {
|
|
602
|
+
// Resolve all pending acks with error result
|
|
603
|
+
for (const pending of this.pendingAcks) {
|
|
604
|
+
pending.resolve((0, result_js_1.err)((0, error_js_1.s2Error)(error)));
|
|
605
|
+
}
|
|
606
|
+
this.pendingAcks = [];
|
|
607
|
+
};
|
|
608
|
+
// Capture HTTP response status
|
|
609
|
+
stream.on("response", (headers) => {
|
|
610
|
+
responseCode = headers[":status"] ?? 500;
|
|
611
|
+
});
|
|
612
|
+
// Handle incoming data (acks or error response)
|
|
613
|
+
stream.on("data", (chunk) => {
|
|
614
|
+
try {
|
|
615
|
+
// Check for HTTP-level errors first (before s2s frame parsing)
|
|
616
|
+
if ((responseCode ?? 200) >= 400) {
|
|
617
|
+
const errorText = textDecoder.decode(chunk);
|
|
618
|
+
try {
|
|
619
|
+
const errorJson = JSON.parse(errorText);
|
|
620
|
+
safeError(new error_js_1.S2Error({
|
|
621
|
+
message: errorJson.message ?? "Unknown error",
|
|
622
|
+
code: errorJson.code,
|
|
623
|
+
status: responseCode,
|
|
624
|
+
origin: "server",
|
|
625
|
+
}));
|
|
626
|
+
}
|
|
627
|
+
catch {
|
|
628
|
+
safeError(new error_js_1.S2Error({
|
|
629
|
+
message: errorText || "Unknown error",
|
|
630
|
+
status: responseCode,
|
|
631
|
+
origin: "server",
|
|
632
|
+
}));
|
|
633
|
+
}
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
this.parser.push(chunk);
|
|
637
|
+
let frame = this.parser.parseFrame();
|
|
638
|
+
while (frame) {
|
|
639
|
+
if (frame.terminal) {
|
|
640
|
+
if (frame.statusCode && frame.statusCode >= 400) {
|
|
641
|
+
const errorText = textDecoder.decode(frame.body);
|
|
642
|
+
const status = frame.statusCode ?? 500;
|
|
643
|
+
try {
|
|
644
|
+
const errorJson = JSON.parse(errorText);
|
|
645
|
+
const err = status === 412
|
|
646
|
+
? (0, error_js_1.makeAppendPreconditionError)(status, errorJson)
|
|
647
|
+
: (0, error_js_1.makeServerError)({ status, statusText: undefined }, errorJson);
|
|
648
|
+
queueMicrotask(() => safeError(err));
|
|
649
|
+
}
|
|
650
|
+
catch {
|
|
651
|
+
const err = (0, error_js_1.makeServerError)({ status, statusText: undefined }, errorText);
|
|
652
|
+
queueMicrotask(() => safeError(err));
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
stream.close();
|
|
656
|
+
}
|
|
657
|
+
else {
|
|
658
|
+
// Parse AppendAck
|
|
659
|
+
try {
|
|
660
|
+
const protoAck = Proto.AppendAck.fromBinary(frame.body);
|
|
661
|
+
const ack = convertAppendAck(protoAck);
|
|
662
|
+
// Resolve the pending ack promise (FIFO)
|
|
663
|
+
const pending = this.pendingAcks.shift();
|
|
664
|
+
if (pending) {
|
|
665
|
+
pending.resolve((0, result_js_1.ok)(ack));
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
catch (parseErr) {
|
|
669
|
+
queueMicrotask(() => safeError(new error_js_1.S2Error({
|
|
670
|
+
message: `Failed to parse AppendAck: ${parseErr}`,
|
|
671
|
+
status: 500,
|
|
672
|
+
})));
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
frame = this.parser.parseFrame();
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
catch (error) {
|
|
679
|
+
queueMicrotask(() => safeError(error));
|
|
680
|
+
}
|
|
681
|
+
});
|
|
682
|
+
stream.on("error", (streamErr) => {
|
|
683
|
+
queueMicrotask(() => safeError(streamErr));
|
|
684
|
+
});
|
|
685
|
+
stream.on("close", () => {
|
|
686
|
+
// Stream closed - resolve any remaining pending acks with error
|
|
687
|
+
// This can happen if the server closes the stream without sending all acks
|
|
688
|
+
if (this.pendingAcks.length > 0) {
|
|
689
|
+
queueMicrotask(() => safeError(new error_js_1.S2Error({
|
|
690
|
+
message: "Stream closed with pending acks",
|
|
691
|
+
status: 502,
|
|
692
|
+
code: "BAD_GATEWAY",
|
|
693
|
+
})));
|
|
694
|
+
}
|
|
695
|
+
});
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* Send a batch and wait for ack. Returns AppendResult (never throws).
|
|
699
|
+
* Pipelined: multiple sends can be in-flight; acks resolve FIFO.
|
|
700
|
+
*/
|
|
701
|
+
sendBatch(input) {
|
|
702
|
+
if (!this.http2Stream || this.http2Stream.closed) {
|
|
703
|
+
return Promise.resolve((0, result_js_1.err)(new error_js_1.S2Error({ message: "HTTP/2 stream is not open", status: 502 })));
|
|
704
|
+
}
|
|
705
|
+
// Convert to protobuf AppendInput
|
|
706
|
+
const bodyBytes = (0, proto_js_1.encodeProtoAppendInput)(input);
|
|
707
|
+
// Frame the message
|
|
708
|
+
const frame = (0, framing_js_1.frameMessage)({
|
|
709
|
+
terminal: false,
|
|
710
|
+
body: bodyBytes,
|
|
711
|
+
});
|
|
712
|
+
// Track pending ack - this promise resolves when the ack is received (FIFO)
|
|
713
|
+
return new Promise((resolve) => {
|
|
714
|
+
this.pendingAcks.push({
|
|
715
|
+
resolve,
|
|
716
|
+
batchSize: input.meteredBytes,
|
|
717
|
+
});
|
|
718
|
+
// Send the frame (pipelined - non-blocking)
|
|
719
|
+
this.http2Stream.write(frame, (writeErr) => {
|
|
720
|
+
if (writeErr) {
|
|
721
|
+
// Remove from pending acks on write error
|
|
722
|
+
const idx = this.pendingAcks.findIndex((p) => p.resolve === resolve);
|
|
723
|
+
if (idx !== -1) {
|
|
724
|
+
this.pendingAcks.splice(idx, 1);
|
|
725
|
+
}
|
|
726
|
+
// Resolve with error result
|
|
727
|
+
resolve((0, result_js_1.err)((0, error_js_1.s2Error)(writeErr)));
|
|
728
|
+
}
|
|
729
|
+
// Write completed successfully - promise resolves later when ack is received
|
|
730
|
+
});
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Close the append session.
|
|
735
|
+
* Waits for all pending appends to complete before resolving.
|
|
736
|
+
* Never throws - returns CloseResult.
|
|
737
|
+
*/
|
|
738
|
+
async close() {
|
|
739
|
+
try {
|
|
740
|
+
this.closed = true;
|
|
741
|
+
// Wait for all pending acks to complete
|
|
742
|
+
while (this.pendingAcks.length > 0) {
|
|
743
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
744
|
+
}
|
|
745
|
+
// Close the HTTP/2 stream (client doesn't send terminal frame for clean close)
|
|
746
|
+
if (this.http2Stream && !this.http2Stream.closed) {
|
|
747
|
+
this.http2Stream.end();
|
|
748
|
+
}
|
|
749
|
+
return (0, result_js_1.okClose)();
|
|
750
|
+
}
|
|
751
|
+
catch (error) {
|
|
752
|
+
return (0, result_js_1.errClose)((0, error_js_1.s2Error)(error));
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
/**
|
|
756
|
+
* Submit an append request to the session.
|
|
757
|
+
* Returns AppendResult (never throws).
|
|
758
|
+
* Pipelined: multiple submits can be in-flight; acks resolve FIFO.
|
|
759
|
+
*/
|
|
760
|
+
async submit(input) {
|
|
761
|
+
// Validate closed state
|
|
762
|
+
if (this.closed) {
|
|
763
|
+
return (0, result_js_1.err)(new error_js_1.S2Error({ message: "AppendSession is closed", status: 400 }));
|
|
764
|
+
}
|
|
765
|
+
// Lazy initialize HTTP/2 stream on first submit
|
|
766
|
+
if (!this.initPromise) {
|
|
767
|
+
this.initPromise = this.initializeStream();
|
|
768
|
+
}
|
|
769
|
+
try {
|
|
770
|
+
await this.initPromise;
|
|
771
|
+
}
|
|
772
|
+
catch (initErr) {
|
|
773
|
+
return (0, result_js_1.err)((0, error_js_1.s2Error)(initErr));
|
|
774
|
+
}
|
|
775
|
+
const recordsArray = Array.from(input.records);
|
|
776
|
+
// Validate batch size limits (non-retryable 400-level error)
|
|
777
|
+
// Note: This should already be validated by AppendInput.create(), but we check defensively
|
|
778
|
+
if (recordsArray.length > 1000) {
|
|
779
|
+
return (0, result_js_1.err)(new error_js_1.S2Error({
|
|
780
|
+
message: `Batch of ${recordsArray.length} exceeds maximum batch size of 1000 records`,
|
|
781
|
+
status: 400,
|
|
782
|
+
code: "INVALID_ARGUMENT",
|
|
783
|
+
}));
|
|
784
|
+
}
|
|
785
|
+
if (input.meteredBytes > 1024 * 1024) {
|
|
786
|
+
return (0, result_js_1.err)(new error_js_1.S2Error({
|
|
787
|
+
message: `Batch size ${input.meteredBytes} bytes exceeds maximum of 1 MiB (1048576 bytes)`,
|
|
788
|
+
status: 400,
|
|
789
|
+
code: "INVALID_ARGUMENT",
|
|
790
|
+
}));
|
|
791
|
+
}
|
|
792
|
+
return this.sendBatch(input);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
/**
|
|
796
|
+
* Convert protobuf StreamPosition to API StreamPosition (internal use)
|
|
797
|
+
*/
|
|
798
|
+
function convertStreamPosition(proto) {
|
|
799
|
+
return {
|
|
800
|
+
seq_num: Number(proto.seqNum),
|
|
801
|
+
timestamp: Number(proto.timestamp),
|
|
802
|
+
};
|
|
803
|
+
}
|
|
804
|
+
/**
|
|
805
|
+
* Convert API StreamPosition to SDK StreamPosition (public interface)
|
|
806
|
+
*/
|
|
807
|
+
function toSDKStreamPosition(pos) {
|
|
808
|
+
return {
|
|
809
|
+
seqNum: pos.seq_num,
|
|
810
|
+
timestamp: new Date(pos.timestamp),
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
function convertAppendAck(proto) {
|
|
814
|
+
if (!proto.start || !proto.end || !proto.tail) {
|
|
815
|
+
throw new Error("Invariant violation: AppendAck is missing required fields");
|
|
816
|
+
}
|
|
817
|
+
return {
|
|
818
|
+
start: toSDKStreamPosition(convertStreamPosition(proto.start)),
|
|
819
|
+
end: toSDKStreamPosition(convertStreamPosition(proto.end)),
|
|
820
|
+
tail: toSDKStreamPosition(convertStreamPosition(proto.tail)),
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
//# sourceMappingURL=index.js.map
|