mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-15 20:17:22 +00:00
refactor registries to make registration more convenient
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { describe, test } from "bun:test";
|
import { describe, expect, test } from "bun:test";
|
||||||
import type { TObject, TString } from "@sinclair/typebox";
|
import type { TObject, TString } from "@sinclair/typebox";
|
||||||
import { Registry } from "../../src/core/registry/Registry";
|
import { Registry } from "../../src/core/registry/Registry";
|
||||||
import { type TSchema, Type } from "../../src/core/utils";
|
import { type TSchema, Type } from "../../src/core/utils";
|
||||||
@@ -11,6 +11,9 @@ class What {
|
|||||||
method() {
|
method() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
getType() {
|
||||||
|
return Type.Object({ type: Type.String() });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
class What2 extends What {}
|
class What2 extends What {}
|
||||||
class NotAllowed {}
|
class NotAllowed {}
|
||||||
@@ -32,25 +35,53 @@ describe("Registry", () => {
|
|||||||
} satisfies Record<string, Test1>);
|
} satisfies Record<string, Test1>);
|
||||||
|
|
||||||
const item = registry.get("first");
|
const item = registry.get("first");
|
||||||
|
expect(item).toBeDefined();
|
||||||
|
expect(item?.cls).toBe(What);
|
||||||
|
|
||||||
|
const second = Type.Object({ type: Type.String(), what: Type.String() });
|
||||||
registry.add("second", {
|
registry.add("second", {
|
||||||
cls: What2,
|
cls: What2,
|
||||||
schema: Type.Object({ type: Type.String(), what: Type.String() }),
|
schema: second,
|
||||||
enabled: true
|
enabled: true
|
||||||
});
|
});
|
||||||
|
// @ts-ignore
|
||||||
|
expect(registry.get("second").schema).toEqual(second);
|
||||||
|
|
||||||
|
const third = Type.Object({ type: Type.String({ default: "1" }), what22: Type.String() });
|
||||||
registry.add("third", {
|
registry.add("third", {
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
cls: NotAllowed,
|
cls: NotAllowed,
|
||||||
schema: Type.Object({ type: Type.String({ default: "1" }), what22: Type.String() }),
|
schema: third,
|
||||||
enabled: true
|
enabled: true
|
||||||
});
|
});
|
||||||
|
// @ts-ignore
|
||||||
|
expect(registry.get("third").schema).toEqual(third);
|
||||||
|
|
||||||
|
const fourth = Type.Object({ type: Type.Number(), what22: Type.String() });
|
||||||
registry.add("fourth", {
|
registry.add("fourth", {
|
||||||
cls: What,
|
cls: What,
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
schema: Type.Object({ type: Type.Number(), what22: Type.String() }),
|
schema: fourth,
|
||||||
enabled: true
|
enabled: true
|
||||||
});
|
});
|
||||||
|
// @ts-ignore
|
||||||
|
expect(registry.get("fourth").schema).toEqual(fourth);
|
||||||
|
|
||||||
console.log("list", registry.all());
|
expect(Object.keys(registry.all()).length).toBe(4);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("uses registration fn", async () => {
|
||||||
|
const registry = new Registry<Test1>((a: ClassRef<What>) => {
|
||||||
|
return {
|
||||||
|
cls: a,
|
||||||
|
schema: a.prototype.getType(),
|
||||||
|
enabled: true
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
registry.register("what2", What2);
|
||||||
|
expect(registry.get("what2")).toBeDefined();
|
||||||
|
expect(registry.get("what2").cls).toBe(What2);
|
||||||
|
expect(registry.get("what2").schema).toEqual(What2.prototype.getType());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,59 +1,5 @@
|
|||||||
import path from "node:path";
|
export * from "./node.adapter";
|
||||||
import { serve as honoServe } from "@hono/node-server";
|
export {
|
||||||
import { serveStatic } from "@hono/node-server/serve-static";
|
StorageLocalAdapter,
|
||||||
import { App, type CreateAppConfig } from "bknd";
|
type LocalAdapterConfig
|
||||||
|
} from "../../media/storage/adapters/StorageLocalAdapter";
|
||||||
export type NodeAdapterOptions = CreateAppConfig & {
|
|
||||||
relativeDistPath?: string;
|
|
||||||
port?: number;
|
|
||||||
hostname?: string;
|
|
||||||
listener?: Parameters<typeof honoServe>[1];
|
|
||||||
};
|
|
||||||
|
|
||||||
export function serve({
|
|
||||||
relativeDistPath,
|
|
||||||
port = 1337,
|
|
||||||
hostname,
|
|
||||||
listener,
|
|
||||||
...config
|
|
||||||
}: NodeAdapterOptions = {}) {
|
|
||||||
const root = path.relative(
|
|
||||||
process.cwd(),
|
|
||||||
path.resolve(relativeDistPath ?? "./node_modules/bknd/dist", "static")
|
|
||||||
);
|
|
||||||
let app: App;
|
|
||||||
|
|
||||||
honoServe(
|
|
||||||
{
|
|
||||||
port,
|
|
||||||
hostname,
|
|
||||||
fetch: async (req: Request) => {
|
|
||||||
if (!app) {
|
|
||||||
app = App.create(config);
|
|
||||||
|
|
||||||
app.emgr.on(
|
|
||||||
"app-built",
|
|
||||||
async () => {
|
|
||||||
app.modules.server.get(
|
|
||||||
"/*",
|
|
||||||
serveStatic({
|
|
||||||
root
|
|
||||||
})
|
|
||||||
);
|
|
||||||
app.registerAdminController();
|
|
||||||
},
|
|
||||||
"sync"
|
|
||||||
);
|
|
||||||
|
|
||||||
await app.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
return app.fetch(req);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(connInfo) => {
|
|
||||||
console.log(`Server is running on http://localhost:${connInfo.port}`);
|
|
||||||
listener?.(connInfo);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|||||||
59
app/src/adapter/node/node.adapter.ts
Normal file
59
app/src/adapter/node/node.adapter.ts
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import path from "node:path";
|
||||||
|
import { serve as honoServe } from "@hono/node-server";
|
||||||
|
import { serveStatic } from "@hono/node-server/serve-static";
|
||||||
|
import { App, type CreateAppConfig } from "bknd";
|
||||||
|
|
||||||
|
export type NodeAdapterOptions = CreateAppConfig & {
|
||||||
|
relativeDistPath?: string;
|
||||||
|
port?: number;
|
||||||
|
hostname?: string;
|
||||||
|
listener?: Parameters<typeof honoServe>[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
export function serve({
|
||||||
|
relativeDistPath,
|
||||||
|
port = 1337,
|
||||||
|
hostname,
|
||||||
|
listener,
|
||||||
|
...config
|
||||||
|
}: NodeAdapterOptions = {}) {
|
||||||
|
const root = path.relative(
|
||||||
|
process.cwd(),
|
||||||
|
path.resolve(relativeDistPath ?? "./node_modules/bknd/dist", "static")
|
||||||
|
);
|
||||||
|
let app: App;
|
||||||
|
|
||||||
|
honoServe(
|
||||||
|
{
|
||||||
|
port,
|
||||||
|
hostname,
|
||||||
|
fetch: async (req: Request) => {
|
||||||
|
if (!app) {
|
||||||
|
app = App.create(config);
|
||||||
|
|
||||||
|
app.emgr.on(
|
||||||
|
"app-built",
|
||||||
|
async () => {
|
||||||
|
app.modules.server.get(
|
||||||
|
"/*",
|
||||||
|
serveStatic({
|
||||||
|
root
|
||||||
|
})
|
||||||
|
);
|
||||||
|
app.registerAdminController();
|
||||||
|
},
|
||||||
|
"sync"
|
||||||
|
);
|
||||||
|
|
||||||
|
await app.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
return app.fetch(req);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(connInfo) => {
|
||||||
|
console.log(`Server is running on http://localhost:${connInfo.port}`);
|
||||||
|
listener?.(connInfo);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,25 +1,42 @@
|
|||||||
export type Constructor<T> = new (...args: any[]) => T;
|
export type Constructor<T> = new (...args: any[]) => T;
|
||||||
export class Registry<Item, Items extends Record<string, object> = Record<string, object>> {
|
|
||||||
|
export type RegisterFn<Item> = (unknown: any) => Item;
|
||||||
|
|
||||||
|
export class Registry<
|
||||||
|
Item,
|
||||||
|
Items extends Record<string, Item> = Record<string, Item>,
|
||||||
|
Fn extends RegisterFn<Item> = RegisterFn<Item>
|
||||||
|
> {
|
||||||
private is_set: boolean = false;
|
private is_set: boolean = false;
|
||||||
private items: Items = {} as Items;
|
private items: Items = {} as Items;
|
||||||
|
|
||||||
set<Actual extends Record<string, object>>(items: Actual) {
|
constructor(private registerFn?: Fn) {}
|
||||||
|
|
||||||
|
set<Actual extends Record<string, Item>>(items: Actual) {
|
||||||
if (this.is_set) {
|
if (this.is_set) {
|
||||||
throw new Error("Registry is already set");
|
throw new Error("Registry is already set");
|
||||||
}
|
}
|
||||||
// @ts-ignore
|
this.items = items as unknown as Items;
|
||||||
this.items = items;
|
|
||||||
this.is_set = true;
|
this.is_set = true;
|
||||||
|
|
||||||
return this as unknown as Registry<Item, Actual>;
|
return this as unknown as Registry<Item, Actual, Fn>;
|
||||||
}
|
}
|
||||||
|
|
||||||
add(name: string, item: Item) {
|
add(name: string, item: Item) {
|
||||||
// @ts-ignore
|
this.items[name as keyof Items] = item as Items[keyof Items];
|
||||||
this.items[name] = item;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
register(name: string, specific: Parameters<Fn>[0]) {
|
||||||
|
if (this.registerFn) {
|
||||||
|
const item = this.registerFn(specific);
|
||||||
|
this.items[name as keyof Items] = item as Items[keyof Items];
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.add(name, specific);
|
||||||
|
}
|
||||||
|
|
||||||
get<Name extends keyof Items>(name: Name): Items[Name] {
|
get<Name extends keyof Items>(name: Name): Items[Name] {
|
||||||
return this.items[name];
|
return this.items[name];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,5 +7,7 @@ export {
|
|||||||
type ModuleSchemas
|
type ModuleSchemas
|
||||||
} from "modules/ModuleManager";
|
} from "modules/ModuleManager";
|
||||||
|
|
||||||
|
export { registries } from "modules/registries";
|
||||||
|
|
||||||
export type * from "./adapter";
|
export type * from "./adapter";
|
||||||
export { Api, type ApiOptions } from "./Api";
|
export { Api, type ApiOptions } from "./Api";
|
||||||
|
|||||||
@@ -17,10 +17,6 @@ import {
|
|||||||
import { type S3AdapterConfig, StorageS3Adapter } from "./storage/adapters/StorageS3Adapter";
|
import { type S3AdapterConfig, StorageS3Adapter } from "./storage/adapters/StorageS3Adapter";
|
||||||
|
|
||||||
export { StorageS3Adapter, type S3AdapterConfig, StorageCloudinaryAdapter, type CloudinaryConfig };
|
export { StorageS3Adapter, type S3AdapterConfig, StorageCloudinaryAdapter, type CloudinaryConfig };
|
||||||
/*export {
|
|
||||||
StorageLocalAdapter,
|
|
||||||
type LocalAdapterConfig
|
|
||||||
} from "./storage/adapters/StorageLocalAdapter";*/
|
|
||||||
|
|
||||||
export * as StorageEvents from "./storage/events";
|
export * as StorageEvents from "./storage/events";
|
||||||
export { type FileUploadedEventData } from "./storage/events";
|
export { type FileUploadedEventData } from "./storage/events";
|
||||||
@@ -31,16 +27,12 @@ type ClassThatImplements<T> = Constructor<T> & { prototype: T };
|
|||||||
export const MediaAdapterRegistry = new Registry<{
|
export const MediaAdapterRegistry = new Registry<{
|
||||||
cls: ClassThatImplements<StorageAdapter>;
|
cls: ClassThatImplements<StorageAdapter>;
|
||||||
schema: TObject;
|
schema: TObject;
|
||||||
}>().set({
|
}>((cls: ClassThatImplements<StorageAdapter>) => ({
|
||||||
s3: {
|
cls,
|
||||||
cls: StorageS3Adapter,
|
schema: cls.prototype.getSchema() as TObject
|
||||||
schema: StorageS3Adapter.prototype.getSchema()
|
}))
|
||||||
},
|
.register("s3", StorageS3Adapter)
|
||||||
cloudinary: {
|
.register("cloudinary", StorageCloudinaryAdapter);
|
||||||
cls: StorageCloudinaryAdapter,
|
|
||||||
schema: StorageCloudinaryAdapter.prototype.getSchema()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export const Adapters = {
|
export const Adapters = {
|
||||||
s3: {
|
s3: {
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
import { serveStatic } from "@hono/node-server/serve-static";
|
import { serveStatic } from "@hono/node-server/serve-static";
|
||||||
import { createClient } from "@libsql/client/node";
|
import { createClient } from "@libsql/client/node";
|
||||||
import { App } from "./src";
|
import { App, registries } from "./src";
|
||||||
import { LibsqlConnection } from "./src/data";
|
import { LibsqlConnection } from "./src/data";
|
||||||
import { StorageLocalAdapter } from "./src/media/storage/adapters/StorageLocalAdapter";
|
import { StorageLocalAdapter } from "./src/media/storage/adapters/StorageLocalAdapter";
|
||||||
import { registries } from "./src/modules/registries";
|
|
||||||
|
|
||||||
registries.media.add("local", {
|
registries.media.register("local", StorageLocalAdapter);
|
||||||
cls: StorageLocalAdapter,
|
|
||||||
schema: StorageLocalAdapter.prototype.getSchema()
|
|
||||||
});
|
|
||||||
|
|
||||||
const credentials = {
|
const credentials = {
|
||||||
url: import.meta.env.VITE_DB_URL!,
|
url: import.meta.env.VITE_DB_URL!,
|
||||||
|
|||||||
Reference in New Issue
Block a user