@kunk/server 3.0.1 → 3.0.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.
- package/.turbo/turbo-build.log +16 -0
- package/.turbo/turbo-deploy.log +0 -0
- package/.turbo/turbo-version$colon$patch.log +4 -0
- package/CHANGELOG.md +0 -10
- package/dist/index.d.mts +2589 -0
- package/dist/index.mjs +1 -0
- package/package.json +9 -4
- package/src/command.ts +1 -2
package/dist/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{ContextData,Generator,Generator as Generator$1,Logger,Throwable,Validator}from"@kunk/api";import{eq,getTableUniqueName}from"drizzle-orm";import*as path from"path";import{T}from"@kunk/model";import pino from"pino";import{drizzle}from"drizzle-orm/bun-sql";import*as DrizzleQuery from"drizzle-orm/sql/expressions";import{Container}from"inversify";import openapi,{fromTypes}from"@elysiajs/openapi";import Elysia,{ValidationError}from"elysia";let SERVER_ERROR;(function(e){function t(e,t){return Throwable.create(`RESOURCE_ID_NOT_FOUND`,404,{resource:e,id:t})}e.RESOURCE_ID_NOT_FOUND=t;function n(e){return Throwable.create(`RESOURCE_NOT_FOUND`,404,{resource:e})}e.RESOURCE_NOT_FOUND=n;function r(e,t){return Throwable.create(e,400,t)}e.BAD_REQUEST=r;function a(e,t){return Throwable.create(`RESOURCE_ID_ALREADY_EXISTS`,400,{resource:e,id:t})}e.RESOURCE_ID_ALREADY_EXISTS=a;function o(...e){return Throwable.create(`VALIDATION_ERROR`,422,{issues:e})}e.VALIDATION=o;function c(e){return Throwable.create(`SCHEMA_VALIDATION_ERROR`,422,{issues:e})}e.SCHEMA_VALIDATION=c;function l(e,t){return Throwable.create(e,500,t)}e.UNEXPECTED=l,e.FORWARD=Throwable.forward;function u(e,t){return SERVER_ERROR.RESOURCE_ID_NOT_FOUND(getTableUniqueName(e),t)}e.GET_ENTITY_NOT_FOUND=u})(SERVER_ERROR||={});function interpolateEnvVars(e){if(typeof e==`string`)return e.replace(/\${([^:-]+)(?:-([^}]+))?}/g,(e,t,n)=>Bun.env[t]||n||``);if(typeof e==`object`&&e){let t=Array.isArray(e)?[]:{};for(let n in e)t[n]=interpolateEnvVars(e[n]);return t}return e}async function loadFromFile(e,t){let n={},r=path.resolve(process.cwd(),`./config/${e}.yaml`);await Bun.file(r).exists()&&(n=await import(r).then(e=>e.default?.[Bun.env.NODE_ENV||`local`]));let i=await t[`~standard`].validate(n);if(i.issues)throw SERVER_ERROR.SCHEMA_VALIDATION(i.issues);return interpolateEnvVars(i.value)}var Config=class e{constructor(e,t){this.schema=e,this.values=t}get(){return this.values}async set(e){let t=await this.schema[`~standard`].validate(e);if(t.issues)throw SERVER_ERROR.SCHEMA_VALIDATION(t.issues);this.values=t.value}static async create(t){let n=await loadFromFile(t.name,t.schema);return new e(t.schema,n)}static set(e,t){e.set(t)}};const DatabaseConfig=await Config.create({name:`database`,schema:T.object({uri:T.string().default("${DATABASE_URI}"),idleTimeout:T.number().default(5),connectionTimeout:T.number().default(30),maxPoolSize:T.number().default(30)})});var Auth=class{},Database=class{},BunGenerator=class extends Generator$1{get id(){return Bun.randomUUIDv7()}code(e){return Bun.randomUUIDv7().replace(/-/g,``).slice(0,e)}};const rootLogger=pino({name:`app`,transport:{target:`pino-pretty`,options:{colorize:!0,translateTime:`SYS:standard`,ignore:`pid,hostname`}}});var PinoLogger=class e{constructor(e=rootLogger){this.logger=e}info(e){this.logger.info(e)}warn(e){this.logger.warn(e)}error(e){this.logger.error(e)}fork(t){return new e(this.logger.child({name:t}))}},DizzleDatabase=class e extends Database{released=!1;constructor(e,t){super(),this.sql=e,this.session=t}static async create(t,n){let r=await t.reserve();return n.tenantId&&await r`SELECT set_config('app.tenant_id', ${n.tenantId}, false);`,new e(drizzle({client:r}),r)}async create(e,t){let n=e,r=await this.sql.insert(n).values(t).returning(),i=Array.isArray(t)?t.length:1;if(r.length!==i)throw SERVER_ERROR.UNEXPECTED(`FAILED_TO_INSERT_ENTITY`,{});return Array.isArray(t)?r:r[0]}async update(e,t,n){let r=e,[i]=await this.sql.update(r).set(n).where(eq(r.id,t)).returning();if(!i)throw SERVER_ERROR.UNEXPECTED(`FAILED_TO_UPDATE_ENTITY`,{});return i}async upsert(e,t){let n=e,[r]=await this.sql.insert(n).values(t.values).onConflictDoUpdate({target:t.target,set:t.values}).returning();if(!r)throw SERVER_ERROR.UNEXPECTED(`FAILED_TO_UPSERT_ENTITY`,{});return r}async findMany(e,t){let n=e,r=await this.sql.select().from(n).where(t?.where).limit(t?.limit??1e3).offset(t?.offset??0).orderBy(...t?.orderBy??[]).execute();if(!r)throw SERVER_ERROR.UNEXPECTED(`FAILED_TO_GET_MANY_ENTITIES`,{});return r}async findOne(e,t){let n=e,[r]=await this.sql.select().from(n).where(t?.where).limit(1).execute();return r||null}async get(e,t){let n=e,[r]=await this.sql.select().from(n).where(eq(n.id,t)).limit(1).execute();if(!r)throw SERVER_ERROR.GET_ENTITY_NOT_FOUND(n,t);return r}async delete(e,t){let n=e;await this.sql.delete(n).where(eq(n.id,t))}async commit(){this.released||(this.released=!0,this.session.release())}};const registry=new Container({defaultScope:`Singleton`});function gen(){return registry.get(Generator$1)}const Q=DrizzleQuery;var Context=class n{gen;logger;constructor(e,n){this.container=e,this.db=n,this.gen=e.get(Generator),this.logger=e.get(Logger)}static async create(t={}){let r=new Container({defaultScope:`Singleton`,parent:registry});return r.bind(ContextData).toConstantValue(t),new n(r,await r.getAsync(Database))}Q=DrizzleQuery;execute=async(e,t)=>{let n=e;n instanceof Function&&(n=e()),n instanceof Promise&&(n=await n.then(e=>e.default));let r=t;if(n.input){let e=await n.input[`~standard`].validate(t);if(e.issues)throw SERVER_ERROR.SCHEMA_VALIDATION(e.issues);r=e.value}let i={...this,command:n,input:r},a=null;try{return await(()=>n.call(i))(i,this)}catch(e){throw a=SERVER_ERROR.FORWARD(e),a}};prepare=(e,t)=>({input:t,execute:()=>this.execute(e,t)});get=e=>this.container.get(e);getAsync=async e=>await this.container.getAsync(e);[Symbol.dispose]=async()=>{await this.db.commit()}};function middleware(e,t){return t.reduceRight((e,t)=>(n=>t({...n,next:e})),e)}var Command=class e{"~type"=`kunk:command`;constructor(e,t,n,r,i,a){this.name=e,this.visibility=t,this.input=n,this.output=r,this.middlewares=i,this.handler=a}static create=t=>(n,r)=>new e(n.name,t,n.input,n.output,n.middlewares||[],r);static PUBLIC=this.create(`PUBLIC`);static PROTECTED=this.create(`PROTECTED`);static PRIVATE=this.create(`PRIVATE`);async internalCall(e){if(!this.handler)throw SERVER_ERROR.UNEXPECTED(`HANDLER_NOT_SET`,{command:this.name});return this.handler(e)}async call(e){return middleware(()=>this.internalCall(e),this.middlewares)(e)}};registry.bind(Logger).to(PinoLogger),registry.bind(Generator).to(BunGenerator),registry.bind(Bun.SQL).toDynamicValue(()=>{let e=DatabaseConfig.get();return new Bun.SQL({url:e.uri,max:e.maxPoolSize,idleTimeout:e.idleTimeout,connectionTimeout:e.connectionTimeout})}).inSingletonScope(),registry.bind(Database).toDynamicValue(async t=>await DizzleDatabase.create(t.get(Bun.SQL),t.get(ContextData))).inRequestScope();const Server=new Elysia().use(openapi({references:fromTypes(),mapJsonSchema:{zod:T.toJSONSchema},documentation:{servers:[{url:`/`,description:`The base URL of the API`,variables:{tenant_id:{default:`test`}}}]}})).onError(({error:e})=>Throwable.is(e)?Response.json(e):e instanceof T.ModelError?Response.json(Throwable.forward(e)):e instanceof ValidationError||e instanceof Error?Response.json(e):Response.json(Throwable.forward(e)));async function route(e,t){let n=e.split(`/`),r=n.slice(0,-1).join(`.`),i=n.pop(),a=(await t).default,o=a.input?.type===`void`?null:a.input,s=a.output?.type===`void`?null:a.output;return console.info(`command loaded:`,e),new Elysia().post(e,async({headers:e,body:t})=>{let n=e[`x-tenant-id`];using r=await Context.create({tenantId:n});let i=await r.execute(a,t);return Response.json(i)},{body:o,response:s,headers:T.object({"x-tenant-id":T.string().default(`{{tenant_id}}`).optional()}),detail:{summary:i},tags:[r]})}export{Auth,BunGenerator,Command,Config,Context,ContextData,Database,DatabaseConfig,DizzleDatabase,DrizzleQuery,Generator,Logger,PinoLogger,Q,SERVER_ERROR,Server,Validator,gen,middleware,registry,route};
|
package/package.json
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kunk/server",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.4",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
7
7
|
"module": "./src/index.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsdown",
|
|
10
|
+
"version:patch": "bun pm version patch",
|
|
11
|
+
"deploy": "bun publish"
|
|
12
|
+
},
|
|
8
13
|
"dependencies": {
|
|
9
|
-
"@kunk/api": "
|
|
10
|
-
"@kunk/tsconfig": "
|
|
11
|
-
"@kunk/model": "
|
|
14
|
+
"@kunk/api": "3.0.0",
|
|
15
|
+
"@kunk/tsconfig": "3.0.0",
|
|
16
|
+
"@kunk/model": "3.0.0",
|
|
12
17
|
"drizzle-orm": "^1.0.0-beta",
|
|
13
18
|
"drizzle-kit": "^1.0.0-beta",
|
|
14
19
|
"@faker-js/faker": "^10.3.0",
|
package/src/command.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { StandardSchemaV1 } from "
|
|
2
|
-
import type { I, ICommand, ICommandHandler, IContextCommand, IMiddleware } from "@/interfaces/+"
|
|
1
|
+
import type { I, ICommand, ICommandHandler, IContextCommand, IMiddleware, StandardSchemaV1 } from "@/interfaces/+"
|
|
3
2
|
import { SERVER_ERROR } from "@/utils/+"
|
|
4
3
|
import { middleware } from "./middleware"
|
|
5
4
|
|