Skip to content

Commit

Permalink
JSR compat
Browse files Browse the repository at this point in the history
* wip: JSR compat

* wip: need to port handlebars and we're good

* feat: use handlebars from JSR

* chore: update version to 3.0.0

* chore: add publish to JSR on push to main

* ci: fix coverage command

* put back to 2.4.0

* chore: exclude folder from JSR

* feat: no slow trype anymore

* fix: mapping decorator type

* docs: readme warning about JSR

* docs: add JSR badge

* chore: export metadata/mod.ts

* feat: export validation and fix type

* chore: export hook

* chore: export logger

* ci: publish without slow-types

* chore: update 2.4.5

* docs: add metadata JSDOC

* docs: hook JSDoc

* chore: 2.4.6

* docs:

* docs: @module for validation export

* docs: logger

* docs: app.ts JSdoc

* docs: exception JSDOC

* docs: router

* docs: injector doc

* docs: guard

* docs: Event

* docs: partial kv queue doc

* chore: 2.4.7

* docs: more router doc

* docs: fix decorators documentation

* docs: better module doc

* docs: fix JSDoc formatting

* chore: 2.5.0

* docs: metadata key
  • Loading branch information
Sorikairox authored Oct 3, 2024
1 parent abb8b90 commit cb34f03
Show file tree
Hide file tree
Showing 58 changed files with 1,600 additions and 173 deletions.
1 change: 0 additions & 1 deletion .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

**Describe the bug** A clear and concise description of what the bug is.
Expand Down
1 change: 0 additions & 1 deletion .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''

---

**Is your feature request related to a problem? Please describe.** A clear and
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
name: Publish
on:
push:
tags:
- "*"
workflow_dispatch:

jobs:
Expand All @@ -19,4 +22,4 @@ jobs:
deno-version: canary

- name: Publish package
run: deno publish --allow-slow-types
run: deno publish
2 changes: 1 addition & 1 deletion .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
strategy:
fail-fast: false
matrix:
version: ["v1.x", canary]
version: ['v1.x', canary]
steps:
- name: Setup repo
uses: actions/checkout@v3
Expand Down
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@
[![CI](https://github.com/savory/Danet/actions/workflows/run-tests.yml/badge.svg)](https://github.com/savory/Danet/actions/workflows/run-tests.yml)
[![codecov](https://codecov.io/gh/Savory/Danet/branch/main/graph/badge.svg?token=R6WXVC669Z)](https://codecov.io/gh/Savory/Danet)
![Made for Deno](https://img.shields.io/badge/made%20for-Deno-6B82F6?style=flat-square)
[![JSR](https://jsr.io/badges/@danet/core)](https://jsr.io/@danet/core)

## Warning

From version 2.4.0, Danet is only available via [JSR](https://jsr.io/) at
[@danet/core](https://jsr.io/@danet/core). It's a step closer to runtime
agnosticism.

## Description

Expand Down Expand Up @@ -44,7 +51,14 @@ We always welcome contributors, feel free to submit a new feature or report a
bug on our [Github Repository](https://github.com/Savory/Danet) and
[join our discord](https://discord.gg/Q7ZHuDPgjA)

## How to start
## Installation

```sh
deno install --global -A -n danet jsr:@danet/cli
danet new <my-project>
```

## Documentation

[Use our CLI](https://github.com/Savory/Danet-CLI)

Expand Down
51 changes: 41 additions & 10 deletions deno.json
Original file line number Diff line number Diff line change
@@ -1,24 +1,43 @@
{
"name": "@danet/core",
"version": "2.3.0",
"exports": "./mod.ts",
"version": "2.5.1",
"exports": {
".": "./mod.ts",
"./metadata": "./src/metadata/mod.ts",
"./validation": "./validation.ts",
"./hook": "./src/hook/mod.ts",
"./logger": "./src/logger.ts"
},
"lint": {
"include": ["src/"],
"exclude": ["node_modules/", "./**/*.test.ts"],
"include": [
"src/"
],
"exclude": [
"node_modules/",
"./**/*.test.ts"
],
"rules": {
"tags": ["recommended"],
"include": ["ban-untagged-todo"],
"exclude": ["no-unused-vars"]
"tags": [
"recommended"
],
"include": [
"ban-untagged-todo"
],
"exclude": [
"no-unused-vars"
]
}
},
"fmt": {
"options": {
"singleQuote": true,
"useTabs": true
},
"files": {
"exclude": ["./node_modules/", "./coverage/", "./doc/"]
}
"exclude": [
"./node_modules/",
"./coverage/",
"./doc/"
]
},
"compilerOptions": {
"emitDecoratorMetadata": true,
Expand All @@ -29,5 +48,17 @@
"tasks": {
"test": "NO_LOG=true COOKIE_SECRET_KEY=mysecretkey deno test -A --unstable-kv --unstable-cron --coverage=coverage spec/**/*.test.ts",
"start:example": "deno run --allow-net --allow-env --watch example/run.ts"
},
"imports": {
"@std/testing": "jsr:@std/[email protected]",
"validatte": "jsr:@danet/[email protected]",
"@std/path": "jsr:@std/[email protected]",
"@std/fmt": "jsr:@std/[email protected]",
"deno_reflect": "jsr:@dx/[email protected]",
"@hono": "jsr:@hono/[email protected]",
"@danet/handlebars": "jsr:@danet/[email protected]"
},
"publish": {
"exclude": ["./coverage/", "./spec", ".github", ".vscode", "./example"]
}
}
9 changes: 7 additions & 2 deletions spec/queue.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ import {
Module,
OnQueueMessage,
} from '../mod.ts';
import { assertEquals, assertSpyCall, spy } from '../src/deps_test.ts';
import {
assertEquals,
assertSpyCall,
assertSpyCalls,
spy,
} from '../src/deps_test.ts';

const sleep = (msec: number) =>
new Promise((resolve) => setTimeout(resolve, msec));
Expand Down Expand Up @@ -64,7 +69,7 @@ Deno.test('Queue Module', async (t) => {
assertEquals(await res.text(), 'OK');

await sleep(500);
assertEquals(callback.calls.length, 1);
assertSpyCalls(callback, 1);
assertSpyCall(callback, 0, {
args: [payload],
});
Expand Down
5 changes: 1 addition & 4 deletions spec/validate-body-decorator.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import {
assertEquals,
assertExists,
} from 'https://deno.land/[email protected]/testing/asserts.ts';
import { assertEquals, assertExists } from '@std/testing/asserts';
import { DanetApplication } from '../src/mod.ts';
import { Module } from '../src/module/mod.ts';
import { Body, Controller, Get, Post } from '../src/router/controller/mod.ts';
Expand Down
133 changes: 131 additions & 2 deletions src/app.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,45 @@
/**
* @module
* DanetApplication class where everything begins.
* @example
* ```typescript
* import {
* Controller,
* DanetApplication,
* Get,
* Module,
* Query,
* } from '../src/mod.ts';
*
* @Controller('')
* class FirstController {
* constructor() {
* }
*
* @Get('hello-world/:name')
* getHelloWorld(
* @Param('name') name: string,
* ) {
* return `Hello World ${name}`;
* }
* }
*
* @Module({
* controllers: [FirstController]
* })
* class FirstModule {}
*
* const app = new DanetApplication();
* await app.init(FirstModule);
*
* let port = Number(Deno.env.get('PORT'));
* if (isNaN(port)) {
* port = 3000;
* }
* app.listen(port);
* ```
*/

import { Application, MiddlewareHandler } from './deps.ts';
import { FilterExecutor } from './exception/filter/executor.ts';
import { GuardExecutor } from './guard/executor.ts';
Expand Down Expand Up @@ -28,6 +70,11 @@ type CORSOptions = {
exposeHeaders?: string[];
};

/**
* DanetApplication is the main application class for initializing and managing the lifecycle of the application.
* It provides methods for bootstrapping modules, registering controllers, and configuring middleware.
* It also provides methods for starting and stopping the application.
*/
export class DanetApplication {
private app: Application = new Application({ strict: false });
private internalHttpServer?: Deno.HttpServer;
Expand All @@ -36,14 +83,14 @@ export class DanetApplication {
private renderer = new HandlebarRenderer();
private guardExecutor = new GuardExecutor(this.injector);
private filterExecutor = new FilterExecutor(this.injector);
public httpRouter = new DanetHTTPRouter(
public httpRouter: DanetHTTPRouter = new DanetHTTPRouter(
this.injector,
this.guardExecutor,
this.filterExecutor,
this.renderer,
this.app,
);
public websocketRouter = new WebSocketRouter(
public websocketRouter: WebSocketRouter = new WebSocketRouter(
this.injector,
this.guardExecutor,
this.filterExecutor,
Expand All @@ -53,10 +100,33 @@ export class DanetApplication {
private logger: Logger = new Logger('DanetApplication');
public entryModule!: ModuleConstructor;

/**
* Retrieves an instance of the specified type from the injector.
*
* @template T - The type of the instance to retrieve.
* @param {Constructor<T> | string} Type - The constructor of the type or a string identifier.
* @returns {T} - The instance of the specified type.
*/
get<T>(Type: Constructor<T> | string): T {
return this.injector.get(Type);
}

/**
* Bootstraps the application by initializing the provided module and its dependencies.
*
* @param NormalOrDynamicModule - The module to bootstrap, which can be either a normal constructor or a dynamic module.
*
* This method performs the following steps:
* 1. Determines if the provided module is a normal constructor or a dynamic module.
* 2. Initializes the module and retrieves its metadata (controllers, imports, injectables).
* 3. Recursively bootstraps all imported modules.
* 4. Bootstraps the module using the injector.
* 5. Registers controllers with either the HTTP router or WebSocket router based on their metadata.
*
* @template Constructor - A class constructor type.
* @template DynamicModule - A type representing a dynamic module with metadata.
* @template ModuleMetadata - A type representing the metadata of a module.
*/
async bootstrap(NormalOrDynamicModule: Constructor | DynamicModule) {
// deno-lint-ignore no-explicit-any
const possibleModuleInstance = NormalOrDynamicModule as any;
Expand Down Expand Up @@ -114,6 +184,12 @@ export class DanetApplication {
}
}

/**
* Initializes the application with the provided module.
*
* @param Module - The constructor of the module to initialize.
* @returns A promise that resolves when the initialization process is complete.
*/
async init(Module: Constructor) {
this.entryModule = Module;
await this.bootstrap(Module);
Expand All @@ -122,12 +198,35 @@ export class DanetApplication {
);
}

/**
* Closes the application by executing the necessary hooks and shutting down the internal HTTP server.
*
* @async
* @returns {Promise<void>} A promise that resolves when the application has been closed.
*/
async close() {
await this.hookExecutor.executeHookForEveryInjectable(hookName.APP_CLOSE);
await this.internalHttpServer?.shutdown();
this.logger.log('Shutting down');
}

/**
* Starts the HTTP server and begins listening on the specified port.
*
* @param {number} [port=3000] - The port number on which the server will listen.
* @returns {Promise<{ port: number }>} A promise that resolves with an object containing the port number.
*
* @remarks
* This method initializes an `AbortController` to manage the server's lifecycle and uses Deno's `serve` function to start the server.
* The server will log a message indicating the port it is listening on.
*
* @example
* ```typescript
* const app = new DanetApplication();
* await app.init(FirstModule);
* const { port } = app.listen(3000);
* ```
*/
listen(port = 3000): Promise<{ port: number }> {
this.controller = new AbortController();
const { signal } = this.controller;
Expand All @@ -144,29 +243,59 @@ export class DanetApplication {
return listen;
}

/**
* Get hono application instance.
*
* @returns {Application} The hono instance.
*/
get router(): Application {
return this.app;
}

/**
* Sets the directory for the view engine.
*
* @param path - The path to the directory to be set as the root for the view engine.
*/
setViewEngineDir(path: string) {
this.renderer.setRootDir(path);
}

/**
* Configures the application to serve static assets from the specified path.
*
* @param path - The file system path from which to serve static assets.
*/
useStaticAssets(path: string) {
this.app.use('*', (context, next: () => Promise<void>) => {
const root = path;
return (serveStatic({ root })(context, next));
});
}

/**
* Adds one or more global middlewares to the global middleware container.
*
* @param {...PossibleMiddlewareType[]} middlewares - The middlewares to be added to the global container.
*/
addGlobalMiddlewares(...middlewares: PossibleMiddlewareType[]) {
globalMiddlewareContainer.push(...middlewares);
}

/**
* Enables Cross-Origin Resource Sharing (CORS) for the application.
*
* @param {CORSOptions} [options] - Optional configuration for CORS.
*/
enableCors(options?: CORSOptions) {
this.app.use('*', cors(options));
}

/**
* Registers a hono middleware handler to be used for all routes.
*
* @param middleware - The middleware handler to be used.
*/
use(middleware: MiddlewareHandler) {
this.app.use('*', middleware);
}
Expand Down
Loading

0 comments on commit cb34f03

Please sign in to comment.