@hivemagnus/ardent-studio 0.1.1 → 0.2.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/README.md CHANGED
@@ -28,7 +28,7 @@ project event stream.
28
28
  | [Oathweave](https://github.com/ChefTaco/Oathweave) | Yes | Sign-in for people (audience `ardentstudio`) and ArdentStudio's own service identity. |
29
29
  | ChatterMost | No | Optional one-way announcements through an incoming webhook. |
30
30
 
31
- Node.js 24.22.1+ or 26.13.0+.
31
+ Node.js 24.22.3+ or 26.13.1+.
32
32
 
33
33
  ## Architecture
34
34
 
@@ -1,6 +1,6 @@
1
- import Database from 'better-sqlite3';
1
+ import Database from './sqlite.js';
2
2
  import { type Migration } from './migrations.js';
3
- export type Db = Database.Database;
3
+ export type Db = Database;
4
4
  export declare class MigrationError extends Error {
5
5
  name: string;
6
6
  }
@@ -1,7 +1,7 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  import { chmodSync, mkdirSync } from 'node:fs';
3
3
  import { dirname } from 'node:path';
4
- import Database from 'better-sqlite3';
4
+ import Database from './sqlite.js';
5
5
  import { MIGRATIONS } from './migrations.js';
6
6
  export class MigrationError extends Error {
7
7
  name = 'MigrationError';
@@ -0,0 +1,30 @@
1
+ import { StatementSync } from '@photostructure/sqlite';
2
+ type Options = {
3
+ readonly?: boolean;
4
+ fileMustExist?: boolean;
5
+ timeout?: number;
6
+ };
7
+ export declare function assertPatchedSqliteVersion(version: unknown): void;
8
+ /** Application storage boundary. Keep transaction ownership on the same connection. */
9
+ declare class Statement {
10
+ private readonly statement;
11
+ constructor(statement: StatementSync);
12
+ run(...parameters: unknown[]): ReturnType<StatementSync['run']>;
13
+ get(...parameters: unknown[]): unknown;
14
+ all(...parameters: unknown[]): unknown[];
15
+ iterate(...parameters: unknown[]): IterableIterator<unknown>;
16
+ }
17
+ export declare class Database {
18
+ #private;
19
+ constructor(path: string, options?: Options);
20
+ get inTransaction(): boolean;
21
+ get open(): boolean;
22
+ prepare(sql: string): Statement;
23
+ exec(sql: string): this;
24
+ pragma(sql: string, options?: {
25
+ simple?: boolean;
26
+ }): unknown;
27
+ transaction<F extends (...args: never[]) => unknown>(fn: F): import("@photostructure/sqlite").TransactionFunction<F>;
28
+ close(): void;
29
+ }
30
+ export default Database;
@@ -0,0 +1,72 @@
1
+ import { pathToFileURL } from 'node:url';
2
+ // The native module bundles patched SQLite independently of the host Node version.
3
+ import { DatabaseSync, enhance } from '@photostructure/sqlite';
4
+ function sqliteOperation(action) {
5
+ try {
6
+ return action();
7
+ }
8
+ catch (error) {
9
+ if (error instanceof Error && 'sqliteCodeName' in error && typeof error.sqliteCodeName === 'string') {
10
+ // Preserve native numeric details while keeping existing busy/locked retry behavior.
11
+ Object.assign(error, { code: error.sqliteCodeName });
12
+ }
13
+ throw error;
14
+ }
15
+ }
16
+ export function assertPatchedSqliteVersion(version) {
17
+ const match = typeof version === 'string' ? /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/.exec(version) : null;
18
+ if (!match)
19
+ throw new Error('Cannot verify embedded SQLite version');
20
+ const [major, minor, patch] = match.slice(1).map(Number);
21
+ if (major === undefined || minor === undefined || patch === undefined ||
22
+ !(major > 3 || (major === 3 && (minor > 54 || (minor === 54 && patch >= 1))))) {
23
+ throw new Error('Embedded SQLite 3.54.1 or later is required');
24
+ }
25
+ }
26
+ /** Application storage boundary. Keep transaction ownership on the same connection. */
27
+ class Statement {
28
+ statement;
29
+ constructor(statement) {
30
+ this.statement = statement;
31
+ }
32
+ run(...parameters) { return sqliteOperation(() => this.statement.run(...parameters)); }
33
+ get(...parameters) { return sqliteOperation(() => this.statement.get(...parameters)); }
34
+ all(...parameters) { return sqliteOperation(() => this.statement.all(...parameters)); }
35
+ iterate(...parameters) { return this.statement.iterate(...parameters); }
36
+ }
37
+ export class Database {
38
+ #database;
39
+ constructor(path, options = {}) {
40
+ let location = path;
41
+ if (options.fileMustExist) {
42
+ if (path === ':memory:')
43
+ throw new Error('An existing on-disk database is required');
44
+ const uri = pathToFileURL(path);
45
+ uri.searchParams.set('mode', options.readonly ? 'ro' : 'rw');
46
+ location = uri;
47
+ }
48
+ this.#database = enhance(new DatabaseSync(location, {
49
+ readOnly: options.readonly ?? false,
50
+ timeout: options.timeout ?? 5000,
51
+ }));
52
+ try {
53
+ const row = this.#database.prepare('SELECT sqlite_version() AS version').get();
54
+ assertPatchedSqliteVersion(row !== null && typeof row === 'object' && 'version' in row ? row.version : undefined);
55
+ }
56
+ catch (error) {
57
+ this.#database.close();
58
+ throw error;
59
+ }
60
+ }
61
+ get inTransaction() { return this.#database.isTransaction; }
62
+ get open() { return this.#database.isOpen; }
63
+ prepare(sql) { return new Statement(sqliteOperation(() => this.#database.prepare(sql))); }
64
+ exec(sql) { sqliteOperation(() => this.#database.exec(sql)); return this; }
65
+ pragma(sql, options) { return sqliteOperation(() => this.#database.pragma(sql, options)); }
66
+ transaction(fn) {
67
+ return this.#database.transaction(fn);
68
+ }
69
+ close() { if (this.#database.isOpen)
70
+ this.#database.close(); }
71
+ }
72
+ export default Database;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hivemagnus/ardent-studio",
3
- "version": "0.1.1",
3
+ "version": "0.2.1",
4
4
  "description": "Ardent Project Studio service: projects, team assignment, conversation room and deliverable review for Ardent agents managed by Magnus",
5
5
  "keywords": [
6
6
  "ardent",
@@ -38,7 +38,7 @@
38
38
  }
39
39
  },
40
40
  "engines": {
41
- "node": "^24.22.1 || ^26.13.0"
41
+ "node": "^24.22.3 || ^26.13.1"
42
42
  },
43
43
  "publishConfig": {
44
44
  "access": "public"
@@ -69,17 +69,16 @@
69
69
  "dependencies": {
70
70
  "@hivemagnus/magnus-contracts": "2.2.0",
71
71
  "@hono/node-server": "^2.1.5",
72
- "better-sqlite3": "^13.0.3",
73
72
  "fflate": "^0.8.3",
74
- "hono": "^4.13.17",
73
+ "hono": "^4.13.18",
75
74
  "jose": "^6.2.15",
76
75
  "pdfjs-dist": "^6.5.438",
77
76
  "yaml": "2.9.1",
78
- "zod": "^4.6.7"
77
+ "zod": "^4.6.7",
78
+ "@photostructure/sqlite": "3.3.1"
79
79
  },
80
80
  "devDependencies": {
81
81
  "@apidevtools/swagger-parser": "^13.1.0",
82
- "@types/better-sqlite3": "^9.6.0",
83
82
  "@types/node": "^24.19.2",
84
83
  "eslint": "10.14.0",
85
84
  "tsx": "^4.23.15",
@@ -88,8 +87,8 @@
88
87
  "vitest": "^5.0.5"
89
88
  },
90
89
  "allowScripts": {
91
- "better-sqlite3@13.0.3": true,
92
- "esbuild@0.28.2": true
90
+ "esbuild@0.28.2": true,
91
+ "@photostructure/sqlite@3.3.1": true
93
92
  },
94
93
  "overrides": {
95
94
  "minimatch": "11.0.5"