@logtape/drizzle-orm 1.3.0-dev.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.
package/dist/mod.js ADDED
@@ -0,0 +1,145 @@
1
+ import { getLogger as getLogger$1 } from "@logtape/logtape";
2
+
3
+ //#region src/mod.ts
4
+ /**
5
+ * A Drizzle ORM-compatible logger that wraps LogTape.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { drizzle } from "drizzle-orm/postgres-js";
10
+ * import { getLogger } from "@logtape/drizzle-orm";
11
+ * import postgres from "postgres";
12
+ *
13
+ * const client = postgres(process.env.DATABASE_URL!);
14
+ * const db = drizzle(client, {
15
+ * logger: getLogger(),
16
+ * });
17
+ * ```
18
+ *
19
+ * @since 1.3.0
20
+ */
21
+ var DrizzleLogger = class {
22
+ #logger;
23
+ #level;
24
+ /**
25
+ * Creates a new DrizzleLogger instance.
26
+ * @param logger The LogTape logger to use.
27
+ * @param level The log level to use for query logging.
28
+ */
29
+ constructor(logger, level = "debug") {
30
+ this.#logger = logger;
31
+ this.#level = level;
32
+ }
33
+ /**
34
+ * Logs a database query with its parameters.
35
+ *
36
+ * The log output includes:
37
+ * - `formattedQuery`: The query with parameter placeholders replaced with
38
+ * actual values (for readability)
39
+ * - `query`: The original query string with placeholders
40
+ * - `params`: The original parameters array
41
+ *
42
+ * @param query The SQL query string with parameter placeholders.
43
+ * @param params The parameter values.
44
+ */
45
+ logQuery(query, params) {
46
+ const stringifiedParams = params.map(serialize);
47
+ const formattedQuery = query.replace(/\$(\d+)/g, (match) => {
48
+ const index = Number.parseInt(match.slice(1), 10);
49
+ return stringifiedParams[index - 1] ?? match;
50
+ });
51
+ const logMethod = this.#logger[this.#level].bind(this.#logger);
52
+ logMethod("Query: {formattedQuery}", {
53
+ formattedQuery,
54
+ query,
55
+ params
56
+ });
57
+ }
58
+ };
59
+ /**
60
+ * Serializes a parameter value to a SQL-safe string representation.
61
+ *
62
+ * @param value The value to serialize.
63
+ * @returns The serialized string representation.
64
+ * @since 1.3.0
65
+ */
66
+ function serialize(value) {
67
+ if (typeof value === "undefined" || value === null) return "NULL";
68
+ if (typeof value === "string") return stringLiteral(value);
69
+ if (typeof value === "number" || typeof value === "bigint") return value.toString();
70
+ if (typeof value === "boolean") return value ? "'t'" : "'f'";
71
+ if (value instanceof Date) return stringLiteral(value.toISOString());
72
+ if (Array.isArray(value)) return `ARRAY[${value.map(serialize).join(", ")}]`;
73
+ if (typeof value === "object") return stringLiteral(JSON.stringify(value));
74
+ return stringLiteral(String(value));
75
+ }
76
+ /**
77
+ * Converts a string to a SQL string literal with proper escaping.
78
+ *
79
+ * @param str The string to convert.
80
+ * @returns The escaped SQL string literal.
81
+ * @since 1.3.0
82
+ */
83
+ function stringLiteral(str) {
84
+ if (/[\\'\n\r\t\b\f]/.test(str)) {
85
+ let escaped = str;
86
+ escaped = escaped.replaceAll("\\", "\\\\");
87
+ escaped = escaped.replaceAll("'", "\\'");
88
+ escaped = escaped.replaceAll("\n", "\\n");
89
+ escaped = escaped.replaceAll("\r", "\\r");
90
+ escaped = escaped.replaceAll(" ", "\\t");
91
+ escaped = escaped.replaceAll("\b", "\\b");
92
+ escaped = escaped.replaceAll("\f", "\\f");
93
+ return `E'${escaped}'`;
94
+ }
95
+ return `'${str}'`;
96
+ }
97
+ /**
98
+ * Normalize category to array format.
99
+ */
100
+ function normalizeCategory(category) {
101
+ return typeof category === "string" ? [category] : category;
102
+ }
103
+ /**
104
+ * Creates a Drizzle ORM-compatible logger that wraps LogTape.
105
+ *
106
+ * @example Basic usage
107
+ * ```typescript
108
+ * import { drizzle } from "drizzle-orm/postgres-js";
109
+ * import { configure } from "@logtape/logtape";
110
+ * import { getLogger } from "@logtape/drizzle-orm";
111
+ * import postgres from "postgres";
112
+ *
113
+ * await configure({
114
+ * // ... LogTape configuration
115
+ * });
116
+ *
117
+ * const client = postgres(process.env.DATABASE_URL!);
118
+ * const db = drizzle(client, {
119
+ * logger: getLogger(),
120
+ * });
121
+ * ```
122
+ *
123
+ * @example With custom category and level
124
+ * ```typescript
125
+ * const db = drizzle(client, {
126
+ * logger: getLogger({
127
+ * category: ["my-app", "database"],
128
+ * level: "info",
129
+ * }),
130
+ * });
131
+ * ```
132
+ *
133
+ * @param options Configuration options for the logger.
134
+ * @returns A Drizzle ORM-compatible logger wrapping LogTape.
135
+ * @since 1.3.0
136
+ */
137
+ function getLogger(options = {}) {
138
+ const category = normalizeCategory(options.category ?? ["drizzle-orm"]);
139
+ const logger = getLogger$1(category);
140
+ return new DrizzleLogger(logger, options.level ?? "debug");
141
+ }
142
+
143
+ //#endregion
144
+ export { DrizzleLogger, getLogger, serialize, stringLiteral };
145
+ //# sourceMappingURL=mod.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.js","names":["#logger","#level","logger: LogTapeLogger","level: LogLevel","query: string","params: unknown[]","value: unknown","str: string","category: string | readonly string[]","options: DrizzleLoggerOptions"],"sources":["../src/mod.ts"],"sourcesContent":["import {\n getLogger as getLogTapeLogger,\n type Logger as LogTapeLogger,\n type LogLevel,\n} from \"@logtape/logtape\";\n\nexport type { LogLevel } from \"@logtape/logtape\";\n\n/**\n * Options for configuring the Drizzle ORM LogTape logger.\n * @since 1.3.0\n */\nexport interface DrizzleLoggerOptions {\n /**\n * The LogTape category to use for logging.\n * @default [\"drizzle-orm\"]\n */\n readonly category?: string | readonly string[];\n\n /**\n * The log level to use for query logging.\n * @default \"debug\"\n */\n readonly level?: LogLevel;\n}\n\n/**\n * Drizzle ORM's Logger interface.\n * @since 1.3.0\n */\nexport interface Logger {\n logQuery(query: string, params: unknown[]): void;\n}\n\n/**\n * A Drizzle ORM-compatible logger that wraps LogTape.\n *\n * @example\n * ```typescript\n * import { drizzle } from \"drizzle-orm/postgres-js\";\n * import { getLogger } from \"@logtape/drizzle-orm\";\n * import postgres from \"postgres\";\n *\n * const client = postgres(process.env.DATABASE_URL!);\n * const db = drizzle(client, {\n * logger: getLogger(),\n * });\n * ```\n *\n * @since 1.3.0\n */\nexport class DrizzleLogger implements Logger {\n readonly #logger: LogTapeLogger;\n readonly #level: LogLevel;\n\n /**\n * Creates a new DrizzleLogger instance.\n * @param logger The LogTape logger to use.\n * @param level The log level to use for query logging.\n */\n constructor(logger: LogTapeLogger, level: LogLevel = \"debug\") {\n this.#logger = logger;\n this.#level = level;\n }\n\n /**\n * Logs a database query with its parameters.\n *\n * The log output includes:\n * - `formattedQuery`: The query with parameter placeholders replaced with\n * actual values (for readability)\n * - `query`: The original query string with placeholders\n * - `params`: The original parameters array\n *\n * @param query The SQL query string with parameter placeholders.\n * @param params The parameter values.\n */\n logQuery(query: string, params: unknown[]): void {\n const stringifiedParams = params.map(serialize);\n const formattedQuery = query.replace(/\\$(\\d+)/g, (match) => {\n const index = Number.parseInt(match.slice(1), 10);\n return stringifiedParams[index - 1] ?? match;\n });\n\n const logMethod = this.#logger[this.#level].bind(this.#logger);\n logMethod(\"Query: {formattedQuery}\", {\n formattedQuery,\n query,\n params,\n });\n }\n}\n\n/**\n * Serializes a parameter value to a SQL-safe string representation.\n *\n * @param value The value to serialize.\n * @returns The serialized string representation.\n * @since 1.3.0\n */\nexport function serialize(value: unknown): string {\n if (typeof value === \"undefined\" || value === null) return \"NULL\";\n if (typeof value === \"string\") return stringLiteral(value);\n if (typeof value === \"number\" || typeof value === \"bigint\") {\n return value.toString();\n }\n if (typeof value === \"boolean\") return value ? \"'t'\" : \"'f'\";\n if (value instanceof Date) return stringLiteral(value.toISOString());\n if (Array.isArray(value)) {\n return `ARRAY[${value.map(serialize).join(\", \")}]`;\n }\n if (typeof value === \"object\") {\n // Assume it's a JSON object\n return stringLiteral(JSON.stringify(value));\n }\n return stringLiteral(String(value));\n}\n\n/**\n * Converts a string to a SQL string literal with proper escaping.\n *\n * @param str The string to convert.\n * @returns The escaped SQL string literal.\n * @since 1.3.0\n */\nexport function stringLiteral(str: string): string {\n if (/[\\\\'\\n\\r\\t\\b\\f]/.test(str)) {\n let escaped = str;\n escaped = escaped.replaceAll(\"\\\\\", \"\\\\\\\\\");\n escaped = escaped.replaceAll(\"'\", \"\\\\'\");\n escaped = escaped.replaceAll(\"\\n\", \"\\\\n\");\n escaped = escaped.replaceAll(\"\\r\", \"\\\\r\");\n escaped = escaped.replaceAll(\"\\t\", \"\\\\t\");\n escaped = escaped.replaceAll(\"\\b\", \"\\\\b\");\n escaped = escaped.replaceAll(\"\\f\", \"\\\\f\");\n return `E'${escaped}'`;\n }\n return `'${str}'`;\n}\n\n/**\n * Normalize category to array format.\n */\nfunction normalizeCategory(\n category: string | readonly string[],\n): readonly string[] {\n return typeof category === \"string\" ? [category] : category;\n}\n\n/**\n * Creates a Drizzle ORM-compatible logger that wraps LogTape.\n *\n * @example Basic usage\n * ```typescript\n * import { drizzle } from \"drizzle-orm/postgres-js\";\n * import { configure } from \"@logtape/logtape\";\n * import { getLogger } from \"@logtape/drizzle-orm\";\n * import postgres from \"postgres\";\n *\n * await configure({\n * // ... LogTape configuration\n * });\n *\n * const client = postgres(process.env.DATABASE_URL!);\n * const db = drizzle(client, {\n * logger: getLogger(),\n * });\n * ```\n *\n * @example With custom category and level\n * ```typescript\n * const db = drizzle(client, {\n * logger: getLogger({\n * category: [\"my-app\", \"database\"],\n * level: \"info\",\n * }),\n * });\n * ```\n *\n * @param options Configuration options for the logger.\n * @returns A Drizzle ORM-compatible logger wrapping LogTape.\n * @since 1.3.0\n */\nexport function getLogger(options: DrizzleLoggerOptions = {}): DrizzleLogger {\n const category = normalizeCategory(options.category ?? [\"drizzle-orm\"]);\n const logger = getLogTapeLogger(category);\n return new DrizzleLogger(logger, options.level ?? \"debug\");\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAmDA,IAAa,gBAAb,MAA6C;CAC3C,AAASA;CACT,AAASC;;;;;;CAOT,YAAYC,QAAuBC,QAAkB,SAAS;AAC5D,OAAKH,UAAU;AACf,OAAKC,SAAS;CACf;;;;;;;;;;;;;CAcD,SAASG,OAAeC,QAAyB;EAC/C,MAAM,oBAAoB,OAAO,IAAI,UAAU;EAC/C,MAAM,iBAAiB,MAAM,QAAQ,YAAY,CAAC,UAAU;GAC1D,MAAM,QAAQ,OAAO,SAAS,MAAM,MAAM,EAAE,EAAE,GAAG;AACjD,UAAO,kBAAkB,QAAQ,MAAM;EACxC,EAAC;EAEF,MAAM,YAAY,KAAKL,QAAQ,KAAKC,QAAQ,KAAK,KAAKD,QAAQ;AAC9D,YAAU,2BAA2B;GACnC;GACA;GACA;EACD,EAAC;CACH;AACF;;;;;;;;AASD,SAAgB,UAAUM,OAAwB;AAChD,YAAW,UAAU,eAAe,UAAU,KAAM,QAAO;AAC3D,YAAW,UAAU,SAAU,QAAO,cAAc,MAAM;AAC1D,YAAW,UAAU,mBAAmB,UAAU,SAChD,QAAO,MAAM,UAAU;AAEzB,YAAW,UAAU,UAAW,QAAO,QAAQ,QAAQ;AACvD,KAAI,iBAAiB,KAAM,QAAO,cAAc,MAAM,aAAa,CAAC;AACpE,KAAI,MAAM,QAAQ,MAAM,CACtB,SAAQ,QAAQ,MAAM,IAAI,UAAU,CAAC,KAAK,KAAK,CAAC;AAElD,YAAW,UAAU,SAEnB,QAAO,cAAc,KAAK,UAAU,MAAM,CAAC;AAE7C,QAAO,cAAc,OAAO,MAAM,CAAC;AACpC;;;;;;;;AASD,SAAgB,cAAcC,KAAqB;AACjD,KAAI,kBAAkB,KAAK,IAAI,EAAE;EAC/B,IAAI,UAAU;AACd,YAAU,QAAQ,WAAW,MAAM,OAAO;AAC1C,YAAU,QAAQ,WAAW,KAAK,MAAM;AACxC,YAAU,QAAQ,WAAW,MAAM,MAAM;AACzC,YAAU,QAAQ,WAAW,MAAM,MAAM;AACzC,YAAU,QAAQ,WAAW,KAAM,MAAM;AACzC,YAAU,QAAQ,WAAW,MAAM,MAAM;AACzC,YAAU,QAAQ,WAAW,MAAM,MAAM;AACzC,UAAQ,IAAI,QAAQ;CACrB;AACD,SAAQ,GAAG,IAAI;AAChB;;;;AAKD,SAAS,kBACPC,UACmB;AACnB,eAAc,aAAa,WAAW,CAAC,QAAS,IAAG;AACpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCD,SAAgB,UAAUC,UAAgC,CAAE,GAAiB;CAC3E,MAAM,WAAW,kBAAkB,QAAQ,YAAY,CAAC,aAAc,EAAC;CACvE,MAAM,SAAS,YAAiB,SAAS;AACzC,QAAO,IAAI,cAAc,QAAQ,QAAQ,SAAS;AACnD"}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@logtape/drizzle-orm",
3
+ "version": "1.3.0-dev.1",
4
+ "description": "Drizzle ORM adapter for LogTape logging library",
5
+ "keywords": [
6
+ "logging",
7
+ "log",
8
+ "logger",
9
+ "drizzle",
10
+ "drizzle-orm",
11
+ "orm",
12
+ "database",
13
+ "sql",
14
+ "adapter",
15
+ "logtape"
16
+ ],
17
+ "license": "MIT",
18
+ "author": {
19
+ "name": "Hong Minhee",
20
+ "email": "hong@minhee.org",
21
+ "url": "https://hongminhee.org/"
22
+ },
23
+ "homepage": "https://logtape.org/",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/dahlia/logtape.git",
27
+ "directory": "packages/drizzle-orm/"
28
+ },
29
+ "bugs": {
30
+ "url": "https://github.com/dahlia/logtape/issues"
31
+ },
32
+ "funding": [
33
+ "https://github.com/sponsors/dahlia"
34
+ ],
35
+ "type": "module",
36
+ "module": "./dist/mod.js",
37
+ "main": "./dist/mod.cjs",
38
+ "types": "./dist/mod.d.ts",
39
+ "exports": {
40
+ ".": {
41
+ "types": {
42
+ "import": "./dist/mod.d.ts",
43
+ "require": "./dist/mod.d.cts"
44
+ },
45
+ "import": "./dist/mod.js",
46
+ "require": "./dist/mod.cjs"
47
+ },
48
+ "./package.json": "./package.json"
49
+ },
50
+ "sideEffects": false,
51
+ "peerDependencies": {
52
+ "@logtape/logtape": "^1.3.0"
53
+ },
54
+ "devDependencies": {
55
+ "@alinea/suite": "^0.6.3",
56
+ "@std/assert": "npm:@jsr/std__assert@^1.0.13",
57
+ "tsdown": "^0.12.7",
58
+ "typescript": "^5.8.3"
59
+ },
60
+ "scripts": {
61
+ "build": "tsdown",
62
+ "prepublish": "tsdown",
63
+ "test": "tsdown && node --experimental-transform-types --test",
64
+ "test:bun": "tsdown && bun test",
65
+ "test:deno": "deno test --allow-env --allow-sys --allow-net",
66
+ "test-all": "tsdown && node --experimental-transform-types --test && bun test && deno test"
67
+ }
68
+ }