rajt 0.0.100 → 0.0.101
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/bin/rajt.js +59 -50
- package/package.json +10 -10
- package/src/cli/commands/dev.ts +1 -1
- package/src/cli/index.ts +2 -2
- package/src/cli/utils.ts +5 -4
- package/src/create-app.ts +2 -2
- package/src/open-api/register.ts +2 -1
- package/src/request.ts +13 -0
- package/src/routes.ts +10 -4
- package/src/utils/environment.ts +10 -8
- package/src/validator.ts +28 -4
package/bin/rajt.js
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { spawn } from 'node:child_process';
|
|
3
|
-
import { join, dirname } from 'node:path';
|
|
3
|
+
import { join, dirname, resolve } from 'node:path';
|
|
4
4
|
import { existsSync } from 'node:fs';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
5
6
|
|
|
6
|
-
const __dirname = dirname(
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
8
|
|
|
8
9
|
const ERR_NODE_VERSION = '18.0.0';
|
|
9
10
|
const MIN_NODE_VERSION = '18.0.0';
|
|
10
11
|
|
|
11
|
-
let rajtProcess;
|
|
12
|
-
|
|
13
12
|
function runRajt() {
|
|
14
13
|
if (process?.versions?.node && semiver(process.versions.node, ERR_NODE_VERSION) < 0) {
|
|
15
14
|
console.error(
|
|
@@ -21,58 +20,70 @@ Consider using a Node.js version manager such as https://volta.sh or https://git
|
|
|
21
20
|
return;
|
|
22
21
|
}
|
|
23
22
|
|
|
24
|
-
const isBun = process?.isBun || typeof Bun
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
join(process.cwd(), _tsxPath),
|
|
35
|
-
'tsx',
|
|
36
|
-
];
|
|
37
|
-
|
|
38
|
-
for (const pathOption of tsxPaths) {
|
|
39
|
-
if (pathOption == 'tsx' || existsSync(pathOption)) {
|
|
40
|
-
tsxPath = pathOption;
|
|
41
|
-
break;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
23
|
+
const isBun = process?.isBun || typeof Bun !== 'undefined';
|
|
24
|
+
const targetScript = resolve(__dirname, '../src/cli/index.ts');
|
|
25
|
+
|
|
26
|
+
let executor = process.execPath;
|
|
27
|
+
let args = [];
|
|
28
|
+
|
|
29
|
+
if (isBun) {
|
|
30
|
+
args = [targetScript, ...process.argv.slice(2)];
|
|
31
|
+
} else {
|
|
32
|
+
const tsxBin = findTsx();
|
|
44
33
|
|
|
45
|
-
if (!
|
|
46
|
-
console.error('
|
|
34
|
+
if (!tsxBin) {
|
|
35
|
+
console.error('Error: "tsx" is not available. Please install tsx:');
|
|
47
36
|
console.error(' npm i -D tsx');
|
|
48
37
|
console.error(' or');
|
|
49
38
|
console.error(' bun i -D tsx');
|
|
50
39
|
process.exit(1);
|
|
51
|
-
return;
|
|
52
40
|
}
|
|
53
|
-
}
|
|
54
41
|
|
|
55
|
-
|
|
56
|
-
process.execPath,
|
|
57
|
-
[
|
|
42
|
+
args = [
|
|
58
43
|
'--no-warnings',
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
44
|
+
tsxBin,
|
|
45
|
+
targetScript,
|
|
46
|
+
...process.argv.slice(2)
|
|
47
|
+
].filter(arg => !arg.includes('experimental-vm-modules') && !arg.includes('loader'));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return execute(executor, args)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function findTsx() {
|
|
54
|
+
const relativePaths = [
|
|
55
|
+
join(__dirname, '../node_modules/tsx/dist/cli.mjs'),
|
|
56
|
+
join(process.cwd(), 'node_modules/tsx/dist/cli.mjs'),
|
|
57
|
+
join(__dirname, '../node_modules/.bin/tsx'),
|
|
58
|
+
join(process.cwd(), 'node_modules/.bin/tsx'),
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
for (const p of relativePaths) {
|
|
62
|
+
if (existsSync(p)) return p;
|
|
63
|
+
if (existsSync(`${p}.exe`)) return `${p}.exe`;
|
|
64
|
+
if (existsSync(`${p}.cmd`)) return `${p}.cmd`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return null
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function execute(command, args) {
|
|
71
|
+
const child = spawn(command, args, {
|
|
72
|
+
stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
|
|
73
|
+
env: {
|
|
74
|
+
...process.env,
|
|
75
|
+
NODE_ENV: process.env.NODE_ENV || 'development',
|
|
76
|
+
TSX_DISABLE_CACHE: '1',
|
|
71
77
|
}
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
.on('
|
|
75
|
-
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
process.on('SIGINT', () => child.kill('SIGINT'))
|
|
81
|
+
.on('SIGTERM', () => child.kill('SIGTERM'));
|
|
82
|
+
|
|
83
|
+
return child
|
|
84
|
+
.on('exit', code => process.exit(code ?? 0))
|
|
85
|
+
.on('message', msg => process.send?.(msg))
|
|
86
|
+
.on('disconnect', () => process.disconnect?.())
|
|
76
87
|
}
|
|
77
88
|
|
|
78
89
|
var fn = new Intl.Collator(0, { numeric: 1 }).compare;
|
|
@@ -101,7 +112,5 @@ function directly() {
|
|
|
101
112
|
}
|
|
102
113
|
|
|
103
114
|
if (directly()) {
|
|
104
|
-
|
|
105
|
-
process.on('SIGINT', () => rajtProcess && rajtProcess.kill())
|
|
106
|
-
.on('SIGTERM', () => rajtProcess && rajtProcess.kill());
|
|
115
|
+
runRajt()
|
|
107
116
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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.101",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
7
7
|
"files": ["bin", "src"],
|
|
@@ -35,25 +35,25 @@
|
|
|
35
35
|
"zip": "zip -j ../../lambda.zip ../../.rajt/dist/index.js"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@hono/node-server": "^1.19.
|
|
38
|
+
"@hono/node-server": "^1.19.11",
|
|
39
39
|
"@hono/standard-validator": "^0.2.2",
|
|
40
40
|
"@hono/zod-validator": "^0.7.6",
|
|
41
|
-
"@scalar/hono-api-reference": "^0.
|
|
41
|
+
"@scalar/hono-api-reference": "^0.10.3",
|
|
42
42
|
"chokidar": "^3.5.2",
|
|
43
43
|
"citty": "^0.1.6",
|
|
44
44
|
"consola": "^3.4.2",
|
|
45
|
-
"cripta": "^0.1.
|
|
45
|
+
"cripta": "^0.1.12",
|
|
46
46
|
"dotenv": "^16.5.0",
|
|
47
47
|
"esbuild": "^0.25.2",
|
|
48
|
-
"forj": "^0.1.
|
|
49
|
-
"hono": "^4.
|
|
48
|
+
"forj": "^0.1.10",
|
|
49
|
+
"hono": "^4.12.8",
|
|
50
50
|
"hono-openapi": "^1.3.0",
|
|
51
|
-
"localflare-api": "^0.
|
|
52
|
-
"localflare-core": "^0.
|
|
53
|
-
"miniflare": "^4.
|
|
51
|
+
"localflare-api": "^0.5.0",
|
|
52
|
+
"localflare-core": "^0.5.0",
|
|
53
|
+
"miniflare": "^4.20260312.0",
|
|
54
54
|
"pathe": "^2.0",
|
|
55
55
|
"quansync": "^0.2.11",
|
|
56
|
-
"t0n": "^0.1.
|
|
56
|
+
"t0n": "^0.1.13",
|
|
57
57
|
"tiny-glob": "^0.2",
|
|
58
58
|
"tsx": "^4.19.4",
|
|
59
59
|
"wrangler": "^4.61.0",
|
package/src/cli/commands/dev.ts
CHANGED
package/src/cli/index.ts
CHANGED
|
@@ -19,8 +19,8 @@ import make from './commands/make'
|
|
|
19
19
|
const directly = () => {
|
|
20
20
|
try {
|
|
21
21
|
// @ts-ignore
|
|
22
|
-
return typeof vitest
|
|
23
|
-
&& import.meta.url
|
|
22
|
+
return typeof vitest === 'undefined'
|
|
23
|
+
&& import.meta.url?.endsWith(process.argv[1].replace(/\\/g, '/'))
|
|
24
24
|
} catch {
|
|
25
25
|
return false
|
|
26
26
|
}
|
package/src/cli/utils.ts
CHANGED
|
@@ -117,7 +117,7 @@ function stripDecorators(source: string) {
|
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
const dist = '.rajt/dist'
|
|
120
|
-
export const build = async (platform: Platform) => {
|
|
120
|
+
export const build = async (platform: Platform, env: string = 'prd') => {
|
|
121
121
|
const startTime = Date.now()
|
|
122
122
|
|
|
123
123
|
const isCF = platform == 'cf'
|
|
@@ -160,9 +160,10 @@ export const build = async (platform: Platform) => {
|
|
|
160
160
|
],
|
|
161
161
|
metafile: true,
|
|
162
162
|
write: false,
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
163
|
+
define: {
|
|
164
|
+
'process.env.RAJT_ENV': env,
|
|
165
|
+
// 'process.env.NODE_ENV': '"development"',
|
|
166
|
+
},
|
|
166
167
|
// tsconfig: join(_root, 'tsconfig.json'),
|
|
167
168
|
// sourcemap: true,
|
|
168
169
|
// logLevel: 'info',
|
package/src/create-app.ts
CHANGED
|
@@ -113,11 +113,11 @@ export const createApp = <E extends Env>(options?: ServerOptions<E>) => {
|
|
|
113
113
|
if (options?.init) options.init(app)
|
|
114
114
|
|
|
115
115
|
const routes = options?.routes || [] // @ts-ignore
|
|
116
|
-
const routeRegister = options?.routeRegister ? options.routeRegister : (_: Hono, route: Route) => {
|
|
116
|
+
const routeRegister = options?.routeRegister ? options.routeRegister : (_: Hono, route: Route) => {
|
|
117
117
|
if (Array.isArray(route)) { // @ts-ignore
|
|
118
118
|
_[getVerb[route[0]]](route[1], ...resolve(...route[2], route[3]))
|
|
119
119
|
} else { // @ts-ignore
|
|
120
|
-
_[route.method](route.path, ...resolve(...route.middlewares
|
|
120
|
+
_[route.method](route.path, ...resolve(...route.middlewares, route.handle))
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
123
|
|
package/src/open-api/register.ts
CHANGED
|
@@ -61,7 +61,8 @@ export function registerOpenAPI(app: Hono, conf: any) {
|
|
|
61
61
|
slug: opts.appName?.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '').replace(/[^\w\s_-]/g, '').replace(/[\s_-]+/g, '_').replace(/[^\x00-\x7F]/g, '') +'_'+ opts.appVersion,
|
|
62
62
|
// hideDownloadButton: true,
|
|
63
63
|
// onLoaded: () => document?.querySelectorAll('[href="https://www.scalar.com"]')?.forEach(el => el.remove()),
|
|
64
|
-
customCss: `[href="https://www.scalar.com"]{display:none}`,
|
|
64
|
+
customCss: `[href="https://www.scalar.com"],.scalar-mcp-layer{display:none!important}`,
|
|
65
|
+
// favicon: 'https://example.com/favicon.png',
|
|
65
66
|
})
|
|
66
67
|
)
|
|
67
68
|
}
|
package/src/request.ts
CHANGED
|
@@ -27,6 +27,7 @@ export default class $Request {
|
|
|
27
27
|
#u: Authnz<any> | null = null
|
|
28
28
|
|
|
29
29
|
#host: string
|
|
30
|
+
#protocol: string
|
|
30
31
|
#routePath?: string
|
|
31
32
|
#matchedRoutes: RouterRoute[]
|
|
32
33
|
|
|
@@ -37,6 +38,7 @@ export default class $Request {
|
|
|
37
38
|
|
|
38
39
|
const url = new URL(c.req.raw.url)
|
|
39
40
|
this.#host = url.protocol +'//'+ url.host
|
|
41
|
+
this.#protocol = url.protocol
|
|
40
42
|
|
|
41
43
|
this.#matchedRoutes = matchedRoutes(c)
|
|
42
44
|
}
|
|
@@ -68,6 +70,13 @@ export default class $Request {
|
|
|
68
70
|
return this.has(prop, value)
|
|
69
71
|
}
|
|
70
72
|
|
|
73
|
+
createToken(data: any, exp: number) {
|
|
74
|
+
return Token.create(this, data, exp)
|
|
75
|
+
}
|
|
76
|
+
parseToken(token: string) {
|
|
77
|
+
return Token.parse(this, token)
|
|
78
|
+
}
|
|
79
|
+
|
|
71
80
|
get cx() {
|
|
72
81
|
return this.#c
|
|
73
82
|
}
|
|
@@ -90,6 +99,10 @@ export default class $Request {
|
|
|
90
99
|
return this.#c.req.header('user-agent')
|
|
91
100
|
}
|
|
92
101
|
|
|
102
|
+
get protocol() {
|
|
103
|
+
return this.#protocol
|
|
104
|
+
}
|
|
105
|
+
|
|
93
106
|
get url() {
|
|
94
107
|
return this.#c.req.raw.url
|
|
95
108
|
}
|
package/src/routes.ts
CHANGED
|
@@ -4,11 +4,13 @@ import { join, resolve, relative } from 'pathe'
|
|
|
4
4
|
import { IMPORT } from 't0n'
|
|
5
5
|
import glob from 'tiny-glob'
|
|
6
6
|
import { config } from 'dotenv'
|
|
7
|
-
import { describeRoute, resolver } from 'hono-openapi'
|
|
7
|
+
import { describeRoute, resolver, validator } from 'hono-openapi'
|
|
8
8
|
import { mimes } from 'hono/utils/mime'
|
|
9
9
|
import { STATUS_CODES } from 'node:http'
|
|
10
10
|
import { registerHandler, registerMiddleware } from './register'
|
|
11
11
|
import createApp from './create-app'
|
|
12
|
+
import _response from './response'
|
|
13
|
+
import _validator from './validator'
|
|
12
14
|
import { isAnonFn } from './utils/func'
|
|
13
15
|
import ensureDir from './utils/ensuredir'
|
|
14
16
|
import versionSHA from './utils/version-sha'
|
|
@@ -20,7 +22,7 @@ import { resolve as _resolve } from './utils/resolve'
|
|
|
20
22
|
import { highlightedMethod, highlightedURI } from './cli/utils'
|
|
21
23
|
|
|
22
24
|
import type * as z from 'zod'
|
|
23
|
-
import type { Routes, StandardSchemaV1 } from './types'
|
|
25
|
+
import type { Routes, Rule, StandardSchemaV1 } from './types'
|
|
24
26
|
|
|
25
27
|
const importName = (name?: string) => (name || 'Fn'+ Math.random().toString(36).substring(2)).replace(/\.ts$/, '')
|
|
26
28
|
const walk = async (dir: string, baseDir: string, fn: Function, parentMw: string[] = []): Promise<void> => {
|
|
@@ -358,9 +360,13 @@ export async function cacheRoutes() {
|
|
|
358
360
|
registerHandler(h[1], mod[h[1]])
|
|
359
361
|
}
|
|
360
362
|
|
|
363
|
+
_validator.setParser((rule: Rule) => validator(rule.target, rule.schema, (result, c) => {
|
|
364
|
+
if (!result.success) // @ts-ignore
|
|
365
|
+
return _response.badRequest(result.error)
|
|
366
|
+
}))
|
|
361
367
|
// @ts-ignore
|
|
362
368
|
const openApi = await generateOpenAPI(createApp({ routes, routeRegister: (app: Hono, route: Route) => {
|
|
363
|
-
app[route.method](route.path, describeRoute(route.desc), ..._resolve(...route.middlewares
|
|
369
|
+
app[route.method](route.path, describeRoute(route.desc), ..._resolve(...route.middlewares, route.handle))
|
|
364
370
|
} }), configs?.rajt || {})
|
|
365
371
|
|
|
366
372
|
const iPath = join(_root, '.rajt/imports.mjs')
|
|
@@ -374,7 +380,7 @@ export async function cacheRoutes() {
|
|
|
374
380
|
stringifyToJS(Object.fromEntries(routes.map(r => ([r.path + r.method, r.name]))))
|
|
375
381
|
|
|
376
382
|
writeFileSync(iPath, `// AUTO-GENERATED FILE - DO NOT EDIT
|
|
377
|
-
${env?.length ? `import { Envir } from '${await dependencyPath('t0n')}/
|
|
383
|
+
${env?.length ? `import { Envir } from '${await dependencyPath('t0n')}/src/envir'\nEnvir.add({${env.map(([key, val]) => key +':'+ stringifyToJS(val)).join(',')}})` : ''}
|
|
378
384
|
${Object.entries(configs)?.length ? `import Config from '${_rajtDir}/src/config'\nConfig.add(${stringifyToJS(configs)})` : ''}
|
|
379
385
|
|
|
380
386
|
import { registerHandler, registerMiddleware } from '${_rajtDir}/src/register'
|
package/src/utils/environment.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
const prd = Symbol('prd')
|
|
2
2
|
const dev = Symbol('dev')
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
// @ts-ignore
|
|
5
|
+
let env = process.env.RAJT_ENV || prd
|
|
5
6
|
|
|
6
|
-
export const getEnv = () => env
|
|
7
|
+
export const getEnv = () => env // @ts-ignore
|
|
7
8
|
export const setEnv = (e: symbol) => env = e
|
|
8
9
|
|
|
9
|
-
export function detectEnvironment() {
|
|
10
|
+
export function detectEnvironment(): symbol {
|
|
10
11
|
try {
|
|
11
12
|
if (
|
|
12
|
-
process.env?.npm_lifecycle_event
|
|
13
|
-
|| process.env?.npm_lifecycle_script
|
|
13
|
+
process.env?.npm_lifecycle_event === 'dev'
|
|
14
|
+
|| process.env?.npm_lifecycle_script === 'rajt'
|
|
14
15
|
|| process.env?.AWS_SAM_LOCAL
|
|
15
16
|
// || process?.argv?.includes('--dev')
|
|
16
17
|
|| process?.argv?.some(arg => ['-port', '-platform', '--dev', '--development', '--watch'].includes(arg))
|
|
@@ -24,10 +25,11 @@ export function detectEnvironment() {
|
|
|
24
25
|
return prd
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
export const isEnv = (e: symbol) => env
|
|
28
|
+
export const isEnv = (e: symbol) => env === e
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
export const
|
|
30
|
+
// @ts-ignore
|
|
31
|
+
export const isDev = () => env === dev
|
|
32
|
+
export const isProd = () => env === prd
|
|
31
33
|
|
|
32
34
|
export const isDevelopment = isDev
|
|
33
35
|
export const isProduction = isProd
|
package/src/validator.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { zValidator } from '@hono/zod-validator'
|
|
2
2
|
import response from './response'
|
|
3
|
+
import type * as z from 'zod'
|
|
3
4
|
import type {
|
|
4
5
|
Rule, Rules, RuleFn,
|
|
5
6
|
ValidationTargets,
|
|
6
7
|
zObject,
|
|
8
|
+
MiddlewareHandler,
|
|
7
9
|
} from './types'
|
|
8
10
|
|
|
9
11
|
export default class $Validator {
|
|
@@ -36,11 +38,33 @@ export default class $Validator {
|
|
|
36
38
|
static readonly header = $Validator.fn('header')!
|
|
37
39
|
static readonly cookie = $Validator.fn('cookie')!
|
|
38
40
|
|
|
41
|
+
static #parser = (rule: Rule) => zValidator(rule.target, rule.schema, (result, c) => {
|
|
42
|
+
if (!result.success) // @ts-ignore
|
|
43
|
+
return response.badRequest(formatZodErrors(result.error.issues || []))
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
static setParser(parser: (rule: Rule) => MiddlewareHandler) {
|
|
47
|
+
this.#parser = parser
|
|
48
|
+
}
|
|
49
|
+
|
|
39
50
|
static parse(rules: Rules): Function[] {
|
|
40
51
|
return (Array.isArray(rules) ? rules : [rules]) // @ts-ignore
|
|
41
|
-
.flatMap(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
52
|
+
.flatMap(this.#parser)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function formatZodErrors(issues: z.ZodIssue[]): Record<string, string[]> {
|
|
57
|
+
const result: Record<string, string[]> = {}
|
|
58
|
+
|
|
59
|
+
for (const issue of issues) {
|
|
60
|
+
const path = issue.path.join('.')
|
|
61
|
+
const key = path || 'root'
|
|
62
|
+
|
|
63
|
+
if (!result[key])
|
|
64
|
+
result[key] = []
|
|
65
|
+
|
|
66
|
+
result[key].push(issue.message)
|
|
45
67
|
}
|
|
68
|
+
|
|
69
|
+
return result
|
|
46
70
|
}
|