farseer-cli 1.0.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/LICENSE +15 -0
- package/README.md +741 -0
- package/dist/commands/app.d.ts +2 -0
- package/dist/commands/app.js +349 -0
- package/dist/commands/app.js.map +7 -0
- package/dist/commands/apps.d.ts +2 -0
- package/dist/commands/apps.js +111 -0
- package/dist/commands/apps.js.map +7 -0
- package/dist/commands/checkout.d.ts +2 -0
- package/dist/commands/checkout.js +166 -0
- package/dist/commands/checkout.js.map +7 -0
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.js +139 -0
- package/dist/commands/config.js.map +7 -0
- package/dist/commands/diff.d.ts +2 -0
- package/dist/commands/diff.js +183 -0
- package/dist/commands/diff.js.map +7 -0
- package/dist/commands/files.js +99 -0
- package/dist/commands/files.js.map +7 -0
- package/dist/commands/install.d.ts +2 -0
- package/dist/commands/install.js +79 -0
- package/dist/commands/install.js.map +7 -0
- package/dist/commands/list.d.ts +2 -0
- package/dist/commands/list.js +92 -0
- package/dist/commands/list.js.map +7 -0
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.js +134 -0
- package/dist/commands/login.js.map +7 -0
- package/dist/commands/logout.d.ts +2 -0
- package/dist/commands/logout.js +59 -0
- package/dist/commands/logout.js.map +7 -0
- package/dist/commands/mcp-server.d.ts +8 -0
- package/dist/commands/mcp-server.js +41 -0
- package/dist/commands/mcp-server.js.map +7 -0
- package/dist/commands/model.d.ts +2 -0
- package/dist/commands/model.js +189 -0
- package/dist/commands/model.js.map +7 -0
- package/dist/commands/pull.d.ts +2 -0
- package/dist/commands/pull.js +287 -0
- package/dist/commands/pull.js.map +7 -0
- package/dist/commands/push.d.ts +2 -0
- package/dist/commands/push.js +251 -0
- package/dist/commands/push.js.map +7 -0
- package/dist/commands/run.d.ts +2 -0
- package/dist/commands/run.js +246 -0
- package/dist/commands/run.js.map +7 -0
- package/dist/commands/setup.d.ts +2 -0
- package/dist/commands/setup.js +137 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.js +145 -0
- package/dist/commands/status.js.map +7 -0
- package/dist/commands/unsetup.d.ts +2 -0
- package/dist/commands/unsetup.js +122 -0
- package/dist/commands/whoami.d.ts +2 -0
- package/dist/commands/whoami.js +63 -0
- package/dist/commands/whoami.js.map +7 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +135 -0
- package/dist/index.js.map +7 -0
- package/dist/mcp/index.d.ts +7 -0
- package/dist/mcp/index.js +35 -0
- package/dist/mcp/index.js.map +7 -0
- package/dist/mcp/prompts/workflows.d.ts +7 -0
- package/dist/mcp/prompts/workflows.js +374 -0
- package/dist/mcp/prompts/workflows.js.map +7 -0
- package/dist/mcp/resources/documentation.d.ts +8 -0
- package/dist/mcp/resources/documentation.js +167 -0
- package/dist/mcp/resources/documentation.js.map +7 -0
- package/dist/mcp/server.d.ts +7 -0
- package/dist/mcp/server.js +49 -0
- package/dist/mcp/server.js.map +7 -0
- package/dist/mcp/tools/appTools.d.ts +7 -0
- package/dist/mcp/tools/appTools.js +377 -0
- package/dist/mcp/tools/appTools.js.map +7 -0
- package/dist/mcp/tools/authTools.d.ts +7 -0
- package/dist/mcp/tools/authTools.js +158 -0
- package/dist/mcp/tools/authTools.js.map +7 -0
- package/dist/mcp/tools/modelTools.d.ts +7 -0
- package/dist/mcp/tools/modelTools.js +331 -0
- package/dist/mcp/tools/modelTools.js.map +7 -0
- package/dist/mcp/tools/runTools.d.ts +7 -0
- package/dist/mcp/tools/runTools.js +231 -0
- package/dist/mcp/tools/runTools.js.map +7 -0
- package/dist/mcp/tools/syncTools.d.ts +7 -0
- package/dist/mcp/tools/syncTools.js +382 -0
- package/dist/mcp/tools/syncTools.js.map +7 -0
- package/dist/mcp/utils/helpers.d.ts +69 -0
- package/dist/mcp/utils/helpers.js +113 -0
- package/dist/mcp/utils/helpers.js.map +7 -0
- package/dist/services/appSyncService.d.ts +75 -0
- package/dist/services/appSyncService.js +370 -0
- package/dist/services/appSyncService.js.map +7 -0
- package/dist/services/configService.d.ts +39 -0
- package/dist/services/configService.js +196 -0
- package/dist/services/configService.js.map +7 -0
- package/dist/services/farseerApi.d.ts +166 -0
- package/dist/services/farseerApi.js +378 -0
- package/dist/services/farseerApi.js.map +7 -0
- package/dist/services/farseerFactory.d.ts +88 -0
- package/dist/services/farseerFactory.js +179 -0
- package/dist/services/farseerFactory.js.map +7 -0
- package/dist/services/farseerService.d.ts +96 -0
- package/dist/services/farseerService.js +614 -0
- package/dist/services/farseerService.js.map +7 -0
- package/dist/services/gitService.d.ts +31 -0
- package/dist/services/gitService.js +134 -0
- package/dist/services/gitService.js.map +7 -0
- package/dist/services/syncService.d.ts +44 -0
- package/dist/services/syncService.js +320 -0
- package/dist/services/syncService.js.map +7 -0
- package/dist/utils/constants.d.ts +7 -0
- package/dist/utils/constants.js +46 -0
- package/dist/utils/constants.js.map +7 -0
- package/dist/utils/helpers.d.ts +69 -0
- package/dist/utils/helpers.js +413 -0
- package/dist/utils/helpers.js.map +7 -0
- package/dist/utils/logger.d.ts +14 -0
- package/dist/utils/logger.js +76 -0
- package/dist/utils/logger.js.map +7 -0
- package/package.json +62 -0
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
var appSyncService_exports = {};
|
|
29
|
+
__export(appSyncService_exports, {
|
|
30
|
+
AppSyncService: () => AppSyncService
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(appSyncService_exports);
|
|
33
|
+
var fs = __toESM(require("fs"));
|
|
34
|
+
var path = __toESM(require("path"));
|
|
35
|
+
var import_helpers = require("../utils/helpers");
|
|
36
|
+
function sanitizeDiacritics(text) {
|
|
37
|
+
const diacriticMap = {
|
|
38
|
+
// Croatian
|
|
39
|
+
"\u010D": "c",
|
|
40
|
+
"\u010C": "C",
|
|
41
|
+
"\u0107": "c",
|
|
42
|
+
"\u0106": "C",
|
|
43
|
+
"\u0161": "s",
|
|
44
|
+
"\u0160": "S",
|
|
45
|
+
"\u017E": "z",
|
|
46
|
+
"\u017D": "Z",
|
|
47
|
+
"\u0111": "d",
|
|
48
|
+
"\u0110": "D",
|
|
49
|
+
// German/Other common
|
|
50
|
+
"\xE4": "a",
|
|
51
|
+
"\xC4": "A",
|
|
52
|
+
"\xF6": "o",
|
|
53
|
+
"\xD6": "O",
|
|
54
|
+
"\xFC": "u",
|
|
55
|
+
"\xDC": "U",
|
|
56
|
+
"\xDF": "ss",
|
|
57
|
+
// Polish
|
|
58
|
+
"\u0105": "a",
|
|
59
|
+
"\u0104": "A",
|
|
60
|
+
"\u0119": "e",
|
|
61
|
+
"\u0118": "E",
|
|
62
|
+
"\u0142": "l",
|
|
63
|
+
"\u0141": "L",
|
|
64
|
+
"\u0144": "n",
|
|
65
|
+
"\u0143": "N",
|
|
66
|
+
"\xF3": "o",
|
|
67
|
+
"\xD3": "O",
|
|
68
|
+
"\u015B": "s",
|
|
69
|
+
"\u015A": "S",
|
|
70
|
+
"\u017A": "z",
|
|
71
|
+
"\u0179": "Z",
|
|
72
|
+
"\u017C": "z",
|
|
73
|
+
"\u017B": "Z",
|
|
74
|
+
// French/Spanish
|
|
75
|
+
"\xE0": "a",
|
|
76
|
+
"\xE1": "a",
|
|
77
|
+
"\xE2": "a",
|
|
78
|
+
"\xE8": "e",
|
|
79
|
+
"\xE9": "e",
|
|
80
|
+
"\xEA": "e",
|
|
81
|
+
"\xEB": "e",
|
|
82
|
+
"\xEC": "i",
|
|
83
|
+
"\xED": "i",
|
|
84
|
+
"\xEE": "i",
|
|
85
|
+
"\xEF": "i",
|
|
86
|
+
"\xF2": "o",
|
|
87
|
+
"\xF4": "o",
|
|
88
|
+
"\xF9": "u",
|
|
89
|
+
"\xFA": "u",
|
|
90
|
+
"\xFB": "u",
|
|
91
|
+
"\xF1": "n",
|
|
92
|
+
"\xD1": "N",
|
|
93
|
+
"\xE7": "c",
|
|
94
|
+
"\xC7": "C"
|
|
95
|
+
};
|
|
96
|
+
return text.split("").map((char) => diacriticMap[char] || char).join("");
|
|
97
|
+
}
|
|
98
|
+
class AppSyncService {
|
|
99
|
+
constructor(tenant, api) {
|
|
100
|
+
this.api = api;
|
|
101
|
+
this.appsDir = (0, import_helpers.getTenantAppsDir)(tenant);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Get filename for an app (keep original name, just sanitize for filesystem)
|
|
105
|
+
*/
|
|
106
|
+
getAppFilename(name) {
|
|
107
|
+
return sanitizeDiacritics(name).replace(/[<>:"/\\|?*]/g, "").trim() + ".json";
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Load all local app configs
|
|
111
|
+
*/
|
|
112
|
+
loadLocalApps() {
|
|
113
|
+
const apps = /* @__PURE__ */ new Map();
|
|
114
|
+
if (!fs.existsSync(this.appsDir)) {
|
|
115
|
+
return apps;
|
|
116
|
+
}
|
|
117
|
+
const files = fs.readdirSync(this.appsDir).filter((f) => f.endsWith(".json"));
|
|
118
|
+
for (const file of files) {
|
|
119
|
+
try {
|
|
120
|
+
const content = fs.readFileSync(path.join(this.appsDir, file), "utf-8");
|
|
121
|
+
const config = JSON.parse(content);
|
|
122
|
+
apps.set(config.name.toLowerCase(), config);
|
|
123
|
+
} catch {
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return apps;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Save a local app config
|
|
130
|
+
*/
|
|
131
|
+
saveLocalApp(config) {
|
|
132
|
+
(0, import_helpers.ensureDirectoryExists)(this.appsDir);
|
|
133
|
+
const filename = this.getAppFilename(config.name);
|
|
134
|
+
const filePath = path.join(this.appsDir, filename);
|
|
135
|
+
fs.writeFileSync(filePath, JSON.stringify(config, null, 2), "utf-8");
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Delete a local app config
|
|
139
|
+
*/
|
|
140
|
+
deleteLocalApp(name) {
|
|
141
|
+
const filename = this.getAppFilename(name);
|
|
142
|
+
const filePath = path.join(this.appsDir, filename);
|
|
143
|
+
if (fs.existsSync(filePath)) {
|
|
144
|
+
fs.unlinkSync(filePath);
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Convert remote app to local config format
|
|
151
|
+
*/
|
|
152
|
+
remoteToLocal(remote, reference) {
|
|
153
|
+
const mainScript = remote.scriptFiles.find((s) => s.id === remote.mainScriptFileId);
|
|
154
|
+
return {
|
|
155
|
+
name: remote.name,
|
|
156
|
+
description: remote.description || "",
|
|
157
|
+
entrypoint: mainScript?.name || null,
|
|
158
|
+
scripts: remote.scriptFiles.map((s) => s.name),
|
|
159
|
+
arguments: remote.expectedArguments.map((a) => ({
|
|
160
|
+
name: a.name,
|
|
161
|
+
defaultValue: a.defaultValue
|
|
162
|
+
})),
|
|
163
|
+
_remote: {
|
|
164
|
+
id: remote.id,
|
|
165
|
+
reference
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Check if local and remote app configs are equivalent
|
|
171
|
+
*/
|
|
172
|
+
areAppsEqual(local, remote) {
|
|
173
|
+
if (local.name !== remote.name) return false;
|
|
174
|
+
if ((local.description || "") !== (remote.description || "")) return false;
|
|
175
|
+
const remoteEntrypoint = remote.scriptFiles.find((s) => s.id === remote.mainScriptFileId)?.name || null;
|
|
176
|
+
if (local.entrypoint !== remoteEntrypoint) return false;
|
|
177
|
+
const localScripts = [...local.scripts].sort();
|
|
178
|
+
const remoteScripts = [...remote.scriptFiles.map((s) => s.name)].sort();
|
|
179
|
+
if (JSON.stringify(localScripts) !== JSON.stringify(remoteScripts)) return false;
|
|
180
|
+
const localArgs = local.arguments.map((a) => `${a.name}=${a.defaultValue}`).sort();
|
|
181
|
+
const remoteArgs = remote.expectedArguments.map((a) => `${a.name}=${a.defaultValue}`).sort();
|
|
182
|
+
if (JSON.stringify(localArgs) !== JSON.stringify(remoteArgs)) return false;
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Pull apps from remote and save locally
|
|
187
|
+
*/
|
|
188
|
+
async pull() {
|
|
189
|
+
const result = {
|
|
190
|
+
created: [],
|
|
191
|
+
updated: [],
|
|
192
|
+
deleted: [],
|
|
193
|
+
unchanged: []
|
|
194
|
+
};
|
|
195
|
+
const localApps = this.loadLocalApps();
|
|
196
|
+
const remoteAppList = await this.api.listApps();
|
|
197
|
+
const remoteApps = /* @__PURE__ */ new Map();
|
|
198
|
+
for (const item of remoteAppList) {
|
|
199
|
+
const app = await this.api.getApp(item.reference);
|
|
200
|
+
if (app) {
|
|
201
|
+
remoteApps.set(app.name.toLowerCase(), { app, reference: item.reference });
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
for (const [key, { app, reference }] of remoteApps) {
|
|
205
|
+
const localConfig = this.remoteToLocal(app, reference);
|
|
206
|
+
const existingLocal = localApps.get(key);
|
|
207
|
+
if (!existingLocal) {
|
|
208
|
+
this.saveLocalApp(localConfig);
|
|
209
|
+
result.created.push(app.name);
|
|
210
|
+
} else if (!this.areAppsEqual(existingLocal, app)) {
|
|
211
|
+
this.saveLocalApp(localConfig);
|
|
212
|
+
result.updated.push(app.name);
|
|
213
|
+
} else {
|
|
214
|
+
result.unchanged.push(app.name);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
for (const [key, local] of localApps) {
|
|
218
|
+
if (!remoteApps.has(key) && local._remote) {
|
|
219
|
+
this.deleteLocalApp(local.name);
|
|
220
|
+
result.deleted.push(local.name);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return result;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Push local apps to remote
|
|
227
|
+
*/
|
|
228
|
+
async push() {
|
|
229
|
+
const result = {
|
|
230
|
+
created: [],
|
|
231
|
+
updated: [],
|
|
232
|
+
deleted: [],
|
|
233
|
+
unchanged: []
|
|
234
|
+
};
|
|
235
|
+
const localApps = this.loadLocalApps();
|
|
236
|
+
const remoteAppList = await this.api.listApps();
|
|
237
|
+
const remoteApps = /* @__PURE__ */ new Map();
|
|
238
|
+
for (const item of remoteAppList) {
|
|
239
|
+
const app = await this.api.getApp(item.reference);
|
|
240
|
+
if (app) {
|
|
241
|
+
remoteApps.set(app.name.toLowerCase(), { app, reference: item.reference });
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
const availableScripts = await this.api.getScriptFiles();
|
|
245
|
+
const scriptIdByPath = /* @__PURE__ */ new Map();
|
|
246
|
+
const scriptIdByName = /* @__PURE__ */ new Map();
|
|
247
|
+
for (const s of availableScripts) {
|
|
248
|
+
const pathKey = s.name.toLowerCase();
|
|
249
|
+
const filenameKey = s.name.split("/").pop()?.toLowerCase() || pathKey;
|
|
250
|
+
scriptIdByPath.set(pathKey, s.id);
|
|
251
|
+
if (!scriptIdByName.has(filenameKey)) {
|
|
252
|
+
scriptIdByName.set(filenameKey, s.id);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
const findScriptId = (scriptRef) => {
|
|
256
|
+
const key = scriptRef.toLowerCase();
|
|
257
|
+
const byPath = scriptIdByPath.get(key);
|
|
258
|
+
if (byPath) return byPath;
|
|
259
|
+
const withPrefix = scriptIdByPath.get(`scripts/${key}`);
|
|
260
|
+
if (withPrefix) return withPrefix;
|
|
261
|
+
return scriptIdByName.get(key.split("/").pop() || key);
|
|
262
|
+
};
|
|
263
|
+
for (const [key, local] of localApps) {
|
|
264
|
+
const remote = remoteApps.get(key);
|
|
265
|
+
if (!remote) {
|
|
266
|
+
try {
|
|
267
|
+
const created = await this.api.createApp(local.name);
|
|
268
|
+
const update = this.buildUpdatePayload(local, findScriptId);
|
|
269
|
+
update.name = local.name;
|
|
270
|
+
update.description = local.description;
|
|
271
|
+
await this.api.updateApp(created.id.toString(), update);
|
|
272
|
+
local._remote = {
|
|
273
|
+
id: created.id,
|
|
274
|
+
reference: created.id.toString()
|
|
275
|
+
};
|
|
276
|
+
this.saveLocalApp(local);
|
|
277
|
+
result.created.push(local.name);
|
|
278
|
+
} catch (error) {
|
|
279
|
+
console.error(`Failed to create app ${local.name}:`, error);
|
|
280
|
+
}
|
|
281
|
+
} else if (!this.areAppsEqual(local, remote.app)) {
|
|
282
|
+
try {
|
|
283
|
+
const update = this.buildUpdatePayload(local, findScriptId);
|
|
284
|
+
update.name = local.name;
|
|
285
|
+
update.description = local.description;
|
|
286
|
+
await this.api.updateApp(remote.reference, update);
|
|
287
|
+
result.updated.push(local.name);
|
|
288
|
+
} catch (error) {
|
|
289
|
+
console.error(`Failed to update app ${local.name}:`, error);
|
|
290
|
+
}
|
|
291
|
+
} else {
|
|
292
|
+
result.unchanged.push(local.name);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
return result;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Build update payload for API
|
|
299
|
+
*/
|
|
300
|
+
buildUpdatePayload(local, findScriptId) {
|
|
301
|
+
const update = {};
|
|
302
|
+
if (local.arguments.length > 0) {
|
|
303
|
+
update.expectedArguments = local.arguments.map((a) => ({
|
|
304
|
+
name: a.name,
|
|
305
|
+
type: "variable",
|
|
306
|
+
defaultValue: a.defaultValue
|
|
307
|
+
}));
|
|
308
|
+
}
|
|
309
|
+
if (local.scripts.length > 0) {
|
|
310
|
+
const scriptIds = [];
|
|
311
|
+
for (const scriptRef of local.scripts) {
|
|
312
|
+
const id = findScriptId(scriptRef);
|
|
313
|
+
if (id) {
|
|
314
|
+
scriptIds.push(id);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
if (scriptIds.length > 0) {
|
|
318
|
+
update.scriptFileIds = scriptIds;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
if (local.entrypoint) {
|
|
322
|
+
const entrypointId = findScriptId(local.entrypoint);
|
|
323
|
+
if (entrypointId) {
|
|
324
|
+
update.mainScriptFileId = entrypointId;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return update;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Get sync status without making changes
|
|
331
|
+
*/
|
|
332
|
+
async getStatus() {
|
|
333
|
+
const status = {
|
|
334
|
+
newLocal: [],
|
|
335
|
+
newRemote: [],
|
|
336
|
+
modified: [],
|
|
337
|
+
synced: []
|
|
338
|
+
};
|
|
339
|
+
const localApps = this.loadLocalApps();
|
|
340
|
+
const remoteAppList = await this.api.listApps();
|
|
341
|
+
const remoteApps = /* @__PURE__ */ new Map();
|
|
342
|
+
for (const item of remoteAppList) {
|
|
343
|
+
const app = await this.api.getApp(item.reference);
|
|
344
|
+
if (app) {
|
|
345
|
+
remoteApps.set(app.name.toLowerCase(), { app, reference: item.reference });
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
for (const [key, local] of localApps) {
|
|
349
|
+
const remote = remoteApps.get(key);
|
|
350
|
+
if (!remote) {
|
|
351
|
+
status.newLocal.push(local.name);
|
|
352
|
+
} else if (!this.areAppsEqual(local, remote.app)) {
|
|
353
|
+
status.modified.push(local.name);
|
|
354
|
+
} else {
|
|
355
|
+
status.synced.push(local.name);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
for (const [key, { app }] of remoteApps) {
|
|
359
|
+
if (!localApps.has(key)) {
|
|
360
|
+
status.newRemote.push(app.name);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return status;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
367
|
+
0 && (module.exports = {
|
|
368
|
+
AppSyncService
|
|
369
|
+
});
|
|
370
|
+
//# sourceMappingURL=appSyncService.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/services/appSyncService.ts"],
|
|
4
|
+
"sourcesContent": ["import * as fs from 'fs';\nimport * as path from 'path';\nimport { RemoteApp, AppArgument } from './farseerApi';\nimport { IFarseerClient } from './farseerFactory';\nimport { getTenantAppsDir, ensureDirectoryExists } from '../utils/helpers';\n\n// Local app config format (stored in apps/*.json)\nexport interface LocalAppConfig {\n name: string;\n description: string;\n entrypoint: string | null; // Script filename (e.g., \"index.ts\")\n scripts: string[]; // List of script filenames\n arguments: {\n name: string;\n defaultValue: string;\n }[];\n _remote?: {\n id: number;\n reference: string;\n };\n}\n\nexport interface AppSyncResult {\n created: string[];\n updated: string[];\n deleted: string[];\n unchanged: string[];\n}\n\nexport interface AppSyncStatus {\n newLocal: string[]; // Local apps not on remote\n newRemote: string[]; // Remote apps not locally\n modified: string[]; // Apps that differ\n synced: string[]; // Apps in sync\n}\n\n/**\n * Sanitize Croatian diacritics and other special characters to ASCII equivalents\n */\nfunction sanitizeDiacritics(text: string): string {\n const diacriticMap: Record<string, string> = {\n // Croatian\n '\u010D': 'c', '\u010C': 'C',\n '\u0107': 'c', '\u0106': 'C',\n '\u0161': 's', '\u0160': 'S',\n '\u017E': 'z', '\u017D': 'Z',\n '\u0111': 'd', '\u0110': 'D',\n // German/Other common\n '\u00E4': 'a', '\u00C4': 'A',\n '\u00F6': 'o', '\u00D6': 'O',\n '\u00FC': 'u', '\u00DC': 'U',\n '\u00DF': 'ss',\n // Polish\n '\u0105': 'a', '\u0104': 'A',\n '\u0119': 'e', '\u0118': 'E',\n '\u0142': 'l', '\u0141': 'L',\n '\u0144': 'n', '\u0143': 'N',\n '\u00F3': 'o', '\u00D3': 'O',\n '\u015B': 's', '\u015A': 'S',\n '\u017A': 'z', '\u0179': 'Z',\n '\u017C': 'z', '\u017B': 'Z',\n // French/Spanish\n '\u00E0': 'a', '\u00E1': 'a', '\u00E2': 'a',\n '\u00E8': 'e', '\u00E9': 'e', '\u00EA': 'e', '\u00EB': 'e',\n '\u00EC': 'i', '\u00ED': 'i', '\u00EE': 'i', '\u00EF': 'i',\n '\u00F2': 'o', '\u00F4': 'o',\n '\u00F9': 'u', '\u00FA': 'u', '\u00FB': 'u',\n '\u00F1': 'n', '\u00D1': 'N',\n '\u00E7': 'c', '\u00C7': 'C',\n };\n\n return text.split('').map(char => diacriticMap[char] || char).join('');\n}\n\n/**\n * Service for syncing app configurations between local JSON files and remote Farseer instance\n */\nexport class AppSyncService {\n private api: IFarseerClient;\n private appsDir: string;\n\n constructor(tenant: string, api: IFarseerClient) {\n this.api = api;\n this.appsDir = getTenantAppsDir(tenant);\n }\n\n /**\n * Get filename for an app (keep original name, just sanitize for filesystem)\n */\n private getAppFilename(name: string): string {\n return sanitizeDiacritics(name)\n .replace(/[<>:\"/\\\\|?*]/g, '') // Remove invalid filename characters\n .trim() + '.json';\n }\n\n /**\n * Load all local app configs\n */\n loadLocalApps(): Map<string, LocalAppConfig> {\n const apps = new Map<string, LocalAppConfig>();\n\n if (!fs.existsSync(this.appsDir)) {\n return apps;\n }\n\n const files = fs.readdirSync(this.appsDir).filter(f => f.endsWith('.json'));\n\n for (const file of files) {\n try {\n const content = fs.readFileSync(path.join(this.appsDir, file), 'utf-8');\n const config = JSON.parse(content) as LocalAppConfig;\n apps.set(config.name.toLowerCase(), config);\n } catch {\n // Skip invalid files\n }\n }\n\n return apps;\n }\n\n /**\n * Save a local app config\n */\n saveLocalApp(config: LocalAppConfig): void {\n ensureDirectoryExists(this.appsDir);\n const filename = this.getAppFilename(config.name);\n const filePath = path.join(this.appsDir, filename);\n fs.writeFileSync(filePath, JSON.stringify(config, null, 2), 'utf-8');\n }\n\n /**\n * Delete a local app config\n */\n deleteLocalApp(name: string): boolean {\n const filename = this.getAppFilename(name);\n const filePath = path.join(this.appsDir, filename);\n\n if (fs.existsSync(filePath)) {\n fs.unlinkSync(filePath);\n return true;\n }\n return false;\n }\n\n /**\n * Convert remote app to local config format\n */\n private remoteToLocal(remote: RemoteApp, reference: string): LocalAppConfig {\n const mainScript = remote.scriptFiles.find(s => s.id === remote.mainScriptFileId);\n\n return {\n name: remote.name,\n description: remote.description || '',\n entrypoint: mainScript?.name || null,\n scripts: remote.scriptFiles.map(s => s.name),\n arguments: remote.expectedArguments.map(a => ({\n name: a.name,\n defaultValue: a.defaultValue,\n })),\n _remote: {\n id: remote.id,\n reference: reference,\n },\n };\n }\n\n /**\n * Check if local and remote app configs are equivalent\n */\n private areAppsEqual(local: LocalAppConfig, remote: RemoteApp): boolean {\n // Compare name\n if (local.name !== remote.name) return false;\n\n // Compare description\n if ((local.description || '') !== (remote.description || '')) return false;\n\n // Compare entrypoint\n const remoteEntrypoint = remote.scriptFiles.find(s => s.id === remote.mainScriptFileId)?.name || null;\n if (local.entrypoint !== remoteEntrypoint) return false;\n\n // Compare scripts\n const localScripts = [...local.scripts].sort();\n const remoteScripts = [...remote.scriptFiles.map(s => s.name)].sort();\n if (JSON.stringify(localScripts) !== JSON.stringify(remoteScripts)) return false;\n\n // Compare arguments\n const localArgs = local.arguments.map(a => `${a.name}=${a.defaultValue}`).sort();\n const remoteArgs = remote.expectedArguments.map(a => `${a.name}=${a.defaultValue}`).sort();\n if (JSON.stringify(localArgs) !== JSON.stringify(remoteArgs)) return false;\n\n return true;\n }\n\n /**\n * Pull apps from remote and save locally\n */\n async pull(): Promise<AppSyncResult> {\n const result: AppSyncResult = {\n created: [],\n updated: [],\n deleted: [],\n unchanged: [],\n };\n\n // Load local apps\n const localApps = this.loadLocalApps();\n\n // Fetch remote apps\n const remoteAppList = await this.api.listApps();\n const remoteApps = new Map<string, { app: RemoteApp; reference: string }>();\n\n for (const item of remoteAppList) {\n const app = await this.api.getApp(item.reference);\n if (app) {\n remoteApps.set(app.name.toLowerCase(), { app, reference: item.reference });\n }\n }\n\n // Process remote apps\n for (const [key, { app, reference }] of remoteApps) {\n const localConfig = this.remoteToLocal(app, reference);\n const existingLocal = localApps.get(key);\n\n if (!existingLocal) {\n // New app from remote\n this.saveLocalApp(localConfig);\n result.created.push(app.name);\n } else if (!this.areAppsEqual(existingLocal, app)) {\n // App changed on remote - update local\n this.saveLocalApp(localConfig);\n result.updated.push(app.name);\n } else {\n result.unchanged.push(app.name);\n }\n }\n\n // Check for apps deleted on remote\n for (const [key, local] of localApps) {\n if (!remoteApps.has(key) && local._remote) {\n // App was synced before but now deleted on remote\n this.deleteLocalApp(local.name);\n result.deleted.push(local.name);\n }\n }\n\n return result;\n }\n\n /**\n * Push local apps to remote\n */\n async push(): Promise<AppSyncResult> {\n const result: AppSyncResult = {\n created: [],\n updated: [],\n deleted: [],\n unchanged: [],\n };\n\n // Load local apps\n const localApps = this.loadLocalApps();\n\n // Fetch remote apps\n const remoteAppList = await this.api.listApps();\n const remoteApps = new Map<string, { app: RemoteApp; reference: string }>();\n\n for (const item of remoteAppList) {\n const app = await this.api.getApp(item.reference);\n if (app) {\n remoteApps.set(app.name.toLowerCase(), { app, reference: item.reference });\n }\n }\n\n // Get available scripts for ID lookup\n // Build maps for both path-based and filename-based lookup (backward compatibility)\n const availableScripts = await this.api.getScriptFiles();\n const scriptIdByPath = new Map<string, string>();\n const scriptIdByName = new Map<string, string>();\n\n for (const s of availableScripts) {\n // s.name now contains full path (e.g., \"Scripts/test.ts\")\n const pathKey = s.name.toLowerCase();\n const filenameKey = s.name.split('/').pop()?.toLowerCase() || pathKey;\n\n scriptIdByPath.set(pathKey, s.id);\n // For filename lookup, only set if not already set (first match wins for ambiguous names)\n if (!scriptIdByName.has(filenameKey)) {\n scriptIdByName.set(filenameKey, s.id);\n }\n }\n\n // Helper to find script ID by path or filename\n const findScriptId = (scriptRef: string): string | undefined => {\n const key = scriptRef.toLowerCase();\n // Try exact path match first\n const byPath = scriptIdByPath.get(key);\n if (byPath) return byPath;\n // Try with Scripts/ prefix\n const withPrefix = scriptIdByPath.get(`scripts/${key}`);\n if (withPrefix) return withPrefix;\n // Fall back to filename match\n return scriptIdByName.get(key.split('/').pop() || key);\n };\n\n // Process local apps\n for (const [key, local] of localApps) {\n const remote = remoteApps.get(key);\n\n if (!remote) {\n // New local app - create on remote\n try {\n const created = await this.api.createApp(local.name);\n\n // Update with config (API requires name and description)\n const update = this.buildUpdatePayload(local, findScriptId);\n update.name = local.name;\n update.description = local.description;\n await this.api.updateApp(created.id.toString(), update);\n\n // Update local with remote ID\n local._remote = {\n id: created.id,\n reference: created.id.toString(),\n };\n this.saveLocalApp(local);\n\n result.created.push(local.name);\n } catch (error) {\n console.error(`Failed to create app ${local.name}:`, error);\n }\n } else if (!this.areAppsEqual(local, remote.app)) {\n // App differs - update remote\n try {\n const update = this.buildUpdatePayload(local, findScriptId);\n update.name = local.name;\n update.description = local.description;\n\n await this.api.updateApp(remote.reference, update);\n result.updated.push(local.name);\n } catch (error) {\n console.error(`Failed to update app ${local.name}:`, error);\n }\n } else {\n result.unchanged.push(local.name);\n }\n }\n\n // Note: We don't auto-delete remote apps when deleted locally\n // User must use \"farseer app delete\" explicitly\n\n return result;\n }\n\n /**\n * Build update payload for API\n */\n private buildUpdatePayload(\n local: LocalAppConfig,\n findScriptId: (scriptRef: string) => string | undefined\n ): {\n name?: string;\n description?: string;\n expectedArguments?: AppArgument[];\n mainScriptFileId?: string | null;\n scriptFileIds?: string[];\n } {\n const update: {\n name?: string;\n description?: string;\n expectedArguments?: AppArgument[];\n mainScriptFileId?: string | null;\n scriptFileIds?: string[];\n } = {};\n\n // Arguments\n if (local.arguments.length > 0) {\n update.expectedArguments = local.arguments.map(a => ({\n name: a.name,\n type: 'variable' as const,\n defaultValue: a.defaultValue,\n }));\n }\n\n // Scripts - lookup by path or filename\n if (local.scripts.length > 0) {\n const scriptIds: string[] = [];\n for (const scriptRef of local.scripts) {\n const id = findScriptId(scriptRef);\n if (id) {\n scriptIds.push(id);\n }\n }\n if (scriptIds.length > 0) {\n update.scriptFileIds = scriptIds;\n }\n }\n\n // Entrypoint - lookup by path or filename\n if (local.entrypoint) {\n const entrypointId = findScriptId(local.entrypoint);\n if (entrypointId) {\n update.mainScriptFileId = entrypointId;\n }\n }\n\n return update;\n }\n\n /**\n * Get sync status without making changes\n */\n async getStatus(): Promise<AppSyncStatus> {\n const status: AppSyncStatus = {\n newLocal: [],\n newRemote: [],\n modified: [],\n synced: [],\n };\n\n // Load local apps\n const localApps = this.loadLocalApps();\n\n // Fetch remote apps\n const remoteAppList = await this.api.listApps();\n const remoteApps = new Map<string, { app: RemoteApp; reference: string }>();\n\n for (const item of remoteAppList) {\n const app = await this.api.getApp(item.reference);\n if (app) {\n remoteApps.set(app.name.toLowerCase(), { app, reference: item.reference });\n }\n }\n\n // Check local apps\n for (const [key, local] of localApps) {\n const remote = remoteApps.get(key);\n\n if (!remote) {\n status.newLocal.push(local.name);\n } else if (!this.areAppsEqual(local, remote.app)) {\n status.modified.push(local.name);\n } else {\n status.synced.push(local.name);\n }\n }\n\n // Check for new remote apps\n for (const [key, { app }] of remoteApps) {\n if (!localApps.has(key)) {\n status.newRemote.push(app.name);\n }\n }\n\n return status;\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAoB;AACpB,WAAsB;AAGtB,qBAAwD;AAmCxD,SAAS,mBAAmB,MAAsB;AAC9C,QAAM,eAAuC;AAAA;AAAA,IAEzC,UAAK;AAAA,IAAK,UAAK;AAAA,IACf,UAAK;AAAA,IAAK,UAAK;AAAA,IACf,UAAK;AAAA,IAAK,UAAK;AAAA,IACf,UAAK;AAAA,IAAK,UAAK;AAAA,IACf,UAAK;AAAA,IAAK,UAAK;AAAA;AAAA,IAEf,QAAK;AAAA,IAAK,QAAK;AAAA,IACf,QAAK;AAAA,IAAK,QAAK;AAAA,IACf,QAAK;AAAA,IAAK,QAAK;AAAA,IACf,QAAK;AAAA;AAAA,IAEL,UAAK;AAAA,IAAK,UAAK;AAAA,IACf,UAAK;AAAA,IAAK,UAAK;AAAA,IACf,UAAK;AAAA,IAAK,UAAK;AAAA,IACf,UAAK;AAAA,IAAK,UAAK;AAAA,IACf,QAAK;AAAA,IAAK,QAAK;AAAA,IACf,UAAK;AAAA,IAAK,UAAK;AAAA,IACf,UAAK;AAAA,IAAK,UAAK;AAAA,IACf,UAAK;AAAA,IAAK,UAAK;AAAA;AAAA,IAEf,QAAK;AAAA,IAAK,QAAK;AAAA,IAAK,QAAK;AAAA,IACzB,QAAK;AAAA,IAAK,QAAK;AAAA,IAAK,QAAK;AAAA,IAAK,QAAK;AAAA,IACnC,QAAK;AAAA,IAAK,QAAK;AAAA,IAAK,QAAK;AAAA,IAAK,QAAK;AAAA,IACnC,QAAK;AAAA,IAAK,QAAK;AAAA,IACf,QAAK;AAAA,IAAK,QAAK;AAAA,IAAK,QAAK;AAAA,IACzB,QAAK;AAAA,IAAK,QAAK;AAAA,IACf,QAAK;AAAA,IAAK,QAAK;AAAA,EACnB;AAEA,SAAO,KAAK,MAAM,EAAE,EAAE,IAAI,UAAQ,aAAa,IAAI,KAAK,IAAI,EAAE,KAAK,EAAE;AACzE;AAKO,MAAM,eAAe;AAAA,EAIxB,YAAY,QAAgB,KAAqB;AAC7C,SAAK,MAAM;AACX,SAAK,cAAU,iCAAiB,MAAM;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,MAAsB;AACzC,WAAO,mBAAmB,IAAI,EACzB,QAAQ,iBAAiB,EAAE,EAC3B,KAAK,IAAI;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,gBAA6C;AACzC,UAAM,OAAO,oBAAI,IAA4B;AAE7C,QAAI,CAAC,GAAG,WAAW,KAAK,OAAO,GAAG;AAC9B,aAAO;AAAA,IACX;AAEA,UAAM,QAAQ,GAAG,YAAY,KAAK,OAAO,EAAE,OAAO,OAAK,EAAE,SAAS,OAAO,CAAC;AAE1E,eAAW,QAAQ,OAAO;AACtB,UAAI;AACA,cAAM,UAAU,GAAG,aAAa,KAAK,KAAK,KAAK,SAAS,IAAI,GAAG,OAAO;AACtE,cAAM,SAAS,KAAK,MAAM,OAAO;AACjC,aAAK,IAAI,OAAO,KAAK,YAAY,GAAG,MAAM;AAAA,MAC9C,QAAQ;AAAA,MAER;AAAA,IACJ;AAEA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,QAA8B;AACvC,8CAAsB,KAAK,OAAO;AAClC,UAAM,WAAW,KAAK,eAAe,OAAO,IAAI;AAChD,UAAM,WAAW,KAAK,KAAK,KAAK,SAAS,QAAQ;AACjD,OAAG,cAAc,UAAU,KAAK,UAAU,QAAQ,MAAM,CAAC,GAAG,OAAO;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,MAAuB;AAClC,UAAM,WAAW,KAAK,eAAe,IAAI;AACzC,UAAM,WAAW,KAAK,KAAK,KAAK,SAAS,QAAQ;AAEjD,QAAI,GAAG,WAAW,QAAQ,GAAG;AACzB,SAAG,WAAW,QAAQ;AACtB,aAAO;AAAA,IACX;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,QAAmB,WAAmC;AACxE,UAAM,aAAa,OAAO,YAAY,KAAK,OAAK,EAAE,OAAO,OAAO,gBAAgB;AAEhF,WAAO;AAAA,MACH,MAAM,OAAO;AAAA,MACb,aAAa,OAAO,eAAe;AAAA,MACnC,YAAY,YAAY,QAAQ;AAAA,MAChC,SAAS,OAAO,YAAY,IAAI,OAAK,EAAE,IAAI;AAAA,MAC3C,WAAW,OAAO,kBAAkB,IAAI,QAAM;AAAA,QAC1C,MAAM,EAAE;AAAA,QACR,cAAc,EAAE;AAAA,MACpB,EAAE;AAAA,MACF,SAAS;AAAA,QACL,IAAI,OAAO;AAAA,QACX;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAa,OAAuB,QAA4B;AAEpE,QAAI,MAAM,SAAS,OAAO,KAAM,QAAO;AAGvC,SAAK,MAAM,eAAe,SAAS,OAAO,eAAe,IAAK,QAAO;AAGrE,UAAM,mBAAmB,OAAO,YAAY,KAAK,OAAK,EAAE,OAAO,OAAO,gBAAgB,GAAG,QAAQ;AACjG,QAAI,MAAM,eAAe,iBAAkB,QAAO;AAGlD,UAAM,eAAe,CAAC,GAAG,MAAM,OAAO,EAAE,KAAK;AAC7C,UAAM,gBAAgB,CAAC,GAAG,OAAO,YAAY,IAAI,OAAK,EAAE,IAAI,CAAC,EAAE,KAAK;AACpE,QAAI,KAAK,UAAU,YAAY,MAAM,KAAK,UAAU,aAAa,EAAG,QAAO;AAG3E,UAAM,YAAY,MAAM,UAAU,IAAI,OAAK,GAAG,EAAE,IAAI,IAAI,EAAE,YAAY,EAAE,EAAE,KAAK;AAC/E,UAAM,aAAa,OAAO,kBAAkB,IAAI,OAAK,GAAG,EAAE,IAAI,IAAI,EAAE,YAAY,EAAE,EAAE,KAAK;AACzF,QAAI,KAAK,UAAU,SAAS,MAAM,KAAK,UAAU,UAAU,EAAG,QAAO;AAErE,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAA+B;AACjC,UAAM,SAAwB;AAAA,MAC1B,SAAS,CAAC;AAAA,MACV,SAAS,CAAC;AAAA,MACV,SAAS,CAAC;AAAA,MACV,WAAW,CAAC;AAAA,IAChB;AAGA,UAAM,YAAY,KAAK,cAAc;AAGrC,UAAM,gBAAgB,MAAM,KAAK,IAAI,SAAS;AAC9C,UAAM,aAAa,oBAAI,IAAmD;AAE1E,eAAW,QAAQ,eAAe;AAC9B,YAAM,MAAM,MAAM,KAAK,IAAI,OAAO,KAAK,SAAS;AAChD,UAAI,KAAK;AACL,mBAAW,IAAI,IAAI,KAAK,YAAY,GAAG,EAAE,KAAK,WAAW,KAAK,UAAU,CAAC;AAAA,MAC7E;AAAA,IACJ;AAGA,eAAW,CAAC,KAAK,EAAE,KAAK,UAAU,CAAC,KAAK,YAAY;AAChD,YAAM,cAAc,KAAK,cAAc,KAAK,SAAS;AACrD,YAAM,gBAAgB,UAAU,IAAI,GAAG;AAEvC,UAAI,CAAC,eAAe;AAEhB,aAAK,aAAa,WAAW;AAC7B,eAAO,QAAQ,KAAK,IAAI,IAAI;AAAA,MAChC,WAAW,CAAC,KAAK,aAAa,eAAe,GAAG,GAAG;AAE/C,aAAK,aAAa,WAAW;AAC7B,eAAO,QAAQ,KAAK,IAAI,IAAI;AAAA,MAChC,OAAO;AACH,eAAO,UAAU,KAAK,IAAI,IAAI;AAAA,MAClC;AAAA,IACJ;AAGA,eAAW,CAAC,KAAK,KAAK,KAAK,WAAW;AAClC,UAAI,CAAC,WAAW,IAAI,GAAG,KAAK,MAAM,SAAS;AAEvC,aAAK,eAAe,MAAM,IAAI;AAC9B,eAAO,QAAQ,KAAK,MAAM,IAAI;AAAA,MAClC;AAAA,IACJ;AAEA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAA+B;AACjC,UAAM,SAAwB;AAAA,MAC1B,SAAS,CAAC;AAAA,MACV,SAAS,CAAC;AAAA,MACV,SAAS,CAAC;AAAA,MACV,WAAW,CAAC;AAAA,IAChB;AAGA,UAAM,YAAY,KAAK,cAAc;AAGrC,UAAM,gBAAgB,MAAM,KAAK,IAAI,SAAS;AAC9C,UAAM,aAAa,oBAAI,IAAmD;AAE1E,eAAW,QAAQ,eAAe;AAC9B,YAAM,MAAM,MAAM,KAAK,IAAI,OAAO,KAAK,SAAS;AAChD,UAAI,KAAK;AACL,mBAAW,IAAI,IAAI,KAAK,YAAY,GAAG,EAAE,KAAK,WAAW,KAAK,UAAU,CAAC;AAAA,MAC7E;AAAA,IACJ;AAIA,UAAM,mBAAmB,MAAM,KAAK,IAAI,eAAe;AACvD,UAAM,iBAAiB,oBAAI,IAAoB;AAC/C,UAAM,iBAAiB,oBAAI,IAAoB;AAE/C,eAAW,KAAK,kBAAkB;AAE9B,YAAM,UAAU,EAAE,KAAK,YAAY;AACnC,YAAM,cAAc,EAAE,KAAK,MAAM,GAAG,EAAE,IAAI,GAAG,YAAY,KAAK;AAE9D,qBAAe,IAAI,SAAS,EAAE,EAAE;AAEhC,UAAI,CAAC,eAAe,IAAI,WAAW,GAAG;AAClC,uBAAe,IAAI,aAAa,EAAE,EAAE;AAAA,MACxC;AAAA,IACJ;AAGA,UAAM,eAAe,CAAC,cAA0C;AAC5D,YAAM,MAAM,UAAU,YAAY;AAElC,YAAM,SAAS,eAAe,IAAI,GAAG;AACrC,UAAI,OAAQ,QAAO;AAEnB,YAAM,aAAa,eAAe,IAAI,WAAW,GAAG,EAAE;AACtD,UAAI,WAAY,QAAO;AAEvB,aAAO,eAAe,IAAI,IAAI,MAAM,GAAG,EAAE,IAAI,KAAK,GAAG;AAAA,IACzD;AAGA,eAAW,CAAC,KAAK,KAAK,KAAK,WAAW;AAClC,YAAM,SAAS,WAAW,IAAI,GAAG;AAEjC,UAAI,CAAC,QAAQ;AAET,YAAI;AACA,gBAAM,UAAU,MAAM,KAAK,IAAI,UAAU,MAAM,IAAI;AAGnD,gBAAM,SAAS,KAAK,mBAAmB,OAAO,YAAY;AAC1D,iBAAO,OAAO,MAAM;AACpB,iBAAO,cAAc,MAAM;AAC3B,gBAAM,KAAK,IAAI,UAAU,QAAQ,GAAG,SAAS,GAAG,MAAM;AAGtD,gBAAM,UAAU;AAAA,YACZ,IAAI,QAAQ;AAAA,YACZ,WAAW,QAAQ,GAAG,SAAS;AAAA,UACnC;AACA,eAAK,aAAa,KAAK;AAEvB,iBAAO,QAAQ,KAAK,MAAM,IAAI;AAAA,QAClC,SAAS,OAAO;AACZ,kBAAQ,MAAM,wBAAwB,MAAM,IAAI,KAAK,KAAK;AAAA,QAC9D;AAAA,MACJ,WAAW,CAAC,KAAK,aAAa,OAAO,OAAO,GAAG,GAAG;AAE9C,YAAI;AACA,gBAAM,SAAS,KAAK,mBAAmB,OAAO,YAAY;AAC1D,iBAAO,OAAO,MAAM;AACpB,iBAAO,cAAc,MAAM;AAE3B,gBAAM,KAAK,IAAI,UAAU,OAAO,WAAW,MAAM;AACjD,iBAAO,QAAQ,KAAK,MAAM,IAAI;AAAA,QAClC,SAAS,OAAO;AACZ,kBAAQ,MAAM,wBAAwB,MAAM,IAAI,KAAK,KAAK;AAAA,QAC9D;AAAA,MACJ,OAAO;AACH,eAAO,UAAU,KAAK,MAAM,IAAI;AAAA,MACpC;AAAA,IACJ;AAKA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKQ,mBACJ,OACA,cAOF;AACE,UAAM,SAMF,CAAC;AAGL,QAAI,MAAM,UAAU,SAAS,GAAG;AAC5B,aAAO,oBAAoB,MAAM,UAAU,IAAI,QAAM;AAAA,QACjD,MAAM,EAAE;AAAA,QACR,MAAM;AAAA,QACN,cAAc,EAAE;AAAA,MACpB,EAAE;AAAA,IACN;AAGA,QAAI,MAAM,QAAQ,SAAS,GAAG;AAC1B,YAAM,YAAsB,CAAC;AAC7B,iBAAW,aAAa,MAAM,SAAS;AACnC,cAAM,KAAK,aAAa,SAAS;AACjC,YAAI,IAAI;AACJ,oBAAU,KAAK,EAAE;AAAA,QACrB;AAAA,MACJ;AACA,UAAI,UAAU,SAAS,GAAG;AACtB,eAAO,gBAAgB;AAAA,MAC3B;AAAA,IACJ;AAGA,QAAI,MAAM,YAAY;AAClB,YAAM,eAAe,aAAa,MAAM,UAAU;AAClD,UAAI,cAAc;AACd,eAAO,mBAAmB;AAAA,MAC9B;AAAA,IACJ;AAEA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAoC;AACtC,UAAM,SAAwB;AAAA,MAC1B,UAAU,CAAC;AAAA,MACX,WAAW,CAAC;AAAA,MACZ,UAAU,CAAC;AAAA,MACX,QAAQ,CAAC;AAAA,IACb;AAGA,UAAM,YAAY,KAAK,cAAc;AAGrC,UAAM,gBAAgB,MAAM,KAAK,IAAI,SAAS;AAC9C,UAAM,aAAa,oBAAI,IAAmD;AAE1E,eAAW,QAAQ,eAAe;AAC9B,YAAM,MAAM,MAAM,KAAK,IAAI,OAAO,KAAK,SAAS;AAChD,UAAI,KAAK;AACL,mBAAW,IAAI,IAAI,KAAK,YAAY,GAAG,EAAE,KAAK,WAAW,KAAK,UAAU,CAAC;AAAA,MAC7E;AAAA,IACJ;AAGA,eAAW,CAAC,KAAK,KAAK,KAAK,WAAW;AAClC,YAAM,SAAS,WAAW,IAAI,GAAG;AAEjC,UAAI,CAAC,QAAQ;AACT,eAAO,SAAS,KAAK,MAAM,IAAI;AAAA,MACnC,WAAW,CAAC,KAAK,aAAa,OAAO,OAAO,GAAG,GAAG;AAC9C,eAAO,SAAS,KAAK,MAAM,IAAI;AAAA,MACnC,OAAO;AACH,eAAO,OAAO,KAAK,MAAM,IAAI;AAAA,MACjC;AAAA,IACJ;AAGA,eAAW,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,YAAY;AACrC,UAAI,CAAC,UAAU,IAAI,GAAG,GAAG;AACrB,eAAO,UAAU,KAAK,IAAI,IAAI;AAAA,MAClC;AAAA,IACJ;AAEA,WAAO;AAAA,EACX;AACJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface ApiKeyCredential {
|
|
2
|
+
type: 'apiKey';
|
|
3
|
+
tenantId: string;
|
|
4
|
+
apiKey: string;
|
|
5
|
+
basePath: string;
|
|
6
|
+
}
|
|
7
|
+
export interface UserAuth {
|
|
8
|
+
accessToken: string;
|
|
9
|
+
refreshToken: string;
|
|
10
|
+
expiresAt: string;
|
|
11
|
+
tenant?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface CurrentCheckout {
|
|
14
|
+
organisation: string;
|
|
15
|
+
tenant: string;
|
|
16
|
+
}
|
|
17
|
+
export interface FarseerConfig {
|
|
18
|
+
credentials: Record<string, ApiKeyCredential>;
|
|
19
|
+
userAuth?: UserAuth;
|
|
20
|
+
currentTenant?: string;
|
|
21
|
+
currentCheckout?: CurrentCheckout;
|
|
22
|
+
}
|
|
23
|
+
export declare function loadConfig(): FarseerConfig;
|
|
24
|
+
export declare function saveConfig(config: FarseerConfig): void;
|
|
25
|
+
export declare function getCredential(tenant: string): ApiKeyCredential | undefined;
|
|
26
|
+
export declare function setCredential(tenant: string, credential: ApiKeyCredential): void;
|
|
27
|
+
export declare function removeCredential(tenant: string): boolean;
|
|
28
|
+
export declare function listCredentials(): Record<string, ApiKeyCredential>;
|
|
29
|
+
export declare function getUserAuth(): UserAuth | undefined;
|
|
30
|
+
export declare function setUserAuth(auth: UserAuth): void;
|
|
31
|
+
export declare function clearUserAuth(): void;
|
|
32
|
+
export declare function isUserAuthValid(): boolean;
|
|
33
|
+
export declare function generateBasePath(organisation: string): string;
|
|
34
|
+
export declare function getCurrentCheckout(): CurrentCheckout | undefined;
|
|
35
|
+
export declare function getCurrentTenant(): string | undefined;
|
|
36
|
+
export declare function getCurrentOrganisation(): string | undefined;
|
|
37
|
+
export declare function setCurrentCheckout(organisation: string, tenant: string): void;
|
|
38
|
+
export declare function setCurrentTenant(tenant: string): void;
|
|
39
|
+
export declare function clearCurrentTenant(): void;
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
var configService_exports = {};
|
|
29
|
+
__export(configService_exports, {
|
|
30
|
+
clearCurrentTenant: () => clearCurrentTenant,
|
|
31
|
+
clearUserAuth: () => clearUserAuth,
|
|
32
|
+
generateBasePath: () => generateBasePath,
|
|
33
|
+
getCredential: () => getCredential,
|
|
34
|
+
getCurrentCheckout: () => getCurrentCheckout,
|
|
35
|
+
getCurrentOrganisation: () => getCurrentOrganisation,
|
|
36
|
+
getCurrentTenant: () => getCurrentTenant,
|
|
37
|
+
getTenantOrg: () => getTenantOrg,
|
|
38
|
+
getUserAuth: () => getUserAuth,
|
|
39
|
+
isUserAuthValid: () => isUserAuthValid,
|
|
40
|
+
listCredentials: () => listCredentials,
|
|
41
|
+
loadConfig: () => loadConfig,
|
|
42
|
+
removeCredential: () => removeCredential,
|
|
43
|
+
saveConfig: () => saveConfig,
|
|
44
|
+
saveTenantOrgMapping: () => saveTenantOrgMapping,
|
|
45
|
+
setCredential: () => setCredential,
|
|
46
|
+
setCurrentCheckout: () => setCurrentCheckout,
|
|
47
|
+
setCurrentTenant: () => setCurrentTenant,
|
|
48
|
+
setUserAuth: () => setUserAuth
|
|
49
|
+
});
|
|
50
|
+
module.exports = __toCommonJS(configService_exports);
|
|
51
|
+
var fs = __toESM(require("fs"));
|
|
52
|
+
var path = __toESM(require("path"));
|
|
53
|
+
var os = __toESM(require("os"));
|
|
54
|
+
const CONFIG_DIR = path.join(os.homedir(), ".farseer");
|
|
55
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
56
|
+
function ensureConfigDir() {
|
|
57
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
58
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function getDefaultConfig() {
|
|
62
|
+
return {
|
|
63
|
+
credentials: {},
|
|
64
|
+
userAuth: void 0
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function loadConfig() {
|
|
68
|
+
ensureConfigDir();
|
|
69
|
+
if (!fs.existsSync(CONFIG_FILE)) {
|
|
70
|
+
return getDefaultConfig();
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
const content = fs.readFileSync(CONFIG_FILE, "utf-8");
|
|
74
|
+
return JSON.parse(content);
|
|
75
|
+
} catch {
|
|
76
|
+
return getDefaultConfig();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function saveConfig(config) {
|
|
80
|
+
ensureConfigDir();
|
|
81
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), "utf-8");
|
|
82
|
+
}
|
|
83
|
+
function getCredential(tenant) {
|
|
84
|
+
const config = loadConfig();
|
|
85
|
+
return config.credentials[tenant];
|
|
86
|
+
}
|
|
87
|
+
function setCredential(tenant, credential) {
|
|
88
|
+
const config = loadConfig();
|
|
89
|
+
config.credentials[tenant] = credential;
|
|
90
|
+
saveConfig(config);
|
|
91
|
+
}
|
|
92
|
+
function removeCredential(tenant) {
|
|
93
|
+
const config = loadConfig();
|
|
94
|
+
if (config.credentials[tenant]) {
|
|
95
|
+
delete config.credentials[tenant];
|
|
96
|
+
saveConfig(config);
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
function listCredentials() {
|
|
102
|
+
const config = loadConfig();
|
|
103
|
+
return config.credentials;
|
|
104
|
+
}
|
|
105
|
+
function getUserAuth() {
|
|
106
|
+
const config = loadConfig();
|
|
107
|
+
return config.userAuth;
|
|
108
|
+
}
|
|
109
|
+
function setUserAuth(auth) {
|
|
110
|
+
const config = loadConfig();
|
|
111
|
+
config.userAuth = auth;
|
|
112
|
+
saveConfig(config);
|
|
113
|
+
}
|
|
114
|
+
function clearUserAuth() {
|
|
115
|
+
const config = loadConfig();
|
|
116
|
+
config.userAuth = void 0;
|
|
117
|
+
saveConfig(config);
|
|
118
|
+
}
|
|
119
|
+
function isUserAuthValid() {
|
|
120
|
+
const auth = getUserAuth();
|
|
121
|
+
if (!auth) return false;
|
|
122
|
+
const expiresAt = new Date(auth.expiresAt);
|
|
123
|
+
const bufferMs = 10 * 1e3;
|
|
124
|
+
return expiresAt.getTime() > Date.now() + bufferMs;
|
|
125
|
+
}
|
|
126
|
+
function generateBasePath(organisation) {
|
|
127
|
+
return `https://${organisation}.farseer.io/api/v3`;
|
|
128
|
+
}
|
|
129
|
+
function getCurrentCheckout() {
|
|
130
|
+
const config = loadConfig();
|
|
131
|
+
if (config.currentCheckout) {
|
|
132
|
+
return config.currentCheckout;
|
|
133
|
+
}
|
|
134
|
+
if (config.currentTenant) {
|
|
135
|
+
return { organisation: config.currentTenant, tenant: config.currentTenant };
|
|
136
|
+
}
|
|
137
|
+
return void 0;
|
|
138
|
+
}
|
|
139
|
+
function getCurrentTenant() {
|
|
140
|
+
const checkout = getCurrentCheckout();
|
|
141
|
+
return checkout?.tenant;
|
|
142
|
+
}
|
|
143
|
+
function getCurrentOrganisation() {
|
|
144
|
+
const checkout = getCurrentCheckout();
|
|
145
|
+
return checkout?.organisation;
|
|
146
|
+
}
|
|
147
|
+
function setCurrentCheckout(organisation, tenant) {
|
|
148
|
+
const config = loadConfig();
|
|
149
|
+
config.currentCheckout = { organisation, tenant };
|
|
150
|
+
config.currentTenant = tenant;
|
|
151
|
+
saveConfig(config);
|
|
152
|
+
}
|
|
153
|
+
function setCurrentTenant(tenant) {
|
|
154
|
+
setCurrentCheckout(tenant, tenant);
|
|
155
|
+
}
|
|
156
|
+
function clearCurrentTenant() {
|
|
157
|
+
const config = loadConfig();
|
|
158
|
+
config.currentTenant = void 0;
|
|
159
|
+
config.currentCheckout = void 0;
|
|
160
|
+
saveConfig(config);
|
|
161
|
+
}
|
|
162
|
+
function saveTenantOrgMapping(tenant, organisation) {
|
|
163
|
+
const config = loadConfig();
|
|
164
|
+
if (!config.tenantOrgMapping) {
|
|
165
|
+
config.tenantOrgMapping = {};
|
|
166
|
+
}
|
|
167
|
+
config.tenantOrgMapping[tenant] = organisation;
|
|
168
|
+
saveConfig(config);
|
|
169
|
+
}
|
|
170
|
+
function getTenantOrg(tenant) {
|
|
171
|
+
const config = loadConfig();
|
|
172
|
+
return config.tenantOrgMapping?.[tenant];
|
|
173
|
+
}
|
|
174
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
175
|
+
0 && (module.exports = {
|
|
176
|
+
clearCurrentTenant,
|
|
177
|
+
clearUserAuth,
|
|
178
|
+
generateBasePath,
|
|
179
|
+
getCredential,
|
|
180
|
+
getCurrentCheckout,
|
|
181
|
+
getCurrentOrganisation,
|
|
182
|
+
getCurrentTenant,
|
|
183
|
+
getTenantOrg,
|
|
184
|
+
getUserAuth,
|
|
185
|
+
isUserAuthValid,
|
|
186
|
+
listCredentials,
|
|
187
|
+
loadConfig,
|
|
188
|
+
removeCredential,
|
|
189
|
+
saveConfig,
|
|
190
|
+
saveTenantOrgMapping,
|
|
191
|
+
setCredential,
|
|
192
|
+
setCurrentCheckout,
|
|
193
|
+
setCurrentTenant,
|
|
194
|
+
setUserAuth
|
|
195
|
+
});
|
|
196
|
+
//# sourceMappingURL=configService.js.map
|