raktajs 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 (172) hide show
  1. package/README.md +90 -0
  2. package/dist/auto-import/generator.d.ts +4 -0
  3. package/dist/auto-import/generator.d.ts.map +1 -0
  4. package/dist/auto-import/index.d.ts +5 -0
  5. package/dist/auto-import/index.d.ts.map +1 -0
  6. package/dist/auto-import/index.js +153 -0
  7. package/dist/auto-import/index.js.map +11 -0
  8. package/dist/auto-import/scanner.d.ts +9 -0
  9. package/dist/auto-import/scanner.d.ts.map +1 -0
  10. package/dist/auto-import/types.d.ts +20 -0
  11. package/dist/auto-import/types.d.ts.map +1 -0
  12. package/dist/cli/build.d.ts +2 -0
  13. package/dist/cli/build.d.ts.map +1 -0
  14. package/dist/cli/dev.d.ts +2 -0
  15. package/dist/cli/dev.d.ts.map +1 -0
  16. package/dist/cli/doctor.d.ts +2 -0
  17. package/dist/cli/doctor.d.ts.map +1 -0
  18. package/dist/cli/imports.d.ts +2 -0
  19. package/dist/cli/imports.d.ts.map +1 -0
  20. package/dist/cli/index.d.ts +3 -0
  21. package/dist/cli/index.d.ts.map +1 -0
  22. package/dist/cli/make.d.ts +4 -0
  23. package/dist/cli/make.d.ts.map +1 -0
  24. package/dist/cli/rakta.d.ts +3 -0
  25. package/dist/cli/rakta.d.ts.map +1 -0
  26. package/dist/cli/rakta.js +1511 -0
  27. package/dist/cli/rakta.js.map +33 -0
  28. package/dist/cli/routes.d.ts +2 -0
  29. package/dist/cli/routes.d.ts.map +1 -0
  30. package/dist/cli/rpcTypes.d.ts +2 -0
  31. package/dist/cli/rpcTypes.d.ts.map +1 -0
  32. package/dist/cli/seo.d.ts +2 -0
  33. package/dist/cli/seo.d.ts.map +1 -0
  34. package/dist/cli/start.d.ts +2 -0
  35. package/dist/cli/start.d.ts.map +1 -0
  36. package/dist/components/Click.d.ts +11 -0
  37. package/dist/components/Click.d.ts.map +1 -0
  38. package/dist/components/Picture.d.ts +22 -0
  39. package/dist/components/Picture.d.ts.map +1 -0
  40. package/dist/components/index.d.ts +5 -0
  41. package/dist/components/index.d.ts.map +1 -0
  42. package/dist/components/index.js +1383 -0
  43. package/dist/components/index.js.map +15 -0
  44. package/dist/config/defineConfig.d.ts +64 -0
  45. package/dist/config/defineConfig.d.ts.map +1 -0
  46. package/dist/config/index.d.ts +4 -0
  47. package/dist/config/index.d.ts.map +1 -0
  48. package/dist/config/index.js +104 -0
  49. package/dist/config/index.js.map +11 -0
  50. package/dist/config/loadConfig.d.ts +4 -0
  51. package/dist/config/loadConfig.d.ts.map +1 -0
  52. package/dist/forge/build.d.ts +7 -0
  53. package/dist/forge/build.d.ts.map +1 -0
  54. package/dist/forge/devServer.d.ts +7 -0
  55. package/dist/forge/devServer.d.ts.map +1 -0
  56. package/dist/forge/index.d.ts +6 -0
  57. package/dist/forge/index.d.ts.map +1 -0
  58. package/dist/forge/index.js +579 -0
  59. package/dist/forge/index.js.map +17 -0
  60. package/dist/forge/inspect.d.ts +9 -0
  61. package/dist/forge/inspect.d.ts.map +1 -0
  62. package/dist/forge/types.d.ts +55 -0
  63. package/dist/forge/types.d.ts.map +1 -0
  64. package/dist/http/errors.d.ts +17 -0
  65. package/dist/http/errors.d.ts.map +1 -0
  66. package/dist/http/index.d.ts +4 -0
  67. package/dist/http/index.d.ts.map +1 -0
  68. package/dist/http/index.js +154 -0
  69. package/dist/http/index.js.map +11 -0
  70. package/dist/http/panturaFetch.d.ts +33 -0
  71. package/dist/http/panturaFetch.d.ts.map +1 -0
  72. package/dist/http/types.d.ts +24 -0
  73. package/dist/http/types.d.ts.map +1 -0
  74. package/dist/index.d.ts +30 -0
  75. package/dist/index.d.ts.map +1 -0
  76. package/dist/index.js +3872 -0
  77. package/dist/index.js.map +50 -0
  78. package/dist/pwa/cache.d.ts +6 -0
  79. package/dist/pwa/cache.d.ts.map +1 -0
  80. package/dist/pwa/index.d.ts +5 -0
  81. package/dist/pwa/index.d.ts.map +1 -0
  82. package/dist/pwa/index.js +136 -0
  83. package/dist/pwa/index.js.map +12 -0
  84. package/dist/pwa/manifest.d.ts +11 -0
  85. package/dist/pwa/manifest.d.ts.map +1 -0
  86. package/dist/pwa/serviceWorker.d.ts +11 -0
  87. package/dist/pwa/serviceWorker.d.ts.map +1 -0
  88. package/dist/pwa/types.d.ts +45 -0
  89. package/dist/pwa/types.d.ts.map +1 -0
  90. package/dist/render/index.d.ts +5 -0
  91. package/dist/render/index.d.ts.map +1 -0
  92. package/dist/render/index.js +183 -0
  93. package/dist/render/index.js.map +11 -0
  94. package/dist/render/modes.d.ts +13 -0
  95. package/dist/render/modes.d.ts.map +1 -0
  96. package/dist/render/renderer.d.ts +15 -0
  97. package/dist/render/renderer.d.ts.map +1 -0
  98. package/dist/render/types.d.ts +72 -0
  99. package/dist/render/types.d.ts.map +1 -0
  100. package/dist/router/index.d.ts +5 -0
  101. package/dist/router/index.d.ts.map +1 -0
  102. package/dist/router/index.js +228 -0
  103. package/dist/router/index.js.map +12 -0
  104. package/dist/router/manifest.d.ts +6 -0
  105. package/dist/router/manifest.d.ts.map +1 -0
  106. package/dist/router/matcher.d.ts +5 -0
  107. package/dist/router/matcher.d.ts.map +1 -0
  108. package/dist/router/scanner.d.ts +6 -0
  109. package/dist/router/scanner.d.ts.map +1 -0
  110. package/dist/router/types.d.ts +45 -0
  111. package/dist/router/types.d.ts.map +1 -0
  112. package/dist/rpc/client.d.ts +24 -0
  113. package/dist/rpc/client.d.ts.map +1 -0
  114. package/dist/rpc/index.d.ts +6 -0
  115. package/dist/rpc/index.d.ts.map +1 -0
  116. package/dist/rpc/index.js +179 -0
  117. package/dist/rpc/index.js.map +13 -0
  118. package/dist/rpc/procedure.d.ts +28 -0
  119. package/dist/rpc/procedure.d.ts.map +1 -0
  120. package/dist/rpc/router.d.ts +12 -0
  121. package/dist/rpc/router.d.ts.map +1 -0
  122. package/dist/rpc/types.d.ts +48 -0
  123. package/dist/rpc/types.d.ts.map +1 -0
  124. package/dist/schema/array.d.ts +15 -0
  125. package/dist/schema/array.d.ts.map +1 -0
  126. package/dist/schema/boolean.d.ts +7 -0
  127. package/dist/schema/boolean.d.ts.map +1 -0
  128. package/dist/schema/errors.d.ts +21 -0
  129. package/dist/schema/errors.d.ts.map +1 -0
  130. package/dist/schema/index.d.ts +11 -0
  131. package/dist/schema/index.d.ts.map +1 -0
  132. package/dist/schema/index.js +393 -0
  133. package/dist/schema/index.js.map +16 -0
  134. package/dist/schema/number.d.ts +17 -0
  135. package/dist/schema/number.d.ts.map +1 -0
  136. package/dist/schema/object.d.ts +19 -0
  137. package/dist/schema/object.d.ts.map +1 -0
  138. package/dist/schema/string.d.ts +18 -0
  139. package/dist/schema/string.d.ts.map +1 -0
  140. package/dist/schema/types.d.ts +27 -0
  141. package/dist/schema/types.d.ts.map +1 -0
  142. package/dist/seo/head.d.ts +8 -0
  143. package/dist/seo/head.d.ts.map +1 -0
  144. package/dist/seo/index.d.ts +9 -0
  145. package/dist/seo/index.d.ts.map +1 -0
  146. package/dist/seo/index.js +1578 -0
  147. package/dist/seo/index.js.map +17 -0
  148. package/dist/seo/metadata.d.ts +106 -0
  149. package/dist/seo/metadata.d.ts.map +1 -0
  150. package/dist/seo/robots.d.ts +14 -0
  151. package/dist/seo/robots.d.ts.map +1 -0
  152. package/dist/seo/sitemap.d.ts +27 -0
  153. package/dist/seo/sitemap.d.ts.map +1 -0
  154. package/dist/store/createStore.d.ts +18 -0
  155. package/dist/store/createStore.d.ts.map +1 -0
  156. package/dist/store/index.d.ts +3 -0
  157. package/dist/store/index.d.ts.map +1 -0
  158. package/dist/store/index.js +925 -0
  159. package/dist/store/index.js.map +12 -0
  160. package/dist/store/types.d.ts +14 -0
  161. package/dist/store/types.d.ts.map +1 -0
  162. package/dist/tide/adapter.d.ts +8 -0
  163. package/dist/tide/adapter.d.ts.map +1 -0
  164. package/dist/tide/index.d.ts +4 -0
  165. package/dist/tide/index.d.ts.map +1 -0
  166. package/dist/tide/index.js +477 -0
  167. package/dist/tide/index.js.map +16 -0
  168. package/dist/tide/runtime.d.ts +8 -0
  169. package/dist/tide/runtime.d.ts.map +1 -0
  170. package/dist/tide/types.d.ts +40 -0
  171. package/dist/tide/types.d.ts.map +1 -0
  172. package/package.json +128 -0
@@ -0,0 +1,228 @@
1
+ // @bun
2
+ // src/router/manifest.ts
3
+ import { existsSync as existsSync2, readFileSync, writeFileSync } from "fs";
4
+
5
+ // src/router/scanner.ts
6
+ import { existsSync, readdirSync, statSync } from "fs";
7
+ import { join, relative } from "path";
8
+ var FILE_TO_KIND = {
9
+ "page.tsx": "page",
10
+ "page.ts": "page",
11
+ "page.jsx": "page",
12
+ "page.js": "page",
13
+ "layout.tsx": "layout",
14
+ "layout.ts": "layout",
15
+ "layout.jsx": "layout",
16
+ "layout.js": "layout",
17
+ "loading.tsx": "loading",
18
+ "loading.ts": "loading",
19
+ "loading.jsx": "loading",
20
+ "loading.js": "loading",
21
+ "notFound.tsx": "notFound",
22
+ "notFound.ts": "notFound",
23
+ "notFound.jsx": "notFound",
24
+ "notFound.js": "notFound",
25
+ "error.tsx": "error",
26
+ "error.ts": "error",
27
+ "error.jsx": "error",
28
+ "error.js": "error",
29
+ "route.ts": "api",
30
+ "route.js": "api"
31
+ };
32
+ function parseSegment(raw) {
33
+ const isDynamic = raw.startsWith("[") && raw.endsWith("]");
34
+ const paramName = isDynamic ? raw.slice(1, -1) : "";
35
+ return { raw, isDynamic, paramName };
36
+ }
37
+ function collectParamNames(segments) {
38
+ return segments.filter((segment) => segment.isDynamic && segment.paramName.length > 0).map((segment) => segment.paramName);
39
+ }
40
+ function segmentsToUrlPattern(segments) {
41
+ if (segments.length === 0)
42
+ return "/";
43
+ const parts = segments.map((segment) => segment.isDynamic && segment.paramName ? `:${segment.paramName}` : segment.raw);
44
+ return `/${parts.join("/")}`;
45
+ }
46
+ function scanDirectory(dirPath, appRoot, results) {
47
+ if (!existsSync(dirPath))
48
+ return;
49
+ const entries = readdirSync(dirPath);
50
+ for (const entryName of entries) {
51
+ const fullPath = join(dirPath, entryName);
52
+ const stats = statSync(fullPath);
53
+ if (stats.isDirectory()) {
54
+ scanDirectory(fullPath, appRoot, results);
55
+ continue;
56
+ }
57
+ if (!stats.isFile())
58
+ continue;
59
+ const kind = FILE_TO_KIND[entryName];
60
+ if (!kind)
61
+ continue;
62
+ const relativePath = relative(appRoot, fullPath).replace(/\\/g, "/");
63
+ const dirRelative = relative(appRoot, dirPath).replace(/\\/g, "/");
64
+ const rawSegments = dirRelative === "" ? [] : dirRelative.split("/");
65
+ const segments = rawSegments.map(parseSegment);
66
+ const urlPattern = segmentsToUrlPattern(segments);
67
+ const paramNames = collectParamNames(segments);
68
+ const isDynamic = paramNames.length > 0;
69
+ results.push({
70
+ filePath: relativePath,
71
+ urlPattern,
72
+ kind,
73
+ segments,
74
+ isDynamic,
75
+ paramNames
76
+ });
77
+ }
78
+ }
79
+ function scanRoutes(options) {
80
+ const results = [];
81
+ scanDirectory(options.appDir, options.appDir, results);
82
+ results.sort((routeA, routeB) => {
83
+ if (routeA.isDynamic !== routeB.isDynamic) {
84
+ return routeA.isDynamic ? 1 : -1;
85
+ }
86
+ return routeA.urlPattern.localeCompare(routeB.urlPattern);
87
+ });
88
+ return results;
89
+ }
90
+
91
+ // src/router/manifest.ts
92
+ function generateManifest(appDir) {
93
+ const routes = scanRoutes({ appDir });
94
+ const manifest = {
95
+ version: "1",
96
+ generatedAt: new Date().toISOString(),
97
+ routes
98
+ };
99
+ return manifest;
100
+ }
101
+ function writeManifest(manifest, outputPath) {
102
+ writeFileSync(outputPath, JSON.stringify(manifest, null, 2), "utf-8");
103
+ }
104
+ function readManifest(manifestPath) {
105
+ if (!existsSync2(manifestPath))
106
+ return null;
107
+ const raw = readFileSync(manifestPath, "utf-8");
108
+ const parsed = JSON.parse(raw);
109
+ if (typeof parsed !== "object" || parsed === null || !("version" in parsed) || !("routes" in parsed)) {
110
+ return null;
111
+ }
112
+ return parsed;
113
+ }
114
+ function printManifest(manifest) {
115
+ const pageRoutes = manifest.routes.filter((route) => route.kind === "page");
116
+ const apiRoutes = manifest.routes.filter((route) => route.kind === "api");
117
+ const layoutRoutes = manifest.routes.filter((route) => route.kind === "layout");
118
+ const specialRoutes = manifest.routes.filter((route) => ["loading", "not-found", "error"].includes(route.kind));
119
+ const line = "\u2500".repeat(56);
120
+ console.log(`
121
+ Rakta.js Route Manifest`);
122
+ console.log(` ${line}`);
123
+ console.log(` Generated: ${manifest.generatedAt}`);
124
+ console.log(` Total: ${manifest.routes.length} routes
125
+ `);
126
+ if (pageRoutes.length > 0) {
127
+ console.log(" Pages:");
128
+ for (const route of pageRoutes) {
129
+ const dynamic = route.isDynamic ? ` [params: ${route.paramNames.join(", ")}]` : "";
130
+ console.log(` GET ${route.urlPattern}${dynamic}`);
131
+ }
132
+ console.log("");
133
+ }
134
+ if (apiRoutes.length > 0) {
135
+ console.log(" API Routes:");
136
+ for (const route of apiRoutes) {
137
+ const dynamic = route.isDynamic ? ` [params: ${route.paramNames.join(", ")}]` : "";
138
+ console.log(` ANY ${route.urlPattern}${dynamic}`);
139
+ }
140
+ console.log("");
141
+ }
142
+ if (layoutRoutes.length > 0) {
143
+ console.log(" Layouts:");
144
+ for (const route of layoutRoutes) {
145
+ console.log(` ${route.urlPattern === "/" ? "root" : route.urlPattern}`);
146
+ }
147
+ console.log("");
148
+ }
149
+ if (specialRoutes.length > 0) {
150
+ console.log(" Special:");
151
+ for (const route of specialRoutes) {
152
+ console.log(` [${route.kind}] ${route.filePath}`);
153
+ }
154
+ console.log("");
155
+ }
156
+ console.log(` ${line}
157
+ `);
158
+ }
159
+ // src/router/matcher.ts
160
+ function escapeRegex(text) {
161
+ return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
162
+ }
163
+ function buildPatternRegex(segments) {
164
+ const paramNames = [];
165
+ const parts = segments.map((segment) => {
166
+ if (segment.isDynamic && segment.paramName) {
167
+ paramNames.push(segment.paramName);
168
+ return "([^/]+)";
169
+ }
170
+ return escapeRegex(segment.raw);
171
+ });
172
+ const pattern = parts.length === 0 ? "" : `/${parts.join("/")}`;
173
+ const regex = new RegExp(`^${pattern || "/"}$`);
174
+ return { regex, paramNames };
175
+ }
176
+ function matchRoute(pathname, routes) {
177
+ const normalized = pathname !== "/" && pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
178
+ for (const entry of routes) {
179
+ if (entry.kind !== "page" && entry.kind !== "api")
180
+ continue;
181
+ const { regex, paramNames } = buildPatternRegex(entry.segments);
182
+ const match = regex.exec(normalized);
183
+ if (!match)
184
+ continue;
185
+ const params = {};
186
+ paramNames.forEach((name, index) => {
187
+ const captured = match[index + 1];
188
+ if (captured !== undefined) {
189
+ params[name] = decodeURIComponent(captured);
190
+ }
191
+ });
192
+ return { entry, params };
193
+ }
194
+ return null;
195
+ }
196
+ function findLayoutsForPathname(pathname, routes) {
197
+ const layoutRoutes = routes.filter((route) => route.kind === "layout");
198
+ return layoutRoutes.filter((layout) => {
199
+ if (layout.urlPattern === "/")
200
+ return true;
201
+ return pathname === layout.urlPattern || pathname.startsWith(`${layout.urlPattern}/`);
202
+ });
203
+ }
204
+ function findSpecialRoute(kind, pathname, routes) {
205
+ const candidates = routes.filter((route) => route.kind === kind);
206
+ let best = null;
207
+ let bestLength = -1;
208
+ for (const candidate of candidates) {
209
+ const prefix = candidate.urlPattern === "/" ? "" : candidate.urlPattern;
210
+ if (pathname.startsWith(prefix) && prefix.length > bestLength) {
211
+ best = candidate;
212
+ bestLength = prefix.length;
213
+ }
214
+ }
215
+ return best;
216
+ }
217
+ export {
218
+ writeManifest,
219
+ scanRoutes,
220
+ readManifest,
221
+ printManifest,
222
+ matchRoute,
223
+ generateManifest,
224
+ findSpecialRoute,
225
+ findLayoutsForPathname
226
+ };
227
+
228
+ //# debugId=6396285B4767304E64756E2164756E21
@@ -0,0 +1,12 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["..\\..\\src\\router\\manifest.ts", "..\\..\\src\\router\\scanner.ts", "..\\..\\src\\router\\matcher.ts"],
4
+ "sourcesContent": [
5
+ "import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { scanRoutes } from \"./scanner\";\nimport type { RouteManifest } from \"./types\";\n\nexport function generateManifest(appDir: string): RouteManifest {\n\tconst routes = scanRoutes({ appDir });\n\n\tconst manifest: RouteManifest = {\n\t\tversion: \"1\",\n\t\tgeneratedAt: new Date().toISOString(),\n\t\troutes,\n\t};\n\n\treturn manifest;\n}\n\nexport function writeManifest(\n\tmanifest: RouteManifest,\n\toutputPath: string,\n): void {\n\twriteFileSync(outputPath, JSON.stringify(manifest, null, 2), \"utf-8\");\n}\n\nexport function readManifest(manifestPath: string): RouteManifest | null {\n\tif (!existsSync(manifestPath)) return null;\n\n\tconst raw = readFileSync(manifestPath, \"utf-8\");\n\n\tconst parsed: unknown = JSON.parse(raw);\n\tif (\n\t\ttypeof parsed !== \"object\" ||\n\t\tparsed === null ||\n\t\t!(\"version\" in parsed) ||\n\t\t!(\"routes\" in parsed)\n\t) {\n\t\treturn null;\n\t}\n\n\treturn parsed as RouteManifest;\n}\n\nexport function printManifest(manifest: RouteManifest): void {\n\tconst pageRoutes = manifest.routes.filter((route) => route.kind === \"page\");\n\tconst apiRoutes = manifest.routes.filter((route) => route.kind === \"api\");\n\tconst layoutRoutes = manifest.routes.filter(\n\t\t(route) => route.kind === \"layout\",\n\t);\n\tconst specialRoutes = manifest.routes.filter((route) =>\n\t\t[\"loading\", \"not-found\", \"error\"].includes(route.kind),\n\t);\n\n\tconst line = \"─\".repeat(56);\n\n\tconsole.log(`\\n Rakta.js Route Manifest`);\n\tconsole.log(` ${line}`);\n\tconsole.log(` Generated: ${manifest.generatedAt}`);\n\tconsole.log(` Total: ${manifest.routes.length} routes\\n`);\n\n\tif (pageRoutes.length > 0) {\n\t\tconsole.log(\" Pages:\");\n\t\tfor (const route of pageRoutes) {\n\t\t\tconst dynamic = route.isDynamic\n\t\t\t\t? ` [params: ${route.paramNames.join(\", \")}]`\n\t\t\t\t: \"\";\n\t\t\tconsole.log(` GET ${route.urlPattern}${dynamic}`);\n\t\t}\n\t\tconsole.log(\"\");\n\t}\n\n\tif (apiRoutes.length > 0) {\n\t\tconsole.log(\" API Routes:\");\n\t\tfor (const route of apiRoutes) {\n\t\t\tconst dynamic = route.isDynamic\n\t\t\t\t? ` [params: ${route.paramNames.join(\", \")}]`\n\t\t\t\t: \"\";\n\t\t\tconsole.log(` ANY ${route.urlPattern}${dynamic}`);\n\t\t}\n\t\tconsole.log(\"\");\n\t}\n\n\tif (layoutRoutes.length > 0) {\n\t\tconsole.log(\" Layouts:\");\n\t\tfor (const route of layoutRoutes) {\n\t\t\tconsole.log(\n\t\t\t\t` ${route.urlPattern === \"/\" ? \"root\" : route.urlPattern}`,\n\t\t\t);\n\t\t}\n\t\tconsole.log(\"\");\n\t}\n\n\tif (specialRoutes.length > 0) {\n\t\tconsole.log(\" Special:\");\n\t\tfor (const route of specialRoutes) {\n\t\t\tconsole.log(` [${route.kind}] ${route.filePath}`);\n\t\t}\n\t\tconsole.log(\"\");\n\t}\n\n\tconsole.log(` ${line}\\n`);\n}\n",
6
+ "import { existsSync, readdirSync, statSync } from \"node:fs\";\nimport { join, relative } from \"node:path\";\nimport type { RouteKind, RouteManifestEntry, RouteSegment } from \"./types.js\";\n\nconst FILE_TO_KIND: Record<string, RouteKind> = {\n\t\"page.tsx\": \"page\",\n\t\"page.ts\": \"page\",\n\t\"page.jsx\": \"page\",\n\t\"page.js\": \"page\",\n\t\"layout.tsx\": \"layout\",\n\t\"layout.ts\": \"layout\",\n\t\"layout.jsx\": \"layout\",\n\t\"layout.js\": \"layout\",\n\t\"loading.tsx\": \"loading\",\n\t\"loading.ts\": \"loading\",\n\t\"loading.jsx\": \"loading\",\n\t\"loading.js\": \"loading\",\n\t\"notFound.tsx\": \"notFound\",\n\t\"notFound.ts\": \"notFound\",\n\t\"notFound.jsx\": \"notFound\",\n\t\"notFound.js\": \"notFound\",\n\t\"error.tsx\": \"error\",\n\t\"error.ts\": \"error\",\n\t\"error.jsx\": \"error\",\n\t\"error.js\": \"error\",\n\t\"route.ts\": \"api\",\n\t\"route.js\": \"api\",\n};\n\nfunction parseSegment(raw: string): RouteSegment {\n\tconst isDynamic = raw.startsWith(\"[\") && raw.endsWith(\"]\");\n\tconst paramName = isDynamic ? raw.slice(1, -1) : \"\";\n\n\treturn { raw, isDynamic, paramName };\n}\n\nfunction collectParamNames(segments: RouteSegment[]): string[] {\n\treturn segments\n\t\t.filter((segment) => segment.isDynamic && segment.paramName.length > 0)\n\t\t.map((segment) => segment.paramName);\n}\n\nfunction segmentsToUrlPattern(segments: RouteSegment[]): string {\n\tif (segments.length === 0) return \"/\";\n\tconst parts = segments.map((segment) =>\n\t\tsegment.isDynamic && segment.paramName\n\t\t\t? `:${segment.paramName}`\n\t\t\t: segment.raw,\n\t);\n\treturn `/${parts.join(\"/\")}`;\n}\n\nfunction scanDirectory(\n\tdirPath: string,\n\tappRoot: string,\n\tresults: RouteManifestEntry[],\n): void {\n\tif (!existsSync(dirPath)) return;\n\n\tconst entries = readdirSync(dirPath);\n\n\tfor (const entryName of entries) {\n\t\tconst fullPath = join(dirPath, entryName);\n\t\tconst stats = statSync(fullPath);\n\n\t\tif (stats.isDirectory()) {\n\t\t\tscanDirectory(fullPath, appRoot, results);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!stats.isFile()) continue;\n\n\t\tconst kind = FILE_TO_KIND[entryName];\n\t\tif (!kind) continue;\n\n\t\t// Get path relative to app root, using forward slashes\n\t\tconst relativePath = relative(appRoot, fullPath).replace(/\\\\/g, \"/\");\n\n\t\t// Extract directory segments (all parts except the filename)\n\t\tconst dirRelative = relative(appRoot, dirPath).replace(/\\\\/g, \"/\");\n\t\tconst rawSegments = dirRelative === \"\" ? [] : dirRelative.split(\"/\");\n\n\t\tconst segments: RouteSegment[] = rawSegments.map(parseSegment);\n\t\tconst urlPattern = segmentsToUrlPattern(segments);\n\t\tconst paramNames = collectParamNames(segments);\n\t\tconst isDynamic = paramNames.length > 0;\n\n\t\tresults.push({\n\t\t\tfilePath: relativePath,\n\t\t\turlPattern,\n\t\t\tkind,\n\t\t\tsegments,\n\t\t\tisDynamic,\n\t\t\tparamNames,\n\t\t});\n\t}\n}\n\nexport interface ScanOptions {\n\tappDir: string;\n}\n\nexport function scanRoutes(options: ScanOptions): RouteManifestEntry[] {\n\tconst results: RouteManifestEntry[] = [];\n\tscanDirectory(options.appDir, options.appDir, results);\n\n\t// Sort: static routes before dynamic, shorter patterns first\n\tresults.sort((routeA, routeB) => {\n\t\tif (routeA.isDynamic !== routeB.isDynamic) {\n\t\t\treturn routeA.isDynamic ? 1 : -1;\n\t\t}\n\t\treturn routeA.urlPattern.localeCompare(routeB.urlPattern);\n\t});\n\n\treturn results;\n}\n",
7
+ "import type {\n\tMatchedRoute,\n\tRouteManifestEntry,\n\tRouteSegment,\n} from \"./types.js\";\n\nfunction escapeRegex(text: string): string {\n\treturn text.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction buildPatternRegex(segments: RouteSegment[]): {\n\tregex: RegExp;\n\tparamNames: string[];\n} {\n\tconst paramNames: string[] = [];\n\n\tconst parts = segments.map((segment) => {\n\t\tif (segment.isDynamic && segment.paramName) {\n\t\t\tparamNames.push(segment.paramName);\n\t\t\t// Match any non-slash sequence for the param\n\t\t\treturn \"([^/]+)\";\n\t\t}\n\t\treturn escapeRegex(segment.raw);\n\t});\n\n\tconst pattern = parts.length === 0 ? \"\" : `/${parts.join(\"/\")}`;\n\tconst regex = new RegExp(`^${pattern || \"/\"}$`);\n\n\treturn { regex, paramNames };\n}\n\nexport function matchRoute(\n\tpathname: string,\n\troutes: RouteManifestEntry[],\n): MatchedRoute | null {\n\t// Normalize pathname: strip trailing slash unless root\n\tconst normalized =\n\t\tpathname !== \"/\" && pathname.endsWith(\"/\")\n\t\t\t? pathname.slice(0, -1)\n\t\t\t: pathname;\n\n\tfor (const entry of routes) {\n\t\t// Only match pages and api routes\n\t\tif (entry.kind !== \"page\" && entry.kind !== \"api\") continue;\n\n\t\tconst { regex, paramNames } = buildPatternRegex(entry.segments);\n\t\tconst match = regex.exec(normalized);\n\n\t\tif (!match) continue;\n\n\t\tconst params: Record<string, string> = {};\n\t\tparamNames.forEach((name, index) => {\n\t\t\tconst captured = match[index + 1];\n\t\t\tif (captured !== undefined) {\n\t\t\t\tparams[name] = decodeURIComponent(captured);\n\t\t\t}\n\t\t});\n\n\t\treturn { entry, params };\n\t}\n\n\treturn null;\n}\n\nexport function findLayoutsForPathname(\n\tpathname: string,\n\troutes: RouteManifestEntry[],\n): RouteManifestEntry[] {\n\tconst layoutRoutes = routes.filter((route) => route.kind === \"layout\");\n\n\treturn layoutRoutes.filter((layout) => {\n\t\tif (layout.urlPattern === \"/\") return true;\n\t\treturn (\n\t\t\tpathname === layout.urlPattern ||\n\t\t\tpathname.startsWith(`${layout.urlPattern}/`)\n\t\t);\n\t});\n}\n\nexport function findSpecialRoute(\n\tkind: \"loading\" | \"not-found\" | \"error\",\n\tpathname: string,\n\troutes: RouteManifestEntry[],\n): RouteManifestEntry | null {\n\tconst candidates = routes.filter((route) => route.kind === kind);\n\n\t// Find the most specific match (longest matching prefix)\n\tlet best: RouteManifestEntry | null = null;\n\tlet bestLength = -1;\n\n\tfor (const candidate of candidates) {\n\t\tconst prefix = candidate.urlPattern === \"/\" ? \"\" : candidate.urlPattern;\n\t\tif (pathname.startsWith(prefix) && prefix.length > bestLength) {\n\t\t\tbest = candidate;\n\t\t\tbestLength = prefix.length;\n\t\t}\n\t}\n\n\treturn best;\n}\n"
8
+ ],
9
+ "mappings": "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",
10
+ "debugId": "6396285B4767304E64756E2164756E21",
11
+ "names": []
12
+ }
@@ -0,0 +1,6 @@
1
+ import type { RouteManifest } from "./types";
2
+ export declare function generateManifest(appDir: string): RouteManifest;
3
+ export declare function writeManifest(manifest: RouteManifest, outputPath: string): void;
4
+ export declare function readManifest(manifestPath: string): RouteManifest | null;
5
+ export declare function printManifest(manifest: RouteManifest): void;
6
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/router/manifest.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAU9D;AAED,wBAAgB,aAAa,CAC5B,QAAQ,EAAE,aAAa,EACvB,UAAU,EAAE,MAAM,GAChB,IAAI,CAEN;AAED,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAgBvE;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CA0D3D"}
@@ -0,0 +1,5 @@
1
+ import type { MatchedRoute, RouteManifestEntry } from "./types.js";
2
+ export declare function matchRoute(pathname: string, routes: RouteManifestEntry[]): MatchedRoute | null;
3
+ export declare function findLayoutsForPathname(pathname: string, routes: RouteManifestEntry[]): RouteManifestEntry[];
4
+ export declare function findSpecialRoute(kind: "loading" | "not-found" | "error", pathname: string, routes: RouteManifestEntry[]): RouteManifestEntry | null;
5
+ //# sourceMappingURL=matcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matcher.d.ts","sourceRoot":"","sources":["../../src/router/matcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,YAAY,EACZ,kBAAkB,EAElB,MAAM,YAAY,CAAC;AA2BpB,wBAAgB,UAAU,CACzB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,kBAAkB,EAAE,GAC1B,YAAY,GAAG,IAAI,CA4BrB;AAED,wBAAgB,sBAAsB,CACrC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,kBAAkB,EAAE,GAC1B,kBAAkB,EAAE,CAUtB;AAED,wBAAgB,gBAAgB,CAC/B,IAAI,EAAE,SAAS,GAAG,WAAW,GAAG,OAAO,EACvC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,kBAAkB,EAAE,GAC1B,kBAAkB,GAAG,IAAI,CAgB3B"}
@@ -0,0 +1,6 @@
1
+ import type { RouteManifestEntry } from "./types.js";
2
+ export interface ScanOptions {
3
+ appDir: string;
4
+ }
5
+ export declare function scanRoutes(options: ScanOptions): RouteManifestEntry[];
6
+ //# sourceMappingURL=scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/router/scanner.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAa,kBAAkB,EAAgB,MAAM,YAAY,CAAC;AAgG9E,MAAM,WAAW,WAAW;IAC3B,MAAM,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,kBAAkB,EAAE,CAarE"}
@@ -0,0 +1,45 @@
1
+ export type RouteKind = "page" | "layout" | "loading" | "notFound" | "error" | "api";
2
+ export interface RouteSegment {
3
+ raw: string;
4
+ isDynamic: boolean;
5
+ paramName: string;
6
+ }
7
+ export interface RouteManifestEntry {
8
+ filePath: string;
9
+ urlPattern: string;
10
+ kind: RouteKind;
11
+ segments: RouteSegment[];
12
+ isDynamic: boolean;
13
+ paramNames: string[];
14
+ }
15
+ export interface RouteManifest {
16
+ version: "1";
17
+ generatedAt: string;
18
+ routes: RouteManifestEntry[];
19
+ }
20
+ export interface MatchedRoute {
21
+ entry: RouteManifestEntry;
22
+ params: Record<string, string>;
23
+ }
24
+ export interface RouteContext {
25
+ params: Record<string, string>;
26
+ searchParams: URLSearchParams;
27
+ pathname: string;
28
+ url: URL;
29
+ }
30
+ export interface PageProps {
31
+ params: Record<string, string>;
32
+ searchParams: Record<string, string>;
33
+ }
34
+ export interface LayoutProps {
35
+ children: React.ReactNode;
36
+ searchParams: Record<string, string>;
37
+ }
38
+ export type ApiMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS";
39
+ export type ApiRouteHandler = (request: Request, context: RouteContext) => Response | Promise<Response>;
40
+ export type ApiRouteModule = Partial<Record<ApiMethod, ApiRouteHandler>>;
41
+ export type GenerateMetadataFn<TParams extends Record<string, string> = Record<string, string>> = (context: {
42
+ params: TParams;
43
+ searchParams?: Record<string, string>;
44
+ }) => Promise<import("../seo/metadata.ts").Metadata> | import("../seo/metadata.ts").Metadata;
45
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/router/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAClB,MAAM,GACN,QAAQ,GACR,SAAS,GACT,UAAU,GACV,OAAO,GACP,KAAK,CAAC;AAET,MAAM,WAAW,YAAY;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC7B,OAAO,EAAE,GAAG,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,kBAAkB,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC5B,KAAK,EAAE,kBAAkB,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,YAAY,EAAE,eAAe,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,GAAG,CAAC;CACT;AAED,MAAM,WAAW,SAAS;IACzB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,WAAW;IAC3B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED,MAAM,MAAM,SAAS,GAClB,KAAK,GACL,MAAM,GACN,KAAK,GACL,OAAO,GACP,QAAQ,GACR,MAAM,GACN,SAAS,CAAC;AAEb,MAAM,MAAM,eAAe,GAAG,CAC7B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,YAAY,KACjB,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAElC,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC,CAAC;AAEzE,MAAM,MAAM,kBAAkB,CAC7B,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAC5D,CAAC,OAAO,EAAE;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC,KACE,OAAO,CAAC,OAAO,oBAAoB,EAAE,QAAQ,CAAC,GAC9C,OAAO,oBAAoB,EAAE,QAAQ,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { RouterClient, RouterDefinition } from "./types";
2
+ export interface RaktaClientConfig {
3
+ readonly baseUrl: string;
4
+ readonly headers?: Record<string, string>;
5
+ readonly timeout?: number;
6
+ }
7
+ export interface RaktaRpcErrorDetail {
8
+ readonly path: ReadonlyArray<string>;
9
+ readonly message: string;
10
+ }
11
+ export declare class RaktaRpcError extends Error {
12
+ readonly code: string;
13
+ readonly details?: ReadonlyArray<RaktaRpcErrorDetail>;
14
+ constructor(message: string, code: string, details?: ReadonlyArray<RaktaRpcErrorDetail>);
15
+ }
16
+ /**
17
+ * CarubanWire — Creates a type-safe RPC client.
18
+ *
19
+ * Usage:
20
+ * const api = createRaktaClient<AppRouter>({ baseUrl: "http://localhost:4000/rpc" });
21
+ * const result = await api.hello.query({ name: "Rakta" });
22
+ */
23
+ export declare function createRaktaClient<TRouter extends RouterDefinition>(clientConfig: RaktaClientConfig): RouterClient<TRouter>;
24
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/rpc/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAe,MAAM,SAAS,CAAC;AAE3E,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,aAAc,SAAQ,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;gBAGrD,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,aAAa,CAAC,mBAAmB,CAAC;CAW7C;AA2CD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,SAAS,gBAAgB,EACjE,YAAY,EAAE,iBAAiB,GAC7B,YAAY,CAAC,OAAO,CAAC,CAWvB"}
@@ -0,0 +1,6 @@
1
+ export type { RaktaClientConfig } from "./client";
2
+ export { createRaktaClient, RaktaRpcError } from "./client";
3
+ export { ProcedureBuilder, publicProcedure } from "./procedure";
4
+ export { createRaktaRouter, createRpcHandler } from "./router";
5
+ export type { InferInput, InferOutput, ProcedureDefinition, ProcedureKind, RouterClient, RouterDefinition, RpcEnvelope, RpcErrorEnvelope, RpcPayload, RpcSuccessEnvelope, } from "./types";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rpc/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC/D,YAAY,EACX,UAAU,EACV,WAAW,EACX,mBAAmB,EACnB,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,UAAU,EACV,kBAAkB,GAClB,MAAM,SAAS,CAAC"}
@@ -0,0 +1,179 @@
1
+ // @bun
2
+ // src/rpc/client.ts
3
+ class RaktaRpcError extends Error {
4
+ code;
5
+ details;
6
+ constructor(message, code, details) {
7
+ super(message);
8
+ this.name = "RaktaRpcError";
9
+ this.code = code;
10
+ if (details !== undefined) {
11
+ this.details = details;
12
+ }
13
+ }
14
+ }
15
+ async function callProcedure(clientConfig, procedureName, procedureInput) {
16
+ const abortController = new AbortController;
17
+ const timeoutMs = clientConfig.timeout ?? 30000;
18
+ const timeoutHandle = setTimeout(() => abortController.abort(), timeoutMs);
19
+ let response;
20
+ try {
21
+ response = await fetch(clientConfig.baseUrl, {
22
+ method: "POST",
23
+ headers: {
24
+ "Content-Type": "application/json",
25
+ ...clientConfig.headers ?? {}
26
+ },
27
+ body: JSON.stringify({
28
+ procedure: procedureName,
29
+ input: procedureInput
30
+ }),
31
+ signal: abortController.signal
32
+ });
33
+ } finally {
34
+ clearTimeout(timeoutHandle);
35
+ }
36
+ const responseEnvelope = await response.json();
37
+ if (!responseEnvelope.ok) {
38
+ throw new RaktaRpcError(responseEnvelope.error, responseEnvelope.code, responseEnvelope.details);
39
+ }
40
+ return responseEnvelope.data;
41
+ }
42
+ function createRaktaClient(clientConfig) {
43
+ return new Proxy({}, {
44
+ get(_target, procedureName) {
45
+ return {
46
+ query: (procedureInput) => callProcedure(clientConfig, procedureName, procedureInput),
47
+ mutate: (procedureInput) => callProcedure(clientConfig, procedureName, procedureInput)
48
+ };
49
+ }
50
+ });
51
+ }
52
+ // src/rpc/procedure.ts
53
+ class ProcedureBuilder {
54
+ inputSchema;
55
+ constructor(inputSchema) {
56
+ if (inputSchema !== undefined) {
57
+ this.inputSchema = inputSchema;
58
+ }
59
+ }
60
+ input(schema) {
61
+ return new ProcedureBuilder(schema);
62
+ }
63
+ query(handler) {
64
+ return this.build("query", handler);
65
+ }
66
+ mutation(handler) {
67
+ return this.build("mutation", handler);
68
+ }
69
+ build(kind, handler) {
70
+ if (this.inputSchema !== undefined) {
71
+ return {
72
+ kind,
73
+ inputSchema: this.inputSchema,
74
+ handler
75
+ };
76
+ }
77
+ return {
78
+ kind,
79
+ handler
80
+ };
81
+ }
82
+ }
83
+ var publicProcedure = new ProcedureBuilder;
84
+ // src/schema/errors.ts
85
+ class RaktaSchemaError extends Error {
86
+ errors;
87
+ constructor(errors) {
88
+ const first = errors[0];
89
+ const prefix = first ? `[${first.path.join(".") || "root"}] ${first.message}` : "Validation failed";
90
+ super(`Rakta Schema: ${prefix}${errors.length > 1 ? ` (and ${errors.length - 1} more)` : ""}`);
91
+ this.name = "RaktaSchemaError";
92
+ this.errors = errors;
93
+ }
94
+ }
95
+
96
+ // src/rpc/router.ts
97
+ function createRaktaRouter(procedures) {
98
+ return procedures;
99
+ }
100
+ function createRpcHandler(router) {
101
+ return async (request) => {
102
+ if (request.method !== "POST") {
103
+ return buildJsonResponse({
104
+ ok: false,
105
+ error: "Only POST requests are accepted",
106
+ code: "method_not_allowed"
107
+ }, 405);
108
+ }
109
+ let rpcPayload;
110
+ try {
111
+ rpcPayload = await request.json();
112
+ } catch {
113
+ return buildJsonResponse({ ok: false, error: "Invalid JSON body", code: "parse_error" }, 400);
114
+ }
115
+ if (typeof rpcPayload.procedure !== "string") {
116
+ return buildJsonResponse({
117
+ ok: false,
118
+ error: "Missing procedure name",
119
+ code: "invalid_request"
120
+ }, 400);
121
+ }
122
+ const selectedProcedure = router[rpcPayload.procedure];
123
+ if (selectedProcedure === undefined) {
124
+ return buildJsonResponse({
125
+ ok: false,
126
+ error: `Procedure "${rpcPayload.procedure}" not found`,
127
+ code: "not_found"
128
+ }, 404);
129
+ }
130
+ let validatedInput = rpcPayload.input;
131
+ if (selectedProcedure.inputSchema !== undefined) {
132
+ const validationErrors = selectedProcedure.inputSchema._run(rpcPayload.input);
133
+ if (validationErrors.length > 0) {
134
+ return buildJsonResponse({
135
+ ok: false,
136
+ error: "Input validation failed",
137
+ code: "validation_error",
138
+ details: validationErrors.map((validationError) => ({
139
+ path: validationError.path,
140
+ message: validationError.message
141
+ }))
142
+ }, 422);
143
+ }
144
+ validatedInput = selectedProcedure.inputSchema.parse(rpcPayload.input);
145
+ }
146
+ try {
147
+ const procedureOutput = await selectedProcedure.handler({
148
+ input: validatedInput
149
+ });
150
+ return buildJsonResponse({ ok: true, data: procedureOutput }, 200);
151
+ } catch (caughtError) {
152
+ if (caughtError instanceof RaktaSchemaError) {
153
+ return buildJsonResponse({
154
+ ok: false,
155
+ error: caughtError.message,
156
+ code: "schema_error"
157
+ }, 422);
158
+ }
159
+ const errorMessage = caughtError instanceof Error ? caughtError.message : "Internal server error";
160
+ return buildJsonResponse({ ok: false, error: errorMessage, code: "internal_error" }, 500);
161
+ }
162
+ };
163
+ }
164
+ function buildJsonResponse(responseEnvelope, statusCode) {
165
+ return new Response(JSON.stringify(responseEnvelope), {
166
+ status: statusCode,
167
+ headers: { "Content-Type": "application/json; charset=utf-8" }
168
+ });
169
+ }
170
+ export {
171
+ publicProcedure,
172
+ createRpcHandler,
173
+ createRaktaRouter,
174
+ createRaktaClient,
175
+ RaktaRpcError,
176
+ ProcedureBuilder
177
+ };
178
+
179
+ //# debugId=B8C3D1D8A1B3BBC664756E2164756E21
@@ -0,0 +1,13 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["..\\..\\src\\rpc\\client.ts", "..\\..\\src\\rpc\\procedure.ts", "..\\..\\src\\schema\\errors.ts", "..\\..\\src\\rpc\\router.ts"],
4
+ "sourcesContent": [
5
+ "import type { RouterClient, RouterDefinition, RpcEnvelope } from \"./types\";\n\nexport interface RaktaClientConfig {\n\treadonly baseUrl: string;\n\treadonly headers?: Record<string, string>;\n\treadonly timeout?: number;\n}\n\nexport interface RaktaRpcErrorDetail {\n\treadonly path: ReadonlyArray<string>;\n\treadonly message: string;\n}\n\nexport class RaktaRpcError extends Error {\n\treadonly code: string;\n\treadonly details?: ReadonlyArray<RaktaRpcErrorDetail>;\n\n\tconstructor(\n\t\tmessage: string,\n\t\tcode: string,\n\t\tdetails?: ReadonlyArray<RaktaRpcErrorDetail>,\n\t) {\n\t\tsuper(message);\n\n\t\tthis.name = \"RaktaRpcError\";\n\t\tthis.code = code;\n\n\t\tif (details !== undefined) {\n\t\t\tthis.details = details;\n\t\t}\n\t}\n}\n\nasync function callProcedure<TInput, TOutput>(\n\tclientConfig: RaktaClientConfig,\n\tprocedureName: string,\n\tprocedureInput: TInput,\n): Promise<TOutput> {\n\tconst abortController = new AbortController();\n\tconst timeoutMs = clientConfig.timeout ?? 30_000;\n\tconst timeoutHandle = setTimeout(() => abortController.abort(), timeoutMs);\n\n\tlet response: Response;\n\n\ttry {\n\t\tresponse = await fetch(clientConfig.baseUrl, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t...(clientConfig.headers ?? {}),\n\t\t\t},\n\t\t\tbody: JSON.stringify({\n\t\t\t\tprocedure: procedureName,\n\t\t\t\tinput: procedureInput,\n\t\t\t}),\n\t\t\tsignal: abortController.signal,\n\t\t});\n\t} finally {\n\t\tclearTimeout(timeoutHandle);\n\t}\n\n\tconst responseEnvelope = (await response.json()) as RpcEnvelope<TOutput>;\n\n\tif (!responseEnvelope.ok) {\n\t\tthrow new RaktaRpcError(\n\t\t\tresponseEnvelope.error,\n\t\t\tresponseEnvelope.code,\n\t\t\tresponseEnvelope.details,\n\t\t);\n\t}\n\n\treturn responseEnvelope.data;\n}\n\n/**\n * CarubanWire — Creates a type-safe RPC client.\n *\n * Usage:\n * const api = createRaktaClient<AppRouter>({ baseUrl: \"http://localhost:4000/rpc\" });\n * const result = await api.hello.query({ name: \"Rakta\" });\n */\nexport function createRaktaClient<TRouter extends RouterDefinition>(\n\tclientConfig: RaktaClientConfig,\n): RouterClient<TRouter> {\n\treturn new Proxy({} as RouterClient<TRouter>, {\n\t\tget(_target, procedureName: string) {\n\t\t\treturn {\n\t\t\t\tquery: (procedureInput: unknown) =>\n\t\t\t\t\tcallProcedure(clientConfig, procedureName, procedureInput),\n\t\t\t\tmutate: (procedureInput: unknown) =>\n\t\t\t\t\tcallProcedure(clientConfig, procedureName, procedureInput),\n\t\t\t};\n\t\t},\n\t});\n}\n",
6
+ "import type { RaktaType } from \"../schema/types\";\nimport type { ProcedureDefinition, ProcedureKind } from \"./types\";\n\n/**\n * CarubanWire — Fluent builder for a single type-safe RPC procedure.\n *\n * Usage:\n * publicProcedure\n * .input(object({ name: string().min(1) }))\n * .query(async ({ input }) => ({ message: `Hello ${input.name}` }))\n */\nexport class ProcedureBuilder<TInput = void> {\n\tprivate readonly inputSchema?: RaktaType<TInput>;\n\n\tconstructor(inputSchema?: RaktaType<TInput>) {\n\t\tif (inputSchema !== undefined) {\n\t\t\tthis.inputSchema = inputSchema;\n\t\t}\n\t}\n\n\t/** Attach an input schema. Returns a new builder with TInput typed. */\n\tinput<TNewInput>(schema: RaktaType<TNewInput>): ProcedureBuilder<TNewInput> {\n\t\treturn new ProcedureBuilder<TNewInput>(schema);\n\t}\n\n\t/** Define a read procedure (CarubanWire query). */\n\tquery<TOutput>(\n\t\thandler: (ctx: { readonly input: TInput }) => Promise<TOutput>,\n\t): ProcedureDefinition<TInput, TOutput> {\n\t\treturn this.build(\"query\", handler);\n\t}\n\n\t/** Define a write procedure (CarubanWire mutation). */\n\tmutation<TOutput>(\n\t\thandler: (ctx: { readonly input: TInput }) => Promise<TOutput>,\n\t): ProcedureDefinition<TInput, TOutput> {\n\t\treturn this.build(\"mutation\", handler);\n\t}\n\n\tprivate build<TOutput>(\n\t\tkind: ProcedureKind,\n\t\thandler: (ctx: { readonly input: TInput }) => Promise<TOutput>,\n\t): ProcedureDefinition<TInput, TOutput> {\n\t\tif (this.inputSchema !== undefined) {\n\t\t\treturn {\n\t\t\t\tkind,\n\t\t\t\tinputSchema: this.inputSchema,\n\t\t\t\thandler,\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tkind,\n\t\t\thandler,\n\t\t};\n\t}\n}\n\n/** The base public procedure builder. Chain .input() and .query()/.mutation() from here. */\nexport const publicProcedure = new ProcedureBuilder<void>();\n",
7
+ "export interface ValidationError {\n\treadonly path: ReadonlyArray<string>;\n\treadonly message: string;\n\treadonly code: string;\n}\n\nexport interface ParseSuccess<TOutput> {\n\treadonly kind: \"success\";\n\treadonly data: TOutput;\n}\n\nexport interface ParseFailure {\n\treadonly kind: \"failure\";\n\treadonly errors: ReadonlyArray<ValidationError>;\n}\n\nexport type ParseResult<TOutput> = ParseSuccess<TOutput> | ParseFailure;\n\nexport class RaktaSchemaError extends Error {\n\treadonly errors: ReadonlyArray<ValidationError>;\n\n\tconstructor(errors: ReadonlyArray<ValidationError>) {\n\t\tconst first = errors[0];\n\n\t\tconst prefix = first\n\t\t\t? `[${first.path.join(\".\") || \"root\"}] ${first.message}`\n\t\t\t: \"Validation failed\";\n\n\t\tsuper(\n\t\t\t`Rakta Schema: ${prefix}${\n\t\t\t\terrors.length > 1 ? ` (and ${errors.length - 1} more)` : \"\"\n\t\t\t}`,\n\t\t);\n\n\t\tthis.name = \"RaktaSchemaError\";\n\t\tthis.errors = errors;\n\t}\n}\n\nexport function prefixErrors(\n\terrors: ReadonlyArray<ValidationError>,\n\tkey: string,\n): ValidationError[] {\n\treturn errors.map((error) => ({\n\t\t...error,\n\t\tpath: [key, ...error.path],\n\t}));\n}\n\nexport const preFixErrors = prefixErrors;\n",
8
+ "import { RaktaSchemaError } from \"../schema/errors\";\nimport type { RouterDefinition, RpcEnvelope, RpcPayload } from \"./types\";\n\n/**\n * CarubanWire - Creates a Rakta RPC router from a map of procedure definitions.\n * The return value is typed as `TRouter` so TypeScript can infer procedure types.\n */\nexport function createRaktaRouter<TRouter extends RouterDefinition>(\n\tprocedures: TRouter,\n): TRouter {\n\treturn procedures;\n}\n\n/**\n * Creates an HTTP request handler for the given router.\n * Mount at your chosen base path, e.g. POST /rpc\n */\nexport function createRpcHandler<TRouter extends RouterDefinition>(\n\trouter: TRouter,\n): (request: Request) => Promise<Response> {\n\treturn async (request: Request): Promise<Response> => {\n\t\tif (request.method !== \"POST\") {\n\t\t\treturn buildJsonResponse<string>(\n\t\t\t\t{\n\t\t\t\t\tok: false,\n\t\t\t\t\terror: \"Only POST requests are accepted\",\n\t\t\t\t\tcode: \"method_not_allowed\",\n\t\t\t\t},\n\t\t\t\t405,\n\t\t\t);\n\t\t}\n\n\t\tlet rpcPayload: RpcPayload;\n\n\t\ttry {\n\t\t\trpcPayload = (await request.json()) as RpcPayload;\n\t\t} catch {\n\t\t\treturn buildJsonResponse<string>(\n\t\t\t\t{ ok: false, error: \"Invalid JSON body\", code: \"parse_error\" },\n\t\t\t\t400,\n\t\t\t);\n\t\t}\n\n\t\tif (typeof rpcPayload.procedure !== \"string\") {\n\t\t\treturn buildJsonResponse<string>(\n\t\t\t\t{\n\t\t\t\t\tok: false,\n\t\t\t\t\terror: \"Missing procedure name\",\n\t\t\t\t\tcode: \"invalid_request\",\n\t\t\t\t},\n\t\t\t\t400,\n\t\t\t);\n\t\t}\n\n\t\tconst selectedProcedure = router[rpcPayload.procedure];\n\n\t\tif (selectedProcedure === undefined) {\n\t\t\treturn buildJsonResponse<string>(\n\t\t\t\t{\n\t\t\t\t\tok: false,\n\t\t\t\t\terror: `Procedure \"${rpcPayload.procedure}\" not found`,\n\t\t\t\t\tcode: \"not_found\",\n\t\t\t\t},\n\t\t\t\t404,\n\t\t\t);\n\t\t}\n\n\t\tlet validatedInput: unknown = rpcPayload.input;\n\n\t\tif (selectedProcedure.inputSchema !== undefined) {\n\t\t\tconst validationErrors = selectedProcedure.inputSchema._run(\n\t\t\t\trpcPayload.input,\n\t\t\t);\n\n\t\t\tif (validationErrors.length > 0) {\n\t\t\t\treturn buildJsonResponse<string>(\n\t\t\t\t\t{\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\terror: \"Input validation failed\",\n\t\t\t\t\t\tcode: \"validation_error\",\n\t\t\t\t\t\tdetails: validationErrors.map((validationError) => ({\n\t\t\t\t\t\t\tpath: validationError.path,\n\t\t\t\t\t\t\tmessage: validationError.message,\n\t\t\t\t\t\t})),\n\t\t\t\t\t},\n\t\t\t\t\t422,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tvalidatedInput = selectedProcedure.inputSchema.parse(rpcPayload.input);\n\t\t}\n\n\t\ttry {\n\t\t\tconst procedureOutput = await selectedProcedure.handler({\n\t\t\t\tinput: validatedInput,\n\t\t\t});\n\n\t\t\treturn buildJsonResponse({ ok: true, data: procedureOutput }, 200);\n\t\t} catch (caughtError) {\n\t\t\tif (caughtError instanceof RaktaSchemaError) {\n\t\t\t\treturn buildJsonResponse<string>(\n\t\t\t\t\t{\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\terror: caughtError.message,\n\t\t\t\t\t\tcode: \"schema_error\",\n\t\t\t\t\t},\n\t\t\t\t\t422,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst errorMessage =\n\t\t\t\tcaughtError instanceof Error\n\t\t\t\t\t? caughtError.message\n\t\t\t\t\t: \"Internal server error\";\n\n\t\t\treturn buildJsonResponse<string>(\n\t\t\t\t{ ok: false, error: errorMessage, code: \"internal_error\" },\n\t\t\t\t500,\n\t\t\t);\n\t\t}\n\t};\n}\n\nfunction buildJsonResponse<TData>(\n\tresponseEnvelope: RpcEnvelope<TData>,\n\tstatusCode: number,\n): Response {\n\treturn new Response(JSON.stringify(responseEnvelope), {\n\t\tstatus: statusCode,\n\t\theaders: { \"Content-Type\": \"application/json; charset=utf-8\" },\n\t});\n}\n"
9
+ ],
10
+ "mappings": ";;AAaO,MAAM,sBAAsB,MAAM;AAAA,EAC/B;AAAA,EACA;AAAA,EAET,WAAW,CACV,SACA,MACA,SACC;AAAA,IACD,MAAM,OAAO;AAAA,IAEb,KAAK,OAAO;AAAA,IACZ,KAAK,OAAO;AAAA,IAEZ,IAAI,YAAY,WAAW;AAAA,MAC1B,KAAK,UAAU;AAAA,IAChB;AAAA;AAEF;AAEA,eAAe,aAA8B,CAC5C,cACA,eACA,gBACmB;AAAA,EACnB,MAAM,kBAAkB,IAAI;AAAA,EAC5B,MAAM,YAAY,aAAa,WAAW;AAAA,EAC1C,MAAM,gBAAgB,WAAW,MAAM,gBAAgB,MAAM,GAAG,SAAS;AAAA,EAEzE,IAAI;AAAA,EAEJ,IAAI;AAAA,IACH,WAAW,MAAM,MAAM,aAAa,SAAS;AAAA,MAC5C,QAAQ;AAAA,MACR,SAAS;AAAA,QACR,gBAAgB;AAAA,WACZ,aAAa,WAAW,CAAC;AAAA,MAC9B;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACpB,WAAW;AAAA,QACX,OAAO;AAAA,MACR,CAAC;AAAA,MACD,QAAQ,gBAAgB;AAAA,IACzB,CAAC;AAAA,YACA;AAAA,IACD,aAAa,aAAa;AAAA;AAAA,EAG3B,MAAM,mBAAoB,MAAM,SAAS,KAAK;AAAA,EAE9C,IAAI,CAAC,iBAAiB,IAAI;AAAA,IACzB,MAAM,IAAI,cACT,iBAAiB,OACjB,iBAAiB,MACjB,iBAAiB,OAClB;AAAA,EACD;AAAA,EAEA,OAAO,iBAAiB;AAAA;AAUlB,SAAS,iBAAmD,CAClE,cACwB;AAAA,EACxB,OAAO,IAAI,MAAM,CAAC,GAA4B;AAAA,IAC7C,GAAG,CAAC,SAAS,eAAuB;AAAA,MACnC,OAAO;AAAA,QACN,OAAO,CAAC,mBACP,cAAc,cAAc,eAAe,cAAc;AAAA,QAC1D,QAAQ,CAAC,mBACR,cAAc,cAAc,eAAe,cAAc;AAAA,MAC3D;AAAA;AAAA,EAEF,CAAC;AAAA;;AClFK,MAAM,iBAAgC;AAAA,EAC3B;AAAA,EAEjB,WAAW,CAAC,aAAiC;AAAA,IAC5C,IAAI,gBAAgB,WAAW;AAAA,MAC9B,KAAK,cAAc;AAAA,IACpB;AAAA;AAAA,EAID,KAAgB,CAAC,QAA2D;AAAA,IAC3E,OAAO,IAAI,iBAA4B,MAAM;AAAA;AAAA,EAI9C,KAAc,CACb,SACuC;AAAA,IACvC,OAAO,KAAK,MAAM,SAAS,OAAO;AAAA;AAAA,EAInC,QAAiB,CAChB,SACuC;AAAA,IACvC,OAAO,KAAK,MAAM,YAAY,OAAO;AAAA;AAAA,EAG9B,KAAc,CACrB,MACA,SACuC;AAAA,IACvC,IAAI,KAAK,gBAAgB,WAAW;AAAA,MACnC,OAAO;AAAA,QACN;AAAA,QACA,aAAa,KAAK;AAAA,QAClB;AAAA,MACD;AAAA,IACD;AAAA,IAEA,OAAO;AAAA,MACN;AAAA,MACA;AAAA,IACD;AAAA;AAEF;AAGO,IAAM,kBAAkB,IAAI;;ACzC5B,MAAM,yBAAyB,MAAM;AAAA,EAClC;AAAA,EAET,WAAW,CAAC,QAAwC;AAAA,IACnD,MAAM,QAAQ,OAAO;AAAA,IAErB,MAAM,SAAS,QACZ,IAAI,MAAM,KAAK,KAAK,GAAG,KAAK,WAAW,MAAM,YAC7C;AAAA,IAEH,MACC,iBAAiB,SAChB,OAAO,SAAS,IAAI,SAAS,OAAO,SAAS,YAAY,IAE3D;AAAA,IAEA,KAAK,OAAO;AAAA,IACZ,KAAK,SAAS;AAAA;AAEhB;;;AC9BO,SAAS,iBAAmD,CAClE,YACU;AAAA,EACV,OAAO;AAAA;AAOD,SAAS,gBAAkD,CACjE,QAC0C;AAAA,EAC1C,OAAO,OAAO,YAAwC;AAAA,IACrD,IAAI,QAAQ,WAAW,QAAQ;AAAA,MAC9B,OAAO,kBACN;AAAA,QACC,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,MAAM;AAAA,MACP,GACA,GACD;AAAA,IACD;AAAA,IAEA,IAAI;AAAA,IAEJ,IAAI;AAAA,MACH,aAAc,MAAM,QAAQ,KAAK;AAAA,MAChC,MAAM;AAAA,MACP,OAAO,kBACN,EAAE,IAAI,OAAO,OAAO,qBAAqB,MAAM,cAAc,GAC7D,GACD;AAAA;AAAA,IAGD,IAAI,OAAO,WAAW,cAAc,UAAU;AAAA,MAC7C,OAAO,kBACN;AAAA,QACC,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,MAAM;AAAA,MACP,GACA,GACD;AAAA,IACD;AAAA,IAEA,MAAM,oBAAoB,OAAO,WAAW;AAAA,IAE5C,IAAI,sBAAsB,WAAW;AAAA,MACpC,OAAO,kBACN;AAAA,QACC,IAAI;AAAA,QACJ,OAAO,cAAc,WAAW;AAAA,QAChC,MAAM;AAAA,MACP,GACA,GACD;AAAA,IACD;AAAA,IAEA,IAAI,iBAA0B,WAAW;AAAA,IAEzC,IAAI,kBAAkB,gBAAgB,WAAW;AAAA,MAChD,MAAM,mBAAmB,kBAAkB,YAAY,KACtD,WAAW,KACZ;AAAA,MAEA,IAAI,iBAAiB,SAAS,GAAG;AAAA,QAChC,OAAO,kBACN;AAAA,UACC,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,MAAM;AAAA,UACN,SAAS,iBAAiB,IAAI,CAAC,qBAAqB;AAAA,YACnD,MAAM,gBAAgB;AAAA,YACtB,SAAS,gBAAgB;AAAA,UAC1B,EAAE;AAAA,QACH,GACA,GACD;AAAA,MACD;AAAA,MAEA,iBAAiB,kBAAkB,YAAY,MAAM,WAAW,KAAK;AAAA,IACtE;AAAA,IAEA,IAAI;AAAA,MACH,MAAM,kBAAkB,MAAM,kBAAkB,QAAQ;AAAA,QACvD,OAAO;AAAA,MACR,CAAC;AAAA,MAED,OAAO,kBAAkB,EAAE,IAAI,MAAM,MAAM,gBAAgB,GAAG,GAAG;AAAA,MAChE,OAAO,aAAa;AAAA,MACrB,IAAI,uBAAuB,kBAAkB;AAAA,QAC5C,OAAO,kBACN;AAAA,UACC,IAAI;AAAA,UACJ,OAAO,YAAY;AAAA,UACnB,MAAM;AAAA,QACP,GACA,GACD;AAAA,MACD;AAAA,MAEA,MAAM,eACL,uBAAuB,QACpB,YAAY,UACZ;AAAA,MAEJ,OAAO,kBACN,EAAE,IAAI,OAAO,OAAO,cAAc,MAAM,iBAAiB,GACzD,GACD;AAAA;AAAA;AAAA;AAKH,SAAS,iBAAwB,CAChC,kBACA,YACW;AAAA,EACX,OAAO,IAAI,SAAS,KAAK,UAAU,gBAAgB,GAAG;AAAA,IACrD,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,kCAAkC;AAAA,EAC9D,CAAC;AAAA;",
11
+ "debugId": "B8C3D1D8A1B3BBC664756E2164756E21",
12
+ "names": []
13
+ }
@@ -0,0 +1,28 @@
1
+ import type { RaktaType } from "../schema/types";
2
+ import type { ProcedureDefinition } from "./types";
3
+ /**
4
+ * CarubanWire — Fluent builder for a single type-safe RPC procedure.
5
+ *
6
+ * Usage:
7
+ * publicProcedure
8
+ * .input(object({ name: string().min(1) }))
9
+ * .query(async ({ input }) => ({ message: `Hello ${input.name}` }))
10
+ */
11
+ export declare class ProcedureBuilder<TInput = void> {
12
+ private readonly inputSchema?;
13
+ constructor(inputSchema?: RaktaType<TInput>);
14
+ /** Attach an input schema. Returns a new builder with TInput typed. */
15
+ input<TNewInput>(schema: RaktaType<TNewInput>): ProcedureBuilder<TNewInput>;
16
+ /** Define a read procedure (CarubanWire query). */
17
+ query<TOutput>(handler: (ctx: {
18
+ readonly input: TInput;
19
+ }) => Promise<TOutput>): ProcedureDefinition<TInput, TOutput>;
20
+ /** Define a write procedure (CarubanWire mutation). */
21
+ mutation<TOutput>(handler: (ctx: {
22
+ readonly input: TInput;
23
+ }) => Promise<TOutput>): ProcedureDefinition<TInput, TOutput>;
24
+ private build;
25
+ }
26
+ /** The base public procedure builder. Chain .input() and .query()/.mutation() from here. */
27
+ export declare const publicProcedure: ProcedureBuilder<void>;
28
+ //# sourceMappingURL=procedure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"procedure.d.ts","sourceRoot":"","sources":["../../src/rpc/procedure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,mBAAmB,EAAiB,MAAM,SAAS,CAAC;AAElE;;;;;;;GAOG;AACH,qBAAa,gBAAgB,CAAC,MAAM,GAAG,IAAI;IAC1C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAoB;gBAErC,WAAW,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC;IAM3C,uEAAuE;IACvE,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,SAAS,CAAC,GAAG,gBAAgB,CAAC,SAAS,CAAC;IAI3E,mDAAmD;IACnD,KAAK,CAAC,OAAO,EACZ,OAAO,EAAE,CAAC,GAAG,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,GAC5D,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC;IAIvC,uDAAuD;IACvD,QAAQ,CAAC,OAAO,EACf,OAAO,EAAE,CAAC,GAAG,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,GAC5D,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC;IAIvC,OAAO,CAAC,KAAK;CAiBb;AAED,4FAA4F;AAC5F,eAAO,MAAM,eAAe,wBAA+B,CAAC"}