@razvan11/paladin 1.0.9 → 1.1.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/dist/app/app.d.ts +12 -0
- package/dist/functions/middleware.d.ts +1 -0
- package/dist/functions/websocket.d.ts +29 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +126 -33
- package/package.json +2 -2
package/dist/app/app.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { Hono } from 'hono';
|
|
|
4
4
|
import '../container/container';
|
|
5
5
|
import type { AppConfigOptions, ValidatorType } from '../types';
|
|
6
6
|
type ControllerClass = new (...args: any[]) => any;
|
|
7
|
+
type WebSocketClass = new (...args: any[]) => any;
|
|
7
8
|
export interface StaticOptions {
|
|
8
9
|
/** URL path prefix (e.g., '/static') */
|
|
9
10
|
path?: string;
|
|
@@ -17,6 +18,8 @@ export declare class App {
|
|
|
17
18
|
readonly validators?: ValidatorType;
|
|
18
19
|
private cors;
|
|
19
20
|
private logger;
|
|
21
|
+
private wsHandlers;
|
|
22
|
+
private server;
|
|
20
23
|
constructor(options: AppConfigOptions);
|
|
21
24
|
init(): void;
|
|
22
25
|
/**
|
|
@@ -33,6 +36,15 @@ export declare class App {
|
|
|
33
36
|
* Register multiple controllers at once
|
|
34
37
|
*/
|
|
35
38
|
registerControllers(...controllers: ControllerClass[]): this;
|
|
39
|
+
/**
|
|
40
|
+
* Register a WebSocket handler with the app
|
|
41
|
+
* Reads handler metadata and stores event handlers
|
|
42
|
+
*/
|
|
43
|
+
registerWebSocket(WSClass: WebSocketClass): this;
|
|
44
|
+
/**
|
|
45
|
+
* Register multiple WebSocket handlers at once
|
|
46
|
+
*/
|
|
47
|
+
registerWebSockets(...handlers: WebSocketClass[]): this;
|
|
36
48
|
/**
|
|
37
49
|
* Normalize and combine path segments
|
|
38
50
|
*/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export declare const WEBSOCKET_METADATA: unique symbol;
|
|
2
|
+
export declare const WS_HANDLERS_METADATA: unique symbol;
|
|
3
|
+
export interface WSHandlerDefinition {
|
|
4
|
+
event: 'message' | 'open' | 'close' | 'drain';
|
|
5
|
+
handlerName: string | symbol;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* @websocket decorator
|
|
9
|
+
* Marks a class as a WebSocket handler and registers it with the DI container
|
|
10
|
+
*
|
|
11
|
+
* @param path - The WebSocket endpoint path (e.g., '/chat')
|
|
12
|
+
*/
|
|
13
|
+
export declare function websocket(path?: string): <T extends new (...args: any[]) => any>(constructor: T) => T;
|
|
14
|
+
/**
|
|
15
|
+
* @onMessage decorator - Handles incoming WebSocket messages
|
|
16
|
+
*/
|
|
17
|
+
export declare const onMessage: () => MethodDecorator;
|
|
18
|
+
/**
|
|
19
|
+
* @onOpen decorator - Handles WebSocket connection open
|
|
20
|
+
*/
|
|
21
|
+
export declare const onOpen: () => MethodDecorator;
|
|
22
|
+
/**
|
|
23
|
+
* @onClose decorator - Handles WebSocket connection close
|
|
24
|
+
*/
|
|
25
|
+
export declare const onClose: () => MethodDecorator;
|
|
26
|
+
/**
|
|
27
|
+
* @onDrain decorator - Handles WebSocket backpressure drain
|
|
28
|
+
*/
|
|
29
|
+
export declare const onDrain: () => MethodDecorator;
|
package/dist/index.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export { default as config } from './functions/config';
|
|
|
15
15
|
export { default as validator } from './functions/validator';
|
|
16
16
|
export { default as env } from './functions/env';
|
|
17
17
|
export { getDataSourceForCLI } from './functions/database';
|
|
18
|
+
export { websocket, onMessage, onOpen, onClose, onDrain, WEBSOCKET_METADATA, WS_HANDLERS_METADATA, type WSHandlerDefinition, } from './functions/websocket';
|
|
18
19
|
export { render, renderElement, createRenderer } from './functions/render';
|
|
19
20
|
export { LayoutView, PageLoader, type LayoutViewProps, } from './components/LayoutView';
|
|
20
21
|
export { asset, publicAsset, setAssetBasePath, getAssetBasePath, } from './functions/asset';
|
package/dist/index.js
CHANGED
|
@@ -15026,10 +15026,10 @@ var require_PrettyError = __commonJS((exports, module) => {
|
|
|
15026
15026
|
}
|
|
15027
15027
|
});
|
|
15028
15028
|
|
|
15029
|
-
//
|
|
15029
|
+
// framework/index.ts
|
|
15030
15030
|
var import_reflect_metadata2 = __toESM(require_Reflect(), 1);
|
|
15031
15031
|
|
|
15032
|
-
//
|
|
15032
|
+
// framework/app/app.ts
|
|
15033
15033
|
var import_reflect_metadata = __toESM(require_Reflect(), 1);
|
|
15034
15034
|
|
|
15035
15035
|
// node_modules/hono/dist/compose.js
|
|
@@ -18893,7 +18893,7 @@ class ne {
|
|
|
18893
18893
|
return a3.#h.planResultCacheService.subscribe(r2), new W2(v.build(() => a3.#h.activationService), T.build(() => a3.#h.bindingService, t4), j.build(() => a3.#h.deactivationService), r2);
|
|
18894
18894
|
}
|
|
18895
18895
|
}
|
|
18896
|
-
//
|
|
18896
|
+
// framework/container/container.ts
|
|
18897
18897
|
var CONTAINER_KEYS = {
|
|
18898
18898
|
APP_NAME: Symbol.for("app.name"),
|
|
18899
18899
|
APP_SECRET: Symbol.for("app.secret"),
|
|
@@ -19399,7 +19399,7 @@ var chalk = createChalk();
|
|
|
19399
19399
|
var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
19400
19400
|
var source_default = chalk;
|
|
19401
19401
|
|
|
19402
|
-
//
|
|
19402
|
+
// framework/logger/logger.ts
|
|
19403
19403
|
var import_pretty_error = __toESM(require_PrettyError(), 1);
|
|
19404
19404
|
|
|
19405
19405
|
class Logger {
|
|
@@ -19781,7 +19781,7 @@ var upgradeWebSocket = defineWebSocketHelper((c3, events) => {
|
|
|
19781
19781
|
return;
|
|
19782
19782
|
});
|
|
19783
19783
|
|
|
19784
|
-
//
|
|
19784
|
+
// framework/functions/controller.ts
|
|
19785
19785
|
var getContainer = () => globalThis.container;
|
|
19786
19786
|
var CONTROLLER_METADATA = Symbol("controller:prefix");
|
|
19787
19787
|
var ROUTES_METADATA = Symbol("controller:routes");
|
|
@@ -19822,7 +19822,7 @@ var del = createMethodDecorator("delete");
|
|
|
19822
19822
|
var options = createMethodDecorator("options");
|
|
19823
19823
|
var all = createMethodDecorator("all");
|
|
19824
19824
|
|
|
19825
|
-
//
|
|
19825
|
+
// framework/functions/asset.ts
|
|
19826
19826
|
var assetBasePath = "/static";
|
|
19827
19827
|
function setAssetBasePath(basePath) {
|
|
19828
19828
|
assetBasePath = basePath.startsWith("/") ? basePath : `/${basePath}`;
|
|
@@ -19840,8 +19840,44 @@ function publicAsset(filename) {
|
|
|
19840
19840
|
return `${assetBasePath}/${normalizedFilename}`.replace(/\/+/g, "/");
|
|
19841
19841
|
}
|
|
19842
19842
|
|
|
19843
|
-
//
|
|
19843
|
+
// framework/functions/websocket.ts
|
|
19844
19844
|
var getContainer2 = () => globalThis.container;
|
|
19845
|
+
var WEBSOCKET_METADATA = Symbol("websocket:path");
|
|
19846
|
+
var WS_HANDLERS_METADATA = Symbol("websocket:handlers");
|
|
19847
|
+
function websocket2(path = "/ws") {
|
|
19848
|
+
return (constructor) => {
|
|
19849
|
+
W()(constructor);
|
|
19850
|
+
Reflect.defineMetadata(WEBSOCKET_METADATA, path, constructor);
|
|
19851
|
+
if (!Reflect.hasMetadata(WS_HANDLERS_METADATA, constructor)) {
|
|
19852
|
+
Reflect.defineMetadata(WS_HANDLERS_METADATA, [], constructor);
|
|
19853
|
+
}
|
|
19854
|
+
const container2 = getContainer2();
|
|
19855
|
+
if (container2 && !container2.isBound(constructor)) {
|
|
19856
|
+
container2.bind(constructor).toSelf().inSingletonScope();
|
|
19857
|
+
}
|
|
19858
|
+
return constructor;
|
|
19859
|
+
};
|
|
19860
|
+
}
|
|
19861
|
+
function createWSEventDecorator(event) {
|
|
19862
|
+
return () => {
|
|
19863
|
+
return (target, propertyKey, _descriptor) => {
|
|
19864
|
+
const constructor = target.constructor;
|
|
19865
|
+
const handlers = Reflect.getMetadata(WS_HANDLERS_METADATA, constructor) || [];
|
|
19866
|
+
handlers.push({
|
|
19867
|
+
event,
|
|
19868
|
+
handlerName: propertyKey
|
|
19869
|
+
});
|
|
19870
|
+
Reflect.defineMetadata(WS_HANDLERS_METADATA, handlers, constructor);
|
|
19871
|
+
};
|
|
19872
|
+
};
|
|
19873
|
+
}
|
|
19874
|
+
var onMessage = createWSEventDecorator("message");
|
|
19875
|
+
var onOpen = createWSEventDecorator("open");
|
|
19876
|
+
var onClose = createWSEventDecorator("close");
|
|
19877
|
+
var onDrain = createWSEventDecorator("drain");
|
|
19878
|
+
|
|
19879
|
+
// framework/app/app.ts
|
|
19880
|
+
var getContainer3 = () => globalThis.container;
|
|
19845
19881
|
|
|
19846
19882
|
class App {
|
|
19847
19883
|
app;
|
|
@@ -19850,17 +19886,18 @@ class App {
|
|
|
19850
19886
|
validators;
|
|
19851
19887
|
cors;
|
|
19852
19888
|
logger;
|
|
19889
|
+
wsHandlers = new Map;
|
|
19890
|
+
server = null;
|
|
19853
19891
|
constructor(options2) {
|
|
19854
19892
|
this.app = new Hono2;
|
|
19855
19893
|
this.name = options2.name;
|
|
19856
|
-
this.container =
|
|
19894
|
+
this.container = getContainer3();
|
|
19857
19895
|
this.validators = options2.validators;
|
|
19858
19896
|
this.logger = new Logger;
|
|
19859
19897
|
this.cors = options2.cors || ["*"];
|
|
19860
19898
|
this.init();
|
|
19861
19899
|
}
|
|
19862
19900
|
init() {
|
|
19863
|
-
console.log(this.cors);
|
|
19864
19901
|
this.app.use("/*", cors({
|
|
19865
19902
|
origin: this.cors,
|
|
19866
19903
|
allowHeaders: ["Content-Type", "Authorization"],
|
|
@@ -19899,6 +19936,26 @@ class App {
|
|
|
19899
19936
|
}
|
|
19900
19937
|
return this;
|
|
19901
19938
|
}
|
|
19939
|
+
registerWebSocket(WSClass) {
|
|
19940
|
+
const path = Reflect.getMetadata(WEBSOCKET_METADATA, WSClass) || "/ws";
|
|
19941
|
+
const handlers = Reflect.getMetadata(WS_HANDLERS_METADATA, WSClass) || [];
|
|
19942
|
+
const instance = this.container.get(WSClass);
|
|
19943
|
+
const handlerMap = {};
|
|
19944
|
+
for (const handler of handlers) {
|
|
19945
|
+
handlerMap[handler.event] = instance[handler.handlerName].bind(instance);
|
|
19946
|
+
}
|
|
19947
|
+
this.wsHandlers.set(path, handlerMap);
|
|
19948
|
+
if (Bun.env.APP_ENV === "local") {
|
|
19949
|
+
this.logger.info(` WS ${path}`);
|
|
19950
|
+
}
|
|
19951
|
+
return this;
|
|
19952
|
+
}
|
|
19953
|
+
registerWebSockets(...handlers) {
|
|
19954
|
+
for (const handler of handlers) {
|
|
19955
|
+
this.registerWebSocket(handler);
|
|
19956
|
+
}
|
|
19957
|
+
return this;
|
|
19958
|
+
}
|
|
19902
19959
|
normalizePath(prefix, path) {
|
|
19903
19960
|
const normalizedPrefix = prefix.startsWith("/") ? prefix : `/${prefix}`;
|
|
19904
19961
|
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
@@ -19911,6 +19968,18 @@ class App {
|
|
|
19911
19968
|
return this.app;
|
|
19912
19969
|
}
|
|
19913
19970
|
async run() {
|
|
19971
|
+
const self2 = this;
|
|
19972
|
+
this.wsHandlers.forEach((_3, path) => {
|
|
19973
|
+
this.app.get(path, (c3) => {
|
|
19974
|
+
const upgraded = self2.server?.upgrade(c3.req.raw, {
|
|
19975
|
+
data: { path }
|
|
19976
|
+
});
|
|
19977
|
+
if (upgraded) {
|
|
19978
|
+
return new Response(null, { status: 101 });
|
|
19979
|
+
}
|
|
19980
|
+
return c3.text("WebSocket upgrade failed", 400);
|
|
19981
|
+
});
|
|
19982
|
+
});
|
|
19914
19983
|
try {
|
|
19915
19984
|
const server = Bun.serve({
|
|
19916
19985
|
port: 3000,
|
|
@@ -19918,12 +19987,29 @@ class App {
|
|
|
19918
19987
|
development: false,
|
|
19919
19988
|
fetch: this.app.fetch,
|
|
19920
19989
|
websocket: {
|
|
19921
|
-
message(ws, message) {
|
|
19922
|
-
|
|
19923
|
-
|
|
19924
|
-
|
|
19990
|
+
message(ws, message) {
|
|
19991
|
+
const wsPath = ws.data?.path;
|
|
19992
|
+
const handlers = self2.wsHandlers.get(wsPath);
|
|
19993
|
+
handlers?.message?.(ws, message);
|
|
19994
|
+
},
|
|
19995
|
+
open(ws) {
|
|
19996
|
+
const wsPath = ws.data?.path;
|
|
19997
|
+
const handlers = self2.wsHandlers.get(wsPath);
|
|
19998
|
+
handlers?.open?.(ws);
|
|
19999
|
+
},
|
|
20000
|
+
close(ws, code, message) {
|
|
20001
|
+
const wsPath = ws.data?.path;
|
|
20002
|
+
const handlers = self2.wsHandlers.get(wsPath);
|
|
20003
|
+
handlers?.close?.(ws, code, message);
|
|
20004
|
+
},
|
|
20005
|
+
drain(ws) {
|
|
20006
|
+
const wsPath = ws.data?.path;
|
|
20007
|
+
const handlers = self2.wsHandlers.get(wsPath);
|
|
20008
|
+
handlers?.drain?.(ws);
|
|
20009
|
+
}
|
|
19925
20010
|
}
|
|
19926
20011
|
});
|
|
20012
|
+
this.server = server;
|
|
19927
20013
|
this.logger.success(`Server started on port ${server.port}`);
|
|
19928
20014
|
return server;
|
|
19929
20015
|
} catch (error) {
|
|
@@ -19936,42 +20022,42 @@ class App {
|
|
|
19936
20022
|
}
|
|
19937
20023
|
}
|
|
19938
20024
|
}
|
|
19939
|
-
//
|
|
20025
|
+
// framework/functions/inject.ts
|
|
19940
20026
|
function inject(identifier) {
|
|
19941
20027
|
return U(identifier);
|
|
19942
20028
|
}
|
|
19943
|
-
//
|
|
19944
|
-
var
|
|
20029
|
+
// framework/functions/service.ts
|
|
20030
|
+
var getContainer4 = () => globalThis.container;
|
|
19945
20031
|
function service() {
|
|
19946
20032
|
return (constructor) => {
|
|
19947
20033
|
W()(constructor);
|
|
19948
|
-
const container2 =
|
|
20034
|
+
const container2 = getContainer4();
|
|
19949
20035
|
if (container2 && !container2.isBound(constructor)) {
|
|
19950
20036
|
container2.bind(constructor).toSelf().inSingletonScope();
|
|
19951
20037
|
}
|
|
19952
20038
|
return constructor;
|
|
19953
20039
|
};
|
|
19954
20040
|
}
|
|
19955
|
-
//
|
|
19956
|
-
var
|
|
20041
|
+
// framework/functions/repository.ts
|
|
20042
|
+
var getContainer5 = () => globalThis.container;
|
|
19957
20043
|
function repository() {
|
|
19958
20044
|
return (constructor) => {
|
|
19959
20045
|
W()(constructor);
|
|
19960
|
-
const container2 =
|
|
20046
|
+
const container2 = getContainer5();
|
|
19961
20047
|
if (container2 && !container2.isBound(constructor)) {
|
|
19962
20048
|
container2.bind(constructor).toSelf().inSingletonScope();
|
|
19963
20049
|
}
|
|
19964
20050
|
return constructor;
|
|
19965
20051
|
};
|
|
19966
20052
|
}
|
|
19967
|
-
//
|
|
19968
|
-
var
|
|
20053
|
+
// framework/functions/database.ts
|
|
20054
|
+
var getContainer6 = () => globalThis.container;
|
|
19969
20055
|
var databaseRegistry = new Map;
|
|
19970
20056
|
function database(options2 = {}) {
|
|
19971
20057
|
return (constructor) => {
|
|
19972
20058
|
W()(constructor);
|
|
19973
20059
|
databaseRegistry.set(constructor, options2);
|
|
19974
|
-
const container2 =
|
|
20060
|
+
const container2 = getContainer6();
|
|
19975
20061
|
if (container2 && !container2.isBound(constructor)) {
|
|
19976
20062
|
container2.bind(constructor).toSelf().inSingletonScope();
|
|
19977
20063
|
}
|
|
@@ -19990,12 +20076,12 @@ function getDataSourceForCLI(DatabaseClass, url) {
|
|
|
19990
20076
|
}
|
|
19991
20077
|
return source;
|
|
19992
20078
|
}
|
|
19993
|
-
//
|
|
19994
|
-
var
|
|
20079
|
+
// framework/functions/config.ts
|
|
20080
|
+
var getContainer7 = () => globalThis.container;
|
|
19995
20081
|
function config() {
|
|
19996
20082
|
return (_target) => {
|
|
19997
20083
|
for (const [key, value] of Object.entries(CONTAINER_KEYS)) {
|
|
19998
|
-
|
|
20084
|
+
getContainer7().bind(value).toConstantValue(Bun.env[key]);
|
|
19999
20085
|
}
|
|
20000
20086
|
};
|
|
20001
20087
|
}
|
|
@@ -20866,14 +20952,14 @@ function validate(schemaNameOrObject, objectOrValidationOptions, maybeValidatorO
|
|
|
20866
20952
|
}
|
|
20867
20953
|
}
|
|
20868
20954
|
|
|
20869
|
-
//
|
|
20955
|
+
// framework/utils/pretty-error.ts
|
|
20870
20956
|
var import_pretty_error2 = __toESM(require_PrettyError(), 1);
|
|
20871
20957
|
var pe2 = new import_pretty_error2.default;
|
|
20872
20958
|
pe2.skipNodeFiles();
|
|
20873
20959
|
pe2.skipPackage("typescript", "bun");
|
|
20874
20960
|
pe2.start();
|
|
20875
20961
|
|
|
20876
|
-
//
|
|
20962
|
+
// framework/functions/validator.ts
|
|
20877
20963
|
function validator() {
|
|
20878
20964
|
return (target) => {
|
|
20879
20965
|
const instance = new target;
|
|
@@ -20886,14 +20972,14 @@ function validator() {
|
|
|
20886
20972
|
});
|
|
20887
20973
|
};
|
|
20888
20974
|
}
|
|
20889
|
-
//
|
|
20890
|
-
var
|
|
20975
|
+
// framework/functions/env.ts
|
|
20976
|
+
var getContainer8 = () => globalThis.container;
|
|
20891
20977
|
function env2() {
|
|
20892
20978
|
return (target, propertyKey) => {
|
|
20893
20979
|
const envVar = String(propertyKey).toUpperCase();
|
|
20894
20980
|
const value = Bun.env[envVar];
|
|
20895
20981
|
if (value) {
|
|
20896
|
-
const container3 =
|
|
20982
|
+
const container3 = getContainer8();
|
|
20897
20983
|
container3.bind(propertyKey).toConstantValue(value);
|
|
20898
20984
|
}
|
|
20899
20985
|
Object.defineProperty(target, propertyKey, {
|
|
@@ -20904,7 +20990,7 @@ function env2() {
|
|
|
20904
20990
|
});
|
|
20905
20991
|
};
|
|
20906
20992
|
}
|
|
20907
|
-
//
|
|
20993
|
+
// framework/functions/render.tsx
|
|
20908
20994
|
import { renderToString } from "react-dom/server";
|
|
20909
20995
|
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
20910
20996
|
function render(c3, Component, props) {
|
|
@@ -20924,7 +21010,7 @@ function createRenderer(c3) {
|
|
|
20924
21010
|
renderElement: (element) => renderElement(c3, element)
|
|
20925
21011
|
};
|
|
20926
21012
|
}
|
|
20927
|
-
//
|
|
21013
|
+
// framework/components/LayoutView.tsx
|
|
20928
21014
|
import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
|
|
20929
21015
|
var LayoutView = ({
|
|
20930
21016
|
title,
|
|
@@ -21020,6 +21106,7 @@ var PageLoader = ({
|
|
|
21020
21106
|
}, undefined, false, undefined, this);
|
|
21021
21107
|
};
|
|
21022
21108
|
export {
|
|
21109
|
+
websocket2 as websocket,
|
|
21023
21110
|
validator,
|
|
21024
21111
|
setAssetBasePath,
|
|
21025
21112
|
service,
|
|
@@ -21031,6 +21118,10 @@ export {
|
|
|
21031
21118
|
post,
|
|
21032
21119
|
patch,
|
|
21033
21120
|
options,
|
|
21121
|
+
onOpen,
|
|
21122
|
+
onMessage,
|
|
21123
|
+
onDrain,
|
|
21124
|
+
onClose,
|
|
21034
21125
|
logger,
|
|
21035
21126
|
inject,
|
|
21036
21127
|
getDataSourceForCLI,
|
|
@@ -21045,6 +21136,8 @@ export {
|
|
|
21045
21136
|
config,
|
|
21046
21137
|
asset,
|
|
21047
21138
|
all,
|
|
21139
|
+
WS_HANDLERS_METADATA,
|
|
21140
|
+
WEBSOCKET_METADATA,
|
|
21048
21141
|
ROUTES_METADATA,
|
|
21049
21142
|
PageLoader,
|
|
21050
21143
|
Logger,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@razvan11/paladin",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "A Bun-based backend framework with decorators, dependency injection, and controller registration",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bun",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
],
|
|
33
33
|
"scripts": {
|
|
34
34
|
"dev": "bun run ./example/index.ts",
|
|
35
|
-
"build": "
|
|
35
|
+
"build": "bun build ./framework/index.ts --outdir ./dist --target bun --external react --external react-dom && bun run build:types",
|
|
36
36
|
"build:types": "tsc -p tsconfig.build.json",
|
|
37
37
|
"prepublishOnly": "bun run build",
|
|
38
38
|
"fmt": "bunx @biomejs/biome format --write",
|