@tstdl/base 0.93.182 → 0.93.184
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 +6 -1
- 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 +10 -1
- 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,116 +0,0 @@
|
|
|
1
|
-
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
|
2
|
-
import { CircuitBreakerState } from '../../circuit-breaker/index.js';
|
|
3
|
-
import { CircuitBreakerProvider } from '../../circuit-breaker/provider.js';
|
|
4
|
-
import { setupIntegrationTest } from '../../testing/index.js';
|
|
5
|
-
import { timeout } from '../../utils/timing.js';
|
|
6
|
-
describe('Circuit Breaker (Standalone) Tests', () => {
|
|
7
|
-
let injector;
|
|
8
|
-
let provider;
|
|
9
|
-
beforeAll(async () => {
|
|
10
|
-
({ injector } = (await setupIntegrationTest({ modules: { circuitBreaker: true } })));
|
|
11
|
-
provider = injector.resolve(CircuitBreakerProvider);
|
|
12
|
-
});
|
|
13
|
-
afterAll(async () => {
|
|
14
|
-
await injector.dispose();
|
|
15
|
-
});
|
|
16
|
-
it('should start in Closed state', async () => {
|
|
17
|
-
const breaker = provider.provide(`cb-init-${Date.now()}`, { threshold: 2, resetTimeout: 1000 });
|
|
18
|
-
const result = await breaker.check();
|
|
19
|
-
expect(result.allowed).toBe(true);
|
|
20
|
-
expect(result.state).toBe(CircuitBreakerState.Closed);
|
|
21
|
-
});
|
|
22
|
-
it('should trip to Open after threshold failures', async () => {
|
|
23
|
-
const breaker = provider.provide(`cb-trip-${Date.now()}`, { threshold: 2, resetTimeout: 1000 });
|
|
24
|
-
// 1. First Failure
|
|
25
|
-
await breaker.recordFailure();
|
|
26
|
-
let result = await breaker.check();
|
|
27
|
-
expect(result.state).toBe(CircuitBreakerState.Closed);
|
|
28
|
-
// 2. Second Failure (Threshold Reached)
|
|
29
|
-
await breaker.recordFailure();
|
|
30
|
-
result = await breaker.check();
|
|
31
|
-
expect(result.allowed).toBe(false);
|
|
32
|
-
expect(result.state).toBe(CircuitBreakerState.Open);
|
|
33
|
-
});
|
|
34
|
-
it('should reset to Closed on success', async () => {
|
|
35
|
-
const breaker = provider.provide(`cb-reset-${Date.now()}`, { threshold: 2, resetTimeout: 1000 });
|
|
36
|
-
// Trip it
|
|
37
|
-
await breaker.recordFailure();
|
|
38
|
-
await breaker.recordFailure();
|
|
39
|
-
expect((await breaker.check()).state).toBe(CircuitBreakerState.Open);
|
|
40
|
-
// Record Success
|
|
41
|
-
await breaker.recordSuccess();
|
|
42
|
-
const result = await breaker.check();
|
|
43
|
-
expect(result.allowed).toBe(true);
|
|
44
|
-
expect(result.state).toBe(CircuitBreakerState.Closed);
|
|
45
|
-
});
|
|
46
|
-
it('should transition to Half-Open (Probe) after timeout', async () => {
|
|
47
|
-
const timeoutMs = 200;
|
|
48
|
-
const breaker = provider.provide(`cb-probe-${Date.now()}`, { threshold: 1, resetTimeout: timeoutMs });
|
|
49
|
-
// Trip it
|
|
50
|
-
await breaker.recordFailure();
|
|
51
|
-
expect((await breaker.check()).state).toBe(CircuitBreakerState.Open);
|
|
52
|
-
// Wait for timeout
|
|
53
|
-
await timeout(timeoutMs + 50);
|
|
54
|
-
// First check should be the Probe
|
|
55
|
-
const probe = await breaker.check();
|
|
56
|
-
expect(probe.allowed).toBe(true);
|
|
57
|
-
expect(probe.state).toBe(CircuitBreakerState.HalfOpen);
|
|
58
|
-
expect(probe.isProbe).toBe(true);
|
|
59
|
-
// Subsequent check should be allowed but not the probe
|
|
60
|
-
const subsequent = await breaker.check();
|
|
61
|
-
expect(subsequent.allowed).toBe(true);
|
|
62
|
-
expect(subsequent.state).toBe(CircuitBreakerState.HalfOpen);
|
|
63
|
-
expect(subsequent.isProbe).toBe(false);
|
|
64
|
-
// Another check should also be allowed
|
|
65
|
-
const third = await breaker.check();
|
|
66
|
-
expect(third.allowed).toBe(true);
|
|
67
|
-
expect(third.state).toBe(CircuitBreakerState.HalfOpen);
|
|
68
|
-
expect(third.isProbe).toBe(false);
|
|
69
|
-
});
|
|
70
|
-
it('should close if Probe succeeds', async () => {
|
|
71
|
-
const timeoutMs = 100;
|
|
72
|
-
const breaker = provider.provide(`cb-probe-success-${Date.now()}`, { threshold: 1, resetTimeout: timeoutMs });
|
|
73
|
-
// Trip and Probe
|
|
74
|
-
await breaker.recordFailure();
|
|
75
|
-
await timeout(timeoutMs + 50);
|
|
76
|
-
await breaker.check(); // Probe triggered
|
|
77
|
-
// Probe succeeds
|
|
78
|
-
await breaker.recordSuccess();
|
|
79
|
-
const result = await breaker.check();
|
|
80
|
-
expect(result.state).toBe(CircuitBreakerState.Closed);
|
|
81
|
-
});
|
|
82
|
-
it('should reopen if Probe fails', async () => {
|
|
83
|
-
const timeoutMs = 100;
|
|
84
|
-
const breaker = provider.provide(`cb-probe-fail-${Date.now()}`, { threshold: 1, resetTimeout: timeoutMs });
|
|
85
|
-
// Trip and Probe
|
|
86
|
-
await breaker.recordFailure();
|
|
87
|
-
await timeout(timeoutMs + 50);
|
|
88
|
-
await breaker.check(); // Probe triggered (State: HalfOpen)
|
|
89
|
-
// Probe fails
|
|
90
|
-
await breaker.recordFailure();
|
|
91
|
-
// Should be Open again
|
|
92
|
-
const result = await breaker.check();
|
|
93
|
-
expect(result.allowed).toBe(false);
|
|
94
|
-
expect(result.state).toBe(CircuitBreakerState.Open);
|
|
95
|
-
});
|
|
96
|
-
it('should trip to Open after threshold failures via recordFailures', async () => {
|
|
97
|
-
const breaker = provider.provide(`cb-bulk-trip-${Date.now()}`, { threshold: 5, resetTimeout: 1000 });
|
|
98
|
-
// 1. Bulk Failure (Threshold Not Reached)
|
|
99
|
-
await breaker.recordFailures(3);
|
|
100
|
-
let result = await breaker.check();
|
|
101
|
-
expect(result.state).toBe(CircuitBreakerState.Closed);
|
|
102
|
-
// 2. Bulk Failure (Threshold Reached)
|
|
103
|
-
await breaker.recordFailures(2);
|
|
104
|
-
result = await breaker.check();
|
|
105
|
-
expect(result.allowed).toBe(false);
|
|
106
|
-
expect(result.state).toBe(CircuitBreakerState.Open);
|
|
107
|
-
});
|
|
108
|
-
it('should trip to Open after threshold failures via single large recordFailures', async () => {
|
|
109
|
-
const breaker = provider.provide(`cb-single-bulk-trip-${Date.now()}`, { threshold: 5, resetTimeout: 1000 });
|
|
110
|
-
// Single large bulk failure exceeding threshold
|
|
111
|
-
await breaker.recordFailures(10);
|
|
112
|
-
const result = await breaker.check();
|
|
113
|
-
expect(result.allowed).toBe(false);
|
|
114
|
-
expect(result.state).toBe(CircuitBreakerState.Open);
|
|
115
|
-
});
|
|
116
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from 'vitest';
|
|
2
|
-
import { encodeUtf8 } from '../../utils/encoding.js';
|
|
3
|
-
import { decrypt, deriveBytes, digest, encrypt, generateEcdsaKey, generateHmacKey, generatePbkdf2Key, generateSymmetricKey, importEcdsaKey, importHkdfKey, importHmacKey, importPbkdf2Key, importSymmetricKey, sign, verify } from '../cryptography.js';
|
|
4
|
-
describe('Cryptography Utilities', () => {
|
|
5
|
-
test('encrypt and decrypt with AES-GCM (string)', async () => {
|
|
6
|
-
const key = await generateSymmetricKey({ name: 'AES-GCM', length: 256 });
|
|
7
|
-
const data = 'Hello World';
|
|
8
|
-
const iv = globalThis.crypto.getRandomValues(new Uint8Array(12));
|
|
9
|
-
const algorithm = { name: 'AES-GCM', iv };
|
|
10
|
-
const encryptionResult = encrypt(algorithm, key, data);
|
|
11
|
-
const encryptedBuffer = await encryptionResult.toBuffer();
|
|
12
|
-
const decryptionResult = decrypt(algorithm, key, encryptedBuffer);
|
|
13
|
-
const decryptedText = await decryptionResult.toUtf8();
|
|
14
|
-
expect(decryptedText).toBe(data);
|
|
15
|
-
expect(await encryptionResult.toHex()).toBeTypeOf('string');
|
|
16
|
-
expect(await encryptionResult.toBase64()).toBeTypeOf('string');
|
|
17
|
-
expect(await encryptionResult.toBase64Url()).toBeTypeOf('string');
|
|
18
|
-
expect(await encryptionResult.toZBase32()).toBeTypeOf('string');
|
|
19
|
-
});
|
|
20
|
-
test('encrypt and decrypt with AES-CBC (Uint8Array)', async () => {
|
|
21
|
-
const key = await generateSymmetricKey({ name: 'AES-CBC', length: 256 });
|
|
22
|
-
const data = new Uint8Array([1, 2, 3, 4, 5]);
|
|
23
|
-
const iv = globalThis.crypto.getRandomValues(new Uint8Array(16));
|
|
24
|
-
const algorithm = { name: 'AES-CBC', iv };
|
|
25
|
-
const encryptionResult = encrypt(algorithm, key, data);
|
|
26
|
-
const encryptedBuffer = await encryptionResult.toBuffer();
|
|
27
|
-
const decryptionResult = decrypt(algorithm, key, encryptedBuffer);
|
|
28
|
-
const decryptedBuffer = await decryptionResult.toBuffer();
|
|
29
|
-
expect(new Uint8Array(decryptedBuffer)).toEqual(data);
|
|
30
|
-
});
|
|
31
|
-
test('digest with SHA-256', async () => {
|
|
32
|
-
const data = 'Hello World';
|
|
33
|
-
const result = digest('SHA-256', data);
|
|
34
|
-
const hex = await result.toHex();
|
|
35
|
-
// SHA-256 of "Hello World"
|
|
36
|
-
expect(hex).toBe('a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e');
|
|
37
|
-
const bufferResult = digest('SHA-256', encodeUtf8(data));
|
|
38
|
-
expect(await bufferResult.toHex()).toBe(hex);
|
|
39
|
-
});
|
|
40
|
-
test('sign and verify with HMAC', async () => {
|
|
41
|
-
const key = await generateHmacKey('SHA-256');
|
|
42
|
-
const data = 'Hello World';
|
|
43
|
-
const algorithm = { name: 'HMAC', hash: 'SHA-256' };
|
|
44
|
-
const signatureResult = sign(algorithm, key, data);
|
|
45
|
-
const signature = await signatureResult.toBuffer();
|
|
46
|
-
// Test with mixed string/binary
|
|
47
|
-
expect(await verify(algorithm, key, signature, data)).toBe(true);
|
|
48
|
-
expect(await verify(algorithm, key, new Uint8Array(signature), encodeUtf8(data))).toBe(true);
|
|
49
|
-
const isInvalid = await verify(algorithm, key, signature, 'Wrong Data');
|
|
50
|
-
expect(isInvalid).toBe(false);
|
|
51
|
-
const isInvalidSignature = await verify(algorithm, key, new Uint8Array(signature.byteLength), data);
|
|
52
|
-
expect(isInvalidSignature).toBe(false);
|
|
53
|
-
});
|
|
54
|
-
test('import and export HMAC key (raw)', async () => {
|
|
55
|
-
const rawKey = encodeUtf8('my-secret-key');
|
|
56
|
-
const key = await importHmacKey('raw-secret', 'SHA-256', rawKey, true);
|
|
57
|
-
expect(key.algorithm.name).toBe('HMAC');
|
|
58
|
-
expect(key.algorithm.hash.name).toBe('SHA-256');
|
|
59
|
-
const exportedKey = await globalThis.crypto.subtle.exportKey('raw', key);
|
|
60
|
-
expect(new Uint8Array(exportedKey)).toEqual(rawKey);
|
|
61
|
-
// Test import with string
|
|
62
|
-
const keyFromString = await importHmacKey('raw-secret', 'SHA-256', encodeUtf8('my-secret-key'));
|
|
63
|
-
expect(keyFromString.algorithm.name).toBe('HMAC');
|
|
64
|
-
});
|
|
65
|
-
test('import HMAC key (JWK)', async () => {
|
|
66
|
-
const jwk = {
|
|
67
|
-
kty: 'oct',
|
|
68
|
-
k: 'bXktc2VjcmV0LWtleQ', // "my-secret-key" in base64url
|
|
69
|
-
alg: 'HS256',
|
|
70
|
-
ext: true,
|
|
71
|
-
};
|
|
72
|
-
const key = await importHmacKey('jwk', 'SHA-256', jwk, true);
|
|
73
|
-
expect(key.algorithm.name).toBe('HMAC');
|
|
74
|
-
const exportedKey = await globalThis.crypto.subtle.exportKey('raw', key);
|
|
75
|
-
expect(new Uint8Array(exportedKey)).toEqual(encodeUtf8('my-secret-key'));
|
|
76
|
-
});
|
|
77
|
-
test('import symmetric key (raw)', async () => {
|
|
78
|
-
const rawKey = globalThis.crypto.getRandomValues(new Uint8Array(32));
|
|
79
|
-
const key = await importSymmetricKey('raw-secret', { name: 'AES-GCM', length: 256 }, rawKey, true);
|
|
80
|
-
expect(key.algorithm.name).toBe('AES-GCM');
|
|
81
|
-
expect(key.algorithm.length).toBe(256);
|
|
82
|
-
const exportedKey = await globalThis.crypto.subtle.exportKey('raw', key);
|
|
83
|
-
expect(new Uint8Array(exportedKey)).toEqual(rawKey);
|
|
84
|
-
// Test import with encoded string (exactly 32 chars)
|
|
85
|
-
const keyFromString = await importSymmetricKey('raw-secret', { name: 'AES-GCM', length: 256 }, encodeUtf8('01234567890123456789012345678901'));
|
|
86
|
-
expect(keyFromString.algorithm.name).toBe('AES-GCM');
|
|
87
|
-
});
|
|
88
|
-
test('import symmetric key (JWK)', async () => {
|
|
89
|
-
const jwk = {
|
|
90
|
-
kty: 'oct',
|
|
91
|
-
k: 'AAECAwQFBgcICQoLDA0ODw', // [0, 1, ..., 15]
|
|
92
|
-
alg: 'A128GCM',
|
|
93
|
-
ext: true,
|
|
94
|
-
};
|
|
95
|
-
const key = await importSymmetricKey('jwk', { name: 'AES-GCM', length: 128 }, jwk, true);
|
|
96
|
-
expect(key.algorithm.name).toBe('AES-GCM');
|
|
97
|
-
const exportedJwk = await globalThis.crypto.subtle.exportKey('jwk', key);
|
|
98
|
-
expect(exportedJwk.k).toBe(jwk.k);
|
|
99
|
-
});
|
|
100
|
-
test('sign and verify with ECDSA', async () => {
|
|
101
|
-
const keyPair = await generateEcdsaKey('P-256');
|
|
102
|
-
const data = 'Hello World';
|
|
103
|
-
const algorithm = { name: 'ECDSA', hash: 'SHA-256' };
|
|
104
|
-
const signatureResult = sign(algorithm, keyPair.privateKey, data);
|
|
105
|
-
const signature = await signatureResult.toBuffer();
|
|
106
|
-
const isValid = await verify(algorithm, keyPair.publicKey, signature, data);
|
|
107
|
-
expect(isValid).toBe(true);
|
|
108
|
-
});
|
|
109
|
-
test('import ECDSA public key (SPKI)', async () => {
|
|
110
|
-
const keyPair = await generateEcdsaKey('P-256', true);
|
|
111
|
-
const spki = await globalThis.crypto.subtle.exportKey('spki', keyPair.publicKey);
|
|
112
|
-
const importedKey = await importEcdsaKey('spki', 'P-256', spki);
|
|
113
|
-
expect(importedKey.type).toBe('public');
|
|
114
|
-
expect(importedKey.algorithm.name).toBe('ECDSA');
|
|
115
|
-
});
|
|
116
|
-
test('import ECDSA public key (JWK)', async () => {
|
|
117
|
-
const keyPair = await generateEcdsaKey('P-256', true);
|
|
118
|
-
const jwk = await globalThis.crypto.subtle.exportKey('jwk', keyPair.publicKey);
|
|
119
|
-
const importedKey = await importEcdsaKey('jwk', 'P-256', jwk);
|
|
120
|
-
expect(importedKey.type).toBe('public');
|
|
121
|
-
expect(importedKey.algorithm.name).toBe('ECDSA');
|
|
122
|
-
});
|
|
123
|
-
test('import HKDF key', async () => {
|
|
124
|
-
const baseKeyMaterial = encodeUtf8('base-secret');
|
|
125
|
-
const baseKey = await importHkdfKey('raw', baseKeyMaterial);
|
|
126
|
-
expect(baseKey.algorithm.name).toBe('HKDF');
|
|
127
|
-
// Test import with string
|
|
128
|
-
const keyFromString = await importHkdfKey('raw', encodeUtf8('base-secret'));
|
|
129
|
-
expect(keyFromString.algorithm.name).toBe('HKDF');
|
|
130
|
-
});
|
|
131
|
-
test('PBKDF2 derivation', async () => {
|
|
132
|
-
const baseKey = await generatePbkdf2Key();
|
|
133
|
-
const salt = globalThis.crypto.getRandomValues(new Uint8Array(16));
|
|
134
|
-
const algorithm = {
|
|
135
|
-
name: 'PBKDF2',
|
|
136
|
-
salt,
|
|
137
|
-
iterations: 1000,
|
|
138
|
-
hash: 'SHA-256',
|
|
139
|
-
};
|
|
140
|
-
const derivedBytes = await deriveBytes(algorithm, baseKey, 32);
|
|
141
|
-
expect(derivedBytes.byteLength).toBe(32);
|
|
142
|
-
const importedKey = await importPbkdf2Key('raw-secret', encodeUtf8('password'));
|
|
143
|
-
const derivedBytes2 = await deriveBytes(algorithm, importedKey, 32);
|
|
144
|
-
expect(derivedBytes2.byteLength).toBe(32);
|
|
145
|
-
// Test import with string
|
|
146
|
-
const keyFromString = await importPbkdf2Key('raw-secret', encodeUtf8('password'));
|
|
147
|
-
expect(keyFromString.algorithm.name).toBe('PBKDF2');
|
|
148
|
-
});
|
|
149
|
-
test('CryptionResult helper methods', async () => {
|
|
150
|
-
const data = 'Hello World';
|
|
151
|
-
const result = digest('SHA-256', data);
|
|
152
|
-
expect(await result.toBuffer()).toBeInstanceOf(ArrayBuffer);
|
|
153
|
-
expect(await result.toHex()).toBeTypeOf('string');
|
|
154
|
-
expect(await result.toBase64()).toBeTypeOf('string');
|
|
155
|
-
expect(await result.toBase64Url()).toBeTypeOf('string');
|
|
156
|
-
expect(await result.toZBase32()).toBeTypeOf('string');
|
|
157
|
-
const key = await generateHmacKey('SHA-256');
|
|
158
|
-
const signResult = sign({ name: 'HMAC', hash: 'SHA-256' }, key, data);
|
|
159
|
-
expect(await signResult.toHex()).toBeTypeOf('string');
|
|
160
|
-
expect(await signResult.toBase64()).toBeTypeOf('string');
|
|
161
|
-
expect(await signResult.toBase64Url()).toBeTypeOf('string');
|
|
162
|
-
expect(await signResult.toZBase32()).toBeTypeOf('string');
|
|
163
|
-
const symKey = await generateSymmetricKey({ name: 'AES-GCM', length: 256 });
|
|
164
|
-
const iv = globalThis.crypto.getRandomValues(new Uint8Array(12));
|
|
165
|
-
const encResult = encrypt({ name: 'AES-GCM', iv }, symKey, data);
|
|
166
|
-
const encrypted = await encResult.toBuffer();
|
|
167
|
-
expect(await encResult.toHex()).toBeTypeOf('string');
|
|
168
|
-
const decResult = decrypt({ name: 'AES-GCM', iv }, symKey, encrypted);
|
|
169
|
-
expect(await decResult.toHex()).toBeTypeOf('string');
|
|
170
|
-
expect(await decResult.toBase64()).toBeTypeOf('string');
|
|
171
|
-
expect(await decResult.toBase64Url()).toBeTypeOf('string');
|
|
172
|
-
expect(await decResult.toZBase32()).toBeTypeOf('string');
|
|
173
|
-
expect(await decResult.toUtf8()).toBe(data);
|
|
174
|
-
});
|
|
175
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from 'vitest';
|
|
2
|
-
import { InvalidTokenError } from '../../errors/invalid-token.error.js';
|
|
3
|
-
import { generateKmacKey, generateSymmetricKey } from '../cryptography.js';
|
|
4
|
-
import { createJwtTokenString, parseAndValidateJwtTokenString, parseJwtTokenString } from '../jwt.js';
|
|
5
|
-
describe('JWT Utilities', () => {
|
|
6
|
-
test('create, parse and validate JWT', async () => {
|
|
7
|
-
const key = await generateKmacKey('KMAC256');
|
|
8
|
-
const token = {
|
|
9
|
-
header: { alg: 'KMAC256', typ: 'JWT' },
|
|
10
|
-
payload: { sub: '1234567890', name: 'John Doe', iat: 1516239022 },
|
|
11
|
-
};
|
|
12
|
-
const tokenString = await createJwtTokenString(token, key);
|
|
13
|
-
expect(tokenString).toBeTypeOf('string');
|
|
14
|
-
expect(tokenString.split('.').length).toBe(3);
|
|
15
|
-
const parsed = parseJwtTokenString(tokenString);
|
|
16
|
-
expect(parsed.token.payload).toEqual(token.payload);
|
|
17
|
-
const validated = await parseAndValidateJwtTokenString(tokenString, 'KMAC256', key);
|
|
18
|
-
expect(validated.payload).toEqual(token.payload);
|
|
19
|
-
});
|
|
20
|
-
test('fail on invalid signature', async () => {
|
|
21
|
-
const key = await generateKmacKey('KMAC256');
|
|
22
|
-
const otherKey = await generateKmacKey('KMAC256');
|
|
23
|
-
const token = {
|
|
24
|
-
header: { alg: 'KMAC256', typ: 'JWT' },
|
|
25
|
-
payload: { sub: '1234567890' },
|
|
26
|
-
};
|
|
27
|
-
const tokenString = await createJwtTokenString(token, key);
|
|
28
|
-
await expect(parseAndValidateJwtTokenString(tokenString, 'KMAC256', otherKey)).rejects.toThrow(InvalidTokenError);
|
|
29
|
-
});
|
|
30
|
-
test('fail on disallowed algorithm', async () => {
|
|
31
|
-
const key = await generateKmacKey('KMAC256');
|
|
32
|
-
const token = {
|
|
33
|
-
header: { alg: 'KMAC256', typ: 'JWT' },
|
|
34
|
-
payload: { sub: '1234567890' },
|
|
35
|
-
};
|
|
36
|
-
const tokenString = await createJwtTokenString(token, key);
|
|
37
|
-
await expect(parseAndValidateJwtTokenString(tokenString, 'KMAC128', key)).rejects.toThrow(InvalidTokenError);
|
|
38
|
-
});
|
|
39
|
-
test('fail on malformed token', () => {
|
|
40
|
-
expect(() => parseJwtTokenString('a.b')).toThrow('Invalid token format');
|
|
41
|
-
expect(() => parseJwtTokenString('')).toThrow('Missing authorization token');
|
|
42
|
-
});
|
|
43
|
-
test('fail on generic error in parseAndValidateJwtTokenString', async () => {
|
|
44
|
-
const key = await generateKmacKey('KMAC256');
|
|
45
|
-
const token = {
|
|
46
|
-
header: { alg: 'KMAC256', typ: 'JWT' },
|
|
47
|
-
payload: { sub: '1234567890' },
|
|
48
|
-
};
|
|
49
|
-
const tokenString = await createJwtTokenString(token, key);
|
|
50
|
-
// Use an incompatible key type to trigger a generic error in Web Crypto
|
|
51
|
-
const aesKey = await generateSymmetricKey({ name: 'AES-GCM', length: 256 });
|
|
52
|
-
await expect(parseAndValidateJwtTokenString(tokenString, 'KMAC256', aesKey)).rejects.toThrow('Invalid token');
|
|
53
|
-
});
|
|
54
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { encodeUtf8 } from '../../utils/encoding.js';
|
|
2
|
-
import { describe, expect, test } from 'vitest';
|
|
3
|
-
import { decrypt, deriveBytes, encrypt, generateAsymmetricKey, generateSymmetricKey, getPublicKey, importKey, importSymmetricKey, sign, supports, verify } from '../cryptography.js';
|
|
4
|
-
describe('Modern Cryptography Features', () => {
|
|
5
|
-
test('SubtleCrypto.supports', async () => {
|
|
6
|
-
expect(await supports('generateKey', { name: 'AES-GCM', length: 256 })).toBe(true);
|
|
7
|
-
expect(await supports('sign', { name: 'HMAC', hash: 'SHA-256' })).toBe(true);
|
|
8
|
-
});
|
|
9
|
-
test('KMAC128 signing and verification', async () => {
|
|
10
|
-
const isSupported = await supports('generateKey', { name: 'KMAC128' });
|
|
11
|
-
if (!isSupported) {
|
|
12
|
-
throw new Error('KMAC128 not supported in this environment');
|
|
13
|
-
}
|
|
14
|
-
const key = await importSymmetricKey('raw-secret', { name: 'KMAC128' }, encodeUtf8('my-secret-key-128bits'));
|
|
15
|
-
const data = 'Hello KMAC';
|
|
16
|
-
const algorithm = { name: 'KMAC128', length: 128, outputLength: 32 };
|
|
17
|
-
const signatureResult = sign(algorithm, key, data);
|
|
18
|
-
const signature = await signatureResult.toBuffer();
|
|
19
|
-
expect(await verify(algorithm, key, signature, data)).toBe(true);
|
|
20
|
-
});
|
|
21
|
-
test('KMAC256 signing and verification', async () => {
|
|
22
|
-
const isSupported = await supports('generateKey', { name: 'KMAC256' });
|
|
23
|
-
console.log('KMAC256 supported:', isSupported);
|
|
24
|
-
if (!isSupported) {
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
const key = await importSymmetricKey('raw-secret', { name: 'KMAC256' }, encodeUtf8('my-secret-key-256bits-long-enough-for-kmac256'));
|
|
28
|
-
const data = 'Hello KMAC256';
|
|
29
|
-
const algorithm = { name: 'KMAC256', length: 256, outputLength: 64 };
|
|
30
|
-
const signatureResult = sign(algorithm, key, data);
|
|
31
|
-
const signature = await signatureResult.toBuffer();
|
|
32
|
-
expect(await verify(algorithm, key, signature, data)).toBe(true);
|
|
33
|
-
});
|
|
34
|
-
test('Argon2id derivation', async () => {
|
|
35
|
-
const isSupported = await supports('importKey', 'Argon2id');
|
|
36
|
-
if (!isSupported) {
|
|
37
|
-
throw new Error('Argon2id not supported in this environment');
|
|
38
|
-
}
|
|
39
|
-
const password = 'my-password';
|
|
40
|
-
const salt = globalThis.crypto.getRandomValues(new Uint8Array(16));
|
|
41
|
-
const key = await importKey('raw-secret', encodeUtf8(password), { name: 'Argon2id' }, false, ['deriveBits']);
|
|
42
|
-
const argon2Params = {
|
|
43
|
-
name: 'Argon2id',
|
|
44
|
-
nonce: salt,
|
|
45
|
-
memory: 8,
|
|
46
|
-
parallelism: 1,
|
|
47
|
-
passes: 1,
|
|
48
|
-
};
|
|
49
|
-
const derivedBits = await deriveBytes(argon2Params, key, 32);
|
|
50
|
-
expect(derivedBits.byteLength).toBe(32);
|
|
51
|
-
});
|
|
52
|
-
test('ML-DSA-44 signing and verification', async () => {
|
|
53
|
-
const isSupported = await supports('generateKey', 'ML-DSA-44');
|
|
54
|
-
if (!isSupported) {
|
|
55
|
-
throw new Error('ML-DSA-44 not supported in this environment');
|
|
56
|
-
}
|
|
57
|
-
const keyPair = await generateAsymmetricKey({ name: 'ML-DSA-44', namedCurve: 'ML-DSA-44' }, true, ['sign', 'verify']);
|
|
58
|
-
const data = 'Hello ML-DSA';
|
|
59
|
-
const algorithm = { name: 'ML-DSA-44' };
|
|
60
|
-
const signatureResult = sign(algorithm, keyPair.privateKey, data);
|
|
61
|
-
const signature = await signatureResult.toBuffer();
|
|
62
|
-
expect(await verify(algorithm, keyPair.publicKey, signature, data)).toBe(true);
|
|
63
|
-
});
|
|
64
|
-
test('ChaCha20-Poly1305 encryption and decryption', async () => {
|
|
65
|
-
const isSupported = await supports('generateKey', { name: 'ChaCha20-Poly1305' });
|
|
66
|
-
if (!isSupported) {
|
|
67
|
-
throw new Error('ChaCha20-Poly1305 not supported in this environment');
|
|
68
|
-
}
|
|
69
|
-
const key = await generateSymmetricKey({ name: 'ChaCha20-Poly1305', length: 256 });
|
|
70
|
-
const data = 'Hello ChaCha20';
|
|
71
|
-
const nonce = globalThis.crypto.getRandomValues(new Uint8Array(12));
|
|
72
|
-
const algorithm = { name: 'ChaCha20-Poly1305', iv: nonce };
|
|
73
|
-
const encryptionResult = encrypt(algorithm, key, data);
|
|
74
|
-
const encryptedBuffer = await encryptionResult.toBuffer();
|
|
75
|
-
const decryptionResult = decrypt(algorithm, key, encryptedBuffer);
|
|
76
|
-
const decryptedText = await decryptionResult.toUtf8();
|
|
77
|
-
expect(decryptedText).toBe(data);
|
|
78
|
-
});
|
|
79
|
-
test('AES-OCB encryption and decryption', async () => {
|
|
80
|
-
const isSupported = await supports('generateKey', { name: 'AES-OCB', length: 256 });
|
|
81
|
-
if (!isSupported) {
|
|
82
|
-
throw new Error('AES-OCB not supported in this environment');
|
|
83
|
-
}
|
|
84
|
-
const key = await generateSymmetricKey({ name: 'AES-OCB', length: 256 });
|
|
85
|
-
const data = 'Hello AES-OCB';
|
|
86
|
-
const iv = globalThis.crypto.getRandomValues(new Uint8Array(12));
|
|
87
|
-
const algorithm = { name: 'AES-OCB', iv };
|
|
88
|
-
const encryptionResult = encrypt(algorithm, key, data);
|
|
89
|
-
const encryptedBuffer = await encryptionResult.toBuffer();
|
|
90
|
-
const decryptionResult = decrypt(algorithm, key, encryptedBuffer);
|
|
91
|
-
const decryptedText = await decryptionResult.toUtf8();
|
|
92
|
-
expect(decryptedText).toBe(data);
|
|
93
|
-
});
|
|
94
|
-
test('getPublicKey from private key', async () => {
|
|
95
|
-
const isSupported = await supports('getPublicKey', 'Ed25519'); // getPublicKey support is often generic but checking Ed25519
|
|
96
|
-
if (!isSupported) {
|
|
97
|
-
// Fallback check if getPublicKey is supported but supports doesn't report it well for Ed25519
|
|
98
|
-
throw new Error('getPublicKey not supported in this environment');
|
|
99
|
-
}
|
|
100
|
-
const keyPair = await generateAsymmetricKey({ name: 'Ed25519', namedCurve: 'Ed25519' }, true, ['sign', 'verify']);
|
|
101
|
-
const publicKey = await getPublicKey(keyPair.privateKey, ['verify']);
|
|
102
|
-
expect(publicKey.type).toBe('public');
|
|
103
|
-
expect(publicKey.algorithm.name).toBe('Ed25519');
|
|
104
|
-
});
|
|
105
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from 'vitest';
|
|
2
|
-
import { runInInjectionContext } from '../../injector/inject.js';
|
|
3
|
-
import { Injector } from '../../injector/injector.js';
|
|
4
|
-
import { importKey } from '../cryptography.js';
|
|
5
|
-
import { configureSecrets, injectDerivedBytes, injectDerivedCryptoKey, masterSecretAlgorithm, masterSecretKeyUsages } from '../module.js';
|
|
6
|
-
describe('Secrets Module', () => {
|
|
7
|
-
test('configure and derive bytes', async () => {
|
|
8
|
-
const injector = new Injector('test');
|
|
9
|
-
const key = 'my-super-secret-key';
|
|
10
|
-
configureSecrets({ injector, key });
|
|
11
|
-
await runInInjectionContext(injector, async () => {
|
|
12
|
-
const derived = injectDerivedBytes('test-info', 32);
|
|
13
|
-
const sameDerived = injectDerivedBytes('test-info', 32);
|
|
14
|
-
const differentDerived = injectDerivedBytes('other-info', 32);
|
|
15
|
-
const bytes = await derived.getBytes();
|
|
16
|
-
expect(bytes.byteLength).toBe(32);
|
|
17
|
-
const sameBytes = await sameDerived.getBytes();
|
|
18
|
-
expect(new Uint8Array(bytes)).toEqual(new Uint8Array(sameBytes));
|
|
19
|
-
const differentBytes = await differentDerived.getBytes();
|
|
20
|
-
expect(new Uint8Array(bytes)).not.toEqual(new Uint8Array(differentBytes));
|
|
21
|
-
});
|
|
22
|
-
});
|
|
23
|
-
test('derive crypto key', async () => {
|
|
24
|
-
const injector = new Injector('test');
|
|
25
|
-
const key = 'my-super-secret-key';
|
|
26
|
-
configureSecrets({ injector, key });
|
|
27
|
-
await runInInjectionContext(injector, async () => {
|
|
28
|
-
const derived = injectDerivedCryptoKey('test-info', { name: 'HMAC', hash: 'SHA-256' }, ['sign']);
|
|
29
|
-
const cryptoKey = await derived.getKey();
|
|
30
|
-
expect(cryptoKey.type).toBe('secret');
|
|
31
|
-
expect(cryptoKey.algorithm.name).toBe('HMAC');
|
|
32
|
-
expect(cryptoKey.usages).toContain('sign');
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
test('fail when not configured', async () => {
|
|
36
|
-
const injector = new Injector('test');
|
|
37
|
-
await runInInjectionContext(injector, async () => {
|
|
38
|
-
// getBaseKeyFromInjector should throw if not configured
|
|
39
|
-
expect(() => injectDerivedBytes('test-info', 32)).toThrow('No secret key configured');
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
test('fail when requesting bytes from key-configured derived key', async () => {
|
|
43
|
-
const injector = new Injector('test');
|
|
44
|
-
configureSecrets({ injector, key: 'secret' });
|
|
45
|
-
await runInInjectionContext(injector, async () => {
|
|
46
|
-
const derived = injectDerivedCryptoKey('info', { name: 'HMAC', hash: 'SHA-256' }, ['sign']);
|
|
47
|
-
await expect(derived.getBytes()).rejects.toThrow('This key was not configured to derive bytes');
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
test('fail when requesting key from byte-configured derived key', async () => {
|
|
51
|
-
const injector = new Injector('test');
|
|
52
|
-
configureSecrets({ injector, key: 'secret' });
|
|
53
|
-
await runInInjectionContext(injector, async () => {
|
|
54
|
-
const derived = injectDerivedBytes('info', 32);
|
|
55
|
-
await expect(derived.getKey()).rejects.toThrow('This key was not configured to derive a CryptoKey');
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
test('hierarchical injector configuration', async () => {
|
|
59
|
-
const parentInjector = new Injector('parent');
|
|
60
|
-
const childInjector = parentInjector.fork('child');
|
|
61
|
-
const key = 'parent-key';
|
|
62
|
-
configureSecrets({ injector: parentInjector, key });
|
|
63
|
-
await runInInjectionContext(childInjector, async () => {
|
|
64
|
-
const derived = injectDerivedBytes('info', 32);
|
|
65
|
-
const bytes = await derived.getBytes();
|
|
66
|
-
expect(bytes.byteLength).toBe(32);
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
test('global injector configuration', async () => {
|
|
70
|
-
const key = 'global-key';
|
|
71
|
-
configureSecrets({ key }); // Registers on global Injector
|
|
72
|
-
const injector = new Injector('test');
|
|
73
|
-
await runInInjectionContext(injector, async () => {
|
|
74
|
-
const derived = injectDerivedBytes('info', 32);
|
|
75
|
-
const bytes = await derived.getBytes();
|
|
76
|
-
expect(bytes.byteLength).toBe(32);
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
test('configureSecrets with BufferSource', async () => {
|
|
80
|
-
const injector = new Injector('test');
|
|
81
|
-
const key = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6]);
|
|
82
|
-
configureSecrets({ injector, key });
|
|
83
|
-
await runInInjectionContext(injector, async () => {
|
|
84
|
-
const derived = injectDerivedBytes(new Uint8Array([1, 2, 3]), 32, { salt: new Uint8Array([4, 5, 6]) });
|
|
85
|
-
const bytes = await derived.getBytes();
|
|
86
|
-
expect(bytes.byteLength).toBe(32);
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
test('configureSecrets with CryptoKey', async () => {
|
|
90
|
-
const injector = new Injector('test');
|
|
91
|
-
const keyMaterial = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6]);
|
|
92
|
-
const cryptoKey = await importKey('raw-secret', keyMaterial, masterSecretAlgorithm, false, masterSecretKeyUsages);
|
|
93
|
-
configureSecrets({ injector, key: cryptoKey });
|
|
94
|
-
await runInInjectionContext(injector, async () => {
|
|
95
|
-
const derived = injectDerivedBytes('', 32, { salt: 'my-salt' });
|
|
96
|
-
const bytes = await derived.getBytes();
|
|
97
|
-
expect(bytes.byteLength).toBe(32);
|
|
98
|
-
});
|
|
99
|
-
});
|
|
100
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|