@fragno-dev/cli 0.2.1 → 0.2.3

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
+ {"version":3,"file":"serve-eh3Tpjhc.js","names":["allFragments: FragnoInstantiatedFragment<\n [],\n unknown,\n Record<string, unknown>,\n Record<string, unknown>,\n Record<string, unknown>,\n unknown,\n Record<string, unknown>\n >[]"],"sources":["../src/commands/serve.ts"],"sourcesContent":["import { createServer, type Server } from \"node:http\";\nimport { resolve, relative } from \"node:path\";\n\nimport { define } from \"gunshi\";\n\nimport type { FragnoInstantiatedFragment } from \"@fragno-dev/core\";\nimport { toNodeHandler } from \"@fragno-dev/node\";\n\nimport { findFragnoFragments } from \"../utils/find-fragno-databases\";\nimport { loadConfig } from \"../utils/load-config\";\n\nexport const serveCommand = define({\n name: \"serve\",\n description: \"Start a local HTTP server to serve one or more Fragno fragments\",\n args: {\n port: {\n type: \"number\",\n short: \"p\",\n description: \"Port to listen on\",\n default: 8080,\n },\n host: {\n type: \"string\",\n short: \"H\",\n description: \"Host to bind to\",\n default: \"localhost\",\n },\n },\n run: async (ctx) => {\n const targets = ctx.positionals;\n const port = ctx.values.port ?? 8080;\n const host = ctx.values.host ?? \"localhost\";\n const cwd = process.cwd();\n\n if (targets.length === 0) {\n throw new Error(\n \"No fragment files specified.\\n\\n\" +\n \"Usage: fragno-cli serve <fragment-file> [fragment-file...]\\n\\n\" +\n \"Example: fragno-cli serve ./src/my-fragment.ts\",\n );\n }\n\n const targetPaths = targets.map((target) => resolve(cwd, target));\n\n // Import all fragment files and find instantiated fragments\n const allFragments: FragnoInstantiatedFragment<\n [],\n unknown,\n Record<string, unknown>,\n Record<string, unknown>,\n Record<string, unknown>,\n unknown,\n Record<string, unknown>\n >[] = [];\n\n for (const targetPath of targetPaths) {\n const relativePath = relative(cwd, targetPath);\n const config = await loadConfig(targetPath);\n const fragments = findFragnoFragments(config);\n\n if (fragments.length === 0) {\n console.warn(\n `Warning: No instantiated fragments found in ${relativePath}.\\n` +\n `Make sure you export an instantiated fragment (e.g., the return value of createMyFragment()).\\n`,\n );\n continue;\n }\n\n allFragments.push(...fragments);\n console.log(\n ` Found ${fragments.length} fragment(s) in ${relativePath}: ${fragments.map((f) => f.name).join(\", \")}`,\n );\n }\n\n if (allFragments.length === 0) {\n throw new Error(\n \"No instantiated fragments found in any of the specified files.\\n\" +\n \"Make sure your files export instantiated fragments.\",\n );\n }\n\n // Build handlers mapped by mountRoute\n const handlers = allFragments.map((fragment) => ({\n mountRoute: fragment.mountRoute,\n handler: toNodeHandler(fragment.handler.bind(fragment)),\n fragment,\n }));\n\n const server = createServer((req, res) => {\n const url = req.url ?? \"\";\n\n for (const { mountRoute, handler } of handlers) {\n if (url.startsWith(mountRoute)) {\n return handler(req, res);\n }\n }\n\n res.statusCode = 404;\n res.setHeader(\"Content-Type\", \"application/json\");\n res.end(\n JSON.stringify({\n error: \"Not Found\",\n availableRoutes: handlers.map((h) => h.mountRoute),\n }),\n );\n });\n\n server.listen(port, host, () => {\n const hostStr = addressToString(server);\n console.log(`\\nFragno server is running on: ${hostStr}\\n`);\n\n for (const { fragment } of handlers) {\n console.log(`Fragment: ${fragment.name}`);\n console.log(` Mount: ${hostStr}${fragment.mountRoute}`);\n\n const routes = fragment.routes as unknown as { method: string; path: string }[];\n if (routes.length > 0) {\n console.log(\" Routes:\");\n for (const route of routes) {\n console.log(` ${route.method} ${fragment.mountRoute}${route.path}`);\n }\n }\n\n console.log(\"\");\n }\n });\n },\n});\n\nfunction addressToString(server: Server, protocol: \"http\" | \"https\" = \"http\"): string {\n const addr = server.address();\n if (!addr) {\n throw new Error(\"Address invalid\");\n }\n\n if (typeof addr === \"string\") {\n return addr;\n }\n\n let host = addr.address;\n\n if (host === \"::\" || host === \"0.0.0.0\") {\n host = \"localhost\";\n }\n\n if (addr.family === \"IPv6\" && host !== \"localhost\") {\n host = `[${host}]`;\n }\n\n return `${protocol}://${host}:${addr.port}`;\n}\n"],"mappings":";;;;;;;AAWA,MAAa,eAAe,OAAO;CACjC,MAAM;CACN,aAAa;CACb,MAAM;EACJ,MAAM;GACJ,MAAM;GACN,OAAO;GACP,aAAa;GACb,SAAS;GACV;EACD,MAAM;GACJ,MAAM;GACN,OAAO;GACP,aAAa;GACb,SAAS;GACV;EACF;CACD,KAAK,OAAO,QAAQ;EAClB,MAAM,UAAU,IAAI;EACpB,MAAM,OAAO,IAAI,OAAO,QAAQ;EAChC,MAAM,OAAO,IAAI,OAAO,QAAQ;EAChC,MAAM,MAAM,QAAQ,KAAK;AAEzB,MAAI,QAAQ,WAAW,EACrB,OAAM,IAAI,MACR,+IAGD;EAGH,MAAM,cAAc,QAAQ,KAAK,WAAW,QAAQ,KAAK,OAAO,CAAC;EAGjE,MAAMA,eAQA,EAAE;AAER,OAAK,MAAM,cAAc,aAAa;GACpC,MAAM,eAAe,SAAS,KAAK,WAAW;GAE9C,MAAM,YAAY,oBADH,MAAM,WAAW,WAAW,CACE;AAE7C,OAAI,UAAU,WAAW,GAAG;AAC1B,YAAQ,KACN,+CAA+C,aAAa,oGAE7D;AACD;;AAGF,gBAAa,KAAK,GAAG,UAAU;AAC/B,WAAQ,IACN,WAAW,UAAU,OAAO,kBAAkB,aAAa,IAAI,UAAU,KAAK,MAAM,EAAE,KAAK,CAAC,KAAK,KAAK,GACvG;;AAGH,MAAI,aAAa,WAAW,EAC1B,OAAM,IAAI,MACR,sHAED;EAIH,MAAM,WAAW,aAAa,KAAK,cAAc;GAC/C,YAAY,SAAS;GACrB,SAAS,cAAc,SAAS,QAAQ,KAAK,SAAS,CAAC;GACvD;GACD,EAAE;EAEH,MAAM,SAAS,cAAc,KAAK,QAAQ;GACxC,MAAM,MAAM,IAAI,OAAO;AAEvB,QAAK,MAAM,EAAE,YAAY,aAAa,SACpC,KAAI,IAAI,WAAW,WAAW,CAC5B,QAAO,QAAQ,KAAK,IAAI;AAI5B,OAAI,aAAa;AACjB,OAAI,UAAU,gBAAgB,mBAAmB;AACjD,OAAI,IACF,KAAK,UAAU;IACb,OAAO;IACP,iBAAiB,SAAS,KAAK,MAAM,EAAE,WAAW;IACnD,CAAC,CACH;IACD;AAEF,SAAO,OAAO,MAAM,YAAY;GAC9B,MAAM,UAAU,gBAAgB,OAAO;AACvC,WAAQ,IAAI,kCAAkC,QAAQ,IAAI;AAE1D,QAAK,MAAM,EAAE,cAAc,UAAU;AACnC,YAAQ,IAAI,aAAa,SAAS,OAAO;AACzC,YAAQ,IAAI,YAAY,UAAU,SAAS,aAAa;IAExD,MAAM,SAAS,SAAS;AACxB,QAAI,OAAO,SAAS,GAAG;AACrB,aAAQ,IAAI,YAAY;AACxB,UAAK,MAAM,SAAS,OAClB,SAAQ,IAAI,OAAO,MAAM,OAAO,GAAG,SAAS,aAAa,MAAM,OAAO;;AAI1E,YAAQ,IAAI,GAAG;;IAEjB;;CAEL,CAAC;AAEF,SAAS,gBAAgB,QAAgB,WAA6B,QAAgB;CACpF,MAAM,OAAO,OAAO,SAAS;AAC7B,KAAI,CAAC,KACH,OAAM,IAAI,MAAM,kBAAkB;AAGpC,KAAI,OAAO,SAAS,SAClB,QAAO;CAGT,IAAI,OAAO,KAAK;AAEhB,KAAI,SAAS,QAAQ,SAAS,UAC5B,QAAO;AAGT,KAAI,KAAK,WAAW,UAAU,SAAS,YACrC,QAAO,IAAI,KAAK;AAGlB,QAAO,GAAG,SAAS,KAAK,KAAK,GAAG,KAAK"}
package/package.json CHANGED
@@ -1,50 +1,48 @@
1
1
  {
2
2
  "name": "@fragno-dev/cli",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
+ "homepage": "https://fragno.dev",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/rejot-dev/fragno.git",
9
+ "directory": "apps/fragno-cli"
10
+ },
11
+ "bin": {
12
+ "fragno-cli": "./bin/run.js"
13
+ },
14
+ "type": "module",
15
+ "main": "./dist/cli.js",
16
+ "module": "./dist/cli.js",
17
+ "types": "./dist/cli.d.ts",
4
18
  "exports": {
5
19
  ".": {
6
- "development": "./src/cli.ts",
7
20
  "types": "./dist/cli.d.ts",
8
21
  "default": "./dist/cli.js"
9
22
  }
10
23
  },
11
- "type": "module",
12
- "bin": {
13
- "fragno-cli": "./bin/run.js"
14
- },
15
- "engines": {
16
- "node": ">=22"
24
+ "dependencies": {
25
+ "@clack/prompts": "^0.11.0",
26
+ "c12": "^3.3.3",
27
+ "gunshi": "^0.26.3",
28
+ "jsonc-parser": "^3.3.1",
29
+ "@fragno-dev/core": "0.2.2",
30
+ "@fragno-dev/db": "0.4.1",
31
+ "@fragno-dev/node": "0.0.9"
17
32
  },
18
33
  "devDependencies": {
19
34
  "@types/node": "^22.19.7",
20
- "@vitest/coverage-istanbul": "^3.2.4",
35
+ "@vitest/coverage-istanbul": "^4.1.0",
21
36
  "@fragno-private/typescript-config": "0.0.1",
22
37
  "@fragno-private/vitest-config": "0.0.0"
23
38
  },
24
- "dependencies": {
25
- "@clack/prompts": "^0.11.0",
26
- "c12": "^3.3.3",
27
- "gunshi": "^0.26.3",
28
- "marked": "^15.0.12",
29
- "marked-terminal": "^7.3.0",
30
- "@fragno-dev/core": "0.2.0",
31
- "@fragno-dev/corpus": "0.0.7",
32
- "@fragno-dev/db": "0.3.0",
33
- "@fragno-dev/node": "0.0.8"
34
- },
35
- "main": "./dist/cli.js",
36
- "module": "./dist/cli.js",
37
- "types": "./dist/cli.d.ts",
38
- "repository": {
39
- "type": "git",
40
- "url": "https://github.com/rejot-dev/fragno.git",
41
- "directory": "apps/fragno-cli"
39
+ "engines": {
40
+ "node": ">=22"
42
41
  },
43
- "homepage": "https://fragno.dev",
44
- "license": "MIT",
45
42
  "scripts": {
46
43
  "build": "tsdown",
47
44
  "build:watch": "tsdown --watch",
48
- "types:check": "tsc --noEmit"
45
+ "types:check": "tsc --noEmit",
46
+ "test": "vitest run"
49
47
  }
50
48
  }
package/src/cli.ts CHANGED
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ import { readFileSync } from "node:fs";
4
+ import { dirname, join } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+
3
7
  import { cli, define } from "gunshi";
8
+
4
9
  import { generateCommand } from "./commands/db/generate.js";
5
- import { migrateCommand } from "./commands/db/migrate.js";
6
10
  import { infoCommand } from "./commands/db/info.js";
11
+ import { migrateCommand } from "./commands/db/migrate.js";
7
12
  import { searchCommand } from "./commands/search.js";
8
- import { corpusCommand } from "./commands/corpus.js";
9
- import { serveCommand } from "./commands/serve.js";
10
- import { readFileSync } from "node:fs";
11
- import { fileURLToPath } from "node:url";
12
- import { dirname, join } from "node:path";
13
13
 
14
14
  const __dirname = dirname(fileURLToPath(import.meta.url));
15
15
  const packageJson = JSON.parse(readFileSync(join(__dirname, "../package.json"), "utf-8"));
@@ -44,14 +44,9 @@ export async function run() {
44
44
  name: "fragno-cli search",
45
45
  version,
46
46
  });
47
- } else if (args[0] === "corpus") {
48
- // Run corpus command directly
49
- await cli(args.slice(1), corpusCommand, {
50
- name: "fragno-cli corpus",
51
- version,
52
- });
53
47
  } else if (args[0] === "serve") {
54
48
  // Run serve command directly
49
+ const { serveCommand } = await import("./commands/serve.js");
55
50
  await cli(args.slice(1), serveCommand, {
56
51
  name: "fragno-cli serve",
57
52
  version,
@@ -112,13 +107,11 @@ export async function run() {
112
107
  console.log(" serve Start a local HTTP server to serve fragments");
113
108
  console.log(" db Database management commands");
114
109
  console.log(" search Search the Fragno documentation");
115
- console.log(" corpus View code examples and documentation for Fragno");
116
110
  console.log("");
117
111
  console.log("For more info, run any command with the `--help` flag:");
118
112
  console.log(" fragno-cli serve --help");
119
113
  console.log(" fragno-cli db --help");
120
114
  console.log(" fragno-cli search --help");
121
- console.log(" fragno-cli corpus --help");
122
115
  console.log("");
123
116
  console.log("OPTIONS:");
124
117
  console.log(" -h, --help Display this help message");
@@ -142,4 +135,4 @@ if (import.meta.main) {
142
135
  await run();
143
136
  }
144
137
 
145
- export { generateCommand, migrateCommand, infoCommand, searchCommand, corpusCommand, serveCommand };
138
+ export { generateCommand, migrateCommand, infoCommand, searchCommand };
@@ -1,7 +1,9 @@
1
1
  import { writeFile, mkdir } from "node:fs/promises";
2
2
  import { resolve, dirname } from "node:path";
3
- import { define } from "gunshi";
3
+
4
4
  import { generateSchemaArtifacts } from "@fragno-dev/db/generation-engine";
5
+ import { define } from "gunshi";
6
+
5
7
  import { importFragmentFiles } from "../../utils/find-fragno-databases";
6
8
 
7
9
  // Define the db generate command with type safety
@@ -1,5 +1,7 @@
1
1
  import { resolve } from "node:path";
2
+
2
3
  import { define } from "gunshi";
4
+
3
5
  import { importFragmentFiles } from "../../utils/find-fragno-databases";
4
6
 
5
7
  export const infoCommand = define({
@@ -1,7 +1,9 @@
1
1
  import { resolve } from "node:path";
2
+
3
+ import { executeMigrations, type ExecuteMigrationResult } from "@fragno-dev/db/generation-engine";
2
4
  import { define } from "gunshi";
5
+
3
6
  import { importFragmentFiles } from "../../utils/find-fragno-databases";
4
- import { executeMigrations, type ExecuteMigrationResult } from "@fragno-dev/db/generation-engine";
5
7
 
6
8
  export const migrateCommand = define({
7
9
  name: "migrate",
@@ -1,4 +1,5 @@
1
1
  import { define } from "gunshi";
2
+
2
3
  import {
3
4
  mergeResultsByUrl,
4
5
  formatAsMarkdown,
@@ -1,10 +1,13 @@
1
1
  import { createServer, type Server } from "node:http";
2
2
  import { resolve, relative } from "node:path";
3
+
3
4
  import { define } from "gunshi";
4
- import { toNodeHandler } from "@fragno-dev/node";
5
+
5
6
  import type { FragnoInstantiatedFragment } from "@fragno-dev/core";
6
- import { loadConfig } from "../utils/load-config";
7
+ import { toNodeHandler } from "@fragno-dev/node";
8
+
7
9
  import { findFragnoFragments } from "../utils/find-fragno-databases";
10
+ import { loadConfig } from "../utils/load-config";
8
11
 
9
12
  export const serveCommand = define({
10
13
  name: "serve",
@@ -1,13 +1,16 @@
1
- import { isFragnoDatabase, type DatabaseAdapter, FragnoDatabase } from "@fragno-dev/db";
1
+ import { relative } from "node:path";
2
+
3
+ import { instantiatedFragmentFakeSymbol } from "@fragno-dev/core/internal/symbols";
2
4
  import {
3
5
  fragnoDatabaseAdapterNameFakeSymbol,
4
6
  fragnoDatabaseAdapterVersionFakeSymbol,
5
7
  } from "@fragno-dev/db/adapters";
6
8
  import type { AnySchema } from "@fragno-dev/db/schema";
7
- import { instantiatedFragmentFakeSymbol } from "@fragno-dev/core/internal/symbols";
9
+
8
10
  import { type FragnoInstantiatedFragment } from "@fragno-dev/core";
11
+ import { isFragnoDatabase, type DatabaseAdapter, FragnoDatabase } from "@fragno-dev/db";
12
+
9
13
  import { loadConfig } from "./load-config";
10
- import { relative } from "node:path";
11
14
 
12
15
  export async function importFragmentFile(path: string): Promise<Record<string, unknown>> {
13
16
  // Enable dry run mode for database schema extraction
@@ -201,13 +204,15 @@ export function findFragnoDatabases(
201
204
  const options = internal.options as Record<string, unknown>;
202
205
 
203
206
  // Check if this is a database fragment by looking for implicit database dependencies
204
- if (!deps["db"] || !deps["schema"]) {
207
+ if (!deps["schema"]) {
205
208
  continue;
206
209
  }
207
210
 
208
211
  const schema = deps["schema"] as AnySchema;
209
- const namespace = deps["namespace"] as string;
210
- const databaseAdapter = options["databaseAdapter"] as DatabaseAdapter | undefined;
212
+ const namespace = deps["namespace"] as string | null;
213
+ const databaseAdapter =
214
+ (deps["databaseAdapter"] as DatabaseAdapter | undefined) ??
215
+ (options["databaseAdapter"] as DatabaseAdapter | undefined);
211
216
 
212
217
  if (!databaseAdapter) {
213
218
  console.warn(
@@ -1,18 +1,26 @@
1
1
  import { describe, it, expect } from "vitest";
2
- import { stripJsonComments, convertTsconfigPathsToJitiAlias } from "./load-config";
2
+
3
3
  import { resolve } from "node:path";
4
4
 
5
+ import { stripJsonComments, convertTsconfigPathsToJitiAlias } from "./load-config";
6
+
5
7
  describe("stripJsonComments", () => {
6
8
  it("should strip single-line comments", () => {
7
9
  const input = `{
8
10
  // This is a comment
9
11
  "key": "value"
10
12
  }`;
11
- const expected = `{
12
-
13
- "key": "value"
13
+ const result = stripJsonComments(input);
14
+ expect(() => JSON.parse(result)).not.toThrow();
15
+ expect(JSON.parse(result)).toEqual({ key: "value" });
16
+ });
17
+
18
+ it("does not strip double slashes in strings", () => {
19
+ const input = `{
20
+ "key": "https://example.com/foo",
21
+ "another": "value"
14
22
  }`;
15
- expect(stripJsonComments(input)).toBe(expected);
23
+ expect(stripJsonComments(input)).toBe(input);
16
24
  });
17
25
 
18
26
  it("should strip multiple single-line comments", () => {
@@ -22,13 +30,21 @@ describe("stripJsonComments", () => {
22
30
  // Second comment
23
31
  "key2": "value2"
24
32
  }`;
25
- const expected = `{
26
-
27
- "key1": "value1",
28
-
29
- "key2": "value2"
30
- }`;
31
- expect(stripJsonComments(input)).toBe(expected);
33
+ const result = stripJsonComments(input);
34
+ expect(() => JSON.parse(result)).not.toThrow();
35
+ expect(JSON.parse(result)).toEqual({ key1: "value1", key2: "value2" });
36
+ });
37
+
38
+ it("does not strip multi line comments chars in strings", () => {
39
+ const input = `{
40
+ "compilerOptions": {
41
+ "paths": {
42
+ "~/*": ["./src/*"]
43
+ }
44
+ },
45
+ "include": ["**/*.ts", "**/*.tsx"],
46
+ }`;
47
+ expect(stripJsonComments(input)).toBe(input);
32
48
  });
33
49
 
34
50
  it("should strip multi-line comments", () => {
@@ -37,11 +53,9 @@ describe("stripJsonComments", () => {
37
53
  multi-line comment */
38
54
  "key": "value"
39
55
  }`;
40
- const expected = `{
41
-
42
- "key": "value"
43
- }`;
44
- expect(stripJsonComments(input)).toBe(expected);
56
+ const result = stripJsonComments(input);
57
+ expect(() => JSON.parse(result)).not.toThrow();
58
+ expect(JSON.parse(result)).toEqual({ key: "value" });
45
59
  });
46
60
 
47
61
  it("should strip multiple multi-line comments", () => {
@@ -52,13 +66,9 @@ describe("stripJsonComments", () => {
52
66
  spanning lines */
53
67
  "key2": "value2"
54
68
  }`;
55
- const expected = `{
56
-
57
- "key1": "value1",
58
-
59
- "key2": "value2"
60
- }`;
61
- expect(stripJsonComments(input)).toBe(expected);
69
+ const result = stripJsonComments(input);
70
+ expect(() => JSON.parse(result)).not.toThrow();
71
+ expect(JSON.parse(result)).toEqual({ key1: "value1", key2: "value2" });
62
72
  });
63
73
 
64
74
  it("should strip both single-line and multi-line comments", () => {
@@ -69,13 +79,9 @@ describe("stripJsonComments", () => {
69
79
  comment */
70
80
  "key2": "value2" // Another single line
71
81
  }`;
72
- const expected = `{
73
-
74
- "key1": "value1",
75
-
76
- "key2": "value2"
77
- }`;
78
- expect(stripJsonComments(input)).toBe(expected);
82
+ const result = stripJsonComments(input);
83
+ expect(() => JSON.parse(result)).not.toThrow();
84
+ expect(JSON.parse(result)).toEqual({ key1: "value1", key2: "value2" });
79
85
  });
80
86
 
81
87
  it("should handle strings with comment-like content", () => {
@@ -83,12 +89,12 @@ describe("stripJsonComments", () => {
83
89
  "url": "https://example.com",
84
90
  "comment": "This // is not a comment"
85
91
  }`;
86
- // Note: This is a known limitation - the simple regex approach
87
- // will strip what looks like comments even inside strings
88
- // For tsconfig.json files this is typically fine since URLs/strings
89
- // with comment syntax are rare
90
92
  const result = stripJsonComments(input);
91
- expect(result).toContain('"url": "https:');
93
+ expect(() => JSON.parse(result)).not.toThrow();
94
+ expect(JSON.parse(result)).toEqual({
95
+ url: "https://example.com",
96
+ comment: "This // is not a comment",
97
+ });
92
98
  });
93
99
 
94
100
  it("should handle empty input", () => {
@@ -1,7 +1,9 @@
1
- import { loadConfig as c12LoadConfig } from "c12";
1
+ import { constants } from "node:fs";
2
2
  import { readFile, access } from "node:fs/promises";
3
3
  import { dirname, resolve, join } from "node:path";
4
- import { constants } from "node:fs";
4
+
5
+ import { loadConfig as c12LoadConfig } from "c12";
6
+ import { stripComments } from "jsonc-parser";
5
7
 
6
8
  /**
7
9
  * Checks if a file exists using async API.
@@ -37,13 +39,7 @@ async function findTsconfig(startPath: string): Promise<string | null> {
37
39
  * Strips comments from JSONC (JSON with Comments) content.
38
40
  */
39
41
  export function stripJsonComments(jsonc: string): string {
40
- // Remove single-line comments (// ...)
41
- let result = jsonc.replace(/\/\/[^\n]*/g, "");
42
-
43
- // Remove multi-line comments (/* ... */)
44
- result = result.replace(/\/\*[\s\S]*?\*\//g, "");
45
-
46
- return result;
42
+ return stripComments(jsonc);
47
43
  }
48
44
 
49
45
  /**
package/tsconfig.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "extends": "@fragno-private/typescript-config/tsconfig.base.json",
2
+ "extends": "@fragno-private/typescript-config/tsconfig.node.json",
3
3
  "compilerOptions": {
4
4
  "outDir": "./dist",
5
5
  "rootDir": ".",
package/vitest.config.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { defineConfig, mergeConfig } from "vitest/config";
2
+
2
3
  import { baseConfig } from "@fragno-private/vitest-config";
3
4
 
4
5
  export default defineConfig(