@kubun/db-adapter 0.3.2 → 0.5.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.
package/lib/index.d.ts CHANGED
@@ -1,4 +1,3 @@
1
1
  export { AbstractPostgresAdapter, type PostgresTypes } from './postgres.js';
2
2
  export { AbstractSQLiteAdapter, type SQLiteTypes } from './sqlite.js';
3
- export type { AbstractAdapter, Adapter, AdapterTypes } from './types.js';
4
- //# sourceMappingURL=index.d.ts.map
3
+ export type { AbstractAdapter, Adapter, AdapterTypes, SearchHit, SearchIndexConfig, SearchQuery, } from './types.js';
package/lib/index.js CHANGED
@@ -1,2 +1 @@
1
- export { AbstractPostgresAdapter } from './postgres.js';
2
- export { AbstractSQLiteAdapter } from './sqlite.js';
1
+ export{AbstractPostgresAdapter}from"./postgres.js";export{AbstractSQLiteAdapter}from"./sqlite.js";
package/lib/postgres.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import type { AbstractAdapter, AdapterTypes, ColumnTypes, Functions } from './types.js';
1
+ import type { Kysely } from 'kysely';
2
+ import type { AbstractAdapter, AdapterTypes, ColumnTypes, Functions, SearchHit, SearchIndexConfig, SearchQuery } from './types.js';
2
3
  export type PostgresTypes = {
3
4
  Binary: Uint8Array;
4
5
  JSON: unknown;
@@ -11,5 +12,9 @@ export declare class AbstractPostgresAdapter<T extends AdapterTypes = PostgresTy
11
12
  encodeJSON(value: unknown): unknown;
12
13
  encodeTimestamp(value: Date): string;
13
14
  decodeTimestamp(value: string): Date;
15
+ createSearchIndex(db: Kysely<unknown>, config: SearchIndexConfig): Promise<void>;
16
+ dropSearchIndex(db: Kysely<unknown>, modelID: string): Promise<void>;
17
+ updateSearchEntry(db: Kysely<unknown>, modelID: string, documentID: string, fields: Record<string, string>, fieldNames: Array<string>): Promise<void>;
18
+ removeSearchEntry(db: Kysely<unknown>, modelID: string, documentID: string): Promise<void>;
19
+ searchIndex(db: Kysely<unknown>, params: SearchQuery): Promise<Array<SearchHit>>;
14
20
  }
15
- //# sourceMappingURL=postgres.d.ts.map
package/lib/postgres.js CHANGED
@@ -1,25 +1,19 @@
1
- export class AbstractPostgresAdapter {
2
- functions = {
3
- now: 'now()'
4
- };
5
- types = {
6
- binary: 'bytea',
7
- json: 'jsonb',
8
- text: 'text',
9
- // Use 3 digits for timestamps to have millisecond precision, same as JS dates
10
- timestamp: 'timestamptz(3)',
11
- uuid: 'uuid'
12
- };
13
- encodeBinary(value) {
14
- return value;
15
- }
16
- encodeJSON(value) {
17
- return value;
18
- }
19
- encodeTimestamp(value) {
20
- return value.toISOString();
21
- }
22
- decodeTimestamp(value) {
23
- return new Date(value);
24
- }
25
- }
1
+ import{sql as e}from"kysely";export class AbstractPostgresAdapter{functions={now:"now()"};types={binary:"bytea",json:"jsonb",text:"text",timestamp:"timestamptz(3)",uuid:"uuid"};encodeBinary(e){return e}encodeJSON(e){return e}encodeTimestamp(e){return e.toISOString()}decodeTimestamp(e){return new Date(e)}async createSearchIndex(t,r){let a=`fts_${r.modelID}`,c=`k_${r.modelID}`;await e`
2
+ CREATE TABLE IF NOT EXISTS ${e.ref(a)} (
3
+ document_id TEXT PRIMARY KEY REFERENCES ${e.ref(c)}(id) ON DELETE CASCADE,
4
+ search_vector tsvector
5
+ )
6
+ `.execute(t),await e`
7
+ CREATE INDEX IF NOT EXISTS ${e.ref(`ftsi_${r.modelID}`)}
8
+ ON ${e.ref(a)} USING GIN(search_vector)
9
+ `.execute(t)}async dropSearchIndex(t,r){let a=`fts_${r}`;await e`DROP TABLE IF EXISTS ${e.ref(a)} CASCADE`.execute(t)}async updateSearchEntry(t,r,a,c,n){let s=`fts_${r}`,o=n.map(t=>{let r=c[t]??"";return e`to_tsvector('simple', ${r})`}).reduce((t,r)=>e`${t} || ${r}`);await e`
10
+ INSERT INTO ${e.ref(s)} (document_id, search_vector)
11
+ VALUES (${a}, ${o})
12
+ ON CONFLICT (document_id) DO UPDATE SET search_vector = ${o}
13
+ `.execute(t)}async removeSearchEntry(t,r,a){let c=`fts_${r}`;await e`DELETE FROM ${e.ref(c)} WHERE document_id = ${a}`.execute(t)}async searchIndex(t,r){let a=`fts_${r.modelID}`;return(await e`
14
+ SELECT document_id, ts_rank(search_vector, plainto_tsquery('simple', ${r.query})) AS rank
15
+ FROM ${e.ref(a)}
16
+ WHERE search_vector @@ plainto_tsquery('simple', ${r.query})
17
+ ORDER BY rank DESC
18
+ LIMIT ${r.limit}
19
+ `.execute(t)).rows.map(e=>({documentID:e.document_id,rank:e.rank}))}}
package/lib/sqlite.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import type { AbstractAdapter, AdapterTypes, ColumnTypes, Functions } from './types.js';
1
+ import type { Kysely } from 'kysely';
2
+ import type { AbstractAdapter, AdapterTypes, ColumnTypes, Functions, SearchHit, SearchIndexConfig, SearchQuery } from './types.js';
2
3
  export type SQLiteTypes = {
3
4
  Binary: Uint8Array;
4
5
  JSON: string;
@@ -11,5 +12,9 @@ export declare class AbstractSQLiteAdapter<T extends AdapterTypes = SQLiteTypes>
11
12
  encodeJSON(value: unknown): string;
12
13
  encodeTimestamp(value: Date): number;
13
14
  decodeTimestamp(value: number): Date;
15
+ createSearchIndex(db: Kysely<unknown>, config: SearchIndexConfig): Promise<void>;
16
+ dropSearchIndex(db: Kysely<unknown>, modelID: string): Promise<void>;
17
+ updateSearchEntry(db: Kysely<unknown>, modelID: string, documentID: string, fields: Record<string, string>, fieldNames: Array<string>): Promise<void>;
18
+ removeSearchEntry(db: Kysely<unknown>, modelID: string, documentID: string): Promise<void>;
19
+ searchIndex(db: Kysely<unknown>, params: SearchQuery): Promise<Array<SearchHit>>;
14
20
  }
15
- //# sourceMappingURL=sqlite.d.ts.map
package/lib/sqlite.js CHANGED
@@ -1,27 +1,6 @@
1
- import { sql } from 'kysely';
2
- export class AbstractSQLiteAdapter {
3
- functions = {
4
- now: sql`(unixepoch())`
5
- };
6
- types = {
7
- binary: 'blob',
8
- json: 'jsonb',
9
- text: 'text',
10
- timestamp: 'integer',
11
- uuid: 'text'
12
- };
13
- encodeBinary(value) {
14
- return value;
15
- }
16
- encodeJSON(value) {
17
- return JSON.stringify(value);
18
- }
19
- encodeTimestamp(value) {
20
- // SQLite timestamps are stored in seconds
21
- return Math.floor(value.getTime() / 1000);
22
- }
23
- decodeTimestamp(value) {
24
- // SQLite timestamps are stored in seconds
25
- return new Date(value * 1000);
26
- }
27
- }
1
+ import{sql as e}from"kysely";export class AbstractSQLiteAdapter{functions={now:e`(unixepoch())`};types={binary:"blob",json:"jsonb",text:"text",timestamp:"integer",uuid:"text"};encodeBinary(e){return e}encodeJSON(e){return JSON.stringify(e)}encodeTimestamp(e){return Math.floor(e.getTime()/1e3)}decodeTimestamp(e){return new Date(1e3*e)}async createSearchIndex(t,r){let a=`fts_${r.modelID}`,n=["document_id UNINDEXED",...r.fields].join(", ");await e`CREATE VIRTUAL TABLE IF NOT EXISTS ${e.ref(a)} USING fts5(${e.raw(n)})`.execute(t)}async dropSearchIndex(t,r){let a=`fts_${r}`;await e`DROP TABLE IF EXISTS ${e.ref(a)}`.execute(t)}async updateSearchEntry(t,r,a,n,i){let c=`fts_${r}`;await e`DELETE FROM ${e.ref(c)} WHERE document_id = ${a}`.execute(t);let o=["document_id",...i].join(", "),d=[a,...i.map(e=>n[e]??"")].map(t=>e.lit(t));await e`INSERT INTO ${e.ref(c)} (${e.raw(o)}) VALUES (${e.join(d)})`.execute(t)}async removeSearchEntry(t,r,a){let n=`fts_${r}`;await e`DELETE FROM ${e.ref(n)} WHERE document_id = ${a}`.execute(t)}async searchIndex(t,r){let a=`fts_${r.modelID}`;return(await e`
2
+ SELECT document_id, rank FROM ${e.ref(a)}
3
+ WHERE ${e.ref(a)} MATCH ${r.query}
4
+ ORDER BY rank
5
+ LIMIT ${r.limit}
6
+ `.execute(t)).rows.map(e=>({documentID:e.document_id,rank:e.rank}))}}
package/lib/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ColumnDataType, Dialect, RawBuilder } from 'kysely';
1
+ import type { ColumnDataType, Dialect, Kysely, RawBuilder } from 'kysely';
2
2
  export type ColumnTypes = {
3
3
  binary: ColumnDataType;
4
4
  json: ColumnDataType;
@@ -14,6 +14,19 @@ export type AdapterTypes = {
14
14
  JSON: unknown;
15
15
  Timestamp: unknown;
16
16
  };
17
+ export type SearchIndexConfig = {
18
+ modelID: string;
19
+ fields: Array<string>;
20
+ };
21
+ export type SearchQuery = {
22
+ query: string;
23
+ modelID: string;
24
+ limit: number;
25
+ };
26
+ export type SearchHit = {
27
+ documentID: string;
28
+ rank: number;
29
+ };
17
30
  export type AbstractAdapter<T extends AdapterTypes = AdapterTypes> = {
18
31
  functions: Functions;
19
32
  types: ColumnTypes;
@@ -21,8 +34,12 @@ export type AbstractAdapter<T extends AdapterTypes = AdapterTypes> = {
21
34
  encodeJSON(value: unknown): T['JSON'];
22
35
  encodeTimestamp(value: Date): T['Timestamp'];
23
36
  decodeTimestamp(value: T['Timestamp']): Date;
37
+ createSearchIndex(db: Kysely<unknown>, config: SearchIndexConfig): Promise<void>;
38
+ dropSearchIndex(db: Kysely<unknown>, modelID: string): Promise<void>;
39
+ updateSearchEntry(db: Kysely<unknown>, modelID: string, documentID: string, fields: Record<string, string>, fieldNames: Array<string>): Promise<void>;
40
+ removeSearchEntry(db: Kysely<unknown>, modelID: string, documentID: string): Promise<void>;
41
+ searchIndex(db: Kysely<unknown>, params: SearchQuery): Promise<Array<SearchHit>>;
24
42
  };
25
43
  export type Adapter<T extends AdapterTypes = AdapterTypes> = AbstractAdapter<T> & {
26
44
  dialect: Dialect;
27
45
  };
28
- //# sourceMappingURL=types.d.ts.map
package/lib/types.js CHANGED
@@ -1 +1 @@
1
- export { };
1
+ export{};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubun/db-adapter",
3
- "version": "0.3.2",
3
+ "version": "0.5.0",
4
4
  "license": "see LICENSE.md",
5
5
  "keywords": [],
6
6
  "type": "module",
@@ -15,7 +15,7 @@
15
15
  ],
16
16
  "sideEffects": false,
17
17
  "dependencies": {
18
- "kysely": "^0.28.2"
18
+ "kysely": "^0.28.11"
19
19
  },
20
20
  "scripts": {
21
21
  "build:clean": "del lib",
@@ -24,7 +24,7 @@
24
24
  "build:types:ci": "tsc --emitDeclarationOnly --declarationMap false",
25
25
  "build": "pnpm run build:clean && pnpm run build:js && pnpm run build:types",
26
26
  "test:types": "tsc --noEmit",
27
- "test:unit": "node --experimental-vm-modules ../../node_modules/jest/bin/jest.js",
27
+ "test:unit": "vitest run",
28
28
  "test": "pnpm run test:types && pnpm run test:unit"
29
29
  }
30
30
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAA;AAC3E,OAAO,EAAE,qBAAqB,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAA;AACrE,YAAY,EAAE,eAAe,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../src/postgres.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAEvF,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,UAAU,CAAA;IAClB,IAAI,EAAE,OAAO,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,qBAAa,uBAAuB,CAAC,CAAC,SAAS,YAAY,GAAG,aAAa,CACzE,YAAW,eAAe,CAAC,CAAC,CAAC;IAE7B,SAAS,EAEJ,SAAS,CAAA;IAEd,KAAK,EAOA,WAAW,CAAA;IAEhB,YAAY,CAAC,KAAK,EAAE,UAAU;IAI9B,UAAU,CAAC,KAAK,EAAE,OAAO;IAIzB,eAAe,CAAC,KAAK,EAAE,IAAI;IAI3B,eAAe,CAAC,KAAK,EAAE,MAAM;CAG9B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../src/sqlite.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAEvF,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,UAAU,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,qBAAa,qBAAqB,CAAC,CAAC,SAAS,YAAY,GAAG,WAAW,CACrE,YAAW,eAAe,CAAC,CAAC,CAAC;IAE7B,SAAS,EAEJ,SAAS,CAAA;IAEd,KAAK,EAMA,WAAW,CAAA;IAEhB,YAAY,CAAC,KAAK,EAAE,UAAU;IAI9B,UAAU,CAAC,KAAK,EAAE,OAAO;IAIzB,eAAe,CAAC,KAAK,EAAE,IAAI;IAK3B,eAAe,CAAC,KAAK,EAAE,MAAM;CAI9B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAEjE,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,cAAc,CAAA;IACtB,IAAI,EAAE,cAAc,CAAA;IACpB,IAAI,EAAE,cAAc,CAAA;IACpB,SAAS,EAAE,cAAc,CAAA;IACzB,IAAI,EAAE,cAAc,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,GAAG,EAAE,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAA;CACjC,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,OAAO,CAAA;IACf,IAAI,EAAE,OAAO,CAAA;IACb,SAAS,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,YAAY,GAAG,YAAY,IAAI;IACnE,SAAS,EAAE,SAAS,CAAA;IACpB,KAAK,EAAE,WAAW,CAAA;IAClB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAA;IAC5C,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,CAAC,CAAC,MAAM,CAAC,CAAA;IACrC,eAAe,CAAC,KAAK,EAAE,IAAI,GAAG,CAAC,CAAC,WAAW,CAAC,CAAA;IAC5C,eAAe,CAAC,KAAK,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,IAAI,CAAA;CAC7C,CAAA;AAED,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,YAAY,GAAG,YAAY,IAAI,eAAe,CAAC,CAAC,CAAC,GAAG;IAChF,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA"}