@impulselab/cli 0.1.0 → 0.1.2

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.
Files changed (39) hide show
  1. package/dist/index.js +92 -9
  2. package/package.json +20 -9
  3. package/src/commands/add.test.ts +0 -147
  4. package/src/commands/add.ts +0 -335
  5. package/src/commands/init.ts +0 -114
  6. package/src/commands/list.ts +0 -79
  7. package/src/config/config-path.ts +0 -7
  8. package/src/config/has-config.ts +0 -9
  9. package/src/config/index.ts +0 -4
  10. package/src/config/read-config.ts +0 -20
  11. package/src/config/write-config.ts +0 -11
  12. package/src/config.test.ts +0 -64
  13. package/src/index.ts +0 -64
  14. package/src/installer.ts +0 -71
  15. package/src/registry/fetch-module-file.ts +0 -21
  16. package/src/registry/fetch-module-manifest.ts +0 -43
  17. package/src/registry/github-urls.ts +0 -13
  18. package/src/registry/index.ts +0 -5
  19. package/src/registry/list-available-modules.ts +0 -113
  20. package/src/registry/parse-module-id.ts +0 -30
  21. package/src/registry/registry.test.ts +0 -181
  22. package/src/schemas/impulse-config.ts +0 -21
  23. package/src/schemas/index.ts +0 -9
  24. package/src/schemas/module-dependency.ts +0 -3
  25. package/src/schemas/module-file.ts +0 -8
  26. package/src/schemas/module-manifest.ts +0 -23
  27. package/src/schemas/module-transform.ts +0 -15
  28. package/src/transforms/add-env.ts +0 -53
  29. package/src/transforms/add-nav-item.test.ts +0 -125
  30. package/src/transforms/add-nav-item.ts +0 -70
  31. package/src/transforms/append-export.test.ts +0 -50
  32. package/src/transforms/append-export.ts +0 -34
  33. package/src/transforms/index.ts +0 -32
  34. package/src/transforms/merge-schema.test.ts +0 -70
  35. package/src/transforms/merge-schema.ts +0 -35
  36. package/src/transforms/register-route.test.ts +0 -177
  37. package/src/transforms/register-route.ts +0 -47
  38. package/src/types.ts +0 -9
  39. package/tsconfig.json +0 -8
@@ -1,53 +0,0 @@
1
- import fsExtra from "fs-extra";
2
- const { readFile, outputFile, pathExists } = fsExtra;
3
- import path from "path";
4
- import * as p from "@clack/prompts";
5
-
6
- /**
7
- * Prompts for an env var value and appends to .env if not already present.
8
- * target: path to .env file (e.g. ".env")
9
- * value: the env var name (e.g. "AUTH_SECRET")
10
- */
11
- export async function addEnv(
12
- target: string,
13
- value: string,
14
- cwd: string,
15
- dryRun: boolean
16
- ): Promise<void> {
17
- const file = path.join(cwd, target);
18
- let content = "";
19
-
20
- if (await pathExists(file)) {
21
- content = await readFile(file, "utf-8");
22
- // Check if key already set — escape value to avoid regex injection
23
- const escaped = value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
24
- const keyPattern = new RegExp(`^${escaped}=`, "m");
25
- if (keyPattern.test(content)) return;
26
- }
27
-
28
- let envValue = "";
29
- if (!dryRun) {
30
- const answer = await p.text({
31
- message: `Enter value for ${value} (leave blank to skip):`,
32
- placeholder: "",
33
- });
34
-
35
- if (p.isCancel(answer)) {
36
- p.log.warn(`Skipped env var: ${value}`);
37
- return;
38
- }
39
-
40
- envValue = String(answer);
41
- }
42
-
43
- const line = `${value}=${envValue}`;
44
-
45
- if (!dryRun) {
46
- const newContent = content
47
- ? content.endsWith("\n")
48
- ? `${content}${line}\n`
49
- : `${content}\n${line}\n`
50
- : `${line}\n`;
51
- await outputFile(file, newContent, "utf-8");
52
- }
53
- }
@@ -1,125 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
- import { mkdtemp, rm } from "fs/promises";
3
- import { outputFile, readFile } from "fs-extra";
4
- import path from "path";
5
- import os from "os";
6
- import { addNavItem } from "./add-nav-item";
7
-
8
- let tmpDir: string;
9
-
10
- beforeEach(async () => {
11
- tmpDir = await mkdtemp(path.join(os.tmpdir(), "impulse-nav-test-"));
12
- });
13
-
14
- afterEach(async () => {
15
- await rm(tmpDir, { recursive: true, force: true });
16
- });
17
-
18
- describe("addNavItem", () => {
19
- it("inserts item into a flat nav array", async () => {
20
- const navFile = path.join(tmpDir, "src/config/nav.ts");
21
- await outputFile(
22
- navFile,
23
- `export const navItems = [\n { title: "Home", href: "/" },\n];\n`
24
- );
25
-
26
- await addNavItem(
27
- "src/config/nav.ts",
28
- '{ title: "Auth", href: "/auth" }',
29
- tmpDir,
30
- false
31
- );
32
-
33
- const result = await readFile(navFile, "utf-8");
34
- expect(result).toContain('{ title: "Auth", href: "/auth" }');
35
- expect(result).toContain('{ title: "Home", href: "/" }');
36
- // insertion uses trailing newline — closing ] must be on its own line
37
- expect(result).toMatch(/\},\n\]/);
38
- });
39
-
40
- it("inserts item into a typed array declaration (const navItems: NavItem[] = [...])", async () => {
41
- const navFile = path.join(tmpDir, "src/config/nav.ts");
42
- await outputFile(
43
- navFile,
44
- `export const navItems: NavItem[] = [\n { title: "Home", href: "/" },\n];\n`
45
- );
46
-
47
- await addNavItem(
48
- "src/config/nav.ts",
49
- '{ title: "Auth", href: "/auth" }',
50
- tmpDir,
51
- false
52
- );
53
-
54
- const result = await readFile(navFile, "utf-8");
55
- expect(result).toContain('{ title: "Auth", href: "/auth" }');
56
- });
57
-
58
- it("inserts item into a nav array with nested arrays (nested subnav)", async () => {
59
- const navFile = path.join(tmpDir, "src/config/nav.ts");
60
- await outputFile(
61
- navFile,
62
- `export const navItems = [\n {\n title: "Settings",\n href: "/settings",\n children: [\n { title: "Profile", href: "/settings/profile" },\n ],\n },\n];\n`
63
- );
64
-
65
- await addNavItem(
66
- "src/config/nav.ts",
67
- '{ title: "Auth", href: "/auth" }',
68
- tmpDir,
69
- false
70
- );
71
-
72
- const result = await readFile(navFile, "utf-8");
73
- // Item should be appended before the outer closing bracket
74
- expect(result).toContain('{ title: "Auth", href: "/auth" }');
75
- // Nested structure must be preserved
76
- expect(result).toContain("children:");
77
- });
78
-
79
- it("does not insert duplicate items", async () => {
80
- const navFile = path.join(tmpDir, "src/config/nav.ts");
81
- const item = '{ title: "Auth", href: "/auth" }';
82
- await outputFile(navFile, `export const navItems = [\n ${item},\n];\n`);
83
-
84
- await addNavItem("src/config/nav.ts", item, tmpDir, false);
85
-
86
- const result = await readFile(navFile, "utf-8");
87
- expect(result.split(item).length - 1).toBe(1);
88
- });
89
-
90
- it("does not write file in dry-run mode", async () => {
91
- const navFile = path.join(tmpDir, "src/config/nav.ts");
92
- const original = `export const navItems = [\n { title: "Home", href: "/" },\n];\n`;
93
- await outputFile(navFile, original);
94
-
95
- await addNavItem(
96
- "src/config/nav.ts",
97
- '{ title: "Auth", href: "/auth" }',
98
- tmpDir,
99
- true
100
- );
101
-
102
- const result = await readFile(navFile, "utf-8");
103
- expect(result).toBe(original);
104
- });
105
-
106
- it("throws if file not found", async () => {
107
- await expect(
108
- addNavItem("nonexistent/nav.ts", '{ title: "X" }', tmpDir, false)
109
- ).rejects.toThrow("target file not found");
110
- });
111
-
112
- it("throws if no nav array can be located", async () => {
113
- const navFile = path.join(tmpDir, "src/config/nav.ts");
114
- await outputFile(navFile, `export const foo = "bar";\n`);
115
-
116
- await expect(
117
- addNavItem(
118
- "src/config/nav.ts",
119
- '{ title: "Auth", href: "/auth" }',
120
- tmpDir,
121
- false
122
- )
123
- ).rejects.toThrow("could not locate nav array");
124
- });
125
- });
@@ -1,70 +0,0 @@
1
- import fsExtra from "fs-extra";
2
- const { readFile, outputFile, pathExists } = fsExtra;
3
- import path from "path";
4
-
5
- /**
6
- * Adds a navigation item to the sidebar config file.
7
- * target: path to the nav config file (e.g. "src/config/nav.ts")
8
- * value: the nav item JSON string to inject
9
- * (e.g. '{ title: "Auth", href: "/auth", icon: "lock" }')
10
- */
11
- export async function addNavItem(
12
- target: string,
13
- value: string,
14
- cwd: string,
15
- dryRun: boolean
16
- ): Promise<void> {
17
- const file = path.join(cwd, target);
18
-
19
- if (!(await pathExists(file))) {
20
- throw new Error(
21
- `add-nav-item: target file not found: ${target}`
22
- );
23
- }
24
-
25
- const content = await readFile(file, "utf-8");
26
- if (content.includes(value)) return;
27
-
28
- // Find the opening bracket of the navItems array using a pattern match,
29
- // then walk brackets to find the matching close — handles nested arrays.
30
- // The type annotation group handles typed declarations: `const navItems: NavItem[] = [`
31
- const openPattern = /(?:const\s+\w+(?:\s*:\s*[\w<>\[\], ]+)?\s*=\s*\[|items\s*:\s*\[)/;
32
- const openMatch = openPattern.exec(content);
33
-
34
- if (!openMatch) {
35
- throw new Error(
36
- `add-nav-item: could not locate nav array in ${target}. Add "${value}" manually.`
37
- );
38
- }
39
-
40
- // Position of the '[' that opens the array
41
- const bracketStart = openMatch.index + openMatch[0].length - 1;
42
-
43
- // Walk forward counting brackets to find the matching ']'
44
- let depth = 0;
45
- let insertPos = -1;
46
- for (let i = bracketStart; i < content.length; i++) {
47
- if (content[i] === "[") depth++;
48
- else if (content[i] === "]") {
49
- depth--;
50
- if (depth === 0) {
51
- insertPos = i;
52
- break;
53
- }
54
- }
55
- }
56
-
57
- if (insertPos === -1) {
58
- throw new Error(
59
- `add-nav-item: could not find closing bracket for nav array in ${target}. Add "${value}" manually.`
60
- );
61
- }
62
-
63
- if (!dryRun) {
64
- const newContent =
65
- content.slice(0, insertPos) +
66
- ` ${value},\n` +
67
- content.slice(insertPos);
68
- await outputFile(file, newContent, "utf-8");
69
- }
70
- }
@@ -1,50 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
- import { mkdtemp, rm } from "fs/promises";
3
- import { outputFile, readFile } from "fs-extra";
4
- import path from "path";
5
- import os from "os";
6
- import { appendExport } from "./append-export";
7
-
8
- let tmpDir: string;
9
-
10
- beforeEach(async () => {
11
- tmpDir = await mkdtemp(path.join(os.tmpdir(), "impulse-test-"));
12
- });
13
-
14
- afterEach(async () => {
15
- await rm(tmpDir, { recursive: true, force: true });
16
- });
17
-
18
- describe("appendExport", () => {
19
- it("creates the file if it does not exist", async () => {
20
- await appendExport("src/index.ts", "export * from './auth'", tmpDir, false);
21
- const content = await readFile(path.join(tmpDir, "src/index.ts"), "utf-8");
22
- expect(content).toBe("export * from './auth'\n");
23
- });
24
-
25
- it("appends to existing file", async () => {
26
- await outputFile(
27
- path.join(tmpDir, "src/index.ts"),
28
- "export * from './existing'\n"
29
- );
30
- await appendExport("src/index.ts", "export * from './auth'", tmpDir, false);
31
- const content = await readFile(path.join(tmpDir, "src/index.ts"), "utf-8");
32
- expect(content).toBe("export * from './existing'\nexport * from './auth'\n");
33
- });
34
-
35
- it("does not duplicate if already present", async () => {
36
- await outputFile(
37
- path.join(tmpDir, "src/index.ts"),
38
- "export * from './auth'\n"
39
- );
40
- await appendExport("src/index.ts", "export * from './auth'", tmpDir, false);
41
- const content = await readFile(path.join(tmpDir, "src/index.ts"), "utf-8");
42
- expect(content).toBe("export * from './auth'\n");
43
- });
44
-
45
- it("does not write in dry-run mode", async () => {
46
- await appendExport("src/index.ts", "export * from './auth'", tmpDir, true);
47
- const { pathExists } = await import("fs-extra");
48
- expect(await pathExists(path.join(tmpDir, "src/index.ts"))).toBe(false);
49
- });
50
- });
@@ -1,34 +0,0 @@
1
- import fsExtra from "fs-extra";
2
- const { readFile, outputFile, pathExists } = fsExtra;
3
- import path from "path";
4
-
5
- /**
6
- * Appends an export line to a barrel file if not already present.
7
- * target: relative path to the barrel file (e.g. "src/server/api/index.ts")
8
- * value: the export line to append (e.g. "export * from './auth'")
9
- */
10
- export async function appendExport(
11
- target: string,
12
- value: string,
13
- cwd: string,
14
- dryRun: boolean
15
- ): Promise<void> {
16
- const file = path.join(cwd, target);
17
-
18
- if (!(await pathExists(file))) {
19
- if (!dryRun) {
20
- await outputFile(file, `${value}\n`, "utf-8");
21
- }
22
- return;
23
- }
24
-
25
- const content = await readFile(file, "utf-8");
26
- if (content.includes(value)) return; // already present
27
-
28
- if (!dryRun) {
29
- const newContent = content.endsWith("\n")
30
- ? `${content}${value}\n`
31
- : `${content}\n${value}\n`;
32
- await outputFile(file, newContent, "utf-8");
33
- }
34
- }
@@ -1,32 +0,0 @@
1
- import { appendExport } from "./append-export";
2
- import { registerRoute } from "./register-route";
3
- import { addNavItem } from "./add-nav-item";
4
- import { mergeSchema } from "./merge-schema";
5
- import { addEnv } from "./add-env";
6
- import type { ModuleTransform } from "../types";
7
-
8
- export async function runTransform(
9
- transform: ModuleTransform,
10
- cwd: string,
11
- dryRun: boolean
12
- ): Promise<void> {
13
- switch (transform.type) {
14
- case "append-export":
15
- await appendExport(transform.target, transform.value, cwd, dryRun);
16
- break;
17
- case "register-route":
18
- await registerRoute(transform.target, transform.value, cwd, dryRun);
19
- break;
20
- case "add-nav-item":
21
- await addNavItem(transform.target, transform.value, cwd, dryRun);
22
- break;
23
- case "merge-schema":
24
- await mergeSchema(transform.target, transform.value, cwd, dryRun);
25
- break;
26
- case "add-env":
27
- await addEnv(transform.target, transform.value, cwd, dryRun);
28
- break;
29
- }
30
- }
31
-
32
- export { appendExport, registerRoute, addNavItem, mergeSchema, addEnv };
@@ -1,70 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
- import { mkdtemp, rm } from "fs/promises";
3
- import { outputFile, readFile } from "fs-extra";
4
- import path from "path";
5
- import os from "os";
6
- import { mergeSchema } from "./merge-schema";
7
-
8
- let tmpDir: string;
9
-
10
- beforeEach(async () => {
11
- tmpDir = await mkdtemp(path.join(os.tmpdir(), "impulse-test-"));
12
- });
13
-
14
- afterEach(async () => {
15
- await rm(tmpDir, { recursive: true, force: true });
16
- });
17
-
18
- describe("mergeSchema", () => {
19
- it("creates schema index if it does not exist", async () => {
20
- await mergeSchema(
21
- "src/server/db/schema/index.ts",
22
- "export * from './auth'",
23
- tmpDir,
24
- false
25
- );
26
- const content = await readFile(
27
- path.join(tmpDir, "src/server/db/schema/index.ts"),
28
- "utf-8"
29
- );
30
- expect(content).toBe("export * from './auth'\n");
31
- });
32
-
33
- it("appends to existing schema index", async () => {
34
- await outputFile(
35
- path.join(tmpDir, "src/server/db/schema/index.ts"),
36
- "export * from './users'\n"
37
- );
38
- await mergeSchema(
39
- "src/server/db/schema/index.ts",
40
- "export * from './auth'",
41
- tmpDir,
42
- false
43
- );
44
- const content = await readFile(
45
- path.join(tmpDir, "src/server/db/schema/index.ts"),
46
- "utf-8"
47
- );
48
- expect(content).toBe(
49
- "export * from './users'\nexport * from './auth'\n"
50
- );
51
- });
52
-
53
- it("skips duplicates", async () => {
54
- await outputFile(
55
- path.join(tmpDir, "src/server/db/schema/index.ts"),
56
- "export * from './auth'\n"
57
- );
58
- await mergeSchema(
59
- "src/server/db/schema/index.ts",
60
- "export * from './auth'",
61
- tmpDir,
62
- false
63
- );
64
- const content = await readFile(
65
- path.join(tmpDir, "src/server/db/schema/index.ts"),
66
- "utf-8"
67
- );
68
- expect(content).toBe("export * from './auth'\n");
69
- });
70
- });
@@ -1,35 +0,0 @@
1
- import fsExtra from "fs-extra";
2
- const { readFile, outputFile, pathExists } = fsExtra;
3
- import path from "path";
4
-
5
- /**
6
- * Adds a Drizzle schema import to the main schema index file.
7
- * target: path to the schema index (e.g. "src/server/db/schema/index.ts")
8
- * value: import/export line (e.g. "export * from './auth'")
9
- */
10
- export async function mergeSchema(
11
- target: string,
12
- value: string,
13
- cwd: string,
14
- dryRun: boolean
15
- ): Promise<void> {
16
- const file = path.join(cwd, target);
17
-
18
- if (!(await pathExists(file))) {
19
- // Create new schema index
20
- if (!dryRun) {
21
- await outputFile(file, `${value}\n`, "utf-8");
22
- }
23
- return;
24
- }
25
-
26
- const content = await readFile(file, "utf-8");
27
- if (content.includes(value)) return;
28
-
29
- if (!dryRun) {
30
- const newContent = content.endsWith("\n")
31
- ? `${content}${value}\n`
32
- : `${content}\n${value}\n`;
33
- await outputFile(file, newContent, "utf-8");
34
- }
35
- }
@@ -1,177 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
- import { mkdtemp, rm } from "fs/promises";
3
- import { outputFile, readFile } from "fs-extra";
4
- import path from "path";
5
- import os from "os";
6
- import { registerRoute } from "./register-route";
7
-
8
- let tmpDir: string;
9
-
10
- beforeEach(async () => {
11
- tmpDir = await mkdtemp(path.join(os.tmpdir(), "impulse-route-test-"));
12
- });
13
-
14
- afterEach(async () => {
15
- await rm(tmpDir, { recursive: true, force: true });
16
- });
17
-
18
- const satisfiesRouter = `import { createRouter } from "@orpc/server";
19
- import { healthRouter } from "./health";
20
-
21
- export const appRouter = createRouter({
22
- health: healthRouter,
23
- } satisfies RouterInput);
24
- `;
25
-
26
- const asRouter = `import { createRouter } from "@orpc/server";
27
- import { healthRouter } from "./health";
28
-
29
- export const appRouter = {
30
- health: healthRouter,
31
- } as AppRouter;
32
- `;
33
-
34
- // Router that contains an inline `as` type cast inside a nested expression
35
- // — the fix must NOT insert into the inline cast.
36
- const routerWithInlineAs = `import { createRouter } from "@orpc/server";
37
-
38
- function helper(x: unknown) {
39
- return (x as string).toUpperCase();
40
- }
41
-
42
- export const appRouter = createRouter({
43
- health: healthRouter,
44
- } satisfies RouterInput);
45
- `;
46
-
47
- // Router where another typed object's `}` appears on its own line before
48
- // `satisfies`/`as` on the next line — cross-line match must be avoided.
49
- const routerWithCrossLineSatisfies = `const config = {
50
- setting: true,
51
- }
52
- satisfies ConfigType;
53
-
54
- export const appRouter = createRouter({
55
- health: healthRouter,
56
- } satisfies RouterInput);
57
- `;
58
-
59
- describe("registerRoute", () => {
60
- it("inserts route into a 'satisfies' router", async () => {
61
- const routerFile = path.join(tmpDir, "src/server/api/router.ts");
62
- await outputFile(routerFile, satisfiesRouter);
63
-
64
- await registerRoute(
65
- "src/server/api/router.ts",
66
- "auth: authRouter",
67
- tmpDir,
68
- false
69
- );
70
-
71
- const result = await readFile(routerFile, "utf-8");
72
- expect(result).toContain("auth: authRouter");
73
- expect(result).toContain("health: healthRouter");
74
- });
75
-
76
- it("inserts route into an 'as' router", async () => {
77
- const routerFile = path.join(tmpDir, "src/server/api/router.ts");
78
- await outputFile(routerFile, asRouter);
79
-
80
- await registerRoute(
81
- "src/server/api/router.ts",
82
- "auth: authRouter",
83
- tmpDir,
84
- false
85
- );
86
-
87
- const result = await readFile(routerFile, "utf-8");
88
- expect(result).toContain("auth: authRouter");
89
- });
90
-
91
- it("does not match when } and satisfies/as are on separate lines (cross-line false match)", async () => {
92
- const routerFile = path.join(tmpDir, "src/server/api/router.ts");
93
- await outputFile(routerFile, routerWithCrossLineSatisfies);
94
-
95
- await registerRoute(
96
- "src/server/api/router.ts",
97
- "auth: authRouter",
98
- tmpDir,
99
- false
100
- );
101
-
102
- const result = await readFile(routerFile, "utf-8");
103
- // Route must appear near the appRouter closing, not near the config object
104
- const insertIdx = result.indexOf("auth: authRouter");
105
- const configSatisfiesIdx = result.indexOf("}\nsatisfies ConfigType");
106
- expect(insertIdx).toBeGreaterThan(configSatisfiesIdx);
107
- });
108
-
109
- it("does not match inline 'as' casts inside nested expressions", async () => {
110
- const routerFile = path.join(tmpDir, "src/server/api/router.ts");
111
- await outputFile(routerFile, routerWithInlineAs);
112
-
113
- await registerRoute(
114
- "src/server/api/router.ts",
115
- "auth: authRouter",
116
- tmpDir,
117
- false
118
- );
119
-
120
- const result = await readFile(routerFile, "utf-8");
121
- // Route must appear just before `} satisfies`, not before `} as string`
122
- const insertIdx = result.indexOf("auth: authRouter");
123
- const satisfiesIdx = result.indexOf("} satisfies");
124
- expect(insertIdx).toBeGreaterThan(-1);
125
- expect(insertIdx).toBeLessThan(satisfiesIdx);
126
- });
127
-
128
- it("does not insert duplicate routes", async () => {
129
- const routerFile = path.join(tmpDir, "src/server/api/router.ts");
130
- await outputFile(routerFile, satisfiesRouter);
131
-
132
- await registerRoute(
133
- "src/server/api/router.ts",
134
- "health: healthRouter",
135
- tmpDir,
136
- false
137
- );
138
-
139
- const result = await readFile(routerFile, "utf-8");
140
- expect(result.split("health: healthRouter").length - 1).toBe(1);
141
- });
142
-
143
- it("does not write file in dry-run mode", async () => {
144
- const routerFile = path.join(tmpDir, "src/server/api/router.ts");
145
- await outputFile(routerFile, satisfiesRouter);
146
-
147
- await registerRoute(
148
- "src/server/api/router.ts",
149
- "auth: authRouter",
150
- tmpDir,
151
- true
152
- );
153
-
154
- const result = await readFile(routerFile, "utf-8");
155
- expect(result).toBe(satisfiesRouter);
156
- });
157
-
158
- it("throws if file not found", async () => {
159
- await expect(
160
- registerRoute("nonexistent/router.ts", "auth: authRouter", tmpDir, false)
161
- ).rejects.toThrow("target file not found");
162
- });
163
-
164
- it("throws if no router closing brace found", async () => {
165
- const routerFile = path.join(tmpDir, "src/server/api/router.ts");
166
- await outputFile(routerFile, `export const foo = "bar";\n`);
167
-
168
- await expect(
169
- registerRoute(
170
- "src/server/api/router.ts",
171
- "auth: authRouter",
172
- tmpDir,
173
- false
174
- )
175
- ).rejects.toThrow("could not find router closing brace");
176
- });
177
- });