@memberjunction/query-gen 5.28.0 → 5.30.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.
@@ -1,4 +1,4 @@
1
1
 
2
- > @memberjunction/query-gen@5.28.0 build
2
+ > @memberjunction/query-gen@5.30.0 build
3
3
  > tsc && tsc-alias -f
4
4
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,42 @@
1
1
  # @memberjunction/query-gen
2
2
 
3
+ ## 5.30.0
4
+
5
+ ### Patch Changes
6
+
7
+ - 216ddc3: Wrap sequential Save/Delete looops in atomic transcatoins (TransactionGroup client-side BeginTransaction/Commit/Rollback server-side)
8
+ - Updated dependencies [c2c5892]
9
+ - Updated dependencies [68bf87f]
10
+ - Updated dependencies [963f2df]
11
+ - Updated dependencies [4729398]
12
+ - Updated dependencies [b1f32a4]
13
+ - Updated dependencies [c199f3b]
14
+ - @memberjunction/aiengine@5.30.0
15
+ - @memberjunction/core-entities@5.30.0
16
+ - @memberjunction/core@5.30.0
17
+ - @memberjunction/ai-core-plus@5.30.0
18
+ - @memberjunction/ai-prompts@5.30.0
19
+ - @memberjunction/sqlserver-dataprovider@5.30.0
20
+ - @memberjunction/ai-vectors-memory@5.30.0
21
+ - @memberjunction/ai@5.30.0
22
+ - @memberjunction/global@5.30.0
23
+
24
+ ## 5.29.0
25
+
26
+ ### Patch Changes
27
+
28
+ - Updated dependencies [e02e24e]
29
+ - Updated dependencies [7006276]
30
+ - @memberjunction/core@5.29.0
31
+ - @memberjunction/core-entities@5.29.0
32
+ - @memberjunction/ai-core-plus@5.29.0
33
+ - @memberjunction/aiengine@5.29.0
34
+ - @memberjunction/ai-prompts@5.29.0
35
+ - @memberjunction/ai-vectors-memory@5.29.0
36
+ - @memberjunction/sqlserver-dataprovider@5.29.0
37
+ - @memberjunction/ai@5.29.0
38
+ - @memberjunction/global@5.29.0
39
+
3
40
  ## 5.28.0
4
41
 
5
42
  ### Patch Changes
@@ -15,13 +15,15 @@ export declare class QueryDatabaseWriter {
15
15
  private categoryCache;
16
16
  constructor();
17
17
  /**
18
- * Write validated queries to the database
18
+ * Write validated queries to the database atomically.
19
19
  *
20
20
  * Creates Query entities. QueryFields and QueryParameters are automatically
21
21
  * extracted by MJQueryEntity.server.ts using AI analysis of the SQL template.
22
- * This happens asynchronously during the Save() operation.
22
+ * That extraction happens asynchronously during the Save() operation.
23
23
  *
24
- * Errors for individual queries are logged but don't stop the batch process.
24
+ * Wraps the whole batch in a single DB transaction any save failure
25
+ * rolls back every query previously queued in this call, so callers
26
+ * see either all queries persisted or none.
25
27
  *
26
28
  * @param validatedQueries - Array of validated queries to write
27
29
  * @param contextUser - User context for entity operations
@@ -1 +1 @@
1
- {"version":3,"file":"QueryDatabaseWriter.d.ts","sourceRoot":"","sources":["../../src/core/QueryDatabaseWriter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAqB,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAKnE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7D;;;GAGG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,aAAa,CAAkC;;IAKvD;;;;;;;;;;;;OAYG;IACG,sBAAsB,CAC1B,gBAAgB,EAAE,cAAc,EAAE,EAClC,WAAW,EAAE,QAAQ,GACpB,OAAO,CAAC,WAAW,CAAC;IA8CvB;;;;OAIG;YACW,aAAa;IAmC3B;;;;;;;;;;OAUG;YACW,oBAAoB;CA8CnC"}
1
+ {"version":3,"file":"QueryDatabaseWriter.d.ts","sourceRoot":"","sources":["../../src/core/QueryDatabaseWriter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAA2C,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAKzF,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7D;;;GAGG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,aAAa,CAAkC;;IAKvD;;;;;;;;;;;;;;OAcG;IACG,sBAAsB,CAC1B,gBAAgB,EAAE,cAAc,EAAE,EAClC,WAAW,EAAE,QAAQ,GACpB,OAAO,CAAC,WAAW,CAAC;IA4CvB;;;;OAIG;YACW,aAAa;IAmC3B;;;;;;;;;;OAUG;YACW,oBAAoB;CA8CnC"}
@@ -17,33 +17,31 @@ export class QueryDatabaseWriter {
17
17
  // No config needed - category info comes from ValidatedQuery
18
18
  }
19
19
  /**
20
- * Write validated queries to the database
20
+ * Write validated queries to the database atomically.
21
21
  *
22
22
  * Creates Query entities. QueryFields and QueryParameters are automatically
23
23
  * extracted by MJQueryEntity.server.ts using AI analysis of the SQL template.
24
- * This happens asynchronously during the Save() operation.
24
+ * That extraction happens asynchronously during the Save() operation.
25
25
  *
26
- * Errors for individual queries are logged but don't stop the batch process.
26
+ * Wraps the whole batch in a single DB transaction any save failure
27
+ * rolls back every query previously queued in this call, so callers
28
+ * see either all queries persisted or none.
27
29
  *
28
30
  * @param validatedQueries - Array of validated queries to write
29
31
  * @param contextUser - User context for entity operations
30
32
  * @returns Write result with success status and per-query results
31
33
  */
32
34
  async writeQueriesToDatabase(validatedQueries, contextUser) {
35
+ if (validatedQueries.length === 0) {
36
+ return { success: true, results: [] };
37
+ }
33
38
  const md = new Metadata();
34
39
  const results = [];
35
- // Process each query
36
- for (const vq of validatedQueries) {
37
- try {
38
- // Get or create the category for this query (with caching)
40
+ const provider = Metadata.Provider;
41
+ await provider.BeginTransaction();
42
+ try {
43
+ for (const vq of validatedQueries) {
39
44
  const categoryId = await this.getCategoryId(vq.category, contextUser);
40
- // Create Query entity ONLY (NO manual fields/params creation)
41
- // MJQueryEntity.server.ts will automatically:
42
- // - Detect Nunjucks syntax
43
- // - Extract parameters using AI
44
- // - Create QueryParameter records
45
- // - Create QueryField records
46
- // - Set UsesTemplate flag
47
45
  const query = await md.GetEntityObject('MJ: Queries', contextUser);
48
46
  query.NewRecord();
49
47
  query.Name = vq.query.queryName;
@@ -54,20 +52,22 @@ export class QueryDatabaseWriter {
54
52
  query.SQL = vq.query.sql;
55
53
  query.OriginalSQL = vq.query.sql;
56
54
  query.Status = 'Pending';
57
- const saved = await query.Save();
58
- if (!saved) {
59
- throw new Error(`Failed to save query: ${query.LatestResult?.Message}`);
55
+ if (!await query.Save()) {
56
+ throw new Error(`Failed to save query '${vq.query.queryName}': ${query.LatestResult?.CompleteMessage ?? 'unknown error'}`);
60
57
  }
61
58
  results.push(`✓ ${query.Name} (ID: ${query.ID}) - AI extraction queued`);
62
59
  }
63
- catch (error) {
64
- results.push(`✗ ${vq.businessQuestion.userQuestion}: ${extractErrorMessage(error, 'Database Write')}`);
65
- }
60
+ await provider.CommitTransaction();
61
+ return { success: true, results };
62
+ }
63
+ catch (error) {
64
+ await provider.RollbackTransaction();
65
+ const message = extractErrorMessage(error, 'Database Write');
66
+ return {
67
+ success: false,
68
+ results: [`✗ Batch rolled back: ${message}`, ...results.map(r => r.replace('✓', '~'))]
69
+ };
66
70
  }
67
- return {
68
- success: true,
69
- results
70
- };
71
71
  }
72
72
  /**
73
73
  * Get or create category ID from QueryCategoryInfo
@@ -1 +1 @@
1
- {"version":3,"file":"QueryDatabaseWriter.js","sourceRoot":"","sources":["../../src/core/QueryDatabaseWriter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"QueryDatabaseWriter.js","sourceRoot":"","sources":["../../src/core/QueryDatabaseWriter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAwB,QAAQ,EAAE,OAAO,EAAY,MAAM,sBAAsB,CAAC;AAMzF,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAE9D;;;GAGG;AACH,MAAM,OAAO,mBAAmB;IAG9B;QAFQ,kBAAa,GAAwB,IAAI,GAAG,EAAE,CAAC;QAGrD,6DAA6D;IAC/D,CAAC;IACD;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,sBAAsB,CAC1B,gBAAkC,EAClC,WAAqB;QAErB,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QACxC,CAAC;QAED,MAAM,EAAE,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAgC,CAAC;QAE3D,MAAM,QAAQ,CAAC,gBAAgB,EAAE,CAAC;QAClC,IAAI,CAAC;YACH,KAAK,MAAM,EAAE,IAAI,gBAAgB,EAAE,CAAC;gBAClC,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;gBAEtE,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,eAAe,CAAgB,aAAa,EAAE,WAAW,CAAC,CAAC;gBAClF,KAAK,CAAC,SAAS,EAAE,CAAC;gBAClB,KAAK,CAAC,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC;gBAChC,KAAK,CAAC,UAAU,GAAG,UAAU,CAAC;gBAC9B,KAAK,CAAC,YAAY,GAAG,EAAE,CAAC,gBAAgB,CAAC,YAAY,CAAC;gBACtD,KAAK,CAAC,WAAW,GAAG,EAAE,CAAC,gBAAgB,CAAC,WAAW,CAAC;gBACpD,KAAK,CAAC,oBAAoB,GAAG,EAAE,CAAC,gBAAgB,CAAC,oBAAoB,CAAC;gBACtE,KAAK,CAAC,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC;gBACzB,KAAK,CAAC,WAAW,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC;gBACjC,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC;gBAEzB,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;oBACxB,MAAM,IAAI,KAAK,CAAC,yBAAyB,EAAE,CAAC,KAAK,CAAC,SAAS,MAAM,KAAK,CAAC,YAAY,EAAE,eAAe,IAAI,eAAe,EAAE,CAAC,CAAC;gBAC7H,CAAC;gBAED,OAAO,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,IAAI,SAAS,KAAK,CAAC,EAAE,0BAA0B,CAAC,CAAC;YAC3E,CAAC;YAED,MAAM,QAAQ,CAAC,iBAAiB,EAAE,CAAC;YACnC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QACpC,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,MAAM,QAAQ,CAAC,mBAAmB,EAAE,CAAC;YACrC,MAAM,OAAO,GAAG,mBAAmB,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;YAC7D,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,CAAC,wBAAwB,OAAO,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;aACvF,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,aAAa,CACzB,QAAwF,EACxF,WAAqB;QAErB,6CAA6C;QAC7C,IAAI,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAE,CAAC;QAChD,CAAC;QAED,4DAA4D;QAC5D,IAAI,QAAQ,GAAkB,IAAI,CAAC;QACnC,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;YACxB,qDAAqD;YACrD,MAAM,cAAc,GAAG;gBACrB,IAAI,EAAE,QAAQ,CAAC,UAAU;gBACzB,UAAU,EAAE,IAAI;gBAChB,WAAW,EAAE,qDAAqD;gBAClE,IAAI,EAAE,QAAQ,CAAC,UAAU;aAC1B,CAAC;YACF,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;QACnE,CAAC;QAED,+BAA+B;QAC/B,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAChD,QAAQ,CAAC,IAAI,EACb,QAAQ,EACR,QAAQ,CAAC,WAAW,EACpB,WAAW,CACZ,CAAC;QAEF,uBAAuB;QACvB,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAClD,OAAO,UAAU,CAAC;IACpB,CAAC;IAED;;;;;;;;;;OAUG;IACK,KAAK,CAAC,oBAAoB,CAChC,YAAoB,EACpB,gBAA+B,EAC/B,WAAmB,EACnB,WAAqB;QAErB,MAAM,EAAE,GAAG,IAAI,OAAO,EAAE,CAAC;QAEzB,6CAA6C;QAC7C,IAAI,MAAM,GAAG,SAAS,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;QAC1D,IAAI,gBAAgB,EAAE,CAAC;YACrB,MAAM,IAAI,kBAAkB,gBAAgB,GAAG,CAAC;QAClD,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,uBAAuB,CAAC;QACpC,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAwB;YACrD,UAAU,EAAE,sBAAsB;YAClC,WAAW,EAAE,MAAM;YACnB,UAAU,EAAE,eAAe;SAC5B,EAAE,WAAW,CAAC,CAAC;QAEhB,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,kCAAkC,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;QAC3E,CAAC;QAED,wCAAwC;QACxC,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChD,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9B,CAAC;QAED,oCAAoC;QACpC,MAAM,EAAE,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC1B,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,eAAe,CAAwB,sBAAsB,EAAE,WAAW,CAAC,CAAC;QACtG,QAAQ,CAAC,SAAS,EAAE,CAAC;QACrB,QAAQ,CAAC,IAAI,GAAG,YAAY,CAAC;QAC7B,QAAQ,CAAC,QAAQ,GAAG,gBAAgB,CAAC;QACrC,QAAQ,CAAC,WAAW,GAAG,WAAW,CAAC;QAEnC,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACpC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,8BAA8B,QAAQ,CAAC,YAAY,EAAE,OAAO,EAAE,CAAC,CAAC;QAClF,CAAC;QAED,OAAO,QAAQ,CAAC,EAAE,CAAC;IACrB,CAAC;CACF"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@memberjunction/query-gen",
3
3
  "type": "module",
4
- "version": "5.28.0",
4
+ "version": "5.30.0",
5
5
  "description": "AI-powered generation of domain-specific SQL query templates with automatic testing, refinement, and metadata export",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -28,15 +28,15 @@
28
28
  "author": "MemberJunction",
29
29
  "license": "MIT",
30
30
  "dependencies": {
31
- "@memberjunction/ai": "5.28.0",
32
- "@memberjunction/ai-core-plus": "5.28.0",
33
- "@memberjunction/aiengine": "5.28.0",
34
- "@memberjunction/ai-prompts": "5.28.0",
35
- "@memberjunction/ai-vectors-memory": "5.28.0",
36
- "@memberjunction/core": "5.28.0",
37
- "@memberjunction/core-entities": "5.28.0",
38
- "@memberjunction/global": "5.28.0",
39
- "@memberjunction/sqlserver-dataprovider": "5.28.0",
31
+ "@memberjunction/ai": "5.30.0",
32
+ "@memberjunction/ai-core-plus": "5.30.0",
33
+ "@memberjunction/aiengine": "5.30.0",
34
+ "@memberjunction/ai-prompts": "5.30.0",
35
+ "@memberjunction/ai-vectors-memory": "5.30.0",
36
+ "@memberjunction/core": "5.30.0",
37
+ "@memberjunction/core-entities": "5.30.0",
38
+ "@memberjunction/global": "5.30.0",
39
+ "@memberjunction/sqlserver-dataprovider": "5.30.0",
40
40
  "chalk": "^5.6.2",
41
41
  "commander": "^14.0.3",
42
42
  "nunjucks": "^3.2.4",
@@ -6,7 +6,7 @@
6
6
  * of the SQL template during the Save() operation.
7
7
  */
8
8
 
9
- import { Metadata, RunView, UserInfo } from '@memberjunction/core';
9
+ import { DatabaseProviderBase, Metadata, RunView, UserInfo } from '@memberjunction/core';
10
10
  import {
11
11
  MJQueryEntity,
12
12
  MJQueryCategoryEntity
@@ -25,13 +25,15 @@ export class QueryDatabaseWriter {
25
25
  // No config needed - category info comes from ValidatedQuery
26
26
  }
27
27
  /**
28
- * Write validated queries to the database
28
+ * Write validated queries to the database atomically.
29
29
  *
30
30
  * Creates Query entities. QueryFields and QueryParameters are automatically
31
31
  * extracted by MJQueryEntity.server.ts using AI analysis of the SQL template.
32
- * This happens asynchronously during the Save() operation.
32
+ * That extraction happens asynchronously during the Save() operation.
33
33
  *
34
- * Errors for individual queries are logged but don't stop the batch process.
34
+ * Wraps the whole batch in a single DB transaction any save failure
35
+ * rolls back every query previously queued in this call, so callers
36
+ * see either all queries persisted or none.
35
37
  *
36
38
  * @param validatedQueries - Array of validated queries to write
37
39
  * @param contextUser - User context for entity operations
@@ -41,22 +43,19 @@ export class QueryDatabaseWriter {
41
43
  validatedQueries: ValidatedQuery[],
42
44
  contextUser: UserInfo
43
45
  ): Promise<WriteResult> {
46
+ if (validatedQueries.length === 0) {
47
+ return { success: true, results: [] };
48
+ }
49
+
44
50
  const md = new Metadata();
45
51
  const results: string[] = [];
52
+ const provider = Metadata.Provider as DatabaseProviderBase;
46
53
 
47
- // Process each query
48
- for (const vq of validatedQueries) {
49
- try {
50
- // Get or create the category for this query (with caching)
54
+ await provider.BeginTransaction();
55
+ try {
56
+ for (const vq of validatedQueries) {
51
57
  const categoryId = await this.getCategoryId(vq.category, contextUser);
52
58
 
53
- // Create Query entity ONLY (NO manual fields/params creation)
54
- // MJQueryEntity.server.ts will automatically:
55
- // - Detect Nunjucks syntax
56
- // - Extract parameters using AI
57
- // - Create QueryParameter records
58
- // - Create QueryField records
59
- // - Set UsesTemplate flag
60
59
  const query = await md.GetEntityObject<MJQueryEntity>('MJ: Queries', contextUser);
61
60
  query.NewRecord();
62
61
  query.Name = vq.query.queryName;
@@ -68,22 +67,23 @@ export class QueryDatabaseWriter {
68
67
  query.OriginalSQL = vq.query.sql;
69
68
  query.Status = 'Pending';
70
69
 
71
- const saved = await query.Save();
72
- if (!saved) {
73
- throw new Error(`Failed to save query: ${query.LatestResult?.Message}`);
70
+ if (!await query.Save()) {
71
+ throw new Error(`Failed to save query '${vq.query.queryName}': ${query.LatestResult?.CompleteMessage ?? 'unknown error'}`);
74
72
  }
75
73
 
76
74
  results.push(`✓ ${query.Name} (ID: ${query.ID}) - AI extraction queued`);
77
-
78
- } catch (error: unknown) {
79
- results.push(`✗ ${vq.businessQuestion.userQuestion}: ${extractErrorMessage(error, 'Database Write')}`);
80
75
  }
81
- }
82
76
 
83
- return {
84
- success: true,
85
- results
86
- };
77
+ await provider.CommitTransaction();
78
+ return { success: true, results };
79
+ } catch (error: unknown) {
80
+ await provider.RollbackTransaction();
81
+ const message = extractErrorMessage(error, 'Database Write');
82
+ return {
83
+ success: false,
84
+ results: [`✗ Batch rolled back: ${message}`, ...results.map(r => r.replace('✓', '~'))]
85
+ };
86
+ }
87
87
  }
88
88
 
89
89
  /**