Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions types/koa/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ declare class Application<
* @param {number} [options.subdomainOffset] Subdomain offset
* @param {string} [options.proxyIpHeader] Proxy IP header, defaults to X-Forwarded-For
* @param {number} [options.maxIpsCount] Max IPs read from proxy IP header, default to 0 (means infinity)
* @param {boolean} [options.asyncLocalStorage] Enable AsyncLocalStorage
* @param {boolean|AsyncLocalStorage} [options.asyncLocalStorage] Pass `true` or an instance of `AsyncLocalStorage` to enable async local storage
*/
constructor(options?: {
env?: string | undefined;
Expand All @@ -474,7 +474,7 @@ declare class Application<
subdomainOffset?: number | undefined;
proxyIpHeader?: string | undefined;
maxIpsCount?: number | undefined;
asyncLocalStorage?: boolean | undefined;
asyncLocalStorage?: boolean | AsyncLocalStorage<ContextT> | undefined;
});

/**
Expand Down
50 changes: 36 additions & 14 deletions types/koa/test/constructor.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,41 @@
import Koa = require("koa");
import assert from "node:assert/strict";
import { AsyncLocalStorage } from "node:async_hooks";

const app = new Koa({
env: "abc",
keys: ["im a newer secret", "i like turtle"],
proxy: true,
subdomainOffset: 2,
proxyIpHeader: "XYZ-Forwarded-For",
maxIpsCount: 2,
asyncLocalStorage: true,
});
{
const app = new Koa({
env: "abc",
keys: ["im a newer secret", "i like turtle"],
proxy: true,
subdomainOffset: 2,
proxyIpHeader: "XYZ-Forwarded-For",
maxIpsCount: 2,
asyncLocalStorage: true,
});

app.use(ctx => {
ctx.body = "Hello World";
});
app.use(ctx => {
ctx.body = "Hello World";
});

app.listen(3000);
app.listen(3000);
}

const server = app.listen();
{
const asyncLocalStorage = new AsyncLocalStorage<Koa.Context>();
const app = new Koa({ asyncLocalStorage });

assert(app.currentContext === undefined);

app.use(async (ctx, next) => {
callSomeFunction();
ctx.body = "ok";
await next();
});

function callSomeFunction() {
const ctx = asyncLocalStorage.getStore();
assert(ctx === app.currentContext);
}

app.listen();
}
39 changes: 39 additions & 0 deletions types/sql.js/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ type ParamsCallback = (obj: ParamsObject) => void;
type SqlJsConfig = Partial<EmscriptenModule>;
type BindParams = SqlValue[] | ParamsObject | null;

type UpdateHookOperation = "insert" | "update" | "delete";
type UpdateHookCallback = (
operation: UpdateHookOperation,
database: string,
table: string,
rowId: number,
) => void;

interface QueryExecResult {
columns: string[];
values: SqlValue[][];
Expand Down Expand Up @@ -149,6 +157,36 @@ declare class Database {
* `;`). This limitation does not apply to params as an object.
*/
run(sql: string, params?: BindParams): Database;

/** Registers an update hook with SQLite.
*
* Every time a row is changed by whatever means, the callback is called
* once with the change (`'insert'`, `'update'` or `'delete'`), the database
* name and table name where the change happened and the
* [rowid](https://www.sqlite.org/rowidtable.html)
* of the row that has been changed.
*
* The rowid is cast to a plain number. If it exceeds
* `Number.MAX_SAFE_INTEGER` (2^53 - 1), an error will be thrown.
*
* **Important notes:**
* - The callback **MUST NOT** modify the database in any way
* - Only a single callback can be registered at a time
* - Unregister the callback by passing `null`
* - Not called for some updates like `ON REPLACE CONFLICT` and `TRUNCATE`
* (a `DELETE FROM` without a `WHERE` clause)
*
* See SQLite documentation on
* [sqlite3_update_hook](https://www.sqlite.org/c3ref/update_hook.html)
* for more details
*
* @param callback
* - Callback to be executed when a row changes. Takes the type of change,
* the name of the database, the name of the table, and the row id of the
* changed row.
* - Set to `null` to unregister.
*/
updateHook(callback: UpdateHookCallback | null): Database;
}

declare class Statement {
Expand Down Expand Up @@ -290,6 +328,7 @@ declare namespace initSqlJs {
// types
SqlValue,
StatementIteratorResult,
UpdateHookCallback,
};

// classes
Expand Down
5 changes: 5 additions & 0 deletions types/sql.js/sql.js-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ initSqlJs().then(SqlJs => {
+ "CREATE TABLE test_table (id INTEGER PRIMARY KEY, content TEXT);";
db.run(createTableStatement);

// Register handler for database changes
db.updateHook((operation, database, table, rowId) => {
console.log("SQLite database is updated", { operation, database, table, rowId });
});

// Insert 2 records for testing.
const insertRecordStatement = "INSERT INTO test_table (id, content) VALUES (@id, @content);";
db.run(insertRecordStatement, {
Expand Down