@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.
- package/.smartconfig.json +114 -0
- package/binary/gitops.ts +4 -0
- package/changelog.md +185 -0
- package/cli.child.js +4 -0
- package/cli.js +4 -0
- package/cli.ts.js +5 -0
- package/deno.json +10 -0
- package/dist_serve/bundle.js +36362 -0
- package/dist_serve/index.html +33 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/cache/classes.cache.cleaner.d.ts +23 -0
- package/dist_ts/cache/classes.cache.cleaner.js +61 -0
- package/dist_ts/cache/classes.cached.document.d.ts +30 -0
- package/dist_ts/cache/classes.cached.document.js +101 -0
- package/dist_ts/cache/classes.cachedb.d.ts +22 -0
- package/dist_ts/cache/classes.cachedb.js +58 -0
- package/dist_ts/cache/classes.secrets.scan.service.d.ts +51 -0
- package/dist_ts/cache/classes.secrets.scan.service.js +237 -0
- package/dist_ts/cache/documents/classes.cached.project.d.ts +13 -0
- package/dist_ts/cache/documents/classes.cached.project.js +101 -0
- package/dist_ts/cache/documents/classes.cached.secret.d.ts +24 -0
- package/dist_ts/cache/documents/classes.cached.secret.js +158 -0
- package/dist_ts/cache/documents/index.d.ts +2 -0
- package/dist_ts/cache/documents/index.js +3 -0
- package/dist_ts/cache/index.d.ts +7 -0
- package/dist_ts/cache/index.js +6 -0
- package/dist_ts/classes/actionlog.d.ts +19 -0
- package/dist_ts/classes/actionlog.js +44 -0
- package/dist_ts/classes/connectionmanager.d.ts +57 -0
- package/dist_ts/classes/connectionmanager.js +247 -0
- package/dist_ts/classes/gitopsapp.d.ts +30 -0
- package/dist_ts/classes/gitopsapp.js +101 -0
- package/dist_ts/classes/jobmanager.d.ts +47 -0
- package/dist_ts/classes/jobmanager.js +301 -0
- package/dist_ts/classes/jobrunners/autobookstackdocs.runner.d.ts +29 -0
- package/dist_ts/classes/jobrunners/autobookstackdocs.runner.js +361 -0
- package/dist_ts/classes/jobrunners/base.jobrunner.d.ts +14 -0
- package/dist_ts/classes/jobrunners/base.jobrunner.js +3 -0
- package/dist_ts/classes/jobrunners/index.d.ts +5 -0
- package/dist_ts/classes/jobrunners/index.js +14 -0
- package/dist_ts/classes/managedsecrets.manager.d.ts +47 -0
- package/dist_ts/classes/managedsecrets.manager.js +247 -0
- package/dist_ts/classes/syncmanager.d.ts +189 -0
- package/dist_ts/classes/syncmanager.js +1787 -0
- package/dist_ts/index.d.ts +6 -0
- package/dist_ts/index.js +32 -0
- package/dist_ts/logging.d.ts +49 -0
- package/dist_ts/logging.js +134 -0
- package/dist_ts/opsserver/classes.opsserver.d.ts +25 -0
- package/dist_ts/opsserver/classes.opsserver.js +70 -0
- package/dist_ts/opsserver/handlers/actionlog.handler.d.ts +9 -0
- package/dist_ts/opsserver/handlers/actionlog.handler.js +24 -0
- package/dist_ts/opsserver/handlers/actions.handler.d.ts +9 -0
- package/dist_ts/opsserver/handlers/actions.handler.js +38 -0
- package/dist_ts/opsserver/handlers/admin.handler.d.ts +19 -0
- package/dist_ts/opsserver/handlers/admin.handler.js +96 -0
- package/dist_ts/opsserver/handlers/connections.handler.d.ts +10 -0
- package/dist_ts/opsserver/handlers/connections.handler.js +109 -0
- package/dist_ts/opsserver/handlers/groups.handler.d.ts +9 -0
- package/dist_ts/opsserver/handlers/groups.handler.js +24 -0
- package/dist_ts/opsserver/handlers/index.d.ts +13 -0
- package/dist_ts/opsserver/handlers/index.js +14 -0
- package/dist_ts/opsserver/handlers/jobs.handler.d.ts +16 -0
- package/dist_ts/opsserver/handlers/jobs.handler.js +146 -0
- package/dist_ts/opsserver/handlers/logs.handler.d.ts +9 -0
- package/dist_ts/opsserver/handlers/logs.handler.js +21 -0
- package/dist_ts/opsserver/handlers/managedsecrets.handler.d.ts +11 -0
- package/dist_ts/opsserver/handlers/managedsecrets.handler.js +110 -0
- package/dist_ts/opsserver/handlers/pipelines.handler.d.ts +31 -0
- package/dist_ts/opsserver/handlers/pipelines.handler.js +204 -0
- package/dist_ts/opsserver/handlers/projects.handler.d.ts +9 -0
- package/dist_ts/opsserver/handlers/projects.handler.js +24 -0
- package/dist_ts/opsserver/handlers/secrets.handler.d.ts +10 -0
- package/dist_ts/opsserver/handlers/secrets.handler.js +171 -0
- package/dist_ts/opsserver/handlers/sync.handler.d.ts +16 -0
- package/dist_ts/opsserver/handlers/sync.handler.js +166 -0
- package/dist_ts/opsserver/handlers/webhook.handler.d.ts +7 -0
- package/dist_ts/opsserver/handlers/webhook.handler.js +55 -0
- package/dist_ts/opsserver/helpers/guards.d.ts +5 -0
- package/dist_ts/opsserver/helpers/guards.js +12 -0
- package/dist_ts/opsserver/index.d.ts +1 -0
- package/dist_ts/opsserver/index.js +2 -0
- package/dist_ts/paths.d.ts +9 -0
- package/dist_ts/paths.js +13 -0
- package/dist_ts/plugins.d.ts +25 -0
- package/dist_ts/plugins.js +32 -0
- package/dist_ts/providers/classes.baseprovider.d.ts +51 -0
- package/dist_ts/providers/classes.baseprovider.js +17 -0
- package/dist_ts/providers/classes.giteaprovider.d.ts +40 -0
- package/dist_ts/providers/classes.giteaprovider.js +224 -0
- package/dist_ts/providers/classes.gitlabprovider.d.ts +39 -0
- package/dist_ts/providers/classes.gitlabprovider.js +207 -0
- package/dist_ts/providers/index.d.ts +3 -0
- package/dist_ts/providers/index.js +4 -0
- package/dist_ts/storage/classes.storagemanager.d.ts +33 -0
- package/dist_ts/storage/classes.storagemanager.js +135 -0
- package/dist_ts/storage/index.d.ts +2 -0
- package/dist_ts/storage/index.js +2 -0
- package/dist_ts/timers.d.ts +4 -0
- package/dist_ts/timers.js +24 -0
- package/dist_ts_bundled/bundle.d.ts +4 -0
- package/dist_ts_bundled/bundle.js +12 -0
- package/dist_ts_interfaces/data/actionlog.d.ts +12 -0
- package/dist_ts_interfaces/data/actionlog.js +2 -0
- package/dist_ts_interfaces/data/branch.d.ts +8 -0
- package/dist_ts_interfaces/data/branch.js +2 -0
- package/dist_ts_interfaces/data/connection.d.ts +12 -0
- package/dist_ts_interfaces/data/connection.js +2 -0
- package/dist_ts_interfaces/data/group.d.ts +10 -0
- package/dist_ts_interfaces/data/group.js +2 -0
- package/dist_ts_interfaces/data/identity.d.ts +7 -0
- package/dist_ts_interfaces/data/identity.js +2 -0
- package/dist_ts_interfaces/data/index.d.ts +11 -0
- package/dist_ts_interfaces/data/index.js +12 -0
- package/dist_ts_interfaces/data/job.d.ts +37 -0
- package/dist_ts_interfaces/data/job.js +2 -0
- package/dist_ts_interfaces/data/managedsecret.d.ts +37 -0
- package/dist_ts_interfaces/data/managedsecret.js +2 -0
- package/dist_ts_interfaces/data/pipeline.d.ts +22 -0
- package/dist_ts_interfaces/data/pipeline.js +2 -0
- package/dist_ts_interfaces/data/project.d.ts +12 -0
- package/dist_ts_interfaces/data/project.js +2 -0
- package/dist_ts_interfaces/data/secret.d.ts +11 -0
- package/dist_ts_interfaces/data/secret.js +2 -0
- package/dist_ts_interfaces/data/sync.d.ts +34 -0
- package/dist_ts_interfaces/data/sync.js +2 -0
- package/dist_ts_interfaces/index.d.ts +5 -0
- package/dist_ts_interfaces/index.js +8 -0
- package/dist_ts_interfaces/plugins.d.ts +2 -0
- package/dist_ts_interfaces/plugins.js +4 -0
- package/dist_ts_interfaces/requests/actionlog.d.ts +15 -0
- package/dist_ts_interfaces/requests/actionlog.js +3 -0
- package/dist_ts_interfaces/requests/actions.d.ts +31 -0
- package/dist_ts_interfaces/requests/actions.js +3 -0
- package/dist_ts_interfaces/requests/admin.d.ts +31 -0
- package/dist_ts_interfaces/requests/admin.js +3 -0
- package/dist_ts_interfaces/requests/connections.d.ts +71 -0
- package/dist_ts_interfaces/requests/connections.js +3 -0
- package/dist_ts_interfaces/requests/groups.d.ts +14 -0
- package/dist_ts_interfaces/requests/groups.js +3 -0
- package/dist_ts_interfaces/requests/index.d.ts +13 -0
- package/dist_ts_interfaces/requests/index.js +14 -0
- package/dist_ts_interfaces/requests/jobs.d.ts +86 -0
- package/dist_ts_interfaces/requests/jobs.js +3 -0
- package/dist_ts_interfaces/requests/logs.d.ts +14 -0
- package/dist_ts_interfaces/requests/logs.js +3 -0
- package/dist_ts_interfaces/requests/managedsecrets.d.ts +84 -0
- package/dist_ts_interfaces/requests/managedsecrets.js +3 -0
- package/dist_ts_interfaces/requests/pipelines.d.ts +55 -0
- package/dist_ts_interfaces/requests/pipelines.js +3 -0
- package/dist_ts_interfaces/requests/projects.d.ts +14 -0
- package/dist_ts_interfaces/requests/projects.js +3 -0
- package/dist_ts_interfaces/requests/secrets.d.ts +72 -0
- package/dist_ts_interfaces/requests/secrets.js +3 -0
- package/dist_ts_interfaces/requests/sync.d.ts +120 -0
- package/dist_ts_interfaces/requests/sync.js +3 -0
- package/dist_ts_interfaces/requests/webhook.d.ts +13 -0
- package/dist_ts_interfaces/requests/webhook.js +3 -0
- package/license +21 -0
- package/package.json +81 -0
- package/readme.md +177 -0
- package/readme.todo.md +3 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/cache/classes.cache.cleaner.ts +69 -0
- package/ts/cache/classes.cached.document.ts +57 -0
- package/ts/cache/classes.cachedb.ts +72 -0
- package/ts/cache/classes.secrets.scan.service.ts +267 -0
- package/ts/cache/documents/classes.cached.project.ts +32 -0
- package/ts/cache/documents/classes.cached.secret.ts +81 -0
- package/ts/cache/documents/index.ts +2 -0
- package/ts/cache/index.ts +7 -0
- package/ts/classes/actionlog.ts +57 -0
- package/ts/classes/connectionmanager.ts +263 -0
- package/ts/classes/gitopsapp.ts +128 -0
- package/ts/classes/jobmanager.ts +337 -0
- package/ts/classes/jobrunners/autobookstackdocs.runner.ts +435 -0
- package/ts/classes/jobrunners/base.jobrunner.ts +16 -0
- package/ts/classes/jobrunners/index.ts +17 -0
- package/ts/classes/managedsecrets.manager.ts +322 -0
- package/ts/classes/syncmanager.ts +2117 -0
- package/ts/index.ts +37 -0
- package/ts/logging.ts +162 -0
- package/ts/opsserver/classes.opsserver.ts +86 -0
- package/ts/opsserver/handlers/actionlog.handler.ts +30 -0
- package/ts/opsserver/handlers/actions.handler.ts +50 -0
- package/ts/opsserver/handlers/admin.handler.ts +122 -0
- package/ts/opsserver/handlers/connections.handler.ts +162 -0
- package/ts/opsserver/handlers/groups.handler.ts +32 -0
- package/ts/opsserver/handlers/index.ts +13 -0
- package/ts/opsserver/handlers/jobs.handler.ts +189 -0
- package/ts/opsserver/handlers/logs.handler.ts +29 -0
- package/ts/opsserver/handlers/managedsecrets.handler.ts +158 -0
- package/ts/opsserver/handlers/pipelines.handler.ts +281 -0
- package/ts/opsserver/handlers/projects.handler.ts +32 -0
- package/ts/opsserver/handlers/secrets.handler.ts +224 -0
- package/ts/opsserver/handlers/sync.handler.ts +224 -0
- package/ts/opsserver/handlers/webhook.handler.ts +62 -0
- package/ts/opsserver/helpers/guards.ts +16 -0
- package/ts/opsserver/index.ts +1 -0
- package/ts/paths.ts +19 -0
- package/ts/plugins.ts +38 -0
- package/ts/providers/classes.baseprovider.ts +99 -0
- package/ts/providers/classes.giteaprovider.ts +279 -0
- package/ts/providers/classes.gitlabprovider.ts +265 -0
- package/ts/providers/index.ts +3 -0
- package/ts/storage/classes.storagemanager.ts +144 -0
- package/ts/storage/index.ts +2 -0
- package/ts/timers.ts +34 -0
- package/ts_interfaces/data/actionlog.ts +13 -0
- package/ts_interfaces/data/branch.ts +9 -0
- package/ts_interfaces/data/connection.ts +13 -0
- package/ts_interfaces/data/group.ts +10 -0
- package/ts_interfaces/data/identity.ts +7 -0
- package/ts_interfaces/data/index.ts +11 -0
- package/ts_interfaces/data/job.ts +42 -0
- package/ts_interfaces/data/managedsecret.ts +41 -0
- package/ts_interfaces/data/pipeline.ts +32 -0
- package/ts_interfaces/data/project.ts +12 -0
- package/ts_interfaces/data/secret.ts +11 -0
- package/ts_interfaces/data/sync.ts +37 -0
- package/ts_interfaces/index.ts +9 -0
- package/ts_interfaces/plugins.ts +6 -0
- package/ts_interfaces/requests/actionlog.ts +19 -0
- package/ts_interfaces/requests/actions.ts +39 -0
- package/ts_interfaces/requests/admin.ts +43 -0
- package/ts_interfaces/requests/connections.ts +95 -0
- package/ts_interfaces/requests/groups.ts +18 -0
- package/ts_interfaces/requests/index.ts +13 -0
- package/ts_interfaces/requests/jobs.ts +118 -0
- package/ts_interfaces/requests/logs.ts +18 -0
- package/ts_interfaces/requests/managedsecrets.ts +112 -0
- package/ts_interfaces/requests/pipelines.ts +71 -0
- package/ts_interfaces/requests/projects.ts +18 -0
- package/ts_interfaces/requests/secrets.ts +92 -0
- package/ts_interfaces/requests/sync.ts +157 -0
- package/ts_interfaces/requests/webhook.ts +18 -0
- package/ts_web/00_commitinfo_data.ts +8 -0
- package/ts_web/appstate.ts +1251 -0
- package/ts_web/elements/gitops-dashboard.ts +350 -0
- package/ts_web/elements/index.ts +10 -0
- package/ts_web/elements/shared/css.ts +29 -0
- package/ts_web/elements/shared/index.ts +1 -0
- package/ts_web/elements/views/actionlog/index.ts +101 -0
- package/ts_web/elements/views/actions/index.ts +209 -0
- package/ts_web/elements/views/buildlog/index.ts +196 -0
- package/ts_web/elements/views/connections/index.ts +260 -0
- package/ts_web/elements/views/groups/index.ts +134 -0
- package/ts_web/elements/views/jobs/index.ts +424 -0
- package/ts_web/elements/views/managedsecrets/index.ts +502 -0
- package/ts_web/elements/views/overview/index.ts +86 -0
- package/ts_web/elements/views/pipelines/index.ts +561 -0
- package/ts_web/elements/views/projects/index.ts +149 -0
- package/ts_web/elements/views/secrets/index.ts +310 -0
- package/ts_web/elements/views/sync/index.ts +512 -0
- package/ts_web/index.ts +7 -0
- package/ts_web/plugins.ts +15 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import { logger } from '../../logging.js';
|
|
3
|
+
import { BaseJobRunner } from './base.jobrunner.js';
|
|
4
|
+
const KEYCHAIN_PREFIX = 'keychain:';
|
|
5
|
+
const BATCH_SIZE = 5;
|
|
6
|
+
const BATCH_DELAY_MS = 200;
|
|
7
|
+
const HASH_STORAGE_PREFIX = '/job-hashes/';
|
|
8
|
+
/** Simple SHA-256 hex hash */
|
|
9
|
+
async function sha256(content) {
|
|
10
|
+
const data = new TextEncoder().encode(content);
|
|
11
|
+
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
|
|
12
|
+
return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, '0')).join('');
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* If the first line of markdown is a heading matching the book name (e.g. "# @org/repo"),
|
|
16
|
+
* strip it — the book title already provides that context.
|
|
17
|
+
*/
|
|
18
|
+
const REDUNDANT_HEADINGS = ['changelog'];
|
|
19
|
+
function stripRedundantHeading(markdown, bookName) {
|
|
20
|
+
const firstNewline = markdown.indexOf('\n');
|
|
21
|
+
const firstLine = (firstNewline === -1 ? markdown : markdown.slice(0, firstNewline)).trim();
|
|
22
|
+
if (firstLine.startsWith('# ')) {
|
|
23
|
+
const heading = firstLine.slice(2).trim().toLowerCase();
|
|
24
|
+
const fullName = bookName.toLowerCase();
|
|
25
|
+
const repoName = bookName.split('/').pop()?.toLowerCase() || '';
|
|
26
|
+
// Strip headings matching the book/repo name (with optional trailing decorations)
|
|
27
|
+
if (heading === fullName || heading === repoName
|
|
28
|
+
|| heading.startsWith(fullName + ' ') || heading.startsWith(repoName + ' ')) {
|
|
29
|
+
return firstNewline === -1 ? '' : markdown.slice(firstNewline + 1);
|
|
30
|
+
}
|
|
31
|
+
// Strip generic redundant headings (e.g. "# Changelog")
|
|
32
|
+
if (REDUNDANT_HEADINGS.includes(heading)) {
|
|
33
|
+
return firstNewline === -1 ? '' : markdown.slice(firstNewline + 1);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return markdown;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Mapping:
|
|
40
|
+
* Git org/group → BookStack Shelf
|
|
41
|
+
* Git repository → BookStack Book (named @group/repo, assigned to shelf)
|
|
42
|
+
* readme.md → BookStack Page (named "readme.md for @group/repo")
|
|
43
|
+
* docs/*.md → BookStack Pages (named "docs/file.md for @group/repo")
|
|
44
|
+
*
|
|
45
|
+
* Content hashes are persisted in storage to skip updates when content hasn't changed.
|
|
46
|
+
*/
|
|
47
|
+
export class AutoBookstackDocsRunner extends BaseJobRunner {
|
|
48
|
+
jobType = 'autobookstackdocs';
|
|
49
|
+
async execute(context) {
|
|
50
|
+
const config = context.jobConfig.autoBookstackDocsConfig;
|
|
51
|
+
if (!config) {
|
|
52
|
+
throw new Error('Missing autoBookstackDocsConfig');
|
|
53
|
+
}
|
|
54
|
+
// 1. Resolve BookStack token from keychain
|
|
55
|
+
let tokenSecret = config.bookstackTarget.tokenSecret;
|
|
56
|
+
if (tokenSecret.startsWith(KEYCHAIN_PREFIX)) {
|
|
57
|
+
const keychainId = tokenSecret.slice(KEYCHAIN_PREFIX.length);
|
|
58
|
+
const resolved = await context.smartSecret.getSecret(keychainId);
|
|
59
|
+
if (!resolved) {
|
|
60
|
+
throw new Error('Could not retrieve BookStack token from keychain');
|
|
61
|
+
}
|
|
62
|
+
tokenSecret = resolved;
|
|
63
|
+
}
|
|
64
|
+
// 2. Connect to BookStack
|
|
65
|
+
const bookstack = new plugins.bookstackClient.BookStackAccount(config.bookstackTarget.baseUrl, config.bookstackTarget.tokenId, tokenSecret);
|
|
66
|
+
await bookstack.testConnection();
|
|
67
|
+
logger.jobLog('info', `Connected to BookStack at ${config.bookstackTarget.baseUrl}`, 'bookstack');
|
|
68
|
+
// 3. Load persisted content hashes (for diff-based updates)
|
|
69
|
+
const hashKey = `${HASH_STORAGE_PREFIX}${context.jobConfig.id}.json`;
|
|
70
|
+
const oldHashes = (await context.storageManager.getJSON(hashKey)) || {};
|
|
71
|
+
const newHashes = {};
|
|
72
|
+
// 4. Pre-load existing shelves for find-or-create
|
|
73
|
+
const existingShelves = await bookstack.getShelves();
|
|
74
|
+
const shelfMap = new Map();
|
|
75
|
+
for (const shelf of existingShelves) {
|
|
76
|
+
shelfMap.set(shelf.name.toLowerCase(), shelf);
|
|
77
|
+
}
|
|
78
|
+
// Track desired state for deletion reconciliation
|
|
79
|
+
const syncedShelfNames = new Set();
|
|
80
|
+
const syncedBookNames = new Map();
|
|
81
|
+
const shelfBookIds = new Map();
|
|
82
|
+
let pagesCreated = 0;
|
|
83
|
+
let pagesUpdated = 0;
|
|
84
|
+
let pagesSkipped = 0;
|
|
85
|
+
// 5. Process each source connection
|
|
86
|
+
for (const connectionId of config.sourceConnectionIds) {
|
|
87
|
+
const conn = context.connectionManager.getConnection(connectionId);
|
|
88
|
+
if (!conn || conn.status === 'paused') {
|
|
89
|
+
logger.jobLog('warn', `Skipping connection ${connectionId} (not found or paused)`, 'bookstack');
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const provider = context.connectionManager.getProvider(connectionId);
|
|
93
|
+
const groups = await provider.getGroups();
|
|
94
|
+
logger.jobLog('info', `Connection "${conn.name}": ${groups.length} groups`, 'bookstack');
|
|
95
|
+
for (const group of groups) {
|
|
96
|
+
// Apply group filters
|
|
97
|
+
if (config.includeGroups && config.includeGroups.length > 0) {
|
|
98
|
+
if (!config.includeGroups.some((g) => g.toLowerCase() === group.name.toLowerCase() || g.toLowerCase() === group.fullPath.toLowerCase())) {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (config.excludeGroups && config.excludeGroups.length > 0) {
|
|
103
|
+
if (config.excludeGroups.some((g) => g.toLowerCase() === group.name.toLowerCase() || g.toLowerCase() === group.fullPath.toLowerCase())) {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// Find or create shelf for this org/group
|
|
108
|
+
const shelfName = group.fullPath || group.name;
|
|
109
|
+
const shelfKey = shelfName.toLowerCase();
|
|
110
|
+
syncedShelfNames.add(shelfKey);
|
|
111
|
+
if (!syncedBookNames.has(shelfKey)) {
|
|
112
|
+
syncedBookNames.set(shelfKey, new Set());
|
|
113
|
+
}
|
|
114
|
+
if (!shelfBookIds.has(shelfKey)) {
|
|
115
|
+
shelfBookIds.set(shelfKey, []);
|
|
116
|
+
}
|
|
117
|
+
let shelf = shelfMap.get(shelfKey);
|
|
118
|
+
if (!shelf) {
|
|
119
|
+
shelf = await bookstack.createShelf({
|
|
120
|
+
name: shelfName,
|
|
121
|
+
description: group.description || `Documentation for ${shelfName}`,
|
|
122
|
+
});
|
|
123
|
+
shelfMap.set(shelfKey, shelf);
|
|
124
|
+
logger.jobLog('info', `Created shelf: ${shelfName}`, 'bookstack');
|
|
125
|
+
}
|
|
126
|
+
// Get projects in this group
|
|
127
|
+
const projects = await provider.getGroupProjects(group.id);
|
|
128
|
+
// Process repos in batches
|
|
129
|
+
for (let i = 0; i < projects.length; i += BATCH_SIZE) {
|
|
130
|
+
if (i > 0)
|
|
131
|
+
await new Promise((r) => setTimeout(r, BATCH_DELAY_MS));
|
|
132
|
+
const batch = projects.slice(i, i + BATCH_SIZE);
|
|
133
|
+
const results = await Promise.all(batch.map((project) => {
|
|
134
|
+
const bookName = `@${group.fullPath}/${project.name}`;
|
|
135
|
+
syncedBookNames.get(shelfKey).add(bookName.toLowerCase());
|
|
136
|
+
return this.syncRepoAsBook(provider, bookstack, context.storageManager, project, bookName, config, group.visibility, oldHashes, newHashes);
|
|
137
|
+
}));
|
|
138
|
+
for (const result of results) {
|
|
139
|
+
if (result) {
|
|
140
|
+
shelfBookIds.get(shelfKey).push(result.bookId);
|
|
141
|
+
pagesCreated += result.created;
|
|
142
|
+
pagesUpdated += result.updated;
|
|
143
|
+
pagesSkipped += result.skipped;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Assign all synced books to this shelf (only if book list changed)
|
|
148
|
+
const bookIds = shelfBookIds.get(shelfKey);
|
|
149
|
+
if (bookIds.length > 0) {
|
|
150
|
+
const shelfHashKey = `__shelf__${shelfKey}`;
|
|
151
|
+
const desiredShelfState = bookIds.slice().sort((a, b) => a - b).join(',');
|
|
152
|
+
if (oldHashes[shelfHashKey] !== desiredShelfState) {
|
|
153
|
+
await shelf.update({ books: bookIds });
|
|
154
|
+
logger.jobLog('info', `Updated shelf "${shelfName}" book assignments`, 'bookstack');
|
|
155
|
+
}
|
|
156
|
+
newHashes[shelfHashKey] = desiredShelfState;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// 6. Deletion reconciliation
|
|
161
|
+
if (config.propagateDeletes) {
|
|
162
|
+
await this.reconcileDeletes(bookstack, shelfMap, syncedShelfNames, syncedBookNames);
|
|
163
|
+
}
|
|
164
|
+
// 7. Persist updated content hashes
|
|
165
|
+
await context.storageManager.setJSON(hashKey, newHashes);
|
|
166
|
+
logger.jobLog('success', `Sync complete — ${pagesCreated} created, ${pagesUpdated} updated, ${pagesSkipped} unchanged`, 'bookstack');
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Syncs a single git repository as a BookStack Book.
|
|
170
|
+
* Returns book ID + page stats, or null if skipped (no docs).
|
|
171
|
+
*/
|
|
172
|
+
async syncRepoAsBook(provider, bookstack, storageManager, project, bookName, config, groupVisibility, oldHashes, newHashes) {
|
|
173
|
+
try {
|
|
174
|
+
// 0. Collect tags from package.json keywords + git repo topics
|
|
175
|
+
const tags = await this.collectTags(provider, project);
|
|
176
|
+
// Collect all pages to sync for this repo
|
|
177
|
+
const pagesToSync = [];
|
|
178
|
+
// 1. Fetch explicit root files (e.g. readme.md)
|
|
179
|
+
for (const filePath of config.filePaths) {
|
|
180
|
+
let content = await provider.getFileContent(project.fullPath, filePath);
|
|
181
|
+
if (content) {
|
|
182
|
+
content = stripRedundantHeading(content, bookName);
|
|
183
|
+
const tagsStr = tags.map((t) => t.name).join(',');
|
|
184
|
+
const hash = await sha256(content + '\0' + tagsStr);
|
|
185
|
+
const pageName = `${filePath} for ${bookName}`;
|
|
186
|
+
pagesToSync.push({ name: pageName, content, hash });
|
|
187
|
+
newHashes[pageName.toLowerCase()] = hash;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// 2. Scan doc directories for .md files
|
|
191
|
+
for (const dir of config.docDirs) {
|
|
192
|
+
const entries = await provider.getDirectoryContents(project.fullPath, dir);
|
|
193
|
+
if (!entries)
|
|
194
|
+
continue;
|
|
195
|
+
const mdFiles = entries.filter((e) => e.type === 'file' && e.name.toLowerCase().endsWith('.md'));
|
|
196
|
+
for (const mdFile of mdFiles) {
|
|
197
|
+
let content = await provider.getFileContent(project.fullPath, mdFile.path);
|
|
198
|
+
if (content) {
|
|
199
|
+
content = stripRedundantHeading(content, bookName);
|
|
200
|
+
const tagsStr = tags.map((t) => t.name).join(',');
|
|
201
|
+
const hash = await sha256(content + '\0' + tagsStr);
|
|
202
|
+
const pageName = `${mdFile.path} for ${bookName}`;
|
|
203
|
+
pagesToSync.push({ name: pageName, content, hash });
|
|
204
|
+
newHashes[pageName.toLowerCase()] = hash;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// Skip repos that have no docs at all
|
|
209
|
+
if (pagesToSync.length === 0)
|
|
210
|
+
return null;
|
|
211
|
+
// 3. Find or create book for this repo
|
|
212
|
+
const book = await this.findOrCreateBook(bookstack, bookName, project.description || '');
|
|
213
|
+
// 4. Get existing pages in this book
|
|
214
|
+
const existingPages = await book.getPages();
|
|
215
|
+
const pageMap = new Map();
|
|
216
|
+
for (const p of existingPages) {
|
|
217
|
+
pageMap.set(p.name.toLowerCase(), p);
|
|
218
|
+
}
|
|
219
|
+
// 5. Create or update pages (only if content changed)
|
|
220
|
+
let created = 0;
|
|
221
|
+
let updated = 0;
|
|
222
|
+
let skipped = 0;
|
|
223
|
+
const syncedPageNames = new Set();
|
|
224
|
+
for (const page of pagesToSync) {
|
|
225
|
+
syncedPageNames.add(page.name.toLowerCase());
|
|
226
|
+
const existing = pageMap.get(page.name.toLowerCase());
|
|
227
|
+
if (existing) {
|
|
228
|
+
// Check hash — skip update if content hasn't changed
|
|
229
|
+
const oldHash = oldHashes[page.name.toLowerCase()];
|
|
230
|
+
if (oldHash === page.hash) {
|
|
231
|
+
skipped++;
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
await existing.update({ markdown: page.content, tags });
|
|
235
|
+
updated++;
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
await bookstack.createPage({
|
|
239
|
+
book_id: book.id,
|
|
240
|
+
name: page.name,
|
|
241
|
+
markdown: page.content,
|
|
242
|
+
tags,
|
|
243
|
+
});
|
|
244
|
+
created++;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
// 6. Delete stale pages within this book
|
|
248
|
+
if (config.propagateDeletes) {
|
|
249
|
+
for (const [name, page] of pageMap) {
|
|
250
|
+
if (!syncedPageNames.has(name)) {
|
|
251
|
+
await page.delete();
|
|
252
|
+
logger.jobLog('warn', `Deleted stale page "${page.name}" from book "${bookName}"`, 'bookstack');
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
// 7. Sync visibility — only update permissions if visibility state changed
|
|
257
|
+
if (config.syncVisibility) {
|
|
258
|
+
const isPrivate = project.visibility === 'private' || project.visibility === 'internal'
|
|
259
|
+
|| groupVisibility === 'private' || groupVisibility === 'internal';
|
|
260
|
+
const visKey = `__vis__${bookName.toLowerCase()}`;
|
|
261
|
+
const desiredVis = isPrivate ? `private:${config.privateRoleId || ''}` : 'public';
|
|
262
|
+
const oldVis = oldHashes[visKey];
|
|
263
|
+
newHashes[visKey] = desiredVis;
|
|
264
|
+
if (oldVis !== desiredVis) {
|
|
265
|
+
if (isPrivate) {
|
|
266
|
+
const permUpdate = {
|
|
267
|
+
fallback_permissions: { inheriting: false, view: false, create: false, update: false, delete: false },
|
|
268
|
+
};
|
|
269
|
+
if (config.privateRoleId) {
|
|
270
|
+
permUpdate.role_permissions = [{ role_id: config.privateRoleId, view: true, create: false, update: false, delete: false }];
|
|
271
|
+
}
|
|
272
|
+
await bookstack.updateContentPermissions('book', book.id, permUpdate);
|
|
273
|
+
logger.jobLog('info', `Restricted book "${bookName}" (private)`, 'bookstack');
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
await bookstack.updateContentPermissions('book', book.id, {
|
|
277
|
+
fallback_permissions: { inheriting: true },
|
|
278
|
+
});
|
|
279
|
+
logger.jobLog('info', `Set book "${bookName}" to public`, 'bookstack');
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
if (created > 0 || updated > 0) {
|
|
284
|
+
logger.jobLog('info', `${bookName}: ${created} created, ${updated} updated, ${skipped} unchanged`, 'bookstack');
|
|
285
|
+
}
|
|
286
|
+
return { bookId: book.id, created, updated, skipped };
|
|
287
|
+
}
|
|
288
|
+
catch (err) {
|
|
289
|
+
logger.jobLog('warn', `Failed to sync repo ${bookName}: ${err}`, 'bookstack');
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Removes stale BookStack shelves and orphaned books.
|
|
295
|
+
*/
|
|
296
|
+
async reconcileDeletes(bookstack, shelfMap, syncedShelfNames, syncedBookNames) {
|
|
297
|
+
// Build flat set of all desired book names
|
|
298
|
+
const allDesiredBookNames = new Set();
|
|
299
|
+
for (const bookNames of syncedBookNames.values()) {
|
|
300
|
+
for (const name of bookNames) {
|
|
301
|
+
allDesiredBookNames.add(name);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
// Delete stale shelves
|
|
305
|
+
for (const [shelfKey, shelf] of shelfMap) {
|
|
306
|
+
if (!syncedShelfNames.has(shelfKey)) {
|
|
307
|
+
await shelf.delete();
|
|
308
|
+
logger.jobLog('warn', `Deleted stale shelf "${shelf.name}"`, 'bookstack');
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
// Delete all orphaned books
|
|
312
|
+
const allBooks = await bookstack.getBooks();
|
|
313
|
+
for (const book of allBooks) {
|
|
314
|
+
if (!allDesiredBookNames.has(book.name.toLowerCase())) {
|
|
315
|
+
await book.delete();
|
|
316
|
+
logger.jobLog('warn', `Deleted orphaned book "${book.name}"`, 'bookstack');
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Collects tags from package.json keywords + git repo topics, deduplicated.
|
|
322
|
+
*/
|
|
323
|
+
async collectTags(provider, project) {
|
|
324
|
+
const tagNames = new Set();
|
|
325
|
+
// Add git repo topics
|
|
326
|
+
if (project.topics) {
|
|
327
|
+
for (const topic of project.topics) {
|
|
328
|
+
if (topic)
|
|
329
|
+
tagNames.add(topic.toLowerCase());
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
// Fetch package.json and extract keywords
|
|
333
|
+
try {
|
|
334
|
+
const pkgJson = await provider.getFileContent(project.fullPath, 'package.json');
|
|
335
|
+
if (pkgJson) {
|
|
336
|
+
const pkg = JSON.parse(pkgJson);
|
|
337
|
+
if (Array.isArray(pkg.keywords)) {
|
|
338
|
+
for (const kw of pkg.keywords) {
|
|
339
|
+
if (typeof kw === 'string' && kw)
|
|
340
|
+
tagNames.add(kw.toLowerCase());
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
catch {
|
|
346
|
+
// package.json missing or invalid — no keywords
|
|
347
|
+
}
|
|
348
|
+
return Array.from(tagNames).map((name) => ({ name, value: '' }));
|
|
349
|
+
}
|
|
350
|
+
async findOrCreateBook(bookstack, bookName, description) {
|
|
351
|
+
const books = await bookstack.getBooks();
|
|
352
|
+
const existing = books.find((b) => b.name.toLowerCase() === bookName.toLowerCase());
|
|
353
|
+
if (existing)
|
|
354
|
+
return existing;
|
|
355
|
+
return bookstack.createBook({
|
|
356
|
+
name: bookName,
|
|
357
|
+
description: description || `Documentation for ${bookName}`,
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0b2Jvb2tzdGFja2RvY3MucnVubmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdHMvY2xhc3Nlcy9qb2JydW5uZXJzL2F1dG9ib29rc3RhY2tkb2NzLnJ1bm5lci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGtCQUFrQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUkxQyxPQUFPLEVBQUUsYUFBYSxFQUF1QixNQUFNLHFCQUFxQixDQUFDO0FBRXpFLE1BQU0sZUFBZSxHQUFHLFdBQVcsQ0FBQztBQUNwQyxNQUFNLFVBQVUsR0FBRyxDQUFDLENBQUM7QUFDckIsTUFBTSxjQUFjLEdBQUcsR0FBRyxDQUFDO0FBQzNCLE1BQU0sbUJBQW1CLEdBQUcsY0FBYyxDQUFDO0FBRTNDLDhCQUE4QjtBQUM5QixLQUFLLFVBQVUsTUFBTSxDQUFDLE9BQWU7SUFDbkMsTUFBTSxJQUFJLEdBQUcsSUFBSSxXQUFXLEVBQUUsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDL0MsTUFBTSxVQUFVLEdBQUcsTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDL0QsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDckcsQ0FBQztBQUVEOzs7R0FHRztBQUNILE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQztBQUV6QyxTQUFTLHFCQUFxQixDQUFDLFFBQWdC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
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type * as interfaces from '../../../dist_ts_interfaces/index.js';
|
|
2
|
+
import type { ConnectionManager } from '../connectionmanager.js';
|
|
3
|
+
import type { StorageManager } from '../../storage/index.js';
|
|
4
|
+
import type * as plugins from '../../plugins.js';
|
|
5
|
+
export interface IJobRunContext {
|
|
6
|
+
jobConfig: interfaces.data.IJobConfig;
|
|
7
|
+
connectionManager: ConnectionManager;
|
|
8
|
+
storageManager: StorageManager;
|
|
9
|
+
smartSecret: plugins.smartsecret.SmartSecret;
|
|
10
|
+
}
|
|
11
|
+
export declare abstract class BaseJobRunner {
|
|
12
|
+
abstract readonly jobType: interfaces.data.TJobType;
|
|
13
|
+
abstract execute(context: IJobRunContext): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export class BaseJobRunner {
|
|
2
|
+
}
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS5qb2JydW5uZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9jbGFzc2VzL2pvYnJ1bm5lcnMvYmFzZS5qb2JydW5uZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBWUEsTUFBTSxPQUFnQixhQUFhO0NBR2xDIn0=
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type * as interfaces from '../../../dist_ts_interfaces/index.js';
|
|
2
|
+
import { BaseJobRunner } from './base.jobrunner.js';
|
|
3
|
+
export { BaseJobRunner, type IJobRunContext } from './base.jobrunner.js';
|
|
4
|
+
export { AutoBookstackDocsRunner } from './autobookstackdocs.runner.js';
|
|
5
|
+
export declare function getRunner(jobType: interfaces.data.TJobType): BaseJobRunner;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseJobRunner } from './base.jobrunner.js';
|
|
2
|
+
import { AutoBookstackDocsRunner } from './autobookstackdocs.runner.js';
|
|
3
|
+
export { BaseJobRunner } from './base.jobrunner.js';
|
|
4
|
+
export { AutoBookstackDocsRunner } from './autobookstackdocs.runner.js';
|
|
5
|
+
const runners = new Map();
|
|
6
|
+
runners.set('autobookstackdocs', new AutoBookstackDocsRunner());
|
|
7
|
+
export function getRunner(jobType) {
|
|
8
|
+
const runner = runners.get(jobType);
|
|
9
|
+
if (!runner) {
|
|
10
|
+
throw new Error(`No runner registered for job type: ${jobType}`);
|
|
11
|
+
}
|
|
12
|
+
return runner;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9jbGFzc2VzL2pvYnJ1bm5lcnMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3BELE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBRXhFLE9BQU8sRUFBRSxhQUFhLEVBQXVCLE1BQU0scUJBQXFCLENBQUM7QUFDekUsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFFeEUsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLEVBQTJDLENBQUM7QUFDbkUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsRUFBRSxJQUFJLHVCQUF1QixFQUFFLENBQUMsQ0FBQztBQUVoRSxNQUFNLFVBQVUsU0FBUyxDQUFDLE9BQWlDO0lBQ3pELE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDcEMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ1osTUFBTSxJQUFJLEtBQUssQ0FBQyxzQ0FBc0MsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUNuRSxDQUFDO0lBQ0QsT0FBTyxNQUFNLENBQUM7QUFDaEIsQ0FBQyJ9
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
import type * as interfaces from '../../dist_ts_interfaces/index.js';
|
|
3
|
+
import type { StorageManager } from '../storage/index.js';
|
|
4
|
+
import type { ConnectionManager } from './connectionmanager.js';
|
|
5
|
+
export declare class ManagedSecretsManager {
|
|
6
|
+
private storageManager;
|
|
7
|
+
private smartSecret;
|
|
8
|
+
private connectionManager;
|
|
9
|
+
private secrets;
|
|
10
|
+
constructor(storageManager: StorageManager, smartSecret: plugins.smartsecret.SmartSecret, connectionManager: ConnectionManager);
|
|
11
|
+
init(): Promise<void>;
|
|
12
|
+
private keychainId;
|
|
13
|
+
private prefixedKey;
|
|
14
|
+
private loadSecrets;
|
|
15
|
+
private persistSecret;
|
|
16
|
+
private removeFromStorage;
|
|
17
|
+
private getSecretValue;
|
|
18
|
+
private toApiModel;
|
|
19
|
+
private pushToTargets;
|
|
20
|
+
getAll(): Promise<interfaces.data.IManagedSecret[]>;
|
|
21
|
+
getById(id: string): Promise<interfaces.data.IManagedSecret | null>;
|
|
22
|
+
create(key: string, value: string, description: string | undefined, targets: interfaces.data.IManagedSecretTarget[]): Promise<{
|
|
23
|
+
managedSecret: interfaces.data.IManagedSecret;
|
|
24
|
+
pushResults: interfaces.data.IManagedSecretTargetStatus[];
|
|
25
|
+
}>;
|
|
26
|
+
update(id: string, updates: {
|
|
27
|
+
value?: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
targets?: interfaces.data.IManagedSecretTarget[];
|
|
30
|
+
}): Promise<{
|
|
31
|
+
managedSecret: interfaces.data.IManagedSecret;
|
|
32
|
+
pushResults: interfaces.data.IManagedSecretTargetStatus[];
|
|
33
|
+
}>;
|
|
34
|
+
delete(id: string): Promise<{
|
|
35
|
+
ok: boolean;
|
|
36
|
+
deleteResults: interfaces.data.IManagedSecretTargetStatus[];
|
|
37
|
+
}>;
|
|
38
|
+
pushOne(id: string): Promise<{
|
|
39
|
+
managedSecret: interfaces.data.IManagedSecret;
|
|
40
|
+
pushResults: interfaces.data.IManagedSecretTargetStatus[];
|
|
41
|
+
}>;
|
|
42
|
+
pushAll(): Promise<Array<{
|
|
43
|
+
managedSecretId: string;
|
|
44
|
+
key: string;
|
|
45
|
+
pushResults: interfaces.data.IManagedSecretTargetStatus[];
|
|
46
|
+
}>>;
|
|
47
|
+
}
|