@objectstack/driver-sql 3.2.9 → 3.3.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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @objectstack/driver-sql@3.2.9 build /home/runner/work/spec/spec/packages/plugins/driver-sql
2
+ > @objectstack/driver-sql@3.3.1 build /home/runner/work/spec/spec/packages/plugins/driver-sql
3
3
  > tsup --config ../../../tsup.config.ts
4
4
 
5
5
  CLI Building entry: src/index.ts
@@ -10,13 +10,13 @@
10
10
  CLI Cleaning output folder
11
11
  ESM Build start
12
12
  CJS Build start
13
- CJS dist/index.js 34.49 KB
14
- CJS dist/index.js.map 59.89 KB
15
- CJS ⚡️ Build success in 137ms
16
- ESM dist/index.mjs 32.82 KB
17
- ESM dist/index.mjs.map 59.82 KB
18
- ESM ⚡️ Build success in 147ms
13
+ ESM dist/index.mjs 36.06 KB
14
+ ESM dist/index.mjs.map 66.43 KB
15
+ ESM ⚡️ Build success in 109ms
16
+ CJS dist/index.js 37.74 KB
17
+ CJS dist/index.js.map 66.50 KB
18
+ CJS ⚡️ Build success in 112ms
19
19
  DTS Build start
20
- DTS ⚡️ Build success in 17850ms
21
- DTS dist/index.d.mts 4.86 KB
22
- DTS dist/index.d.ts 4.86 KB
20
+ DTS ⚡️ Build success in 11711ms
21
+ DTS dist/index.d.mts 7.80 KB
22
+ DTS dist/index.d.ts 7.80 KB
package/CHANGELOG.md ADDED
@@ -0,0 +1,19 @@
1
+ # @objectstack/driver-sql
2
+
3
+ ## 3.3.1
4
+
5
+ ### Patch Changes
6
+
7
+ - @objectstack/spec@3.3.1
8
+ - @objectstack/core@3.3.1
9
+
10
+ ## 3.3.0
11
+
12
+ ### Minor Changes
13
+
14
+ - 814a6c4: sql driver
15
+
16
+ ### Patch Changes
17
+
18
+ - @objectstack/spec@3.3.0
19
+ - @objectstack/core@3.3.0
package/dist/index.d.mts CHANGED
@@ -1,11 +1,11 @@
1
- import { QueryInput, DriverOptions } from '@objectstack/spec/data';
2
- import { DriverInterface } from '@objectstack/core';
3
- import { Knex } from 'knex';
1
+ import { QueryAST, DriverOptions } from '@objectstack/spec/data';
2
+ import { IDataDriver } from '@objectstack/spec/contracts';
3
+ import knex, { Knex } from 'knex';
4
4
 
5
5
  /**
6
6
  * SQL Driver for ObjectStack
7
7
  *
8
- * Implements the standard DriverInterface from @objectstack/spec via Knex.js.
8
+ * Implements the standard IDataDriver from @objectstack/spec via Knex.js.
9
9
  * Supports PostgreSQL, MySQL, SQLite, and other SQL databases.
10
10
  */
11
11
 
@@ -41,84 +41,139 @@ type SqlDriverConfig = Knex.Config;
41
41
  /**
42
42
  * SQL Driver for ObjectStack.
43
43
  *
44
- * Implements the DriverInterface contract via Knex.js for optimal SQL
44
+ * Implements the IDataDriver contract via Knex.js for optimal SQL
45
45
  * generation against PostgreSQL, MySQL, SQLite and other SQL databases.
46
46
  */
47
- declare class SqlDriver implements DriverInterface {
48
- readonly name = "com.objectstack.driver.sql";
49
- readonly version = "1.0.0";
47
+ declare class SqlDriver implements IDataDriver {
48
+ readonly name: string;
49
+ readonly version: string;
50
50
  readonly supports: {
51
+ create: boolean;
52
+ read: boolean;
53
+ update: boolean;
54
+ delete: boolean;
55
+ bulkCreate: boolean;
56
+ bulkUpdate: boolean;
57
+ bulkDelete: boolean;
51
58
  transactions: boolean;
52
- joins: boolean;
53
- fullTextSearch: boolean;
54
- jsonFields: boolean;
55
- arrayFields: boolean;
59
+ savepoints: boolean;
56
60
  queryFilters: boolean;
57
61
  queryAggregations: boolean;
58
62
  querySorting: boolean;
59
63
  queryPagination: boolean;
60
64
  queryWindowFunctions: boolean;
61
65
  querySubqueries: boolean;
66
+ queryCTE: boolean;
67
+ joins: boolean;
68
+ fullTextSearch: boolean;
69
+ jsonQuery: boolean;
70
+ geospatialQuery: boolean;
71
+ streaming: boolean;
72
+ jsonFields: boolean;
73
+ arrayFields: boolean;
74
+ vectorSearch: boolean;
75
+ schemaSync: boolean;
76
+ batchSchemaSync: boolean;
77
+ migrations: boolean;
78
+ indexes: boolean;
79
+ connectionPooling: boolean;
80
+ preparedStatements: boolean;
81
+ queryCache: boolean;
62
82
  };
63
- private knex;
64
- private config;
65
- private jsonFields;
66
- private booleanFields;
67
- private tablesWithTimestamps;
83
+ protected knex: Knex;
84
+ protected config: Knex.Config;
85
+ protected jsonFields: Record<string, string[]>;
86
+ protected booleanFields: Record<string, string[]>;
87
+ protected tablesWithTimestamps: Set<string>;
68
88
  /** Whether the underlying database is a SQLite variant (sqlite3 or better-sqlite3). */
69
- private get isSqlite();
89
+ protected get isSqlite(): boolean;
70
90
  /** Whether the underlying database is PostgreSQL. */
71
- private get isPostgres();
91
+ protected get isPostgres(): boolean;
72
92
  /** Whether the underlying database is MySQL. */
73
- private get isMysql();
93
+ protected get isMysql(): boolean;
74
94
  constructor(config: SqlDriverConfig);
75
95
  connect(): Promise<void>;
76
96
  checkHealth(): Promise<boolean>;
77
97
  disconnect(): Promise<void>;
78
- find(object: string, query: QueryInput, options?: DriverOptions): Promise<any[]>;
79
- findOne(object: string, query: QueryInput, options?: DriverOptions): Promise<any>;
98
+ find(object: string, query: QueryAST, options?: DriverOptions): Promise<any[]>;
99
+ findOne(object: string, query: QueryAST, options?: DriverOptions): Promise<any>;
100
+ /**
101
+ * Stream records matching a structured query.
102
+ * NOTE: Current implementation fetches all results then yields them.
103
+ * TODO: Use Knex .stream() for true cursor-based streaming on large datasets.
104
+ */
105
+ findStream(object: string, query: QueryAST, options?: DriverOptions): AsyncGenerator<Record<string, any>>;
80
106
  create(object: string, data: Record<string, any>, options?: DriverOptions): Promise<any>;
81
107
  update(object: string, id: string | number, data: Record<string, any>, options?: DriverOptions): Promise<any>;
82
- delete(object: string, id: string | number, options?: DriverOptions): Promise<any>;
108
+ upsert(object: string, data: Record<string, any>, conflictKeys?: string[], options?: DriverOptions): Promise<Record<string, any>>;
109
+ delete(object: string, id: string | number, options?: DriverOptions): Promise<boolean>;
83
110
  bulkCreate(object: string, data: any[], options?: DriverOptions): Promise<any>;
84
- updateMany(object: string, query: QueryInput, data: any, options?: DriverOptions): Promise<any>;
85
- deleteMany(object: string, query: QueryInput, options?: DriverOptions): Promise<any>;
86
- count(object: string, query: QueryInput, options?: DriverOptions): Promise<number>;
111
+ /**
112
+ * Batch-update multiple records by ID.
113
+ * NOTE: Current implementation performs sequential updates for correctness.
114
+ * TODO: Optimize with SQL CASE statements or batched transactions for performance.
115
+ */
116
+ bulkUpdate(object: string, updates: Array<{
117
+ id: string | number;
118
+ data: Record<string, any>;
119
+ }>, options?: DriverOptions): Promise<Record<string, any>[]>;
120
+ bulkDelete(object: string, ids: Array<string | number>, options?: DriverOptions): Promise<void>;
121
+ updateMany(object: string, query: QueryAST, data: any, options?: DriverOptions): Promise<number>;
122
+ deleteMany(object: string, query: QueryAST, options?: DriverOptions): Promise<number>;
123
+ count(object: string, query?: QueryAST, options?: DriverOptions): Promise<number>;
87
124
  execute(command: any, params?: any[], options?: DriverOptions): Promise<any>;
88
125
  beginTransaction(): Promise<Knex.Transaction>;
126
+ /** IDataDriver standard */
127
+ commit(transaction: unknown): Promise<void>;
128
+ /** IDataDriver standard */
129
+ rollback(transaction: unknown): Promise<void>;
130
+ /** @deprecated Use commit() instead */
89
131
  commitTransaction(trx: Knex.Transaction): Promise<void>;
132
+ /** @deprecated Use rollback() instead */
90
133
  rollbackTransaction(trx: Knex.Transaction): Promise<void>;
91
134
  aggregate(object: string, query: any, options?: DriverOptions): Promise<any>;
92
135
  distinct(object: string, field: string, filters?: any, options?: DriverOptions): Promise<any[]>;
93
136
  findWithWindowFunctions(object: string, query: any, options?: DriverOptions): Promise<any[]>;
137
+ /** IDataDriver standard: analyze query performance */
138
+ explain(object: string, query: any, options?: DriverOptions): Promise<any>;
94
139
  analyzeQuery(object: string, query: any, options?: DriverOptions): Promise<any>;
95
140
  syncSchema(object: string, schema: unknown, _options?: DriverOptions): Promise<void>;
141
+ dropTable(object: string, _options?: DriverOptions): Promise<void>;
96
142
  /**
97
143
  * Batch-initialise tables from an array of object definitions.
98
144
  */
99
145
  initObjects(objects: Array<{
100
146
  name: string;
147
+ tableName?: string;
101
148
  fields?: Record<string, any>;
102
149
  }>): Promise<void>;
103
150
  introspectSchema(): Promise<IntrospectedSchema>;
104
151
  /** Expose the underlying Knex instance for advanced usage. */
105
152
  getKnex(): Knex;
106
- private getBuilder;
107
- private applyFilters;
108
- private applyFilterCondition;
109
- private mapSortField;
110
- private mapAggregateFunc;
111
- private buildWindowFunction;
112
- private createColumn;
113
- private ensureDatabaseExists;
114
- private createDatabase;
115
- private isJsonField;
116
- private formatInput;
117
- private formatOutput;
118
- private introspectColumns;
119
- private introspectForeignKeys;
120
- private introspectPrimaryKeys;
121
- private introspectUniqueConstraints;
153
+ protected getBuilder(object: string, options?: DriverOptions): knex.Knex.QueryBuilder<any, {
154
+ _base: any;
155
+ _hasSelection: false;
156
+ _keys: never;
157
+ _aliases: {};
158
+ _single: false;
159
+ _intersectProps: {};
160
+ _unionProps: never;
161
+ }[]>;
162
+ protected applyFilters(builder: Knex.QueryBuilder, filters: any): void;
163
+ protected applyFilterCondition(builder: Knex.QueryBuilder, condition: any, logicalOp?: 'and' | 'or'): void;
164
+ protected mapSortField(field: string): string;
165
+ protected mapAggregateFunc(func: string): string;
166
+ protected buildWindowFunction(spec: any): string;
167
+ protected createColumn(table: Knex.CreateTableBuilder, name: string, field: any): void;
168
+ protected ensureDatabaseExists(): Promise<void>;
169
+ protected createDatabase(): Promise<void>;
170
+ protected isJsonField(type: string, field: any): boolean;
171
+ protected formatInput(object: string, data: any): any;
172
+ protected formatOutput(object: string, data: any): any;
173
+ protected introspectColumns(tableName: string): Promise<IntrospectedColumn[]>;
174
+ protected introspectForeignKeys(tableName: string): Promise<IntrospectedForeignKey[]>;
175
+ protected introspectPrimaryKeys(tableName: string): Promise<string[]>;
176
+ protected introspectUniqueConstraints(tableName: string): Promise<string[]>;
122
177
  }
123
178
 
124
179
  declare const _default: {
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { QueryInput, DriverOptions } from '@objectstack/spec/data';
2
- import { DriverInterface } from '@objectstack/core';
3
- import { Knex } from 'knex';
1
+ import { QueryAST, DriverOptions } from '@objectstack/spec/data';
2
+ import { IDataDriver } from '@objectstack/spec/contracts';
3
+ import knex, { Knex } from 'knex';
4
4
 
5
5
  /**
6
6
  * SQL Driver for ObjectStack
7
7
  *
8
- * Implements the standard DriverInterface from @objectstack/spec via Knex.js.
8
+ * Implements the standard IDataDriver from @objectstack/spec via Knex.js.
9
9
  * Supports PostgreSQL, MySQL, SQLite, and other SQL databases.
10
10
  */
11
11
 
@@ -41,84 +41,139 @@ type SqlDriverConfig = Knex.Config;
41
41
  /**
42
42
  * SQL Driver for ObjectStack.
43
43
  *
44
- * Implements the DriverInterface contract via Knex.js for optimal SQL
44
+ * Implements the IDataDriver contract via Knex.js for optimal SQL
45
45
  * generation against PostgreSQL, MySQL, SQLite and other SQL databases.
46
46
  */
47
- declare class SqlDriver implements DriverInterface {
48
- readonly name = "com.objectstack.driver.sql";
49
- readonly version = "1.0.0";
47
+ declare class SqlDriver implements IDataDriver {
48
+ readonly name: string;
49
+ readonly version: string;
50
50
  readonly supports: {
51
+ create: boolean;
52
+ read: boolean;
53
+ update: boolean;
54
+ delete: boolean;
55
+ bulkCreate: boolean;
56
+ bulkUpdate: boolean;
57
+ bulkDelete: boolean;
51
58
  transactions: boolean;
52
- joins: boolean;
53
- fullTextSearch: boolean;
54
- jsonFields: boolean;
55
- arrayFields: boolean;
59
+ savepoints: boolean;
56
60
  queryFilters: boolean;
57
61
  queryAggregations: boolean;
58
62
  querySorting: boolean;
59
63
  queryPagination: boolean;
60
64
  queryWindowFunctions: boolean;
61
65
  querySubqueries: boolean;
66
+ queryCTE: boolean;
67
+ joins: boolean;
68
+ fullTextSearch: boolean;
69
+ jsonQuery: boolean;
70
+ geospatialQuery: boolean;
71
+ streaming: boolean;
72
+ jsonFields: boolean;
73
+ arrayFields: boolean;
74
+ vectorSearch: boolean;
75
+ schemaSync: boolean;
76
+ batchSchemaSync: boolean;
77
+ migrations: boolean;
78
+ indexes: boolean;
79
+ connectionPooling: boolean;
80
+ preparedStatements: boolean;
81
+ queryCache: boolean;
62
82
  };
63
- private knex;
64
- private config;
65
- private jsonFields;
66
- private booleanFields;
67
- private tablesWithTimestamps;
83
+ protected knex: Knex;
84
+ protected config: Knex.Config;
85
+ protected jsonFields: Record<string, string[]>;
86
+ protected booleanFields: Record<string, string[]>;
87
+ protected tablesWithTimestamps: Set<string>;
68
88
  /** Whether the underlying database is a SQLite variant (sqlite3 or better-sqlite3). */
69
- private get isSqlite();
89
+ protected get isSqlite(): boolean;
70
90
  /** Whether the underlying database is PostgreSQL. */
71
- private get isPostgres();
91
+ protected get isPostgres(): boolean;
72
92
  /** Whether the underlying database is MySQL. */
73
- private get isMysql();
93
+ protected get isMysql(): boolean;
74
94
  constructor(config: SqlDriverConfig);
75
95
  connect(): Promise<void>;
76
96
  checkHealth(): Promise<boolean>;
77
97
  disconnect(): Promise<void>;
78
- find(object: string, query: QueryInput, options?: DriverOptions): Promise<any[]>;
79
- findOne(object: string, query: QueryInput, options?: DriverOptions): Promise<any>;
98
+ find(object: string, query: QueryAST, options?: DriverOptions): Promise<any[]>;
99
+ findOne(object: string, query: QueryAST, options?: DriverOptions): Promise<any>;
100
+ /**
101
+ * Stream records matching a structured query.
102
+ * NOTE: Current implementation fetches all results then yields them.
103
+ * TODO: Use Knex .stream() for true cursor-based streaming on large datasets.
104
+ */
105
+ findStream(object: string, query: QueryAST, options?: DriverOptions): AsyncGenerator<Record<string, any>>;
80
106
  create(object: string, data: Record<string, any>, options?: DriverOptions): Promise<any>;
81
107
  update(object: string, id: string | number, data: Record<string, any>, options?: DriverOptions): Promise<any>;
82
- delete(object: string, id: string | number, options?: DriverOptions): Promise<any>;
108
+ upsert(object: string, data: Record<string, any>, conflictKeys?: string[], options?: DriverOptions): Promise<Record<string, any>>;
109
+ delete(object: string, id: string | number, options?: DriverOptions): Promise<boolean>;
83
110
  bulkCreate(object: string, data: any[], options?: DriverOptions): Promise<any>;
84
- updateMany(object: string, query: QueryInput, data: any, options?: DriverOptions): Promise<any>;
85
- deleteMany(object: string, query: QueryInput, options?: DriverOptions): Promise<any>;
86
- count(object: string, query: QueryInput, options?: DriverOptions): Promise<number>;
111
+ /**
112
+ * Batch-update multiple records by ID.
113
+ * NOTE: Current implementation performs sequential updates for correctness.
114
+ * TODO: Optimize with SQL CASE statements or batched transactions for performance.
115
+ */
116
+ bulkUpdate(object: string, updates: Array<{
117
+ id: string | number;
118
+ data: Record<string, any>;
119
+ }>, options?: DriverOptions): Promise<Record<string, any>[]>;
120
+ bulkDelete(object: string, ids: Array<string | number>, options?: DriverOptions): Promise<void>;
121
+ updateMany(object: string, query: QueryAST, data: any, options?: DriverOptions): Promise<number>;
122
+ deleteMany(object: string, query: QueryAST, options?: DriverOptions): Promise<number>;
123
+ count(object: string, query?: QueryAST, options?: DriverOptions): Promise<number>;
87
124
  execute(command: any, params?: any[], options?: DriverOptions): Promise<any>;
88
125
  beginTransaction(): Promise<Knex.Transaction>;
126
+ /** IDataDriver standard */
127
+ commit(transaction: unknown): Promise<void>;
128
+ /** IDataDriver standard */
129
+ rollback(transaction: unknown): Promise<void>;
130
+ /** @deprecated Use commit() instead */
89
131
  commitTransaction(trx: Knex.Transaction): Promise<void>;
132
+ /** @deprecated Use rollback() instead */
90
133
  rollbackTransaction(trx: Knex.Transaction): Promise<void>;
91
134
  aggregate(object: string, query: any, options?: DriverOptions): Promise<any>;
92
135
  distinct(object: string, field: string, filters?: any, options?: DriverOptions): Promise<any[]>;
93
136
  findWithWindowFunctions(object: string, query: any, options?: DriverOptions): Promise<any[]>;
137
+ /** IDataDriver standard: analyze query performance */
138
+ explain(object: string, query: any, options?: DriverOptions): Promise<any>;
94
139
  analyzeQuery(object: string, query: any, options?: DriverOptions): Promise<any>;
95
140
  syncSchema(object: string, schema: unknown, _options?: DriverOptions): Promise<void>;
141
+ dropTable(object: string, _options?: DriverOptions): Promise<void>;
96
142
  /**
97
143
  * Batch-initialise tables from an array of object definitions.
98
144
  */
99
145
  initObjects(objects: Array<{
100
146
  name: string;
147
+ tableName?: string;
101
148
  fields?: Record<string, any>;
102
149
  }>): Promise<void>;
103
150
  introspectSchema(): Promise<IntrospectedSchema>;
104
151
  /** Expose the underlying Knex instance for advanced usage. */
105
152
  getKnex(): Knex;
106
- private getBuilder;
107
- private applyFilters;
108
- private applyFilterCondition;
109
- private mapSortField;
110
- private mapAggregateFunc;
111
- private buildWindowFunction;
112
- private createColumn;
113
- private ensureDatabaseExists;
114
- private createDatabase;
115
- private isJsonField;
116
- private formatInput;
117
- private formatOutput;
118
- private introspectColumns;
119
- private introspectForeignKeys;
120
- private introspectPrimaryKeys;
121
- private introspectUniqueConstraints;
153
+ protected getBuilder(object: string, options?: DriverOptions): knex.Knex.QueryBuilder<any, {
154
+ _base: any;
155
+ _hasSelection: false;
156
+ _keys: never;
157
+ _aliases: {};
158
+ _single: false;
159
+ _intersectProps: {};
160
+ _unionProps: never;
161
+ }[]>;
162
+ protected applyFilters(builder: Knex.QueryBuilder, filters: any): void;
163
+ protected applyFilterCondition(builder: Knex.QueryBuilder, condition: any, logicalOp?: 'and' | 'or'): void;
164
+ protected mapSortField(field: string): string;
165
+ protected mapAggregateFunc(func: string): string;
166
+ protected buildWindowFunction(spec: any): string;
167
+ protected createColumn(table: Knex.CreateTableBuilder, name: string, field: any): void;
168
+ protected ensureDatabaseExists(): Promise<void>;
169
+ protected createDatabase(): Promise<void>;
170
+ protected isJsonField(type: string, field: any): boolean;
171
+ protected formatInput(object: string, data: any): any;
172
+ protected formatOutput(object: string, data: any): any;
173
+ protected introspectColumns(tableName: string): Promise<IntrospectedColumn[]>;
174
+ protected introspectForeignKeys(tableName: string): Promise<IntrospectedForeignKey[]>;
175
+ protected introspectPrimaryKeys(tableName: string): Promise<string[]>;
176
+ protected introspectUniqueConstraints(tableName: string): Promise<string[]>;
122
177
  }
123
178
 
124
179
  declare const _default: {