@forwardimpact/libutil 0.1.63 → 0.1.65
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/bin/fit-download-bundle.js +1 -1
- package/bin/fit-tiktoken.js +1 -1
- package/finder.js +19 -0
- package/package.json +3 -3
- package/test/finder.test.js +73 -0
- package/test/logger.test.js +0 -103
package/bin/fit-tiktoken.js
CHANGED
package/finder.js
CHANGED
|
@@ -47,6 +47,25 @@ export class Finder {
|
|
|
47
47
|
return null;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Resolve a data directory by upward traversal, with HOME fallback.
|
|
52
|
+
* @param {string} baseName - Directory name to find (e.g. "data")
|
|
53
|
+
* @param {string} homeDir - User home directory path
|
|
54
|
+
* @returns {string} Absolute path to found directory
|
|
55
|
+
*/
|
|
56
|
+
findData(baseName, homeDir) {
|
|
57
|
+
const cwd = this.#process.cwd();
|
|
58
|
+
const found = this.findUpward(cwd, baseName);
|
|
59
|
+
if (found) return found;
|
|
60
|
+
|
|
61
|
+
const homePath = path.join(homeDir, ".fit", baseName);
|
|
62
|
+
if (fs.existsSync(homePath)) return homePath;
|
|
63
|
+
|
|
64
|
+
throw new Error(
|
|
65
|
+
`No ${baseName} directory found from ${cwd} or ${homePath}.`,
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
50
69
|
/**
|
|
51
70
|
* Find the project root directory
|
|
52
71
|
* @param {string} startPath - Starting directory path
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forwardimpact/libutil",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.65",
|
|
4
4
|
"description": "Utility functions and utilities for Guide",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "D. Olsson <hi@senzilla.io>",
|
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
"fit-tiktoken": "./bin/fit-tiktoken.js"
|
|
12
12
|
},
|
|
13
13
|
"engines": {
|
|
14
|
-
"
|
|
14
|
+
"bun": ">=1.2.0"
|
|
15
15
|
},
|
|
16
16
|
"scripts": {
|
|
17
|
-
"test": "node --test test/*.test.js"
|
|
17
|
+
"test": "bun run node --test test/*.test.js"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@forwardimpact/libtelemetry": "^0.1.22"
|
package/test/finder.test.js
CHANGED
|
@@ -257,6 +257,79 @@ describe("Finder", () => {
|
|
|
257
257
|
});
|
|
258
258
|
});
|
|
259
259
|
|
|
260
|
+
describe("findData", () => {
|
|
261
|
+
test("finds data/ in CWD via findUpward", () => {
|
|
262
|
+
const dataDir = path.join(tempDir, "data");
|
|
263
|
+
fs.mkdirSync(dataDir);
|
|
264
|
+
|
|
265
|
+
const cwdFinder = new Finder(fsPromises, mockLogger, {
|
|
266
|
+
cwd: () => tempDir,
|
|
267
|
+
});
|
|
268
|
+
const result = cwdFinder.findData("data", "/nonexistent-home");
|
|
269
|
+
|
|
270
|
+
assert.strictEqual(result, dataDir);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
test("finds data/ in a parent directory via findUpward", () => {
|
|
274
|
+
const dataDir = path.join(tempDir, "data");
|
|
275
|
+
fs.mkdirSync(dataDir);
|
|
276
|
+
const subDir = path.join(tempDir, "products", "pathway");
|
|
277
|
+
fs.mkdirSync(subDir, { recursive: true });
|
|
278
|
+
|
|
279
|
+
const cwdFinder = new Finder(fsPromises, mockLogger, {
|
|
280
|
+
cwd: () => subDir,
|
|
281
|
+
});
|
|
282
|
+
const result = cwdFinder.findData("data", "/nonexistent-home");
|
|
283
|
+
|
|
284
|
+
assert.strictEqual(result, dataDir);
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
test("falls back to ~/.fit/data/ when CWD traversal fails", () => {
|
|
288
|
+
const fakeHome = path.join(tempDir, "fakehome");
|
|
289
|
+
const homeFitData = path.join(fakeHome, ".fit", "data");
|
|
290
|
+
fs.mkdirSync(homeFitData, { recursive: true });
|
|
291
|
+
|
|
292
|
+
const isolatedDir = path.join(tempDir, "isolated");
|
|
293
|
+
fs.mkdirSync(isolatedDir);
|
|
294
|
+
|
|
295
|
+
const cwdFinder = new Finder(fsPromises, mockLogger, {
|
|
296
|
+
cwd: () => isolatedDir,
|
|
297
|
+
});
|
|
298
|
+
const result = cwdFinder.findData("data", fakeHome);
|
|
299
|
+
|
|
300
|
+
assert.strictEqual(result, homeFitData);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
test("throws when neither CWD traversal nor HOME fallback finds directory", () => {
|
|
304
|
+
const isolatedDir = path.join(tempDir, "isolated");
|
|
305
|
+
fs.mkdirSync(isolatedDir);
|
|
306
|
+
|
|
307
|
+
const cwdFinder = new Finder(fsPromises, mockLogger, {
|
|
308
|
+
cwd: () => isolatedDir,
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
assert.throws(() => cwdFinder.findData("data", "/nonexistent-home"), {
|
|
312
|
+
message: /No data directory found/,
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
test("CWD takes priority over HOME when both exist", () => {
|
|
317
|
+
const cwdData = path.join(tempDir, "data");
|
|
318
|
+
fs.mkdirSync(cwdData);
|
|
319
|
+
|
|
320
|
+
const fakeHome = path.join(tempDir, "fakehome");
|
|
321
|
+
const homeFitData = path.join(fakeHome, ".fit", "data");
|
|
322
|
+
fs.mkdirSync(homeFitData, { recursive: true });
|
|
323
|
+
|
|
324
|
+
const cwdFinder = new Finder(fsPromises, mockLogger, {
|
|
325
|
+
cwd: () => tempDir,
|
|
326
|
+
});
|
|
327
|
+
const result = cwdFinder.findData("data", fakeHome);
|
|
328
|
+
|
|
329
|
+
assert.strictEqual(result, cwdData);
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
|
|
260
333
|
describe("findPackagePath", () => {
|
|
261
334
|
test("finds package in local monorepo structure", () => {
|
|
262
335
|
// Create mock monorepo structure
|
package/test/logger.test.js
CHANGED
|
@@ -97,28 +97,6 @@ describe("Logger", () => {
|
|
|
97
97
|
assert.strictEqual(consoleOutput.length, 0);
|
|
98
98
|
});
|
|
99
99
|
|
|
100
|
-
test(
|
|
101
|
-
"logs message with data object",
|
|
102
|
-
{ skip: "Future PR will fix this" },
|
|
103
|
-
() => {
|
|
104
|
-
process.env.DEBUG = "test";
|
|
105
|
-
const logger = new Logger("test");
|
|
106
|
-
|
|
107
|
-
logger.debug("ProcessMethod", "Processing", {
|
|
108
|
-
items: "50/200",
|
|
109
|
-
retry: "2/3",
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
assert.strictEqual(consoleOutput.length, 1);
|
|
113
|
-
assert.ok(consoleOutput[0].includes("DEBUG"));
|
|
114
|
-
assert.ok(consoleOutput[0].includes("test"));
|
|
115
|
-
assert.ok(consoleOutput[0].includes("ProcessMethod"));
|
|
116
|
-
assert.ok(consoleOutput[0].includes("Processing"));
|
|
117
|
-
assert.ok(consoleOutput[0].includes('items="50/200"'));
|
|
118
|
-
assert.ok(consoleOutput[0].includes('retry="2/3"'));
|
|
119
|
-
},
|
|
120
|
-
);
|
|
121
|
-
|
|
122
100
|
test("handles empty data object", () => {
|
|
123
101
|
process.env.DEBUG = "test";
|
|
124
102
|
const logger = new Logger("test");
|
|
@@ -140,87 +118,6 @@ describe("Logger", () => {
|
|
|
140
118
|
assert.ok(consoleOutput[0].match(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/));
|
|
141
119
|
});
|
|
142
120
|
|
|
143
|
-
test(
|
|
144
|
-
"extracts trace context from error objects",
|
|
145
|
-
{ skip: "Future PR will fix this" },
|
|
146
|
-
() => {
|
|
147
|
-
process.env.DEBUG = "test";
|
|
148
|
-
const logger = new Logger("test");
|
|
149
|
-
|
|
150
|
-
// Create error with trace context (as added by Tracer)
|
|
151
|
-
const error = new Error("Test error");
|
|
152
|
-
Object.defineProperties(error, {
|
|
153
|
-
trace_id: {
|
|
154
|
-
value: "abc123def456",
|
|
155
|
-
enumerable: false,
|
|
156
|
-
writable: false,
|
|
157
|
-
},
|
|
158
|
-
span_id: {
|
|
159
|
-
value: "789xyz012",
|
|
160
|
-
enumerable: false,
|
|
161
|
-
writable: false,
|
|
162
|
-
},
|
|
163
|
-
service_name: {
|
|
164
|
-
value: "test-service",
|
|
165
|
-
enumerable: false,
|
|
166
|
-
writable: false,
|
|
167
|
-
},
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
logger.error("TestMethod", error);
|
|
171
|
-
|
|
172
|
-
assert.strictEqual(consoleOutput.length, 1);
|
|
173
|
-
assert.ok(consoleOutput[0].includes("ERROR"));
|
|
174
|
-
assert.ok(consoleOutput[0].includes("Test error"));
|
|
175
|
-
assert.ok(
|
|
176
|
-
consoleOutput[0].includes("trace_id=abc123def456"),
|
|
177
|
-
"Should include trace_id in structured data",
|
|
178
|
-
);
|
|
179
|
-
assert.ok(
|
|
180
|
-
consoleOutput[0].includes("span_id=789xyz012"),
|
|
181
|
-
"Should include span_id in structured data",
|
|
182
|
-
);
|
|
183
|
-
assert.ok(
|
|
184
|
-
consoleOutput[0].includes("service_name=test-service"),
|
|
185
|
-
"Should include service_name in structured data",
|
|
186
|
-
);
|
|
187
|
-
},
|
|
188
|
-
);
|
|
189
|
-
|
|
190
|
-
test(
|
|
191
|
-
"merges trace context with provided attributes",
|
|
192
|
-
{ skip: "Future PR will fix this" },
|
|
193
|
-
() => {
|
|
194
|
-
process.env.DEBUG = "test";
|
|
195
|
-
const logger = new Logger("test");
|
|
196
|
-
|
|
197
|
-
const error = new Error("Test error");
|
|
198
|
-
Object.defineProperty(error, "trace_id", {
|
|
199
|
-
value: "trace123",
|
|
200
|
-
enumerable: false,
|
|
201
|
-
writable: false,
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
logger.error("TestMethod", error, { retry: "1/3", status: "500" });
|
|
205
|
-
|
|
206
|
-
assert.strictEqual(consoleOutput.length, 1);
|
|
207
|
-
assert.ok(consoleOutput[0].includes("ERROR"));
|
|
208
|
-
assert.ok(consoleOutput[0].includes("Test error"));
|
|
209
|
-
assert.ok(
|
|
210
|
-
consoleOutput[0].includes('trace_id="abc123def456"'),
|
|
211
|
-
"Should include trace_id in structured data",
|
|
212
|
-
);
|
|
213
|
-
assert.ok(
|
|
214
|
-
consoleOutput[0].includes('span_id="789xyz012"'),
|
|
215
|
-
"Should include span_id in structured data",
|
|
216
|
-
);
|
|
217
|
-
assert.ok(
|
|
218
|
-
consoleOutput[0].includes('service_name="test-service"'),
|
|
219
|
-
"Should include service_name in structured data",
|
|
220
|
-
);
|
|
221
|
-
},
|
|
222
|
-
);
|
|
223
|
-
|
|
224
121
|
test("merges trace context with provided attributes", () => {
|
|
225
122
|
process.env.DEBUG = "test";
|
|
226
123
|
const logger = new Logger("test");
|