@weaver-wow/cli 1.0.0 → 1.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.
@@ -1,126 +0,0 @@
1
-
2
- import { symlinkSync, existsSync, rmSync, statSync } from "node:fs";
3
- import { join, resolve } from "node:path";
4
- import { intro, outro, spinner, confirm, text } from "@clack/prompts";
5
- import picocolors from "picocolors";
6
- import { loadConfig } from "../utils/config";
7
- import { findWoWPath } from "../utils/wow-path";
8
-
9
- export async function linkCommand() {
10
- intro(picocolors.bgBlue(" 🧵 Weaver Link "));
11
-
12
- const s = spinner();
13
- s.start("Reading configuration...");
14
-
15
- let config = await loadConfig();
16
-
17
- // Determine Addon Name
18
- let addonName = config?.addonName;
19
- if (!addonName && existsSync("package.json")) {
20
- try {
21
- const pkg = JSON.parse(await Bun.file("package.json").text());
22
- addonName = pkg.name ? pkg.name.charAt(0).toUpperCase() + pkg.name.slice(1) : "MyAddon";
23
- } catch {}
24
- }
25
- addonName = addonName || "MyAddon";
26
-
27
- // Determine WoW Path
28
- let wowPath = config?.wowPath;
29
- if (!wowPath) {
30
- s.stop("Searching for WoW installation...");
31
- wowPath = await findWoWPath();
32
-
33
- if (!wowPath) {
34
- const manualPath = await text({
35
- message: "Could not auto-detect WoW. Enter path manually:",
36
- placeholder: "C:\\Program Files (x86)\\World of Warcraft"
37
- });
38
- if (typeof manualPath === 'symbol') process.exit(0);
39
- wowPath = manualPath as string;
40
- } else {
41
- const useFound = await confirm({
42
- message: `Found WoW at ${picocolors.cyan(wowPath)}. Use this?`,
43
- initialValue: true
44
- });
45
- if (!useFound) {
46
- const manualPath = await text({
47
- message: "Enter path manually:",
48
- placeholder: "C:\\Program Files (x86)\\World of Warcraft"
49
- });
50
- if (typeof manualPath === 'symbol') process.exit(0);
51
- wowPath = manualPath as string;
52
- }
53
- }
54
- }
55
-
56
- if (!wowPath) {
57
- console.error(picocolors.red("WoW path is required."));
58
- process.exit(1);
59
- }
60
-
61
- // Determine target directory (Interface/AddOns)
62
- // Default to retail for now, or use config.flavor
63
- const flavor = config?.flavor || "_retail_";
64
- const addonsDir = join(wowPath, flavor, "Interface", "AddOns");
65
-
66
- if (!existsSync(addonsDir)) {
67
- console.error(picocolors.red(`Could not find AddOns directory at: ${addonsDir}`));
68
- console.log(picocolors.yellow(`(Make sure you have run the game at least once to create folders)`));
69
- process.exit(1);
70
- }
71
-
72
- const targetLinkPath = join(addonsDir, addonName);
73
- const sourceDistPath = resolve("dist"); // Absolute path to dist
74
-
75
- if (!existsSync(sourceDistPath)) {
76
- console.error(picocolors.red("dist/ folder does not exist. Run 'bun wvr build' first."));
77
- process.exit(1);
78
- }
79
-
80
- s.start(`Linking ${picocolors.cyan(addonName)} to WoW...`);
81
-
82
- // Check if link already exists
83
- if (existsSync(targetLinkPath)) {
84
- const stats = statSync(targetLinkPath);
85
- if (stats.isSymbolicLink()) {
86
- s.stop("Link already exists.");
87
- // Maybe check where it points?
88
- outro("Addon is already linked.");
89
- return;
90
- } else {
91
- // It's a real folder?
92
- s.stop("Target exists as a real folder.");
93
- const overwrite = await confirm({
94
- message: `Folder ${targetLinkPath} already exists (not a link). Delete and link?`,
95
- initialValue: false
96
- });
97
- if (!overwrite) {
98
- outro("Aborted.");
99
- return;
100
- }
101
- s.start("Removing existing folder...");
102
- try {
103
- rmSync(targetLinkPath, { recursive: true, force: true }); // Dangerous?
104
- } catch (e) {
105
- s.stop(picocolors.red("Failed to remove existing folder."));
106
- console.error(e);
107
- process.exit(1);
108
- }
109
- }
110
- }
111
-
112
- // Create Symlink
113
- try {
114
- // Use "junction" for Windows directory links without admin
115
- const type = process.platform === "win32" ? "junction" : "dir";
116
- symlinkSync(sourceDistPath, targetLinkPath, type);
117
- } catch (e) {
118
- s.stop(picocolors.red("Failed to create symlink"));
119
- console.error("Error details:", e);
120
- console.log(picocolors.yellow("Try running as Administrator if on Windows."));
121
- process.exit(1);
122
- }
123
-
124
- s.stop(picocolors.green("Linked successfully!"));
125
- outro(`Dev changes in ${picocolors.bold("dist/")} will now reflect in WoW immediately.`);
126
- }
package/src/cli/index.ts DELETED
@@ -1,31 +0,0 @@
1
- import { Command } from "commander";
2
- import { initCommand } from "./commands/init";
3
- import { buildCommand } from "./commands/build";
4
- import { devCommand } from "./commands/dev";
5
- import { linkCommand } from "./commands/link";
6
-
7
- const program = new Command();
8
-
9
- program
10
- .name("wvr")
11
- .description("Weaver Addon Toolchain")
12
- .version("1.0.0");
13
-
14
- program.command("init")
15
- .description("Initialize a new Weaver project")
16
- .option("-y, --yes", "Skip prompts and use defaults")
17
- .action((options) => initCommand(options));
18
-
19
- program.command("build")
20
- .description("Build the addon for production")
21
- .action(() => buildCommand());
22
-
23
- program.command("dev")
24
- .description("Start development server (watch mode)")
25
- .action(() => devCommand());
26
-
27
- program.command("link")
28
- .description("Symlink dist folder to WoW AddOns")
29
- .action(() => linkCommand());
30
-
31
- program.parse(process.argv);
@@ -1,16 +0,0 @@
1
-
2
- import { existsSync } from "node:fs";
3
- import { WeaverConfig } from "../../schema";
4
-
5
- export async function loadConfig(): Promise<WeaverConfig | null> {
6
- if (existsSync("weaver.config.ts")) {
7
- try {
8
- const configPath = Bun.pathToFileURL("weaver.config.ts").href;
9
- const configModule = await import(configPath);
10
- return configModule.default;
11
- } catch (e) {
12
- console.warn("Failed to load weaver.config.ts:", e);
13
- }
14
- }
15
- return null;
16
- }
@@ -1,44 +0,0 @@
1
-
2
- import { $ } from "bun";
3
- import { existsSync } from "node:fs";
4
- import { join } from "node:path";
5
-
6
- export async function findWoWPath(): Promise<string | null> {
7
- // 1. Try Registry (Windows only)
8
- if (process.platform === "win32") {
9
- try {
10
- const result = await $`reg query "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Blizzard Entertainment\\World of Warcraft" /v InstallPath`.text();
11
- // Output looks like: " InstallPath REG_SZ C:\Program Files (x86)\World of Warcraft\"
12
- const match = result.match(/REG_SZ\s+(.*)/);
13
- if (match && match[1]) {
14
- const path = match[1].trim();
15
- if (existsSync(path)) return path;
16
- }
17
- } catch (e) {
18
- // Registry key not found or error accessing reg command
19
- }
20
- }
21
-
22
- // 2. Common Path Scan
23
- const commonPaths = [
24
- "C:\\Games\\World of Warcraft",
25
- "D:\\Games\\World of Warcraft",
26
- "E:\\Games\\World of Warcraft",
27
- "C:\\Program Files (x86)\\World of Warcraft",
28
- "C:\\Program Files\\World of Warcraft"
29
- ];
30
-
31
- for (const path of commonPaths) {
32
- if (existsSync(path)) return path;
33
- }
34
-
35
- return null;
36
- }
37
-
38
- export function validateWoWPath(path: string): boolean {
39
- const retail = join(path, "_retail_");
40
- const classic = join(path, "_classic_");
41
- const classicEra = join(path, "_classic_era_");
42
-
43
- return existsSync(retail) || existsSync(classic) || existsSync(classicEra);
44
- }
package/src/schema.ts DELETED
@@ -1,18 +0,0 @@
1
-
2
- import { z } from "zod";
3
- import type { WeaverConfig as IWeaverConfig } from "../../weaver/src/types/config";
4
-
5
- export const WeaverConfigSchema = z.object({
6
- addonName: z.string(),
7
- flavor: z.enum(["_retail_", "_classic_", "_classic_era_"]),
8
- interface: z.string(),
9
- outDir: z.string().optional().default("Interface/AddOns"),
10
- entry: z.string().optional().default("src/App.tsx"),
11
- wowPath: z.string().optional().nullable(),
12
- });
13
-
14
- export type WeaverConfig = z.infer<typeof WeaverConfigSchema>;
15
-
16
- // Verify it matches the interface
17
- type Verification = WeaverConfig extends IWeaverConfig ? (IWeaverConfig extends WeaverConfig ? true : false) : false;
18
- const _v: Verification = true;