@serve.zone/gitops 2.13.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.
Files changed (258) hide show
  1. package/.smartconfig.json +114 -0
  2. package/binary/gitops.ts +4 -0
  3. package/changelog.md +185 -0
  4. package/cli.child.js +4 -0
  5. package/cli.js +4 -0
  6. package/cli.ts.js +5 -0
  7. package/deno.json +10 -0
  8. package/dist_serve/bundle.js +36362 -0
  9. package/dist_serve/index.html +33 -0
  10. package/dist_ts/00_commitinfo_data.d.ts +8 -0
  11. package/dist_ts/00_commitinfo_data.js +9 -0
  12. package/dist_ts/cache/classes.cache.cleaner.d.ts +23 -0
  13. package/dist_ts/cache/classes.cache.cleaner.js +61 -0
  14. package/dist_ts/cache/classes.cached.document.d.ts +30 -0
  15. package/dist_ts/cache/classes.cached.document.js +101 -0
  16. package/dist_ts/cache/classes.cachedb.d.ts +22 -0
  17. package/dist_ts/cache/classes.cachedb.js +58 -0
  18. package/dist_ts/cache/classes.secrets.scan.service.d.ts +51 -0
  19. package/dist_ts/cache/classes.secrets.scan.service.js +237 -0
  20. package/dist_ts/cache/documents/classes.cached.project.d.ts +13 -0
  21. package/dist_ts/cache/documents/classes.cached.project.js +101 -0
  22. package/dist_ts/cache/documents/classes.cached.secret.d.ts +24 -0
  23. package/dist_ts/cache/documents/classes.cached.secret.js +158 -0
  24. package/dist_ts/cache/documents/index.d.ts +2 -0
  25. package/dist_ts/cache/documents/index.js +3 -0
  26. package/dist_ts/cache/index.d.ts +7 -0
  27. package/dist_ts/cache/index.js +6 -0
  28. package/dist_ts/classes/actionlog.d.ts +19 -0
  29. package/dist_ts/classes/actionlog.js +44 -0
  30. package/dist_ts/classes/connectionmanager.d.ts +57 -0
  31. package/dist_ts/classes/connectionmanager.js +247 -0
  32. package/dist_ts/classes/gitopsapp.d.ts +30 -0
  33. package/dist_ts/classes/gitopsapp.js +101 -0
  34. package/dist_ts/classes/jobmanager.d.ts +47 -0
  35. package/dist_ts/classes/jobmanager.js +301 -0
  36. package/dist_ts/classes/jobrunners/autobookstackdocs.runner.d.ts +29 -0
  37. package/dist_ts/classes/jobrunners/autobookstackdocs.runner.js +361 -0
  38. package/dist_ts/classes/jobrunners/base.jobrunner.d.ts +14 -0
  39. package/dist_ts/classes/jobrunners/base.jobrunner.js +3 -0
  40. package/dist_ts/classes/jobrunners/index.d.ts +5 -0
  41. package/dist_ts/classes/jobrunners/index.js +14 -0
  42. package/dist_ts/classes/managedsecrets.manager.d.ts +47 -0
  43. package/dist_ts/classes/managedsecrets.manager.js +247 -0
  44. package/dist_ts/classes/syncmanager.d.ts +189 -0
  45. package/dist_ts/classes/syncmanager.js +1787 -0
  46. package/dist_ts/index.d.ts +6 -0
  47. package/dist_ts/index.js +32 -0
  48. package/dist_ts/logging.d.ts +49 -0
  49. package/dist_ts/logging.js +134 -0
  50. package/dist_ts/opsserver/classes.opsserver.d.ts +25 -0
  51. package/dist_ts/opsserver/classes.opsserver.js +70 -0
  52. package/dist_ts/opsserver/handlers/actionlog.handler.d.ts +9 -0
  53. package/dist_ts/opsserver/handlers/actionlog.handler.js +24 -0
  54. package/dist_ts/opsserver/handlers/actions.handler.d.ts +9 -0
  55. package/dist_ts/opsserver/handlers/actions.handler.js +38 -0
  56. package/dist_ts/opsserver/handlers/admin.handler.d.ts +19 -0
  57. package/dist_ts/opsserver/handlers/admin.handler.js +96 -0
  58. package/dist_ts/opsserver/handlers/connections.handler.d.ts +10 -0
  59. package/dist_ts/opsserver/handlers/connections.handler.js +109 -0
  60. package/dist_ts/opsserver/handlers/groups.handler.d.ts +9 -0
  61. package/dist_ts/opsserver/handlers/groups.handler.js +24 -0
  62. package/dist_ts/opsserver/handlers/index.d.ts +13 -0
  63. package/dist_ts/opsserver/handlers/index.js +14 -0
  64. package/dist_ts/opsserver/handlers/jobs.handler.d.ts +16 -0
  65. package/dist_ts/opsserver/handlers/jobs.handler.js +146 -0
  66. package/dist_ts/opsserver/handlers/logs.handler.d.ts +9 -0
  67. package/dist_ts/opsserver/handlers/logs.handler.js +21 -0
  68. package/dist_ts/opsserver/handlers/managedsecrets.handler.d.ts +11 -0
  69. package/dist_ts/opsserver/handlers/managedsecrets.handler.js +110 -0
  70. package/dist_ts/opsserver/handlers/pipelines.handler.d.ts +31 -0
  71. package/dist_ts/opsserver/handlers/pipelines.handler.js +204 -0
  72. package/dist_ts/opsserver/handlers/projects.handler.d.ts +9 -0
  73. package/dist_ts/opsserver/handlers/projects.handler.js +24 -0
  74. package/dist_ts/opsserver/handlers/secrets.handler.d.ts +10 -0
  75. package/dist_ts/opsserver/handlers/secrets.handler.js +171 -0
  76. package/dist_ts/opsserver/handlers/sync.handler.d.ts +16 -0
  77. package/dist_ts/opsserver/handlers/sync.handler.js +166 -0
  78. package/dist_ts/opsserver/handlers/webhook.handler.d.ts +7 -0
  79. package/dist_ts/opsserver/handlers/webhook.handler.js +55 -0
  80. package/dist_ts/opsserver/helpers/guards.d.ts +5 -0
  81. package/dist_ts/opsserver/helpers/guards.js +12 -0
  82. package/dist_ts/opsserver/index.d.ts +1 -0
  83. package/dist_ts/opsserver/index.js +2 -0
  84. package/dist_ts/paths.d.ts +9 -0
  85. package/dist_ts/paths.js +13 -0
  86. package/dist_ts/plugins.d.ts +25 -0
  87. package/dist_ts/plugins.js +32 -0
  88. package/dist_ts/providers/classes.baseprovider.d.ts +51 -0
  89. package/dist_ts/providers/classes.baseprovider.js +17 -0
  90. package/dist_ts/providers/classes.giteaprovider.d.ts +40 -0
  91. package/dist_ts/providers/classes.giteaprovider.js +224 -0
  92. package/dist_ts/providers/classes.gitlabprovider.d.ts +39 -0
  93. package/dist_ts/providers/classes.gitlabprovider.js +207 -0
  94. package/dist_ts/providers/index.d.ts +3 -0
  95. package/dist_ts/providers/index.js +4 -0
  96. package/dist_ts/storage/classes.storagemanager.d.ts +33 -0
  97. package/dist_ts/storage/classes.storagemanager.js +135 -0
  98. package/dist_ts/storage/index.d.ts +2 -0
  99. package/dist_ts/storage/index.js +2 -0
  100. package/dist_ts/timers.d.ts +4 -0
  101. package/dist_ts/timers.js +24 -0
  102. package/dist_ts_bundled/bundle.d.ts +4 -0
  103. package/dist_ts_bundled/bundle.js +12 -0
  104. package/dist_ts_interfaces/data/actionlog.d.ts +12 -0
  105. package/dist_ts_interfaces/data/actionlog.js +2 -0
  106. package/dist_ts_interfaces/data/branch.d.ts +8 -0
  107. package/dist_ts_interfaces/data/branch.js +2 -0
  108. package/dist_ts_interfaces/data/connection.d.ts +12 -0
  109. package/dist_ts_interfaces/data/connection.js +2 -0
  110. package/dist_ts_interfaces/data/group.d.ts +10 -0
  111. package/dist_ts_interfaces/data/group.js +2 -0
  112. package/dist_ts_interfaces/data/identity.d.ts +7 -0
  113. package/dist_ts_interfaces/data/identity.js +2 -0
  114. package/dist_ts_interfaces/data/index.d.ts +11 -0
  115. package/dist_ts_interfaces/data/index.js +12 -0
  116. package/dist_ts_interfaces/data/job.d.ts +37 -0
  117. package/dist_ts_interfaces/data/job.js +2 -0
  118. package/dist_ts_interfaces/data/managedsecret.d.ts +37 -0
  119. package/dist_ts_interfaces/data/managedsecret.js +2 -0
  120. package/dist_ts_interfaces/data/pipeline.d.ts +22 -0
  121. package/dist_ts_interfaces/data/pipeline.js +2 -0
  122. package/dist_ts_interfaces/data/project.d.ts +12 -0
  123. package/dist_ts_interfaces/data/project.js +2 -0
  124. package/dist_ts_interfaces/data/secret.d.ts +11 -0
  125. package/dist_ts_interfaces/data/secret.js +2 -0
  126. package/dist_ts_interfaces/data/sync.d.ts +34 -0
  127. package/dist_ts_interfaces/data/sync.js +2 -0
  128. package/dist_ts_interfaces/index.d.ts +5 -0
  129. package/dist_ts_interfaces/index.js +8 -0
  130. package/dist_ts_interfaces/plugins.d.ts +2 -0
  131. package/dist_ts_interfaces/plugins.js +4 -0
  132. package/dist_ts_interfaces/requests/actionlog.d.ts +15 -0
  133. package/dist_ts_interfaces/requests/actionlog.js +3 -0
  134. package/dist_ts_interfaces/requests/actions.d.ts +31 -0
  135. package/dist_ts_interfaces/requests/actions.js +3 -0
  136. package/dist_ts_interfaces/requests/admin.d.ts +31 -0
  137. package/dist_ts_interfaces/requests/admin.js +3 -0
  138. package/dist_ts_interfaces/requests/connections.d.ts +71 -0
  139. package/dist_ts_interfaces/requests/connections.js +3 -0
  140. package/dist_ts_interfaces/requests/groups.d.ts +14 -0
  141. package/dist_ts_interfaces/requests/groups.js +3 -0
  142. package/dist_ts_interfaces/requests/index.d.ts +13 -0
  143. package/dist_ts_interfaces/requests/index.js +14 -0
  144. package/dist_ts_interfaces/requests/jobs.d.ts +86 -0
  145. package/dist_ts_interfaces/requests/jobs.js +3 -0
  146. package/dist_ts_interfaces/requests/logs.d.ts +14 -0
  147. package/dist_ts_interfaces/requests/logs.js +3 -0
  148. package/dist_ts_interfaces/requests/managedsecrets.d.ts +84 -0
  149. package/dist_ts_interfaces/requests/managedsecrets.js +3 -0
  150. package/dist_ts_interfaces/requests/pipelines.d.ts +55 -0
  151. package/dist_ts_interfaces/requests/pipelines.js +3 -0
  152. package/dist_ts_interfaces/requests/projects.d.ts +14 -0
  153. package/dist_ts_interfaces/requests/projects.js +3 -0
  154. package/dist_ts_interfaces/requests/secrets.d.ts +72 -0
  155. package/dist_ts_interfaces/requests/secrets.js +3 -0
  156. package/dist_ts_interfaces/requests/sync.d.ts +120 -0
  157. package/dist_ts_interfaces/requests/sync.js +3 -0
  158. package/dist_ts_interfaces/requests/webhook.d.ts +13 -0
  159. package/dist_ts_interfaces/requests/webhook.js +3 -0
  160. package/license +21 -0
  161. package/package.json +81 -0
  162. package/readme.md +177 -0
  163. package/readme.todo.md +3 -0
  164. package/ts/00_commitinfo_data.ts +8 -0
  165. package/ts/cache/classes.cache.cleaner.ts +69 -0
  166. package/ts/cache/classes.cached.document.ts +57 -0
  167. package/ts/cache/classes.cachedb.ts +72 -0
  168. package/ts/cache/classes.secrets.scan.service.ts +267 -0
  169. package/ts/cache/documents/classes.cached.project.ts +32 -0
  170. package/ts/cache/documents/classes.cached.secret.ts +81 -0
  171. package/ts/cache/documents/index.ts +2 -0
  172. package/ts/cache/index.ts +7 -0
  173. package/ts/classes/actionlog.ts +57 -0
  174. package/ts/classes/connectionmanager.ts +263 -0
  175. package/ts/classes/gitopsapp.ts +128 -0
  176. package/ts/classes/jobmanager.ts +337 -0
  177. package/ts/classes/jobrunners/autobookstackdocs.runner.ts +435 -0
  178. package/ts/classes/jobrunners/base.jobrunner.ts +16 -0
  179. package/ts/classes/jobrunners/index.ts +17 -0
  180. package/ts/classes/managedsecrets.manager.ts +322 -0
  181. package/ts/classes/syncmanager.ts +2117 -0
  182. package/ts/index.ts +37 -0
  183. package/ts/logging.ts +162 -0
  184. package/ts/opsserver/classes.opsserver.ts +86 -0
  185. package/ts/opsserver/handlers/actionlog.handler.ts +30 -0
  186. package/ts/opsserver/handlers/actions.handler.ts +50 -0
  187. package/ts/opsserver/handlers/admin.handler.ts +122 -0
  188. package/ts/opsserver/handlers/connections.handler.ts +162 -0
  189. package/ts/opsserver/handlers/groups.handler.ts +32 -0
  190. package/ts/opsserver/handlers/index.ts +13 -0
  191. package/ts/opsserver/handlers/jobs.handler.ts +189 -0
  192. package/ts/opsserver/handlers/logs.handler.ts +29 -0
  193. package/ts/opsserver/handlers/managedsecrets.handler.ts +158 -0
  194. package/ts/opsserver/handlers/pipelines.handler.ts +281 -0
  195. package/ts/opsserver/handlers/projects.handler.ts +32 -0
  196. package/ts/opsserver/handlers/secrets.handler.ts +224 -0
  197. package/ts/opsserver/handlers/sync.handler.ts +224 -0
  198. package/ts/opsserver/handlers/webhook.handler.ts +62 -0
  199. package/ts/opsserver/helpers/guards.ts +16 -0
  200. package/ts/opsserver/index.ts +1 -0
  201. package/ts/paths.ts +19 -0
  202. package/ts/plugins.ts +38 -0
  203. package/ts/providers/classes.baseprovider.ts +99 -0
  204. package/ts/providers/classes.giteaprovider.ts +279 -0
  205. package/ts/providers/classes.gitlabprovider.ts +265 -0
  206. package/ts/providers/index.ts +3 -0
  207. package/ts/storage/classes.storagemanager.ts +144 -0
  208. package/ts/storage/index.ts +2 -0
  209. package/ts/timers.ts +34 -0
  210. package/ts_interfaces/data/actionlog.ts +13 -0
  211. package/ts_interfaces/data/branch.ts +9 -0
  212. package/ts_interfaces/data/connection.ts +13 -0
  213. package/ts_interfaces/data/group.ts +10 -0
  214. package/ts_interfaces/data/identity.ts +7 -0
  215. package/ts_interfaces/data/index.ts +11 -0
  216. package/ts_interfaces/data/job.ts +42 -0
  217. package/ts_interfaces/data/managedsecret.ts +41 -0
  218. package/ts_interfaces/data/pipeline.ts +32 -0
  219. package/ts_interfaces/data/project.ts +12 -0
  220. package/ts_interfaces/data/secret.ts +11 -0
  221. package/ts_interfaces/data/sync.ts +37 -0
  222. package/ts_interfaces/index.ts +9 -0
  223. package/ts_interfaces/plugins.ts +6 -0
  224. package/ts_interfaces/requests/actionlog.ts +19 -0
  225. package/ts_interfaces/requests/actions.ts +39 -0
  226. package/ts_interfaces/requests/admin.ts +43 -0
  227. package/ts_interfaces/requests/connections.ts +95 -0
  228. package/ts_interfaces/requests/groups.ts +18 -0
  229. package/ts_interfaces/requests/index.ts +13 -0
  230. package/ts_interfaces/requests/jobs.ts +118 -0
  231. package/ts_interfaces/requests/logs.ts +18 -0
  232. package/ts_interfaces/requests/managedsecrets.ts +112 -0
  233. package/ts_interfaces/requests/pipelines.ts +71 -0
  234. package/ts_interfaces/requests/projects.ts +18 -0
  235. package/ts_interfaces/requests/secrets.ts +92 -0
  236. package/ts_interfaces/requests/sync.ts +157 -0
  237. package/ts_interfaces/requests/webhook.ts +18 -0
  238. package/ts_web/00_commitinfo_data.ts +8 -0
  239. package/ts_web/appstate.ts +1251 -0
  240. package/ts_web/elements/gitops-dashboard.ts +350 -0
  241. package/ts_web/elements/index.ts +10 -0
  242. package/ts_web/elements/shared/css.ts +29 -0
  243. package/ts_web/elements/shared/index.ts +1 -0
  244. package/ts_web/elements/views/actionlog/index.ts +101 -0
  245. package/ts_web/elements/views/actions/index.ts +209 -0
  246. package/ts_web/elements/views/buildlog/index.ts +196 -0
  247. package/ts_web/elements/views/connections/index.ts +260 -0
  248. package/ts_web/elements/views/groups/index.ts +134 -0
  249. package/ts_web/elements/views/jobs/index.ts +424 -0
  250. package/ts_web/elements/views/managedsecrets/index.ts +502 -0
  251. package/ts_web/elements/views/overview/index.ts +86 -0
  252. package/ts_web/elements/views/pipelines/index.ts +561 -0
  253. package/ts_web/elements/views/projects/index.ts +149 -0
  254. package/ts_web/elements/views/secrets/index.ts +310 -0
  255. package/ts_web/elements/views/sync/index.ts +512 -0
  256. package/ts_web/index.ts +7 -0
  257. package/ts_web/plugins.ts +15 -0
  258. package/tsconfig.json +15 -0
@@ -0,0 +1,32 @@
1
+ import * as plugins from '../../plugins.js';
2
+ import type { OpsServer } from '../classes.opsserver.js';
3
+ import * as interfaces from '../../../ts_interfaces/index.js';
4
+ import { requireValidIdentity } from '../helpers/guards.js';
5
+
6
+ export class ProjectsHandler {
7
+ public typedrouter = new plugins.typedrequest.TypedRouter();
8
+
9
+ constructor(private opsServerRef: OpsServer) {
10
+ this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
11
+ this.registerHandlers();
12
+ }
13
+
14
+ private registerHandlers(): void {
15
+ this.typedrouter.addTypedHandler(
16
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetProjects>(
17
+ 'getProjects',
18
+ async (dataArg) => {
19
+ await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
20
+ const provider = this.opsServerRef.gitopsAppRef.connectionManager.getProvider(
21
+ dataArg.connectionId,
22
+ );
23
+ const projects = await provider.getProjects({
24
+ search: dataArg.search,
25
+ page: dataArg.page,
26
+ });
27
+ return { projects };
28
+ },
29
+ ),
30
+ );
31
+ }
32
+ }
@@ -0,0 +1,224 @@
1
+ import * as plugins from '../../plugins.js';
2
+ import type { OpsServer } from '../classes.opsserver.js';
3
+ import * as interfaces from '../../../ts_interfaces/index.js';
4
+ import { requireValidIdentity } from '../helpers/guards.js';
5
+
6
+ export class SecretsHandler {
7
+ public typedrouter = new plugins.typedrequest.TypedRouter();
8
+
9
+ constructor(private opsServerRef: OpsServer) {
10
+ this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
11
+ this.registerHandlers();
12
+ }
13
+
14
+ private get actionLog() {
15
+ return this.opsServerRef.gitopsAppRef.actionLog;
16
+ }
17
+
18
+ private registerHandlers(): void {
19
+ // Get all secrets (cache-first, falls back to live fetch)
20
+ this.typedrouter.addTypedHandler(
21
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetAllSecrets>(
22
+ 'getAllSecrets',
23
+ async (dataArg) => {
24
+ await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
25
+ const scanService = this.opsServerRef.gitopsAppRef.secretsScanService;
26
+
27
+ // Try cache first
28
+ const hasCached = await scanService.hasCachedData(dataArg.connectionId, dataArg.scope);
29
+ if (hasCached) {
30
+ const secrets = await scanService.getCachedSecrets({
31
+ connectionId: dataArg.connectionId,
32
+ scope: dataArg.scope,
33
+ });
34
+ return { secrets };
35
+ }
36
+
37
+ // Cache miss: live fetch and save to cache
38
+ const provider = this.opsServerRef.gitopsAppRef.connectionManager.getProvider(
39
+ dataArg.connectionId,
40
+ );
41
+
42
+ const allSecrets: interfaces.data.ISecret[] = [];
43
+
44
+ if (dataArg.scope === 'project') {
45
+ const projects = await provider.getProjects();
46
+ for (let i = 0; i < projects.length; i += 5) {
47
+ const batch = projects.slice(i, i + 5);
48
+ const results = await Promise.allSettled(
49
+ batch.map(async (p) => {
50
+ const secrets = await provider.getProjectSecrets(p.id);
51
+ return secrets.map((s) => ({
52
+ ...s,
53
+ scopeName: p.fullPath || p.name,
54
+ scope: 'project' as const,
55
+ scopeId: p.id,
56
+ connectionId: dataArg.connectionId,
57
+ }));
58
+ }),
59
+ );
60
+ for (const result of results) {
61
+ if (result.status === 'fulfilled') {
62
+ allSecrets.push(...result.value);
63
+ }
64
+ }
65
+ }
66
+ } else {
67
+ const groups = await provider.getGroups();
68
+ for (let i = 0; i < groups.length; i += 5) {
69
+ const batch = groups.slice(i, i + 5);
70
+ const results = await Promise.allSettled(
71
+ batch.map(async (g) => {
72
+ const secrets = await provider.getGroupSecrets(g.id);
73
+ return secrets.map((s) => ({
74
+ ...s,
75
+ scopeName: g.fullPath || g.name,
76
+ scope: 'group' as const,
77
+ scopeId: g.id,
78
+ connectionId: dataArg.connectionId,
79
+ }));
80
+ }),
81
+ );
82
+ for (const result of results) {
83
+ if (result.status === 'fulfilled') {
84
+ allSecrets.push(...result.value);
85
+ }
86
+ }
87
+ }
88
+ }
89
+
90
+ // Save fetched secrets to cache (fire-and-forget)
91
+ scanService.saveSecrets(allSecrets).catch(() => {});
92
+
93
+ return { secrets: allSecrets };
94
+ },
95
+ ),
96
+ );
97
+
98
+ // Get secrets (cache-first for single entity)
99
+ this.typedrouter.addTypedHandler(
100
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetSecrets>(
101
+ 'getSecrets',
102
+ async (dataArg) => {
103
+ await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
104
+ const scanService = this.opsServerRef.gitopsAppRef.secretsScanService;
105
+
106
+ // Try cache first
107
+ const cached = await scanService.getCachedSecrets({
108
+ connectionId: dataArg.connectionId,
109
+ scope: dataArg.scope,
110
+ scopeId: dataArg.scopeId,
111
+ });
112
+ if (cached.length > 0) {
113
+ return { secrets: cached };
114
+ }
115
+
116
+ // Cache miss: live fetch
117
+ const provider = this.opsServerRef.gitopsAppRef.connectionManager.getProvider(
118
+ dataArg.connectionId,
119
+ );
120
+ const secrets = dataArg.scope === 'project'
121
+ ? await provider.getProjectSecrets(dataArg.scopeId)
122
+ : await provider.getGroupSecrets(dataArg.scopeId);
123
+
124
+ // Save to cache (fire-and-forget)
125
+ const fullSecrets = secrets.map((s) => ({
126
+ ...s,
127
+ scope: dataArg.scope,
128
+ scopeId: dataArg.scopeId,
129
+ connectionId: dataArg.connectionId,
130
+ }));
131
+ scanService.saveSecrets(fullSecrets).catch(() => {});
132
+
133
+ return { secrets };
134
+ },
135
+ ),
136
+ );
137
+
138
+ // Create secret
139
+ this.typedrouter.addTypedHandler(
140
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_CreateSecret>(
141
+ 'createSecret',
142
+ async (dataArg) => {
143
+ await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
144
+ const provider = this.opsServerRef.gitopsAppRef.connectionManager.getProvider(
145
+ dataArg.connectionId,
146
+ );
147
+ const secret = dataArg.scope === 'project'
148
+ ? await provider.createProjectSecret(dataArg.scopeId, dataArg.key, dataArg.value)
149
+ : await provider.createGroupSecret(dataArg.scopeId, dataArg.key, dataArg.value);
150
+ // Refresh cache for this entity
151
+ const scanService = this.opsServerRef.gitopsAppRef.secretsScanService;
152
+ scanService.scanEntity(dataArg.connectionId, dataArg.scope, dataArg.scopeId).catch(() => {});
153
+ this.actionLog.append({
154
+ actionType: 'create',
155
+ entityType: 'secret',
156
+ entityId: `${dataArg.scopeId}/${dataArg.key}`,
157
+ entityName: dataArg.key,
158
+ details: `Created ${dataArg.scope} secret "${dataArg.key}" in ${dataArg.scopeId}`,
159
+ username: dataArg.identity.username,
160
+ });
161
+ return { secret };
162
+ },
163
+ ),
164
+ );
165
+
166
+ // Update secret
167
+ this.typedrouter.addTypedHandler(
168
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_UpdateSecret>(
169
+ 'updateSecret',
170
+ async (dataArg) => {
171
+ await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
172
+ const provider = this.opsServerRef.gitopsAppRef.connectionManager.getProvider(
173
+ dataArg.connectionId,
174
+ );
175
+ const secret = dataArg.scope === 'project'
176
+ ? await provider.updateProjectSecret(dataArg.scopeId, dataArg.key, dataArg.value)
177
+ : await provider.updateGroupSecret(dataArg.scopeId, dataArg.key, dataArg.value);
178
+ // Refresh cache for this entity
179
+ const scanService = this.opsServerRef.gitopsAppRef.secretsScanService;
180
+ scanService.scanEntity(dataArg.connectionId, dataArg.scope, dataArg.scopeId).catch(() => {});
181
+ this.actionLog.append({
182
+ actionType: 'update',
183
+ entityType: 'secret',
184
+ entityId: `${dataArg.scopeId}/${dataArg.key}`,
185
+ entityName: dataArg.key,
186
+ details: `Updated ${dataArg.scope} secret "${dataArg.key}" in ${dataArg.scopeId}`,
187
+ username: dataArg.identity.username,
188
+ });
189
+ return { secret };
190
+ },
191
+ ),
192
+ );
193
+
194
+ // Delete secret
195
+ this.typedrouter.addTypedHandler(
196
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_DeleteSecret>(
197
+ 'deleteSecret',
198
+ async (dataArg) => {
199
+ await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
200
+ const provider = this.opsServerRef.gitopsAppRef.connectionManager.getProvider(
201
+ dataArg.connectionId,
202
+ );
203
+ if (dataArg.scope === 'project') {
204
+ await provider.deleteProjectSecret(dataArg.scopeId, dataArg.key);
205
+ } else {
206
+ await provider.deleteGroupSecret(dataArg.scopeId, dataArg.key);
207
+ }
208
+ // Refresh cache for this entity
209
+ const scanService = this.opsServerRef.gitopsAppRef.secretsScanService;
210
+ scanService.scanEntity(dataArg.connectionId, dataArg.scope, dataArg.scopeId).catch(() => {});
211
+ this.actionLog.append({
212
+ actionType: 'delete',
213
+ entityType: 'secret',
214
+ entityId: `${dataArg.scopeId}/${dataArg.key}`,
215
+ entityName: dataArg.key,
216
+ details: `Deleted ${dataArg.scope} secret "${dataArg.key}" from ${dataArg.scopeId}`,
217
+ username: dataArg.identity.username,
218
+ });
219
+ return { ok: true };
220
+ },
221
+ ),
222
+ );
223
+ }
224
+ }
@@ -0,0 +1,224 @@
1
+ import * as plugins from '../../plugins.js';
2
+ import type { OpsServer } from '../classes.opsserver.js';
3
+ import * as interfaces from '../../../ts_interfaces/index.js';
4
+ import { requireValidIdentity } from '../helpers/guards.js';
5
+ import { logger } from '../../logging.js';
6
+
7
+ export class SyncHandler {
8
+ public typedrouter = new plugins.typedrequest.TypedRouter();
9
+
10
+ constructor(private opsServerRef: OpsServer) {
11
+ this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
12
+ this.registerHandlers();
13
+ this.setupBroadcast();
14
+ }
15
+
16
+ /**
17
+ * Wire up the logger's broadcast function to push sync log entries
18
+ * to all connected frontends via TypedSocket.
19
+ */
20
+ private setupBroadcast(): void {
21
+ logger.setBroadcastFn((entry) => {
22
+ try {
23
+ const typedsocket = this.opsServerRef.server?.typedserver?.typedsocket;
24
+ if (!typedsocket) return;
25
+ typedsocket.findAllTargetConnectionsByTag('syncLogClient').then((connections) => {
26
+ for (const conn of connections) {
27
+ typedsocket
28
+ .createTypedRequest<interfaces.requests.IReq_PushSyncLog>('pushSyncLog', conn)
29
+ .fire({ entry })
30
+ .catch(() => {});
31
+ }
32
+ }).catch(() => {});
33
+ } catch {
34
+ // Server may not be ready yet — ignore
35
+ }
36
+ });
37
+ }
38
+
39
+ private get syncManager() {
40
+ return this.opsServerRef.gitopsAppRef.syncManager;
41
+ }
42
+
43
+ private get actionLog() {
44
+ return this.opsServerRef.gitopsAppRef.actionLog;
45
+ }
46
+
47
+ private registerHandlers(): void {
48
+ // Get all sync configs
49
+ this.typedrouter.addTypedHandler(
50
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetSyncConfigs>(
51
+ 'getSyncConfigs',
52
+ async (dataArg) => {
53
+ await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
54
+ return { configs: this.syncManager.getConfigs() };
55
+ },
56
+ ),
57
+ );
58
+
59
+ // Create sync config
60
+ this.typedrouter.addTypedHandler(
61
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_CreateSyncConfig>(
62
+ 'createSyncConfig',
63
+ async (dataArg) => {
64
+ await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
65
+ const config = await this.syncManager.createConfig({
66
+ name: dataArg.name,
67
+ sourceConnectionId: dataArg.sourceConnectionId,
68
+ targetConnectionId: dataArg.targetConnectionId,
69
+ targetGroupOffset: dataArg.targetGroupOffset,
70
+ intervalMinutes: dataArg.intervalMinutes,
71
+ enforceDelete: dataArg.enforceDelete,
72
+ enforceGroupDelete: dataArg.enforceGroupDelete,
73
+ addMirrorHint: dataArg.addMirrorHint,
74
+ useGroupAvatarsForProjects: dataArg.useGroupAvatarsForProjects,
75
+ });
76
+ this.actionLog.append({
77
+ actionType: 'create',
78
+ entityType: 'sync',
79
+ entityId: config.id,
80
+ entityName: config.name,
81
+ details: `Created sync config "${config.name}" (${config.intervalMinutes}m interval)`,
82
+ username: dataArg.identity.username,
83
+ });
84
+ return { config };
85
+ },
86
+ ),
87
+ );
88
+
89
+ // Update sync config
90
+ this.typedrouter.addTypedHandler(
91
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_UpdateSyncConfig>(
92
+ 'updateSyncConfig',
93
+ async (dataArg) => {
94
+ await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
95
+ const config = await this.syncManager.updateConfig(dataArg.syncConfigId, {
96
+ name: dataArg.name,
97
+ targetGroupOffset: dataArg.targetGroupOffset,
98
+ intervalMinutes: dataArg.intervalMinutes,
99
+ enforceDelete: dataArg.enforceDelete,
100
+ enforceGroupDelete: dataArg.enforceGroupDelete,
101
+ addMirrorHint: dataArg.addMirrorHint,
102
+ useGroupAvatarsForProjects: dataArg.useGroupAvatarsForProjects,
103
+ });
104
+ this.actionLog.append({
105
+ actionType: 'update',
106
+ entityType: 'sync',
107
+ entityId: config.id,
108
+ entityName: config.name,
109
+ details: `Updated sync config "${config.name}"`,
110
+ username: dataArg.identity.username,
111
+ });
112
+ return { config };
113
+ },
114
+ ),
115
+ );
116
+
117
+ // Delete sync config
118
+ this.typedrouter.addTypedHandler(
119
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_DeleteSyncConfig>(
120
+ 'deleteSyncConfig',
121
+ async (dataArg) => {
122
+ await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
123
+ const config = this.syncManager.getConfig(dataArg.syncConfigId);
124
+ await this.syncManager.deleteConfig(dataArg.syncConfigId);
125
+ this.actionLog.append({
126
+ actionType: 'delete',
127
+ entityType: 'sync',
128
+ entityId: dataArg.syncConfigId,
129
+ entityName: config?.name || dataArg.syncConfigId,
130
+ details: `Deleted sync config "${config?.name || dataArg.syncConfigId}"`,
131
+ username: dataArg.identity.username,
132
+ });
133
+ return { ok: true };
134
+ },
135
+ ),
136
+ );
137
+
138
+ // Pause/resume sync config
139
+ this.typedrouter.addTypedHandler(
140
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_PauseSyncConfig>(
141
+ 'pauseSyncConfig',
142
+ async (dataArg) => {
143
+ await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
144
+ const config = await this.syncManager.pauseConfig(
145
+ dataArg.syncConfigId,
146
+ dataArg.paused,
147
+ );
148
+ this.actionLog.append({
149
+ actionType: dataArg.paused ? 'pause' : 'resume',
150
+ entityType: 'sync',
151
+ entityId: config.id,
152
+ entityName: config.name,
153
+ details: `${dataArg.paused ? 'Paused' : 'Resumed'} sync config "${config.name}"`,
154
+ username: dataArg.identity.username,
155
+ });
156
+ return { config };
157
+ },
158
+ ),
159
+ );
160
+
161
+ // Trigger sync manually
162
+ this.typedrouter.addTypedHandler(
163
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_TriggerSync>(
164
+ 'triggerSync',
165
+ async (dataArg) => {
166
+ await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
167
+ const config = this.syncManager.getConfig(dataArg.syncConfigId);
168
+ if (!config) {
169
+ return { ok: false, message: 'Sync config not found' };
170
+ }
171
+ // Fire and forget — force=true bypasses paused check for manual triggers
172
+ this.syncManager.executeSync(dataArg.syncConfigId, true).catch((err) => {
173
+ console.error(`Manual sync trigger failed: ${err}`);
174
+ });
175
+ this.actionLog.append({
176
+ actionType: 'sync',
177
+ entityType: 'sync',
178
+ entityId: config.id,
179
+ entityName: config.name,
180
+ details: `Manually triggered sync "${config.name}"`,
181
+ username: dataArg.identity.username,
182
+ });
183
+ return { ok: true, message: 'Sync triggered' };
184
+ },
185
+ ),
186
+ );
187
+
188
+ // Preview sync (dry run — shows source → target mappings)
189
+ this.typedrouter.addTypedHandler(
190
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_PreviewSync>(
191
+ 'previewSync',
192
+ async (dataArg) => {
193
+ await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
194
+ const result = await this.syncManager.previewSync(dataArg.syncConfigId);
195
+ return { mappings: result.mappings, deletions: result.deletions, groupDeletions: result.groupDeletions };
196
+ },
197
+ ),
198
+ );
199
+
200
+ // Get repo statuses for a sync config
201
+ this.typedrouter.addTypedHandler(
202
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetSyncRepoStatuses>(
203
+ 'getSyncRepoStatuses',
204
+ async (dataArg) => {
205
+ await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
206
+ const statuses = await this.syncManager.getRepoStatuses(dataArg.syncConfigId);
207
+ return { statuses };
208
+ },
209
+ ),
210
+ );
211
+
212
+ // Get recent sync log entries
213
+ this.typedrouter.addTypedHandler(
214
+ new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetSyncLogs>(
215
+ 'getSyncLogs',
216
+ async (dataArg) => {
217
+ await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
218
+ const logs = logger.getSyncLogs(dataArg.limit || 200);
219
+ return { logs };
220
+ },
221
+ ),
222
+ );
223
+ }
224
+ }
@@ -0,0 +1,62 @@
1
+ import * as plugins from '../../plugins.js';
2
+ import { logger } from '../../logging.js';
3
+ import type { OpsServer } from '../classes.opsserver.js';
4
+ import * as interfaces from '../../../ts_interfaces/index.js';
5
+
6
+ export class WebhookHandler {
7
+ constructor(private opsServerRef: OpsServer) {}
8
+
9
+ public registerRoutes(typedserver: plugins.typedserver.TypedServer): void {
10
+ typedserver.addRoute('/webhook/:connectionId', 'POST', async (ctx) => {
11
+ const connectionId = ctx.params.connectionId;
12
+
13
+ // Validate connection exists
14
+ const connection = this.opsServerRef.gitopsAppRef.connectionManager.getConnection(connectionId);
15
+ if (!connection) {
16
+ return new Response(JSON.stringify({ error: 'Connection not found' }), {
17
+ status: 404,
18
+ headers: { 'Content-Type': 'application/json' },
19
+ });
20
+ }
21
+
22
+ // Parse event type from provider-specific headers
23
+ const giteaEvent = ctx.headers.get('X-Gitea-Event');
24
+ const gitlabEvent = ctx.headers.get('X-Gitlab-Event');
25
+ const event = giteaEvent || gitlabEvent || 'unknown';
26
+ const provider = giteaEvent ? 'gitea' : gitlabEvent ? 'gitlab' : 'unknown';
27
+
28
+ logger.info(`Webhook received: ${provider}/${event} for connection ${connection.name} (${connectionId})`);
29
+
30
+ // Broadcast to all connected frontends via TypedSocket
31
+ try {
32
+ const typedsocket = this.opsServerRef.server.typedserver.typedsocket;
33
+ if (typedsocket) {
34
+ const connections = await typedsocket.findAllTargetConnectionsByTag('syncLogClient');
35
+ for (const conn of connections) {
36
+ const req = typedsocket.createTypedRequest<interfaces.requests.IReq_WebhookNotification>(
37
+ 'webhookNotification',
38
+ conn,
39
+ );
40
+ req.fire({
41
+ connectionId,
42
+ provider,
43
+ event,
44
+ timestamp: Date.now(),
45
+ }).catch((err: any) => {
46
+ logger.warn(`Failed to notify client: ${err.message || err}`);
47
+ });
48
+ }
49
+ }
50
+ } catch (err: any) {
51
+ logger.warn(`Failed to broadcast webhook event: ${err.message || err}`);
52
+ }
53
+
54
+ return new Response(JSON.stringify({ ok: true }), {
55
+ status: 200,
56
+ headers: { 'Content-Type': 'application/json' },
57
+ });
58
+ });
59
+
60
+ logger.info('WebhookHandler routes registered');
61
+ }
62
+ }
@@ -0,0 +1,16 @@
1
+ import * as plugins from '../../plugins.js';
2
+ import type { AdminHandler } from '../handlers/admin.handler.js';
3
+ import * as interfaces from '../../../ts_interfaces/index.js';
4
+
5
+ export async function requireValidIdentity<T extends { identity?: interfaces.data.IIdentity }>(
6
+ adminHandler: AdminHandler,
7
+ dataArg: T,
8
+ ): Promise<void> {
9
+ if (!dataArg.identity) {
10
+ throw new plugins.typedrequest.TypedResponseError('No identity provided');
11
+ }
12
+ const passed = await adminHandler.validIdentityGuard.exec({ identity: dataArg.identity });
13
+ if (!passed) {
14
+ throw new plugins.typedrequest.TypedResponseError('Valid identity required');
15
+ }
16
+ }
@@ -0,0 +1 @@
1
+ export { OpsServer } from './classes.opsserver.js';
package/ts/paths.ts ADDED
@@ -0,0 +1,19 @@
1
+ import * as plugins from './plugins.js';
2
+
3
+ export interface IGitopsPaths {
4
+ gitopsHomeDir: string;
5
+ defaultStoragePath: string;
6
+ defaultTsmDbPath: string;
7
+ }
8
+
9
+ /**
10
+ * Resolve gitops paths. Accepts optional baseDir for test isolation.
11
+ */
12
+ export function resolvePaths(baseDir?: string): IGitopsPaths {
13
+ const home = baseDir ?? plugins.path.join(process.env.HOME ?? '/tmp', '.serve.zone', 'gitops');
14
+ return {
15
+ gitopsHomeDir: home,
16
+ defaultStoragePath: plugins.path.join(home, 'storage'),
17
+ defaultTsmDbPath: plugins.path.join(home, 'tsmdb'),
18
+ };
19
+ }
package/ts/plugins.ts ADDED
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Centralized dependency imports for GitOps
3
+ */
4
+
5
+ // Node native scope
6
+ import * as path from 'node:path';
7
+ import * as fs from 'node:fs/promises';
8
+ import * as os from 'node:os';
9
+ import * as nodeUrl from 'node:url';
10
+ import * as childProcess from 'node:child_process';
11
+ import { Buffer } from 'node:buffer';
12
+
13
+ export { path, fs, os, nodeUrl, childProcess, Buffer };
14
+
15
+ // TypedRequest/TypedServer infrastructure
16
+ import * as typedrequest from '@api.global/typedrequest';
17
+ import * as typedserver from '@api.global/typedserver';
18
+ export { typedrequest, typedserver };
19
+
20
+ // Auth & Guards
21
+ import * as smartguard from '@push.rocks/smartguard';
22
+ import * as smartjwt from '@push.rocks/smartjwt';
23
+ export { smartguard, smartjwt };
24
+
25
+ // API Clients
26
+ import * as giteaClient from '@apiclient.xyz/gitea';
27
+ import * as gitlabClient from '@apiclient.xyz/gitlab';
28
+ import * as bookstackClient from '@apiclient.xyz/bookstack';
29
+ export { giteaClient, gitlabClient, bookstackClient };
30
+
31
+ // Database
32
+ import * as smartmongo from '@push.rocks/smartmongo';
33
+ import * as smartdata from '@push.rocks/smartdata';
34
+ export { smartmongo, smartdata };
35
+
36
+ // Secrets
37
+ import * as smartsecret from '@push.rocks/smartsecret';
38
+ export { smartsecret };