zod-codegen 1.7.1 → 1.7.2

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/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## [1.7.2](https://github.com/julienandreu/zod-codegen/compare/v1.7.1...v1.7.2) (2026-03-10)
2
+
3
+ ### 🐛 Bug Fixes
4
+
5
+ - redact credentials from source URL in generated file headers ([#88](https://github.com/julienandreu/zod-codegen/issues/88)) ([692901d](https://github.com/julienandreu/zod-codegen/commit/692901d0b3ea8a53cbb92102bc9c3f7f90aa44aa))
6
+
1
7
  ## [1.7.1](https://github.com/julienandreu/zod-codegen/compare/v1.7.0...v1.7.1) (2026-03-10)
2
8
 
3
9
  ### 🐛 Bug Fixes
@@ -4,6 +4,7 @@ export declare class SyncFileWriterService implements FileWriter {
4
4
  private readonly version;
5
5
  private readonly inputPath;
6
6
  constructor(name: string, version: string, inputPath: string);
7
+ private redactUrl;
7
8
  writeFile(filePath: string, content: string): void;
8
9
  resolveOutputPath(outputDir: string, fileName?: string): string;
9
10
  }
@@ -1 +1 @@
1
- {"version":3,"file":"file-writer.service.d.ts","sourceRoot":"","sources":["../../../src/services/file-writer.service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE/D,qBAAa,qBAAsB,YAAW,UAAU;IAEpD,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAFT,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM;IAGpC,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAqBlD,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,SAAW,GAAG,MAAM;CAGlE"}
1
+ {"version":3,"file":"file-writer.service.d.ts","sourceRoot":"","sources":["../../../src/services/file-writer.service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE/D,qBAAa,qBAAsB,YAAW,UAAU;IAEpD,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAFT,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM;IAGpC,OAAO,CAAC,SAAS;IAajB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAqBlD,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,SAAW,GAAG,MAAM;CAGlE"}
@@ -9,12 +9,25 @@ export class SyncFileWriterService {
9
9
  this.version = version;
10
10
  this.inputPath = inputPath;
11
11
  }
12
+ redactUrl(path) {
13
+ try {
14
+ const url = new URL(path);
15
+ if ((url.protocol === 'http:' || url.protocol === 'https:') && url.password) {
16
+ url.password = '***';
17
+ return url.toString();
18
+ }
19
+ }
20
+ catch {
21
+ // Not a URL, return as-is
22
+ }
23
+ return path;
24
+ }
12
25
  writeFile(filePath, content) {
13
26
  const generatedContent = [
14
27
  '// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.',
15
28
  `// Built with ${this.name}@${this.version}`,
16
29
  `// Latest edit: ${new Date().toUTCString()}`,
17
- `// Source file: ${this.inputPath}`,
30
+ `// Source file: ${this.redactUrl(this.inputPath)}`,
18
31
  '/* eslint-disable */',
19
32
  '// @ts-nocheck',
20
33
  '',
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=file-writer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-writer.test.d.ts","sourceRoot":"","sources":["../../../tests/unit/file-writer.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,53 @@
1
+ import { existsSync, mkdirSync, readFileSync, rmSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
5
+ import { SyncFileWriterService } from '../../src/services/file-writer.service';
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+ const testOutputDir = join(__dirname, '../../test-output-writer');
8
+ describe('SyncFileWriterService', () => {
9
+ beforeEach(() => {
10
+ if (existsSync(testOutputDir)) {
11
+ rmSync(testOutputDir, { recursive: true, force: true });
12
+ }
13
+ mkdirSync(testOutputDir, { recursive: true });
14
+ });
15
+ afterEach(() => {
16
+ if (existsSync(testOutputDir)) {
17
+ rmSync(testOutputDir, { recursive: true, force: true });
18
+ }
19
+ });
20
+ describe('credential redaction', () => {
21
+ it('should redact password from URL with embedded credentials', () => {
22
+ const writer = new SyncFileWriterService('zod-codegen', '1.0.0', 'https://user:secretpass@api.example.com/openapi.json');
23
+ const outPath = join(testOutputDir, 'api.ts');
24
+ writer.writeFile(outPath, 'const x = 1;');
25
+ const content = readFileSync(outPath, 'utf-8');
26
+ expect(content).toContain('// Source file: https://user:***@api.example.com/openapi.json');
27
+ expect(content).not.toContain('secretpass');
28
+ });
29
+ it('should redact password from URL with percent-encoded credentials', () => {
30
+ const writer = new SyncFileWriterService('zod-codegen', '1.0.0', 'https://api%2Bstaging%40saris.ai:hnt.xjx3rby8YKM8wnm@api.staging.saris.ai/api/openapi.json');
31
+ const outPath = join(testOutputDir, 'api.ts');
32
+ writer.writeFile(outPath, 'const x = 1;');
33
+ const content = readFileSync(outPath, 'utf-8');
34
+ expect(content).toContain('api%2Bstaging%40saris.ai');
35
+ expect(content).toContain(':***@');
36
+ expect(content).not.toContain('hnt.xjx3rby8YKM8wnm');
37
+ });
38
+ it('should leave URL without credentials unchanged', () => {
39
+ const writer = new SyncFileWriterService('zod-codegen', '1.0.0', 'https://api.example.com/openapi.json');
40
+ const outPath = join(testOutputDir, 'api.ts');
41
+ writer.writeFile(outPath, 'const x = 1;');
42
+ const content = readFileSync(outPath, 'utf-8');
43
+ expect(content).toContain('// Source file: https://api.example.com/openapi.json');
44
+ });
45
+ it('should leave local file paths unchanged', () => {
46
+ const writer = new SyncFileWriterService('zod-codegen', '1.0.0', './samples/openapi.json');
47
+ const outPath = join(testOutputDir, 'api.ts');
48
+ writer.writeFile(outPath, 'const x = 1;');
49
+ const content = readFileSync(outPath, 'utf-8');
50
+ expect(content).toContain('// Source file: ./samples/openapi.json');
51
+ });
52
+ });
53
+ });
package/package.json CHANGED
@@ -101,5 +101,5 @@
101
101
  "release": "semantic-release",
102
102
  "release:dry": "semantic-release --dry-run"
103
103
  },
104
- "version": "1.7.1"
104
+ "version": "1.7.2"
105
105
  }
@@ -9,12 +9,25 @@ export class SyncFileWriterService implements FileWriter {
9
9
  private readonly inputPath: string
10
10
  ) {}
11
11
 
12
+ private redactUrl(path: string): string {
13
+ try {
14
+ const url = new URL(path);
15
+ if ((url.protocol === 'http:' || url.protocol === 'https:') && url.password) {
16
+ url.password = '***';
17
+ return url.toString();
18
+ }
19
+ } catch {
20
+ // Not a URL, return as-is
21
+ }
22
+ return path;
23
+ }
24
+
12
25
  writeFile(filePath: string, content: string): void {
13
26
  const generatedContent = [
14
27
  '// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.',
15
28
  `// Built with ${this.name}@${this.version}`,
16
29
  `// Latest edit: ${new Date().toUTCString()}`,
17
- `// Source file: ${this.inputPath}`,
30
+ `// Source file: ${this.redactUrl(this.inputPath)}`,
18
31
  '/* eslint-disable */',
19
32
  '// @ts-nocheck',
20
33
  '',
@@ -0,0 +1,69 @@
1
+ import { existsSync, mkdirSync, readFileSync, rmSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
5
+ import { SyncFileWriterService } from '../../src/services/file-writer.service';
6
+
7
+ const __dirname = dirname(fileURLToPath(import.meta.url));
8
+ const testOutputDir = join(__dirname, '../../test-output-writer');
9
+
10
+ describe('SyncFileWriterService', () => {
11
+ beforeEach(() => {
12
+ if (existsSync(testOutputDir)) {
13
+ rmSync(testOutputDir, { recursive: true, force: true });
14
+ }
15
+
16
+ mkdirSync(testOutputDir, { recursive: true });
17
+ });
18
+
19
+ afterEach(() => {
20
+ if (existsSync(testOutputDir)) {
21
+ rmSync(testOutputDir, { recursive: true, force: true });
22
+ }
23
+ });
24
+
25
+ describe('credential redaction', () => {
26
+ it('should redact password from URL with embedded credentials', () => {
27
+ const writer = new SyncFileWriterService('zod-codegen', '1.0.0', 'https://user:secretpass@api.example.com/openapi.json');
28
+
29
+ const outPath = join(testOutputDir, 'api.ts');
30
+ writer.writeFile(outPath, 'const x = 1;');
31
+
32
+ const content = readFileSync(outPath, 'utf-8');
33
+ expect(content).toContain('// Source file: https://user:***@api.example.com/openapi.json');
34
+ expect(content).not.toContain('secretpass');
35
+ });
36
+
37
+ it('should redact password from URL with percent-encoded credentials', () => {
38
+ const writer = new SyncFileWriterService('zod-codegen', '1.0.0', 'https://api%2Bstaging%40saris.ai:hnt.xjx3rby8YKM8wnm@api.staging.saris.ai/api/openapi.json');
39
+
40
+ const outPath = join(testOutputDir, 'api.ts');
41
+ writer.writeFile(outPath, 'const x = 1;');
42
+
43
+ const content = readFileSync(outPath, 'utf-8');
44
+ expect(content).toContain('api%2Bstaging%40saris.ai');
45
+ expect(content).toContain(':***@');
46
+ expect(content).not.toContain('hnt.xjx3rby8YKM8wnm');
47
+ });
48
+
49
+ it('should leave URL without credentials unchanged', () => {
50
+ const writer = new SyncFileWriterService('zod-codegen', '1.0.0', 'https://api.example.com/openapi.json');
51
+
52
+ const outPath = join(testOutputDir, 'api.ts');
53
+ writer.writeFile(outPath, 'const x = 1;');
54
+
55
+ const content = readFileSync(outPath, 'utf-8');
56
+ expect(content).toContain('// Source file: https://api.example.com/openapi.json');
57
+ });
58
+
59
+ it('should leave local file paths unchanged', () => {
60
+ const writer = new SyncFileWriterService('zod-codegen', '1.0.0', './samples/openapi.json');
61
+
62
+ const outPath = join(testOutputDir, 'api.ts');
63
+ writer.writeFile(outPath, 'const x = 1;');
64
+
65
+ const content = readFileSync(outPath, 'utf-8');
66
+ expect(content).toContain('// Source file: ./samples/openapi.json');
67
+ });
68
+ });
69
+ });