rajt 0.0.57 → 0.0.58
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 +31 -11
- package/src/bin/rajt.js +123 -0
- package/src/cli/commands/dev/index.ts +294 -0
- package/src/cli/commands/dev/utils.ts +206 -0
- package/src/cli/index.ts +69 -0
- package/src/cli/types.ts +1 -0
- package/src/create-app.ts +8 -2
- package/src/dev.ts +18 -15
- package/src/dynamodb/compact.ts +3 -3
- package/src/dynamodb/decorators.ts +12 -12
- package/src/dynamodb/model.ts +2 -2
- package/src/dynamodb/repository.ts +1 -1
- package/src/esbuild.mjs +11 -9
- package/src/http.ts +3 -3
- package/src/index.ts +1 -1
- package/src/prod-aws.ts +2 -17
- package/src/prod-cf.ts +1 -18
- package/src/prod.ts +16 -0
- package/src/scripts/cache-routes.ts +1 -1
- 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 +2 -2
- package/src/utils/shutdown.ts +19 -0
- package/src/enum.ts +0 -75
- 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,9 +1,12 @@
|
|
|
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.58",
|
|
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",
|
|
@@ -18,6 +21,7 @@
|
|
|
18
21
|
"src"
|
|
19
22
|
],
|
|
20
23
|
"scripts": {
|
|
24
|
+
"rajt": "./src/bin/rajt.js",
|
|
21
25
|
"dev": "tsx watch src/dev.ts",
|
|
22
26
|
"aws:build": "bun run --silent cache:routes && bun run --silent aws:export && bun run --silent clean:temp",
|
|
23
27
|
"cf:build": "bun run --silent cache:routes && bun run --silent cf:export && bun run --silent clean:temp",
|
|
@@ -33,7 +37,7 @@
|
|
|
33
37
|
"sam:package": "sam package --template-file ../../template-prod.yaml --output-template-file ../../packaged.yaml",
|
|
34
38
|
"sam:deploy": "sam deploy --template-file ../../packaged.yaml --stack-name rajt-llrt --capabilities CAPABILITY_IAM",
|
|
35
39
|
"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
|
|
40
|
+
"cf:local-": "source ../../.env.dev && bun run --silent cf:build:watch -- cd ../../dist && bunx wrangler dev --port=$PORT --persist-to='../.wrangler/state'",
|
|
37
41
|
"cf:deploy": "bun run --silent cf:build && cd ../../dist && bunx wrangler deploy",
|
|
38
42
|
"cache:routes": "tsx src/scripts/cache-routes.ts",
|
|
39
43
|
"ensure-dirs": "rm -rf ../../dist ../../tmp && mkdir -p ../../tmp && chmod 755 ../../tmp && mkdir -p ../../dist && chmod 755 ../../dist",
|
|
@@ -46,22 +50,38 @@
|
|
|
46
50
|
"dependencies": {
|
|
47
51
|
"@aws-sdk/client-dynamodb": "3.817.0",
|
|
48
52
|
"@aws-sdk/lib-dynamodb": "3.817.0",
|
|
49
|
-
"@hono/node-server": "^1.14.1",
|
|
50
53
|
"@hono/zod-validator": "^0.4.3",
|
|
54
|
+
"cripta": "^0.1",
|
|
55
|
+
"hono": "^4.7.6",
|
|
56
|
+
"pluralize": "^8.0",
|
|
57
|
+
"t0n": "^0.1.5",
|
|
58
|
+
"ua-parser-js": "^2.0.4"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@cloudflare/workers-types": "^4.20251230.0",
|
|
62
|
+
"@hono/node-server": "^1.14.1",
|
|
63
|
+
"@iarna/toml": "^2.2.5",
|
|
64
|
+
"@miniflare/core": "^2.14.4",
|
|
65
|
+
"@miniflare/d1": "^2.14.4",
|
|
66
|
+
"@miniflare/durable-objects": "^2.14.4",
|
|
67
|
+
"@miniflare/kv": "^2.14.4",
|
|
68
|
+
"@miniflare/r2": "^2.14.4",
|
|
69
|
+
"@miniflare/scheduler": "^2.14.4",
|
|
70
|
+
"@miniflare/sites": "^2.14.4",
|
|
71
|
+
"@miniflare/storage-file": "^2.14.4",
|
|
72
|
+
"@miniflare/web-sockets": "^2.14.4",
|
|
51
73
|
"@types/node": "^20.11.0",
|
|
74
|
+
"@types/pluralize": "^0.0.33",
|
|
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"
|
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 === undefined || 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
|
+
}
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs'
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import { dirname, join, relative } from 'node:path'
|
|
4
|
+
import { spawn, type ChildProcess } from 'node:child_process'
|
|
5
|
+
|
|
6
|
+
import chokidar from 'chokidar'
|
|
7
|
+
import colors from 'picocolors'
|
|
8
|
+
import { defineCommand } from 'citty'
|
|
9
|
+
import type { ChokidarEventName } from '../../types'
|
|
10
|
+
|
|
11
|
+
import type { Miniflare } from 'miniflare'
|
|
12
|
+
import { build, createMiniflare } from './utils'
|
|
13
|
+
import { getAvailablePort } from '../../../utils/port'
|
|
14
|
+
import shutdown from '../../../utils/shutdown'
|
|
15
|
+
|
|
16
|
+
const __dirname = join(dirname(fileURLToPath(import.meta.url)), '../../../../../../')
|
|
17
|
+
|
|
18
|
+
export default defineCommand({
|
|
19
|
+
meta: {
|
|
20
|
+
name: 'dev',
|
|
21
|
+
description: '💻 Start the localhost server\n',
|
|
22
|
+
},
|
|
23
|
+
args: {
|
|
24
|
+
port: {
|
|
25
|
+
description: 'Port to listen on',
|
|
26
|
+
type: 'number',
|
|
27
|
+
default: 3000,
|
|
28
|
+
},
|
|
29
|
+
host: {
|
|
30
|
+
description: 'Host to forward requests to, defaults to the zone of project',
|
|
31
|
+
type: 'string',
|
|
32
|
+
default: 'localhost',
|
|
33
|
+
},
|
|
34
|
+
platform: {
|
|
35
|
+
alias: 'p',
|
|
36
|
+
description: 'Environment platform',
|
|
37
|
+
type: 'enum',
|
|
38
|
+
options: ['aws', 'cf', 'node'] as const,
|
|
39
|
+
required: true,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
async run({ args }) {
|
|
43
|
+
const platform = args.p || args.platform
|
|
44
|
+
const desiredPort = args.port ? Number(args.port) : 3000
|
|
45
|
+
const host = args.host ? String(args.host) : 'localhost'
|
|
46
|
+
switch (platform) {
|
|
47
|
+
case 'aws':
|
|
48
|
+
return withPort(desiredPort, async (port) => {
|
|
49
|
+
let isBuilding = false
|
|
50
|
+
let lambda: ChildProcess | null = null
|
|
51
|
+
|
|
52
|
+
const buildLambda = async () => {
|
|
53
|
+
if (isBuilding) return
|
|
54
|
+
isBuilding = true
|
|
55
|
+
logger.step('Building lambda')
|
|
56
|
+
try {
|
|
57
|
+
await build(platform)
|
|
58
|
+
if (!lambda) await startLambda()
|
|
59
|
+
} catch (e) {
|
|
60
|
+
logger.error('Build failed:', e)
|
|
61
|
+
process.exit(0)
|
|
62
|
+
} finally {
|
|
63
|
+
isBuilding = false
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const stopLambda = async () => {
|
|
68
|
+
if (!lambda) return
|
|
69
|
+
logger.step('Stopping lambda process...')
|
|
70
|
+
try {
|
|
71
|
+
if (!lambda?.killed) {
|
|
72
|
+
lambda.kill('SIGTERM')
|
|
73
|
+
await wait(1000)
|
|
74
|
+
|
|
75
|
+
if (!lambda?.killed) { // force kill
|
|
76
|
+
lambda.kill('SIGKILL')
|
|
77
|
+
await wait(1000)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
lambda = null
|
|
82
|
+
} catch (e) {
|
|
83
|
+
logger.warn('Error stopping lambda:', e)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const startLambda = async () => {
|
|
88
|
+
await stopLambda()
|
|
89
|
+
|
|
90
|
+
lambda = spawn(
|
|
91
|
+
'sam',
|
|
92
|
+
[
|
|
93
|
+
'local', 'start-api',
|
|
94
|
+
'--warm-containers', 'LAZY',
|
|
95
|
+
'--debug', '--template-file', join(__dirname, 'template-dev.yaml'),
|
|
96
|
+
'--port', args.port,
|
|
97
|
+
],
|
|
98
|
+
{
|
|
99
|
+
stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
|
|
100
|
+
// stdio: ['pipe', 'pipe', 'pipe', 'ipc'],
|
|
101
|
+
shell: process.platform == 'win32',
|
|
102
|
+
env: {...process.env, DOCKER_HOST: getDockerHost()},
|
|
103
|
+
}
|
|
104
|
+
).on('exit', code => {
|
|
105
|
+
logger.step(`Lambda process exited with code ${code ?? 0}`)
|
|
106
|
+
if (code !== 0 && code !== null)
|
|
107
|
+
logger.error('Lambda process crashed, waiting for restart...')
|
|
108
|
+
|
|
109
|
+
lambda = null
|
|
110
|
+
})
|
|
111
|
+
.on('message', msg => {
|
|
112
|
+
if (process.send) process.send(msg)
|
|
113
|
+
}).on('disconnect', () => {
|
|
114
|
+
if (process.disconnect) process.disconnect()
|
|
115
|
+
}).on('error', e => {
|
|
116
|
+
logger.error('Lambda process error:', e)
|
|
117
|
+
lambda = null
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
await wait(2000)
|
|
121
|
+
|
|
122
|
+
logger.step('Lambda process started successfully')
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
await buildLambda()
|
|
126
|
+
logger.step(`API running on http://${host}:${port}`)
|
|
127
|
+
|
|
128
|
+
watch(async () => {
|
|
129
|
+
await buildLambda()
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
shutdown(async () => {
|
|
133
|
+
await stopLambda()
|
|
134
|
+
})
|
|
135
|
+
})
|
|
136
|
+
case 'cf':
|
|
137
|
+
return withPort(desiredPort, async (port) => {
|
|
138
|
+
let isBuilding = false
|
|
139
|
+
|
|
140
|
+
const buildWorker = async () => {
|
|
141
|
+
if (isBuilding) return
|
|
142
|
+
isBuilding = true
|
|
143
|
+
logger.step('Building worker')
|
|
144
|
+
try {
|
|
145
|
+
await build(platform)
|
|
146
|
+
await startWorker()
|
|
147
|
+
} catch (e) {
|
|
148
|
+
logger.error('Build failed:', e)
|
|
149
|
+
process.exit(0)
|
|
150
|
+
} finally {
|
|
151
|
+
isBuilding = false
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
let worker: Miniflare | null = null
|
|
156
|
+
const startWorker = async () => {
|
|
157
|
+
if (worker) await worker.dispose()
|
|
158
|
+
|
|
159
|
+
worker = await createMiniflare({ port, host, liveReload: false })
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
await buildWorker()
|
|
163
|
+
logger.step(`API running on http://${host}:${port}`)
|
|
164
|
+
|
|
165
|
+
watch(async () => {
|
|
166
|
+
logger.step('Restarting server')
|
|
167
|
+
await buildWorker()
|
|
168
|
+
logger.step('Server restarted')
|
|
169
|
+
})
|
|
170
|
+
})
|
|
171
|
+
case 'node':
|
|
172
|
+
return withPort(desiredPort, async (port) => {
|
|
173
|
+
logger.step(`API running on http://${host}:${port}`)
|
|
174
|
+
|
|
175
|
+
spawn(
|
|
176
|
+
process.execPath,
|
|
177
|
+
[
|
|
178
|
+
join(__dirname, 'node_modules/.bin/tsx'), 'watch', join(__dirname, 'node_modules/rajt/src/dev.ts'),
|
|
179
|
+
],
|
|
180
|
+
{
|
|
181
|
+
stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
|
|
182
|
+
env: {...process.env, PORT: args.port},
|
|
183
|
+
}
|
|
184
|
+
).on('exit', code => process.exit(code ?? 0))
|
|
185
|
+
.on('message', msg => {
|
|
186
|
+
if (process.send) process.send(msg)
|
|
187
|
+
}).on('disconnect', () => {
|
|
188
|
+
if (process.disconnect) process.disconnect()
|
|
189
|
+
})
|
|
190
|
+
})
|
|
191
|
+
default:
|
|
192
|
+
return logger.warn(
|
|
193
|
+
`🟠 Provide a valid platform: ${['aws', 'cf', 'node'].map(p => colors.blue(p)).join(', ')}.\n`
|
|
194
|
+
)
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
function withPort(desiredPort: number, cb: (port: number) => void) {
|
|
200
|
+
getAvailablePort(desiredPort)
|
|
201
|
+
.then((port: number) => {
|
|
202
|
+
if (port != desiredPort)
|
|
203
|
+
logger.warn(`Port ${desiredPort} was in use, using ${port} as a fallback`)
|
|
204
|
+
|
|
205
|
+
cb(port)
|
|
206
|
+
}).catch(e => logger.error('Error finding available port:', e))
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function getAssetChangeMessage(
|
|
210
|
+
e: ChokidarEventName,
|
|
211
|
+
path: string
|
|
212
|
+
): string {
|
|
213
|
+
path = relative(__dirname, path)
|
|
214
|
+
switch (e) {
|
|
215
|
+
case 'add':
|
|
216
|
+
return `File ${path} was added`
|
|
217
|
+
case 'addDir':
|
|
218
|
+
return `Directory ${path} was added`
|
|
219
|
+
case 'unlink':
|
|
220
|
+
return `File ${path} was removed`
|
|
221
|
+
case 'unlinkDir':
|
|
222
|
+
return `Directory ${path} was removed`
|
|
223
|
+
case 'change':
|
|
224
|
+
default:
|
|
225
|
+
return `${path} changed`
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
async function watch(cb: (e: ChokidarEventName | string, file: string) => Promise<void>) {
|
|
230
|
+
const codeWatcher = chokidar.watch([
|
|
231
|
+
join(__dirname, 'actions/**/*.ts'),
|
|
232
|
+
join(__dirname, 'configs/**/*.ts'),
|
|
233
|
+
join(__dirname, 'enums/**/*.ts'),
|
|
234
|
+
join(__dirname, 'locales/**/*.ts'),
|
|
235
|
+
join(__dirname, 'middlewares/**/*.ts'),
|
|
236
|
+
join(__dirname, 'models/**/*.ts'),
|
|
237
|
+
join(__dirname, 'utils/**/*.ts'),
|
|
238
|
+
join(__dirname, '.env.dev'),
|
|
239
|
+
join(__dirname, '.env.prod'),
|
|
240
|
+
join(__dirname, 'package.json'),
|
|
241
|
+
join(__dirname, 'wrangler.toml'),
|
|
242
|
+
], {
|
|
243
|
+
ignored: /(^|[/\\])\../, // ignore hidden files
|
|
244
|
+
persistent: true,
|
|
245
|
+
ignoreInitial: true,
|
|
246
|
+
awaitWriteFinish: {
|
|
247
|
+
stabilityThreshold: 200,
|
|
248
|
+
pollInterval: 100,
|
|
249
|
+
},
|
|
250
|
+
})
|
|
251
|
+
let restartTimeout: NodeJS.Timeout | null = null
|
|
252
|
+
|
|
253
|
+
const watcher = (e: ChokidarEventName) => async (file: string) => {
|
|
254
|
+
logger.step(getAssetChangeMessage(e, file))
|
|
255
|
+
|
|
256
|
+
if (restartTimeout)
|
|
257
|
+
clearTimeout(restartTimeout)
|
|
258
|
+
|
|
259
|
+
restartTimeout = setTimeout(async () => {
|
|
260
|
+
await cb(e, file)
|
|
261
|
+
}, 300)
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
codeWatcher.on('change', watcher('change'))
|
|
265
|
+
codeWatcher.on('add', watcher('add'))
|
|
266
|
+
codeWatcher.on('unlink', watcher('unlink'))
|
|
267
|
+
codeWatcher.on('addDir', watcher('addDir'))
|
|
268
|
+
codeWatcher.on('unlinkDir', watcher('unlinkDir'))
|
|
269
|
+
|
|
270
|
+
logger.step('Watching for file changes')
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
async function wait(ms: number) {
|
|
274
|
+
return new Promise(r => setTimeout(r, ms))
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function getDockerHost() {
|
|
278
|
+
const platform = process.platform
|
|
279
|
+
|
|
280
|
+
if (platform === 'darwin') {
|
|
281
|
+
for (const socket of [
|
|
282
|
+
'/Users/'+ process.env.USER +'/.docker/run/docker.sock',
|
|
283
|
+
'/var/run/docker.sock',
|
|
284
|
+
process.env.DOCKER_HOST
|
|
285
|
+
]) {
|
|
286
|
+
if (socket && existsSync(socket.replace(/^unix:\/\//, '')))
|
|
287
|
+
return socket.includes('://') ? socket : `unix://${socket}`
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return 'tcp://localhost:2375'
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return process.env.DOCKER_HOST || (platform == 'win32' ? 'tcp://localhost:2375' : 'unix:///var/run/docker.sock')
|
|
294
|
+
}
|