monsqlize 2.0.5 → 3.0.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/CHANGELOG.md +14 -5
- package/MIGRATION.md +105 -0
- package/README.md +183 -189
- package/SECURITY.md +21 -0
- package/changelogs/README.md +16 -4
- package/changelogs/v2.0.6.md +16 -0
- package/changelogs/v2.0.7.md +63 -0
- package/changelogs/v3.0.0.md +97 -0
- package/dist/cjs/cli/data-task.cjs +17768 -0
- package/dist/cjs/index.cjs +12166 -5505
- package/dist/cjs/transaction/Transaction.cjs +151 -19
- package/dist/cjs/transaction/TransactionManager.cjs +152 -20
- package/dist/esm/index.mjs +12171 -5509
- package/dist/types/base.d.mts +81 -0
- package/dist/types/collection.d.mts +1156 -0
- package/dist/types/collection.d.ts +138 -15
- package/dist/types/data-tasks.d.mts +221 -0
- package/dist/types/data-tasks.d.ts +221 -0
- package/dist/types/expression.d.mts +115 -0
- package/dist/types/index.d.mts +24 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/lock.d.mts +77 -0
- package/dist/types/lock.d.ts +7 -4
- package/dist/types/model.d.mts +666 -0
- package/dist/types/model.d.ts +46 -14
- package/dist/types/mongodb.d.mts +56 -0
- package/dist/types/monsqlize.d.mts +638 -0
- package/dist/types/monsqlize.d.ts +130 -16
- package/dist/types/pool.d.mts +84 -0
- package/dist/types/runtime.d.mts +400 -0
- package/dist/types/runtime.d.ts +18 -5
- package/dist/types/saga.d.mts +148 -0
- package/dist/types/saga.d.ts +11 -6
- package/dist/types/slow-query-log.d.mts +126 -0
- package/dist/types/sync.d.mts +149 -0
- package/dist/types/sync.d.ts +47 -1
- package/dist/types/transaction.d.mts +152 -0
- package/dist/types/transaction.d.ts +8 -0
- package/package.json +32 -14
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import type { LoggerLike } from './base.mjs';
|
|
2
|
+
|
|
3
|
+
export interface SlowQueryLogEntry {
|
|
4
|
+
database: string;
|
|
5
|
+
collection: string;
|
|
6
|
+
operation: string;
|
|
7
|
+
durationMs: number;
|
|
8
|
+
query?: unknown;
|
|
9
|
+
timestamp?: Date;
|
|
10
|
+
queryHash?: string;
|
|
11
|
+
metadata?: Record<string, unknown>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface SlowQueryLogRecord {
|
|
15
|
+
queryHash: string;
|
|
16
|
+
database: string;
|
|
17
|
+
collection: string;
|
|
18
|
+
operation: string;
|
|
19
|
+
count: number;
|
|
20
|
+
totalTimeMs: number;
|
|
21
|
+
avgTimeMs: number;
|
|
22
|
+
maxTimeMs: number;
|
|
23
|
+
minTimeMs: number;
|
|
24
|
+
firstSeen: Date;
|
|
25
|
+
lastSeen: Date;
|
|
26
|
+
sampleQuery?: unknown;
|
|
27
|
+
metadata?: Record<string, unknown>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface SlowQueryLogFilter {
|
|
31
|
+
database?: string;
|
|
32
|
+
collection?: string;
|
|
33
|
+
operation?: string;
|
|
34
|
+
queryHash?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface SlowQueryLogQueryOptions {
|
|
38
|
+
sort?: Record<string, 1 | -1>;
|
|
39
|
+
limit?: number;
|
|
40
|
+
skip?: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface SlowQueryLogStorageConfig {
|
|
44
|
+
type?: 'memory' | 'mongodb';
|
|
45
|
+
useBusinessConnection?: boolean;
|
|
46
|
+
uri?: string | null;
|
|
47
|
+
database?: string;
|
|
48
|
+
collection?: string;
|
|
49
|
+
ttl?: number;
|
|
50
|
+
options?: Record<string, unknown>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface SlowQueryLogConfig {
|
|
54
|
+
enabled: boolean;
|
|
55
|
+
storage: SlowQueryLogStorageConfig;
|
|
56
|
+
batch: {
|
|
57
|
+
enabled: boolean;
|
|
58
|
+
size: number;
|
|
59
|
+
interval: number;
|
|
60
|
+
maxBufferSize: number;
|
|
61
|
+
};
|
|
62
|
+
filter: {
|
|
63
|
+
excludeDatabases: string[];
|
|
64
|
+
excludeCollections: string[];
|
|
65
|
+
excludeOperations: string[];
|
|
66
|
+
minExecutionTimeMs: number;
|
|
67
|
+
};
|
|
68
|
+
advanced: {
|
|
69
|
+
errorHandling: 'log' | 'throw' | 'silent';
|
|
70
|
+
autoCreateIndexes: boolean;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export type SlowQueryLogConfigInput = boolean | Partial<SlowQueryLogConfig>;
|
|
75
|
+
|
|
76
|
+
export interface SlowQueryLogStorage {
|
|
77
|
+
initialize(): Promise<void>;
|
|
78
|
+
save(log: SlowQueryLogEntry): Promise<void>;
|
|
79
|
+
saveBatch(logs: SlowQueryLogEntry[]): Promise<void>;
|
|
80
|
+
query(filter?: SlowQueryLogFilter, options?: SlowQueryLogQueryOptions): Promise<SlowQueryLogRecord[]>;
|
|
81
|
+
close(): Promise<void>;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export declare const DEFAULT_SLOW_QUERY_LOG_CONFIG: SlowQueryLogConfig;
|
|
85
|
+
export declare function generateQueryHash(input: unknown): string;
|
|
86
|
+
|
|
87
|
+
export declare class BatchQueue {
|
|
88
|
+
constructor(storage: Pick<SlowQueryLogStorage, 'saveBatch'>, options?: Partial<SlowQueryLogConfig['batch']>, logger?: LoggerLike | null);
|
|
89
|
+
add(log: SlowQueryLogEntry): Promise<void>;
|
|
90
|
+
flush(): Promise<void>;
|
|
91
|
+
close(): Promise<void>;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export declare class SlowQueryLogMemoryStorage implements SlowQueryLogStorage {
|
|
95
|
+
initialize(): Promise<void>;
|
|
96
|
+
save(log: SlowQueryLogEntry): Promise<void>;
|
|
97
|
+
saveBatch(logs: SlowQueryLogEntry[]): Promise<void>;
|
|
98
|
+
query(filter?: SlowQueryLogFilter, options?: SlowQueryLogQueryOptions): Promise<SlowQueryLogRecord[]>;
|
|
99
|
+
close(): Promise<void>;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export declare class MongoDBSlowQueryLogStorage implements SlowQueryLogStorage {
|
|
103
|
+
constructor(config?: SlowQueryLogStorageConfig, businessClient?: unknown, logger?: LoggerLike | null);
|
|
104
|
+
initialize(): Promise<void>;
|
|
105
|
+
save(log: SlowQueryLogEntry): Promise<void>;
|
|
106
|
+
saveBatch(logs: SlowQueryLogEntry[]): Promise<void>;
|
|
107
|
+
query(filter?: SlowQueryLogFilter, options?: SlowQueryLogQueryOptions): Promise<SlowQueryLogRecord[]>;
|
|
108
|
+
close(): Promise<void>;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export declare class SlowQueryLogConfigManager {
|
|
112
|
+
static mergeConfig(userConfig?: SlowQueryLogConfigInput, businessType?: string): SlowQueryLogConfig;
|
|
113
|
+
static validate(config: SlowQueryLogConfig, businessType?: string): boolean;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export declare class SlowQueryLogManager {
|
|
117
|
+
readonly config: SlowQueryLogConfig;
|
|
118
|
+
readonly storage: SlowQueryLogStorage;
|
|
119
|
+
readonly queue: BatchQueue | null;
|
|
120
|
+
constructor(userConfig?: SlowQueryLogConfigInput, businessClient?: unknown, businessType?: string, logger?: LoggerLike | null);
|
|
121
|
+
initialize(): Promise<void>;
|
|
122
|
+
save(log: SlowQueryLogEntry): Promise<void>;
|
|
123
|
+
query(filter?: SlowQueryLogFilter, options?: SlowQueryLogQueryOptions): Promise<SlowQueryLogRecord[]>;
|
|
124
|
+
close(): Promise<void>;
|
|
125
|
+
}
|
|
126
|
+
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import type { ChangeStreamDocument, Document, MongoClientOptions } from 'mongodb';
|
|
2
|
+
|
|
3
|
+
import type { LoggerLike } from './base.mjs';
|
|
4
|
+
|
|
5
|
+
export type SyncChangeEvent<TDocument extends Document = Document> = ChangeStreamDocument<TDocument> & {
|
|
6
|
+
_id?: unknown;
|
|
7
|
+
operationType: 'insert' | 'update' | 'replace' | 'delete';
|
|
8
|
+
ns: {
|
|
9
|
+
db: string;
|
|
10
|
+
coll: string;
|
|
11
|
+
};
|
|
12
|
+
documentKey?: Record<string, unknown>;
|
|
13
|
+
fullDocument?: TDocument;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export interface SyncTargetHealthCheckConfig {
|
|
17
|
+
/** Whether to enable health checks; defaults to true. */
|
|
18
|
+
enabled?: boolean;
|
|
19
|
+
/** Health check interval in milliseconds; defaults to 30000. */
|
|
20
|
+
interval?: number;
|
|
21
|
+
/** Timeout for a single health check in milliseconds; defaults to 5000. */
|
|
22
|
+
timeout?: number;
|
|
23
|
+
/** Number of retries after failure; defaults to 3. */
|
|
24
|
+
retries?: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface SyncTargetConfig {
|
|
28
|
+
name: string;
|
|
29
|
+
uri?: string;
|
|
30
|
+
pool?: string;
|
|
31
|
+
databaseName?: string;
|
|
32
|
+
/** Collections handled by this target; omit or pass ['*'] to handle all collections. */
|
|
33
|
+
collections?: string[];
|
|
34
|
+
options?: MongoClientOptions;
|
|
35
|
+
apply?: (event: SyncChangeEvent, document: Record<string, unknown> | undefined, context?: SyncTargetApplyContext) => Promise<void>;
|
|
36
|
+
/** Target node health check configuration. @since v1.0.8 */
|
|
37
|
+
healthCheck?: SyncTargetHealthCheckConfig;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface SyncTargetApplyContext {
|
|
41
|
+
targetName: string;
|
|
42
|
+
idempotencyKey?: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface SyncIdempotencyStoreLike {
|
|
46
|
+
get(key: string): Promise<unknown> | unknown;
|
|
47
|
+
set(key: string, value: unknown, ttl?: number): Promise<unknown> | unknown;
|
|
48
|
+
del?(key: string): Promise<unknown> | unknown;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type SyncIdempotencyMarkMode = 'success' | 'start';
|
|
52
|
+
|
|
53
|
+
export interface SyncIdempotencyConfig {
|
|
54
|
+
/** Enable runtime per-target idempotency checks. Defaults to false. */
|
|
55
|
+
enabled?: boolean;
|
|
56
|
+
/** Optional durable store; when omitted, an in-memory store is used. */
|
|
57
|
+
store?: SyncIdempotencyStoreLike;
|
|
58
|
+
/** Cache/store key prefix. Defaults to monsqlize:sync:idempotency. */
|
|
59
|
+
keyPrefix?: string;
|
|
60
|
+
/** Marker TTL in milliseconds. Store implementations may ignore it. */
|
|
61
|
+
ttl?: number;
|
|
62
|
+
/** Mark after target success by default; start mode requires target-owned recovery for post-mark failures. */
|
|
63
|
+
markMode?: SyncIdempotencyMarkMode;
|
|
64
|
+
/** Custom event key builder. Return null/undefined to disable idempotency for that event. */
|
|
65
|
+
keyBuilder?: (event: SyncChangeEvent, targetName: string) => string | null | undefined;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface ResumeTokenRedisLike {
|
|
69
|
+
get(key: string): Promise<string | null> | string | null;
|
|
70
|
+
set(key: string, value: string): Promise<unknown> | unknown;
|
|
71
|
+
del?(key: string): Promise<unknown> | unknown;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface ResumeTokenConfig {
|
|
75
|
+
storage?: 'file' | 'redis';
|
|
76
|
+
path?: string;
|
|
77
|
+
redis?: ResumeTokenRedisLike;
|
|
78
|
+
key?: string;
|
|
79
|
+
/** Throw when a stored resume token cannot be loaded or parsed. Defaults to strictSave. */
|
|
80
|
+
strictLoad?: boolean;
|
|
81
|
+
/** Throw when resume-token persistence fails. Defaults to true for reliable CDC. */
|
|
82
|
+
strictSave?: boolean;
|
|
83
|
+
/** Number of retry attempts after a failed token save. Defaults to 0. */
|
|
84
|
+
saveRetries?: number;
|
|
85
|
+
/** Delay between token-save retries in milliseconds. Defaults to 100. */
|
|
86
|
+
saveRetryDelayMs?: number;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface SyncConfig {
|
|
90
|
+
enabled: boolean;
|
|
91
|
+
targets: SyncTargetConfig[];
|
|
92
|
+
/** Source collections watched by the manager; omit or pass ['*'] to watch all collections. */
|
|
93
|
+
collections?: string[];
|
|
94
|
+
resumeToken?: ResumeTokenConfig;
|
|
95
|
+
filter?: (event: SyncChangeEvent) => boolean;
|
|
96
|
+
/** Optional per-target idempotency gate for replay protection. */
|
|
97
|
+
idempotency?: SyncIdempotencyConfig;
|
|
98
|
+
/**
|
|
99
|
+
* Transform a change-stream document before forwarding to sync targets.
|
|
100
|
+
* v1 form took a single argument (`doc => ...`); v2 added a second `event` argument.
|
|
101
|
+
* Signature is permissive (`any`) to accept both forms — v1 was never typed.
|
|
102
|
+
*/
|
|
103
|
+
transform?: (document: any, event?: SyncChangeEvent) => any;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface SyncStats {
|
|
107
|
+
isRunning: boolean;
|
|
108
|
+
eventCount: number;
|
|
109
|
+
syncedCount: number;
|
|
110
|
+
errorCount: number;
|
|
111
|
+
startTime: Date | null;
|
|
112
|
+
lastEventTime: Date | null;
|
|
113
|
+
lastError: Error | null;
|
|
114
|
+
tokenSaveErrorCount: number;
|
|
115
|
+
lastTokenSaveError: Error | null;
|
|
116
|
+
duplicateEventCount: number;
|
|
117
|
+
duplicateTargetCount: number;
|
|
118
|
+
targets: Array<{
|
|
119
|
+
name: string;
|
|
120
|
+
syncCount: number;
|
|
121
|
+
errorCount: number;
|
|
122
|
+
duplicateCount: number;
|
|
123
|
+
lastSyncTime: Date | null;
|
|
124
|
+
lastError: Error | null;
|
|
125
|
+
successRate: string;
|
|
126
|
+
}>;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export declare function validateSyncConfig(config: SyncConfig): void;
|
|
130
|
+
|
|
131
|
+
export declare class ResumeTokenStore {
|
|
132
|
+
constructor(options?: ResumeTokenConfig & { logger?: LoggerLike | null; });
|
|
133
|
+
load(): Promise<unknown | null>;
|
|
134
|
+
save(token: unknown): Promise<void>;
|
|
135
|
+
clear(): Promise<void>;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export declare class ChangeStreamSyncManager {
|
|
139
|
+
constructor(options: {
|
|
140
|
+
db: unknown;
|
|
141
|
+
poolManager?: unknown;
|
|
142
|
+
config: SyncConfig;
|
|
143
|
+
logger?: LoggerLike | null;
|
|
144
|
+
});
|
|
145
|
+
start(): Promise<void>;
|
|
146
|
+
stop(): Promise<void>;
|
|
147
|
+
getStats(): SyncStats;
|
|
148
|
+
}
|
|
149
|
+
|
package/dist/types/sync.d.ts
CHANGED
|
@@ -29,13 +29,42 @@ export interface SyncTargetConfig {
|
|
|
29
29
|
uri?: string;
|
|
30
30
|
pool?: string;
|
|
31
31
|
databaseName?: string;
|
|
32
|
+
/** Collections handled by this target; omit or pass ['*'] to handle all collections. */
|
|
32
33
|
collections?: string[];
|
|
33
34
|
options?: MongoClientOptions;
|
|
34
|
-
apply?: (event: SyncChangeEvent, document: Record<string, unknown> | undefined) => Promise<void>;
|
|
35
|
+
apply?: (event: SyncChangeEvent, document: Record<string, unknown> | undefined, context?: SyncTargetApplyContext) => Promise<void>;
|
|
35
36
|
/** Target node health check configuration. @since v1.0.8 */
|
|
36
37
|
healthCheck?: SyncTargetHealthCheckConfig;
|
|
37
38
|
}
|
|
38
39
|
|
|
40
|
+
export interface SyncTargetApplyContext {
|
|
41
|
+
targetName: string;
|
|
42
|
+
idempotencyKey?: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface SyncIdempotencyStoreLike {
|
|
46
|
+
get(key: string): Promise<unknown> | unknown;
|
|
47
|
+
set(key: string, value: unknown, ttl?: number): Promise<unknown> | unknown;
|
|
48
|
+
del?(key: string): Promise<unknown> | unknown;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type SyncIdempotencyMarkMode = 'success' | 'start';
|
|
52
|
+
|
|
53
|
+
export interface SyncIdempotencyConfig {
|
|
54
|
+
/** Enable runtime per-target idempotency checks. Defaults to false. */
|
|
55
|
+
enabled?: boolean;
|
|
56
|
+
/** Optional durable store; when omitted, an in-memory store is used. */
|
|
57
|
+
store?: SyncIdempotencyStoreLike;
|
|
58
|
+
/** Cache/store key prefix. Defaults to monsqlize:sync:idempotency. */
|
|
59
|
+
keyPrefix?: string;
|
|
60
|
+
/** Marker TTL in milliseconds. Store implementations may ignore it. */
|
|
61
|
+
ttl?: number;
|
|
62
|
+
/** Mark after target success by default; start mode requires target-owned recovery for post-mark failures. */
|
|
63
|
+
markMode?: SyncIdempotencyMarkMode;
|
|
64
|
+
/** Custom event key builder. Return null/undefined to disable idempotency for that event. */
|
|
65
|
+
keyBuilder?: (event: SyncChangeEvent, targetName: string) => string | null | undefined;
|
|
66
|
+
}
|
|
67
|
+
|
|
39
68
|
export interface ResumeTokenRedisLike {
|
|
40
69
|
get(key: string): Promise<string | null> | string | null;
|
|
41
70
|
set(key: string, value: string): Promise<unknown> | unknown;
|
|
@@ -47,14 +76,25 @@ export interface ResumeTokenConfig {
|
|
|
47
76
|
path?: string;
|
|
48
77
|
redis?: ResumeTokenRedisLike;
|
|
49
78
|
key?: string;
|
|
79
|
+
/** Throw when a stored resume token cannot be loaded or parsed. Defaults to strictSave. */
|
|
80
|
+
strictLoad?: boolean;
|
|
81
|
+
/** Throw when resume-token persistence fails. Defaults to true for reliable CDC. */
|
|
82
|
+
strictSave?: boolean;
|
|
83
|
+
/** Number of retry attempts after a failed token save. Defaults to 0. */
|
|
84
|
+
saveRetries?: number;
|
|
85
|
+
/** Delay between token-save retries in milliseconds. Defaults to 100. */
|
|
86
|
+
saveRetryDelayMs?: number;
|
|
50
87
|
}
|
|
51
88
|
|
|
52
89
|
export interface SyncConfig {
|
|
53
90
|
enabled: boolean;
|
|
54
91
|
targets: SyncTargetConfig[];
|
|
92
|
+
/** Source collections watched by the manager; omit or pass ['*'] to watch all collections. */
|
|
55
93
|
collections?: string[];
|
|
56
94
|
resumeToken?: ResumeTokenConfig;
|
|
57
95
|
filter?: (event: SyncChangeEvent) => boolean;
|
|
96
|
+
/** Optional per-target idempotency gate for replay protection. */
|
|
97
|
+
idempotency?: SyncIdempotencyConfig;
|
|
58
98
|
/**
|
|
59
99
|
* Transform a change-stream document before forwarding to sync targets.
|
|
60
100
|
* v1 form took a single argument (`doc => ...`); v2 added a second `event` argument.
|
|
@@ -70,10 +110,16 @@ export interface SyncStats {
|
|
|
70
110
|
errorCount: number;
|
|
71
111
|
startTime: Date | null;
|
|
72
112
|
lastEventTime: Date | null;
|
|
113
|
+
lastError: Error | null;
|
|
114
|
+
tokenSaveErrorCount: number;
|
|
115
|
+
lastTokenSaveError: Error | null;
|
|
116
|
+
duplicateEventCount: number;
|
|
117
|
+
duplicateTargetCount: number;
|
|
73
118
|
targets: Array<{
|
|
74
119
|
name: string;
|
|
75
120
|
syncCount: number;
|
|
76
121
|
errorCount: number;
|
|
122
|
+
duplicateCount: number;
|
|
77
123
|
lastSyncTime: Date | null;
|
|
78
124
|
lastError: Error | null;
|
|
79
125
|
successRate: string;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type { CacheLike } from './runtime.mjs';
|
|
2
|
+
import type { LoggerLike } from './base.mjs';
|
|
3
|
+
|
|
4
|
+
export type CacheInvalidationIntent =
|
|
5
|
+
| { type: 'pattern'; value: string }
|
|
6
|
+
| { type: 'key'; value: string };
|
|
7
|
+
|
|
8
|
+
/** Minimal MongoDB session contract used by the transaction layer. */
|
|
9
|
+
export interface MongoSession {
|
|
10
|
+
id: unknown;
|
|
11
|
+
inTransaction(): boolean;
|
|
12
|
+
startTransaction(options?: Record<string, unknown>): void;
|
|
13
|
+
commitTransaction(): Promise<void>;
|
|
14
|
+
abortTransaction(): Promise<void>;
|
|
15
|
+
endSession(): Promise<void>;
|
|
16
|
+
/** v1 compat — v1 callers read `session.transaction?.state`; populated by the underlying driver. */
|
|
17
|
+
transaction?: { state?: string;[key: string]: unknown };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Options forwarded to the MongoDB driver when starting a transaction session. */
|
|
21
|
+
export interface TransactionOptions {
|
|
22
|
+
readConcern?: {
|
|
23
|
+
level: 'local' | 'majority' | 'snapshot' | 'linearizable' | 'available';
|
|
24
|
+
};
|
|
25
|
+
readPreference?: 'primary' | 'primaryPreferred' | 'secondary' | 'secondaryPreferred' | 'nearest';
|
|
26
|
+
causalConsistency?: boolean;
|
|
27
|
+
/** Maximum transaction duration in milliseconds before an automatic abort. */
|
|
28
|
+
maxDuration?: number;
|
|
29
|
+
/** @alias maxDuration — v1 compat field */
|
|
30
|
+
timeout?: number;
|
|
31
|
+
enableRetry?: boolean;
|
|
32
|
+
maxRetries?: number;
|
|
33
|
+
retryDelay?: number;
|
|
34
|
+
retryBackoff?: number;
|
|
35
|
+
enableCacheLock?: boolean;
|
|
36
|
+
lockCleanupInterval?: number;
|
|
37
|
+
writeConcern?: Record<string, unknown>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Snapshot of a transaction's current state. */
|
|
41
|
+
export interface TransactionInfo {
|
|
42
|
+
id: string;
|
|
43
|
+
status: 'pending' | 'started' | 'committed' | 'aborted';
|
|
44
|
+
duration: number;
|
|
45
|
+
sessionId: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Aggregate statistics for all transactions managed by a `TransactionManager`. */
|
|
49
|
+
export interface TransactionStats {
|
|
50
|
+
totalTransactions: number;
|
|
51
|
+
successfulTransactions: number;
|
|
52
|
+
failedTransactions: number;
|
|
53
|
+
readOnlyTransactions: number;
|
|
54
|
+
writeTransactions: number;
|
|
55
|
+
activeTransactions: number;
|
|
56
|
+
averageDuration: number;
|
|
57
|
+
p95Duration: number;
|
|
58
|
+
p99Duration: number;
|
|
59
|
+
successRate: string;
|
|
60
|
+
readOnlyRatio: string;
|
|
61
|
+
sampleCount: number;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* In-memory lock tracker used to serialise cache invalidation across transaction boundaries.
|
|
66
|
+
* Attached to `TransactionManager`; locks are auto-released when a transaction commits or aborts.
|
|
67
|
+
*/
|
|
68
|
+
export declare class CacheLockManager {
|
|
69
|
+
constructor(options?: { logger?: LoggerLike | null; maxDuration?: number; cleanupInterval?: number; });
|
|
70
|
+
/** Register a lock for `key` owned by `owner`. */
|
|
71
|
+
addLock(key: string, owner: { id?: unknown; } | string): void;
|
|
72
|
+
/** Return `true` if `key` is currently locked. */
|
|
73
|
+
isLocked(key: string): boolean;
|
|
74
|
+
/** Release all locks held by `owner`. */
|
|
75
|
+
releaseLocks(owner: { id?: unknown; } | string): void;
|
|
76
|
+
/** Return lock usage statistics. */
|
|
77
|
+
getStats(): { totalLocks: number; activeLocks: number; maxDuration: number; };
|
|
78
|
+
/** Release all locks immediately. */
|
|
79
|
+
clear(): void;
|
|
80
|
+
/** Stop the background cleanup timer. */
|
|
81
|
+
stop(): void;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Represents a single MongoDB transaction session with optional cache-lock integration. */
|
|
85
|
+
export declare class Transaction {
|
|
86
|
+
readonly id: string;
|
|
87
|
+
readonly session: MongoSession;
|
|
88
|
+
readonly state: 'pending' | 'active' | 'committed' | 'aborted';
|
|
89
|
+
constructor(session: MongoSession, options?: {
|
|
90
|
+
cache?: CacheLike | null;
|
|
91
|
+
logger?: LoggerLike | null;
|
|
92
|
+
lockManager?: CacheLockManager | null;
|
|
93
|
+
timeout?: number;
|
|
94
|
+
transactionOptions?: Record<string, unknown>;
|
|
95
|
+
});
|
|
96
|
+
/** Begin the transaction (starts the MongoDB session transaction). */
|
|
97
|
+
start(): Promise<void>;
|
|
98
|
+
/** Commit the transaction; replays recorded cache invalidations on success. */
|
|
99
|
+
commit(): Promise<void>;
|
|
100
|
+
/** Abort the transaction and discard pending cache invalidations. */
|
|
101
|
+
abort(): Promise<void>;
|
|
102
|
+
/** Alias for `commit()` — v1 compat shorthand. */
|
|
103
|
+
end(): Promise<void>;
|
|
104
|
+
/** Record a cache-invalidation pattern to be replayed on commit. */
|
|
105
|
+
recordInvalidation(pattern: string): Promise<void>;
|
|
106
|
+
/** Record an exact cache key or pattern invalidation intent to be replayed on commit. */
|
|
107
|
+
recordCacheInvalidation(intent: CacheInvalidationIntent): Promise<void>;
|
|
108
|
+
/** @internal Record that a MongoDB write helper ran in this transaction. */
|
|
109
|
+
recordWriteOperation(): void;
|
|
110
|
+
/** Return the elapsed duration in milliseconds since the transaction started. */
|
|
111
|
+
getDuration(): number;
|
|
112
|
+
/** Return a snapshot of the transaction's current state and metadata. */
|
|
113
|
+
getInfo(): TransactionInfo;
|
|
114
|
+
/** Return v1-compatible per-transaction statistics. */
|
|
115
|
+
getStats(): {
|
|
116
|
+
id: string;
|
|
117
|
+
state: 'pending' | 'active' | 'committed' | 'aborted';
|
|
118
|
+
duration: number;
|
|
119
|
+
hasWriteOperation: boolean;
|
|
120
|
+
operationCount: number;
|
|
121
|
+
lockedKeysCount: number;
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** Manages the lifecycle of MongoDB transactions, including retry and session pooling. */
|
|
126
|
+
export declare class TransactionManager {
|
|
127
|
+
constructor(options: {
|
|
128
|
+
client: unknown;
|
|
129
|
+
cache?: CacheLike | null;
|
|
130
|
+
logger?: LoggerLike | null;
|
|
131
|
+
lockManager?: CacheLockManager | null;
|
|
132
|
+
maxDuration?: number;
|
|
133
|
+
enableRetry?: boolean;
|
|
134
|
+
maxRetries?: number;
|
|
135
|
+
retryDelay?: number;
|
|
136
|
+
retryBackoff?: number;
|
|
137
|
+
defaultReadConcern?: TransactionOptions['readConcern'];
|
|
138
|
+
defaultWriteConcern?: TransactionOptions['writeConcern'];
|
|
139
|
+
defaultReadPreference?: TransactionOptions['readPreference'];
|
|
140
|
+
maxStatsSamples?: number;
|
|
141
|
+
});
|
|
142
|
+
/** Open a new transaction session. */
|
|
143
|
+
startSession(options?: TransactionOptions): Promise<Transaction>;
|
|
144
|
+
/** Execute `callback` inside a transaction; commits on success, aborts on failure. */
|
|
145
|
+
withTransaction<T>(callback: (transaction: Transaction) => Promise<T>, options?: TransactionOptions): Promise<T>;
|
|
146
|
+
/** Return all currently active (uncommitted) transactions. */
|
|
147
|
+
getActiveTransactions(): Transaction[];
|
|
148
|
+
/** Abort all active transactions immediately. */
|
|
149
|
+
abortAll(): Promise<void>;
|
|
150
|
+
/** Return aggregate transaction statistics. */
|
|
151
|
+
getStats(): TransactionStats;
|
|
152
|
+
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { CacheLike } from './runtime';
|
|
2
2
|
import type { LoggerLike } from './base';
|
|
3
3
|
|
|
4
|
+
export type CacheInvalidationIntent =
|
|
5
|
+
| { type: 'pattern'; value: string }
|
|
6
|
+
| { type: 'key'; value: string };
|
|
7
|
+
|
|
4
8
|
/** Minimal MongoDB session contract used by the transaction layer. */
|
|
5
9
|
export interface MongoSession {
|
|
6
10
|
id: unknown;
|
|
@@ -99,6 +103,10 @@ export declare class Transaction {
|
|
|
99
103
|
end(): Promise<void>;
|
|
100
104
|
/** Record a cache-invalidation pattern to be replayed on commit. */
|
|
101
105
|
recordInvalidation(pattern: string): Promise<void>;
|
|
106
|
+
/** Record an exact cache key or pattern invalidation intent to be replayed on commit. */
|
|
107
|
+
recordCacheInvalidation(intent: CacheInvalidationIntent): Promise<void>;
|
|
108
|
+
/** @internal Record that a MongoDB write helper ran in this transaction. */
|
|
109
|
+
recordWriteOperation(): void;
|
|
102
110
|
/** Return the elapsed duration in milliseconds since the transaction started. */
|
|
103
111
|
getDuration(): number;
|
|
104
112
|
/** Return a snapshot of the transaction's current state and metadata. */
|
package/package.json
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "monsqlize",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "TypeScript
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"description": "TypeScript production data runtime layer for MongoDB today, with cache, transactions, pools, models, sync, and observability",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./dist/cjs/index.cjs",
|
|
7
7
|
"module": "./dist/esm/index.mjs",
|
|
8
8
|
"types": "./dist/types/index.d.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"monsqlize": "dist/cjs/cli/data-task.cjs"
|
|
11
|
+
},
|
|
9
12
|
"exports": {
|
|
10
13
|
".": {
|
|
11
|
-
"types":
|
|
14
|
+
"types": {
|
|
15
|
+
"import": "./dist/types/index.d.mts",
|
|
16
|
+
"require": "./dist/types/index.d.ts"
|
|
17
|
+
},
|
|
12
18
|
"require": "./dist/cjs/index.cjs",
|
|
13
19
|
"import": "./dist/esm/index.mjs"
|
|
14
20
|
},
|
|
@@ -18,6 +24,10 @@
|
|
|
18
24
|
"dist/**/*.cjs",
|
|
19
25
|
"dist/**/*.mjs",
|
|
20
26
|
"dist/**/*.d.ts",
|
|
27
|
+
"dist/**/*.d.mts",
|
|
28
|
+
"changelogs/v3.0.0.md",
|
|
29
|
+
"changelogs/v2.0.7.md",
|
|
30
|
+
"changelogs/v2.0.6.md",
|
|
21
31
|
"changelogs/v2.0.5.md",
|
|
22
32
|
"changelogs/v2.0.4.md",
|
|
23
33
|
"changelogs/v2.0.3.md",
|
|
@@ -25,20 +35,25 @@
|
|
|
25
35
|
"changelogs/v2.0.1.md",
|
|
26
36
|
"changelogs/v2.0.0.md",
|
|
27
37
|
"README.md",
|
|
38
|
+
"MIGRATION.md",
|
|
39
|
+
"SECURITY.md",
|
|
28
40
|
"LICENSE",
|
|
29
41
|
"CHANGELOG.md"
|
|
30
42
|
],
|
|
31
43
|
"keywords": [
|
|
32
44
|
"mongodb",
|
|
33
45
|
"database",
|
|
34
|
-
"
|
|
46
|
+
"data-runtime",
|
|
47
|
+
"database-runtime",
|
|
35
48
|
"cache",
|
|
36
49
|
"transaction",
|
|
37
50
|
"distributed",
|
|
51
|
+
"cache-invalidation",
|
|
38
52
|
"pagination",
|
|
39
53
|
"performance",
|
|
40
54
|
"mongodb-driver",
|
|
41
55
|
"nosql",
|
|
56
|
+
"typescript",
|
|
42
57
|
"query-builder",
|
|
43
58
|
"api"
|
|
44
59
|
],
|
|
@@ -60,7 +75,7 @@
|
|
|
60
75
|
"mongodbMemoryServer": {
|
|
61
76
|
"downloadDir": ".cache/mongodb-memory-server/binaries",
|
|
62
77
|
"preferGlobalPath": "false",
|
|
63
|
-
"version": "7.0.
|
|
78
|
+
"version": "7.0.37"
|
|
64
79
|
}
|
|
65
80
|
},
|
|
66
81
|
"engines": {
|
|
@@ -80,24 +95,27 @@
|
|
|
80
95
|
"test:real-env:private": "node scripts/validation/run-private-real-env-checks.cjs",
|
|
81
96
|
"test:examples": "npm run build && tsc -p tsconfig.examples.json && node scripts/run-examples.cjs",
|
|
82
97
|
"test:performance": "npm run build && npm run build:tests && node .generated/test-dist/test/performance/baselines/function-cache.benchmark.js",
|
|
83
|
-
"test:unit": "npm run build && npm run build:tests && node
|
|
98
|
+
"test:unit": "npm run build && npm run build:tests && node test/run-tests.cjs unit",
|
|
84
99
|
"test:integration": "npm run build && npm run build:tests && node --test --test-concurrency=1 .generated/test-dist/test/integration/cache/cache.test.js .generated/test-dist/test/integration/cache/cache-behavior.test.js .generated/test-dist/test/integration/mongodb/connect.test.js .generated/test-dist/test/integration/mongodb/queries.test.js .generated/test-dist/test/integration/mongodb/management.test.js .generated/test-dist/test/integration/mongodb/writes-batch.test.js .generated/test-dist/test/integration/mongodb/find.test.js .generated/test-dist/test/integration/mongodb/find-one.test.js .generated/test-dist/test/integration/mongodb/find-page.test.js .generated/test-dist/test/integration/mongodb/aggregate.test.js .generated/test-dist/test/integration/mongodb/chaining.test.js .generated/test-dist/test/integration/mongodb/insert.test.js .generated/test-dist/test/integration/mongodb/update.test.js .generated/test-dist/test/integration/mongodb/delete.test.js .generated/test-dist/test/integration/mongodb/update-pipeline.test.js .generated/test-dist/test/integration/model/model-features.test.js .generated/test-dist/test/integration/transaction/transaction.test.js .generated/test-dist/test/integration/pool/pool.test.js .generated/test-dist/test/integration/pool/pool-behavior.test.js .generated/test-dist/test/integration/watch/watch-native.test.js .generated/test-dist/test/integration/runtime/runtime-core-regression.test.js .generated/test-dist/test/integration/sync/sync.test.js .generated/test-dist/test/integration/slow-query-log/slow-query-log.test.js .generated/test-dist/test/integration/model/model-crud-extended.test.js .generated/test-dist/test/integration/mongodb/management-complete.test.js .generated/test-dist/test/integration/runtime/runtime-methods-extended.test.js .generated/test-dist/test/integration/mongodb/find-page-advanced.test.js",
|
|
100
|
+
"test:data-tasks:integration": "npm run build && npm run build:tests && node test/run-tests.cjs data-tasks-integration",
|
|
101
|
+
"test:data-task-cli": "npm run build && npm run build:tests && node test/run-tests.cjs data-task-cli",
|
|
102
|
+
"test:pack-install": "npm run build && node scripts/pack-install-smoke.cjs",
|
|
85
103
|
"test:refactor-guard": "npm run build && npm run build:tests && node --test --test-concurrency=1 .generated/test-dist/test/compatibility/exports/exports.test.js .generated/test-dist/test/integration/model/model-features.test.js .generated/test-dist/test/integration/runtime/runtime-core-regression.test.js .generated/test-dist/test/integration/sync/sync.test.js",
|
|
86
104
|
"test:refactor-guard:cache": "npm run build && npm run build:tests && node --test .generated/test-dist/test/unit/cache/cache-refactor-guard.test.js",
|
|
87
|
-
"test:coverage": "
|
|
105
|
+
"test:coverage": "node scripts/run-coverage.cjs",
|
|
88
106
|
"test:audit": "npm audit --omit=dev --registry=https://registry.npmjs.org/",
|
|
89
107
|
"test": "npm run build && npm run build:tests && node test/run-tests.cjs",
|
|
90
|
-
"type-check": "npm run build && tsc -p tsconfig.json --noEmit && tsd --files test/types/root-import.test-d.ts --files test/types/cache-usage.test-d.ts --files test/types/model-usage.test-d.ts --files test/types/pool-usage.test-d.ts --files test/types/sync-usage.test-d.ts --files test/types/slow-query-log-usage.test-d.ts --files test/types/saga-usage.test-d.ts",
|
|
108
|
+
"type-check": "npm run build && tsc -p tsconfig.json --noEmit && tsd --files test/types/root-import.test-d.ts --files test/types/cache-usage.test-d.ts --files test/types/model-usage.test-d.ts --files test/types/pool-usage.test-d.ts --files test/types/sync-usage.test-d.ts --files test/types/slow-query-log-usage.test-d.ts --files test/types/saga-usage.test-d.ts --files test/types/data-tasks-usage.test-d.ts",
|
|
91
109
|
"check:test-language": "node scripts/check-test-language.cjs",
|
|
92
110
|
"check:docs-examples": "node scripts/validation/check-doc-example-matrix.cjs",
|
|
111
|
+
"check:release-candidate": "node scripts/check-release-candidate.cjs",
|
|
93
112
|
"verify:fast": "npm run lint && npm run check:docs-examples && npm run type-check && npm run check:sizes:strict && npm run test:runtime && npm run test:compatibility && npm run test:refactor-guard && npm run test:refactor-guard:cache",
|
|
94
113
|
"verify:full": "npm run lint && npm run check:docs-examples && npm run type-check && npm run check:sizes:strict && npm run test:examples && npm run test:server-matrix",
|
|
95
114
|
"verify:release": "npm run verify:full && npm run test:real-env:private",
|
|
96
115
|
"verify": "npm run verify:full",
|
|
97
116
|
"release:preflight": "node scripts/release-preflight.cjs",
|
|
98
117
|
"prepublishOnly": "npm run release:preflight",
|
|
99
|
-
"release:publish": "npm run release:preflight && npm publish --ignore-scripts"
|
|
100
|
-
"postpublish": "echo 'Publish succeeded. Create GitHub Release: https://github.com/vextjs/monSQLize/releases/new?tag=v'$npm_package_version"
|
|
118
|
+
"release:publish": "npm run release:preflight && npm publish --ignore-scripts"
|
|
101
119
|
},
|
|
102
120
|
"devDependencies": {
|
|
103
121
|
"@eslint/js": "9.39.4",
|
|
@@ -105,9 +123,9 @@
|
|
|
105
123
|
"@types/semver": "7.7.1",
|
|
106
124
|
"c8": "11.0.0",
|
|
107
125
|
"chai": "6.2.2",
|
|
108
|
-
"esbuild": "0.
|
|
126
|
+
"esbuild": "0.28.1",
|
|
109
127
|
"eslint": "9.39.4",
|
|
110
|
-
"mongodb-memory-server": "
|
|
128
|
+
"mongodb-memory-server": "10.4.3",
|
|
111
129
|
"sinon": "22.0.0",
|
|
112
130
|
"tsd": "0.33.0",
|
|
113
131
|
"typescript": "5.9.3"
|
|
@@ -115,9 +133,9 @@
|
|
|
115
133
|
"dependencies": {
|
|
116
134
|
"async-lock": "1.4.1",
|
|
117
135
|
"cache-hub": "2.2.4",
|
|
118
|
-
"ioredis": "5.
|
|
136
|
+
"ioredis": "5.11.1",
|
|
119
137
|
"mongodb": "6.21.0",
|
|
120
|
-
"schema-dsl": "2.
|
|
138
|
+
"schema-dsl": "2.1.6",
|
|
121
139
|
"ssh2": "1.17.0"
|
|
122
140
|
}
|
|
123
141
|
}
|