Skip to content

Commit

Permalink
feat(tsoa)!: new lift API (#194)
Browse files Browse the repository at this point in the history
- Changes API from (`liftClient`, `getClient`) to  (`lift`, `lifted`)
- Lift API is now `service.lift(resource, id: "name", allow: ["action"])`. didn't use `as` because it is highlighted as a special keyword in the IDE
- Uses [asynclocalstorage](https://nodejs.org/api/async_context.html#class-asynclocalstorage) instead of req for storing and passing lifted clients context
  • Loading branch information
eladcon authored Apr 11, 2024
1 parent 09de4ab commit 38adce3
Show file tree
Hide file tree
Showing 13 changed files with 51 additions and 36 deletions.
8 changes: 4 additions & 4 deletions tsoa/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,21 @@ It is also possible to use Wing resources from the TS code

```js
let bucket = new cloud.Bucket();
service.liftClient("bucket", bucket, ["put"]);
service.lift(bucket, id: "bucket", allow: ["put"]);
```

```ts
// someController.ts ...
import { getClient } from "@winglibs/tsoa/clients.js";
import { lifted } from "@winglibs/tsoa/clients.js";

@Get("{userId}")
public async getUser(
@Path() userId: number,
@Request() request: Req,
@Query() name?: string,
): Promise<User> {
let bucket = getClient(request, "bucket");
bucket.put(userId.toString(), name ?? "not-a-name");
let bucket = lifted("bucket");
await bucket.put(userId.toString(), name ?? "not-a-name");

return {
id :userId,
Expand Down
4 changes: 2 additions & 2 deletions tsoa/app-aws.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
const express = require("express");
const { setClients } = require("./clients");
const { setLifted } = require("./clients");
const serverlessHttp = require("serverless-http");

var _clients = undefined;

const app = express();
app.use((req, res, next) => {
setClients(req, _clients);
setLifted(_clients);
next();
});
app.use(
Expand Down
4 changes: 2 additions & 2 deletions tsoa/app.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
const express = require("express");
const { setClients } = require("./clients");
const { setLifted } = require("./clients");

exports.runServer = async (routes, clients) => {
const app = express();

app.use((req, res, next) => {
setClients(req, clients);
setLifted(clients);
next();
});

Expand Down
6 changes: 2 additions & 4 deletions tsoa/clients.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { Request } from 'express';
declare const lifted: (id: string) => any;

declare const getClient: (req: Request, id: string) => any;

export { getClient };
export { lifted };
20 changes: 11 additions & 9 deletions tsoa/clients.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
module.exports.getClients = (req) => {
return req.__wing_clients;
};
const { AsyncLocalStorage } = require("node:async_hooks");

// this might run in a different context in sim
const asyncLocalStorage = new AsyncLocalStorage();
global.asyncLocalStorage = asyncLocalStorage;

/**
* Get a Wing client from the request object.
* @param {Object} req - The request object.
* @param {string} id - The client Id.
* @returns {Object} - The requested client.
*/
module.exports.getClient = (req, id) => {
if (!req.__wing_clients || !req.__wing_clients[id]) {
module.exports.lifted = (id) => {
const clients = global.asyncLocalStorage.getStore();
if (!clients || !clients[id]) {
throw new Error(`Wing client ${id} not found`);
}
return req.__wing_clients[id];
return clients[id];
};

module.exports.setClients = (req, clients) => {
req.__wing_clients = clients;
module.exports.setLifted = (clients) => {
global.asyncLocalStorage.enterWith(clients);
};
4 changes: 2 additions & 2 deletions tsoa/lib.w
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub class Service impl types.IService {
new cloud.Endpoint(this.url);
}

pub liftClient(id: str, client: std.Resource, ops: Array<str>) {
this.inner.liftClient(id, client, ops);
pub lift(client: std.Resource, ops: types.LiftOptions) {
this.inner.lift(client, ops);
}
}
4 changes: 2 additions & 2 deletions tsoa/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tsoa/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@winglibs/tsoa",
"description": "TSOA library for Wing",
"version": "0.0.2",
"version": "0.1.0",
"author": {
"email": "[email protected]",
"name": "Eyal Keren"
Expand Down
6 changes: 3 additions & 3 deletions tsoa/sim.w
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ pub class Service_sim impl types.IService {
}, link: true);
}

pub liftClient(id: str, client: std.Resource, ops: Array<str>) {
client.onLift(this.service, ops);
this.clients.set(id, client);
pub lift(client: std.Resource, ops: types.LiftOptions) {
client.onLift(this.service, ops.allow);
this.clients.set(ops.id, client);
}

extern "./lib.js" inflight static startService(options: types.StartServiceOptions): StartResponse;
Expand Down
4 changes: 2 additions & 2 deletions tsoa/test-assets/usersController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
Request,
} from "tsoa";

import { getClient } from "../clients.js";
import { lifted } from "../clients.js";
import { Request as Req } from "express";

interface User {
Expand All @@ -36,7 +36,7 @@ export class UsersController extends Controller {
@Request() request: Req,
@Query() name?: string,
): Promise<User> {
let bucket = getClient(request, "bucket");
let bucket = lifted("bucket");
await bucket.put(userId.toString(), name ?? "not-a-name");

return {
Expand Down
2 changes: 1 addition & 1 deletion tsoa/test/lib.test.w
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ let service = new tsoa.Service(
routesDir: "../test-assets/build",
);

service.liftClient("bucket", bucket, ["put"]);
service.lift(bucket, id: "bucket", allow: ["put"]);

test "will start tsoa service" {
let res = http.get("{service.url}/users/123?name=stam");
Expand Down
6 changes: 3 additions & 3 deletions tsoa/tfaws.w
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,9 @@ pub class Service_tfaws impl types.IService {
this.url = deploy.invokeUrl;
}

pub liftClient(id: str, client: std.Resource, ops: Array<str>) {
client.onLift(this.func.fn, ops);
this.clients.set(id, client);
pub lift(client: std.Resource, ops: types.LiftOptions) {
client.onLift(this.func.fn, ops.allow);
this.clients.set(ops.id, client);
}

extern "./lib.js" static build(options: types.StartServiceOptions): str;
Expand Down
17 changes: 16 additions & 1 deletion tsoa/types.w
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,24 @@ pub struct ServiceProps {
routesDir: str;
}

/**
* Options for the lift method.
*/
pub struct LiftOptions {
/**
* Id of the client
*/
id: str;

/**
* List of operations to allow for this client
*/
allow: Array<str>;
}

/**
* Starts a new TSOA service.
*/
pub interface IService {
liftClient(id: str, client: std.Resource, ops: Array<str>): void;
lift(client: std.Resource, ops: LiftOptions): void;
}

0 comments on commit 38adce3

Please sign in to comment.