@uniglot/wont-let-you-see 0.1.0 → 0.1.1

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.
@@ -0,0 +1 @@
1
+ * @uniglot
package/dist/index.js CHANGED
@@ -114,7 +114,7 @@ function getOriginal(sessionId, token) {
114
114
 
115
115
  // src/config.ts
116
116
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
117
- import { join as join2 } from "path";
117
+ import { join as join2, dirname } from "path";
118
118
  import { homedir as homedir2 } from "os";
119
119
  var DEFAULT_CONFIG = {
120
120
  enabled: true,
@@ -122,18 +122,39 @@ var DEFAULT_CONFIG = {
122
122
  customPatterns: []
123
123
  };
124
124
  var CONFIG_FILENAME = ".wont-let-you-see.json";
125
- function loadJsonConfig() {
126
- const paths = [
127
- join2(process.cwd(), CONFIG_FILENAME),
128
- join2(homedir2(), CONFIG_FILENAME)
129
- ];
130
- for (const configPath of paths) {
125
+ function findConfigInAncestors(startDir) {
126
+ const home = homedir2();
127
+ let currentDir = startDir;
128
+ while (true) {
129
+ const configPath = join2(currentDir, CONFIG_FILENAME);
131
130
  if (existsSync2(configPath)) {
132
- try {
133
- const content = readFileSync2(configPath, "utf-8");
134
- return JSON.parse(content);
135
- } catch {}
131
+ return configPath;
132
+ }
133
+ if (currentDir === home) {
134
+ break;
136
135
  }
136
+ const parentDir = dirname(currentDir);
137
+ if (parentDir === currentDir) {
138
+ break;
139
+ }
140
+ currentDir = parentDir;
141
+ }
142
+ return null;
143
+ }
144
+ function loadJsonConfig() {
145
+ const ancestorConfig = findConfigInAncestors(process.cwd());
146
+ if (ancestorConfig) {
147
+ try {
148
+ const content = readFileSync2(ancestorConfig, "utf-8");
149
+ return JSON.parse(content);
150
+ } catch {}
151
+ }
152
+ const homeConfig = join2(homedir2(), CONFIG_FILENAME);
153
+ if (existsSync2(homeConfig)) {
154
+ try {
155
+ const content = readFileSync2(homeConfig, "utf-8");
156
+ return JSON.parse(content);
157
+ } catch {}
137
158
  }
138
159
  return {};
139
160
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniglot/wont-let-you-see",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "OpenCode plugin that masks sensitive cloud infrastructure data (AWS, Kubernetes) from LLMs",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,16 +1,32 @@
1
- import { describe, it, expect, beforeEach, afterEach } from "vitest";
1
+ import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
2
2
  import { getConfig, resetConfig, isPatternEnabled } from "../config";
3
+ import * as fs from "fs";
4
+ import * as path from "path";
5
+
6
+ vi.mock("fs", async () => {
7
+ const actual = await vi.importActual<typeof fs>("fs");
8
+ return {
9
+ ...actual,
10
+ existsSync: vi.fn(),
11
+ readFileSync: vi.fn(),
12
+ };
13
+ });
3
14
 
4
15
  describe("Config", () => {
5
16
  const originalEnv = { ...process.env };
17
+ const originalCwd = process.cwd;
6
18
 
7
19
  beforeEach(() => {
8
20
  resetConfig();
21
+ vi.mocked(fs.existsSync).mockReturnValue(false);
22
+ vi.mocked(fs.readFileSync).mockReturnValue("{}");
9
23
  });
10
24
 
11
25
  afterEach(() => {
12
26
  process.env = { ...originalEnv };
27
+ process.cwd = originalCwd;
13
28
  resetConfig();
29
+ vi.clearAllMocks();
14
30
  });
15
31
 
16
32
  describe("getConfig", () => {
@@ -95,4 +111,77 @@ describe("Config", () => {
95
111
  expect(isPatternEnabled("vpc")).toBe(true);
96
112
  });
97
113
  });
114
+
115
+ describe("ancestor directory config lookup", () => {
116
+ it("should find config in parent directory when cwd is subdirectory", () => {
117
+ process.cwd = () => "/project/packages/app";
118
+
119
+ vi.mocked(fs.existsSync).mockImplementation((p) => {
120
+ return p === path.join("/project", ".wont-let-you-see.json");
121
+ });
122
+ vi.mocked(fs.readFileSync).mockReturnValue(
123
+ JSON.stringify({ enabled: false, customPatterns: ["secret123"] }),
124
+ );
125
+
126
+ const config = getConfig();
127
+ expect(config.enabled).toBe(false);
128
+ expect(config.customPatterns).toEqual(["secret123"]);
129
+ });
130
+
131
+ it("should find config in grandparent directory", () => {
132
+ process.cwd = () => "/project/packages/app/src/components";
133
+
134
+ vi.mocked(fs.existsSync).mockImplementation((p) => {
135
+ return p === path.join("/project", ".wont-let-you-see.json");
136
+ });
137
+ vi.mocked(fs.readFileSync).mockReturnValue(
138
+ JSON.stringify({ revealedPatterns: ["ipv4"] }),
139
+ );
140
+
141
+ const config = getConfig();
142
+ expect(config.revealedPatterns).toEqual(["ipv4"]);
143
+ });
144
+
145
+ it("should prefer config in closer ancestor over distant ancestor", () => {
146
+ process.cwd = () => "/project/packages/app";
147
+
148
+ vi.mocked(fs.existsSync).mockImplementation((p) => {
149
+ return (
150
+ p === path.join("/project/packages/app", ".wont-let-you-see.json") ||
151
+ p === path.join("/project", ".wont-let-you-see.json")
152
+ );
153
+ });
154
+ vi.mocked(fs.readFileSync).mockImplementation((p) => {
155
+ if (
156
+ p === path.join("/project/packages/app", ".wont-let-you-see.json")
157
+ ) {
158
+ return JSON.stringify({ customPatterns: ["app-secret"] });
159
+ }
160
+ return JSON.stringify({ customPatterns: ["root-secret"] });
161
+ });
162
+
163
+ const config = getConfig();
164
+ expect(config.customPatterns).toEqual(["app-secret"]);
165
+ });
166
+
167
+ it("should prefer cwd config over parent config", () => {
168
+ process.cwd = () => "/project/subdir";
169
+
170
+ vi.mocked(fs.existsSync).mockImplementation((p) => {
171
+ return (
172
+ p === path.join("/project/subdir", ".wont-let-you-see.json") ||
173
+ p === path.join("/project", ".wont-let-you-see.json")
174
+ );
175
+ });
176
+ vi.mocked(fs.readFileSync).mockImplementation((p) => {
177
+ if (p === path.join("/project/subdir", ".wont-let-you-see.json")) {
178
+ return JSON.stringify({ enabled: false });
179
+ }
180
+ return JSON.stringify({ enabled: true });
181
+ });
182
+
183
+ const config = getConfig();
184
+ expect(config.enabled).toBe(false);
185
+ });
186
+ });
98
187
  });
package/src/config.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { existsSync, readFileSync } from "fs";
2
- import { join } from "path";
2
+ import { join, dirname, parse } from "path";
3
3
  import { homedir } from "os";
4
4
 
5
5
  export interface Config {
@@ -16,19 +16,47 @@ const DEFAULT_CONFIG: Config = {
16
16
 
17
17
  const CONFIG_FILENAME = ".wont-let-you-see.json";
18
18
 
19
- function loadJsonConfig(): Partial<Config> {
20
- const paths = [
21
- join(process.cwd(), CONFIG_FILENAME),
22
- join(homedir(), CONFIG_FILENAME),
23
- ];
19
+ function findConfigInAncestors(startDir: string): string | null {
20
+ const home = homedir();
21
+ let currentDir = startDir;
24
22
 
25
- for (const configPath of paths) {
23
+ while (true) {
24
+ const configPath = join(currentDir, CONFIG_FILENAME);
26
25
  if (existsSync(configPath)) {
27
- try {
28
- const content = readFileSync(configPath, "utf-8");
29
- return JSON.parse(content);
30
- } catch {}
26
+ return configPath;
27
+ }
28
+
29
+ if (currentDir === home) {
30
+ break;
31
31
  }
32
+
33
+ const parentDir = dirname(currentDir);
34
+ if (parentDir === currentDir) {
35
+ break;
36
+ }
37
+ currentDir = parentDir;
38
+ }
39
+
40
+ return null;
41
+ }
42
+
43
+ function loadJsonConfig(): Partial<Config> {
44
+ // First, search up from cwd to find nearest config
45
+ const ancestorConfig = findConfigInAncestors(process.cwd());
46
+ if (ancestorConfig) {
47
+ try {
48
+ const content = readFileSync(ancestorConfig, "utf-8");
49
+ return JSON.parse(content);
50
+ } catch {}
51
+ }
52
+
53
+ // Fall back to home directory
54
+ const homeConfig = join(homedir(), CONFIG_FILENAME);
55
+ if (existsSync(homeConfig)) {
56
+ try {
57
+ const content = readFileSync(homeConfig, "utf-8");
58
+ return JSON.parse(content);
59
+ } catch {}
32
60
  }
33
61
 
34
62
  return {};