@fourteensystems/shipguard 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.
Files changed (139) hide show
  1. package/README.md +213 -0
  2. package/bin/shipguard.mjs +2 -0
  3. package/dist/cli/commands/baseline.d.ts +7 -0
  4. package/dist/cli/commands/baseline.d.ts.map +1 -0
  5. package/dist/cli/commands/baseline.js +22 -0
  6. package/dist/cli/commands/baseline.js.map +1 -0
  7. package/dist/cli/commands/ci.d.ts +13 -0
  8. package/dist/cli/commands/ci.d.ts.map +1 -0
  9. package/dist/cli/commands/ci.js +91 -0
  10. package/dist/cli/commands/ci.js.map +1 -0
  11. package/dist/cli/commands/explain.d.ts +2 -0
  12. package/dist/cli/commands/explain.d.ts.map +1 -0
  13. package/dist/cli/commands/explain.js +20 -0
  14. package/dist/cli/commands/explain.js.map +1 -0
  15. package/dist/cli/commands/init.d.ts +7 -0
  16. package/dist/cli/commands/init.d.ts.map +1 -0
  17. package/dist/cli/commands/init.js +91 -0
  18. package/dist/cli/commands/init.js.map +1 -0
  19. package/dist/cli/commands/rules.d.ts +2 -0
  20. package/dist/cli/commands/rules.d.ts.map +1 -0
  21. package/dist/cli/commands/rules.js +13 -0
  22. package/dist/cli/commands/rules.js.map +1 -0
  23. package/dist/cli/commands/scan.d.ts +10 -0
  24. package/dist/cli/commands/scan.d.ts.map +1 -0
  25. package/dist/cli/commands/scan.js +55 -0
  26. package/dist/cli/commands/scan.js.map +1 -0
  27. package/dist/cli/commands/waive.d.ts +8 -0
  28. package/dist/cli/commands/waive.d.ts.map +1 -0
  29. package/dist/cli/commands/waive.js +34 -0
  30. package/dist/cli/commands/waive.js.map +1 -0
  31. package/dist/cli/index.d.ts +2 -0
  32. package/dist/cli/index.d.ts.map +1 -0
  33. package/dist/cli/index.js +63 -0
  34. package/dist/cli/index.js.map +1 -0
  35. package/dist/engine/baseline.d.ts +11 -0
  36. package/dist/engine/baseline.d.ts.map +1 -0
  37. package/dist/engine/baseline.js +39 -0
  38. package/dist/engine/baseline.js.map +1 -0
  39. package/dist/engine/config.d.ts +8 -0
  40. package/dist/engine/config.d.ts.map +1 -0
  41. package/dist/engine/config.js +130 -0
  42. package/dist/engine/config.js.map +1 -0
  43. package/dist/engine/extensions/load.d.ts +11 -0
  44. package/dist/engine/extensions/load.d.ts.map +1 -0
  45. package/dist/engine/extensions/load.js +26 -0
  46. package/dist/engine/extensions/load.js.map +1 -0
  47. package/dist/engine/extensions/registry.d.ts +5 -0
  48. package/dist/engine/extensions/registry.d.ts.map +1 -0
  49. package/dist/engine/extensions/registry.js +11 -0
  50. package/dist/engine/extensions/registry.js.map +1 -0
  51. package/dist/engine/extensions/types.d.ts +51 -0
  52. package/dist/engine/extensions/types.d.ts.map +1 -0
  53. package/dist/engine/extensions/types.js +2 -0
  54. package/dist/engine/extensions/types.js.map +1 -0
  55. package/dist/engine/report.d.ts +5 -0
  56. package/dist/engine/report.d.ts.map +1 -0
  57. package/dist/engine/report.js +88 -0
  58. package/dist/engine/report.js.map +1 -0
  59. package/dist/engine/run.d.ts +9 -0
  60. package/dist/engine/run.d.ts.map +1 -0
  61. package/dist/engine/run.js +101 -0
  62. package/dist/engine/run.js.map +1 -0
  63. package/dist/engine/sarif.d.ts +3 -0
  64. package/dist/engine/sarif.d.ts.map +1 -0
  65. package/dist/engine/sarif.js +58 -0
  66. package/dist/engine/sarif.js.map +1 -0
  67. package/dist/engine/score.d.ts +13 -0
  68. package/dist/engine/score.d.ts.map +1 -0
  69. package/dist/engine/score.js +97 -0
  70. package/dist/engine/score.js.map +1 -0
  71. package/dist/engine/types.d.ts +119 -0
  72. package/dist/engine/types.d.ts.map +1 -0
  73. package/dist/engine/types.js +2 -0
  74. package/dist/engine/types.js.map +1 -0
  75. package/dist/engine/version.d.ts +5 -0
  76. package/dist/engine/version.d.ts.map +1 -0
  77. package/dist/engine/version.js +15 -0
  78. package/dist/engine/version.js.map +1 -0
  79. package/dist/engine/waivers.d.ts +9 -0
  80. package/dist/engine/waivers.d.ts.map +1 -0
  81. package/dist/engine/waivers.js +55 -0
  82. package/dist/engine/waivers.js.map +1 -0
  83. package/dist/index.d.ts +12 -0
  84. package/dist/index.d.ts.map +1 -0
  85. package/dist/index.js +11 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/next/deps.d.ts +4 -0
  88. package/dist/next/deps.d.ts.map +1 -0
  89. package/dist/next/deps.js +102 -0
  90. package/dist/next/deps.js.map +1 -0
  91. package/dist/next/detect.d.ts +10 -0
  92. package/dist/next/detect.d.ts.map +1 -0
  93. package/dist/next/detect.js +57 -0
  94. package/dist/next/detect.js.map +1 -0
  95. package/dist/next/index.d.ts +5 -0
  96. package/dist/next/index.d.ts.map +1 -0
  97. package/dist/next/index.js +41 -0
  98. package/dist/next/index.js.map +1 -0
  99. package/dist/next/middleware.d.ts +3 -0
  100. package/dist/next/middleware.d.ts.map +1 -0
  101. package/dist/next/middleware.js +33 -0
  102. package/dist/next/middleware.js.map +1 -0
  103. package/dist/next/routes.d.ts +5 -0
  104. package/dist/next/routes.d.ts.map +1 -0
  105. package/dist/next/routes.js +125 -0
  106. package/dist/next/routes.js.map +1 -0
  107. package/dist/next/server-actions.d.ts +4 -0
  108. package/dist/next/server-actions.d.ts.map +1 -0
  109. package/dist/next/server-actions.js +107 -0
  110. package/dist/next/server-actions.js.map +1 -0
  111. package/dist/next/trpc.d.ts +3 -0
  112. package/dist/next/trpc.d.ts.map +1 -0
  113. package/dist/next/trpc.js +339 -0
  114. package/dist/next/trpc.js.map +1 -0
  115. package/dist/next/types.d.ts +100 -0
  116. package/dist/next/types.d.ts.map +1 -0
  117. package/dist/next/types.js +2 -0
  118. package/dist/next/types.js.map +1 -0
  119. package/dist/rules/auth-boundary-missing.d.ts +5 -0
  120. package/dist/rules/auth-boundary-missing.d.ts.map +1 -0
  121. package/dist/rules/auth-boundary-missing.js +278 -0
  122. package/dist/rules/auth-boundary-missing.js.map +1 -0
  123. package/dist/rules/index.d.ts +12 -0
  124. package/dist/rules/index.d.ts.map +1 -0
  125. package/dist/rules/index.js +41 -0
  126. package/dist/rules/index.js.map +1 -0
  127. package/dist/rules/rate-limit-missing.d.ts +5 -0
  128. package/dist/rules/rate-limit-missing.d.ts.map +1 -0
  129. package/dist/rules/rate-limit-missing.js +230 -0
  130. package/dist/rules/rate-limit-missing.js.map +1 -0
  131. package/dist/rules/tenancy-scope-missing.d.ts +5 -0
  132. package/dist/rules/tenancy-scope-missing.d.ts.map +1 -0
  133. package/dist/rules/tenancy-scope-missing.js +149 -0
  134. package/dist/rules/tenancy-scope-missing.js.map +1 -0
  135. package/dist/util/paths.d.ts +6 -0
  136. package/dist/util/paths.d.ts.map +1 -0
  137. package/dist/util/paths.js +18 -0
  138. package/dist/util/paths.js.map +1 -0
  139. package/package.json +55 -0
@@ -0,0 +1,102 @@
1
+ import path from "node:path";
2
+ import { readFileSync } from "node:fs";
3
+ export function readDeps(rootDir) {
4
+ const pkgPath = path.join(rootDir, "package.json");
5
+ let pkg;
6
+ try {
7
+ pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
8
+ }
9
+ catch (err) {
10
+ throw new Error(`Failed to parse ${pkgPath}: ${err instanceof Error ? err.message : String(err)}`);
11
+ }
12
+ const deps = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) };
13
+ return {
14
+ hasNextAuth: Boolean(deps["next-auth"] || deps["@auth/core"] || deps["@auth/nextjs"]),
15
+ hasClerk: Boolean(deps["@clerk/nextjs"]),
16
+ hasSupabase: Boolean(deps["@supabase/ssr"] || deps["@supabase/auth-helpers-nextjs"]),
17
+ hasKinde: Boolean(deps["@kinde-oss/kinde-auth-nextjs"]),
18
+ hasWorkOS: Boolean(deps["@workos-inc/authkit-nextjs"]),
19
+ hasBetterAuth: Boolean(deps["better-auth"]),
20
+ hasLucia: Boolean(deps["lucia"]),
21
+ hasAuth0: Boolean(deps["@auth0/nextjs-auth0"]),
22
+ hasIronSession: Boolean(deps["iron-session"]),
23
+ hasFirebaseAuth: Boolean(deps["firebase-admin"] || deps["next-firebase-auth-edge"]),
24
+ hasUpstashRatelimit: Boolean(deps["@upstash/ratelimit"]),
25
+ hasArcjet: Boolean(deps["@arcjet/next"]),
26
+ hasUnkey: Boolean(deps["@unkey/ratelimit"] || deps["@unkey/nextjs"]),
27
+ hasPrisma: Boolean(deps["prisma"] || deps["@prisma/client"]),
28
+ hasDrizzle: Boolean(deps["drizzle-orm"]),
29
+ hasTrpc: Boolean(deps["@trpc/server"]),
30
+ };
31
+ }
32
+ export function defaultHintsFromDeps(deps, hasMiddlewareTs) {
33
+ const authFns = new Set(["requireUser", "requireAuth", "auth", "getServerSession", "getSession"]);
34
+ if (deps.hasNextAuth) {
35
+ authFns.add("auth");
36
+ authFns.add("getServerSession");
37
+ authFns.add("withAuth");
38
+ }
39
+ if (deps.hasClerk) {
40
+ authFns.add("currentUser");
41
+ authFns.add("auth");
42
+ authFns.add("clerkClient");
43
+ }
44
+ if (deps.hasKinde) {
45
+ authFns.add("getKindeServerSession");
46
+ }
47
+ if (deps.hasWorkOS) {
48
+ authFns.add("withAuth");
49
+ authFns.add("getUser");
50
+ authFns.add("authkitMiddleware");
51
+ }
52
+ if (deps.hasBetterAuth) {
53
+ authFns.add("auth");
54
+ }
55
+ if (deps.hasLucia) {
56
+ authFns.add("validateRequest");
57
+ authFns.add("validateSession");
58
+ }
59
+ if (deps.hasAuth0) {
60
+ authFns.add("getSession");
61
+ authFns.add("withApiAuthRequired");
62
+ authFns.add("withPageAuthRequired");
63
+ }
64
+ if (deps.hasIronSession) {
65
+ authFns.add("getIronSession");
66
+ }
67
+ if (deps.hasFirebaseAuth) {
68
+ authFns.add("verifyIdToken");
69
+ authFns.add("getTokens");
70
+ authFns.add("verifySessionCookie");
71
+ }
72
+ const rl = new Set([
73
+ "rateLimit", "withRateLimit", "limit",
74
+ "checkRateLimitAndThrowError", // cal.com pattern
75
+ "ratelimitOrThrow", // dub pattern
76
+ "rateLimitOrThrow", // common variant
77
+ ]);
78
+ if (deps.hasUpstashRatelimit) {
79
+ rl.add("Ratelimit");
80
+ rl.add("ratelimit");
81
+ }
82
+ if (deps.hasArcjet) {
83
+ rl.add("aj.protect");
84
+ rl.add("fixedWindow");
85
+ rl.add("slidingWindow");
86
+ rl.add("tokenBucket");
87
+ }
88
+ if (deps.hasUnkey) {
89
+ rl.add("withUnkey");
90
+ rl.add("verifyKey");
91
+ }
92
+ return {
93
+ auth: {
94
+ functions: [...authFns],
95
+ middlewareFiles: hasMiddlewareTs ? ["middleware.ts"] : [],
96
+ allowlistPaths: [],
97
+ },
98
+ rateLimit: { wrappers: [...rl], allowlistPaths: [] },
99
+ tenancy: { orgFieldNames: ["orgId", "tenantId", "workspaceId", "organizationId", "teamId", "accountId"] },
100
+ };
101
+ }
102
+ //# sourceMappingURL=deps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deps.js","sourceRoot":"","sources":["../../src/next/deps.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export interface DetectResult {
2
+ ok: boolean;
3
+ reason?: string;
4
+ hasRouteHandlers: boolean;
5
+ hasServerActions: boolean;
6
+ /** Resolved app directory relative to rootDir ("app" or "src/app") */
7
+ appDir: string;
8
+ }
9
+ export declare function detectNextAppRouter(rootDir: string): DetectResult;
10
+ //# sourceMappingURL=detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/next/detect.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC;CAChB;AAQD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAiDjE"}
@@ -0,0 +1,57 @@
1
+ import path from "node:path";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import fg from "fast-glob";
4
+ const NO_DETECT = {
5
+ hasRouteHandlers: false,
6
+ hasServerActions: false,
7
+ appDir: "app",
8
+ };
9
+ export function detectNextAppRouter(rootDir) {
10
+ const pkgPath = path.join(rootDir, "package.json");
11
+ if (!existsSync(pkgPath)) {
12
+ return { ok: false, reason: "package.json not found", ...NO_DETECT };
13
+ }
14
+ let pkg;
15
+ try {
16
+ pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
17
+ }
18
+ catch (err) {
19
+ return { ok: false, reason: `Failed to parse package.json: ${err instanceof Error ? err.message : String(err)}`, ...NO_DETECT };
20
+ }
21
+ const deps = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) };
22
+ if (!deps["next"]) {
23
+ return { ok: false, reason: "next dependency not found", ...NO_DETECT };
24
+ }
25
+ // Support both app/ and src/app/ (both are standard Next.js conventions)
26
+ let appDir = "app";
27
+ if (!existsSync(path.join(rootDir, "app"))) {
28
+ if (existsSync(path.join(rootDir, "src/app"))) {
29
+ appDir = "src/app";
30
+ }
31
+ else {
32
+ return { ok: false, reason: "app/ directory not found (checked app/ and src/app/)", ...NO_DETECT };
33
+ }
34
+ }
35
+ // Check for route handlers
36
+ const routeFiles = fg.globSync(`${appDir}/**/route.{ts,js,tsx,jsx}`, { cwd: rootDir });
37
+ const hasRouteHandlers = routeFiles.length > 0;
38
+ // Check for server actions ("use server" directive)
39
+ let hasServerActions = false;
40
+ const tsFiles = fg.globSync(`${appDir}/**/*.{ts,tsx,js,jsx}`, { cwd: rootDir, ignore: ["**/node_modules/**"] });
41
+ for (const f of tsFiles.slice(0, 100)) {
42
+ try {
43
+ const content = readFileSync(path.join(rootDir, f), "utf8");
44
+ if (/["']use server["']/m.test(content)) {
45
+ hasServerActions = true;
46
+ break;
47
+ }
48
+ }
49
+ catch {
50
+ // Skip unreadable files (broken symlinks, permissions, etc.)
51
+ }
52
+ }
53
+ // Valid Next.js App Router project even if no route handlers or server actions
54
+ // (e.g., a pure pages app, or a blog with no API surface — produces 0 findings)
55
+ return { ok: true, hasRouteHandlers, hasServerActions, appDir };
56
+ }
57
+ //# sourceMappingURL=detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/next/detect.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,MAAM,WAAW,CAAC;AAW3B,MAAM,SAAS,GAAwC;IACrD,gBAAgB,EAAE,KAAK;IACvB,gBAAgB,EAAE,KAAK;IACvB,MAAM,EAAE,KAAK;CACd,CAAC;AAEF,MAAM,UAAU,mBAAmB,CAAC,OAAe;IACjD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IACnD,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,wBAAwB,EAAE,GAAG,SAAS,EAAE,CAAC;IACvE,CAAC;IAED,IAAI,GAA4B,CAAC;IACjC,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IAClD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,iCAAiC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,SAAS,EAAE,CAAC;IAClI,CAAC;IACD,MAAM,IAAI,GAAG,EAAE,GAAG,CAAE,GAAG,CAAC,YAAuC,IAAI,EAAE,CAAC,EAAE,GAAG,CAAE,GAAG,CAAC,eAA0C,IAAI,EAAE,CAAC,EAAE,CAAC;IACrI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAClB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,2BAA2B,EAAE,GAAG,SAAS,EAAE,CAAC;IAC1E,CAAC;IAED,yEAAyE;IACzE,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;QAC3C,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;YAC9C,MAAM,GAAG,SAAS,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,sDAAsD,EAAE,GAAG,SAAS,EAAE,CAAC;QACrG,CAAC;IACH,CAAC;IAED,2BAA2B;IAC3B,MAAM,UAAU,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,MAAM,2BAA2B,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;IACvF,MAAM,gBAAgB,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;IAE/C,oDAAoD;IACpD,IAAI,gBAAgB,GAAG,KAAK,CAAC;IAC7B,MAAM,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,MAAM,uBAAuB,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC;IAChH,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;QACtC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;YAC5D,IAAI,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBACxC,gBAAgB,GAAG,IAAI,CAAC;gBACxB,MAAM;YACR,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,6DAA6D;QAC/D,CAAC;IACH,CAAC;IAED,+EAA+E;IAC/E,gFAAgF;IAChF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,EAAE,CAAC;AAClE,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { NextIndex } from "./types.js";
2
+ export type { NextIndex } from "./types.js";
3
+ export { detectNextAppRouter } from "./detect.js";
4
+ export declare function buildNextIndex(rootDir: string, exclude: string[]): Promise<NextIndex>;
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAQ5C,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,SAAS,CAAC,CAqCpB"}
@@ -0,0 +1,41 @@
1
+ import path from "node:path";
2
+ import { existsSync } from "node:fs";
3
+ import { detectNextAppRouter } from "./detect.js";
4
+ import { readDeps, defaultHintsFromDeps } from "./deps.js";
5
+ import { analyzeMiddleware } from "./middleware.js";
6
+ import { findRouteHandlers, classifyMutationRoutes } from "./routes.js";
7
+ import { findServerActions, classifyMutationActions } from "./server-actions.js";
8
+ import { buildTrpcIndex } from "./trpc.js";
9
+ export { detectNextAppRouter } from "./detect.js";
10
+ export async function buildNextIndex(rootDir, exclude) {
11
+ const det = detectNextAppRouter(rootDir);
12
+ if (!det.ok) {
13
+ throw new Error(`Shipguard v1 supports Next.js App Router only: ${det.reason ?? "unknown reason"}`);
14
+ }
15
+ const { appDir } = det;
16
+ const deps = readDeps(rootDir);
17
+ // Check for middleware in standard locations
18
+ const hasMiddlewareTs = existsSync(path.join(rootDir, "middleware.ts"))
19
+ || existsSync(path.join(rootDir, "middleware.js"))
20
+ || existsSync(path.join(rootDir, "src/middleware.ts"))
21
+ || existsSync(path.join(rootDir, "src/middleware.js"));
22
+ const hints = defaultHintsFromDeps(deps, hasMiddlewareTs);
23
+ const middleware = analyzeMiddleware(rootDir);
24
+ const allRoutes = await findRouteHandlers(rootDir, exclude, appDir);
25
+ const mutationRoutes = classifyMutationRoutes(allRoutes);
26
+ const allActions = await findServerActions(rootDir, exclude, appDir);
27
+ const mutationActions = classifyMutationActions(allActions);
28
+ const trpc = await buildTrpcIndex(rootDir, appDir, exclude);
29
+ return {
30
+ version: 1,
31
+ framework: "next-app-router",
32
+ rootDir,
33
+ deps,
34
+ hints,
35
+ middleware,
36
+ routes: { all: allRoutes, mutationRoutes },
37
+ serverActions: { all: allActions, mutationActions: mutationActions },
38
+ trpc,
39
+ };
40
+ }
41
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAG3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAe,EACf,OAAiB;IAEjB,MAAM,GAAG,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACzC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,kDAAkD,GAAG,CAAC,MAAM,IAAI,gBAAgB,EAAE,CAAC,CAAC;IACtG,CAAC;IAED,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC;IACvB,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAE/B,6CAA6C;IAC7C,MAAM,eAAe,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;WAClE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;WAC/C,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;WACnD,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC;IAEzD,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IAC1D,MAAM,UAAU,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAE9C,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IACpE,MAAM,cAAc,GAAG,sBAAsB,CAAC,SAAS,CAAC,CAAC;IAEzD,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IACrE,MAAM,eAAe,GAAG,uBAAuB,CAAC,UAAU,CAAC,CAAC;IAE5D,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAE5D,OAAO;QACL,OAAO,EAAE,CAAC;QACV,SAAS,EAAE,iBAAiB;QAC5B,OAAO;QACP,IAAI;QACJ,KAAK;QACL,UAAU;QACV,MAAM,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,cAAc,EAAE;QAC1C,aAAa,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE;QACpE,IAAI;KACL,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { NextMiddlewareIndex } from "./types.js";
2
+ export declare function analyzeMiddleware(rootDir: string): NextMiddlewareIndex;
3
+ //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/next/middleware.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,mBAAmB,CAkCtE"}
@@ -0,0 +1,33 @@
1
+ import path from "node:path";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ export function analyzeMiddleware(rootDir) {
4
+ // Next.js middleware can be at root or src/
5
+ const candidates = ["middleware.ts", "middleware.js", "src/middleware.ts", "src/middleware.js"];
6
+ let file;
7
+ let src = "";
8
+ for (const candidate of candidates) {
9
+ const abs = path.join(rootDir, candidate);
10
+ if (existsSync(abs)) {
11
+ file = candidate;
12
+ src = readFileSync(abs, "utf8");
13
+ break;
14
+ }
15
+ }
16
+ if (!file) {
17
+ return { authLikely: false, rateLimitLikely: false, matcherPatterns: [] };
18
+ }
19
+ // Best-effort heuristics (keep conservative)
20
+ const authLikely = /getToken\s*\(|auth\s*\(|clerkMiddleware\s*\(|authMiddleware\s*\(|withAuth\s*\(|getServerSession\s*\(|\.auth\.getUser\s*\(|createMiddlewareClient\s*\(|authkitMiddleware\s*\(|kindeMiddleware\s*\(|withMiddlewareAuthRequired\s*\(|validateRequest\s*\(|getIronSession\s*\(/.test(src);
21
+ const rateLimitLikely = /ratelimit|rateLimit|upstash/i.test(src);
22
+ // Extract matcher config if present
23
+ const matcherPatterns = [];
24
+ const matcherMatch = src.match(/matcher\s*:\s*(\[[\s\S]*?\])/);
25
+ if (matcherMatch) {
26
+ const literals = matcherMatch[1].matchAll(/"([^"]+)"|'([^']+)'/g);
27
+ for (const m of literals) {
28
+ matcherPatterns.push(m[1] ?? m[2]);
29
+ }
30
+ }
31
+ return { file, authLikely, rateLimitLikely, matcherPatterns };
32
+ }
33
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/next/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGnD,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,4CAA4C;IAC5C,MAAM,UAAU,GAAG,CAAC,eAAe,EAAE,eAAe,EAAE,mBAAmB,EAAE,mBAAmB,CAAC,CAAC;IAChG,IAAI,IAAwB,CAAC;IAC7B,IAAI,GAAG,GAAG,EAAE,CAAC;IAEb,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAC1C,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACpB,IAAI,GAAG,SAAS,CAAC;YACjB,GAAG,GAAG,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAChC,MAAM;QACR,CAAC;IACH,CAAC;IAED,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;IAC5E,CAAC;IAED,6CAA6C;IAC7C,MAAM,UAAU,GAAG,4QAA4Q,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1S,MAAM,eAAe,GAAG,8BAA8B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEjE,oCAAoC;IACpC,MAAM,eAAe,GAAa,EAAE,CAAC;IACrC,MAAM,YAAY,GAAG,GAAG,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAC/D,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,QAAQ,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAC;QAClE,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,CAAC;AAChE,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { NextRoute, MutationSignals } from "./types.js";
2
+ export declare function findRouteHandlers(rootDir: string, excludeGlobs: string[], appDir?: string): Promise<NextRoute[]>;
3
+ export declare function classifyMutationRoutes(all: NextRoute[]): NextRoute[];
4
+ export declare function detectMutationSignals(src: string): MutationSignals;
5
+ //# sourceMappingURL=routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/next/routes.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AA4B7D,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EAAE,EACtB,MAAM,GAAE,MAAc,GACrB,OAAO,CAAC,SAAS,EAAE,CAAC,CAkCtB;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAOpE;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CA4ClE"}
@@ -0,0 +1,125 @@
1
+ import path from "node:path";
2
+ import { readFileSync } from "node:fs";
3
+ import fg from "fast-glob";
4
+ /**
5
+ * Prisma write methods that indicate mutation.
6
+ */
7
+ const PRISMA_WRITE_METHODS = [
8
+ "create", "createMany", "createManyAndReturn",
9
+ "update", "updateMany",
10
+ "upsert",
11
+ "delete", "deleteMany",
12
+ ];
13
+ /**
14
+ * Stripe write patterns (method chains that indicate mutation).
15
+ */
16
+ const STRIPE_WRITE_PATTERNS = [
17
+ /stripe\.\w+\.create\s*\(/,
18
+ /stripe\.\w+\.update\s*\(/,
19
+ /stripe\.\w+\.del\s*\(/,
20
+ /stripe\.checkout\.sessions\.create\s*\(/,
21
+ /stripe\.subscriptions\./,
22
+ ];
23
+ /**
24
+ * Admin-like path segments that suggest privileged operations.
25
+ */
26
+ const ADMIN_PATH_SEGMENTS = /\/(admin|billing|invite|role|plan|sync|reindex|delete|remove)\//i;
27
+ export async function findRouteHandlers(rootDir, excludeGlobs, appDir = "app") {
28
+ const files = fg.globSync(`${appDir}/**/route.{ts,js,tsx,jsx}`, {
29
+ cwd: rootDir,
30
+ ignore: ["**/node_modules/**", ...excludeGlobs],
31
+ });
32
+ const routes = [];
33
+ for (const file of files) {
34
+ const abs = path.join(rootDir, file);
35
+ let src;
36
+ try {
37
+ src = readFileSync(abs, "utf8");
38
+ }
39
+ catch {
40
+ continue; // Skip unreadable files
41
+ }
42
+ const signals = detectMutationSignals(src);
43
+ const method = detectExportedMethods(src);
44
+ const pathname = fileToPathname(file, appDir);
45
+ const isApi = pathname.startsWith("/api/") || pathname === "/api";
46
+ routes.push({
47
+ kind: "route-handler",
48
+ file,
49
+ method,
50
+ pathname,
51
+ isApi,
52
+ isPublic: true, // conservative default; can be overridden by config
53
+ signals,
54
+ });
55
+ }
56
+ return routes;
57
+ }
58
+ export function classifyMutationRoutes(all) {
59
+ return all.filter((r) => r.signals.hasMutationEvidence ||
60
+ r.signals.hasDbWriteEvidence ||
61
+ r.signals.hasStripeWriteEvidence);
62
+ }
63
+ export function detectMutationSignals(src) {
64
+ const details = [];
65
+ // Prisma writes
66
+ let hasDbWrite = false;
67
+ for (const method of PRISMA_WRITE_METHODS) {
68
+ const pattern = new RegExp(`\\.${method}\\s*\\(`, "g");
69
+ if (pattern.test(src)) {
70
+ hasDbWrite = true;
71
+ details.push(`prisma.${method}`);
72
+ }
73
+ }
74
+ // Stripe writes
75
+ let hasStripeWrite = false;
76
+ for (const pattern of STRIPE_WRITE_PATTERNS) {
77
+ if (pattern.test(src)) {
78
+ hasStripeWrite = true;
79
+ details.push("stripe write operation");
80
+ break;
81
+ }
82
+ }
83
+ // Raw SQL writes
84
+ const rawSqlWrite = /\$executeRaw|query\s*\(\s*["'`](?:INSERT|UPDATE|DELETE)/i.test(src);
85
+ if (rawSqlWrite) {
86
+ hasDbWrite = true;
87
+ details.push("raw SQL write");
88
+ }
89
+ // General mutation signals: request body reading, admin path patterns
90
+ const readBody = /request\.json\s*\(|request\.formData\s*\(|req\.body/.test(src);
91
+ if (readBody) {
92
+ details.push("reads request body");
93
+ }
94
+ const hasMutation = hasDbWrite || hasStripeWrite || readBody;
95
+ return {
96
+ hasMutationEvidence: hasMutation,
97
+ hasDbWriteEvidence: hasDbWrite,
98
+ hasStripeWriteEvidence: hasStripeWrite,
99
+ mutationDetails: details,
100
+ };
101
+ }
102
+ function detectExportedMethods(src) {
103
+ const methods = [];
104
+ if (/export\s+(?:async\s+)?function\s+GET/m.test(src))
105
+ methods.push("GET");
106
+ if (/export\s+(?:async\s+)?function\s+POST/m.test(src))
107
+ methods.push("POST");
108
+ if (/export\s+(?:async\s+)?function\s+PUT/m.test(src))
109
+ methods.push("PUT");
110
+ if (/export\s+(?:async\s+)?function\s+PATCH/m.test(src))
111
+ methods.push("PATCH");
112
+ if (/export\s+(?:async\s+)?function\s+DELETE/m.test(src))
113
+ methods.push("DELETE");
114
+ return methods.length > 0 ? methods.join(",") : undefined;
115
+ }
116
+ function fileToPathname(file, appDir = "app") {
117
+ // app/api/users/[id]/route.ts → /api/users/[id]
118
+ // src/app/api/users/[id]/route.ts → /api/users/[id]
119
+ const prefix = appDir.endsWith("/") ? appDir : appDir + "/";
120
+ return "/" + file
121
+ .replace(new RegExp(`^${prefix.replace(/[/]/g, "\\/")}`), "")
122
+ .replace(/\/route\.\w+$/, "")
123
+ .replace(/\\/g, "/");
124
+ }
125
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/next/routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { NextServerAction } from "./types.js";
2
+ export declare function findServerActions(rootDir: string, excludeGlobs: string[], appDir?: string): Promise<NextServerAction[]>;
3
+ export declare function classifyMutationActions(all: NextServerAction[]): NextServerAction[];
4
+ //# sourceMappingURL=server-actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-actions.d.ts","sourceRoot":"","sources":["../../src/next/server-actions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAmB,MAAM,YAAY,CAAC;AAOpE,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EAAE,EACtB,MAAM,GAAE,MAAc,GACrB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA4C7B;AAED,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,gBAAgB,EAAE,GAAG,gBAAgB,EAAE,CAOnF"}
@@ -0,0 +1,107 @@
1
+ import path from "node:path";
2
+ import { readFileSync } from "node:fs";
3
+ import fg from "fast-glob";
4
+ const PRISMA_WRITE_METHODS = [
5
+ "create", "createMany", "update", "updateMany",
6
+ "upsert", "delete", "deleteMany",
7
+ ];
8
+ export async function findServerActions(rootDir, excludeGlobs, appDir = "app") {
9
+ const files = fg.globSync(`${appDir}/**/*.{ts,tsx,js,jsx}`, {
10
+ cwd: rootDir,
11
+ ignore: ["**/node_modules/**", "**/route.{ts,js,tsx,jsx}", ...excludeGlobs],
12
+ });
13
+ // Also check src/ for server actions (if appDir isn't already src/app)
14
+ const srcFiles = appDir.startsWith("src/")
15
+ ? []
16
+ : fg.globSync("src/**/*.{ts,tsx,js,jsx}", {
17
+ cwd: rootDir,
18
+ ignore: ["**/node_modules/**", ...excludeGlobs],
19
+ });
20
+ const allFiles = [...files, ...srcFiles];
21
+ const actions = [];
22
+ for (const file of allFiles) {
23
+ const abs = path.join(rootDir, file);
24
+ let src;
25
+ try {
26
+ src = readFileSync(abs, "utf8");
27
+ }
28
+ catch {
29
+ continue; // Skip unreadable files
30
+ }
31
+ // Check for "use server" directive (file-level or inline)
32
+ if (!/["']use server["']/m.test(src))
33
+ continue;
34
+ const isFileLevel = /^["']use server["']/m.test(src);
35
+ const exportNames = extractExportedFunctions(src, isFileLevel);
36
+ for (const exportName of exportNames) {
37
+ const signals = detectActionMutationSignals(src);
38
+ actions.push({
39
+ kind: "server-action",
40
+ file,
41
+ exportName,
42
+ signals,
43
+ });
44
+ }
45
+ }
46
+ return actions;
47
+ }
48
+ export function classifyMutationActions(all) {
49
+ return all.filter((a) => a.signals.hasMutationEvidence ||
50
+ a.signals.hasDbWriteEvidence ||
51
+ a.signals.hasStripeWriteEvidence);
52
+ }
53
+ function extractExportedFunctions(src, isFileLevel) {
54
+ const names = [];
55
+ if (isFileLevel) {
56
+ // All exported functions are server actions
57
+ const exportMatches = src.matchAll(/export\s+(?:async\s+)?function\s+(\w+)/g);
58
+ for (const m of exportMatches) {
59
+ names.push(m[1]);
60
+ }
61
+ // Also named exports: export const foo = async () => ...
62
+ const constMatches = src.matchAll(/export\s+const\s+(\w+)\s*=/g);
63
+ for (const m of constMatches) {
64
+ names.push(m[1]);
65
+ }
66
+ }
67
+ else {
68
+ // Only functions after inline "use server" are actions
69
+ // Match function declarations with "use server" inside the body
70
+ const inlineMatches = src.matchAll(/(?:export\s+)?(?:async\s+)?function\s+(\w+)\s*\([^)]*\)\s*\{[^}]*?["']use server["']/g);
71
+ for (const m of inlineMatches) {
72
+ names.push(m[1]);
73
+ }
74
+ // Match arrow functions with "use server" inside the body
75
+ // e.g.: export const foo = async () => { "use server"; ... }
76
+ // const bar = async (data: FormData) => { "use server"; ... }
77
+ const arrowMatches = src.matchAll(/(?:export\s+)?const\s+(\w+)\s*=\s*(?:async\s+)?(?:\([^)]*\)|[a-zA-Z_]\w*)\s*=>\s*\{[^}]*?["']use server["']/g);
78
+ for (const m of arrowMatches) {
79
+ names.push(m[1]);
80
+ }
81
+ }
82
+ return names.length > 0 ? names : ["<anonymous>"];
83
+ }
84
+ function detectActionMutationSignals(src) {
85
+ const details = [];
86
+ let hasDbWrite = false;
87
+ for (const method of PRISMA_WRITE_METHODS) {
88
+ const pattern = new RegExp(`\\.${method}\\s*\\(`, "g");
89
+ if (pattern.test(src)) {
90
+ hasDbWrite = true;
91
+ details.push(`prisma.${method}`);
92
+ }
93
+ }
94
+ let hasStripeWrite = false;
95
+ if (/stripe\.\w+\.(create|update|del)\s*\(/.test(src)) {
96
+ hasStripeWrite = true;
97
+ details.push("stripe write operation");
98
+ }
99
+ const hasMutation = hasDbWrite || hasStripeWrite;
100
+ return {
101
+ hasMutationEvidence: hasMutation,
102
+ hasDbWriteEvidence: hasDbWrite,
103
+ hasStripeWriteEvidence: hasStripeWrite,
104
+ mutationDetails: details,
105
+ };
106
+ }
107
+ //# sourceMappingURL=server-actions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-actions.js","sourceRoot":"","sources":["../../src/next/server-actions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { TrpcIndex } from "./types.js";
2
+ export declare function buildTrpcIndex(rootDir: string, appDir: string, _excludeGlobs: string[]): Promise<TrpcIndex>;
3
+ //# sourceMappingURL=trpc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trpc.d.ts","sourceRoot":"","sources":["../../src/next/trpc.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAkC,MAAM,YAAY,CAAC;AA0B5E,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EAAE,GACtB,OAAO,CAAC,SAAS,CAAC,CA2BpB"}