|
4 | 4 | DEFAULT_INCLUDE_EXTENSIONS, |
5 | 5 | DEFAULT_EXCLUDE_PATTERNS, |
6 | 6 | ENV_PATTERNS, |
| 7 | + buildSveltekitAliasPatterns, |
7 | 8 | } from '../../../../src/core/scan/patterns'; |
8 | 9 | import type { ScanOptions } from '../../../../src/config/types'; |
9 | 10 |
|
@@ -455,6 +456,70 @@ describe('scanFile - Pattern Detection', () => { |
455 | 456 | }); |
456 | 457 | }); |
457 | 458 |
|
| 459 | + describe('buildSveltekitAliasPatterns', () => { |
| 460 | + function makeMatch( |
| 461 | + fullMatch: string, |
| 462 | + ...groups: (string | undefined)[] |
| 463 | + ): RegExpExecArray { |
| 464 | + return Object.assign([fullMatch, ...groups], { |
| 465 | + index: 0, |
| 466 | + input: fullMatch, |
| 467 | + }) as unknown as RegExpExecArray; |
| 468 | + } |
| 469 | + |
| 470 | + it('returns two patterns for a given alias', () => { |
| 471 | + const patterns = buildSveltekitAliasPatterns('privateEnv'); |
| 472 | + expect(patterns).toHaveLength(2); |
| 473 | + expect(patterns[0]?.regex).toBeInstanceOf(RegExp); |
| 474 | + expect(patterns[1]?.regex).toBeInstanceOf(RegExp); |
| 475 | + expect(patterns.every((p) => p.name === 'sveltekit')).toBe(true); |
| 476 | + }); |
| 477 | + |
| 478 | + it('dot notation pattern matches alias.VAR', () => { |
| 479 | + const [dotPattern] = buildSveltekitAliasPatterns('privateEnv'); |
| 480 | + expect(dotPattern!.regex.test('privateEnv.MY_SECRET')).toBe(true); |
| 481 | + expect(dotPattern!.regex.test('env.MY_SECRET')).toBe(false); |
| 482 | + }); |
| 483 | + |
| 484 | + it('destructuring processor returns [] for empty content (if !content branch)', () => { |
| 485 | + const [, destructurePattern] = buildSveltekitAliasPatterns('privateEnv'); |
| 486 | + const result = destructurePattern!.processor!(makeMatch('{}', '')); |
| 487 | + expect(result).toEqual([]); |
| 488 | + }); |
| 489 | + |
| 490 | + it('destructuring processor returns [] when content is undefined', () => { |
| 491 | + const [, destructurePattern] = buildSveltekitAliasPatterns('privateEnv'); |
| 492 | + const result = destructurePattern!.processor!(makeMatch('{}', undefined)); |
| 493 | + expect(result).toEqual([]); |
| 494 | + }); |
| 495 | + |
| 496 | + it('destructuring processor returns empty string for part starting with : (key falsy branch)', () => { |
| 497 | + // ':ALIAS' splits to key='' which is falsy → '' → filtered by uppercase check |
| 498 | + const code = `import { env as privateEnv } from '$env/dynamic/private'; |
| 499 | +const { :ALIAS } = privateEnv;`; |
| 500 | + const result = scanFile('test.ts', code, baseOpts); |
| 501 | + expect(result).toHaveLength(0); |
| 502 | + }); |
| 503 | + |
| 504 | + it('destructuring processor extracts multiple vars from aliased import', () => { |
| 505 | + const code = `import { env as privateEnv } from '$env/dynamic/private'; |
| 506 | +const { SECRET_KEY, API_TOKEN } = privateEnv;`; |
| 507 | + const result = scanFile('test.ts', code, baseOpts); |
| 508 | + expect(result.map((u) => u.variable).sort()).toEqual([ |
| 509 | + 'API_TOKEN', |
| 510 | + 'SECRET_KEY', |
| 511 | + ]); |
| 512 | + }); |
| 513 | + |
| 514 | + it('destructuring processor handles aliased keys: { VAR: alias } = privateEnv', () => { |
| 515 | + const code = `import { env as privateEnv } from '$env/dynamic/private'; |
| 516 | +const { SECRET_KEY: secret } = privateEnv;`; |
| 517 | + const result = scanFile('test.ts', code, baseOpts); |
| 518 | + expect(result).toHaveLength(1); |
| 519 | + expect(result[0]?.variable).toBe('SECRET_KEY'); |
| 520 | + }); |
| 521 | + }); |
| 522 | + |
458 | 523 | describe('SvelteKit env Object Access', () => { |
459 | 524 | it('detects env.VARIABLE_NAME access', () => { |
460 | 525 | const code = 'const token = env.KEYCLOAK_SECRET;'; |
|
0 commit comments