@amiable-dev/docusaurus-plugin-stentorosaur 0.17.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/theme/StatusItem/MiniHeatmap.module.css +10 -12
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +10 -2
- package/scripts/bootstrap-summary.js +0 -0
- package/scripts/config.js +359 -0
- package/scripts/init.js +58 -0
- package/src/plugin-status.d.ts +127 -0
- package/templates/Makefile.status +146 -0
- package/templates/README.md +96 -0
- package/.notifyrc.example.json +0 -43
- package/ANALYSIS-MANIFEST.txt +0 -358
- package/ARCHITECTURE-DIAGRAM.txt +0 -220
- package/QUICKSTART.md +0 -440
- package/copyUntypedFiles.js +0 -24
- package/docs/README.md +0 -122
- package/docs/reference/CONFIGURATION.md +0 -994
- package/jest.setup.js +0 -17
- package/settings.json +0 -5
- package/tsconfig.tsbuildinfo +0 -1
|
@@ -19,19 +19,19 @@
|
|
|
19
19
|
.cells {
|
|
20
20
|
display: flex;
|
|
21
21
|
gap: 2px;
|
|
22
|
-
|
|
22
|
+
width: 100%;
|
|
23
23
|
margin-bottom: 0.75rem;
|
|
24
|
-
overflow
|
|
24
|
+
overflow: hidden;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
.cell {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
flex: 1;
|
|
29
|
+
min-width: 0;
|
|
30
|
+
height: 40px;
|
|
31
|
+
border-radius: 2px;
|
|
31
32
|
cursor: pointer;
|
|
32
|
-
transition:
|
|
33
|
+
transition: opacity 0.2s ease;
|
|
33
34
|
position: relative;
|
|
34
|
-
flex-shrink: 0;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
.cell.hasIncident {
|
|
@@ -74,9 +74,8 @@
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
.cell:hover {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
z-index: 1;
|
|
77
|
+
opacity: 0.7;
|
|
78
|
+
filter: brightness(1.1);
|
|
80
79
|
}
|
|
81
80
|
|
|
82
81
|
.legend {
|
|
@@ -135,8 +134,7 @@
|
|
|
135
134
|
}
|
|
136
135
|
|
|
137
136
|
.cell {
|
|
138
|
-
|
|
139
|
-
height: 20px;
|
|
137
|
+
height: 30px;
|
|
140
138
|
}
|
|
141
139
|
|
|
142
140
|
.uptimeStats {
|
package/lib/version.d.ts
CHANGED
package/lib/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amiable-dev/docusaurus-plugin-stentorosaur",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "A Docusaurus plugin for displaying status monitoring dashboard powered by GitHub Issues and Actions, similar to Upptime",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "src/plugin-status.d.ts",
|
|
@@ -11,8 +11,16 @@
|
|
|
11
11
|
"stentorosaur-setup-status-branch": "scripts/setup-status-branch.js",
|
|
12
12
|
"stentorosaur-migrate-to-status-branch": "scripts/migrate-to-status-branch.js",
|
|
13
13
|
"stentorosaur-cleanup-status-branch": "scripts/cleanup-status-branch.js",
|
|
14
|
-
"stentorosaur-bootstrap-summary": "scripts/bootstrap-summary.js"
|
|
14
|
+
"stentorosaur-bootstrap-summary": "scripts/bootstrap-summary.js",
|
|
15
|
+
"stentorosaur-init": "scripts/init.js",
|
|
16
|
+
"stentorosaur-config": "scripts/config.js"
|
|
15
17
|
},
|
|
18
|
+
"files": [
|
|
19
|
+
"lib",
|
|
20
|
+
"scripts",
|
|
21
|
+
"templates",
|
|
22
|
+
"src/plugin-status.d.ts"
|
|
23
|
+
],
|
|
16
24
|
"keywords": [
|
|
17
25
|
"docusaurus",
|
|
18
26
|
"plugin",
|
|
File without changes
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Stentorosaur configuration management CLI
|
|
5
|
+
* Manages .monitorrc.json and docusaurus.config plugin options
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs-extra');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
|
|
11
|
+
const CONFIG_FILE = '.monitorrc.json';
|
|
12
|
+
const ENTITIES_FILE = '.stentorosaur-entities.json';
|
|
13
|
+
|
|
14
|
+
// Parse command line arguments
|
|
15
|
+
function parseArgs(args) {
|
|
16
|
+
const result = { command: args[0], options: {} };
|
|
17
|
+
|
|
18
|
+
for (let i = 1; i < args.length; i++) {
|
|
19
|
+
const arg = args[i];
|
|
20
|
+
if (arg.startsWith('--')) {
|
|
21
|
+
const key = arg.slice(2);
|
|
22
|
+
const nextArg = args[i + 1];
|
|
23
|
+
if (nextArg && !nextArg.startsWith('--')) {
|
|
24
|
+
result.options[key] = nextArg;
|
|
25
|
+
i++;
|
|
26
|
+
} else {
|
|
27
|
+
result.options[key] = true;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Load monitor config
|
|
36
|
+
async function loadConfig() {
|
|
37
|
+
const configPath = path.join(process.cwd(), CONFIG_FILE);
|
|
38
|
+
|
|
39
|
+
if (!await fs.pathExists(configPath)) {
|
|
40
|
+
return {
|
|
41
|
+
"$schema": "https://json-schema.org/draft-07/schema#",
|
|
42
|
+
"description": "Configuration file for status monitoring script",
|
|
43
|
+
"systems": []
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return await fs.readJson(configPath);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Save monitor config
|
|
51
|
+
async function saveConfig(config) {
|
|
52
|
+
const configPath = path.join(process.cwd(), CONFIG_FILE);
|
|
53
|
+
await fs.writeJson(configPath, config, { spaces: 2 });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Load entities config (for processes and additional metadata)
|
|
57
|
+
async function loadEntities() {
|
|
58
|
+
const entitiesPath = path.join(process.cwd(), ENTITIES_FILE);
|
|
59
|
+
|
|
60
|
+
if (!await fs.pathExists(entitiesPath)) {
|
|
61
|
+
return { systems: [], processes: [] };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return await fs.readJson(entitiesPath);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Save entities config
|
|
68
|
+
async function saveEntities(entities) {
|
|
69
|
+
const entitiesPath = path.join(process.cwd(), ENTITIES_FILE);
|
|
70
|
+
await fs.writeJson(entitiesPath, entities, { spaces: 2 });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Add a system to monitor
|
|
74
|
+
async function addSystem(options) {
|
|
75
|
+
const name = options.name;
|
|
76
|
+
const url = options.url;
|
|
77
|
+
const method = options.method || 'GET';
|
|
78
|
+
const timeout = options.timeout || '10000';
|
|
79
|
+
const expectedCodes = options['expected-codes'] || '200';
|
|
80
|
+
|
|
81
|
+
if (!name || !url) {
|
|
82
|
+
console.error('\x1b[31mError:\x1b[0m Both --name and --url are required');
|
|
83
|
+
console.log('\nUsage: stentorosaur-config add-system --name api --url https://api.example.com/health');
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const config = await loadConfig();
|
|
88
|
+
|
|
89
|
+
// Check if system already exists
|
|
90
|
+
const existingIndex = config.systems.findIndex(s => s.system === name);
|
|
91
|
+
|
|
92
|
+
const newSystem = {
|
|
93
|
+
system: name,
|
|
94
|
+
url: url,
|
|
95
|
+
method: method.toUpperCase(),
|
|
96
|
+
timeout: parseInt(timeout, 10),
|
|
97
|
+
expectedCodes: expectedCodes.split(',').map(c => parseInt(c.trim(), 10)),
|
|
98
|
+
maxResponseTime: 30000
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
if (existingIndex >= 0) {
|
|
102
|
+
config.systems[existingIndex] = newSystem;
|
|
103
|
+
console.log(`\x1b[33mUpdated:\x1b[0m System '${name}' configuration updated`);
|
|
104
|
+
} else {
|
|
105
|
+
config.systems.push(newSystem);
|
|
106
|
+
console.log(`\x1b[32mAdded:\x1b[0m System '${name}' added to ${CONFIG_FILE}`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
await saveConfig(config);
|
|
110
|
+
|
|
111
|
+
// Also add to entities for docusaurus config reference
|
|
112
|
+
const entities = await loadEntities();
|
|
113
|
+
if (!entities.systems.find(s => s.name === name)) {
|
|
114
|
+
entities.systems.push({ name, type: 'system', url });
|
|
115
|
+
await saveEntities(entities);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
console.log(`\n URL: ${url}`);
|
|
119
|
+
console.log(` Method: ${method.toUpperCase()}`);
|
|
120
|
+
console.log(` Timeout: ${timeout}ms`);
|
|
121
|
+
console.log(` Expected codes: ${expectedCodes}`);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Add a business process
|
|
125
|
+
async function addProcess(options) {
|
|
126
|
+
const name = options.name;
|
|
127
|
+
const description = options.description || '';
|
|
128
|
+
|
|
129
|
+
if (!name) {
|
|
130
|
+
console.error('\x1b[31mError:\x1b[0m --name is required');
|
|
131
|
+
console.log('\nUsage: stentorosaur-config add-process --name deployments --description "Deployment pipeline"');
|
|
132
|
+
process.exit(1);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const entities = await loadEntities();
|
|
136
|
+
|
|
137
|
+
// Check if process already exists
|
|
138
|
+
const existingIndex = entities.processes.findIndex(p => p.name === name);
|
|
139
|
+
|
|
140
|
+
const newProcess = {
|
|
141
|
+
name,
|
|
142
|
+
type: 'process',
|
|
143
|
+
description: description || `${name} process tracking`
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
if (existingIndex >= 0) {
|
|
147
|
+
entities.processes[existingIndex] = newProcess;
|
|
148
|
+
console.log(`\x1b[33mUpdated:\x1b[0m Process '${name}' configuration updated`);
|
|
149
|
+
} else {
|
|
150
|
+
entities.processes.push(newProcess);
|
|
151
|
+
console.log(`\x1b[32mAdded:\x1b[0m Process '${name}' added to ${ENTITIES_FILE}`);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
await saveEntities(entities);
|
|
155
|
+
|
|
156
|
+
console.log(`\n Description: ${newProcess.description}`);
|
|
157
|
+
console.log(`\n\x1b[33mNote:\x1b[0m Add 'process:${name}' label to GitHub Issues to track this process.`);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Remove a system
|
|
161
|
+
async function removeSystem(options) {
|
|
162
|
+
const name = options.name;
|
|
163
|
+
|
|
164
|
+
if (!name) {
|
|
165
|
+
console.error('\x1b[31mError:\x1b[0m --name is required');
|
|
166
|
+
console.log('\nUsage: stentorosaur-config remove-system --name api');
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const config = await loadConfig();
|
|
171
|
+
const originalLength = config.systems.length;
|
|
172
|
+
config.systems = config.systems.filter(s => s.system !== name);
|
|
173
|
+
|
|
174
|
+
if (config.systems.length === originalLength) {
|
|
175
|
+
console.log(`\x1b[33mWarning:\x1b[0m System '${name}' not found in ${CONFIG_FILE}`);
|
|
176
|
+
} else {
|
|
177
|
+
await saveConfig(config);
|
|
178
|
+
console.log(`\x1b[32mRemoved:\x1b[0m System '${name}' from ${CONFIG_FILE}`);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Also remove from entities
|
|
182
|
+
const entities = await loadEntities();
|
|
183
|
+
entities.systems = entities.systems.filter(s => s.name !== name);
|
|
184
|
+
await saveEntities(entities);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// List all configured systems and processes
|
|
188
|
+
async function list() {
|
|
189
|
+
const config = await loadConfig();
|
|
190
|
+
const entities = await loadEntities();
|
|
191
|
+
|
|
192
|
+
console.log('\n\x1b[32mMonitored Systems:\x1b[0m');
|
|
193
|
+
console.log('─'.repeat(60));
|
|
194
|
+
|
|
195
|
+
if (config.systems.length === 0) {
|
|
196
|
+
console.log(' No systems configured');
|
|
197
|
+
console.log(' Run: make status-add-system name=api url=https://...');
|
|
198
|
+
} else {
|
|
199
|
+
for (const system of config.systems) {
|
|
200
|
+
console.log(`\n \x1b[36m${system.system}\x1b[0m`);
|
|
201
|
+
console.log(` URL: ${system.url}`);
|
|
202
|
+
console.log(` Method: ${system.method}`);
|
|
203
|
+
console.log(` Timeout: ${system.timeout}ms`);
|
|
204
|
+
console.log(` Expected: ${system.expectedCodes.join(', ')}`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
console.log('\n\n\x1b[32mBusiness Processes:\x1b[0m');
|
|
209
|
+
console.log('─'.repeat(60));
|
|
210
|
+
|
|
211
|
+
if (!entities.processes || entities.processes.length === 0) {
|
|
212
|
+
console.log(' No processes configured');
|
|
213
|
+
console.log(' Run: make status-add-process name=deployments');
|
|
214
|
+
} else {
|
|
215
|
+
for (const process of entities.processes) {
|
|
216
|
+
console.log(`\n \x1b[36m${process.name}\x1b[0m`);
|
|
217
|
+
console.log(` Label: process:${process.name}`);
|
|
218
|
+
if (process.description) {
|
|
219
|
+
console.log(` Description: ${process.description}`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
console.log('\n');
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Validate configuration
|
|
228
|
+
async function validate() {
|
|
229
|
+
const configPath = path.join(process.cwd(), CONFIG_FILE);
|
|
230
|
+
|
|
231
|
+
if (!await fs.pathExists(configPath)) {
|
|
232
|
+
console.error(`\x1b[31mError:\x1b[0m ${CONFIG_FILE} not found`);
|
|
233
|
+
console.log('Run: make status-init');
|
|
234
|
+
process.exit(1);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
try {
|
|
238
|
+
const config = await fs.readJson(configPath);
|
|
239
|
+
|
|
240
|
+
const errors = [];
|
|
241
|
+
const warnings = [];
|
|
242
|
+
|
|
243
|
+
if (!config.systems || !Array.isArray(config.systems)) {
|
|
244
|
+
errors.push('Missing or invalid "systems" array');
|
|
245
|
+
} else {
|
|
246
|
+
for (let i = 0; i < config.systems.length; i++) {
|
|
247
|
+
const system = config.systems[i];
|
|
248
|
+
|
|
249
|
+
if (!system.system) {
|
|
250
|
+
errors.push(`System ${i + 1}: Missing "system" name`);
|
|
251
|
+
}
|
|
252
|
+
if (!system.url) {
|
|
253
|
+
errors.push(`System ${i + 1}: Missing "url"`);
|
|
254
|
+
} else {
|
|
255
|
+
try {
|
|
256
|
+
new URL(system.url);
|
|
257
|
+
} catch {
|
|
258
|
+
errors.push(`System ${i + 1}: Invalid URL "${system.url}"`);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (system.timeout && (typeof system.timeout !== 'number' || system.timeout < 0)) {
|
|
262
|
+
warnings.push(`System ${i + 1}: Invalid timeout value`);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (errors.length > 0) {
|
|
268
|
+
console.log('\x1b[31mValidation failed:\x1b[0m\n');
|
|
269
|
+
errors.forEach(e => console.log(` - ${e}`));
|
|
270
|
+
process.exit(1);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (warnings.length > 0) {
|
|
274
|
+
console.log('\x1b[33mWarnings:\x1b[0m\n');
|
|
275
|
+
warnings.forEach(w => console.log(` - ${w}`));
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
console.log(`\x1b[32mConfiguration valid!\x1b[0m`);
|
|
279
|
+
console.log(` ${config.systems.length} system(s) configured`);
|
|
280
|
+
|
|
281
|
+
} catch (err) {
|
|
282
|
+
console.error(`\x1b[31mError:\x1b[0m Failed to parse ${CONFIG_FILE}`);
|
|
283
|
+
console.error(err.message);
|
|
284
|
+
process.exit(1);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Generate docusaurus config snippet
|
|
289
|
+
async function generateConfig() {
|
|
290
|
+
const entities = await loadEntities();
|
|
291
|
+
|
|
292
|
+
const allEntities = [
|
|
293
|
+
...entities.systems.map(s => ({ name: s.name, type: 'system' })),
|
|
294
|
+
...entities.processes.map(p => ({ name: p.name, type: 'process' }))
|
|
295
|
+
];
|
|
296
|
+
|
|
297
|
+
console.log('\n\x1b[32mDocusaurus Config Snippet:\x1b[0m');
|
|
298
|
+
console.log('─'.repeat(60));
|
|
299
|
+
console.log(`
|
|
300
|
+
// Add to docusaurus.config.js plugins array:
|
|
301
|
+
[
|
|
302
|
+
'@amiable-dev/docusaurus-plugin-stentorosaur',
|
|
303
|
+
{
|
|
304
|
+
owner: 'your-org',
|
|
305
|
+
repo: 'your-repo',
|
|
306
|
+
entities: ${JSON.stringify(allEntities, null, 6).replace(/\n/g, '\n ')},
|
|
307
|
+
},
|
|
308
|
+
],
|
|
309
|
+
`);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Main CLI
|
|
313
|
+
async function main() {
|
|
314
|
+
const args = process.argv.slice(2);
|
|
315
|
+
|
|
316
|
+
if (args.length === 0) {
|
|
317
|
+
console.log('Stentorosaur Configuration Manager\n');
|
|
318
|
+
console.log('Commands:');
|
|
319
|
+
console.log(' add-system Add a system to monitor');
|
|
320
|
+
console.log(' add-process Add a business process');
|
|
321
|
+
console.log(' remove-system Remove a system');
|
|
322
|
+
console.log(' list List all configured systems and processes');
|
|
323
|
+
console.log(' validate Validate configuration files');
|
|
324
|
+
console.log(' generate Generate docusaurus.config.js snippet');
|
|
325
|
+
console.log('\nRun with --help for more info');
|
|
326
|
+
process.exit(0);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const { command, options } = parseArgs(args);
|
|
330
|
+
|
|
331
|
+
switch (command) {
|
|
332
|
+
case 'add-system':
|
|
333
|
+
await addSystem(options);
|
|
334
|
+
break;
|
|
335
|
+
case 'add-process':
|
|
336
|
+
await addProcess(options);
|
|
337
|
+
break;
|
|
338
|
+
case 'remove-system':
|
|
339
|
+
await removeSystem(options);
|
|
340
|
+
break;
|
|
341
|
+
case 'list':
|
|
342
|
+
await list();
|
|
343
|
+
break;
|
|
344
|
+
case 'validate':
|
|
345
|
+
await validate();
|
|
346
|
+
break;
|
|
347
|
+
case 'generate':
|
|
348
|
+
await generateConfig();
|
|
349
|
+
break;
|
|
350
|
+
default:
|
|
351
|
+
console.error(`\x1b[31mError:\x1b[0m Unknown command '${command}'`);
|
|
352
|
+
process.exit(1);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
main().catch(err => {
|
|
357
|
+
console.error('\x1b[31mError:\x1b[0m', err.message);
|
|
358
|
+
process.exit(1);
|
|
359
|
+
});
|
package/scripts/init.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Initialize Stentorosaur status monitoring in a consuming project
|
|
5
|
+
* Creates .monitorrc.json and status-data directory
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs-extra');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
|
|
11
|
+
const CONFIG_FILE = '.monitorrc.json';
|
|
12
|
+
const STATUS_DATA_DIR = 'status-data';
|
|
13
|
+
|
|
14
|
+
const DEFAULT_CONFIG = {
|
|
15
|
+
"$schema": "https://json-schema.org/draft-07/schema#",
|
|
16
|
+
"description": "Configuration file for status monitoring script",
|
|
17
|
+
"systems": []
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
async function init() {
|
|
21
|
+
const cwd = process.cwd();
|
|
22
|
+
const configPath = path.join(cwd, CONFIG_FILE);
|
|
23
|
+
const statusDataPath = path.join(cwd, STATUS_DATA_DIR);
|
|
24
|
+
|
|
25
|
+
console.log('Initializing Stentorosaur status monitoring...\n');
|
|
26
|
+
|
|
27
|
+
// Create .monitorrc.json if it doesn't exist
|
|
28
|
+
if (await fs.pathExists(configPath)) {
|
|
29
|
+
console.log(`\x1b[33mWarning:\x1b[0m ${CONFIG_FILE} already exists. Skipping...`);
|
|
30
|
+
} else {
|
|
31
|
+
await fs.writeJson(configPath, DEFAULT_CONFIG, { spaces: 2 });
|
|
32
|
+
console.log(`\x1b[32mCreated:\x1b[0m ${CONFIG_FILE}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Create status-data directory
|
|
36
|
+
await fs.ensureDir(statusDataPath);
|
|
37
|
+
console.log(`\x1b[32mCreated:\x1b[0m ${STATUS_DATA_DIR}/`);
|
|
38
|
+
|
|
39
|
+
// Create .gitkeep in status-data
|
|
40
|
+
const gitkeepPath = path.join(statusDataPath, '.gitkeep');
|
|
41
|
+
if (!await fs.pathExists(gitkeepPath)) {
|
|
42
|
+
await fs.writeFile(gitkeepPath, '');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
console.log('\n\x1b[32mStatus monitoring initialized!\x1b[0m\n');
|
|
46
|
+
console.log('Next steps:');
|
|
47
|
+
console.log(' 1. Add systems to monitor:');
|
|
48
|
+
console.log(' make status-add-system name=api url=https://api.example.com/health\n');
|
|
49
|
+
console.log(' 2. Copy GitHub Actions workflows:');
|
|
50
|
+
console.log(' make status-workflows\n');
|
|
51
|
+
console.log(' 3. Test your configuration:');
|
|
52
|
+
console.log(' make status-test\n');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
init().catch(err => {
|
|
56
|
+
console.error('\x1b[31mError:\x1b[0m', err.message);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
});
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Your Organization
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
declare module 'docusaurus-plugin-stentorosaur' {
|
|
9
|
+
export type StatusItemStatus = 'up' | 'down' | 'degraded' | 'maintenance';
|
|
10
|
+
|
|
11
|
+
export interface StatusItem {
|
|
12
|
+
name: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
status: StatusItemStatus;
|
|
15
|
+
lastChecked?: string;
|
|
16
|
+
uptime?: string;
|
|
17
|
+
responseTime?: number;
|
|
18
|
+
incidentCount?: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface StatusIncident {
|
|
22
|
+
id: number;
|
|
23
|
+
title: string;
|
|
24
|
+
status: 'open' | 'closed';
|
|
25
|
+
severity: 'critical' | 'major' | 'minor' | 'maintenance';
|
|
26
|
+
createdAt: string;
|
|
27
|
+
updatedAt: string;
|
|
28
|
+
closedAt?: string;
|
|
29
|
+
url: string;
|
|
30
|
+
body?: string;
|
|
31
|
+
labels: string[];
|
|
32
|
+
affectedSystems: string[];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface PluginOptions {
|
|
36
|
+
/**
|
|
37
|
+
* GitHub repository owner (defaults to the site's organizationName)
|
|
38
|
+
*/
|
|
39
|
+
owner?: string;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* GitHub repository name (defaults to the site's projectName)
|
|
43
|
+
*/
|
|
44
|
+
repo?: string;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Label to filter status issues (defaults to 'status')
|
|
48
|
+
*/
|
|
49
|
+
statusLabel?: string;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Labels that identify different systems/processes to track
|
|
53
|
+
*/
|
|
54
|
+
systemLabels?: string[];
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* GitHub personal access token for API requests
|
|
58
|
+
* Should be stored in environment variable
|
|
59
|
+
*/
|
|
60
|
+
token?: string;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* How often to update status (in minutes, defaults to 60)
|
|
64
|
+
*/
|
|
65
|
+
updateInterval?: number;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Path where status data is stored (defaults to 'status-data')
|
|
69
|
+
*/
|
|
70
|
+
dataPath?: string;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Title for the status page
|
|
74
|
+
*/
|
|
75
|
+
title?: string;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Description for the status page
|
|
79
|
+
*/
|
|
80
|
+
description?: string;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Whether to show response times
|
|
84
|
+
*/
|
|
85
|
+
showResponseTimes?: boolean;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Whether to show uptime percentages
|
|
89
|
+
*/
|
|
90
|
+
showUptime?: boolean;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
declare module '@theme/StatusBoard' {
|
|
95
|
+
import type {StatusItem} from 'docusaurus-plugin-stentorosaur';
|
|
96
|
+
|
|
97
|
+
export interface Props {
|
|
98
|
+
items: StatusItem[];
|
|
99
|
+
title?: string;
|
|
100
|
+
description?: string;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export default function StatusBoard(props: Props): JSX.Element;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
declare module '@theme/StatusItem' {
|
|
107
|
+
import type {StatusItem} from 'docusaurus-plugin-stentorosaur';
|
|
108
|
+
|
|
109
|
+
export interface Props {
|
|
110
|
+
item: StatusItem;
|
|
111
|
+
showResponseTime?: boolean;
|
|
112
|
+
showUptime?: boolean;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export default function StatusItem(props: Props): JSX.Element;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
declare module '@theme/IncidentHistory' {
|
|
119
|
+
import type {StatusIncident} from 'docusaurus-plugin-stentorosaur';
|
|
120
|
+
|
|
121
|
+
export interface Props {
|
|
122
|
+
incidents: StatusIncident[];
|
|
123
|
+
maxItems?: number;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export default function IncidentHistory(props: Props): JSX.Element;
|
|
127
|
+
}
|