@linebridge/bootloader 1.0.0
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/LICENSE +29 -0
- package/bin +2 -0
- package/boot.cjs +70 -0
- package/boot_function.cjs +48 -0
- package/globals.cjs +51 -0
- package/libs/aliases.cjs +18 -0
- package/libs/infisical.cjs +51 -0
- package/libs/watcher.cjs +33 -0
- package/package.json +28 -0
- package/run.cjs +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
Comty License
|
|
2
|
+
Version 1.0
|
|
3
|
+
|
|
4
|
+
Issued on: 01/01/2024
|
|
5
|
+
|
|
6
|
+
1. Grant of Rights
|
|
7
|
+
Under this Comty License, permission is hereby granted, free of charge, to any person obtaining a copy of the software and associated documentation files (the "Software"), to use, copy, modify, merge, publish, and distribute copies of the Software, subject to the following conditions:
|
|
8
|
+
|
|
9
|
+
2. Non-Commercial Use
|
|
10
|
+
The use of the Software is restricted solely to non-commercial purposes. The sale, leasing, renting, sublicensing, or any other form of commercial exploitation of the Software or its derivatives is not permitted.
|
|
11
|
+
|
|
12
|
+
3. Distribution
|
|
13
|
+
a. You may redistribute the Software in its original form or with modifications, provided that you retain this copyright notice and this Comty License in all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
b. If you distribute modified versions of the Software, you must include a clear notice indicating the changes you made and the date of those changes.
|
|
16
|
+
|
|
17
|
+
4. Derivatives
|
|
18
|
+
a. The creation of derivative works based on the Software is permitted, provided that these derivative works are distributed under this same Comty License.
|
|
19
|
+
|
|
20
|
+
b. Derivative works must clearly indicate that they have been modified from the original Software.
|
|
21
|
+
|
|
22
|
+
5. Limitation of Liability
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
24
|
+
|
|
25
|
+
6. Termination
|
|
26
|
+
This license and the rights granted herein will terminate automatically if you breach any of the terms of this Comty License. Upon termination, you must cease all use of the Software and destroy all copies you possess, whether modified or unmodified.
|
|
27
|
+
|
|
28
|
+
7. Governing Law
|
|
29
|
+
This Comty License shall be governed by and construed in accordance with the laws of Spain, without regard to its conflict of law principles.
|
package/bin
ADDED
package/boot.cjs
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
require("dotenv").config({
|
|
2
|
+
quiet: true,
|
|
3
|
+
})
|
|
4
|
+
|
|
5
|
+
const path = require("node:path")
|
|
6
|
+
const Module = require("node:module")
|
|
7
|
+
const Aliases = require("./libs/aliases.cjs")
|
|
8
|
+
|
|
9
|
+
// Override file execution arg
|
|
10
|
+
process.argv.splice(1, 1)
|
|
11
|
+
process.argv[1] = path.resolve(process.argv[1])
|
|
12
|
+
|
|
13
|
+
// Expose to global
|
|
14
|
+
global["paths"] = {
|
|
15
|
+
root: process.env.ROOT_PATH ?? process.cwd(),
|
|
16
|
+
__src: path.resolve(
|
|
17
|
+
process.env.ROOT_PATH ?? process.cwd(),
|
|
18
|
+
path.dirname(process.argv[1]),
|
|
19
|
+
),
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
global["aliases"] = {
|
|
23
|
+
// expose src
|
|
24
|
+
"@": global.paths.__src,
|
|
25
|
+
|
|
26
|
+
// expose shared resources
|
|
27
|
+
"@db": path.resolve(global.paths.root, "db"),
|
|
28
|
+
"@db_models": path.resolve(global.paths.root, "db_models"),
|
|
29
|
+
"@shared-classes": path.resolve(global.paths.root, "classes"),
|
|
30
|
+
"@shared-middlewares": path.resolve(global.paths.root, "middlewares"),
|
|
31
|
+
"@shared-utils": path.resolve(global.paths.root, "utils"),
|
|
32
|
+
"@shared-lib": path.resolve(global.paths.root, "lib"),
|
|
33
|
+
|
|
34
|
+
// expose internal resources
|
|
35
|
+
"@classes": path.resolve(global.paths.__src, "classes"),
|
|
36
|
+
"@middlewares": path.resolve(global.paths.__src, "middlewares"),
|
|
37
|
+
"@routes": path.resolve(global.paths.__src, "routes"),
|
|
38
|
+
"@models": path.resolve(global.paths.__src, "models"),
|
|
39
|
+
"@config": path.resolve(global.paths.__src, "config"),
|
|
40
|
+
"@utils": path.resolve(global.paths.__src, "utils"),
|
|
41
|
+
"@lib": path.resolve(global.paths.__src, "lib"),
|
|
42
|
+
|
|
43
|
+
"@services": path.resolve(global.paths.root, "services"),
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
// try to read the package.json
|
|
48
|
+
const packageJson = require(path.resolve(global.paths.root, "package.json"))
|
|
49
|
+
|
|
50
|
+
if (packageJson) {
|
|
51
|
+
if (typeof packageJson.aliases === "object") {
|
|
52
|
+
for (const [key, value] of Object.entries(packageJson.aliases)) {
|
|
53
|
+
global["aliases"][key] = path.resolve(global.paths.root, value)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// apply global functions & patches
|
|
59
|
+
require("./globals.cjs")
|
|
60
|
+
// use sucrase transcompiler
|
|
61
|
+
require("sucrase/register")
|
|
62
|
+
|
|
63
|
+
// Apply aliases
|
|
64
|
+
Aliases.registerBase(global.paths.__src, global["aliases"])
|
|
65
|
+
|
|
66
|
+
// execute main
|
|
67
|
+
Module.runMain()
|
|
68
|
+
} catch (error) {
|
|
69
|
+
console.error("[BOOT] ❌ Boot error: ", error)
|
|
70
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const InfisicalLib = require("./libs/infisical.cjs")
|
|
2
|
+
|
|
3
|
+
async function Boot(main) {
|
|
4
|
+
if (!main) {
|
|
5
|
+
throw new Error("main class is not defined")
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
console.log(
|
|
9
|
+
`[BOOT] Booting in [${global.isProduction ? "production" : "development"}] mode...`,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
if (
|
|
13
|
+
InfisicalLib.client &&
|
|
14
|
+
process.env.INFISICAL_CLIENT_ID &&
|
|
15
|
+
process.env.INFISICAL_CLIENT_SECRET &&
|
|
16
|
+
typeof InfisicalLib.LoadFromEnv === "function"
|
|
17
|
+
) {
|
|
18
|
+
await InfisicalLib.LoadFromEnv()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const instance = new main()
|
|
22
|
+
|
|
23
|
+
process.on("exit", (code) => {
|
|
24
|
+
console.log(`[BOOT] Closing ...`)
|
|
25
|
+
|
|
26
|
+
instance._fireClose()
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
process.on("SIGTERM", () => {
|
|
30
|
+
process.exit(0)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
process.on("SIGINT", () => {
|
|
34
|
+
process.exit(0)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
await instance.run()
|
|
38
|
+
|
|
39
|
+
if (process.env.lb_service && process.send) {
|
|
40
|
+
process.send({
|
|
41
|
+
status: "ready",
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return instance
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
module.exports = Boot
|
package/globals.cjs
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const { webcrypto: crypto } = require("node:crypto")
|
|
2
|
+
const { Buffer } = require("node:buffer")
|
|
3
|
+
|
|
4
|
+
global.isProduction = process.env.NODE_ENV === "production"
|
|
5
|
+
|
|
6
|
+
global.b64Decode = (data) => {
|
|
7
|
+
return Buffer.from(data, "base64").toString("utf-8")
|
|
8
|
+
}
|
|
9
|
+
global.b64Encode = (data) => {
|
|
10
|
+
return Buffer.from(data, "utf-8").toString("base64")
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
global.nanoid = (t = 21) =>
|
|
14
|
+
crypto
|
|
15
|
+
.getRandomValues(new Uint8Array(t))
|
|
16
|
+
.reduce(
|
|
17
|
+
(t, e) =>
|
|
18
|
+
(t +=
|
|
19
|
+
(e &= 63) < 36
|
|
20
|
+
? e.toString(36)
|
|
21
|
+
: e < 62
|
|
22
|
+
? (e - 26).toString(36).toUpperCase()
|
|
23
|
+
: e > 62
|
|
24
|
+
? "-"
|
|
25
|
+
: "_"),
|
|
26
|
+
"",
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
Array.prototype.updateFromObjectKeys = function (obj) {
|
|
30
|
+
this.forEach((value, index) => {
|
|
31
|
+
if (obj[value] !== undefined) {
|
|
32
|
+
this[index] = obj[value]
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
return this
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
global.ToBoolean = (value) => {
|
|
40
|
+
if (typeof value === "boolean") {
|
|
41
|
+
return value
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (typeof value === "string") {
|
|
45
|
+
return value.toLowerCase() === "true"
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return false
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
global.Boot = require("./boot_function.cjs")
|
package/libs/aliases.cjs
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const path = require("node:path")
|
|
2
|
+
const moduleAlias = require("module-alias")
|
|
3
|
+
|
|
4
|
+
class Aliases {
|
|
5
|
+
static registerBase = (fromPath, customAliases = {}) => {
|
|
6
|
+
if (typeof fromPath === "undefined") {
|
|
7
|
+
if (module.parent.filename.includes("dist")) {
|
|
8
|
+
fromPath = path.resolve(process.cwd(), "dist")
|
|
9
|
+
} else {
|
|
10
|
+
fromPath = path.resolve(process.cwd(), "src")
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
moduleAlias.addAliases(customAliases)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = Aliases
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
class InfisicalLib {
|
|
2
|
+
static get client() {
|
|
3
|
+
try {
|
|
4
|
+
const mod = require("@infisical/sdk")
|
|
5
|
+
|
|
6
|
+
return mod.InfisicalSDK
|
|
7
|
+
} catch (e) {
|
|
8
|
+
return null
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
static LoadFromEnv = async () => {
|
|
13
|
+
if (!InfisicalLib.client) {
|
|
14
|
+
console.warn(
|
|
15
|
+
"WARN: Infisical client not found, skipping env injection...",
|
|
16
|
+
)
|
|
17
|
+
return null
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const envMode =
|
|
21
|
+
(global.FORCE_ENV ?? global.isProduction) ? "prod" : "dev"
|
|
22
|
+
|
|
23
|
+
console.log(
|
|
24
|
+
`[BOOT] 🔑 Injecting env variables from INFISICAL in [${envMode}] mode...`,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
const client = new InfisicalLib.client()
|
|
28
|
+
|
|
29
|
+
await client.auth().universalAuth.login({
|
|
30
|
+
clientId: process.env.INFISICAL_CLIENT_ID,
|
|
31
|
+
clientSecret: process.env.INFISICAL_CLIENT_SECRET,
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
const list = await client.secrets().listSecrets({
|
|
35
|
+
environment: envMode,
|
|
36
|
+
projectId: process.env.INFISICAL_PROJECT_ID ?? null,
|
|
37
|
+
secretPath: process.env.INFISICAL_PATH ?? "/",
|
|
38
|
+
includeImports: false,
|
|
39
|
+
attachToProcessEnv: false,
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
//inject to process.env
|
|
43
|
+
list.secrets.forEach((secret) => {
|
|
44
|
+
if (!process.env[secret.secretKey]) {
|
|
45
|
+
process.env[secret.secretKey] = secret.secretValue
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
module.exports = InfisicalLib
|
package/libs/watcher.cjs
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const chokidar = require("chokidar")
|
|
2
|
+
const { minimatch } = require("minimatch")
|
|
3
|
+
|
|
4
|
+
const defaultIgnored = [
|
|
5
|
+
"**/.cache/**",
|
|
6
|
+
"**/node_modules/**",
|
|
7
|
+
"**/dist/**",
|
|
8
|
+
"**/build/**",
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
class Watcher {
|
|
12
|
+
static create = async (fromPath, { onReload }) => {
|
|
13
|
+
console.log("[WATCHER] Starting watching path >", fromPath)
|
|
14
|
+
|
|
15
|
+
global._watcher = chokidar.watch(fromPath, {
|
|
16
|
+
ignored: (path) =>
|
|
17
|
+
defaultIgnored.some((pattern) => minimatch(path, pattern)),
|
|
18
|
+
persistent: true,
|
|
19
|
+
ignoreInitial: true,
|
|
20
|
+
awaitWriteFinish: true,
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
global._watcher.on("all", (event, filePath) => {
|
|
24
|
+
console.log(`[WATCHER] Event [${event}] > ${filePath}`)
|
|
25
|
+
|
|
26
|
+
if (typeof onReload === "function") {
|
|
27
|
+
onReload()
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
module.exports = Watcher
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@linebridge/bootloader",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "commonjs",
|
|
5
|
+
"main": "./run.cjs",
|
|
6
|
+
"private": false,
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"linebridge-boot": "./bin"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"chokidar": "^5.0.0",
|
|
15
|
+
"dotenv": "^17.4.2",
|
|
16
|
+
"minimatch": "^10.2.6",
|
|
17
|
+
"module-alias": "^2.3.4",
|
|
18
|
+
"sucrase": "^3.35.1"
|
|
19
|
+
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"@infisical/sdk": "^5.0.2"
|
|
22
|
+
},
|
|
23
|
+
"peerDependenciesMeta": {
|
|
24
|
+
"@infisical/sdk": {
|
|
25
|
+
"optional": true
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
package/run.cjs
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const path = require("node:path")
|
|
2
|
+
const childProcess = require("node:child_process")
|
|
3
|
+
const Watcher = require("./libs/watcher.cjs")
|
|
4
|
+
|
|
5
|
+
const bootloaderPath = path.resolve(__dirname, "boot.cjs")
|
|
6
|
+
const mainModulePath = process.argv[2]
|
|
7
|
+
|
|
8
|
+
if (!mainModulePath) {
|
|
9
|
+
console.error("[BOOT] No main script provided")
|
|
10
|
+
process.exit(1)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const mainModuleSrc = path.resolve(process.cwd(), path.dirname(mainModulePath))
|
|
14
|
+
|
|
15
|
+
let childProcessInstance = null
|
|
16
|
+
let reloadTimeout = null
|
|
17
|
+
|
|
18
|
+
function selfReload() {
|
|
19
|
+
if (!childProcessInstance) {
|
|
20
|
+
console.error(
|
|
21
|
+
"[BOOT] Cannot self-reload. Missing childProcessInstance.",
|
|
22
|
+
)
|
|
23
|
+
return process.exit(0)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
console.log("[BOOT] Reloading...")
|
|
27
|
+
|
|
28
|
+
childProcessInstance.kill()
|
|
29
|
+
|
|
30
|
+
runFork()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function selfReloadDebounce() {
|
|
34
|
+
if (reloadTimeout) {
|
|
35
|
+
clearTimeout(reloadTimeout)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
reloadTimeout = setTimeout(selfReload, 300)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function runFork() {
|
|
42
|
+
childProcessInstance = childProcess.fork(bootloaderPath, [mainModulePath], {
|
|
43
|
+
stdio: "inherit",
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// if --watch flag exist, start file watcher
|
|
48
|
+
if (process.argv.includes("--watch")) {
|
|
49
|
+
Watcher.create(mainModuleSrc, {
|
|
50
|
+
onReload: selfReloadDebounce,
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
runFork()
|
|
54
|
+
} else {
|
|
55
|
+
require(bootloaderPath)
|
|
56
|
+
}
|