@memberjunction/metadata-sync 6.2.0-edge.5 → 6.2.0-edge.7
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/README.md +151 -2
- package/dist/config.d.ts +37 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/RecordProcessor.d.ts +16 -0
- package/dist/lib/RecordProcessor.d.ts.map +1 -1
- package/dist/lib/RecordProcessor.js +51 -4
- package/dist/lib/RecordProcessor.js.map +1 -1
- package/dist/lib/collection-promotion.d.ts +89 -0
- package/dist/lib/collection-promotion.d.ts.map +1 -0
- package/dist/lib/collection-promotion.js +154 -0
- package/dist/lib/collection-promotion.js.map +1 -0
- package/dist/lib/deletion-auditor.d.ts.map +1 -1
- package/dist/lib/deletion-auditor.js +1 -1
- package/dist/lib/deletion-auditor.js.map +1 -1
- package/dist/lib/deletion-prescan.d.ts +26 -0
- package/dist/lib/deletion-prescan.d.ts.map +1 -0
- package/dist/lib/deletion-prescan.js +56 -0
- package/dist/lib/deletion-prescan.js.map +1 -0
- package/dist/lib/env-sql-redactor.d.ts +1 -1
- package/dist/lib/env-sql-redactor.d.ts.map +1 -1
- package/dist/lib/env-sql-redactor.js +7 -72
- package/dist/lib/env-sql-redactor.js.map +1 -1
- package/dist/lib/lookup-sql.d.ts +109 -0
- package/dist/lib/lookup-sql.d.ts.map +1 -0
- package/dist/lib/lookup-sql.js +243 -0
- package/dist/lib/lookup-sql.js.map +1 -0
- package/dist/lib/natural-key-preflight.d.ts +86 -0
- package/dist/lib/natural-key-preflight.d.ts.map +1 -0
- package/dist/lib/natural-key-preflight.js +174 -0
- package/dist/lib/natural-key-preflight.js.map +1 -0
- package/dist/lib/record-dependency-analyzer.d.ts +14 -3
- package/dist/lib/record-dependency-analyzer.d.ts.map +1 -1
- package/dist/lib/record-dependency-analyzer.js +59 -72
- package/dist/lib/record-dependency-analyzer.js.map +1 -1
- package/dist/lib/schema-placeholders.d.ts +29 -0
- package/dist/lib/schema-placeholders.d.ts.map +1 -0
- package/dist/lib/schema-placeholders.js +72 -0
- package/dist/lib/schema-placeholders.js.map +1 -0
- package/dist/lib/sql-log-filters.d.ts +31 -0
- package/dist/lib/sql-log-filters.d.ts.map +1 -0
- package/dist/lib/sql-log-filters.js +41 -0
- package/dist/lib/sql-log-filters.js.map +1 -0
- package/dist/lib/sql-logger.d.ts +9 -1
- package/dist/lib/sql-logger.d.ts.map +1 -1
- package/dist/lib/sql-logger.js +12 -7
- package/dist/lib/sql-logger.js.map +1 -1
- package/dist/lib/sql-set-line.d.ts +26 -0
- package/dist/lib/sql-set-line.d.ts.map +1 -0
- package/dist/lib/sql-set-line.js +84 -0
- package/dist/lib/sql-set-line.js.map +1 -0
- package/dist/lib/sync-engine.d.ts +14 -2
- package/dist/lib/sync-engine.d.ts.map +1 -1
- package/dist/lib/sync-engine.js +68 -9
- package/dist/lib/sync-engine.js.map +1 -1
- package/dist/services/PullService.d.ts +2 -0
- package/dist/services/PullService.d.ts.map +1 -1
- package/dist/services/PullService.js +20 -2
- package/dist/services/PullService.js.map +1 -1
- package/dist/services/PushService.d.ts +42 -0
- package/dist/services/PushService.d.ts.map +1 -1
- package/dist/services/PushService.js +180 -58
- package/dist/services/PushService.js.map +1 -1
- package/dist/services/ValidationService.d.ts +31 -0
- package/dist/services/ValidationService.d.ts.map +1 -1
- package/dist/services/ValidationService.js +135 -9
- package/dist/services/ValidationService.js.map +1 -1
- package/dist/services/WatchService.d.ts +2 -0
- package/dist/services/WatchService.d.ts.map +1 -1
- package/dist/services/WatchService.js +19 -2
- package/dist/services/WatchService.js.map +1 -1
- package/package.json +15 -15
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-placeholders.js","sourceRoot":"","sources":["../../src/lib/schema-placeholders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,6BAA6B,EAA6B,MAAM,2CAA2C,CAAC;AAErH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,sGAAsG;AACtG,MAAM,CAAC,MAAM,0BAA0B,GAAyB,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,yBAAyB,EAAE,CAAC;AAE3H;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CAAC,UAAyC,EAAE,QAAqC;IACxH,MAAM,QAAQ,GAAG,UAAU,CAAC,UAAU,EAAE,UAAU,EAAE,kBAAkB,CAAC,CAAC;IACxE,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,MAAM,YAAY,GAAG,UAAU,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC1D,OAAO,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,GAAW,EAAE,KAAsC;IACzF,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC3C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,WAAW,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAClE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IACD,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,GAAG,CAAC;IACb,CAAC;IACD,MAAM,YAAY,GAAG,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1G,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,GAAG,6BAA6B,UAAU,YAAY,YAAY,EAAE,GAAG,CAAC,CAAC;IACpG,OAAO,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,IAAY,EAAE,MAAc,EAAE,KAAa,EAAE,EAAE,CAAC,GAAG,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;AAClI,CAAC;AAED,6FAA6F;AAC7F,SAAS,cAAc,CAAC,QAAqC;IAC3D,MAAM,SAAS,GAAY,QAAQ,EAAE,SAAS,CAAC;IAC/C,IAAI,SAAS,KAAK,IAAI,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,CAAC,CAAC,oBAAoB,IAAI,SAAS,CAAC,EAAE,CAAC;QAChG,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,SAAS,CAAC,kBAAkB,CAAC;AACtC,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IAChC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,KAAK,GAA2B,EAAE,CAAC;IACzC,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;QAC1B,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,QAAQ,IAAI,KAAK,IAAI,aAAa,IAAI,KAAK,EAAE,CAAC;YAC/F,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC;YACtC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,WAAW,KAAK,QAAQ,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACjH,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The statement filter push hands its SQL log. Besides the patterns a project sets
|
|
3
|
+
* in `.mj-sync.json`, push leaves out the saves of run and log records that the server writes
|
|
4
|
+
* while a push runs (prompt runs, agent runs and steps, action execution logs). Those rows are
|
|
5
|
+
* telemetry, not metadata, and a migration built from the log must not carry them.
|
|
6
|
+
* @module sql-log-filters
|
|
7
|
+
*/
|
|
8
|
+
import type { SyncConfig } from '../config.js';
|
|
9
|
+
/**
|
|
10
|
+
* Exclude patterns push always applies to its SQL log, unless
|
|
11
|
+
* `sqlLogging.excludeTransactionalDefaults` is false or `filterType` is 'include'. Each matches the
|
|
12
|
+
* entity's generated create or update procedure by whole name, so `spCreateAIAgentRun` does not
|
|
13
|
+
* also match `spCreateAIAgentRunMedia`.
|
|
14
|
+
*/
|
|
15
|
+
export declare const DEFAULT_TRANSACTIONAL_EXCLUDE_PATTERNS: readonly string[];
|
|
16
|
+
/** The statement filter for a push SQL log. */
|
|
17
|
+
export interface SqlLogFilter {
|
|
18
|
+
/** Patterns to pass to the SQL logger, or undefined when there are none. */
|
|
19
|
+
Patterns: string[] | undefined;
|
|
20
|
+
/** How the logger applies `Patterns`. */
|
|
21
|
+
FilterType: 'exclude' | 'include';
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Builds the SQL log filter from the root `sqlLogging` settings. In exclude mode (the default) the
|
|
25
|
+
* built-in transactional patterns are added after the project's own, unless
|
|
26
|
+
* `excludeTransactionalDefaults` is false. In include mode only the project's patterns apply: the
|
|
27
|
+
* log already holds nothing but what they match, and adding exclude patterns to an include list
|
|
28
|
+
* would invert their meaning.
|
|
29
|
+
*/
|
|
30
|
+
export declare function ResolveSqlLogFilter(sqlLogging: SyncConfig['sqlLogging']): SqlLogFilter;
|
|
31
|
+
//# sourceMappingURL=sql-log-filters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql-log-filters.d.ts","sourceRoot":"","sources":["../../src/lib/sql-log-filters.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C;;;;;GAKG;AACH,eAAO,MAAM,sCAAsC,EAAE,SAAS,MAAM,EAKnE,CAAC;AAEF,+CAA+C;AAC/C,MAAM,WAAW,YAAY;IAC3B,4EAA4E;IAC5E,QAAQ,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC/B,yCAAyC;IACzC,UAAU,EAAE,SAAS,GAAG,SAAS,CAAC;CACnC;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,UAAU,CAAC,YAAY,CAAC,GAAG,YAAY,CAatF"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The statement filter push hands its SQL log. Besides the patterns a project sets
|
|
3
|
+
* in `.mj-sync.json`, push leaves out the saves of run and log records that the server writes
|
|
4
|
+
* while a push runs (prompt runs, agent runs and steps, action execution logs). Those rows are
|
|
5
|
+
* telemetry, not metadata, and a migration built from the log must not carry them.
|
|
6
|
+
* @module sql-log-filters
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Exclude patterns push always applies to its SQL log, unless
|
|
10
|
+
* `sqlLogging.excludeTransactionalDefaults` is false or `filterType` is 'include'. Each matches the
|
|
11
|
+
* entity's generated create or update procedure by whole name, so `spCreateAIAgentRun` does not
|
|
12
|
+
* also match `spCreateAIAgentRunMedia`.
|
|
13
|
+
*/
|
|
14
|
+
export const DEFAULT_TRANSACTIONAL_EXCLUDE_PATTERNS = [
|
|
15
|
+
'/\\bsp(Create|Update)AIPromptRun\\b/i',
|
|
16
|
+
'/\\bsp(Create|Update)AIAgentRun\\b/i',
|
|
17
|
+
'/\\bsp(Create|Update)AIAgentRunStep\\b/i',
|
|
18
|
+
'/\\bsp(Create|Update)ActionExecutionLog\\b/i',
|
|
19
|
+
];
|
|
20
|
+
/**
|
|
21
|
+
* Builds the SQL log filter from the root `sqlLogging` settings. In exclude mode (the default) the
|
|
22
|
+
* built-in transactional patterns are added after the project's own, unless
|
|
23
|
+
* `excludeTransactionalDefaults` is false. In include mode only the project's patterns apply: the
|
|
24
|
+
* log already holds nothing but what they match, and adding exclude patterns to an include list
|
|
25
|
+
* would invert their meaning.
|
|
26
|
+
*/
|
|
27
|
+
export function ResolveSqlLogFilter(sqlLogging) {
|
|
28
|
+
const filterType = sqlLogging?.filterType ?? 'exclude';
|
|
29
|
+
const userPatterns = sqlLogging?.filterPatterns ?? [];
|
|
30
|
+
if (filterType === 'include' || sqlLogging?.excludeTransactionalDefaults === false) {
|
|
31
|
+
return { Patterns: userPatterns.length > 0 ? [...userPatterns] : undefined, FilterType: filterType };
|
|
32
|
+
}
|
|
33
|
+
const patterns = [...userPatterns];
|
|
34
|
+
for (const pattern of DEFAULT_TRANSACTIONAL_EXCLUDE_PATTERNS) {
|
|
35
|
+
if (!patterns.includes(pattern)) {
|
|
36
|
+
patterns.push(pattern);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return { Patterns: patterns, FilterType: filterType };
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=sql-log-filters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql-log-filters.js","sourceRoot":"","sources":["../../src/lib/sql-log-filters.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sCAAsC,GAAsB;IACvE,uCAAuC;IACvC,sCAAsC;IACtC,0CAA0C;IAC1C,8CAA8C;CAC/C,CAAC;AAUF;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAoC;IACtE,MAAM,UAAU,GAAG,UAAU,EAAE,UAAU,IAAI,SAAS,CAAC;IACvD,MAAM,YAAY,GAAG,UAAU,EAAE,cAAc,IAAI,EAAE,CAAC;IACtD,IAAI,UAAU,KAAK,SAAS,IAAI,UAAU,EAAE,4BAA4B,KAAK,KAAK,EAAE,CAAC;QACnF,OAAO,EAAE,QAAQ,EAAE,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC;IACvG,CAAC;IACD,MAAM,QAAQ,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC;IACnC,KAAK,MAAM,OAAO,IAAI,sCAAsC,EAAE,CAAC;QAC7D,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAChC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC;AACxD,CAAC"}
|
package/dist/lib/sql-logger.d.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* This module provides SQL logging functionality to capture all database operations
|
|
6
6
|
* during push commands. It supports both raw SQL logging and migration-formatted output.
|
|
7
7
|
*/
|
|
8
|
+
import type { SqlSchemaPlaceholder } from '@memberjunction/generic-database-provider';
|
|
8
9
|
import { SyncConfig } from '../config.js';
|
|
9
10
|
export interface SQLLoggerOptions {
|
|
10
11
|
enabled: boolean;
|
|
@@ -15,7 +16,14 @@ export declare class SQLLogger {
|
|
|
15
16
|
private options;
|
|
16
17
|
private statements;
|
|
17
18
|
private isInitialized;
|
|
18
|
-
|
|
19
|
+
private readonly schemaPlaceholders;
|
|
20
|
+
/**
|
|
21
|
+
* `schemaPlaceholders` are the rules a migration-format log applies (see `ResolveSchemaPlaceholders`);
|
|
22
|
+
* without them, `__mj` becomes `${flyway:defaultSchema}`. Kept for API callers: `mj sync push`
|
|
23
|
+
* passes no rules here and writes its log through the provider's `SqlLoggingSessionImpl`, so the
|
|
24
|
+
* tests of this parameter cover no production path.
|
|
25
|
+
*/
|
|
26
|
+
constructor(syncConfig: SyncConfig | null, schemaPlaceholders?: SqlSchemaPlaceholder[]);
|
|
19
27
|
get Enabled(): boolean;
|
|
20
28
|
/** @deprecated Use {@link Enabled}. */
|
|
21
29
|
get enabled(): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sql-logger.d.ts","sourceRoot":"","sources":["../../src/lib/sql-logger.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"sql-logger.d.ts","sourceRoot":"","sources":["../../src/lib/sql-logger.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACtF,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAGvC,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAyB;IAE5D;;;;;OAKG;gBACS,UAAU,EAAE,UAAU,GAAG,IAAI,EAAE,kBAAkB,CAAC,EAAE,oBAAoB,EAAE;IAStF,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,uCAAuC;IACvC,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAUjC,0CAA0C;IACpC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC;;OAEG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,IAAI;IAqB/C,4CAA4C;IAC5C,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,IAAI;IAI/C;;OAEG;IACH,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,IAAI;IAQ7D,8CAA8C;IAC9C,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,IAAI;IAI7D;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IA6C7C,wCAAwC;IAClC,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAI7C;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb,qCAAqC;IACrC,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAgBzB"}
|
package/dist/lib/sql-logger.js
CHANGED
|
@@ -7,8 +7,15 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import fs from 'fs-extra';
|
|
9
9
|
import path from 'path';
|
|
10
|
+
import { ApplySchemaPlaceholders, DEFAULT_SCHEMA_PLACEHOLDER } from './schema-placeholders.js';
|
|
10
11
|
export class SQLLogger {
|
|
11
|
-
|
|
12
|
+
/**
|
|
13
|
+
* `schemaPlaceholders` are the rules a migration-format log applies (see `ResolveSchemaPlaceholders`);
|
|
14
|
+
* without them, `__mj` becomes `${flyway:defaultSchema}`. Kept for API callers: `mj sync push`
|
|
15
|
+
* passes no rules here and writes its log through the provider's `SqlLoggingSessionImpl`, so the
|
|
16
|
+
* tests of this parameter cover no production path.
|
|
17
|
+
*/
|
|
18
|
+
constructor(syncConfig, schemaPlaceholders) {
|
|
12
19
|
this.statements = [];
|
|
13
20
|
this.isInitialized = false;
|
|
14
21
|
this.options = {
|
|
@@ -16,6 +23,7 @@ export class SQLLogger {
|
|
|
16
23
|
outputDirectory: syncConfig?.sqlLogging?.outputDirectory ?? './sql_logging',
|
|
17
24
|
formatAsMigration: syncConfig?.sqlLogging?.formatAsMigration ?? false
|
|
18
25
|
};
|
|
26
|
+
this.schemaPlaceholders = schemaPlaceholders && schemaPlaceholders.length > 0 ? schemaPlaceholders : [DEFAULT_SCHEMA_PLACEHOLDER];
|
|
19
27
|
}
|
|
20
28
|
get Enabled() {
|
|
21
29
|
return this.options.enabled;
|
|
@@ -97,13 +105,10 @@ export class SQLLogger {
|
|
|
97
105
|
`-- Generated at: ${new Date().toISOString()}`,
|
|
98
106
|
'-- Description: Metadata changes pushed via mj sync push command',
|
|
99
107
|
'',
|
|
100
|
-
'-- Note:
|
|
101
|
-
'-- Replace ${flyway:defaultSchema} with your target schema name',
|
|
108
|
+
'-- Note: schema names are written as Flyway placeholders',
|
|
102
109
|
'',
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
return stmt.replace(/(\[?)__mj(\]?)\./g, '${flyway:defaultSchema}.');
|
|
106
|
-
})
|
|
110
|
+
// One pass, brackets kept; `schema.` inside string data is rewritten too
|
|
111
|
+
...this.statements.map(stmt => ApplySchemaPlaceholders(stmt, this.schemaPlaceholders))
|
|
107
112
|
].join('\n');
|
|
108
113
|
}
|
|
109
114
|
else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sql-logger.js","sourceRoot":"","sources":["../../src/lib/sql-logger.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"sql-logger.js","sourceRoot":"","sources":["../../src/lib/sql-logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Shared helpers for the push SQL log rewrites that work on the
|
|
3
|
+
* `SET @<CodeName>_<12 hex>[_n] = <literal>` lines of a SQL Server save statement.
|
|
4
|
+
* Used by the env redactor (env-sql-redactor.ts) and the lookup rewriter (lookup-sql.ts).
|
|
5
|
+
* @module sql-set-line
|
|
6
|
+
*/
|
|
7
|
+
import type { BaseEntity } from '@memberjunction/core';
|
|
8
|
+
/** Registrations made without a save-call hash, which match any 12-hex suffix. */
|
|
9
|
+
export declare const ANY_SAVE_CALL_SUFFIX = "";
|
|
10
|
+
/** The lower-cased save-call hashes named in a statement, plus `ANY_SAVE_CALL_SUFFIX`. */
|
|
11
|
+
export declare function SaveCallHashesIn(sql: string): Set<string>;
|
|
12
|
+
/** `text` with every regular-expression metacharacter escaped. */
|
|
13
|
+
export declare function EscapeRegExp(text: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* One whole `SET @<codeName>_<suffix>[_n] = <literal>` line. Group 1 is the indent, group 2 the
|
|
16
|
+
* variable name. The suffix is the given hash, or any 12 hex when the hash is `ANY_SAVE_CALL_SUFFIX`.
|
|
17
|
+
* `flags` must include `g` and `m`.
|
|
18
|
+
*/
|
|
19
|
+
export declare function SetLinePattern(codeName: string, hash: string, literals: string[], flags?: string): RegExp;
|
|
20
|
+
/** The literal forms SQL Server writes for a value in a SET line. Empty when none can be matched. */
|
|
21
|
+
export declare function SqlLiteralsOf(value: unknown): string[];
|
|
22
|
+
/** The IS-A level of `entity` whose table holds the field: walks up while a parent holds it. */
|
|
23
|
+
export declare function OwningLevel(entity: BaseEntity, fieldName: string): BaseEntity;
|
|
24
|
+
/** `entity` and each IS-A parent above it, leaf first. */
|
|
25
|
+
export declare function IsALevels(entity: BaseEntity): BaseEntity[];
|
|
26
|
+
//# sourceMappingURL=sql-set-line.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql-set-line.d.ts","sourceRoot":"","sources":["../../src/lib/sql-set-line.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,kFAAkF;AAClF,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAKvC,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAMzD;AAED,kEAAkE;AAClE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,KAAK,SAAO,GAAG,MAAM,CAIvG;AAED,qGAAqG;AACrG,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAiBtD;AAED,gGAAgG;AAChG,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU,CAM7E;AAED,0DAA0D;AAC1D,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,EAAE,CAQ1D"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/** Registrations made without a save-call hash, which match any 12-hex suffix. */
|
|
2
|
+
export const ANY_SAVE_CALL_SUFFIX = '';
|
|
3
|
+
/** The 12-hex save-call hash of a variable suffix in a statement (`_<hash>` or `_<hash>_<n>`). */
|
|
4
|
+
const SAVE_CALL_SUFFIX = /_([0-9a-fA-F]{12})(?![0-9a-fA-F])/g;
|
|
5
|
+
/** The lower-cased save-call hashes named in a statement, plus `ANY_SAVE_CALL_SUFFIX`. */
|
|
6
|
+
export function SaveCallHashesIn(sql) {
|
|
7
|
+
const hashes = new Set([ANY_SAVE_CALL_SUFFIX]);
|
|
8
|
+
for (const match of sql.matchAll(SAVE_CALL_SUFFIX)) {
|
|
9
|
+
hashes.add(match[1].toLowerCase());
|
|
10
|
+
}
|
|
11
|
+
return hashes;
|
|
12
|
+
}
|
|
13
|
+
/** `text` with every regular-expression metacharacter escaped. */
|
|
14
|
+
export function EscapeRegExp(text) {
|
|
15
|
+
return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* One whole `SET @<codeName>_<suffix>[_n] = <literal>` line. Group 1 is the indent, group 2 the
|
|
19
|
+
* variable name. The suffix is the given hash, or any 12 hex when the hash is `ANY_SAVE_CALL_SUFFIX`.
|
|
20
|
+
* `flags` must include `g` and `m`.
|
|
21
|
+
*/
|
|
22
|
+
export function SetLinePattern(codeName, hash, literals, flags = 'gm') {
|
|
23
|
+
const alternatives = literals.map(EscapeRegExp).join('|');
|
|
24
|
+
const suffix = hash === ANY_SAVE_CALL_SUFFIX ? '[0-9a-fA-F]{12}' : EscapeRegExp(hash);
|
|
25
|
+
return new RegExp(`^([ \\t]*)SET (@${EscapeRegExp(codeName)}_${suffix}(?:_\\d+)?) = (?:${alternatives})[ \\t]*$`, flags);
|
|
26
|
+
}
|
|
27
|
+
/** The literal forms SQL Server writes for a value in a SET line. Empty when none can be matched. */
|
|
28
|
+
export function SqlLiteralsOf(value) {
|
|
29
|
+
if (value instanceof Date) {
|
|
30
|
+
return Number.isNaN(value.getTime()) ? [] : [`'${value.toISOString()}'`];
|
|
31
|
+
}
|
|
32
|
+
if (typeof value === 'boolean') {
|
|
33
|
+
return [value ? '1' : '0'];
|
|
34
|
+
}
|
|
35
|
+
if (typeof value === 'number' || typeof value === 'bigint') {
|
|
36
|
+
return [String(value)];
|
|
37
|
+
}
|
|
38
|
+
if (value !== null && typeof value === 'object') {
|
|
39
|
+
return quotedLiterals(JSON.stringify(value));
|
|
40
|
+
}
|
|
41
|
+
if (typeof value !== 'string') {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
return [...quotedLiterals(value), ...stringValueLiterals(value)];
|
|
45
|
+
}
|
|
46
|
+
/** The IS-A level of `entity` whose table holds the field: walks up while a parent holds it. */
|
|
47
|
+
export function OwningLevel(entity, fieldName) {
|
|
48
|
+
let level = entity;
|
|
49
|
+
while (level.ISAParent && level.EntityInfo.ParentEntityFieldNames?.has(fieldName)) {
|
|
50
|
+
level = level.ISAParent;
|
|
51
|
+
}
|
|
52
|
+
return level;
|
|
53
|
+
}
|
|
54
|
+
/** `entity` and each IS-A parent above it, leaf first. */
|
|
55
|
+
export function IsALevels(entity) {
|
|
56
|
+
const levels = [];
|
|
57
|
+
let level = entity;
|
|
58
|
+
while (level) {
|
|
59
|
+
levels.push(level);
|
|
60
|
+
level = level.ISAParent;
|
|
61
|
+
}
|
|
62
|
+
return levels;
|
|
63
|
+
}
|
|
64
|
+
/** The number or bit literal forms of a string value that holds a number or a boolean. */
|
|
65
|
+
function stringValueLiterals(value) {
|
|
66
|
+
const trimmed = value.trim();
|
|
67
|
+
const literals = [];
|
|
68
|
+
if (/^-?\d+(\.\d+)?$/.test(trimmed)) {
|
|
69
|
+
literals.push(trimmed);
|
|
70
|
+
}
|
|
71
|
+
const lower = trimmed.toLowerCase();
|
|
72
|
+
if (lower === 'true') {
|
|
73
|
+
literals.push('1');
|
|
74
|
+
}
|
|
75
|
+
else if (lower === 'false') {
|
|
76
|
+
literals.push('0');
|
|
77
|
+
}
|
|
78
|
+
return literals;
|
|
79
|
+
}
|
|
80
|
+
function quotedLiterals(text) {
|
|
81
|
+
const escaped = text.replace(/'/g, "''");
|
|
82
|
+
return [`N'${escaped}'`, `'${escaped}'`];
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=sql-set-line.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql-set-line.js","sourceRoot":"","sources":["../../src/lib/sql-set-line.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,6 +11,7 @@ import { EntityInfo, IMetadataProvider, BaseEntity, UserInfo } from '@memberjunc
|
|
|
11
11
|
import { EntityConfig } from '../config.js';
|
|
12
12
|
import { BatchContextIndex, BatchContextStub } from './batch-context-index.js';
|
|
13
13
|
import { SyncMetadataEngine } from './sync-metadata-engine.js';
|
|
14
|
+
import type { LookupSqlSource } from './lookup-sql.js';
|
|
14
15
|
/** Accepted types for the batchContext parameter (indexed or plain Map). */
|
|
15
16
|
export type BatchContext = BatchContextIndex | Map<string, BaseEntity | BatchContextStub>;
|
|
16
17
|
/**
|
|
@@ -69,6 +70,8 @@ export interface SyncResolutionCollector {
|
|
|
69
70
|
fieldPrefix: string;
|
|
70
71
|
/** Field name → names of the variables whose values went into that field. Filled only when present. */
|
|
71
72
|
EnvFields?: Map<string, Set<string>>;
|
|
73
|
+
/** Field name → the `@lookup` its value came from, for the SQL log (#5626). Filled only when present. */
|
|
74
|
+
LookupSources?: Map<string, LookupSqlSource>;
|
|
72
75
|
}
|
|
73
76
|
/**
|
|
74
77
|
* Represents the structure of a metadata record with optional sync tracking
|
|
@@ -132,6 +135,8 @@ export declare class SyncEngine {
|
|
|
132
135
|
readonly ResolvedEnvVariables: Set<string>;
|
|
133
136
|
/** Runs right before a `@lookup:…?create` lookup saves the record it creates, with the env-sourced fields of that record. */
|
|
134
137
|
BeforeLookupCreateSave: ((entity: BaseEntity, envFields: ReadonlyMap<string, ReadonlySet<string>>) => void) | null;
|
|
138
|
+
/** Runs right before a `@lookup:…?create` lookup saves the record it creates, with the lookup that creates it. */
|
|
139
|
+
BeforeLookupCreateSaveSource: ((entity: BaseEntity, lookup: LookupSqlSource) => void) | null;
|
|
135
140
|
SetMetadataEngine(engine: SyncMetadataEngine): void;
|
|
136
141
|
/** @deprecated Use {@link SetMetadataEngine}. */
|
|
137
142
|
setMetadataEngine(engine: SyncMetadataEngine): void;
|
|
@@ -264,7 +269,7 @@ export declare class SyncEngine {
|
|
|
264
269
|
ResolveLookup(entityName: string, lookupFields: Array<{
|
|
265
270
|
fieldName: string;
|
|
266
271
|
fieldValue: string;
|
|
267
|
-
}>, autoCreate?: boolean, createFields?: Record<string, any>, batchContext?: BatchContext, allowDefer?: boolean, originalValue?: string, recordProvider?: IMetadataProvider, envFields?: ReadonlyMap<string, ReadonlySet<string
|
|
272
|
+
}>, autoCreate?: boolean, createFields?: Record<string, any>, batchContext?: BatchContext, allowDefer?: boolean, originalValue?: string, recordProvider?: IMetadataProvider, envFields?: ReadonlyMap<string, ReadonlySet<string>>, lookupSource?: LookupSqlSource): Promise<string>;
|
|
268
273
|
/** `Field='value' AND …` for messages; env-sourced criteria print as `Field=<from @env:VAR>`. */
|
|
269
274
|
private describeLookupFilter;
|
|
270
275
|
/**
|
|
@@ -277,7 +282,7 @@ export declare class SyncEngine {
|
|
|
277
282
|
resolveLookup(entityName: string, lookupFields: Array<{
|
|
278
283
|
fieldName: string;
|
|
279
284
|
fieldValue: string;
|
|
280
|
-
}>, autoCreate?: boolean, createFields?: Record<string, any>, batchContext?: BatchContext, allowDefer?: boolean, originalValue?: string, recordProvider?: IMetadataProvider, envFields?: ReadonlyMap<string, ReadonlySet<string
|
|
285
|
+
}>, autoCreate?: boolean, createFields?: Record<string, any>, batchContext?: BatchContext, allowDefer?: boolean, originalValue?: string, recordProvider?: IMetadataProvider, envFields?: ReadonlyMap<string, ReadonlySet<string>>, lookupSource?: LookupSqlSource): Promise<string>;
|
|
281
286
|
/**
|
|
282
287
|
* Build cascading defaults for a file path and process field values
|
|
283
288
|
*
|
|
@@ -464,6 +469,13 @@ export declare class SyncEngine {
|
|
|
464
469
|
* `cacheResult` controls whether a hit is added to the preload cache.
|
|
465
470
|
*/
|
|
466
471
|
private loadFromDatabase;
|
|
472
|
+
/**
|
|
473
|
+
* Loads a record by primary key straight from the database, never from the preload cache, on
|
|
474
|
+
* `recordProvider` when one is passed (so the read joins that provider's transaction). Returns
|
|
475
|
+
* `null` when no row exists. A hit is not cached. Used where the cache can be stale inside the
|
|
476
|
+
* push transaction, such as a row an earlier delete's cascade removed (#4935).
|
|
477
|
+
*/
|
|
478
|
+
LoadEntityFromDatabase(entityName: string, primaryKey: Record<string, unknown>, recordProvider?: IMetadataProvider): Promise<BaseEntity | null>;
|
|
467
479
|
/** @deprecated Use {@link LoadEntity}. */
|
|
468
480
|
loadEntity(entityName: string, primaryKey: Record<string, any>, recordProvider?: IMetadataProvider): Promise<BaseEntity | null>;
|
|
469
481
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-engine.d.ts","sourceRoot":"","sources":["../../src/lib/sync-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,EAAE,UAAU,EAAuB,iBAAiB,EAAuC,UAAU,EAAgB,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGnK,OAAO,EAAE,YAAY,EAAgB,MAAM,WAAW,CAAC;AAGvD,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"sync-engine.d.ts","sourceRoot":"","sources":["../../src/lib/sync-engine.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/sync-engine.js
CHANGED
|
@@ -100,6 +100,8 @@ export class SyncEngine {
|
|
|
100
100
|
this.ResolvedEnvVariables = new Set();
|
|
101
101
|
/** Runs right before a `@lookup:…?create` lookup saves the record it creates, with the env-sourced fields of that record. */
|
|
102
102
|
this.BeforeLookupCreateSave = null;
|
|
103
|
+
/** Runs right before a `@lookup:…?create` lookup saves the record it creates, with the lookup that creates it. */
|
|
104
|
+
this.BeforeLookupCreateSaveSource = null;
|
|
103
105
|
/**
|
|
104
106
|
* Where non-fatal warnings raised inside the engine go (the BaseEntity-fallback notice on the
|
|
105
107
|
* lookup auto-create path, for one). PushService points this at its own warnings list so the
|
|
@@ -330,6 +332,9 @@ export class SyncEngine {
|
|
|
330
332
|
const lookupPairs = lookupPart.split('&');
|
|
331
333
|
// Collector for nested resolutions within this lookup
|
|
332
334
|
const nestedResolutions = [];
|
|
335
|
+
// What the lookup matched on, so the SQL log can match on it too
|
|
336
|
+
const sqlCriteria = [];
|
|
337
|
+
let criteriaFromEnv = false;
|
|
333
338
|
// Criteria and create fields whose values came from @env:, for the lookup messages
|
|
334
339
|
const lookupEnvFields = new Map();
|
|
335
340
|
for (const pair of lookupPairs) {
|
|
@@ -341,10 +346,13 @@ export class SyncEngine {
|
|
|
341
346
|
const rawFieldValue = fieldValue.trim();
|
|
342
347
|
// Recursively process the field value to resolve any nested @ commands
|
|
343
348
|
// Create a temporary collector to capture nested resolutions and env-sourced criteria
|
|
344
|
-
const nestedCollector = { notes: [], fieldPrefix: '', EnvFields: new Map() };
|
|
349
|
+
const nestedCollector = { notes: [], fieldPrefix: '', EnvFields: new Map(), LookupSources: new Map() };
|
|
345
350
|
const processedValue = await this.ProcessFieldValue(rawFieldValue, baseDir, parentRecord, rootRecord, depth + 1, batchContext, nestedCollector, lookupFieldName, // Pass field name for tracking
|
|
346
351
|
recordProvider);
|
|
347
352
|
const criteriaVariables = this.addLookupEnvField(lookupEnvFields, lookupFieldName.trim(), nestedCollector);
|
|
353
|
+
const nestedSource = nestedCollector.LookupSources?.get(lookupFieldName);
|
|
354
|
+
criteriaFromEnv = criteriaFromEnv || Boolean(criteriaVariables) || nestedSource?.EnvSourced === true;
|
|
355
|
+
sqlCriteria.push({ FieldName: lookupFieldName.trim(), Value: nestedSource ?? String(processedValue) });
|
|
348
356
|
// If the raw value was a lookup expression that got resolved, track it as nested
|
|
349
357
|
if (rawFieldValue.startsWith(METADATA_KEYWORDS.LOOKUP) && rawFieldValue !== processedValue) {
|
|
350
358
|
nestedResolutions.push({
|
|
@@ -368,7 +376,11 @@ export class SyncEngine {
|
|
|
368
376
|
this.addLookupEnvField(lookupEnvFields, createField.Name, createCollector);
|
|
369
377
|
}
|
|
370
378
|
}
|
|
371
|
-
const
|
|
379
|
+
const lookupSource = { Expression: value, EntityName: entityName, Criteria: sqlCriteria, EnvSourced: criteriaFromEnv };
|
|
380
|
+
const resolvedValue = await this.ResolveLookup(entityName, lookupFields, hasCreate, createFields, batchContext, allowDefer, value, recordProvider, lookupEnvFields, lookupSource);
|
|
381
|
+
if (fieldName) {
|
|
382
|
+
resolutionCollector?.LookupSources?.set(fieldName, lookupSource);
|
|
383
|
+
}
|
|
372
384
|
const sourceVariables = this.recordCopiedEnvValue(resolvedValue, resolutionCollector, fieldName);
|
|
373
385
|
// Track the resolution if collector is provided
|
|
374
386
|
if (resolutionCollector && fieldName) {
|
|
@@ -465,7 +477,7 @@ export class SyncEngine {
|
|
|
465
477
|
});
|
|
466
478
|
return `${encodeURIComponent(entityName.toLowerCase())}|${parts.join('&')}`;
|
|
467
479
|
}
|
|
468
|
-
async ResolveLookup(entityName, lookupFields, autoCreate = false, createFields = {}, batchContext, allowDefer = false, originalValue, recordProvider, envFields) {
|
|
480
|
+
async ResolveLookup(entityName, lookupFields, autoCreate = false, createFields = {}, batchContext, allowDefer = false, originalValue, recordProvider, envFields, lookupSource) {
|
|
469
481
|
// Criteria and create fields whose values came from @env: print as labels
|
|
470
482
|
const envMask = new EnvDisplayMask(envFields);
|
|
471
483
|
const lookupCacheKey = this.buildLookupCacheKey(entityName, lookupFields);
|
|
@@ -584,7 +596,14 @@ export class SyncEngine {
|
|
|
584
596
|
filterParts.push(`${dialect.LowerCase(fieldName)} = ${dialect.LowerCase(`'${escaped}'`)}`);
|
|
585
597
|
}
|
|
586
598
|
else {
|
|
587
|
-
|
|
599
|
+
// An unquoted value is spliced into the SQL verbatim, so it must be a pure
|
|
600
|
+
// numeric/boolean token — anything else (e.g. `1 OR 1=1`) would rewrite the lookup.
|
|
601
|
+
const trimmedLookupVal = fieldValue.trim();
|
|
602
|
+
if (!quotes && !/^-?\d+(\.\d+)?$/.test(trimmedLookupVal) && !/^(true|false)$/i.test(trimmedLookupVal)) {
|
|
603
|
+
throw new Error(`Lookup value '${fieldValue}' for non-string field '${fieldName}' on entity '${entityName}' must be a numeric or boolean literal`);
|
|
604
|
+
}
|
|
605
|
+
const formattedVal = quotes ? fieldValue.replace(/'/g, "''") : trimmedLookupVal;
|
|
606
|
+
filterParts.push(`${fieldName} = ${quotes}${formattedVal}${quotes}`);
|
|
588
607
|
}
|
|
589
608
|
}
|
|
590
609
|
}
|
|
@@ -593,6 +612,7 @@ export class SyncEngine {
|
|
|
593
612
|
EntityName: entityName,
|
|
594
613
|
ExtraFilter: extraFilter,
|
|
595
614
|
MaxRows: 1,
|
|
615
|
+
SkipTotalRowCount: true,
|
|
596
616
|
// BypassCache: lookups during a push must always go to the DB.
|
|
597
617
|
// The provider's RunView cache can return stale or filtered results
|
|
598
618
|
// (especially across the LOWER()-based case-insensitive lookups
|
|
@@ -652,6 +672,9 @@ export class SyncEngine {
|
|
|
652
672
|
if (envFields) {
|
|
653
673
|
this.BeforeLookupCreateSave?.(newEntity, envFields);
|
|
654
674
|
}
|
|
675
|
+
if (lookupSource) {
|
|
676
|
+
this.BeforeLookupCreateSaveSource?.(newEntity, lookupSource);
|
|
677
|
+
}
|
|
655
678
|
const saved = await newEntity.Save();
|
|
656
679
|
if (!saved) {
|
|
657
680
|
const message = newEntity.LatestResult?.Message;
|
|
@@ -703,8 +726,8 @@ export class SyncEngine {
|
|
|
703
726
|
return merged;
|
|
704
727
|
}
|
|
705
728
|
/** @deprecated Use {@link ResolveLookup}. */
|
|
706
|
-
async resolveLookup(entityName, lookupFields, autoCreate = false, createFields = {}, batchContext, allowDefer = false, originalValue, recordProvider, envFields) {
|
|
707
|
-
return this.ResolveLookup(entityName, lookupFields, autoCreate, createFields, batchContext, allowDefer, originalValue, recordProvider, envFields);
|
|
729
|
+
async resolveLookup(entityName, lookupFields, autoCreate = false, createFields = {}, batchContext, allowDefer = false, originalValue, recordProvider, envFields, lookupSource) {
|
|
730
|
+
return this.ResolveLookup(entityName, lookupFields, autoCreate, createFields, batchContext, allowDefer, originalValue, recordProvider, envFields, lookupSource);
|
|
708
731
|
}
|
|
709
732
|
/**
|
|
710
733
|
* Build cascading defaults for a file path and process field values
|
|
@@ -1177,16 +1200,39 @@ export class SyncEngine {
|
|
|
1177
1200
|
if (value === undefined || value === null) {
|
|
1178
1201
|
throw new Error(`Missing primary key value for ${pk.Name} in entity ${entityName}`);
|
|
1179
1202
|
}
|
|
1203
|
+
// Reject non-primitive or non-finite values from untrusted JSON metadata (e.g. arrays/objects/NaN)
|
|
1204
|
+
// before building either quoted or unquoted SQL primary-key predicates.
|
|
1205
|
+
if ((typeof value !== 'string' && typeof value !== 'number' && typeof value !== 'boolean') ||
|
|
1206
|
+
(typeof value === 'number' && !Number.isFinite(value))) {
|
|
1207
|
+
throw new Error(`Primary key value for '${pk.Name}' on entity '${entityName}' must be a string, finite number, or boolean primitive`);
|
|
1208
|
+
}
|
|
1180
1209
|
// Check if field needs quotes
|
|
1181
1210
|
const field = entityInfo.Fields.find(f => f.Name === pk.Name);
|
|
1182
1211
|
const quotes = field?.NeedsQuotes ? "'" : '';
|
|
1183
|
-
|
|
1184
|
-
|
|
1212
|
+
if (!quotes) {
|
|
1213
|
+
// An unquoted value is spliced into the SQL verbatim, so string forms must also be pure
|
|
1214
|
+
// numeric/boolean tokens — anything else would splice SQL into the primary-key filter.
|
|
1215
|
+
if (typeof value === 'string') {
|
|
1216
|
+
const trimmedPk = value.trim();
|
|
1217
|
+
if (!/^-?\d+(\.\d+)?$/.test(trimmedPk) && !/^(true|false)$/i.test(trimmedPk)) {
|
|
1218
|
+
throw new Error(`Primary key value '${value}' for non-string field '${pk.Name}' on entity '${entityName}' must be a numeric or boolean literal`);
|
|
1219
|
+
}
|
|
1220
|
+
filters.push(`${pk.Name} = ${trimmedPk}`);
|
|
1221
|
+
}
|
|
1222
|
+
else {
|
|
1223
|
+
filters.push(`${pk.Name} = ${String(value)}`);
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
else {
|
|
1227
|
+
const escapedValue = String(value).replace(/'/g, "''");
|
|
1228
|
+
filters.push(`${pk.Name} = '${escapedValue}'`);
|
|
1229
|
+
}
|
|
1185
1230
|
}
|
|
1186
1231
|
const result = await rv.RunView({
|
|
1187
1232
|
EntityName: entityName,
|
|
1188
1233
|
ExtraFilter: filters.join(' AND '),
|
|
1189
|
-
MaxRows: 1
|
|
1234
|
+
MaxRows: 1,
|
|
1235
|
+
SkipTotalRowCount: true
|
|
1190
1236
|
}, this.contextUser);
|
|
1191
1237
|
// If no record found, return null without attempting to load
|
|
1192
1238
|
if (!result.Success || result.Results.length === 0) {
|
|
@@ -1203,6 +1249,19 @@ export class SyncEngine {
|
|
|
1203
1249
|
}
|
|
1204
1250
|
return loadedEntity;
|
|
1205
1251
|
}
|
|
1252
|
+
/**
|
|
1253
|
+
* Loads a record by primary key straight from the database, never from the preload cache, on
|
|
1254
|
+
* `recordProvider` when one is passed (so the read joins that provider's transaction). Returns
|
|
1255
|
+
* `null` when no row exists. A hit is not cached. Used where the cache can be stale inside the
|
|
1256
|
+
* push transaction, such as a row an earlier delete's cascade removed (#4935).
|
|
1257
|
+
*/
|
|
1258
|
+
async LoadEntityFromDatabase(entityName, primaryKey, recordProvider) {
|
|
1259
|
+
const entityInfo = this.GetEntityInfo(entityName);
|
|
1260
|
+
if (!entityInfo) {
|
|
1261
|
+
throw new Error(`Entity not found: ${entityName}`);
|
|
1262
|
+
}
|
|
1263
|
+
return this.loadFromDatabase(entityName, entityInfo, primaryKey, recordProvider, false);
|
|
1264
|
+
}
|
|
1206
1265
|
/** @deprecated Use {@link LoadEntity}. */
|
|
1207
1266
|
async loadEntity(entityName, primaryKey, recordProvider) {
|
|
1208
1267
|
return this.LoadEntity(entityName, primaryKey, recordProvider);
|