@nola-lang/console 0.1.4

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.
@@ -0,0 +1,36 @@
1
+ import { type ConsoleNotice } from "./core/service.js";
2
+ export declare const CONSOLE_DEFAULT_PORT = 4141;
3
+ /**
4
+ * The console is one instance per dev machine, so its root folder is
5
+ * per-machine, not per-project: `~/.nola/console`. Everything the console
6
+ * keeps lives under it — the database at `data/console.db` today, further
7
+ * settings later. `StartConsoleOptions.path` is the only override.
8
+ */
9
+ export declare function defaultConsolePath(): string;
10
+ /** The SQLite database inside a console root. */
11
+ export declare function consoleDbPath(root: string): string;
12
+ export interface StartConsoleOptions {
13
+ /** Exact port to bind — no scanning (0 = OS-assigned). Default: scan upward from 4141. */
14
+ port?: number;
15
+ /** Default 127.0.0.1 — loopback only (console design §13). */
16
+ host?: string;
17
+ /** The console's root folder — default `~/.nola/console`; created on demand. The database lives at `<path>/data/console.db`. */
18
+ path?: string;
19
+ /** Directory of the built UI. Default: `ui/` beside the compiled module (dist/ui in the published package); absent falls back to the placeholder page. */
20
+ uiDir?: string;
21
+ }
22
+ export interface RunningConsole {
23
+ url: string;
24
+ port: number;
25
+ /** The console root (`StartConsoleOptions.path` resolved). */
26
+ path: string;
27
+ /** The SQLite database inside the root. */
28
+ dbPath: string;
29
+ /** Subscribe to every ingested envelope and the `cleared` notice (the same fan-out the SSE stream reads); returns the unsubscribe. */
30
+ onEvent(listener: (notice: ConsoleNotice) => void): () => void;
31
+ close(): Promise<void>;
32
+ }
33
+ export declare function findFreePort(host: string, start: number, attempts?: number): Promise<number>;
34
+ /** Open storage, mount the app, bind loopback — one process, one local database (console design §13). */
35
+ export declare function startConsole(options?: StartConsoleOptions): Promise<RunningConsole>;
36
+ //# sourceMappingURL=start.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../src/start.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,aAAa,EAAkB,MAAM,mBAAmB,CAAC;AAIvE,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,iDAAiD;AACjD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,MAAM,WAAW,mBAAmB;IAClC,0FAA0F;IAC1F,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gIAAgI;IAChI,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0JAA0J;IAC1J,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,sIAAsI;IACtI,OAAO,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAC/D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAU9F;AAED,yGAAyG;AACzG,wBAAsB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,cAAc,CAAC,CA4B7F"}
package/dist/start.js ADDED
@@ -0,0 +1,66 @@
1
+ import { mkdirSync } from "node:fs";
2
+ import { createServer } from "node:net";
3
+ import { homedir } from "node:os";
4
+ import { dirname, join } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { serve } from "@hono/node-server";
7
+ import { ConsoleService } from "./core/service.js";
8
+ import { createApp } from "./server/app.js";
9
+ import { SqliteConsoleStorage } from "./storage/sqlite.js";
10
+ export const CONSOLE_DEFAULT_PORT = 4141;
11
+ /**
12
+ * The console is one instance per dev machine, so its root folder is
13
+ * per-machine, not per-project: `~/.nola/console`. Everything the console
14
+ * keeps lives under it — the database at `data/console.db` today, further
15
+ * settings later. `StartConsoleOptions.path` is the only override.
16
+ */
17
+ export function defaultConsolePath() {
18
+ return join(homedir(), ".nola", "console");
19
+ }
20
+ /** The SQLite database inside a console root. */
21
+ export function consoleDbPath(root) {
22
+ return join(root, "data", "console.db");
23
+ }
24
+ export async function findFreePort(host, start, attempts = 20) {
25
+ for (let port = start; port < start + attempts; port++) {
26
+ const free = await new Promise((resolve) => {
27
+ const probe = createServer();
28
+ probe.once("error", () => resolve(false));
29
+ probe.listen({ port, host }, () => probe.close(() => resolve(true)));
30
+ });
31
+ if (free)
32
+ return port;
33
+ }
34
+ throw new Error(`No free port found in ${start}..${start + attempts - 1}.`);
35
+ }
36
+ /** Open storage, mount the app, bind loopback — one process, one local database (console design §13). */
37
+ export async function startConsole(options = {}) {
38
+ const host = options.host ?? "127.0.0.1";
39
+ const path = options.path ?? defaultConsolePath();
40
+ const dbPath = consoleDbPath(path);
41
+ mkdirSync(dirname(dbPath), { recursive: true });
42
+ const storage = new SqliteConsoleStorage(dbPath);
43
+ const service = new ConsoleService(storage);
44
+ const uiDir = options.uiDir ?? fileURLToPath(new URL("ui/", import.meta.url));
45
+ const app = createApp(service, { uiDir });
46
+ const port = options.port ?? (await findFreePort(host, CONSOLE_DEFAULT_PORT));
47
+ const server = await new Promise((resolve, reject) => {
48
+ const s = serve({ fetch: app.fetch, port, hostname: host }, () => resolve(s));
49
+ s.once("error", reject);
50
+ });
51
+ // An explicit port 0 binds an OS-assigned port — report the real one.
52
+ const address = server.address();
53
+ const boundPort = typeof address === "object" && address !== null ? address.port : port;
54
+ return {
55
+ url: `http://${host}:${boundPort}`,
56
+ port: boundPort,
57
+ path,
58
+ dbPath,
59
+ onEvent: (listener) => service.onEvent(listener),
60
+ close: async () => {
61
+ await new Promise((resolve, reject) => server.close((err) => (err ? reject(err) : resolve())));
62
+ await storage.close();
63
+ },
64
+ };
65
+ }
66
+ //# sourceMappingURL=start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../src/start.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { NolaIngestEnvelope } from "@nola-lang/core";
2
+ import type { AskDetail, ConsoleStorage, DefinitionDetail, DefinitionSummary, ProjectSummary, RecordsQuery, TraceDetail, TraceRecord } from "./types.js";
3
+ /** Local trace store over node:sqlite. All reduction is SQL upserts, so event arrival order does not matter. */
4
+ export declare class SqliteConsoleStorage implements ConsoleStorage {
5
+ #private;
6
+ constructor(path: string);
7
+ ingest(envelope: NolaIngestEnvelope): Promise<void>;
8
+ listProjects(): Promise<ProjectSummary[]>;
9
+ listRecords(query?: RecordsQuery): Promise<TraceRecord[]>;
10
+ getTrace(invocationId: string): Promise<TraceDetail | undefined>;
11
+ getAsk(askId: string): Promise<AskDetail | undefined>;
12
+ listDefinitions(query?: {
13
+ project?: string;
14
+ noProject?: boolean;
15
+ }): Promise<DefinitionSummary[]>;
16
+ getDefinition(def: string): Promise<DefinitionDetail | undefined>;
17
+ clear(): Promise<void>;
18
+ close(): Promise<void>;
19
+ }
20
+ //# sourceMappingURL=sqlite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/storage/sqlite.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAW,kBAAkB,EAAkB,MAAM,iBAAiB,CAAC;AAEnF,OAAO,KAAK,EACV,SAAS,EAIT,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EAGjB,cAAc,EACd,YAAY,EACZ,WAAW,EACX,WAAW,EACZ,MAAM,YAAY,CAAC;AA2KpB,gHAAgH;AAChH,qBAAa,oBAAqB,YAAW,cAAc;;gBAG7C,IAAI,EAAE,MAAM;IA+DlB,MAAM,CAAC,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAkNnD,YAAY,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAiFzC,WAAW,CAAC,KAAK,GAAE,YAAiB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAoB7D,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAwBhE,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IAiErD,eAAe,CAAC,KAAK,GAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAepG,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC;IAWjE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAOtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}