neosqlite 1.0.0

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.
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.NeosqliteJobs = void 0;
7
+ const cron_parser_1 = __importDefault(require("cron-parser"));
8
+ const chrono_node_1 = require("chrono-node");
9
+ const client_1 = require("../client");
10
+ const util_1 = require("../client/util");
11
+ const types_1 = require("../types");
12
+ class NeosqliteJobs {
13
+ constructor(options) {
14
+ this.jobsRegistry = {};
15
+ // Jobs worker information
16
+ this.activeJobs = 0;
17
+ this.isRunning = false;
18
+ this.options = options;
19
+ this.db = (0, client_1.createClient)(options);
20
+ }
21
+ get jobsTable() {
22
+ return this.options.jobsTable ?? "jobs";
23
+ }
24
+ get maxJobs() {
25
+ return this.options.maxJobs ?? 10;
26
+ }
27
+ get processEvery() {
28
+ return this.options.processEvery ?? 5000;
29
+ }
30
+ get maxRetries() {
31
+ return this.options.maxRetries ?? 3;
32
+ }
33
+ /**
34
+ * Setup tables and start the job worker for neosqlite jobs
35
+ */
36
+ async start() {
37
+ await this.setupTables();
38
+ await this.setupJobWorker();
39
+ }
40
+ /**
41
+ * Stop the job worker from listening for jobs
42
+ */
43
+ async stop() {
44
+ this.isRunning = false;
45
+ }
46
+ /**
47
+ * Register a job to be run
48
+ */
49
+ register(name, options, fn, onFailure) {
50
+ this.jobsRegistry[name] = { name, options, fn, onFailure };
51
+ }
52
+ /**
53
+ * Queue a job to run instantly based on its
54
+ * priority
55
+ */
56
+ async queue(name, data) {
57
+ const job = this.jobsRegistry[name];
58
+ if (!job)
59
+ return console.error(`Job ${name} does not exist`);
60
+ this.db.write({
61
+ sql: (0, util_1.queryString)("INSERT INTO " + this.jobsTable, "(name, data, runAt, priority)", "VALUES (:name, :data, CURRENT_TIMESTAMP, :priority)"),
62
+ args: {
63
+ name: job.name,
64
+ priority: job.options.priority ?? 0,
65
+ data: data ? JSON.stringify(data) : null,
66
+ },
67
+ });
68
+ }
69
+ /**
70
+ * Schedule a job to run in the future. This can use a date string, or a human-readable string
71
+ * such as 'in 10 minutes' or 'next week'
72
+ */
73
+ async schedule(date, name, data) {
74
+ const job = this.jobsRegistry[name];
75
+ if (!job)
76
+ return console.error(`Job ${name} does not exist`);
77
+ const parsedDate = (0, chrono_node_1.parseDate)(date);
78
+ if (!parsedDate)
79
+ return;
80
+ this.db.write({
81
+ sql: (0, util_1.queryString)("INSERT INTO " + this.jobsTable, "(name, data, runAt, priority)", "VALUES (:name, :data, :runAt, :priority)"),
82
+ args: {
83
+ name: job.name,
84
+ priority: job.options.priority ?? 0,
85
+ data: data ? JSON.stringify(data) : null,
86
+ runAt: (0, util_1.toSqliteDateString)(parsedDate),
87
+ },
88
+ });
89
+ }
90
+ /**
91
+ * Schedule a job to run every time the cron string is met
92
+ */
93
+ async every(cronString, name, data) {
94
+ const job = this.jobsRegistry[name];
95
+ if (!job)
96
+ return console.error(`Job ${name} does not exist`);
97
+ const interval = cron_parser_1.default.parse(cronString);
98
+ const runAt = interval.next().toDate();
99
+ this.db.write({
100
+ sql: (0, util_1.queryString)("INSERT OR IGNORE INTO " + this.jobsTable, "(name, data, runAt, priority, cron)", "VALUES (:name, :data, :runAt, :priority, :cron)"),
101
+ args: {
102
+ name: job.name,
103
+ priority: job.options.priority ?? 0,
104
+ data: data ? JSON.stringify(data) : null,
105
+ runAt: (0, util_1.toSqliteDateString)(runAt),
106
+ cron: cronString,
107
+ },
108
+ });
109
+ }
110
+ /**
111
+ * Creates the jobs table and sets up indexes on it
112
+ */
113
+ async setupTables() {
114
+ const jobStatuses = Object.values(types_1.JobStatus)
115
+ .map((s) => `'${s}'`)
116
+ .join(", ");
117
+ this.db.write((0, util_1.queryString)("CREATE TABLE IF NOT EXISTS " + this.jobsTable + " (", " id INTEGER PRIMARY KEY AUTOINCREMENT,", " name TEXT NOT NULL,", " data TEXT,", " runAt DATETIME NOT NULL,", " priority INTEGER DEFAULT 0,", " cron TEXT,", " attempts INTEGER DEFAULT 0,", " status TEXT CHECK (status IN ( " + jobStatuses + ")) DEFAULT '" + types_1.JobStatus.Pending + "',", " updatedAt DATETIME DEFAULT CURRENT_TIMESTAMP,", " createdAt DATETIME DEFAULT CURRENT_TIMESTAMP", ")"));
118
+ // Prevent multiple cron jobs from getting scheduled for the same dates
119
+ this.db.write(`CREATE UNIQUE INDEX IF NOT EXISTS idx_${this.jobsTable}_name_cron_runAt ON ${this.jobsTable} (name, cron, runAt)`);
120
+ this.db.write(`CREATE INDEX IF NOT EXISTS idx_${this.jobsTable}_status_runAt_priority ON ${this.jobsTable} (status, runAt, priority DESC)`);
121
+ }
122
+ /**
123
+ * Sets up the jobs worker to run automatically
124
+ */
125
+ async setupJobWorker() {
126
+ if (this.isRunning)
127
+ return;
128
+ this.isRunning = true;
129
+ const loop = async () => {
130
+ if (!this.isRunning)
131
+ return;
132
+ try {
133
+ if (this.activeJobs < this.maxJobs) {
134
+ const limit = this.maxJobs - this.activeJobs;
135
+ const rows = this.db.writeReturning({
136
+ sql: (0, util_1.queryString)("UPDATE jobs", "SET status = :runningStatus,", " attempts = attempts + 1,", " updatedAt = CURRENT_TIMESTAMP", "WHERE id IN (", " SELECT id", " FROM jobs", " WHERE status = :pendingStatus", " AND runAt <= CURRENT_TIMESTAMP", " ORDER BY priority DESC, runAt ASC", " LIMIT :limit", ")", "RETURNING *"),
137
+ args: {
138
+ limit,
139
+ pendingStatus: types_1.JobStatus.Pending,
140
+ runningStatus: types_1.JobStatus.Running,
141
+ },
142
+ });
143
+ for (const row of rows) {
144
+ this.activeJobs++;
145
+ this.processJob(row).finally(() => {
146
+ this.activeJobs--;
147
+ });
148
+ }
149
+ }
150
+ }
151
+ catch (err) {
152
+ console.error(err);
153
+ }
154
+ setTimeout(loop, this.processEvery);
155
+ };
156
+ loop();
157
+ }
158
+ async processJob(row) {
159
+ const id = Number(row["id"]);
160
+ const name = String(row["name"]);
161
+ const attempts = Number(row["attempts"]);
162
+ const cron = row["cron"] ? String(row["cron"]) : null;
163
+ const data = row["data"] ? (0, util_1.Jsonify)(String(row["data"])) : null;
164
+ const job = this.jobsRegistry[name];
165
+ if (!job)
166
+ return;
167
+ try {
168
+ await Promise.resolve(job.fn(data));
169
+ this.db.write({
170
+ sql: (0, util_1.queryString)("UPDATE " + this.jobsTable, "SET status = :status, updatedAt = CURRENT_TIMESTAMP", "WHERE id = :id"),
171
+ args: { id, status: types_1.JobStatus.Completed },
172
+ });
173
+ // If this is a cronjob, schedule the next run
174
+ if (cron) {
175
+ const interval = cron_parser_1.default.parse(cron);
176
+ const nextRun = interval.next().toDate();
177
+ this.db.write({
178
+ sql: (0, util_1.queryString)("INSERT OR IGNORE INTO " + this.jobsTable, "(name, data, runAt, priority, cron)", "VALUES (:name, :data, :runAt, :priority, :cron)"),
179
+ args: {
180
+ cron,
181
+ name: job.name,
182
+ priority: job.options.priority ?? 0,
183
+ data: data ? JSON.stringify(data) : null,
184
+ runAt: (0, util_1.toSqliteDateString)(nextRun),
185
+ },
186
+ });
187
+ }
188
+ }
189
+ catch (err) {
190
+ const updatedStatus = attempts >= this.maxRetries ? types_1.JobStatus.Failed : types_1.JobStatus.Pending;
191
+ this.db.write({
192
+ sql: (0, util_1.queryString)("UPDATE " + this.jobsTable, "SET status = :status, updatedAt = CURRENT_TIMESTAMP", "WHERE id = :id"),
193
+ args: { id, status: updatedStatus },
194
+ });
195
+ if (updatedStatus === types_1.JobStatus.Failed && job.onFailure) {
196
+ await Promise.resolve(job.onFailure(err));
197
+ }
198
+ }
199
+ }
200
+ }
201
+ exports.NeosqliteJobs = NeosqliteJobs;
@@ -0,0 +1,2 @@
1
+ import type { CliCommandOptions } from "../../types";
2
+ export default function Down({ migrationTable, migrationPath, ...config }: CliCommandOptions): Promise<void>;
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.default = Down;
40
+ const promises_1 = __importDefault(require("fs/promises"));
41
+ const client_1 = require("../../client");
42
+ const util_1 = require("../util");
43
+ async function Down({ migrationTable, migrationPath, ...config }) {
44
+ const db = (0, client_1.createClient)(config);
45
+ await (0, util_1.validateMigrationDirectory)(migrationPath);
46
+ (0, util_1.createMigrationTableIfNotExists)(db, migrationTable);
47
+ // Query the last migration that was ran
48
+ const result = db.readOne("SELECT id, filepath FROM " + migrationTable + " ORDER BY timestamp DESC LIMIT 1");
49
+ if (!result) {
50
+ (0, util_1.logError)("No migrations have been ran");
51
+ process.exit(0);
52
+ }
53
+ const id = String(result["id"]);
54
+ const filepath = String(result["filepath"]);
55
+ const files = await promises_1.default.readdir(migrationPath);
56
+ const matchingFile = files.filter((file) => {
57
+ const fileName = file.split(".")[0];
58
+ return fileName === filepath;
59
+ });
60
+ if (!matchingFile.length) {
61
+ (0, util_1.logError)(`Unable to find migration ${filepath}`);
62
+ process.exit(0);
63
+ }
64
+ const migration = (await Promise.resolve(`${`${migrationPath}/${matchingFile[0]}`}`).then(s => __importStar(require(s)))).default;
65
+ // Run the migration
66
+ db.transaction(() => migration.down(db));
67
+ // Store the migration data
68
+ db.write({
69
+ sql: "DELETE FROM " + migrationTable + " WHERE id = :id",
70
+ args: { id },
71
+ });
72
+ (0, util_1.logSuccess)(`Reverted migration ${filepath}`);
73
+ process.exit(0);
74
+ }
@@ -0,0 +1,6 @@
1
+ import { CliCommandOptions } from "../../types";
2
+ interface NewCommandOptions extends CliCommandOptions {
3
+ name: string;
4
+ }
5
+ export default function New({ name, migrationPath }: NewCommandOptions): Promise<void>;
6
+ export {};
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = New;
4
+ const promises_1 = require("fs/promises");
5
+ const util_1 = require("../util");
6
+ async function New({ name, migrationPath }) {
7
+ const epochTime = Date.now();
8
+ const fileName = `${epochTime}_${name}.ts`;
9
+ const fileContents = `
10
+ import type { NeosqliteClient } from 'neosqlite';
11
+
12
+ export default class Migration_${epochTime}_${name} {
13
+ public static async up(db: NeosqliteClient) {
14
+ // Add your migration logic here
15
+ }
16
+
17
+ public static async down(db: NeosqliteClient) {
18
+ // Add your rollback logic here
19
+ }
20
+ }
21
+ `;
22
+ await (0, promises_1.mkdir)(migrationPath, { recursive: true }).catch((e) => (0, util_1.logError)(e.message));
23
+ await (0, promises_1.writeFile)(`${migrationPath}/${fileName}`, fileContents).catch((e) => (0, util_1.logError)(e.message));
24
+ (0, util_1.logSuccess)(`Created migration ${fileName}`);
25
+ process.exit(0);
26
+ }
@@ -0,0 +1,2 @@
1
+ import { CliCommandOptions } from "../../types";
2
+ export default function Up({ migrationPath, migrationTable, ...config }: CliCommandOptions): Promise<void>;
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.default = Up;
40
+ const promises_1 = __importDefault(require("fs/promises"));
41
+ const client_1 = require("../../client");
42
+ const util_1 = require("../util");
43
+ async function Up({ migrationPath, migrationTable, ...config }) {
44
+ const db = (0, client_1.createClient)(config);
45
+ await (0, util_1.validateMigrationDirectory)(migrationPath);
46
+ (0, util_1.createMigrationTableIfNotExists)(db, migrationTable);
47
+ // Query all of the migrations that have already been ran
48
+ const result = db.read("SELECT filepath FROM " + migrationTable);
49
+ const migratedFiles = result.map((row) => String(row["filepath"]));
50
+ const files = await promises_1.default.readdir(migrationPath);
51
+ const migrationFiles = files.filter((file) => {
52
+ const fileName = file.split(".")[0];
53
+ return (file.endsWith(".ts") || file.endsWith(".js")) && !migratedFiles.includes(fileName);
54
+ });
55
+ if (!migrationFiles.length) {
56
+ (0, util_1.logWarn)("No migrations to run");
57
+ process.exit(0);
58
+ }
59
+ // Sort the files by timestamp, in ascending order so that they run in the order they were created
60
+ migrationFiles.sort((a, b) => {
61
+ const aTimestamp = parseInt(a.split("_")[0]);
62
+ const bTimestamp = parseInt(b.split("_")[0]);
63
+ return aTimestamp - bTimestamp;
64
+ });
65
+ // Apply the migrations
66
+ for (const fileName of migrationFiles) {
67
+ const migration = (await Promise.resolve(`${`${migrationPath}/${fileName}`}`).then(s => __importStar(require(s)))).default;
68
+ const normalizedFileName = fileName.split(".")[0];
69
+ // Run the migration
70
+ db.transaction(() => migration.up(db));
71
+ // Store the migration data
72
+ db.write({
73
+ sql: "INSERT INTO " + migrationTable + "(filepath, timestamp) VALUES (:filepath, :timestamp)",
74
+ args: { filepath: normalizedFileName, timestamp: Date.now() },
75
+ });
76
+ (0, util_1.logSuccess)(`Applied migration ${fileName}`);
77
+ }
78
+ (0, util_1.logSuccess)(`Successfully ran ${migrationFiles.length} migration(s)`);
79
+ process.exit(0);
80
+ }
@@ -0,0 +1,6 @@
1
+ import { CliCommandOptions, NeosqliteClient } from "../types";
2
+ export interface MigrationFile {
3
+ up: (db: NeosqliteClient) => void;
4
+ down: (db: NeosqliteClient) => void;
5
+ }
6
+ export declare function createNeosqliteMigrationCli(props: CliCommandOptions): void;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createNeosqliteMigrationCli = createNeosqliteMigrationCli;
7
+ const commander_1 = require("commander");
8
+ const up_1 = __importDefault(require("./commands/up"));
9
+ const new_1 = __importDefault(require("./commands/new"));
10
+ const down_1 = __importDefault(require("./commands/down"));
11
+ const package_json_1 = __importDefault(require("../../package.json"));
12
+ function createNeosqliteMigrationCli(props) {
13
+ props.migrationTable = props.migrationTable ?? "migrations";
14
+ const program = new commander_1.Command();
15
+ program.name("migrate").description("Migration CLI").version(package_json_1.default.version);
16
+ program
17
+ .command("up")
18
+ .description("Apply all unapplied migrations")
19
+ .action(() => (0, up_1.default)(props));
20
+ program
21
+ .command("down")
22
+ .description("Undo the last migration")
23
+ .action(() => (0, down_1.default)(props));
24
+ program
25
+ .command("new")
26
+ .option("-n, --name <name>", "The name of the migration")
27
+ .action((options) => {
28
+ if (!options.name) {
29
+ console.error("Please provide a name for the migration. Use the --name flag");
30
+ process.exit(1);
31
+ }
32
+ (0, new_1.default)({ ...props, name: options.name });
33
+ });
34
+ program.parse(process.argv);
35
+ }
@@ -0,0 +1,9 @@
1
+ import { NeosqliteClient } from "../types";
2
+ export declare const logSuccess: (message: string) => void;
3
+ export declare const logError: (message: string) => void;
4
+ export declare const logWarn: (message: string) => void;
5
+ export declare const createMigrationTableIfNotExists: (db: NeosqliteClient, migrationTable?: string) => {
6
+ changes: number;
7
+ lastInsertedRowid: number;
8
+ };
9
+ export declare const validateMigrationDirectory: (migrationPath: string) => Promise<void>;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.validateMigrationDirectory = exports.createMigrationTableIfNotExists = exports.logWarn = exports.logError = exports.logSuccess = void 0;
7
+ const promises_1 = __importDefault(require("fs/promises"));
8
+ const util_1 = require("../client/util");
9
+ const RESET = "\x1b[0m";
10
+ const RED = "\x1b[31m";
11
+ const GREEN = "\x1b[32m";
12
+ const YELLOW = "\x1b[33m";
13
+ const CHECK = "✔";
14
+ const CROSS = "✖";
15
+ const WARN = "⚠";
16
+ const logSuccess = (message) => {
17
+ console.log(`${GREEN}${CHECK}${RESET} ${message}`);
18
+ };
19
+ exports.logSuccess = logSuccess;
20
+ const logError = (message) => {
21
+ console.log(`${RED}${CROSS}${RESET} ${message}`);
22
+ };
23
+ exports.logError = logError;
24
+ const logWarn = (message) => {
25
+ console.log(`${YELLOW}${WARN}${RESET} ${message}`);
26
+ };
27
+ exports.logWarn = logWarn;
28
+ const createMigrationTableIfNotExists = (db, migrationTable = "migrations") => {
29
+ return db.write({
30
+ sql: (0, util_1.queryString)("CREATE TABLE IF NOT EXISTS " + migrationTable + "(", " id INTEGER PRIMARY KEY AUTOINCREMENT,", " filepath TEXT,", " timestamp INTEGER", ")"),
31
+ });
32
+ };
33
+ exports.createMigrationTableIfNotExists = createMigrationTableIfNotExists;
34
+ const validateMigrationDirectory = async (migrationPath) => {
35
+ try {
36
+ await promises_1.default.access(migrationPath);
37
+ }
38
+ catch (e) {
39
+ (0, exports.logError)("Unable to find the migration directory. Make sure it exists");
40
+ process.exit(0);
41
+ }
42
+ };
43
+ exports.validateMigrationDirectory = validateMigrationDirectory;
@@ -0,0 +1,75 @@
1
+ import type { BackupMetadata, BackupOptions, PragmaOptions } from "better-sqlite3";
2
+ export type NeosqliteConfig = {
3
+ /** The filename of the database */
4
+ file: ":memory:" | string;
5
+ /** When a query is logged using `logQuery: true`, you will receive the full query string via this callback */
6
+ onQueryLog?: (query: string) => void;
7
+ /** When a query finishes, gather data about the query from this callback */
8
+ onQueryComplete?: (data: OnQueryFinishData) => void;
9
+ };
10
+ export type NeosqliteClient = {
11
+ /** Call a pragma */
12
+ pragma: (source: string, options?: PragmaOptions | undefined) => unknown;
13
+ /** Backup the database */
14
+ backup: (destinationFile: string, options?: BackupOptions | undefined) => Promise<BackupMetadata>;
15
+ /** Create a transaction and execute queries within it */
16
+ transaction: (fn: Function) => void;
17
+ /** Read data from the database, returns all matching rows */
18
+ read: (params: ExecuteQueryParams) => Row[];
19
+ /** Read data from the database, returns the first matching row */
20
+ readOne: (params: ExecuteQueryParams) => Row | undefined;
21
+ /** Write data to the database, returns all matching rows via RETURNING */
22
+ writeReturning: (params: ExecuteQueryParams) => Row[];
23
+ /** Write data to the database, returns the number of rows affected */
24
+ write: (params: ExecuteQueryParams) => {
25
+ changes: number;
26
+ lastInsertedRowid: number;
27
+ };
28
+ };
29
+ export type OnQueryFinishData = {
30
+ /** The query that was executed */
31
+ query: string;
32
+ /** The time it took to execute the query in milliseconds */
33
+ time: number;
34
+ };
35
+ export type QueryParams = {
36
+ /** The SQL query to execute */
37
+ sql: string;
38
+ /** When true, the query string will be sent to onQueryLog */
39
+ logQuery?: boolean;
40
+ /** The values to bind to the query string */
41
+ args?: Record<string, number | string | boolean | null>;
42
+ };
43
+ export type Row = Record<string, number | string | boolean | null>;
44
+ export type ExecuteQueryParams = string | QueryParams;
45
+ export declare enum JobPriority {
46
+ Low = 1,
47
+ Medium = 2,
48
+ High = 3
49
+ }
50
+ export declare enum JobStatus {
51
+ Pending = "pending",
52
+ Running = "running",
53
+ Failed = "failed",
54
+ Completed = "completed"
55
+ }
56
+ export interface CliCommandOptions extends NeosqliteConfig {
57
+ /** The path containing the migration files */
58
+ migrationPath: string;
59
+ /** The name of the table to store migrations in. Defaults to "migrations" */
60
+ migrationTable?: string;
61
+ }
62
+ export interface CreateJobsOptions extends NeosqliteConfig {
63
+ /** The name of the table to store jobs in. Defaults to "jobs" */
64
+ jobsTable?: string;
65
+ /** How often to process jobs in milliseconds. Defaults to 5000 */
66
+ processEvery?: number;
67
+ /** The maximum number of retries for each job. Defaults to 3 */
68
+ maxRetries?: number;
69
+ /** The maximum number of jobs to execute at once. Defaults to 10 */
70
+ maxJobs?: number;
71
+ }
72
+ export interface JobOptions {
73
+ /** The priority of the job */
74
+ priority?: number;
75
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JobStatus = exports.JobPriority = void 0;
4
+ var JobPriority;
5
+ (function (JobPriority) {
6
+ JobPriority[JobPriority["Low"] = 1] = "Low";
7
+ JobPriority[JobPriority["Medium"] = 2] = "Medium";
8
+ JobPriority[JobPriority["High"] = 3] = "High";
9
+ })(JobPriority || (exports.JobPriority = JobPriority = {}));
10
+ var JobStatus;
11
+ (function (JobStatus) {
12
+ JobStatus["Pending"] = "pending";
13
+ JobStatus["Running"] = "running";
14
+ JobStatus["Failed"] = "failed";
15
+ JobStatus["Completed"] = "completed";
16
+ })(JobStatus || (exports.JobStatus = JobStatus = {}));
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "neosqlite",
3
+ "description": "A lightweight wrapper around better-sqlite3 that adds developer-friendly features like job scheduling, migrations, error handling, query logging, SQL utilities, and more",
4
+ "version": "1.0.0",
5
+ "main": "lib/src/index.js",
6
+ "scripts": {
7
+ "build": "tsc",
8
+ "prepare": "npm run build"
9
+ },
10
+ "keywords": [
11
+ "sqlite",
12
+ "database",
13
+ "neosqlite"
14
+ ],
15
+ "author": "JS00001",
16
+ "license": "ISC",
17
+ "dependencies": {
18
+ "better-sqlite3": "^12.6.2",
19
+ "chrono-node": "^2.8.4",
20
+ "commander": "^14.0.1",
21
+ "cron-parser": "^5.4.0"
22
+ },
23
+ "devDependencies": {
24
+ "@types/better-sqlite3": "^7.6.13",
25
+ "tsx": "^4.20.5",
26
+ "typescript": "^5.9.2"
27
+ },
28
+ "publishConfig": {
29
+ "access": "public"
30
+ }
31
+ }