@tenonhq/dovetail-core 0.0.85
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 +6 -0
- package/dist/FileLogger.js +207 -0
- package/dist/FileUtils.js +387 -0
- package/dist/Logger.js +88 -0
- package/dist/MultiScopeWatcher.js +615 -0
- package/dist/PluginManager.js +125 -0
- package/dist/_defaultOptionsOLD.js +44 -0
- package/dist/allScopesCommands.js +418 -0
- package/dist/appUtils.js +929 -0
- package/dist/benchmark.js +104 -0
- package/dist/bootstrap.js +62 -0
- package/dist/claudeCommand.js +60 -0
- package/dist/clickupCommands.js +472 -0
- package/dist/clickupPushHelper.js +33 -0
- package/dist/commander.js +466 -0
- package/dist/commands.js +378 -0
- package/dist/config.js +697 -0
- package/dist/constants.js +15 -0
- package/dist/createRecordCommand.js +314 -0
- package/dist/dashboardCommand.js +38 -0
- package/dist/defaultOptions.js +14 -0
- package/dist/deleteRecordCommand.js +282 -0
- package/dist/flowDesigner/values.js +55 -0
- package/dist/genericUtils.js +189 -0
- package/dist/gitUtils.js +99 -0
- package/dist/index.js +35 -0
- package/dist/initSystem/corePlugin.js +344 -0
- package/dist/initSystem/discovery.js +107 -0
- package/dist/initSystem/orchestrator.js +408 -0
- package/dist/logMessages.js +82 -0
- package/dist/loginCommand.js +20 -0
- package/dist/migrateCommand.js +123 -0
- package/dist/projectFiles.js +32 -0
- package/dist/recentEdits.js +66 -0
- package/dist/schemaCommand.js +85 -0
- package/dist/snClient.js +519 -0
- package/dist/tests/benchmarkRefresh.test.js +265 -0
- package/dist/tests/clickupCommands.test.js +384 -0
- package/dist/tests/clickupPushHelper.test.js +124 -0
- package/dist/tests/configFallback.test.js +68 -0
- package/dist/tests/cred.test.js +59 -0
- package/dist/tests/discovery.test.js +67 -0
- package/dist/tests/ensureUpdateSetWarnings.test.js +218 -0
- package/dist/tests/errorLogLevels.test.js +273 -0
- package/dist/tests/example.test.js +6 -0
- package/dist/tests/fileContextSkipReason.test.js +116 -0
- package/dist/tests/globalDebounce.test.js +308 -0
- package/dist/tests/migrateCommand.test.js +113 -0
- package/dist/tests/multi-scope-watcher.test.js +558 -0
- package/dist/tests/orchestrator.test.js +23 -0
- package/dist/tests/pushFiles.test.js +248 -0
- package/dist/tests/rateLimitCoordination.test.js +271 -0
- package/dist/tests/resolveConfigReadOnly.test.js +67 -0
- package/dist/tests/retryOnHttpErr.test.js +154 -0
- package/dist/tests/scopeCaching.test.js +115 -0
- package/dist/tests/serializeUpdateSetConfig.test.js +325 -0
- package/dist/tests/snClient.fallback.test.js +120 -0
- package/dist/tests/syncManifestRefresh.test.js +287 -0
- package/dist/tests/syncManifestWhitelist.test.js +192 -0
- package/dist/tests/taskClear.test.js +170 -0
- package/dist/tests/taskStaleness.test.js +220 -0
- package/dist/tests/unwrapSNResponseError.test.js +145 -0
- package/dist/tests/v2Values.test.js +79 -0
- package/dist/tests/validateTaskId.test.js +304 -0
- package/dist/tests/verifyUpdateSetSwitch.test.js +277 -0
- package/dist/tests/writeEnvVar.test.js +119 -0
- package/dist/updateSetCommands.js +702 -0
- package/dist/wizard.js +40 -0
- package/package.json +69 -0
- package/skills/dove-configure-pipeline.md +158 -0
- package/skills/dove-create-plugin.md +174 -0
- package/skills/dove-create-record.md +135 -0
- package/skills/dove-debug-build.md +117 -0
- package/skills/dove-delete-record.md +104 -0
- package/skills/dove-manage-tables.md +174 -0
- package/skills/dove-manage-update-sets.md +88 -0
- package/skills/dove-setup-project.md +154 -0
- package/skills/dove-troubleshoot-sync.md +113 -0
package/README.md
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.fileLogger = void 0;
|
|
40
|
+
exports.enableFileLogging = enableFileLogging;
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
44
|
+
class FileLogger {
|
|
45
|
+
logFilePath;
|
|
46
|
+
logStream = null;
|
|
47
|
+
initialized = false;
|
|
48
|
+
constructor() {
|
|
49
|
+
// Initialize on first use
|
|
50
|
+
this.logFilePath = "";
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Initialize the file logger in the current working directory
|
|
54
|
+
*/
|
|
55
|
+
initialize() {
|
|
56
|
+
if (this.initialized)
|
|
57
|
+
return;
|
|
58
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
59
|
+
const logFileName = `dovetail-debug-${timestamp}.log`;
|
|
60
|
+
// Create log file in the current working directory (ServiceNow folder)
|
|
61
|
+
this.logFilePath = path.join(process.cwd(), logFileName);
|
|
62
|
+
try {
|
|
63
|
+
// Create or append to the log file
|
|
64
|
+
this.logStream = fs.createWriteStream(this.logFilePath, { flags: 'a' });
|
|
65
|
+
this.initialized = true;
|
|
66
|
+
// Write header to log file
|
|
67
|
+
this.writeToFile(`\n${"=".repeat(80)}`);
|
|
68
|
+
this.writeToFile(`Dovetail Debug Log - Started at ${new Date().toISOString()}`);
|
|
69
|
+
this.writeToFile(`Log file: ${this.logFilePath}`);
|
|
70
|
+
this.writeToFile(`Working directory: ${process.cwd()}`);
|
|
71
|
+
this.writeToFile(`${"=".repeat(80)}\n`);
|
|
72
|
+
// Also log to console
|
|
73
|
+
console.log(chalk_1.default.cyan(`📝 Debug logging enabled: ${this.logFilePath}`));
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
console.error(chalk_1.default.red(`Failed to create log file: ${error}`));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Write a message to the log file
|
|
81
|
+
*/
|
|
82
|
+
writeToFile(message) {
|
|
83
|
+
if (!this.initialized) {
|
|
84
|
+
this.initialize();
|
|
85
|
+
}
|
|
86
|
+
if (this.logStream && this.logStream.writable) {
|
|
87
|
+
const timestamp = new Date().toISOString();
|
|
88
|
+
this.logStream.write(`[${timestamp}] ${message}\n`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Format a message for both console and file output
|
|
93
|
+
*/
|
|
94
|
+
formatMessage(level, message, ...args) {
|
|
95
|
+
let fullMessage = message;
|
|
96
|
+
// If there are additional arguments, stringify them
|
|
97
|
+
if (args.length > 0) {
|
|
98
|
+
const additionalInfo = args.map(arg => {
|
|
99
|
+
if (typeof arg === 'object') {
|
|
100
|
+
try {
|
|
101
|
+
return JSON.stringify(arg, null, 2);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return String(arg);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return String(arg);
|
|
108
|
+
}).join(' ');
|
|
109
|
+
fullMessage = `${message} ${additionalInfo}`;
|
|
110
|
+
}
|
|
111
|
+
return fullMessage;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Debug level logging - file only, no console output
|
|
115
|
+
*/
|
|
116
|
+
debug(message, ...args) {
|
|
117
|
+
const formattedMessage = this.formatMessage('DEBUG', message, ...args);
|
|
118
|
+
this.writeToFile(`[DEBUG] ${formattedMessage}`);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Info level logging
|
|
122
|
+
*/
|
|
123
|
+
info(message, ...args) {
|
|
124
|
+
const formattedMessage = this.formatMessage('INFO', message, ...args);
|
|
125
|
+
// Write to console with color
|
|
126
|
+
console.log(chalk_1.default.blue(message), ...args);
|
|
127
|
+
// Write to file
|
|
128
|
+
this.writeToFile(`[INFO] ${formattedMessage}`);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Warning level logging
|
|
132
|
+
*/
|
|
133
|
+
warn(message, ...args) {
|
|
134
|
+
const formattedMessage = this.formatMessage('WARN', message, ...args);
|
|
135
|
+
// Write to console with color
|
|
136
|
+
console.log(chalk_1.default.yellow(message), ...args);
|
|
137
|
+
// Write to file
|
|
138
|
+
this.writeToFile(`[WARN] ${formattedMessage}`);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Error level logging
|
|
142
|
+
*/
|
|
143
|
+
error(message, ...args) {
|
|
144
|
+
const formattedMessage = this.formatMessage('ERROR', message, ...args);
|
|
145
|
+
// Write to console with color
|
|
146
|
+
console.error(chalk_1.default.red(message), ...args);
|
|
147
|
+
// Write to file
|
|
148
|
+
this.writeToFile(`[ERROR] ${formattedMessage}`);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Success level logging
|
|
152
|
+
*/
|
|
153
|
+
success(message, ...args) {
|
|
154
|
+
const formattedMessage = this.formatMessage('SUCCESS', message, ...args);
|
|
155
|
+
// Write to console with color
|
|
156
|
+
console.log(chalk_1.default.green(message), ...args);
|
|
157
|
+
// Write to file
|
|
158
|
+
this.writeToFile(`[SUCCESS] ${formattedMessage}`);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Close the log file stream
|
|
162
|
+
*/
|
|
163
|
+
close() {
|
|
164
|
+
if (this.logStream) {
|
|
165
|
+
this.writeToFile(`\n${"=".repeat(80)}`);
|
|
166
|
+
this.writeToFile(`Log session ended at ${new Date().toISOString()}`);
|
|
167
|
+
this.writeToFile(`${"=".repeat(80)}\n`);
|
|
168
|
+
this.logStream.end();
|
|
169
|
+
this.logStream = null;
|
|
170
|
+
this.initialized = false;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Get the path to the current log file
|
|
175
|
+
*/
|
|
176
|
+
getLogFilePath() {
|
|
177
|
+
return this.logFilePath;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// Create singleton instance
|
|
181
|
+
const fileLogger = new FileLogger();
|
|
182
|
+
exports.fileLogger = fileLogger;
|
|
183
|
+
// Also export a function to replace console.log globally
|
|
184
|
+
function enableFileLogging() {
|
|
185
|
+
// Store original console.log
|
|
186
|
+
const originalConsoleLog = console.log;
|
|
187
|
+
// Override console.log to also write to file
|
|
188
|
+
console.log = function (...args) {
|
|
189
|
+
// Call original console.log
|
|
190
|
+
originalConsoleLog.apply(console, args);
|
|
191
|
+
// Also write to file
|
|
192
|
+
const message = args.map(arg => {
|
|
193
|
+
if (typeof arg === 'object') {
|
|
194
|
+
try {
|
|
195
|
+
return JSON.stringify(arg, null, 2);
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
return String(arg);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return String(arg);
|
|
202
|
+
}).join(' ');
|
|
203
|
+
fileLogger.debug(message);
|
|
204
|
+
};
|
|
205
|
+
// Log that file logging is enabled
|
|
206
|
+
fileLogger.info('File logging has been enabled for this session');
|
|
207
|
+
}
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.writeFileForce = exports.writeSNFileForce = exports.writeSNFileIfNotExists = exports.writeBuildFile = exports.summarizeFile = exports.encodedPathsToFilePaths = exports.isValidPath = exports.splitEncodedPaths = exports.getPathsInPath = exports.isDirectory = exports.toAbsolutePath = exports.getFileContextFromPath = exports.getFileContextWithSkipReason = exports.getBuildExt = exports.isUnderPath = exports.appendToPath = exports.pathExists = exports.createDirRecursively = exports.writeSNFileIfDifferent = exports.writeSNFileCurry = exports.writeScopeManifest = exports.writeManifestFile = exports.SNFileExists = void 0;
|
|
40
|
+
exports.writeEnvVar = writeEnvVar;
|
|
41
|
+
exports.writeEnvVars = writeEnvVars;
|
|
42
|
+
const constants_1 = require("./constants");
|
|
43
|
+
const fs_1 = __importStar(require("fs"));
|
|
44
|
+
const path_1 = __importDefault(require("path"));
|
|
45
|
+
const ConfigManager = __importStar(require("./config"));
|
|
46
|
+
const FileLogger_1 = require("./FileLogger");
|
|
47
|
+
const SNFileExists = (parentDirPath) => async (file) => {
|
|
48
|
+
try {
|
|
49
|
+
const files = await fs_1.promises.readdir(parentDirPath);
|
|
50
|
+
const reg = new RegExp(`${file.name}\..*$`);
|
|
51
|
+
return !!files.find((f) => reg.test(f));
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
exports.SNFileExists = SNFileExists;
|
|
58
|
+
const writeManifestFile = async (man, scope) => {
|
|
59
|
+
if (scope) {
|
|
60
|
+
const manifestPath = ConfigManager.getScopeManifestPath(scope);
|
|
61
|
+
FileLogger_1.fileLogger.debug("Writing manifest for scope " + scope + " to " + manifestPath);
|
|
62
|
+
return fs_1.promises.writeFile(manifestPath, JSON.stringify(man, null, 2));
|
|
63
|
+
}
|
|
64
|
+
const manifestPath = ConfigManager.getManifestPath();
|
|
65
|
+
FileLogger_1.fileLogger.debug("Writing manifest to " + manifestPath);
|
|
66
|
+
return fs_1.promises.writeFile(manifestPath, JSON.stringify(man, null, 2));
|
|
67
|
+
};
|
|
68
|
+
exports.writeManifestFile = writeManifestFile;
|
|
69
|
+
const writeScopeManifest = async (scope, man) => {
|
|
70
|
+
const manifestPath = ConfigManager.getScopeManifestPath(scope);
|
|
71
|
+
FileLogger_1.fileLogger.debug("Writing scope manifest: " + scope + " -> " + manifestPath);
|
|
72
|
+
return fs_1.promises.writeFile(manifestPath, JSON.stringify(man, null, 2));
|
|
73
|
+
};
|
|
74
|
+
exports.writeScopeManifest = writeScopeManifest;
|
|
75
|
+
const writeSNFileCurry = (checkExists) => async (file, parentPath) => {
|
|
76
|
+
let { name, type, content = "" } = file;
|
|
77
|
+
if (!content) {
|
|
78
|
+
content = "";
|
|
79
|
+
}
|
|
80
|
+
const fullPath = path_1.default.join(parentPath, `${name}.${type}`);
|
|
81
|
+
const write = async () => {
|
|
82
|
+
FileLogger_1.fileLogger.debug("Writing: " + fullPath);
|
|
83
|
+
try {
|
|
84
|
+
const result = await fs_1.promises.writeFile(fullPath, content);
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
FileLogger_1.fileLogger.error("Failed to write " + fullPath + ":", error);
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
if (checkExists) {
|
|
93
|
+
const exists = await (0, exports.SNFileExists)(parentPath)(file);
|
|
94
|
+
if (!exists) {
|
|
95
|
+
await write();
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
FileLogger_1.fileLogger.debug("Skipped (exists): " + fullPath);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
await write();
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
exports.writeSNFileCurry = writeSNFileCurry;
|
|
106
|
+
/**
|
|
107
|
+
* Writes the SN file to disk only if the local content differs from `file.content`.
|
|
108
|
+
* Returns `true` if the file was written (missing or differed), `false` if skipped.
|
|
109
|
+
*
|
|
110
|
+
* Used by `sinc refresh` to pull ServiceNow-side edits without churning unchanged
|
|
111
|
+
* files (preserves mtime, avoids noisy watchers, keeps diff output clean).
|
|
112
|
+
*/
|
|
113
|
+
const writeSNFileIfDifferent = async (file, parentPath) => {
|
|
114
|
+
let { name, type, content = "" } = file;
|
|
115
|
+
if (!content)
|
|
116
|
+
content = "";
|
|
117
|
+
const fullPath = path_1.default.join(parentPath, `${name}.${type}`);
|
|
118
|
+
let localContent = null;
|
|
119
|
+
try {
|
|
120
|
+
localContent = await fs_1.promises.readFile(fullPath, "utf8");
|
|
121
|
+
}
|
|
122
|
+
catch (e) {
|
|
123
|
+
localContent = null;
|
|
124
|
+
}
|
|
125
|
+
if (localContent === content) {
|
|
126
|
+
FileLogger_1.fileLogger.debug("Unchanged: " + fullPath);
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
if (localContent !== null) {
|
|
130
|
+
FileLogger_1.fileLogger.debug("Overwriting local content (differs from instance): " + fullPath);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
FileLogger_1.fileLogger.debug("Writing (missing locally): " + fullPath);
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
await fs_1.promises.writeFile(fullPath, content);
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
FileLogger_1.fileLogger.error("Failed to write " + fullPath + ":", error);
|
|
141
|
+
throw error;
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
exports.writeSNFileIfDifferent = writeSNFileIfDifferent;
|
|
145
|
+
const createDirRecursively = async (path) => {
|
|
146
|
+
await fs_1.promises.mkdir(path, { recursive: true });
|
|
147
|
+
};
|
|
148
|
+
exports.createDirRecursively = createDirRecursively;
|
|
149
|
+
const pathExists = async (path) => {
|
|
150
|
+
try {
|
|
151
|
+
await fs_1.promises.access(path, fs_1.default.constants.F_OK);
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
catch (e) {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
exports.pathExists = pathExists;
|
|
159
|
+
const appendToPath = (prefix) => (suffix) => path_1.default.join(prefix, suffix);
|
|
160
|
+
exports.appendToPath = appendToPath;
|
|
161
|
+
/**
|
|
162
|
+
* Detects if a path is under a parent directory
|
|
163
|
+
* @param parentPath full path to parent directory
|
|
164
|
+
* @param potentialChildPath full path to child directory
|
|
165
|
+
*/
|
|
166
|
+
const isUnderPath = (parentPath, potentialChildPath) => {
|
|
167
|
+
const parentTokens = parentPath.split(path_1.default.sep);
|
|
168
|
+
const childTokens = potentialChildPath.split(path_1.default.sep);
|
|
169
|
+
return parentTokens.every((token, index) => token === childTokens[index]);
|
|
170
|
+
};
|
|
171
|
+
exports.isUnderPath = isUnderPath;
|
|
172
|
+
const getFileExtension = (filePath) => {
|
|
173
|
+
try {
|
|
174
|
+
return "." + path_1.default.basename(filePath).split(".").slice(1).join(".");
|
|
175
|
+
}
|
|
176
|
+
catch (e) {
|
|
177
|
+
return "";
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
const getBuildExt = (table, recordName, field, scope) => {
|
|
181
|
+
var manifest = ConfigManager.getManifest();
|
|
182
|
+
if (!manifest) {
|
|
183
|
+
throw new Error("Failed to retrieve manifest");
|
|
184
|
+
}
|
|
185
|
+
var resolvedManifest = manifest;
|
|
186
|
+
if (scope && ConfigManager.isMultiScopeManifest(manifest)) {
|
|
187
|
+
var scopeMan = ConfigManager.resolveManifestForScope(manifest, scope);
|
|
188
|
+
if (!scopeMan) {
|
|
189
|
+
throw new Error("Failed to find scope " + scope + " in manifest");
|
|
190
|
+
}
|
|
191
|
+
resolvedManifest = scopeMan;
|
|
192
|
+
}
|
|
193
|
+
const files = resolvedManifest.tables[table].records[recordName].files;
|
|
194
|
+
const file = files.find((f) => f.name === field);
|
|
195
|
+
if (!file) {
|
|
196
|
+
throw new Error("Unable to find file");
|
|
197
|
+
}
|
|
198
|
+
return file.type;
|
|
199
|
+
};
|
|
200
|
+
exports.getBuildExt = getBuildExt;
|
|
201
|
+
const getTargetFieldFromPath = (filePath, table, ext) => {
|
|
202
|
+
return table === "sys_atf_step"
|
|
203
|
+
? "inputs.script"
|
|
204
|
+
: path_1.default.basename(filePath, ext);
|
|
205
|
+
};
|
|
206
|
+
const getFileContextWithSkipReason = (filePath) => {
|
|
207
|
+
const ext = getFileExtension(filePath);
|
|
208
|
+
const [tableName, recordName] = path_1.default
|
|
209
|
+
.dirname(filePath)
|
|
210
|
+
.split(path_1.default.sep)
|
|
211
|
+
.slice(-2);
|
|
212
|
+
const targetField = getTargetFieldFromPath(filePath, tableName, ext);
|
|
213
|
+
var manifest = ConfigManager.getManifest();
|
|
214
|
+
if (!manifest) {
|
|
215
|
+
throw new Error("No manifest has been loaded!");
|
|
216
|
+
}
|
|
217
|
+
var scope;
|
|
218
|
+
var tables;
|
|
219
|
+
if (ConfigManager.isMultiScopeManifest(manifest)) {
|
|
220
|
+
var detectedScope = ConfigManager.resolveScopeFromPath(filePath);
|
|
221
|
+
if (!detectedScope) {
|
|
222
|
+
return { skipReason: "scope not found" };
|
|
223
|
+
}
|
|
224
|
+
var scopeMan = ConfigManager.resolveManifestForScope(manifest, detectedScope);
|
|
225
|
+
if (!scopeMan) {
|
|
226
|
+
return { skipReason: "scope manifest not found" };
|
|
227
|
+
}
|
|
228
|
+
scope = scopeMan.scope || detectedScope;
|
|
229
|
+
tables = scopeMan.tables;
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
scope = manifest.scope;
|
|
233
|
+
tables = manifest.tables;
|
|
234
|
+
}
|
|
235
|
+
try {
|
|
236
|
+
const { records } = tables[tableName];
|
|
237
|
+
const record = records[recordName];
|
|
238
|
+
const { files, sys_id } = record;
|
|
239
|
+
const field = files.find((file) => file.name === targetField);
|
|
240
|
+
if (!field) {
|
|
241
|
+
return { skipReason: "not in manifest" };
|
|
242
|
+
}
|
|
243
|
+
return {
|
|
244
|
+
context: {
|
|
245
|
+
filePath,
|
|
246
|
+
ext,
|
|
247
|
+
sys_id,
|
|
248
|
+
name: recordName,
|
|
249
|
+
scope,
|
|
250
|
+
tableName,
|
|
251
|
+
targetField,
|
|
252
|
+
},
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
catch (e) {
|
|
256
|
+
return { skipReason: "not in manifest" };
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
exports.getFileContextWithSkipReason = getFileContextWithSkipReason;
|
|
260
|
+
const getFileContextFromPath = (filePath) => {
|
|
261
|
+
return (0, exports.getFileContextWithSkipReason)(filePath).context;
|
|
262
|
+
};
|
|
263
|
+
exports.getFileContextFromPath = getFileContextFromPath;
|
|
264
|
+
const toAbsolutePath = (p) => path_1.default.isAbsolute(p) ? p : path_1.default.join(process.cwd(), p);
|
|
265
|
+
exports.toAbsolutePath = toAbsolutePath;
|
|
266
|
+
const isDirectory = async (p) => {
|
|
267
|
+
const stats = await fs_1.promises.stat(p);
|
|
268
|
+
return stats.isDirectory();
|
|
269
|
+
};
|
|
270
|
+
exports.isDirectory = isDirectory;
|
|
271
|
+
const getPathsInPath = async (p) => {
|
|
272
|
+
if (!(0, exports.isUnderPath)(ConfigManager.getSourcePath(), p) &&
|
|
273
|
+
!(0, exports.isUnderPath)(ConfigManager.getBuildPath(), p)) {
|
|
274
|
+
return [];
|
|
275
|
+
}
|
|
276
|
+
const isDir = await (0, exports.isDirectory)(p);
|
|
277
|
+
if (!isDir) {
|
|
278
|
+
return [p];
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
const childPaths = await fs_1.promises.readdir(p);
|
|
282
|
+
const pathPromises = childPaths.map((childPath) => (0, exports.getPathsInPath)(path_1.default.resolve(p, childPath)));
|
|
283
|
+
const stackedPaths = await Promise.all(pathPromises);
|
|
284
|
+
return stackedPaths.flat();
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
exports.getPathsInPath = getPathsInPath;
|
|
288
|
+
const splitEncodedPaths = (encodedPaths) => encodedPaths.split(constants_1.PATH_DELIMITER).filter((p) => p && p !== "");
|
|
289
|
+
exports.splitEncodedPaths = splitEncodedPaths;
|
|
290
|
+
const isValidPath = async (path) => {
|
|
291
|
+
return (0, exports.pathExists)(path);
|
|
292
|
+
};
|
|
293
|
+
exports.isValidPath = isValidPath;
|
|
294
|
+
const encodedPathsToFilePaths = async (encodedPaths) => {
|
|
295
|
+
const pathSplits = (0, exports.splitEncodedPaths)(encodedPaths);
|
|
296
|
+
const validChecks = await Promise.all(pathSplits.map(exports.isValidPath));
|
|
297
|
+
const validSplits = pathSplits.filter((_, index) => validChecks[index]);
|
|
298
|
+
const splitPaths = await Promise.all(validSplits.map(exports.getPathsInPath));
|
|
299
|
+
const deDupedPaths = splitPaths.flat().reduce((acc, cur) => {
|
|
300
|
+
acc.add(cur);
|
|
301
|
+
return acc;
|
|
302
|
+
}, new Set());
|
|
303
|
+
return Array.from(deDupedPaths);
|
|
304
|
+
};
|
|
305
|
+
exports.encodedPathsToFilePaths = encodedPathsToFilePaths;
|
|
306
|
+
const summarizeFile = (ctx) => {
|
|
307
|
+
const { tableName, name: recordName, sys_id } = ctx;
|
|
308
|
+
return `${tableName}/${recordName}/${sys_id}`;
|
|
309
|
+
};
|
|
310
|
+
exports.summarizeFile = summarizeFile;
|
|
311
|
+
const writeBuildFile = async (folderPath, newPath, fileContents) => {
|
|
312
|
+
const buildPath = ConfigManager.getBuildPath();
|
|
313
|
+
const resolvedFolder = path_1.default.resolve(folderPath);
|
|
314
|
+
const resolvedFile = path_1.default.resolve(newPath);
|
|
315
|
+
if (!(0, exports.isUnderPath)(buildPath, resolvedFolder) || !(0, exports.isUnderPath)(buildPath, resolvedFile)) {
|
|
316
|
+
throw new Error(`Write rejected: path "${resolvedFile}" is outside build directory "${buildPath}"`);
|
|
317
|
+
}
|
|
318
|
+
try {
|
|
319
|
+
await fs_1.promises.access(folderPath, fs_1.default.constants.F_OK);
|
|
320
|
+
}
|
|
321
|
+
catch (e) {
|
|
322
|
+
await fs_1.promises.mkdir(folderPath, { recursive: true });
|
|
323
|
+
}
|
|
324
|
+
await fs_1.promises.writeFile(newPath, fileContents);
|
|
325
|
+
};
|
|
326
|
+
exports.writeBuildFile = writeBuildFile;
|
|
327
|
+
exports.writeSNFileIfNotExists = (0, exports.writeSNFileCurry)(true);
|
|
328
|
+
exports.writeSNFileForce = (0, exports.writeSNFileCurry)(false);
|
|
329
|
+
exports.writeFileForce = fs_1.promises.writeFile;
|
|
330
|
+
// ============================================================================
|
|
331
|
+
// .env File Utilities — merge-style writes (never destructive)
|
|
332
|
+
// ============================================================================
|
|
333
|
+
function escapeRegex(str) {
|
|
334
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
335
|
+
}
|
|
336
|
+
function quoteEnvValue(value) {
|
|
337
|
+
if (/[\s#"'\\]/.test(value)) {
|
|
338
|
+
return "\"" + value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n") + "\"";
|
|
339
|
+
}
|
|
340
|
+
return value;
|
|
341
|
+
}
|
|
342
|
+
function mergeEnvLine(content, key, value) {
|
|
343
|
+
const escaped = escapeRegex(key);
|
|
344
|
+
const regex = new RegExp("^" + escaped + "=.*$", "m");
|
|
345
|
+
const line = key + "=" + quoteEnvValue(value);
|
|
346
|
+
if (regex.test(content)) {
|
|
347
|
+
return content.replace(regex, line);
|
|
348
|
+
}
|
|
349
|
+
if (content.length > 0 && content.charAt(content.length - 1) !== "\n") {
|
|
350
|
+
content += "\n";
|
|
351
|
+
}
|
|
352
|
+
return content + line + "\n";
|
|
353
|
+
}
|
|
354
|
+
function readEnvFile(envPath) {
|
|
355
|
+
try {
|
|
356
|
+
return fs_1.default.readFileSync(envPath, "utf8");
|
|
357
|
+
}
|
|
358
|
+
catch (e) {
|
|
359
|
+
return "";
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* @description Writes a single env variable to a .env file, preserving existing values.
|
|
364
|
+
* @param {Object} params - Parameters object.
|
|
365
|
+
* @param {string} params.key - The environment variable name.
|
|
366
|
+
* @param {string} params.value - The value to set.
|
|
367
|
+
* @param {string} [params.envPath] - Path to .env file. Defaults to process.cwd()/.env.
|
|
368
|
+
*/
|
|
369
|
+
function writeEnvVar(params) {
|
|
370
|
+
const resolvedPath = params.envPath || path_1.default.resolve(process.cwd(), ".env");
|
|
371
|
+
const content = mergeEnvLine(readEnvFile(resolvedPath), params.key, params.value);
|
|
372
|
+
fs_1.default.writeFileSync(resolvedPath, content, "utf8");
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* @description Writes multiple env variables to a .env file in a single read/write cycle.
|
|
376
|
+
* @param {Object} params - Parameters object.
|
|
377
|
+
* @param {Array<{key: string; value: string}>} params.vars - Array of key/value pairs to write.
|
|
378
|
+
* @param {string} [params.envPath] - Path to .env file. Defaults to process.cwd()/.env.
|
|
379
|
+
*/
|
|
380
|
+
function writeEnvVars(params) {
|
|
381
|
+
const resolvedPath = params.envPath || path_1.default.resolve(process.cwd(), ".env");
|
|
382
|
+
let content = readEnvFile(resolvedPath);
|
|
383
|
+
params.vars.forEach(({ key, value }) => {
|
|
384
|
+
content = mergeEnvLine(content, key, value);
|
|
385
|
+
});
|
|
386
|
+
fs_1.default.writeFileSync(resolvedPath, content, "utf8");
|
|
387
|
+
}
|
package/dist/Logger.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.logger = void 0;
|
|
40
|
+
const winston_1 = __importStar(require("winston"));
|
|
41
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
42
|
+
class SincLogger {
|
|
43
|
+
logger;
|
|
44
|
+
constructor() {
|
|
45
|
+
this.logger = winston_1.default.createLogger(this.genLoggerOpts());
|
|
46
|
+
}
|
|
47
|
+
setLogLevel(level) {
|
|
48
|
+
this.logger = winston_1.default.createLogger(this.genLoggerOpts(level));
|
|
49
|
+
}
|
|
50
|
+
getLogLevel() {
|
|
51
|
+
return this.logger.level;
|
|
52
|
+
}
|
|
53
|
+
genLoggerOpts(level = "info") {
|
|
54
|
+
return {
|
|
55
|
+
format: winston_1.format.printf(info => {
|
|
56
|
+
return `${info.message}`;
|
|
57
|
+
}),
|
|
58
|
+
level,
|
|
59
|
+
transports: [new winston_1.transports.Console()]
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
info(text) {
|
|
63
|
+
this.logger.info(chalk_1.default.blue(text));
|
|
64
|
+
}
|
|
65
|
+
error(text) {
|
|
66
|
+
this.logger.error(chalk_1.default.red(text));
|
|
67
|
+
}
|
|
68
|
+
warn(text) {
|
|
69
|
+
this.logger.warn(chalk_1.default.yellow(text));
|
|
70
|
+
}
|
|
71
|
+
success(text) {
|
|
72
|
+
this.logger.info(chalk_1.default.green(text));
|
|
73
|
+
}
|
|
74
|
+
verbose(text) {
|
|
75
|
+
this.logger.verbose(text);
|
|
76
|
+
}
|
|
77
|
+
debug(text) {
|
|
78
|
+
this.logger.debug(text);
|
|
79
|
+
}
|
|
80
|
+
silly(text) {
|
|
81
|
+
this.logger.silly(text);
|
|
82
|
+
}
|
|
83
|
+
getInternalLogger() {
|
|
84
|
+
return this.logger;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const loggerInst = new SincLogger();
|
|
88
|
+
exports.logger = loggerInst;
|