@memberjunction/metadata-sync 2.54.0 → 2.56.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/README.md +92 -51
- package/dist/index.d.ts +21 -1
- package/dist/index.js +41 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/file-backup-manager.js +2 -2
- package/dist/lib/file-backup-manager.js.map +1 -1
- package/dist/lib/sql-logger.d.ts +44 -0
- package/dist/lib/sql-logger.js +140 -0
- package/dist/lib/sql-logger.js.map +1 -0
- package/dist/lib/sync-engine.js +2 -2
- package/dist/lib/sync-engine.js.map +1 -1
- package/dist/lib/transaction-manager.d.ts +36 -0
- package/dist/lib/transaction-manager.js +117 -0
- package/dist/lib/transaction-manager.js.map +1 -0
- package/dist/services/FileResetService.d.ts +30 -0
- package/dist/services/FileResetService.js +182 -0
- package/dist/services/FileResetService.js.map +1 -0
- package/dist/services/InitService.d.ts +17 -0
- package/dist/services/InitService.js +118 -0
- package/dist/services/InitService.js.map +1 -0
- package/dist/services/PullService.d.ts +45 -0
- package/dist/services/PullService.js +564 -0
- package/dist/services/PullService.js.map +1 -0
- package/dist/services/PushService.d.ts +45 -0
- package/dist/services/PushService.js +394 -0
- package/dist/services/PushService.js.map +1 -0
- package/dist/services/StatusService.d.ts +32 -0
- package/dist/services/StatusService.js +138 -0
- package/dist/services/StatusService.js.map +1 -0
- package/dist/services/WatchService.d.ts +32 -0
- package/dist/services/WatchService.js +242 -0
- package/dist/services/WatchService.js.map +1 -0
- package/dist/services/index.d.ts +16 -0
- package/dist/services/index.js +28 -0
- package/dist/services/index.js.map +1 -0
- package/package.json +14 -45
- package/bin/debug.js +0 -7
- package/bin/run +0 -17
- package/bin/run.js +0 -6
- package/dist/commands/file-reset/index.d.ts +0 -15
- package/dist/commands/file-reset/index.js +0 -221
- package/dist/commands/file-reset/index.js.map +0 -1
- package/dist/commands/init/index.d.ts +0 -7
- package/dist/commands/init/index.js +0 -155
- package/dist/commands/init/index.js.map +0 -1
- package/dist/commands/pull/index.d.ts +0 -246
- package/dist/commands/pull/index.js +0 -1448
- package/dist/commands/pull/index.js.map +0 -1
- package/dist/commands/push/index.d.ts +0 -41
- package/dist/commands/push/index.js +0 -1131
- package/dist/commands/push/index.js.map +0 -1
- package/dist/commands/status/index.d.ts +0 -10
- package/dist/commands/status/index.js +0 -199
- package/dist/commands/status/index.js.map +0 -1
- package/dist/commands/validate/index.d.ts +0 -15
- package/dist/commands/validate/index.js +0 -149
- package/dist/commands/validate/index.js.map +0 -1
- package/dist/commands/watch/index.d.ts +0 -15
- package/dist/commands/watch/index.js +0 -300
- package/dist/commands/watch/index.js.map +0 -1
- package/dist/hooks/init.d.ts +0 -3
- package/dist/hooks/init.js +0 -59
- package/dist/hooks/init.js.map +0 -1
- package/oclif.manifest.json +0 -376
package/README.md
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
# MemberJunction Metadata Sync
|
|
2
2
|
|
|
3
|
-
A
|
|
3
|
+
A library for synchronizing MemberJunction database metadata with local file system representations. This library is integrated into the MemberJunction CLI (`mj`) and is accessed through `mj sync` commands. It enables developers and non-technical users to manage MJ metadata using their preferred editors and version control systems while maintaining the database as the source of truth.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
MetadataSync is included with the MemberJunction CLI. Install the CLI globally:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g @memberjunction/cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Then use the sync commands:
|
|
14
|
+
```bash
|
|
15
|
+
mj sync --help
|
|
16
|
+
```
|
|
4
17
|
|
|
5
18
|
## Purpose
|
|
6
19
|
|
|
@@ -401,10 +414,10 @@ echo '{
|
|
|
401
414
|
#### Step 4: Test and Validate
|
|
402
415
|
```bash
|
|
403
416
|
# Dry run to check for errors
|
|
404
|
-
mj
|
|
417
|
+
mj sync push --dir="templates" --dry-run
|
|
405
418
|
|
|
406
419
|
# If successful, do actual push
|
|
407
|
-
mj
|
|
420
|
+
mj sync push --dir="templates"
|
|
408
421
|
```
|
|
409
422
|
|
|
410
423
|
### AI/LLM Guidelines
|
|
@@ -896,60 +909,65 @@ Templates can reference other templates:
|
|
|
896
909
|
|
|
897
910
|
## CLI Commands
|
|
898
911
|
|
|
912
|
+
All MetadataSync functionality is accessed through the MemberJunction CLI (`mj`) under the `sync` namespace. The commands previously available through `mj-sync` are now integrated as `mj sync` commands:
|
|
913
|
+
|
|
899
914
|
```bash
|
|
900
915
|
# Validate all metadata files
|
|
901
|
-
mj
|
|
916
|
+
mj sync validate
|
|
902
917
|
|
|
903
918
|
# Validate a specific directory
|
|
904
|
-
mj
|
|
919
|
+
mj sync validate --dir="./metadata"
|
|
905
920
|
|
|
906
921
|
# Validate with detailed output
|
|
907
|
-
mj
|
|
922
|
+
mj sync validate --verbose
|
|
908
923
|
|
|
909
924
|
# Validate with JSON output for CI/CD
|
|
910
|
-
mj
|
|
925
|
+
mj sync validate --format=json
|
|
911
926
|
|
|
912
927
|
# Save validation report to markdown file
|
|
913
|
-
mj
|
|
928
|
+
mj sync validate --save-report
|
|
914
929
|
|
|
915
930
|
# Initialize a directory for metadata sync
|
|
916
|
-
mj
|
|
931
|
+
mj sync init
|
|
917
932
|
|
|
918
933
|
# Pull all AI Prompts from database to ai-prompts directory
|
|
919
|
-
mj
|
|
934
|
+
mj sync pull --entity="AI Prompts"
|
|
920
935
|
|
|
921
936
|
# Pull specific records by filter
|
|
922
|
-
mj
|
|
937
|
+
mj sync pull --entity="AI Prompts" --filter="CategoryID='customer-service-id'"
|
|
923
938
|
|
|
924
939
|
# Pull multiple records into a single file (NEW)
|
|
925
|
-
mj
|
|
926
|
-
mj
|
|
940
|
+
mj sync pull --entity="AI Prompts" --multi-file="all-prompts"
|
|
941
|
+
mj sync pull --entity="AI Prompts" --filter="Status='Active'" --multi-file="active-prompts.json"
|
|
927
942
|
|
|
928
943
|
# Push all changes from current directory and subdirectories
|
|
929
|
-
mj
|
|
944
|
+
mj sync push
|
|
930
945
|
|
|
931
946
|
# Push only specific entity directory
|
|
932
|
-
mj
|
|
947
|
+
mj sync push --dir="ai-prompts"
|
|
933
948
|
|
|
934
949
|
# Push with verbose output (NEW)
|
|
935
|
-
mj
|
|
936
|
-
mj
|
|
950
|
+
mj sync push -v
|
|
951
|
+
mj sync push --verbose
|
|
937
952
|
|
|
938
953
|
# Dry run to see what would change
|
|
939
|
-
mj
|
|
954
|
+
mj sync push --dry-run
|
|
940
955
|
|
|
941
956
|
# Show status of local vs database
|
|
942
|
-
mj
|
|
957
|
+
mj sync status
|
|
943
958
|
|
|
944
959
|
# Watch for changes and auto-push
|
|
945
|
-
mj
|
|
960
|
+
mj sync watch
|
|
946
961
|
|
|
947
962
|
# CI/CD mode (push with no prompts, fails on validation errors)
|
|
948
|
-
mj
|
|
963
|
+
mj sync push --ci
|
|
949
964
|
|
|
950
965
|
# Push/Pull without validation
|
|
951
|
-
mj
|
|
952
|
-
mj
|
|
966
|
+
mj sync push --no-validate
|
|
967
|
+
mj sync pull --entity="AI Prompts" --no-validate
|
|
968
|
+
|
|
969
|
+
# Reset file checksums after manual edits
|
|
970
|
+
mj sync file-reset
|
|
953
971
|
```
|
|
954
972
|
|
|
955
973
|
## Configuration
|
|
@@ -1103,7 +1121,7 @@ Migration files include:
|
|
|
1103
1121
|
|
|
1104
1122
|
2. **Run push command** as normal:
|
|
1105
1123
|
```bash
|
|
1106
|
-
mj
|
|
1124
|
+
mj sync push
|
|
1107
1125
|
```
|
|
1108
1126
|
|
|
1109
1127
|
3. **Review generated SQL** in the output directory:
|
|
@@ -1637,12 +1655,13 @@ Processing AI Prompts in demo/ai-prompts
|
|
|
1637
1655
|
## Use Cases
|
|
1638
1656
|
|
|
1639
1657
|
### Developer Workflow
|
|
1640
|
-
1.
|
|
1641
|
-
2.
|
|
1642
|
-
3.
|
|
1643
|
-
4.
|
|
1644
|
-
5.
|
|
1645
|
-
6.
|
|
1658
|
+
1. Install the MJ CLI: `npm install -g @memberjunction/cli`
|
|
1659
|
+
2. `mj sync pull --entity="AI Prompts"` to get latest prompts with their models
|
|
1660
|
+
3. Edit prompts and adjust model configurations in VS Code
|
|
1661
|
+
4. Test locally with `mj sync push --dry-run`
|
|
1662
|
+
5. Commit changes to Git
|
|
1663
|
+
6. PR review with diff visualization
|
|
1664
|
+
7. CI/CD runs `mj sync push --ci` on merge
|
|
1646
1665
|
|
|
1647
1666
|
### Content Team Workflow
|
|
1648
1667
|
1. Pull prompts to local directory
|
|
@@ -1655,8 +1674,8 @@ Processing AI Prompts in demo/ai-prompts
|
|
|
1655
1674
|
```yaml
|
|
1656
1675
|
- name: Push Metadata to Production
|
|
1657
1676
|
run: |
|
|
1658
|
-
npm install -g @memberjunction/
|
|
1659
|
-
mj
|
|
1677
|
+
npm install -g @memberjunction/cli
|
|
1678
|
+
mj sync push --ci --entity="AI Prompts"
|
|
1660
1679
|
```
|
|
1661
1680
|
|
|
1662
1681
|
## Benefits
|
|
@@ -1691,31 +1710,31 @@ The MetadataSync tool includes a comprehensive validation system that checks you
|
|
|
1691
1710
|
By default, validation runs automatically before push and pull operations:
|
|
1692
1711
|
```bash
|
|
1693
1712
|
# These commands validate first, then proceed if valid
|
|
1694
|
-
mj
|
|
1695
|
-
mj
|
|
1713
|
+
mj sync push
|
|
1714
|
+
mj sync pull --entity="AI Prompts"
|
|
1696
1715
|
```
|
|
1697
1716
|
|
|
1698
1717
|
#### Manual Validation
|
|
1699
1718
|
Run validation without performing any sync operations:
|
|
1700
1719
|
```bash
|
|
1701
1720
|
# Validate current directory
|
|
1702
|
-
mj
|
|
1721
|
+
mj sync validate
|
|
1703
1722
|
|
|
1704
1723
|
# Validate specific directory
|
|
1705
|
-
mj
|
|
1724
|
+
mj sync validate --dir="./metadata"
|
|
1706
1725
|
|
|
1707
1726
|
# Verbose output shows all files checked
|
|
1708
|
-
mj
|
|
1727
|
+
mj sync validate --verbose
|
|
1709
1728
|
```
|
|
1710
1729
|
|
|
1711
1730
|
#### CI/CD Integration
|
|
1712
1731
|
Get JSON output for automated pipelines:
|
|
1713
1732
|
```bash
|
|
1714
1733
|
# JSON output for parsing
|
|
1715
|
-
mj
|
|
1734
|
+
mj sync validate --format=json
|
|
1716
1735
|
|
|
1717
1736
|
# In CI mode, validation failures cause immediate exit
|
|
1718
|
-
mj
|
|
1737
|
+
mj sync push --ci
|
|
1719
1738
|
```
|
|
1720
1739
|
|
|
1721
1740
|
#### Validation During Push
|
|
@@ -1730,8 +1749,8 @@ mj-sync push --ci
|
|
|
1730
1749
|
For emergency fixes or when you know validation will fail:
|
|
1731
1750
|
```bash
|
|
1732
1751
|
# Skip validation checks (USE WITH CAUTION!)
|
|
1733
|
-
mj
|
|
1734
|
-
mj
|
|
1752
|
+
mj sync push --no-validate
|
|
1753
|
+
mj sync pull --entity="AI Prompts" --no-validate
|
|
1735
1754
|
```
|
|
1736
1755
|
|
|
1737
1756
|
⚠️ **Warning:** Using `--no-validate` may push invalid metadata to your database, potentially breaking your application. Only use this flag when absolutely necessary.
|
|
@@ -1803,7 +1822,7 @@ Errors
|
|
|
1803
1822
|
Entity: Templates
|
|
1804
1823
|
Field: Status
|
|
1805
1824
|
File: ./metadata/templates/.my-template.json
|
|
1806
|
-
→ Suggestion: Check spelling of 'Status'. Run 'mj
|
|
1825
|
+
→ Suggestion: Check spelling of 'Status'. Run 'mj sync list-entities' to see available entities.
|
|
1807
1826
|
|
|
1808
1827
|
2. File not found: ./shared/footer.html
|
|
1809
1828
|
Entity: Templates
|
|
@@ -1837,7 +1856,7 @@ Errors
|
|
|
1837
1856
|
"field": "Status",
|
|
1838
1857
|
"file": "./metadata/templates/.my-template.json",
|
|
1839
1858
|
"message": "Field \"Status\" does not exist on entity \"Templates\"",
|
|
1840
|
-
"suggestion": "Check spelling of 'Status'. Run 'mj
|
|
1859
|
+
"suggestion": "Check spelling of 'Status'. Run 'mj sync list-entities' to see available entities."
|
|
1841
1860
|
}
|
|
1842
1861
|
],
|
|
1843
1862
|
"warnings": [...]
|
|
@@ -1931,9 +1950,9 @@ Control validation behavior in your workflow:
|
|
|
1931
1950
|
|
|
1932
1951
|
### Best Practices
|
|
1933
1952
|
|
|
1934
|
-
1. **Run validation during development**: `mj
|
|
1953
|
+
1. **Run validation during development**: `mj sync validate` frequently
|
|
1935
1954
|
2. **Fix errors before warnings**: Errors block operations, warnings don't
|
|
1936
|
-
3. **Use verbose mode** to understand issues: `mj
|
|
1955
|
+
3. **Use verbose mode** to understand issues: `mj sync validate -v`
|
|
1937
1956
|
4. **Include in CI/CD**: Parse JSON output for automated checks
|
|
1938
1957
|
5. **Don't skip validation** unless absolutely necessary
|
|
1939
1958
|
|
|
@@ -1945,7 +1964,7 @@ If validation fails:
|
|
|
1945
1964
|
|
|
1946
1965
|
1. **Read the error message carefully** - It includes specific details
|
|
1947
1966
|
2. **Check the suggestion** - Most errors include how to fix them
|
|
1948
|
-
3. **Use verbose mode** for more context: `mj
|
|
1967
|
+
3. **Use verbose mode** for more context: `mj sync validate -v`
|
|
1949
1968
|
4. **Verify entity definitions** in generated entity files
|
|
1950
1969
|
5. **Check file paths** are relative to the metadata directory
|
|
1951
1970
|
|
|
@@ -1953,9 +1972,9 @@ If validation fails:
|
|
|
1953
1972
|
|
|
1954
1973
|
For large metadata sets:
|
|
1955
1974
|
|
|
1956
|
-
1. **Disable best practice checks**: `mj
|
|
1957
|
-
2. **Validate specific directories**: `mj
|
|
1958
|
-
3. **Reduce nesting depth warning**: `mj
|
|
1975
|
+
1. **Disable best practice checks**: `mj sync validate --no-best-practices`
|
|
1976
|
+
2. **Validate specific directories**: `mj sync validate --dir="./prompts"`
|
|
1977
|
+
3. **Reduce nesting depth warning**: `mj sync validate --max-depth=20`
|
|
1959
1978
|
|
|
1960
1979
|
## Programmatic Usage
|
|
1961
1980
|
|
|
@@ -2074,8 +2093,8 @@ export async function validateBeforeDeploy(metadataPath: string): Promise<boolea
|
|
|
2074
2093
|
# Example GitHub Actions workflow
|
|
2075
2094
|
- name: Validate Metadata
|
|
2076
2095
|
run: |
|
|
2077
|
-
npm install @memberjunction/
|
|
2078
|
-
npx mj
|
|
2096
|
+
npm install @memberjunction/cli
|
|
2097
|
+
npx mj sync validate --dir=./metadata --format=json > validation-results.json
|
|
2079
2098
|
|
|
2080
2099
|
- name: Check Validation Results
|
|
2081
2100
|
run: |
|
|
@@ -2096,3 +2115,25 @@ export async function validateBeforeDeploy(metadataPath: string): Promise<boolea
|
|
|
2096
2115
|
- Team collaboration features
|
|
2097
2116
|
- Bidirectional sync for related entities
|
|
2098
2117
|
- Custom transformation pipelines
|
|
2118
|
+
|
|
2119
|
+
## Migration from Standalone MetadataSync
|
|
2120
|
+
|
|
2121
|
+
If you were previously using the standalone `mj-sync` command:
|
|
2122
|
+
|
|
2123
|
+
1. **Update your installation**: Install the MJ CLI instead of standalone MetadataSync
|
|
2124
|
+
```bash
|
|
2125
|
+
npm install -g @memberjunction/cli
|
|
2126
|
+
```
|
|
2127
|
+
|
|
2128
|
+
2. **Update your scripts**: Replace `mj-sync` with `mj sync` in all scripts and documentation
|
|
2129
|
+
```bash
|
|
2130
|
+
# Old command (standalone package)
|
|
2131
|
+
mj-sync push --dir="metadata"
|
|
2132
|
+
|
|
2133
|
+
# New command
|
|
2134
|
+
mj sync push --dir="metadata"
|
|
2135
|
+
```
|
|
2136
|
+
|
|
2137
|
+
3. **Configuration unchanged**: All `.mj-sync.json` configuration files work exactly the same
|
|
2138
|
+
|
|
2139
|
+
4. **Same functionality**: The underlying MetadataSync library is identical, just accessed through the unified CLI
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,24 @@
|
|
|
1
|
-
export { run } from '@oclif/core';
|
|
2
1
|
export { FileBackupManager } from './lib/file-backup-manager';
|
|
3
2
|
export { SyncEngine } from './lib/sync-engine';
|
|
4
3
|
export type { RecordData } from './lib/sync-engine';
|
|
4
|
+
export { ConfigManager, configManager } from './lib/config-manager';
|
|
5
|
+
export { getSyncEngine, resetSyncEngine } from './lib/singleton-manager';
|
|
6
|
+
export { SQLLogger } from './lib/sql-logger';
|
|
7
|
+
export { TransactionManager } from './lib/transaction-manager';
|
|
8
|
+
export { InitService } from './services/InitService';
|
|
9
|
+
export type { InitOptions, InitCallbacks } from './services/InitService';
|
|
10
|
+
export { PullService } from './services/PullService';
|
|
11
|
+
export type { PullOptions, PullCallbacks, PullResult } from './services/PullService';
|
|
12
|
+
export { PushService } from './services/PushService';
|
|
13
|
+
export type { PushOptions, PushCallbacks, PushResult } from './services/PushService';
|
|
14
|
+
export { StatusService } from './services/StatusService';
|
|
15
|
+
export type { StatusOptions, StatusCallbacks, StatusResult } from './services/StatusService';
|
|
16
|
+
export { FileResetService } from './services/FileResetService';
|
|
17
|
+
export type { FileResetOptions, FileResetCallbacks, FileResetResult } from './services/FileResetService';
|
|
18
|
+
export { WatchService } from './services/WatchService';
|
|
19
|
+
export type { WatchOptions, WatchCallbacks, WatchResult } from './services/WatchService';
|
|
20
|
+
export { ValidationService } from './services/ValidationService';
|
|
21
|
+
export { FormattingService } from './services/FormattingService';
|
|
22
|
+
export { loadMJConfig, loadSyncConfig, loadEntityConfig, loadFolderConfig, type EntityConfig, type FolderConfig, type RelatedEntityConfig } from './config';
|
|
23
|
+
export { initializeProvider, getSystemUser, findEntityDirectories, getDataProvider } from './lib/provider-utils';
|
|
24
|
+
export type { ValidationResult, ValidationError, ValidationWarning, EntityDependency, FileValidationResult, ValidationOptions, ReferenceType, ParsedReference } from './types/validation';
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,48 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
5
|
-
Object.defineProperty(exports, "run", { enumerable: true, get: function () { return core_1.run; } });
|
|
3
|
+
exports.getDataProvider = exports.findEntityDirectories = exports.getSystemUser = exports.initializeProvider = exports.loadFolderConfig = exports.loadEntityConfig = exports.loadSyncConfig = exports.loadMJConfig = exports.FormattingService = exports.ValidationService = exports.WatchService = exports.FileResetService = exports.StatusService = exports.PushService = exports.PullService = exports.InitService = exports.TransactionManager = exports.SQLLogger = exports.resetSyncEngine = exports.getSyncEngine = exports.configManager = exports.ConfigManager = exports.SyncEngine = exports.FileBackupManager = void 0;
|
|
4
|
+
// Core library exports
|
|
6
5
|
var file_backup_manager_1 = require("./lib/file-backup-manager");
|
|
7
6
|
Object.defineProperty(exports, "FileBackupManager", { enumerable: true, get: function () { return file_backup_manager_1.FileBackupManager; } });
|
|
8
7
|
var sync_engine_1 = require("./lib/sync-engine");
|
|
9
8
|
Object.defineProperty(exports, "SyncEngine", { enumerable: true, get: function () { return sync_engine_1.SyncEngine; } });
|
|
9
|
+
var config_manager_1 = require("./lib/config-manager");
|
|
10
|
+
Object.defineProperty(exports, "ConfigManager", { enumerable: true, get: function () { return config_manager_1.ConfigManager; } });
|
|
11
|
+
Object.defineProperty(exports, "configManager", { enumerable: true, get: function () { return config_manager_1.configManager; } });
|
|
12
|
+
var singleton_manager_1 = require("./lib/singleton-manager");
|
|
13
|
+
Object.defineProperty(exports, "getSyncEngine", { enumerable: true, get: function () { return singleton_manager_1.getSyncEngine; } });
|
|
14
|
+
Object.defineProperty(exports, "resetSyncEngine", { enumerable: true, get: function () { return singleton_manager_1.resetSyncEngine; } });
|
|
15
|
+
var sql_logger_1 = require("./lib/sql-logger");
|
|
16
|
+
Object.defineProperty(exports, "SQLLogger", { enumerable: true, get: function () { return sql_logger_1.SQLLogger; } });
|
|
17
|
+
var transaction_manager_1 = require("./lib/transaction-manager");
|
|
18
|
+
Object.defineProperty(exports, "TransactionManager", { enumerable: true, get: function () { return transaction_manager_1.TransactionManager; } });
|
|
19
|
+
// Service exports
|
|
20
|
+
var InitService_1 = require("./services/InitService");
|
|
21
|
+
Object.defineProperty(exports, "InitService", { enumerable: true, get: function () { return InitService_1.InitService; } });
|
|
22
|
+
var PullService_1 = require("./services/PullService");
|
|
23
|
+
Object.defineProperty(exports, "PullService", { enumerable: true, get: function () { return PullService_1.PullService; } });
|
|
24
|
+
var PushService_1 = require("./services/PushService");
|
|
25
|
+
Object.defineProperty(exports, "PushService", { enumerable: true, get: function () { return PushService_1.PushService; } });
|
|
26
|
+
var StatusService_1 = require("./services/StatusService");
|
|
27
|
+
Object.defineProperty(exports, "StatusService", { enumerable: true, get: function () { return StatusService_1.StatusService; } });
|
|
28
|
+
var FileResetService_1 = require("./services/FileResetService");
|
|
29
|
+
Object.defineProperty(exports, "FileResetService", { enumerable: true, get: function () { return FileResetService_1.FileResetService; } });
|
|
30
|
+
var WatchService_1 = require("./services/WatchService");
|
|
31
|
+
Object.defineProperty(exports, "WatchService", { enumerable: true, get: function () { return WatchService_1.WatchService; } });
|
|
32
|
+
var ValidationService_1 = require("./services/ValidationService");
|
|
33
|
+
Object.defineProperty(exports, "ValidationService", { enumerable: true, get: function () { return ValidationService_1.ValidationService; } });
|
|
34
|
+
var FormattingService_1 = require("./services/FormattingService");
|
|
35
|
+
Object.defineProperty(exports, "FormattingService", { enumerable: true, get: function () { return FormattingService_1.FormattingService; } });
|
|
36
|
+
// Configuration types
|
|
37
|
+
var config_1 = require("./config");
|
|
38
|
+
Object.defineProperty(exports, "loadMJConfig", { enumerable: true, get: function () { return config_1.loadMJConfig; } });
|
|
39
|
+
Object.defineProperty(exports, "loadSyncConfig", { enumerable: true, get: function () { return config_1.loadSyncConfig; } });
|
|
40
|
+
Object.defineProperty(exports, "loadEntityConfig", { enumerable: true, get: function () { return config_1.loadEntityConfig; } });
|
|
41
|
+
Object.defineProperty(exports, "loadFolderConfig", { enumerable: true, get: function () { return config_1.loadFolderConfig; } });
|
|
42
|
+
// Provider utilities
|
|
43
|
+
var provider_utils_1 = require("./lib/provider-utils");
|
|
44
|
+
Object.defineProperty(exports, "initializeProvider", { enumerable: true, get: function () { return provider_utils_1.initializeProvider; } });
|
|
45
|
+
Object.defineProperty(exports, "getSystemUser", { enumerable: true, get: function () { return provider_utils_1.getSystemUser; } });
|
|
46
|
+
Object.defineProperty(exports, "findEntityDirectories", { enumerable: true, get: function () { return provider_utils_1.findEntityDirectories; } });
|
|
47
|
+
Object.defineProperty(exports, "getDataProvider", { enumerable: true, get: function () { return provider_utils_1.getDataProvider; } });
|
|
10
48
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,uBAAuB;AACvB,iEAA8D;AAArD,wHAAA,iBAAiB,OAAA;AAC1B,iDAA+C;AAAtC,yGAAA,UAAU,OAAA;AAEnB,uDAAoE;AAA3D,+GAAA,aAAa,OAAA;AAAE,+GAAA,aAAa,OAAA;AACrC,6DAAyE;AAAhE,kHAAA,aAAa,OAAA;AAAE,oHAAA,eAAe,OAAA;AACvC,+CAA6C;AAApC,uGAAA,SAAS,OAAA;AAClB,iEAA+D;AAAtD,yHAAA,kBAAkB,OAAA;AAE3B,kBAAkB;AAClB,sDAAqD;AAA5C,0GAAA,WAAW,OAAA;AAGpB,sDAAqD;AAA5C,0GAAA,WAAW,OAAA;AAGpB,sDAAqD;AAA5C,0GAAA,WAAW,OAAA;AAGpB,0DAAyD;AAAhD,8GAAA,aAAa,OAAA;AAGtB,gEAA+D;AAAtD,oHAAA,gBAAgB,OAAA;AAGzB,wDAAuD;AAA9C,4GAAA,YAAY,OAAA;AAGrB,kEAAiE;AAAxD,sHAAA,iBAAiB,OAAA;AAC1B,kEAAiE;AAAxD,sHAAA,iBAAiB,OAAA;AAE1B,sBAAsB;AACtB,mCAQkB;AAPhB,sGAAA,YAAY,OAAA;AACZ,wGAAA,cAAc,OAAA;AACd,0GAAA,gBAAgB,OAAA;AAChB,0GAAA,gBAAgB,OAAA;AAMlB,qBAAqB;AACrB,uDAK8B;AAJ5B,oHAAA,kBAAkB,OAAA;AAClB,+GAAA,aAAa,OAAA;AACb,uHAAA,qBAAqB,OAAA;AACrB,iHAAA,eAAe,OAAA","sourcesContent":["// Core library exports\nexport { FileBackupManager } from './lib/file-backup-manager';\nexport { SyncEngine } from './lib/sync-engine';\nexport type { RecordData } from './lib/sync-engine';\nexport { ConfigManager, configManager } from './lib/config-manager';\nexport { getSyncEngine, resetSyncEngine } from './lib/singleton-manager';\nexport { SQLLogger } from './lib/sql-logger';\nexport { TransactionManager } from './lib/transaction-manager';\n\n// Service exports\nexport { InitService } from './services/InitService';\nexport type { InitOptions, InitCallbacks } from './services/InitService';\n\nexport { PullService } from './services/PullService';\nexport type { PullOptions, PullCallbacks, PullResult } from './services/PullService';\n\nexport { PushService } from './services/PushService';\nexport type { PushOptions, PushCallbacks, PushResult } from './services/PushService';\n\nexport { StatusService } from './services/StatusService';\nexport type { StatusOptions, StatusCallbacks, StatusResult } from './services/StatusService';\n\nexport { FileResetService } from './services/FileResetService';\nexport type { FileResetOptions, FileResetCallbacks, FileResetResult } from './services/FileResetService';\n\nexport { WatchService } from './services/WatchService';\nexport type { WatchOptions, WatchCallbacks, WatchResult } from './services/WatchService';\n\nexport { ValidationService } from './services/ValidationService';\nexport { FormattingService } from './services/FormattingService';\n\n// Configuration types\nexport {\n loadMJConfig,\n loadSyncConfig,\n loadEntityConfig,\n loadFolderConfig,\n type EntityConfig,\n type FolderConfig,\n type RelatedEntityConfig\n} from './config';\n\n// Provider utilities\nexport {\n initializeProvider,\n getSystemUser,\n findEntityDirectories,\n getDataProvider\n} from './lib/provider-utils';\n\n// Validation types\nexport type {\n ValidationResult,\n ValidationError,\n ValidationWarning,\n EntityDependency,\n FileValidationResult,\n ValidationOptions,\n ReferenceType,\n ParsedReference\n} from './types/validation';"]}
|
|
@@ -15,7 +15,7 @@ exports.FileBackupManager = void 0;
|
|
|
15
15
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
16
16
|
const path_1 = __importDefault(require("path"));
|
|
17
17
|
const os_1 = __importDefault(require("os"));
|
|
18
|
-
const
|
|
18
|
+
const uuid_1 = require("uuid");
|
|
19
19
|
/**
|
|
20
20
|
* Manages file backups and rollback operations for MetadataSync
|
|
21
21
|
*
|
|
@@ -61,7 +61,7 @@ class FileBackupManager {
|
|
|
61
61
|
}
|
|
62
62
|
// Create a unique temporary directory for this session
|
|
63
63
|
const tempRoot = os_1.default.tmpdir();
|
|
64
|
-
const sessionId = (0,
|
|
64
|
+
const sessionId = (0, uuid_1.v4)();
|
|
65
65
|
this.backupDir = path_1.default.join(tempRoot, 'mj-metadata-sync', sessionId);
|
|
66
66
|
await fs_extra_1.default.ensureDir(this.backupDir);
|
|
67
67
|
this.initialized = true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-backup-manager.js","sourceRoot":"","sources":["../../src/lib/file-backup-manager.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;;;;AAEH,wDAA0B;AAC1B,gDAAwB;AACxB,4CAAoB;AACpB
|
|
1
|
+
{"version":3,"file":"file-backup-manager.js","sourceRoot":"","sources":["../../src/lib/file-backup-manager.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview File backup and rollback manager for MetadataSync operations\n * @module file-backup-manager\n * \n * This module provides functionality to create backups of files before modification\n * and allows rolling back all changes if any operation fails. It ensures atomic\n * file operations by maintaining a temporary backup directory during push operations.\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport os from 'os';\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Represents a backed-up file with its original and backup paths\n */\ninterface BackupEntry {\n /** Original file path that was backed up */\n originalPath: string;\n /** Path to the backup copy of the file */\n backupPath: string;\n /** Whether the file existed before modification */\n existed: boolean;\n}\n\n/**\n * Manages file backups and rollback operations for MetadataSync\n * \n * Creates temporary backups of all modified files during a push operation,\n * allowing atomic rollback of all file changes if any error occurs.\n * \n * @class FileBackupManager\n * @example\n * ```typescript\n * const backupManager = new FileBackupManager();\n * await backupManager.initialize();\n * \n * try {\n * await backupManager.backupFile('/path/to/file.json');\n * // Modify the file\n * await fs.writeJson('/path/to/file.json', newData);\n * \n * // If all operations succeed\n * await backupManager.cleanup();\n * } catch (error) {\n * // Rollback all file changes\n * await backupManager.rollback();\n * throw error;\n * }\n * ```\n */\nexport class FileBackupManager {\n private backupDir: string = '';\n private backups: BackupEntry[] = [];\n private initialized: boolean = false;\n \n /**\n * Initialize the backup manager by creating a temporary directory\n * \n * Creates a unique temporary directory for storing file backups during\n * the current operation. Must be called before any backup operations.\n * \n * @returns Promise that resolves when initialization is complete\n * @throws Error if temporary directory creation fails\n */\n async initialize(): Promise<void> {\n if (this.initialized) {\n throw new Error('FileBackupManager already initialized');\n }\n \n // Create a unique temporary directory for this session\n const tempRoot = os.tmpdir();\n const sessionId = uuidv4();\n this.backupDir = path.join(tempRoot, 'mj-metadata-sync', sessionId);\n \n await fs.ensureDir(this.backupDir);\n this.initialized = true;\n }\n \n /**\n * Create a backup of a file before modification\n * \n * Copies the current state of a file to the backup directory. If the file\n * doesn't exist, records that fact for proper rollback handling.\n * \n * @param filePath - Absolute path to the file to backup\n * @returns Promise that resolves when backup is complete\n * @throws Error if backup operation fails\n */\n async backupFile(filePath: string): Promise<void> {\n if (!this.initialized) {\n throw new Error('FileBackupManager not initialized. Call initialize() first.');\n }\n \n // Check if we already have a backup for this file\n const existingBackup = this.backups.find(b => b.originalPath === filePath);\n if (existingBackup) {\n // Already backed up, don't backup again\n return;\n }\n \n const exists = await fs.pathExists(filePath);\n const backupFileName = `${path.basename(filePath)}_${Date.now()}_${this.backups.length}`;\n const backupPath = path.join(this.backupDir, backupFileName);\n \n const backupEntry: BackupEntry = {\n originalPath: filePath,\n backupPath: backupPath,\n existed: exists\n };\n \n if (exists) {\n // Copy the file to backup location\n await fs.copy(filePath, backupPath);\n }\n \n this.backups.push(backupEntry);\n }\n \n /**\n * Rollback all file changes by restoring from backups\n * \n * Restores all backed-up files to their original state. Files that didn't\n * exist before the operation are deleted. This operation is atomic - either\n * all files are restored or none are.\n * \n * @returns Promise that resolves when rollback is complete\n * @throws Error if any rollback operation fails\n */\n async rollback(): Promise<void> {\n if (!this.initialized) {\n return; // Nothing to rollback\n }\n \n const errors: string[] = [];\n \n // Process backups in reverse order (last modified first)\n for (const backup of this.backups.reverse()) {\n try {\n if (backup.existed) {\n // Restore the original file\n await fs.copy(backup.backupPath, backup.originalPath, { overwrite: true });\n } else {\n // File didn't exist before, remove it\n if (await fs.pathExists(backup.originalPath)) {\n await fs.remove(backup.originalPath);\n }\n }\n } catch (error) {\n const errorMsg = `Failed to rollback ${backup.originalPath}: ${error instanceof Error ? error.message : String(error)}`;\n errors.push(errorMsg);\n console.error(errorMsg);\n }\n }\n \n // Clean up backup directory\n try {\n await this.cleanup();\n } catch (error) {\n console.error('Failed to cleanup backup directory during rollback:', error);\n }\n \n if (errors.length > 0) {\n throw new Error(`Rollback completed with errors:\\n${errors.join('\\n')}`);\n }\n }\n \n /**\n * Clean up backup directory after successful operation\n * \n * Removes all temporary backup files and the backup directory. Should be\n * called after all operations complete successfully.\n * \n * @returns Promise that resolves when cleanup is complete\n */\n async cleanup(): Promise<void> {\n if (!this.initialized || !this.backupDir) {\n return;\n }\n \n try {\n await fs.remove(this.backupDir);\n } catch (error) {\n // Log but don't throw - cleanup errors shouldn't fail the operation\n console.warn(`Failed to cleanup backup directory ${this.backupDir}:`, error);\n }\n \n this.backups = [];\n this.initialized = false;\n this.backupDir = '';\n }\n \n /**\n * Get statistics about current backup session\n * \n * @returns Object containing backup statistics\n */\n getStats(): { totalBackups: number; backupDir: string; initialized: boolean } {\n return {\n totalBackups: this.backups.length,\n backupDir: this.backupDir,\n initialized: this.initialized\n };\n }\n}"]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview SQL Logger for capturing database operations during metadata sync
|
|
3
|
+
* @module sql-logger
|
|
4
|
+
*
|
|
5
|
+
* This module provides SQL logging functionality to capture all database operations
|
|
6
|
+
* during push commands. It supports both raw SQL logging and migration-formatted output.
|
|
7
|
+
*/
|
|
8
|
+
import { SyncConfig } from '../config';
|
|
9
|
+
export interface SQLLoggerOptions {
|
|
10
|
+
enabled: boolean;
|
|
11
|
+
outputDirectory: string;
|
|
12
|
+
formatAsMigration: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare class SQLLogger {
|
|
15
|
+
private options;
|
|
16
|
+
private statements;
|
|
17
|
+
private isInitialized;
|
|
18
|
+
constructor(syncConfig: SyncConfig | null);
|
|
19
|
+
get enabled(): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Initialize the SQL logger and prepare output directory
|
|
22
|
+
*/
|
|
23
|
+
initialize(): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Log a SQL statement
|
|
26
|
+
*/
|
|
27
|
+
logStatement(sql: string, params?: any[]): void;
|
|
28
|
+
/**
|
|
29
|
+
* Log a transaction boundary
|
|
30
|
+
*/
|
|
31
|
+
logTransaction(action: 'BEGIN' | 'COMMIT' | 'ROLLBACK'): void;
|
|
32
|
+
/**
|
|
33
|
+
* Write the collected SQL statements to file
|
|
34
|
+
*/
|
|
35
|
+
writeLog(): Promise<string | undefined>;
|
|
36
|
+
/**
|
|
37
|
+
* Clear all logged statements
|
|
38
|
+
*/
|
|
39
|
+
clear(): void;
|
|
40
|
+
/**
|
|
41
|
+
* Format a parameter value for SQL
|
|
42
|
+
*/
|
|
43
|
+
private formatParamValue;
|
|
44
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview SQL Logger for capturing database operations during metadata sync
|
|
4
|
+
* @module sql-logger
|
|
5
|
+
*
|
|
6
|
+
* This module provides SQL logging functionality to capture all database operations
|
|
7
|
+
* during push commands. It supports both raw SQL logging and migration-formatted output.
|
|
8
|
+
*/
|
|
9
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.SQLLogger = void 0;
|
|
14
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
15
|
+
const path_1 = __importDefault(require("path"));
|
|
16
|
+
class SQLLogger {
|
|
17
|
+
options;
|
|
18
|
+
statements = [];
|
|
19
|
+
isInitialized = false;
|
|
20
|
+
constructor(syncConfig) {
|
|
21
|
+
this.options = {
|
|
22
|
+
enabled: syncConfig?.sqlLogging?.enabled || false,
|
|
23
|
+
outputDirectory: syncConfig?.sqlLogging?.outputDirectory || './sql_logging',
|
|
24
|
+
formatAsMigration: syncConfig?.sqlLogging?.formatAsMigration || false
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
get enabled() {
|
|
28
|
+
return this.options.enabled;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Initialize the SQL logger and prepare output directory
|
|
32
|
+
*/
|
|
33
|
+
async initialize() {
|
|
34
|
+
if (!this.options.enabled || this.isInitialized) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
// Ensure output directory exists
|
|
38
|
+
await fs_extra_1.default.ensureDir(this.options.outputDirectory);
|
|
39
|
+
this.isInitialized = true;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Log a SQL statement
|
|
43
|
+
*/
|
|
44
|
+
logStatement(sql, params) {
|
|
45
|
+
if (!this.options.enabled) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
// Format SQL with parameters inline for readability
|
|
49
|
+
let formattedSql = sql;
|
|
50
|
+
if (params && params.length > 0) {
|
|
51
|
+
// Replace parameter placeholders with actual values
|
|
52
|
+
params.forEach((param, index) => {
|
|
53
|
+
const placeholder = `@param${index + 1}`;
|
|
54
|
+
const value = this.formatParamValue(param);
|
|
55
|
+
formattedSql = formattedSql.replace(new RegExp(placeholder, 'g'), value);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
this.statements.push(formattedSql);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Log a transaction boundary
|
|
62
|
+
*/
|
|
63
|
+
logTransaction(action) {
|
|
64
|
+
if (!this.options.enabled) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
this.statements.push(`${action} TRANSACTION;`);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Write the collected SQL statements to file
|
|
71
|
+
*/
|
|
72
|
+
async writeLog() {
|
|
73
|
+
if (!this.options.enabled || this.statements.length === 0) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
await this.initialize();
|
|
77
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
78
|
+
let filename;
|
|
79
|
+
let content;
|
|
80
|
+
if (this.options.formatAsMigration) {
|
|
81
|
+
// Format as Flyway migration
|
|
82
|
+
const migrationTimestamp = timestamp.replace(/[-T]/g, '').substring(0, 14);
|
|
83
|
+
filename = `V${migrationTimestamp}__MetadataSync_Push.sql`;
|
|
84
|
+
content = [
|
|
85
|
+
'-- MemberJunction MetadataSync Push Migration',
|
|
86
|
+
`-- Generated at: ${new Date().toISOString()}`,
|
|
87
|
+
'-- Description: Metadata changes pushed via mj sync push command',
|
|
88
|
+
'',
|
|
89
|
+
'-- Note: Schema placeholders can be replaced during deployment',
|
|
90
|
+
'-- Replace ${flyway:defaultSchema} with your target schema name',
|
|
91
|
+
'',
|
|
92
|
+
...this.statements.map(stmt => {
|
|
93
|
+
// Add schema placeholders for migration format
|
|
94
|
+
return stmt.replace(/(\[?)__mj(\]?)\./g, '${flyway:defaultSchema}.');
|
|
95
|
+
})
|
|
96
|
+
].join('\n');
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
// Regular SQL log format
|
|
100
|
+
filename = `metadatasync-push-${timestamp}.sql`;
|
|
101
|
+
content = [
|
|
102
|
+
'-- MemberJunction MetadataSync SQL Log',
|
|
103
|
+
`-- Generated at: ${new Date().toISOString()}`,
|
|
104
|
+
`-- Total statements: ${this.statements.length}`,
|
|
105
|
+
'',
|
|
106
|
+
...this.statements
|
|
107
|
+
].join('\n');
|
|
108
|
+
}
|
|
109
|
+
const filePath = path_1.default.join(this.options.outputDirectory, filename);
|
|
110
|
+
await fs_extra_1.default.writeFile(filePath, content, 'utf8');
|
|
111
|
+
return filePath;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Clear all logged statements
|
|
115
|
+
*/
|
|
116
|
+
clear() {
|
|
117
|
+
this.statements = [];
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Format a parameter value for SQL
|
|
121
|
+
*/
|
|
122
|
+
formatParamValue(value) {
|
|
123
|
+
if (value === null) {
|
|
124
|
+
return 'NULL';
|
|
125
|
+
}
|
|
126
|
+
if (typeof value === 'string') {
|
|
127
|
+
// Escape single quotes and wrap in quotes
|
|
128
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
129
|
+
}
|
|
130
|
+
if (typeof value === 'boolean') {
|
|
131
|
+
return value ? '1' : '0';
|
|
132
|
+
}
|
|
133
|
+
if (value instanceof Date) {
|
|
134
|
+
return `'${value.toISOString()}'`;
|
|
135
|
+
}
|
|
136
|
+
return String(value);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
exports.SQLLogger = SQLLogger;
|
|
140
|
+
//# sourceMappingURL=sql-logger.js.map
|