@quark-fw/plugin-env 0.1.13
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/package.json +31 -0
- package/src/global.d.ts +22 -0
- package/src/helpers.ts +41 -0
- package/src/index.ts +45 -0
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@quark-fw/plugin-env",
|
|
3
|
+
"version": "0.1.13",
|
|
4
|
+
"main": "src/index.ts",
|
|
5
|
+
"types": "src/index.ts",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "tsx watch src/index.ts",
|
|
9
|
+
"build": "echo raw-src package, no build"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"src"
|
|
13
|
+
],
|
|
14
|
+
"keywords": [
|
|
15
|
+
"quark"
|
|
16
|
+
],
|
|
17
|
+
"author": "",
|
|
18
|
+
"license": "ISC",
|
|
19
|
+
"description": ".env plugin for the Quark framework: every env var as an atom, live-reloaded via chokidar (published as raw TS sources; consumers run tsx)",
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@quark-fw/atom": "0.1.13",
|
|
25
|
+
"@quark-fw/plugin": "0.1.13",
|
|
26
|
+
"chokidar": "^5.0.0"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"@quark-fw/core": "0.1.13"
|
|
30
|
+
}
|
|
31
|
+
}
|
package/src/global.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import "@quark-fw/core/src/global.d.ts";
|
|
2
|
+
import { Atom } from "@quark-fw/atom";
|
|
3
|
+
|
|
4
|
+
export {};
|
|
5
|
+
|
|
6
|
+
declare global {
|
|
7
|
+
interface Events {
|
|
8
|
+
"env:changed": [key: string, value: string | undefined];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface Quark {
|
|
12
|
+
env: {
|
|
13
|
+
get(key: string): Atom<string | undefined>;
|
|
14
|
+
set(key: string, value: string): void;
|
|
15
|
+
has(key: string): boolean;
|
|
16
|
+
subscribe(
|
|
17
|
+
key: string,
|
|
18
|
+
fn: (value: string | undefined) => void,
|
|
19
|
+
): () => void;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
}
|
package/src/helpers.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Хелперы env-плагина: загрузка .env и наблюдение за его изменениями.
|
|
2
|
+
import chokidar, { FSWatcher } from "chokidar";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
|
|
5
|
+
export function loadEnvFile(quark: Quark, path: string) {
|
|
6
|
+
const content = fs.readFileSync(path, "utf8");
|
|
7
|
+
for (const line of content.split("\n")) {
|
|
8
|
+
const trimmed = line.trim();
|
|
9
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
10
|
+
const [key, ...rest] = trimmed.split("=");
|
|
11
|
+
const value = rest.join("=").trim();
|
|
12
|
+
quark.env.set(key, value);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let watcher: FSWatcher | undefined;
|
|
17
|
+
|
|
18
|
+
export function watchEnv(quark: Quark, envPath = ".env") {
|
|
19
|
+
if (!fs.existsSync(envPath)) return;
|
|
20
|
+
|
|
21
|
+
// начальная загрузка
|
|
22
|
+
loadEnvFile(quark, envPath);
|
|
23
|
+
|
|
24
|
+
watcher = chokidar.watch(envPath, {
|
|
25
|
+
ignoreInitial: true,
|
|
26
|
+
awaitWriteFinish: {
|
|
27
|
+
stabilityThreshold: 200,
|
|
28
|
+
pollInterval: 50,
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
watcher.on("change", () => {
|
|
33
|
+
console.log(".env file changed");
|
|
34
|
+
loadEnvFile(quark, envPath);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function closeEnvWatcher() {
|
|
39
|
+
await watcher?.close();
|
|
40
|
+
watcher = undefined;
|
|
41
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import atom, { Atom } from "@quark-fw/atom";
|
|
2
|
+
import { closeEnvWatcher, watchEnv } from "./helpers.js";
|
|
3
|
+
import {} from "@quark-fw/plugin-env/src/global.js";
|
|
4
|
+
|
|
5
|
+
await quark.registerPlugin({
|
|
6
|
+
name: "env",
|
|
7
|
+
extend(quark) {
|
|
8
|
+
const store = new Map<string, Atom<string | undefined>>();
|
|
9
|
+
function ensureAtom(key: string) {
|
|
10
|
+
if (!store.has(key)) {
|
|
11
|
+
const initial = process.env[key];
|
|
12
|
+
const a = atom(`env:${key}`, initial);
|
|
13
|
+
store.set(key, a);
|
|
14
|
+
|
|
15
|
+
// подписка на изменения
|
|
16
|
+
a.subscribe((v) => {
|
|
17
|
+
quark.ee.value.emit("env:changed", key, v);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return store.get(key)!;
|
|
21
|
+
}
|
|
22
|
+
quark.env = {
|
|
23
|
+
get(key) {
|
|
24
|
+
return ensureAtom(key);
|
|
25
|
+
},
|
|
26
|
+
set(key, value) {
|
|
27
|
+
const a = ensureAtom(key);
|
|
28
|
+
a.value = value;
|
|
29
|
+
},
|
|
30
|
+
has(key) {
|
|
31
|
+
return store.has(key) || key in process.env;
|
|
32
|
+
},
|
|
33
|
+
subscribe(key, fn) {
|
|
34
|
+
const a = ensureAtom(key);
|
|
35
|
+
return a.subscribe(fn);
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
},
|
|
39
|
+
onInit(quark) {
|
|
40
|
+
watchEnv(quark);
|
|
41
|
+
},
|
|
42
|
+
async onDestroy() {
|
|
43
|
+
await closeEnvWatcher();
|
|
44
|
+
},
|
|
45
|
+
});
|