@moriajs/db 0.3.5 → 0.4.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.
@@ -1,4 +1,4 @@
1
1
 
2
- > @moriajs/db@0.3.5 build C:\Codes\node\2026\github\moriajs\packages\db
2
+ > @moriajs/db@0.4.0 build C:\Codes\node\2026\github\moriajs\packages\db
3
3
  > tsc
4
4
 
package/dist/index.d.ts CHANGED
@@ -1,25 +1,21 @@
1
- /**
2
- * @moriajs/db
3
- *
4
- * Database-agnostic adapter layer built on Kysely.
5
- * Default: PostgreSQL (production), SQLite (development).
6
- * Designed to work with kysely-schema for schema-first development.
7
- */
8
- import { Kysely } from 'kysely';
1
+ import { MoriaDB, MoriaDBAdapter } from './types.js';
2
+ export * from './types.js';
9
3
  /**
10
4
  * Supported database adapters.
11
5
  */
12
- export type DatabaseAdapter = 'pg' | 'sqlite' | 'mysql';
6
+ export type DatabaseAdapterName = 'pg' | 'sqlite' | 'mysql';
13
7
  /**
14
8
  * Configuration for creating a database connection.
15
9
  */
16
10
  export interface DatabaseConfig {
17
- /** Database adapter to use */
18
- adapter: DatabaseAdapter;
19
- /** Connection URL (for pg/mysql) */
11
+ /** Database adapter name to use */
12
+ adapter: DatabaseAdapterName;
13
+ /** Connection URL (for pg/mysql/pongo) */
20
14
  url?: string;
21
15
  /** File path (for sqlite) */
22
16
  filename?: string;
17
+ /** Whether to use Pongo (Document API) instead of Kysely (SQL API) for Postgres */
18
+ usePongo?: boolean;
23
19
  /** Connection pool size */
24
20
  pool?: {
25
21
  min?: number;
@@ -27,45 +23,49 @@ export interface DatabaseConfig {
27
23
  };
28
24
  }
29
25
  /**
30
- * Create a Kysely database instance with the specified adapter.
31
- *
32
- * @example
33
- * ```ts
34
- * // Production (PostgreSQL)
35
- * const db = await createDatabase({
36
- * adapter: 'pg',
37
- * url: process.env.DATABASE_URL,
38
- * });
39
- *
40
- * // Development (SQLite)
41
- * const db = await createDatabase({
42
- * adapter: 'sqlite',
43
- * filename: './dev.db',
44
- * });
45
- * ```
26
+ * Kysely Adapter Implementation (SQL)
27
+ */
28
+ export declare class KyselyAdapter implements MoriaDBAdapter {
29
+ private config;
30
+ private db;
31
+ constructor(config: DatabaseConfig);
32
+ connect(): Promise<void>;
33
+ disconnect(): Promise<void>;
34
+ private createDialect;
35
+ find<T>(collection: string, filter?: any): Promise<T[]>;
36
+ findOne<T>(collection: string, filter?: any): Promise<T | null>;
37
+ insertOne<T>(collection: string, data: any): Promise<T>;
38
+ updateOne(collection: string, filter: any, data: any): Promise<void>;
39
+ deleteOne(collection: string, filter: any): Promise<void>;
40
+ raw<T>(): T;
41
+ }
42
+ /**
43
+ * Pongo Adapter Implementation (Document Store on Postgres)
44
+ */
45
+ export declare class PongoAdapter implements MoriaDBAdapter {
46
+ private config;
47
+ private client;
48
+ constructor(config: DatabaseConfig);
49
+ connect(): Promise<void>;
50
+ disconnect(): Promise<void>;
51
+ find<T extends Record<string, any> = any>(collection: string, filter?: any): Promise<T[]>;
52
+ findOne<T extends Record<string, any> = any>(collection: string, filter?: any): Promise<T | null>;
53
+ insertOne<T extends Record<string, any> = any>(collection: string, data: any): Promise<T>;
54
+ updateOne(collection: string, filter: any, data: any): Promise<void>;
55
+ deleteOne(collection: string, filter: any): Promise<void>;
56
+ raw<T>(): T;
57
+ }
58
+ /**
59
+ * Factory to create a MoriaDB instance.
46
60
  */
47
- export declare function createDatabase<T>(config: DatabaseConfig): Promise<Kysely<T>>;
61
+ export declare function createDatabase(config: DatabaseConfig): Promise<MoriaDB>;
48
62
  /**
49
- * Create a MoriaJS database plugin for Fastify integration.
50
- *
51
- * @example
52
- * ```ts
53
- * import { createApp } from '@moriajs/core';
54
- * import { createDatabasePlugin } from '@moriajs/db';
55
- *
56
- * const app = await createApp();
57
- * await app.use(createDatabasePlugin({
58
- * adapter: 'sqlite',
59
- * filename: './dev.db',
60
- * }));
61
- * ```
63
+ * MoriaJS database plugin for Fastify integration.
62
64
  */
63
65
  export declare function createDatabasePlugin(config: DatabaseConfig): {
64
66
  name: string;
65
67
  register({ server }: {
66
- server: {
67
- decorate: (key: string, value: unknown) => void;
68
- };
68
+ server: any;
69
69
  }): Promise<void>;
70
70
  };
71
71
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAkC,MAAM,QAAQ,CAAC;AAEhE;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG,QAAQ,GAAG,OAAO,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,8BAA8B;IAC9B,OAAO,EAAE,eAAe,CAAC;IACzB,oCAAoC;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2BAA2B;IAC3B,IAAI,CAAC,EAAE;QACH,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACL;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAGlF;AA0CD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc;;yBAGxB;QAAE,MAAM,EAAE;YAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;SAAE,CAAA;KAAE;EAKjG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAErD,cAAc,YAAY,CAAC;AAE3B;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,IAAI,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,mCAAmC;IACnC,OAAO,EAAE,mBAAmB,CAAC;IAC7B,0CAA0C;IAC1C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mFAAmF;IACnF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2BAA2B;IAC3B,IAAI,CAAC,EAAE;QACH,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACL;AAED;;GAEG;AACH,qBAAa,aAAc,YAAW,cAAc;IAGpC,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,EAAE,CAA4B;gBAElB,MAAM,EAAE,cAAc;IAEpC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAKxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YAMnB,aAAa;IAyBrB,IAAI,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAE,GAAQ,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAQ3D,OAAO,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAE,GAAQ,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IASnE,SAAS,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC;IASvD,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAQpE,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ/D,GAAG,CAAC,CAAC,KAAK,CAAC;CAGd;AAED;;GAEG;AACH,qBAAa,YAAa,YAAW,cAAc;IAGnC,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,MAAM,CAA4B;gBAEtB,MAAM,EAAE,cAAc;IAEpC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAQxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAM3B,IAAI,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAE,GAAQ,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAI7F,OAAO,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAE,GAAQ,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAIrG,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC;IAKzF,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpE,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/D,GAAG,CAAC,CAAC,KAAK,CAAC;CAGd;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAY7E;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc;;yBAGxB;QAAE,MAAM,EAAE,GAAG,CAAA;KAAE;EASjD"}
package/dist/index.js CHANGED
@@ -1,81 +1,148 @@
1
- /**
2
- * @moriajs/db
3
- *
4
- * Database-agnostic adapter layer built on Kysely.
5
- * Default: PostgreSQL (production), SQLite (development).
6
- * Designed to work with kysely-schema for schema-first development.
7
- */
8
1
  import { Kysely, PostgresDialect, SqliteDialect } from 'kysely';
2
+ import { pongoClient } from '@event-driven-io/pongo';
3
+ import { MoriaDB } from './types.js';
4
+ export * from './types.js';
9
5
  /**
10
- * Create a Kysely database instance with the specified adapter.
11
- *
12
- * @example
13
- * ```ts
14
- * // Production (PostgreSQL)
15
- * const db = await createDatabase({
16
- * adapter: 'pg',
17
- * url: process.env.DATABASE_URL,
18
- * });
19
- *
20
- * // Development (SQLite)
21
- * const db = await createDatabase({
22
- * adapter: 'sqlite',
23
- * filename: './dev.db',
24
- * });
25
- * ```
6
+ * Kysely Adapter Implementation (SQL)
26
7
  */
27
- export async function createDatabase(config) {
28
- const dialect = await createDialect(config);
29
- return new Kysely({ dialect });
8
+ export class KyselyAdapter {
9
+ config;
10
+ db = null;
11
+ constructor(config) {
12
+ this.config = config;
13
+ }
14
+ async connect() {
15
+ const dialect = await this.createDialect(this.config);
16
+ this.db = new Kysely({ dialect });
17
+ }
18
+ async disconnect() {
19
+ if (this.db) {
20
+ await this.db.destroy();
21
+ }
22
+ }
23
+ async createDialect(config) {
24
+ switch (config.adapter) {
25
+ case 'pg': {
26
+ // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-explicit-any
27
+ const pg = globalThis.require('pg');
28
+ return new PostgresDialect({
29
+ pool: new pg.Pool({
30
+ connectionString: config.url,
31
+ min: config.pool?.min ?? 2,
32
+ max: config.pool?.max ?? 10,
33
+ }),
34
+ });
35
+ }
36
+ case 'sqlite': {
37
+ const BetterSqlite3Module = await import('better-sqlite3');
38
+ const BetterSqlite3 = BetterSqlite3Module.default;
39
+ return new SqliteDialect({
40
+ database: new BetterSqlite3(config.filename ?? ':memory:'),
41
+ });
42
+ }
43
+ default:
44
+ throw new Error(`@moriajs/db: Unsupported Kysely adapter "${config.adapter}"`);
45
+ }
46
+ }
47
+ async find(collection, filter = {}) {
48
+ let query = this.db.selectFrom(collection).selectAll();
49
+ for (const [key, value] of Object.entries(filter)) {
50
+ query = query.where(key, '=', value);
51
+ }
52
+ return await query.execute();
53
+ }
54
+ async findOne(collection, filter = {}) {
55
+ let query = this.db.selectFrom(collection).selectAll();
56
+ for (const [key, value] of Object.entries(filter)) {
57
+ query = query.where(key, '=', value);
58
+ }
59
+ const result = await query.limit(1).executeTakeFirst();
60
+ return result || null;
61
+ }
62
+ async insertOne(collection, data) {
63
+ const result = await this.db
64
+ .insertInto(collection)
65
+ .values(data)
66
+ .returningAll()
67
+ .executeTakeFirstOrThrow();
68
+ return result;
69
+ }
70
+ async updateOne(collection, filter, data) {
71
+ let query = this.db.updateTable(collection).set(data);
72
+ for (const [key, value] of Object.entries(filter)) {
73
+ query = query.where(key, '=', value);
74
+ }
75
+ await query.execute();
76
+ }
77
+ async deleteOne(collection, filter) {
78
+ let query = this.db.deleteFrom(collection);
79
+ for (const [key, value] of Object.entries(filter)) {
80
+ query = query.where(key, '=', value);
81
+ }
82
+ await query.execute();
83
+ }
84
+ raw() {
85
+ return this.db;
86
+ }
30
87
  }
31
88
  /**
32
- * Create the appropriate Kysely dialect based on adapter config.
89
+ * Pongo Adapter Implementation (Document Store on Postgres)
33
90
  */
34
- async function createDialect(config) {
35
- switch (config.adapter) {
36
- case 'pg': {
37
- // Dynamic import — pg is an optional dependency
38
- // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-explicit-any
39
- const pg = globalThis.require('pg');
40
- return new PostgresDialect({
41
- pool: new pg.Pool({
42
- connectionString: config.url,
43
- min: config.pool?.min ?? 2,
44
- max: config.pool?.max ?? 10,
45
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
- }),
47
- });
48
- }
49
- case 'sqlite': {
50
- // Dynamic import — better-sqlite3 is an optional dependency
51
- const BetterSqlite3Module = await import('better-sqlite3');
52
- const BetterSqlite3 = BetterSqlite3Module.default;
53
- return new SqliteDialect({
54
- database: new BetterSqlite3(config.filename ?? ':memory:'),
55
- });
91
+ export class PongoAdapter {
92
+ config;
93
+ client = null;
94
+ constructor(config) {
95
+ this.config = config;
96
+ }
97
+ async connect() {
98
+ if (!this.config.url) {
99
+ throw new Error('@moriajs/db: PostgreSQL connection URL is required for Pongo');
56
100
  }
57
- case 'mysql': {
58
- throw new Error('@moriajs/db: MySQL adapter is not yet implemented. ' +
59
- 'Contributions welcome!');
101
+ this.client = pongoClient(this.config.url);
102
+ await this.client.connect();
103
+ }
104
+ async disconnect() {
105
+ if (this.client) {
106
+ await this.client.close();
60
107
  }
61
- default:
62
- throw new Error(`@moriajs/db: Unknown adapter "${config.adapter}"`);
108
+ }
109
+ async find(collection, filter = {}) {
110
+ return await this.client.db().collection(collection).find(filter);
111
+ }
112
+ async findOne(collection, filter = {}) {
113
+ return await this.client.db().collection(collection).findOne(filter);
114
+ }
115
+ async insertOne(collection, data) {
116
+ const result = await this.client.db().collection(collection).insertOne(data);
117
+ return result;
118
+ }
119
+ async updateOne(collection, filter, data) {
120
+ await this.client.db().collection(collection).updateOne(filter, { $set: data });
121
+ }
122
+ async deleteOne(collection, filter) {
123
+ await this.client.db().collection(collection).deleteOne(filter);
124
+ }
125
+ raw() {
126
+ return this.client;
63
127
  }
64
128
  }
65
129
  /**
66
- * Create a MoriaJS database plugin for Fastify integration.
67
- *
68
- * @example
69
- * ```ts
70
- * import { createApp } from '@moriajs/core';
71
- * import { createDatabasePlugin } from '@moriajs/db';
72
- *
73
- * const app = await createApp();
74
- * await app.use(createDatabasePlugin({
75
- * adapter: 'sqlite',
76
- * filename: './dev.db',
77
- * }));
78
- * ```
130
+ * Factory to create a MoriaDB instance.
131
+ */
132
+ export async function createDatabase(config) {
133
+ let adapter;
134
+ if (config.usePongo && config.adapter === 'pg') {
135
+ adapter = new PongoAdapter(config);
136
+ }
137
+ else {
138
+ adapter = new KyselyAdapter(config);
139
+ }
140
+ const db = new MoriaDB(adapter);
141
+ await db.connect();
142
+ return db;
143
+ }
144
+ /**
145
+ * MoriaJS database plugin for Fastify integration.
79
146
  */
80
147
  export function createDatabasePlugin(config) {
81
148
  return {
@@ -83,6 +150,9 @@ export function createDatabasePlugin(config) {
83
150
  async register({ server }) {
84
151
  const db = await createDatabase(config);
85
152
  server.decorate('db', db);
153
+ server.addHook('onClose', async () => {
154
+ await db.disconnect();
155
+ });
86
156
  },
87
157
  };
88
158
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAwBhE;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAI,MAAsB;IAC1D,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC;IAC5C,OAAO,IAAI,MAAM,CAAI,EAAE,OAAO,EAAE,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,aAAa,CAAC,MAAsB;IAC/C,QAAQ,MAAM,CAAC,OAAO,EAAE,CAAC;QACrB,KAAK,IAAI,CAAC,CAAC,CAAC;YACR,gDAAgD;YAChD,qGAAqG;YACrG,MAAM,EAAE,GAAI,UAAkB,CAAC,OAAO,CAAC,IAAI,CAA6D,CAAC;YACzG,OAAO,IAAI,eAAe,CAAC;gBACvB,IAAI,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC;oBACd,gBAAgB,EAAE,MAAM,CAAC,GAAG;oBAC5B,GAAG,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC;oBAC1B,GAAG,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,IAAI,EAAE;oBAC3B,8DAA8D;iBACjE,CAAQ;aACZ,CAAC,CAAC;QACP,CAAC;QAED,KAAK,QAAQ,CAAC,CAAC,CAAC;YACZ,4DAA4D;YAC5D,MAAM,mBAAmB,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;YAC3D,MAAM,aAAa,GAAG,mBAAmB,CAAC,OAAO,CAAC;YAClD,OAAO,IAAI,aAAa,CAAC;gBACrB,QAAQ,EAAE,IAAI,aAAa,CAAC,MAAM,CAAC,QAAQ,IAAI,UAAU,CAAC;aAC7D,CAAC,CAAC;QACP,CAAC;QAED,KAAK,OAAO,CAAC,CAAC,CAAC;YACX,MAAM,IAAI,KAAK,CACX,qDAAqD;gBACrD,wBAAwB,CAC3B,CAAC;QACN,CAAC;QAED;YACI,MAAM,IAAI,KAAK,CAAC,iCAAiC,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC;IAC5E,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAsB;IACvD,OAAO;QACH,IAAI,EAAE,aAAa;QACnB,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAmE;YACtF,MAAM,EAAE,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;YACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC9B,CAAC;KACJ,CAAC;AACN,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * MoriaDB Agnostic Interface
3
+ */
4
+ export interface MoriaDBAdapter {
5
+ /** Connect to the database */
6
+ connect(): Promise<void>;
7
+ /** Close the database connection */
8
+ disconnect(): Promise<void>;
9
+ /** Find multiple documents/rows */
10
+ find<T extends Record<string, any>>(collection: string, filter: any): Promise<T[]>;
11
+ /** Find a single document/row */
12
+ findOne<T extends Record<string, any>>(collection: string, filter: any): Promise<T | null>;
13
+ /** Insert one document/row */
14
+ insertOne<T extends Record<string, any>>(collection: string, data: any): Promise<T>;
15
+ /** Update documents/rows */
16
+ updateOne(collection: string, filter: any, data: any): Promise<void>;
17
+ /** Delete documents/rows */
18
+ deleteOne(collection: string, filter: any): Promise<void>;
19
+ /** Get the raw underlying driver instance (Kysely, Pongo, etc.) */
20
+ raw<T>(): T;
21
+ }
22
+ export declare class MoriaDB {
23
+ private adapter;
24
+ constructor(adapter: MoriaDBAdapter);
25
+ connect(): Promise<void>;
26
+ disconnect(): Promise<void>;
27
+ find<T extends Record<string, any>>(collection: string, filter?: any): Promise<T[]>;
28
+ findOne<T extends Record<string, any>>(collection: string, filter?: any): Promise<T | null>;
29
+ insertOne<T extends Record<string, any>>(collection: string, data: any): Promise<T>;
30
+ updateOne(collection: string, filter: any, data: any): Promise<void>;
31
+ deleteOne(collection: string, filter: any): Promise<void>;
32
+ /**
33
+ * Access the raw underlying driver instance.
34
+ * Use this when you need library-specific features.
35
+ */
36
+ raw<T>(): T;
37
+ }
38
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,cAAc;IAC3B,8BAA8B;IAC9B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,oCAAoC;IACpC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B,mCAAmC;IACnC,IAAI,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IACnF,iCAAiC;IACjC,OAAO,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC3F,8BAA8B;IAC9B,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACpF,4BAA4B;IAC5B,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,4BAA4B;IAC5B,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1D,mEAAmE;IACnE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;CACf;AAED,qBAAa,OAAO;IACJ,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,cAAc;IAErC,OAAO;IAIP,UAAU;IAIV,IAAI,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAE,GAAQ,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAIvF,OAAO,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAE,GAAQ,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAI/F,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC;IAInF,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpE,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/D;;;OAGG;IACH,GAAG,CAAC,CAAC,KAAK,CAAC;CAGd"}
package/dist/types.js ADDED
@@ -0,0 +1,38 @@
1
+ /**
2
+ * MoriaDB Agnostic Interface
3
+ */
4
+ export class MoriaDB {
5
+ adapter;
6
+ constructor(adapter) {
7
+ this.adapter = adapter;
8
+ }
9
+ async connect() {
10
+ return this.adapter.connect();
11
+ }
12
+ async disconnect() {
13
+ return this.adapter.disconnect();
14
+ }
15
+ async find(collection, filter = {}) {
16
+ return this.adapter.find(collection, filter);
17
+ }
18
+ async findOne(collection, filter = {}) {
19
+ return this.adapter.findOne(collection, filter);
20
+ }
21
+ async insertOne(collection, data) {
22
+ return this.adapter.insertOne(collection, data);
23
+ }
24
+ async updateOne(collection, filter, data) {
25
+ return this.adapter.updateOne(collection, filter, data);
26
+ }
27
+ async deleteOne(collection, filter) {
28
+ return this.adapter.deleteOne(collection, filter);
29
+ }
30
+ /**
31
+ * Access the raw underlying driver instance.
32
+ * Use this when you need library-specific features.
33
+ */
34
+ raw() {
35
+ return this.adapter.raw();
36
+ }
37
+ }
38
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAuBH,MAAM,OAAO,OAAO;IACI;IAApB,YAAoB,OAAuB;QAAvB,YAAO,GAAP,OAAO,CAAgB;IAAI,CAAC;IAEhD,KAAK,CAAC,OAAO;QACT,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,UAAU;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,IAAI,CAAgC,UAAkB,EAAE,SAAc,EAAE;QAC1E,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAI,UAAU,EAAE,MAAM,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,OAAO,CAAgC,UAAkB,EAAE,SAAc,EAAE;QAC7E,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAI,UAAU,EAAE,MAAM,CAAC,CAAC;IACvD,CAAC;IAED,KAAK,CAAC,SAAS,CAAgC,UAAkB,EAAE,IAAS;QACxE,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAI,UAAU,EAAE,IAAI,CAAC,CAAC;IACvD,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,UAAkB,EAAE,MAAW,EAAE,IAAS;QACtD,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,UAAkB,EAAE,MAAW;QAC3C,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACtD,CAAC;IAED;;;OAGG;IACH,GAAG;QACC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAK,CAAC;IACjC,CAAC;CACJ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moriajs/db",
3
- "version": "0.3.5",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "description": "MoriaJS database — Kysely adapters with kysely-schema integration",
6
6
  "main": "./dist/index.js",
@@ -12,7 +12,8 @@
12
12
  }
13
13
  },
14
14
  "dependencies": {
15
- "kysely": "^0.27.0"
15
+ "kysely": "^0.27.0",
16
+ "@event-driven-io/pongo": "^0.16.11"
16
17
  },
17
18
  "optionalDependencies": {
18
19
  "pg": "^8.13.0",
@@ -25,7 +26,7 @@
25
26
  "@types/better-sqlite3": "^7.6.0"
26
27
  },
27
28
  "peerDependencies": {
28
- "@moriajs/core": "0.3.5"
29
+ "@moriajs/core": "0.4.0"
29
30
  },
30
31
  "license": "MIT",
31
32
  "author": "Guntur-D <guntur.d.npm@gmail.com>",
package/src/index.ts CHANGED
@@ -1,28 +1,26 @@
1
- /**
2
- * @moriajs/db
3
- *
4
- * Database-agnostic adapter layer built on Kysely.
5
- * Default: PostgreSQL (production), SQLite (development).
6
- * Designed to work with kysely-schema for schema-first development.
7
- */
8
-
9
1
  import { Kysely, PostgresDialect, SqliteDialect } from 'kysely';
2
+ import { pongoClient, PongoClient } from '@event-driven-io/pongo';
3
+ import { MoriaDB, MoriaDBAdapter } from './types.js';
4
+
5
+ export * from './types.js';
10
6
 
11
7
  /**
12
8
  * Supported database adapters.
13
9
  */
14
- export type DatabaseAdapter = 'pg' | 'sqlite' | 'mysql';
10
+ export type DatabaseAdapterName = 'pg' | 'sqlite' | 'mysql';
15
11
 
16
12
  /**
17
13
  * Configuration for creating a database connection.
18
14
  */
19
15
  export interface DatabaseConfig {
20
- /** Database adapter to use */
21
- adapter: DatabaseAdapter;
22
- /** Connection URL (for pg/mysql) */
16
+ /** Database adapter name to use */
17
+ adapter: DatabaseAdapterName;
18
+ /** Connection URL (for pg/mysql/pongo) */
23
19
  url?: string;
24
20
  /** File path (for sqlite) */
25
21
  filename?: string;
22
+ /** Whether to use Pongo (Document API) instead of Kysely (SQL API) for Postgres */
23
+ usePongo?: boolean;
26
24
  /** Connection pool size */
27
25
  pool?: {
28
26
  min?: number;
@@ -31,89 +29,174 @@ export interface DatabaseConfig {
31
29
  }
32
30
 
33
31
  /**
34
- * Create a Kysely database instance with the specified adapter.
35
- *
36
- * @example
37
- * ```ts
38
- * // Production (PostgreSQL)
39
- * const db = await createDatabase({
40
- * adapter: 'pg',
41
- * url: process.env.DATABASE_URL,
42
- * });
43
- *
44
- * // Development (SQLite)
45
- * const db = await createDatabase({
46
- * adapter: 'sqlite',
47
- * filename: './dev.db',
48
- * });
49
- * ```
32
+ * Kysely Adapter Implementation (SQL)
50
33
  */
51
- export async function createDatabase<T>(config: DatabaseConfig): Promise<Kysely<T>> {
52
- const dialect = await createDialect(config);
53
- return new Kysely<T>({ dialect });
34
+ export class KyselyAdapter implements MoriaDBAdapter {
35
+ private db: Kysely<any> | null = null;
36
+
37
+ constructor(private config: DatabaseConfig) { }
38
+
39
+ async connect(): Promise<void> {
40
+ const dialect = await this.createDialect(this.config);
41
+ this.db = new Kysely<any>({ dialect });
42
+ }
43
+
44
+ async disconnect(): Promise<void> {
45
+ if (this.db) {
46
+ await this.db.destroy();
47
+ }
48
+ }
49
+
50
+ private async createDialect(config: DatabaseConfig) {
51
+ switch (config.adapter) {
52
+ case 'pg': {
53
+ // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-explicit-any
54
+ const pg = (globalThis as any).require('pg') as { Pool: new (opts: Record<string, unknown>) => unknown };
55
+ return new PostgresDialect({
56
+ pool: new pg.Pool({
57
+ connectionString: config.url,
58
+ min: config.pool?.min ?? 2,
59
+ max: config.pool?.max ?? 10,
60
+ }) as any,
61
+ });
62
+ }
63
+ case 'sqlite': {
64
+ const BetterSqlite3Module = await import('better-sqlite3');
65
+ const BetterSqlite3 = BetterSqlite3Module.default;
66
+ return new SqliteDialect({
67
+ database: new BetterSqlite3(config.filename ?? ':memory:'),
68
+ });
69
+ }
70
+ default:
71
+ throw new Error(`@moriajs/db: Unsupported Kysely adapter "${config.adapter}"`);
72
+ }
73
+ }
74
+
75
+ async find<T>(collection: string, filter: any = {}): Promise<T[]> {
76
+ let query = this.db!.selectFrom(collection).selectAll();
77
+ for (const [key, value] of Object.entries(filter)) {
78
+ query = query.where(key as any, '=', value as any);
79
+ }
80
+ return await query.execute() as T[];
81
+ }
82
+
83
+ async findOne<T>(collection: string, filter: any = {}): Promise<T | null> {
84
+ let query = this.db!.selectFrom(collection).selectAll();
85
+ for (const [key, value] of Object.entries(filter)) {
86
+ query = query.where(key as any, '=', value as any);
87
+ }
88
+ const result = await query.limit(1).executeTakeFirst();
89
+ return (result as T) || null;
90
+ }
91
+
92
+ async insertOne<T>(collection: string, data: any): Promise<T> {
93
+ const result = await this.db!
94
+ .insertInto(collection)
95
+ .values(data)
96
+ .returningAll()
97
+ .executeTakeFirstOrThrow();
98
+ return result as T;
99
+ }
100
+
101
+ async updateOne(collection: string, filter: any, data: any): Promise<void> {
102
+ let query = this.db!.updateTable(collection).set(data);
103
+ for (const [key, value] of Object.entries(filter)) {
104
+ query = query.where(key as any, '=', value as any);
105
+ }
106
+ await query.execute();
107
+ }
108
+
109
+ async deleteOne(collection: string, filter: any): Promise<void> {
110
+ let query = this.db!.deleteFrom(collection);
111
+ for (const [key, value] of Object.entries(filter)) {
112
+ query = query.where(key as any, '=', value as any);
113
+ }
114
+ await query.execute();
115
+ }
116
+
117
+ raw<T>(): T {
118
+ return this.db as unknown as T;
119
+ }
54
120
  }
55
121
 
56
122
  /**
57
- * Create the appropriate Kysely dialect based on adapter config.
123
+ * Pongo Adapter Implementation (Document Store on Postgres)
58
124
  */
59
- async function createDialect(config: DatabaseConfig) {
60
- switch (config.adapter) {
61
- case 'pg': {
62
- // Dynamic import — pg is an optional dependency
63
- // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-explicit-any
64
- const pg = (globalThis as any).require('pg') as { Pool: new (opts: Record<string, unknown>) => unknown };
65
- return new PostgresDialect({
66
- pool: new pg.Pool({
67
- connectionString: config.url,
68
- min: config.pool?.min ?? 2,
69
- max: config.pool?.max ?? 10,
70
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
71
- }) as any,
72
- });
73
- }
125
+ export class PongoAdapter implements MoriaDBAdapter {
126
+ private client: PongoClient | null = null;
74
127
 
75
- case 'sqlite': {
76
- // Dynamic import — better-sqlite3 is an optional dependency
77
- const BetterSqlite3Module = await import('better-sqlite3');
78
- const BetterSqlite3 = BetterSqlite3Module.default;
79
- return new SqliteDialect({
80
- database: new BetterSqlite3(config.filename ?? ':memory:'),
81
- });
128
+ constructor(private config: DatabaseConfig) { }
129
+
130
+ async connect(): Promise<void> {
131
+ if (!this.config.url) {
132
+ throw new Error('@moriajs/db: PostgreSQL connection URL is required for Pongo');
82
133
  }
134
+ this.client = pongoClient(this.config.url);
135
+ await this.client.connect();
136
+ }
83
137
 
84
- case 'mysql': {
85
- throw new Error(
86
- '@moriajs/db: MySQL adapter is not yet implemented. ' +
87
- 'Contributions welcome!'
88
- );
138
+ async disconnect(): Promise<void> {
139
+ if (this.client) {
140
+ await this.client.close();
89
141
  }
142
+ }
143
+
144
+ async find<T extends Record<string, any> = any>(collection: string, filter: any = {}): Promise<T[]> {
145
+ return await this.client!.db().collection<T>(collection).find(filter) as any;
146
+ }
147
+
148
+ async findOne<T extends Record<string, any> = any>(collection: string, filter: any = {}): Promise<T | null> {
149
+ return await this.client!.db().collection<T>(collection).findOne(filter) as any;
150
+ }
151
+
152
+ async insertOne<T extends Record<string, any> = any>(collection: string, data: any): Promise<T> {
153
+ const result = await this.client!.db().collection<T>(collection).insertOne(data);
154
+ return result as unknown as T;
155
+ }
90
156
 
91
- default:
92
- throw new Error(`@moriajs/db: Unknown adapter "${config.adapter}"`);
157
+ async updateOne(collection: string, filter: any, data: any): Promise<void> {
158
+ await this.client!.db().collection(collection).updateOne(filter, { $set: data });
159
+ }
160
+
161
+ async deleteOne(collection: string, filter: any): Promise<void> {
162
+ await this.client!.db().collection(collection).deleteOne(filter);
163
+ }
164
+
165
+ raw<T>(): T {
166
+ return this.client as unknown as T;
93
167
  }
94
168
  }
95
169
 
96
170
  /**
97
- * Create a MoriaJS database plugin for Fastify integration.
98
- *
99
- * @example
100
- * ```ts
101
- * import { createApp } from '@moriajs/core';
102
- * import { createDatabasePlugin } from '@moriajs/db';
103
- *
104
- * const app = await createApp();
105
- * await app.use(createDatabasePlugin({
106
- * adapter: 'sqlite',
107
- * filename: './dev.db',
108
- * }));
109
- * ```
171
+ * Factory to create a MoriaDB instance.
172
+ */
173
+ export async function createDatabase(config: DatabaseConfig): Promise<MoriaDB> {
174
+ let adapter: MoriaDBAdapter;
175
+
176
+ if (config.usePongo && config.adapter === 'pg') {
177
+ adapter = new PongoAdapter(config);
178
+ } else {
179
+ adapter = new KyselyAdapter(config);
180
+ }
181
+
182
+ const db = new MoriaDB(adapter);
183
+ await db.connect();
184
+ return db;
185
+ }
186
+
187
+ /**
188
+ * MoriaJS database plugin for Fastify integration.
110
189
  */
111
190
  export function createDatabasePlugin(config: DatabaseConfig) {
112
191
  return {
113
192
  name: '@moriajs/db',
114
- async register({ server }: { server: { decorate: (key: string, value: unknown) => void } }) {
193
+ async register({ server }: { server: any }) {
115
194
  const db = await createDatabase(config);
116
195
  server.decorate('db', db);
196
+
197
+ server.addHook('onClose', async () => {
198
+ await db.disconnect();
199
+ });
117
200
  },
118
201
  };
119
202
  }
package/src/types.ts ADDED
@@ -0,0 +1,64 @@
1
+ /**
2
+ * MoriaDB Agnostic Interface
3
+ */
4
+
5
+ export interface MoriaDBAdapter {
6
+ /** Connect to the database */
7
+ connect(): Promise<void>;
8
+ /** Close the database connection */
9
+ disconnect(): Promise<void>;
10
+
11
+ /** Find multiple documents/rows */
12
+ find<T extends Record<string, any>>(collection: string, filter: any): Promise<T[]>;
13
+ /** Find a single document/row */
14
+ findOne<T extends Record<string, any>>(collection: string, filter: any): Promise<T | null>;
15
+ /** Insert one document/row */
16
+ insertOne<T extends Record<string, any>>(collection: string, data: any): Promise<T>;
17
+ /** Update documents/rows */
18
+ updateOne(collection: string, filter: any, data: any): Promise<void>;
19
+ /** Delete documents/rows */
20
+ deleteOne(collection: string, filter: any): Promise<void>;
21
+
22
+ /** Get the raw underlying driver instance (Kysely, Pongo, etc.) */
23
+ raw<T>(): T;
24
+ }
25
+
26
+ export class MoriaDB {
27
+ constructor(private adapter: MoriaDBAdapter) { }
28
+
29
+ async connect() {
30
+ return this.adapter.connect();
31
+ }
32
+
33
+ async disconnect() {
34
+ return this.adapter.disconnect();
35
+ }
36
+
37
+ async find<T extends Record<string, any>>(collection: string, filter: any = {}): Promise<T[]> {
38
+ return this.adapter.find<T>(collection, filter);
39
+ }
40
+
41
+ async findOne<T extends Record<string, any>>(collection: string, filter: any = {}): Promise<T | null> {
42
+ return this.adapter.findOne<T>(collection, filter);
43
+ }
44
+
45
+ async insertOne<T extends Record<string, any>>(collection: string, data: any): Promise<T> {
46
+ return this.adapter.insertOne<T>(collection, data);
47
+ }
48
+
49
+ async updateOne(collection: string, filter: any, data: any): Promise<void> {
50
+ return this.adapter.updateOne(collection, filter, data);
51
+ }
52
+
53
+ async deleteOne(collection: string, filter: any): Promise<void> {
54
+ return this.adapter.deleteOne(collection, filter);
55
+ }
56
+
57
+ /**
58
+ * Access the raw underlying driver instance.
59
+ * Use this when you need library-specific features.
60
+ */
61
+ raw<T>(): T {
62
+ return this.adapter.raw<T>();
63
+ }
64
+ }