tangled
alpha
login
or
join now
maxine.puppykitty.racing
/
typelex
forked from
danabra.mov/typelex
0
fork
atom
An experimental TypeSpec syntax for Lexicon
0
fork
atom
overview
issues
pulls
pipelines
nit
danabra.mov
5 months ago
3cf2e105
17a20b86
+24
-19
3 changed files
expand all
collapse all
unified
split
packages
cli
package.json
src
commands
init.ts
pnpm-lock.yaml
+2
-1
packages/cli/package.json
···
1
{
2
"name": "@typelex/cli",
3
-
"version": "0.2.5",
4
"main": "dist/index.js",
5
"type": "module",
6
"bin": {
···
26
"license": "MIT",
27
"dependencies": {
28
"@typespec/compiler": "^1.4.0",
0
29
"yargs": "^18.0.0"
30
},
31
"devDependencies": {
···
1
{
2
"name": "@typelex/cli",
3
+
"version": "0.2.7",
4
"main": "dist/index.js",
5
"type": "module",
6
"bin": {
···
26
"license": "MIT",
27
"dependencies": {
28
"@typespec/compiler": "^1.4.0",
29
+
"picocolors": "^1.1.1",
30
"yargs": "^18.0.0"
31
},
32
"devDependencies": {
+19
-18
packages/cli/src/commands/init.ts
···
2
import { mkdir, writeFile, readFile, access, stat } from "fs/promises";
3
import { spawn } from "child_process";
4
import { createInterface } from "readline";
0
5
6
function createMainTemplate(namespace: string): string {
7
return `import "@typelex/emitter";
···
30
});
31
32
return new Promise((resolve) => {
33
-
rl.question("\x1b[36mYour app's namespace (e.g., com.example.*): \x1b[0m", (answer) => {
34
rl.close();
35
resolve(answer.trim());
36
});
···
46
const mainTspPath = resolve(typelexDir, "main.tsp");
47
const externalsTspPath = resolve(typelexDir, "externals.tsp");
48
49
-
console.log("Initializing typelex project...\n");
50
console.log("Installing dependencies...");
51
52
// Detect package manager: walk up from cwd
···
86
console.log("\n✓ Installed @typelex/cli and @typelex/emitter\n");
87
resolvePromise();
88
} else {
89
-
console.error("\nFailed to install dependencies");
90
process.exit(code ?? 1);
91
}
92
});
93
94
install.on("error", (err) => {
95
-
console.error("Failed to install dependencies:", err);
96
reject(err);
97
});
98
});
···
102
103
// Validate namespace format
104
while (!namespace.endsWith(".*")) {
105
-
console.error(`Error: namespace must end with .*`);
106
-
console.error(`Got: ${namespace}\n`);
107
namespace = await promptNamespace();
108
}
109
···
146
await access(mainTspPath);
147
const content = await readFile(mainTspPath, "utf-8");
148
if (content.trim().length > 0) {
149
-
console.log("✓ typelex/main.tsp already exists, skipping");
150
shouldCreateMain = false;
151
}
152
} catch {
···
155
156
if (shouldCreateMain) {
157
await writeFile(mainTspPath, createMainTemplate(namespacePrefix), "utf-8");
158
-
console.log("✓ Created typelex/main.tsp");
159
}
160
161
// Always create/overwrite externals.tsp
162
await writeFile(externalsTspPath, EXTERNALS_TSP_TEMPLATE, "utf-8");
163
-
console.log("✓ Created typelex/externals.tsp");
164
165
// Add build script to package.json
166
const packageJsonPath = resolve(cwd, "package.json");
···
173
const outFlag = lexiconsDir ? ` --out ${lexiconsDir}` : "";
174
packageJson.scripts["build:typelex"] = `typelex compile ${namespace}${outFlag}`;
175
await writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2) + "\n", "utf-8");
176
-
console.log("✓ Added build:typelex script to package.json");
177
if (hasLocalLexicons) {
178
-
console.log(` Using existing lexicons directory: ./lexicons`);
179
} else if (lexiconsDir) {
180
-
console.log(` Using existing lexicons directory: ${lexiconsDir}`);
181
}
182
} else {
183
-
console.log("✓ build:typelex script already exists in package.json");
184
}
185
} catch (err) {
186
-
console.warn("⚠ Could not update package.json:", (err as Error).message);
187
}
188
189
-
console.log("\nTypelex initialized successfully!");
190
-
console.log("\nNext steps:");
191
-
console.log(" 1. Edit typelex/main.tsp to define your lexicons");
192
-
console.log(" 2. Run: npm run build:typelex");
193
}
···
2
import { mkdir, writeFile, readFile, access, stat } from "fs/promises";
3
import { spawn } from "child_process";
4
import { createInterface } from "readline";
5
+
import pc from "picocolors";
6
7
function createMainTemplate(namespace: string): string {
8
return `import "@typelex/emitter";
···
31
});
32
33
return new Promise((resolve) => {
34
+
rl.question(`Enter your app's root namespace (e.g. ${pc.cyan("com.example.*")}): `, (answer) => {
35
rl.close();
36
resolve(answer.trim());
37
});
···
47
const mainTspPath = resolve(typelexDir, "main.tsp");
48
const externalsTspPath = resolve(typelexDir, "externals.tsp");
49
50
+
console.log(pc.bold("Initializing typelex project...\n"));
51
console.log("Installing dependencies...");
52
53
// Detect package manager: walk up from cwd
···
87
console.log("\n✓ Installed @typelex/cli and @typelex/emitter\n");
88
resolvePromise();
89
} else {
90
+
console.error(pc.red("✗ Failed to install dependencies"));
91
process.exit(code ?? 1);
92
}
93
});
94
95
install.on("error", (err) => {
96
+
console.error(pc.red("✗ Failed to install dependencies:"), err);
97
reject(err);
98
});
99
});
···
103
104
// Validate namespace format
105
while (!namespace.endsWith(".*")) {
106
+
console.error(pc.red(`Error: namespace must end with ${pc.bold(".*")}`));
107
+
console.error(pc.red(`Got: ${pc.bold(namespace)}\n`));
108
namespace = await promptNamespace();
109
}
110
···
147
await access(mainTspPath);
148
const content = await readFile(mainTspPath, "utf-8");
149
if (content.trim().length > 0) {
150
+
console.log(`✓ ${pc.cyan("typelex/main.tsp")} already exists, skipping`);
151
shouldCreateMain = false;
152
}
153
} catch {
···
156
157
if (shouldCreateMain) {
158
await writeFile(mainTspPath, createMainTemplate(namespacePrefix), "utf-8");
159
+
console.log(`✓ Created ${pc.cyan("typelex/main.tsp")}`);
160
}
161
162
// Always create/overwrite externals.tsp
163
await writeFile(externalsTspPath, EXTERNALS_TSP_TEMPLATE, "utf-8");
164
+
console.log(`✓ Created ${pc.cyan("typelex/externals.tsp")}`);
165
166
// Add build script to package.json
167
const packageJsonPath = resolve(cwd, "package.json");
···
174
const outFlag = lexiconsDir ? ` --out ${lexiconsDir}` : "";
175
packageJson.scripts["build:typelex"] = `typelex compile ${namespace}${outFlag}`;
176
await writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2) + "\n", "utf-8");
177
+
console.log(`✓ Added ${pc.cyan("build:typelex")} script to ${pc.cyan("package.json")}`);
178
if (hasLocalLexicons) {
179
+
console.log(pc.dim(` Using existing lexicons directory: ${pc.cyan("./lexicons")}`));
180
} else if (lexiconsDir) {
181
+
console.log(pc.dim(` Using existing lexicons directory: ${pc.cyan(lexiconsDir)}`));
182
}
183
} else {
184
+
console.log(`✓ ${pc.cyan("build:typelex")} script already exists in ${pc.cyan("package.json")}`);
185
}
186
} catch (err) {
187
+
console.warn(pc.yellow(`⚠ Could not update ${pc.cyan("package.json")}:`), (err as Error).message);
188
}
189
190
+
console.log(pc.bold("\n✓ Typelex initialized successfully!"));
191
+
console.log(pc.bold("\nNext steps:"));
192
+
console.log(` 1. Edit ${pc.cyan("typelex/main.tsp")} to define your lexicons`);
193
+
console.log(` 2. Run: ${pc.cyan("npm run build:typelex")}`);
194
}
+3
pnpm-lock.yaml
···
20
'@typespec/compiler':
21
specifier: ^1.4.0
22
version: 1.4.0(@types/node@20.19.19)
0
0
0
23
yargs:
24
specifier: ^18.0.0
25
version: 18.0.0
···
20
'@typespec/compiler':
21
specifier: ^1.4.0
22
version: 1.4.0(@types/node@20.19.19)
23
+
picocolors:
24
+
specifier: ^1.1.1
25
+
version: 1.1.1
26
yargs:
27
specifier: ^18.0.0
28
version: 18.0.0