@effect-x/envault 0.1.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 +21 -0
- package/README.md +53 -0
- package/dist/assets/highlights-CBXJmSNL.scm +205 -0
- package/dist/assets/highlights-D8AwpUmb.scm +284 -0
- package/dist/assets/highlights-Dj7C7yga.scm +150 -0
- package/dist/assets/highlights-_y98o7mL.scm +604 -0
- package/dist/assets/highlights-oYFuV_X8.scm +115 -0
- package/dist/assets/injections-jD0OqTrg.scm +27 -0
- package/dist/assets/tree-sitter-javascript-BIQS8cIx.wasm +0 -0
- package/dist/assets/tree-sitter-markdown-BcT6zdLB.wasm +0 -0
- package/dist/assets/tree-sitter-markdown_inline-C00NH7xW.wasm +0 -0
- package/dist/assets/tree-sitter-typescript-BQpamM5l.wasm +0 -0
- package/dist/assets/tree-sitter-zig-g3m_vtcZ.wasm +0 -0
- package/dist/bin.d.ts +1 -0
- package/dist/bin.js +58845 -0
- package/dist/bin.js.map +1 -0
- package/dist/chunk-2mx7fq49-DWgCruu_.js +5 -0
- package/dist/chunk-2mx7fq49-DWgCruu_.js.map +1 -0
- package/dist/chunk-C-LSD6C2.js +14 -0
- package/dist/chunk-bdqvmfwv-WZRmk9C2.js +10212 -0
- package/dist/chunk-bdqvmfwv-WZRmk9C2.js.map +1 -0
- package/dist/wrapper-BUyLZ9aM.js +1606 -0
- package/dist/wrapper-BUyLZ9aM.js.map +1 -0
- package/package.json +110 -0
- package/src/bin.ts +53 -0
- package/src/domain.ts +56 -0
- package/src/env-file.ts +440 -0
- package/src/tui/App.tsx +1591 -0
- package/src/tui/atoms.ts +227 -0
- package/src/tui/colors.ts +58 -0
- package/src/tui/modal.ts +15 -0
- package/src/tui/primitives.tsx +168 -0
- package/src/tui/runTui.tsx +68 -0
- package/src/tui/types.ts +127 -0
- package/src/workspace.ts +120 -0
package/src/workspace.ts
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import { promises as fs } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import type { WorkspaceInfo, WorkspaceKind } from "./domain.ts";
|
|
5
|
+
import { EnvFileError } from "./env-file.ts";
|
|
6
|
+
|
|
7
|
+
const readJson = (
|
|
8
|
+
target: string,
|
|
9
|
+
): Effect.Effect<Record<string, unknown> | undefined, EnvFileError> =>
|
|
10
|
+
Effect.tryPromise({
|
|
11
|
+
try: async () => JSON.parse(await fs.readFile(target, "utf8")) as Record<string, unknown>,
|
|
12
|
+
catch: (cause) =>
|
|
13
|
+
new EnvFileError({ message: `Failed to read JSON ${target}: ${String(cause)}` }),
|
|
14
|
+
}).pipe(Effect.catch(() => Effect.succeed(undefined)));
|
|
15
|
+
|
|
16
|
+
const exists = (target: string): Effect.Effect<boolean> =>
|
|
17
|
+
Effect.tryPromise({
|
|
18
|
+
try: async () => {
|
|
19
|
+
await fs.access(target);
|
|
20
|
+
return true;
|
|
21
|
+
},
|
|
22
|
+
catch: () => new EnvFileError({ message: `Path does not exist: ${target}` }),
|
|
23
|
+
}).pipe(Effect.catch(() => Effect.succeed(false)));
|
|
24
|
+
|
|
25
|
+
const packageWorkspacePatterns = (
|
|
26
|
+
packageJson: Record<string, unknown> | undefined,
|
|
27
|
+
): ReadonlyArray<string> => {
|
|
28
|
+
if (packageJson === undefined) return [];
|
|
29
|
+
const workspaces = packageJson["workspaces"];
|
|
30
|
+
if (Array.isArray(workspaces))
|
|
31
|
+
return workspaces.filter((value): value is string => typeof value === "string");
|
|
32
|
+
if (typeof workspaces === "object" && workspaces !== null && "packages" in workspaces) {
|
|
33
|
+
const packages = (workspaces as { readonly packages?: unknown | undefined }).packages;
|
|
34
|
+
return Array.isArray(packages)
|
|
35
|
+
? packages.filter((value): value is string => typeof value === "string")
|
|
36
|
+
: [];
|
|
37
|
+
}
|
|
38
|
+
return [];
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const readPnpmWorkspacePatterns = async (target: string): Promise<ReadonlyArray<string>> => {
|
|
42
|
+
const content = await fs.readFile(target, "utf8");
|
|
43
|
+
const patterns: Array<string> = [];
|
|
44
|
+
for (const line of content.split(/\r?\n/u)) {
|
|
45
|
+
const match = line.match(/^\s*-\s+(.+)\s*$/u);
|
|
46
|
+
if (match?.[1] !== undefined) {
|
|
47
|
+
patterns.push(match[1].replace(/^['"]|['"]$/gu, ""));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return patterns;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const expandSimplePattern = async (
|
|
54
|
+
root: string,
|
|
55
|
+
pattern: string,
|
|
56
|
+
): Promise<ReadonlyArray<string>> => {
|
|
57
|
+
const starIndex = pattern.indexOf("*");
|
|
58
|
+
if (starIndex < 0) return [path.resolve(root, pattern)];
|
|
59
|
+
|
|
60
|
+
const base = pattern.slice(0, starIndex).replace(/\/$/u, "");
|
|
61
|
+
const basePath = path.resolve(root, base);
|
|
62
|
+
const entries = await fs.readdir(basePath, { withFileTypes: true }).catch(() => []);
|
|
63
|
+
|
|
64
|
+
return entries
|
|
65
|
+
.filter((entry) => entry.isDirectory())
|
|
66
|
+
.map((entry) => path.join(basePath, entry.name));
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const detectKind = ({
|
|
70
|
+
packagePatterns,
|
|
71
|
+
pnpmPatterns,
|
|
72
|
+
hasMoon,
|
|
73
|
+
hasNx,
|
|
74
|
+
}: {
|
|
75
|
+
readonly packagePatterns: ReadonlyArray<string>;
|
|
76
|
+
readonly pnpmPatterns: ReadonlyArray<string>;
|
|
77
|
+
readonly hasMoon: boolean;
|
|
78
|
+
readonly hasNx: boolean;
|
|
79
|
+
}): WorkspaceKind => {
|
|
80
|
+
if (hasMoon) return "moon";
|
|
81
|
+
if (hasNx) return "nx";
|
|
82
|
+
if (pnpmPatterns.length > 0) return "pnpm";
|
|
83
|
+
if (packagePatterns.length > 0) return "npm";
|
|
84
|
+
return "single";
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export const detectWorkspace = (root: string): Effect.Effect<WorkspaceInfo, EnvFileError> =>
|
|
88
|
+
Effect.gen(function* () {
|
|
89
|
+
const absoluteRoot = path.resolve(root);
|
|
90
|
+
const packageJson = yield* readJson(path.join(absoluteRoot, "package.json"));
|
|
91
|
+
const packagePatterns = packageWorkspacePatterns(packageJson);
|
|
92
|
+
const pnpmWorkspacePath = path.join(absoluteRoot, "pnpm-workspace.yaml");
|
|
93
|
+
const pnpmPatterns = (yield* exists(pnpmWorkspacePath))
|
|
94
|
+
? yield* Effect.tryPromise({
|
|
95
|
+
try: () => readPnpmWorkspacePatterns(pnpmWorkspacePath),
|
|
96
|
+
catch: (cause) =>
|
|
97
|
+
new EnvFileError({ message: `Failed to read pnpm-workspace.yaml: ${String(cause)}` }),
|
|
98
|
+
})
|
|
99
|
+
: [];
|
|
100
|
+
const hasMoon = yield* exists(path.join(absoluteRoot, ".moon", "workspace.yml"));
|
|
101
|
+
const hasNx = yield* exists(path.join(absoluteRoot, "nx.json"));
|
|
102
|
+
const patterns = pnpmPatterns.length > 0 ? pnpmPatterns : packagePatterns;
|
|
103
|
+
const expanded = yield* Effect.tryPromise({
|
|
104
|
+
try: async () =>
|
|
105
|
+
(
|
|
106
|
+
await Promise.all(patterns.map((pattern) => expandSimplePattern(absoluteRoot, pattern)))
|
|
107
|
+
).flat(),
|
|
108
|
+
catch: (cause) =>
|
|
109
|
+
new EnvFileError({ message: `Failed to expand workspace patterns: ${String(cause)}` }),
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
root: absoluteRoot,
|
|
114
|
+
kind: detectKind({ packagePatterns, pnpmPatterns, hasMoon, hasNx }),
|
|
115
|
+
packageDirectories: expanded.sort((left, right) => left.localeCompare(right)),
|
|
116
|
+
};
|
|
117
|
+
}).pipe(Effect.withSpan("workspace.detect"));
|
|
118
|
+
|
|
119
|
+
export const encodeWorkspaceInfo = (workspace: WorkspaceInfo): unknown =>
|
|
120
|
+
Schema.encodeUnknownSync(Schema.Any)(workspace);
|