@checkmate-monitor/maintenance-common 0.1.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/CHANGELOG.md +38 -0
- package/package.json +27 -0
- package/src/index.ts +47 -0
- package/src/permissions.ts +19 -0
- package/src/plugin-metadata.ts +9 -0
- package/src/routes.ts +31 -0
- package/src/rpc-contract.ts +110 -0
- package/src/schemas.ts +96 -0
- package/src/slots.ts +18 -0
- package/tsconfig.json +6 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# @checkmate-monitor/maintenance-common
|
|
2
|
+
|
|
3
|
+
## 0.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- eff5b4e: Add standalone maintenance scheduling plugin
|
|
8
|
+
|
|
9
|
+
- New `@checkmate-monitor/maintenance-common` package with Zod schemas, permissions, oRPC contract, and extension slots
|
|
10
|
+
- New `@checkmate-monitor/maintenance-backend` package with Drizzle schema, service, and oRPC router
|
|
11
|
+
- New `@checkmate-monitor/maintenance-frontend` package with admin page and system detail panel
|
|
12
|
+
- Shared `DateTimePicker` component added to `@checkmate-monitor/ui`
|
|
13
|
+
- Database migrations for maintenances, maintenance_systems, and maintenance_updates tables
|
|
14
|
+
|
|
15
|
+
- 4dd644d: Enable external application (API key) access to management endpoints
|
|
16
|
+
|
|
17
|
+
Changed `userType: "user"` to `userType: "authenticated"` for 52 endpoints across 5 packages, allowing external applications (service accounts with API keys) to call these endpoints programmatically while maintaining RBAC permission checks:
|
|
18
|
+
|
|
19
|
+
- **incident-common**: createIncident, updateIncident, addUpdate, resolveIncident, deleteIncident
|
|
20
|
+
- **maintenance-common**: createMaintenance, updateMaintenance, addUpdate, closeMaintenance, deleteMaintenance
|
|
21
|
+
- **catalog-common**: System CRUD, Group CRUD, addSystemToGroup, removeSystemFromGroup
|
|
22
|
+
- **healthcheck-common**: Configuration management, system associations, retention config, detailed history
|
|
23
|
+
- **integration-common**: Subscription management, connection management, event discovery, delivery logs
|
|
24
|
+
|
|
25
|
+
This enables automation use cases such as:
|
|
26
|
+
|
|
27
|
+
- Creating incidents from external monitoring systems (Prometheus, Grafana)
|
|
28
|
+
- Scheduling maintenances from CI/CD pipelines
|
|
29
|
+
- Managing catalog systems from infrastructure-as-code tools
|
|
30
|
+
- Configuring health checks from deployment scripts
|
|
31
|
+
|
|
32
|
+
### Patch Changes
|
|
33
|
+
|
|
34
|
+
- Updated dependencies [ffc28f6]
|
|
35
|
+
- Updated dependencies [b55fae6]
|
|
36
|
+
- @checkmate-monitor/common@0.1.0
|
|
37
|
+
- @checkmate-monitor/signal-common@0.1.0
|
|
38
|
+
- @checkmate-monitor/frontend-api@0.0.2
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@checkmate-monitor/maintenance-common",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"import": "./src/index.ts"
|
|
8
|
+
}
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@checkmate-monitor/common": "workspace:*",
|
|
12
|
+
"@checkmate-monitor/frontend-api": "workspace:*",
|
|
13
|
+
"@checkmate-monitor/signal-common": "workspace:*",
|
|
14
|
+
"@orpc/contract": "^1.13.2",
|
|
15
|
+
"zod": "^4.2.1"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"typescript": "^5.7.2",
|
|
19
|
+
"@checkmate-monitor/tsconfig": "workspace:*",
|
|
20
|
+
"@checkmate-monitor/scripts": "workspace:*"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"lint": "bun run lint:code",
|
|
25
|
+
"lint:code": "eslint . --max-warnings 0"
|
|
26
|
+
}
|
|
27
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export { permissions, permissionList } from "./permissions";
|
|
2
|
+
export {
|
|
3
|
+
maintenanceContract,
|
|
4
|
+
MaintenanceApi,
|
|
5
|
+
type MaintenanceContract,
|
|
6
|
+
} from "./rpc-contract";
|
|
7
|
+
export {
|
|
8
|
+
MaintenanceStatusEnum,
|
|
9
|
+
MaintenanceSchema,
|
|
10
|
+
MaintenanceWithSystemsSchema,
|
|
11
|
+
MaintenanceUpdateSchema,
|
|
12
|
+
MaintenanceDetailSchema,
|
|
13
|
+
CreateMaintenanceInputSchema,
|
|
14
|
+
UpdateMaintenanceInputSchema,
|
|
15
|
+
AddMaintenanceUpdateInputSchema,
|
|
16
|
+
type MaintenanceStatus,
|
|
17
|
+
type Maintenance,
|
|
18
|
+
type MaintenanceWithSystems,
|
|
19
|
+
type MaintenanceUpdate,
|
|
20
|
+
type MaintenanceDetail,
|
|
21
|
+
type CreateMaintenanceInput,
|
|
22
|
+
type UpdateMaintenanceInput,
|
|
23
|
+
type AddMaintenanceUpdateInput,
|
|
24
|
+
} from "./schemas";
|
|
25
|
+
export { MaintenanceDetailsSlot, MaintenanceStatusSlot } from "./slots";
|
|
26
|
+
export * from "./plugin-metadata";
|
|
27
|
+
export { maintenanceRoutes } from "./routes";
|
|
28
|
+
|
|
29
|
+
// =============================================================================
|
|
30
|
+
// REALTIME SIGNALS
|
|
31
|
+
// =============================================================================
|
|
32
|
+
|
|
33
|
+
import { createSignal } from "@checkmate-monitor/signal-common";
|
|
34
|
+
import { z } from "zod";
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Broadcast when a maintenance is created, updated, or closed.
|
|
38
|
+
* Frontend components listening to this signal can refetch state for affected systems.
|
|
39
|
+
*/
|
|
40
|
+
export const MAINTENANCE_UPDATED = createSignal(
|
|
41
|
+
"maintenance.updated",
|
|
42
|
+
z.object({
|
|
43
|
+
maintenanceId: z.string(),
|
|
44
|
+
systemIds: z.array(z.string()),
|
|
45
|
+
action: z.enum(["created", "updated", "closed"]),
|
|
46
|
+
})
|
|
47
|
+
);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { createPermission, type Permission } from "@checkmate-monitor/common";
|
|
2
|
+
|
|
3
|
+
export const permissions = {
|
|
4
|
+
/** Read access to maintenances - granted to all authenticated users by default */
|
|
5
|
+
maintenanceRead: createPermission(
|
|
6
|
+
"maintenance",
|
|
7
|
+
"read",
|
|
8
|
+
"View planned maintenances",
|
|
9
|
+
{ isAuthenticatedDefault: true, isPublicDefault: true }
|
|
10
|
+
),
|
|
11
|
+
/** Manage maintenances - create, edit, delete, and add updates */
|
|
12
|
+
maintenanceManage: createPermission(
|
|
13
|
+
"maintenance",
|
|
14
|
+
"manage",
|
|
15
|
+
"Manage planned maintenances"
|
|
16
|
+
),
|
|
17
|
+
} as const satisfies Record<string, Permission>;
|
|
18
|
+
|
|
19
|
+
export const permissionList = Object.values(permissions);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { definePluginMetadata } from "@checkmate-monitor/common";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Plugin metadata for the maintenance plugin.
|
|
5
|
+
* Exported from the common package so both backend and frontend can reference it.
|
|
6
|
+
*/
|
|
7
|
+
export const pluginMetadata = definePluginMetadata({
|
|
8
|
+
pluginId: "maintenance",
|
|
9
|
+
});
|
package/src/routes.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { createRoutes } from "@checkmate-monitor/common";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Route definitions for the maintenance plugin.
|
|
5
|
+
* Import and use these routes in both frontend plugins and for link generation.
|
|
6
|
+
*
|
|
7
|
+
* @example Frontend plugin usage
|
|
8
|
+
* ```tsx
|
|
9
|
+
* import { maintenanceRoutes } from "@checkmate-monitor/maintenance-common";
|
|
10
|
+
*
|
|
11
|
+
* createFrontendPlugin({
|
|
12
|
+
* routes: [
|
|
13
|
+
* { route: maintenanceRoutes.routes.config, element: <ConfigPage /> },
|
|
14
|
+
* ],
|
|
15
|
+
* });
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @example Link generation
|
|
19
|
+
* ```tsx
|
|
20
|
+
* import { maintenanceRoutes } from "@checkmate-monitor/maintenance-common";
|
|
21
|
+
* import { usePluginRoute } from "@checkmate-monitor/frontend-api";
|
|
22
|
+
*
|
|
23
|
+
* const getRoute = usePluginRoute();
|
|
24
|
+
* <Link to={getRoute(maintenanceRoutes.routes.config)}>Maintenances</Link>
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export const maintenanceRoutes = createRoutes("maintenance", {
|
|
28
|
+
config: "/config",
|
|
29
|
+
systemHistory: "/system/:systemId/history",
|
|
30
|
+
detail: "/:maintenanceId",
|
|
31
|
+
});
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { oc } from "@orpc/contract";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import {
|
|
4
|
+
createClientDefinition,
|
|
5
|
+
type ProcedureMetadata,
|
|
6
|
+
} from "@checkmate-monitor/common";
|
|
7
|
+
import { permissions } from "./permissions";
|
|
8
|
+
import { pluginMetadata } from "./plugin-metadata";
|
|
9
|
+
import {
|
|
10
|
+
MaintenanceWithSystemsSchema,
|
|
11
|
+
MaintenanceDetailSchema,
|
|
12
|
+
MaintenanceUpdateSchema,
|
|
13
|
+
CreateMaintenanceInputSchema,
|
|
14
|
+
UpdateMaintenanceInputSchema,
|
|
15
|
+
AddMaintenanceUpdateInputSchema,
|
|
16
|
+
MaintenanceStatusEnum,
|
|
17
|
+
} from "./schemas";
|
|
18
|
+
|
|
19
|
+
const _base = oc.$meta<ProcedureMetadata>({});
|
|
20
|
+
|
|
21
|
+
export const maintenanceContract = {
|
|
22
|
+
/** List all maintenances with optional status filter */
|
|
23
|
+
listMaintenances: _base
|
|
24
|
+
.meta({
|
|
25
|
+
userType: "public",
|
|
26
|
+
permissions: [permissions.maintenanceRead.id],
|
|
27
|
+
})
|
|
28
|
+
.input(
|
|
29
|
+
z
|
|
30
|
+
.object({
|
|
31
|
+
status: MaintenanceStatusEnum.optional(),
|
|
32
|
+
systemId: z.string().optional(),
|
|
33
|
+
})
|
|
34
|
+
.optional()
|
|
35
|
+
)
|
|
36
|
+
.output(z.array(MaintenanceWithSystemsSchema)),
|
|
37
|
+
|
|
38
|
+
/** Get a single maintenance with all details */
|
|
39
|
+
getMaintenance: _base
|
|
40
|
+
.meta({
|
|
41
|
+
userType: "public",
|
|
42
|
+
permissions: [permissions.maintenanceRead.id],
|
|
43
|
+
})
|
|
44
|
+
.input(z.object({ id: z.string() }))
|
|
45
|
+
.output(MaintenanceDetailSchema.nullable()),
|
|
46
|
+
|
|
47
|
+
/** Get active or upcoming maintenances for a specific system */
|
|
48
|
+
getMaintenancesForSystem: _base
|
|
49
|
+
.meta({
|
|
50
|
+
userType: "public",
|
|
51
|
+
permissions: [permissions.maintenanceRead.id],
|
|
52
|
+
})
|
|
53
|
+
.input(z.object({ systemId: z.string() }))
|
|
54
|
+
.output(z.array(MaintenanceWithSystemsSchema)),
|
|
55
|
+
|
|
56
|
+
/** Create a new maintenance */
|
|
57
|
+
createMaintenance: _base
|
|
58
|
+
.meta({
|
|
59
|
+
userType: "authenticated",
|
|
60
|
+
permissions: [permissions.maintenanceManage.id],
|
|
61
|
+
})
|
|
62
|
+
.input(CreateMaintenanceInputSchema)
|
|
63
|
+
.output(MaintenanceWithSystemsSchema),
|
|
64
|
+
|
|
65
|
+
/** Update an existing maintenance */
|
|
66
|
+
updateMaintenance: _base
|
|
67
|
+
.meta({
|
|
68
|
+
userType: "authenticated",
|
|
69
|
+
permissions: [permissions.maintenanceManage.id],
|
|
70
|
+
})
|
|
71
|
+
.input(UpdateMaintenanceInputSchema)
|
|
72
|
+
.output(MaintenanceWithSystemsSchema),
|
|
73
|
+
|
|
74
|
+
/** Add a status update to a maintenance */
|
|
75
|
+
addUpdate: _base
|
|
76
|
+
.meta({
|
|
77
|
+
userType: "authenticated",
|
|
78
|
+
permissions: [permissions.maintenanceManage.id],
|
|
79
|
+
})
|
|
80
|
+
.input(AddMaintenanceUpdateInputSchema)
|
|
81
|
+
.output(MaintenanceUpdateSchema),
|
|
82
|
+
|
|
83
|
+
/** Close a maintenance early (sets status to completed) */
|
|
84
|
+
closeMaintenance: _base
|
|
85
|
+
.meta({
|
|
86
|
+
userType: "authenticated",
|
|
87
|
+
permissions: [permissions.maintenanceManage.id],
|
|
88
|
+
})
|
|
89
|
+
.input(z.object({ id: z.string(), message: z.string().optional() }))
|
|
90
|
+
.output(MaintenanceWithSystemsSchema),
|
|
91
|
+
|
|
92
|
+
/** Delete a maintenance */
|
|
93
|
+
deleteMaintenance: _base
|
|
94
|
+
.meta({
|
|
95
|
+
userType: "authenticated",
|
|
96
|
+
permissions: [permissions.maintenanceManage.id],
|
|
97
|
+
})
|
|
98
|
+
.input(z.object({ id: z.string() }))
|
|
99
|
+
.output(z.object({ success: z.boolean() })),
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// Export contract type
|
|
103
|
+
export type MaintenanceContract = typeof maintenanceContract;
|
|
104
|
+
|
|
105
|
+
// Export client definition for type-safe forPlugin usage
|
|
106
|
+
// Use: const client = rpcApi.forPlugin(MaintenanceApi);
|
|
107
|
+
export const MaintenanceApi = createClientDefinition(
|
|
108
|
+
maintenanceContract,
|
|
109
|
+
pluginMetadata
|
|
110
|
+
);
|
package/src/schemas.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Maintenance status enum values
|
|
5
|
+
*/
|
|
6
|
+
export const MaintenanceStatusEnum = z.enum([
|
|
7
|
+
"scheduled",
|
|
8
|
+
"in_progress",
|
|
9
|
+
"completed",
|
|
10
|
+
"cancelled",
|
|
11
|
+
]);
|
|
12
|
+
export type MaintenanceStatus = z.infer<typeof MaintenanceStatusEnum>;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Core maintenance entity schema
|
|
16
|
+
*/
|
|
17
|
+
export const MaintenanceSchema = z.object({
|
|
18
|
+
id: z.string(),
|
|
19
|
+
title: z.string(),
|
|
20
|
+
description: z.string().optional(),
|
|
21
|
+
status: MaintenanceStatusEnum,
|
|
22
|
+
startAt: z.date(),
|
|
23
|
+
endAt: z.date(),
|
|
24
|
+
createdAt: z.date(),
|
|
25
|
+
updatedAt: z.date(),
|
|
26
|
+
});
|
|
27
|
+
export type Maintenance = z.infer<typeof MaintenanceSchema>;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Maintenance with related systems
|
|
31
|
+
*/
|
|
32
|
+
export const MaintenanceWithSystemsSchema = MaintenanceSchema.extend({
|
|
33
|
+
systemIds: z.array(z.string()),
|
|
34
|
+
});
|
|
35
|
+
export type MaintenanceWithSystems = z.infer<
|
|
36
|
+
typeof MaintenanceWithSystemsSchema
|
|
37
|
+
>;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Maintenance update schema - status updates posted to a maintenance
|
|
41
|
+
*/
|
|
42
|
+
export const MaintenanceUpdateSchema = z.object({
|
|
43
|
+
id: z.string(),
|
|
44
|
+
maintenanceId: z.string(),
|
|
45
|
+
message: z.string(),
|
|
46
|
+
statusChange: MaintenanceStatusEnum.optional(),
|
|
47
|
+
createdAt: z.date(),
|
|
48
|
+
createdBy: z.string().optional(),
|
|
49
|
+
});
|
|
50
|
+
export type MaintenanceUpdate = z.infer<typeof MaintenanceUpdateSchema>;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Full maintenance detail with systems and updates
|
|
54
|
+
*/
|
|
55
|
+
export const MaintenanceDetailSchema = MaintenanceWithSystemsSchema.extend({
|
|
56
|
+
updates: z.array(MaintenanceUpdateSchema),
|
|
57
|
+
});
|
|
58
|
+
export type MaintenanceDetail = z.infer<typeof MaintenanceDetailSchema>;
|
|
59
|
+
|
|
60
|
+
// Input schemas for mutations
|
|
61
|
+
export const CreateMaintenanceInputSchema = z
|
|
62
|
+
.object({
|
|
63
|
+
title: z.string().min(1, "Title is required"),
|
|
64
|
+
description: z.string().optional(),
|
|
65
|
+
startAt: z.date(),
|
|
66
|
+
endAt: z.date(),
|
|
67
|
+
systemIds: z.array(z.string()).min(1, "At least one system is required"),
|
|
68
|
+
})
|
|
69
|
+
.refine((data) => data.endAt > data.startAt, {
|
|
70
|
+
message: "End date must be after start date",
|
|
71
|
+
path: ["endAt"],
|
|
72
|
+
});
|
|
73
|
+
export type CreateMaintenanceInput = z.infer<
|
|
74
|
+
typeof CreateMaintenanceInputSchema
|
|
75
|
+
>;
|
|
76
|
+
|
|
77
|
+
export const UpdateMaintenanceInputSchema = z.object({
|
|
78
|
+
id: z.string(),
|
|
79
|
+
title: z.string().min(1).optional(),
|
|
80
|
+
description: z.string().nullable().optional(),
|
|
81
|
+
startAt: z.date().optional(),
|
|
82
|
+
endAt: z.date().optional(),
|
|
83
|
+
systemIds: z.array(z.string()).min(1).optional(),
|
|
84
|
+
});
|
|
85
|
+
export type UpdateMaintenanceInput = z.infer<
|
|
86
|
+
typeof UpdateMaintenanceInputSchema
|
|
87
|
+
>;
|
|
88
|
+
|
|
89
|
+
export const AddMaintenanceUpdateInputSchema = z.object({
|
|
90
|
+
maintenanceId: z.string(),
|
|
91
|
+
message: z.string().min(1, "Message is required"),
|
|
92
|
+
statusChange: MaintenanceStatusEnum.optional(),
|
|
93
|
+
});
|
|
94
|
+
export type AddMaintenanceUpdateInput = z.infer<
|
|
95
|
+
typeof AddMaintenanceUpdateInputSchema
|
|
96
|
+
>;
|
package/src/slots.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createSlot } from "@checkmate-monitor/frontend-api";
|
|
2
|
+
import type { MaintenanceWithSystems } from "./schemas";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Slot for extending maintenance detail views.
|
|
6
|
+
* Plugins can add additional content or actions to maintenance details.
|
|
7
|
+
*/
|
|
8
|
+
export const MaintenanceDetailsSlot = createSlot<{
|
|
9
|
+
maintenance: MaintenanceWithSystems;
|
|
10
|
+
}>("plugin.maintenance.details");
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Slot for adding custom status indicators to maintenances.
|
|
14
|
+
* Can be used to show external integrations, alerts, etc.
|
|
15
|
+
*/
|
|
16
|
+
export const MaintenanceStatusSlot = createSlot<{
|
|
17
|
+
maintenance: MaintenanceWithSystems;
|
|
18
|
+
}>("plugin.maintenance.status");
|