@dev-blinq/cucumber_client 1.0.1691-dev → 1.0.1693-dev

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.
@@ -1,7 +1,6 @@
1
- import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
2
- import path from "path";
3
- import url from "url";
4
- import logger from "../../logger.js";
1
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
2
+ import path from "node:path";
3
+ import url from "node:url";
5
4
  import { CodePage, getAiConfig } from "../code_gen/page_reflection.js";
6
5
  import { generateCode, generatePageName } from "../code_gen/playwright_codeget.js";
7
6
  import { invertCodeToCommand } from "../code_gen/code_inversion.js";
@@ -9,8 +8,9 @@ import { Step } from "../cucumber/feature.js";
9
8
  import { locateDefinitionPath, StepsDefinitions } from "../cucumber/steps_definitions.js";
10
9
  import { Recording } from "../recording.js";
11
10
  import { generateApiCode } from "../code_gen/api_codegen.js";
12
- import { tmpdir } from "os";
13
- import { createHash } from "crypto";
11
+ import { tmpdir } from "node:os";
12
+ import { createHash } from "node:crypto";
13
+ import { getErrorMessage } from "../utils/socket_logger.js";
14
14
 
15
15
  const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
16
16
 
@@ -495,7 +495,15 @@ function makeStepTextUnique(step, stepsDefinitions) {
495
495
  step.text = stepText;
496
496
  }
497
497
 
498
- export async function saveRecording({ step, cucumberStep, codePage, projectDir, stepsDefinitions, parametersMap }) {
498
+ export async function saveRecording({
499
+ step,
500
+ cucumberStep,
501
+ codePage,
502
+ projectDir,
503
+ stepsDefinitions,
504
+ parametersMap,
505
+ logger,
506
+ }) {
499
507
  if (step.commands && Array.isArray(step.commands)) {
500
508
  step.commands = step.commands.map((cmd) => toRecordingStep(cmd, parametersMap, step.text));
501
509
  }
@@ -506,21 +514,19 @@ export async function saveRecording({ step, cucumberStep, codePage, projectDir,
506
514
  rmSync(routesPath, { recursive: true });
507
515
  }
508
516
  mkdirSync(routesPath, { recursive: true });
509
- saveRoutes({ step, folderPath: routesPath });
517
+ saveRoutes({ step, folderPath: routesPath }, logger);
510
518
  } else {
511
519
  if (existsSync(routesPath)) {
512
- // remove the folder
513
520
  try {
514
521
  rmSync(routesPath, { recursive: true });
515
- //
516
522
  } catch (error) {
517
- //
523
+ logger.error(`Error removing temp routes folder: ${getErrorMessage(error)}`);
518
524
  }
519
525
  routesPath = path.join(projectDir, "data", "routes");
520
526
  if (!existsSync(routesPath)) {
521
527
  mkdirSync(routesPath, { recursive: true });
522
528
  }
523
- saveRoutes({ step, folderPath: routesPath });
529
+ saveRoutes({ step, folderPath: routesPath }, logger);
524
530
  }
525
531
  }
526
532
 
@@ -529,7 +535,7 @@ export async function saveRecording({ step, cucumberStep, codePage, projectDir,
529
535
  }
530
536
 
531
537
  if (step.isImplemented && step.shouldOverride) {
532
- let stepDef = stepsDefinitions.findMatchingStep(step.text);
538
+ const stepDef = stepsDefinitions.findMatchingStep(step.text);
533
539
  codePage = getCodePage(stepDef.file);
534
540
  } else {
535
541
  const isUtilStep = makeStepTextUnique(step, stepsDefinitions);
@@ -555,21 +561,20 @@ export async function saveRecording({ step, cucumberStep, codePage, projectDir,
555
561
  rmSync(routesPath, { recursive: true });
556
562
  }
557
563
  mkdirSync(routesPath, { recursive: true });
558
- saveRoutes({ step, folderPath: routesPath });
564
+ saveRoutes({ step, folderPath: routesPath }, logger);
559
565
  } else {
560
566
  if (existsSync(routesPath)) {
561
- // remove the folder
562
567
  try {
563
568
  rmSync(routesPath, { recursive: true });
564
569
  } catch (error) {
565
- //
570
+ logger.error(`Error removing temp routes folder: ${getErrorMessage(error)}`);
566
571
  }
567
572
  }
568
573
  routesPath = path.join(projectDir, "data", "routes");
569
574
  if (!existsSync(routesPath)) {
570
575
  mkdirSync(routesPath, { recursive: true });
571
576
  }
572
- saveRoutes({ step, folderPath: routesPath });
577
+ saveRoutes({ step, folderPath: routesPath }, logger);
573
578
  }
574
579
 
575
580
  cucumberStep.text = step.text;
@@ -639,7 +644,6 @@ export async function saveRecording({ step, cucumberStep, codePage, projectDir,
639
644
  const generateCodeResult = generateCode(recording, codePage, userData, projectDir, methodName);
640
645
  console.log("Generated code for step:", step.text);
641
646
  if (generateCodeResult.noCode === true) {
642
- logger.log("No code generated for step: " + step.text);
643
647
  return generateCodeResult.page;
644
648
  }
645
649
  codePage = generateCodeResult.page;
@@ -749,7 +753,7 @@ export const getCommandsForImplementedStep = (stepName, stepsDefinitions, stepPa
749
753
  const file = step?.file;
750
754
  const locatorsJson = getLocatorsJson(file);
751
755
  if (!step) {
752
- throw new Error("Step definition not found" + stepName);
756
+ throw new Error(`Step definition not found: ${stepName}`);
753
757
  }
754
758
  isImplemented = true;
755
759
  const { codeCommands, codePage, elements, parametersNames, error } =
@@ -833,7 +837,7 @@ export async function executeStep({ stepsDefinitions, cucumberStep, context, cod
833
837
  }
834
838
  }
835
839
 
836
- export async function updateStepDefinitions({ scenario, featureName, projectDir }) {
840
+ export async function updateStepDefinitions({ scenario, featureName, projectDir, logger }) {
837
841
  // set the candidate step definition file name
838
842
  // set the utils file path
839
843
  const utilsFilePath = path.join(projectDir, "features", "step_definitions", "utils.mjs");
@@ -867,32 +871,25 @@ export async function updateStepDefinitions({ scenario, featureName, projectDir
867
871
  if ((step.isImplemented && !step.shouldOverride) || step.commands.length === 0) {
868
872
  let routesPath = path.join(tmpdir(), `blinq_temp_routes`);
869
873
  if (process.env.TEMP_RUN === "true") {
870
- console.log("Save routes in temp folder for running:", routesPath);
871
874
  if (existsSync(routesPath)) {
872
- console.log("Removing existing temp_routes_folder:", routesPath);
873
875
  routesPath = path.join(tmpdir(), `blinq_temp_routes`);
874
876
  rmSync(routesPath, { recursive: true });
875
877
  }
876
878
  mkdirSync(routesPath, { recursive: true });
877
- console.log("Created temp_routes_folder:", routesPath);
878
- saveRoutes({ step, folderPath: routesPath });
879
+ saveRoutes({ step, folderPath: routesPath }, logger);
879
880
  } else {
880
- console.log("Saving routes in project directory:", projectDir);
881
881
  if (existsSync(routesPath)) {
882
- // remove the folder
883
882
  try {
884
883
  rmSync(routesPath, { recursive: true });
885
- console.log("Removed temp_routes_folder:", routesPath);
886
884
  } catch (error) {
887
- console.error("Error removing temp_routes folder", error);
885
+ logger.error(`Error removing temp routes folder: ${getErrorMessage(error)}`);
888
886
  }
889
887
  }
890
888
  routesPath = path.join(projectDir, "data", "routes");
891
- console.log("Saving routes to:", routesPath);
892
889
  if (!existsSync(routesPath)) {
893
890
  mkdirSync(routesPath, { recursive: true });
894
891
  }
895
- saveRoutes({ step, folderPath: routesPath });
892
+ saveRoutes({ step, folderPath: routesPath }, logger);
896
893
  }
897
894
  if (step.commands && Array.isArray(step.commands)) {
898
895
  step.commands = step.commands.map((cmd) => toRecordingStep(cmd, scenario.parametersMap));
@@ -902,7 +899,6 @@ export async function updateStepDefinitions({ scenario, featureName, projectDir
902
899
  const cucumberStep = getCucumberStep({ step });
903
900
  const pageName = generatePageName(step.startFrame?.url ?? "default");
904
901
  const stepDefsFilePath = locateDefinitionPath(featureFolder, pageName);
905
- // path.join(stepDefinitionFolderPath, pageName + "_page.mjs");
906
902
  let codePage = getCodePage(stepDefsFilePath);
907
903
  codePage = await saveRecording({
908
904
  step,
@@ -923,7 +919,7 @@ export async function updateStepDefinitions({ scenario, featureName, projectDir
923
919
  writeFileSync(utilsFilePath, utilsContent, "utf8");
924
920
  }
925
921
 
926
- export function saveRoutes({ step, folderPath }) {
922
+ export function saveRoutes({ step, folderPath }, logger) {
927
923
  const routeItems = step.routeItems;
928
924
  if (!routeItems || routeItems.length === 0) {
929
925
  return;
@@ -946,21 +942,18 @@ export function saveRoutes({ step, folderPath }) {
946
942
  };
947
943
  });
948
944
 
949
- const routesFilePath = path.join(folderPath, stepNameHash + ".json");
950
- console.log("Routes file path:", routesFilePath);
945
+ const routesFilePath = path.join(folderPath, `${stepNameHash}.json`);
951
946
  const routesData = {
952
947
  template,
953
948
  routes: routeItemsWithFilters,
954
949
  };
955
- console.log("Routes data to save:", routesData);
956
950
 
957
951
  if (!existsSync(folderPath)) {
958
952
  mkdirSync(folderPath, { recursive: true });
959
953
  }
960
954
  try {
961
955
  writeFileSync(routesFilePath, JSON.stringify(routesData, null, 2), "utf8");
962
- console.log("Saved routes to", routesFilePath);
963
956
  } catch (error) {
964
- console.error("Failed to save routes to", routesFilePath, "Error:", error);
957
+ logger.error(`Error saving routes to ${routesFilePath}: ${getErrorMessage(error)}`);
965
958
  }
966
959
  }
@@ -1,8 +1,9 @@
1
- import { existsSync, readFileSync, writeFileSync } from "fs";
2
- import path from "path";
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import path from "node:path";
3
3
  import { getDefaultPrettierConfig } from "../code_cleanup/utils.js";
4
4
  import prettier from "prettier";
5
- export function containsScenario({ featureFileContent, scenarioName }) {
5
+
6
+ function containsScenario({ featureFileContent, scenarioName }) {
6
7
  const lines = featureFileContent.split("\n");
7
8
  for (const line of lines) {
8
9
  const trimmedLine = line.trim();
@@ -14,7 +15,7 @@ export function containsScenario({ featureFileContent, scenarioName }) {
14
15
  }
15
16
  }
16
17
 
17
- export function testStringForRegex(text) {
18
+ function testStringForRegex(text) {
18
19
  const regexEndPattern = /\/([gimuy]*)$/;
19
20
  if (text.startsWith("/")) {
20
21
  const match = regexEndPattern.test(text);
@@ -31,7 +32,7 @@ export function testStringForRegex(text) {
31
32
  return false;
32
33
  }
33
34
 
34
- const escapeNonPrintables = (text) => {
35
+ function escapeNonPrintables(text) {
35
36
  const t = text.replace(/\n/g, "\\n").replace(/\t/g, "\\t"); // .replace(/\|/g, "\\|");
36
37
  let result = "";
37
38
  // replace \ with \\ and | with \|
@@ -60,8 +61,9 @@ const escapeNonPrintables = (text) => {
60
61
  }
61
62
  }
62
63
  return result;
63
- };
64
- export function getCommandContent(command) {
64
+ }
65
+
66
+ function getCommandContent(command) {
65
67
  switch (command.type) {
66
68
  case "click_element": {
67
69
  return `${command.count === 2 ? "Double click" : "Click"} on ${escapeNonPrintables(command.element.name)}`;
@@ -108,15 +110,15 @@ export function getCommandContent(command) {
108
110
  }
109
111
  }
110
112
 
111
- export function getExamplesContent(parametersMap, datasets) {
113
+ function getExamplesContent(parametersMap, datasets) {
112
114
  if (datasets && datasets.length > 0) {
113
- let result = ''
115
+ let result = "";
114
116
  const keys = Object.keys(parametersMap);
115
117
  result += "\t\tExamples:\n";
116
118
 
117
119
  result += `\t\t| ${keys.join(" | ")} |\n`;
118
120
  for (const dataset of datasets) {
119
- result += `\t\t| ${dataset.data.map(d => escapeNonPrintables(d.value)).join(" | ")} |\n`;
121
+ result += `\t\t| ${dataset.data.map((d) => escapeNonPrintables(d.value)).join(" | ")} |\n`;
120
122
  }
121
123
  return result;
122
124
  }
@@ -155,19 +157,19 @@ function getTagsContent(scenario, featureFileObject) {
155
157
  return tagsContent;
156
158
  }
157
159
 
158
- export function getScenarioContent({ scenario }, featureFileObject) {
160
+ function getScenarioContent({ scenario }, featureFileObject) {
159
161
  const prametersMap = scenario.parametersMap ?? {};
160
162
  const isParmatersMapEmpty = Object.keys(prametersMap).length === 0;
161
163
  let scenarioContent = isParmatersMapEmpty ? `Scenario: ${scenario.name}\n` : `Scenario Outline: ${scenario.name}\n`;
162
164
 
163
- let tagsContent = getTagsContent(scenario, featureFileObject);
165
+ const tagsContent = getTagsContent(scenario, featureFileObject);
164
166
 
165
- scenarioContent = "\t" + tagsContent + "\n" + scenarioContent;
167
+ scenarioContent = `\t${tagsContent}\n${scenarioContent}`;
166
168
 
167
169
  for (const step of scenario.steps) {
168
170
  const commands = step.commands ?? [];
169
- let commentContents = commands.map(getCommandContent).map(escapeNonPrintables);
170
- let commentContent = commentContents.filter((content) => content.length > 0).join(", ");
171
+ const commentContents = commands.map(getCommandContent).map(escapeNonPrintables);
172
+ const commentContent = commentContents.filter((content) => content.length > 0).join(", ");
171
173
 
172
174
  if (commentContent) {
173
175
  scenarioContent += `\t# ${commentContent}\n`;
@@ -179,14 +181,15 @@ export function getScenarioContent({ scenario }, featureFileObject) {
179
181
  }
180
182
  return scenarioContent;
181
183
  }
182
- export const escapeString = (str) => {
184
+
185
+ function escapeString(str) {
183
186
  // Step 1: Replace all literal newline characters with a temporary placeholder
184
187
  const placeholder = "\\n";
185
188
  str = str.replace(/\n/g, placeholder);
186
189
  return str;
187
- };
190
+ }
188
191
 
189
- const GherkinToObject = (gherkin) => {
192
+ function GherkinToObject(gherkin) {
190
193
  const obj = {
191
194
  featureName: "",
192
195
  scenarios: [],
@@ -222,7 +225,7 @@ const GherkinToObject = (gherkin) => {
222
225
  }
223
226
 
224
227
  const getScenario = () => {
225
- let scenario = {
228
+ const scenario = {
226
229
  name: "",
227
230
  tags: [],
228
231
  steps: [],
@@ -299,7 +302,7 @@ const GherkinToObject = (gherkin) => {
299
302
  skipEmptyLines();
300
303
  }
301
304
  return obj;
302
- };
305
+ }
303
306
 
304
307
  // remove lines starting with "Scenario:" or "Scenario Outline:" that contain the scenario name until the next scenario and then append the new scenario content
305
308
  // assumes that there are no multiple scenarios with the same name and having comments and tags in each scenario
@@ -333,14 +336,14 @@ function updateExistingScenario({
333
336
  continue;
334
337
  }
335
338
 
336
- let scenarioHeader = `${scenario.hasParams ? "Scenario Outline" : "Scenario"}: ${scenario.name}`;
339
+ const scenarioHeader = `${scenario.hasParams ? "Scenario Outline" : "Scenario"}: ${scenario.name}`;
337
340
  let tagsLine;
338
341
 
339
342
  if (scenario.tags?.length > 0) {
340
343
  tagsLine = scenario.tags.map((t) => `@${t}`).join(" ");
341
344
  }
342
345
 
343
- if (tagsLine) results.push("\t" + tagsLine);
346
+ if (tagsLine) results.push(`\t${tagsLine}`);
344
347
  results.push(`\t${scenarioHeader}`);
345
348
 
346
349
  for (const step of scenario.steps) {
@@ -359,8 +362,8 @@ function updateExistingScenario({
359
362
  return results.join("\n");
360
363
  }
361
364
 
362
- export async function updateFeatureFile({ featureName, scenario, override, projectDir }) {
363
- const featureFilePath = path.join(projectDir, "features", featureName + ".feature");
365
+ async function updateFeatureFile({ featureName, scenario, override, projectDir, logger }) {
366
+ const featureFilePath = path.join(projectDir, "features", `${featureName}.feature`);
364
367
  const isFeatureFileExists = existsSync(featureFilePath);
365
368
  const scenarioContent = getScenarioContent(
366
369
  { scenario },
@@ -391,13 +394,13 @@ export async function updateFeatureFile({ featureName, scenario, override, proje
391
394
  plugins: ["prettier-plugin-gherkin"],
392
395
  });
393
396
  } catch (error) {
394
- console.error("Error formatting feature file content with Prettier:", error);
397
+ logger.error("Error formatting feature file content with Prettier:", error);
395
398
  }
396
399
  writeFileSync(featureFilePath, updatedFeatureFileContent);
397
400
  return;
398
401
  }
399
402
  }
400
- let updatedFeatureFileContent = featureFileContent + "\n" + scenarioContent;
403
+ let updatedFeatureFileContent = `${featureFileContent}\n${scenarioContent}`;
401
404
  try {
402
405
  updatedFeatureFileContent = await prettier.format(updatedFeatureFileContent, {
403
406
  ...prettierConfig,
@@ -405,7 +408,7 @@ export async function updateFeatureFile({ featureName, scenario, override, proje
405
408
  plugins: ["prettier-plugin-gherkin"],
406
409
  });
407
410
  } catch (error) {
408
- console.error("Error formatting feature file content with Prettier:", error);
411
+ logger.error("Error formatting feature file content with Prettier:", error);
409
412
  }
410
413
  writeFileSync(featureFilePath, updatedFeatureFileContent);
411
414
  } else {
@@ -417,8 +420,22 @@ export async function updateFeatureFile({ featureName, scenario, override, proje
417
420
  plugins: ["prettier-plugin-gherkin"],
418
421
  });
419
422
  } catch (error) {
420
- console.error("Error formatting feature file content with Prettier:", error);
423
+ logger.error("Error formatting feature file content with Prettier:", error);
421
424
  }
422
425
  writeFileSync(featureFilePath, featureFileContent);
423
426
  }
424
427
  }
428
+
429
+ export {
430
+ containsScenario,
431
+ testStringForRegex,
432
+ escapeNonPrintables,
433
+ getCommandContent,
434
+ getExamplesContent,
435
+ getTagsContent,
436
+ getScenarioContent,
437
+ escapeString,
438
+ GherkinToObject,
439
+ updateExistingScenario,
440
+ updateFeatureFile,
441
+ };
@@ -0,0 +1,21 @@
1
+ import path from "node:path";
2
+ import os from "node:os";
3
+ function getAppDataDir(project_id) {
4
+ if (process.env.BLINQ_APPDATA_DIR) {
5
+ return path.join(process.env.BLINQ_APPDATA_DIR, "blinq.io", project_id);
6
+ }
7
+ let appDataDir;
8
+ switch (process.platform) {
9
+ case "win32":
10
+ appDataDir = path.join(process.env.APPDATA, "blinq.io", project_id);
11
+ break;
12
+ case "darwin":
13
+ appDataDir = path.join(os.homedir(), "Library", "Application Support", "blinq.io", project_id);
14
+ break;
15
+ default:
16
+ appDataDir = path.join(os.homedir(), ".config", "blinq.io", project_id);
17
+ break;
18
+ }
19
+ return appDataDir;
20
+ }
21
+ export { getAppDataDir };
@@ -1,3 +1,19 @@
1
+ function getErrorMessage(err) {
2
+ if (typeof err === "string") {
3
+ return err;
4
+ }
5
+ else if (err instanceof Error) {
6
+ return err.message;
7
+ }
8
+ else {
9
+ try {
10
+ return JSON.stringify(err);
11
+ }
12
+ catch {
13
+ return String(err);
14
+ }
15
+ }
16
+ }
1
17
  /**
2
18
  * SocketLogger - Singleton for structured socket-based logging.
3
19
  *
@@ -10,8 +26,8 @@
10
26
  export class SocketLogger {
11
27
  static instance;
12
28
  socket = null;
13
- defaultContext = "";
14
- defaultEventName = "recorder.log";
29
+ defaultContext = "BVTRecorder";
30
+ defaultEventName = "BVTRecorder.log";
15
31
  constructor() { }
16
32
  static getInstance() {
17
33
  if (!SocketLogger.instance) {
@@ -24,7 +40,7 @@ export class SocketLogger {
24
40
  this.defaultContext = opts?.context || "";
25
41
  this.defaultEventName = opts?.eventName || "recorder.log";
26
42
  }
27
- log(level, message, extra, eventName, context) {
43
+ log(level, message, extra, context) {
28
44
  if (!this.socket || typeof this.socket.emit !== "function")
29
45
  return;
30
46
  const data = typeof message === "object" ? message : { message };
@@ -32,39 +48,47 @@ export class SocketLogger {
32
48
  try {
33
49
  dataSize = Buffer.byteLength(JSON.stringify(data || ""), "utf8");
34
50
  }
35
- catch (e) {
51
+ catch {
36
52
  dataSize = -1;
37
53
  }
38
54
  const eventPayload = {
39
55
  level,
40
56
  context: context || this.defaultContext,
41
- data: JSON.stringify(data),
57
+ data: JSON.stringify({
58
+ ...data,
59
+ errorMessage: level === "error" && data ? getErrorMessage(data) : undefined,
60
+ }),
42
61
  timestamp: new Date().toISOString(),
43
62
  dataSize,
44
63
  ...extra,
45
64
  };
46
65
  try {
47
66
  if (this.socket) {
48
- this.socket.emit(eventName || this.defaultEventName, eventPayload);
67
+ this.socket.emit(this.defaultEventName, eventPayload);
49
68
  }
69
+ console.log(`${context ?? this.defaultContext} [${level.toUpperCase()}]:`, {
70
+ ...data,
71
+ ...extra,
72
+ });
50
73
  }
51
74
  catch (e) {
52
75
  console.error("Socket logging error:", e);
53
76
  console.log("Socket event payload:", eventPayload);
54
77
  }
55
78
  }
56
- info(msg, ext) {
57
- this.log("info", msg, ext);
79
+ info(msg, ext, ctx) {
80
+ this.log("info", msg, ext, ctx);
58
81
  }
59
- warn(msg, ext) {
60
- this.log("warn", msg, ext);
82
+ warn(msg, ext, ctx) {
83
+ this.log("warn", msg, ext, ctx);
61
84
  }
62
- debug(msg, ext) {
63
- this.log("debug", msg, ext);
85
+ debug(msg, ext, ctx) {
86
+ this.log("debug", msg, ext, ctx);
64
87
  }
65
- error(msg, ext) {
66
- this.log("error", msg, ext);
88
+ error(msg, ext, ctx) {
89
+ this.log("error", msg, ext, ctx);
67
90
  }
68
91
  }
69
92
  const socketLoggerInstance = SocketLogger.getInstance();
70
93
  export default socketLoggerInstance;
94
+ export { getErrorMessage };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dev-blinq/cucumber_client",
3
- "version": "1.0.1691-dev",
3
+ "version": "1.0.1693-dev",
4
4
  "description": " ",
5
5
  "main": "bin/index.js",
6
6
  "types": "bin/index.d.ts",
@@ -14,6 +14,8 @@
14
14
  "tests_prod": "rm -rf results.json && cross-env NODE_ENV_BLINQ=prod TOKEN=xxx npx mocha --parallel --jobs=10 ./tests",
15
15
  "tests": "node ./multi_test_runner.js",
16
16
  "lint": "eslint ./src/**/*.js",
17
+ "test:unit": "vitest run",
18
+ "test:unit:watch": "vitest watch",
17
19
  "clean_old": "rimraf -g build1 && rimraf -g types1",
18
20
  "clean": "rimraf -g build && rimraf -g types",
19
21
  "build_old": "npm run clean_old && npm run pack_old",
@@ -70,6 +72,8 @@
70
72
  "readline-sync": "^1.4.10",
71
73
  "ts-node": "^10.9.2",
72
74
  "tsup": "^8.5.0",
73
- "typescript": "^5.9.2"
75
+ "typescript": "^5.9.2",
76
+ "vite-tsconfig-paths": "^6.0.4",
77
+ "vitest": "^2.1.4"
74
78
  }
75
79
  }
@@ -1,23 +0,0 @@
1
- import path from "path";
2
- import os from "os";
3
-
4
- export const getAppDataDir = (project_id) => {
5
- if (process.env.BLINQ_APPDATA_DIR) {
6
- return path.join(process.env.BLINQ_APPDATA_DIR, "blinq.io", project_id);
7
- }
8
-
9
- let appDataDir;
10
-
11
- switch (process.platform) {
12
- case "win32":
13
- appDataDir = path.join(process.env.APPDATA, "blinq.io", project_id);
14
- break;
15
- case "darwin":
16
- appDataDir = path.join(os.homedir(), "Library", "Application Support", "blinq.io", project_id);
17
- break;
18
- default:
19
- appDataDir = path.join(os.homedir(), ".config", "blinq.io", project_id);
20
- break;
21
- }
22
- return appDataDir;
23
- };