From 716c5533b2c0f53dbf38073f490a46e82b32fbe7 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Sirois Date: Tue, 30 Jun 2026 16:10:38 -0400 Subject: [PATCH 1/2] feat: emit func_name caller-symbol tag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `traceCaller()` already parses the V8 frame that holds the enclosing function/method symbol (e.g. `UserService.list`, `reactionsRepo.findFavorites`) — it was discarded by the regex that keeps only `path:line:col`. Capture it and emit it as a new `func_name` SQLCommenter tag. Unlike `file:line:col`, a symbol is edit-stable: it doesn't drift when code above the call site changes, which makes captured-query → source-method mapping reliable across revisions. `func_name` is the shared join key other adapters (e.g. postgres-tracked-pool) already emit. Capture-when-present, fall back to `file` alone: anonymous / `` / top-level frames (and minified builds) emit `file` only, never an empty tag. `traceCaller()` now returns `{ file, symbol? }`, threaded through the 0.4.0 per-query concurrency machinery unchanged — only the payload widened from a string. Applied to drizzle, mikroorm, and typeorm; READMEs gain the row. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../packages/sqlcommenter-drizzle/README.md | 1 + .../sqlcommenter-drizzle/src/index.ts | 52 ++++++-- .../test/func-name.spec.ts | 115 ++++++++++++++++++ .../packages/sqlcommenter-mikroorm/README.md | 1 + .../sqlcommenter-mikroorm/src/index.ts | 43 ++++++- .../test/driver-integration.spec.ts | 11 +- .../packages/sqlcommenter-typeorm/README.md | 1 + .../sqlcommenter-typeorm/src/index.ts | 43 ++++++- .../test/driver-integration.spec.ts | 17 ++- 9 files changed, 266 insertions(+), 18 deletions(-) create mode 100644 nodejs/sqlcommenter-nodejs/packages/sqlcommenter-drizzle/test/func-name.spec.ts diff --git a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-drizzle/README.md b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-drizzle/README.md index adc33703..940cf27f 100644 --- a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-drizzle/README.md +++ b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-drizzle/README.md @@ -10,6 +10,7 @@ Emits the following fields into the query: | ------------- | -------------------- | --------------------------------------------------------------- | | db_driver | Yes | The driver used to connect to the database. (Drizzle) | | file | Yes | The file that the query was executed in. | +| func_name | Yes, if named | The function/method that built the query. Omitted if anonymous. | | route | No | The route that the query was executed in. | | method | No | The http method for the request that the query was executed in. | | anything else | No | Any other information that the user wants to add to the query. | diff --git a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-drizzle/src/index.ts b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-drizzle/src/index.ts index d12557c5..6b4b99f2 100644 --- a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-drizzle/src/index.ts +++ b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-drizzle/src/index.ts @@ -21,7 +21,7 @@ type DriverSession = { prepareQuery: (query: unknown) => unknown }; // `prepareQuery` (`then`/`execute`/`prepare` -> `_prepare` -> `session.prepareQuery` runs with // no `await` in between). Because the window is synchronous, concurrent queries can never // interleave inside it, so each query reads exactly its own caller. -let currentCaller: string | undefined; +let currentCaller: CallerInfo | undefined; // Marks a query object whose `then`/`execute`/`prepare` have already been wrapped, so chained // rebuilds returning the same object aren't wrapped twice. @@ -48,7 +48,37 @@ function isValidCaller(line: string): boolean { // but its hard to parse that manually. Let future me deal with it const filepathRegex = /([^ (]*?:\d+:\d+)\)?$/; -export function traceCaller(): string | undefined { +/** The provenance captured from a single V8 stack frame. */ +export type CallerInfo = { + // The source location, `path:line:col`, resolved to the real project root. + file: string; + // The enclosing function/method symbol as V8 reports it (e.g. `UserService.list`, + // `reactionsRepo.findFavorites`). Absent for anonymous/top-level frames. Unlike `file`, + // a symbol is edit-stable — it doesn't drift when lines above the call site change. + symbol?: string; +}; + +/** + * Pulls the enclosing function/method symbol out of a V8 stack frame. Named frames look like + * ` at ()`; anonymous/top-level frames are ` at ` with no + * symbol to capture, so we return nothing and the caller falls back to `file` alone. + */ +function extractSymbol(frame: string): string | undefined { + const match = frame.match(/^\s*at (.+) \(/); + if (!match) { + return; + } + // V8 prefixes async frames with `async ` in some versions; the symbol is what follows. + const symbol = match[1].replace(/^async /, ""); + // Anonymous functions — including arrow-assigned methods that surface as + // `Object.` in bundled/minified builds — carry no stable name. + if (!symbol || symbol.includes("")) { + return; + } + return symbol; +} + +export function traceCaller(): CallerInfo | undefined { // we're not using the Error.capturaStackTrace because it doesn't play nicely // with stack traces that aren't full paths to a specific file. // eg: webpack:// or relative paths will produce no result at all so that's not usable @@ -66,7 +96,8 @@ export function traceCaller(): string | undefined { } const match = methodCaller.match(filepathRegex); if (match) { - return resolveFilePath(match[1]); + // The symbol comes from the same frame we already selected — no new frame-selection logic. + return { file: resolveFilePath(match[1]), symbol: extractSymbol(methodCaller) }; } } @@ -74,7 +105,7 @@ export function traceCaller(): string | undefined { * Wraps `then`/`execute`/`prepare` on a built query so that, while the query synchronously * reaches `prepareQuery`, its own build-time caller is the one published in `currentCaller`. */ -function tagExecutable(executable: any, caller: string) { +function tagExecutable(executable: any, caller: CallerInfo) { if (!executable || typeof executable !== "object" || executable[TAGGED]) { return; } @@ -102,7 +133,7 @@ function tagExecutable(executable: any, caller: string) { * Proxy so that whatever its methods return is run back through `handleResult` and the eventual * executable gets tagged with the caller captured at build time. */ -function wrapBuilder(builder: any, caller: string): unknown { +function wrapBuilder(builder: any, caller: CallerInfo): unknown { return new Proxy(builder, { get(target, prop, receiver) { const value = Reflect.get(target, prop, receiver); @@ -116,7 +147,7 @@ function wrapBuilder(builder: any, caller: string): unknown { }); } -function handleResult(result: any, caller: string): unknown { +function handleResult(result: any, caller: CallerInfo): unknown { if (!result || typeof result !== "object") { return result; } @@ -230,6 +261,7 @@ export function patchDrizzle( const WellKnownFields = { dbDriver: "db_driver", file: "file", + funcName: "func_name", route: "route", } as const; @@ -256,8 +288,12 @@ function patchSession(session: DriverSession) { const tags: [string, string][] = [[WellKnownFields.dbDriver, "drizzle"]]; // adding traceparent and tracestate pushW3CTraceContext(tags); - if (caller) { - tags.push([WellKnownFields.file, caller]); + if (caller?.file) { + tags.push([WellKnownFields.file, caller.file]); + } + // The enclosing symbol is edit-stable provenance; absent for anonymous frames. + if (caller?.symbol) { + tags.push([WellKnownFields.funcName, caller.symbol]); } if (args[0]) { const query = args[0]; diff --git a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-drizzle/test/func-name.spec.ts b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-drizzle/test/func-name.spec.ts new file mode 100644 index 00000000..9e750b98 --- /dev/null +++ b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-drizzle/test/func-name.spec.ts @@ -0,0 +1,115 @@ +import { test } from "node:test"; +import assert from "node:assert"; +import { pgTable, serial, text } from "drizzle-orm/pg-core"; +import { drizzle } from "drizzle-orm/pglite"; +import { patchDrizzle, traceCaller } from "../src/index.js"; + +// --- Unit: symbol capture straight from the stack frame --------------------- +// Test files are whitelisted by `isValidCaller`, so `traceCaller()` selects the +// frame of whatever test-file function calls it. + +function namedFunction() { + return traceCaller(); +} +const arrowAssigned = () => traceCaller(); +const repo = { + findFavorites() { + return traceCaller(); + }, +}; + +test("captures the enclosing named function as symbol, with file", () => { + const caller = namedFunction(); + assert.ok(caller?.file, "file must always be captured"); + assert.strictEqual(caller?.symbol, "namedFunction"); +}); + +test("captures an object method as Object.", () => { + assert.strictEqual(repo.findFavorites()?.symbol, "Object.findFavorites"); +}); + +test("captures an arrow assigned to a const by its inferred name", () => { + assert.strictEqual(arrowAssigned()?.symbol, "arrowAssigned"); +}); + +test("omits the symbol for an anonymous frame but keeps file", () => { + // An immediately-invoked anonymous arrow has no stable name in V8. + const caller = ((): ReturnType => traceCaller())(); + assert.ok(caller?.file, "file is still captured as the fallback"); + assert.strictEqual(caller?.symbol, undefined); +}); + +// --- Integration: the tag actually lands in the emitted comment ------------- + +const watches = pgTable("watches", { + id: serial("id").primaryKey(), + name: text("name"), +}); +const notifs = pgTable("notifs", { + id: serial("id").primaryKey(), + name: text("name"), +}); + +function tag(sql: string, key: string): string | undefined { + const match = sql.match(new RegExp(`${key}='([^']*)'`)); + return match ? decodeURIComponent(match[1]) : undefined; +} + +async function setupLoggedDb() { + const logged: string[] = []; + const db = patchDrizzle( + drizzle({ + schema: { watches, notifs }, + logger: { logQuery: (query) => logged.push(query) }, + }), + ); + await db.$client.exec( + "CREATE TABLE watches (id serial primary key, name text); CREATE TABLE notifs (id serial primary key, name text);", + ); + return { db, logged }; +} + +test("emits func_name alongside file for a named caller", async () => { + const { db, logged } = await setupLoggedDb(); + async function loadWatches() { + return db.select().from(watches); + } + await loadWatches(); + + const sql = logged.find((q) => q.includes('from "watches"'))!; + assert.strictEqual(tag(sql, "func_name"), "loadWatches"); + assert.ok(tag(sql, "file"), "file is still emitted"); + // serializeTags sorts keys alphabetically: db_driver, file, func_name. + assert.ok( + sql.indexOf("file=") < sql.indexOf("func_name="), + "file precedes func_name in the sorted comment", + ); +}); + +test("omits func_name (but keeps file) when the caller is anonymous", async () => { + const { db, logged } = await setupLoggedDb(); + // The query is built directly in this anonymous async arrow. + await (async () => { + await db.select().from(watches); + })(); + + const sql = logged.find((q) => q.includes('from "watches"'))!; + assert.strictEqual(tag(sql, "func_name"), undefined); + assert.ok(tag(sql, "file"), "file is still emitted as the fallback"); +}); + +test("concurrent queries each keep their own func_name", async () => { + const { db, logged } = await setupLoggedDb(); + async function queryWatches() { + return db.select().from(watches); + } + async function queryNotifs() { + return db.select().from(notifs); + } + await Promise.all([queryWatches(), queryNotifs()]); + + const watchesSql = logged.find((q) => q.includes('from "watches"'))!; + const notifsSql = logged.find((q) => q.includes('from "notifs"'))!; + assert.strictEqual(tag(watchesSql, "func_name"), "queryWatches"); + assert.strictEqual(tag(notifsSql, "func_name"), "queryNotifs"); +}); diff --git a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-mikroorm/README.md b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-mikroorm/README.md index 7255660c..55739835 100644 --- a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-mikroorm/README.md +++ b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-mikroorm/README.md @@ -10,6 +10,7 @@ Emits the following fields into the query: | ------------- | -------------------- | --------------------------------------------------------------- | | db_driver | Yes | The driver used to connect to the database. (MikroORM) | | file | Yes | The file that the query was executed in. | +| func_name | Yes, if named | The function/method that built the query. Omitted if anonymous. | | route | No | The route that the query was executed in. | | method | No | The http method for the request that the query was executed in. | | anything else | No | Any other information that the user wants to add to the query. | diff --git a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-mikroorm/src/index.ts b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-mikroorm/src/index.ts index 953dc07e..1847ab68 100644 --- a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-mikroorm/src/index.ts +++ b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-mikroorm/src/index.ts @@ -30,7 +30,37 @@ function isValidCaller(line: string): boolean { // (file.ts:12:12) or file.ts:12:12 const filepathRegex = /([^ (]*?:\d+:\d+)\)?$/; -export function traceCaller(): string | undefined { +/** The provenance captured from a single V8 stack frame. */ +export type CallerInfo = { + // The source location, `path:line:col`, resolved to the real project root. + file: string; + // The enclosing function/method symbol as V8 reports it (e.g. `UserService.list`). Absent for + // anonymous/top-level frames. Unlike `file`, it's edit-stable — a method name doesn't drift + // when lines above the call site change. + symbol?: string; +}; + +/** + * Pulls the enclosing function/method symbol out of a V8 stack frame. Named frames look like + * ` at ()`; anonymous/top-level frames are ` at ` with no + * symbol to capture, so we return nothing and the caller falls back to `file` alone. + */ +function extractSymbol(frame: string): string | undefined { + const match = frame.match(/^\s*at (.+) \(/); + if (!match) { + return; + } + // V8 prefixes async frames with `async ` in some versions; the symbol is what follows. + const symbol = match[1].replace(/^async /, ""); + // Anonymous functions — including arrow-assigned methods that surface as + // `Object.` in bundled/minified builds — carry no stable name. + if (!symbol || symbol.includes("")) { + return; + } + return symbol; +} + +export function traceCaller(): CallerInfo | undefined { const stack = new Error().stack; if (!stack) { return; @@ -43,13 +73,14 @@ export function traceCaller(): string | undefined { } const match = methodCaller.match(filepathRegex); if (match) { - return resolveFilePath(match[1]); + return { file: resolveFilePath(match[1]), symbol: extractSymbol(methodCaller) }; } } const WellKnownFields = { dbDriver: "db_driver", file: "file", + funcName: "func_name", route: "route", } as const; @@ -71,8 +102,12 @@ function buildOnQuery( [WellKnownFields.dbDriver, "mikroorm"], ]; pushW3CTraceContext(tags); - if (caller) { - tags.push([WellKnownFields.file, caller]); + if (caller?.file) { + tags.push([WellKnownFields.file, caller.file]); + } + // The enclosing symbol is edit-stable provenance; absent for anonymous frames. + if (caller?.symbol) { + tags.push([WellKnownFields.funcName, caller.symbol]); } if (requestContext) { for (const key in requestContext) { diff --git a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-mikroorm/test/driver-integration.spec.ts b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-mikroorm/test/driver-integration.spec.ts index 711c56b0..16432acc 100644 --- a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-mikroorm/test/driver-integration.spec.ts +++ b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-mikroorm/test/driver-integration.spec.ts @@ -108,5 +108,14 @@ test("patchMikroORM preserves original SQL content", () => { test("traceCaller returns a file path with line and column", () => { const caller = traceCaller(); assert.ok(caller, "traceCaller should return a value"); - assert.match(caller!, /:\d+:\d+$/, "Should end with :line:column"); + assert.match(caller!.file, /:\d+:\d+$/, "file should end with :line:column"); +}); + +test("traceCaller captures the enclosing function symbol when present", () => { + function loadRow() { + return traceCaller(); + } + const caller = loadRow(); + assert.ok(caller?.file, "file is always captured"); + assert.strictEqual(caller?.symbol, "loadRow"); }); diff --git a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-typeorm/README.md b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-typeorm/README.md index 57a5db01..7ddeb80d 100644 --- a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-typeorm/README.md +++ b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-typeorm/README.md @@ -8,6 +8,7 @@ Emits the following fields into the query: | ------------- | -------------------- | --------------------------------------------------------------- | | db_driver | Yes | The driver used to connect to the database. (TypeORM) | | file | Yes | The file that the query was executed in. | +| func_name | Yes, if named | The function/method that built the query. Omitted if anonymous. | | route | No | The route that the query was executed in. | | method | No | The http method for the request that the query was executed in. | | anything else | No | Any other information that the user wants to add to the query. | diff --git a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-typeorm/src/index.ts b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-typeorm/src/index.ts index 4ed1186c..6170d5ae 100644 --- a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-typeorm/src/index.ts +++ b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-typeorm/src/index.ts @@ -35,7 +35,37 @@ function isValidCaller(line: string): boolean { // (file.ts:12:12) or file.ts:12:12 const filepathRegex = /([^ (]*?:\d+:\d+)\)?$/; -export function traceCaller(): string | undefined { +/** The provenance captured from a single V8 stack frame. */ +export type CallerInfo = { + // The source location, `path:line:col`, resolved to the real project root. + file: string; + // The enclosing function/method symbol as V8 reports it (e.g. `UserService.list`). Absent for + // anonymous/top-level frames. Unlike `file`, it's edit-stable — a method name doesn't drift + // when lines above the call site change. + symbol?: string; +}; + +/** + * Pulls the enclosing function/method symbol out of a V8 stack frame. Named frames look like + * ` at ()`; anonymous/top-level frames are ` at ` with no + * symbol to capture, so we return nothing and the caller falls back to `file` alone. + */ +function extractSymbol(frame: string): string | undefined { + const match = frame.match(/^\s*at (.+) \(/); + if (!match) { + return; + } + // V8 prefixes async frames with `async ` in some versions; the symbol is what follows. + const symbol = match[1].replace(/^async /, ""); + // Anonymous functions — including arrow-assigned methods that surface as + // `Object.` in bundled/minified builds — carry no stable name. + if (!symbol || symbol.includes("")) { + return; + } + return symbol; +} + +export function traceCaller(): CallerInfo | undefined { const stack = new Error().stack; if (!stack) { return; @@ -48,13 +78,14 @@ export function traceCaller(): string | undefined { } const match = methodCaller.match(filepathRegex); if (match) { - return resolveFilePath(match[1]); + return { file: resolveFilePath(match[1]), symbol: extractSymbol(methodCaller) }; } } const WellKnownFields = { dbDriver: "db_driver", file: "file", + funcName: "func_name", route: "route", } as const; @@ -81,8 +112,12 @@ function patchQueryRunnerPrototype(proto: any) { [WellKnownFields.dbDriver, "typeorm"], ]; pushW3CTraceContext(tags); - if (caller) { - tags.push([WellKnownFields.file, caller]); + if (caller?.file) { + tags.push([WellKnownFields.file, caller.file]); + } + // The enclosing symbol is edit-stable provenance; absent for anonymous frames. + if (caller?.symbol) { + tags.push([WellKnownFields.funcName, caller.symbol]); } if (requestContext) { for (const key in requestContext) { diff --git a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-typeorm/test/driver-integration.spec.ts b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-typeorm/test/driver-integration.spec.ts index e14f6169..5387d2b8 100644 --- a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-typeorm/test/driver-integration.spec.ts +++ b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-typeorm/test/driver-integration.spec.ts @@ -1,7 +1,7 @@ import { test } from "node:test"; import assert from "node:assert"; import { DataSource, EntitySchema } from "typeorm"; -import { patchTypeORM } from "../src/index.js"; +import { patchTypeORM, traceCaller } from "../src/index.js"; const UserEntity = new EntitySchema({ name: "User", @@ -186,3 +186,18 @@ test("query result is preserved", async () => { await dataSource.destroy(); } }); + +test("traceCaller returns a file path with line and column", () => { + const caller = traceCaller(); + assert.ok(caller, "traceCaller should return a value"); + assert.match(caller!.file, /:\d+:\d+$/, "file should end with :line:column"); +}); + +test("traceCaller captures the enclosing function symbol when present", () => { + function loadRow() { + return traceCaller(); + } + const caller = loadRow(); + assert.ok(caller?.file, "file is always captured"); + assert.strictEqual(caller?.symbol, "loadRow"); +}); From 69e725fda1a5809cc5548e2b2ca2e530a448a873 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Sirois Date: Tue, 30 Jun 2026 16:10:50 -0400 Subject: [PATCH 2/2] chore(release): bump minor versions for the func_name tag - @query-doctor/sqlcommenter-drizzle: 0.4.0 -> 0.5.0 - @query-doctor/sqlcommenter-mikroorm: 0.3.0 -> 0.4.0 - @query-doctor/sqlcommenter-typeorm: 0.3.0 -> 0.4.0 Co-Authored-By: Claude Opus 4.8 (1M context) --- .../packages/sqlcommenter-drizzle/package-lock.json | 4 ++-- .../packages/sqlcommenter-drizzle/package.json | 2 +- .../packages/sqlcommenter-mikroorm/package-lock.json | 4 ++-- .../packages/sqlcommenter-mikroorm/package.json | 2 +- .../packages/sqlcommenter-typeorm/package-lock.json | 4 ++-- .../packages/sqlcommenter-typeorm/package.json | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-drizzle/package-lock.json b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-drizzle/package-lock.json index 05fdaa36..3d8a203d 100644 --- a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-drizzle/package-lock.json +++ b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-drizzle/package-lock.json @@ -1,12 +1,12 @@ { "name": "@query-doctor/sqlcommenter-drizzle", - "version": "0.4.0", + "version": "0.5.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@query-doctor/sqlcommenter-drizzle", - "version": "0.4.0", + "version": "0.5.0", "license": "Apache-2.0", "dependencies": { "@opentelemetry/api": "~1.9.0" diff --git a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-drizzle/package.json b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-drizzle/package.json index d63a9454..b9c29d93 100644 --- a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-drizzle/package.json +++ b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-drizzle/package.json @@ -1,6 +1,6 @@ { "name": "@query-doctor/sqlcommenter-drizzle", - "version": "0.4.0", + "version": "0.5.0", "description": "SQLCommenter patch for drizzle-orm", "main": "dist/cjs/index.js", "type": "module", diff --git a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-mikroorm/package-lock.json b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-mikroorm/package-lock.json index 7ba26f54..e06ac4e2 100644 --- a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-mikroorm/package-lock.json +++ b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-mikroorm/package-lock.json @@ -1,12 +1,12 @@ { "name": "@query-doctor/sqlcommenter-mikroorm", - "version": "0.3.0", + "version": "0.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@query-doctor/sqlcommenter-mikroorm", - "version": "0.3.0", + "version": "0.4.0", "license": "Apache-2.0", "dependencies": { "@opentelemetry/api": "~1.9.0" diff --git a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-mikroorm/package.json b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-mikroorm/package.json index fdd78ba3..a00abf01 100644 --- a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-mikroorm/package.json +++ b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-mikroorm/package.json @@ -1,6 +1,6 @@ { "name": "@query-doctor/sqlcommenter-mikroorm", - "version": "0.3.0", + "version": "0.4.0", "description": "SQLCommenter patch for MikroORM", "main": "dist/cjs/index.js", "type": "module", diff --git a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-typeorm/package-lock.json b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-typeorm/package-lock.json index d50dc7f9..8b2f60b5 100644 --- a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-typeorm/package-lock.json +++ b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-typeorm/package-lock.json @@ -1,12 +1,12 @@ { "name": "@query-doctor/sqlcommenter-typeorm", - "version": "0.3.0", + "version": "0.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@query-doctor/sqlcommenter-typeorm", - "version": "0.3.0", + "version": "0.4.0", "license": "Apache-2.0", "dependencies": { "@opentelemetry/api": "~1.9.0" diff --git a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-typeorm/package.json b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-typeorm/package.json index bd9665a1..c670d773 100644 --- a/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-typeorm/package.json +++ b/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-typeorm/package.json @@ -1,6 +1,6 @@ { "name": "@query-doctor/sqlcommenter-typeorm", - "version": "0.3.0", + "version": "0.4.0", "description": "SQLCommenter patch for TypeORM", "main": "dist/cjs/index.js", "type": "module",