@noormdev/sdk 1.0.0-alpha.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/dist/chunk-MERTHCAJ.js +299 -0
- package/dist/chunk-MERTHCAJ.js.map +1 -0
- package/dist/engine-B4JH5RQJ.js +3 -0
- package/dist/engine-B4JH5RQJ.js.map +1 -0
- package/dist/index.d.ts +2083 -0
- package/dist/index.js +8150 -0
- package/dist/index.js.map +1 -0
- package/dist/mssql-T4M7OGEC.js +46 -0
- package/dist/mssql-T4M7OGEC.js.map +1 -0
- package/dist/mysql-C2DR4TF7.js +28 -0
- package/dist/mysql-C2DR4TF7.js.map +1 -0
- package/dist/postgres-SIDJBSIT.js +29 -0
- package/dist/postgres-SIDJBSIT.js.map +1 -0
- package/dist/sqlite-5VZTBN5J.js +21 -0
- package/dist/sqlite-5VZTBN5J.js.map +1 -0
- package/package.json +56 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,2083 @@
|
|
|
1
|
+
// Generated by dts-bundle-generator v9.5.1
|
|
2
|
+
|
|
3
|
+
import { Kysely } from 'kysely';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Supported database dialects.
|
|
7
|
+
*/
|
|
8
|
+
export type Dialect = "postgres" | "mysql" | "sqlite" | "mssql";
|
|
9
|
+
/**
|
|
10
|
+
* Database connection configuration.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const postgresConfig: ConnectionConfig = {
|
|
15
|
+
* dialect: 'postgres',
|
|
16
|
+
* host: 'localhost',
|
|
17
|
+
* port: 5432,
|
|
18
|
+
* database: 'myapp',
|
|
19
|
+
* user: 'postgres',
|
|
20
|
+
* password: 'secret',
|
|
21
|
+
* }
|
|
22
|
+
*
|
|
23
|
+
* const sqliteConfig: ConnectionConfig = {
|
|
24
|
+
* dialect: 'sqlite',
|
|
25
|
+
* database: './data.db',
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export interface ConnectionConfig {
|
|
30
|
+
dialect: Dialect;
|
|
31
|
+
host?: string;
|
|
32
|
+
port?: number;
|
|
33
|
+
user?: string;
|
|
34
|
+
password?: string;
|
|
35
|
+
database: string;
|
|
36
|
+
filename?: string;
|
|
37
|
+
pool?: {
|
|
38
|
+
min?: number;
|
|
39
|
+
max?: number;
|
|
40
|
+
};
|
|
41
|
+
ssl?: boolean | {
|
|
42
|
+
rejectUnauthorized?: boolean;
|
|
43
|
+
ca?: string;
|
|
44
|
+
cert?: string;
|
|
45
|
+
key?: string;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Full configuration object.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```typescript
|
|
53
|
+
* const config: Config = {
|
|
54
|
+
* name: 'dev',
|
|
55
|
+
* type: 'local',
|
|
56
|
+
* isTest: false,
|
|
57
|
+
* protected: false,
|
|
58
|
+
* connection: {
|
|
59
|
+
* dialect: 'postgres',
|
|
60
|
+
* host: 'localhost',
|
|
61
|
+
* port: 5432,
|
|
62
|
+
* database: 'myapp_dev',
|
|
63
|
+
* user: 'postgres',
|
|
64
|
+
* password: 'postgres',
|
|
65
|
+
* },
|
|
66
|
+
* paths: {
|
|
67
|
+
* sql: './sql',
|
|
68
|
+
* changes: './changes',
|
|
69
|
+
* },
|
|
70
|
+
* }
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export interface Config {
|
|
74
|
+
name: string;
|
|
75
|
+
type: "local" | "remote";
|
|
76
|
+
isTest: boolean;
|
|
77
|
+
protected: boolean;
|
|
78
|
+
connection: ConnectionConfig;
|
|
79
|
+
paths: {
|
|
80
|
+
sql: string;
|
|
81
|
+
changes: string;
|
|
82
|
+
};
|
|
83
|
+
identity?: string;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Settings Types
|
|
87
|
+
*
|
|
88
|
+
* Settings define project-wide build behavior and stage configuration.
|
|
89
|
+
* Unlike encrypted configs (credentials), settings are version controlled
|
|
90
|
+
* and shared across the team via .noorm/settings.yml
|
|
91
|
+
*/
|
|
92
|
+
/**
|
|
93
|
+
* Secret type hints for CLI input handling.
|
|
94
|
+
*
|
|
95
|
+
* - string: Plain text input
|
|
96
|
+
* - password: Masked input, no echo
|
|
97
|
+
* - api_key: Masked input, validated format
|
|
98
|
+
* - connection_string: Validated as URI
|
|
99
|
+
*/
|
|
100
|
+
export type SecretType = "string" | "password" | "api_key" | "connection_string";
|
|
101
|
+
/**
|
|
102
|
+
* Required secret definition for a stage.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```yaml
|
|
106
|
+
* secrets:
|
|
107
|
+
* - key: DB_PASSWORD
|
|
108
|
+
* type: password
|
|
109
|
+
* description: Database password
|
|
110
|
+
* required: true
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
export interface StageSecret {
|
|
114
|
+
/** Secret key name (e.g., DB_PASSWORD) */
|
|
115
|
+
key: string;
|
|
116
|
+
/** Type hint for CLI input handling */
|
|
117
|
+
type: SecretType;
|
|
118
|
+
/** Human-readable description shown in CLI prompts */
|
|
119
|
+
description?: string;
|
|
120
|
+
/** Whether the secret is required (default: true) */
|
|
121
|
+
required?: boolean;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Stage defaults that can be overridden when creating a config.
|
|
125
|
+
*
|
|
126
|
+
* These provide initial values. Some are enforceable constraints:
|
|
127
|
+
* - protected: true - Cannot be overridden to false
|
|
128
|
+
* - isTest: true - Cannot be overridden to false
|
|
129
|
+
* - dialect - Cannot be changed after creation
|
|
130
|
+
*/
|
|
131
|
+
export interface StageDefaults {
|
|
132
|
+
dialect?: "postgres" | "mysql" | "sqlite" | "mssql";
|
|
133
|
+
host?: string;
|
|
134
|
+
port?: number;
|
|
135
|
+
database?: string;
|
|
136
|
+
user?: string;
|
|
137
|
+
password?: string;
|
|
138
|
+
ssl?: boolean;
|
|
139
|
+
isTest?: boolean;
|
|
140
|
+
protected?: boolean;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Stage definition - a preconfigured config template.
|
|
144
|
+
*
|
|
145
|
+
* Stages are team-defined config templates with defaults, constraints,
|
|
146
|
+
* and required secrets. They're managed via version control.
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```yaml
|
|
150
|
+
* stages:
|
|
151
|
+
* prod:
|
|
152
|
+
* description: Production database
|
|
153
|
+
* locked: true
|
|
154
|
+
* defaults:
|
|
155
|
+
* dialect: postgres
|
|
156
|
+
* protected: true
|
|
157
|
+
* secrets:
|
|
158
|
+
* - key: DB_PASSWORD
|
|
159
|
+
* type: password
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
export interface Stage {
|
|
163
|
+
/** Human-readable description shown in CLI */
|
|
164
|
+
description?: string;
|
|
165
|
+
/** If true, configs linked to this stage cannot be deleted */
|
|
166
|
+
locked?: boolean;
|
|
167
|
+
/** Default values when creating config from this stage */
|
|
168
|
+
defaults?: StageDefaults;
|
|
169
|
+
/** Required secrets that must be set before config is usable */
|
|
170
|
+
secrets?: StageSecret[];
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Conditions for rule matching.
|
|
174
|
+
*
|
|
175
|
+
* All conditions in a rule are AND'd together.
|
|
176
|
+
* A rule matches when ALL specified conditions are true.
|
|
177
|
+
*/
|
|
178
|
+
export interface RuleMatch {
|
|
179
|
+
/** Config name (exact match) */
|
|
180
|
+
name?: string;
|
|
181
|
+
/** Protected config flag */
|
|
182
|
+
protected?: boolean;
|
|
183
|
+
/** Test database flag */
|
|
184
|
+
isTest?: boolean;
|
|
185
|
+
/** Connection type */
|
|
186
|
+
type?: "local" | "remote";
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Stage-based rule for conditional include/exclude.
|
|
190
|
+
*
|
|
191
|
+
* Rules control which files/folders are included or excluded
|
|
192
|
+
* based on the active config's properties.
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* ```yaml
|
|
196
|
+
* rules:
|
|
197
|
+
* - match:
|
|
198
|
+
* isTest: true
|
|
199
|
+
* include:
|
|
200
|
+
* - sql/seeds
|
|
201
|
+
* - match:
|
|
202
|
+
* protected: true
|
|
203
|
+
* exclude:
|
|
204
|
+
* - sql/dangerous
|
|
205
|
+
* ```
|
|
206
|
+
*/
|
|
207
|
+
export interface Rule {
|
|
208
|
+
/** User-friendly description (e.g., "test seeds", "prod config") */
|
|
209
|
+
description?: string;
|
|
210
|
+
/** Conditions that must all match */
|
|
211
|
+
match: RuleMatch;
|
|
212
|
+
/** Folders to include when rule matches */
|
|
213
|
+
include?: string[];
|
|
214
|
+
/** Folders to exclude when rule matches */
|
|
215
|
+
exclude?: string[];
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Build configuration - controls file inclusion and execution order.
|
|
219
|
+
*/
|
|
220
|
+
export interface BuildConfig {
|
|
221
|
+
/**
|
|
222
|
+
* Folders to include, executed in this order.
|
|
223
|
+
* First listed = first executed.
|
|
224
|
+
*/
|
|
225
|
+
include?: string[];
|
|
226
|
+
/** Folders to exclude from all builds */
|
|
227
|
+
exclude?: string[];
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Path configuration - override default locations.
|
|
231
|
+
*/
|
|
232
|
+
export interface PathConfig {
|
|
233
|
+
/** Path to SQL files (relative to project root) */
|
|
234
|
+
sql?: string;
|
|
235
|
+
/** Path to change files (relative to project root) */
|
|
236
|
+
changes?: string;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Strict mode configuration.
|
|
240
|
+
*
|
|
241
|
+
* When enabled, requires certain stages to exist before operations can run.
|
|
242
|
+
*/
|
|
243
|
+
export interface StrictConfig {
|
|
244
|
+
/** Enable strict mode */
|
|
245
|
+
enabled?: boolean;
|
|
246
|
+
/** Required stage names that must have configs */
|
|
247
|
+
stages?: string[];
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Logging configuration.
|
|
251
|
+
*/
|
|
252
|
+
export interface LoggingConfig {
|
|
253
|
+
/** Enable file logging */
|
|
254
|
+
enabled?: boolean;
|
|
255
|
+
/** Minimum level to capture: silent, error, warn, info, verbose */
|
|
256
|
+
level?: "silent" | "error" | "warn" | "info" | "verbose";
|
|
257
|
+
/** Log file path (relative to project root) */
|
|
258
|
+
file?: string;
|
|
259
|
+
/** Rotate log when size exceeded (e.g., '10mb') */
|
|
260
|
+
maxSize?: string;
|
|
261
|
+
/** Number of rotated files to keep */
|
|
262
|
+
maxFiles?: number;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Teardown configuration.
|
|
266
|
+
*
|
|
267
|
+
* Controls database reset and teardown behavior.
|
|
268
|
+
*
|
|
269
|
+
* @example
|
|
270
|
+
* ```yaml
|
|
271
|
+
* teardown:
|
|
272
|
+
* preserveTables:
|
|
273
|
+
* - AppSettings
|
|
274
|
+
* - UserRoles
|
|
275
|
+
* postScript: "sql/teardown/cleanup.sql"
|
|
276
|
+
* ```
|
|
277
|
+
*/
|
|
278
|
+
export interface TeardownConfig {
|
|
279
|
+
/** Tables to always preserve during truncate operations */
|
|
280
|
+
preserveTables?: string[];
|
|
281
|
+
/** SQL script to run after schema teardown (relative to project root) */
|
|
282
|
+
postScript?: string;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Complete settings configuration.
|
|
286
|
+
*
|
|
287
|
+
* Stored in .noorm/settings.yml and version controlled.
|
|
288
|
+
*/
|
|
289
|
+
export interface Settings {
|
|
290
|
+
/** Build configuration */
|
|
291
|
+
build?: BuildConfig;
|
|
292
|
+
/** Path overrides */
|
|
293
|
+
paths?: PathConfig;
|
|
294
|
+
/** Stage-based rules for conditional include/exclude */
|
|
295
|
+
rules?: Rule[];
|
|
296
|
+
/** Preconfigured config templates */
|
|
297
|
+
stages?: Record<string, Stage>;
|
|
298
|
+
/** Strict mode requiring specific stages */
|
|
299
|
+
strict?: StrictConfig;
|
|
300
|
+
/** Logging configuration */
|
|
301
|
+
logging?: LoggingConfig;
|
|
302
|
+
/** Universal secrets required by ALL stages */
|
|
303
|
+
secrets?: StageSecret[];
|
|
304
|
+
/** Database teardown/reset configuration */
|
|
305
|
+
teardown?: TeardownConfig;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Settings events emitted by the settings module.
|
|
309
|
+
*/
|
|
310
|
+
export interface SettingsEvents {
|
|
311
|
+
/** Settings loaded from file or defaults */
|
|
312
|
+
"settings:loaded": {
|
|
313
|
+
path: string;
|
|
314
|
+
settings: Settings;
|
|
315
|
+
fromFile: boolean;
|
|
316
|
+
};
|
|
317
|
+
/** Settings saved to disk */
|
|
318
|
+
"settings:saved": {
|
|
319
|
+
path: string;
|
|
320
|
+
};
|
|
321
|
+
/** Settings file initialized */
|
|
322
|
+
"settings:initialized": {
|
|
323
|
+
path: string;
|
|
324
|
+
force: boolean;
|
|
325
|
+
};
|
|
326
|
+
/** Stage added or updated */
|
|
327
|
+
"settings:stage-set": {
|
|
328
|
+
name: string;
|
|
329
|
+
stage: Stage;
|
|
330
|
+
};
|
|
331
|
+
/** Stage removed */
|
|
332
|
+
"settings:stage-removed": {
|
|
333
|
+
name: string;
|
|
334
|
+
};
|
|
335
|
+
/** Rule added */
|
|
336
|
+
"settings:rule-added": {
|
|
337
|
+
rule: Rule;
|
|
338
|
+
};
|
|
339
|
+
/** Rule removed */
|
|
340
|
+
"settings:rule-removed": {
|
|
341
|
+
index: number;
|
|
342
|
+
rule: Rule;
|
|
343
|
+
};
|
|
344
|
+
/** Build config updated */
|
|
345
|
+
"settings:build-updated": {
|
|
346
|
+
build: BuildConfig;
|
|
347
|
+
};
|
|
348
|
+
/** Paths config updated */
|
|
349
|
+
"settings:paths-updated": {
|
|
350
|
+
paths: PathConfig;
|
|
351
|
+
};
|
|
352
|
+
/** Strict mode config updated */
|
|
353
|
+
"settings:strict-updated": {
|
|
354
|
+
strict: StrictConfig;
|
|
355
|
+
};
|
|
356
|
+
/** Logging config updated */
|
|
357
|
+
"settings:logging-updated": {
|
|
358
|
+
logging: LoggingConfig;
|
|
359
|
+
};
|
|
360
|
+
/** Secret added (universal or stage-scoped) */
|
|
361
|
+
"settings:secret-added": {
|
|
362
|
+
secret: StageSecret;
|
|
363
|
+
scope: "universal" | "stage";
|
|
364
|
+
stageName?: string;
|
|
365
|
+
};
|
|
366
|
+
/** Secret updated (universal or stage-scoped) */
|
|
367
|
+
"settings:secret-updated": {
|
|
368
|
+
key: string;
|
|
369
|
+
secret: StageSecret;
|
|
370
|
+
scope: "universal" | "stage";
|
|
371
|
+
stageName?: string;
|
|
372
|
+
};
|
|
373
|
+
/** Secret removed (universal or stage-scoped) */
|
|
374
|
+
"settings:secret-removed": {
|
|
375
|
+
key: string;
|
|
376
|
+
scope: "universal" | "stage";
|
|
377
|
+
stageName?: string;
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Identity types.
|
|
382
|
+
*
|
|
383
|
+
* Two types of identity in noorm:
|
|
384
|
+
* 1. Audit Identity - Simple name/email for tracking "who executed this"
|
|
385
|
+
* 2. Cryptographic Identity - Full keypair system for config sharing and team discovery
|
|
386
|
+
*/
|
|
387
|
+
/**
|
|
388
|
+
* Source of audit identity resolution.
|
|
389
|
+
*/
|
|
390
|
+
export type IdentitySource = "state" | "config" | "env" | "git" | "system";
|
|
391
|
+
/**
|
|
392
|
+
* Resolved audit identity.
|
|
393
|
+
*
|
|
394
|
+
* Used for tracking "who" executed a change or SQL file.
|
|
395
|
+
*
|
|
396
|
+
* @example
|
|
397
|
+
* ```typescript
|
|
398
|
+
* const identity: Identity = {
|
|
399
|
+
* name: 'John Doe',
|
|
400
|
+
* email: 'john@example.com',
|
|
401
|
+
* source: 'git',
|
|
402
|
+
* }
|
|
403
|
+
* ```
|
|
404
|
+
*/
|
|
405
|
+
export interface Identity {
|
|
406
|
+
/** User's name */
|
|
407
|
+
name: string;
|
|
408
|
+
/** User's email (optional) */
|
|
409
|
+
email?: string;
|
|
410
|
+
/** How the identity was resolved */
|
|
411
|
+
source: IdentitySource;
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Operation status values.
|
|
415
|
+
*
|
|
416
|
+
* - pending: Operation started but not finished
|
|
417
|
+
* - success: Operation completed successfully
|
|
418
|
+
* - failed: Operation failed with error
|
|
419
|
+
* - reverted: Operation was reverted
|
|
420
|
+
* - stale: Operation's schema objects were torn down (needs re-run)
|
|
421
|
+
*/
|
|
422
|
+
export type OperationStatus = "pending" | "success" | "failed" | "reverted" | "stale";
|
|
423
|
+
/**
|
|
424
|
+
* Direction values.
|
|
425
|
+
*/
|
|
426
|
+
export type Direction = "change" | "revert";
|
|
427
|
+
/**
|
|
428
|
+
* File execution status values.
|
|
429
|
+
*/
|
|
430
|
+
export type ExecutionStatus = "pending" | "success" | "failed" | "skipped";
|
|
431
|
+
/**
|
|
432
|
+
* Overview counts for all categories.
|
|
433
|
+
*/
|
|
434
|
+
export interface ExploreOverview {
|
|
435
|
+
tables: number;
|
|
436
|
+
views: number;
|
|
437
|
+
procedures: number;
|
|
438
|
+
functions: number;
|
|
439
|
+
types: number;
|
|
440
|
+
indexes: number;
|
|
441
|
+
foreignKeys: number;
|
|
442
|
+
triggers: number;
|
|
443
|
+
locks: number;
|
|
444
|
+
connections: number;
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Table summary for list display.
|
|
448
|
+
*/
|
|
449
|
+
export interface TableSummary {
|
|
450
|
+
name: string;
|
|
451
|
+
schema?: string;
|
|
452
|
+
columnCount: number;
|
|
453
|
+
rowCountEstimate?: number;
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Index summary for list display.
|
|
457
|
+
*/
|
|
458
|
+
export interface IndexSummary {
|
|
459
|
+
name: string;
|
|
460
|
+
schema?: string;
|
|
461
|
+
tableName: string;
|
|
462
|
+
tableSchema?: string;
|
|
463
|
+
columns: string[];
|
|
464
|
+
isUnique: boolean;
|
|
465
|
+
isPrimary: boolean;
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Foreign key summary for list display.
|
|
469
|
+
*/
|
|
470
|
+
export interface ForeignKeySummary {
|
|
471
|
+
name: string;
|
|
472
|
+
schema?: string;
|
|
473
|
+
tableName: string;
|
|
474
|
+
tableSchema?: string;
|
|
475
|
+
columns: string[];
|
|
476
|
+
referencedTable: string;
|
|
477
|
+
referencedSchema?: string;
|
|
478
|
+
referencedColumns: string[];
|
|
479
|
+
onDelete?: string;
|
|
480
|
+
onUpdate?: string;
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Column detail for tables/views.
|
|
484
|
+
*/
|
|
485
|
+
export interface ColumnDetail {
|
|
486
|
+
name: string;
|
|
487
|
+
dataType: string;
|
|
488
|
+
isNullable: boolean;
|
|
489
|
+
defaultValue?: string;
|
|
490
|
+
isPrimaryKey: boolean;
|
|
491
|
+
ordinalPosition: number;
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Full table detail.
|
|
495
|
+
*/
|
|
496
|
+
export interface TableDetail {
|
|
497
|
+
name: string;
|
|
498
|
+
schema?: string;
|
|
499
|
+
columns: ColumnDetail[];
|
|
500
|
+
indexes: IndexSummary[];
|
|
501
|
+
foreignKeys: ForeignKeySummary[];
|
|
502
|
+
rowCountEstimate?: number;
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Result of a truncate operation.
|
|
506
|
+
*/
|
|
507
|
+
export interface TruncateResult {
|
|
508
|
+
/** Tables that were truncated */
|
|
509
|
+
truncated: string[];
|
|
510
|
+
/** Tables that were preserved */
|
|
511
|
+
preserved: string[];
|
|
512
|
+
/** SQL statements executed (or would execute in dry-run) */
|
|
513
|
+
statements: string[];
|
|
514
|
+
/** Duration in milliseconds */
|
|
515
|
+
durationMs: number;
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Result of a teardown operation.
|
|
519
|
+
*/
|
|
520
|
+
export interface TeardownResult {
|
|
521
|
+
/** Objects dropped by category */
|
|
522
|
+
dropped: {
|
|
523
|
+
tables: string[];
|
|
524
|
+
views: string[];
|
|
525
|
+
functions: string[];
|
|
526
|
+
procedures: string[];
|
|
527
|
+
types: string[];
|
|
528
|
+
foreignKeys: string[];
|
|
529
|
+
};
|
|
530
|
+
/** Objects preserved */
|
|
531
|
+
preserved: string[];
|
|
532
|
+
/** SQL statements executed (or would execute in dry-run) */
|
|
533
|
+
statements: string[];
|
|
534
|
+
/** Duration in milliseconds */
|
|
535
|
+
durationMs: number;
|
|
536
|
+
/** Post-script execution result (if any) */
|
|
537
|
+
postScriptResult?: {
|
|
538
|
+
executed: boolean;
|
|
539
|
+
error?: string;
|
|
540
|
+
};
|
|
541
|
+
/** Number of changes marked as stale (if configName provided) */
|
|
542
|
+
staleCount?: number;
|
|
543
|
+
/** ID of the reset record created (if configName provided) */
|
|
544
|
+
resetRecordId?: number;
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* Options for running SQL files.
|
|
548
|
+
*
|
|
549
|
+
* @example
|
|
550
|
+
* ```typescript
|
|
551
|
+
* const options: RunOptions = {
|
|
552
|
+
* force: true, // Re-run even if unchanged
|
|
553
|
+
* abortOnError: false // Continue on failures
|
|
554
|
+
* }
|
|
555
|
+
* ```
|
|
556
|
+
*/
|
|
557
|
+
export interface RunOptions {
|
|
558
|
+
/** Re-run files even if unchanged. Default: false */
|
|
559
|
+
force?: boolean;
|
|
560
|
+
/** Number of files to run in parallel. Default: 1 (sequential for DDL safety) */
|
|
561
|
+
concurrency?: number;
|
|
562
|
+
/** Stop execution on first failure. Default: true */
|
|
563
|
+
abortOnError?: boolean;
|
|
564
|
+
/** Report what would run without executing. Default: false */
|
|
565
|
+
dryRun?: boolean;
|
|
566
|
+
/** Output rendered SQL without executing. Default: false */
|
|
567
|
+
preview?: boolean;
|
|
568
|
+
/** Write preview output to file instead of stdout. Default: null */
|
|
569
|
+
output?: string | null;
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Why a file was skipped.
|
|
573
|
+
*/
|
|
574
|
+
export type SkipReason = "unchanged" | "already-run";
|
|
575
|
+
/**
|
|
576
|
+
* Result of executing a single file.
|
|
577
|
+
*
|
|
578
|
+
* @example
|
|
579
|
+
* ```typescript
|
|
580
|
+
* const result: FileResult = {
|
|
581
|
+
* filepath: '/project/sql/001.sql',
|
|
582
|
+
* checksum: 'abc123...',
|
|
583
|
+
* status: 'success',
|
|
584
|
+
* durationMs: 42,
|
|
585
|
+
* }
|
|
586
|
+
* ```
|
|
587
|
+
*/
|
|
588
|
+
export interface FileResult {
|
|
589
|
+
/** Absolute path to the file */
|
|
590
|
+
filepath: string;
|
|
591
|
+
/** SHA-256 hash of file contents */
|
|
592
|
+
checksum: string;
|
|
593
|
+
/** Execution status */
|
|
594
|
+
status: ExecutionStatus;
|
|
595
|
+
/** Why the file was skipped (only when status is 'skipped') */
|
|
596
|
+
skipReason?: SkipReason;
|
|
597
|
+
/** Execution time in milliseconds */
|
|
598
|
+
durationMs?: number;
|
|
599
|
+
/** Error message if failed */
|
|
600
|
+
error?: string;
|
|
601
|
+
/** Rendered SQL (only in preview mode) */
|
|
602
|
+
renderedSql?: string;
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* Overall status of a batch operation.
|
|
606
|
+
*/
|
|
607
|
+
export type BatchStatus = "success" | "failed" | "partial";
|
|
608
|
+
/**
|
|
609
|
+
* Result of a batch operation (build, dir).
|
|
610
|
+
*
|
|
611
|
+
* @example
|
|
612
|
+
* ```typescript
|
|
613
|
+
* const result: BatchResult = {
|
|
614
|
+
* status: 'success',
|
|
615
|
+
* files: [...],
|
|
616
|
+
* filesRun: 5,
|
|
617
|
+
* filesSkipped: 2,
|
|
618
|
+
* filesFailed: 0,
|
|
619
|
+
* durationMs: 1234,
|
|
620
|
+
* }
|
|
621
|
+
* ```
|
|
622
|
+
*/
|
|
623
|
+
export interface BatchResult {
|
|
624
|
+
/** Overall status */
|
|
625
|
+
status: BatchStatus;
|
|
626
|
+
/** Results for each file */
|
|
627
|
+
files: FileResult[];
|
|
628
|
+
/** Number of files executed */
|
|
629
|
+
filesRun: number;
|
|
630
|
+
/** Number of files skipped */
|
|
631
|
+
filesSkipped: number;
|
|
632
|
+
/** Number of files that failed */
|
|
633
|
+
filesFailed: number;
|
|
634
|
+
/** Total execution time in milliseconds */
|
|
635
|
+
durationMs: number;
|
|
636
|
+
/** Change ID in tracking table */
|
|
637
|
+
changeId?: number;
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* File extension type in changes.
|
|
641
|
+
*
|
|
642
|
+
* - 'sql' for direct SQL files (.sql, .sql.tmpl)
|
|
643
|
+
* - 'txt' for manifest files referencing build SQL
|
|
644
|
+
*/
|
|
645
|
+
export type ChangeFileType = "sql" | "txt";
|
|
646
|
+
/**
|
|
647
|
+
* A single file within a change.
|
|
648
|
+
*
|
|
649
|
+
* @example
|
|
650
|
+
* ```typescript
|
|
651
|
+
* const file: ChangeFile = {
|
|
652
|
+
* filename: '001_alter-users.sql',
|
|
653
|
+
* path: '/project/changes/2024-01-15-add-users/change/001_alter-users.sql',
|
|
654
|
+
* type: 'sql',
|
|
655
|
+
* }
|
|
656
|
+
* ```
|
|
657
|
+
*/
|
|
658
|
+
export interface ChangeFile {
|
|
659
|
+
/** Filename (e.g., "001_alter-users.sql") */
|
|
660
|
+
filename: string;
|
|
661
|
+
/** Absolute path to file */
|
|
662
|
+
path: string;
|
|
663
|
+
/** File type */
|
|
664
|
+
type: ChangeFileType;
|
|
665
|
+
/** For .txt files, the resolved SQL paths (relative to schema dir) */
|
|
666
|
+
resolvedPaths?: string[];
|
|
667
|
+
/** Execution status after running */
|
|
668
|
+
status?: ExecutionStatus;
|
|
669
|
+
/** Why the file was skipped */
|
|
670
|
+
skipReason?: string;
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* A change with merged disk and database information.
|
|
674
|
+
*
|
|
675
|
+
* Used by the list command to show all changes with status.
|
|
676
|
+
*
|
|
677
|
+
* @example
|
|
678
|
+
* ```typescript
|
|
679
|
+
* const item: ChangeListItem = {
|
|
680
|
+
* // From disk
|
|
681
|
+
* name: '2024-01-15-add-users',
|
|
682
|
+
* path: '/project/changes/...',
|
|
683
|
+
* // ...other Change fields
|
|
684
|
+
*
|
|
685
|
+
* // From DB
|
|
686
|
+
* status: 'success',
|
|
687
|
+
* appliedAt: new Date(),
|
|
688
|
+
* // ...other ChangeStatus fields
|
|
689
|
+
*
|
|
690
|
+
* // Computed
|
|
691
|
+
* isNew: false,
|
|
692
|
+
* orphaned: false,
|
|
693
|
+
* }
|
|
694
|
+
* ```
|
|
695
|
+
*/
|
|
696
|
+
export interface ChangeListItem {
|
|
697
|
+
/** Change name (always present) */
|
|
698
|
+
name: string;
|
|
699
|
+
/** Absolute path to change folder */
|
|
700
|
+
path?: string;
|
|
701
|
+
/** Date parsed from name (null if no date prefix) */
|
|
702
|
+
date?: Date | null;
|
|
703
|
+
/** Human-readable description from name */
|
|
704
|
+
description?: string;
|
|
705
|
+
/** Files in change/ folder */
|
|
706
|
+
changeFiles?: ChangeFile[];
|
|
707
|
+
/** Files in revert/ folder */
|
|
708
|
+
revertFiles?: ChangeFile[];
|
|
709
|
+
/** Whether changelog.md exists */
|
|
710
|
+
hasChangelog?: boolean;
|
|
711
|
+
/** Current status */
|
|
712
|
+
status: OperationStatus;
|
|
713
|
+
/** When last applied (null if never) */
|
|
714
|
+
appliedAt: Date | null;
|
|
715
|
+
/** Who applied it */
|
|
716
|
+
appliedBy: string | null;
|
|
717
|
+
/** When reverted (null if not reverted) */
|
|
718
|
+
revertedAt: Date | null;
|
|
719
|
+
/** Error message if failed */
|
|
720
|
+
errorMessage: string | null;
|
|
721
|
+
/** True if exists on disk but no DB record */
|
|
722
|
+
isNew: boolean;
|
|
723
|
+
/** True if exists in DB but folder deleted from disk */
|
|
724
|
+
orphaned: boolean;
|
|
725
|
+
}
|
|
726
|
+
/**
|
|
727
|
+
* Options for executing a change.
|
|
728
|
+
*
|
|
729
|
+
* @example
|
|
730
|
+
* ```typescript
|
|
731
|
+
* const options: ChangeOptions = {
|
|
732
|
+
* force: false,
|
|
733
|
+
* dryRun: false,
|
|
734
|
+
* preview: false,
|
|
735
|
+
* }
|
|
736
|
+
* ```
|
|
737
|
+
*/
|
|
738
|
+
export interface ChangeOptions {
|
|
739
|
+
/** Re-run even if already applied. Default: false */
|
|
740
|
+
force?: boolean;
|
|
741
|
+
/** Render to tmp/ without executing. Default: false */
|
|
742
|
+
dryRun?: boolean;
|
|
743
|
+
/** Output rendered SQL without executing. Default: false */
|
|
744
|
+
preview?: boolean;
|
|
745
|
+
/** Write preview output to file. Default: null */
|
|
746
|
+
output?: string | null;
|
|
747
|
+
}
|
|
748
|
+
/**
|
|
749
|
+
* Result of executing a single change.
|
|
750
|
+
*
|
|
751
|
+
* @example
|
|
752
|
+
* ```typescript
|
|
753
|
+
* const result: ChangeResult = {
|
|
754
|
+
* name: '2024-01-15-add-users',
|
|
755
|
+
* direction: 'change',
|
|
756
|
+
* status: 'success',
|
|
757
|
+
* files: [...],
|
|
758
|
+
* durationMs: 1234,
|
|
759
|
+
* }
|
|
760
|
+
* ```
|
|
761
|
+
*/
|
|
762
|
+
export interface ChangeResult {
|
|
763
|
+
/** Change name */
|
|
764
|
+
name: string;
|
|
765
|
+
/** Operation direction */
|
|
766
|
+
direction: Direction;
|
|
767
|
+
/** Final status */
|
|
768
|
+
status: OperationStatus;
|
|
769
|
+
/** Individual file results */
|
|
770
|
+
files: ChangeFileResult[];
|
|
771
|
+
/** Total execution time */
|
|
772
|
+
durationMs: number;
|
|
773
|
+
/** Error message if failed */
|
|
774
|
+
error?: string;
|
|
775
|
+
/** Operation ID in tracking table */
|
|
776
|
+
operationId?: number;
|
|
777
|
+
}
|
|
778
|
+
/**
|
|
779
|
+
* Result of executing a single file within a change.
|
|
780
|
+
*/
|
|
781
|
+
export interface ChangeFileResult {
|
|
782
|
+
/** File path */
|
|
783
|
+
filepath: string;
|
|
784
|
+
/** File checksum */
|
|
785
|
+
checksum: string;
|
|
786
|
+
/** Execution status */
|
|
787
|
+
status: ExecutionStatus;
|
|
788
|
+
/** Why skipped (if skipped) */
|
|
789
|
+
skipReason?: string;
|
|
790
|
+
/** Execution time in milliseconds */
|
|
791
|
+
durationMs?: number;
|
|
792
|
+
/** Error message if failed */
|
|
793
|
+
error?: string;
|
|
794
|
+
/** Rendered SQL (only in preview mode) */
|
|
795
|
+
renderedSql?: string;
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* Result of a batch operation (next, ff, rewind).
|
|
799
|
+
*/
|
|
800
|
+
export interface BatchChangeResult {
|
|
801
|
+
/** Overall status */
|
|
802
|
+
status: "success" | "failed" | "partial";
|
|
803
|
+
/** Results for each change */
|
|
804
|
+
changes: ChangeResult[];
|
|
805
|
+
/** Number of changes executed */
|
|
806
|
+
executed: number;
|
|
807
|
+
/** Number of changes skipped */
|
|
808
|
+
skipped: number;
|
|
809
|
+
/** Number of changes that failed */
|
|
810
|
+
failed: number;
|
|
811
|
+
/** Total execution time */
|
|
812
|
+
durationMs: number;
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* A single execution record from history.
|
|
816
|
+
*/
|
|
817
|
+
export interface ChangeHistoryRecord {
|
|
818
|
+
/** Record ID */
|
|
819
|
+
id: number;
|
|
820
|
+
/** Change name */
|
|
821
|
+
name: string;
|
|
822
|
+
/** Operation direction */
|
|
823
|
+
direction: Direction;
|
|
824
|
+
/** Status */
|
|
825
|
+
status: OperationStatus;
|
|
826
|
+
/** When executed */
|
|
827
|
+
executedAt: Date;
|
|
828
|
+
/** Who executed */
|
|
829
|
+
executedBy: string;
|
|
830
|
+
/** Duration in milliseconds */
|
|
831
|
+
durationMs: number;
|
|
832
|
+
/** Error message if failed */
|
|
833
|
+
errorMessage: string | null;
|
|
834
|
+
/** Checksum of files */
|
|
835
|
+
checksum: string;
|
|
836
|
+
}
|
|
837
|
+
/**
|
|
838
|
+
* Lock manager types.
|
|
839
|
+
*
|
|
840
|
+
* Defines the shape of locks and options for acquiring them.
|
|
841
|
+
* Used to prevent concurrent operations on the same database.
|
|
842
|
+
*
|
|
843
|
+
* WHY: Concurrent DDL operations can corrupt database state.
|
|
844
|
+
* Locks ensure only one process modifies the schema at a time.
|
|
845
|
+
*/
|
|
846
|
+
/**
|
|
847
|
+
* Lock state returned after acquisition.
|
|
848
|
+
*
|
|
849
|
+
* @example
|
|
850
|
+
* ```typescript
|
|
851
|
+
* const lock = await lockManager.acquire('dev', 'alice@example.com')
|
|
852
|
+
* console.log(lock.lockedBy) // 'alice@example.com'
|
|
853
|
+
* console.log(lock.expiresAt) // Date object
|
|
854
|
+
* ```
|
|
855
|
+
*/
|
|
856
|
+
interface Lock$1 {
|
|
857
|
+
/** Identity string of holder */
|
|
858
|
+
lockedBy: string;
|
|
859
|
+
/** When acquired */
|
|
860
|
+
lockedAt: Date;
|
|
861
|
+
/** Auto-expiry time */
|
|
862
|
+
expiresAt: Date;
|
|
863
|
+
/** Optional reason for acquiring */
|
|
864
|
+
reason?: string;
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* Options for acquiring a lock.
|
|
868
|
+
*
|
|
869
|
+
* @example
|
|
870
|
+
* ```typescript
|
|
871
|
+
* // Wait up to 30s for lock, polling every 500ms
|
|
872
|
+
* const options: LockOptions = {
|
|
873
|
+
* timeout: 60_000, // Lock expires after 60s
|
|
874
|
+
* wait: true, // Block until available
|
|
875
|
+
* waitTimeout: 30_000, // Max wait time
|
|
876
|
+
* pollInterval: 500, // Check every 500ms
|
|
877
|
+
* reason: 'Running migrations',
|
|
878
|
+
* }
|
|
879
|
+
* ```
|
|
880
|
+
*/
|
|
881
|
+
interface LockOptions$1 {
|
|
882
|
+
/**
|
|
883
|
+
* Database dialect for date formatting.
|
|
884
|
+
*
|
|
885
|
+
* SQLite stores dates as ISO strings, other dialects can use Date objects.
|
|
886
|
+
* @default 'postgres'
|
|
887
|
+
*/
|
|
888
|
+
dialect?: "postgres" | "mysql" | "sqlite" | "mssql";
|
|
889
|
+
/**
|
|
890
|
+
* Lock duration in milliseconds.
|
|
891
|
+
*
|
|
892
|
+
* After this time, the lock expires and can be claimed by others.
|
|
893
|
+
* @default 300_000 (5 minutes)
|
|
894
|
+
*/
|
|
895
|
+
timeout?: number;
|
|
896
|
+
/**
|
|
897
|
+
* Block until lock is available?
|
|
898
|
+
*
|
|
899
|
+
* If true, will poll until the lock is acquired or waitTimeout is reached.
|
|
900
|
+
* @default false
|
|
901
|
+
*/
|
|
902
|
+
wait?: boolean;
|
|
903
|
+
/**
|
|
904
|
+
* Max time to wait for lock in milliseconds.
|
|
905
|
+
*
|
|
906
|
+
* Only used if wait is true.
|
|
907
|
+
* @default 30_000 (30 seconds)
|
|
908
|
+
*/
|
|
909
|
+
waitTimeout?: number;
|
|
910
|
+
/**
|
|
911
|
+
* How often to poll when waiting, in milliseconds.
|
|
912
|
+
*
|
|
913
|
+
* Only used if wait is true.
|
|
914
|
+
* @default 1_000 (1 second)
|
|
915
|
+
*/
|
|
916
|
+
pollInterval?: number;
|
|
917
|
+
/**
|
|
918
|
+
* Optional reason for acquiring the lock.
|
|
919
|
+
*
|
|
920
|
+
* Shown to users who are blocked by this lock.
|
|
921
|
+
*/
|
|
922
|
+
reason?: string;
|
|
923
|
+
}
|
|
924
|
+
/**
|
|
925
|
+
* Result of a lock status check.
|
|
926
|
+
*/
|
|
927
|
+
export interface LockStatus {
|
|
928
|
+
/** Whether the lock is currently held */
|
|
929
|
+
isLocked: boolean;
|
|
930
|
+
/** Lock details if held, null if not */
|
|
931
|
+
lock: Lock$1 | null;
|
|
932
|
+
}
|
|
933
|
+
/**
|
|
934
|
+
* Lock-related errors.
|
|
935
|
+
*
|
|
936
|
+
* WHY: Specific error types allow callers to handle lock failures
|
|
937
|
+
* differently from other errors (e.g., prompt user to wait vs retry).
|
|
938
|
+
*/
|
|
939
|
+
/**
|
|
940
|
+
* Error when lock cannot be acquired.
|
|
941
|
+
*
|
|
942
|
+
* Thrown when another process holds the lock and wait=false,
|
|
943
|
+
* or when waitTimeout is exceeded.
|
|
944
|
+
*
|
|
945
|
+
* @example
|
|
946
|
+
* ```typescript
|
|
947
|
+
* const [lock, err] = await attempt(() => lockManager.acquire(config, identity))
|
|
948
|
+
* if (err instanceof LockAcquireError) {
|
|
949
|
+
* console.log(`Blocked by ${err.holder} since ${err.heldSince}`)
|
|
950
|
+
* }
|
|
951
|
+
* ```
|
|
952
|
+
*/
|
|
953
|
+
export declare class LockAcquireError extends Error {
|
|
954
|
+
readonly configName: string;
|
|
955
|
+
readonly holder: string;
|
|
956
|
+
readonly heldSince: Date;
|
|
957
|
+
readonly expiresAt: Date;
|
|
958
|
+
readonly reason?: string | undefined;
|
|
959
|
+
readonly name: "LockAcquireError";
|
|
960
|
+
constructor(configName: string, holder: string, heldSince: Date, expiresAt: Date, reason?: string | undefined);
|
|
961
|
+
}
|
|
962
|
+
/**
|
|
963
|
+
* Error when lock expires during operation.
|
|
964
|
+
*
|
|
965
|
+
* Thrown when validating lock before a critical operation
|
|
966
|
+
* and discovering it has expired.
|
|
967
|
+
*
|
|
968
|
+
* @example
|
|
969
|
+
* ```typescript
|
|
970
|
+
* // Before committing transaction
|
|
971
|
+
* const [, err] = await attempt(() => lockManager.validate(configName, identity))
|
|
972
|
+
* if (err instanceof LockExpiredError) {
|
|
973
|
+
* await transaction.rollback()
|
|
974
|
+
* throw new Error('Lock expired, operation aborted')
|
|
975
|
+
* }
|
|
976
|
+
* ```
|
|
977
|
+
*/
|
|
978
|
+
export declare class LockExpiredError extends Error {
|
|
979
|
+
readonly configName: string;
|
|
980
|
+
readonly identity: string;
|
|
981
|
+
readonly expiredAt: Date;
|
|
982
|
+
readonly name: "LockExpiredError";
|
|
983
|
+
constructor(configName: string, identity: string, expiredAt: Date);
|
|
984
|
+
}
|
|
985
|
+
/**
|
|
986
|
+
* Result of processing a SQL file.
|
|
987
|
+
*/
|
|
988
|
+
interface ProcessResult {
|
|
989
|
+
/**
|
|
990
|
+
* The SQL content (rendered if template, raw if .sql).
|
|
991
|
+
*/
|
|
992
|
+
sql: string;
|
|
993
|
+
/**
|
|
994
|
+
* Whether the file was a template.
|
|
995
|
+
*/
|
|
996
|
+
isTemplate: boolean;
|
|
997
|
+
/**
|
|
998
|
+
* Render duration in milliseconds (only for templates).
|
|
999
|
+
*/
|
|
1000
|
+
durationMs?: number;
|
|
1001
|
+
}
|
|
1002
|
+
/**
|
|
1003
|
+
* SDK Types.
|
|
1004
|
+
*
|
|
1005
|
+
* All interfaces and types for the noorm programmatic SDK.
|
|
1006
|
+
*/
|
|
1007
|
+
/**
|
|
1008
|
+
* Options for creating an SDK context.
|
|
1009
|
+
*
|
|
1010
|
+
* @example
|
|
1011
|
+
* ```typescript
|
|
1012
|
+
* // Basic usage with stored config
|
|
1013
|
+
* const ctx = await createContext({ config: 'dev' })
|
|
1014
|
+
*
|
|
1015
|
+
* // Require test database for safety
|
|
1016
|
+
* const ctx = await createContext({
|
|
1017
|
+
* config: 'test',
|
|
1018
|
+
* requireTest: true,
|
|
1019
|
+
* })
|
|
1020
|
+
*
|
|
1021
|
+
* // Allow destructive ops on protected config
|
|
1022
|
+
* const ctx = await createContext({
|
|
1023
|
+
* config: 'staging',
|
|
1024
|
+
* allowProtected: true,
|
|
1025
|
+
* })
|
|
1026
|
+
*
|
|
1027
|
+
* // Env-only mode (CI/CD) - no stored config needed
|
|
1028
|
+
* // Requires NOORM_CONNECTION_DIALECT and NOORM_CONNECTION_DATABASE
|
|
1029
|
+
* const ctx = await createContext()
|
|
1030
|
+
*
|
|
1031
|
+
* // Override stored config via NOORM_* env vars
|
|
1032
|
+
* // NOORM_CONNECTION_HOST=override.host
|
|
1033
|
+
* const ctx = await createContext({ config: 'prod' })
|
|
1034
|
+
* ```
|
|
1035
|
+
*/
|
|
1036
|
+
export interface CreateContextOptions {
|
|
1037
|
+
/**
|
|
1038
|
+
* Config name from state.
|
|
1039
|
+
*
|
|
1040
|
+
* If omitted:
|
|
1041
|
+
* - Uses `NOORM_CONFIG` env var if set
|
|
1042
|
+
* - Falls back to env-only mode if `NOORM_CONNECTION_DIALECT`
|
|
1043
|
+
* and `NOORM_CONNECTION_DATABASE` are set
|
|
1044
|
+
*/
|
|
1045
|
+
config?: string;
|
|
1046
|
+
/** Project root directory. Defaults to process.cwd() */
|
|
1047
|
+
projectRoot?: string;
|
|
1048
|
+
/** Refuse if config.isTest !== true. Default: false */
|
|
1049
|
+
requireTest?: boolean;
|
|
1050
|
+
/** Allow destructive ops on protected configs. Default: false */
|
|
1051
|
+
allowProtected?: boolean;
|
|
1052
|
+
/** Stage name for stage defaults (from settings.yml) */
|
|
1053
|
+
stage?: string;
|
|
1054
|
+
}
|
|
1055
|
+
/**
|
|
1056
|
+
* Result of an execute() call.
|
|
1057
|
+
*/
|
|
1058
|
+
export interface ExecuteResult {
|
|
1059
|
+
/** Number of rows affected (if available) */
|
|
1060
|
+
rowsAffected?: number;
|
|
1061
|
+
}
|
|
1062
|
+
/**
|
|
1063
|
+
* Transaction context for use within transaction callbacks.
|
|
1064
|
+
*
|
|
1065
|
+
* @example
|
|
1066
|
+
* ```typescript
|
|
1067
|
+
* await ctx.transaction(async (tx) => {
|
|
1068
|
+
* const [user] = await tx.query('SELECT * FROM users WHERE id = $1', [id])
|
|
1069
|
+
* await tx.execute('UPDATE users SET login_count = login_count + 1 WHERE id = $1', [id])
|
|
1070
|
+
* return user
|
|
1071
|
+
* })
|
|
1072
|
+
* ```
|
|
1073
|
+
*/
|
|
1074
|
+
export interface TransactionContext {
|
|
1075
|
+
/**
|
|
1076
|
+
* Execute a SELECT query within the transaction.
|
|
1077
|
+
*/
|
|
1078
|
+
query<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<T[]>;
|
|
1079
|
+
/**
|
|
1080
|
+
* Execute an INSERT/UPDATE/DELETE within the transaction.
|
|
1081
|
+
*/
|
|
1082
|
+
execute(sql: string, params?: unknown[]): Promise<ExecuteResult>;
|
|
1083
|
+
}
|
|
1084
|
+
/**
|
|
1085
|
+
* Options for build operations.
|
|
1086
|
+
*/
|
|
1087
|
+
export interface BuildOptions {
|
|
1088
|
+
/** Skip checksum checks, rebuild everything. Default: false */
|
|
1089
|
+
force?: boolean;
|
|
1090
|
+
}
|
|
1091
|
+
export type Events<Shape> = keyof Shape;
|
|
1092
|
+
declare namespace ObserverEngine {
|
|
1093
|
+
interface EventCallback<Shape> {
|
|
1094
|
+
(data: Shape, info?: {
|
|
1095
|
+
event: string;
|
|
1096
|
+
listener: Function;
|
|
1097
|
+
} | undefined): void;
|
|
1098
|
+
}
|
|
1099
|
+
type RgxEmitData<Shape> = {
|
|
1100
|
+
event: Events<Shape>;
|
|
1101
|
+
data: Shape[Events<Shape>];
|
|
1102
|
+
};
|
|
1103
|
+
type Cleanup = () => void;
|
|
1104
|
+
type Component<Ev extends Record<string, any>> = {
|
|
1105
|
+
on: ObserverEngine<Ev>["on"];
|
|
1106
|
+
once: ObserverEngine<Ev>["once"];
|
|
1107
|
+
emit: ObserverEngine<Ev>["emit"];
|
|
1108
|
+
off: ObserverEngine<Ev>["off"];
|
|
1109
|
+
};
|
|
1110
|
+
type Child<C, Ev extends Record<string, any>> = C & Component<Ev> & {
|
|
1111
|
+
cleanup: Cleanup;
|
|
1112
|
+
clear: Cleanup;
|
|
1113
|
+
};
|
|
1114
|
+
type Instance<Ev extends Record<string, any>> = Component<Ev> & {
|
|
1115
|
+
observe: ObserverEngine<Ev>["observe"];
|
|
1116
|
+
$observer: ObserverEngine<Ev>;
|
|
1117
|
+
};
|
|
1118
|
+
type FuncName = "on" | "once" | "off" | "emit" | "cleanup";
|
|
1119
|
+
type SpyAction<Ev extends Record<string, any>> = {
|
|
1120
|
+
event: keyof Ev | RegExp | "*";
|
|
1121
|
+
listener?: Function | null | undefined;
|
|
1122
|
+
data?: unknown | undefined;
|
|
1123
|
+
fn: FuncName;
|
|
1124
|
+
context: ObserverEngine<Ev>;
|
|
1125
|
+
};
|
|
1126
|
+
interface Spy<Ev extends Record<string, any>> {
|
|
1127
|
+
(action: SpyAction<Ev>): void;
|
|
1128
|
+
}
|
|
1129
|
+
interface EmitValidator<Ev extends Record<string, any>> {
|
|
1130
|
+
(event: keyof Ev, data: Ev[keyof Ev], context: ObserverEngine<Ev>): void;
|
|
1131
|
+
(event: RegExp, data: unknown, context: ObserverEngine<Ev>): void;
|
|
1132
|
+
(event: "*", data: unknown, context: ObserverEngine<Ev>): void;
|
|
1133
|
+
}
|
|
1134
|
+
type Options<Ev extends Record<string, any>> = {
|
|
1135
|
+
name?: string | undefined;
|
|
1136
|
+
spy?: Spy<Ev> | undefined;
|
|
1137
|
+
emitValidator?: EmitValidator<Ev> | undefined;
|
|
1138
|
+
signal?: AbortSignal | undefined;
|
|
1139
|
+
};
|
|
1140
|
+
type ListenerOptions = {
|
|
1141
|
+
signal?: AbortSignal | undefined;
|
|
1142
|
+
};
|
|
1143
|
+
type ObserveOptions = {
|
|
1144
|
+
signal?: AbortSignal | undefined;
|
|
1145
|
+
};
|
|
1146
|
+
}
|
|
1147
|
+
/**
|
|
1148
|
+
* Generic function type for type-safe function signatures.
|
|
1149
|
+
*
|
|
1150
|
+
* Enables consistent typing across utility functions and higher-order functions
|
|
1151
|
+
* where function parameters need to be strongly typed.
|
|
1152
|
+
*
|
|
1153
|
+
* @example
|
|
1154
|
+
* function memoize<A extends any[], R>(fn: Func<A, R>): Func<A, R>
|
|
1155
|
+
* function debounce<A extends any[]>(fn: Func<A, void>, ms: number): Func<A, void>
|
|
1156
|
+
*/
|
|
1157
|
+
export type Func<A extends any[] = any[], R = any> = (...args: A) => R;
|
|
1158
|
+
/**
|
|
1159
|
+
* Represents a value that can be either synchronous or asynchronous.
|
|
1160
|
+
*
|
|
1161
|
+
* Critical for utility functions that need to handle both sync and async
|
|
1162
|
+
* operations uniformly, enabling flexible API design.
|
|
1163
|
+
*
|
|
1164
|
+
* @example
|
|
1165
|
+
* function processData<T>(processor: () => MaybePromise<T>): Promise<T>
|
|
1166
|
+
* function transform<T, U>(value: T, transformer: (val: T) => MaybePromise<U>): Promise<U>
|
|
1167
|
+
*/
|
|
1168
|
+
export type MaybePromise<T> = T | Promise<T>;
|
|
1169
|
+
export interface EventGeneratorOptions {
|
|
1170
|
+
signal?: AbortSignal | undefined;
|
|
1171
|
+
}
|
|
1172
|
+
declare class EventGenerator<S extends Record<string, any>, E extends Events<S> | RegExp = Events<S>> {
|
|
1173
|
+
#private;
|
|
1174
|
+
cleanup: ObserverEngine.Cleanup;
|
|
1175
|
+
next: () => Promise<EventData<S, E>>;
|
|
1176
|
+
constructor(observer: ObserverEngine<S>, event: E | RegExp, options?: EventGeneratorOptions);
|
|
1177
|
+
[Symbol.asyncIterator](): AsyncGenerator<Awaited<EventData<S, E>>, undefined, unknown>;
|
|
1178
|
+
get lastValue(): E extends Events<S> ? S[E] : E extends RegExp ? ObserverEngine.RgxEmitData<S> : S[Events<S>];
|
|
1179
|
+
get done(): boolean;
|
|
1180
|
+
emit(data?: (E extends Events<S> ? S[E] : S[Events<S>])): void;
|
|
1181
|
+
}
|
|
1182
|
+
declare class ObserverEngine<Shape extends Record<string, any> = Record<string, any>> {
|
|
1183
|
+
#private;
|
|
1184
|
+
constructor(options?: ObserverEngine.Options<Shape>);
|
|
1185
|
+
name: string;
|
|
1186
|
+
/**
|
|
1187
|
+
* Returns facts about the the internal state of the observable instance.
|
|
1188
|
+
*/
|
|
1189
|
+
$facts(): {
|
|
1190
|
+
listeners: (keyof Shape)[];
|
|
1191
|
+
rgxListeners: string[];
|
|
1192
|
+
listenerCounts: Record<string, number>;
|
|
1193
|
+
hasSpy: boolean;
|
|
1194
|
+
};
|
|
1195
|
+
/**
|
|
1196
|
+
* The internals of the observable instance.
|
|
1197
|
+
*
|
|
1198
|
+
* NOTE: Do not use this to try to meddle with the
|
|
1199
|
+
* internals of the observable instance. This is for
|
|
1200
|
+
* debugging purposes only.
|
|
1201
|
+
*/
|
|
1202
|
+
$internals(): {
|
|
1203
|
+
listenerMap: Map<keyof Shape, Set<Func>>;
|
|
1204
|
+
rgxListenerMap: Map<string, Set<Func>>;
|
|
1205
|
+
internalListener: EventTarget;
|
|
1206
|
+
name: string;
|
|
1207
|
+
spy: ObserverEngine.Spy<Shape> | undefined;
|
|
1208
|
+
};
|
|
1209
|
+
/**
|
|
1210
|
+
* Returns if the observable instance has the given event
|
|
1211
|
+
*/
|
|
1212
|
+
$has(event: Events<Shape>): boolean;
|
|
1213
|
+
/**
|
|
1214
|
+
* Returns if the observable instance has a regex event
|
|
1215
|
+
*/
|
|
1216
|
+
$has(event: RegExp): boolean;
|
|
1217
|
+
/**
|
|
1218
|
+
* Returns if the observable instance has the given event
|
|
1219
|
+
*/
|
|
1220
|
+
$has(event: string): boolean;
|
|
1221
|
+
/**
|
|
1222
|
+
* Enables or disables debugging for the observable instance.
|
|
1223
|
+
* Works in conjunction with your spy function. Provides a
|
|
1224
|
+
* stack trace of events that are triggered, listened to, and
|
|
1225
|
+
* cleaned up.
|
|
1226
|
+
*
|
|
1227
|
+
* @param on Whether to enable or disable debugging
|
|
1228
|
+
*/
|
|
1229
|
+
debug(on?: boolean): void;
|
|
1230
|
+
/**
|
|
1231
|
+
* Sets the spy function for the observable instance.
|
|
1232
|
+
* @param spy The spy function to set
|
|
1233
|
+
* @param force Whether to force the spy function to be set even if one is already set
|
|
1234
|
+
*/
|
|
1235
|
+
spy(spy: ObserverEngine.Spy<Shape>, force?: boolean): void;
|
|
1236
|
+
/**
|
|
1237
|
+
* Observes given component as an extension of this observable instance.
|
|
1238
|
+
* @param component Component to wrap events around
|
|
1239
|
+
* @param options Optional configuration including signal for cleanup
|
|
1240
|
+
*
|
|
1241
|
+
* @example
|
|
1242
|
+
*
|
|
1243
|
+
* const obs = new ObserverEngine();
|
|
1244
|
+
*
|
|
1245
|
+
* const modal = {};
|
|
1246
|
+
*
|
|
1247
|
+
* obs.observe(modal);
|
|
1248
|
+
*
|
|
1249
|
+
* modal.on('modal-open', () => {});
|
|
1250
|
+
*
|
|
1251
|
+
* obs.trigger('modal-open'); // opens modal
|
|
1252
|
+
* modal.trigger('modal-open'); // opens modal
|
|
1253
|
+
*
|
|
1254
|
+
* modal.cleanup(); // clears all event listeners
|
|
1255
|
+
*/
|
|
1256
|
+
observe<C>(component: C, options?: ObserverEngine.ObserveOptions): ObserverEngine.Child<C, Shape>;
|
|
1257
|
+
/**
|
|
1258
|
+
* Returns an event generator that will listen for the specified event
|
|
1259
|
+
*
|
|
1260
|
+
* @example
|
|
1261
|
+
*
|
|
1262
|
+
* const obs = new ObserverEngine();
|
|
1263
|
+
*
|
|
1264
|
+
* const something = obs.on('something');
|
|
1265
|
+
* const data = await something.next(); // waits for next event
|
|
1266
|
+
* something.emit('special'); // emits data to listeners
|
|
1267
|
+
*
|
|
1268
|
+
* something.cleanup(); // stops listening for events
|
|
1269
|
+
*/
|
|
1270
|
+
on<E extends Events<Shape>>(event: E, options?: ObserverEngine.ListenerOptions): EventGenerator<Shape, E>;
|
|
1271
|
+
on<E extends string>(event: E, options?: ObserverEngine.ListenerOptions): EventGenerator<Record<E, any>>;
|
|
1272
|
+
/**
|
|
1273
|
+
* Listens for the specified event and executes the given callback
|
|
1274
|
+
*
|
|
1275
|
+
* @example
|
|
1276
|
+
*
|
|
1277
|
+
* const obs = new ObserverEngine();
|
|
1278
|
+
*
|
|
1279
|
+
* obs.on('something', (data) => {
|
|
1280
|
+
* console.log(data);
|
|
1281
|
+
* });
|
|
1282
|
+
*/
|
|
1283
|
+
on<E extends Events<Shape>>(event: E, listener: ObserverEngine.EventCallback<Shape[E]>, options?: ObserverEngine.ListenerOptions): ObserverEngine.Cleanup;
|
|
1284
|
+
on<E extends string>(event: E, listener: ObserverEngine.EventCallback<Record<E, any>>, options?: ObserverEngine.ListenerOptions): ObserverEngine.Cleanup;
|
|
1285
|
+
/**
|
|
1286
|
+
* Returns an event generator that will listen for all events matching the regex
|
|
1287
|
+
*
|
|
1288
|
+
* @example
|
|
1289
|
+
*
|
|
1290
|
+
* const obs = new ObserverEngine();
|
|
1291
|
+
*
|
|
1292
|
+
* const onEvent = obs.on(/some/);
|
|
1293
|
+
* const { event, data } = await onEvent.next(); // waits for next event
|
|
1294
|
+
* onEvent.emit('something'); // emits data to listeners
|
|
1295
|
+
*
|
|
1296
|
+
* onEvent.cleanup(); // stops listening for events
|
|
1297
|
+
*/
|
|
1298
|
+
on(event: RegExp, options?: ObserverEngine.ListenerOptions): EventGenerator<Shape, RegExp>;
|
|
1299
|
+
/**
|
|
1300
|
+
* Listens for all events matching the regex and executes the given callback
|
|
1301
|
+
*
|
|
1302
|
+
* @example
|
|
1303
|
+
*
|
|
1304
|
+
* const obs = new ObserverEngine();
|
|
1305
|
+
*
|
|
1306
|
+
* obs.on(/some/, ({ event, data }) => {
|
|
1307
|
+
* console.log(event, data);
|
|
1308
|
+
* });
|
|
1309
|
+
*/
|
|
1310
|
+
on(event: RegExp, listener: ObserverEngine.EventCallback<ObserverEngine.RgxEmitData<Shape>>, options?: ObserverEngine.ListenerOptions): ObserverEngine.Cleanup;
|
|
1311
|
+
/**
|
|
1312
|
+
* Returns an event promise that resolves when
|
|
1313
|
+
* the specified event is emitted
|
|
1314
|
+
*/
|
|
1315
|
+
once<E extends Events<Shape>>(event: E, options?: ObserverEngine.ListenerOptions): EventPromise<Shape[E]>;
|
|
1316
|
+
/**
|
|
1317
|
+
* Returns an event promise that resolves when
|
|
1318
|
+
* the specified event is emitted. This overload
|
|
1319
|
+
* is untyped and can be used to listen for any
|
|
1320
|
+
* event that is emitted.
|
|
1321
|
+
*/
|
|
1322
|
+
once<E extends string>(event: E, options?: ObserverEngine.ListenerOptions): EventPromise<Record<E, any>>;
|
|
1323
|
+
/**
|
|
1324
|
+
* Executes a callback once when the specified
|
|
1325
|
+
* event is emitted
|
|
1326
|
+
*/
|
|
1327
|
+
once<E extends Events<Shape>>(event: E, listener: ObserverEngine.EventCallback<Shape[E]>, options?: ObserverEngine.ListenerOptions): ObserverEngine.Cleanup;
|
|
1328
|
+
/**
|
|
1329
|
+
* Executes a callback once when the specified
|
|
1330
|
+
* event is emitted. This overload is untyped
|
|
1331
|
+
* and can be used to listen for any event that
|
|
1332
|
+
* is emitted.
|
|
1333
|
+
*/
|
|
1334
|
+
once<E extends string>(event: E, listener: ObserverEngine.EventCallback<Record<E, any>>, options?: ObserverEngine.ListenerOptions): ObserverEngine.Cleanup;
|
|
1335
|
+
/**
|
|
1336
|
+
* Returns an event promise that resolves when
|
|
1337
|
+
* any events matching the regex are emitted
|
|
1338
|
+
*/
|
|
1339
|
+
once(event: RegExp, options?: ObserverEngine.ListenerOptions): EventPromise<ObserverEngine.RgxEmitData<Shape>>;
|
|
1340
|
+
/**
|
|
1341
|
+
* Executes a callback once when any events
|
|
1342
|
+
* matching the regex are emitted
|
|
1343
|
+
*/
|
|
1344
|
+
once(event: RegExp, listener: ObserverEngine.EventCallback<ObserverEngine.RgxEmitData<Shape>>, options?: ObserverEngine.ListenerOptions): ObserverEngine.Cleanup;
|
|
1345
|
+
/**
|
|
1346
|
+
* Stop listening for an event
|
|
1347
|
+
* @param event
|
|
1348
|
+
* @param listener
|
|
1349
|
+
*/
|
|
1350
|
+
off(event: Events<Shape> | RegExp | string, listener?: Function): void;
|
|
1351
|
+
/** Emits an event */
|
|
1352
|
+
emit<E extends Events<Shape> | RegExp | string>(event: E, data?: E extends Events<Shape> ? Shape[E] : E extends string ? Record<E, any>[E] : unknown): void;
|
|
1353
|
+
clear(): void;
|
|
1354
|
+
queue<E extends Events<Shape> | RegExp>(event: E, process: (data: EventData<Shape, E>) => MaybePromise<any>, options: QueueOpts): EventQueue<Shape, E>;
|
|
1355
|
+
}
|
|
1356
|
+
export type EventData<S, E extends Events<S> | RegExp = Events<S>> = (E extends Events<S> ? S[E] : E extends RegExp ? ObserverEngine.RgxEmitData<S> : S[Events<S>]);
|
|
1357
|
+
declare class EventPromise<T> extends Promise<T> {
|
|
1358
|
+
cleanup?: () => void;
|
|
1359
|
+
reject?: (err: Error | string) => void;
|
|
1360
|
+
resolve?: (value: T) => void;
|
|
1361
|
+
}
|
|
1362
|
+
declare class InternalQueueEvent<T = unknown> {
|
|
1363
|
+
readonly data: T;
|
|
1364
|
+
constructor(data: T);
|
|
1365
|
+
}
|
|
1366
|
+
declare enum QueueRejectionReason {
|
|
1367
|
+
full = "Queue is full",
|
|
1368
|
+
notRunning = "Queue is not running"
|
|
1369
|
+
}
|
|
1370
|
+
export type QueueEventData<S, E extends Events<S> | RegExp = Events<S>> = {
|
|
1371
|
+
data?: EventData<S, E>;
|
|
1372
|
+
_taskId?: string;
|
|
1373
|
+
priority?: number;
|
|
1374
|
+
reason?: QueueRejectionReason;
|
|
1375
|
+
startedAt?: number;
|
|
1376
|
+
rateLimited?: boolean;
|
|
1377
|
+
elapsed?: number;
|
|
1378
|
+
error?: Error;
|
|
1379
|
+
force?: boolean;
|
|
1380
|
+
pending?: number;
|
|
1381
|
+
flushed?: number;
|
|
1382
|
+
drained?: number;
|
|
1383
|
+
count?: number;
|
|
1384
|
+
};
|
|
1385
|
+
export type QueueEvents<S extends Record<string, any>, E extends Events<S> | RegExp = Events<S>> = {
|
|
1386
|
+
added: QueueEventData<S, E>;
|
|
1387
|
+
start: void;
|
|
1388
|
+
started: void;
|
|
1389
|
+
stopped: void;
|
|
1390
|
+
processing: QueueEventData<S, E> & {
|
|
1391
|
+
startedAt: number;
|
|
1392
|
+
rateLimited: boolean;
|
|
1393
|
+
};
|
|
1394
|
+
success: QueueEventData<S, E> & {
|
|
1395
|
+
startedAt: number;
|
|
1396
|
+
elapsed: number;
|
|
1397
|
+
rateLimited: boolean;
|
|
1398
|
+
};
|
|
1399
|
+
error: QueueEventData<S, E> & {
|
|
1400
|
+
error: Error;
|
|
1401
|
+
rateLimited: boolean;
|
|
1402
|
+
};
|
|
1403
|
+
timeout: QueueEventData<S, E> & {
|
|
1404
|
+
error: Error;
|
|
1405
|
+
rateLimited: boolean;
|
|
1406
|
+
};
|
|
1407
|
+
rejected: QueueEventData<S, E> & {
|
|
1408
|
+
reason: QueueRejectionReason;
|
|
1409
|
+
};
|
|
1410
|
+
"rate-limited": QueueEventData<S, E> & {
|
|
1411
|
+
rateLimited: boolean;
|
|
1412
|
+
};
|
|
1413
|
+
empty: void;
|
|
1414
|
+
idle: void;
|
|
1415
|
+
drain: {
|
|
1416
|
+
pending: number;
|
|
1417
|
+
};
|
|
1418
|
+
drained: {
|
|
1419
|
+
pending?: number;
|
|
1420
|
+
drained?: number;
|
|
1421
|
+
};
|
|
1422
|
+
flush: {
|
|
1423
|
+
pending: number;
|
|
1424
|
+
};
|
|
1425
|
+
flushed: {
|
|
1426
|
+
flushed: number;
|
|
1427
|
+
};
|
|
1428
|
+
paused: void;
|
|
1429
|
+
resumed: void;
|
|
1430
|
+
cleanup: void;
|
|
1431
|
+
purged: {
|
|
1432
|
+
count: number;
|
|
1433
|
+
};
|
|
1434
|
+
shutdown: {
|
|
1435
|
+
force: boolean;
|
|
1436
|
+
pending?: number;
|
|
1437
|
+
};
|
|
1438
|
+
};
|
|
1439
|
+
declare enum QueueState {
|
|
1440
|
+
running = "running",
|
|
1441
|
+
paused = "paused",
|
|
1442
|
+
stopped = "stopped",
|
|
1443
|
+
draining = "draining"
|
|
1444
|
+
}
|
|
1445
|
+
/**
|
|
1446
|
+
* The options for the queue
|
|
1447
|
+
*/
|
|
1448
|
+
export interface QueueOpts {
|
|
1449
|
+
/**
|
|
1450
|
+
* The name of the queue
|
|
1451
|
+
*/
|
|
1452
|
+
name: string;
|
|
1453
|
+
/**
|
|
1454
|
+
* The type of queue to use
|
|
1455
|
+
*
|
|
1456
|
+
* @default 'fifo'
|
|
1457
|
+
*/
|
|
1458
|
+
type?: "fifo" | "lifo";
|
|
1459
|
+
/**
|
|
1460
|
+
* The concurrency of the queue
|
|
1461
|
+
*
|
|
1462
|
+
* @default 1
|
|
1463
|
+
*/
|
|
1464
|
+
concurrency?: number;
|
|
1465
|
+
/**
|
|
1466
|
+
* The poll interval in milliseconds before the queue will
|
|
1467
|
+
* check for new items after idle.
|
|
1468
|
+
*
|
|
1469
|
+
* @default 100
|
|
1470
|
+
*/
|
|
1471
|
+
pollIntervalMs?: number;
|
|
1472
|
+
/**
|
|
1473
|
+
* The jitter percentage to displace
|
|
1474
|
+
* the next process time. This stops all concurrent
|
|
1475
|
+
* processes from happening at the same time.
|
|
1476
|
+
*
|
|
1477
|
+
* @range [0, 1]
|
|
1478
|
+
* @default 1
|
|
1479
|
+
*/
|
|
1480
|
+
jitterFactor?: number;
|
|
1481
|
+
/**
|
|
1482
|
+
* The interval in milliseconds before picking up the next item
|
|
1483
|
+
*
|
|
1484
|
+
* @note If the interval is 0, the queue will not wait between items
|
|
1485
|
+
*
|
|
1486
|
+
* @default 0
|
|
1487
|
+
*/
|
|
1488
|
+
processIntervalMs?: number;
|
|
1489
|
+
/**
|
|
1490
|
+
* The timeout in milliseconds before the task is considered timed out
|
|
1491
|
+
*
|
|
1492
|
+
* @note If the timeout is 0, the task will not be considered timed out
|
|
1493
|
+
*
|
|
1494
|
+
* @default 0
|
|
1495
|
+
*/
|
|
1496
|
+
taskTimeoutMs?: number;
|
|
1497
|
+
/**
|
|
1498
|
+
* The maximum size of the queue
|
|
1499
|
+
*
|
|
1500
|
+
* @default 999_999_999
|
|
1501
|
+
*/
|
|
1502
|
+
maxQueueSize?: number;
|
|
1503
|
+
/**
|
|
1504
|
+
* The rate limit of the queue in items per window
|
|
1505
|
+
*
|
|
1506
|
+
* @default 999_999_999
|
|
1507
|
+
*/
|
|
1508
|
+
rateLimitCapacity?: number;
|
|
1509
|
+
/**
|
|
1510
|
+
* The rate limit window in milliseconds
|
|
1511
|
+
*
|
|
1512
|
+
* @default 1000
|
|
1513
|
+
*/
|
|
1514
|
+
rateLimitIntervalMs?: number;
|
|
1515
|
+
/**
|
|
1516
|
+
* Automatically start the queue
|
|
1517
|
+
*
|
|
1518
|
+
* @default true
|
|
1519
|
+
*/
|
|
1520
|
+
autoStart?: boolean;
|
|
1521
|
+
/**
|
|
1522
|
+
* Whether to enable debug mode. Can be set to 'info' or 'verbose' to
|
|
1523
|
+
* get more detailed output.
|
|
1524
|
+
*
|
|
1525
|
+
* @default false
|
|
1526
|
+
*/
|
|
1527
|
+
debug?: boolean | "info" | "verbose";
|
|
1528
|
+
}
|
|
1529
|
+
declare class EventQueue<S extends Record<string, any>, E extends Events<S> | RegExp = Events<S>> {
|
|
1530
|
+
#private;
|
|
1531
|
+
private opts;
|
|
1532
|
+
constructor(opts: QueueOpts & {
|
|
1533
|
+
event: E | RegExp;
|
|
1534
|
+
process: (data: EventData<S, E>) => Promise<void>;
|
|
1535
|
+
observer?: ObserverEngine<S>;
|
|
1536
|
+
});
|
|
1537
|
+
/**
|
|
1538
|
+
* Start the queue if it is not already started
|
|
1539
|
+
*/
|
|
1540
|
+
start(): Promise<void> | undefined;
|
|
1541
|
+
/**
|
|
1542
|
+
* Stop the queue
|
|
1543
|
+
*/
|
|
1544
|
+
stop(): void;
|
|
1545
|
+
/**
|
|
1546
|
+
* Pause the queue
|
|
1547
|
+
*/
|
|
1548
|
+
pause(): Promise<void> | undefined;
|
|
1549
|
+
/**
|
|
1550
|
+
* Resume the queue
|
|
1551
|
+
*/
|
|
1552
|
+
resume(): Promise<void> | undefined;
|
|
1553
|
+
/**
|
|
1554
|
+
* Empty and process all items in the queue and
|
|
1555
|
+
* then stop the queue. Returns the number of items
|
|
1556
|
+
* processed.
|
|
1557
|
+
*/
|
|
1558
|
+
shutdown(force?: boolean): Promise<number>;
|
|
1559
|
+
/**
|
|
1560
|
+
* Executes `limit` items in the queue
|
|
1561
|
+
* and then emits a `flush` event. Returns the number
|
|
1562
|
+
* of items processed.
|
|
1563
|
+
*/
|
|
1564
|
+
flush(limit?: number): Promise<number>;
|
|
1565
|
+
/**
|
|
1566
|
+
* Clears the queue and emits a `purge` event. Returns
|
|
1567
|
+
* the number of items purged.
|
|
1568
|
+
*/
|
|
1569
|
+
purge(): number;
|
|
1570
|
+
/**
|
|
1571
|
+
* Emit an event to the observer, which then gets
|
|
1572
|
+
* picked up by the queue and processed.
|
|
1573
|
+
*
|
|
1574
|
+
* @param data The data to add to the queue
|
|
1575
|
+
* @param priority The priority of the data
|
|
1576
|
+
*
|
|
1577
|
+
* @note If priority is provided, it will be used to determine the order of the data in the queue.
|
|
1578
|
+
* The higher the priority, the sooner the data will be processed.
|
|
1579
|
+
*
|
|
1580
|
+
* @note If priority is not provided, the data will be added to the queue with a priority of 0.
|
|
1581
|
+
*/
|
|
1582
|
+
add(data: EventData<S, E>, priority?: number): boolean;
|
|
1583
|
+
debug(on?: boolean | "info" | "verbose"): void;
|
|
1584
|
+
on<K extends keyof QueueEvents<S, E>>(event: K, listener: ((payload: InternalQueueEvent<QueueEvents<S, E>[K]>) => void)): ObserverEngine.Cleanup;
|
|
1585
|
+
on<K extends keyof QueueEvents<S, E>>(event: K): EventGenerator<QueueEvents<S, E>, K>;
|
|
1586
|
+
once<K extends keyof QueueEvents<S, E>>(event: K): EventPromise<InternalQueueEvent<QueueEvents<S, E>[K]>>;
|
|
1587
|
+
once<K extends keyof QueueEvents<S, E>>(event: K, listener: ((payload: InternalQueueEvent<QueueEvents<S, E>[K]>) => void)): ObserverEngine.Cleanup;
|
|
1588
|
+
off<K extends keyof QueueEvents<S, E>>(event: K, listener?: Function): void;
|
|
1589
|
+
/**
|
|
1590
|
+
* The name of the queue
|
|
1591
|
+
*/
|
|
1592
|
+
get name(): string;
|
|
1593
|
+
/**
|
|
1594
|
+
* Whether the queue is waiting for the
|
|
1595
|
+
* the
|
|
1596
|
+
*/
|
|
1597
|
+
get isWaiting(): boolean;
|
|
1598
|
+
/**
|
|
1599
|
+
* Whether the queue is idle
|
|
1600
|
+
*/
|
|
1601
|
+
get isIdle(): boolean;
|
|
1602
|
+
/**
|
|
1603
|
+
* Whether the queue is running
|
|
1604
|
+
*/
|
|
1605
|
+
get isRunning(): boolean;
|
|
1606
|
+
/**
|
|
1607
|
+
* Whether the queue is paused
|
|
1608
|
+
*/
|
|
1609
|
+
get isPaused(): boolean;
|
|
1610
|
+
/**
|
|
1611
|
+
* Whether the queue is stopped
|
|
1612
|
+
*/
|
|
1613
|
+
get isStopped(): boolean;
|
|
1614
|
+
/**
|
|
1615
|
+
* Whether the queue is draining
|
|
1616
|
+
*/
|
|
1617
|
+
get isDraining(): boolean;
|
|
1618
|
+
/**
|
|
1619
|
+
* The current state of the queue
|
|
1620
|
+
*/
|
|
1621
|
+
get state(): QueueState;
|
|
1622
|
+
/**
|
|
1623
|
+
* The number of items in the queue
|
|
1624
|
+
*/
|
|
1625
|
+
get pending(): number;
|
|
1626
|
+
/**
|
|
1627
|
+
* The stats of the queue
|
|
1628
|
+
*/
|
|
1629
|
+
get stats(): {
|
|
1630
|
+
processed: number;
|
|
1631
|
+
processing: number;
|
|
1632
|
+
avgProcessingTime: number;
|
|
1633
|
+
success: number;
|
|
1634
|
+
error: number;
|
|
1635
|
+
rejected: number;
|
|
1636
|
+
};
|
|
1637
|
+
get snapshot(): {
|
|
1638
|
+
name: string;
|
|
1639
|
+
state: QueueState;
|
|
1640
|
+
pending: number;
|
|
1641
|
+
stats: {
|
|
1642
|
+
processed: number;
|
|
1643
|
+
processing: number;
|
|
1644
|
+
avgProcessingTime: number;
|
|
1645
|
+
success: number;
|
|
1646
|
+
error: number;
|
|
1647
|
+
rejected: number;
|
|
1648
|
+
};
|
|
1649
|
+
rateLimiter: {
|
|
1650
|
+
currentTokens: number;
|
|
1651
|
+
capacity: number;
|
|
1652
|
+
refillIntervalMs: number;
|
|
1653
|
+
totalRequests: number;
|
|
1654
|
+
rejectedRequests: number;
|
|
1655
|
+
successfulRequests: number;
|
|
1656
|
+
rejectionRate: number;
|
|
1657
|
+
totalWaitTime: number;
|
|
1658
|
+
waitCount: number;
|
|
1659
|
+
averageWaitTime: number;
|
|
1660
|
+
uptime: number;
|
|
1661
|
+
createdAt: number;
|
|
1662
|
+
};
|
|
1663
|
+
activeRunners: number;
|
|
1664
|
+
runningNodes: Set<`${number}-${number}`>;
|
|
1665
|
+
isIdle: boolean;
|
|
1666
|
+
isWaiting: boolean;
|
|
1667
|
+
isRunning: boolean;
|
|
1668
|
+
isPaused: boolean;
|
|
1669
|
+
isStopped: boolean;
|
|
1670
|
+
isDraining: boolean;
|
|
1671
|
+
isEmpty: boolean;
|
|
1672
|
+
};
|
|
1673
|
+
}
|
|
1674
|
+
/**
|
|
1675
|
+
* Shutdown phases in order of execution.
|
|
1676
|
+
*
|
|
1677
|
+
* Each phase has a specific purpose in the graceful shutdown sequence.
|
|
1678
|
+
*/
|
|
1679
|
+
export type ShutdownPhase = "stopping" | "completing" | "releasing" | "flushing" | "exiting";
|
|
1680
|
+
/**
|
|
1681
|
+
* Shutdown phase status.
|
|
1682
|
+
*/
|
|
1683
|
+
export type PhaseStatus = "pending" | "running" | "completed" | "timeout" | "skipped";
|
|
1684
|
+
/**
|
|
1685
|
+
* Reasons for shutdown.
|
|
1686
|
+
*/
|
|
1687
|
+
export type ShutdownReason = "signal" | "user" | "error" | "programmatic";
|
|
1688
|
+
/**
|
|
1689
|
+
* Application mode.
|
|
1690
|
+
*/
|
|
1691
|
+
export type AppMode = "tui" | "headless";
|
|
1692
|
+
/**
|
|
1693
|
+
* All events emitted by noorm core modules.
|
|
1694
|
+
*
|
|
1695
|
+
* Events are namespaced by module:
|
|
1696
|
+
* - `file:*` - Individual SQL file execution
|
|
1697
|
+
* - `build:*` - Schema build operations
|
|
1698
|
+
* - `run:*` - Ad-hoc file/dir execution
|
|
1699
|
+
* - `change:*` - Change execution
|
|
1700
|
+
* - `lock:*` - Lock acquisition/release
|
|
1701
|
+
* - `state:*` - State load/persist
|
|
1702
|
+
* - `config:*` - Config CRUD
|
|
1703
|
+
* - `secret:*` - Secret CRUD
|
|
1704
|
+
* - `db:*` - Database lifecycle
|
|
1705
|
+
* - `template:*` - Template rendering
|
|
1706
|
+
* - `identity:*` - Identity resolution
|
|
1707
|
+
* - `connection:*` - Database connections
|
|
1708
|
+
* - `settings:*` - Settings lifecycle and mutations
|
|
1709
|
+
* - `error` - Catch-all errors
|
|
1710
|
+
*/
|
|
1711
|
+
export interface NoormEvents extends SettingsEvents {
|
|
1712
|
+
"file:before": {
|
|
1713
|
+
filepath: string;
|
|
1714
|
+
checksum: string;
|
|
1715
|
+
configName: string;
|
|
1716
|
+
};
|
|
1717
|
+
"file:after": {
|
|
1718
|
+
filepath: string;
|
|
1719
|
+
status: "success" | "failed";
|
|
1720
|
+
durationMs: number;
|
|
1721
|
+
error?: string;
|
|
1722
|
+
};
|
|
1723
|
+
"file:skip": {
|
|
1724
|
+
filepath: string;
|
|
1725
|
+
reason: "unchanged" | "already-run";
|
|
1726
|
+
};
|
|
1727
|
+
"file:dry-run": {
|
|
1728
|
+
filepath: string;
|
|
1729
|
+
outputPath: string;
|
|
1730
|
+
};
|
|
1731
|
+
"change:created": {
|
|
1732
|
+
name: string;
|
|
1733
|
+
path: string;
|
|
1734
|
+
};
|
|
1735
|
+
"change:start": {
|
|
1736
|
+
name: string;
|
|
1737
|
+
direction: "change" | "revert";
|
|
1738
|
+
files: string[];
|
|
1739
|
+
};
|
|
1740
|
+
"change:file": {
|
|
1741
|
+
change: string;
|
|
1742
|
+
filepath: string;
|
|
1743
|
+
index: number;
|
|
1744
|
+
total: number;
|
|
1745
|
+
};
|
|
1746
|
+
"change:complete": {
|
|
1747
|
+
name: string;
|
|
1748
|
+
direction: "change" | "revert";
|
|
1749
|
+
status: "success" | "failed";
|
|
1750
|
+
durationMs: number;
|
|
1751
|
+
};
|
|
1752
|
+
"change:skip": {
|
|
1753
|
+
name: string;
|
|
1754
|
+
reason: string;
|
|
1755
|
+
};
|
|
1756
|
+
"build:start": {
|
|
1757
|
+
sqlPath: string;
|
|
1758
|
+
fileCount: number;
|
|
1759
|
+
};
|
|
1760
|
+
"build:complete": {
|
|
1761
|
+
status: "success" | "failed" | "partial";
|
|
1762
|
+
filesRun: number;
|
|
1763
|
+
filesSkipped: number;
|
|
1764
|
+
filesFailed: number;
|
|
1765
|
+
durationMs: number;
|
|
1766
|
+
};
|
|
1767
|
+
"run:file": {
|
|
1768
|
+
filepath: string;
|
|
1769
|
+
configName: string;
|
|
1770
|
+
};
|
|
1771
|
+
"run:dir": {
|
|
1772
|
+
dirpath: string;
|
|
1773
|
+
fileCount: number;
|
|
1774
|
+
configName: string;
|
|
1775
|
+
};
|
|
1776
|
+
"lock:acquiring": {
|
|
1777
|
+
configName: string;
|
|
1778
|
+
identity: string;
|
|
1779
|
+
};
|
|
1780
|
+
"lock:acquired": {
|
|
1781
|
+
configName: string;
|
|
1782
|
+
identity: string;
|
|
1783
|
+
expiresAt: Date;
|
|
1784
|
+
};
|
|
1785
|
+
"lock:released": {
|
|
1786
|
+
configName: string;
|
|
1787
|
+
identity: string;
|
|
1788
|
+
};
|
|
1789
|
+
"lock:blocked": {
|
|
1790
|
+
configName: string;
|
|
1791
|
+
holder: string;
|
|
1792
|
+
heldSince: Date;
|
|
1793
|
+
};
|
|
1794
|
+
"lock:expired": {
|
|
1795
|
+
configName: string;
|
|
1796
|
+
previousHolder: string;
|
|
1797
|
+
};
|
|
1798
|
+
"state:loaded": {
|
|
1799
|
+
configCount: number;
|
|
1800
|
+
activeConfig: string | null;
|
|
1801
|
+
version: string;
|
|
1802
|
+
};
|
|
1803
|
+
"state:persisted": {
|
|
1804
|
+
configCount: number;
|
|
1805
|
+
};
|
|
1806
|
+
"state:migrated": {
|
|
1807
|
+
from: string;
|
|
1808
|
+
to: string;
|
|
1809
|
+
};
|
|
1810
|
+
"config:created": {
|
|
1811
|
+
name: string;
|
|
1812
|
+
};
|
|
1813
|
+
"config:updated": {
|
|
1814
|
+
name: string;
|
|
1815
|
+
fields: string[];
|
|
1816
|
+
};
|
|
1817
|
+
"config:deleted": {
|
|
1818
|
+
name: string;
|
|
1819
|
+
};
|
|
1820
|
+
"config:activated": {
|
|
1821
|
+
name: string;
|
|
1822
|
+
previous: string | null;
|
|
1823
|
+
};
|
|
1824
|
+
"secret:set": {
|
|
1825
|
+
configName: string;
|
|
1826
|
+
key: string;
|
|
1827
|
+
};
|
|
1828
|
+
"secret:deleted": {
|
|
1829
|
+
configName: string;
|
|
1830
|
+
key: string;
|
|
1831
|
+
};
|
|
1832
|
+
"global-secret:set": {
|
|
1833
|
+
key: string;
|
|
1834
|
+
};
|
|
1835
|
+
"global-secret:deleted": {
|
|
1836
|
+
key: string;
|
|
1837
|
+
};
|
|
1838
|
+
"known-user:added": {
|
|
1839
|
+
email: string;
|
|
1840
|
+
source: string;
|
|
1841
|
+
};
|
|
1842
|
+
"db:creating": {
|
|
1843
|
+
configName: string;
|
|
1844
|
+
database: string;
|
|
1845
|
+
};
|
|
1846
|
+
"db:created": {
|
|
1847
|
+
configName: string;
|
|
1848
|
+
database: string;
|
|
1849
|
+
durationMs: number;
|
|
1850
|
+
};
|
|
1851
|
+
"db:destroying": {
|
|
1852
|
+
configName: string;
|
|
1853
|
+
database: string;
|
|
1854
|
+
};
|
|
1855
|
+
"db:destroyed": {
|
|
1856
|
+
configName: string;
|
|
1857
|
+
database: string;
|
|
1858
|
+
};
|
|
1859
|
+
"db:bootstrap": {
|
|
1860
|
+
configName: string;
|
|
1861
|
+
tables: string[];
|
|
1862
|
+
};
|
|
1863
|
+
"template:render": {
|
|
1864
|
+
filepath: string;
|
|
1865
|
+
durationMs: number;
|
|
1866
|
+
};
|
|
1867
|
+
"template:load": {
|
|
1868
|
+
filepath: string;
|
|
1869
|
+
format: string;
|
|
1870
|
+
};
|
|
1871
|
+
"template:helpers": {
|
|
1872
|
+
filepath: string;
|
|
1873
|
+
count: number;
|
|
1874
|
+
};
|
|
1875
|
+
"identity:resolved": {
|
|
1876
|
+
name: string;
|
|
1877
|
+
email?: string;
|
|
1878
|
+
source: "state" | "git" | "system" | "config" | "env";
|
|
1879
|
+
};
|
|
1880
|
+
"identity:created": {
|
|
1881
|
+
identityHash: string;
|
|
1882
|
+
name: string;
|
|
1883
|
+
email: string;
|
|
1884
|
+
machine: string;
|
|
1885
|
+
};
|
|
1886
|
+
"identity:registered": {
|
|
1887
|
+
identityHash: string;
|
|
1888
|
+
name: string;
|
|
1889
|
+
email: string;
|
|
1890
|
+
};
|
|
1891
|
+
"identity:synced": {
|
|
1892
|
+
configName: string;
|
|
1893
|
+
registered: boolean;
|
|
1894
|
+
knownUsersCount: number;
|
|
1895
|
+
};
|
|
1896
|
+
"connection:open": {
|
|
1897
|
+
configName: string;
|
|
1898
|
+
dialect: string;
|
|
1899
|
+
};
|
|
1900
|
+
"connection:close": {
|
|
1901
|
+
configName: string;
|
|
1902
|
+
};
|
|
1903
|
+
"connection:error": {
|
|
1904
|
+
configName: string;
|
|
1905
|
+
error: string;
|
|
1906
|
+
};
|
|
1907
|
+
"app:starting": {
|
|
1908
|
+
mode: AppMode;
|
|
1909
|
+
};
|
|
1910
|
+
"app:ready": {
|
|
1911
|
+
mode: AppMode;
|
|
1912
|
+
startedAt: Date;
|
|
1913
|
+
};
|
|
1914
|
+
"app:shutdown": {
|
|
1915
|
+
reason: ShutdownReason;
|
|
1916
|
+
exitCode: number;
|
|
1917
|
+
};
|
|
1918
|
+
"app:shutdown:phase": {
|
|
1919
|
+
phase: ShutdownPhase;
|
|
1920
|
+
status: PhaseStatus;
|
|
1921
|
+
durationMs?: number;
|
|
1922
|
+
error?: Error;
|
|
1923
|
+
};
|
|
1924
|
+
"app:exit": {
|
|
1925
|
+
code: number;
|
|
1926
|
+
};
|
|
1927
|
+
"app:fatal": {
|
|
1928
|
+
error: Error;
|
|
1929
|
+
type?: "exception" | "rejection";
|
|
1930
|
+
};
|
|
1931
|
+
"router:navigated": {
|
|
1932
|
+
from: string;
|
|
1933
|
+
to: string;
|
|
1934
|
+
params: Record<string, string | number | boolean | undefined>;
|
|
1935
|
+
};
|
|
1936
|
+
"router:popped": {
|
|
1937
|
+
popped: string;
|
|
1938
|
+
to: string;
|
|
1939
|
+
};
|
|
1940
|
+
error: {
|
|
1941
|
+
source: string;
|
|
1942
|
+
error: Error;
|
|
1943
|
+
context?: Record<string, unknown>;
|
|
1944
|
+
};
|
|
1945
|
+
}
|
|
1946
|
+
export type NoormEventNames = Events<NoormEvents>;
|
|
1947
|
+
/**
|
|
1948
|
+
* SDK Context implementation.
|
|
1949
|
+
*
|
|
1950
|
+
* Provides programmatic access to all noorm operations.
|
|
1951
|
+
*
|
|
1952
|
+
* @example
|
|
1953
|
+
* ```typescript
|
|
1954
|
+
* const ctx = await createContext({ config: 'dev' })
|
|
1955
|
+
* await ctx.connect()
|
|
1956
|
+
*
|
|
1957
|
+
* // Run queries
|
|
1958
|
+
* const users = await ctx.query('SELECT * FROM users')
|
|
1959
|
+
*
|
|
1960
|
+
* // Clean disconnect
|
|
1961
|
+
* await ctx.disconnect()
|
|
1962
|
+
* ```
|
|
1963
|
+
*/
|
|
1964
|
+
export declare class Context<DB = unknown> {
|
|
1965
|
+
#private;
|
|
1966
|
+
constructor(config: Config, settings: Settings, identity: Identity, options: CreateContextOptions, projectRoot: string);
|
|
1967
|
+
get config(): Config;
|
|
1968
|
+
get settings(): Settings;
|
|
1969
|
+
get identity(): Identity;
|
|
1970
|
+
get dialect(): Dialect;
|
|
1971
|
+
get connected(): boolean;
|
|
1972
|
+
get observer(): ObserverEngine<NoormEvents>;
|
|
1973
|
+
get kysely(): Kysely<DB>;
|
|
1974
|
+
connect(): Promise<void>;
|
|
1975
|
+
disconnect(): Promise<void>;
|
|
1976
|
+
query<T = Record<string, unknown>>(sqlStr: string, _params?: unknown[]): Promise<T[]>;
|
|
1977
|
+
execute(sqlStr: string, _params?: unknown[]): Promise<ExecuteResult>;
|
|
1978
|
+
transaction<T>(fn: (tx: TransactionContext) => Promise<T>): Promise<T>;
|
|
1979
|
+
listTables(): Promise<TableSummary[]>;
|
|
1980
|
+
describeTable(name: string, schema?: string): Promise<TableDetail | null>;
|
|
1981
|
+
overview(): Promise<ExploreOverview>;
|
|
1982
|
+
truncate(): Promise<TruncateResult>;
|
|
1983
|
+
teardown(): Promise<TeardownResult>;
|
|
1984
|
+
build(options?: BuildOptions): Promise<BatchResult>;
|
|
1985
|
+
reset(): Promise<void>;
|
|
1986
|
+
runFile(filepath: string, options?: RunOptions): Promise<FileResult>;
|
|
1987
|
+
runFiles(filepaths: string[], options?: RunOptions): Promise<BatchResult>;
|
|
1988
|
+
runDir(dirpath: string, options?: RunOptions): Promise<BatchResult>;
|
|
1989
|
+
applyChange(name: string, options?: ChangeOptions): Promise<ChangeResult>;
|
|
1990
|
+
revertChange(name: string, options?: ChangeOptions): Promise<ChangeResult>;
|
|
1991
|
+
fastForward(): Promise<BatchChangeResult>;
|
|
1992
|
+
getChangeStatus(): Promise<ChangeListItem[]>;
|
|
1993
|
+
getPendingChanges(): Promise<ChangeListItem[]>;
|
|
1994
|
+
getSecret(key: string): string | undefined;
|
|
1995
|
+
acquireLock(options?: LockOptions$1): Promise<Lock$1>;
|
|
1996
|
+
releaseLock(): Promise<void>;
|
|
1997
|
+
getLockStatus(): Promise<LockStatus>;
|
|
1998
|
+
withLock<T>(fn: () => Promise<T>, options?: LockOptions$1): Promise<T>;
|
|
1999
|
+
forceReleaseLock(): Promise<boolean>;
|
|
2000
|
+
renderTemplate(filepath: string): Promise<ProcessResult>;
|
|
2001
|
+
getHistory(limit?: number): Promise<ChangeHistoryRecord[]>;
|
|
2002
|
+
computeChecksum(filepath: string): Promise<string>;
|
|
2003
|
+
testConnection(): Promise<{
|
|
2004
|
+
ok: boolean;
|
|
2005
|
+
error?: string;
|
|
2006
|
+
}>;
|
|
2007
|
+
}
|
|
2008
|
+
/**
|
|
2009
|
+
* Error thrown when requireTest is enabled but config.isTest is false.
|
|
2010
|
+
*
|
|
2011
|
+
* @example
|
|
2012
|
+
* ```typescript
|
|
2013
|
+
* const ctx = await createContext({
|
|
2014
|
+
* config: 'prod',
|
|
2015
|
+
* requireTest: true, // Will throw RequireTestError
|
|
2016
|
+
* })
|
|
2017
|
+
* ```
|
|
2018
|
+
*/
|
|
2019
|
+
export declare class RequireTestError extends Error {
|
|
2020
|
+
readonly configName: string;
|
|
2021
|
+
readonly name: "RequireTestError";
|
|
2022
|
+
constructor(configName: string);
|
|
2023
|
+
}
|
|
2024
|
+
/**
|
|
2025
|
+
* Error thrown when attempting destructive operations on protected configs.
|
|
2026
|
+
*
|
|
2027
|
+
* @example
|
|
2028
|
+
* ```typescript
|
|
2029
|
+
* // If config.protected is true and allowProtected is false
|
|
2030
|
+
* await ctx.truncate() // Throws ProtectedConfigError
|
|
2031
|
+
* ```
|
|
2032
|
+
*/
|
|
2033
|
+
export declare class ProtectedConfigError extends Error {
|
|
2034
|
+
readonly configName: string;
|
|
2035
|
+
readonly operation: string;
|
|
2036
|
+
readonly name: "ProtectedConfigError";
|
|
2037
|
+
constructor(configName: string, operation: string);
|
|
2038
|
+
}
|
|
2039
|
+
/**
|
|
2040
|
+
* Create an SDK context for programmatic database access.
|
|
2041
|
+
*
|
|
2042
|
+
* Configuration is resolved using the full priority chain:
|
|
2043
|
+
* defaults <- stage <- stored <- env <- flags
|
|
2044
|
+
*
|
|
2045
|
+
* This enables:
|
|
2046
|
+
* - ENV var overrides (`NOORM_*`) for stored configs
|
|
2047
|
+
* - Env-only mode (no stored config) for CI/CD
|
|
2048
|
+
*
|
|
2049
|
+
* @param options - Context creation options
|
|
2050
|
+
* @returns Unconnected context (call connect() to use)
|
|
2051
|
+
*
|
|
2052
|
+
* @example
|
|
2053
|
+
* ```typescript
|
|
2054
|
+
* // Basic usage with stored config
|
|
2055
|
+
* const ctx = await createContext({ config: 'dev' })
|
|
2056
|
+
* await ctx.connect()
|
|
2057
|
+
*
|
|
2058
|
+
* // Require test database for safety in tests
|
|
2059
|
+
* const ctx = await createContext({
|
|
2060
|
+
* config: 'test',
|
|
2061
|
+
* requireTest: true,
|
|
2062
|
+
* })
|
|
2063
|
+
*
|
|
2064
|
+
* // Allow destructive ops on protected config
|
|
2065
|
+
* const ctx = await createContext({
|
|
2066
|
+
* config: 'staging',
|
|
2067
|
+
* allowProtected: true,
|
|
2068
|
+
* })
|
|
2069
|
+
*
|
|
2070
|
+
* // Env-only mode (CI/CD) - no stored config needed
|
|
2071
|
+
* // Requires NOORM_CONNECTION_DIALECT and NOORM_CONNECTION_DATABASE
|
|
2072
|
+
* const ctx = await createContext()
|
|
2073
|
+
* ```
|
|
2074
|
+
*/
|
|
2075
|
+
export declare function createContext<DB = unknown>(options?: CreateContextOptions): Promise<Context<DB>>;
|
|
2076
|
+
|
|
2077
|
+
export {
|
|
2078
|
+
Lock$1 as Lock,
|
|
2079
|
+
LockOptions$1 as LockOptions,
|
|
2080
|
+
ProcessResult as TemplateResult,
|
|
2081
|
+
};
|
|
2082
|
+
|
|
2083
|
+
export {};
|