@wizeworks/lens-cloud 0.0.0-stage → 0.3.0-alpha.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/LICENSE +21 -0
- package/README.md +63 -2
- package/dist/alerts/evaluate.d.ts +10 -0
- package/dist/alerts/evaluate.d.ts.map +1 -0
- package/dist/alerts/evaluate.js +66 -0
- package/dist/alerts/evaluate.js.map +1 -0
- package/dist/alerts/notify.d.ts +17 -0
- package/dist/alerts/notify.d.ts.map +1 -0
- package/dist/alerts/notify.js +46 -0
- package/dist/alerts/notify.js.map +1 -0
- package/dist/app.d.ts +18 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +2 -0
- package/dist/app.js.map +1 -0
- package/dist/auth/crypto.d.ts +19 -0
- package/dist/auth/crypto.d.ts.map +1 -0
- package/dist/auth/crypto.js +33 -0
- package/dist/auth/crypto.js.map +1 -0
- package/dist/auth/principal.d.ts +33 -0
- package/dist/auth/principal.d.ts.map +1 -0
- package/dist/auth/principal.js +64 -0
- package/dist/auth/principal.js.map +1 -0
- package/dist/auth/roles.d.ts +10 -0
- package/dist/auth/roles.d.ts.map +1 -0
- package/dist/auth/roles.js +9 -0
- package/dist/auth/roles.js.map +1 -0
- package/dist/cli-args.d.ts +5 -0
- package/dist/cli-args.d.ts.map +1 -0
- package/dist/cli-args.js +45 -0
- package/dist/cli-args.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +28 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +33 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +20 -0
- package/dist/config.js.map +1 -0
- package/dist/db/db.d.ts +19 -0
- package/dist/db/db.d.ts.map +1 -0
- package/dist/db/db.js +57 -0
- package/dist/db/db.js.map +1 -0
- package/dist/db/migrate.d.ts +6 -0
- package/dist/db/migrate.d.ts.map +1 -0
- package/dist/db/migrate.js +25 -0
- package/dist/db/migrate.js.map +1 -0
- package/dist/db/schema.d.ts +3 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +200 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/http/http.d.ts +17 -0
- package/dist/http/http.d.ts.map +1 -0
- package/dist/http/http.js +62 -0
- package/dist/http/http.js.map +1 -0
- package/dist/http/limiter.d.ts +11 -0
- package/dist/http/limiter.d.ts.map +1 -0
- package/dist/http/limiter.js +31 -0
- package/dist/http/limiter.js.map +1 -0
- package/dist/http/router.d.ts +21 -0
- package/dist/http/router.d.ts.map +1 -0
- package/dist/http/router.js +28 -0
- package/dist/http/router.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/jobs.d.ts +4 -0
- package/dist/jobs.d.ts.map +1 -0
- package/dist/jobs.js +42 -0
- package/dist/jobs.js.map +1 -0
- package/dist/repo/alerts.d.ts +48 -0
- package/dist/repo/alerts.d.ts.map +1 -0
- package/dist/repo/alerts.js +38 -0
- package/dist/repo/alerts.js.map +1 -0
- package/dist/repo/audit.d.ts +11 -0
- package/dist/repo/audit.d.ts.map +1 -0
- package/dist/repo/audit.js +17 -0
- package/dist/repo/audit.js.map +1 -0
- package/dist/repo/metric-read.d.ts +12 -0
- package/dist/repo/metric-read.d.ts.map +1 -0
- package/dist/repo/metric-read.js +11 -0
- package/dist/repo/metric-read.js.map +1 -0
- package/dist/repo/metric-write.d.ts +9 -0
- package/dist/repo/metric-write.d.ts.map +1 -0
- package/dist/repo/metric-write.js +53 -0
- package/dist/repo/metric-write.js.map +1 -0
- package/dist/repo/orgs.d.ts +47 -0
- package/dist/repo/orgs.d.ts.map +1 -0
- package/dist/repo/orgs.js +75 -0
- package/dist/repo/orgs.js.map +1 -0
- package/dist/repo/projects.d.ts +37 -0
- package/dist/repo/projects.d.ts.map +1 -0
- package/dist/repo/projects.js +57 -0
- package/dist/repo/projects.js.map +1 -0
- package/dist/repo/trace-read.d.ts +28 -0
- package/dist/repo/trace-read.d.ts.map +1 -0
- package/dist/repo/trace-read.js +76 -0
- package/dist/repo/trace-read.js.map +1 -0
- package/dist/repo/trace-write.d.ts +9 -0
- package/dist/repo/trace-write.d.ts.map +1 -0
- package/dist/repo/trace-write.js +82 -0
- package/dist/repo/trace-write.js.map +1 -0
- package/dist/repo/users.d.ts +24 -0
- package/dist/repo/users.d.ts.map +1 -0
- package/dist/repo/users.js +65 -0
- package/dist/repo/users.js.map +1 -0
- package/dist/routes/alerts.d.ts +4 -0
- package/dist/routes/alerts.d.ts.map +1 -0
- package/dist/routes/alerts.js +99 -0
- package/dist/routes/alerts.js.map +1 -0
- package/dist/routes/auth.d.ts +4 -0
- package/dist/routes/auth.d.ts.map +1 -0
- package/dist/routes/auth.js +106 -0
- package/dist/routes/auth.js.map +1 -0
- package/dist/routes/data.d.ts +7 -0
- package/dist/routes/data.d.ts.map +1 -0
- package/dist/routes/data.js +74 -0
- package/dist/routes/data.js.map +1 -0
- package/dist/routes/index.d.ts +5 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +23 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/ingest.d.ts +8 -0
- package/dist/routes/ingest.d.ts.map +1 -0
- package/dist/routes/ingest.js +38 -0
- package/dist/routes/ingest.js.map +1 -0
- package/dist/routes/mcp.d.ts +4 -0
- package/dist/routes/mcp.d.ts.map +1 -0
- package/dist/routes/mcp.js +52 -0
- package/dist/routes/mcp.js.map +1 -0
- package/dist/routes/metrics.d.ts +13 -0
- package/dist/routes/metrics.d.ts.map +1 -0
- package/dist/routes/metrics.js +29 -0
- package/dist/routes/metrics.js.map +1 -0
- package/dist/routes/models.d.ts +4 -0
- package/dist/routes/models.d.ts.map +1 -0
- package/dist/routes/models.js +71 -0
- package/dist/routes/models.js.map +1 -0
- package/dist/routes/orgs.d.ts +4 -0
- package/dist/routes/orgs.d.ts.map +1 -0
- package/dist/routes/orgs.js +96 -0
- package/dist/routes/orgs.js.map +1 -0
- package/dist/routes/projects.d.ts +4 -0
- package/dist/routes/projects.d.ts.map +1 -0
- package/dist/routes/projects.js +54 -0
- package/dist/routes/projects.js.map +1 -0
- package/dist/routes/shares.d.ts +11 -0
- package/dist/routes/shares.d.ts.map +1 -0
- package/dist/routes/shares.js +61 -0
- package/dist/routes/shares.js.map +1 -0
- package/dist/scale-exec.d.ts +11 -0
- package/dist/scale-exec.d.ts.map +1 -0
- package/dist/scale-exec.js +26 -0
- package/dist/scale-exec.js.map +1 -0
- package/dist/server.d.ts +13 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +95 -0
- package/dist/server.js.map +1 -0
- package/dist/settle.d.ts +26 -0
- package/dist/settle.d.ts.map +1 -0
- package/dist/settle.js +85 -0
- package/dist/settle.js.map +1 -0
- package/package.json +63 -3
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export type SignupMode = "open" | "invite";
|
|
2
|
+
export interface CloudOptions {
|
|
3
|
+
/** "postgres://...", "pglite:<folder>", or "memory". Default "pglite:./.wizelens-cloud". */
|
|
4
|
+
database?: string;
|
|
5
|
+
/** Default 5970. 0 picks a free port. */
|
|
6
|
+
port?: number;
|
|
7
|
+
/** Default "0.0.0.0". */
|
|
8
|
+
host?: string;
|
|
9
|
+
/** The address people use, for links in invites and shares. Default http://localhost:<port>. */
|
|
10
|
+
publicUrl?: string;
|
|
11
|
+
/** "invite": only the first account and invited people can sign up. "open": anyone can. Default "invite". */
|
|
12
|
+
signup?: SignupMode;
|
|
13
|
+
/** Default retention for new organizations, in days. Default 30. */
|
|
14
|
+
retentionDays?: number;
|
|
15
|
+
/** Ingest calls per key per minute. Default 1200. */
|
|
16
|
+
ingestPerMinute?: number;
|
|
17
|
+
/** How often alert rules run, in ms. Default 60000. */
|
|
18
|
+
alertIntervalMs?: number;
|
|
19
|
+
/** Let alert webhooks call private and local addresses, and plain http. For self-hosting on a private network. Default false. */
|
|
20
|
+
allowPrivateWebhooks?: boolean;
|
|
21
|
+
redactKeys?: string[];
|
|
22
|
+
uiDir?: string;
|
|
23
|
+
/** For tests: the clock and the HTTP client alerts use. */
|
|
24
|
+
now?: () => number;
|
|
25
|
+
fetch?: typeof fetch;
|
|
26
|
+
}
|
|
27
|
+
export type CloudConfig = Required<Omit<CloudOptions, "uiDir" | "publicUrl">> & {
|
|
28
|
+
uiDir: string | undefined;
|
|
29
|
+
publicUrl: string | undefined;
|
|
30
|
+
secureCookies: boolean;
|
|
31
|
+
};
|
|
32
|
+
export declare function resolveConfig(o?: CloudOptions): CloudConfig;
|
|
33
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE3C,MAAM,WAAW,YAAY;IAC3B,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yBAAyB;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gGAAgG;IAChG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6GAA6G;IAC7G,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,oEAAoE;IACpE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qDAAqD;IACrD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uDAAuD;IACvD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iIAAiI;IACjI,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAED,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,GAAG,WAAW,CAAC,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,aAAa,EAAE,OAAO,CAAA;CAAE,CAAC;AAErK,wBAAgB,aAAa,CAAC,CAAC,GAAE,YAAiB,GAAG,WAAW,CAiB/D"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { DEFAULT_REDACT_KEYS } from "@wizeworks/lens-core";
|
|
2
|
+
export function resolveConfig(o = {}) {
|
|
3
|
+
return {
|
|
4
|
+
database: o.database ?? "pglite:./.wizelens-cloud",
|
|
5
|
+
port: o.port ?? 5970,
|
|
6
|
+
host: o.host ?? "0.0.0.0",
|
|
7
|
+
publicUrl: o.publicUrl?.replace(/\/+$/, ""),
|
|
8
|
+
signup: o.signup ?? "invite",
|
|
9
|
+
retentionDays: o.retentionDays ?? 30,
|
|
10
|
+
ingestPerMinute: o.ingestPerMinute ?? 1200,
|
|
11
|
+
alertIntervalMs: o.alertIntervalMs ?? 60_000,
|
|
12
|
+
allowPrivateWebhooks: o.allowPrivateWebhooks ?? false,
|
|
13
|
+
redactKeys: o.redactKeys ?? [...DEFAULT_REDACT_KEYS],
|
|
14
|
+
uiDir: o.uiDir,
|
|
15
|
+
now: o.now ?? Date.now,
|
|
16
|
+
fetch: o.fetch ?? fetch,
|
|
17
|
+
secureCookies: !!o.publicUrl?.startsWith("https://"),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAgC3D,MAAM,UAAU,aAAa,CAAC,CAAC,GAAiB,EAAE;IAChD,OAAO;QACL,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI,0BAA0B;QAClD,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,IAAI;QACpB,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,SAAS;QACzB,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QAC3C,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,QAAQ;QAC5B,aAAa,EAAE,CAAC,CAAC,aAAa,IAAI,EAAE;QACpC,eAAe,EAAE,CAAC,CAAC,eAAe,IAAI,IAAI;QAC1C,eAAe,EAAE,CAAC,CAAC,eAAe,IAAI,MAAM;QAC5C,oBAAoB,EAAE,CAAC,CAAC,oBAAoB,IAAI,KAAK;QACrD,UAAU,EAAE,CAAC,CAAC,UAAU,IAAI,CAAC,GAAG,mBAAmB,CAAC;QACpD,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,GAAG,EAAE,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG;QACtB,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,KAAK;QACvB,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,UAAU,CAAC,UAAU,CAAC;KACrD,CAAC;AACJ,CAAC"}
|
package/dist/db/db.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** Something that runs SQL: the database, or one transaction. Postgres syntax, `$1` parameters. */
|
|
2
|
+
export interface Queryable {
|
|
3
|
+
query<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<T[]>;
|
|
4
|
+
}
|
|
5
|
+
export interface Db extends Queryable {
|
|
6
|
+
/** Run `fn` in one transaction. It rolls back when `fn` throws. */
|
|
7
|
+
tx<T>(fn: (q: Queryable) => Promise<T>): Promise<T>;
|
|
8
|
+
/** Run several statements without parameters (migrations). */
|
|
9
|
+
exec(sql: string): Promise<void>;
|
|
10
|
+
close(): Promise<void>;
|
|
11
|
+
readonly kind: "postgres" | "pglite";
|
|
12
|
+
}
|
|
13
|
+
/** A managed Postgres, from a `postgres://` URL. */
|
|
14
|
+
export declare function openPostgres(url: string): Promise<Db>;
|
|
15
|
+
/** Postgres in this process (PGlite): a folder on disk, or memory when `dir` is undefined. For tests and trials. */
|
|
16
|
+
export declare function openPglite(dir?: string): Promise<Db>;
|
|
17
|
+
/** "postgres://..." opens Postgres; "pglite:<folder>" or "memory" opens PGlite. */
|
|
18
|
+
export declare function openDb(url: string): Promise<Db>;
|
|
19
|
+
//# sourceMappingURL=db.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db/db.ts"],"names":[],"mappings":"AAGA,mGAAmG;AACnG,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;CACnF;AAED,MAAM,WAAW,EAAG,SAAQ,SAAS;IACnC,mEAAmE;IACnE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACpD,8DAA8D;IAC9D,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,QAAQ,CAAC;CACtC;AAMD,oDAAoD;AACpD,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC,CAwB3D;AAED,oHAAoH;AACpH,wBAAsB,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC,CAa1D;AAED,mFAAmF;AACnF,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC,CAK/C"}
|
package/dist/db/db.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const wrap = (client) => ({
|
|
2
|
+
query: async (sql, params = []) => (await client.query(sql, params)).rows,
|
|
3
|
+
});
|
|
4
|
+
/** A managed Postgres, from a `postgres://` URL. */
|
|
5
|
+
export async function openPostgres(url) {
|
|
6
|
+
const { default: pg } = await import("pg");
|
|
7
|
+
// Times are stored as double precision, so no bigint parsing is needed.
|
|
8
|
+
const pool = new pg.Pool({ connectionString: url, max: 10 });
|
|
9
|
+
return {
|
|
10
|
+
kind: "postgres",
|
|
11
|
+
...wrap(pool),
|
|
12
|
+
async tx(fn) {
|
|
13
|
+
const client = await pool.connect();
|
|
14
|
+
try {
|
|
15
|
+
await client.query("BEGIN");
|
|
16
|
+
const out = await fn(wrap(client));
|
|
17
|
+
await client.query("COMMIT");
|
|
18
|
+
return out;
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
await client.query("ROLLBACK");
|
|
22
|
+
throw err;
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
client.release();
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
exec: async (sql) => void (await pool.query(sql)),
|
|
29
|
+
close: () => pool.end(),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/** Postgres in this process (PGlite): a folder on disk, or memory when `dir` is undefined. For tests and trials. */
|
|
33
|
+
export async function openPglite(dir) {
|
|
34
|
+
const { PGlite: Lite } = await import("@electric-sql/pglite");
|
|
35
|
+
const lite = await Lite.create(dir);
|
|
36
|
+
const q = (runner) => ({
|
|
37
|
+
query: async (sql, params = []) => (await runner.query(sql, params)).rows,
|
|
38
|
+
});
|
|
39
|
+
return {
|
|
40
|
+
kind: "pglite",
|
|
41
|
+
...q(lite),
|
|
42
|
+
tx: (fn) => lite.transaction((t) => fn(q(t))),
|
|
43
|
+
exec: async (sql) => void (await lite.exec(sql)),
|
|
44
|
+
close: () => lite.close(),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/** "postgres://..." opens Postgres; "pglite:<folder>" or "memory" opens PGlite. */
|
|
48
|
+
export function openDb(url) {
|
|
49
|
+
if (/^postgres(ql)?:\/\//i.test(url))
|
|
50
|
+
return openPostgres(url);
|
|
51
|
+
if (url === "memory")
|
|
52
|
+
return openPglite();
|
|
53
|
+
if (url.startsWith("pglite:"))
|
|
54
|
+
return openPglite(url.slice("pglite:".length));
|
|
55
|
+
throw new Error(`Unknown database URL "${url}". Use postgres://..., pglite:<folder>, or memory.`);
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/db/db.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Db } from "./db.js";
|
|
2
|
+
/** Apply every migration not applied yet, each in its own transaction. Returns how many ran. */
|
|
3
|
+
export declare function migrate(db: Db): Promise<number>;
|
|
4
|
+
/** One migration as single statements, so it runs inside a transaction on every driver. */
|
|
5
|
+
export declare const splitStatements: (sql: string) => string[];
|
|
6
|
+
//# sourceMappingURL=migrate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/db/migrate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAGlC,gGAAgG;AAChG,wBAAsB,OAAO,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAcrD;AAED,2FAA2F;AAC3F,eAAO,MAAM,eAAe,QAAS,MAAM,KAAG,MAAM,EAIhC,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { MIGRATIONS, MIGRATIONS_TABLE } from "./schema.js";
|
|
2
|
+
/** Apply every migration not applied yet, each in its own transaction. Returns how many ran. */
|
|
3
|
+
export async function migrate(db) {
|
|
4
|
+
await db.exec(MIGRATIONS_TABLE);
|
|
5
|
+
const done = new Set((await db.query("SELECT version FROM wizelens_migrations")).map((r) => r.version));
|
|
6
|
+
let ran = 0;
|
|
7
|
+
for (let i = 0; i < MIGRATIONS.length; i++) {
|
|
8
|
+
const version = i + 1;
|
|
9
|
+
if (done.has(version))
|
|
10
|
+
continue;
|
|
11
|
+
await db.tx(async (q) => {
|
|
12
|
+
for (const statement of splitStatements(MIGRATIONS[i]))
|
|
13
|
+
await q.query(statement);
|
|
14
|
+
await q.query("INSERT INTO wizelens_migrations (version, applied_ms) VALUES ($1, $2)", [version, Date.now()]);
|
|
15
|
+
});
|
|
16
|
+
ran++;
|
|
17
|
+
}
|
|
18
|
+
return ran;
|
|
19
|
+
}
|
|
20
|
+
/** One migration as single statements, so it runs inside a transaction on every driver. */
|
|
21
|
+
export const splitStatements = (sql) => sql
|
|
22
|
+
.split(/;\s*\n/)
|
|
23
|
+
.map((s) => s.trim().replace(/;$/, ""))
|
|
24
|
+
.filter(Boolean);
|
|
25
|
+
//# sourceMappingURL=migrate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/db/migrate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE3D,gGAAgG;AAChG,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,EAAM;IAClC,MAAM,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAsB,yCAAyC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7H,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;YAAE,SAAS;QAChC,MAAM,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;YACtB,KAAK,MAAM,SAAS,IAAI,eAAe,CAAC,UAAU,CAAC,CAAC,CAAE,CAAC;gBAAE,MAAM,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YAClF,MAAM,CAAC,CAAC,KAAK,CAAC,uEAAuE,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAChH,CAAC,CAAC,CAAC;QACH,GAAG,EAAE,CAAC;IACR,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,2FAA2F;AAC3F,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAW,EAAY,EAAE,CACvD,GAAG;KACA,KAAK,CAAC,QAAQ,CAAC;KACf,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;KACtC,MAAM,CAAC,OAAO,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,UAAU,EAAE,SAAS,MAAM,EAoMvC,CAAC;AAEF,eAAO,MAAM,gBAAgB,uHAAuH,CAAC"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
// Cloud schema, one entry per version. Never edit a shipped entry: add a new one (docs/CONTRACT.md, "Cloud storage").
|
|
2
|
+
export const MIGRATIONS = [
|
|
3
|
+
`
|
|
4
|
+
CREATE TABLE orgs (
|
|
5
|
+
id TEXT PRIMARY KEY, name TEXT NOT NULL, slug TEXT NOT NULL UNIQUE,
|
|
6
|
+
retention_days INTEGER NOT NULL DEFAULT 30, created_ms DOUBLE PRECISION NOT NULL
|
|
7
|
+
);
|
|
8
|
+
CREATE TABLE users (
|
|
9
|
+
id TEXT PRIMARY KEY, email TEXT NOT NULL UNIQUE, name TEXT NOT NULL, password_hash TEXT NOT NULL,
|
|
10
|
+
created_ms DOUBLE PRECISION NOT NULL
|
|
11
|
+
);
|
|
12
|
+
CREATE TABLE members (
|
|
13
|
+
org_id TEXT NOT NULL REFERENCES orgs(id) ON DELETE CASCADE, user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
14
|
+
role TEXT NOT NULL, created_ms DOUBLE PRECISION NOT NULL, PRIMARY KEY (org_id, user_id)
|
|
15
|
+
);
|
|
16
|
+
CREATE TABLE sessions (
|
|
17
|
+
token_hash TEXT PRIMARY KEY, user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
18
|
+
created_ms DOUBLE PRECISION NOT NULL, expires_ms DOUBLE PRECISION NOT NULL
|
|
19
|
+
);
|
|
20
|
+
CREATE TABLE invites (
|
|
21
|
+
token_hash TEXT PRIMARY KEY, org_id TEXT NOT NULL REFERENCES orgs(id) ON DELETE CASCADE, email TEXT NOT NULL,
|
|
22
|
+
role TEXT NOT NULL, created_by TEXT NOT NULL, created_ms DOUBLE PRECISION NOT NULL,
|
|
23
|
+
expires_ms DOUBLE PRECISION NOT NULL, accepted_ms DOUBLE PRECISION
|
|
24
|
+
);
|
|
25
|
+
CREATE TABLE projects (
|
|
26
|
+
id TEXT PRIMARY KEY, org_id TEXT NOT NULL REFERENCES orgs(id) ON DELETE CASCADE, name TEXT NOT NULL, slug TEXT NOT NULL,
|
|
27
|
+
created_ms DOUBLE PRECISION NOT NULL, UNIQUE (org_id, slug)
|
|
28
|
+
);
|
|
29
|
+
CREATE TABLE api_keys (
|
|
30
|
+
id TEXT PRIMARY KEY, org_id TEXT NOT NULL REFERENCES orgs(id) ON DELETE CASCADE, kind TEXT NOT NULL,
|
|
31
|
+
project_ids TEXT NOT NULL, name TEXT NOT NULL, prefix TEXT NOT NULL, token_hash TEXT NOT NULL UNIQUE,
|
|
32
|
+
created_by TEXT NOT NULL, created_ms DOUBLE PRECISION NOT NULL, last_used_ms DOUBLE PRECISION, revoked_ms DOUBLE PRECISION
|
|
33
|
+
);
|
|
34
|
+
CREATE TABLE traces (
|
|
35
|
+
project_id TEXT NOT NULL, trace_id TEXT NOT NULL, start_ms DOUBLE PRECISION NOT NULL, end_ms DOUBLE PRECISION NOT NULL,
|
|
36
|
+
updated_ms DOUBLE PRECISION NOT NULL, env TEXT NOT NULL DEFAULT '', PRIMARY KEY (project_id, trace_id)
|
|
37
|
+
);
|
|
38
|
+
CREATE TABLE spans (
|
|
39
|
+
project_id TEXT NOT NULL, trace_id TEXT NOT NULL, span_id TEXT NOT NULL, service TEXT NOT NULL,
|
|
40
|
+
start_ms DOUBLE PRECISION NOT NULL, duration_ms DOUBLE PRECISION NOT NULL, session TEXT, json TEXT NOT NULL,
|
|
41
|
+
PRIMARY KEY (project_id, trace_id, span_id)
|
|
42
|
+
);
|
|
43
|
+
CREATE TABLE logs (
|
|
44
|
+
project_id TEXT NOT NULL, trace_id TEXT NOT NULL, key TEXT NOT NULL, time_ms DOUBLE PRECISION NOT NULL, json TEXT NOT NULL,
|
|
45
|
+
PRIMARY KEY (project_id, trace_id, key)
|
|
46
|
+
);
|
|
47
|
+
CREATE TABLE services (
|
|
48
|
+
project_id TEXT NOT NULL, service TEXT NOT NULL, environment TEXT NOT NULL, host TEXT NOT NULL, via TEXT NOT NULL,
|
|
49
|
+
info TEXT NOT NULL, first_seen DOUBLE PRECISION NOT NULL, last_seen DOUBLE PRECISION NOT NULL,
|
|
50
|
+
PRIMARY KEY (project_id, service, environment, host)
|
|
51
|
+
);
|
|
52
|
+
CREATE TABLE alert_rules (
|
|
53
|
+
id TEXT PRIMARY KEY, project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE, name TEXT NOT NULL,
|
|
54
|
+
metric TEXT NOT NULL, op TEXT NOT NULL, threshold DOUBLE PRECISION NOT NULL, window_ms DOUBLE PRECISION NOT NULL,
|
|
55
|
+
env TEXT NOT NULL DEFAULT '', channels TEXT NOT NULL, enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
|
56
|
+
state TEXT NOT NULL DEFAULT 'ok', last_value DOUBLE PRECISION, last_eval_ms DOUBLE PRECISION,
|
|
57
|
+
created_by TEXT NOT NULL, created_ms DOUBLE PRECISION NOT NULL
|
|
58
|
+
);
|
|
59
|
+
CREATE TABLE alert_events (
|
|
60
|
+
id TEXT PRIMARY KEY, rule_id TEXT NOT NULL REFERENCES alert_rules(id) ON DELETE CASCADE, project_id TEXT NOT NULL,
|
|
61
|
+
kind TEXT NOT NULL, value DOUBLE PRECISION, threshold DOUBLE PRECISION NOT NULL, message TEXT NOT NULL,
|
|
62
|
+
time_ms DOUBLE PRECISION NOT NULL, delivery TEXT NOT NULL DEFAULT ''
|
|
63
|
+
);
|
|
64
|
+
CREATE TABLE shares (
|
|
65
|
+
id TEXT PRIMARY KEY, project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE, trace_id TEXT NOT NULL,
|
|
66
|
+
token_hash TEXT NOT NULL UNIQUE, created_by TEXT NOT NULL, created_ms DOUBLE PRECISION NOT NULL,
|
|
67
|
+
expires_ms DOUBLE PRECISION NOT NULL, revoked_ms DOUBLE PRECISION, views INTEGER NOT NULL DEFAULT 0
|
|
68
|
+
);
|
|
69
|
+
CREATE TABLE audit (
|
|
70
|
+
id TEXT PRIMARY KEY, org_id TEXT NOT NULL, actor TEXT NOT NULL, action TEXT NOT NULL, detail TEXT NOT NULL,
|
|
71
|
+
time_ms DOUBLE PRECISION NOT NULL
|
|
72
|
+
);
|
|
73
|
+
CREATE INDEX ix_traces_updated ON traces (project_id, updated_ms);
|
|
74
|
+
CREATE INDEX ix_traces_start ON traces (project_id, start_ms);
|
|
75
|
+
CREATE INDEX ix_traces_start_all ON traces (start_ms);
|
|
76
|
+
CREATE INDEX ix_spans_session ON spans (project_id, session) WHERE session IS NOT NULL;
|
|
77
|
+
CREATE INDEX ix_alert_events_project ON alert_events (project_id, time_ms);
|
|
78
|
+
CREATE INDEX ix_audit_org ON audit (org_id, time_ms);
|
|
79
|
+
CREATE INDEX ix_members_user ON members (user_id);
|
|
80
|
+
`,
|
|
81
|
+
`
|
|
82
|
+
CREATE TABLE metric_points (
|
|
83
|
+
project_id TEXT NOT NULL, time_ms DOUBLE PRECISION NOT NULL, env TEXT NOT NULL DEFAULT '', service TEXT NOT NULL,
|
|
84
|
+
name TEXT NOT NULL, series_key TEXT NOT NULL, json TEXT NOT NULL
|
|
85
|
+
);
|
|
86
|
+
CREATE INDEX ix_metric_points_name ON metric_points (project_id, name, time_ms);
|
|
87
|
+
CREATE INDEX ix_metric_points_time ON metric_points (project_id, time_ms);
|
|
88
|
+
ALTER TABLE alert_rules ADD COLUMN metric_name TEXT NOT NULL DEFAULT '';
|
|
89
|
+
ALTER TABLE alert_rules ADD COLUMN metric_stat TEXT NOT NULL DEFAULT '';
|
|
90
|
+
ALTER TABLE alert_rules ADD COLUMN metric_service TEXT NOT NULL DEFAULT '';
|
|
91
|
+
`,
|
|
92
|
+
`
|
|
93
|
+
ALTER TABLE traces ADD COLUMN settled_ms DOUBLE PRECISION NOT NULL DEFAULT 0;
|
|
94
|
+
ALTER TABLE traces ADD COLUMN contrib TEXT;
|
|
95
|
+
CREATE INDEX ix_traces_dirty ON traces (start_ms) WHERE settled_ms < updated_ms;
|
|
96
|
+
CREATE TABLE scale_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL);
|
|
97
|
+
CREATE TABLE fact_requests (
|
|
98
|
+
project_id TEXT NOT NULL, trace_id TEXT NOT NULL, env TEXT NOT NULL DEFAULT '', start_ms DOUBLE PRECISION NOT NULL,
|
|
99
|
+
method TEXT NOT NULL, path TEXT NOT NULL, endpoint TEXT NOT NULL, status INTEGER, status_class TEXT NOT NULL, failed BOOLEAN NOT NULL,
|
|
100
|
+
dur_class TEXT NOT NULL, aborted BOOLEAN NOT NULL, duration_ms DOUBLE PRECISION NOT NULL, server_ms DOUBLE PRECISION,
|
|
101
|
+
db_ms DOUBLE PRECISION NOT NULL, db_count INTEGER NOT NULL, fetch_count INTEGER NOT NULL, fetch_ms DOUBLE PRECISION NOT NULL,
|
|
102
|
+
render_ms DOUBLE PRECISION, network_ms DOUBLE PRECISION, service TEXT NOT NULL, services TEXT NOT NULL, errors INTEGER NOT NULL,
|
|
103
|
+
insights INTEGER NOT NULL, health TEXT NOT NULL, user_agent TEXT, client_address TEXT, end_user TEXT, request_id TEXT,
|
|
104
|
+
tags TEXT NOT NULL, search TEXT NOT NULL, PRIMARY KEY (project_id, trace_id)
|
|
105
|
+
);
|
|
106
|
+
CREATE INDEX ix_fact_requests_time ON fact_requests (project_id, start_ms);
|
|
107
|
+
CREATE TABLE fact_traces (
|
|
108
|
+
project_id TEXT NOT NULL, trace_id TEXT NOT NULL, env TEXT NOT NULL DEFAULT '', start_ms DOUBLE PRECISION NOT NULL, path TEXT NOT NULL,
|
|
109
|
+
duration_ms DOUBLE PRECISION NOT NULL, health TEXT, status TEXT NOT NULL, services TEXT NOT NULL, span_count INTEGER NOT NULL,
|
|
110
|
+
slow BOOLEAN NOT NULL, search TEXT NOT NULL, PRIMARY KEY (project_id, trace_id)
|
|
111
|
+
);
|
|
112
|
+
CREATE INDEX ix_fact_traces_time ON fact_traces (project_id, start_ms);
|
|
113
|
+
CREATE TABLE fact_logs (
|
|
114
|
+
project_id TEXT NOT NULL, trace_id TEXT NOT NULL, idx INTEGER NOT NULL, env TEXT NOT NULL DEFAULT '', time_ms DOUBLE PRECISION NOT NULL,
|
|
115
|
+
level TEXT NOT NULL, level_rank SMALLINT NOT NULL, service TEXT NOT NULL, category TEXT NOT NULL, message TEXT NOT NULL,
|
|
116
|
+
trace_name TEXT NOT NULL, span_id TEXT, attributes TEXT NOT NULL, search TEXT NOT NULL, PRIMARY KEY (project_id, trace_id, idx)
|
|
117
|
+
);
|
|
118
|
+
CREATE INDEX ix_fact_logs_time ON fact_logs (project_id, time_ms);
|
|
119
|
+
CREATE TABLE fact_critical (
|
|
120
|
+
project_id TEXT NOT NULL, trace_id TEXT NOT NULL, span_id TEXT NOT NULL, env TEXT NOT NULL DEFAULT '', start_ms DOUBLE PRECISION NOT NULL,
|
|
121
|
+
duration_ms DOUBLE PRECISION NOT NULL, name TEXT NOT NULL, service TEXT NOT NULL, layer TEXT NOT NULL, PRIMARY KEY (project_id, trace_id, span_id)
|
|
122
|
+
);
|
|
123
|
+
CREATE INDEX ix_fact_critical_time ON fact_critical (project_id, start_ms);
|
|
124
|
+
CREATE INDEX ix_fact_critical_slow ON fact_critical (project_id, duration_ms);
|
|
125
|
+
CREATE TABLE rollup_10s (
|
|
126
|
+
project_id TEXT NOT NULL, env TEXT NOT NULL, kind TEXT NOT NULL, key TEXT NOT NULL, bucket_ms DOUBLE PRECISION NOT NULL,
|
|
127
|
+
n DOUBLE PRECISION NOT NULL, err DOUBLE PRECISION NOT NULL, sum_v DOUBLE PRECISION NOT NULL,
|
|
128
|
+
c0 DOUBLE PRECISION NOT NULL DEFAULT 0, c1 DOUBLE PRECISION NOT NULL DEFAULT 0, c2 DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
129
|
+
c3 DOUBLE PRECISION NOT NULL DEFAULT 0, c4 DOUBLE PRECISION NOT NULL DEFAULT 0, c5 DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
130
|
+
first_ms DOUBLE PRECISION NOT NULL, last_ms DOUBLE PRECISION NOT NULL, top_rank DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
131
|
+
top TEXT, ids TEXT NOT NULL DEFAULT '', PRIMARY KEY (project_id, kind, bucket_ms, env, key)
|
|
132
|
+
);
|
|
133
|
+
CREATE INDEX ix_rollup_10s_key ON rollup_10s (project_id, kind, key, bucket_ms);
|
|
134
|
+
CREATE TABLE rollup_5m (
|
|
135
|
+
project_id TEXT NOT NULL, env TEXT NOT NULL, kind TEXT NOT NULL, key TEXT NOT NULL, bucket_ms DOUBLE PRECISION NOT NULL,
|
|
136
|
+
n DOUBLE PRECISION NOT NULL, err DOUBLE PRECISION NOT NULL, sum_v DOUBLE PRECISION NOT NULL,
|
|
137
|
+
c0 DOUBLE PRECISION NOT NULL DEFAULT 0, c1 DOUBLE PRECISION NOT NULL DEFAULT 0, c2 DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
138
|
+
c3 DOUBLE PRECISION NOT NULL DEFAULT 0, c4 DOUBLE PRECISION NOT NULL DEFAULT 0, c5 DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
139
|
+
first_ms DOUBLE PRECISION NOT NULL, last_ms DOUBLE PRECISION NOT NULL, top_rank DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
140
|
+
top TEXT, ids TEXT NOT NULL DEFAULT '', PRIMARY KEY (project_id, kind, bucket_ms, env, key)
|
|
141
|
+
);
|
|
142
|
+
CREATE INDEX ix_rollup_5m_key ON rollup_5m (project_id, kind, key, bucket_ms);
|
|
143
|
+
CREATE TABLE rollup_1h (
|
|
144
|
+
project_id TEXT NOT NULL, env TEXT NOT NULL, kind TEXT NOT NULL, key TEXT NOT NULL, bucket_ms DOUBLE PRECISION NOT NULL,
|
|
145
|
+
n DOUBLE PRECISION NOT NULL, err DOUBLE PRECISION NOT NULL, sum_v DOUBLE PRECISION NOT NULL,
|
|
146
|
+
c0 DOUBLE PRECISION NOT NULL DEFAULT 0, c1 DOUBLE PRECISION NOT NULL DEFAULT 0, c2 DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
147
|
+
c3 DOUBLE PRECISION NOT NULL DEFAULT 0, c4 DOUBLE PRECISION NOT NULL DEFAULT 0, c5 DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
148
|
+
first_ms DOUBLE PRECISION NOT NULL, last_ms DOUBLE PRECISION NOT NULL, top_rank DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
149
|
+
top TEXT, ids TEXT NOT NULL DEFAULT '', PRIMARY KEY (project_id, kind, bucket_ms, env, key)
|
|
150
|
+
);
|
|
151
|
+
CREATE INDEX ix_rollup_1h_key ON rollup_1h (project_id, kind, key, bucket_ms);
|
|
152
|
+
CREATE TABLE hist_10s (
|
|
153
|
+
project_id TEXT NOT NULL, env TEXT NOT NULL, kind TEXT NOT NULL, key TEXT NOT NULL, bucket_ms DOUBLE PRECISION NOT NULL,
|
|
154
|
+
bin INTEGER NOT NULL, cnt DOUBLE PRECISION NOT NULL, PRIMARY KEY (project_id, kind, bucket_ms, env, key, bin)
|
|
155
|
+
);
|
|
156
|
+
CREATE TABLE hist_5m (
|
|
157
|
+
project_id TEXT NOT NULL, env TEXT NOT NULL, kind TEXT NOT NULL, key TEXT NOT NULL, bucket_ms DOUBLE PRECISION NOT NULL,
|
|
158
|
+
bin INTEGER NOT NULL, cnt DOUBLE PRECISION NOT NULL, PRIMARY KEY (project_id, kind, bucket_ms, env, key, bin)
|
|
159
|
+
);
|
|
160
|
+
CREATE TABLE hist_1h (
|
|
161
|
+
project_id TEXT NOT NULL, env TEXT NOT NULL, kind TEXT NOT NULL, key TEXT NOT NULL, bucket_ms DOUBLE PRECISION NOT NULL,
|
|
162
|
+
bin INTEGER NOT NULL, cnt DOUBLE PRECISION NOT NULL, PRIMARY KEY (project_id, kind, bucket_ms, env, key, bin)
|
|
163
|
+
);
|
|
164
|
+
CREATE TABLE metric_series (
|
|
165
|
+
project_id TEXT NOT NULL, env TEXT NOT NULL, series_key TEXT NOT NULL, name TEXT NOT NULL, service TEXT NOT NULL, kind TEXT NOT NULL,
|
|
166
|
+
unit TEXT NOT NULL, description TEXT NOT NULL, monotonic BOOLEAN NOT NULL, temporality TEXT NOT NULL, attributes TEXT NOT NULL,
|
|
167
|
+
last_ms DOUBLE PRECISION NOT NULL, last_value DOUBLE PRECISION, last_hist TEXT, PRIMARY KEY (project_id, env, series_key)
|
|
168
|
+
);
|
|
169
|
+
CREATE INDEX ix_metric_series_name ON metric_series (project_id, name);
|
|
170
|
+
CREATE TABLE metric_10s (
|
|
171
|
+
project_id TEXT NOT NULL, env TEXT NOT NULL, series_key TEXT NOT NULL, name TEXT NOT NULL, bucket_ms DOUBLE PRECISION NOT NULL,
|
|
172
|
+
cnt DOUBLE PRECISION NOT NULL, vsum DOUBLE PRECISION NOT NULL, vmin DOUBLE PRECISION, vmax DOUBLE PRECISION,
|
|
173
|
+
first_ms DOUBLE PRECISION NOT NULL, first_v DOUBLE PRECISION, last_ms DOUBLE PRECISION NOT NULL, last_v DOUBLE PRECISION,
|
|
174
|
+
rate_delta DOUBLE PRECISION NOT NULL DEFAULT 0, rate_ms DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
175
|
+
h_count DOUBLE PRECISION NOT NULL DEFAULT 0, h_sum DOUBLE PRECISION NOT NULL DEFAULT 0, h_min DOUBLE PRECISION, h_max DOUBLE PRECISION,
|
|
176
|
+
h_bounds TEXT, h_counts TEXT, PRIMARY KEY (project_id, name, bucket_ms, env, series_key)
|
|
177
|
+
);
|
|
178
|
+
CREATE TABLE metric_5m (
|
|
179
|
+
project_id TEXT NOT NULL, env TEXT NOT NULL, series_key TEXT NOT NULL, name TEXT NOT NULL, bucket_ms DOUBLE PRECISION NOT NULL,
|
|
180
|
+
cnt DOUBLE PRECISION NOT NULL, vsum DOUBLE PRECISION NOT NULL, vmin DOUBLE PRECISION, vmax DOUBLE PRECISION,
|
|
181
|
+
first_ms DOUBLE PRECISION NOT NULL, first_v DOUBLE PRECISION, last_ms DOUBLE PRECISION NOT NULL, last_v DOUBLE PRECISION,
|
|
182
|
+
rate_delta DOUBLE PRECISION NOT NULL DEFAULT 0, rate_ms DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
183
|
+
h_count DOUBLE PRECISION NOT NULL DEFAULT 0, h_sum DOUBLE PRECISION NOT NULL DEFAULT 0, h_min DOUBLE PRECISION, h_max DOUBLE PRECISION,
|
|
184
|
+
h_bounds TEXT, h_counts TEXT, PRIMARY KEY (project_id, name, bucket_ms, env, series_key)
|
|
185
|
+
);
|
|
186
|
+
CREATE TABLE metric_1h (
|
|
187
|
+
project_id TEXT NOT NULL, env TEXT NOT NULL, series_key TEXT NOT NULL, name TEXT NOT NULL, bucket_ms DOUBLE PRECISION NOT NULL,
|
|
188
|
+
cnt DOUBLE PRECISION NOT NULL, vsum DOUBLE PRECISION NOT NULL, vmin DOUBLE PRECISION, vmax DOUBLE PRECISION,
|
|
189
|
+
first_ms DOUBLE PRECISION NOT NULL, first_v DOUBLE PRECISION, last_ms DOUBLE PRECISION NOT NULL, last_v DOUBLE PRECISION,
|
|
190
|
+
rate_delta DOUBLE PRECISION NOT NULL DEFAULT 0, rate_ms DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
191
|
+
h_count DOUBLE PRECISION NOT NULL DEFAULT 0, h_sum DOUBLE PRECISION NOT NULL DEFAULT 0, h_min DOUBLE PRECISION, h_max DOUBLE PRECISION,
|
|
192
|
+
h_bounds TEXT, h_counts TEXT, PRIMARY KEY (project_id, name, bucket_ms, env, series_key)
|
|
193
|
+
);
|
|
194
|
+
CREATE INDEX ix_metric_10s_time ON metric_10s (project_id, bucket_ms);
|
|
195
|
+
CREATE INDEX ix_metric_5m_time ON metric_5m (project_id, bucket_ms);
|
|
196
|
+
CREATE INDEX ix_metric_1h_time ON metric_1h (project_id, bucket_ms);
|
|
197
|
+
`,
|
|
198
|
+
];
|
|
199
|
+
export const MIGRATIONS_TABLE = `CREATE TABLE IF NOT EXISTS wizelens_migrations (version INTEGER PRIMARY KEY, applied_ms DOUBLE PRECISION NOT NULL)`;
|
|
200
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA,sHAAsH;AACtH,MAAM,CAAC,MAAM,UAAU,GAAsB;IAC3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6ED;IACC;;;;;;;;;;CAUD;IACC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyGD;CACA,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,oHAAoH,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
+
/** A failure that becomes one JSON error answer. */
|
|
3
|
+
export declare class HttpError extends Error {
|
|
4
|
+
readonly status: number;
|
|
5
|
+
constructor(status: number, message: string);
|
|
6
|
+
}
|
|
7
|
+
export declare const fail: (status: number, message: string) => never;
|
|
8
|
+
export declare function sendJson(res: ServerResponse, status: number, value: unknown, headers?: Record<string, string | string[]>): void;
|
|
9
|
+
/** A small JSON body. Throws 400 for bad JSON or more than 1 MB. */
|
|
10
|
+
export declare function readJsonBody(req: IncomingMessage): Promise<Record<string, unknown>>;
|
|
11
|
+
export declare function cookieOf(req: IncomingMessage, name: string): string | undefined;
|
|
12
|
+
/** A cookie header: HttpOnly, SameSite=Lax, Secure on https. `maxAgeS` 0 deletes it. */
|
|
13
|
+
export declare const cookie: (name: string, value: string, maxAgeS: number, secure: boolean) => string;
|
|
14
|
+
export declare const bearerOf: (req: IncomingMessage) => string | undefined;
|
|
15
|
+
/** Read a string field. Throws 400 when it is required and missing. */
|
|
16
|
+
export declare function str(body: Record<string, unknown>, key: string, required?: boolean): string;
|
|
17
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/http/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAIjE,oDAAoD;AACpD,qBAAa,SAAU,SAAQ,KAAK;IAEhC,QAAQ,CAAC,MAAM,EAAE,MAAM;IADzB,YACW,MAAM,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM,EAGhB;CACF;AAED,eAAO,MAAM,IAAI,WAAY,MAAM,WAAW,MAAM,KAAG,KAEtD,CAAC;AAEF,wBAAgB,QAAQ,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAM,GAAG,IAAI,CAGnI;AAED,oEAAoE;AACpE,wBAAsB,YAAY,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAiBzF;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAM/E;AAED,wFAAwF;AACxF,eAAO,MAAM,MAAM,SAAU,MAAM,SAAS,MAAM,WAAW,MAAM,UAAU,OAAO,KAAG,MACgC,CAAC;AAExH,eAAO,MAAM,QAAQ,QAAS,eAAe,KAAG,MAAM,GAAG,SAGxD,CAAC;AAEF,uEAAuE;AACvE,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,UAAO,GAAG,MAAM,CAKvF"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const MAX_JSON = 1024 * 1024;
|
|
2
|
+
/** A failure that becomes one JSON error answer. */
|
|
3
|
+
export class HttpError extends Error {
|
|
4
|
+
status;
|
|
5
|
+
constructor(status, message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.status = status;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export const fail = (status, message) => {
|
|
11
|
+
throw new HttpError(status, message);
|
|
12
|
+
};
|
|
13
|
+
export function sendJson(res, status, value, headers = {}) {
|
|
14
|
+
res.writeHead(status, { "Content-Type": "application/json; charset=utf-8", "Cache-Control": "no-store", ...headers });
|
|
15
|
+
res.end(JSON.stringify(value));
|
|
16
|
+
}
|
|
17
|
+
/** A small JSON body. Throws 400 for bad JSON or more than 1 MB. */
|
|
18
|
+
export async function readJsonBody(req) {
|
|
19
|
+
const chunks = [];
|
|
20
|
+
let size = 0;
|
|
21
|
+
for await (const chunk of req) {
|
|
22
|
+
const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
23
|
+
size += buf.length;
|
|
24
|
+
if (size > MAX_JSON)
|
|
25
|
+
fail(413, "The body is too large.");
|
|
26
|
+
chunks.push(buf);
|
|
27
|
+
}
|
|
28
|
+
const text = Buffer.concat(chunks).toString("utf8");
|
|
29
|
+
try {
|
|
30
|
+
const v = text ? JSON.parse(text) : {};
|
|
31
|
+
return v && typeof v === "object" && !Array.isArray(v) ? v : fail(400, "Send a JSON object.");
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
if (err instanceof HttpError)
|
|
35
|
+
throw err;
|
|
36
|
+
return fail(400, "The body is not valid JSON.");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export function cookieOf(req, name) {
|
|
40
|
+
for (const part of String(req.headers.cookie ?? "").split(";")) {
|
|
41
|
+
const [k, ...v] = part.trim().split("=");
|
|
42
|
+
if (k === name)
|
|
43
|
+
return decodeURIComponent(v.join("="));
|
|
44
|
+
}
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
/** A cookie header: HttpOnly, SameSite=Lax, Secure on https. `maxAgeS` 0 deletes it. */
|
|
48
|
+
export const cookie = (name, value, maxAgeS, secure) => `${name}=${encodeURIComponent(value)}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${maxAgeS}${secure ? "; Secure" : ""}`;
|
|
49
|
+
export const bearerOf = (req) => {
|
|
50
|
+
const auth = String(req.headers.authorization ?? "");
|
|
51
|
+
return auth.toLowerCase().startsWith("bearer ") ? auth.slice(7).trim() || undefined : undefined;
|
|
52
|
+
};
|
|
53
|
+
/** Read a string field. Throws 400 when it is required and missing. */
|
|
54
|
+
export function str(body, key, required = true) {
|
|
55
|
+
const v = body[key];
|
|
56
|
+
if (typeof v === "string" && v.trim())
|
|
57
|
+
return v;
|
|
58
|
+
if (required)
|
|
59
|
+
fail(400, `"${key}" is required.`);
|
|
60
|
+
return "";
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/http/http.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** A fixed-window counter per key: at most `limit` calls per `windowMs`. In memory, per process. */
|
|
2
|
+
export declare class RateLimiter {
|
|
3
|
+
#private;
|
|
4
|
+
private readonly limit;
|
|
5
|
+
private readonly windowMs;
|
|
6
|
+
private readonly now;
|
|
7
|
+
constructor(limit: number, windowMs: number, now?: () => number);
|
|
8
|
+
/** True when the call is allowed. */
|
|
9
|
+
take(key: string): boolean;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=limiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limiter.d.ts","sourceRoot":"","sources":["../../src/http/limiter.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,qBAAa,WAAW;;IAIpB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAHtB,YACmB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,GAAG,GAAE,MAAM,MAAiB,EAC3C;IAEJ,qCAAqC;IACrC,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAUzB;CAKF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** A fixed-window counter per key: at most `limit` calls per `windowMs`. In memory, per process. */
|
|
2
|
+
export class RateLimiter {
|
|
3
|
+
limit;
|
|
4
|
+
windowMs;
|
|
5
|
+
now;
|
|
6
|
+
#counts = new Map();
|
|
7
|
+
constructor(limit, windowMs, now = Date.now) {
|
|
8
|
+
this.limit = limit;
|
|
9
|
+
this.windowMs = windowMs;
|
|
10
|
+
this.now = now;
|
|
11
|
+
}
|
|
12
|
+
/** True when the call is allowed. */
|
|
13
|
+
take(key) {
|
|
14
|
+
const t = this.now();
|
|
15
|
+
const c = this.#counts.get(key);
|
|
16
|
+
if (!c || t - c.start >= this.windowMs) {
|
|
17
|
+
this.#counts.set(key, { start: t, n: 1 });
|
|
18
|
+
if (this.#counts.size > 10_000)
|
|
19
|
+
this.#sweep(t);
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
c.n++;
|
|
23
|
+
return c.n <= this.limit;
|
|
24
|
+
}
|
|
25
|
+
#sweep(t) {
|
|
26
|
+
for (const [k, c] of this.#counts)
|
|
27
|
+
if (t - c.start >= this.windowMs)
|
|
28
|
+
this.#counts.delete(k);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=limiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limiter.js","sourceRoot":"","sources":["../../src/http/limiter.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,MAAM,OAAO,WAAW;IAIH,KAAK;IACL,QAAQ;IACR,GAAG;IALb,OAAO,GAAG,IAAI,GAAG,EAAwC,CAAC;IAEnE,YACmB,KAAa,EACb,QAAgB,EAChB,GAAG,GAAiB,IAAI,CAAC,GAAG;qBAF5B,KAAK;wBACL,QAAQ;mBACR,GAAG;IACnB,CAAC;IAEJ,qCAAqC;IACrC,IAAI,CAAC,GAAW;QACd,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACrB,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACvC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAC1C,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,MAAM;gBAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC/C,OAAO,IAAI,CAAC;QACd,CAAC;QACD,CAAC,CAAC,CAAC,EAAE,CAAC;QACN,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC;IAC3B,CAAC;IAED,MAAM,CAAC,CAAS;QACd,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO;YAAE,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ;gBAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC9F,CAAC;CACF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
+
export interface RouteCtx {
|
|
3
|
+
req: IncomingMessage;
|
|
4
|
+
res: ServerResponse;
|
|
5
|
+
url: URL;
|
|
6
|
+
params: Record<string, string>;
|
|
7
|
+
}
|
|
8
|
+
export type Handler<C extends RouteCtx = RouteCtx> = (ctx: C) => Promise<void>;
|
|
9
|
+
/** Method and path matching, with `:name` path parts. Paths are below the base path. */
|
|
10
|
+
export declare class Router<C extends RouteCtx = RouteCtx> {
|
|
11
|
+
#private;
|
|
12
|
+
on(method: string, path: string, handler: Handler<C>): this;
|
|
13
|
+
/** The handler and path params for a request, or undefined. */
|
|
14
|
+
match(method: string, path: string): {
|
|
15
|
+
handler: Handler<C>;
|
|
16
|
+
params: Record<string, string>;
|
|
17
|
+
} | undefined;
|
|
18
|
+
/** True when some route has this path with another method (for 405). */
|
|
19
|
+
hasPath(path: string): boolean;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/http/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEjE,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,eAAe,CAAC;IACrB,GAAG,EAAE,cAAc,CAAC;IACpB,GAAG,EAAE,GAAG,CAAC;IACT,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,IAAI,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAS/E,wFAAwF;AACxF,qBAAa,MAAM,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ;;IAG/C,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAK1D;IAED,+DAA+D;IAC/D,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,SAAS,CASvG;IAED,wEAAwE;IACxE,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7B;CACF"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Method and path matching, with `:name` path parts. Paths are below the base path. */
|
|
2
|
+
export class Router {
|
|
3
|
+
#routes = [];
|
|
4
|
+
on(method, path, handler) {
|
|
5
|
+
const keys = [];
|
|
6
|
+
const source = path.replace(/:([a-zA-Z]+)/g, (_, k) => (keys.push(k), "([^/]+)"));
|
|
7
|
+
this.#routes.push({ method, pattern: new RegExp(`^${source}$`), keys, handler });
|
|
8
|
+
return this;
|
|
9
|
+
}
|
|
10
|
+
/** The handler and path params for a request, or undefined. */
|
|
11
|
+
match(method, path) {
|
|
12
|
+
for (const r of this.#routes) {
|
|
13
|
+
if (r.method !== method)
|
|
14
|
+
continue;
|
|
15
|
+
const m = r.pattern.exec(path);
|
|
16
|
+
if (!m)
|
|
17
|
+
continue;
|
|
18
|
+
const params = Object.fromEntries(r.keys.map((k, i) => [k, decodeURIComponent(m[i + 1])]));
|
|
19
|
+
return { handler: r.handler, params };
|
|
20
|
+
}
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
/** True when some route has this path with another method (for 405). */
|
|
24
|
+
hasPath(path) {
|
|
25
|
+
return this.#routes.some((r) => r.pattern.test(path));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/http/router.ts"],"names":[],"mappings":"AAkBA,wFAAwF;AACxF,MAAM,OAAO,MAAM;IACR,OAAO,GAAe,EAAE,CAAC;IAElC,EAAE,CAAC,MAAc,EAAE,IAAY,EAAE,OAAmB;QAClD,MAAM,IAAI,GAAa,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;QAC1F,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QACjF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,+DAA+D;IAC/D,KAAK,CAAC,MAAc,EAAE,IAAY;QAChC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC7B,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM;gBAAE,SAAS;YAClC,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/B,IAAI,CAAC,CAAC;gBAAE,SAAS;YACjB,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5F,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;QACxC,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,wEAAwE;IACxE,OAAO,CAAC,IAAY;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACxD,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { createCloud, CLOUD_VERSION } from "./server.js";
|
|
2
|
+
export type { Cloud } from "./server.js";
|
|
3
|
+
export type { CloudOptions } from "./config.js";
|
|
4
|
+
export { openDb } from "./db/db.js";
|
|
5
|
+
export type { Db } from "./db/db.js";
|
|
6
|
+
export { migrate } from "./db/migrate.js";
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACzD,YAAY,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACpC,YAAY,EAAE,EAAE,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC"}
|