d1-sql-tag 0.2.1 → 0.2.2
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/README.md +3 -5
- package/dist/index.js +9 -23
- package/dist/index.js.map +1 -1
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# `d1-sql-tag`
|
|
2
2
|
|
|
3
|
+
[](https://badge.fury.io/js/d1-sql-tag)
|
|
4
|
+
|
|
3
5
|
A template literal for working with [Cloudflare D1](https://developers.cloudflare.com/d1/)
|
|
4
6
|
database.
|
|
5
7
|
|
|
@@ -34,11 +36,7 @@ function createSqlTag(db: D1Database) {
|
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
export default {
|
|
37
|
-
async fetch(
|
|
38
|
-
request: Request,
|
|
39
|
-
env: Env,
|
|
40
|
-
ctx: ExecutionContext,
|
|
41
|
-
): Promise<Response> {
|
|
39
|
+
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
|
|
42
40
|
const sql = createSqlTag(env.DB);
|
|
43
41
|
const result = await sql`SELECT ${"hello world"} AS message`.all<{
|
|
44
42
|
message: string;
|
package/dist/index.js
CHANGED
|
@@ -23,9 +23,7 @@ function createD1SqlTag(db, options) {
|
|
|
23
23
|
const id = makeBatchId();
|
|
24
24
|
options?.beforeQuery?.(id, queries);
|
|
25
25
|
const start = Date.now();
|
|
26
|
-
const result = await db.batch(
|
|
27
|
-
statements.map((it) => makeNativeStatement(db, it))
|
|
28
|
-
);
|
|
26
|
+
const result = await db.batch(statements.map((it) => makeNativeStatement(db, it)));
|
|
29
27
|
const duration = Date.now() - start;
|
|
30
28
|
options?.afterQuery?.(id, queries, result, duration);
|
|
31
29
|
for (let i = 0; i < result.length; i++) {
|
|
@@ -80,7 +78,10 @@ function expandTemplate(rootTemplateStrings, rootTemplateValues) {
|
|
|
80
78
|
if (valueIsFragment) {
|
|
81
79
|
expand(value.templateStrings, value.templateValues);
|
|
82
80
|
} else {
|
|
83
|
-
|
|
81
|
+
let valueIndex = values.indexOf(value);
|
|
82
|
+
if (valueIndex === -1) {
|
|
83
|
+
valueIndex = values.push(value) - 1;
|
|
84
|
+
}
|
|
84
85
|
query += `?${valueIndex + 1}`;
|
|
85
86
|
}
|
|
86
87
|
}
|
|
@@ -94,17 +95,9 @@ async function executeAll(db, options, statement, mapper) {
|
|
|
94
95
|
const batchId2 = makeBatchId();
|
|
95
96
|
options?.beforeQuery?.(batchId2, [statement.query]);
|
|
96
97
|
const start = Date.now();
|
|
97
|
-
const result = await makeNativeStatement(
|
|
98
|
-
db,
|
|
99
|
-
statement
|
|
100
|
-
).all();
|
|
98
|
+
const result = await makeNativeStatement(db, statement).all();
|
|
101
99
|
const duration = Date.now() - start;
|
|
102
|
-
options?.afterQuery?.(
|
|
103
|
-
batchId2,
|
|
104
|
-
[statement.query],
|
|
105
|
-
[result],
|
|
106
|
-
duration
|
|
107
|
-
);
|
|
100
|
+
options?.afterQuery?.(batchId2, [statement.query], [result], duration);
|
|
108
101
|
if (mapper) {
|
|
109
102
|
result.results = result.results.map(mapper);
|
|
110
103
|
}
|
|
@@ -116,12 +109,7 @@ async function executeRun(db, options, statement) {
|
|
|
116
109
|
const start = Date.now();
|
|
117
110
|
const result = await makeNativeStatement(db, statement).run();
|
|
118
111
|
const duration = Date.now() - start;
|
|
119
|
-
options?.afterQuery?.(
|
|
120
|
-
batchId2,
|
|
121
|
-
[statement.query],
|
|
122
|
-
[result],
|
|
123
|
-
duration
|
|
124
|
-
);
|
|
112
|
+
options?.afterQuery?.(batchId2, [statement.query], [result], duration);
|
|
125
113
|
return result;
|
|
126
114
|
}
|
|
127
115
|
function makeNativeStatement(db, statement) {
|
|
@@ -146,9 +134,7 @@ function logQueryResults(queries, results, duration) {
|
|
|
146
134
|
const result = results[i];
|
|
147
135
|
console.log(`${i + 1}: ${cleanupSqlQuery(query)}`);
|
|
148
136
|
const logSuffix = "rows_read" in result.meta ? ` \xB7 ${result.meta.rows_read} read \xB7 ${result.meta.rows_written} written` : "";
|
|
149
|
-
console.log(
|
|
150
|
-
` \u21B3 ${result.meta.duration}ms \xB7 ${result.meta.changes} changed` + logSuffix
|
|
151
|
-
);
|
|
137
|
+
console.log(` \u21B3 ${result.meta.duration}ms \xB7 ${result.meta.changes} changed` + logSuffix);
|
|
152
138
|
}
|
|
153
139
|
}
|
|
154
140
|
function cleanupSqlQuery(query) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/sql-tag.ts","../src/logger.ts"],"sourcesContent":["import type { D1Database, D1Result } from \"@cloudflare/workers-types\";\n\nexport type Primitive = string | number | boolean | null;\n\nexport type SqlTag = ((\n strings: TemplateStringsArray,\n ...values: (Primitive | SqlQueryFragment)[]\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};\n\nexport interface SqlQueryFragment {\n build<\n T extends object = Record<string, Primitive>,\n >(): RawPreparedStatement<T>;\n all<T extends object = Record<string, Primitive>>(): Promise<D1Result<T>>;\n run(): Promise<D1Result>;\n templateStrings: TemplateStringsArray;\n templateValues: (Primitive | SqlQueryFragment)[];\n}\n\ninterface PreparedStatementBase<T extends object> {\n query: string;\n values: Primitive[];\n all(): Promise<D1Result<T>>;\n run(): Promise<D1Result>;\n [rowTypeSymbol]: T;\n}\n\ninterface MappedPreparedStatement<TRaw extends object, TMapped extends object>\n extends PreparedStatementBase<TMapped> {\n mapper: (row: TRaw) => TMapped;\n}\n\ninterface RawPreparedStatement<T extends object>\n extends PreparedStatementBase<T> {\n map<TMapped extends object>(\n mapper: (row: T) => TMapped,\n ): MappedPreparedStatement<T, TMapped>;\n}\n\ntype PreparedStatement<\n T extends object,\n U extends object = Record<string, Primitive>,\n> = RawPreparedStatement<T> | MappedPreparedStatement<U, T>;\n\nexport type RowType<\n T extends\n | PreparedStatementBase<any>\n | ((...args: any) => PreparedStatementBase<any>),\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>>\n extends D1Result<T> {}\n\ninterface SqlTagOptions {\n beforeQuery?: (id: number, queries: string[]) => void;\n afterQuery?: (\n id: number,\n queries: string[],\n results: SqlResult[],\n duration: number,\n ) => void;\n}\n\nlet batchId = 0;\nconst rowTypeSymbol = Symbol(\"rowType\");\n\nexport function createD1SqlTag(\n db: D1Database,\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(\n statements.map((it) => makeNativeStatement(db, it)),\n )) 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 return sqlTag;\n}\n\nfunction buildPreparedStatement<T extends object>(\n db: D1Database,\n options: SqlTagOptions | undefined,\n templateStrings: TemplateStringsArray,\n templateValues: (Primitive | SqlQueryFragment)[],\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: (Primitive | SqlQueryFragment)[],\n) {\n let query = \"\";\n const values: Primitive[] = [];\n\n function expand(\n templateStrings: TemplateStringsArray,\n templateValues: (Primitive | SqlQueryFragment)[],\n ) {\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 if (valueIsFragment) {\n expand(value.templateStrings, value.templateValues);\n } else {\n const valueIndex = values.push(value as Primitive) - 1;\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,\n options: SqlTagOptions | undefined,\n statement:\n | RawPreparedStatement<TRaw>\n | 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(\n db,\n statement as any,\n ).all()) as SqlResult<TMapped>;\n\n const duration = Date.now() - start;\n options?.afterQuery?.(\n batchId,\n [statement.query],\n [result as SqlResult],\n duration,\n );\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,\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?.(\n batchId,\n [statement.query],\n [result as SqlResult],\n duration,\n );\n return result;\n}\n\nfunction makeNativeStatement<T extends object>(\n db: D1Database,\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","import type { SqlResult } from \"./sql-tag.js\";\n\nexport function logQueryResults(\n queries: string[],\n results: SqlResult[],\n duration?: number,\n) {\n console.log(\n `D1 batch: ${typeof duration === \"number\" ? `${duration}ms · ` : \"\"}${\n queries.length\n } 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(\n ` ↳ ${result.meta.duration}ms · ${result.meta.changes} changed` +\n logSuffix,\n );\n }\n}\n\nfunction cleanupSqlQuery(query: string) {\n return query.replace(/\\n/g, \" \").replace(/\\s+/g, \" \");\n}\n"],"mappings":"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","names":["batchId"]}
|
|
1
|
+
{"version":3,"sources":["../src/sql-tag.ts","../src/logger.ts"],"sourcesContent":["import type { D1Database, D1Result } from \"@cloudflare/workers-types\";\n\nexport type Primitive = string | number | boolean | null;\n\nexport type SqlTag = ((\n strings: TemplateStringsArray,\n ...values: (Primitive | SqlQueryFragment)[]\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};\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<D1Result>;\n templateStrings: TemplateStringsArray;\n templateValues: (Primitive | SqlQueryFragment)[];\n}\n\ninterface PreparedStatementBase<T extends object> {\n query: string;\n values: Primitive[];\n all(): Promise<D1Result<T>>;\n run(): Promise<D1Result>;\n [rowTypeSymbol]: T;\n}\n\ninterface MappedPreparedStatement<TRaw extends object, 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> = 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\nlet batchId = 0;\nconst rowTypeSymbol = Symbol(\"rowType\");\n\nexport function createD1SqlTag(db: D1Database, options?: SqlTagOptions): 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 return sqlTag;\n}\n\nfunction buildPreparedStatement<T extends object>(\n db: D1Database,\n options: SqlTagOptions | undefined,\n templateStrings: TemplateStringsArray,\n templateValues: (Primitive | SqlQueryFragment)[],\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: (Primitive | SqlQueryFragment)[],\n) {\n let query = \"\";\n const values: Primitive[] = [];\n\n function expand(\n templateStrings: TemplateStringsArray,\n templateValues: (Primitive | SqlQueryFragment)[],\n ) {\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,\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,\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,\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","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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","names":["batchId"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "d1-sql-tag",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "A template literal for working with Cloudflare D1 database",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"d1",
|
|
@@ -17,13 +17,17 @@
|
|
|
17
17
|
"type": "git",
|
|
18
18
|
"url": "git+https://github.com/jonasb/d1-sql-tag.git"
|
|
19
19
|
},
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"provenance": true
|
|
22
|
+
},
|
|
20
23
|
"scripts": {
|
|
21
24
|
"build": "tsup src/index.ts --format esm --sourcemap --dts",
|
|
22
25
|
"changeset": "changeset",
|
|
23
26
|
"prettier:check": "prettier --check .",
|
|
24
27
|
"prettier:fix": "prettier --write .",
|
|
25
28
|
"release": "npm run build && npm run test && changeset publish",
|
|
26
|
-
"test": "node --import tsx --test test/sql-tag.test.ts"
|
|
29
|
+
"test": "node --import tsx --test test/sql-tag.test.ts",
|
|
30
|
+
"test:watch": "node --import tsx --watch --test test/sql-tag.test.ts"
|
|
27
31
|
},
|
|
28
32
|
"devDependencies": {
|
|
29
33
|
"@changesets/cli": "^2.27.1",
|