d1-sql-tag 0.6.1 → 0.6.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.
@@ -56,4 +56,4 @@ declare function createMockSqlTag<T extends MockSqlTagHandler>(handler: T): Mock
56
56
  declare function logQueryResults(queries: string[], results: SqlResult[], duration?: number): void;
57
57
  //#endregion
58
58
  export { type MockSqlTag, type MockSqlTagHandler, type Primitive, type RowType, type SqlQueryFragment, type SqlTag, createD1SqlTag, createMockSqlTag, logQueryResults };
59
- //# sourceMappingURL=index.d.mts.map
59
+ //# sourceMappingURL=index.d.ts.map
@@ -216,4 +216,4 @@ function cleanupSqlQuery(query) {
216
216
 
217
217
  //#endregion
218
218
  export { createD1SqlTag, createMockSqlTag, logQueryResults };
219
- //# sourceMappingURL=index.mjs.map
219
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["sqlTag: SqlTag","statement: RawPreparedStatement<T>","mappedStatement: MappedPreparedStatement<T, U>","values: Primitive[]","batchId"],"sources":["../src/sql-tag.ts","../src/logger.ts"],"sourcesContent":["import type {\n D1Database,\n D1Response,\n D1Result,\n D1DatabaseSession,\n} from \"@cloudflare/workers-types/experimental/index.js\";\n\nexport type Primitive = string | number | boolean | null;\n\ninterface JoinFragment {\n templateStrings: TemplateStringsArray;\n templateValues: Primitive[];\n}\n\nexport type SqlTag = ((\n strings: TemplateStringsArray,\n ...values: (Primitive | SqlQueryFragment | JoinFragment)[]\n) => SqlQueryFragment) & {\n batch<T extends readonly PreparedStatementBase<object>[]>(\n statements: T,\n ): Promise<{\n -readonly [P in keyof T]: SqlResult<RowType<T[P]>>;\n }>;\n join(values: Primitive[]): JoinFragment;\n};\n\nexport interface SqlQueryFragment {\n build<T extends object = Record<string, Primitive>>(): RawPreparedStatement<T>;\n all<T extends object = Record<string, Primitive>>(): Promise<D1Result<T>>;\n run(): Promise<D1Response>;\n templateStrings: TemplateStringsArray;\n templateValues: TemplateValue[];\n}\n\ntype TemplateValue = Primitive | SqlQueryFragment | JoinFragment;\n\ninterface PreparedStatementBase<T extends object> {\n query: string;\n values: Primitive[];\n all(): Promise<D1Result<T>>;\n run(): Promise<D1Response>;\n [rowTypeSymbol]: T;\n}\n\ninterface MappedPreparedStatement<\n TRaw extends object,\n TMapped extends object,\n> extends PreparedStatementBase<TMapped> {\n mapper: (row: TRaw) => TMapped;\n}\n\ninterface RawPreparedStatement<T extends object> extends PreparedStatementBase<T> {\n map<TMapped extends object>(mapper: (row: T) => TMapped): MappedPreparedStatement<T, TMapped>;\n}\n\ntype PreparedStatement<T extends object, U extends object = Record<string, Primitive>> =\n | RawPreparedStatement<T>\n | MappedPreparedStatement<U, T>;\n\nexport type RowType<\n T extends PreparedStatementBase<any> | ((...args: any) => PreparedStatementBase<any>),\n> =\n T extends PreparedStatementBase<any>\n ? T[typeof rowTypeSymbol]\n : T extends (...args: any) => PreparedStatementBase<any>\n ? ReturnType<T>[typeof rowTypeSymbol]\n : never;\n\nexport interface SqlResult<T extends object = Record<string, Primitive>> extends D1Result<T> {}\n\ninterface SqlTagOptions {\n beforeQuery?: (id: number, queries: string[]) => void;\n afterQuery?: (id: number, queries: string[], results: SqlResult[], duration: number) => void;\n}\n\nexport interface MockSqlTagHandler {\n all<T extends object>(query: string, values: Primitive[]): Promise<D1Result<T>>;\n run(query: string, values: Primitive[]): Promise<D1Response>;\n batch(statements: Array<{ query: string; values: Primitive[] }>): Promise<D1Result<object>[]>;\n}\n\nexport type MockSqlTag<T extends MockSqlTagHandler> = SqlTag & { handler: T };\n\nlet batchId = 0;\nconst rowTypeSymbol = Symbol(\"rowType\");\n\nexport function createD1SqlTag(\n db: D1Database | D1DatabaseSession,\n options?: SqlTagOptions,\n): SqlTag {\n const sqlTag: SqlTag = (strings, ...values): SqlQueryFragment => {\n const fragment: SqlQueryFragment = {\n build() {\n return buildPreparedStatement(db, options, strings, values);\n },\n all<T extends object>() {\n return buildPreparedStatement<T>(db, options, strings, values).all();\n },\n run() {\n return buildPreparedStatement(db, options, strings, values).run();\n },\n templateStrings: strings,\n templateValues: values,\n };\n return fragment;\n };\n sqlTag.batch = async (statements) => {\n const queries = statements.map((it) => it.query);\n\n const id = makeBatchId();\n options?.beforeQuery?.(id, queries);\n const start = Date.now();\n const result = (await db.batch(statements.map((it) => makeNativeStatement(db, it)))) as any;\n const duration = Date.now() - start;\n options?.afterQuery?.(id, queries, result, duration);\n\n for (let i = 0; i < result.length; i++) {\n const statement = statements[i];\n const statementResult = result[i];\n if (\"mapper\" in statement) {\n statementResult.results = statementResult.results.map(statement.mapper);\n }\n }\n\n return result;\n };\n sqlTag.join = join;\n return sqlTag;\n}\n\nexport function createMockSqlTag<T extends MockSqlTagHandler>(handler: T): MockSqlTag<T> {\n const sqlTag = ((strings, ...values): SqlQueryFragment => {\n const fragment: SqlQueryFragment = {\n build() {\n return buildMockPreparedStatement(handler, strings, values);\n },\n all<T extends object>() {\n return buildMockPreparedStatement<T>(handler, strings, values).all();\n },\n run() {\n return buildMockPreparedStatement(handler, strings, values).run();\n },\n templateStrings: strings,\n templateValues: values,\n };\n return fragment;\n }) as MockSqlTag<T>;\n sqlTag.batch = async (statements) => {\n const statementsData = statements.map((it) => ({ query: it.query, values: it.values }));\n const result = (await handler.batch(statementsData)) as any;\n\n for (let i = 0; i < result.length; i++) {\n const statement = statements[i];\n const statementResult = result[i];\n if (\"mapper\" in statement) {\n statementResult.results = statementResult.results.map(statement.mapper);\n }\n }\n\n return result;\n };\n sqlTag.join = join;\n sqlTag.handler = handler;\n return sqlTag;\n}\n\nfunction buildMockPreparedStatement<T extends object>(\n handler: MockSqlTagHandler,\n templateStrings: TemplateStringsArray,\n templateValues: TemplateValue[],\n): RawPreparedStatement<T> {\n const { query, values } = expandTemplate(templateStrings, templateValues);\n\n const statement: RawPreparedStatement<T> = {\n async all() {\n const result = (await handler.all(query, values)) as SqlResult<T>;\n return result;\n },\n run() {\n return handler.run(query, values);\n },\n map<U extends object>(mapper: (row: T) => U) {\n const mappedStatement: MappedPreparedStatement<T, U> = {\n async all() {\n const result = (await handler.all(query, values)) as SqlResult<T>;\n result.results = result.results.map(mapper as any);\n return result as unknown as D1Result<U>;\n },\n run() {\n return handler.run(query, values);\n },\n query,\n values,\n mapper,\n [rowTypeSymbol]: null as any,\n };\n return mappedStatement;\n },\n query,\n values,\n [rowTypeSymbol]: null as any,\n };\n\n return statement;\n}\n\nfunction buildPreparedStatement<T extends object>(\n db: D1Database | D1DatabaseSession,\n options: SqlTagOptions | undefined,\n templateStrings: TemplateStringsArray,\n templateValues: TemplateValue[],\n): RawPreparedStatement<T> {\n const { query, values } = expandTemplate(templateStrings, templateValues);\n\n const statement: RawPreparedStatement<T> = {\n all() {\n return executeAll(db, options, statement, null);\n },\n run() {\n return executeRun(db, options, statement);\n },\n map<U extends object>(mapper: (row: T) => U) {\n const mappedStatement: MappedPreparedStatement<T, U> = {\n all() {\n return executeAll(db, options, mappedStatement, mapper);\n },\n run() {\n return executeRun(db, options, mappedStatement);\n },\n query,\n values,\n mapper,\n [rowTypeSymbol]: null as any,\n };\n return mappedStatement;\n },\n query,\n values,\n [rowTypeSymbol]: null as any,\n };\n\n return statement;\n}\n\nfunction expandTemplate(\n rootTemplateStrings: TemplateStringsArray,\n rootTemplateValues: TemplateValue[],\n) {\n let query = \"\";\n const values: Primitive[] = [];\n\n function expand(templateStrings: TemplateStringsArray, templateValues: TemplateValue[]) {\n for (let i = 0; i < templateStrings.length; i++) {\n if (i > 0) {\n const value = templateValues[i - 1];\n const valueIsFragment =\n value &&\n typeof value === \"object\" &&\n \"templateStrings\" in value &&\n \"templateValues\" in value;\n\n if (valueIsFragment) {\n expand(value.templateStrings, value.templateValues);\n } else {\n let valueIndex = values.indexOf(value);\n if (valueIndex === -1) {\n valueIndex = values.push(value) - 1;\n }\n query += `?${valueIndex + 1}`;\n }\n }\n query += templateStrings[i];\n }\n }\n\n expand(rootTemplateStrings, rootTemplateValues);\n\n return { query, values };\n}\n\nasync function executeAll<TRaw extends object, TMapped extends object>(\n db: D1Database | D1DatabaseSession,\n options: SqlTagOptions | undefined,\n statement: RawPreparedStatement<TRaw> | MappedPreparedStatement<TRaw, TMapped>,\n mapper: ((row: TRaw) => TMapped) | null,\n) {\n const batchId = makeBatchId();\n options?.beforeQuery?.(batchId, [statement.query]);\n const start = Date.now();\n\n const result = (await makeNativeStatement(db, statement as any).all()) as SqlResult<TMapped>;\n\n const duration = Date.now() - start;\n options?.afterQuery?.(batchId, [statement.query], [result as SqlResult], duration);\n\n if (mapper) {\n result.results = result.results.map(mapper as any);\n }\n\n return result;\n}\n\nasync function executeRun<T extends object, U extends object>(\n db: D1Database | D1DatabaseSession,\n options: SqlTagOptions | undefined,\n statement: PreparedStatement<T, U>,\n) {\n const batchId = makeBatchId();\n options?.beforeQuery?.(batchId, [statement.query]);\n const start = Date.now();\n const result = await makeNativeStatement(db, statement).run();\n const duration = Date.now() - start;\n options?.afterQuery?.(batchId, [statement.query], [result as SqlResult], duration);\n return result;\n}\n\nfunction makeNativeStatement<T extends object>(\n db: D1Database | D1DatabaseSession,\n statement: PreparedStatementBase<T>,\n) {\n let stmt = db.prepare(statement.query);\n if (statement.values.length > 0) {\n stmt = stmt.bind(...statement.values);\n }\n return stmt;\n}\n\nfunction makeBatchId() {\n batchId += 1;\n return batchId;\n}\n\nfunction makeTemplateStrings(strings: string[]): TemplateStringsArray {\n const templateStrings = strings as unknown as TemplateStringsArray;\n Object.defineProperty(templateStrings, \"raw\", { value: strings });\n return templateStrings;\n}\n\nfunction join(values: Primitive[]): JoinFragment {\n if (values.length === 0) {\n return {\n templateStrings: makeTemplateStrings([\"NULL\"]),\n templateValues: [],\n };\n }\n\n // Create templateStrings: [\"\", \", \", \", \", \"\"] with length = values.length + 1\n const strings = [\"\"];\n for (let i = 1; i < values.length; i++) {\n strings.push(\", \");\n }\n strings.push(\"\");\n\n return {\n templateStrings: makeTemplateStrings(strings),\n templateValues: values,\n };\n}\n","import type { SqlResult } from \"./sql-tag.js\";\n\nexport function logQueryResults(queries: string[], results: SqlResult[], duration?: number) {\n console.log(\n `D1 batch: ${typeof duration === \"number\" ? `${duration}ms · ` : \"\"}${queries.length} queries`,\n );\n for (let i = 0; i < queries.length; i++) {\n const query = queries[i];\n const result = results[i];\n\n console.log(`${i + 1}: ${cleanupSqlQuery(query)}`);\n\n const logSuffix =\n \"rows_read\" in result.meta\n ? ` · ${result.meta.rows_read} read · ${result.meta.rows_written} written`\n : \"\";\n console.log(` ↳ ${result.meta.duration}ms · ${result.meta.changes} changed` + logSuffix);\n }\n}\n\nfunction cleanupSqlQuery(query: string) {\n return query.replace(/\\n/g, \" \").replace(/\\s+/g, \" \");\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "d1-sql-tag",
3
- "version": "0.6.1",
3
+ "version": "0.6.3",
4
4
  "description": "A template literal for working with Cloudflare D1 database",
5
5
  "keywords": [
6
6
  "d1",
@@ -11,8 +11,8 @@
11
11
  "type": "module",
12
12
  "exports": {
13
13
  ".": {
14
- "types": "./dist/index.d.mts",
15
- "import": "./dist/index.mjs"
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js"
16
16
  }
17
17
  },
18
18
  "repository": {
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","names":["sqlTag: SqlTag","statement: RawPreparedStatement<T>","mappedStatement: MappedPreparedStatement<T, U>","values: Primitive[]","batchId"],"sources":["../src/sql-tag.ts","../src/logger.ts"],"sourcesContent":["import type {\n D1Database,\n D1Response,\n D1Result,\n D1DatabaseSession,\n} from \"@cloudflare/workers-types/experimental/index.js\";\n\nexport type Primitive = string | number | boolean | null;\n\ninterface JoinFragment {\n templateStrings: TemplateStringsArray;\n templateValues: Primitive[];\n}\n\nexport type SqlTag = ((\n strings: TemplateStringsArray,\n ...values: (Primitive | SqlQueryFragment | JoinFragment)[]\n) => SqlQueryFragment) & {\n batch<T extends readonly PreparedStatementBase<object>[]>(\n statements: T,\n ): Promise<{\n -readonly [P in keyof T]: SqlResult<RowType<T[P]>>;\n }>;\n join(values: Primitive[]): JoinFragment;\n};\n\nexport interface SqlQueryFragment {\n build<T extends object = Record<string, Primitive>>(): RawPreparedStatement<T>;\n all<T extends object = Record<string, Primitive>>(): Promise<D1Result<T>>;\n run(): Promise<D1Response>;\n templateStrings: TemplateStringsArray;\n templateValues: TemplateValue[];\n}\n\ntype TemplateValue = Primitive | SqlQueryFragment | JoinFragment;\n\ninterface PreparedStatementBase<T extends object> {\n query: string;\n values: Primitive[];\n all(): Promise<D1Result<T>>;\n run(): Promise<D1Response>;\n [rowTypeSymbol]: T;\n}\n\ninterface MappedPreparedStatement<\n TRaw extends object,\n TMapped extends object,\n> extends PreparedStatementBase<TMapped> {\n mapper: (row: TRaw) => TMapped;\n}\n\ninterface RawPreparedStatement<T extends object> extends PreparedStatementBase<T> {\n map<TMapped extends object>(mapper: (row: T) => TMapped): MappedPreparedStatement<T, TMapped>;\n}\n\ntype PreparedStatement<T extends object, U extends object = Record<string, Primitive>> =\n | RawPreparedStatement<T>\n | MappedPreparedStatement<U, T>;\n\nexport type RowType<\n T extends PreparedStatementBase<any> | ((...args: any) => PreparedStatementBase<any>),\n> =\n T extends PreparedStatementBase<any>\n ? T[typeof rowTypeSymbol]\n : T extends (...args: any) => PreparedStatementBase<any>\n ? ReturnType<T>[typeof rowTypeSymbol]\n : never;\n\nexport interface SqlResult<T extends object = Record<string, Primitive>> extends D1Result<T> {}\n\ninterface SqlTagOptions {\n beforeQuery?: (id: number, queries: string[]) => void;\n afterQuery?: (id: number, queries: string[], results: SqlResult[], duration: number) => void;\n}\n\nexport interface MockSqlTagHandler {\n all<T extends object>(query: string, values: Primitive[]): Promise<D1Result<T>>;\n run(query: string, values: Primitive[]): Promise<D1Response>;\n batch(statements: Array<{ query: string; values: Primitive[] }>): Promise<D1Result<object>[]>;\n}\n\nexport type MockSqlTag<T extends MockSqlTagHandler> = SqlTag & { handler: T };\n\nlet batchId = 0;\nconst rowTypeSymbol = Symbol(\"rowType\");\n\nexport function createD1SqlTag(\n db: D1Database | D1DatabaseSession,\n options?: SqlTagOptions,\n): SqlTag {\n const sqlTag: SqlTag = (strings, ...values): SqlQueryFragment => {\n const fragment: SqlQueryFragment = {\n build() {\n return buildPreparedStatement(db, options, strings, values);\n },\n all<T extends object>() {\n return buildPreparedStatement<T>(db, options, strings, values).all();\n },\n run() {\n return buildPreparedStatement(db, options, strings, values).run();\n },\n templateStrings: strings,\n templateValues: values,\n };\n return fragment;\n };\n sqlTag.batch = async (statements) => {\n const queries = statements.map((it) => it.query);\n\n const id = makeBatchId();\n options?.beforeQuery?.(id, queries);\n const start = Date.now();\n const result = (await db.batch(statements.map((it) => makeNativeStatement(db, it)))) as any;\n const duration = Date.now() - start;\n options?.afterQuery?.(id, queries, result, duration);\n\n for (let i = 0; i < result.length; i++) {\n const statement = statements[i];\n const statementResult = result[i];\n if (\"mapper\" in statement) {\n statementResult.results = statementResult.results.map(statement.mapper);\n }\n }\n\n return result;\n };\n sqlTag.join = join;\n return sqlTag;\n}\n\nexport function createMockSqlTag<T extends MockSqlTagHandler>(handler: T): MockSqlTag<T> {\n const sqlTag = ((strings, ...values): SqlQueryFragment => {\n const fragment: SqlQueryFragment = {\n build() {\n return buildMockPreparedStatement(handler, strings, values);\n },\n all<T extends object>() {\n return buildMockPreparedStatement<T>(handler, strings, values).all();\n },\n run() {\n return buildMockPreparedStatement(handler, strings, values).run();\n },\n templateStrings: strings,\n templateValues: values,\n };\n return fragment;\n }) as MockSqlTag<T>;\n sqlTag.batch = async (statements) => {\n const statementsData = statements.map((it) => ({ query: it.query, values: it.values }));\n const result = (await handler.batch(statementsData)) as any;\n\n for (let i = 0; i < result.length; i++) {\n const statement = statements[i];\n const statementResult = result[i];\n if (\"mapper\" in statement) {\n statementResult.results = statementResult.results.map(statement.mapper);\n }\n }\n\n return result;\n };\n sqlTag.join = join;\n sqlTag.handler = handler;\n return sqlTag;\n}\n\nfunction buildMockPreparedStatement<T extends object>(\n handler: MockSqlTagHandler,\n templateStrings: TemplateStringsArray,\n templateValues: TemplateValue[],\n): RawPreparedStatement<T> {\n const { query, values } = expandTemplate(templateStrings, templateValues);\n\n const statement: RawPreparedStatement<T> = {\n async all() {\n const result = (await handler.all(query, values)) as SqlResult<T>;\n return result;\n },\n run() {\n return handler.run(query, values);\n },\n map<U extends object>(mapper: (row: T) => U) {\n const mappedStatement: MappedPreparedStatement<T, U> = {\n async all() {\n const result = (await handler.all(query, values)) as SqlResult<T>;\n result.results = result.results.map(mapper as any);\n return result as unknown as D1Result<U>;\n },\n run() {\n return handler.run(query, values);\n },\n query,\n values,\n mapper,\n [rowTypeSymbol]: null as any,\n };\n return mappedStatement;\n },\n query,\n values,\n [rowTypeSymbol]: null as any,\n };\n\n return statement;\n}\n\nfunction buildPreparedStatement<T extends object>(\n db: D1Database | D1DatabaseSession,\n options: SqlTagOptions | undefined,\n templateStrings: TemplateStringsArray,\n templateValues: TemplateValue[],\n): RawPreparedStatement<T> {\n const { query, values } = expandTemplate(templateStrings, templateValues);\n\n const statement: RawPreparedStatement<T> = {\n all() {\n return executeAll(db, options, statement, null);\n },\n run() {\n return executeRun(db, options, statement);\n },\n map<U extends object>(mapper: (row: T) => U) {\n const mappedStatement: MappedPreparedStatement<T, U> = {\n all() {\n return executeAll(db, options, mappedStatement, mapper);\n },\n run() {\n return executeRun(db, options, mappedStatement);\n },\n query,\n values,\n mapper,\n [rowTypeSymbol]: null as any,\n };\n return mappedStatement;\n },\n query,\n values,\n [rowTypeSymbol]: null as any,\n };\n\n return statement;\n}\n\nfunction expandTemplate(\n rootTemplateStrings: TemplateStringsArray,\n rootTemplateValues: TemplateValue[],\n) {\n let query = \"\";\n const values: Primitive[] = [];\n\n function expand(templateStrings: TemplateStringsArray, templateValues: TemplateValue[]) {\n for (let i = 0; i < templateStrings.length; i++) {\n if (i > 0) {\n const value = templateValues[i - 1];\n const valueIsFragment =\n value &&\n typeof value === \"object\" &&\n \"templateStrings\" in value &&\n \"templateValues\" in value;\n\n if (valueIsFragment) {\n expand(value.templateStrings, value.templateValues);\n } else {\n let valueIndex = values.indexOf(value);\n if (valueIndex === -1) {\n valueIndex = values.push(value) - 1;\n }\n query += `?${valueIndex + 1}`;\n }\n }\n query += templateStrings[i];\n }\n }\n\n expand(rootTemplateStrings, rootTemplateValues);\n\n return { query, values };\n}\n\nasync function executeAll<TRaw extends object, TMapped extends object>(\n db: D1Database | D1DatabaseSession,\n options: SqlTagOptions | undefined,\n statement: RawPreparedStatement<TRaw> | MappedPreparedStatement<TRaw, TMapped>,\n mapper: ((row: TRaw) => TMapped) | null,\n) {\n const batchId = makeBatchId();\n options?.beforeQuery?.(batchId, [statement.query]);\n const start = Date.now();\n\n const result = (await makeNativeStatement(db, statement as any).all()) as SqlResult<TMapped>;\n\n const duration = Date.now() - start;\n options?.afterQuery?.(batchId, [statement.query], [result as SqlResult], duration);\n\n if (mapper) {\n result.results = result.results.map(mapper as any);\n }\n\n return result;\n}\n\nasync function executeRun<T extends object, U extends object>(\n db: D1Database | D1DatabaseSession,\n options: SqlTagOptions | undefined,\n statement: PreparedStatement<T, U>,\n) {\n const batchId = makeBatchId();\n options?.beforeQuery?.(batchId, [statement.query]);\n const start = Date.now();\n const result = await makeNativeStatement(db, statement).run();\n const duration = Date.now() - start;\n options?.afterQuery?.(batchId, [statement.query], [result as SqlResult], duration);\n return result;\n}\n\nfunction makeNativeStatement<T extends object>(\n db: D1Database | D1DatabaseSession,\n statement: PreparedStatementBase<T>,\n) {\n let stmt = db.prepare(statement.query);\n if (statement.values.length > 0) {\n stmt = stmt.bind(...statement.values);\n }\n return stmt;\n}\n\nfunction makeBatchId() {\n batchId += 1;\n return batchId;\n}\n\nfunction makeTemplateStrings(strings: string[]): TemplateStringsArray {\n const templateStrings = strings as unknown as TemplateStringsArray;\n Object.defineProperty(templateStrings, \"raw\", { value: strings });\n return templateStrings;\n}\n\nfunction join(values: Primitive[]): JoinFragment {\n if (values.length === 0) {\n return {\n templateStrings: makeTemplateStrings([\"NULL\"]),\n templateValues: [],\n };\n }\n\n // Create templateStrings: [\"\", \", \", \", \", \"\"] with length = values.length + 1\n const strings = [\"\"];\n for (let i = 1; i < values.length; i++) {\n strings.push(\", \");\n }\n strings.push(\"\");\n\n return {\n templateStrings: makeTemplateStrings(strings),\n templateValues: values,\n };\n}\n","import type { SqlResult } from \"./sql-tag.js\";\n\nexport function logQueryResults(queries: string[], results: SqlResult[], duration?: number) {\n console.log(\n `D1 batch: ${typeof duration === \"number\" ? `${duration}ms · ` : \"\"}${queries.length} queries`,\n );\n for (let i = 0; i < queries.length; i++) {\n const query = queries[i];\n const result = results[i];\n\n console.log(`${i + 1}: ${cleanupSqlQuery(query)}`);\n\n const logSuffix =\n \"rows_read\" in result.meta\n ? ` · ${result.meta.rows_read} read · ${result.meta.rows_written} written`\n : \"\";\n console.log(` ↳ ${result.meta.duration}ms · ${result.meta.changes} changed` + logSuffix);\n }\n}\n\nfunction cleanupSqlQuery(query: string) {\n return query.replace(/\\n/g, \" \").replace(/\\s+/g, \" \");\n}\n"],"mappings":"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"}