This commit is contained in:
Dax Raad
2025-05-26 14:52:38 -04:00
parent 802389a90e
commit b87ba57819
5 changed files with 63 additions and 25 deletions

View File

@@ -22,7 +22,13 @@ export namespace App {
log.info("created", { path: dataDir }); log.info("created", { path: dataDir });
const services = new Map<any, any>(); const services = new Map<
any,
{
state: any;
shutdown?: (input: any) => Promise<void>;
}
>();
const result = { const result = {
get services() { get services() {
@@ -39,15 +45,22 @@ export namespace App {
return result; return result;
} }
export function state<T extends (app: Info) => any>(key: any, init: T) { export function state<State>(
key: any,
init: (app: Info) => State,
shutdown?: (state: Awaited<State>) => Promise<void>,
) {
return () => { return () => {
const app = ctx.use(); const app = ctx.use();
const services = app.services; const services = app.services;
if (!services.has(key)) { if (!services.has(key)) {
log.info("registering service", { name: key }); log.info("registering service", { name: key });
services.set(key, init(app)); services.set(key, {
state: init(app),
shutdown: shutdown,
});
} }
return services.get(key) as ReturnType<T>; return services.get(key)?.state as State;
}; };
} }
@@ -62,7 +75,12 @@ export namespace App {
const app = await create(input); const app = await create(input);
return ctx.provide(app, async () => { return ctx.provide(app, async () => {
return cb(app); const result = await cb(app);
for (const [key, entry] of app.services.entries()) {
log.info("shutdown", { name: key });
await entry.shutdown?.(await entry.state);
}
return result;
}); });
} }
} }

View File

@@ -30,11 +30,20 @@ export namespace Identifier {
descending: boolean, descending: boolean,
given?: string, given?: string,
): string { ): string {
if (given) { if (!given) {
if (given.startsWith(prefixes[prefix])) return given; return generateNewID(prefix, descending);
throw new Error(`ID ${given} does not start with ${prefixes[prefix]}`);
} }
if (!given.startsWith(prefixes[prefix])) {
throw new Error(`ID ${given} does not start with ${prefixes[prefix]}`);
}
return given;
}
function generateNewID(
prefix: keyof typeof prefixes,
descending: boolean,
): string {
const currentTimestamp = Date.now(); const currentTimestamp = Date.now();
if (currentTimestamp !== lastTimestamp) { if (currentTimestamp !== lastTimestamp) {
@@ -45,9 +54,7 @@ export namespace Identifier {
let now = BigInt(currentTimestamp) * BigInt(0x1000) + BigInt(counter); let now = BigInt(currentTimestamp) * BigInt(0x1000) + BigInt(counter);
if (descending) { now = descending ? ~now : now;
now = ~now;
}
const timeBytes = Buffer.alloc(6); const timeBytes = Buffer.alloc(6);
for (let i = 0; i < 6; i++) { for (let i = 0; i < 6; i++) {

View File

@@ -178,6 +178,11 @@ export namespace LSPClient {
}), }),
]); ]);
}, },
async shutdown() {
log.info("shutting down");
connection.end();
connection.dispose();
},
}; };
return result; return result;

View File

@@ -5,22 +5,30 @@ import { LSPClient } from "./client";
export namespace LSP { export namespace LSP {
const log = Log.create({ service: "lsp" }); const log = Log.create({ service: "lsp" });
const state = App.state("lsp", async () => { const state = App.state(
const clients = new Map<string, LSPClient.Info>(); "lsp",
async () => {
const clients = new Map<string, LSPClient.Info>();
// QUESTION: how lazy should lsp auto discovery be? should it not initialize until a file is opened? // QUESTION: how lazy should lsp auto discovery be? should it not initialize until a file is opened?
clients.set( clients.set(
"typescript", "typescript",
await LSPClient.create({ await LSPClient.create({
cmd: ["bun", "x", "typescript-language-server", "--stdio"], cmd: ["bun", "x", "typescript-language-server", "--stdio"],
}), }),
); );
return { return {
clients, clients,
diagnostics: new Map<string, any>(), diagnostics: new Map<string, any>(),
}; };
}); },
async (state) => {
for (const client of state.clients.values()) {
await client.shutdown();
}
},
);
export async function run<T>( export async function run<T>(
input: (client: LSPClient.Info) => Promise<T>, input: (client: LSPClient.Info) => Promise<T>,

View File

@@ -1,4 +1,4 @@
export const LANGUAGE_EXTENSIONS = { export const LANGUAGE_EXTENSIONS: Record<string, string> = {
".abap": "abap", ".abap": "abap",
".bat": "bat", ".bat": "bat",
".bib": "bibtex", ".bib": "bibtex",