@mlagie/sql-connector 3.0.3 → 3.1.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/docs/API.md ADDED
@@ -0,0 +1,240 @@
1
+ # API reference
2
+
3
+ ## Table of contents
4
+
5
+ 1. [Root exports](#root-exports)
6
+ 2. [Connection](#connection)
7
+ 3. [Schema](#schema)
8
+ 4. [Model](#model)
9
+ 5. [ModelInstance](#modelinstance)
10
+ 6. [Migration](#migration)
11
+ 7. [MigrationPlan](#migrationplan)
12
+ 8. [MigrationStore](#migrationstore)
13
+ 9. [MigrationRunner](#migrationrunner)
14
+ 10. [SchemaDiffer](#schemadiffer)
15
+ 11. [SchemaInspector](#schemainspector)
16
+ 12. [Dialect classes](#dialect-classes)
17
+
18
+ ## Root exports
19
+
20
+ ```js
21
+ const api = require('@mlagie/sql-connector');
22
+ ```
23
+
24
+ Exports:
25
+
26
+ ```text
27
+ client
28
+ connect
29
+ logout
30
+ Schema
31
+ Model
32
+ ModelInstance
33
+ sqlTypeMap
34
+ Migration
35
+ MigrationPlan
36
+ MigrationStore
37
+ MigrationRunner
38
+ SchemaDiffer
39
+ SchemaInspector
40
+ MySQLDialect
41
+ PostgreSQLDialect
42
+ MigrationError
43
+ DestructiveMigrationError
44
+ MigrationChecksumError
45
+ ```
46
+
47
+ ## Connection
48
+
49
+ ### `connect(config, dialect?)`
50
+
51
+ Connects to MySQL by default or PostgreSQL when `dialect` is `postgres`.
52
+
53
+ ### `logout()`
54
+
55
+ Closes the active connector connection.
56
+
57
+ ## Schema
58
+
59
+ ### `new Schema(schemaDict)`
60
+
61
+ Stores a declarative table schema.
62
+
63
+ Property:
64
+
65
+ - `schemaDict` — field definitions.
66
+
67
+ ## Model
68
+
69
+ ### `new Model(name, schema)`
70
+
71
+ Creates a model for a table.
72
+
73
+ ### `Model.syncAllTables()`
74
+
75
+ Creates all pending model tables in dependency order.
76
+
77
+ ### `model.save(data)`
78
+
79
+ Inserts a row.
80
+
81
+ ### `model.find(options?)`
82
+
83
+ Returns `ModelInstance[]` using structured filters and query options.
84
+
85
+ ### `model.count(filter?)`
86
+
87
+ Returns the number of matching rows.
88
+
89
+ ### `model.delete(filter)`
90
+
91
+ Deletes matching rows and returns the affected-row status used by the model API.
92
+
93
+ ### `model.dropTable()`
94
+
95
+ Drops the model table.
96
+
97
+ ### `model.generate_uuid(column?)`
98
+
99
+ Generates a unique UUID for a column, defaulting to `uuid`.
100
+
101
+ ### `model.customRequest(sql)`
102
+
103
+ Executes trusted raw SQL.
104
+
105
+ ## ModelInstance
106
+
107
+ ### `instance.updateOne(data)`
108
+
109
+ Updates the loaded row, preferring primary-key fields from its schema when available.
110
+
111
+ ### `instance.delete(filter?)`
112
+
113
+ Deletes the current row or the supplied filter.
114
+
115
+ ### `instance.customRequest(sql)`
116
+
117
+ Executes trusted raw SQL and wraps returned data.
118
+
119
+ ### `instance.getRecordData()`
120
+
121
+ Returns the underlying record data.
122
+
123
+ ### `instance.toJSON()`
124
+
125
+ Returns record data for JSON serialization.
126
+
127
+ ## Migration
128
+
129
+ ### `new Migration(options?)`
130
+
131
+ Options include:
132
+
133
+ - `connection`;
134
+ - `dialect`;
135
+ - `models`;
136
+ - `directory`;
137
+ - `backupDirectory`;
138
+ - `encryptionKey`;
139
+ - `retention`;
140
+ - `allowDestructiveChanges`;
141
+ - `allowDropTables`.
142
+
143
+ Methods:
144
+
145
+ - `plan(options?)`;
146
+ - `migrate(options?)`;
147
+ - `status()`;
148
+ - `cleanup()`.
149
+
150
+ Static methods:
151
+
152
+ - `Migration.plan(options?)`;
153
+ - `Migration.migrate(options?)`;
154
+ - `Migration.status(options?)`.
155
+
156
+ ## MigrationPlan
157
+
158
+ Properties:
159
+
160
+ - `id`;
161
+ - `operations`;
162
+ - `sql`;
163
+ - `snapshot`;
164
+ - `previousSnapshot`;
165
+ - `dialect`;
166
+ - `checksum`;
167
+ - `approved`.
168
+
169
+ Methods:
170
+
171
+ - `hasChanges()`;
172
+ - `hasDestructiveChanges()`;
173
+ - `destructiveChanges()`;
174
+ - `approve()`;
175
+ - `execute(options?)`;
176
+ - `toJSON()`.
177
+
178
+ ## MigrationStore
179
+
180
+ Constructor options:
181
+
182
+ - `directory`;
183
+ - `backupDirectory`;
184
+ - `encryptionKey`;
185
+ - `retention`.
186
+
187
+ Methods:
188
+
189
+ - `ensureDirectories()`;
190
+ - `writeMigration(plan)`;
191
+ - `writeBackup(name, content)`;
192
+ - `cleanup()`;
193
+ - `writeSnapshot(snapshot)`;
194
+ - `readSnapshot()`;
195
+ - `listMigrationFiles()`;
196
+ - `validateChecksum(actual, expected)`.
197
+
198
+ ## MigrationRunner
199
+
200
+ Methods:
201
+
202
+ - `ensureMigrationTable()`;
203
+ - `applied()`;
204
+ - `execute(plan, options?)`;
205
+ - `sqlForOperation(operation)`.
206
+
207
+ ## SchemaDiffer
208
+
209
+ Constructor options:
210
+
211
+ - `allowDestructiveChanges`;
212
+ - `allowDropTables`.
213
+
214
+ ### `diff(desired, current)`
215
+
216
+ Returns migration operations.
217
+
218
+ ## SchemaInspector
219
+
220
+ ### `inspect()`
221
+
222
+ Returns the normalized database schema snapshot used by the migration planner.
223
+
224
+ ## Migration errors
225
+
226
+ ### `MigrationError`
227
+
228
+ Base migration error with a `code` and optional `details`.
229
+
230
+ ### `DestructiveMigrationError`
231
+
232
+ Raised when a destructive schema operation is not explicitly authorized.
233
+
234
+ ### `MigrationChecksumError`
235
+
236
+ Raised when a migration checksum does not match the expected value.
237
+
238
+ ## Dialect classes
239
+
240
+ `MySQLDialect` and `PostgreSQLDialect` implement migration-specific SQL generation and introspection.
@@ -0,0 +1,56 @@
1
+ # SQL dialect reference
2
+
3
+ ## Table of contents
4
+
5
+ 1. [Supported dialects](#supported-dialects)
6
+ 2. [Runtime query behavior](#runtime-query-behavior)
7
+ 3. [Migration DDL](#migration-ddl)
8
+ 4. [MySQL](#mysql)
9
+ 5. [PostgreSQL](#postgresql)
10
+
11
+ ## Supported dialects
12
+
13
+ The connector supports:
14
+
15
+ - `mysql`;
16
+ - `postgres`.
17
+
18
+ MySQL is the default runtime dialect.
19
+
20
+ ## Runtime query behavior
21
+
22
+ | Behavior | MySQL | PostgreSQL |
23
+ |---|---|---|
24
+ | Identifier quote | `` `name` `` | `"name"` |
25
+ | Parameter | `?` | `$1`, `$2`, ... |
26
+ | Boolean literal | `1` / `0` | `TRUE` / `FALSE` |
27
+ | UUID generation | `UUID()` | `gen_random_uuid()` |
28
+
29
+ The query layer tracks placeholder indexes so conditions such as `IN`, `BETWEEN`, `LIMIT` and `OFFSET` remain valid for PostgreSQL.
30
+
31
+ ## Migration DDL
32
+
33
+ The migration subsystem uses dedicated dialect classes because schema DDL requires different SQL on MySQL and PostgreSQL.
34
+
35
+ Migration-specific responsibilities include:
36
+
37
+ - type mapping;
38
+ - column definitions;
39
+ - table creation;
40
+ - adding, renaming, altering and dropping columns;
41
+ - table removal;
42
+ - schema introspection;
43
+ - migration-history storage;
44
+ - transactional DDL behavior.
45
+
46
+ ## MySQL
47
+
48
+ The runtime uses `mysql2`.
49
+
50
+ The migration dialect creates the migration history table with `DATETIME` timestamps and uses InnoDB table options for generated tables.
51
+
52
+ ## PostgreSQL
53
+
54
+ The runtime uses `pg`.
55
+
56
+ The migration dialect uses PostgreSQL identity syntax for auto-incrementing integer fields and `TIMESTAMPTZ` for migration-history timestamps.
@@ -0,0 +1,277 @@
1
+ # Migration reference
2
+
3
+ ## Table of contents
4
+
5
+ 1. [Purpose](#purpose)
6
+ 2. [Prerequisites](#prerequisites)
7
+ 3. [Planning](#planning)
8
+ 4. [Executing](#executing)
9
+ 5. [Migration options](#migration-options)
10
+ 6. [Operations](#operations)
11
+ 7. [Renames](#renames)
12
+ 8. [Destructive changes](#destructive-changes)
13
+ 9. [Checksums and history](#checksums-and-history)
14
+ 10. [Encrypted migration files](#encrypted-migration-files)
15
+ 11. [Backups](#backups)
16
+ 12. [Status and cleanup](#status-and-cleanup)
17
+ 13. [Migration classes](#migration-classes)
18
+
19
+ ## Purpose
20
+
21
+ The migration subsystem turns model schemas into controlled database schema changes.
22
+
23
+ It compares:
24
+
25
+ - the desired schema derived from `Model` objects;
26
+ - the schema currently reported by the active database dialect.
27
+
28
+ It then creates explicit operations and dialect-specific SQL.
29
+
30
+ ## Prerequisites
31
+
32
+ Connect before constructing a migration unless an explicit connection is supplied:
33
+
34
+ ```js
35
+ await connect(config, 'postgres');
36
+ const migration = new Migration();
37
+ ```
38
+
39
+ For writing migration files, provide an encryption key through `encryptionKey` or `SQL_CONNECTOR_MIGRATION_KEY`.
40
+
41
+ ## Planning
42
+
43
+ ```js
44
+ const plan = await Migration.plan({
45
+ name: 'users-schema',
46
+ });
47
+ ```
48
+
49
+ The plan contains:
50
+
51
+ - `id`;
52
+ - `dialect`;
53
+ - `checksum`;
54
+ - `operations`;
55
+ - generated `sql`;
56
+ - desired snapshot;
57
+ - baseline snapshot.
58
+
59
+ Inspect it before execution:
60
+
61
+ ```js
62
+ console.log(plan.toJSON());
63
+ console.log(plan.sql);
64
+ ```
65
+
66
+ ## Executing
67
+
68
+ Approval is required by default:
69
+
70
+ ```js
71
+ const plan = await Migration.plan({ name: 'users-schema' });
72
+
73
+ if (plan.hasChanges()) {
74
+ plan.approve();
75
+ await plan.execute();
76
+ }
77
+ ```
78
+
79
+ Or:
80
+
81
+ ```js
82
+ await Migration.migrate({
83
+ name: 'users-schema',
84
+ });
85
+ ```
86
+
87
+ `Migration.migrate()` approves a changed plan by default and then executes it with the runner's approval checks enabled.
88
+
89
+ ## Migration options
90
+
91
+ ```js
92
+ new Migration({
93
+ connection,
94
+ dialect: 'mysql',
95
+ models,
96
+ directory: './migrations',
97
+ backupDirectory: './migrations/backups',
98
+ encryptionKey: process.env.SQL_CONNECTOR_MIGRATION_KEY,
99
+ retention: '30d',
100
+ allowDestructiveChanges: false,
101
+ allowDropTables: false,
102
+ });
103
+ ```
104
+
105
+ `retention` accepts milliseconds as a number or strings using `ms`, `s`, `m`, `h`, `d` and `w`.
106
+
107
+ ## Operations
108
+
109
+ The differ can generate:
110
+
111
+ - `createTable`;
112
+ - `addColumn`;
113
+ - `renameColumn`;
114
+ - `alterColumn`;
115
+ - `dropColumn`;
116
+ - `dropTable`.
117
+
118
+ The first four are non-destructive in the differ's classification. `dropColumn` and `dropTable` are destructive.
119
+
120
+ ## Renames
121
+
122
+ Declare a rename explicitly:
123
+
124
+ ```js
125
+ const schema = new Schema({
126
+ email_address: {
127
+ type: String,
128
+ length: 320,
129
+ oldname: 'email',
130
+ },
131
+ });
132
+ ```
133
+
134
+ The differ checks that the old column exists and that the new name is not already occupied.
135
+
136
+ ## Destructive changes
137
+
138
+ By default:
139
+
140
+ - dropping a column throws `DestructiveMigrationError`;
141
+ - dropping a table throws `DestructiveMigrationError`.
142
+
143
+ Allow them explicitly during planning and execution:
144
+
145
+ ```js
146
+ const plan = await migration.plan({
147
+ allowDestructiveChanges: true,
148
+ allowDropTables: true,
149
+ });
150
+
151
+ plan.approve();
152
+
153
+ await plan.execute({
154
+ allowDestructiveChanges: true,
155
+ });
156
+ ```
157
+
158
+ Use these options deliberately in production workflows.
159
+
160
+ ## Checksums and history
161
+
162
+ The runner creates `sql_connector_migrations` in the active database.
163
+
164
+ Each applied migration stores:
165
+
166
+ - migration id;
167
+ - SHA-256 checksum;
168
+ - applied timestamp;
169
+ - creation timestamp.
170
+
171
+ If an id already exists with a different checksum, execution fails rather than changing migration history silently.
172
+
173
+ ## Encrypted migration files
174
+
175
+ After a successful migration, the desired schema snapshot is also persisted as `schema.snapshot.json`. Applied plans are written as encrypted files named:
176
+
177
+ ```text
178
+ <directory>/<migration-id>.sql.enc
179
+ ```
180
+
181
+ The encryption key is required to write these files.
182
+
183
+ ```bash
184
+ export SQL_CONNECTOR_MIGRATION_KEY='a-long-random-secret'
185
+ ```
186
+
187
+ The encryption implementation uses AES-256-GCM and a derived key.
188
+
189
+ ## Backups
190
+
191
+ If retention is enabled, affected tables are selected before execution and stored as encrypted JSON:
192
+
193
+ ```text
194
+ <backupDirectory>/<migration-id>.json.enc
195
+ ```
196
+
197
+ ```js
198
+ const migration = new Migration({
199
+ encryptionKey: process.env.SQL_CONNECTOR_MIGRATION_KEY,
200
+ retention: '30d',
201
+ });
202
+ ```
203
+
204
+ Backups are data snapshots, not automatic rollback scripts. Restoration must be handled separately.
205
+
206
+ ## Status and cleanup
207
+
208
+ ```js
209
+ const migration = new Migration();
210
+ const status = await migration.status();
211
+ console.table(status);
212
+
213
+ await migration.cleanup();
214
+ ```
215
+
216
+ `cleanup()` removes backup files older than the configured retention period.
217
+
218
+ ## Migration classes
219
+
220
+ ### `Migration`
221
+
222
+ High-level API for planning, applying, checking status and cleaning backups.
223
+
224
+ Methods:
225
+
226
+ - `plan(options)`;
227
+ - `migrate(options)`;
228
+ - `status()`;
229
+ - `cleanup()`.
230
+
231
+ Static equivalents:
232
+
233
+ - `Migration.plan(options)`;
234
+ - `Migration.migrate(options)`;
235
+ - `Migration.status(options)`.
236
+
237
+ ### `MigrationPlan`
238
+
239
+ Methods:
240
+
241
+ - `hasChanges()`;
242
+ - `hasDestructiveChanges()`;
243
+ - `destructiveChanges()`;
244
+ - `approve()`;
245
+ - `execute(options)`;
246
+ - `toJSON()`.
247
+
248
+ ### `MigrationStore`
249
+
250
+ Manages:
251
+
252
+ - migration directory;
253
+ - backup directory;
254
+ - encrypted migration files;
255
+ - encrypted backups;
256
+ - schema snapshot;
257
+ - retention cleanup;
258
+ - checksum validation.
259
+
260
+ ### `MigrationRunner`
261
+
262
+ Responsible for:
263
+
264
+ - migration history table;
265
+ - operation execution;
266
+ - transaction handling through the dialect;
267
+ - checksum consistency;
268
+ - backup creation;
269
+ - persisted migration state.
270
+
271
+ ### `SchemaDiffer`
272
+
273
+ Compares desired and current snapshots and produces migration operations.
274
+
275
+ ### `SchemaInspector`
276
+
277
+ Reads the active database schema through dialect-specific information-schema queries.