@azlib/scheduler 1.1.0 → 1.2.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 +13 -0
- package/dist/{cli-config-7F2U8qPM.mjs → cli-config-6u8AzSdw.mjs} +183 -103
- package/dist/cli-config-6u8AzSdw.mjs.map +1 -0
- package/dist/{cli-config-Cz8QP_4I.cjs → cli-config-CFBl-YOh.cjs} +217 -101
- package/dist/dashboard/cli.cjs +1 -1
- package/dist/dashboard/cli.d.cts +1 -1
- package/dist/dashboard/cli.d.mts +1 -1
- package/dist/dashboard/cli.mjs +1 -1
- package/dist/dashboard/public/assets/index-DczjtqRn.js +12 -0
- package/dist/dashboard/public/index.html +2 -2
- package/dist/dashboard.cjs +7 -1
- package/dist/dashboard.d.cts +13 -2
- package/dist/dashboard.d.cts.map +1 -1
- package/dist/dashboard.d.mts +13 -2
- package/dist/dashboard.d.mts.map +1 -1
- package/dist/dashboard.mjs +2 -2
- package/dist/http-server-Cme4XKyH.d.mts +34 -0
- package/dist/http-server-Cme4XKyH.d.mts.map +1 -0
- package/dist/http-server-u1BnbkAK.d.cts +34 -0
- package/dist/http-server-u1BnbkAK.d.cts.map +1 -0
- package/package.json +4 -4
- package/dist/cli-config-7F2U8qPM.mjs.map +0 -1
- package/dist/dashboard/public/assets/index-eWhp41cY.js +0 -12
- package/dist/http-server-DN6Lg464.d.cts +0 -19
- package/dist/http-server-DN6Lg464.d.cts.map +0 -1
- package/dist/http-server-DPQ9HIK-.d.mts +0 -19
- package/dist/http-server-DPQ9HIK-.d.mts.map +0 -1
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>@azlib/scheduler dashboard</title>
|
|
7
|
-
<script type="module" crossorigin src="
|
|
8
|
-
<link rel="stylesheet" crossorigin href="
|
|
7
|
+
<script type="module" crossorigin src="./assets/index-DczjtqRn.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="./assets/index-CbmpG6_w.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<div id="root"></div>
|
package/dist/dashboard.cjs
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_cli_config = require("./cli-config-
|
|
2
|
+
const require_cli_config = require("./cli-config-CFBl-YOh.cjs");
|
|
3
3
|
const require_store_dashboard = require("./store-dashboard-Sg4BBWiJ.cjs");
|
|
4
4
|
const require_queue_dashboard_service = require("./queue-dashboard-service-BFXcnfUr.cjs");
|
|
5
|
+
exports.DashboardHttpError = require_cli_config.DashboardHttpError;
|
|
5
6
|
exports.createSchedulerDashboardFromPersistence = require_store_dashboard.createSchedulerDashboardFromPersistence;
|
|
6
7
|
exports.createSchedulerDashboardFromStores = require_store_dashboard.createSchedulerDashboardFromStores;
|
|
8
|
+
exports.createSchedulerDashboardNodeHandler = require_cli_config.createSchedulerDashboardNodeHandler;
|
|
7
9
|
exports.createSchedulerDashboardServer = require_cli_config.createSchedulerDashboardServer;
|
|
8
10
|
exports.createSchedulerDashboardService = require_queue_dashboard_service.createSchedulerDashboardService;
|
|
11
|
+
exports.handleSchedulerDashboardRequest = require_cli_config.handleSchedulerDashboardRequest;
|
|
12
|
+
exports.normalizeDashboardBasePath = require_cli_config.normalizeDashboardBasePath;
|
|
9
13
|
exports.parseDashboardCliEnv = require_cli_config.parseDashboardCliEnv;
|
|
14
|
+
exports.resolveDashboardApiBase = require_cli_config.resolveDashboardApiBase;
|
|
15
|
+
exports.stripDashboardBasePath = require_cli_config.stripDashboardBasePath;
|
package/dist/dashboard.d.cts
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
import { n as SchedulerDashboardItem, r as SchedulerDashboardService, t as SchedulerDashboardHealth } from "./dashboard-types-BHjRLcxJ.cjs";
|
|
2
2
|
import { i as createSchedulerDashboardService, n as createSchedulerDashboardFromStores, t as createSchedulerDashboardFromPersistence } from "./store-dashboard-C44d7sdh.cjs";
|
|
3
|
-
import { n as SchedulerDashboardServerOptions, r as createSchedulerDashboardServer, t as SchedulerDashboardServer } from "./http-server-
|
|
3
|
+
import { a as SchedulerDashboardHandlerOptions, c as handleSchedulerDashboardRequest, i as DashboardAuthorize, n as SchedulerDashboardServerOptions, o as SchedulerDashboardRequestHandler, r as createSchedulerDashboardServer, s as createSchedulerDashboardNodeHandler, t as SchedulerDashboardServer } from "./http-server-u1BnbkAK.cjs";
|
|
4
4
|
import { SqlDialectAdapter } from "@azlib/persistence";
|
|
5
|
+
//#region src/dashboard/http-auth.d.ts
|
|
6
|
+
declare class DashboardHttpError extends Error {
|
|
7
|
+
readonly status: number;
|
|
8
|
+
constructor(status: number, message: string);
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/dashboard/http-path.d.ts
|
|
12
|
+
declare function normalizeDashboardBasePath(basePath?: string): string;
|
|
13
|
+
declare function stripDashboardBasePath(pathname: string, basePath?: string): string | null;
|
|
14
|
+
declare function resolveDashboardApiBase(pathname: string): string;
|
|
15
|
+
//#endregion
|
|
5
16
|
//#region src/dashboard/sql-drivers.d.ts
|
|
6
17
|
type SchedulerDashboardDialect = "postgres" | "mysql" | "sqlite" | "mssql";
|
|
7
18
|
//#endregion
|
|
@@ -16,5 +27,5 @@ interface SchedulerDashboardCliConfig {
|
|
|
16
27
|
}
|
|
17
28
|
declare function parseDashboardCliEnv(env: Record<string, string | undefined>): SchedulerDashboardCliConfig;
|
|
18
29
|
//#endregion
|
|
19
|
-
export { type SchedulerDashboardHealth, type SchedulerDashboardItem, type SchedulerDashboardServer, type SchedulerDashboardServerOptions, type SchedulerDashboardService, createSchedulerDashboardFromPersistence, createSchedulerDashboardFromStores, createSchedulerDashboardServer, createSchedulerDashboardService, parseDashboardCliEnv };
|
|
30
|
+
export { type DashboardAuthorize, DashboardHttpError, type SchedulerDashboardHandlerOptions, type SchedulerDashboardHealth, type SchedulerDashboardItem, type SchedulerDashboardRequestHandler, type SchedulerDashboardServer, type SchedulerDashboardServerOptions, type SchedulerDashboardService, createSchedulerDashboardFromPersistence, createSchedulerDashboardFromStores, createSchedulerDashboardNodeHandler, createSchedulerDashboardServer, createSchedulerDashboardService, handleSchedulerDashboardRequest, normalizeDashboardBasePath, parseDashboardCliEnv, resolveDashboardApiBase, stripDashboardBasePath };
|
|
20
31
|
//# sourceMappingURL=dashboard.d.cts.map
|
package/dist/dashboard.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard.d.cts","names":[],"sources":["../src/dashboard/sql-drivers.ts","../src/dashboard/cli-config.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"dashboard.d.cts","names":[],"sources":["../src/dashboard/http-auth.ts","../src/dashboard/http-path.ts","../src/dashboard/sql-drivers.ts","../src/dashboard/cli-config.ts"],"mappings":";;;;;cAAa,2BAA2B;WAC7B;EAET,YAAY,gBAAgB;;;;iBCHd,2BAA2B;iBAS3B,uBACd,kBACA;iBAiBc,wBAAwB;;;KChB5B;;;UCJK;EACf;EACA,SAAS;EACT;EACA;EACA;EACA;;iBAmCc,qBACd,KAAK,qCACJ"}
|
package/dist/dashboard.d.mts
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
import { n as SchedulerDashboardItem, r as SchedulerDashboardService, t as SchedulerDashboardHealth } from "./dashboard-types-BHjRLcxJ.mjs";
|
|
2
2
|
import { i as createSchedulerDashboardService, n as createSchedulerDashboardFromStores, t as createSchedulerDashboardFromPersistence } from "./store-dashboard-D-yIxXxL.mjs";
|
|
3
|
-
import { n as SchedulerDashboardServerOptions, r as createSchedulerDashboardServer, t as SchedulerDashboardServer } from "./http-server-
|
|
3
|
+
import { a as SchedulerDashboardHandlerOptions, c as handleSchedulerDashboardRequest, i as DashboardAuthorize, n as SchedulerDashboardServerOptions, o as SchedulerDashboardRequestHandler, r as createSchedulerDashboardServer, s as createSchedulerDashboardNodeHandler, t as SchedulerDashboardServer } from "./http-server-Cme4XKyH.mjs";
|
|
4
4
|
import { SqlDialectAdapter } from "@azlib/persistence";
|
|
5
|
+
//#region src/dashboard/http-auth.d.ts
|
|
6
|
+
declare class DashboardHttpError extends Error {
|
|
7
|
+
readonly status: number;
|
|
8
|
+
constructor(status: number, message: string);
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/dashboard/http-path.d.ts
|
|
12
|
+
declare function normalizeDashboardBasePath(basePath?: string): string;
|
|
13
|
+
declare function stripDashboardBasePath(pathname: string, basePath?: string): string | null;
|
|
14
|
+
declare function resolveDashboardApiBase(pathname: string): string;
|
|
15
|
+
//#endregion
|
|
5
16
|
//#region src/dashboard/sql-drivers.d.ts
|
|
6
17
|
type SchedulerDashboardDialect = "postgres" | "mysql" | "sqlite" | "mssql";
|
|
7
18
|
//#endregion
|
|
@@ -16,5 +27,5 @@ interface SchedulerDashboardCliConfig {
|
|
|
16
27
|
}
|
|
17
28
|
declare function parseDashboardCliEnv(env: Record<string, string | undefined>): SchedulerDashboardCliConfig;
|
|
18
29
|
//#endregion
|
|
19
|
-
export { type SchedulerDashboardHealth, type SchedulerDashboardItem, type SchedulerDashboardServer, type SchedulerDashboardServerOptions, type SchedulerDashboardService, createSchedulerDashboardFromPersistence, createSchedulerDashboardFromStores, createSchedulerDashboardServer, createSchedulerDashboardService, parseDashboardCliEnv };
|
|
30
|
+
export { type DashboardAuthorize, DashboardHttpError, type SchedulerDashboardHandlerOptions, type SchedulerDashboardHealth, type SchedulerDashboardItem, type SchedulerDashboardRequestHandler, type SchedulerDashboardServer, type SchedulerDashboardServerOptions, type SchedulerDashboardService, createSchedulerDashboardFromPersistence, createSchedulerDashboardFromStores, createSchedulerDashboardNodeHandler, createSchedulerDashboardServer, createSchedulerDashboardService, handleSchedulerDashboardRequest, normalizeDashboardBasePath, parseDashboardCliEnv, resolveDashboardApiBase, stripDashboardBasePath };
|
|
20
31
|
//# sourceMappingURL=dashboard.d.mts.map
|
package/dist/dashboard.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard.d.mts","names":[],"sources":["../src/dashboard/sql-drivers.ts","../src/dashboard/cli-config.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"dashboard.d.mts","names":[],"sources":["../src/dashboard/http-auth.ts","../src/dashboard/http-path.ts","../src/dashboard/sql-drivers.ts","../src/dashboard/cli-config.ts"],"mappings":";;;;;cAAa,2BAA2B;WAC7B;EAET,YAAY,gBAAgB;;;;iBCHd,2BAA2B;iBAS3B,uBACd,kBACA;iBAiBc,wBAAwB;;;KChB5B;;;UCJK;EACf;EACA,SAAS;EACT;EACA;EACA;EACA;;iBAmCc,qBACd,KAAK,qCACJ"}
|
package/dist/dashboard.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { n as createSchedulerDashboardFromStores, t as createSchedulerDashboardFromPersistence } from "./store-dashboard-Cyf_JILa.mjs";
|
|
2
2
|
import { t as createSchedulerDashboardService } from "./queue-dashboard-service-C0QapgOg.mjs";
|
|
3
|
-
import { i as createSchedulerDashboardServer, t as parseDashboardCliEnv } from "./cli-config-
|
|
4
|
-
export { createSchedulerDashboardFromPersistence, createSchedulerDashboardFromStores, createSchedulerDashboardServer, createSchedulerDashboardService, parseDashboardCliEnv };
|
|
3
|
+
import { a as createSchedulerDashboardNodeHandler, c as normalizeDashboardBasePath, d as DashboardHttpError, i as createSchedulerDashboardServer, l as resolveDashboardApiBase, o as handleSchedulerDashboardRequest, t as parseDashboardCliEnv, u as stripDashboardBasePath } from "./cli-config-6u8AzSdw.mjs";
|
|
4
|
+
export { DashboardHttpError, createSchedulerDashboardFromPersistence, createSchedulerDashboardFromStores, createSchedulerDashboardNodeHandler, createSchedulerDashboardServer, createSchedulerDashboardService, handleSchedulerDashboardRequest, normalizeDashboardBasePath, parseDashboardCliEnv, resolveDashboardApiBase, stripDashboardBasePath };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { r as SchedulerDashboardService } from "./dashboard-types-BHjRLcxJ.mjs";
|
|
2
|
+
import { IncomingMessage, ServerResponse } from "node:http";
|
|
3
|
+
//#region src/dashboard/http-handler.d.ts
|
|
4
|
+
type DashboardAuthorize = (input: {
|
|
5
|
+
method: string;
|
|
6
|
+
pathname: string;
|
|
7
|
+
authorization?: string | string[];
|
|
8
|
+
}) => void | Promise<void>;
|
|
9
|
+
interface SchedulerDashboardHandlerOptions {
|
|
10
|
+
dashboard: SchedulerDashboardService;
|
|
11
|
+
token?: string;
|
|
12
|
+
authorize?: DashboardAuthorize;
|
|
13
|
+
publicDir?: string;
|
|
14
|
+
basePath?: string;
|
|
15
|
+
}
|
|
16
|
+
type SchedulerDashboardRequestHandler = (req: IncomingMessage, res: ServerResponse, next?: (err?: unknown) => void) => void;
|
|
17
|
+
declare function handleSchedulerDashboardRequest(req: IncomingMessage, res: ServerResponse, options: SchedulerDashboardHandlerOptions): Promise<boolean>;
|
|
18
|
+
declare function createSchedulerDashboardNodeHandler(options: SchedulerDashboardHandlerOptions): SchedulerDashboardRequestHandler;
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region src/dashboard/http-server.d.ts
|
|
21
|
+
interface SchedulerDashboardServerOptions extends SchedulerDashboardHandlerOptions {
|
|
22
|
+
port?: number;
|
|
23
|
+
host?: string;
|
|
24
|
+
}
|
|
25
|
+
interface SchedulerDashboardServer {
|
|
26
|
+
readonly port: number;
|
|
27
|
+
readonly host: string;
|
|
28
|
+
listen(): Promise<void>;
|
|
29
|
+
close(): Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
declare function createSchedulerDashboardServer(options: SchedulerDashboardServerOptions): SchedulerDashboardServer;
|
|
32
|
+
//#endregion
|
|
33
|
+
export { SchedulerDashboardHandlerOptions as a, handleSchedulerDashboardRequest as c, DashboardAuthorize as i, SchedulerDashboardServerOptions as n, SchedulerDashboardRequestHandler as o, createSchedulerDashboardServer as r, createSchedulerDashboardNodeHandler as s, SchedulerDashboardServer as t };
|
|
34
|
+
//# sourceMappingURL=http-server-Cme4XKyH.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-server-Cme4XKyH.d.mts","names":[],"sources":["../src/dashboard/http-handler.ts","../src/dashboard/http-server.ts"],"mappings":";;;KA+BY,sBAAsB;EAChC;EACA;EACA;aACW;UAEI;EACf,WAAW;EACX;EACA,YAAY;EACZ;EACA;;KAGU,oCACV,KAAK,iBACL,KAAK,gBACL,QAAQ;iBAuOY,gCACpB,KAAK,iBACL,KAAK,gBACL,SAAS,mCACR;iBAiDa,oCACd,SAAS,mCACR;;;UC5Tc,wCACP;EACR;EACA;;UAGe;WACN;WACA;EACT,UAAU;EACV,SAAS;;iBAGK,+BACd,SAAS,kCACR"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { r as SchedulerDashboardService } from "./dashboard-types-BHjRLcxJ.cjs";
|
|
2
|
+
import { IncomingMessage, ServerResponse } from "node:http";
|
|
3
|
+
//#region src/dashboard/http-handler.d.ts
|
|
4
|
+
type DashboardAuthorize = (input: {
|
|
5
|
+
method: string;
|
|
6
|
+
pathname: string;
|
|
7
|
+
authorization?: string | string[];
|
|
8
|
+
}) => void | Promise<void>;
|
|
9
|
+
interface SchedulerDashboardHandlerOptions {
|
|
10
|
+
dashboard: SchedulerDashboardService;
|
|
11
|
+
token?: string;
|
|
12
|
+
authorize?: DashboardAuthorize;
|
|
13
|
+
publicDir?: string;
|
|
14
|
+
basePath?: string;
|
|
15
|
+
}
|
|
16
|
+
type SchedulerDashboardRequestHandler = (req: IncomingMessage, res: ServerResponse, next?: (err?: unknown) => void) => void;
|
|
17
|
+
declare function handleSchedulerDashboardRequest(req: IncomingMessage, res: ServerResponse, options: SchedulerDashboardHandlerOptions): Promise<boolean>;
|
|
18
|
+
declare function createSchedulerDashboardNodeHandler(options: SchedulerDashboardHandlerOptions): SchedulerDashboardRequestHandler;
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region src/dashboard/http-server.d.ts
|
|
21
|
+
interface SchedulerDashboardServerOptions extends SchedulerDashboardHandlerOptions {
|
|
22
|
+
port?: number;
|
|
23
|
+
host?: string;
|
|
24
|
+
}
|
|
25
|
+
interface SchedulerDashboardServer {
|
|
26
|
+
readonly port: number;
|
|
27
|
+
readonly host: string;
|
|
28
|
+
listen(): Promise<void>;
|
|
29
|
+
close(): Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
declare function createSchedulerDashboardServer(options: SchedulerDashboardServerOptions): SchedulerDashboardServer;
|
|
32
|
+
//#endregion
|
|
33
|
+
export { SchedulerDashboardHandlerOptions as a, handleSchedulerDashboardRequest as c, DashboardAuthorize as i, SchedulerDashboardServerOptions as n, SchedulerDashboardRequestHandler as o, createSchedulerDashboardServer as r, createSchedulerDashboardNodeHandler as s, SchedulerDashboardServer as t };
|
|
34
|
+
//# sourceMappingURL=http-server-u1BnbkAK.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-server-u1BnbkAK.d.cts","names":[],"sources":["../src/dashboard/http-handler.ts","../src/dashboard/http-server.ts"],"mappings":";;;KA+BY,sBAAsB;EAChC;EACA;EACA;aACW;UAEI;EACf,WAAW;EACX;EACA,YAAY;EACZ;EACA;;KAGU,oCACV,KAAK,iBACL,KAAK,gBACL,QAAQ;iBAuOY,gCACpB,KAAK,iBACL,KAAK,gBACL,SAAS,mCACR;iBAiDa,oCACd,SAAS,mCACR;;;UC5Tc,wCACP;EACR;EACA;;UAGe;WACN;WACA;EACT,UAAU;EACV,SAAS;;iBAGK,+BACd,SAAS,kCACR"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@azlib/scheduler",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@azlib/cache": "0.2.2",
|
|
34
34
|
"@azlib/logger": "0.2.2",
|
|
35
|
-
"@azlib/queue": "1.0.5",
|
|
36
35
|
"@azlib/persistence": "0.5.0",
|
|
36
|
+
"@azlib/queue": "1.0.5",
|
|
37
37
|
"@azlib/std": "0.5.0"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
@@ -84,9 +84,9 @@
|
|
|
84
84
|
"registry": "https://registry.npmjs.org"
|
|
85
85
|
},
|
|
86
86
|
"scripts": {
|
|
87
|
-
"build": "rm -rf dist && tsdown && vite build --config
|
|
87
|
+
"build": "rm -rf dist && tsdown && vite build --config monitor/vite.config.ts",
|
|
88
88
|
"dev": "tsdown --watch",
|
|
89
|
-
"lint": "tsc -p tsconfig.json --noEmit && tsc -p
|
|
89
|
+
"lint": "tsc -p tsconfig.json --noEmit && tsc -p monitor/tsconfig.json --noEmit",
|
|
90
90
|
"test": "vitest run --project unit --project ui",
|
|
91
91
|
"test:browser": "vitest run --project browser",
|
|
92
92
|
"test:browser:headed": "vitest run --project browser --browser.headless=false",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cli-config-7F2U8qPM.mjs","names":[],"sources":["../src/dashboard/http-auth.ts","../src/dashboard/http-parse.ts","../src/dashboard/public-dir.ts","../src/dashboard/http-server.ts","../src/dashboard/sql-drivers.ts","../src/dashboard/cli-config.ts"],"sourcesContent":["export class DashboardHttpError extends Error {\n readonly status: number;\n\n constructor(status: number, message: string) {\n super(message);\n this.name = \"DashboardHttpError\";\n this.status = status;\n }\n}\n\nexport function isLoopbackHost(host: string): boolean {\n const normalized = host.trim().toLowerCase();\n return (\n normalized === \"127.0.0.1\" ||\n normalized === \"localhost\" ||\n normalized === \"::1\" ||\n normalized === \"[::1]\"\n );\n}\n\nexport function authorizeDashboardRequest(input: {\n token?: string;\n authorization?: string | string[] | undefined;\n}): void {\n if (!input.token) {\n return;\n }\n const header = Array.isArray(input.authorization)\n ? input.authorization[0]\n : input.authorization;\n const expected = `Bearer ${input.token}`;\n if (header !== expected) {\n throw new DashboardHttpError(401, \"Unauthorized\");\n }\n}\n\nexport function assertDashboardBindSafety(input: {\n host: string;\n token?: string;\n}): void {\n if (!isLoopbackHost(input.host) && !input.token) {\n throw new Error(\n \"DASHBOARD_TOKEN is required when HOST is not a loopback address\",\n );\n }\n}\n","import { asBoolean, asRecord, asString } from \"@azlib/std\";\n\nimport type { SchedulerJobDefinition } from \"../contracts/scheduler-types.js\";\nimport { parseSchedule } from \"../core/schedule-parser.js\";\nimport { DashboardHttpError } from \"./http-auth.js\";\n\nconst DEFAULT_TIMEZONE = \"UTC\";\n\nfunction requiredText(value: unknown, field: string): string {\n const text = asString(value)?.trim();\n if (!text) {\n throw new DashboardHttpError(400, `${field} is required.`);\n }\n return text;\n}\n\nfunction parseConfig(value: unknown): unknown {\n if (value === undefined || value === null || value === \"\") {\n return {};\n }\n if (typeof value === \"string\") {\n try {\n return JSON.parse(value) as unknown;\n } catch {\n throw new DashboardHttpError(400, \"config must be valid JSON.\");\n }\n }\n return value;\n}\n\nfunction parseScheduleFromRecord(\n record: Record<string, unknown>,\n): SchedulerJobDefinition[\"schedule\"] {\n const nested = asRecord(record.schedule);\n const scheduleType =\n asString(record.scheduleType)?.trim() ||\n asString(nested?.scheduleType)?.trim() ||\n \"cron\";\n if (scheduleType !== \"cron\" && scheduleType !== \"once\") {\n throw new DashboardHttpError(400, \"scheduleType must be cron or once.\");\n }\n const expression = requiredText(\n record.expression ?? nested?.expression,\n \"expression\",\n );\n const timezone =\n asString(record.timezone)?.trim() ||\n asString(nested?.timezone)?.trim() ||\n DEFAULT_TIMEZONE;\n parseSchedule(scheduleType, expression, timezone);\n return {\n scheduleType,\n expression,\n timezone,\n };\n}\n\nexport function parseCreateJobBody(body: unknown): SchedulerJobDefinition {\n const record = asRecord(body);\n if (!record) {\n throw new DashboardHttpError(400, \"Request body must be a JSON object.\");\n }\n return {\n name: requiredText(record.name, \"name\"),\n handlerKey: requiredText(record.handlerKey, \"handlerKey\"),\n schedule: parseScheduleFromRecord(record),\n config: parseConfig(record.config),\n enabled: asBoolean(record.enabled) ?? true,\n };\n}\n\nexport function parseUpdateJobBody(\n body: unknown,\n): Partial<SchedulerJobDefinition> {\n const record = asRecord(body);\n if (!record) {\n throw new DashboardHttpError(400, \"Request body must be a JSON object.\");\n }\n const patch: Partial<SchedulerJobDefinition> = {};\n if (record.name !== undefined) {\n patch.name = requiredText(record.name, \"name\");\n }\n if (record.handlerKey !== undefined) {\n patch.handlerKey = requiredText(record.handlerKey, \"handlerKey\");\n }\n if (\n record.expression !== undefined ||\n record.timezone !== undefined ||\n record.scheduleType !== undefined ||\n record.schedule !== undefined\n ) {\n patch.schedule = parseScheduleFromRecord(record);\n }\n if (record.config !== undefined) {\n patch.config = parseConfig(record.config);\n }\n if (record.enabled !== undefined) {\n patch.enabled = asBoolean(record.enabled) ?? true;\n }\n return patch;\n}\n","import { existsSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport function resolveDashboardPublicDir(fromFileUrl: string): string {\n const dir = dirname(fileURLToPath(fromFileUrl));\n const nested = join(dir, \"public\");\n const sibling = join(dir, \"dashboard\", \"public\");\n if (existsSync(join(nested, \"index.html\"))) {\n return nested;\n }\n if (existsSync(join(sibling, \"index.html\"))) {\n return sibling;\n }\n return nested;\n}\n","import {\n createReadStream,\n existsSync,\n statSync,\n} from \"node:fs\";\nimport * as http from \"node:http\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { extname, join, relative, resolve, sep } from \"node:path\";\n\nimport type { SchedulerDashboardService } from \"./dashboard-types.js\";\nimport {\n authorizeDashboardRequest,\n DashboardHttpError,\n} from \"./http-auth.js\";\nimport { parseCreateJobBody, parseUpdateJobBody } from \"./http-parse.js\";\nimport { resolveDashboardPublicDir } from \"./public-dir.js\";\n\nconst MIME_TYPES: Record<string, string> = {\n \".css\": \"text/css; charset=utf-8\",\n \".html\": \"text/html; charset=utf-8\",\n \".js\": \"text/javascript; charset=utf-8\",\n \".json\": \"application/json; charset=utf-8\",\n \".map\": \"application/json; charset=utf-8\",\n \".svg\": \"image/svg+xml\",\n \".woff2\": \"font/woff2\",\n};\n\nexport interface SchedulerDashboardServerOptions {\n dashboard: SchedulerDashboardService;\n port?: number;\n host?: string;\n token?: string;\n publicDir?: string;\n}\n\nexport interface SchedulerDashboardServer {\n readonly port: number;\n readonly host: string;\n listen(): Promise<void>;\n close(): Promise<void>;\n}\n\nfunction sendJson(\n res: ServerResponse,\n status: number,\n body: unknown,\n): void {\n res.writeHead(status, { \"Content-Type\": \"application/json; charset=utf-8\" });\n res.end(JSON.stringify(body));\n}\n\nfunction sendError(res: ServerResponse, error: unknown): void {\n if (error instanceof DashboardHttpError) {\n sendJson(res, error.status, { error: error.message });\n return;\n }\n const message = error instanceof Error ? error.message : \"Unknown error\";\n const status = message.includes(\"not found\")\n ? 404\n : message.includes(\"Only failed\")\n ? 400\n : message.includes(\"Unknown handlerKey\")\n ? 400\n : 500;\n sendJson(res, status, { error: message });\n}\n\nasync function readJsonBody(req: IncomingMessage): Promise<unknown> {\n const chunks: Buffer[] = [];\n for await (const chunk of req) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n if (chunks.length === 0) {\n return {};\n }\n const raw = Buffer.concat(chunks).toString(\"utf8\");\n if (!raw.trim()) {\n return {};\n }\n try {\n return JSON.parse(raw) as unknown;\n } catch {\n throw new DashboardHttpError(400, \"Request body must be valid JSON.\");\n }\n}\n\nfunction matchPath(\n pathname: string,\n pattern: string,\n): Record<string, string> | null {\n const pathParts = pathname.split(\"/\").filter(Boolean);\n const patternParts = pattern.split(\"/\").filter(Boolean);\n if (pathParts.length !== patternParts.length) {\n return null;\n }\n const params: Record<string, string> = {};\n for (let i = 0; i < patternParts.length; i += 1) {\n const expected = patternParts[i] ?? \"\";\n const actual = pathParts[i] ?? \"\";\n if (expected.startsWith(\":\")) {\n params[expected.slice(1)] = decodeURIComponent(actual);\n continue;\n }\n if (expected !== actual) {\n return null;\n }\n }\n return params;\n}\n\nfunction servePublicFile(\n publicDir: string,\n urlPath: string,\n res: ServerResponse,\n): boolean {\n if (!existsSync(publicDir)) {\n return false;\n }\n const pathname = decodeURIComponent(urlPath.split(\"?\")[0] ?? \"/\");\n const requested = pathname === \"/\" ? \"/index.html\" : pathname;\n const abs = resolve(publicDir, `.${requested}`);\n const rel = relative(resolve(publicDir), abs);\n if (rel.startsWith(\"..\") || rel.includes(`..${sep}`)) {\n return false;\n }\n\n const filePath =\n existsSync(abs) && statSync(abs).isFile()\n ? abs\n : join(publicDir, \"index.html\");\n if (!existsSync(filePath) || !statSync(filePath).isFile()) {\n return false;\n }\n\n const type = MIME_TYPES[extname(filePath)] ?? \"application/octet-stream\";\n res.writeHead(200, { \"Content-Type\": type });\n createReadStream(filePath).pipe(res);\n return true;\n}\n\nexport function createSchedulerDashboardServer(\n options: SchedulerDashboardServerOptions,\n): SchedulerDashboardServer {\n const port = options.port ?? 9100;\n const host = options.host ?? \"127.0.0.1\";\n const publicDir =\n options.publicDir ?? resolveDashboardPublicDir(import.meta.url);\n const dashboard = options.dashboard;\n\n const server = http.createServer((req, res) => {\n void handleRequest(req, res).catch((error: unknown) => {\n if (!res.headersSent) {\n sendError(res, error);\n }\n });\n });\n\n async function handleRequest(\n req: IncomingMessage,\n res: ServerResponse,\n ): Promise<void> {\n const method = req.method ?? \"GET\";\n const url = new URL(req.url ?? \"/\", `http://${host}:${port}`);\n const pathname = url.pathname;\n\n if (method === \"GET\" && pathname === \"/health\") {\n res.writeHead(200, { \"Content-Type\": \"text/plain; charset=utf-8\" });\n res.end(\"ok\");\n return;\n }\n\n if (pathname === \"/api\" || pathname.startsWith(\"/api/\")) {\n authorizeDashboardRequest({\n token: options.token,\n authorization: req.headers.authorization,\n });\n await handleApi(method, pathname, req, res);\n return;\n }\n\n if (method === \"GET\" && servePublicFile(publicDir, pathname, res)) {\n return;\n }\n\n res.writeHead(404, { \"Content-Type\": \"text/plain; charset=utf-8\" });\n res.end(\"Not Found\");\n }\n\n async function handleApi(\n method: string,\n pathname: string,\n req: IncomingMessage,\n res: ServerResponse,\n ): Promise<void> {\n try {\n if (method === \"GET\" && pathname === \"/api/health\") {\n sendJson(res, 200, await dashboard.getHealth());\n return;\n }\n\n if (method === \"GET\" && pathname === \"/api/handlers\") {\n sendJson(res, 200, { handlers: dashboard.listHandlerKeys() });\n return;\n }\n\n if (method === \"GET\" && pathname === \"/api/jobs\") {\n sendJson(res, 200, { items: await dashboard.listItems() });\n return;\n }\n\n if (method === \"POST\" && pathname === \"/api/jobs\") {\n const created = await dashboard.createJob(\n parseCreateJobBody(await readJsonBody(req)),\n );\n sendJson(res, 201, created);\n return;\n }\n\n const jobExec = matchPath(pathname, \"/api/jobs/:jobId/executions\");\n if (jobExec && method === \"GET\") {\n sendJson(res, 200, {\n executions: await dashboard.listExecutions(jobExec.jobId ?? \"\"),\n });\n return;\n }\n\n const jobAction = matchPath(pathname, \"/api/jobs/:jobId/:action\");\n if (jobAction && method === \"POST\") {\n const jobId = jobAction.jobId ?? \"\";\n if (jobAction.action === \"pause\") {\n await dashboard.pauseJob(jobId);\n res.writeHead(204);\n res.end();\n return;\n }\n if (jobAction.action === \"resume\") {\n await dashboard.resumeJob(jobId);\n res.writeHead(204);\n res.end();\n return;\n }\n if (jobAction.action === \"run\") {\n await dashboard.runJob(jobId);\n res.writeHead(204);\n res.end();\n return;\n }\n }\n\n const retry = matchPath(pathname, \"/api/executions/:executionId/retry\");\n if (retry && method === \"POST\") {\n await dashboard.retryExecution(retry.executionId ?? \"\");\n res.writeHead(204);\n res.end();\n return;\n }\n\n const job = matchPath(pathname, \"/api/jobs/:jobId\");\n if (job) {\n const jobId = job.jobId ?? \"\";\n if (method === \"GET\") {\n const item = await dashboard.getJob(jobId);\n if (!item) {\n throw new DashboardHttpError(404, `Job not found: ${jobId}`);\n }\n sendJson(res, 200, item);\n return;\n }\n if (method === \"PATCH\") {\n await dashboard.updateJob(\n jobId,\n parseUpdateJobBody(await readJsonBody(req)),\n );\n res.writeHead(204);\n res.end();\n return;\n }\n if (method === \"DELETE\") {\n await dashboard.deleteJob(jobId);\n res.writeHead(204);\n res.end();\n return;\n }\n }\n\n sendJson(res, 404, { error: \"Not Found\" });\n } catch (error) {\n sendError(res, error);\n }\n }\n\n return {\n get port() {\n return port;\n },\n get host() {\n return host;\n },\n listen(): Promise<void> {\n return new Promise((resolveListen, reject) => {\n server.once(\"error\", reject);\n server.listen(port, host, () => {\n server.off(\"error\", reject);\n resolveListen();\n });\n });\n },\n close(): Promise<void> {\n return new Promise((resolveClose, reject) => {\n server.close((err) => (err ? reject(err) : resolveClose()));\n });\n },\n };\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport {\n createMySqlDialectAdapter,\n createPostgresDialectAdapter,\n createSqlClientAdapter,\n createSqlServerDialectAdapter,\n createSqliteDialectAdapter,\n type SqlDialectAdapter,\n type SqlDriverLike,\n} from \"@azlib/persistence\";\n\nexport type SchedulerDashboardDialect =\n | \"postgres\"\n | \"mysql\"\n | \"sqlite\"\n | \"mssql\";\n\nexport function rewriteQuestionParams(\n sql: string,\n style: \"$n\" | \"?\" | \"@pn\",\n): string {\n if (style === \"?\") {\n return sql;\n }\n let index = 0;\n return sql.replaceAll(\"?\", () => {\n index += 1;\n return style === \"$n\" ? `$${index}` : `@p${index}`;\n });\n}\n\nexport function inferDashboardDialect(\n databaseUrl: string,\n): SchedulerDashboardDialect {\n const scheme = databaseUrl.split(\":\")[0]?.toLowerCase() ?? \"\";\n if (scheme === \"postgres\" || scheme === \"postgresql\") {\n return \"postgres\";\n }\n if (scheme === \"mysql\" || scheme === \"mariadb\") {\n return \"mysql\";\n }\n if (scheme === \"mssql\" || scheme === \"sqlserver\") {\n return \"mssql\";\n }\n if (scheme === \"sqlite\" || scheme === \"file\") {\n return \"sqlite\";\n }\n return \"postgres\";\n}\n\nexport function dialectAdapterFor(\n dialect: SchedulerDashboardDialect,\n): SqlDialectAdapter {\n if (dialect === \"mysql\") {\n return createMySqlDialectAdapter();\n }\n if (dialect === \"sqlite\") {\n return createSqliteDialectAdapter();\n }\n if (dialect === \"mssql\") {\n return createSqlServerDialectAdapter();\n }\n return createPostgresDialectAdapter();\n}\n\nfunction sqlitePathFromUrl(databaseUrl: string): string {\n if (databaseUrl.startsWith(\"file:\")) {\n return databaseUrl.slice(\"file:\".length);\n }\n if (databaseUrl.startsWith(\"sqlite:\")) {\n return databaseUrl.slice(\"sqlite:\".length);\n }\n return databaseUrl;\n}\n\ntype PgQueryable = {\n query: (\n sql: string,\n params?: unknown[],\n ) => Promise<{ rows: unknown[] }>;\n};\n\ntype PgPool = PgQueryable & {\n connect: () => Promise<PgQueryable & { release: () => void }>;\n};\n\ntype MysqlConn = {\n execute: (\n sql: string,\n params?: unknown[],\n ) => Promise<[unknown, unknown]>;\n beginTransaction: () => Promise<void>;\n commit: () => Promise<void>;\n rollback: () => Promise<void>;\n release: () => void;\n};\n\ntype MysqlPool = {\n execute: (\n sql: string,\n params?: unknown[],\n ) => Promise<[unknown, unknown]>;\n getConnection: () => Promise<MysqlConn>;\n};\n\ntype SqliteDatabase = {\n prepare: (sql: string) => {\n all: (...params: unknown[]) => unknown[];\n run: (...params: unknown[]) => unknown;\n };\n};\n\ntype MssqlRequest = {\n input: (name: string, value: unknown) => void;\n query: (sql: string) => Promise<{ recordset: unknown[] }>;\n};\n\ntype MssqlPool = {\n request: () => MssqlRequest;\n};\n\nfunction bindMssqlParams(\n request: MssqlRequest,\n params: readonly unknown[] | undefined,\n): void {\n (params ?? []).forEach((value, index) => {\n request.input(`p${index + 1}`, value);\n });\n}\n\nfunction createPgDriver(pool: PgPool): SqlDriverLike {\n const txStore = new AsyncLocalStorage<PgQueryable>();\n const active = (): PgQueryable => txStore.getStore() ?? pool;\n const runQuery = async (sql: string, params?: readonly unknown[]) =>\n active().query(rewriteQuestionParams(sql, \"$n\"), [...(params ?? [])]);\n\n return {\n query: async <T = unknown>(sql: string, params?: readonly unknown[]) => {\n const result = await runQuery(sql, params);\n return result.rows as T[];\n },\n execute: async (sql: string, params?: readonly unknown[]) => {\n await runQuery(sql, params);\n },\n transaction: async <T>(run: () => Promise<T>): Promise<T> => {\n const existing = txStore.getStore();\n if (existing) {\n return run();\n }\n const conn = await pool.connect();\n try {\n await conn.query(\"BEGIN\");\n const result = await txStore.run(conn, run);\n await conn.query(\"COMMIT\");\n return result;\n } catch (error) {\n await conn.query(\"ROLLBACK\");\n throw error;\n } finally {\n conn.release();\n }\n },\n };\n}\n\nfunction createMysqlDriver(pool: MysqlPool): SqlDriverLike {\n const txStore = new AsyncLocalStorage<MysqlConn | MysqlPool>();\n const active = (): MysqlConn | MysqlPool => txStore.getStore() ?? pool;\n\n return {\n query: async <T = unknown>(sql: string, params?: readonly unknown[]) => {\n const [rows] = await active().execute(sql, [...(params ?? [])]);\n return rows as T[];\n },\n execute: async (sql: string, params?: readonly unknown[]) => {\n await active().execute(sql, [...(params ?? [])]);\n },\n transaction: async <T>(run: () => Promise<T>): Promise<T> => {\n const existing = txStore.getStore();\n if (existing) {\n return run();\n }\n const conn = await pool.getConnection();\n try {\n await conn.beginTransaction();\n const result = await txStore.run(conn, run);\n await conn.commit();\n return result;\n } catch (error) {\n await conn.rollback();\n throw error;\n } finally {\n conn.release();\n }\n },\n };\n}\n\nexport async function createDashboardSqlDriver(\n databaseUrl: string,\n dialect: SchedulerDashboardDialect,\n): Promise<SqlDriverLike> {\n if (dialect === \"postgres\") {\n const pg = (await import(\"pg\")) as {\n default?: { Pool: new (config: { connectionString: string }) => PgPool };\n Pool?: new (config: { connectionString: string }) => PgPool;\n };\n const Pool = pg.Pool ?? pg.default?.Pool;\n if (!Pool) {\n throw new Error(\"The pg package is required for postgres dashboards.\");\n }\n return createPgDriver(new Pool({ connectionString: databaseUrl }));\n }\n\n if (dialect === \"mysql\") {\n const mysql = (await import(\"mysql2/promise\")) as {\n default?: { createPool: (url: string) => MysqlPool };\n createPool?: (url: string) => MysqlPool;\n };\n const createPool = mysql.createPool ?? mysql.default?.createPool;\n if (!createPool) {\n throw new Error(\"The mysql2 package is required for mysql dashboards.\");\n }\n return createMysqlDriver(createPool(databaseUrl));\n }\n\n if (dialect === \"sqlite\") {\n const sqlite = (await import(\"better-sqlite3\")) as {\n default?: new (path: string) => SqliteDatabase;\n };\n const Database = sqlite.default;\n if (!Database) {\n throw new Error(\n \"The better-sqlite3 package is required for sqlite dashboards.\",\n );\n }\n const db = new Database(sqlitePathFromUrl(databaseUrl));\n return {\n query: async <T = unknown>(sql: string, params?: readonly unknown[]) =>\n db.prepare(sql).all(...(params ?? [])) as T[],\n execute: async (sql: string, params?: readonly unknown[]) => {\n db.prepare(sql).run(...(params ?? []));\n },\n transaction: async <T>(run: () => Promise<T>): Promise<T> => run(),\n };\n }\n\n const mssql = (await import(\"mssql\")) as {\n default?: { connect: (url: string) => Promise<MssqlPool> };\n connect?: (url: string) => Promise<MssqlPool>;\n };\n const connect = mssql.connect ?? mssql.default?.connect;\n if (!connect) {\n throw new Error(\"The mssql package is required for mssql dashboards.\");\n }\n const pool = await connect(databaseUrl);\n return {\n query: async <T = unknown>(sql: string, params?: readonly unknown[]) => {\n const request = pool.request();\n bindMssqlParams(request, params);\n const result = await request.query(rewriteQuestionParams(sql, \"@pn\"));\n return result.recordset as T[];\n },\n execute: async (sql: string, params?: readonly unknown[]) => {\n const request = pool.request();\n bindMssqlParams(request, params);\n await request.query(rewriteQuestionParams(sql, \"@pn\"));\n },\n transaction: async <T>(run: () => Promise<T>): Promise<T> => run(),\n };\n}\n\nexport function createDashboardPersistenceConfig(input: {\n driver: SqlDriverLike;\n dialect: SchedulerDashboardDialect;\n namespace?: string;\n}) {\n return {\n client: createSqlClientAdapter(input.driver),\n dialect: dialectAdapterFor(input.dialect),\n namespace: input.namespace,\n };\n}\n","import { asString } from \"@azlib/std\";\n\nimport { assertDashboardBindSafety } from \"./http-auth.js\";\nimport {\n inferDashboardDialect,\n type SchedulerDashboardDialect,\n} from \"./sql-drivers.js\";\n\nexport interface SchedulerDashboardCliConfig {\n databaseUrl: string;\n dialect: SchedulerDashboardDialect;\n namespace: string;\n port: number;\n host: string;\n token?: string;\n}\n\nfunction parsePort(value: string | undefined, fallback: number): number {\n if (!value) {\n return fallback;\n }\n const port = Number(value);\n if (!Number.isInteger(port) || port <= 0 || port > 65535) {\n throw new Error(`Invalid PORT: ${value}`);\n }\n return port;\n}\n\nfunction parseDialect(\n value: string | undefined,\n databaseUrl: string,\n): SchedulerDashboardDialect {\n const explicit = value?.trim().toLowerCase();\n if (!explicit) {\n return inferDashboardDialect(databaseUrl);\n }\n if (\n explicit === \"postgres\" ||\n explicit === \"mysql\" ||\n explicit === \"sqlite\" ||\n explicit === \"mssql\"\n ) {\n return explicit;\n }\n throw new Error(\n `Invalid SCHEDULER_DIALECT: ${value}. Use postgres, mysql, sqlite, or mssql.`,\n );\n}\n\nexport function parseDashboardCliEnv(\n env: Record<string, string | undefined>,\n): SchedulerDashboardCliConfig {\n const databaseUrl = asString(env.DATABASE_URL)?.trim();\n if (!databaseUrl) {\n throw new Error(\"DATABASE_URL is required\");\n }\n\n const host = asString(env.HOST)?.trim() || \"127.0.0.1\";\n const token = asString(env.DASHBOARD_TOKEN)?.trim() || undefined;\n assertDashboardBindSafety({ host, token });\n\n return {\n databaseUrl,\n dialect: parseDialect(env.SCHEDULER_DIALECT, databaseUrl),\n namespace: asString(env.SCHEDULER_NAMESPACE)?.trim() || \"azlib\",\n port: parsePort(env.PORT, 9100),\n host,\n token,\n };\n}\n"],"mappings":"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"}
|