nucleus-core-ts 0.10.8 → 0.10.9

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/.build-ok CHANGED
@@ -1 +1 @@
1
- 0.10.8
1
+ 0.10.9
package/dist/server.d.ts CHANGED
@@ -30,5 +30,6 @@ export { serve } from './src/Server/NucleusServer';
30
30
  export { buildOpenApiDocument } from './src/Server/openapi';
31
31
  export { collectRoutes, type RouteCollector } from './src/Server/routeCollector';
32
32
  export type { AnyRoute, Guard, RouteGroup } from './src/Server/router';
33
+ export { NucleusTestApp } from './src/Server/testApp';
33
34
  export { defineWebSocketRoute, type WebSocketRoute } from './src/Server/websocket';
34
35
  export { decodeHeaderList } from './src/Utils/headerList';
package/dist/server.js CHANGED
@@ -606,4 +606,4 @@ ${content}
606
606
  <script id="api-reference" data-url="${forHtml(documentUrl)}"></script>
607
607
  <script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
608
608
  </body>
609
- </html>`}function chainGuards(...guards){return async(context)=>{for(let guard5 of guards){let early=await guard5(context);if(early!==void 0)return early}return}}function docsGroup(groups,config){let swagger=config.swagger;if(swagger?.enabled===!1)return null;let base=swagger?.path??"/swagger",info=swagger?.documentation?.info,title=info?.title??"Nucleus API",description=info?.description??"Auto-generated API documentation",document=buildOpenApiDocument(groups,swagger),page=viewerHtml(`${base}/json`,title,description);return{prefix:base,routes:[defineRoute({method:"GET",path:"/",detail:{summary:"API documentation",tags:["Documentation"]},handler:()=>new Response(page,{headers:{"content-type":"text/html; charset=utf8"}})}),defineRoute({method:"GET",path:"/json",detail:{summary:"OpenAPI document",tags:["Documentation"]},handler:()=>document})]}}async function createNucleusServer(options){await buildNucleus(options.config);let groups=getMountedRouteGroups();if(groups.length===0)throw Error("createNucleusServer: the plugin mounted no route groups. That is a wiring "+"fault, not an empty install \u2014 refusing to serve rather than answering 404 to everything.");let resolved=getResolvedOptions2(),rawOptions=options.config.options,securityOf=(candidate)=>typeof candidate==="object"&&candidate!==null?candidate.security?.maxRequestBodyBytes:void 0,maxRequestBodyBytes=securityOf(resolved)??securityOf(rawOptions),storageCeiling=requiredBodyCeiling({storageEnabled:resolved?.storage?.enabled,maxFileSizeBytes:resolved?.storage?.maxFileSizeBytes,maxFiles:resolved?.storage?.formData?.maxFiles}),bunBodyCeiling=bunBodyCeilingFor({storageRequired:storageCeiling,guardCeiling:maxRequestBodyBytes});for(let step of getBootSteps())await step({config:{serve:{maxRequestBodySize:bunBodyCeiling}}});let hostRoutes=options.routes??[],resolvedSwagger=resolved?.swagger,outerSwagger=options.config.swagger,docs=docsGroup([...groups,...hostRoutes],{swagger:outerSwagger??resolvedSwagger});return serve({groups:[...groups,...docs?[docs]:[],...hostRoutes],maxRequestBodyBytes:bunBodyCeiling,onStop:[...getShutdownSteps(),...options.onStop??[]],socket:options.socket??getMountedSocket()??void 0,staticAssets:(()=>{let directory=getMountedStaticAssets();return directory?{prefix:"/nucleus-core",directory}:void 0})(),onRequest:chainGuards(...options.onRequest?[options.onRequest]:[],createInboundGuard({maxRequestBodyBytes}),getAuthMiddleware()),onError:getErrorHandler(),onAfter:getAfterHandler()??void 0,context:(()=>{let runtime=getMountedRuntime2();return runtime?{nucleus:runtime}:void 0})(),port:options.port,hostname:options.hostname})}init_routeCollector();init_websocket();export{serve,defineWebSocketRoute,defineRoute,decodeHeaderList,createNucleusServer,collectRoutes,buildOpenApiDocument,buildNucleus};
609
+ </html>`}function chainGuards(...guards){return async(context)=>{for(let guard5 of guards){let early=await guard5(context);if(early!==void 0)return early}return}}function docsGroup(groups,config){let swagger=config.swagger;if(swagger?.enabled===!1)return null;let base=swagger?.path??"/swagger",info=swagger?.documentation?.info,title=info?.title??"Nucleus API",description=info?.description??"Auto-generated API documentation",document=buildOpenApiDocument(groups,swagger),page=viewerHtml(`${base}/json`,title,description);return{prefix:base,routes:[defineRoute({method:"GET",path:"/",detail:{summary:"API documentation",tags:["Documentation"]},handler:()=>new Response(page,{headers:{"content-type":"text/html; charset=utf8"}})}),defineRoute({method:"GET",path:"/json",detail:{summary:"OpenAPI document",tags:["Documentation"]},handler:()=>document})]}}async function createNucleusServer(options){await buildNucleus(options.config);let groups=getMountedRouteGroups();if(groups.length===0)throw Error("createNucleusServer: the plugin mounted no route groups. That is a wiring "+"fault, not an empty install \u2014 refusing to serve rather than answering 404 to everything.");let resolved=getResolvedOptions2(),rawOptions=options.config.options,securityOf=(candidate)=>typeof candidate==="object"&&candidate!==null?candidate.security?.maxRequestBodyBytes:void 0,maxRequestBodyBytes=securityOf(resolved)??securityOf(rawOptions),storageCeiling=requiredBodyCeiling({storageEnabled:resolved?.storage?.enabled,maxFileSizeBytes:resolved?.storage?.maxFileSizeBytes,maxFiles:resolved?.storage?.formData?.maxFiles}),bunBodyCeiling=bunBodyCeilingFor({storageRequired:storageCeiling,guardCeiling:maxRequestBodyBytes});for(let step of getBootSteps())await step({config:{serve:{maxRequestBodySize:bunBodyCeiling}}});let hostRoutes=options.routes??[],resolvedSwagger=resolved?.swagger,outerSwagger=options.config.swagger,docs=docsGroup([...groups,...hostRoutes],{swagger:outerSwagger??resolvedSwagger});return serve({groups:[...groups,...docs?[docs]:[],...hostRoutes],maxRequestBodyBytes:bunBodyCeiling,onStop:[...getShutdownSteps(),...options.onStop??[]],socket:options.socket??getMountedSocket()??void 0,staticAssets:(()=>{let directory=getMountedStaticAssets();return directory?{prefix:"/nucleus-core",directory}:void 0})(),onRequest:chainGuards(...options.onRequest?[options.onRequest]:[],createInboundGuard({maxRequestBodyBytes}),getAuthMiddleware()),onError:getErrorHandler(),onAfter:getAfterHandler()??void 0,context:(()=>{let runtime=getMountedRuntime2();return runtime?{nucleus:runtime}:void 0})(),port:options.port,hostname:options.hostname})}init_routeCollector();init_response();function compile(pattern2){let names2=[],source=pattern2.split("/").map((segment)=>{if(segment.startsWith(":"))return names2.push(segment.slice(1)),"([^/]+)";if(segment==="*")return names2.push("*"),"(.*)";return segment.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}).join("/");return{regex:new RegExp(`^${source}/?$`),names:names2}}var DEFAULT_ERROR_RESPONDER=({set:set2,error:error3})=>{let carried=error3?.status,status=typeof carried==="number"&&carried>=100&&carried<=599?carried:500;set2.status=status;let message=status<500?String(error3?.message??""):"Internal Server Error";return Response.json(withEnvelopeFlags({isSuccess:!1,message,status,errors:[{message}],data:null}))};class NucleusTestApp{mountConfig;recorded=[];sockets=[];globalGuard;beforeHandlers=[];listening=null;errorResponder;afterResponder;table=null;constructor(mountConfig={}){this.mountConfig=mountConfig;for(let method of["get","post","put","patch","delete","head","options"]){let register=(path8,handler,schema3)=>{return this.add(method.toUpperCase(),path8,handler,schema3),this};this[method]=register}}add(method,path8,handler,schema3={}){let prefix=this.mountConfig.prefix??"",joined=path8==="/"?prefix||"/":`${prefix}${path8}`;this.recorded.push({method,path:joined,route:{method,path:joined,handler,body:schema3.body,query:schema3.query,params:schema3.params,detail:schema3.detail,type:schema3.type}}),this.table=null}ws(path8,definition){return this.sockets.push({path:path8,...definition}),this}use(plugin){if(plugin instanceof NucleusTestApp){for(let one of plugin.recorded)this.recorded.push(one);for(let socket of plugin.sockets)this.sockets.push(socket);return this.table=null,this}let group=plugin;if(group&&Array.isArray(group.routes)){let prefix=typeof group.prefix==="string"?group.prefix:"";for(let route of group.routes){let declared=route.path==="/"?"":route.path,path8=`${prefix}${declared}`||"/";this.recorded.push({method:route.method,path:path8,route:{...route,path:path8}})}this.table=null}return this}onRequest(guard5){return this.globalGuard=guard5,this.table=null,this}onError(responder){return this.errorResponder=responder,this.table=null,this}onAfterHandle(responder){return this.afterResponder=responder,this.table=null,this}onBeforeHandle(guard5){return this.beforeHandlers.push(guard5),this.table=null,this}decorate(key2,value2){let entries=typeof key2==="string"?{[key2]:value2}:key2;return Object.assign(this,entries),this}listen(port=0){return this.listening=serve({groups:[{routes:this.recorded.map((one)=>one.route)}],socket:this.sockets[0],port:Number(port)||0,reusePort:!1,onRequest:this.globalGuard,onError:this.errorResponder??DEFAULT_ERROR_RESPONDER,onAfter:this.afterResponder}),this}get server(){return this.listening??void 0}stop(closeActiveConnections){return this.listening?.stop(closeActiveConnections)}get socketRoutes(){return this.sockets}get routes(){return this.recorded.map((one)=>`${one.method} ${one.path}`)}build(){if(this.table)return this.table;let groups=[{guards:this.beforeHandlers,routes:this.recorded.map((one)=>one.route)}];return this.table=buildRoutes(groups,{onRequest:this.globalGuard,onError:this.errorResponder??DEFAULT_ERROR_RESPONDER,onAfter:this.afterResponder}),this.table}async handle(request){let table=this.build(),{pathname}=new URL(request.url),method=request.method.toUpperCase(),exact=table[pathname]??table[pathname.replace(/\/$/,"")];if(exact?.[method])return exact[method](request);for(let[pattern2,byMethod]of Object.entries(table)){if(!byMethod[method])continue;if(!pattern2.includes(":")&&!pattern2.includes("*"))continue;let{regex,names:names2}=compile(pattern2),matched=regex.exec(pathname);if(!matched)continue;let params={};return names2.forEach((name2,index)=>{params[name2]=decodeURIComponent(matched[index+1]??"")}),request.params=params,byMethod[method](request)}return new Response("NOT_FOUND",{status:404})}}init_websocket();export{serve,defineWebSocketRoute,defineRoute,decodeHeaderList,createNucleusServer,collectRoutes,buildOpenApiDocument,buildNucleus,NucleusTestApp};
@@ -41,7 +41,20 @@ export declare class NucleusTestApp {
41
41
  private add;
42
42
  /** Elysia's `.ws`. Recorded so socket wiring can be asserted, not served. */
43
43
  ws(path: string, definition: unknown): this;
44
- /** Merges another instance's routes; anything else is accepted and ignored. */
44
+ /**
45
+ * Merges another instance's routes, or mounts a `RouteGroup` directly.
46
+ *
47
+ * The group form is what a converted consumer needs. Their factories used to
48
+ * return an Elysia app and now return `{ prefix, routes }`, so a test that
49
+ * said `new Elysia().use(createTheirRoutes())` has nothing to hand this
50
+ * class — it only ever merged its own kind. Found while moving a real
51
+ * delivery: twelve route files and the entry point converted cleanly, and
52
+ * six test files had no way to mount what the factories now return.
53
+ *
54
+ * Anything else is still accepted and ignored, because the Elysia shape this
55
+ * mimics took plugins of every kind and a test that passes one should not
56
+ * start throwing.
57
+ */
45
58
  use(plugin: unknown): this;
46
59
  onRequest(guard: Handler): this;
47
60
  onError(responder: Handler): this;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nucleus-core-ts",
3
- "version": "0.10.8",
3
+ "version": "0.10.9",
4
4
  "description": "Production-ready, enterprise-grade TypeScript framework for building multi-tenant APIs",
5
5
  "author": "Hidayet Can Özcan <hidayetcan@gmail.com>",
6
6
  "license": "SEE LICENSE IN LICENSE",