@openora/core 0.4.1-canary.37 → 0.4.1-canary.39
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/dist/.tsbuildinfo +1 -1
- package/dist/admin-console/__tests__/backoffice.router.test.js +67 -51
- package/dist/admin-console/__tests__/backoffice.router.test.js.map +1 -1
- package/dist/admin-console/__tests__/backoffice.service.test.js +1 -13
- package/dist/admin-console/__tests__/backoffice.service.test.js.map +1 -1
- package/dist/analytics/__tests__/analytics.contract.test.js +12 -0
- package/dist/analytics/__tests__/analytics.contract.test.js.map +1 -1
- package/dist/analytics/__tests__/financial-analytics.service.test.js +3 -3
- package/dist/analytics/__tests__/financial-analytics.service.test.js.map +1 -1
- package/dist/analytics/service/financial-analytics.service.d.ts.map +1 -1
- package/dist/analytics/service/financial-analytics.service.js +14 -17
- package/dist/analytics/service/financial-analytics.service.js.map +1 -1
- package/dist/analytics/service/funnel-analytics.service.d.ts.map +1 -1
- package/dist/analytics/service/funnel-analytics.service.js +8 -11
- package/dist/analytics/service/funnel-analytics.service.js.map +1 -1
- package/dist/audit/__tests__/audit.service.test.js +128 -251
- package/dist/audit/__tests__/audit.service.test.js.map +1 -1
- package/dist/casino/gaming/__tests__/gaming.service.test.js +83 -89
- package/dist/casino/gaming/__tests__/gaming.service.test.js.map +1 -1
- package/dist/casino/lobby/__tests__/lobby.cache.test.js +42 -33
- package/dist/casino/lobby/__tests__/lobby.cache.test.js.map +1 -1
- package/dist/cms/__tests__/cms.reads.test.js +59 -80
- package/dist/cms/__tests__/cms.reads.test.js.map +1 -1
- package/dist/cms/__tests__/cms.router.test.js +62 -20
- package/dist/cms/__tests__/cms.router.test.js.map +1 -1
- package/dist/cms/__tests__/cms.service.test.js +116 -14
- package/dist/cms/__tests__/cms.service.test.js.map +1 -1
- package/dist/common/errors/__tests__/errors.mapper.test.d.ts +2 -0
- package/dist/common/errors/__tests__/errors.mapper.test.d.ts.map +1 -0
- package/dist/common/errors/__tests__/errors.mapper.test.js +59 -0
- package/dist/common/errors/__tests__/errors.mapper.test.js.map +1 -0
- package/dist/compliance/__tests__/assert.test.d.ts +2 -0
- package/dist/compliance/__tests__/assert.test.d.ts.map +1 -0
- package/dist/compliance/__tests__/assert.test.js +34 -0
- package/dist/compliance/__tests__/assert.test.js.map +1 -0
- package/dist/compliance/__tests__/compliance.service.test.js +149 -84
- package/dist/compliance/__tests__/compliance.service.test.js.map +1 -1
- package/dist/compliance/__tests__/kyc.service.test.js +247 -155
- package/dist/compliance/__tests__/kyc.service.test.js.map +1 -1
- package/dist/compliance/__tests__/limits.contract.test.d.ts +2 -0
- package/dist/compliance/__tests__/limits.contract.test.d.ts.map +1 -0
- package/dist/compliance/__tests__/limits.contract.test.js +43 -0
- package/dist/compliance/__tests__/limits.contract.test.js.map +1 -0
- package/dist/compliance/__tests__/rg-monitoring.service.test.js +256 -101
- package/dist/compliance/__tests__/rg-monitoring.service.test.js.map +1 -1
- package/dist/compliance/__tests__/rg.contract.test.js +1 -20
- package/dist/compliance/__tests__/rg.contract.test.js.map +1 -1
- package/dist/compliance/__tests__/rg.router.test.js +113 -65
- package/dist/compliance/__tests__/rg.router.test.js.map +1 -1
- package/dist/compliance/__tests__/rg.service.test.js +277 -235
- package/dist/compliance/__tests__/rg.service.test.js.map +1 -1
- package/dist/compliance/service/rg-monitoring.service.d.ts.map +1 -1
- package/dist/compliance/service/rg-monitoring.service.js +11 -8
- package/dist/compliance/service/rg-monitoring.service.js.map +1 -1
- package/dist/contracts/__tests__/compose-contract.test.d.ts +2 -0
- package/dist/contracts/__tests__/compose-contract.test.d.ts.map +1 -0
- package/dist/contracts/__tests__/compose-contract.test.js +27 -0
- package/dist/contracts/__tests__/compose-contract.test.js.map +1 -0
- package/dist/contracts/adapters/__tests__/token.test.d.ts +2 -0
- package/dist/contracts/adapters/__tests__/token.test.d.ts.map +1 -0
- package/dist/contracts/adapters/__tests__/token.test.js +14 -0
- package/dist/contracts/adapters/__tests__/token.test.js.map +1 -0
- package/dist/contracts/schemas/__tests__/events.test.d.ts +2 -0
- package/dist/contracts/schemas/__tests__/events.test.d.ts.map +1 -0
- package/dist/contracts/schemas/__tests__/events.test.js +51 -0
- package/dist/contracts/schemas/__tests__/events.test.js.map +1 -0
- package/dist/contracts/schemas/__tests__/igaming-config.test.d.ts +2 -0
- package/dist/contracts/schemas/__tests__/igaming-config.test.d.ts.map +1 -0
- package/dist/contracts/schemas/__tests__/igaming-config.test.js +38 -0
- package/dist/contracts/schemas/__tests__/igaming-config.test.js.map +1 -0
- package/dist/contracts/schemas/reporting.d.ts +7 -2
- package/dist/contracts/schemas/reporting.d.ts.map +1 -1
- package/dist/contracts/schemas/reporting.js +2 -1
- package/dist/contracts/schemas/reporting.js.map +1 -1
- package/dist/engagement/chat/__tests__/chat.service.test.js +524 -364
- package/dist/engagement/chat/__tests__/chat.service.test.js.map +1 -1
- package/dist/engagement/notifications/__tests__/notifications.service.test.js +125 -68
- package/dist/engagement/notifications/__tests__/notifications.service.test.js.map +1 -1
- package/dist/iam/__tests__/iam.service.test.js +367 -596
- package/dist/iam/__tests__/iam.service.test.js.map +1 -1
- package/dist/pam/identity/__tests__/admin-user-directory.test.js +144 -68
- package/dist/pam/identity/__tests__/admin-user-directory.test.js.map +1 -1
- package/dist/pam/identity/__tests__/identity.rate-limit.test.js +33 -22
- package/dist/pam/identity/__tests__/identity.rate-limit.test.js.map +1 -1
- package/dist/pam/identity/__tests__/identity.service.test.js +217 -298
- package/dist/pam/identity/__tests__/identity.service.test.js.map +1 -1
- package/dist/pam/identity/__tests__/login-enforcement.service.test.js +97 -32
- package/dist/pam/identity/__tests__/login-enforcement.service.test.js.map +1 -1
- package/dist/pam/identity/__tests__/phone-login.service.test.js +163 -134
- package/dist/pam/identity/__tests__/phone-login.service.test.js.map +1 -1
- package/dist/pam/identity/__tests__/rg-guard.test.d.ts +2 -0
- package/dist/pam/identity/__tests__/rg-guard.test.d.ts.map +1 -0
- package/dist/pam/identity/__tests__/rg-guard.test.js +21 -0
- package/dist/pam/identity/__tests__/rg-guard.test.js.map +1 -0
- package/dist/pam/player-management/__tests__/kyc-status-writer.test.js +73 -26
- package/dist/pam/player-management/__tests__/kyc-status-writer.test.js.map +1 -1
- package/dist/pam/player-management/__tests__/player.router.test.js +63 -46
- package/dist/pam/player-management/__tests__/player.router.test.js.map +1 -1
- package/dist/pam/player-management/__tests__/player.service.test.js +207 -111
- package/dist/pam/player-management/__tests__/player.service.test.js.map +1 -1
- package/dist/pam/profile/__tests__/profile.service.test.js +89 -41
- package/dist/pam/profile/__tests__/profile.service.test.js.map +1 -1
- package/dist/pam/shared/__tests__/shared-mappers.test.d.ts +2 -0
- package/dist/pam/shared/__tests__/shared-mappers.test.d.ts.map +1 -0
- package/dist/pam/shared/__tests__/shared-mappers.test.js +55 -0
- package/dist/pam/shared/__tests__/shared-mappers.test.js.map +1 -0
- package/dist/pam/tag/__tests__/get-active-tag-keys.test.js +72 -30
- package/dist/pam/tag/__tests__/get-active-tag-keys.test.js.map +1 -1
- package/dist/pam/tag/__tests__/tag-evaluation.service.test.js +308 -235
- package/dist/pam/tag/__tests__/tag-evaluation.service.test.js.map +1 -1
- package/dist/pam/tag/__tests__/tag-rule.service.test.js +136 -140
- package/dist/pam/tag/__tests__/tag-rule.service.test.js.map +1 -1
- package/dist/pam/tag/__tests__/tag.router.test.js +76 -25
- package/dist/pam/tag/__tests__/tag.router.test.js.map +1 -1
- package/dist/pam/tag/__tests__/tag.service.test.js +224 -247
- package/dist/pam/tag/__tests__/tag.service.test.js.map +1 -1
- package/dist/server/auth/__tests__/admin-guard.test.js +107 -117
- package/dist/server/auth/__tests__/admin-guard.test.js.map +1 -1
- package/dist/server/auth/__tests__/permission-levels.test.d.ts +2 -0
- package/dist/server/auth/__tests__/permission-levels.test.d.ts.map +1 -0
- package/dist/server/auth/__tests__/permission-levels.test.js +89 -0
- package/dist/server/auth/__tests__/permission-levels.test.js.map +1 -0
- package/dist/server/auth/__tests__/session-resolver.test.js +45 -13
- package/dist/server/auth/__tests__/session-resolver.test.js.map +1 -1
- package/dist/server/db/__tests__/query-helpers.test.js +72 -1
- package/dist/server/db/__tests__/query-helpers.test.js.map +1 -1
- package/dist/server/db/outbox/__tests__/relay.test.js +74 -81
- package/dist/server/db/outbox/__tests__/relay.test.js.map +1 -1
- package/dist/server/kernel/__tests__/bullmq-job-queue.test.js +204 -154
- package/dist/server/kernel/__tests__/bullmq-job-queue.test.js.map +1 -1
- package/dist/server/kernel/__tests__/cache.test.js +26 -13
- package/dist/server/kernel/__tests__/cache.test.js.map +1 -1
- package/dist/server/kernel/__tests__/domain-error.test.d.ts +2 -0
- package/dist/server/kernel/__tests__/domain-error.test.d.ts.map +1 -0
- package/dist/server/kernel/__tests__/domain-error.test.js +35 -0
- package/dist/server/kernel/__tests__/domain-error.test.js.map +1 -0
- package/dist/server/kernel/__tests__/error-reporter.test.d.ts +2 -0
- package/dist/server/kernel/__tests__/error-reporter.test.d.ts.map +1 -0
- package/dist/server/kernel/__tests__/error-reporter.test.js +52 -0
- package/dist/server/kernel/__tests__/error-reporter.test.js.map +1 -0
- package/dist/server/kernel/__tests__/event-bus.test.js +60 -20
- package/dist/server/kernel/__tests__/event-bus.test.js.map +1 -1
- package/dist/server/kernel/__tests__/orpc-error-map.test.d.ts +2 -0
- package/dist/server/kernel/__tests__/orpc-error-map.test.d.ts.map +1 -0
- package/dist/server/kernel/__tests__/orpc-error-map.test.js +54 -0
- package/dist/server/kernel/__tests__/orpc-error-map.test.js.map +1 -0
- package/dist/server/kernel/__tests__/platform-config-loader.test.d.ts +2 -0
- package/dist/server/kernel/__tests__/platform-config-loader.test.d.ts.map +1 -0
- package/dist/server/kernel/__tests__/platform-config-loader.test.js +112 -0
- package/dist/server/kernel/__tests__/platform-config-loader.test.js.map +1 -0
- package/dist/server/kernel/__tests__/rate-limiter.test.js +22 -13
- package/dist/server/kernel/__tests__/rate-limiter.test.js.map +1 -1
- package/dist/server/kernel/__tests__/realtime-transport.test.d.ts.map +1 -0
- package/dist/{testing/fakes → server/kernel}/__tests__/realtime-transport.test.js.map +1 -1
- package/dist/server/kernel/__tests__/redis-cache.test.js +34 -34
- package/dist/server/kernel/__tests__/redis-cache.test.js.map +1 -1
- package/dist/server/kernel/__tests__/redis-rate-limiter.test.js +49 -44
- package/dist/server/kernel/__tests__/redis-rate-limiter.test.js.map +1 -1
- package/dist/server/kernel/__tests__/redis-streams-broker.test.js +141 -262
- package/dist/server/kernel/__tests__/redis-streams-broker.test.js.map +1 -1
- package/dist/server/kernel/__tests__/request-context.test.d.ts +2 -0
- package/dist/server/kernel/__tests__/request-context.test.d.ts.map +1 -0
- package/dist/server/kernel/__tests__/request-context.test.js +64 -0
- package/dist/server/kernel/__tests__/request-context.test.js.map +1 -0
- package/dist/server/kernel/__tests__/router-utils.test.d.ts +2 -0
- package/dist/server/kernel/__tests__/router-utils.test.d.ts.map +1 -0
- package/dist/server/kernel/__tests__/router-utils.test.js +80 -0
- package/dist/server/kernel/__tests__/router-utils.test.js.map +1 -0
- package/dist/server/kernel/bullmq-job-queue.d.ts.map +1 -1
- package/dist/server/kernel/bullmq-job-queue.js +8 -2
- package/dist/server/kernel/bullmq-job-queue.js.map +1 -1
- package/dist/server/runtime/__tests__/create-app.test.js +26 -18
- package/dist/server/runtime/__tests__/create-app.test.js.map +1 -1
- package/dist/testing/index.d.ts +2 -6
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +2 -10
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/mock.d.ts +28 -16
- package/dist/testing/mock.d.ts.map +1 -1
- package/dist/testing/mock.js +58 -37
- package/dist/testing/mock.js.map +1 -1
- package/dist/testing/real-infra.d.ts +47 -0
- package/dist/testing/real-infra.d.ts.map +1 -0
- package/dist/testing/real-infra.js +122 -0
- package/dist/testing/real-infra.js.map +1 -0
- package/dist/wallet/__tests__/admin-reporting.test.js +201 -90
- package/dist/wallet/__tests__/admin-reporting.test.js.map +1 -1
- package/dist/wallet/__tests__/rail-for.test.d.ts +2 -0
- package/dist/wallet/__tests__/rail-for.test.d.ts.map +1 -0
- package/dist/wallet/__tests__/rail-for.test.js +22 -0
- package/dist/wallet/__tests__/rail-for.test.js.map +1 -0
- package/dist/wallet/__tests__/wallet-auto-rule.router.test.js +82 -63
- package/dist/wallet/__tests__/wallet-auto-rule.router.test.js.map +1 -1
- package/dist/wallet/__tests__/wallet-auto-withdrawal.test.js +414 -437
- package/dist/wallet/__tests__/wallet-auto-withdrawal.test.js.map +1 -1
- package/dist/wallet/__tests__/wallet-commands.service.test.js +116 -155
- package/dist/wallet/__tests__/wallet-commands.service.test.js.map +1 -1
- package/dist/wallet/__tests__/wallet-kyc-gate.test.js +63 -42
- package/dist/wallet/__tests__/wallet-kyc-gate.test.js.map +1 -1
- package/dist/wallet/__tests__/wallet-webhook.router.test.js +129 -51
- package/dist/wallet/__tests__/wallet-webhook.router.test.js.map +1 -1
- package/dist/wallet/__tests__/wallet.rate-limit.test.js +74 -21
- package/dist/wallet/__tests__/wallet.rate-limit.test.js.map +1 -1
- package/dist/wallet/__tests__/wallet.router.test.js +56 -36
- package/dist/wallet/__tests__/wallet.router.test.js.map +1 -1
- package/dist/wallet/__tests__/wallet.service.test.js +623 -887
- package/dist/wallet/__tests__/wallet.service.test.js.map +1 -1
- package/package.json +1 -2
- package/dist/casino/lobby/__tests__/lobby.service.test.d.ts +0 -2
- package/dist/casino/lobby/__tests__/lobby.service.test.d.ts.map +0 -1
- package/dist/casino/lobby/__tests__/lobby.service.test.js +0 -11
- package/dist/casino/lobby/__tests__/lobby.service.test.js.map +0 -1
- package/dist/contracts/schemas/__tests__/identity-schemas.test.d.ts +0 -2
- package/dist/contracts/schemas/__tests__/identity-schemas.test.d.ts.map +0 -1
- package/dist/contracts/schemas/__tests__/identity-schemas.test.js +0 -43
- package/dist/contracts/schemas/__tests__/identity-schemas.test.js.map +0 -1
- package/dist/testing/fakes/__tests__/cache.test.d.ts +0 -2
- package/dist/testing/fakes/__tests__/cache.test.d.ts.map +0 -1
- package/dist/testing/fakes/__tests__/cache.test.js +0 -89
- package/dist/testing/fakes/__tests__/cache.test.js.map +0 -1
- package/dist/testing/fakes/__tests__/job-queue.test.d.ts +0 -2
- package/dist/testing/fakes/__tests__/job-queue.test.d.ts.map +0 -1
- package/dist/testing/fakes/__tests__/job-queue.test.js +0 -135
- package/dist/testing/fakes/__tests__/job-queue.test.js.map +0 -1
- package/dist/testing/fakes/__tests__/rate-limiter.test.d.ts +0 -2
- package/dist/testing/fakes/__tests__/rate-limiter.test.d.ts.map +0 -1
- package/dist/testing/fakes/__tests__/rate-limiter.test.js +0 -83
- package/dist/testing/fakes/__tests__/rate-limiter.test.js.map +0 -1
- package/dist/testing/fakes/__tests__/realtime-authorizer.test.d.ts +0 -2
- package/dist/testing/fakes/__tests__/realtime-authorizer.test.d.ts.map +0 -1
- package/dist/testing/fakes/__tests__/realtime-authorizer.test.js +0 -19
- package/dist/testing/fakes/__tests__/realtime-authorizer.test.js.map +0 -1
- package/dist/testing/fakes/__tests__/realtime-transport.test.d.ts.map +0 -1
- package/dist/testing/fakes/cache.d.ts +0 -14
- package/dist/testing/fakes/cache.d.ts.map +0 -1
- package/dist/testing/fakes/cache.js +0 -56
- package/dist/testing/fakes/cache.js.map +0 -1
- package/dist/testing/fakes/event-bus.d.ts +0 -17
- package/dist/testing/fakes/event-bus.d.ts.map +0 -1
- package/dist/testing/fakes/event-bus.js +0 -30
- package/dist/testing/fakes/event-bus.js.map +0 -1
- package/dist/testing/fakes/job-queue.d.ts +0 -40
- package/dist/testing/fakes/job-queue.d.ts.map +0 -1
- package/dist/testing/fakes/job-queue.js +0 -200
- package/dist/testing/fakes/job-queue.js.map +0 -1
- package/dist/testing/fakes/rate-limiter.d.ts +0 -11
- package/dist/testing/fakes/rate-limiter.d.ts.map +0 -1
- package/dist/testing/fakes/rate-limiter.js +0 -39
- package/dist/testing/fakes/rate-limiter.js.map +0 -1
- package/dist/testing/fakes/realtime-authorizer.d.ts +0 -10
- package/dist/testing/fakes/realtime-authorizer.d.ts.map +0 -1
- package/dist/testing/fakes/realtime-authorizer.js +0 -10
- package/dist/testing/fakes/realtime-authorizer.js.map +0 -1
- package/dist/testing/fakes/realtime-transport.d.ts +0 -2
- package/dist/testing/fakes/realtime-transport.d.ts.map +0 -1
- package/dist/testing/fakes/realtime-transport.js +0 -2
- package/dist/testing/fakes/realtime-transport.js.map +0 -1
- /package/dist/{testing/fakes → server/kernel}/__tests__/realtime-transport.test.d.ts +0 -0
- /package/dist/{testing/fakes → server/kernel}/__tests__/realtime-transport.test.js +0 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { ORPCError } from '@orpc/server';
|
|
3
|
+
import { getUserId, extractClientMeta } from '../router-utils.js';
|
|
4
|
+
const withRequest = (extra = {}) => ({
|
|
5
|
+
request: { headers: {} },
|
|
6
|
+
...extra,
|
|
7
|
+
});
|
|
8
|
+
const reasonOf = (fn) => {
|
|
9
|
+
try {
|
|
10
|
+
fn();
|
|
11
|
+
}
|
|
12
|
+
catch (err) {
|
|
13
|
+
return err.data.reason;
|
|
14
|
+
}
|
|
15
|
+
throw new Error('expected getUserId to throw');
|
|
16
|
+
};
|
|
17
|
+
describe('getUserId', () => {
|
|
18
|
+
it('returns the resolved caller id', () => {
|
|
19
|
+
expect(getUserId(withRequest({ auth: { userId: 'user-1' } }))).toBe('user-1');
|
|
20
|
+
});
|
|
21
|
+
it.each([
|
|
22
|
+
['undefined', undefined],
|
|
23
|
+
['null', null],
|
|
24
|
+
['a primitive', 'not-a-context'],
|
|
25
|
+
['an object without request', { auth: { userId: 'user-1' } }],
|
|
26
|
+
['a context whose request is not an object', { request: 'GET /' }],
|
|
27
|
+
])('rejects %s as a missing request context', (_label, context) => {
|
|
28
|
+
expect(reasonOf(() => getUserId(context))).toBe('missing_request_context');
|
|
29
|
+
});
|
|
30
|
+
it.each([
|
|
31
|
+
['no auth at all', withRequest()],
|
|
32
|
+
['an auth without a userId', withRequest({ auth: {} })],
|
|
33
|
+
['an empty userId', withRequest({ auth: { userId: '' } })],
|
|
34
|
+
])('rejects %s as unauthenticated', (_label, context) => {
|
|
35
|
+
expect(reasonOf(() => getUserId(context))).toBe('authentication_required');
|
|
36
|
+
});
|
|
37
|
+
it('throws UNAUTHORIZED rather than a bare Error', () => {
|
|
38
|
+
expect(() => getUserId(undefined)).toThrow(ORPCError);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
describe('extractClientMeta', () => {
|
|
42
|
+
const meta = (headers) => extractClientMeta(headers);
|
|
43
|
+
it('reads a single x-forwarded-for entry', () => {
|
|
44
|
+
expect(meta({ 'x-forwarded-for': '203.0.113.7' }).ip).toBe('203.0.113.7');
|
|
45
|
+
});
|
|
46
|
+
it('takes the leftmost hop of a proxy chain and trims it', () => {
|
|
47
|
+
expect(meta({ 'x-forwarded-for': ' 203.0.113.7 , 10.0.0.1, 10.0.0.2' }).ip).toBe('203.0.113.7');
|
|
48
|
+
});
|
|
49
|
+
it('takes the first value when the header arrives repeated', () => {
|
|
50
|
+
expect(meta({ 'x-forwarded-for': ['203.0.113.7', '198.51.100.4'] }).ip).toBe('203.0.113.7');
|
|
51
|
+
});
|
|
52
|
+
it('falls back to x-real-ip when x-forwarded-for is absent', () => {
|
|
53
|
+
expect(meta({ 'x-real-ip': '198.51.100.4' }).ip).toBe('198.51.100.4');
|
|
54
|
+
});
|
|
55
|
+
it('falls back to x-real-ip when x-forwarded-for is empty', () => {
|
|
56
|
+
expect(meta({ 'x-forwarded-for': '', 'x-real-ip': '198.51.100.4' }).ip).toBe('198.51.100.4');
|
|
57
|
+
});
|
|
58
|
+
it('prefers x-forwarded-for over x-real-ip', () => {
|
|
59
|
+
expect(meta({ 'x-forwarded-for': '203.0.113.7', 'x-real-ip': '198.51.100.4' }).ip).toBe('203.0.113.7');
|
|
60
|
+
});
|
|
61
|
+
it('reads the first x-real-ip when that header arrives repeated', () => {
|
|
62
|
+
expect(meta({ 'x-real-ip': ['198.51.100.4', '198.51.100.9'] }).ip).toBe('198.51.100.4');
|
|
63
|
+
});
|
|
64
|
+
it('carries the user agent through', () => {
|
|
65
|
+
expect(meta({ 'user-agent': 'curl/8.4.0' }).userAgent).toBe('curl/8.4.0');
|
|
66
|
+
});
|
|
67
|
+
it('takes the first user agent when the header arrives repeated', () => {
|
|
68
|
+
expect(meta({ 'user-agent': ['curl/8.4.0', 'wget'] }).userAgent).toBe('curl/8.4.0');
|
|
69
|
+
});
|
|
70
|
+
it('returns nulls rather than undefined for an empty header bag', () => {
|
|
71
|
+
expect(meta({})).toEqual({ ip: null, userAgent: null });
|
|
72
|
+
});
|
|
73
|
+
it('returns nulls when the headers are present but undefined', () => {
|
|
74
|
+
expect(meta({ 'x-forwarded-for': undefined, 'user-agent': undefined })).toEqual({
|
|
75
|
+
ip: null,
|
|
76
|
+
userAgent: null,
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
//# sourceMappingURL=router-utils.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router-utils.test.js","sourceRoot":"","sources":["../../../../src/server/kernel/__tests__/router-utils.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bullmq-job-queue.d.ts","sourceRoot":"","sources":["../../../src/server/kernel/bullmq-job-queue.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,eAAe,EACf,SAAS,EACT,cAAc,EACd,aAAa,EAEb,kBAAkB,EACnB,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"bullmq-job-queue.d.ts","sourceRoot":"","sources":["../../../src/server/kernel/bullmq-job-queue.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,eAAe,EACf,SAAS,EACT,cAAc,EACd,aAAa,EAEb,kBAAkB,EACnB,MAAM,yBAAyB,CAAC;AAwBjC;;;;;;;;;;;GAWG;AACH,qBAAa,cAAe,YAAW,eAAe;IACpD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoC;IAC3D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAC/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyC;IAChE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;gBAExC,QAAQ,EAAE,MAAM;IAK5B,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IA+B5F,cAAc,CAAC,CAAC,EAAE,YAAY,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,IAAI;IAqC5D,QAAQ,CAAC,CAAC,EACR,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,CAAC,EACV,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,IAAI,CAAC;IAWhB,UAAU,CAAC,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMzD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B,OAAO,CAAC,QAAQ;YAUF,UAAU;CAwBzB"}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { Queue, Worker } from 'bullmq';
|
|
2
2
|
import { createLogger } from './logger.js';
|
|
3
|
+
// BullMQ reserves ':' as its Redis key separator and rejects an all-digit id, so an
|
|
4
|
+
// `idempotencyKey` is percent-encoded into a safe job id. The encoding is injective -
|
|
5
|
+
// two distinct keys can never collapse onto one job id and silently dedupe apart.
|
|
6
|
+
function toJobId(idempotencyKey) {
|
|
7
|
+
const encoded = idempotencyKey.replaceAll('%', '%25').replaceAll(':', '%3A');
|
|
8
|
+
return /^\d+$/.test(encoded) ? `key-${encoded}` : encoded;
|
|
9
|
+
}
|
|
3
10
|
/**
|
|
4
11
|
* Durable `JOB_QUEUE` reference driver, auto-bound by `createApp` when
|
|
5
12
|
* `REDIS_URL` is set - jobs survive a process restart and `cron`/`everyMs`
|
|
@@ -35,8 +42,7 @@ export class BullMqJobQueue {
|
|
|
35
42
|
meta: { ...opts.meta, idempotencyKey: opts.idempotencyKey },
|
|
36
43
|
};
|
|
37
44
|
const jobOpts = {
|
|
38
|
-
|
|
39
|
-
jobId: opts.idempotencyKey,
|
|
45
|
+
jobId: opts.idempotencyKey ? toJobId(opts.idempotencyKey) : undefined,
|
|
40
46
|
delay: opts.delayMs,
|
|
41
47
|
attempts: opts.attempts,
|
|
42
48
|
backoff: opts.backoff ? { type: opts.backoff.type, delay: opts.backoff.delayMs } : undefined,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bullmq-job-queue.js","sourceRoot":"","sources":["../../../src/server/kernel/bullmq-job-queue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAsD,MAAM,QAAQ,CAAC;AAS3F,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAe3C;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,cAAc;IACR,MAAM,GAAG,YAAY,CAAC,kBAAkB,CAAC,CAAC;IAC1C,UAAU,CAAoB;IAC9B,MAAM,GAAG,IAAI,GAAG,EAA8B,CAAC;IAC/C,OAAO,GAA0B,EAAE,CAAC;IACpC,cAAc,GAAG,IAAI,GAAG,EAAU,CAAC;IAEpD,YAAY,QAAgB;QAC1B,kFAAkF;QAClF,IAAI,CAAC,UAAU,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,oBAAoB,EAAE,IAAI,EAAE,CAAC;IAClE,CAAC;IAED,OAAO,CAAI,KAAgB,EAAE,OAAU,EAAE,OAAuB,EAAE;QAChE,IAAI,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACxD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAC/B,mFAAmF;YACnF,qFAAqF;YACrF,uEAAuE;YACvE,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,EAAE,KAAK,EAAE,EACT,sHAAsH,CACvH,CAAC;QACJ,CAAC;QAED,MAAM,QAAQ,GAAgB;YAC5B,OAAO;YACP,IAAI,EAAE,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE;SAC5D,CAAC;QAEF,MAAM,OAAO,GAAgB;YAC3B,
|
|
1
|
+
{"version":3,"file":"bullmq-job-queue.js","sourceRoot":"","sources":["../../../src/server/kernel/bullmq-job-queue.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect, afterEach } from 'vitest';
|
|
2
2
|
import { MESSAGE_BROKER, JOB_QUEUE, CACHE, RATE_LIMITER } from '@openora/core/contracts';
|
|
3
|
-
import {
|
|
4
|
-
import { createLogger } from '../../kernel/index.js';
|
|
3
|
+
import { redisUrlForWorker } from '@openora/core/testing';
|
|
5
4
|
import { createApp } from '../create-app.js';
|
|
6
5
|
// A syntactically valid but unreachable DB url - fine here because nothing in this
|
|
7
6
|
// suite ever runs a query: DrizzleService's pg.Pool connects lazily, and neither
|
|
@@ -12,22 +11,31 @@ describe('createApp - distributed-only durable seams (ADR-0030)', () => {
|
|
|
12
11
|
it('throws a clear, actionable error when no durable seam is bound', async () => {
|
|
13
12
|
await expect(createApp({ plugins: [], databaseUrl: DUMMY_DATABASE_URL, openapi: { enabled: false } })).rejects.toThrow(/MESSAGE_BROKER.*JOB_QUEUE.*CACHE.*RATE_LIMITER/s);
|
|
14
13
|
});
|
|
15
|
-
it('boots and serves once
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
14
|
+
it('boots and serves once REDIS_URL auto-binds all four seams', async () => {
|
|
15
|
+
const saved = process.env['REDIS_URL'];
|
|
16
|
+
process.env['REDIS_URL'] = redisUrlForWorker();
|
|
17
|
+
try {
|
|
18
|
+
const created = await createApp({
|
|
19
|
+
plugins: [],
|
|
20
|
+
databaseUrl: DUMMY_DATABASE_URL,
|
|
21
|
+
openapi: { enabled: false },
|
|
22
|
+
});
|
|
23
|
+
for (const token of [MESSAGE_BROKER, JOB_QUEUE, CACHE, RATE_LIMITER]) {
|
|
24
|
+
expect(created.container.has(token)).toBe(true);
|
|
25
|
+
}
|
|
26
|
+
const res = await created.app.request('/health');
|
|
27
|
+
expect(res.status).toBe(200);
|
|
28
|
+
expect(await res.json()).toMatchObject({ status: 'ok' });
|
|
29
|
+
await created.close();
|
|
30
|
+
}
|
|
31
|
+
finally {
|
|
32
|
+
if (saved === undefined) {
|
|
33
|
+
delete process.env['REDIS_URL'];
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
process.env['REDIS_URL'] = saved;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
31
39
|
});
|
|
32
40
|
});
|
|
33
41
|
describe('createApp - service name for the Redis Streams consumer group', () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-app.test.js","sourceRoot":"","sources":["../../../../src/server/runtime/__tests__/create-app.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACzF,OAAO,
|
|
1
|
+
{"version":3,"file":"create-app.test.js","sourceRoot":"","sources":["../../../../src/server/runtime/__tests__/create-app.test.ts"],"names":[],"mappings":"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"}
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
3
|
-
export { InProcessCache } from './fakes/cache.js';
|
|
4
|
-
export { InProcessJobQueue } from './fakes/job-queue.js';
|
|
5
|
-
export { InProcessRealtimeTransport } from './fakes/realtime-transport.js';
|
|
6
|
-
export { SseClientAuthorizer, type SseClientAuthorizerOptions, } from './fakes/realtime-authorizer.js';
|
|
1
|
+
export { InProcessRealtimeTransport, SseClientAuthorizer } from '@openora/core/server';
|
|
2
|
+
export { createTestDb, createTestRedis, redisUrlForWorker, waitForConsumerGroup, type Migration, type TestDb, type TestRedis, } from './real-infra.js';
|
|
7
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACvF,OAAO,EACL,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,KAAK,SAAS,EACd,KAAK,MAAM,EACX,KAAK,SAAS,GACf,MAAM,iBAAiB,CAAC"}
|
package/dist/testing/index.js
CHANGED
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
// production path; `bootTestApp` (@openora/testing) and core's own unit tests bind
|
|
4
|
-
// them explicitly via a `configure` callback so the suite still runs with zero infra.
|
|
5
|
-
export { InMemoryBroker } from './fakes/event-bus.js';
|
|
6
|
-
export { InProcessRateLimiter } from './fakes/rate-limiter.js';
|
|
7
|
-
export { InProcessCache } from './fakes/cache.js';
|
|
8
|
-
export { InProcessJobQueue } from './fakes/job-queue.js';
|
|
9
|
-
export { InProcessRealtimeTransport } from './fakes/realtime-transport.js';
|
|
10
|
-
export { SseClientAuthorizer, } from './fakes/realtime-authorizer.js';
|
|
1
|
+
export { InProcessRealtimeTransport, SseClientAuthorizer } from '@openora/core/server';
|
|
2
|
+
export { createTestDb, createTestRedis, redisUrlForWorker, waitForConsumerGroup, } from './real-infra.js';
|
|
11
3
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACvF,OAAO,EACL,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,oBAAoB,GAIrB,MAAM,iBAAiB,CAAC"}
|
package/dist/testing/mock.d.ts
CHANGED
|
@@ -1,32 +1,44 @@
|
|
|
1
1
|
import { type Mock } from 'vitest';
|
|
2
|
-
import type { AdminCaller, DrizzleService, OssContext } from '@openora/core/server';
|
|
3
|
-
import type { ClientMeta } from '@openora/core/contracts';
|
|
2
|
+
import type { AdminCaller, AdminGuard, DrizzleService, EventBus, OssContext } from '@openora/core/server';
|
|
3
|
+
import type { AuditWritePort, ClientMeta } from '@openora/core/contracts';
|
|
4
4
|
/** Build a typed test double from a partial shape. */
|
|
5
5
|
export declare const mock: <T>(partial?: object) => T;
|
|
6
|
-
/** Wrap a fake `db` handle (usually a chainable Proxy) as a DrizzleService. */
|
|
7
|
-
export declare const mockDb: (db: unknown) => DrizzleService;
|
|
8
6
|
export declare const NO_CLIENT_META: ClientMeta;
|
|
9
7
|
export declare const adminCaller: (over?: Partial<AdminCaller>) => AdminCaller;
|
|
10
8
|
export declare const testContext: (over?: Partial<OssContext>) => OssContext;
|
|
11
|
-
/** Read a private field off an instance without widening the class's public API. */
|
|
12
|
-
export declare const readPrivate: <V = unknown>(obj: object, key: string) => V;
|
|
13
9
|
type Row = Record<string, unknown>;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}): Record<string, unknown>;
|
|
18
|
-
export declare function makeDrizzle(results?: {
|
|
10
|
+
/** Fake `DrizzleService` for tests asserting call order/shape rather than committed state -
|
|
11
|
+
* reach for `createTestDb` when a real unique index, lock or transaction outcome matters. */
|
|
12
|
+
export declare const makeDrizzle: (results?: {
|
|
19
13
|
select?: Row[][];
|
|
20
14
|
returning?: Row[][];
|
|
21
|
-
})
|
|
22
|
-
|
|
15
|
+
}) => DrizzleService;
|
|
16
|
+
type MockedEventBus = EventBus & {
|
|
23
17
|
emit: Mock;
|
|
24
18
|
on: Mock;
|
|
25
19
|
emitInTransaction: Mock;
|
|
26
20
|
};
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
21
|
+
/**
|
|
22
|
+
* EventBus double whose three methods are vitest mocks, so a test can both pass it
|
|
23
|
+
* to a service and assert on `events.emit` without a second `mock<EventBus>()` wrap.
|
|
24
|
+
*/
|
|
25
|
+
export declare const makeEventBus: () => MockedEventBus;
|
|
26
|
+
export declare const makeAuditWriter: () => AuditWritePort & {
|
|
27
|
+
record: Mock;
|
|
30
28
|
};
|
|
29
|
+
/**
|
|
30
|
+
* AdminGuard double driven by permission lists rather than a hand-rolled `assert`.
|
|
31
|
+
*
|
|
32
|
+
* Pass `allow` for an allowlist (anything unlisted throws FORBIDDEN, so `allow: []`
|
|
33
|
+
* denies every guarded route) or `deny` for a denylist. Each entry is a bare
|
|
34
|
+
* resource (`'admin'`, matching any action on it) or a full `resource:action`.
|
|
35
|
+
* With neither list every check passes. An unguarded `assert(ctx)` - no resource -
|
|
36
|
+
* always passes, mirroring the real guard's plain admin check.
|
|
37
|
+
*/
|
|
38
|
+
export declare const makeAdminGuard: (options?: {
|
|
39
|
+
allow?: readonly string[];
|
|
40
|
+
deny?: readonly string[];
|
|
41
|
+
caller?: Partial<AdminCaller>;
|
|
42
|
+
}) => AdminGuard;
|
|
31
43
|
export {};
|
|
32
44
|
//# sourceMappingURL=mock.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../../src/testing/mock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAM,KAAK,IAAI,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../../src/testing/mock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAM,KAAK,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEvC,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,cAAc,EACd,QAAQ,EACR,UAAU,EACX,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAQ1E,sDAAsD;AACtD,eAAO,MAAM,IAAI,GAAI,CAAC,EAAE,UAAS,MAAW,KAAG,CAA4B,CAAC;AAE5E,eAAO,MAAM,cAAc,EAAE,UAA0C,CAAC;AAExE,eAAO,MAAM,WAAW,GAAI,OAAM,OAAO,CAAC,WAAW,CAAM,KAAG,WAK5D,CAAC;AAEH,eAAO,MAAM,WAAW,GAAI,OAAM,OAAO,CAAC,UAAU,CAAM,KAAG,UAI3D,CAAC;AAEH,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAsCnC;6FAC6F;AAC7F,eAAO,MAAM,WAAW,GAAI,UAAS;IAAE,MAAM,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,GAAG,EAAE,EAAE,CAAA;CAAO,KAOrD,cAC7B,CAAC;AAEF,KAAK,cAAc,GAAG,QAAQ,GAAG;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,IAAI,CAAC;IAAC,iBAAiB,EAAE,IAAI,CAAA;CAAE,CAAC;AAEnF;;;GAGG;AACH,eAAO,MAAM,YAAY,QAAO,cACkD,CAAC;AAEnF,eAAO,MAAM,eAAe,QAAO,cAAc,GAAG;IAAE,MAAM,EAAE,IAAI,CAAA;CAEhE,CAAC;AAcH;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,GACzB,UAAS;IACP,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CAC1B,KACL,UAQC,CAAC"}
|
package/dist/testing/mock.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { vi } from 'vitest';
|
|
2
|
+
import { ORPCError } from '@orpc/server';
|
|
2
3
|
// The one sanctioned home for test-double type assertions. A unit test standing in
|
|
3
4
|
// for a collaborator is inherently partial, so the cast lives here - documented and
|
|
4
5
|
// in one place - instead of scattered `as unknown as` across every test body.
|
|
@@ -6,8 +7,6 @@ import { vi } from 'vitest';
|
|
|
6
7
|
// funnelled through these helpers.
|
|
7
8
|
/** Build a typed test double from a partial shape. */
|
|
8
9
|
export const mock = (partial = {}) => partial;
|
|
9
|
-
/** Wrap a fake `db` handle (usually a chainable Proxy) as a DrizzleService. */
|
|
10
|
-
export const mockDb = (db) => ({ db });
|
|
11
10
|
export const NO_CLIENT_META = { ip: null, userAgent: null };
|
|
12
11
|
export const adminCaller = (over = {}) => ({
|
|
13
12
|
userId: 'admin-1',
|
|
@@ -20,32 +19,32 @@ export const testContext = (over = {}) => ({
|
|
|
20
19
|
clientMeta: NO_CLIENT_META,
|
|
21
20
|
...over,
|
|
22
21
|
});
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
const CHAIN_METHODS = [
|
|
23
|
+
'select',
|
|
24
|
+
'from',
|
|
25
|
+
'innerJoin',
|
|
26
|
+
'leftJoin',
|
|
27
|
+
'orderBy',
|
|
28
|
+
'groupBy',
|
|
29
|
+
'limit',
|
|
30
|
+
'offset',
|
|
31
|
+
'for',
|
|
32
|
+
'insert',
|
|
33
|
+
'values',
|
|
34
|
+
'onConflictDoNothing',
|
|
35
|
+
'onConflictDoUpdate',
|
|
36
|
+
'update',
|
|
37
|
+
'set',
|
|
38
|
+
'delete',
|
|
39
|
+
'where',
|
|
40
|
+
];
|
|
41
|
+
/** Chainable, awaitable Drizzle double: awaiting the builder pops the next `select` queue
|
|
42
|
+
* entry, `.returning()` pops the `returning` queue - a test supplies per-statement results
|
|
43
|
+
* in call order. */
|
|
44
|
+
const makeQueryBuilder = (results) => {
|
|
28
45
|
const builder = {};
|
|
29
46
|
const chain = () => builder;
|
|
30
|
-
for (const m of
|
|
31
|
-
'select',
|
|
32
|
-
'from',
|
|
33
|
-
'innerJoin',
|
|
34
|
-
'leftJoin',
|
|
35
|
-
'orderBy',
|
|
36
|
-
'groupBy',
|
|
37
|
-
'limit',
|
|
38
|
-
'offset',
|
|
39
|
-
'for',
|
|
40
|
-
'insert',
|
|
41
|
-
'values',
|
|
42
|
-
'onConflictDoNothing',
|
|
43
|
-
'onConflictDoUpdate',
|
|
44
|
-
'update',
|
|
45
|
-
'set',
|
|
46
|
-
'delete',
|
|
47
|
-
'where',
|
|
48
|
-
]) {
|
|
47
|
+
for (const m of CHAIN_METHODS) {
|
|
49
48
|
builder[m] = vi.fn(chain);
|
|
50
49
|
}
|
|
51
50
|
builder['returning'] = vi.fn(() => Promise.resolve(results.returning.shift() ?? []));
|
|
@@ -53,23 +52,45 @@ export function makeQueryBuilder(results) {
|
|
|
53
52
|
// oxlint-disable-next-line unicorn/no-thenable -- the builder must be awaitable to mimic Drizzle.
|
|
54
53
|
builder['then'] = (resolve) => resolve(results.select.shift() ?? []);
|
|
55
54
|
return builder;
|
|
56
|
-
}
|
|
57
|
-
|
|
55
|
+
};
|
|
56
|
+
/** Fake `DrizzleService` for tests asserting call order/shape rather than committed state -
|
|
57
|
+
* reach for `createTestDb` when a real unique index, lock or transaction outcome matters. */
|
|
58
|
+
export const makeDrizzle = (results = {}) => {
|
|
58
59
|
const state = { select: results.select ?? [], returning: results.returning ?? [] };
|
|
59
60
|
const builder = makeQueryBuilder(state);
|
|
60
61
|
const db = {
|
|
61
62
|
...builder,
|
|
62
63
|
transaction: vi.fn(async (fn) => fn(builder)),
|
|
63
64
|
};
|
|
64
|
-
return
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
65
|
+
return { db };
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* EventBus double whose three methods are vitest mocks, so a test can both pass it
|
|
69
|
+
* to a service and assert on `events.emit` without a second `mock<EventBus>()` wrap.
|
|
70
|
+
*/
|
|
71
|
+
export const makeEventBus = () => mock({ emit: vi.fn(), on: vi.fn(), emitInTransaction: vi.fn() });
|
|
72
|
+
export const makeAuditWriter = () => ({
|
|
73
|
+
record: vi.fn(async () => undefined),
|
|
70
74
|
});
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
const matches = (refs, resource, action) => refs.includes(resource) || refs.includes(`${resource}:${action}`);
|
|
76
|
+
const isPermitted = (options, resource, action) => options.allow
|
|
77
|
+
? matches(options.allow, resource, action)
|
|
78
|
+
: !matches(options.deny ?? [], resource, action);
|
|
79
|
+
/**
|
|
80
|
+
* AdminGuard double driven by permission lists rather than a hand-rolled `assert`.
|
|
81
|
+
*
|
|
82
|
+
* Pass `allow` for an allowlist (anything unlisted throws FORBIDDEN, so `allow: []`
|
|
83
|
+
* denies every guarded route) or `deny` for a denylist. Each entry is a bare
|
|
84
|
+
* resource (`'admin'`, matching any action on it) or a full `resource:action`.
|
|
85
|
+
* With neither list every check passes. An unguarded `assert(ctx)` - no resource -
|
|
86
|
+
* always passes, mirroring the real guard's plain admin check.
|
|
87
|
+
*/
|
|
88
|
+
export const makeAdminGuard = (options = {}) => mock({
|
|
89
|
+
assert: vi.fn(async (_ctx, resource, action) => {
|
|
90
|
+
if (resource && action && !isPermitted(options, resource, action)) {
|
|
91
|
+
throw new ORPCError('FORBIDDEN', { message: `Missing permission: ${resource}:${action}` });
|
|
92
|
+
}
|
|
93
|
+
return adminCaller(options.caller);
|
|
94
|
+
}),
|
|
74
95
|
});
|
|
75
96
|
//# sourceMappingURL=mock.js.map
|
package/dist/testing/mock.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mock.js","sourceRoot":"","sources":["../../src/testing/mock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAa,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"mock.js","sourceRoot":"","sources":["../../src/testing/mock.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { createClient } from 'redis';
|
|
2
|
+
import { DrizzleService } from '@openora/core/server';
|
|
3
|
+
/**
|
|
4
|
+
* The Redis URL for THIS worker's logical DB, in the `redis://host:port/db` form that
|
|
5
|
+
* ioredis-based drivers (BullMQ) parse. Keeps BullMQ on the same per-worker DB as
|
|
6
|
+
* `createTestRedis`, so a `flush()` tears both down together.
|
|
7
|
+
*/
|
|
8
|
+
export declare function redisUrlForWorker(): string;
|
|
9
|
+
/**
|
|
10
|
+
* Poll until a Redis Streams consumer group exists on `stream`. The broker creates its
|
|
11
|
+
* group lazily inside the read loop (at `$`), so a publish issued before the group
|
|
12
|
+
* exists would be missed - tests await this after subscribing, before publishing.
|
|
13
|
+
*/
|
|
14
|
+
export declare function waitForConsumerGroup(client: ReturnType<typeof createClient>, { stream, group, timeoutMs }: {
|
|
15
|
+
stream: string;
|
|
16
|
+
group: string;
|
|
17
|
+
timeoutMs?: number;
|
|
18
|
+
}): Promise<void>;
|
|
19
|
+
/** A per-module migration entrypoint (`packages/core/src/<module>/migrate.ts`). */
|
|
20
|
+
export type Migration = (databaseUrl: string) => Promise<unknown>;
|
|
21
|
+
export type TestDb = {
|
|
22
|
+
url: string;
|
|
23
|
+
drizzle: DrizzleService;
|
|
24
|
+
drop: () => Promise<void>;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Create a throwaway `test_<random>` database, apply the given per-module migrations
|
|
28
|
+
* against it, and return a `DrizzleService` bound to it. `drop()` disposes the pool
|
|
29
|
+
* and drops the database with FORCE (terminating any lingering backends).
|
|
30
|
+
*
|
|
31
|
+
* `DrizzleService` reads `DATABASE_URL` in its constructor, so this points the env at
|
|
32
|
+
* the ephemeral url just before constructing it - safe because a test file owns one db.
|
|
33
|
+
*/
|
|
34
|
+
export declare function createTestDb(migrations: Migration[]): Promise<TestDb>;
|
|
35
|
+
export type TestRedis = {
|
|
36
|
+
client: ReturnType<typeof createClient>;
|
|
37
|
+
flush: () => Promise<void>;
|
|
38
|
+
quit: () => Promise<void>;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Connect a node-redis client selected to a per-worker logical DB (VITEST_POOL_ID % 16),
|
|
42
|
+
* so parallel vitest workers never collide on keys. `flush()` is a `flushDb` (safe - it
|
|
43
|
+
* only clears this worker's logical DB), for tearing down between tests. `reconnectStrategy`
|
|
44
|
+
* is off: node-redis otherwise retries a down server forever and hangs the run.
|
|
45
|
+
*/
|
|
46
|
+
export declare function createTestRedis(): Promise<TestRedis>;
|
|
47
|
+
//# sourceMappingURL=real-infra.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"real-infra.d.ts","sourceRoot":"","sources":["../../src/testing/real-infra.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAkBtD;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,EACvC,EAAE,MAAM,EAAE,KAAK,EAAE,SAAgB,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACzF,OAAO,CAAC,IAAI,CAAC,CAgBf;AAeD,mFAAmF;AACnF,MAAM,MAAM,SAAS,GAAG,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAElE,MAAM,MAAM,MAAM,GAAG;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,cAAc,CAAC;IACxB,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA8B3E;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,MAAM,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;IACxC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,SAAS,CAAC,CAqB1D"}
|