tangled
alpha
login
or
join now
danabra.mov
/
typelex
56
fork
atom
An experimental TypeSpec syntax for Lexicon
56
fork
atom
overview
issues
1
pulls
2
pipelines
nits
danabra.mov
5 months ago
d6fda094
b90f9277
+51
-36
2 changed files
expand all
collapse all
unified
split
packages
cli
src
cli.ts
commands
init.ts
+17
-1
packages/cli/src/cli.ts
···
19
});
20
},
21
async (argv) => {
22
-
await initCommand(argv.setup);
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
23
}
24
)
25
.command(
···
19
});
20
},
21
async (argv) => {
22
+
// Extract any unknown flags to pass through to package manager
23
+
const flags: string[] = [];
24
+
const knownFlags = new Set(["setup", "_", "$0"]);
25
+
26
+
for (const [key, value] of Object.entries(argv)) {
27
+
if (!knownFlags.has(key)) {
28
+
// Single letter = short flag, multiple letters = long flag
29
+
const prefix = key.length === 1 ? "-" : "--";
30
+
if (typeof value === "boolean" && value) {
31
+
flags.push(`${prefix}${key}`);
32
+
} else if (value !== false && value !== undefined) {
33
+
flags.push(`${prefix}${key}`, String(value));
34
+
}
35
+
}
36
+
}
37
+
38
+
await initCommand(argv.setup, flags);
39
}
40
)
41
.command(
+34
-35
packages/cli/src/commands/init.ts
···
4
import { createInterface } from "readline";
5
import pc from "picocolors";
6
7
-
// Gradient colors matching website (approximated with ANSI 256 colors)
8
-
// Darker variant for better readability on white terminals
9
function gradientText(text: string): string {
10
-
// Approximating: #4a9eff -> #7a8ef7 -> #ff85c1 -> #9b7ef7
11
-
// Using darker ANSI 256 color codes for a blue->purple->pink gradient
12
const colors = [
13
-
'\x1b[38;5;33m', // darker blue
14
-
'\x1b[38;5;69m', // blue-purple
15
-
'\x1b[38;5;99m', // purple
16
-
'\x1b[38;5;133m', // purple-pink
17
-
'\x1b[38;5;170m', // pink
18
-
'\x1b[38;5;170m', // pink
19
-
'\x1b[38;5;133m', // purple-pink
20
];
21
const reset = '\x1b[0m';
22
···
60
});
61
}
62
63
-
/**
64
-
* Initialize command - installs packages and hands off to local version
65
-
* This is what gets called by npx
66
-
*/
67
-
export async function initCommand(isSetup: boolean = false): Promise<void> {
68
-
const cwd = process.cwd();
0
0
0
0
0
0
0
0
0
69
70
-
// If this is the second pass (after handoff), run setup
71
if (isSetup) {
72
return initSetup();
73
}
74
75
console.log(`Adding ${gradientText("typelex")}...\n`);
76
77
-
// Detect package manager: walk up from cwd
78
let packageManager = "npm";
79
-
let dir = cwd;
80
while (dir !== resolve(dir, "..") && packageManager === "npm") {
81
try {
82
await access(resolve(dir, "pnpm-lock.yaml"));
···
95
dir = resolve(dir, "..");
96
}
97
98
-
// Install dependencies (always use latest)
99
await new Promise<void>((resolvePromise, reject) => {
100
const args = packageManager === "npm"
101
? ["install", "--save-dev", "@typelex/cli@latest", "@typelex/emitter@latest"]
102
: ["add", "-D", "@typelex/cli@latest", "@typelex/emitter@latest"];
103
0
0
0
104
const install = spawn(packageManager, args, {
105
-
cwd,
106
stdio: "inherit",
107
});
108
···
122
});
123
});
124
125
-
// Hand off to locally installed version
126
-
// Find where node_modules actually is (could be at workspace root with pnpm)
127
-
let nodeModulesDir = resolve(cwd, "node_modules");
128
-
let searchDir = cwd;
129
-
130
-
// Search upward for node_modules with typelex installed
131
while (searchDir !== resolve(searchDir, "..")) {
132
try {
133
const candidatePath = resolve(searchDir, "node_modules/.bin/typelex");
···
135
nodeModulesDir = resolve(searchDir, "node_modules");
136
break;
137
} catch {
138
-
// Not found, try parent
139
}
140
-
searchDir = resolve(searchDir, "..");
141
}
142
143
return new Promise((resolvePromise, reject) => {
144
const localCli = resolve(nodeModulesDir, ".bin/typelex");
145
const setup = spawn(localCli, ["init", "--setup"], {
146
-
cwd,
147
stdio: "inherit",
148
});
149
···
162
});
163
}
164
165
-
/**
166
-
* Setup function - called after packages are installed
167
-
* This runs from the locally installed version
168
-
*/
169
export async function initSetup(): Promise<void> {
170
const cwd = process.cwd();
171
const typelexDir = resolve(cwd, "typelex");
···
4
import { createInterface } from "readline";
5
import pc from "picocolors";
6
0
0
7
function gradientText(text: string): string {
0
0
8
const colors = [
9
+
'\x1b[38;5;33m',
10
+
'\x1b[38;5;69m',
11
+
'\x1b[38;5;99m',
12
+
'\x1b[38;5;133m',
13
+
'\x1b[38;5;170m',
14
+
'\x1b[38;5;170m',
15
+
'\x1b[38;5;133m',
16
];
17
const reset = '\x1b[0m';
18
···
56
});
57
}
58
59
+
export async function initCommand(isSetup: boolean = false, flags: string[] = []): Promise<void> {
60
+
const originalCwd = process.cwd();
61
+
62
+
// Find nearest package.json upward
63
+
let projectRoot = originalCwd;
64
+
let dir = originalCwd;
65
+
while (dir !== resolve(dir, "..")) {
66
+
try {
67
+
await access(resolve(dir, "package.json"));
68
+
projectRoot = dir;
69
+
break;
70
+
} catch {
71
+
dir = resolve(dir, "..");
72
+
}
73
+
}
74
0
75
if (isSetup) {
76
return initSetup();
77
}
78
79
console.log(`Adding ${gradientText("typelex")}...\n`);
80
81
+
// Detect package manager
82
let packageManager = "npm";
83
+
dir = projectRoot;
84
while (dir !== resolve(dir, "..") && packageManager === "npm") {
85
try {
86
await access(resolve(dir, "pnpm-lock.yaml"));
···
99
dir = resolve(dir, "..");
100
}
101
102
+
// Install dependencies
103
await new Promise<void>((resolvePromise, reject) => {
104
const args = packageManager === "npm"
105
? ["install", "--save-dev", "@typelex/cli@latest", "@typelex/emitter@latest"]
106
: ["add", "-D", "@typelex/cli@latest", "@typelex/emitter@latest"];
107
108
+
// Add any additional flags
109
+
args.push(...flags);
110
+
111
const install = spawn(packageManager, args, {
112
+
cwd: projectRoot,
113
stdio: "inherit",
114
});
115
···
129
});
130
});
131
132
+
// Find node_modules
133
+
let nodeModulesDir = resolve(projectRoot, "node_modules");
134
+
let searchDir = projectRoot;
0
0
0
135
while (searchDir !== resolve(searchDir, "..")) {
136
try {
137
const candidatePath = resolve(searchDir, "node_modules/.bin/typelex");
···
139
nodeModulesDir = resolve(searchDir, "node_modules");
140
break;
141
} catch {
142
+
searchDir = resolve(searchDir, "..");
143
}
0
144
}
145
146
return new Promise((resolvePromise, reject) => {
147
const localCli = resolve(nodeModulesDir, ".bin/typelex");
148
const setup = spawn(localCli, ["init", "--setup"], {
149
+
cwd: projectRoot,
150
stdio: "inherit",
151
});
152
···
165
});
166
}
167
0
0
0
0
168
export async function initSetup(): Promise<void> {
169
const cwd = process.cwd();
170
const typelexDir = resolve(cwd, "typelex");