@lde/sparql-monitor 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,7 +8,85 @@ Monitor SPARQL endpoints with periodic checks, storing observations in PostgreSQ
8
8
  npm install @lde/sparql-monitor
9
9
  ```
10
10
 
11
- ## Usage
11
+ ## CLI Usage
12
+
13
+ The easiest way to use the monitor is via the CLI with a configuration file.
14
+
15
+ ### Quick Start
16
+
17
+ 1. Create a configuration file (TypeScript, JavaScript, JSON, or YAML)
18
+ 2. Run the monitor
19
+
20
+ ```bash
21
+ # Start continuous monitoring
22
+ npx sparql-monitor start
23
+
24
+ # Run a one-off check
25
+ npx sparql-monitor check
26
+
27
+ # Check a specific monitor
28
+ npx sparql-monitor check dbpedia
29
+
30
+ # Use a custom config path
31
+ npx sparql-monitor start --config ./configs/production.config.ts
32
+ ```
33
+
34
+ ### TypeScript Config (`sparql-monitor.config.ts`)
35
+
36
+ ```typescript
37
+ import { defineConfig } from '@lde/sparql-monitor';
38
+
39
+ export default defineConfig({
40
+ databaseUrl: process.env.DATABASE_URL,
41
+ intervalSeconds: 300,
42
+ monitors: [
43
+ {
44
+ identifier: 'dbpedia',
45
+ endpointUrl: new URL('https://dbpedia.org/sparql'),
46
+ query: 'ASK { ?s ?p ?o }',
47
+ },
48
+ {
49
+ identifier: 'wikidata',
50
+ endpointUrl: new URL('https://query.wikidata.org/sparql'),
51
+ query: 'SELECT * WHERE { ?s ?p ?o } LIMIT 1',
52
+ },
53
+ ],
54
+ });
55
+ ```
56
+
57
+ ### YAML Config (`sparql-monitor.config.yaml`)
58
+
59
+ ```yaml
60
+ databaseUrl: ${DATABASE_URL}
61
+ intervalSeconds: 300
62
+ monitors:
63
+ - identifier: dbpedia
64
+ endpointUrl: https://dbpedia.org/sparql
65
+ query: ASK { ?s ?p ?o }
66
+ - identifier: wikidata
67
+ endpointUrl: https://query.wikidata.org/sparql
68
+ query: SELECT * WHERE { ?s ?p ?o } LIMIT 1
69
+ ```
70
+
71
+ ### Environment Variables
72
+
73
+ Create a `.env` file for sensitive configuration:
74
+
75
+ ```
76
+ DATABASE_URL=postgres://user:pass@localhost:5432/monitoring
77
+ ```
78
+
79
+ The CLI automatically loads `.env` files.
80
+
81
+ ### Config Auto-Discovery
82
+
83
+ The CLI searches for configuration in this order:
84
+
85
+ 1. `sparql-monitor.config.{ts,mts,js,mjs,json,yaml,yml}`
86
+ 2. `.sparql-monitorrc`
87
+ 3. `package.json` → `"sparql-monitor"` key
88
+
89
+ ## Programmatic Usage
12
90
 
13
91
  ```typescript
14
92
  import {
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { loadConfig } from 'c12';
4
+ import { createRequire } from 'node:module';
5
+ import { MonitorService } from './service.js';
6
+ import { PostgresObservationStore } from './store.js';
7
+ import { normalizeConfig } from './config.js';
8
+ const require = createRequire(import.meta.url);
9
+ const { version } = require('../package.json');
10
+ async function loadMonitorContext(configFile) {
11
+ const { config: rawConfig } = await loadConfig({
12
+ name: 'sparql-monitor',
13
+ configFile,
14
+ dotenv: true,
15
+ });
16
+ if (!rawConfig) {
17
+ console.error('Error: No configuration found.');
18
+ console.error('Create a sparql-monitor.config.ts file or specify --config.');
19
+ process.exit(1);
20
+ }
21
+ const config = normalizeConfig(rawConfig);
22
+ const databaseUrl = config.databaseUrl ?? process.env.DATABASE_URL;
23
+ if (!databaseUrl) {
24
+ console.error('Error: databaseUrl required (set in config or DATABASE_URL env).');
25
+ process.exit(1);
26
+ }
27
+ if (config.monitors.length === 0) {
28
+ console.error('Error: No monitors configured.');
29
+ process.exit(1);
30
+ }
31
+ const store = await PostgresObservationStore.create(databaseUrl);
32
+ const service = new MonitorService({
33
+ store,
34
+ monitors: config.monitors,
35
+ intervalSeconds: config.intervalSeconds,
36
+ });
37
+ return {
38
+ config: { ...config, databaseUrl },
39
+ store,
40
+ service,
41
+ };
42
+ }
43
+ const program = new Command();
44
+ program
45
+ .name('sparql-monitor')
46
+ .description('Monitor SPARQL endpoints')
47
+ .version(version);
48
+ program
49
+ .command('start')
50
+ .description('Start monitoring all configured endpoints')
51
+ .option('-c, --config <path>', 'Config file path')
52
+ .action(async (options) => {
53
+ const { config, store, service } = await loadMonitorContext(options.config);
54
+ await service.checkAll();
55
+ service.start();
56
+ console.log(`Monitoring ${config.monitors.length} endpoint(s)...`);
57
+ console.log(`Interval: ${config.intervalSeconds ?? 300} seconds`);
58
+ const shutdown = async () => {
59
+ console.log('\nShutting down...');
60
+ service.stop();
61
+ await store.close();
62
+ process.exit(0);
63
+ };
64
+ process.on('SIGINT', shutdown);
65
+ process.on('SIGTERM', shutdown);
66
+ });
67
+ program
68
+ .command('check [identifier]')
69
+ .description('Run immediate check (all monitors or specific one)')
70
+ .option('-c, --config <path>', 'Config file path')
71
+ .action(async (identifier, options) => {
72
+ const { config, store, service } = await loadMonitorContext(options.config);
73
+ try {
74
+ if (identifier) {
75
+ const monitor = config.monitors.find((m) => m.identifier === identifier);
76
+ if (!monitor) {
77
+ console.error(`Error: Monitor '${identifier}' not found.`);
78
+ console.error('Available monitors:', config.monitors.map((m) => m.identifier).join(', '));
79
+ process.exit(1);
80
+ }
81
+ console.log(`Checking ${identifier}...`);
82
+ await service.checkNow(identifier);
83
+ console.log(`Check completed for ${identifier}.`);
84
+ }
85
+ else {
86
+ console.log(`Checking ${config.monitors.length} endpoint(s)...`);
87
+ await service.checkAll();
88
+ console.log('All checks completed.');
89
+ }
90
+ }
91
+ finally {
92
+ await store.close();
93
+ }
94
+ });
95
+ program.parse();
@@ -0,0 +1,54 @@
1
+ import type { MonitorConfig } from './types.js';
2
+ /**
3
+ * Raw config as loaded from file (URL can be string or URL).
4
+ */
5
+ export interface RawMonitorConfig {
6
+ /** Unique identifier for this monitor. */
7
+ identifier: string;
8
+ /** URL of the SPARQL endpoint to monitor (string or URL). */
9
+ endpointUrl: string | URL;
10
+ /** SPARQL query to execute. */
11
+ query: string;
12
+ }
13
+ /**
14
+ * Configuration for the SPARQL monitor.
15
+ */
16
+ export interface SparqlMonitorConfig {
17
+ /** PostgreSQL connection string. */
18
+ databaseUrl?: string;
19
+ /** Polling interval in seconds (default: 300). */
20
+ intervalSeconds?: number;
21
+ /** Monitor definitions. */
22
+ monitors: RawMonitorConfig[];
23
+ }
24
+ /**
25
+ * Type helper for TypeScript config files.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * // sparql-monitor.config.ts
30
+ * import { defineConfig } from '@lde/sparql-monitor';
31
+ *
32
+ * export default defineConfig({
33
+ * databaseUrl: process.env.DATABASE_URL,
34
+ * intervalSeconds: 300,
35
+ * monitors: [
36
+ * {
37
+ * identifier: 'dbpedia',
38
+ * endpointUrl: new URL('https://dbpedia.org/sparql'),
39
+ * query: 'ASK { ?s ?p ?o }',
40
+ * },
41
+ * ],
42
+ * });
43
+ * ```
44
+ */
45
+ export declare function defineConfig(config: SparqlMonitorConfig): SparqlMonitorConfig;
46
+ /**
47
+ * Normalize config (convert string URLs to URL objects).
48
+ */
49
+ export declare function normalizeConfig(raw: SparqlMonitorConfig): {
50
+ databaseUrl?: string;
51
+ intervalSeconds?: number;
52
+ monitors: MonitorConfig[];
53
+ };
54
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,WAAW,EAAE,MAAM,GAAG,GAAG,CAAC;IAC1B,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kDAAkD;IAClD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2BAA2B;IAC3B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,mBAAmB,GAAG,mBAAmB,CAE7E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,mBAAmB,GAAG;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B,CAWA"}
package/dist/config.js ADDED
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Type helper for TypeScript config files.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * // sparql-monitor.config.ts
7
+ * import { defineConfig } from '@lde/sparql-monitor';
8
+ *
9
+ * export default defineConfig({
10
+ * databaseUrl: process.env.DATABASE_URL,
11
+ * intervalSeconds: 300,
12
+ * monitors: [
13
+ * {
14
+ * identifier: 'dbpedia',
15
+ * endpointUrl: new URL('https://dbpedia.org/sparql'),
16
+ * query: 'ASK { ?s ?p ?o }',
17
+ * },
18
+ * ],
19
+ * });
20
+ * ```
21
+ */
22
+ export function defineConfig(config) {
23
+ return config;
24
+ }
25
+ /**
26
+ * Normalize config (convert string URLs to URL objects).
27
+ */
28
+ export function normalizeConfig(raw) {
29
+ return {
30
+ ...raw,
31
+ monitors: raw.monitors.map((m) => ({
32
+ ...m,
33
+ endpointUrl: typeof m.endpointUrl === 'string'
34
+ ? new URL(m.endpointUrl)
35
+ : m.endpointUrl,
36
+ })),
37
+ };
38
+ }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export type { MonitorConfig, Observation, ObservationStore } from './types.js';
2
2
  export { PostgresObservationStore } from './store.js';
3
3
  export { MonitorService, type MonitorServiceOptions } from './service.js';
4
+ export { defineConfig, type SparqlMonitorConfig } from './config.js';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export { PostgresObservationStore } from './store.js';
2
2
  export { MonitorService } from './service.js';
3
+ export { defineConfig } from './config.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lde/sparql-monitor",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "Monitor SPARQL endpoints with periodic checks",
5
5
  "repository": {
6
6
  "url": "https://github.com/ldengine/lde"
@@ -18,14 +18,19 @@
18
18
  "main": "./dist/index.js",
19
19
  "module": "./dist/index.js",
20
20
  "types": "./dist/index.d.ts",
21
+ "bin": {
22
+ "sparql-monitor": "./dist/cli.js"
23
+ },
21
24
  "files": [
22
25
  "dist",
23
26
  "!**/*.tsbuildinfo"
24
27
  ],
25
28
  "dependencies": {
29
+ "c12": "^3.0.2",
30
+ "commander": "^13.1.0",
26
31
  "cron": "^4.1.0",
27
- "drizzle-kit": "^0.30.4",
28
- "drizzle-orm": "^0.38.4",
32
+ "drizzle-kit": "^0.31.8",
33
+ "drizzle-orm": "^0.45.1",
29
34
  "fetch-sparql-endpoint": "^6.0.0",
30
35
  "postgres": "^3.4.5",
31
36
  "tslib": "^2.3.0"