@tstdl/base 0.93.181 → 0.93.183
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/api/server/api-request-token.provider.js +1 -1
- package/api/server/gateway.js +8 -3
- package/authentication/authentication.api.d.ts +13 -40
- package/authentication/authentication.api.js +5 -14
- package/authentication/client/authentication.service.d.ts +6 -14
- package/authentication/client/authentication.service.js +22 -4
- package/authentication/client/module.d.ts +1 -1
- package/authentication/client/module.js +4 -4
- package/authentication/models/index.d.ts +1 -0
- package/authentication/models/index.js +1 -0
- package/authentication/models/totp-results.model.d.ts +11 -0
- package/authentication/models/totp-results.model.js +37 -0
- package/authentication/server/authentication.api-controller.d.ts +3 -3
- package/authentication/server/authentication.api-controller.js +31 -4
- package/authentication/server/authentication.service.d.ts +5 -14
- package/authentication/server/authentication.service.js +6 -4
- package/core.d.ts +0 -5
- package/core.js +0 -8
- package/document-management/api/document-management.api.d.ts +2 -2
- package/document-management/service-models/document.service-model.d.ts +1 -1
- package/examples/config.d.ts +25 -0
- package/examples/config.js +26 -0
- package/notification/server/module.d.ts +1 -1
- package/notification/server/module.js +1 -1
- package/package.json +5 -5
- package/signals/api.d.ts +5 -1
- package/signals/api.js +3 -1
- package/signals/implementation/api.d.ts +13 -5
- package/signals/implementation/api.js +7 -1
- package/signals/implementation/asserts.d.ts +2 -2
- package/signals/implementation/asserts.js +3 -3
- package/signals/implementation/computed.d.ts +7 -34
- package/signals/implementation/computed.js +14 -83
- package/signals/implementation/configure.js +6 -2
- package/signals/implementation/effect.d.ts +65 -46
- package/signals/implementation/effect.js +97 -62
- package/signals/implementation/index.d.ts +2 -4
- package/signals/implementation/index.js +2 -4
- package/signals/implementation/linked_signal.d.ts +36 -0
- package/signals/implementation/linked_signal.js +34 -0
- package/signals/implementation/primitive/computed.d.ts +55 -0
- package/signals/implementation/primitive/computed.js +107 -0
- package/signals/implementation/primitive/effect.d.ts +26 -0
- package/signals/implementation/primitive/effect.js +31 -0
- package/signals/implementation/{equality.d.ts → primitive/equality.d.ts} +1 -1
- package/signals/implementation/{equality.js → primitive/equality.js} +1 -1
- package/signals/implementation/primitive/errors.d.ts +10 -0
- package/signals/implementation/{errors.js → primitive/errors.js} +3 -4
- package/signals/implementation/primitive/formatter.d.ts +19 -0
- package/signals/implementation/primitive/formatter.js +136 -0
- package/signals/implementation/{graph.d.ts → primitive/graph.d.ts} +68 -36
- package/signals/implementation/primitive/graph.js +386 -0
- package/signals/implementation/primitive/linked_signal.d.ts +46 -0
- package/signals/implementation/primitive/linked_signal.js +110 -0
- package/signals/implementation/primitive/signal.d.ts +31 -0
- package/signals/implementation/primitive/signal.js +80 -0
- package/signals/implementation/primitive/untracked.d.ts +12 -0
- package/signals/implementation/primitive/untracked.js +23 -0
- package/signals/implementation/{watch.d.ts → primitive/watch.d.ts} +1 -2
- package/signals/implementation/{watch.js → primitive/watch.js} +22 -16
- package/signals/implementation/resource/api.d.ts +275 -0
- package/signals/implementation/resource/api.js +26 -0
- package/signals/implementation/resource/debounce.d.ts +13 -0
- package/signals/implementation/resource/debounce.js +113 -0
- package/signals/implementation/resource/from_snapshots.d.ts +16 -0
- package/signals/implementation/resource/from_snapshots.js +44 -0
- package/signals/implementation/resource/index.d.ts +11 -0
- package/signals/implementation/resource/index.js +11 -0
- package/signals/implementation/resource/resource.d.ts +110 -0
- package/signals/implementation/resource/resource.js +402 -0
- package/signals/implementation/root_effect_scheduler.d.ts +50 -0
- package/signals/implementation/root_effect_scheduler.js +66 -0
- package/signals/implementation/signal.d.ts +42 -18
- package/signals/implementation/signal.js +29 -49
- package/signals/implementation/to-observable.d.ts +12 -5
- package/signals/implementation/to-observable.js +12 -2
- package/signals/implementation/to-signal.d.ts +9 -18
- package/signals/implementation/to-signal.js +46 -13
- package/signals/implementation/untracked.d.ts +1 -1
- package/signals/implementation/untracked.js +3 -11
- package/signals/operators/debounce.d.ts +8 -0
- package/signals/operators/debounce.js +19 -0
- package/signals/operators/derive-async.js +43 -15
- package/signals/operators/index.d.ts +2 -0
- package/signals/operators/index.js +2 -0
- package/signals/operators/throttle.d.ts +8 -0
- package/signals/operators/throttle.js +31 -0
- package/ai/genkit/tests/multi-region.test.d.ts +0 -2
- package/ai/genkit/tests/multi-region.test.js +0 -179
- package/ai/genkit/tests/token-limit-fallback.test.d.ts +0 -2
- package/ai/genkit/tests/token-limit-fallback.test.js +0 -209
- package/ai/prompts/tests/prompt-builder.test.d.ts +0 -1
- package/ai/prompts/tests/prompt-builder.test.js +0 -22
- package/ai/tests/instructions-formatter.test.d.ts +0 -1
- package/ai/tests/instructions-formatter.test.js +0 -116
- package/ai/tests/steering.test.d.ts +0 -1
- package/ai/tests/steering.test.js +0 -37
- package/api/client/tests/api-client.test.d.ts +0 -1
- package/api/client/tests/api-client.test.js +0 -194
- package/api/server/tests/csrf.middleware.test.d.ts +0 -1
- package/api/server/tests/csrf.middleware.test.js +0 -91
- package/authentication/tests/authentication-password-requirements.validator.test.d.ts +0 -1
- package/authentication/tests/authentication-password-requirements.validator.test.js +0 -29
- package/authentication/tests/authentication.api-controller.test.d.ts +0 -1
- package/authentication/tests/authentication.api-controller.test.js +0 -156
- package/authentication/tests/authentication.api-request-token.provider.test.d.ts +0 -1
- package/authentication/tests/authentication.api-request-token.provider.test.js +0 -48
- package/authentication/tests/authentication.client-error-handling.test.d.ts +0 -1
- package/authentication/tests/authentication.client-error-handling.test.js +0 -123
- package/authentication/tests/authentication.client-middleware.test.d.ts +0 -1
- package/authentication/tests/authentication.client-middleware.test.js +0 -118
- package/authentication/tests/authentication.client-service-methods.test.d.ts +0 -1
- package/authentication/tests/authentication.client-service-methods.test.js +0 -177
- package/authentication/tests/authentication.client-service-refresh.test.d.ts +0 -1
- package/authentication/tests/authentication.client-service-refresh.test.js +0 -153
- package/authentication/tests/authentication.client-service.test.d.ts +0 -1
- package/authentication/tests/authentication.client-service.test.js +0 -76
- package/authentication/tests/authentication.refresh-busy-loop.test.d.ts +0 -1
- package/authentication/tests/authentication.refresh-busy-loop.test.js +0 -84
- package/authentication/tests/authentication.service.test.d.ts +0 -1
- package/authentication/tests/authentication.service.test.js +0 -167
- package/authentication/tests/authentication.test-ancillary-service.d.ts +0 -9
- package/authentication/tests/authentication.test-ancillary-service.js +0 -27
- package/authentication/tests/brute-force-protection.test.d.ts +0 -1
- package/authentication/tests/brute-force-protection.test.js +0 -211
- package/authentication/tests/helper.test.d.ts +0 -1
- package/authentication/tests/helper.test.js +0 -122
- package/authentication/tests/password-requirements.error.test.d.ts +0 -1
- package/authentication/tests/password-requirements.error.test.js +0 -14
- package/authentication/tests/remember.api.test.d.ts +0 -1
- package/authentication/tests/remember.api.test.js +0 -117
- package/authentication/tests/remember.service.test.d.ts +0 -1
- package/authentication/tests/remember.service.test.js +0 -83
- package/authentication/tests/subject.service.test.d.ts +0 -1
- package/authentication/tests/subject.service.test.js +0 -140
- package/authentication/tests/suspended-subject.test.d.ts +0 -1
- package/authentication/tests/suspended-subject.test.js +0 -120
- package/authentication/tests/totp.enrollment.test.d.ts +0 -1
- package/authentication/tests/totp.enrollment.test.js +0 -123
- package/authentication/tests/totp.login.test.d.ts +0 -1
- package/authentication/tests/totp.login.test.js +0 -213
- package/authentication/tests/totp.recovery-codes.test.d.ts +0 -1
- package/authentication/tests/totp.recovery-codes.test.js +0 -97
- package/authentication/tests/totp.status.test.d.ts +0 -1
- package/authentication/tests/totp.status.test.js +0 -72
- package/cancellation/tests/coverage.test.d.ts +0 -1
- package/cancellation/tests/coverage.test.js +0 -49
- package/cancellation/tests/leak.test.d.ts +0 -1
- package/cancellation/tests/leak.test.js +0 -35
- package/cancellation/tests/token.test.d.ts +0 -1
- package/cancellation/tests/token.test.js +0 -136
- package/circuit-breaker/tests/circuit-breaker.test.d.ts +0 -1
- package/circuit-breaker/tests/circuit-breaker.test.js +0 -116
- package/cryptography/tests/cryptography.test.d.ts +0 -1
- package/cryptography/tests/cryptography.test.js +0 -175
- package/cryptography/tests/jwt.test.d.ts +0 -1
- package/cryptography/tests/jwt.test.js +0 -54
- package/cryptography/tests/modern.test.d.ts +0 -1
- package/cryptography/tests/modern.test.js +0 -105
- package/cryptography/tests/module.test.d.ts +0 -1
- package/cryptography/tests/module.test.js +0 -100
- package/cryptography/tests/totp.test.d.ts +0 -1
- package/cryptography/tests/totp.test.js +0 -108
- package/document-management/tests/ai-config-hierarchy.test.d.ts +0 -1
- package/document-management/tests/ai-config-hierarchy.test.js +0 -59
- package/document-management/tests/ai-config-integration.test.d.ts +0 -1
- package/document-management/tests/ai-config-integration.test.js +0 -125
- package/document-management/tests/ai-config-merge.test.d.ts +0 -1
- package/document-management/tests/ai-config-merge.test.js +0 -46
- package/document-management/tests/document-management-ai-overrides.test.d.ts +0 -1
- package/document-management/tests/document-management-ai-overrides.test.js +0 -63
- package/document-management/tests/document-management-core.test.d.ts +0 -1
- package/document-management/tests/document-management-core.test.js +0 -157
- package/document-management/tests/document-management.api.test.d.ts +0 -1
- package/document-management/tests/document-management.api.test.js +0 -101
- package/document-management/tests/document-statistics.service.test.d.ts +0 -1
- package/document-management/tests/document-statistics.service.test.js +0 -498
- package/document-management/tests/document-validation-ai-overrides.test.d.ts +0 -1
- package/document-management/tests/document-validation-ai-overrides.test.js +0 -87
- package/document-management/tests/document.service.test.d.ts +0 -1
- package/document-management/tests/document.service.test.js +0 -143
- package/document-management/tests/enum-helpers.test.d.ts +0 -1
- package/document-management/tests/enum-helpers.test.js +0 -452
- package/document-management/tests/helper.d.ts +0 -24
- package/document-management/tests/helper.js +0 -39
- package/errors/tests/format.test.d.ts +0 -1
- package/errors/tests/format.test.js +0 -84
- package/http/tests/server-timing.test.d.ts +0 -1
- package/http/tests/server-timing.test.js +0 -42
- package/injector/tests/advanced.test.d.ts +0 -1
- package/injector/tests/advanced.test.js +0 -116
- package/injector/tests/async-init.test.d.ts +0 -1
- package/injector/tests/async-init.test.js +0 -77
- package/injector/tests/basic.test.d.ts +0 -1
- package/injector/tests/basic.test.js +0 -114
- package/injector/tests/hierarchical.test.d.ts +0 -1
- package/injector/tests/hierarchical.test.js +0 -59
- package/injector/tests/leak.test.d.ts +0 -1
- package/injector/tests/leak.test.js +0 -45
- package/injector/tests/lifecycles.test.d.ts +0 -1
- package/injector/tests/lifecycles.test.js +0 -109
- package/logger/tests/pretty-print.test.d.ts +0 -1
- package/logger/tests/pretty-print.test.js +0 -60
- package/notification/tests/notification-api.test.d.ts +0 -1
- package/notification/tests/notification-api.test.js +0 -124
- package/notification/tests/notification-client.test.d.ts +0 -1
- package/notification/tests/notification-client.test.js +0 -101
- package/notification/tests/notification-flow.test.d.ts +0 -1
- package/notification/tests/notification-flow.test.js +0 -296
- package/notification/tests/notification-sse.service.test.d.ts +0 -1
- package/notification/tests/notification-sse.service.test.js +0 -43
- package/notification/tests/notification-type.service.test.d.ts +0 -1
- package/notification/tests/notification-type.service.test.js +0 -41
- package/object-storage/s3/tests/s3.object-storage.integration.test.d.ts +0 -1
- package/object-storage/s3/tests/s3.object-storage.integration.test.js +0 -303
- package/orm/tests/build-jsonb.test.d.ts +0 -1
- package/orm/tests/build-jsonb.test.js +0 -39
- package/orm/tests/data-types.test.d.ts +0 -1
- package/orm/tests/data-types.test.js +0 -39
- package/orm/tests/database-extension.test.d.ts +0 -1
- package/orm/tests/database-extension.test.js +0 -63
- package/orm/tests/database-migration.test.d.ts +0 -1
- package/orm/tests/database-migration.test.js +0 -83
- package/orm/tests/decorators.test.d.ts +0 -1
- package/orm/tests/decorators.test.js +0 -77
- package/orm/tests/encryption.test.d.ts +0 -1
- package/orm/tests/encryption.test.js +0 -31
- package/orm/tests/query-complex.test.d.ts +0 -1
- package/orm/tests/query-complex.test.js +0 -172
- package/orm/tests/query-converter-complex.test.d.ts +0 -1
- package/orm/tests/query-converter-complex.test.js +0 -131
- package/orm/tests/query-converter.test.d.ts +0 -1
- package/orm/tests/query-converter.test.js +0 -123
- package/orm/tests/repository-advanced.test.d.ts +0 -1
- package/orm/tests/repository-advanced.test.js +0 -189
- package/orm/tests/repository-attributes.test.d.ts +0 -1
- package/orm/tests/repository-attributes.test.js +0 -83
- package/orm/tests/repository-compound-primary-key.test.d.ts +0 -2
- package/orm/tests/repository-compound-primary-key.test.js +0 -226
- package/orm/tests/repository-comprehensive.test.d.ts +0 -1
- package/orm/tests/repository-comprehensive.test.js +0 -162
- package/orm/tests/repository-coverage.test.d.ts +0 -2
- package/orm/tests/repository-coverage.test.js +0 -242
- package/orm/tests/repository-cti-complex.test.d.ts +0 -1
- package/orm/tests/repository-cti-complex.test.js +0 -151
- package/orm/tests/repository-cti-embedded.test.d.ts +0 -1
- package/orm/tests/repository-cti-embedded.test.js +0 -178
- package/orm/tests/repository-cti-extensive.test.d.ts +0 -2
- package/orm/tests/repository-cti-extensive.test.js +0 -279
- package/orm/tests/repository-cti-mapping.test.d.ts +0 -2
- package/orm/tests/repository-cti-mapping.test.js +0 -108
- package/orm/tests/repository-cti-search.test.d.ts +0 -1
- package/orm/tests/repository-cti-search.test.js +0 -141
- package/orm/tests/repository-cti-soft-delete.test.d.ts +0 -2
- package/orm/tests/repository-cti-soft-delete.test.js +0 -103
- package/orm/tests/repository-cti-transactions.test.d.ts +0 -1
- package/orm/tests/repository-cti-transactions.test.js +0 -112
- package/orm/tests/repository-cti-upsert-many.test.d.ts +0 -2
- package/orm/tests/repository-cti-upsert-many.test.js +0 -115
- package/orm/tests/repository-cti.test.d.ts +0 -2
- package/orm/tests/repository-cti.test.js +0 -390
- package/orm/tests/repository-edge-cases.test.d.ts +0 -1
- package/orm/tests/repository-edge-cases.test.js +0 -178
- package/orm/tests/repository-expiration.test.d.ts +0 -2
- package/orm/tests/repository-expiration.test.js +0 -140
- package/orm/tests/repository-extra-coverage.test.d.ts +0 -2
- package/orm/tests/repository-extra-coverage.test.js +0 -402
- package/orm/tests/repository-mapping.test.d.ts +0 -2
- package/orm/tests/repository-mapping.test.js +0 -65
- package/orm/tests/repository-regression.test.d.ts +0 -1
- package/orm/tests/repository-regression.test.js +0 -288
- package/orm/tests/repository-search-coverage.test.d.ts +0 -1
- package/orm/tests/repository-search-coverage.test.js +0 -107
- package/orm/tests/repository-search.test.d.ts +0 -1
- package/orm/tests/repository-search.test.js +0 -105
- package/orm/tests/repository-soft-delete.test.d.ts +0 -1
- package/orm/tests/repository-soft-delete.test.js +0 -118
- package/orm/tests/repository-transactions-nested.test.d.ts +0 -1
- package/orm/tests/repository-transactions-nested.test.js +0 -178
- package/orm/tests/repository-types.test.d.ts +0 -1
- package/orm/tests/repository-types.test.js +0 -184
- package/orm/tests/repository-undelete.test.d.ts +0 -2
- package/orm/tests/repository-undelete.test.js +0 -201
- package/orm/tests/schema-converter.test.d.ts +0 -1
- package/orm/tests/schema-converter.test.js +0 -82
- package/orm/tests/schema-generation.test.d.ts +0 -2
- package/orm/tests/schema-generation.test.js +0 -174
- package/orm/tests/sql-helpers.test.d.ts +0 -1
- package/orm/tests/sql-helpers.test.js +0 -67
- package/orm/tests/transaction-safety.test.d.ts +0 -1
- package/orm/tests/transaction-safety.test.js +0 -81
- package/orm/tests/transactional.test.d.ts +0 -1
- package/orm/tests/transactional.test.js +0 -215
- package/orm/tests/utils.test.d.ts +0 -1
- package/orm/tests/utils.test.js +0 -70
- package/pdf/tests/utils.test.d.ts +0 -1
- package/pdf/tests/utils.test.js +0 -187
- package/process/tests/spawn.test.d.ts +0 -1
- package/process/tests/spawn.test.js +0 -182
- package/rate-limit/tests/postgres-rate-limiter.test.d.ts +0 -1
- package/rate-limit/tests/postgres-rate-limiter.test.js +0 -84
- package/renderer/tests/renderer.test.d.ts +0 -1
- package/renderer/tests/renderer.test.js +0 -88
- package/rpc/tests/rpc.integration.test.d.ts +0 -1
- package/rpc/tests/rpc.integration.test.js +0 -615
- package/signals/implementation/errors.d.ts +0 -2
- package/signals/implementation/graph.js +0 -312
- package/signals/implementation/writable-signal.d.ts +0 -48
- package/signals/implementation/writable-signal.js +0 -32
- package/task-queue/tests/coverage-branch.test.d.ts +0 -1
- package/task-queue/tests/coverage-branch.test.js +0 -395
- package/task-queue/tests/coverage-enhancement.test.d.ts +0 -1
- package/task-queue/tests/coverage-enhancement.test.js +0 -150
- package/task-queue/tests/dag.test.d.ts +0 -1
- package/task-queue/tests/dag.test.js +0 -188
- package/task-queue/tests/dependencies.test.d.ts +0 -1
- package/task-queue/tests/dependencies.test.js +0 -296
- package/task-queue/tests/enqueue-batch.test.d.ts +0 -1
- package/task-queue/tests/enqueue-batch.test.js +0 -125
- package/task-queue/tests/enqueue-item.test.d.ts +0 -1
- package/task-queue/tests/enqueue-item.test.js +0 -12
- package/task-queue/tests/fan-out-spawning.test.d.ts +0 -1
- package/task-queue/tests/fan-out-spawning.test.js +0 -94
- package/task-queue/tests/idempotent-replacement.test.d.ts +0 -1
- package/task-queue/tests/idempotent-replacement.test.js +0 -114
- package/task-queue/tests/missing-idempotent-tasks.test.d.ts +0 -1
- package/task-queue/tests/missing-idempotent-tasks.test.js +0 -39
- package/task-queue/tests/optimization-edge-cases.test.d.ts +0 -1
- package/task-queue/tests/optimization-edge-cases.test.js +0 -124
- package/task-queue/tests/queue-generic.test.d.ts +0 -1
- package/task-queue/tests/queue-generic.test.js +0 -8
- package/task-queue/tests/queue.test.d.ts +0 -1
- package/task-queue/tests/queue.test.js +0 -756
- package/task-queue/tests/shutdown.test.d.ts +0 -1
- package/task-queue/tests/shutdown.test.js +0 -41
- package/task-queue/tests/task-context.test.d.ts +0 -1
- package/task-queue/tests/task-context.test.js +0 -7
- package/task-queue/tests/task-union.test.d.ts +0 -1
- package/task-queue/tests/task-union.test.js +0 -18
- package/task-queue/tests/transactions.test.d.ts +0 -1
- package/task-queue/tests/transactions.test.js +0 -47
- package/task-queue/tests/typing.test.d.ts +0 -1
- package/task-queue/tests/typing.test.js +0 -9
- package/task-queue/tests/worker.test.d.ts +0 -1
- package/task-queue/tests/worker.test.js +0 -258
- package/task-queue/tests/zombie-parent.test.d.ts +0 -1
- package/task-queue/tests/zombie-parent.test.js +0 -45
- package/task-queue/tests/zombie-recovery.test.d.ts +0 -1
- package/task-queue/tests/zombie-recovery.test.js +0 -51
- package/utils/tests/backoff.test.d.ts +0 -1
- package/utils/tests/backoff.test.js +0 -41
- package/utils/tests/retry-with-backoff.test.d.ts +0 -1
- package/utils/tests/retry-with-backoff.test.js +0 -49
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
/** biome-ignore-all lint/suspicious/useAwait: defineModel requires async */
|
|
2
|
-
import { genkit, GenkitError, z } from 'genkit';
|
|
3
|
-
import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
4
|
-
import { CircuitBreakerState } from '../../../circuit-breaker/index.js';
|
|
5
|
-
import { CircuitBreakerProvider } from '../../../circuit-breaker/provider.js';
|
|
6
|
-
import { Logger } from '../../../logger/logger.js';
|
|
7
|
-
import { setupIntegrationTest } from '../../../testing/index.js';
|
|
8
|
-
import { timeout } from '../../../utils/timing.js';
|
|
9
|
-
import { vertexAiMultiLocation } from '../multi-region.plugin.js';
|
|
10
|
-
vi.mock('../../../utils/array/index.js', async (importOriginal) => {
|
|
11
|
-
const actual = await importOriginal();
|
|
12
|
-
return {
|
|
13
|
-
...actual,
|
|
14
|
-
shuffle: vi.fn((items) => [...items]),
|
|
15
|
-
};
|
|
16
|
-
});
|
|
17
|
-
vi.mock('@genkit-ai/google-genai', () => ({
|
|
18
|
-
// biome-ignore lint/style/useNamingConvention: given
|
|
19
|
-
vertexAI: {
|
|
20
|
-
model: vi.fn((name) => ({
|
|
21
|
-
name: `vertexai/${name}`,
|
|
22
|
-
info: { label: 'mock' },
|
|
23
|
-
configSchema: z.object({}),
|
|
24
|
-
})),
|
|
25
|
-
},
|
|
26
|
-
// biome-ignore lint/style/useNamingConvention: given
|
|
27
|
-
googleAI: vi.fn(),
|
|
28
|
-
}));
|
|
29
|
-
describe('Genkit vertexai-multi-location Token Limit Fallback Tests', () => {
|
|
30
|
-
let ai;
|
|
31
|
-
let cbProvider;
|
|
32
|
-
let logger;
|
|
33
|
-
beforeAll(async () => {
|
|
34
|
-
const { injector } = await setupIntegrationTest({ modules: { circuitBreaker: true } });
|
|
35
|
-
cbProvider = injector.resolve(CircuitBreakerProvider);
|
|
36
|
-
logger = injector.resolve(Logger, 'Test');
|
|
37
|
-
});
|
|
38
|
-
beforeEach(async () => {
|
|
39
|
-
vi.clearAllMocks();
|
|
40
|
-
ai = genkit({
|
|
41
|
-
plugins: [
|
|
42
|
-
vertexAiMultiLocation({
|
|
43
|
-
locations: ['region-1', 'region-2', 'region-3'],
|
|
44
|
-
circuitBreakerProvider: cbProvider,
|
|
45
|
-
logger,
|
|
46
|
-
circuitBreakerConfig: { resetTimeout: 1_000_000, threshold: 1 },
|
|
47
|
-
tokenLimitCircuitBreakerConfig: { resetTimeout: 10, threshold: 1 },
|
|
48
|
-
}),
|
|
49
|
-
],
|
|
50
|
-
});
|
|
51
|
-
const config = { threshold: 1, resetTimeout: 1_000_000 };
|
|
52
|
-
await cbProvider.provide('genkit:vertex-ai:location:region-1', config).recordSuccess();
|
|
53
|
-
await cbProvider.provide('genkit:vertex-ai:location:region-2', config).recordSuccess();
|
|
54
|
-
await cbProvider.provide('genkit:vertex-ai:location:region-3', config).recordSuccess();
|
|
55
|
-
await cbProvider.provide('genkit:vertex-ai:location:region-1:token-limit', config).recordSuccess();
|
|
56
|
-
await cbProvider.provide('genkit:vertex-ai:location:region-2:token-limit', config).recordSuccess();
|
|
57
|
-
await cbProvider.provide('genkit:vertex-ai:location:region-3:token-limit', config).recordSuccess();
|
|
58
|
-
});
|
|
59
|
-
it('should fallback on token limit error but NOT trip main circuit breaker', async () => {
|
|
60
|
-
const tokenLimitErrorMessage = 'Unable to submit request because the input token count is 135224 but model only supports up to 131072.';
|
|
61
|
-
let region1Called = false;
|
|
62
|
-
let region2Called = false;
|
|
63
|
-
ai.defineModel({
|
|
64
|
-
name: 'vertexai/gemini-2.5-flash',
|
|
65
|
-
}, async (request) => {
|
|
66
|
-
if (request.config?.location === 'region-1') {
|
|
67
|
-
region1Called = true;
|
|
68
|
-
throw new GenkitError({
|
|
69
|
-
status: 'INVALID_ARGUMENT',
|
|
70
|
-
message: tokenLimitErrorMessage,
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
if (request.config?.location === 'region-2') {
|
|
74
|
-
region2Called = true;
|
|
75
|
-
return {
|
|
76
|
-
message: {
|
|
77
|
-
role: 'model',
|
|
78
|
-
content: [{ text: 'success from region-2' }],
|
|
79
|
-
},
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
throw new Error('Unexpected location');
|
|
83
|
-
});
|
|
84
|
-
const response = await ai.generate({
|
|
85
|
-
model: 'vertexai-multi-location/gemini-2.5-flash',
|
|
86
|
-
prompt: 'test',
|
|
87
|
-
});
|
|
88
|
-
expect(response.text).toBe('success from region-2');
|
|
89
|
-
expect(region1Called).toBe(true);
|
|
90
|
-
expect(region2Called).toBe(true);
|
|
91
|
-
// Verify main circuit breaker for region-1 is still CLOSED (allowed)
|
|
92
|
-
const cb = cbProvider.provide('genkit:vertex-ai:location:region-1', { threshold: 1, resetTimeout: 1000000 });
|
|
93
|
-
const status = await cb.check();
|
|
94
|
-
expect(status.state).toBe(CircuitBreakerState.Closed);
|
|
95
|
-
expect(status.allowed).toBe(true);
|
|
96
|
-
});
|
|
97
|
-
it('should skip locations with known token limits within the same request once it is known to be large', async () => {
|
|
98
|
-
const tokenLimitErrorMessage = 'Unable to submit request because the input token count is 135224 but model only supports up to 131072.';
|
|
99
|
-
// First, trip the token limit breaker for region-2
|
|
100
|
-
const tokenLimitCB2 = cbProvider.provide('genkit:vertex-ai:location:region-2:token-limit', { threshold: 1, resetTimeout: 1000000 });
|
|
101
|
-
await tokenLimitCB2.recordFailure();
|
|
102
|
-
let region1Called = false;
|
|
103
|
-
let region2Called = false;
|
|
104
|
-
let region3Called = false;
|
|
105
|
-
ai.defineModel({
|
|
106
|
-
name: 'vertexai/gemini-2.5-flash',
|
|
107
|
-
}, async (request) => {
|
|
108
|
-
if (request.config?.location === 'region-1') {
|
|
109
|
-
region1Called = true;
|
|
110
|
-
throw new GenkitError({
|
|
111
|
-
status: 'INVALID_ARGUMENT',
|
|
112
|
-
message: tokenLimitErrorMessage,
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
if (request.config?.location === 'region-2') {
|
|
116
|
-
region2Called = true;
|
|
117
|
-
return { message: { role: 'model', content: [{ text: 'success from region-2' }] } };
|
|
118
|
-
}
|
|
119
|
-
if (request.config?.location === 'region-3') {
|
|
120
|
-
region3Called = true;
|
|
121
|
-
return {
|
|
122
|
-
message: {
|
|
123
|
-
role: 'model',
|
|
124
|
-
content: [{ text: 'success from region-3' }],
|
|
125
|
-
},
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
throw new Error('Unexpected location');
|
|
129
|
-
});
|
|
130
|
-
// Initial shuffle is mocked to [region-1, region-2, region-3]
|
|
131
|
-
const response = await ai.generate({
|
|
132
|
-
model: 'vertexai-multi-location/gemini-2.5-flash',
|
|
133
|
-
prompt: 'test',
|
|
134
|
-
});
|
|
135
|
-
expect(response.text).toBe('success from region-3');
|
|
136
|
-
expect(region1Called).toBe(true); // Fails, makes request "known to be large"
|
|
137
|
-
expect(region2Called).toBe(false); // Should be skipped because it is known to have a low limit
|
|
138
|
-
expect(region3Called).toBe(true); // Should be tried as it is not known to be limited
|
|
139
|
-
});
|
|
140
|
-
it('should record success for token limit breaker when it succeeds after being known to be large', async () => {
|
|
141
|
-
const tokenLimitErrorMessage = 'Unable to submit request because the input token count is 135224 but model only supports up to 131072.';
|
|
142
|
-
let region1Called = false;
|
|
143
|
-
let region2Called = false;
|
|
144
|
-
let region3Called = false;
|
|
145
|
-
ai.defineModel({ name: 'vertexai/gemini-2.5-flash' }, async (request) => {
|
|
146
|
-
if (request.config?.location === 'region-1') {
|
|
147
|
-
region1Called = true;
|
|
148
|
-
throw new GenkitError({
|
|
149
|
-
status: 'INVALID_ARGUMENT',
|
|
150
|
-
message: tokenLimitErrorMessage,
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
if (request.config?.location === 'region-2') {
|
|
154
|
-
region2Called = true;
|
|
155
|
-
return { message: { role: 'model', content: [{ text: 'success from region-2' }] } };
|
|
156
|
-
}
|
|
157
|
-
if (request.config?.location === 'region-3') {
|
|
158
|
-
region3Called = true;
|
|
159
|
-
return { message: { role: 'model', content: [{ text: 'success from region-3' }] } };
|
|
160
|
-
}
|
|
161
|
-
throw new Error(`Unexpected location: ${request.config?.location}`);
|
|
162
|
-
});
|
|
163
|
-
// Initial shuffle is [region-1, region-2, region-3].
|
|
164
|
-
// Let's use a very short reset timeout for region-2.
|
|
165
|
-
const shortConfig = { threshold: 1, resetTimeout: 10 };
|
|
166
|
-
const tokenLimitCBShort = cbProvider.provide('genkit:vertex-ai:location:region-2:token-limit', shortConfig);
|
|
167
|
-
await tokenLimitCBShort.recordFailure();
|
|
168
|
-
// Small delay to ensure it goes to Half-Open
|
|
169
|
-
await timeout(50);
|
|
170
|
-
await ai.generate({
|
|
171
|
-
model: 'vertexai-multi-location/gemini-2.5-flash',
|
|
172
|
-
prompt: 'test',
|
|
173
|
-
});
|
|
174
|
-
expect(region1Called).toBe(true);
|
|
175
|
-
expect(region2Called).toBe(true); // Should NOT be skipped because it is Half-Open
|
|
176
|
-
expect(region3Called).toBe(false);
|
|
177
|
-
const status = await tokenLimitCBShort.check();
|
|
178
|
-
expect(status.state).toBe(CircuitBreakerState.Closed);
|
|
179
|
-
});
|
|
180
|
-
it('should record success for token limit breaker via usage-based learning (proactive success)', async () => {
|
|
181
|
-
// We want to verify that if a request has many tokens, it records success even if isLargeRequest was false.
|
|
182
|
-
const tokenLimitThreshold = 131_072;
|
|
183
|
-
const aiWithThreshold = genkit({
|
|
184
|
-
plugins: [
|
|
185
|
-
vertexAiMultiLocation({
|
|
186
|
-
locations: ['region-1'],
|
|
187
|
-
circuitBreakerProvider: cbProvider,
|
|
188
|
-
logger,
|
|
189
|
-
tokenLimitThreshold,
|
|
190
|
-
}),
|
|
191
|
-
],
|
|
192
|
-
});
|
|
193
|
-
// Trip the breaker first
|
|
194
|
-
const tokenLimitCB = cbProvider.provide('genkit:vertex-ai:location:region-1:token-limit', { threshold: 1, resetTimeout: 1000000 });
|
|
195
|
-
await tokenLimitCB.recordFailure();
|
|
196
|
-
aiWithThreshold.defineModel({ name: 'vertexai/gemini-2.5-flash' }, async () => ({
|
|
197
|
-
message: { role: 'model', content: [{ text: 'success' }] },
|
|
198
|
-
usage: { inputTokens: tokenLimitThreshold + 1 },
|
|
199
|
-
}));
|
|
200
|
-
// This request is NOT known to be large initially.
|
|
201
|
-
// But it returns usage > threshold.
|
|
202
|
-
await aiWithThreshold.generate({
|
|
203
|
-
model: 'vertexai-multi-location/gemini-2.5-flash',
|
|
204
|
-
prompt: 'test',
|
|
205
|
-
});
|
|
206
|
-
const status = await tokenLimitCB.check();
|
|
207
|
-
expect(status.state).toBe(CircuitBreakerState.Closed);
|
|
208
|
-
});
|
|
209
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { StringSchema } from '../../../schema/schemas/string.js';
|
|
3
|
-
import { promptBuilder } from '../prompt-builder.js';
|
|
4
|
-
describe('PromptBuilder', () => {
|
|
5
|
-
it('should add output schema to the prompt', () => {
|
|
6
|
-
const builder = promptBuilder()
|
|
7
|
-
.setRole('Test Role')
|
|
8
|
-
.setOutputSchema(new StringSchema({ description: 'Test Description' }))
|
|
9
|
-
.setTask('Test Task');
|
|
10
|
-
const prompt = builder.buildUserPrompt();
|
|
11
|
-
const text = prompt[0].text;
|
|
12
|
-
expect(text).toContain('# **Output Schema**');
|
|
13
|
-
expect(text).toContain('"type": "string"');
|
|
14
|
-
expect(text).toContain('"description": "Test Description"');
|
|
15
|
-
// Check order: Role -> Output Schema -> Task
|
|
16
|
-
const roleIndex = text.indexOf('# **Role**');
|
|
17
|
-
const schemaIndex = text.indexOf('# **Output Schema**');
|
|
18
|
-
const taskIndex = text.indexOf('# **Task**');
|
|
19
|
-
expect(roleIndex).toBeLessThan(schemaIndex);
|
|
20
|
-
expect(schemaIndex).toBeLessThan(taskIndex);
|
|
21
|
-
});
|
|
22
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
/** biome-ignore-all lint/style/useNamingConvention: instructions are uppercase */
|
|
2
|
-
import { describe, expect, test } from 'vitest';
|
|
3
|
-
import { formatInstructions, orderedList, sections, unorderedList } from '../prompts/instructions-formatter.js';
|
|
4
|
-
describe('Instructions Formatter', () => {
|
|
5
|
-
test('should format a simple unordered list of strings', () => {
|
|
6
|
-
const instructions = ['Item 1', 'Item 2'];
|
|
7
|
-
const result = formatInstructions(instructions);
|
|
8
|
-
expect(result).toBe(`- Item 1
|
|
9
|
-
- Item 2`);
|
|
10
|
-
});
|
|
11
|
-
test('should format an object as sections by default', () => {
|
|
12
|
-
const instructions = {
|
|
13
|
-
'Section 1': 'Content 1',
|
|
14
|
-
'Section 2': 'Content 2',
|
|
15
|
-
};
|
|
16
|
-
const result = formatInstructions(instructions);
|
|
17
|
-
expect(result).toBe(`# Section 1
|
|
18
|
-
|
|
19
|
-
Content 1
|
|
20
|
-
|
|
21
|
-
# Section 2
|
|
22
|
-
|
|
23
|
-
Content 2`);
|
|
24
|
-
});
|
|
25
|
-
test('should format nested unordered lists', () => {
|
|
26
|
-
const instructions = unorderedList({
|
|
27
|
-
Parent: unorderedList([
|
|
28
|
-
'Child 1',
|
|
29
|
-
'Child 2',
|
|
30
|
-
]),
|
|
31
|
-
});
|
|
32
|
-
const result = formatInstructions(instructions);
|
|
33
|
-
expect(result).toBe(`- **Parent:**
|
|
34
|
-
- Child 1
|
|
35
|
-
- Child 2`);
|
|
36
|
-
});
|
|
37
|
-
test('should format ordered lists', () => {
|
|
38
|
-
const instructions = orderedList(['First', 'Second']);
|
|
39
|
-
const result = formatInstructions(instructions);
|
|
40
|
-
expect(result).toBe(`1. First
|
|
41
|
-
2. Second`);
|
|
42
|
-
});
|
|
43
|
-
test('should format nested mixed lists', () => {
|
|
44
|
-
const instructions = orderedList({
|
|
45
|
-
'Step 1': unorderedList([
|
|
46
|
-
'Substep A',
|
|
47
|
-
'Substep B',
|
|
48
|
-
]),
|
|
49
|
-
});
|
|
50
|
-
const result = formatInstructions(instructions);
|
|
51
|
-
expect(result).toBe(`1. **Step 1:**
|
|
52
|
-
- Substep A
|
|
53
|
-
- Substep B`);
|
|
54
|
-
});
|
|
55
|
-
test('should handle hanging indents for multi-line strings', () => {
|
|
56
|
-
const instructions = unorderedList([
|
|
57
|
-
`Line 1
|
|
58
|
-
Line 2`,
|
|
59
|
-
]);
|
|
60
|
-
const result = formatInstructions(instructions);
|
|
61
|
-
expect(result).toBe(`- Line 1
|
|
62
|
-
Line 2`);
|
|
63
|
-
});
|
|
64
|
-
test('should handle sections with instructions', () => {
|
|
65
|
-
const instructions = sections('General Info', {
|
|
66
|
-
SubSection: 'Details',
|
|
67
|
-
});
|
|
68
|
-
const result = formatInstructions(instructions);
|
|
69
|
-
expect(result).toBe(`General Info
|
|
70
|
-
|
|
71
|
-
# SubSection
|
|
72
|
-
|
|
73
|
-
Details`);
|
|
74
|
-
});
|
|
75
|
-
test('should handle nested sections (incrementing H level)', () => {
|
|
76
|
-
const instructions = sections({
|
|
77
|
-
'Level 1': sections({
|
|
78
|
-
'Level 2': 'Deep content',
|
|
79
|
-
}),
|
|
80
|
-
});
|
|
81
|
-
const result = formatInstructions(instructions);
|
|
82
|
-
expect(result).toBe(`# Level 1
|
|
83
|
-
|
|
84
|
-
## Level 2
|
|
85
|
-
|
|
86
|
-
Deep content`);
|
|
87
|
-
});
|
|
88
|
-
test('should handle complex nested structures with mixed styles', () => {
|
|
89
|
-
const instructions = sections({
|
|
90
|
-
Task: 'Perform the following actions',
|
|
91
|
-
Steps: orderedList({
|
|
92
|
-
'Step A': 'Do something',
|
|
93
|
-
'Step B': unorderedList([
|
|
94
|
-
'Subtask B1',
|
|
95
|
-
'Subtask B2',
|
|
96
|
-
]),
|
|
97
|
-
}),
|
|
98
|
-
Conclusion: 'All done',
|
|
99
|
-
});
|
|
100
|
-
const expected = `# Task
|
|
101
|
-
|
|
102
|
-
Perform the following actions
|
|
103
|
-
|
|
104
|
-
# Steps
|
|
105
|
-
|
|
106
|
-
1. **Step A:** Do something
|
|
107
|
-
2. **Step B:**
|
|
108
|
-
- Subtask B1
|
|
109
|
-
- Subtask B2
|
|
110
|
-
|
|
111
|
-
# Conclusion
|
|
112
|
-
|
|
113
|
-
All done`;
|
|
114
|
-
expect(formatInstructions(instructions)).toBe(expected);
|
|
115
|
-
});
|
|
116
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from 'vitest';
|
|
2
|
-
import { fewShotPrompt, formatInstructions, languagePrompt, stylePrompt } from '../../ai/prompts/index.js';
|
|
3
|
-
describe('ai-prompt-factories', () => {
|
|
4
|
-
test('fewShotPrompt should format positive examples', () => {
|
|
5
|
-
const prompt = formatInstructions(fewShotPrompt([
|
|
6
|
-
{ input: { text: 'hello' }, output: { result: 'world' } },
|
|
7
|
-
]));
|
|
8
|
-
expect(prompt).toContain('Examples');
|
|
9
|
-
expect(prompt).toContain('Example 1 (POSITIVE)');
|
|
10
|
-
expect(prompt).toContain('**Input:** {"text":"hello"}');
|
|
11
|
-
expect(prompt).toContain('**Output:** {"result":"world"}');
|
|
12
|
-
});
|
|
13
|
-
test('fewShotPrompt should format negative examples with reasons', () => {
|
|
14
|
-
const examples = [
|
|
15
|
-
{ input: { text: 'bad' }, output: { result: 'no' }, isNegative: true, reason: 'This is not allowed' },
|
|
16
|
-
];
|
|
17
|
-
const prompt = formatInstructions(fewShotPrompt(examples));
|
|
18
|
-
expect(prompt).toContain('Example 1 (NEGATIVE)');
|
|
19
|
-
expect(prompt).toContain('**Reason:** This is not allowed');
|
|
20
|
-
});
|
|
21
|
-
test('fewShotPrompt should format string examples without quotes', () => {
|
|
22
|
-
const prompt = formatInstructions(fewShotPrompt([
|
|
23
|
-
{ input: 'input string', output: 'output string' },
|
|
24
|
-
]));
|
|
25
|
-
expect(prompt).toContain('**Input:** input string');
|
|
26
|
-
expect(prompt).toContain('**Output:** output string');
|
|
27
|
-
});
|
|
28
|
-
test('languagePrompt should include the language', () => {
|
|
29
|
-
const prompt = languagePrompt('German');
|
|
30
|
-
expect(prompt).toBe('IMPORTANT: All generated text content MUST be in German.');
|
|
31
|
-
});
|
|
32
|
-
test('stylePrompt should include the instructions', () => {
|
|
33
|
-
const prompt = stylePrompt('Use formal tone.');
|
|
34
|
-
expect(prompt).toContain('Style & Formatting Instructions');
|
|
35
|
-
expect(prompt).toContain('Use formal tone.');
|
|
36
|
-
});
|
|
37
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import { CancellationToken } from '../../../cancellation/index.js';
|
|
3
|
-
import { HttpClient } from '../../../http/client/index.js';
|
|
4
|
-
import { bustCache } from '../../../http/index.js';
|
|
5
|
-
import { object } from '../../../schema/index.js';
|
|
6
|
-
import { DataStream } from '../../../sse/data-stream.js';
|
|
7
|
-
import { ServerSentEvents } from '../../../sse/server-sent-events.js';
|
|
8
|
-
import { defineApi } from '../../types.js';
|
|
9
|
-
import { compileClient } from '../client.js';
|
|
10
|
-
describe('ApiClient', () => {
|
|
11
|
-
it('should pass abortSignal and handle positional arguments', async () => {
|
|
12
|
-
const apiDefinition = defineApi({
|
|
13
|
-
resource: 'test',
|
|
14
|
-
endpoints: {
|
|
15
|
-
noParams: {
|
|
16
|
-
method: 'GET',
|
|
17
|
-
resource: 'no-params',
|
|
18
|
-
},
|
|
19
|
-
onlyParams: {
|
|
20
|
-
method: 'GET',
|
|
21
|
-
resource: 'only-params',
|
|
22
|
-
parameters: object({
|
|
23
|
-
id: String,
|
|
24
|
-
}),
|
|
25
|
-
},
|
|
26
|
-
paramsAndBody: {
|
|
27
|
-
method: 'POST',
|
|
28
|
-
resource: 'params-and-body',
|
|
29
|
-
parameters: object({
|
|
30
|
-
id: String,
|
|
31
|
-
}),
|
|
32
|
-
body: object({
|
|
33
|
-
data: String,
|
|
34
|
-
}),
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
});
|
|
38
|
-
const mockHttpClient = Object.assign(Object.create(HttpClient.prototype), {
|
|
39
|
-
rawRequest: vi.fn().mockResolvedValue({
|
|
40
|
-
statusCode: 200,
|
|
41
|
-
hasBody: false,
|
|
42
|
-
close: vi.fn(),
|
|
43
|
-
}),
|
|
44
|
-
options: { baseUrl: 'http://localhost/' },
|
|
45
|
-
});
|
|
46
|
-
const Client = compileClient(apiDefinition);
|
|
47
|
-
const client = new Client(mockHttpClient);
|
|
48
|
-
const abortController = new AbortController();
|
|
49
|
-
const cancellationToken = new CancellationToken();
|
|
50
|
-
// 1. No params
|
|
51
|
-
await client.noParams({ cancellationSignal: abortController.signal });
|
|
52
|
-
expect(mockHttpClient.rawRequest).toHaveBeenLastCalledWith(expect.objectContaining({
|
|
53
|
-
url: expect.stringContaining('no-params'),
|
|
54
|
-
}));
|
|
55
|
-
let lastRequest = mockHttpClient.rawRequest.mock.calls.at(-1)[0];
|
|
56
|
-
expect(lastRequest.cancellationSignal.isSet).toBe(false);
|
|
57
|
-
abortController.abort();
|
|
58
|
-
expect(lastRequest.cancellationSignal.isSet).toBe(true);
|
|
59
|
-
// 2. Only params
|
|
60
|
-
await client.onlyParams({ id: '123' }, { cancellationSignal: cancellationToken.abortSignal });
|
|
61
|
-
expect(mockHttpClient.rawRequest).toHaveBeenLastCalledWith(expect.objectContaining({
|
|
62
|
-
url: expect.stringContaining('only-params'),
|
|
63
|
-
parameters: { id: '123' },
|
|
64
|
-
}));
|
|
65
|
-
lastRequest = mockHttpClient.rawRequest.mock.calls.at(-1)[0];
|
|
66
|
-
expect(lastRequest.cancellationSignal.isSet).toBe(false);
|
|
67
|
-
cancellationToken.set();
|
|
68
|
-
expect(lastRequest.cancellationSignal.isSet).toBe(true);
|
|
69
|
-
// 3. Params and body
|
|
70
|
-
const abortController3 = new AbortController();
|
|
71
|
-
await client.paramsAndBody({ id: '456' }, { data: 'val' }, { cancellationSignal: abortController3.signal });
|
|
72
|
-
expect(mockHttpClient.rawRequest).toHaveBeenLastCalledWith(expect.objectContaining({
|
|
73
|
-
url: expect.stringContaining('params-and-body'),
|
|
74
|
-
parameters: { id: '456' },
|
|
75
|
-
body: { json: { data: 'val' } },
|
|
76
|
-
}));
|
|
77
|
-
lastRequest = mockHttpClient.rawRequest.mock.calls.at(-1)[0];
|
|
78
|
-
expect(lastRequest.cancellationSignal.isSet).toBe(false);
|
|
79
|
-
abortController3.abort();
|
|
80
|
-
expect(lastRequest.cancellationSignal.isSet).toBe(true);
|
|
81
|
-
// 4. Omitted requestOptions
|
|
82
|
-
await client.onlyParams({ id: '789' });
|
|
83
|
-
expect(mockHttpClient.rawRequest).toHaveBeenLastCalledWith(expect.objectContaining({
|
|
84
|
-
url: expect.stringContaining('only-params'),
|
|
85
|
-
parameters: { id: '789' },
|
|
86
|
-
}));
|
|
87
|
-
lastRequest = mockHttpClient.rawRequest.mock.calls.at(-1)[0];
|
|
88
|
-
expect(lastRequest.cancellationSignal.isSet).toBe(false);
|
|
89
|
-
});
|
|
90
|
-
it('should handle different HTTP methods', async () => {
|
|
91
|
-
const apiDefinition = defineApi({
|
|
92
|
-
resource: 'methods',
|
|
93
|
-
endpoints: {
|
|
94
|
-
get: { method: 'GET' },
|
|
95
|
-
post: { method: 'POST' },
|
|
96
|
-
put: { method: 'PUT' },
|
|
97
|
-
patch: { method: 'PATCH' },
|
|
98
|
-
delete: { method: 'DELETE' },
|
|
99
|
-
},
|
|
100
|
-
});
|
|
101
|
-
const mockHttpClient = Object.assign(Object.create(HttpClient.prototype), {
|
|
102
|
-
rawRequest: vi.fn().mockResolvedValue({ statusCode: 200, hasBody: false, close: vi.fn() }),
|
|
103
|
-
options: { baseUrl: 'http://localhost/' },
|
|
104
|
-
});
|
|
105
|
-
const Client = compileClient(apiDefinition);
|
|
106
|
-
const client = new Client(mockHttpClient);
|
|
107
|
-
await client.get();
|
|
108
|
-
expect(mockHttpClient.rawRequest.mock.calls.at(-1)[0].method).toBe('GET');
|
|
109
|
-
await client.post();
|
|
110
|
-
expect(mockHttpClient.rawRequest.mock.calls.at(-1)[0].method).toBe('POST');
|
|
111
|
-
await client.put();
|
|
112
|
-
expect(mockHttpClient.rawRequest.mock.calls.at(-1)[0].method).toBe('PUT');
|
|
113
|
-
await client.patch();
|
|
114
|
-
expect(mockHttpClient.rawRequest.mock.calls.at(-1)[0].method).toBe('PATCH');
|
|
115
|
-
await client.delete();
|
|
116
|
-
expect(mockHttpClient.rawRequest.mock.calls.at(-1)[0].method).toBe('DELETE');
|
|
117
|
-
});
|
|
118
|
-
it('should handle body types', async () => {
|
|
119
|
-
const apiDefinition = defineApi({
|
|
120
|
-
resource: 'body',
|
|
121
|
-
endpoints: {
|
|
122
|
-
json: { method: 'POST', body: object({ foo: String }) },
|
|
123
|
-
text: { method: 'POST', body: String },
|
|
124
|
-
binary: { method: 'POST', body: Uint8Array },
|
|
125
|
-
},
|
|
126
|
-
});
|
|
127
|
-
const mockHttpClient = Object.assign(Object.create(HttpClient.prototype), {
|
|
128
|
-
rawRequest: vi.fn().mockResolvedValue({ statusCode: 200, hasBody: false, close: vi.fn() }),
|
|
129
|
-
options: { baseUrl: 'http://localhost/' },
|
|
130
|
-
});
|
|
131
|
-
const Client = compileClient(apiDefinition);
|
|
132
|
-
const client = new Client(mockHttpClient);
|
|
133
|
-
await client.json(undefined, { foo: 'bar' });
|
|
134
|
-
expect(mockHttpClient.rawRequest.mock.calls.at(-1)[0].body).toEqual({ json: { foo: 'bar' } });
|
|
135
|
-
await client.text(undefined, 'hello');
|
|
136
|
-
expect(mockHttpClient.rawRequest.mock.calls.at(-1)[0].body).toEqual({ text: 'hello' });
|
|
137
|
-
const buffer = new Uint8Array([1, 2, 3]);
|
|
138
|
-
await client.binary(undefined, buffer);
|
|
139
|
-
expect(mockHttpClient.rawRequest.mock.calls.at(-1)[0].body).toEqual({ binary: buffer });
|
|
140
|
-
});
|
|
141
|
-
it('should handle credentials, bustCache and resource methods', async () => {
|
|
142
|
-
const apiDefinition = defineApi({
|
|
143
|
-
resource: 'features',
|
|
144
|
-
endpoints: {
|
|
145
|
-
withCredentials: { method: 'GET', credentials: true },
|
|
146
|
-
withBustCache: { method: 'GET', bustCache: true },
|
|
147
|
-
},
|
|
148
|
-
});
|
|
149
|
-
const mockHttpClient = Object.assign(Object.create(HttpClient.prototype), {
|
|
150
|
-
rawRequest: vi.fn().mockResolvedValue({ statusCode: 200, hasBody: false, close: vi.fn() }),
|
|
151
|
-
options: { baseUrl: 'http://localhost/' },
|
|
152
|
-
});
|
|
153
|
-
const Client = compileClient(apiDefinition);
|
|
154
|
-
const client = new Client(mockHttpClient);
|
|
155
|
-
await client.withCredentials();
|
|
156
|
-
expect(mockHttpClient.rawRequest.mock.calls.at(-1)[0].credentials).toBe('include');
|
|
157
|
-
await client.withBustCache();
|
|
158
|
-
expect(mockHttpClient.rawRequest.mock.calls.at(-1)[0].context[bustCache]).toBe(true);
|
|
159
|
-
expect(Client.getEndpointResource('withCredentials')).not.toContain('withCredentials');
|
|
160
|
-
expect(Client.getEndpointUrl('withCredentials').href).toBe('http://baseurl/api/v1/features');
|
|
161
|
-
expect(client.getEndpointUrl('withCredentials').href).toBe('http://localhost/api/v1/features');
|
|
162
|
-
});
|
|
163
|
-
it('should handle Server Sent Events and DataStream', async () => {
|
|
164
|
-
const apiDefinition = defineApi({
|
|
165
|
-
resource: 'sse',
|
|
166
|
-
endpoints: {
|
|
167
|
-
events: { method: 'GET', result: ServerSentEvents },
|
|
168
|
-
stream: { method: 'GET', result: DataStream },
|
|
169
|
-
},
|
|
170
|
-
});
|
|
171
|
-
const mockEventSource = {
|
|
172
|
-
addEventListener: vi.fn(),
|
|
173
|
-
removeEventListener: vi.fn(),
|
|
174
|
-
close: vi.fn(),
|
|
175
|
-
readyState: 0,
|
|
176
|
-
};
|
|
177
|
-
const EventSourceMock = vi.fn().mockImplementation(function () {
|
|
178
|
-
return mockEventSource;
|
|
179
|
-
});
|
|
180
|
-
vi.stubGlobal('EventSource', EventSourceMock);
|
|
181
|
-
const mockHttpClient = Object.assign(Object.create(HttpClient.prototype), {
|
|
182
|
-
options: { baseUrl: 'http://localhost/' },
|
|
183
|
-
});
|
|
184
|
-
const Client = compileClient(apiDefinition);
|
|
185
|
-
const client = new Client(mockHttpClient);
|
|
186
|
-
const sse = await client.events();
|
|
187
|
-
expect(sse).toBeInstanceOf(ServerSentEvents);
|
|
188
|
-
expect(EventSourceMock).toHaveBeenCalledWith(expect.stringContaining('sse'), expect.any(Object));
|
|
189
|
-
const stream = await client.stream();
|
|
190
|
-
expect(stream).toBeInstanceOf(Object); // It's an Observable
|
|
191
|
-
expect(EventSourceMock).toHaveBeenCalledWith(expect.stringContaining('sse'), expect.any(Object));
|
|
192
|
-
vi.unstubAllGlobals();
|
|
193
|
-
});
|
|
194
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|