@open-mercato/shared 0.5.1-develop.2856.35de414092 → 0.5.1-develop.2860.07af3a6a9d

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.
@@ -6,8 +6,10 @@ function readRateLimitConfig() {
6
6
  throw new Error(`Invalid RATE_LIMIT_STRATEGY "${strategy}". Must be one of: ${VALID_STRATEGIES.join(", ")}`);
7
7
  }
8
8
  const trustProxyDepth = parsePositiveInt(process.env.RATE_LIMIT_TRUST_PROXY_DEPTH) ?? 1;
9
+ const integrationTest = parseBooleanWithDefault(process.env.OM_INTEGRATION_TEST, false);
10
+ const enabled = integrationTest ? false : parseBooleanWithDefault(process.env.RATE_LIMIT_ENABLED, true);
9
11
  return {
10
- enabled: parseBooleanWithDefault(process.env.RATE_LIMIT_ENABLED, true),
12
+ enabled,
11
13
  strategy,
12
14
  keyPrefix: process.env.RATE_LIMIT_KEY_PREFIX ?? "rl",
13
15
  redisUrl: process.env.REDIS_URL,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/ratelimit/config.ts"],
4
- "sourcesContent": ["import { parseBooleanWithDefault } from '@open-mercato/shared/lib/boolean'\nimport type { RateLimitConfig, RateLimitGlobalConfig, RateLimitStrategy } from './types'\n\nconst VALID_STRATEGIES: RateLimitStrategy[] = ['memory', 'redis']\n\nexport function readRateLimitConfig(): RateLimitGlobalConfig {\n const strategy = (process.env.RATE_LIMIT_STRATEGY ?? 'memory') as RateLimitStrategy\n if (!VALID_STRATEGIES.includes(strategy)) {\n throw new Error(`Invalid RATE_LIMIT_STRATEGY \"${strategy}\". Must be one of: ${VALID_STRATEGIES.join(', ')}`)\n }\n\n const trustProxyDepth = parsePositiveInt(process.env.RATE_LIMIT_TRUST_PROXY_DEPTH) ?? 1\n\n return {\n enabled: parseBooleanWithDefault(process.env.RATE_LIMIT_ENABLED, true),\n strategy,\n keyPrefix: process.env.RATE_LIMIT_KEY_PREFIX ?? 'rl',\n redisUrl: process.env.REDIS_URL,\n trustProxyDepth,\n }\n}\n\n/**\n * Read per-endpoint rate limit config from environment variables with hardcoded defaults.\n * Environment variable names follow the pattern: RATE_LIMIT_{PREFIX}_POINTS, RATE_LIMIT_{PREFIX}_DURATION, etc.\n */\nexport function readEndpointRateLimitConfig(\n envPrefix: string,\n defaults: { points: number; duration: number; blockDuration?: number; keyPrefix: string },\n): RateLimitConfig {\n return {\n points: parsePositiveInt(process.env[`RATE_LIMIT_${envPrefix}_POINTS`]) ?? defaults.points,\n duration: parsePositiveInt(process.env[`RATE_LIMIT_${envPrefix}_DURATION`]) ?? defaults.duration,\n blockDuration: parsePositiveInt(process.env[`RATE_LIMIT_${envPrefix}_BLOCK_DURATION`]) ?? defaults.blockDuration,\n keyPrefix: defaults.keyPrefix,\n }\n}\n\nfunction parsePositiveInt(raw: string | undefined): number | undefined {\n if (raw === undefined || raw === '') return undefined\n const parsed = Number(raw)\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : undefined\n}\n"],
5
- "mappings": "AAAA,SAAS,+BAA+B;AAGxC,MAAM,mBAAwC,CAAC,UAAU,OAAO;AAEzD,SAAS,sBAA6C;AAC3D,QAAM,WAAY,QAAQ,IAAI,uBAAuB;AACrD,MAAI,CAAC,iBAAiB,SAAS,QAAQ,GAAG;AACxC,UAAM,IAAI,MAAM,gCAAgC,QAAQ,sBAAsB,iBAAiB,KAAK,IAAI,CAAC,EAAE;AAAA,EAC7G;AAEA,QAAM,kBAAkB,iBAAiB,QAAQ,IAAI,4BAA4B,KAAK;AAEtF,SAAO;AAAA,IACL,SAAS,wBAAwB,QAAQ,IAAI,oBAAoB,IAAI;AAAA,IACrE;AAAA,IACA,WAAW,QAAQ,IAAI,yBAAyB;AAAA,IAChD,UAAU,QAAQ,IAAI;AAAA,IACtB;AAAA,EACF;AACF;AAMO,SAAS,4BACd,WACA,UACiB;AACjB,SAAO;AAAA,IACL,QAAQ,iBAAiB,QAAQ,IAAI,cAAc,SAAS,SAAS,CAAC,KAAK,SAAS;AAAA,IACpF,UAAU,iBAAiB,QAAQ,IAAI,cAAc,SAAS,WAAW,CAAC,KAAK,SAAS;AAAA,IACxF,eAAe,iBAAiB,QAAQ,IAAI,cAAc,SAAS,iBAAiB,CAAC,KAAK,SAAS;AAAA,IACnG,WAAW,SAAS;AAAA,EACtB;AACF;AAEA,SAAS,iBAAiB,KAA6C;AACrE,MAAI,QAAQ,UAAa,QAAQ,GAAI,QAAO;AAC5C,QAAM,SAAS,OAAO,GAAG;AACzB,SAAO,OAAO,SAAS,MAAM,KAAK,UAAU,IAAI,SAAS;AAC3D;",
4
+ "sourcesContent": ["import { parseBooleanWithDefault } from '@open-mercato/shared/lib/boolean'\nimport type { RateLimitConfig, RateLimitGlobalConfig, RateLimitStrategy } from './types'\n\nconst VALID_STRATEGIES: RateLimitStrategy[] = ['memory', 'redis']\n\nexport function readRateLimitConfig(): RateLimitGlobalConfig {\n const strategy = (process.env.RATE_LIMIT_STRATEGY ?? 'memory') as RateLimitStrategy\n if (!VALID_STRATEGIES.includes(strategy)) {\n throw new Error(`Invalid RATE_LIMIT_STRATEGY \"${strategy}\". Must be one of: ${VALID_STRATEGIES.join(', ')}`)\n }\n\n const trustProxyDepth = parsePositiveInt(process.env.RATE_LIMIT_TRUST_PROXY_DEPTH) ?? 1\n\n // Integration test runs disable rate limiting globally so suites do not\n // have to juggle per-endpoint bypass headers or reshape default caps.\n // The targeted OM_TEST_MODE + OM_TEST_AUTH_RATE_LIMIT_MODE=opt-in escape\n // hatch (checkAuthRateLimit) still works for suites that explicitly test\n // rate-limit behavior.\n const integrationTest = parseBooleanWithDefault(process.env.OM_INTEGRATION_TEST, false)\n const enabled = integrationTest\n ? false\n : parseBooleanWithDefault(process.env.RATE_LIMIT_ENABLED, true)\n\n return {\n enabled,\n strategy,\n keyPrefix: process.env.RATE_LIMIT_KEY_PREFIX ?? 'rl',\n redisUrl: process.env.REDIS_URL,\n trustProxyDepth,\n }\n}\n\n/**\n * Read per-endpoint rate limit config from environment variables with hardcoded defaults.\n * Environment variable names follow the pattern: RATE_LIMIT_{PREFIX}_POINTS, RATE_LIMIT_{PREFIX}_DURATION, etc.\n */\nexport function readEndpointRateLimitConfig(\n envPrefix: string,\n defaults: { points: number; duration: number; blockDuration?: number; keyPrefix: string },\n): RateLimitConfig {\n return {\n points: parsePositiveInt(process.env[`RATE_LIMIT_${envPrefix}_POINTS`]) ?? defaults.points,\n duration: parsePositiveInt(process.env[`RATE_LIMIT_${envPrefix}_DURATION`]) ?? defaults.duration,\n blockDuration: parsePositiveInt(process.env[`RATE_LIMIT_${envPrefix}_BLOCK_DURATION`]) ?? defaults.blockDuration,\n keyPrefix: defaults.keyPrefix,\n }\n}\n\nfunction parsePositiveInt(raw: string | undefined): number | undefined {\n if (raw === undefined || raw === '') return undefined\n const parsed = Number(raw)\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : undefined\n}\n"],
5
+ "mappings": "AAAA,SAAS,+BAA+B;AAGxC,MAAM,mBAAwC,CAAC,UAAU,OAAO;AAEzD,SAAS,sBAA6C;AAC3D,QAAM,WAAY,QAAQ,IAAI,uBAAuB;AACrD,MAAI,CAAC,iBAAiB,SAAS,QAAQ,GAAG;AACxC,UAAM,IAAI,MAAM,gCAAgC,QAAQ,sBAAsB,iBAAiB,KAAK,IAAI,CAAC,EAAE;AAAA,EAC7G;AAEA,QAAM,kBAAkB,iBAAiB,QAAQ,IAAI,4BAA4B,KAAK;AAOtF,QAAM,kBAAkB,wBAAwB,QAAQ,IAAI,qBAAqB,KAAK;AACtF,QAAM,UAAU,kBACZ,QACA,wBAAwB,QAAQ,IAAI,oBAAoB,IAAI;AAEhE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,WAAW,QAAQ,IAAI,yBAAyB;AAAA,IAChD,UAAU,QAAQ,IAAI;AAAA,IACtB;AAAA,EACF;AACF;AAMO,SAAS,4BACd,WACA,UACiB;AACjB,SAAO;AAAA,IACL,QAAQ,iBAAiB,QAAQ,IAAI,cAAc,SAAS,SAAS,CAAC,KAAK,SAAS;AAAA,IACpF,UAAU,iBAAiB,QAAQ,IAAI,cAAc,SAAS,WAAW,CAAC,KAAK,SAAS;AAAA,IACxF,eAAe,iBAAiB,QAAQ,IAAI,cAAc,SAAS,iBAAiB,CAAC,KAAK,SAAS;AAAA,IACnG,WAAW,SAAS;AAAA,EACtB;AACF;AAEA,SAAS,iBAAiB,KAA6C;AACrE,MAAI,QAAQ,UAAa,QAAQ,GAAI,QAAO;AAC5C,QAAM,SAAS,OAAO,GAAG;AACzB,SAAO,OAAO,SAAS,MAAM,KAAK,UAAU,IAAI,SAAS;AAC3D;",
6
6
  "names": []
7
7
  }
@@ -1,4 +1,4 @@
1
- const APP_VERSION = "0.5.1-develop.2856.35de414092";
1
+ const APP_VERSION = "0.5.1-develop.2860.07af3a6a9d";
2
2
  const appVersion = APP_VERSION;
3
3
  export {
4
4
  APP_VERSION,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/version.ts"],
4
- "sourcesContent": ["// Build-time generated version\nexport const APP_VERSION = '0.5.1-develop.2856.35de414092'\nexport const appVersion = APP_VERSION\n"],
4
+ "sourcesContent": ["// Build-time generated version\nexport const APP_VERSION = '0.5.1-develop.2860.07af3a6a9d'\nexport const appVersion = APP_VERSION\n"],
5
5
  "mappings": "AACO,MAAM,cAAc;AACpB,MAAM,aAAa;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/shared",
3
- "version": "0.5.1-develop.2856.35de414092",
3
+ "version": "0.5.1-develop.2860.07af3a6a9d",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -92,7 +92,7 @@
92
92
  "@mikro-orm/core": "^7.0.10",
93
93
  "@mikro-orm/decorators": "^7.0.10",
94
94
  "@mikro-orm/postgresql": "^7.0.10",
95
- "@open-mercato/cache": "0.5.1-develop.2856.35de414092",
95
+ "@open-mercato/cache": "0.5.1-develop.2860.07af3a6a9d",
96
96
  "dotenv": "^17.4.2",
97
97
  "rate-limiter-flexible": "^11.0.1",
98
98
  "reflect-metadata": "^0.2.2",
@@ -0,0 +1,33 @@
1
+ import { readRateLimitConfig } from '../config'
2
+
3
+ describe('readRateLimitConfig', () => {
4
+ const originalEnv = { ...process.env }
5
+
6
+ afterEach(() => {
7
+ process.env = { ...originalEnv }
8
+ })
9
+
10
+ it('defaults to enabled when no env is set', () => {
11
+ delete process.env.RATE_LIMIT_ENABLED
12
+ delete process.env.OM_INTEGRATION_TEST
13
+ expect(readRateLimitConfig().enabled).toBe(true)
14
+ })
15
+
16
+ it('honors RATE_LIMIT_ENABLED=false', () => {
17
+ process.env.RATE_LIMIT_ENABLED = 'false'
18
+ delete process.env.OM_INTEGRATION_TEST
19
+ expect(readRateLimitConfig().enabled).toBe(false)
20
+ })
21
+
22
+ it('forces enabled=false under OM_INTEGRATION_TEST=true even when RATE_LIMIT_ENABLED=true', () => {
23
+ process.env.RATE_LIMIT_ENABLED = 'true'
24
+ process.env.OM_INTEGRATION_TEST = 'true'
25
+ expect(readRateLimitConfig().enabled).toBe(false)
26
+ })
27
+
28
+ it('ignores OM_INTEGRATION_TEST=false', () => {
29
+ process.env.RATE_LIMIT_ENABLED = 'true'
30
+ process.env.OM_INTEGRATION_TEST = 'false'
31
+ expect(readRateLimitConfig().enabled).toBe(true)
32
+ })
33
+ })
@@ -11,8 +11,18 @@ export function readRateLimitConfig(): RateLimitGlobalConfig {
11
11
 
12
12
  const trustProxyDepth = parsePositiveInt(process.env.RATE_LIMIT_TRUST_PROXY_DEPTH) ?? 1
13
13
 
14
+ // Integration test runs disable rate limiting globally so suites do not
15
+ // have to juggle per-endpoint bypass headers or reshape default caps.
16
+ // The targeted OM_TEST_MODE + OM_TEST_AUTH_RATE_LIMIT_MODE=opt-in escape
17
+ // hatch (checkAuthRateLimit) still works for suites that explicitly test
18
+ // rate-limit behavior.
19
+ const integrationTest = parseBooleanWithDefault(process.env.OM_INTEGRATION_TEST, false)
20
+ const enabled = integrationTest
21
+ ? false
22
+ : parseBooleanWithDefault(process.env.RATE_LIMIT_ENABLED, true)
23
+
14
24
  return {
15
- enabled: parseBooleanWithDefault(process.env.RATE_LIMIT_ENABLED, true),
25
+ enabled,
16
26
  strategy,
17
27
  keyPrefix: process.env.RATE_LIMIT_KEY_PREFIX ?? 'rl',
18
28
  redisUrl: process.env.REDIS_URL,