charon-hooks 0.2.0 → 0.2.1
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/dist/server/index.js +149 -73
- package/package.json +1 -1
package/dist/server/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// src/server/app.ts
|
|
2
2
|
import { Hono as Hono8 } from "hono";
|
|
3
|
-
import { dirname as
|
|
4
|
-
import { fileURLToPath } from "url";
|
|
5
|
-
import { existsSync as
|
|
3
|
+
import { dirname as dirname3, resolve as resolve4 } from "path";
|
|
4
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
5
|
+
import { existsSync as existsSync5 } from "fs";
|
|
6
6
|
|
|
7
7
|
// src/server/middleware/logger.ts
|
|
8
8
|
import { createMiddleware } from "hono/factory";
|
|
@@ -106,8 +106,8 @@ function serveStatic({ root, path: fallbackPath }) {
|
|
|
106
106
|
import { Hono } from "hono";
|
|
107
107
|
|
|
108
108
|
// src/lib/config/loader.ts
|
|
109
|
-
import { readFileSync as readFileSync2, writeFileSync, mkdirSync, watch, existsSync as
|
|
110
|
-
import { dirname } from "path";
|
|
109
|
+
import { readFileSync as readFileSync2, writeFileSync, mkdirSync as mkdirSync2, watch, existsSync as existsSync3 } from "fs";
|
|
110
|
+
import { dirname as dirname2 } from "path";
|
|
111
111
|
|
|
112
112
|
// src/lib/config/schema.ts
|
|
113
113
|
import { z } from "zod";
|
|
@@ -258,8 +258,8 @@ function initSchema(db2) {
|
|
|
258
258
|
var db = null;
|
|
259
259
|
function getDb() {
|
|
260
260
|
if (!db) {
|
|
261
|
-
const
|
|
262
|
-
db = createDatabase(
|
|
261
|
+
const dbPath2 = process.env.CHARON_DB || "charon.db";
|
|
262
|
+
db = createDatabase(dbPath2);
|
|
263
263
|
initSchema(db);
|
|
264
264
|
}
|
|
265
265
|
return db;
|
|
@@ -422,16 +422,92 @@ function listEvents(db2, filter) {
|
|
|
422
422
|
}
|
|
423
423
|
|
|
424
424
|
// src/lib/pipeline/sanitizer.ts
|
|
425
|
-
import { resolve as
|
|
425
|
+
import { resolve as resolve3 } from "path";
|
|
426
426
|
import { pathToFileURL } from "url";
|
|
427
|
+
|
|
428
|
+
// src/lib/data-dir.ts
|
|
429
|
+
import { existsSync as existsSync2, mkdirSync, copyFileSync, readdirSync } from "fs";
|
|
430
|
+
import { resolve as resolve2, dirname } from "path";
|
|
431
|
+
import { homedir } from "os";
|
|
432
|
+
import { fileURLToPath } from "url";
|
|
433
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
434
|
+
var cwd = process.cwd();
|
|
435
|
+
var userDataDir = process.env.CHARON_DATA_DIR || resolve2(homedir(), ".charon");
|
|
436
|
+
var isDevMode = existsSync2(resolve2(cwd, "sanitizers")) || existsSync2(resolve2(cwd, "src/lib/data-dir.ts"));
|
|
437
|
+
var dataDir = isDevMode ? process.cwd() : userDataDir;
|
|
438
|
+
var configDir = resolve2(dataDir, "config");
|
|
439
|
+
var triggersPath = resolve2(configDir, "triggers.yaml");
|
|
440
|
+
var configPath = resolve2(configDir, "config.yaml");
|
|
441
|
+
var sanitizersDir = resolve2(dataDir, "sanitizers");
|
|
442
|
+
var dbPath = process.env.CHARON_DB || resolve2(dataDir, "charon.db");
|
|
443
|
+
function getBundledDir() {
|
|
444
|
+
const devPath = resolve2(process.cwd());
|
|
445
|
+
const prodPath = resolve2(__dirname, "../..");
|
|
446
|
+
if (existsSync2(resolve2(devPath, "src/lib/data-dir.ts"))) {
|
|
447
|
+
return devPath;
|
|
448
|
+
}
|
|
449
|
+
return prodPath;
|
|
450
|
+
}
|
|
451
|
+
function initializeDataDir() {
|
|
452
|
+
if (isDevMode) {
|
|
453
|
+
console.log("[data-dir] Dev mode: using", dataDir);
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
console.log("[data-dir] Prod mode: using", dataDir);
|
|
457
|
+
if (!existsSync2(dataDir)) {
|
|
458
|
+
mkdirSync(dataDir, { recursive: true });
|
|
459
|
+
}
|
|
460
|
+
if (!existsSync2(configDir)) {
|
|
461
|
+
mkdirSync(configDir, { recursive: true });
|
|
462
|
+
}
|
|
463
|
+
if (!existsSync2(sanitizersDir)) {
|
|
464
|
+
mkdirSync(sanitizersDir, { recursive: true });
|
|
465
|
+
}
|
|
466
|
+
const bundledDir = getBundledDir();
|
|
467
|
+
copyDefaultFile(
|
|
468
|
+
resolve2(bundledDir, "config/config.yaml.dist"),
|
|
469
|
+
resolve2(configDir, "config.yaml")
|
|
470
|
+
);
|
|
471
|
+
copyDefaultFile(
|
|
472
|
+
resolve2(bundledDir, "config/triggers.yaml.dist"),
|
|
473
|
+
resolve2(configDir, "triggers.yaml")
|
|
474
|
+
);
|
|
475
|
+
const bundledSanitizersDir = resolve2(bundledDir, "sanitizers");
|
|
476
|
+
if (existsSync2(bundledSanitizersDir)) {
|
|
477
|
+
const existingSanitizers = existsSync2(sanitizersDir) ? readdirSync(sanitizersDir).filter((f) => f.endsWith(".ts")) : [];
|
|
478
|
+
if (existingSanitizers.length === 0) {
|
|
479
|
+
const defaultSanitizers = readdirSync(bundledSanitizersDir).filter(
|
|
480
|
+
(f) => f.endsWith(".ts")
|
|
481
|
+
);
|
|
482
|
+
for (const file of defaultSanitizers) {
|
|
483
|
+
copyDefaultFile(
|
|
484
|
+
resolve2(bundledSanitizersDir, file),
|
|
485
|
+
resolve2(sanitizersDir, file)
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
if (defaultSanitizers.length > 0) {
|
|
489
|
+
console.log(
|
|
490
|
+
`[data-dir] Installed ${defaultSanitizers.length} default sanitizer(s)`
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
function copyDefaultFile(src, dest) {
|
|
497
|
+
if (!existsSync2(dest) && existsSync2(src)) {
|
|
498
|
+
copyFileSync(src, dest);
|
|
499
|
+
console.log(`[data-dir] Created ${dest}`);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// src/lib/pipeline/sanitizer.ts
|
|
427
504
|
var sanitizerCache = /* @__PURE__ */ new Map();
|
|
428
|
-
var SANITIZERS_DIR = process.env.CHARON_SANITIZERS_DIR || "sanitizers";
|
|
429
505
|
async function loadSanitizer(name) {
|
|
430
506
|
if (sanitizerCache.has(name)) {
|
|
431
507
|
return sanitizerCache.get(name);
|
|
432
508
|
}
|
|
433
509
|
try {
|
|
434
|
-
const sanitizerPath =
|
|
510
|
+
const sanitizerPath = resolve3(sanitizersDir, `${name}.ts`);
|
|
435
511
|
const sanitizerUrl = pathToFileURL(sanitizerPath).href;
|
|
436
512
|
const mod = await import(sanitizerUrl);
|
|
437
513
|
const fn = mod.default;
|
|
@@ -754,7 +830,7 @@ async function startTunnel(config, port = 3e3) {
|
|
|
754
830
|
}
|
|
755
831
|
try {
|
|
756
832
|
await ngrok.disconnect();
|
|
757
|
-
await new Promise((
|
|
833
|
+
await new Promise((resolve5) => setTimeout(resolve5, 1e3));
|
|
758
834
|
} catch {
|
|
759
835
|
}
|
|
760
836
|
listener = null;
|
|
@@ -837,9 +913,9 @@ var DEFAULT_CONFIG = `# Charon trigger configuration
|
|
|
837
913
|
|
|
838
914
|
triggers: []
|
|
839
915
|
`;
|
|
840
|
-
async function loadConfig(path =
|
|
841
|
-
if (!
|
|
842
|
-
|
|
916
|
+
async function loadConfig(path = triggersPath) {
|
|
917
|
+
if (!existsSync3(path)) {
|
|
918
|
+
mkdirSync2(dirname2(path), { recursive: true });
|
|
843
919
|
writeFileSync(path, DEFAULT_CONFIG, "utf-8");
|
|
844
920
|
console.log(`[config] Created default config at ${path}`);
|
|
845
921
|
}
|
|
@@ -851,8 +927,8 @@ async function loadConfig(path = "config/triggers.yaml") {
|
|
|
851
927
|
cachedConfig = result.data;
|
|
852
928
|
return result.data;
|
|
853
929
|
}
|
|
854
|
-
async function initializeApp(
|
|
855
|
-
const config = await loadConfig(
|
|
930
|
+
async function initializeApp(configPath2 = triggersPath) {
|
|
931
|
+
const config = await loadConfig(configPath2);
|
|
856
932
|
const db2 = getDb();
|
|
857
933
|
initScheduler(db2, config.triggers);
|
|
858
934
|
if (config.tunnel) {
|
|
@@ -860,7 +936,7 @@ async function initializeApp(configPath = "config/triggers.yaml") {
|
|
|
860
936
|
} else {
|
|
861
937
|
await stopTunnel();
|
|
862
938
|
}
|
|
863
|
-
startConfigWatcher(
|
|
939
|
+
startConfigWatcher(configPath2);
|
|
864
940
|
return {
|
|
865
941
|
config,
|
|
866
942
|
tunnel: getTunnelStatus()
|
|
@@ -876,11 +952,11 @@ function getTrigger(id) {
|
|
|
876
952
|
const config = getConfig();
|
|
877
953
|
return config.triggers.find((t) => t.id === id);
|
|
878
954
|
}
|
|
879
|
-
async function deleteTrigger(id,
|
|
880
|
-
if (!
|
|
955
|
+
async function deleteTrigger(id, configPath2 = triggersPath) {
|
|
956
|
+
if (!existsSync3(configPath2)) {
|
|
881
957
|
return false;
|
|
882
958
|
}
|
|
883
|
-
const content = readFileSync2(
|
|
959
|
+
const content = readFileSync2(configPath2, "utf-8");
|
|
884
960
|
const result = parseConfig(content);
|
|
885
961
|
if (!result.success) {
|
|
886
962
|
console.error(`[config] Cannot delete trigger: invalid config`);
|
|
@@ -895,22 +971,22 @@ async function deleteTrigger(id, configPath = "config/triggers.yaml") {
|
|
|
895
971
|
config.triggers.splice(triggerIndex, 1);
|
|
896
972
|
const yaml = await import("yaml");
|
|
897
973
|
const newContent = yaml.stringify(config);
|
|
898
|
-
writeFileSync(
|
|
974
|
+
writeFileSync(configPath2, newContent, "utf-8");
|
|
899
975
|
console.log(`[config] Deleted trigger '${id}'`);
|
|
900
976
|
cachedConfig = config;
|
|
901
977
|
return true;
|
|
902
978
|
}
|
|
903
|
-
function startConfigWatcher(
|
|
904
|
-
if (configWatcher && watchedConfigPath ===
|
|
979
|
+
function startConfigWatcher(configPath2 = triggersPath) {
|
|
980
|
+
if (configWatcher && watchedConfigPath === configPath2) {
|
|
905
981
|
return;
|
|
906
982
|
}
|
|
907
983
|
stopConfigWatcher();
|
|
908
|
-
if (!
|
|
909
|
-
console.warn(`[config] Config file not found: ${
|
|
984
|
+
if (!existsSync3(configPath2)) {
|
|
985
|
+
console.warn(`[config] Config file not found: ${configPath2}, skipping watcher`);
|
|
910
986
|
return;
|
|
911
987
|
}
|
|
912
|
-
watchedConfigPath =
|
|
913
|
-
configWatcher = watch(
|
|
988
|
+
watchedConfigPath = configPath2;
|
|
989
|
+
configWatcher = watch(configPath2, (eventType) => {
|
|
914
990
|
if (eventType === "change") {
|
|
915
991
|
if (reloadTimeout) {
|
|
916
992
|
clearTimeout(reloadTimeout);
|
|
@@ -918,7 +994,7 @@ function startConfigWatcher(configPath = "config/triggers.yaml") {
|
|
|
918
994
|
reloadTimeout = setTimeout(async () => {
|
|
919
995
|
console.log("[config] File changed, reloading...");
|
|
920
996
|
try {
|
|
921
|
-
await reloadConfig(
|
|
997
|
+
await reloadConfig(configPath2);
|
|
922
998
|
console.log("[config] Reload complete");
|
|
923
999
|
} catch (err) {
|
|
924
1000
|
console.error("[config] Reload failed:", err instanceof Error ? err.message : err);
|
|
@@ -926,7 +1002,7 @@ function startConfigWatcher(configPath = "config/triggers.yaml") {
|
|
|
926
1002
|
}, 300);
|
|
927
1003
|
}
|
|
928
1004
|
});
|
|
929
|
-
console.log(`[config] Watching ${
|
|
1005
|
+
console.log(`[config] Watching ${configPath2} for changes`);
|
|
930
1006
|
}
|
|
931
1007
|
function stopConfigWatcher() {
|
|
932
1008
|
if (reloadTimeout) {
|
|
@@ -940,8 +1016,8 @@ function stopConfigWatcher() {
|
|
|
940
1016
|
console.log("[config] Stopped watching config file");
|
|
941
1017
|
}
|
|
942
1018
|
}
|
|
943
|
-
async function reloadConfig(
|
|
944
|
-
const config = await loadConfig(
|
|
1019
|
+
async function reloadConfig(configPath2) {
|
|
1020
|
+
const config = await loadConfig(configPath2);
|
|
945
1021
|
const db2 = getDb();
|
|
946
1022
|
initScheduler(db2, config.triggers);
|
|
947
1023
|
if (config.tunnel) {
|
|
@@ -955,14 +1031,14 @@ async function reloadConfig(configPath) {
|
|
|
955
1031
|
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
956
1032
|
import { parse as parseYaml2, stringify as stringifyYaml } from "yaml";
|
|
957
1033
|
var DEFAULT_CONFIG_PATH = "config/triggers.yaml";
|
|
958
|
-
async function writeTrigger(trigger,
|
|
1034
|
+
async function writeTrigger(trigger, configPath2 = DEFAULT_CONFIG_PATH) {
|
|
959
1035
|
const validation = validateTrigger(trigger);
|
|
960
1036
|
if (!validation.success) {
|
|
961
1037
|
const messages = validation.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join(", ");
|
|
962
1038
|
return { success: false, error: `Validation failed: ${messages}` };
|
|
963
1039
|
}
|
|
964
1040
|
try {
|
|
965
|
-
const content = readFileSync3(
|
|
1041
|
+
const content = readFileSync3(configPath2, "utf-8");
|
|
966
1042
|
const config = parseYaml2(content) || {};
|
|
967
1043
|
if (!config.triggers) {
|
|
968
1044
|
config.triggers = [];
|
|
@@ -996,15 +1072,15 @@ async function writeTrigger(trigger, configPath = DEFAULT_CONFIG_PATH) {
|
|
|
996
1072
|
defaultStringType: "PLAIN",
|
|
997
1073
|
defaultKeyType: "PLAIN"
|
|
998
1074
|
});
|
|
999
|
-
writeFileSync2(
|
|
1075
|
+
writeFileSync2(configPath2, yamlOutput);
|
|
1000
1076
|
return { success: true };
|
|
1001
1077
|
} catch (err) {
|
|
1002
1078
|
return { success: false, error: `Write failed: ${err instanceof Error ? err.message : String(err)}` };
|
|
1003
1079
|
}
|
|
1004
1080
|
}
|
|
1005
|
-
async function deleteTrigger2(id,
|
|
1081
|
+
async function deleteTrigger2(id, configPath2 = DEFAULT_CONFIG_PATH) {
|
|
1006
1082
|
try {
|
|
1007
|
-
const content = readFileSync3(
|
|
1083
|
+
const content = readFileSync3(configPath2, "utf-8");
|
|
1008
1084
|
const config = parseYaml2(content) || {};
|
|
1009
1085
|
if (!config.triggers || !Array.isArray(config.triggers)) {
|
|
1010
1086
|
return { success: false, error: `Trigger '${id}' not found` };
|
|
@@ -1019,15 +1095,15 @@ async function deleteTrigger2(id, configPath = DEFAULT_CONFIG_PATH) {
|
|
|
1019
1095
|
defaultStringType: "PLAIN",
|
|
1020
1096
|
defaultKeyType: "PLAIN"
|
|
1021
1097
|
});
|
|
1022
|
-
writeFileSync2(
|
|
1098
|
+
writeFileSync2(configPath2, yamlOutput);
|
|
1023
1099
|
return { success: true };
|
|
1024
1100
|
} catch (err) {
|
|
1025
1101
|
return { success: false, error: `Delete failed: ${err instanceof Error ? err.message : String(err)}` };
|
|
1026
1102
|
}
|
|
1027
1103
|
}
|
|
1028
|
-
async function listTriggerIds(
|
|
1104
|
+
async function listTriggerIds(configPath2 = DEFAULT_CONFIG_PATH) {
|
|
1029
1105
|
try {
|
|
1030
|
-
const content = readFileSync3(
|
|
1106
|
+
const content = readFileSync3(configPath2, "utf-8");
|
|
1031
1107
|
const config = parseYaml2(content) || {};
|
|
1032
1108
|
if (!config.triggers || !Array.isArray(config.triggers)) {
|
|
1033
1109
|
return [];
|
|
@@ -1037,9 +1113,9 @@ async function listTriggerIds(configPath = DEFAULT_CONFIG_PATH) {
|
|
|
1037
1113
|
return [];
|
|
1038
1114
|
}
|
|
1039
1115
|
}
|
|
1040
|
-
async function writeTunnelConfig(tunnel,
|
|
1116
|
+
async function writeTunnelConfig(tunnel, configPath2 = DEFAULT_CONFIG_PATH) {
|
|
1041
1117
|
try {
|
|
1042
|
-
const content = readFileSync3(
|
|
1118
|
+
const content = readFileSync3(configPath2, "utf-8");
|
|
1043
1119
|
const config = parseYaml2(content) || {};
|
|
1044
1120
|
const tunnelObj = {
|
|
1045
1121
|
enabled: tunnel.enabled,
|
|
@@ -1058,15 +1134,15 @@ async function writeTunnelConfig(tunnel, configPath = DEFAULT_CONFIG_PATH) {
|
|
|
1058
1134
|
defaultStringType: "PLAIN",
|
|
1059
1135
|
defaultKeyType: "PLAIN"
|
|
1060
1136
|
});
|
|
1061
|
-
writeFileSync2(
|
|
1137
|
+
writeFileSync2(configPath2, yamlOutput);
|
|
1062
1138
|
return { success: true };
|
|
1063
1139
|
} catch (err) {
|
|
1064
1140
|
return { success: false, error: `Write failed: ${err instanceof Error ? err.message : String(err)}` };
|
|
1065
1141
|
}
|
|
1066
1142
|
}
|
|
1067
|
-
async function getTunnelConfig(
|
|
1143
|
+
async function getTunnelConfig(configPath2 = DEFAULT_CONFIG_PATH) {
|
|
1068
1144
|
try {
|
|
1069
|
-
const content = readFileSync3(
|
|
1145
|
+
const content = readFileSync3(configPath2, "utf-8");
|
|
1070
1146
|
const config = parseYaml2(content) || {};
|
|
1071
1147
|
if (!config.tunnel) {
|
|
1072
1148
|
return null;
|
|
@@ -1085,7 +1161,7 @@ async function getTunnelConfig(configPath = DEFAULT_CONFIG_PATH) {
|
|
|
1085
1161
|
|
|
1086
1162
|
// src/server/routes/triggers.ts
|
|
1087
1163
|
var triggersRoutes = new Hono();
|
|
1088
|
-
async function createTriggerInternal(trigger,
|
|
1164
|
+
async function createTriggerInternal(trigger, configPath2) {
|
|
1089
1165
|
const validation = validateTrigger(trigger);
|
|
1090
1166
|
if (!validation.success) {
|
|
1091
1167
|
return {
|
|
@@ -1095,7 +1171,7 @@ async function createTriggerInternal(trigger, configPath) {
|
|
|
1095
1171
|
status: 400
|
|
1096
1172
|
};
|
|
1097
1173
|
}
|
|
1098
|
-
const existingIds = await listTriggerIds(
|
|
1174
|
+
const existingIds = await listTriggerIds(configPath2);
|
|
1099
1175
|
if (existingIds.includes(trigger.id)) {
|
|
1100
1176
|
return {
|
|
1101
1177
|
success: false,
|
|
@@ -1103,7 +1179,7 @@ async function createTriggerInternal(trigger, configPath) {
|
|
|
1103
1179
|
status: 409
|
|
1104
1180
|
};
|
|
1105
1181
|
}
|
|
1106
|
-
const result = await writeTrigger(trigger,
|
|
1182
|
+
const result = await writeTrigger(trigger, configPath2);
|
|
1107
1183
|
if (!result.success) {
|
|
1108
1184
|
return {
|
|
1109
1185
|
success: false,
|
|
@@ -1117,7 +1193,7 @@ async function createTriggerInternal(trigger, configPath) {
|
|
|
1117
1193
|
status: 201
|
|
1118
1194
|
};
|
|
1119
1195
|
}
|
|
1120
|
-
async function updateTriggerInternal(id, trigger,
|
|
1196
|
+
async function updateTriggerInternal(id, trigger, configPath2) {
|
|
1121
1197
|
const validation = validateTrigger(trigger);
|
|
1122
1198
|
if (!validation.success) {
|
|
1123
1199
|
return {
|
|
@@ -1127,7 +1203,7 @@ async function updateTriggerInternal(id, trigger, configPath) {
|
|
|
1127
1203
|
status: 400
|
|
1128
1204
|
};
|
|
1129
1205
|
}
|
|
1130
|
-
const existingIds = await listTriggerIds(
|
|
1206
|
+
const existingIds = await listTriggerIds(configPath2);
|
|
1131
1207
|
if (!existingIds.includes(id)) {
|
|
1132
1208
|
return {
|
|
1133
1209
|
success: false,
|
|
@@ -1144,7 +1220,7 @@ async function updateTriggerInternal(id, trigger, configPath) {
|
|
|
1144
1220
|
};
|
|
1145
1221
|
}
|
|
1146
1222
|
if (idChanged) {
|
|
1147
|
-
const deleteResult = await deleteTrigger2(id,
|
|
1223
|
+
const deleteResult = await deleteTrigger2(id, configPath2);
|
|
1148
1224
|
if (!deleteResult.success) {
|
|
1149
1225
|
return {
|
|
1150
1226
|
success: false,
|
|
@@ -1153,7 +1229,7 @@ async function updateTriggerInternal(id, trigger, configPath) {
|
|
|
1153
1229
|
};
|
|
1154
1230
|
}
|
|
1155
1231
|
}
|
|
1156
|
-
const result = await writeTrigger(trigger,
|
|
1232
|
+
const result = await writeTrigger(trigger, configPath2);
|
|
1157
1233
|
if (!result.success) {
|
|
1158
1234
|
return {
|
|
1159
1235
|
success: false,
|
|
@@ -1169,8 +1245,8 @@ async function updateTriggerInternal(id, trigger, configPath) {
|
|
|
1169
1245
|
status: 200
|
|
1170
1246
|
};
|
|
1171
1247
|
}
|
|
1172
|
-
async function deleteTriggerInternal(id,
|
|
1173
|
-
const existingIds = await listTriggerIds(
|
|
1248
|
+
async function deleteTriggerInternal(id, configPath2) {
|
|
1249
|
+
const existingIds = await listTriggerIds(configPath2);
|
|
1174
1250
|
if (!existingIds.includes(id)) {
|
|
1175
1251
|
return {
|
|
1176
1252
|
success: false,
|
|
@@ -1178,7 +1254,7 @@ async function deleteTriggerInternal(id, configPath) {
|
|
|
1178
1254
|
status: 404
|
|
1179
1255
|
};
|
|
1180
1256
|
}
|
|
1181
|
-
const result = await deleteTrigger2(id,
|
|
1257
|
+
const result = await deleteTrigger2(id, configPath2);
|
|
1182
1258
|
if (!result.success) {
|
|
1183
1259
|
return {
|
|
1184
1260
|
success: false,
|
|
@@ -1199,9 +1275,9 @@ async function ensureConfig() {
|
|
|
1199
1275
|
configLoaded = true;
|
|
1200
1276
|
}
|
|
1201
1277
|
}
|
|
1202
|
-
async function testTriggerInternal(id, payload,
|
|
1203
|
-
if (
|
|
1204
|
-
await loadConfig(
|
|
1278
|
+
async function testTriggerInternal(id, payload, configPath2) {
|
|
1279
|
+
if (configPath2) {
|
|
1280
|
+
await loadConfig(configPath2);
|
|
1205
1281
|
} else {
|
|
1206
1282
|
await ensureConfig();
|
|
1207
1283
|
}
|
|
@@ -1360,10 +1436,9 @@ runsRoutes.get("/:id", async (c) => {
|
|
|
1360
1436
|
|
|
1361
1437
|
// src/server/routes/sanitizers.ts
|
|
1362
1438
|
import { Hono as Hono3 } from "hono";
|
|
1363
|
-
import { readdirSync, existsSync as
|
|
1439
|
+
import { readdirSync as readdirSync2, existsSync as existsSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "fs";
|
|
1364
1440
|
import { join as join2 } from "path";
|
|
1365
1441
|
var sanitizersRoutes = new Hono3();
|
|
1366
|
-
var DEFAULT_SANITIZERS_DIR = process.env.CHARON_SANITIZERS_DIR || "sanitizers";
|
|
1367
1442
|
var BOILERPLATE = `/**
|
|
1368
1443
|
* Sanitizer function for processing webhook payloads.
|
|
1369
1444
|
*
|
|
@@ -1383,17 +1458,17 @@ export default sanitize;
|
|
|
1383
1458
|
function sanitizeName(name) {
|
|
1384
1459
|
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").replace(/-+/g, "-");
|
|
1385
1460
|
}
|
|
1386
|
-
function listSanitizersInternal(
|
|
1387
|
-
if (!
|
|
1461
|
+
function listSanitizersInternal(dir = sanitizersDir) {
|
|
1462
|
+
if (!existsSync4(dir)) {
|
|
1388
1463
|
return [];
|
|
1389
1464
|
}
|
|
1390
|
-
const files =
|
|
1465
|
+
const files = readdirSync2(dir);
|
|
1391
1466
|
return files.filter((f) => f.endsWith(".ts")).map((f) => ({
|
|
1392
1467
|
name: f.replace(".ts", ""),
|
|
1393
|
-
path: join2(
|
|
1468
|
+
path: join2(dir, f)
|
|
1394
1469
|
}));
|
|
1395
1470
|
}
|
|
1396
|
-
function createSanitizerInternal(rawName,
|
|
1471
|
+
function createSanitizerInternal(rawName, dir = sanitizersDir) {
|
|
1397
1472
|
if (!rawName || typeof rawName !== "string") {
|
|
1398
1473
|
return { success: false, error: "Name is required", status: 400 };
|
|
1399
1474
|
}
|
|
@@ -1401,12 +1476,12 @@ function createSanitizerInternal(rawName, sanitizersDir = DEFAULT_SANITIZERS_DIR
|
|
|
1401
1476
|
if (!name) {
|
|
1402
1477
|
return { success: false, error: "Invalid name", status: 400 };
|
|
1403
1478
|
}
|
|
1404
|
-
const filePath = join2(
|
|
1405
|
-
if (
|
|
1479
|
+
const filePath = join2(dir, `${name}.ts`);
|
|
1480
|
+
if (existsSync4(filePath)) {
|
|
1406
1481
|
return { success: false, error: `Sanitizer '${name}' already exists`, status: 409 };
|
|
1407
1482
|
}
|
|
1408
|
-
if (!
|
|
1409
|
-
|
|
1483
|
+
if (!existsSync4(dir)) {
|
|
1484
|
+
mkdirSync3(dir, { recursive: true });
|
|
1410
1485
|
}
|
|
1411
1486
|
writeFileSync3(filePath, BOILERPLATE);
|
|
1412
1487
|
return { success: true, name, path: filePath, status: 201 };
|
|
@@ -1711,10 +1786,10 @@ async function tunnelProxyMiddleware(c, next) {
|
|
|
1711
1786
|
}
|
|
1712
1787
|
|
|
1713
1788
|
// src/server/app.ts
|
|
1714
|
-
var
|
|
1715
|
-
var prodClientDir =
|
|
1716
|
-
var devClientDir =
|
|
1717
|
-
var clientDir =
|
|
1789
|
+
var __dirname2 = dirname3(fileURLToPath2(import.meta.url));
|
|
1790
|
+
var prodClientDir = resolve4(__dirname2, "../client");
|
|
1791
|
+
var devClientDir = resolve4(process.cwd(), "dist/client");
|
|
1792
|
+
var clientDir = existsSync5(devClientDir) ? devClientDir : prodClientDir;
|
|
1718
1793
|
var app = new Hono8();
|
|
1719
1794
|
app.use("*", quietLogger);
|
|
1720
1795
|
app.use("*", tunnelProxyMiddleware);
|
|
@@ -1726,11 +1801,12 @@ app.route("/api/webhook", webhookRoutes);
|
|
|
1726
1801
|
app.route("/api/task", taskRoutes);
|
|
1727
1802
|
app.route("/api/promise", promiseRoutes);
|
|
1728
1803
|
app.use("/*", serveStatic({ root: clientDir }));
|
|
1729
|
-
app.get("*", serveStatic({ path:
|
|
1804
|
+
app.get("*", serveStatic({ path: resolve4(clientDir, "index.html") }));
|
|
1730
1805
|
|
|
1731
1806
|
// src/server/init.ts
|
|
1732
1807
|
async function initializeServices() {
|
|
1733
1808
|
try {
|
|
1809
|
+
initializeDataDir();
|
|
1734
1810
|
const { config, tunnel } = await initializeApp();
|
|
1735
1811
|
console.log(`[init] Loaded ${config.triggers.length} triggers`);
|
|
1736
1812
|
if (tunnel.connected) {
|