savory / danet Goto Github PK
View Code? Open in Web Editor NEWThe most mature backend framework for Deno. Create awesome HTTP and WebSocket server as well as KVQueue workers !
Home Page: https://danet.land
License: Other
The most mature backend framework for Deno. Create awesome HTTP and WebSocket server as well as KVQueue workers !
Home Page: https://danet.land
License: Other
Is your feature request related to a problem? Please describe.
We should be able to render an HTML generated by Handlebars.
Describe the solution you'd like
A @View('viewname')
decorator for controller methods
DanetRouter should get a TemplateEngine attribute that will render the given view, with variables returned from the controller's method.
Here is an example:
@Controller('')
class myController {
@View('index')
renderIndex() {
return { latestNews: ['an array of latests', 'news to display'] };
}
}
Additional context
Take inspiration of nestjs
Problem
If you are importing a fresh project into Danet that has Deno config file in jsonc
, then fresh integration won't work.
fresh_app
|_ deno.jsonc
Error
$ deno task launch-server
Task launch-server deno run --allow-net --allow-read --allow-run --allow-write --unstable --allow-env run.ts
The manifest has been generated for 7 routes and 0 islands.
error: Uncaught (in promise) TypeError: Module not found "file:///danet_app/src/fresh_app/deno.json".
at file:///danet_app/src/fresh_app/fresh.gen.ts:5:20
const manifest = (await import(url + './fresh.gen.ts')).default;
^
at async Function.enableFreshOnRoot (https://deno.land/x/[email protected]/mod.ts:43:21)
at async bootstrap (file:///danet_app/src/bootstrap.ts:14:3)
at async file:///danet_app/run.ts:3:21
Solution
Allow to pass Deno config file type in FreshModule.enableFreshOnRoot
function.
Enum options:
json
(default),jsonc
enum DenoConfigFileType {
JSON = 'json',
JSONC = 'jsonc'
}
The README could have some code to introduce the framework. We all know it is similar to Nest in Deno. But how much similar??
I thought something like this one below... based in Danet-Starter
If it's possible I'd like to open a simple PR to do that. Being assigned to this Issue =D
import { Module, Controller, Injectable, Get, DanetApplication } from 'https://deno.land/x/[email protected]/mod.ts';
// Services...
@Injectable()
export class helloService {
sayHello() {
console.log('Hello World')
}
}
// Controllers...
@Controller('hello')
export class helloController {
constructor(private service: helloService){}
@Get()
hello() {
this.service.sayHello()
}
}
// Modules...
@Module({
controllers: [helloController],
injectables: [helloService],
})
export class TodoModule {}
// Deploy...
export const bootstrap = async () => {
const application = new DanetApplication();
await application.init(AppModule);
return application;
}
Move hook management outside of injector
Is your feature request related to a problem? Please describe.
We should be able to do something like this app.useStaticAssets(join(__dirname, '..', 'public'));
to render static assets from the given directory.
It could attach a middleware on oak app
, such as the following from stackoverflow :
// static content
app.use(async (context, next) => {
const root = `${Deno.cwd()}/${ROOTDIR}`
try {
await context.send({ root })
} catch {
next()
}
})
Is your feature request related to a problem? Please describe.
Currently, we cannot do something like the following :
@Controller()
class Controller {
constructor(@Inject('DATABASE_SERVICE') databaseService)
}
Describe the solution you'd like
We should be able to do it
Additional context
Maybe use TSyringe to handle injection instead of doing it by hand
Is your feature request related to a problem? Please describe.
Take inspiration from https://github.com/nestjs/docs.nestjs.com/blob/master/content/guards.md
Is your feature request related to a problem? Please describe.
Describe the solution you'd like
As you are apparently considering a V2 I wanted to make some suggestions with the question: Do you really want to rebuild NestJS?
I am asking because the dependency injection and the modules can make the life of a developer hard and frustrating (thinking of import/export of services, useFactory, circular dependencies). Also NestJS takes 81 ms to start an empty Express app while "plain" Express takes 7 ms and is therefor not usable for serverless functions.
Looking back into Angular (the inspiration of NestJS) it is not needed anymore to register a class that has the @Injectable()
decorator. Instead it "just works" and is even tree shaked if it is not used anywhere. Also a thing that Angular did is the remove of modules: Standalone apps dont need modules anymore (but can still import modules for compatibility), components (in our case controllers) import whatever they need in their @Component()
decorator and Angular does the magic of putting it all together and tree shaking what is not used.
I just wanted to add this things to consider, you might close this issue :)
P.S. What about another name as well? I am not native english and this name "Danet" is really hard to remember, especially compared to something fresh like "fresh" or even the dead project "mandarine".
For now, DanetApplication
references an oak
Application. We should abstract it to prepare for other HTTP engines
We should get an installation/starter page for newcomers, that explains the content of the starter-app !
Nest reference : https://docs.nestjs.com/first-steps
When using @Body
decorator, we should be able to validate the body we are receiving
Using our validatte package, we should validate bodies.
This should be an opt-out feature, we validate by default.
opt-out may look like this :
export const bootstrap = async () => {
const application = new DanetApplication();
application.disableBodyValidation();
await application.init(AppModule);
return application;
}
Upon injecting the body in router.ts
we can validate it, and throws a 400 Bad Request containing validateObject
return value.
Is your feature request related to a problem? Please describe.
Add documentation for our OnAppClose
and OnAppBootstrap
hooks.
Take inspiration from https://github.com/nestjs/docs.nestjs.com/blob/master/content/fundamentals/lifecycle-events.md
Is your feature request related to a problem? Please describe.
Add documentation to explain Injectable and Injectable scopes.
Take inspiration from
https://docs.nestjs.com/providers
and
Is your feature request related to a problem? Please describe.
I was going though this project and noticed that there are some missing items based on the Github Community Standards recommendations that would make the project contributor friendly, e.g. a code of conduct and a pull request template.
Describe the solution you'd like
Let me know if this is something you would like to implement on this project.
info:
deno 1.24.3 (release, x86_64-pc-windows-msvc) v8 10.4.132.20 typescript 4.7.4
deno run -A main.ts
error: Uncaught SyntaxError: The requested module './Reflect.ts' does not provide an export named 'Reflect' export { Reflect } from "./Reflect.ts";
Is your feature request related to a problem? Please describe.
Let's say I have a global AuthGuard
because almost all my routes need authentication.
The few that don't need it should have a decorator such as @Public
that set metadata.
In my global AuthGuard
, I should be able to get a reference to the Method (via ctx
) to get access to its metadata.
Describe the solution you'd like
In router/router.ts:handleRoute
, we should add Controller
and ControllerMethod
in ctx
!
Additional context
Maybe something similar to NestJS
ctx.getHandler(),
ctx.getClass(),
Is your feature request related to a problem? Please describe.
For now, we only have ForbiddenHttpException
defined as follow :
import { HTTP_STATUS } from './enum.ts';
export class ForbiddenHttpException {
public status = HTTP_STATUS.FORBIDDEN;
public message = 'Forbidden';
}
We should defined a class for each exception listed below:
BAD_REQUEST = 400,
UNAUTHORIZED = 401,
PAYMENT_REQUIRED = 402,
FORBIDDEN = 403,
NOT_FOUND = 404,
METHOD_NOT_ALLOWED = 405,
NOT_ACCEPTABLE = 406,
PROXY_AUTHENTICATION_REQUIRED = 407,
REQUEST_TIMEOUT = 408,
CONFLICT = 409,
GONE = 410,
LENGTH_REQUIRED = 411,
PRECONDITION_FAILED = 412,
PAYLOAD_TOO_LARGE = 413,
URI_TOO_LONG = 414,
UNSUPPORTED_MEDIA_TYPE = 415,
REQUESTED_RANGE_NOT_SATISFIABLE = 416,
EXPECTATION_FAILED = 417,
I_AM_A_TEAPOT = 418,
MISDIRECTED = 421,
UNPROCESSABLE_ENTITY = 422,
FAILED_DEPENDENCY = 424,
PRECONDITION_REQUIRED = 428,
TOO_MANY_REQUESTS = 429,
INTERNAL_SERVER_ERROR = 500,
NOT_IMPLEMENTED = 501,
BAD_GATEWAY = 502,
SERVICE_UNAVAILABLE = 503,
GATEWAY_TIMEOUT = 504,
HTTP_VERSION_NOT_SUPPORTED = 505
Is your feature request related to a problem? Please describe.
As a Nest.JS developer, I'd like the possibility of running cron jobs using the framework decorators and module system.
References:
Describe the solution you'd like
I imagine something like this:
@Module({
imports: [
ScheduleModule.forRoot()
],
})
export class AppModule {}
@Cron
decorator to register listeners to timed events:@Injectable()
export class TasksService {
private readonly logger = new Logger(TasksService.name);
@Cron('45 * * * * *')
handleCron() {
this.logger.debug('Called when the current second is 45');
}
}
The ScheduleModule
can be totally made using Deno native features, like the Deno.Cron module
Other than that, I think the implementation should be fairly similar to the Events
feature (#76)
My mongo database is at
'mongodb://127.0.0.1:27017/exp_danet'
I can directly alter
mongodb.service.ts
but would nice to be able to specify it in .env
It breaks the file format that is specific to retype
nestjs-zod interacts deeply with nestJS.
So to make it works with Danet, Danet should look like NestJS
Is your feature request related to a problem? Please describe.
GuardExecutor
and FilterExecutor
look alike. We should probably be able to refactor this!
Describe the solution you'd like
An executor
class with an attribute that contains the related metadatakey to get the function to execute. Then maybe create children classes for GuardExecutor
and FilterExecutor
.
Is your feature request related to a problem? Please describe.
We should be able to attach a custom exception filter to the app, a controller, or a method.
Describe the solution you'd like
Create a @UseFiter
decorator that take either a class name or class instance
Additional context
Take inspiration in Nest
Is your feature request related to a problem? Please describe.
If I want to set a controller/method metadata, for example with a Public
decorator, I have to create it as follows:
export const IS_PUBLIC_KEY = 'isPublic';
export const Public = () =>
(
// deno-lint-ignore ban-types
target: ControllerConstructor | Object,
propertyKey?: string | symbol,
// deno-lint-ignore no-explicit-any
descriptor?: TypedPropertyDescriptor<any>,
) => {
if (propertyKey && descriptor) {
MetadataHelper.setMetadata(
IS_PUBLIC_KEY,
true,
descriptor.value,
);
} else {
MetadataHelper.setMetadata(IS_PUBLIC_KEY, true, target);
}
};
This is way too verbose, especially when creating multiple decorators that only set metadata.
Describe the solution you'd like
We should create a SetMetadata
function to be used as follows:
export const IS_PUBLIC_KEY = 'isPublic';
export const Public = () => SetMetadata(IS_PUBLIC_KEY, true);
Describe the bug
A clear and concise description of what the bug is.
For now, Controllers are singleton;
Expected behavior
Controller whose one or more dependencies have SCOPE.REQUEST
should be instantiated on every request.
We need to add metadata on the controller that tags it as "SCOPE.REQUEST" when injecting its dependencies. Then when adding it to resolved
map, either uses a singleton or a factory.
We should be able to get any header using an @Header('myheadername')
decorator in controller's methods.
Describe the bug
When adding a Fresh project to Deno, the Fresh Layouts don't work, both when using Fresh from the root and from a given path.
Fresh Project
Fresh into Danet
Expected
My layout for root routes including a header
, footer
, and content inside the main
tag.
Console Logs
$ deno task launch-server
The manifest has been generated for 8 routes and 0 islands.
Sun, 24 Sep 2023 16:41:02 GMT [Injector] Bootstraping DatabaseModule
Sun, 24 Sep 2023 16:41:02 GMT [Injector] Bootstraping TodoModule
Sun, 24 Sep 2023 16:41:02 GMT [Router] Registering TodoController todo
Sun, 24 Sep 2023 16:41:02 GMT [Router] Registering [GET] /todo
Sun, 24 Sep 2023 16:41:02 GMT [Router] Registering [GET] /todo/:id
Sun, 24 Sep 2023 16:41:02 GMT [Router] Registering [POST] /todo
Sun, 24 Sep 2023 16:41:02 GMT [Router] Registering [PUT] /todo/:id
Sun, 24 Sep 2023 16:41:02 GMT [Router] Registering [DELETE] /todo/:id
Sun, 24 Sep 2023 16:41:02 GMT [Injector] Bootstraping AppModule
Sun, 24 Sep 2023 16:41:02 GMT [Router] Registering AppController /
Sun, 24 Sep 2023 16:41:02 GMT [Router] Registering [GET] /
Sun, 24 Sep 2023 16:41:02 GMT [DanetApplication] Listening on 3000
[uncaught application error]: Http - connection closed before message completed
at Object.respondWith (ext:deno_http/01_http.js:334:25)
at eventLoopTick (ext:core/01_core.js:197:13)
[uncaught application error]: Http - connection closed before message completed
request: {
url: "http://localhost:3000/_frsh/alive",
method: "GET",
hasBody: false
}
response: { status: 200, type: undefined, hasBody: true, writable: false }
at Object.respondWith (ext:deno_http/01_http.js:334:25)
at eventLoopTick (ext:core/01_core.js:197:13)
rest api build using danet can be deployed using deno deploy ?
danet bundle command is build on top of deno bundle, in the recent version of deno this command is depricated
as mention there https://deno.land/[email protected]/tools/bundler
Controllers' page lack bootstrap code to run the app
https://savory.github.io/Danet/first-steps/controllers/
Need to add
import { AppModule } from './app.module.ts';
import { DanetApplication } from './deps.ts';
export const bootstrap = async () => {
const application = new DanetApplication();
await application.init(AppModule);
return application;
}
openapi/swagger describe RESTful APIs generated from code when using some decorator like https://docs.nestjs.com/openapi/introduction. we need some decorator in Danet for this perpose.
I think there a need for auth modules as referance, in starter repo or in other place. I suggess so because most project need auth.
Describe the bug
When a guard's canActivate
method returns false, the controllers' code will be executed regardless of the fact that it shouldn't.
Expected behavior
Stop execution by throwing a 403 error if canActivate
returns false
Describe the bug A clear and concise description of what the bug is.
deno install --allow-read --allow-write --allow-run --allow-env -n danet https://deno.land/x/danet_cli/main.ts
deno install
behavior will change in Deno 2. To preserve the current behavior use the -g
or --global
flag.
error: The module's source code could not be parsed: Expected ';', got '=' at https://deno.land/x/[email protected]/bundle.ts:8:45
options: { entrypoint: string, bundlePath = './bundle' },
Desktop (please complete the following information):
Kubuntu 24.04
Deno 1.43.4
Problem
If you are importing a fresh project into Danet that has imports
within deno.json
file, then fresh integration won't work.
// danet_app/src/fresh_app/deno.json
{
"lock": false,
"tasks": {
"build": "deno run -A dev.ts build",
"compile:sass": "sass ./static/scss/styles.scss:./static/css/styles.min.css --style compressed",
"compile:sass:watch": "sass --watch ./static/scss/styles.scss:./static/css/styles.min.css --style compressed",
"preview": "deno run -A main.ts",
"start": "deno run -A --watch=watch=static/,routes/ dev.ts",
"start:dev": "deno task compile:sass && (deno task compile:sass:watch & deno task start)",
"update": "deno run -A -r https://fresh.deno.dev/update ."
},
"imports": {
"$fresh/": "https://deno.land/x/[email protected]/",
"$fresh-seo/": "https://deno.land/x/[email protected]/",
"$std/": "https://deno.land/[email protected]/",
"@preact/signals": "https://esm.sh/*@preact/[email protected]",
"@preact/signals-core": "https://esm.sh/*@preact/[email protected]",
"preact": "https://esm.sh/[email protected]",
"preact/": "https://esm.sh/[email protected]/",
"preact-render-to-string": "https://esm.sh/*[email protected]",
"preact-router": "https://esm.sh/[email protected]",
"wouter-preact": "https://esm.sh/*[email protected]",
"wouter-preact/": "https://esm.sh/*[email protected]/"
},
"lint": {
"rules": {
"tags": [
"fresh",
"recommended"
]
},
"exclude": [
"_fresh"
]
},
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "preact"
},
"fmt": {
"exclude": [
"_fresh"
]
}
}
Error
$ deno task launch-server
Task launch-server deno run --allow-net --allow-read --allow-run --allow-write --unstable --allow-env run.ts
The manifest has been generated for 7 routes and 0 islands.
error: Uncaught (in promise) Error: deno.json must contain an 'importMap' property.
throw new Error("deno.json must contain an 'importMap' property.");
^
at Function.fromManifest (https://deno.land/x/[email protected]/src/server/context.ts:111:13)
at Function.enableFreshOnRoot (https://deno.land/x/[email protected]/mod.ts:44:40)
at async bootstrap (file:///danet_app/src/bootstrap.ts:14:3)
at async file:///danet_app/run.ts:3:21
Solution
Add the information to the Integration docs that Fresh project dependencies
should be added to the import_map file
of the Danet project
, and that the imports property in Fresh
should be replaced by the importMap property
pointing to the import_map file of Danet
.
Is your feature request related to a problem? Please describe.
As a Nest.JS developer, I'd like the possibility of making an event-driven system using the framework decorators and module system.
References:
Describe the solution you'd like
I'm not sure about the internals, but I imagine something like this:
this.emitter.connect({
// Add queue configs when the app is initializing (SQS, Kafka, etc)
})
than, I'd like to bind class methods to events:
// initialization
class MyListeners {
@OnEvent('new-user')
handleWelcomeNewUser(user: User) {
// Do some side effect
}
}
and also should be able to emit these events, something like:
// initialization
class MyListeners {
createUser(user: UserDto) {
// create user
this.emitter.send('new-user', user)
}
}
Describe alternatives you've considered
At the moment, the alternative I have considered is to make an EventEmitter
module, which manages queues and subscriptions using Deno.Kv
queues, to keep it as native as possible.
This is not ideal, but it can work if we set the (un)subscription
in onAppBootstrap
and onAppClose
respectively.
@Injectable()
export class MyListeners implements OnAppBootstrap, OnAppClose {
listeners: string[] = []
constructor(@Inject(EventEmitter) private eventEmitter: EventEmitter) {}
eventHandler() {
// do something
}
async onAppBootstrap() {
const eventId = await this.eventEmitter.subscribe('event', this.eventHandler);
this.listeners.push(eventId)
}
async onAppClose() {
await Promise.all(
this.listeners.map(
this.eventEmitter.unsubscribe,
)
);
}
}
We should be able to get the session in controllers' methods without using @Req
decorator, using a new decorator @Session
.
It could either take a parameter to return a specific attribute, or no parameter to return the whole session.
It would be used as follow :
class CustomSessionContent {
userId: string;
userToken: string;
}
@Controller('')
export class AppController {
constructor() {
}
@Get()
helloWorld(@Session() mySession: CustomeSessionContent, @Session('userId') userId: string) {
}
}
I want to use the service like in nest js
but apparently not working
is there something wrong with me
cats.controller.ts
import {
Controller,
Injectable,
Get } from 'https://deno.land/x/danet/mod.ts';
import {Childservice} from './service/my.service.ts';
@Controller('cats')
export class CatsController {
constructor(private childservice:Childservice){}
@Get()
findAll(): string {
return this.childservice.Gethello()
}
}
my.service.ts
import {
Controller,
Injectable,
SCOPE,
Get } from 'https://deno.land/x/danet/mod.ts';
@Injectable({ scope: SCOPE.REQUEST })
export class Childservice{
Gethello(){
return "ini service"
}
}
error message in browser :
{"status":500,"message":"Cannot read properties of undefined (reading 'Gethello')"}
how can I create script in Danet project for common tasks like create tables, create user, database migrations.....? I hope see some doc about this or examples.
Problem
If you are importing a fresh project into Danet with custom folders like src
folder, then fresh integration
won't work.
fresh_app
|_ src
|_ fresh.gen.ts
Error
$ deno task launch-server
Task launch-server deno run --allow-net --allow-read --allow-run --allow-write --unstable --allow-env run.ts
error: Uncaught (in promise) TypeError: Module not found "danet_app/src/fresh_app/fresh.gen.ts".
const manifest = (await import(url + './fresh.gen.ts')).default;
^
at async Function.enableFreshOnRoot (https://deno.land/x/[email protected]/mod.ts:43:21)
at async bootstrap (file:///danet_app/src/bootstrap.ts:12:3)
at async file:///danet_app/run.ts:3:21
Solution
Allow to pass fresh.gen.ts
custom directory in FreshModule.enableFreshOnRoot
function.
/
root directory as default
Is your feature request related to a problem? Please describe.
We should have a Retype documentation on github page.
Additional context
https://retype.com/guides/github-actions/
For now, any injectable declared by a module can be injected in any other module.
For example:
@Module({
injectables: [userService, privateLogicService]
})
export class UserModule {
}
privateLogicService
will be accessible in any module that import UserModule
.
We should encapsulate injectables to the current module scope and make them exportables with an export
property.
Example :
@Module({
injectables: [userService, privateLogicService],
export: [userService]
})
export class UserModule {
}
it will be better if we can open swagger UI using the /swagger url
Is your feature request related to a problem? Please describe.
When a controller or an injectable is request scoped, it should be useful to give the actual Request object when instantiating them.
Describe the solution you'd like
Give Request
to the injector when getting a class instance, so it can inject it on instantiating request-scoped classes.
Changing signature to :
public get<T>(Type: Constructor<T> | string, context?: httpContext): T {
Nest's way of doing it is clean :
@Injectable({ scope: Scope.REQUEST })
export class CatsService {
constructor(@Inject(REQUEST) private request: Request) {}
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.