@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/dist/config.js
ADDED
|
@@ -0,0 +1,697 @@
|
|
|
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.loadConfigs = void 0;
|
|
40
|
+
exports.getConfig = getConfig;
|
|
41
|
+
exports.getConfigPath = getConfigPath;
|
|
42
|
+
exports.checkConfigPath = checkConfigPath;
|
|
43
|
+
exports.getRootDir = getRootDir;
|
|
44
|
+
exports.getManifest = getManifest;
|
|
45
|
+
exports.getManifestPath = getManifestPath;
|
|
46
|
+
exports.getScopeManifestPath = getScopeManifestPath;
|
|
47
|
+
exports.getSourcePath = getSourcePath;
|
|
48
|
+
exports.getSourcePathForScope = getSourcePathForScope;
|
|
49
|
+
exports.getBuildPath = getBuildPath;
|
|
50
|
+
exports.getEnvPath = getEnvPath;
|
|
51
|
+
exports.getDiffPath = getDiffPath;
|
|
52
|
+
exports.getDiffFile = getDiffFile;
|
|
53
|
+
exports.getRefresh = getRefresh;
|
|
54
|
+
exports.getDefaultConfigFile = getDefaultConfigFile;
|
|
55
|
+
exports.generateConfigFile = generateConfigFile;
|
|
56
|
+
exports.loadScopeManifest = loadScopeManifest;
|
|
57
|
+
exports.updateManifest = updateManifest;
|
|
58
|
+
exports.isMultiScopeManifest = isMultiScopeManifest;
|
|
59
|
+
exports.resolveManifestForScope = resolveManifestForScope;
|
|
60
|
+
exports.resolveScopeFromPath = resolveScopeFromPath;
|
|
61
|
+
exports.loadConfigPath = loadConfigPath;
|
|
62
|
+
exports.isDirectiveKey = isDirectiveKey;
|
|
63
|
+
exports.stripDirectiveKeys = stripDirectiveKeys;
|
|
64
|
+
exports.resolveConfigForScope = resolveConfigForScope;
|
|
65
|
+
exports.getReadOnlyTablesForScope = getReadOnlyTablesForScope;
|
|
66
|
+
const path_1 = __importDefault(require("path"));
|
|
67
|
+
const fs_1 = __importStar(require("fs"));
|
|
68
|
+
const Logger_1 = require("./Logger");
|
|
69
|
+
const defaultOptions_1 = require("./defaultOptions");
|
|
70
|
+
// Resolve an artifact path, preferring the dove.* name and falling back to the
|
|
71
|
+
// legacy sinc.* name when only the legacy file exists. Returns the new path if
|
|
72
|
+
// neither exists (so writes default to the new name).
|
|
73
|
+
function resolveDovePath(rootDir, doveName, sincName) {
|
|
74
|
+
const newPath = path_1.default.join(rootDir, doveName);
|
|
75
|
+
const oldPath = path_1.default.join(rootDir, sincName);
|
|
76
|
+
if (fs_1.default.existsSync(newPath))
|
|
77
|
+
return newPath;
|
|
78
|
+
if (fs_1.default.existsSync(oldPath))
|
|
79
|
+
return oldPath;
|
|
80
|
+
return newPath;
|
|
81
|
+
}
|
|
82
|
+
const DEFAULT_CONFIG = {
|
|
83
|
+
sourceDirectory: "src",
|
|
84
|
+
buildDirectory: "build",
|
|
85
|
+
rules: [],
|
|
86
|
+
includes: defaultOptions_1.includes,
|
|
87
|
+
excludes: defaultOptions_1.excludes,
|
|
88
|
+
tableOptions: {},
|
|
89
|
+
refreshInterval: 30,
|
|
90
|
+
scopes: {},
|
|
91
|
+
};
|
|
92
|
+
let root_dir;
|
|
93
|
+
let config;
|
|
94
|
+
let manifest;
|
|
95
|
+
let config_path;
|
|
96
|
+
let source_path;
|
|
97
|
+
let build_path;
|
|
98
|
+
let env_path;
|
|
99
|
+
let manifest_path;
|
|
100
|
+
let diff_path;
|
|
101
|
+
let diff_file;
|
|
102
|
+
let refresh_interval;
|
|
103
|
+
const loadConfigs = async () => {
|
|
104
|
+
try {
|
|
105
|
+
let noConfigPath = false; //Prevents logging error messages during init
|
|
106
|
+
const path = await loadConfigPath();
|
|
107
|
+
if (path)
|
|
108
|
+
config_path = path;
|
|
109
|
+
else
|
|
110
|
+
noConfigPath = true;
|
|
111
|
+
await loadRootDir(noConfigPath);
|
|
112
|
+
const cfg = await loadConfig(noConfigPath);
|
|
113
|
+
if (cfg)
|
|
114
|
+
config = cfg;
|
|
115
|
+
await loadEnvPath();
|
|
116
|
+
await loadSourcePath();
|
|
117
|
+
await loadBuildPath();
|
|
118
|
+
await loadManifestPath();
|
|
119
|
+
await loadManifest();
|
|
120
|
+
await loadDiffPath();
|
|
121
|
+
await loadDiffFile();
|
|
122
|
+
await loadRefresh();
|
|
123
|
+
}
|
|
124
|
+
catch (e) {
|
|
125
|
+
throw e;
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
exports.loadConfigs = loadConfigs;
|
|
129
|
+
function getConfig() {
|
|
130
|
+
if (config)
|
|
131
|
+
return config;
|
|
132
|
+
throw new Error("Error getting config");
|
|
133
|
+
}
|
|
134
|
+
function getConfigPath() {
|
|
135
|
+
if (config_path)
|
|
136
|
+
return config_path;
|
|
137
|
+
throw new Error("Error getting config path");
|
|
138
|
+
}
|
|
139
|
+
function checkConfigPath() {
|
|
140
|
+
if (config_path)
|
|
141
|
+
return config_path;
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
function getRootDir() {
|
|
145
|
+
if (root_dir)
|
|
146
|
+
return root_dir;
|
|
147
|
+
throw new Error("Error getting root directory");
|
|
148
|
+
}
|
|
149
|
+
function getManifest(setup = false) {
|
|
150
|
+
if (manifest)
|
|
151
|
+
return manifest;
|
|
152
|
+
if (!setup)
|
|
153
|
+
throw new Error("Error getting manifest");
|
|
154
|
+
}
|
|
155
|
+
function getManifestPath(scope) {
|
|
156
|
+
if (scope) {
|
|
157
|
+
const rootDir = getRootDir();
|
|
158
|
+
return resolveDovePath(rootDir, `dove.manifest.${scope}.json`, `sinc.manifest.${scope}.json`);
|
|
159
|
+
}
|
|
160
|
+
if (manifest_path)
|
|
161
|
+
return manifest_path;
|
|
162
|
+
throw new Error("Error getting manifest path");
|
|
163
|
+
}
|
|
164
|
+
function getScopeManifestPath(scope) {
|
|
165
|
+
const rootDir = getRootDir();
|
|
166
|
+
return resolveDovePath(rootDir, `dove.manifest.${scope}.json`, `sinc.manifest.${scope}.json`);
|
|
167
|
+
}
|
|
168
|
+
function getSourcePath() {
|
|
169
|
+
if (source_path)
|
|
170
|
+
return source_path;
|
|
171
|
+
throw new Error("Error getting source path");
|
|
172
|
+
}
|
|
173
|
+
function getSourcePathForScope(scopeName) {
|
|
174
|
+
var cfg = getConfig();
|
|
175
|
+
var scopeConfig = cfg.scopes && cfg.scopes[scopeName];
|
|
176
|
+
if (scopeConfig && typeof scopeConfig === "object" && scopeConfig.sourceDirectory) {
|
|
177
|
+
return path_1.default.resolve(getRootDir(), scopeConfig.sourceDirectory);
|
|
178
|
+
}
|
|
179
|
+
return getSourcePath();
|
|
180
|
+
}
|
|
181
|
+
function getBuildPath() {
|
|
182
|
+
if (build_path)
|
|
183
|
+
return build_path;
|
|
184
|
+
throw new Error("Error getting build path");
|
|
185
|
+
}
|
|
186
|
+
function getEnvPath() {
|
|
187
|
+
if (env_path)
|
|
188
|
+
return env_path;
|
|
189
|
+
throw new Error("Error getting env path");
|
|
190
|
+
}
|
|
191
|
+
function getDiffPath() {
|
|
192
|
+
if (diff_path)
|
|
193
|
+
return diff_path;
|
|
194
|
+
throw new Error("Error getting diff path");
|
|
195
|
+
}
|
|
196
|
+
function getDiffFile() {
|
|
197
|
+
if (diff_file)
|
|
198
|
+
return diff_file;
|
|
199
|
+
throw new Error("Error getting diff file");
|
|
200
|
+
}
|
|
201
|
+
function getRefresh() {
|
|
202
|
+
if (refresh_interval)
|
|
203
|
+
return refresh_interval;
|
|
204
|
+
throw new Error("Error getting refresh interval");
|
|
205
|
+
}
|
|
206
|
+
function getDefaultConfigFile() {
|
|
207
|
+
return `
|
|
208
|
+
module.exports = {
|
|
209
|
+
sourceDirectory: "src",
|
|
210
|
+
buildDirectory: "build",
|
|
211
|
+
rules: [],
|
|
212
|
+
excludes:{},
|
|
213
|
+
includes:{},
|
|
214
|
+
tableOptions:{},
|
|
215
|
+
refreshInterval:30
|
|
216
|
+
};
|
|
217
|
+
`.trim();
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* @description Generates a full dove.config.js with multi-scope support, table whitelist,
|
|
221
|
+
* field type overrides, and plugin rules. Used by `dove init` when creating a new config.
|
|
222
|
+
* @param {Object} params - Configuration parameters
|
|
223
|
+
* @param {Array<{scope: string, sourceDirectory: string}>} params.scopes - Selected scopes with source directories
|
|
224
|
+
* @returns {string} Complete dove.config.js file content
|
|
225
|
+
*/
|
|
226
|
+
function generateConfigFile(params) {
|
|
227
|
+
var scopeEntries = params.scopes.map(function (s) {
|
|
228
|
+
return "\t\t" + s.scope + ": {\n\t\t\tsourceDirectory: \"" + s.sourceDirectory + "\",\n\t\t},";
|
|
229
|
+
}).join("\n");
|
|
230
|
+
return "module.exports = {\n" +
|
|
231
|
+
"\tsourceDirectory: \"src\",\n" +
|
|
232
|
+
"\tbuildDirectory: \"build\",\n" +
|
|
233
|
+
"\n" +
|
|
234
|
+
"\t// Plugin Rules Configuration\n" +
|
|
235
|
+
"\trules: [\n" +
|
|
236
|
+
"\t\t{\n" +
|
|
237
|
+
"\t\t\tmatch: /sys_script_include.*\\.ts$/,\n" +
|
|
238
|
+
"\t\t\tplugins: [\n" +
|
|
239
|
+
"\t\t\t\t{\n" +
|
|
240
|
+
"\t\t\t\t\tname: \"@tenonhq/dovetail-typescript-plugin\",\n" +
|
|
241
|
+
"\t\t\t\t\toptions: {\n" +
|
|
242
|
+
"\t\t\t\t\t\ttranspile: true,\n" +
|
|
243
|
+
"\t\t\t\t\t\ttypeCheck: true,\n" +
|
|
244
|
+
"\t\t\t\t\t\ttsconfig: \"./tsconfig.servicenow.json\",\n" +
|
|
245
|
+
"\t\t\t\t\t},\n" +
|
|
246
|
+
"\t\t\t\t},\n" +
|
|
247
|
+
"\t\t\t\t{\n" +
|
|
248
|
+
"\t\t\t\t\tname: \"@tenonhq/dovetail-eslint-plugin\",\n" +
|
|
249
|
+
"\t\t\t\t\toptions: {\n" +
|
|
250
|
+
"\t\t\t\t\t\tconfigFile: \"./.eslintrc.js\",\n" +
|
|
251
|
+
"\t\t\t\t\t\tfix: false,\n" +
|
|
252
|
+
"\t\t\t\t\t\tcache: true,\n" +
|
|
253
|
+
"\t\t\t\t\t},\n" +
|
|
254
|
+
"\t\t\t\t},\n" +
|
|
255
|
+
"\t\t\t\t{\n" +
|
|
256
|
+
"\t\t\t\t\tname: \"@tenonhq/dovetail-babel-plugin\",\n" +
|
|
257
|
+
"\t\t\t\t\toptions: {\n" +
|
|
258
|
+
"\t\t\t\t\t\tconfigFile: \"./.babelrc\",\n" +
|
|
259
|
+
"\t\t\t\t\t},\n" +
|
|
260
|
+
"\t\t\t\t},\n" +
|
|
261
|
+
"\t\t\t\t{\n" +
|
|
262
|
+
"\t\t\t\t\tname: \"@tenonhq/dovetail-prettier-plugin\",\n" +
|
|
263
|
+
"\t\t\t\t\toptions: {\n" +
|
|
264
|
+
"\t\t\t\t\t\tconfigFile: \"./.prettierrc.js\",\n" +
|
|
265
|
+
"\t\t\t\t\t},\n" +
|
|
266
|
+
"\t\t\t\t},\n" +
|
|
267
|
+
"\t\t\t],\n" +
|
|
268
|
+
"\t\t},\n" +
|
|
269
|
+
"\t],\n" +
|
|
270
|
+
"\n" +
|
|
271
|
+
"\tincludes: {\n" +
|
|
272
|
+
"\t\t_tables: [\n" +
|
|
273
|
+
"\t\t\t\"sys_script_include\",\n" +
|
|
274
|
+
"\t\t\t\"sys_script\",\n" +
|
|
275
|
+
"\t\t\t\"sys_ui_script\",\n" +
|
|
276
|
+
"\t\t\t\"sys_ui_page\",\n" +
|
|
277
|
+
"\t\t\t\"sys_ux_client_script\",\n" +
|
|
278
|
+
"\t\t\t\"sys_processor\",\n" +
|
|
279
|
+
"\t\t\t\"sys_ws_operation\",\n" +
|
|
280
|
+
"\t\t\t\"sys_rest_message_fn\",\n" +
|
|
281
|
+
"\t\t\t\"sys_ui_action\",\n" +
|
|
282
|
+
"\t\t\t\"sys_security_acl\",\n" +
|
|
283
|
+
"\t\t\t\"sysevent_script_action\",\n" +
|
|
284
|
+
"\t\t\t\"sys_ux_macroponent\",\n" +
|
|
285
|
+
"\t\t\t\"sys_ux_event\",\n" +
|
|
286
|
+
"\t\t\t\"sys_ux_client_script_include\",\n" +
|
|
287
|
+
"\t\t\t\"sys_ux_screen\",\n" +
|
|
288
|
+
"\t\t\t\"sys_script_fix\",\n" +
|
|
289
|
+
"\t\t],\n" +
|
|
290
|
+
"\t\tsys_script_include: {\n" +
|
|
291
|
+
"\t\t\tscript: { type: \"js\" },\n" +
|
|
292
|
+
"\t\t},\n" +
|
|
293
|
+
"\t\tsys_script: {\n" +
|
|
294
|
+
"\t\t\tscript: { type: \"js\" },\n" +
|
|
295
|
+
"\t\t},\n" +
|
|
296
|
+
"\t\tsys_ui_script: {\n" +
|
|
297
|
+
"\t\t\tscript: { type: \"js\" },\n" +
|
|
298
|
+
"\t\t},\n" +
|
|
299
|
+
"\t\tsys_ui_page: {\n" +
|
|
300
|
+
"\t\t\tprocessing_script: { type: \"js\" },\n" +
|
|
301
|
+
"\t\t\tclient_script: { type: \"js\" },\n" +
|
|
302
|
+
"\t\t\thtml: { type: \"html\" },\n" +
|
|
303
|
+
"\t\t},\n" +
|
|
304
|
+
"\t\tsys_processor: {\n" +
|
|
305
|
+
"\t\t\tscript: { type: \"js\" },\n" +
|
|
306
|
+
"\t\t},\n" +
|
|
307
|
+
"\t\tsys_ws_operation: {\n" +
|
|
308
|
+
"\t\t\toperation_script: { type: \"js\" },\n" +
|
|
309
|
+
"\t\t},\n" +
|
|
310
|
+
"\t\tsys_rest_message_fn: {\n" +
|
|
311
|
+
"\t\t\tcontent: { type: \"txt\" },\n" +
|
|
312
|
+
"\t\t},\n" +
|
|
313
|
+
"\t\tsys_ui_action: {\n" +
|
|
314
|
+
"\t\t\tscript: { type: \"js\" },\n" +
|
|
315
|
+
"\t\t\tclient_script_v2: { type: \"js\" },\n" +
|
|
316
|
+
"\t\t},\n" +
|
|
317
|
+
"\t\tsys_security_acl: {\n" +
|
|
318
|
+
"\t\t\tscript: { type: \"js\" },\n" +
|
|
319
|
+
"\t\t},\n" +
|
|
320
|
+
"\t\tsysevent_script_action: {\n" +
|
|
321
|
+
"\t\t\tscript: { type: \"js\" },\n" +
|
|
322
|
+
"\t\t},\n" +
|
|
323
|
+
"\t\tsys_script_fix: {\n" +
|
|
324
|
+
"\t\t\tscript: { type: \"js\" },\n" +
|
|
325
|
+
"\t\t},\n" +
|
|
326
|
+
"\t\tsys_ux_macroponent: {\n" +
|
|
327
|
+
"\t\t\tcomposition: { type: \"json\" },\n" +
|
|
328
|
+
"\t\t\tprops: { type: \"json\" },\n" +
|
|
329
|
+
"\t\t\tdata: { type: \"json\" },\n" +
|
|
330
|
+
"\t\t\trequired_translations: { type: \"json\" },\n" +
|
|
331
|
+
"\t\t\troot_component_definition: { type: \"json\" },\n" +
|
|
332
|
+
"\t\t\tstate_properties: { type: \"json\" },\n" +
|
|
333
|
+
"\t\t\troot_component_config: { type: \"json\" },\n" +
|
|
334
|
+
"\t\t\tinternal_event_mappings: { type: \"json\" },\n" +
|
|
335
|
+
"\t\t\tstate_persistence_config: { type: \"json\" },\n" +
|
|
336
|
+
"\t\t},\n" +
|
|
337
|
+
"\t\tsys_ux_event: {\n" +
|
|
338
|
+
"\t\t\tdescription: { type: \"txt\" },\n" +
|
|
339
|
+
"\t\t\tevent_name: { type: \"txt\" },\n" +
|
|
340
|
+
"\t\t\tlabel: { type: \"txt\" },\n" +
|
|
341
|
+
"\t\t\tprops: { type: \"json\" },\n" +
|
|
342
|
+
"\t\t\trequired_translations: { type: \"json\" },\n" +
|
|
343
|
+
"\t\t},\n" +
|
|
344
|
+
"\t\tsys_ux_client_script: {\n" +
|
|
345
|
+
"\t\t\tscript: { type: \"js\" },\n" +
|
|
346
|
+
"\t\t\tname: { type: \"txt\" },\n" +
|
|
347
|
+
"\t\t},\n" +
|
|
348
|
+
"\t\tsys_ux_client_script_include: {\n" +
|
|
349
|
+
"\t\t\tscript: { type: \"js\" },\n" +
|
|
350
|
+
"\t\t\tname: { type: \"txt\" },\n" +
|
|
351
|
+
"\t\t},\n" +
|
|
352
|
+
"\t\tsys_ux_screen: {\n" +
|
|
353
|
+
"\t\t\tmacroponent_config: { type: \"json\" },\n" +
|
|
354
|
+
"\t\t\tevent_mappings: { type: \"json\" },\n" +
|
|
355
|
+
"\t\t},\n" +
|
|
356
|
+
"\t\t_scopes: {},\n" +
|
|
357
|
+
"\t},\n" +
|
|
358
|
+
"\n" +
|
|
359
|
+
"\texcludes: {\n" +
|
|
360
|
+
"\t\t_tables: [],\n" +
|
|
361
|
+
"\t},\n" +
|
|
362
|
+
"\n" +
|
|
363
|
+
"\tmanifestOptions: {\n" +
|
|
364
|
+
"\t\tupdateFields: true,\n" +
|
|
365
|
+
"\t\tupdateDependencies: true,\n" +
|
|
366
|
+
"\t},\n" +
|
|
367
|
+
"\n" +
|
|
368
|
+
"\tserver: {\n" +
|
|
369
|
+
"\t\twatchPath: \"./src\",\n" +
|
|
370
|
+
"\t},\n" +
|
|
371
|
+
"\n" +
|
|
372
|
+
"\tscopes: {\n" +
|
|
373
|
+
scopeEntries + "\n" +
|
|
374
|
+
"\t},\n" +
|
|
375
|
+
"};\n";
|
|
376
|
+
}
|
|
377
|
+
async function loadConfig(skipConfigPath = false) {
|
|
378
|
+
if (skipConfigPath) {
|
|
379
|
+
Logger_1.logger.warn("Couldn't find config file. Loading default...");
|
|
380
|
+
return DEFAULT_CONFIG;
|
|
381
|
+
}
|
|
382
|
+
try {
|
|
383
|
+
let configPath = getConfigPath();
|
|
384
|
+
if (configPath) {
|
|
385
|
+
let projectConfig = (await Promise.resolve(`${configPath}`).then(s => __importStar(require(s)))).default;
|
|
386
|
+
// Config is king — no merging with defaults. dove.config.js is the single source of truth.
|
|
387
|
+
var { includes: pIncludes = {}, excludes: pExcludes = {}, tableOptions: pTableOptions = {}, scopes: pScopes = {}, } = projectConfig;
|
|
388
|
+
projectConfig.includes = pIncludes;
|
|
389
|
+
projectConfig.excludes = pExcludes;
|
|
390
|
+
projectConfig.tableOptions = pTableOptions;
|
|
391
|
+
projectConfig.scopes = pScopes;
|
|
392
|
+
return projectConfig;
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
Logger_1.logger.warn("Couldn't find config file. Loading default...");
|
|
396
|
+
return DEFAULT_CONFIG;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
catch (e) {
|
|
400
|
+
let message;
|
|
401
|
+
if (e instanceof Error)
|
|
402
|
+
message = e.message;
|
|
403
|
+
else
|
|
404
|
+
message = String(e);
|
|
405
|
+
Logger_1.logger.warn(message);
|
|
406
|
+
Logger_1.logger.warn("Couldn't find config file. Loading default...");
|
|
407
|
+
return DEFAULT_CONFIG;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
async function loadManifest() {
|
|
411
|
+
try {
|
|
412
|
+
// Try to load legacy single manifest first
|
|
413
|
+
let manifestString = await fs_1.promises.readFile(getManifestPath(), "utf-8");
|
|
414
|
+
manifest = JSON.parse(manifestString);
|
|
415
|
+
}
|
|
416
|
+
catch (e) {
|
|
417
|
+
// If no single manifest, try to load all scope-specific manifests
|
|
418
|
+
manifest = await loadAllScopeManifests();
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
async function loadAllScopeManifests() {
|
|
422
|
+
try {
|
|
423
|
+
const rootDir = getRootDir();
|
|
424
|
+
const files = await fs_1.promises.readdir(rootDir);
|
|
425
|
+
const manifestFiles = files.filter(f => ((f.startsWith('dove.manifest.') && f !== 'dove.manifest.json') ||
|
|
426
|
+
(f.startsWith('sinc.manifest.') && f !== 'sinc.manifest.json')) &&
|
|
427
|
+
f.endsWith('.json'));
|
|
428
|
+
if (manifestFiles.length === 0) {
|
|
429
|
+
return undefined;
|
|
430
|
+
}
|
|
431
|
+
// Combine all scope manifests into a single structure for backward compatibility
|
|
432
|
+
const combinedManifest = {};
|
|
433
|
+
for (const file of manifestFiles) {
|
|
434
|
+
const scope = file.replace(/^(dove|sinc)\.manifest\./, '').replace('.json', '');
|
|
435
|
+
const manifestPath = path_1.default.join(rootDir, file);
|
|
436
|
+
try {
|
|
437
|
+
const content = await fs_1.promises.readFile(manifestPath, "utf-8");
|
|
438
|
+
const scopeManifest = JSON.parse(content);
|
|
439
|
+
// If the manifest already has the scope at root level, use it directly
|
|
440
|
+
if (scopeManifest.scope && scopeManifest.tables) {
|
|
441
|
+
combinedManifest[scope] = scopeManifest;
|
|
442
|
+
}
|
|
443
|
+
else {
|
|
444
|
+
// Otherwise wrap it
|
|
445
|
+
combinedManifest[scope] = scopeManifest;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
catch (e) {
|
|
449
|
+
Logger_1.logger.warn(`Failed to load manifest for scope ${scope}: ${e}`);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
return Object.keys(combinedManifest).length > 0 ? combinedManifest : undefined;
|
|
453
|
+
}
|
|
454
|
+
catch (e) {
|
|
455
|
+
return undefined;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
async function loadScopeManifest(scope) {
|
|
459
|
+
try {
|
|
460
|
+
const manifestPath = getScopeManifestPath(scope);
|
|
461
|
+
const content = await fs_1.promises.readFile(manifestPath, "utf-8");
|
|
462
|
+
return JSON.parse(content);
|
|
463
|
+
}
|
|
464
|
+
catch (e) {
|
|
465
|
+
return undefined;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
function updateManifest(man) {
|
|
469
|
+
manifest = man;
|
|
470
|
+
}
|
|
471
|
+
function isMultiScopeManifest(man) {
|
|
472
|
+
return typeof man === "object" && man !== null && !man.scope && !man.tables;
|
|
473
|
+
}
|
|
474
|
+
function resolveManifestForScope(man, scope) {
|
|
475
|
+
if (!isMultiScopeManifest(man)) {
|
|
476
|
+
if (!scope || man.scope === scope) {
|
|
477
|
+
return man;
|
|
478
|
+
}
|
|
479
|
+
return undefined;
|
|
480
|
+
}
|
|
481
|
+
var scopeMan = man[scope];
|
|
482
|
+
if (scopeMan && scopeMan.tables) {
|
|
483
|
+
return scopeMan;
|
|
484
|
+
}
|
|
485
|
+
return undefined;
|
|
486
|
+
}
|
|
487
|
+
function resolveScopeFromPath(filePath) {
|
|
488
|
+
var cfg = getConfig();
|
|
489
|
+
if (!cfg.scopes)
|
|
490
|
+
return undefined;
|
|
491
|
+
var scopeNames = Object.keys(cfg.scopes);
|
|
492
|
+
for (var i = 0; i < scopeNames.length; i++) {
|
|
493
|
+
var scopeSourcePath = getSourcePathForScope(scopeNames[i]);
|
|
494
|
+
if (filePath.indexOf(scopeSourcePath) === 0) {
|
|
495
|
+
return scopeNames[i];
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
return undefined;
|
|
499
|
+
}
|
|
500
|
+
// Exported for tests only.
|
|
501
|
+
async function loadConfigPath(pth) {
|
|
502
|
+
if (!pth) {
|
|
503
|
+
pth = process.cwd();
|
|
504
|
+
}
|
|
505
|
+
// check to see if config is found
|
|
506
|
+
let files = await fs_1.promises.readdir(pth);
|
|
507
|
+
if (files.includes("dove.config.js")) {
|
|
508
|
+
return path_1.default.join(pth, "dove.config.js");
|
|
509
|
+
}
|
|
510
|
+
if (files.includes("sinc.config.js")) {
|
|
511
|
+
Logger_1.logger.warn("Found legacy 'sinc.config.js' — please rename to 'dove.config.js' (run 'npx dove migrate'). Continuing with the legacy file.");
|
|
512
|
+
return path_1.default.join(pth, "sinc.config.js");
|
|
513
|
+
}
|
|
514
|
+
if (isRoot(pth)) {
|
|
515
|
+
return false;
|
|
516
|
+
}
|
|
517
|
+
return loadConfigPath(path_1.default.dirname(pth));
|
|
518
|
+
function isRoot(pth) {
|
|
519
|
+
return path_1.default.parse(pth).root === pth;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
async function loadRefresh() {
|
|
523
|
+
let { refreshInterval = 30 } = getConfig();
|
|
524
|
+
refresh_interval = refreshInterval;
|
|
525
|
+
}
|
|
526
|
+
async function loadSourcePath() {
|
|
527
|
+
let rootDir = getRootDir();
|
|
528
|
+
let { sourceDirectory = "src" } = getConfig();
|
|
529
|
+
source_path = path_1.default.join(rootDir, sourceDirectory);
|
|
530
|
+
}
|
|
531
|
+
async function loadBuildPath() {
|
|
532
|
+
let rootDir = getRootDir();
|
|
533
|
+
let { buildDirectory = "build" } = getConfig();
|
|
534
|
+
build_path = path_1.default.join(rootDir, buildDirectory);
|
|
535
|
+
}
|
|
536
|
+
async function loadEnvPath() {
|
|
537
|
+
let rootDir = getRootDir();
|
|
538
|
+
env_path = path_1.default.join(rootDir, ".env");
|
|
539
|
+
}
|
|
540
|
+
async function loadManifestPath() {
|
|
541
|
+
let rootDir = getRootDir();
|
|
542
|
+
manifest_path = resolveDovePath(rootDir, "dove.manifest.json", "sinc.manifest.json");
|
|
543
|
+
}
|
|
544
|
+
async function loadDiffPath() {
|
|
545
|
+
let rootDir = getRootDir();
|
|
546
|
+
diff_path = resolveDovePath(rootDir, "dove.diff.manifest.json", "sinc.diff.manifest.json");
|
|
547
|
+
}
|
|
548
|
+
async function loadDiffFile() {
|
|
549
|
+
try {
|
|
550
|
+
let diffString = await fs_1.promises.readFile(getDiffPath(), "utf-8");
|
|
551
|
+
diff_file = JSON.parse(diffString);
|
|
552
|
+
}
|
|
553
|
+
catch (e) {
|
|
554
|
+
diff_file = undefined;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
async function loadRootDir(skip) {
|
|
558
|
+
if (skip) {
|
|
559
|
+
root_dir = process.cwd();
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
let configPath = getConfigPath();
|
|
563
|
+
if (configPath)
|
|
564
|
+
root_dir = path_1.default.dirname(configPath);
|
|
565
|
+
else
|
|
566
|
+
root_dir = process.cwd();
|
|
567
|
+
}
|
|
568
|
+
function isDirectiveKey(key) {
|
|
569
|
+
return key.charAt(0) === "_";
|
|
570
|
+
}
|
|
571
|
+
function stripDirectiveKeys(obj) {
|
|
572
|
+
var result = {};
|
|
573
|
+
var keys = Object.keys(obj || {});
|
|
574
|
+
for (var i = 0; i < keys.length; i++) {
|
|
575
|
+
if (!isDirectiveKey(keys[i])) {
|
|
576
|
+
result[keys[i]] = obj[keys[i]];
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
return result;
|
|
580
|
+
}
|
|
581
|
+
function resolveConfigForScope(scopeName, cfgOverride) {
|
|
582
|
+
var cfg = cfgOverride || getConfig();
|
|
583
|
+
var cfgIncludes = cfg.includes || {};
|
|
584
|
+
var cfgExcludes = cfg.excludes || {};
|
|
585
|
+
// Backward compat: support old "table" key (no underscore)
|
|
586
|
+
var globalTables = cfgIncludes._tables || [];
|
|
587
|
+
if (!cfgIncludes._tables && Array.isArray(cfgIncludes.table)) {
|
|
588
|
+
Logger_1.logger.warn("Deprecation: 'table' key in includes is deprecated. Use '_tables' instead.");
|
|
589
|
+
globalTables = cfgIncludes.table;
|
|
590
|
+
}
|
|
591
|
+
// Resolve scope-specific overrides
|
|
592
|
+
var scopesDirective = cfgIncludes._scopes || {};
|
|
593
|
+
var scopeOverride = scopesDirective[scopeName] || {};
|
|
594
|
+
var scopeTables = scopeOverride._tables || [];
|
|
595
|
+
// Deduplicated union of global + scope tables
|
|
596
|
+
var tableSet = {};
|
|
597
|
+
var i;
|
|
598
|
+
for (i = 0; i < globalTables.length; i++) {
|
|
599
|
+
tableSet[globalTables[i]] = true;
|
|
600
|
+
}
|
|
601
|
+
for (i = 0; i < scopeTables.length; i++) {
|
|
602
|
+
tableSet[scopeTables[i]] = true;
|
|
603
|
+
}
|
|
604
|
+
// Field overrides: global non-_ keys and scope-specific non-_ keys
|
|
605
|
+
var globalFieldOverrides = stripDirectiveKeys(cfgIncludes);
|
|
606
|
+
var scopeFieldOverrides = stripDirectiveKeys(scopeOverride);
|
|
607
|
+
// Implicitly add tables that have field overrides to the whitelist
|
|
608
|
+
var globalOverrideTables = Object.keys(globalFieldOverrides);
|
|
609
|
+
for (i = 0; i < globalOverrideTables.length; i++) {
|
|
610
|
+
if (!tableSet[globalOverrideTables[i]]) {
|
|
611
|
+
tableSet[globalOverrideTables[i]] = true;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
var scopeOverrideTables = Object.keys(scopeFieldOverrides);
|
|
615
|
+
for (i = 0; i < scopeOverrideTables.length; i++) {
|
|
616
|
+
if (!tableSet[scopeOverrideTables[i]]) {
|
|
617
|
+
tableSet[scopeOverrideTables[i]] = true;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
var resolvedTables = Object.keys(tableSet);
|
|
621
|
+
// Resolve excludes _tables
|
|
622
|
+
var excludeTables = cfgExcludes._tables || [];
|
|
623
|
+
if (!cfgExcludes._tables && Array.isArray(cfgExcludes.table)) {
|
|
624
|
+
excludeTables = cfgExcludes.table;
|
|
625
|
+
}
|
|
626
|
+
// Remove excluded tables from the resolved list
|
|
627
|
+
if (excludeTables.length > 0) {
|
|
628
|
+
var excludeSet = {};
|
|
629
|
+
for (i = 0; i < excludeTables.length; i++) {
|
|
630
|
+
excludeSet[excludeTables[i]] = true;
|
|
631
|
+
}
|
|
632
|
+
resolvedTables = resolvedTables.filter(function (t) {
|
|
633
|
+
return !excludeSet[t];
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
// Deep merge field overrides: global + scope, scope wins on conflicts per field
|
|
637
|
+
var fieldOverrides = {};
|
|
638
|
+
var allTableKeys = {};
|
|
639
|
+
var gKeys = Object.keys(globalFieldOverrides);
|
|
640
|
+
var sKeys = Object.keys(scopeFieldOverrides);
|
|
641
|
+
for (i = 0; i < gKeys.length; i++) {
|
|
642
|
+
allTableKeys[gKeys[i]] = true;
|
|
643
|
+
}
|
|
644
|
+
for (i = 0; i < sKeys.length; i++) {
|
|
645
|
+
allTableKeys[sKeys[i]] = true;
|
|
646
|
+
}
|
|
647
|
+
for (var tblKey in allTableKeys) {
|
|
648
|
+
var globalEntry = globalFieldOverrides[tblKey];
|
|
649
|
+
var scopeEntry = scopeFieldOverrides[tblKey];
|
|
650
|
+
if (globalEntry && scopeEntry && typeof globalEntry === "object" && typeof scopeEntry === "object") {
|
|
651
|
+
fieldOverrides[tblKey] = Object.assign({}, globalEntry, scopeEntry);
|
|
652
|
+
}
|
|
653
|
+
else {
|
|
654
|
+
fieldOverrides[tblKey] = scopeEntry || globalEntry;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
// API includes: merged field overrides (no _ keys)
|
|
658
|
+
var apiIncludes = Object.assign({}, fieldOverrides);
|
|
659
|
+
// API excludes: strip _ keys
|
|
660
|
+
var apiExcludes = stripDirectiveKeys(cfgExcludes);
|
|
661
|
+
// Read-only tables: union of global _readOnlyTables and scope-level override.
|
|
662
|
+
// A table flagged read-only is still pulled from the instance but pushes are
|
|
663
|
+
// skipped. Default when absent: empty (bidirectional for all tables).
|
|
664
|
+
var globalReadOnly = Array.isArray(cfgIncludes._readOnlyTables)
|
|
665
|
+
? cfgIncludes._readOnlyTables
|
|
666
|
+
: [];
|
|
667
|
+
var scopeReadOnly = Array.isArray(scopeOverride._readOnlyTables)
|
|
668
|
+
? scopeOverride._readOnlyTables
|
|
669
|
+
: [];
|
|
670
|
+
var readOnlySet = {};
|
|
671
|
+
for (i = 0; i < globalReadOnly.length; i++) {
|
|
672
|
+
readOnlySet[globalReadOnly[i]] = true;
|
|
673
|
+
}
|
|
674
|
+
for (i = 0; i < scopeReadOnly.length; i++) {
|
|
675
|
+
readOnlySet[scopeReadOnly[i]] = true;
|
|
676
|
+
}
|
|
677
|
+
var resolvedReadOnly = Object.keys(readOnlySet);
|
|
678
|
+
return {
|
|
679
|
+
tables: resolvedTables,
|
|
680
|
+
fieldOverrides: fieldOverrides,
|
|
681
|
+
apiIncludes: apiIncludes,
|
|
682
|
+
apiExcludes: apiExcludes,
|
|
683
|
+
readOnlyTables: resolvedReadOnly,
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
// Convenience wrapper for push-side lookups — returns a Set for O(1) membership.
|
|
687
|
+
// Fails safe (empty set = all tables writable) when config isn't available
|
|
688
|
+
// rather than blocking a push over a lookup error.
|
|
689
|
+
function getReadOnlyTablesForScope(scopeName) {
|
|
690
|
+
try {
|
|
691
|
+
var resolved = resolveConfigForScope(scopeName);
|
|
692
|
+
return new Set(resolved.readOnlyTables || []);
|
|
693
|
+
}
|
|
694
|
+
catch (e) {
|
|
695
|
+
return new Set();
|
|
696
|
+
}
|
|
697
|
+
}
|