@uptimizr/collector-server 1.0.1 → 1.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/README.md +18 -3
- package/dist/cli.js +36 -33
- package/dist/cli.js.map +1 -1
- package/dist/cliStore.d.ts +45 -0
- package/dist/cliStore.d.ts.map +1 -0
- package/dist/cliStore.js +123 -0
- package/dist/cliStore.js.map +1 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -12,8 +12,9 @@ database (the OSS default store is a single DuckDB file). The store is
|
|
|
12
12
|
created and migrated automatically.
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
|
-
# 1. One-time setup: generates a visitor-hash secret, creates
|
|
16
|
-
# mints a first project + API key, and writes a
|
|
15
|
+
# 1. One-time setup: generates a visitor-hash secret, creates + migrates the
|
|
16
|
+
# store (DuckDB by default), mints a first project + API key, and writes a
|
|
17
|
+
# local .env.
|
|
17
18
|
npx -p @uptimizr/collector-server uptimizr init "My Project"
|
|
18
19
|
|
|
19
20
|
# 2. Start the ingestion + query API (reads the generated .env; 0.0.0.0:4318).
|
|
@@ -26,6 +27,20 @@ and this server's URL (the **`endpoint`**) to your client SDK (e.g.
|
|
|
26
27
|
dashboard. Mint more projects later with
|
|
27
28
|
`npx -p @uptimizr/collector-server uptimizr new-project "<name>"`.
|
|
28
29
|
|
|
30
|
+
`init`, `new-project` and `migrate` target the store selected by
|
|
31
|
+
`COLLECTOR_STORE`, read through the same connection variables `serve` uses — so
|
|
32
|
+
to self-host on Postgres, SQL Server or ClickHouse instead of DuckDB, export the
|
|
33
|
+
store and its connection settings before running them (see
|
|
34
|
+
[Configuration](#configuration)), or let `npm create uptimizr@latest -- --store <s>`
|
|
35
|
+
generate the `.env` for you:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
export COLLECTOR_STORE=postgres
|
|
39
|
+
export POSTGRES_URL=postgresql://uptimizr:uptimizr@localhost:5432/uptimizr
|
|
40
|
+
npx -p @uptimizr/collector-server uptimizr init "My Project" # schema + first project live in Postgres
|
|
41
|
+
npx -p @uptimizr/collector-server uptimizr serve
|
|
42
|
+
```
|
|
43
|
+
|
|
29
44
|
### All-in-one: serve the dashboard too
|
|
30
45
|
|
|
31
46
|
The collector can also serve a pre-built static dashboard from its own origin, so
|
|
@@ -72,7 +87,7 @@ file; back up by copying the file).
|
|
|
72
87
|
|
|
73
88
|
> Installing as a dependency instead of via `npx`? `npm install @uptimizr/collector-server`
|
|
74
89
|
> exposes the `uptimizr` CLI (`init` / `serve` / `new-project` / `migrate`) plus
|
|
75
|
-
> the legacy `uptimizr-collector` bin; `@uptimizr/db` exposes
|
|
90
|
+
> the legacy `uptimizr-collector` bin; `@uptimizr/db` exposes the DuckDB-only
|
|
76
91
|
> `uptimizr-db-new-project` / `uptimizr-db-migrate`.
|
|
77
92
|
|
|
78
93
|
## Endpoints
|
package/dist/cli.js
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { randomBytes } from "node:crypto";
|
|
3
|
-
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { appendFileSync, existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { resolve } from "node:path";
|
|
5
|
-
import {
|
|
5
|
+
import { openCliStore, renderEnv, resolveCliStoreKind } from "./cliStore.js";
|
|
6
6
|
/**
|
|
7
7
|
* Unified `uptimizr` CLI (ADR 0029) — collapses the multi-step npm self-host
|
|
8
8
|
* (`export VISITOR_HASH_SECRET` → `uptimizr-db-new-project` → `uptimizr-collector`)
|
|
9
9
|
* into `uptimizr init && uptimizr serve`.
|
|
10
10
|
*
|
|
11
11
|
* Subcommands:
|
|
12
|
-
* - `init` — generate a visitor-hash secret, create the
|
|
12
|
+
* - `init` — generate a visitor-hash secret, create + migrate the
|
|
13
13
|
* store, mint a first project + API key, and write `.env`.
|
|
14
14
|
* - `serve` (default) — run the ingestion + query API (see {@link serve}).
|
|
15
15
|
* - `new-project <name>` — mint an additional project + API key.
|
|
16
|
-
* - `migrate` — apply
|
|
16
|
+
* - `migrate` — apply store migrations.
|
|
17
17
|
*
|
|
18
|
-
*
|
|
18
|
+
* Every command targets the store selected by `COLLECTOR_STORE` — the OSS
|
|
19
|
+
* DuckDB default (no Docker, no external database; ADR 0020), or the optional
|
|
20
|
+
* `postgres` / `mssql` / `clickhouse` stores — read through the same connection
|
|
21
|
+
* variables `serve` uses, so the project minted by `init` is the one the running
|
|
22
|
+
* collector resolves.
|
|
19
23
|
*/
|
|
20
24
|
const ENV_FILE = resolve(process.cwd(), ".env");
|
|
21
25
|
/** Load a local `.env` (Node 22 built-in) so `serve`/`migrate` see config without a wrapper. */
|
|
@@ -31,31 +35,26 @@ function nameArg(args) {
|
|
|
31
35
|
.join(" ")
|
|
32
36
|
.trim();
|
|
33
37
|
}
|
|
34
|
-
function renderEnv(secret) {
|
|
35
|
-
return `${[
|
|
36
|
-
"# Uptimizr collector configuration (generated by 'uptimizr init').",
|
|
37
|
-
"# OSS default store is DuckDB — no Docker, no external database.",
|
|
38
|
-
"",
|
|
39
|
-
`VISITOR_HASH_SECRET=${secret}`,
|
|
40
|
-
"COLLECTOR_STORE=duckdb",
|
|
41
|
-
"DUCKDB_PATH=./data/uptimizr.duckdb",
|
|
42
|
-
"COLLECTOR_PORT=4318",
|
|
43
|
-
].join("\n")}\n`;
|
|
44
|
-
}
|
|
45
38
|
/** Persist a generated secret so `serve` works on the next run. */
|
|
46
|
-
function ensureSecretPersisted(secret, generated) {
|
|
47
|
-
|
|
48
|
-
|
|
39
|
+
function ensureSecretPersisted(secret, generated, store) {
|
|
40
|
+
try {
|
|
41
|
+
// `wx` creates the file only when it does not exist yet, so there is no
|
|
42
|
+
// exists-then-write window in which another process could create it.
|
|
43
|
+
writeFileSync(ENV_FILE, renderEnv(secret, store), { flag: "wx" });
|
|
49
44
|
console.error(`✓ wrote ${ENV_FILE}`);
|
|
50
45
|
return;
|
|
51
46
|
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
if (err.code !== "EEXIST")
|
|
49
|
+
throw err;
|
|
50
|
+
}
|
|
52
51
|
if (!generated)
|
|
53
52
|
return;
|
|
54
53
|
const content = readFileSync(ENV_FILE, "utf8");
|
|
55
54
|
if (/^VISITOR_HASH_SECRET=/m.test(content))
|
|
56
55
|
return;
|
|
57
56
|
const sep = content.length === 0 || content.endsWith("\n") ? "" : "\n";
|
|
58
|
-
|
|
57
|
+
appendFileSync(ENV_FILE, `${sep}VISITOR_HASH_SECRET=${secret}\n`);
|
|
59
58
|
console.error(`✓ added VISITOR_HASH_SECRET to ${ENV_FILE}`);
|
|
60
59
|
}
|
|
61
60
|
async function cmdInit(name) {
|
|
@@ -66,14 +65,15 @@ async function cmdInit(name) {
|
|
|
66
65
|
secret = randomBytes(32).toString("hex");
|
|
67
66
|
process.env.VISITOR_HASH_SECRET = secret;
|
|
68
67
|
}
|
|
69
|
-
const
|
|
70
|
-
await
|
|
71
|
-
const project = await
|
|
72
|
-
const { key } = await
|
|
68
|
+
const store = resolveCliStoreKind();
|
|
69
|
+
const db = await openCliStore();
|
|
70
|
+
const project = await db.createProject(name);
|
|
71
|
+
const { key } = await db.createApiKey(project.id);
|
|
73
72
|
await db.close();
|
|
74
|
-
ensureSecretPersisted(secret, generated);
|
|
73
|
+
ensureSecretPersisted(secret, generated, store);
|
|
75
74
|
const port = Number(process.env.COLLECTOR_PORT ?? 4318);
|
|
76
75
|
console.error("\n✓ Uptimizr is ready.");
|
|
76
|
+
console.error(` Store: ${store}`);
|
|
77
77
|
console.error(` Project: ${project.id} (${project.name})`);
|
|
78
78
|
console.error(` API key: ${key} (shown once — put it in your app config)`);
|
|
79
79
|
console.error(` Endpoint: http://localhost:${port}/api/v1`);
|
|
@@ -81,10 +81,9 @@ async function cmdInit(name) {
|
|
|
81
81
|
}
|
|
82
82
|
async function cmdNewProject(name) {
|
|
83
83
|
loadLocalEnv();
|
|
84
|
-
const db = await
|
|
85
|
-
await
|
|
86
|
-
const
|
|
87
|
-
const { key } = await duckdbCreateApiKey(db, project.id);
|
|
84
|
+
const db = await openCliStore();
|
|
85
|
+
const project = await db.createProject(name);
|
|
86
|
+
const { key } = await db.createApiKey(project.id);
|
|
88
87
|
await db.close();
|
|
89
88
|
console.error(`✓ project created: ${project.id} (${project.name})`);
|
|
90
89
|
console.error(` API key (shown once): ${key}`);
|
|
@@ -92,14 +91,14 @@ async function cmdNewProject(name) {
|
|
|
92
91
|
}
|
|
93
92
|
async function cmdMigrate() {
|
|
94
93
|
loadLocalEnv();
|
|
95
|
-
|
|
96
|
-
await
|
|
94
|
+
// Opening the store applies its migrations, exactly as `serve` does on boot.
|
|
95
|
+
const db = await openCliStore();
|
|
97
96
|
await db.close();
|
|
98
|
-
console.error(
|
|
97
|
+
console.error(`✓ migrations applied (${resolveCliStoreKind()})`);
|
|
99
98
|
}
|
|
100
99
|
function printUsage() {
|
|
101
100
|
console.error([
|
|
102
|
-
"uptimizr — self-host the OSS 3D-analytics collector (DuckDB, no Docker).",
|
|
101
|
+
"uptimizr — self-host the OSS 3D-analytics collector (DuckDB by default, no Docker).",
|
|
103
102
|
"",
|
|
104
103
|
"Usage:",
|
|
105
104
|
" uptimizr init [name] generate a secret, create the store, mint a project + key, write .env",
|
|
@@ -108,6 +107,10 @@ function printUsage() {
|
|
|
108
107
|
" uptimizr migrate apply store migrations",
|
|
109
108
|
" uptimizr help show this help",
|
|
110
109
|
"",
|
|
110
|
+
"Every command targets the store selected by COLLECTOR_STORE (duckdb | postgres | mssql |",
|
|
111
|
+
"clickhouse), using the same connection variables as `serve` (DUCKDB_PATH, POSTGRES_URL,",
|
|
112
|
+
"MSSQL_URL, CLICKHOUSE_*). Unset = duckdb.",
|
|
113
|
+
"",
|
|
111
114
|
"Quick start: uptimizr init && uptimizr serve",
|
|
112
115
|
].join("\n"));
|
|
113
116
|
}
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The persistent stores the `uptimizr` CLI can bootstrap (`init` / `new-project`
|
|
3
|
+
* / `migrate`). Mirrors the `COLLECTOR_STORE` values `serve` accepts, minus
|
|
4
|
+
* `memory`, which keeps nothing between processes and so has nothing to
|
|
5
|
+
* initialise.
|
|
6
|
+
*/
|
|
7
|
+
export declare const CLI_STORES: readonly ["duckdb", "postgres", "mssql", "clickhouse"];
|
|
8
|
+
export type CliStoreKind = (typeof CLI_STORES)[number];
|
|
9
|
+
/**
|
|
10
|
+
* The slice of a store the CLI needs: mint projects and API keys against an
|
|
11
|
+
* already-migrated store, then release the connection. Each engine's
|
|
12
|
+
* `createProject` / `createApiKey` live in its own package; this narrows them
|
|
13
|
+
* to one engine-neutral shape so the commands stay store-agnostic.
|
|
14
|
+
*/
|
|
15
|
+
export interface CliStore {
|
|
16
|
+
createProject(name: string): Promise<{
|
|
17
|
+
id: string;
|
|
18
|
+
name: string;
|
|
19
|
+
}>;
|
|
20
|
+
/** Issue a query-capable API key; the plaintext is returned exactly once. */
|
|
21
|
+
createApiKey(projectId: string): Promise<{
|
|
22
|
+
key: string;
|
|
23
|
+
}>;
|
|
24
|
+
close(): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Normalise `COLLECTOR_STORE` for the CLI: unset (or blank) selects the OSS
|
|
28
|
+
* DuckDB default; `memory` and unknown values throw with an actionable message
|
|
29
|
+
* rather than silently bootstrapping the wrong store.
|
|
30
|
+
*/
|
|
31
|
+
export declare function resolveCliStoreKind(env?: NodeJS.ProcessEnv): CliStoreKind;
|
|
32
|
+
/**
|
|
33
|
+
* The `.env` `uptimizr init` writes when none exists: the secret, the selected
|
|
34
|
+
* store, and whichever of that store's connection variables were set.
|
|
35
|
+
*/
|
|
36
|
+
export declare function renderEnv(secret: string, store: CliStoreKind, env?: NodeJS.ProcessEnv): string;
|
|
37
|
+
/**
|
|
38
|
+
* Open the store selected by `COLLECTOR_STORE` and apply its migrations, the
|
|
39
|
+
* same way `serve` does on boot, then hand back the metadata helpers the CLI
|
|
40
|
+
* commands need. Connection settings come from the same env variables as
|
|
41
|
+
* `serve` (`DUCKDB_PATH`, `POSTGRES_URL`, `MSSQL_URL`, `CLICKHOUSE_*`, …), so a
|
|
42
|
+
* project minted here is the one the running collector will resolve.
|
|
43
|
+
*/
|
|
44
|
+
export declare function openCliStore(env?: NodeJS.ProcessEnv): Promise<CliStore>;
|
|
45
|
+
//# sourceMappingURL=cliStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cliStore.d.ts","sourceRoot":"","sources":["../src/cliStore.ts"],"names":[],"mappings":"AA4BA;;;;;GAKG;AACH,eAAO,MAAM,UAAU,wDAAyD,CAAC;AAEjF,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACvB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnE,6EAA6E;IAC7E,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,YAAY,CAUtF;AAuBD;;;GAGG;AACH,wBAAgB,SAAS,CACvB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,EACnB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAmBR;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,QAAQ,CAAC,CA4C1F"}
|
package/dist/cliStore.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { createDuckdbClient, duckdbCreateApiKey, duckdbCreateProject, migrateDuckdb, readDbSettings, } from "@uptimizr/db";
|
|
2
|
+
import { createApiKey as chCreateApiKey, createClickhouseClient, createProject as chCreateProject, migrateClickhouse, } from "@uptimizr/db-clickhouse";
|
|
3
|
+
import { createApiKey as msCreateApiKey, createMssqlClient, createProject as msCreateProject, ensureMssqlDatabase, migrateMssql, resolveMssqlConfig, } from "@uptimizr/db-mssql";
|
|
4
|
+
import { createApiKey as pgCreateApiKey, createPostgresClient, createProject as pgCreateProject, migratePostgres, } from "@uptimizr/db-postgres";
|
|
5
|
+
/**
|
|
6
|
+
* The persistent stores the `uptimizr` CLI can bootstrap (`init` / `new-project`
|
|
7
|
+
* / `migrate`). Mirrors the `COLLECTOR_STORE` values `serve` accepts, minus
|
|
8
|
+
* `memory`, which keeps nothing between processes and so has nothing to
|
|
9
|
+
* initialise.
|
|
10
|
+
*/
|
|
11
|
+
export const CLI_STORES = ["duckdb", "postgres", "mssql", "clickhouse"];
|
|
12
|
+
/**
|
|
13
|
+
* Normalise `COLLECTOR_STORE` for the CLI: unset (or blank) selects the OSS
|
|
14
|
+
* DuckDB default; `memory` and unknown values throw with an actionable message
|
|
15
|
+
* rather than silently bootstrapping the wrong store.
|
|
16
|
+
*/
|
|
17
|
+
export function resolveCliStoreKind(env = process.env) {
|
|
18
|
+
const value = env.COLLECTOR_STORE?.trim() || "duckdb";
|
|
19
|
+
if (CLI_STORES.includes(value))
|
|
20
|
+
return value;
|
|
21
|
+
if (value === "memory") {
|
|
22
|
+
throw new Error("COLLECTOR_STORE=memory keeps nothing between runs, so there is no store to initialise. " +
|
|
23
|
+
"Seed its project and key with COLLECTOR_MEMORY_PROJECT_ID / COLLECTOR_MEMORY_API_KEY instead.");
|
|
24
|
+
}
|
|
25
|
+
throw new Error(`Unknown COLLECTOR_STORE "${value}". Expected one of: ${CLI_STORES.join(", ")}.`);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Connection variables `init` copies from the environment into a fresh `.env`
|
|
29
|
+
* (when set), so the store it bootstrapped is the one `serve` opens next run.
|
|
30
|
+
*/
|
|
31
|
+
const STORE_ENV_KEYS = {
|
|
32
|
+
duckdb: ["DUCKDB_PATH"],
|
|
33
|
+
postgres: ["POSTGRES_URL", "DATABASE_URL", "POSTGRES_SCHEMA", "POSTGRES_POOL_MAX"],
|
|
34
|
+
mssql: [
|
|
35
|
+
"MSSQL_URL",
|
|
36
|
+
"MSSQL_SERVER",
|
|
37
|
+
"MSSQL_PORT",
|
|
38
|
+
"MSSQL_DATABASE",
|
|
39
|
+
"MSSQL_USER",
|
|
40
|
+
"MSSQL_PASSWORD",
|
|
41
|
+
"MSSQL_ENCRYPT",
|
|
42
|
+
"MSSQL_TRUST_SERVER_CERTIFICATE",
|
|
43
|
+
"MSSQL_POOL_MAX",
|
|
44
|
+
],
|
|
45
|
+
clickhouse: ["CLICKHOUSE_URL", "CLICKHOUSE_DATABASE", "CLICKHOUSE_USER", "CLICKHOUSE_PASSWORD"],
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* The `.env` `uptimizr init` writes when none exists: the secret, the selected
|
|
49
|
+
* store, and whichever of that store's connection variables were set.
|
|
50
|
+
*/
|
|
51
|
+
export function renderEnv(secret, store, env = process.env) {
|
|
52
|
+
const lines = [
|
|
53
|
+
"# Uptimizr collector configuration (generated by 'uptimizr init').",
|
|
54
|
+
store === "duckdb"
|
|
55
|
+
? "# OSS default store is DuckDB — no Docker, no external database."
|
|
56
|
+
: `# Store: ${store} — connection settings captured when 'uptimizr init' ran.`,
|
|
57
|
+
"",
|
|
58
|
+
`VISITOR_HASH_SECRET=${secret}`,
|
|
59
|
+
`COLLECTOR_STORE=${store}`,
|
|
60
|
+
];
|
|
61
|
+
for (const key of STORE_ENV_KEYS[store]) {
|
|
62
|
+
const value = env[key];
|
|
63
|
+
if (value !== undefined)
|
|
64
|
+
lines.push(`${key}=${value}`);
|
|
65
|
+
}
|
|
66
|
+
if (store === "duckdb" && env.DUCKDB_PATH === undefined) {
|
|
67
|
+
lines.push("DUCKDB_PATH=./data/uptimizr.duckdb");
|
|
68
|
+
}
|
|
69
|
+
lines.push(`COLLECTOR_PORT=${env.COLLECTOR_PORT ?? 4318}`);
|
|
70
|
+
return `${lines.join("\n")}\n`;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Open the store selected by `COLLECTOR_STORE` and apply its migrations, the
|
|
74
|
+
* same way `serve` does on boot, then hand back the metadata helpers the CLI
|
|
75
|
+
* commands need. Connection settings come from the same env variables as
|
|
76
|
+
* `serve` (`DUCKDB_PATH`, `POSTGRES_URL`, `MSSQL_URL`, `CLICKHOUSE_*`, …), so a
|
|
77
|
+
* project minted here is the one the running collector will resolve.
|
|
78
|
+
*/
|
|
79
|
+
export async function openCliStore(env = process.env) {
|
|
80
|
+
const kind = resolveCliStoreKind(env);
|
|
81
|
+
const settings = readDbSettings(env);
|
|
82
|
+
switch (kind) {
|
|
83
|
+
case "duckdb": {
|
|
84
|
+
const db = await createDuckdbClient(settings.duckdb.path);
|
|
85
|
+
await migrateDuckdb(db);
|
|
86
|
+
return {
|
|
87
|
+
createProject: (name) => duckdbCreateProject(db, name),
|
|
88
|
+
createApiKey: (projectId) => duckdbCreateApiKey(db, projectId),
|
|
89
|
+
close: () => db.close(),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
case "postgres": {
|
|
93
|
+
const pgc = createPostgresClient(settings.postgres);
|
|
94
|
+
await migratePostgres(pgc, settings.postgres);
|
|
95
|
+
return {
|
|
96
|
+
createProject: (name) => pgCreateProject(pgc, name),
|
|
97
|
+
createApiKey: (projectId) => pgCreateApiKey(pgc, projectId),
|
|
98
|
+
close: () => pgc.close(),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
case "mssql": {
|
|
102
|
+
const database = resolveMssqlConfig(settings.mssql).database ?? settings.mssql.database;
|
|
103
|
+
await ensureMssqlDatabase(settings.mssql, database);
|
|
104
|
+
const msc = createMssqlClient(settings.mssql);
|
|
105
|
+
await migrateMssql(msc);
|
|
106
|
+
return {
|
|
107
|
+
createProject: (name) => msCreateProject(msc, name),
|
|
108
|
+
createApiKey: (projectId) => msCreateApiKey(msc, projectId),
|
|
109
|
+
close: () => msc.close(),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
case "clickhouse": {
|
|
113
|
+
const ch = createClickhouseClient(settings.clickhouse);
|
|
114
|
+
await migrateClickhouse(ch, settings.clickhouse);
|
|
115
|
+
return {
|
|
116
|
+
createProject: (name) => chCreateProject(ch, name),
|
|
117
|
+
createApiKey: (projectId) => chCreateApiKey(ch, projectId),
|
|
118
|
+
close: () => ch.close(),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=cliStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cliStore.js","sourceRoot":"","sources":["../src/cliStore.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uptimizr/collector-server",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Uptimizr ingestion + query API (Fastify). Self-hostable collector for the OSS data-collector.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"uptimizr",
|
|
@@ -42,17 +42,17 @@
|
|
|
42
42
|
"@fastify/helmet": "^13.1.1",
|
|
43
43
|
"@fastify/rate-limit": "^11.2.0",
|
|
44
44
|
"@fastify/static": "^10.1.3",
|
|
45
|
-
"fastify": "^5.12.
|
|
45
|
+
"fastify": "^5.12.3",
|
|
46
46
|
"fastify-type-provider-zod": "^7.0.0",
|
|
47
47
|
"zod": "^4.5.4",
|
|
48
48
|
"@uptimizr/db": "1.0.1",
|
|
49
|
-
"@uptimizr/db-clickhouse": "1.0.1",
|
|
50
49
|
"@uptimizr/db-mssql": "1.0.1",
|
|
51
50
|
"@uptimizr/db-postgres": "1.0.1",
|
|
51
|
+
"@uptimizr/db-clickhouse": "1.0.1",
|
|
52
52
|
"@uptimizr/schema": "1.0.0"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@types/node": "^26.4.
|
|
55
|
+
"@types/node": "^26.4.1",
|
|
56
56
|
"tsx": "^4.23.13",
|
|
57
57
|
"vitest": "^4.1.11"
|
|
58
58
|
},
|