rajt 0.0.57 → 0.0.59
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/README.md +10 -7
- package/package.json +35 -15
- package/src/action-old.ts +72 -0
- package/src/action.ts +12 -61
- package/src/auth/ability.ts +2 -2
- package/src/auth/authnz.ts +3 -0
- package/src/auth/index.ts +0 -1
- package/src/auth/token.ts +27 -24
- package/src/bin/rajt.js +123 -0
- package/src/cli/commands/dev/index.ts +294 -0
- package/src/cli/commands/dev/utils.ts +215 -0
- package/src/cli/index.ts +69 -0
- package/src/cli/types.ts +1 -0
- package/src/create-app.ts +15 -9
- package/src/db/d1.d.ts +1 -0
- package/src/db/d1.ts +1 -0
- package/src/dev.ts +18 -15
- package/src/enum.ts +2 -75
- package/src/esbuild.mjs +11 -9
- package/src/http.ts +9 -8
- package/src/index.ts +1 -3
- package/src/prod-aws.ts +2 -17
- package/src/prod-cf.ts +1 -18
- package/src/prod.ts +16 -0
- package/src/request-old.ts +98 -0
- package/src/request.ts +152 -71
- package/src/response.ts +71 -26
- package/src/routes.ts +66 -2
- package/src/scripts/cache-routes.ts +1 -64
- package/src/types.ts +24 -4
- package/src/utils/environment.ts +3 -2
- package/src/utils/func.ts +2 -2
- package/src/utils/local-date.ts +13 -0
- package/src/utils/logger.ts +61 -0
- package/src/utils/port.ts +1 -3
- package/src/utils/resolve.ts +4 -3
- package/src/utils/shutdown.ts +19 -0
- package/src/validator.ts +68 -0
- package/src/auth/auth.ts +0 -33
- package/src/dynamodb/client.ts +0 -125
- package/src/dynamodb/compact.ts +0 -205
- package/src/dynamodb/decorators.ts +0 -126
- package/src/dynamodb/index.ts +0 -4
- package/src/dynamodb/model.ts +0 -258
- package/src/dynamodb/query-builder.ts +0 -174
- package/src/dynamodb/repository.ts +0 -31
- package/src/dynamodb/schema.ts +0 -107
- package/src/dynamodb/types.ts +0 -32
- package/src/utils/lenght.ts +0 -32
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
<h1 align="left"
|
|
1
|
+
<h1 align="left">λ Rajt<br/><a href="https://pr.new/attla/rajt"><img align="right" src="https://developer.stackblitz.com/img/start_pr_dark_small.svg" alt="Start new PR in StackBlitz Codeflow"></a><a href="https://npmjs.com/package/rajt"><img align="right" src="https://img.shields.io/npm/v/rajt.svg" alt="npm package"></a></h1>
|
|
2
2
|
<br/>
|
|
3
3
|
|
|
4
|
-
> This framework is fully geared towards the serverless world, specifically AWS Lambda (Node.js and LLRT) / Cloudflare Workers.
|
|
4
|
+
> This framework is fully geared towards the serverless world, specifically AWS Lambda (Node.js, Bun and LLRT runtime) / Cloudflare Workers.
|
|
5
5
|
|
|
6
6
|
- 💡 Instant Server Start
|
|
7
7
|
- ⚡️ Fast Cold Start
|
|
@@ -9,12 +9,15 @@
|
|
|
9
9
|
|
|
10
10
|
[Read the Docs to Learn More](https://github.com/attla/rajt/blob/main/DOCS.md)
|
|
11
11
|
|
|
12
|
-
## Packages
|
|
12
|
+
## Ecosystem Packages
|
|
13
13
|
|
|
14
|
-
| Package
|
|
15
|
-
|
|
|
16
|
-
| [rajt](https://github.com/attla/rajt)
|
|
17
|
-
| [create-rajt](https://github.com/attla/create-rajt) |  |
|
|
14
|
+
| Package | Version | Description |
|
|
15
|
+
| -: | :- | :- |
|
|
16
|
+
| [rajt](https://github.com/attla/rajt) | [](https://npm.im/rajt) | 🧱 The core of Rajt serverless framework. |
|
|
17
|
+
| [create-rajt](https://github.com/attla/create-rajt) | [](https://npm.im/create-rajt) | 📁 CLI tool for create new Rajt projects, from starter templates. |
|
|
18
|
+
| [forj](https://github.com/attla/forj) | [](https://npm.im/forj) | 🗂️ Just another query builder in typescript |
|
|
19
|
+
| [t0n](https://github.com/attla/t0n) | [](https://npm.im/t0n) | 🧰 Collection of elegant typescript resources for web artisans. |
|
|
20
|
+
| [cripta](https://github.com/attla/cripta) | [](https://npm.im/cripta) | 🧛 A layer of encryption a little too judicious. |
|
|
18
21
|
|
|
19
22
|
## License
|
|
20
23
|
|
package/package.json
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rajt",
|
|
3
3
|
"description": "A serverless bundler layer, fully typed for AWS Lambda (Node.js and LLRT) and Cloudflare Workers.",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.59",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"rajt": "./src/bin/rajt.js"
|
|
9
|
+
},
|
|
7
10
|
"exports": {
|
|
8
11
|
".": "./src/index.ts",
|
|
9
12
|
"./auth": "./src/auth/index.ts",
|
|
10
|
-
"./
|
|
11
|
-
"./
|
|
13
|
+
"./d1": "./src/db/d1.ts",
|
|
14
|
+
"./d1/types": "./src/db.d.ts",
|
|
15
|
+
"./dynamodb": "./src/db/dynamodb.ts",
|
|
16
|
+
"./dynamodb/types": "./src/db/dynamodb.d.ts",
|
|
17
|
+
"./enum": "./src/enum.ts",
|
|
12
18
|
"./http": "./src/http.ts",
|
|
13
19
|
"./types": "./src/types.ts",
|
|
14
20
|
"./env": "./src/utils/environment.ts",
|
|
@@ -18,6 +24,7 @@
|
|
|
18
24
|
"src"
|
|
19
25
|
],
|
|
20
26
|
"scripts": {
|
|
27
|
+
"rajt": "./src/bin/rajt.js",
|
|
21
28
|
"dev": "tsx watch src/dev.ts",
|
|
22
29
|
"aws:build": "bun run --silent cache:routes && bun run --silent aws:export && bun run --silent clean:temp",
|
|
23
30
|
"cf:build": "bun run --silent cache:routes && bun run --silent cf:export && bun run --silent clean:temp",
|
|
@@ -33,7 +40,7 @@
|
|
|
33
40
|
"sam:package": "sam package --template-file ../../template-prod.yaml --output-template-file ../../packaged.yaml",
|
|
34
41
|
"sam:deploy": "sam deploy --template-file ../../packaged.yaml --stack-name rajt-llrt --capabilities CAPABILITY_IAM",
|
|
35
42
|
"sam:update": "source ../../.env.prod && aws lambda update-function-code --function-name $AWS_NAME --zip-file fileb://../../lambda.zip --region $AWS_REGION --no-cli-pager 2>&1 >/dev/null",
|
|
36
|
-
"cf:local": "bun run --silent cf:build
|
|
43
|
+
"cf:local-": "source ../../.env.dev && bun run --silent cf:build:watch -- cd ../../dist && bunx wrangler dev --port=$PORT --persist-to='../.wrangler/state'",
|
|
37
44
|
"cf:deploy": "bun run --silent cf:build && cd ../../dist && bunx wrangler deploy",
|
|
38
45
|
"cache:routes": "tsx src/scripts/cache-routes.ts",
|
|
39
46
|
"ensure-dirs": "rm -rf ../../dist ../../tmp && mkdir -p ../../tmp && chmod 755 ../../tmp && mkdir -p ../../dist && chmod 755 ../../dist",
|
|
@@ -44,24 +51,37 @@
|
|
|
44
51
|
"start": "node ../../dist/index.js"
|
|
45
52
|
},
|
|
46
53
|
"dependencies": {
|
|
47
|
-
"@aws-sdk/client-dynamodb": "3.817.0",
|
|
48
|
-
"@aws-sdk/lib-dynamodb": "3.817.0",
|
|
49
|
-
"@hono/node-server": "^1.14.1",
|
|
50
54
|
"@hono/zod-validator": "^0.4.3",
|
|
55
|
+
"cripta": "^0.1",
|
|
56
|
+
"forj": "^0.0.2",
|
|
57
|
+
"hono": "^4.7.6",
|
|
58
|
+
"t0n": "^0.1.5",
|
|
59
|
+
"ua-parser-js": "^2.0.4"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@cloudflare/workers-types": "^4.20251230.0",
|
|
63
|
+
"@hono/node-server": "^1.14.1",
|
|
64
|
+
"@iarna/toml": "^2.2.5",
|
|
65
|
+
"@miniflare/core": "^2.14.4",
|
|
66
|
+
"@miniflare/d1": "^2.14.4",
|
|
67
|
+
"@miniflare/durable-objects": "^2.14.4",
|
|
68
|
+
"@miniflare/kv": "^2.14.4",
|
|
69
|
+
"@miniflare/r2": "^2.14.4",
|
|
70
|
+
"@miniflare/scheduler": "^2.14.4",
|
|
71
|
+
"@miniflare/sites": "^2.14.4",
|
|
72
|
+
"@miniflare/storage-file": "^2.14.4",
|
|
73
|
+
"@miniflare/web-sockets": "^2.14.4",
|
|
51
74
|
"@types/node": "^20.11.0",
|
|
75
|
+
"bun-types": "^1.2.14",
|
|
52
76
|
"chokidar-cli": "^3.0.0",
|
|
53
|
-
"
|
|
77
|
+
"citty": "^0.1.6",
|
|
54
78
|
"dotenv": "^16.5.0",
|
|
55
79
|
"esbuild": "^0.25.2",
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"tsconfig-paths": "^4.2.0",
|
|
80
|
+
"miniflare": "^4.20251217.0",
|
|
81
|
+
"picocolors": "^1.1.1",
|
|
59
82
|
"tsx": "^4.19.3",
|
|
60
83
|
"typescript": "^5.8.3",
|
|
61
|
-
"
|
|
62
|
-
},
|
|
63
|
-
"devDependencies": {
|
|
64
|
-
"bun-types": "^1.2.14"
|
|
84
|
+
"wrangler": "^4.56.0"
|
|
65
85
|
},
|
|
66
86
|
"engines": {
|
|
67
87
|
"node": ">=18.0.0"
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// import { Context, Handler, HonoRequest, MiddlewareHandler, Next, ValidationTargets } from 'hono'
|
|
2
|
+
// import { JSONValue } from 'hono/utils/types'
|
|
3
|
+
import { Context, Handler, ValidationTargets } from 'hono'
|
|
4
|
+
import { z, ZodObject } from 'zod'
|
|
5
|
+
import { zValidator } from '@hono/zod-validator'
|
|
6
|
+
import response from './response'
|
|
7
|
+
import cx from './context'
|
|
8
|
+
|
|
9
|
+
export type ActionType = Function | Handler | Action | (new () => Action)
|
|
10
|
+
|
|
11
|
+
type RuleDefinition = {
|
|
12
|
+
schema: z.ZodObject<any>
|
|
13
|
+
target: keyof ValidationTargets
|
|
14
|
+
eTarget?: 'fieldErrors' | 'formErrors'
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default class Action {
|
|
18
|
+
static rule<T extends keyof ValidationTargets>(target: T): { schema: (schema: ZodObject<any>) => RuleDefinition }
|
|
19
|
+
static rule<T extends keyof ValidationTargets>(target: T, schema: ZodObject<any>): RuleDefinition
|
|
20
|
+
static rule<T extends keyof ValidationTargets>(target: T, schema?: ZodObject<any>):
|
|
21
|
+
| { schema: (schema: ZodObject<any>) => RuleDefinition }
|
|
22
|
+
| RuleDefinition
|
|
23
|
+
{
|
|
24
|
+
if (schema !== undefined) {
|
|
25
|
+
return {
|
|
26
|
+
target,
|
|
27
|
+
schema,
|
|
28
|
+
eTarget: 'fieldErrors' // | 'formErrors'
|
|
29
|
+
} satisfies RuleDefinition
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
schema: (schema: ZodObject<any>) => ({
|
|
34
|
+
target,
|
|
35
|
+
schema,
|
|
36
|
+
eTarget: 'fieldErrors' // | 'formErrors'
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static validate() {
|
|
42
|
+
const rules = this.rules()
|
|
43
|
+
const h = async (c: Context) => {
|
|
44
|
+
return await this.handle(cx.cx)
|
|
45
|
+
}
|
|
46
|
+
if (!rules) return [h]
|
|
47
|
+
|
|
48
|
+
const rulesArray: Function[] = (Array.isArray(rules) ? rules : [rules])
|
|
49
|
+
// @ts-ignore
|
|
50
|
+
.map(rule => zValidator(rule.target, rule.schema, (result, c) => {
|
|
51
|
+
if (!result.success) {
|
|
52
|
+
// @ts-ignore
|
|
53
|
+
return response.badRequest({ ...result.error.flatten()[rule.eTarget] })
|
|
54
|
+
}
|
|
55
|
+
}))
|
|
56
|
+
|
|
57
|
+
rulesArray.push(h)
|
|
58
|
+
return rulesArray
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static run() {
|
|
62
|
+
return this.validate()
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
static rules(): RuleDefinition[] | RuleDefinition | null {
|
|
66
|
+
return null
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static async handle(c: Context): Promise<Response> {
|
|
70
|
+
return Promise.resolve(response.raw(200, 'Action handle not implemented'))
|
|
71
|
+
}
|
|
72
|
+
}
|
package/src/action.ts
CHANGED
|
@@ -1,72 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { Context,
|
|
4
|
-
import { z, ZodObject } from 'zod'
|
|
5
|
-
import { zValidator } from '@hono/zod-validator'
|
|
6
|
-
import Response from './response'
|
|
7
|
-
import cx from './context'
|
|
8
|
-
|
|
9
|
-
export type ActionType = Function | Handler | Action | (new () => Action)
|
|
10
|
-
|
|
11
|
-
type RuleDefinition = {
|
|
12
|
-
schema: z.ZodObject<any>
|
|
13
|
-
target: keyof ValidationTargets
|
|
14
|
-
eTarget?: 'fieldErrors' | 'formErrors'
|
|
15
|
-
}
|
|
1
|
+
import response from './response'
|
|
2
|
+
import validator from './validator'
|
|
3
|
+
import type { Context, IRequest, IResponse, IValidator, Rules } from './types'
|
|
16
4
|
|
|
17
5
|
export default class Action {
|
|
18
|
-
static
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
| { schema: (schema: ZodObject<any>) => RuleDefinition }
|
|
22
|
-
| RuleDefinition
|
|
23
|
-
{
|
|
24
|
-
if (schema !== undefined) {
|
|
25
|
-
return {
|
|
26
|
-
target,
|
|
27
|
-
schema,
|
|
28
|
-
eTarget: 'fieldErrors' // | 'formErrors'
|
|
29
|
-
} satisfies RuleDefinition
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return {
|
|
33
|
-
schema: (schema: ZodObject<any>) => ({
|
|
34
|
-
target,
|
|
35
|
-
schema,
|
|
36
|
-
eTarget: 'fieldErrors' // | 'formErrors'
|
|
37
|
-
})
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
static validate() {
|
|
42
|
-
const rules = this.rules()
|
|
43
|
-
const h = async (c: Context) => {
|
|
44
|
-
return await this.handle(cx.cx)
|
|
45
|
-
}
|
|
6
|
+
static run() {
|
|
7
|
+
const rules = this.rules(validator)
|
|
8
|
+
const h = async (c: Context) => await this.handle(c.get('_'), response)
|
|
46
9
|
if (!rules) return [h]
|
|
47
10
|
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (!result.success) {
|
|
52
|
-
// @ts-ignore
|
|
53
|
-
return Response.badRequest({ ...result.error.flatten()[rule.eTarget] })
|
|
54
|
-
}
|
|
55
|
-
}))
|
|
56
|
-
|
|
57
|
-
rulesArray.push(h)
|
|
58
|
-
return rulesArray
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
static run() {
|
|
62
|
-
return this.validate()
|
|
11
|
+
const pipe = validator.parse(rules)
|
|
12
|
+
pipe.push(h)
|
|
13
|
+
return pipe
|
|
63
14
|
}
|
|
64
15
|
|
|
65
|
-
static rules():
|
|
16
|
+
static rules(v: IValidator): Rules {
|
|
66
17
|
return null
|
|
67
18
|
}
|
|
68
19
|
|
|
69
|
-
static async handle(
|
|
70
|
-
return Promise.resolve(
|
|
20
|
+
static async handle(req: IRequest, res: IResponse): Promise<Response> {
|
|
21
|
+
return Promise.resolve(res.raw(200, 'Action handle not implemented'))
|
|
71
22
|
}
|
|
72
23
|
}
|
package/src/auth/ability.ts
CHANGED
|
@@ -16,8 +16,8 @@ export class Ability {
|
|
|
16
16
|
const paths = actions?.map(a => Array.isArray(a) ? a[0] + a[1] : a.method + a.path) || []
|
|
17
17
|
const items = new Set(paths)
|
|
18
18
|
|
|
19
|
-
if (items.size
|
|
20
|
-
throw new Error(`Duplicate routes detected: "${paths.filter((path, index) => paths.indexOf(path)
|
|
19
|
+
if (items.size != actions.length)
|
|
20
|
+
throw new Error(`Duplicate routes detected: "${paths.filter((path, index) => paths.indexOf(path) != index).join('", "')}"`)
|
|
21
21
|
|
|
22
22
|
this.#abilities = Array.from(new Set(actions?.map(a => Array.isArray(a) ? a[3] : a.name) || []))
|
|
23
23
|
.map(a => this.format(a))
|
package/src/auth/authnz.ts
CHANGED
package/src/auth/index.ts
CHANGED
package/src/auth/token.ts
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import { Envir } from 't0n'
|
|
2
2
|
import { Token as Factory } from 'cripta'
|
|
3
3
|
import { UAParser } from 'ua-parser-js'
|
|
4
|
-
import
|
|
4
|
+
import type { IRequest } from '@/types'
|
|
5
5
|
|
|
6
6
|
export class Token {
|
|
7
|
+
static #cookieName: string = '__auth_'
|
|
7
8
|
static #name: string = 'Authorization'
|
|
8
9
|
static #prefix: string = 'bearer'
|
|
9
10
|
|
|
10
|
-
static fromRequest() {
|
|
11
|
-
const token = this.fromCookie() || this.fromHeader()
|
|
12
|
-
return token ? this.parse(token) : null
|
|
11
|
+
static fromRequest(req: IRequest) {
|
|
12
|
+
const token = this.fromCookie(req) || this.fromHeader(req)
|
|
13
|
+
return token ? this.parse(req, token) : null
|
|
13
14
|
}
|
|
14
15
|
|
|
15
|
-
static fromHeader(): string | null {
|
|
16
|
-
const header =
|
|
16
|
+
static fromHeader(req: IRequest): string | null {
|
|
17
|
+
const header = req.header(this.#name) || req.header('HTTP_AUTHORIZATION') || req.header('REDIRECT_HTTP_AUTHORIZATION') || null
|
|
17
18
|
|
|
18
19
|
if (header) {
|
|
19
20
|
const pos = header.toLowerCase().indexOf(this.#prefix.toLowerCase())
|
|
@@ -29,39 +30,39 @@ export class Token {
|
|
|
29
30
|
return null
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
static fromCookie(): string | null {
|
|
33
|
-
const uid =
|
|
33
|
+
static fromCookie(req: IRequest): string | null {
|
|
34
|
+
const uid = req.header('uid')
|
|
34
35
|
|
|
35
36
|
if (uid) {
|
|
36
|
-
const auth =
|
|
37
|
+
const auth = req.cookie.get(this.#cookieName + uid)
|
|
37
38
|
return auth ? auth : null
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
return null
|
|
41
42
|
}
|
|
42
43
|
|
|
43
|
-
static parse(token: string) {
|
|
44
|
-
const host = this.host()
|
|
44
|
+
static parse(req: IRequest, token: string) {
|
|
45
|
+
const host = this.host(req)
|
|
45
46
|
const serveHost = Envir.get('FLOW_SERVER', host) as string
|
|
46
47
|
|
|
47
48
|
return Factory.parse(token)
|
|
48
49
|
.issuedBy(serveHost)
|
|
49
50
|
.permittedFor(host)
|
|
50
|
-
.withClaim('u', this.userAgent())
|
|
51
|
-
.withClaim('i', this.ip())
|
|
51
|
+
.withClaim('u', this.userAgent(req))
|
|
52
|
+
.withClaim('i', this.ip(req))
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
static create(user: any, exp: number = 7200) {
|
|
55
|
+
static create(req: IRequest, user: any, exp: number = 7200) {
|
|
55
56
|
const time = Math.floor(Date.now() / 1000)
|
|
56
|
-
const host = this.host(
|
|
57
|
+
const host = this.host(req)
|
|
57
58
|
|
|
58
59
|
return Factory.create()
|
|
59
60
|
.issuedBy(host)
|
|
60
61
|
.permittedFor(host)
|
|
61
62
|
.issuedAt(time)
|
|
62
63
|
.expiresAt(time + exp)
|
|
63
|
-
.withClaim('u', this.userAgent())
|
|
64
|
-
.withClaim('i', this.ip())
|
|
64
|
+
.withClaim('u', this.userAgent(req))
|
|
65
|
+
.withClaim('i', this.ip(req))
|
|
65
66
|
.body(user)
|
|
66
67
|
}
|
|
67
68
|
|
|
@@ -73,8 +74,9 @@ export class Token {
|
|
|
73
74
|
this.#name = name
|
|
74
75
|
}
|
|
75
76
|
|
|
76
|
-
static host(
|
|
77
|
-
|
|
77
|
+
static host(req: IRequest): string {
|
|
78
|
+
const url = req.url || req.header('host')
|
|
79
|
+
if (!url) return ''
|
|
78
80
|
|
|
79
81
|
let formattedUrl = String(url)
|
|
80
82
|
if (!formattedUrl.startsWith('http'))
|
|
@@ -88,13 +90,14 @@ export class Token {
|
|
|
88
90
|
}
|
|
89
91
|
}
|
|
90
92
|
|
|
91
|
-
static userAgent() {
|
|
92
|
-
|
|
93
|
-
|
|
93
|
+
static userAgent(req: IRequest) {
|
|
94
|
+
const ua = req?.userAgent
|
|
95
|
+
if (!ua) return 0
|
|
96
|
+
const { browser, device, os } = UAParser(ua)
|
|
94
97
|
return (browser?.name || '') + (browser?.major || '') + (device?.model || '') + (os?.name || '')
|
|
95
98
|
}
|
|
96
99
|
|
|
97
|
-
static ip() {
|
|
98
|
-
return
|
|
100
|
+
static ip(req: IRequest) {
|
|
101
|
+
return req?.ip || 0
|
|
99
102
|
}
|
|
100
103
|
}
|
package/src/bin/rajt.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
|
+
import { join, dirname } from "node:path";
|
|
4
|
+
import { existsSync } from "node:fs";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = dirname(__filename);
|
|
9
|
+
|
|
10
|
+
const ERR_NODE_VERSION = "18.0.0";
|
|
11
|
+
const MIN_NODE_VERSION = "18.0.0";
|
|
12
|
+
|
|
13
|
+
let rajtProcess;
|
|
14
|
+
|
|
15
|
+
// Executes ../src/cli/index.ts
|
|
16
|
+
function runRajt() {
|
|
17
|
+
if (semiver(process.versions.node, ERR_NODE_VERSION) < 0) {
|
|
18
|
+
console.error(
|
|
19
|
+
`Rajt requires at least Node.js v${MIN_NODE_VERSION}. You are using v${process.versions.node}. Please update your version of Node.js.
|
|
20
|
+
|
|
21
|
+
Consider using a Node.js version manager such as https://volta.sh or https://github.com/nvm-sh/nvm.`
|
|
22
|
+
);
|
|
23
|
+
process.exitCode = 1;
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const tsxPaths = [
|
|
28
|
+
// join(__dirname, "../node_modules/.bin/tsx"),
|
|
29
|
+
// join(__dirname, "../../.bin/tsx"),
|
|
30
|
+
join(__dirname, "../node_modules/.bin/tsx"),
|
|
31
|
+
join(__dirname, "../../node_modules/.bin/tsx"),
|
|
32
|
+
join(process.cwd(), "node_modules/.bin/tsx"),
|
|
33
|
+
"tsx",
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
let tsxPath;
|
|
37
|
+
for (const pathOption of tsxPaths) {
|
|
38
|
+
if (pathOption == "tsx" || existsSync(pathOption)) {
|
|
39
|
+
tsxPath = pathOption;
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!tsxPath) {
|
|
45
|
+
console.error("TypeScript file found but tsx is not available. Please install tsx:");
|
|
46
|
+
console.error(" npm i -D tsx");
|
|
47
|
+
console.error(" or");
|
|
48
|
+
console.error(" bun i -D tsx");
|
|
49
|
+
process.exit(1);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return spawn(
|
|
54
|
+
process.execPath,
|
|
55
|
+
[
|
|
56
|
+
"--no-warnings",
|
|
57
|
+
...process.execArgv,
|
|
58
|
+
tsxPath,
|
|
59
|
+
join(__dirname, "../rajt/src/cli/index.ts"),
|
|
60
|
+
...process.argv.slice(2),
|
|
61
|
+
].filter(arg =>
|
|
62
|
+
!arg.includes('experimental-vm-modules') &&
|
|
63
|
+
!arg.includes('loader')
|
|
64
|
+
),
|
|
65
|
+
{
|
|
66
|
+
stdio: ["inherit", "inherit", "inherit", "ipc"],
|
|
67
|
+
env: {
|
|
68
|
+
...process.env,
|
|
69
|
+
NODE_ENV: process.env.NODE_ENV || 'development',
|
|
70
|
+
TSX_DISABLE_CACHE: process.env.TSX_DISABLE_CACHE || '1',
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
)
|
|
74
|
+
.on("exit", (code) =>
|
|
75
|
+
process.exit(code == null ? 0 : code)
|
|
76
|
+
)
|
|
77
|
+
.on("message", (message) => {
|
|
78
|
+
if (process.send) {
|
|
79
|
+
process.send(message);
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
.on("disconnect", () => {
|
|
83
|
+
if (process.disconnect) {
|
|
84
|
+
process.disconnect();
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
var fn = new Intl.Collator(0, { numeric: 1 }).compare;
|
|
90
|
+
|
|
91
|
+
function semiver(a, b, bool) {
|
|
92
|
+
a = a.split(".");
|
|
93
|
+
b = b.split(".");
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
fn(a[0], b[0]) ||
|
|
97
|
+
fn(a[1], b[1]) ||
|
|
98
|
+
((b[2] = b.slice(2).join(".")),
|
|
99
|
+
(bool = /[.-]/.test((a[2] = a.slice(2).join(".")))),
|
|
100
|
+
bool == /[.-]/.test(b[2]) ? fn(a[2], b[2]) : bool ? -1 : 1)
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function directly() {
|
|
105
|
+
try {
|
|
106
|
+
return ![typeof require, typeof module].includes('undefined') && require.main == module
|
|
107
|
+
|| import.meta.url == `file://${process.argv[1]}`
|
|
108
|
+
|| process.argv[1].endsWith(process.env?.npm_package_bin_rajt)
|
|
109
|
+
|| import.meta?.url?.endsWith(process.env?.npm_package_bin_rajt)
|
|
110
|
+
} catch {
|
|
111
|
+
return false
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (directly()) {
|
|
116
|
+
rajtProcess = runRajt();
|
|
117
|
+
process.on("SIGINT", () => {
|
|
118
|
+
rajtProcess && rajtProcess.kill();
|
|
119
|
+
});
|
|
120
|
+
process.on("SIGTERM", () => {
|
|
121
|
+
rajtProcess && rajtProcess.kill();
|
|
122
|
+
});
|
|
123
|
+
}
|