@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
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.FileResetService = void 0;
|
|
7
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
10
|
+
const config_1 = require("../config");
|
|
11
|
+
const config_manager_1 = require("../lib/config-manager");
|
|
12
|
+
class FileResetService {
|
|
13
|
+
async resetFiles(options = {}, callbacks) {
|
|
14
|
+
const sections = options.sections || 'both';
|
|
15
|
+
// Load sync config
|
|
16
|
+
const syncConfig = await (0, config_1.loadSyncConfig)(config_manager_1.configManager.getOriginalCwd());
|
|
17
|
+
if (!syncConfig) {
|
|
18
|
+
throw new Error('No .mj-sync.json found in current directory');
|
|
19
|
+
}
|
|
20
|
+
// Find all metadata JSON files
|
|
21
|
+
callbacks?.onProgress?.('Finding metadata files');
|
|
22
|
+
const pattern = syncConfig.filePattern || '.*.json';
|
|
23
|
+
const files = await (0, fast_glob_1.default)(pattern, {
|
|
24
|
+
cwd: config_manager_1.configManager.getOriginalCwd(),
|
|
25
|
+
absolute: true,
|
|
26
|
+
ignore: ['.mj-sync.json', '.mj-folder.json'],
|
|
27
|
+
});
|
|
28
|
+
if (files.length === 0) {
|
|
29
|
+
callbacks?.onLog?.('No metadata files found');
|
|
30
|
+
return {
|
|
31
|
+
processedFiles: 0,
|
|
32
|
+
modifiedFiles: 0,
|
|
33
|
+
totalPrimaryKeys: 0,
|
|
34
|
+
totalSyncs: 0,
|
|
35
|
+
filesWithPrimaryKey: 0,
|
|
36
|
+
filesWithSync: 0,
|
|
37
|
+
backupsCreated: 0
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
callbacks?.onLog?.(`Found ${files.length} metadata file${files.length === 1 ? '' : 's'}`);
|
|
41
|
+
// Count what will be removed
|
|
42
|
+
let filesWithPrimaryKey = 0;
|
|
43
|
+
let filesWithSync = 0;
|
|
44
|
+
let totalPrimaryKeys = 0;
|
|
45
|
+
let totalSyncs = 0;
|
|
46
|
+
for (const file of files) {
|
|
47
|
+
const content = await fs_extra_1.default.readJson(file);
|
|
48
|
+
const stats = this.countSections(content);
|
|
49
|
+
if (stats.primaryKeyCount > 0) {
|
|
50
|
+
filesWithPrimaryKey++;
|
|
51
|
+
totalPrimaryKeys += stats.primaryKeyCount;
|
|
52
|
+
}
|
|
53
|
+
if (stats.syncCount > 0) {
|
|
54
|
+
filesWithSync++;
|
|
55
|
+
totalSyncs += stats.syncCount;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Report what will be removed
|
|
59
|
+
if (sections === 'both' || sections === 'primaryKey') {
|
|
60
|
+
callbacks?.onLog?.(`Will remove ${totalPrimaryKeys} primaryKey section${totalPrimaryKeys === 1 ? '' : 's'} from ${filesWithPrimaryKey} file${filesWithPrimaryKey === 1 ? '' : 's'}`);
|
|
61
|
+
}
|
|
62
|
+
if (sections === 'both' || sections === 'sync') {
|
|
63
|
+
callbacks?.onLog?.(`Will remove ${totalSyncs} sync section${totalSyncs === 1 ? '' : 's'} from ${filesWithSync} file${filesWithSync === 1 ? '' : 's'}`);
|
|
64
|
+
}
|
|
65
|
+
if (options.dryRun) {
|
|
66
|
+
callbacks?.onLog?.('Dry run mode - no files will be modified');
|
|
67
|
+
if (options.verbose) {
|
|
68
|
+
for (const file of files) {
|
|
69
|
+
const content = await fs_extra_1.default.readJson(file);
|
|
70
|
+
const stats = this.countSections(content);
|
|
71
|
+
if (stats.primaryKeyCount > 0 || stats.syncCount > 0) {
|
|
72
|
+
callbacks?.onLog?.(`${path_1.default.relative(config_manager_1.configManager.getOriginalCwd(), file)}:`);
|
|
73
|
+
if (stats.primaryKeyCount > 0) {
|
|
74
|
+
callbacks?.onLog?.(` - ${stats.primaryKeyCount} primaryKey section${stats.primaryKeyCount === 1 ? '' : 's'}`);
|
|
75
|
+
}
|
|
76
|
+
if (stats.syncCount > 0) {
|
|
77
|
+
callbacks?.onLog?.(` - ${stats.syncCount} sync section${stats.syncCount === 1 ? '' : 's'}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
processedFiles: files.length,
|
|
84
|
+
modifiedFiles: 0,
|
|
85
|
+
totalPrimaryKeys,
|
|
86
|
+
totalSyncs,
|
|
87
|
+
filesWithPrimaryKey,
|
|
88
|
+
filesWithSync,
|
|
89
|
+
backupsCreated: 0
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// Process files
|
|
93
|
+
callbacks?.onProgress?.('Processing files');
|
|
94
|
+
let processedFiles = 0;
|
|
95
|
+
let modifiedFiles = 0;
|
|
96
|
+
let backupsCreated = 0;
|
|
97
|
+
for (const file of files) {
|
|
98
|
+
processedFiles++;
|
|
99
|
+
const content = await fs_extra_1.default.readJson(file);
|
|
100
|
+
const originalContent = JSON.stringify(content);
|
|
101
|
+
// Remove sections
|
|
102
|
+
const cleanedContent = this.removeSections(content, sections);
|
|
103
|
+
// Only write if content changed
|
|
104
|
+
if (JSON.stringify(cleanedContent) !== originalContent) {
|
|
105
|
+
// Create backup if requested
|
|
106
|
+
if (!options.noBackup) {
|
|
107
|
+
const backupPath = `${file}.backup`;
|
|
108
|
+
await fs_extra_1.default.writeJson(backupPath, content, { spaces: 2 });
|
|
109
|
+
backupsCreated++;
|
|
110
|
+
}
|
|
111
|
+
// Write cleaned content
|
|
112
|
+
await fs_extra_1.default.writeJson(file, cleanedContent, { spaces: 2 });
|
|
113
|
+
modifiedFiles++;
|
|
114
|
+
if (options.verbose) {
|
|
115
|
+
callbacks?.onLog?.(`✓ ${path_1.default.relative(config_manager_1.configManager.getOriginalCwd(), file)}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
processedFiles,
|
|
121
|
+
modifiedFiles,
|
|
122
|
+
totalPrimaryKeys,
|
|
123
|
+
totalSyncs,
|
|
124
|
+
filesWithPrimaryKey,
|
|
125
|
+
filesWithSync,
|
|
126
|
+
backupsCreated
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
countSections(data) {
|
|
130
|
+
let primaryKeyCount = 0;
|
|
131
|
+
let syncCount = 0;
|
|
132
|
+
if (Array.isArray(data)) {
|
|
133
|
+
for (const item of data) {
|
|
134
|
+
const stats = this.countSections(item);
|
|
135
|
+
primaryKeyCount += stats.primaryKeyCount;
|
|
136
|
+
syncCount += stats.syncCount;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
else if (data && typeof data === 'object') {
|
|
140
|
+
if ('primaryKey' in data)
|
|
141
|
+
primaryKeyCount++;
|
|
142
|
+
if ('sync' in data)
|
|
143
|
+
syncCount++;
|
|
144
|
+
// Check related entities
|
|
145
|
+
if (data.relatedEntities) {
|
|
146
|
+
for (const entityData of Object.values(data.relatedEntities)) {
|
|
147
|
+
const stats = this.countSections(entityData);
|
|
148
|
+
primaryKeyCount += stats.primaryKeyCount;
|
|
149
|
+
syncCount += stats.syncCount;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return { primaryKeyCount, syncCount };
|
|
154
|
+
}
|
|
155
|
+
removeSections(data, sections) {
|
|
156
|
+
if (Array.isArray(data)) {
|
|
157
|
+
return data.map(item => this.removeSections(item, sections));
|
|
158
|
+
}
|
|
159
|
+
else if (data && typeof data === 'object') {
|
|
160
|
+
const cleaned = { ...data };
|
|
161
|
+
// Remove specified sections
|
|
162
|
+
if (sections === 'both' || sections === 'primaryKey') {
|
|
163
|
+
delete cleaned.primaryKey;
|
|
164
|
+
}
|
|
165
|
+
if (sections === 'both' || sections === 'sync') {
|
|
166
|
+
delete cleaned.sync;
|
|
167
|
+
}
|
|
168
|
+
// Process related entities
|
|
169
|
+
if (cleaned.relatedEntities) {
|
|
170
|
+
const cleanedRelated = {};
|
|
171
|
+
for (const [entityName, entityData] of Object.entries(cleaned.relatedEntities)) {
|
|
172
|
+
cleanedRelated[entityName] = this.removeSections(entityData, sections);
|
|
173
|
+
}
|
|
174
|
+
cleaned.relatedEntities = cleanedRelated;
|
|
175
|
+
}
|
|
176
|
+
return cleaned;
|
|
177
|
+
}
|
|
178
|
+
return data;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
exports.FileResetService = FileResetService;
|
|
182
|
+
//# sourceMappingURL=FileResetService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileResetService.js","sourceRoot":"","sources":["../../src/services/FileResetService.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs-extra';\nimport path from 'path';\nimport fastGlob from 'fast-glob';\nimport { loadSyncConfig } from '../config';\nimport { configManager } from '../lib/config-manager';\n\nexport interface FileResetOptions {\n sections?: 'both' | 'primaryKey' | 'sync';\n dryRun?: boolean;\n noBackup?: boolean;\n verbose?: boolean;\n}\n\nexport interface FileResetCallbacks {\n onProgress?: (message: string) => void;\n onLog?: (message: string) => void;\n onWarn?: (message: string) => void;\n onConfirm?: (message: string) => Promise<boolean>;\n}\n\nexport interface FileResetResult {\n processedFiles: number;\n modifiedFiles: number;\n totalPrimaryKeys: number;\n totalSyncs: number;\n filesWithPrimaryKey: number;\n filesWithSync: number;\n backupsCreated: number;\n}\n\nexport interface FileStats {\n primaryKeyCount: number;\n syncCount: number;\n}\n\nexport class FileResetService {\n \n async resetFiles(options: FileResetOptions = {}, callbacks?: FileResetCallbacks): Promise<FileResetResult> {\n const sections = options.sections || 'both';\n \n // Load sync config\n const syncConfig = await loadSyncConfig(configManager.getOriginalCwd());\n if (!syncConfig) {\n throw new Error('No .mj-sync.json found in current directory');\n }\n \n // Find all metadata JSON files\n callbacks?.onProgress?.('Finding metadata files');\n const pattern = syncConfig.filePattern || '.*.json';\n const files = await fastGlob(pattern, {\n cwd: configManager.getOriginalCwd(),\n absolute: true,\n ignore: ['.mj-sync.json', '.mj-folder.json'],\n });\n \n if (files.length === 0) {\n callbacks?.onLog?.('No metadata files found');\n return {\n processedFiles: 0,\n modifiedFiles: 0,\n totalPrimaryKeys: 0,\n totalSyncs: 0,\n filesWithPrimaryKey: 0,\n filesWithSync: 0,\n backupsCreated: 0\n };\n }\n \n callbacks?.onLog?.(`Found ${files.length} metadata file${files.length === 1 ? '' : 's'}`);\n \n // Count what will be removed\n let filesWithPrimaryKey = 0;\n let filesWithSync = 0;\n let totalPrimaryKeys = 0;\n let totalSyncs = 0;\n \n for (const file of files) {\n const content = await fs.readJson(file);\n const stats = this.countSections(content);\n if (stats.primaryKeyCount > 0) {\n filesWithPrimaryKey++;\n totalPrimaryKeys += stats.primaryKeyCount;\n }\n if (stats.syncCount > 0) {\n filesWithSync++;\n totalSyncs += stats.syncCount;\n }\n }\n \n // Report what will be removed\n if (sections === 'both' || sections === 'primaryKey') {\n callbacks?.onLog?.(`Will remove ${totalPrimaryKeys} primaryKey section${totalPrimaryKeys === 1 ? '' : 's'} from ${filesWithPrimaryKey} file${filesWithPrimaryKey === 1 ? '' : 's'}`);\n }\n if (sections === 'both' || sections === 'sync') {\n callbacks?.onLog?.(`Will remove ${totalSyncs} sync section${totalSyncs === 1 ? '' : 's'} from ${filesWithSync} file${filesWithSync === 1 ? '' : 's'}`);\n }\n \n if (options.dryRun) {\n callbacks?.onLog?.('Dry run mode - no files will be modified');\n \n if (options.verbose) {\n for (const file of files) {\n const content = await fs.readJson(file);\n const stats = this.countSections(content);\n if (stats.primaryKeyCount > 0 || stats.syncCount > 0) {\n callbacks?.onLog?.(`${path.relative(configManager.getOriginalCwd(), file)}:`);\n if (stats.primaryKeyCount > 0) {\n callbacks?.onLog?.(` - ${stats.primaryKeyCount} primaryKey section${stats.primaryKeyCount === 1 ? '' : 's'}`);\n }\n if (stats.syncCount > 0) {\n callbacks?.onLog?.(` - ${stats.syncCount} sync section${stats.syncCount === 1 ? '' : 's'}`);\n }\n }\n }\n }\n \n return {\n processedFiles: files.length,\n modifiedFiles: 0,\n totalPrimaryKeys,\n totalSyncs,\n filesWithPrimaryKey,\n filesWithSync,\n backupsCreated: 0\n };\n }\n \n // Process files\n callbacks?.onProgress?.('Processing files');\n let processedFiles = 0;\n let modifiedFiles = 0;\n let backupsCreated = 0;\n \n for (const file of files) {\n processedFiles++;\n const content = await fs.readJson(file);\n const originalContent = JSON.stringify(content);\n \n // Remove sections\n const cleanedContent = this.removeSections(content, sections);\n \n // Only write if content changed\n if (JSON.stringify(cleanedContent) !== originalContent) {\n // Create backup if requested\n if (!options.noBackup) {\n const backupPath = `${file}.backup`;\n await fs.writeJson(backupPath, content, { spaces: 2 });\n backupsCreated++;\n }\n \n // Write cleaned content\n await fs.writeJson(file, cleanedContent, { spaces: 2 });\n modifiedFiles++;\n \n if (options.verbose) {\n callbacks?.onLog?.(`✓ ${path.relative(configManager.getOriginalCwd(), file)}`);\n }\n }\n }\n \n return {\n processedFiles,\n modifiedFiles,\n totalPrimaryKeys,\n totalSyncs,\n filesWithPrimaryKey,\n filesWithSync,\n backupsCreated\n };\n }\n \n private countSections(data: any): FileStats {\n let primaryKeyCount = 0;\n let syncCount = 0;\n \n if (Array.isArray(data)) {\n for (const item of data) {\n const stats = this.countSections(item);\n primaryKeyCount += stats.primaryKeyCount;\n syncCount += stats.syncCount;\n }\n } else if (data && typeof data === 'object') {\n if ('primaryKey' in data) primaryKeyCount++;\n if ('sync' in data) syncCount++;\n \n // Check related entities\n if (data.relatedEntities) {\n for (const entityData of Object.values(data.relatedEntities)) {\n const stats = this.countSections(entityData);\n primaryKeyCount += stats.primaryKeyCount;\n syncCount += stats.syncCount;\n }\n }\n }\n \n return { primaryKeyCount, syncCount };\n }\n \n private removeSections(data: any, sections: string): any {\n if (Array.isArray(data)) {\n return data.map(item => this.removeSections(item, sections));\n } else if (data && typeof data === 'object') {\n const cleaned = { ...data };\n \n // Remove specified sections\n if (sections === 'both' || sections === 'primaryKey') {\n delete cleaned.primaryKey;\n }\n if (sections === 'both' || sections === 'sync') {\n delete cleaned.sync;\n }\n \n // Process related entities\n if (cleaned.relatedEntities) {\n const cleanedRelated: any = {};\n for (const [entityName, entityData] of Object.entries(cleaned.relatedEntities)) {\n cleanedRelated[entityName] = this.removeSections(entityData, sections);\n }\n cleaned.relatedEntities = cleanedRelated;\n }\n \n return cleaned;\n }\n \n return data;\n }\n}"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface InitOptions {
|
|
2
|
+
overwrite?: boolean;
|
|
3
|
+
setupEntity?: 'ai-prompts' | 'other' | 'no';
|
|
4
|
+
entityName?: string;
|
|
5
|
+
dirName?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface InitCallbacks {
|
|
8
|
+
onProgress?: (message: string) => void;
|
|
9
|
+
onSuccess?: (message: string) => void;
|
|
10
|
+
onError?: (message: string) => void;
|
|
11
|
+
}
|
|
12
|
+
export declare class InitService {
|
|
13
|
+
initialize(options?: InitOptions, callbacks?: InitCallbacks): Promise<void>;
|
|
14
|
+
private createAIPromptsExample;
|
|
15
|
+
getNextSteps(): string[];
|
|
16
|
+
getErrorHint(error: Error | string): string | null;
|
|
17
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.InitService = void 0;
|
|
7
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
class InitService {
|
|
10
|
+
async initialize(options = {}, callbacks) {
|
|
11
|
+
try {
|
|
12
|
+
// Check if already initialized
|
|
13
|
+
if (await fs_extra_1.default.pathExists('.mj-sync.json')) {
|
|
14
|
+
if (!options.overwrite) {
|
|
15
|
+
throw new Error('Directory already initialized. Use overwrite option to proceed.');
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
// Create root configuration
|
|
19
|
+
const rootConfig = {
|
|
20
|
+
version: '1.0.0',
|
|
21
|
+
push: {
|
|
22
|
+
validateBeforePush: true,
|
|
23
|
+
requireConfirmation: true
|
|
24
|
+
},
|
|
25
|
+
watch: {
|
|
26
|
+
debounceMs: 1000,
|
|
27
|
+
ignorePatterns: ['*.tmp', '*.bak', '.DS_Store']
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
callbacks?.onProgress?.('Creating root configuration');
|
|
31
|
+
await fs_extra_1.default.writeJson('.mj-sync.json', rootConfig, { spaces: 2 });
|
|
32
|
+
callbacks?.onSuccess?.('Created .mj-sync.json');
|
|
33
|
+
// Set up entity directory if requested
|
|
34
|
+
if (options.setupEntity && options.setupEntity !== 'no') {
|
|
35
|
+
const entityName = options.setupEntity === 'ai-prompts'
|
|
36
|
+
? 'AI Prompts'
|
|
37
|
+
: options.entityName || '';
|
|
38
|
+
const dirName = options.setupEntity === 'ai-prompts'
|
|
39
|
+
? 'ai-prompts'
|
|
40
|
+
: options.dirName || entityName.toLowerCase().replace(/\s+/g, '-');
|
|
41
|
+
// Create entity directory
|
|
42
|
+
callbacks?.onProgress?.(`Creating ${dirName} directory`);
|
|
43
|
+
await fs_extra_1.default.ensureDir(dirName);
|
|
44
|
+
// Create entity configuration
|
|
45
|
+
const entityConfig = {
|
|
46
|
+
entity: entityName,
|
|
47
|
+
filePattern: '*.json',
|
|
48
|
+
defaults: {}
|
|
49
|
+
};
|
|
50
|
+
await fs_extra_1.default.writeJson(path_1.default.join(dirName, '.mj-sync.json'), entityConfig, { spaces: 2 });
|
|
51
|
+
callbacks?.onSuccess?.(`Created ${dirName} directory with entity configuration`);
|
|
52
|
+
// Create example structure
|
|
53
|
+
if (options.setupEntity === 'ai-prompts') {
|
|
54
|
+
await this.createAIPromptsExample(dirName);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
60
|
+
callbacks?.onError?.(errorMessage);
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async createAIPromptsExample(dirName) {
|
|
65
|
+
const exampleDir = path_1.default.join(dirName, 'examples');
|
|
66
|
+
await fs_extra_1.default.ensureDir(exampleDir);
|
|
67
|
+
// Create folder config
|
|
68
|
+
const folderConfig = {
|
|
69
|
+
defaults: {
|
|
70
|
+
CategoryID: '@lookup:AI Prompt Categories.Name=Examples',
|
|
71
|
+
Temperature: 0.7
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
await fs_extra_1.default.writeJson(path_1.default.join(exampleDir, '.mj-folder.json'), folderConfig, { spaces: 2 });
|
|
75
|
+
// Create example prompt
|
|
76
|
+
const examplePrompt = {
|
|
77
|
+
_primaryKey: {
|
|
78
|
+
ID: 'example-001'
|
|
79
|
+
},
|
|
80
|
+
_fields: {
|
|
81
|
+
Name: 'Example Greeting Prompt',
|
|
82
|
+
Description: 'A simple example prompt to demonstrate the sync tool',
|
|
83
|
+
PromptTypeID: '@lookup:AI Prompt Types.Name=Chat',
|
|
84
|
+
Temperature: 0.8,
|
|
85
|
+
MaxTokens: 150,
|
|
86
|
+
Prompt: '@file:greeting.prompt.md'
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
await fs_extra_1.default.writeJson(path_1.default.join(exampleDir, 'greeting.json'), examplePrompt, { spaces: 2 });
|
|
90
|
+
// Create the markdown file
|
|
91
|
+
const promptContent = `You are a friendly assistant. Please greet the user warmly and ask how you can help them today.
|
|
92
|
+
|
|
93
|
+
Be conversational and welcoming in your tone.`;
|
|
94
|
+
await fs_extra_1.default.writeFile(path_1.default.join(exampleDir, 'greeting.prompt.md'), promptContent);
|
|
95
|
+
}
|
|
96
|
+
getNextSteps() {
|
|
97
|
+
return [
|
|
98
|
+
'Run "mj sync pull --entity=\'AI Prompts\'" to pull existing data',
|
|
99
|
+
'Edit files locally',
|
|
100
|
+
'Run "mj sync push" to sync changes back to the database'
|
|
101
|
+
];
|
|
102
|
+
}
|
|
103
|
+
getErrorHint(error) {
|
|
104
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
105
|
+
if (errorMessage.includes('permission') || errorMessage.includes('EACCES')) {
|
|
106
|
+
return 'This appears to be a file permission issue. Make sure you have write permissions in the current directory.';
|
|
107
|
+
}
|
|
108
|
+
else if (errorMessage.includes('ENOENT') || errorMessage.includes('no such file')) {
|
|
109
|
+
return 'This appears to be a file or directory access issue. Make sure the current directory exists and is accessible.';
|
|
110
|
+
}
|
|
111
|
+
else if (errorMessage.includes('already exists') || errorMessage.includes('EEXIST')) {
|
|
112
|
+
return 'Files or directories already exist. Try using the overwrite option or manually remove existing files.';
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
exports.InitService = InitService;
|
|
118
|
+
//# sourceMappingURL=InitService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InitService.js","sourceRoot":"","sources":["../../src/services/InitService.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs-extra';\nimport path from 'path';\n\nexport interface InitOptions {\n overwrite?: boolean;\n setupEntity?: 'ai-prompts' | 'other' | 'no';\n entityName?: string;\n dirName?: string;\n}\n\nexport interface InitCallbacks {\n onProgress?: (message: string) => void;\n onSuccess?: (message: string) => void;\n onError?: (message: string) => void;\n}\n\nexport class InitService {\n async initialize(options: InitOptions = {}, callbacks?: InitCallbacks): Promise<void> {\n try {\n // Check if already initialized\n if (await fs.pathExists('.mj-sync.json')) {\n if (!options.overwrite) {\n throw new Error('Directory already initialized. Use overwrite option to proceed.');\n }\n }\n \n // Create root configuration\n const rootConfig = {\n version: '1.0.0',\n push: {\n validateBeforePush: true,\n requireConfirmation: true\n },\n watch: {\n debounceMs: 1000,\n ignorePatterns: ['*.tmp', '*.bak', '.DS_Store']\n }\n };\n \n callbacks?.onProgress?.('Creating root configuration');\n await fs.writeJson('.mj-sync.json', rootConfig, { spaces: 2 });\n callbacks?.onSuccess?.('Created .mj-sync.json');\n \n // Set up entity directory if requested\n if (options.setupEntity && options.setupEntity !== 'no') {\n const entityName = options.setupEntity === 'ai-prompts' \n ? 'AI Prompts'\n : options.entityName || '';\n \n const dirName = options.setupEntity === 'ai-prompts'\n ? 'ai-prompts'\n : options.dirName || entityName.toLowerCase().replace(/\\s+/g, '-');\n \n // Create entity directory\n callbacks?.onProgress?.(`Creating ${dirName} directory`);\n await fs.ensureDir(dirName);\n \n // Create entity configuration\n const entityConfig = {\n entity: entityName,\n filePattern: '*.json',\n defaults: {}\n };\n \n await fs.writeJson(path.join(dirName, '.mj-sync.json'), entityConfig, { spaces: 2 });\n callbacks?.onSuccess?.(`Created ${dirName} directory with entity configuration`);\n \n // Create example structure\n if (options.setupEntity === 'ai-prompts') {\n await this.createAIPromptsExample(dirName);\n }\n }\n \n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n callbacks?.onError?.(errorMessage);\n throw error;\n }\n }\n \n private async createAIPromptsExample(dirName: string): Promise<void> {\n const exampleDir = path.join(dirName, 'examples');\n await fs.ensureDir(exampleDir);\n \n // Create folder config\n const folderConfig = {\n defaults: {\n CategoryID: '@lookup:AI Prompt Categories.Name=Examples',\n Temperature: 0.7\n }\n };\n \n await fs.writeJson(path.join(exampleDir, '.mj-folder.json'), folderConfig, { spaces: 2 });\n \n // Create example prompt\n const examplePrompt = {\n _primaryKey: {\n ID: 'example-001'\n },\n _fields: {\n Name: 'Example Greeting Prompt',\n Description: 'A simple example prompt to demonstrate the sync tool',\n PromptTypeID: '@lookup:AI Prompt Types.Name=Chat',\n Temperature: 0.8,\n MaxTokens: 150,\n Prompt: '@file:greeting.prompt.md'\n }\n };\n \n await fs.writeJson(\n path.join(exampleDir, 'greeting.json'), \n examplePrompt, \n { spaces: 2 }\n );\n \n // Create the markdown file\n const promptContent = `You are a friendly assistant. Please greet the user warmly and ask how you can help them today.\n\nBe conversational and welcoming in your tone.`;\n \n await fs.writeFile(\n path.join(exampleDir, 'greeting.prompt.md'),\n promptContent\n );\n }\n \n getNextSteps(): string[] {\n return [\n 'Run \"mj sync pull --entity=\\'AI Prompts\\'\" to pull existing data',\n 'Edit files locally',\n 'Run \"mj sync push\" to sync changes back to the database'\n ];\n }\n \n getErrorHint(error: Error | string): string | null {\n const errorMessage = error instanceof Error ? error.message : String(error);\n \n if (errorMessage.includes('permission') || errorMessage.includes('EACCES')) {\n return 'This appears to be a file permission issue. Make sure you have write permissions in the current directory.';\n } else if (errorMessage.includes('ENOENT') || errorMessage.includes('no such file')) {\n return 'This appears to be a file or directory access issue. Make sure the current directory exists and is accessible.';\n } else if (errorMessage.includes('already exists') || errorMessage.includes('EEXIST')) {\n return 'Files or directories already exist. Try using the overwrite option or manually remove existing files.';\n }\n \n return null;\n }\n}"]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { UserInfo } from '@memberjunction/core';
|
|
2
|
+
import { SyncEngine } from '../lib/sync-engine';
|
|
3
|
+
export interface PullOptions {
|
|
4
|
+
entity: string;
|
|
5
|
+
filter?: string;
|
|
6
|
+
dryRun?: boolean;
|
|
7
|
+
multiFile?: string;
|
|
8
|
+
verbose?: boolean;
|
|
9
|
+
noValidate?: boolean;
|
|
10
|
+
targetDir?: string;
|
|
11
|
+
updateExistingRecords?: boolean;
|
|
12
|
+
createNewFileIfNotFound?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface PullCallbacks {
|
|
15
|
+
onProgress?: (message: string) => void;
|
|
16
|
+
onSuccess?: (message: string) => void;
|
|
17
|
+
onError?: (message: string) => void;
|
|
18
|
+
onWarn?: (message: string) => void;
|
|
19
|
+
onLog?: (message: string) => void;
|
|
20
|
+
}
|
|
21
|
+
export interface PullResult {
|
|
22
|
+
processed: number;
|
|
23
|
+
created: number;
|
|
24
|
+
updated: number;
|
|
25
|
+
skipped: number;
|
|
26
|
+
targetDir: string;
|
|
27
|
+
}
|
|
28
|
+
export declare class PullService {
|
|
29
|
+
private syncEngine;
|
|
30
|
+
private contextUser;
|
|
31
|
+
constructor(syncEngine: SyncEngine, contextUser: UserInfo);
|
|
32
|
+
pull(options: PullOptions, callbacks?: PullCallbacks): Promise<PullResult>;
|
|
33
|
+
private handleAsyncPropertyLoading;
|
|
34
|
+
private processRecords;
|
|
35
|
+
private processIndividualRecords;
|
|
36
|
+
private processRecord;
|
|
37
|
+
private processRecordData;
|
|
38
|
+
private findEntityDirectories;
|
|
39
|
+
private buildFileName;
|
|
40
|
+
private findExistingFiles;
|
|
41
|
+
private loadExistingRecords;
|
|
42
|
+
private createPrimaryKeyLookup;
|
|
43
|
+
private mergeRecords;
|
|
44
|
+
private createBackup;
|
|
45
|
+
}
|