@kosmojs/dev 0.0.11 → 0.0.21

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 (225) hide show
  1. package/LICENSE +21 -0
  2. package/package.json +13 -45
  3. package/pkg/{src/base-plugin/ast.d.ts → ast.d.ts} +11 -16
  4. package/pkg/{src/base-plugin → base-plugin}/api-handler.d.ts +2 -2
  5. package/pkg/{src/base-plugin → base-plugin}/index.d.ts +1 -1
  6. package/pkg/{src/base-plugin → base-plugin}/worker.d.ts +2 -3
  7. package/pkg/base-plugin/worker.js +614 -196
  8. package/pkg/base-plugin/worker.js.map +4 -4
  9. package/pkg/{src/base-plugin/cache.d.ts → cache.d.ts} +3 -3
  10. package/pkg/defaults.d.ts +13 -0
  11. package/pkg/fs.d.ts +1 -0
  12. package/pkg/index.d.ts +9 -0
  13. package/pkg/index.js +991 -313
  14. package/pkg/index.js.map +4 -4
  15. package/pkg/paths.d.ts +13 -0
  16. package/pkg/render.d.ts +28 -0
  17. package/pkg/routes-factory/base.d.ts +47 -0
  18. package/pkg/routes-factory/index.d.ts +9 -0
  19. package/pkg/routes-factory/nesting.d.ts +3 -0
  20. package/pkg/{src/base-plugin/routes → routes-factory}/resolve.d.ts +3 -3
  21. package/pkg/{src/stub-generator → stub-generator}/index.d.ts +1 -1
  22. package/pkg/stub-generator/index.js +155 -24
  23. package/pkg/stub-generator/index.js.map +4 -4
  24. package/pkg/typebox.d.ts +2 -0
  25. package/pkg/types.d.ts +305 -0
  26. package/pkg/base-plugin/routes.js +0 -819
  27. package/pkg/base-plugin/routes.js.map +0 -7
  28. package/pkg/cli/cli.js +0 -583
  29. package/pkg/cli/cli.js.map +0 -7
  30. package/pkg/cli/index.js +0 -422
  31. package/pkg/cli/index.js.map +0 -7
  32. package/pkg/cli/templates/.env +0 -1
  33. package/pkg/cli/templates/@src/api/app.hbs +0 -32
  34. package/pkg/cli/templates/@src/api/router.hbs +0 -11
  35. package/pkg/cli/templates/@src/api/server.hbs +0 -4
  36. package/pkg/cli/templates/@src/api/use.hbs +0 -6
  37. package/pkg/cli/templates/@src/config/index.hbs +0 -2
  38. package/pkg/cli/templates/@src/index.html +0 -4
  39. package/pkg/cli/templates/@src/vite.config.hbs +0 -29
  40. package/pkg/cli/templates/core/api/app.ts +0 -6
  41. package/pkg/cli/templates/core/api/env.d.ts +0 -4
  42. package/pkg/cli/templates/core/api/errors.ts +0 -18
  43. package/pkg/cli/templates/core/api/router.ts +0 -6
  44. package/pkg/cli/templates/core/api/server.ts +0 -63
  45. package/pkg/cli/templates/core/api/use.ts +0 -25
  46. package/pkg/cli/templates/vite.base.hbs +0 -44
  47. package/pkg/src/base-plugin/routes/nesting.d.ts +0 -5
  48. package/pkg/src/base-plugin/routes.d.ts +0 -9
  49. package/pkg/src/cli/base.d.ts +0 -30
  50. package/pkg/src/cli/cli.d.ts +0 -2
  51. package/pkg/src/cli/factory.d.ts +0 -12
  52. package/pkg/src/cli/index.d.ts +0 -2
  53. package/pkg/src/cli/templates/core/api/app.d.ts +0 -3
  54. package/pkg/src/cli/templates/core/api/errors.d.ts +0 -1
  55. package/pkg/src/cli/templates/core/api/router.d.ts +0 -3
  56. package/pkg/src/cli/templates/core/api/server.d.ts +0 -3
  57. package/pkg/src/cli/templates/core/api/use.d.ts +0 -2
  58. package/pkg/src/index.d.ts +0 -6
  59. package/pkg/test/@fixtures/app/@src/api/articles/[...path]/index.d.ts +0 -0
  60. package/pkg/test/@fixtures/app/@src/api/books/[category]/[[author]]/index.d.ts +0 -0
  61. package/pkg/test/@fixtures/app/@src/api/books/[category]/index.d.ts +0 -0
  62. package/pkg/test/@fixtures/app/@src/api/books/index.d.ts +0 -0
  63. package/pkg/test/@fixtures/app/@src/api/files/[[folder]]/[[id]].json/index.d.ts +0 -0
  64. package/pkg/test/@fixtures/app/@src/api/files/[[folder]]/index.d.ts +0 -0
  65. package/pkg/test/@fixtures/app/@src/api/index/index.d.ts +0 -0
  66. package/pkg/test/@fixtures/app/@src/api/pages/[...path].html/index.d.ts +0 -0
  67. package/pkg/test/@fixtures/app/@src/api/users/[id].json/index.d.ts +0 -0
  68. package/pkg/test/@fixtures/app/@src/pages/about/careers/[jobId]/index.d.ts +0 -0
  69. package/pkg/test/@fixtures/app/@src/pages/about/careers/layout.d.ts +0 -0
  70. package/pkg/test/@fixtures/app/@src/pages/about/index.d.ts +0 -0
  71. package/pkg/test/@fixtures/app/@src/pages/about/layout.d.ts +0 -0
  72. package/pkg/test/@fixtures/app/@src/pages/about/team/index.d.ts +0 -0
  73. package/pkg/test/@fixtures/app/@src/pages/account/layout.d.ts +0 -0
  74. package/pkg/test/@fixtures/app/@src/pages/account/profile/index.d.ts +0 -0
  75. package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/index.d.ts +0 -0
  76. package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/resources/[[type]]/[...path]/index.d.ts +0 -0
  77. package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/resources/[[type]]/index.d.ts +0 -0
  78. package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/resources/[[type]]/layout.d.ts +0 -0
  79. package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/resources/index.d.ts +0 -0
  80. package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/resources/layout.d.ts +0 -0
  81. package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/settings/general/index.d.ts +0 -0
  82. package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/settings/index.d.ts +0 -0
  83. package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/settings/layout.d.ts +0 -0
  84. package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/settings/permissions/index.d.ts +0 -0
  85. package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/users/[userId]/index.d.ts +0 -0
  86. package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/users/index.d.ts +0 -0
  87. package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/users/layout.d.ts +0 -0
  88. package/pkg/test/@fixtures/app/@src/pages/admin/index.d.ts +0 -0
  89. package/pkg/test/@fixtures/app/@src/pages/admin/layout.d.ts +0 -0
  90. package/pkg/test/@fixtures/app/@src/pages/blog/[[category]]/[[tag]]/index.d.ts +0 -0
  91. package/pkg/test/@fixtures/app/@src/pages/blog/[[category]]/index.d.ts +0 -0
  92. package/pkg/test/@fixtures/app/@src/pages/blog/index.d.ts +0 -0
  93. package/pkg/test/@fixtures/app/@src/pages/blog/layout.d.ts +0 -0
  94. package/pkg/test/@fixtures/app/@src/pages/blog/post/[slug]/index.d.ts +0 -0
  95. package/pkg/test/@fixtures/app/@src/pages/blog/post/[slug]/layout.d.ts +0 -0
  96. package/pkg/test/@fixtures/app/@src/pages/contact/index.d.ts +0 -0
  97. package/pkg/test/@fixtures/app/@src/pages/contact/layout.d.ts +0 -0
  98. package/pkg/test/@fixtures/app/@src/pages/courses/[courseId]/layout.d.ts +0 -0
  99. package/pkg/test/@fixtures/app/@src/pages/courses/[courseId]/lessons/[[lessonId]]/assignments/[...assignmentPath]/index.d.ts +0 -0
  100. package/pkg/test/@fixtures/app/@src/pages/dashboard/[view]/index.d.ts +0 -0
  101. package/pkg/test/@fixtures/app/@src/pages/dashboard/analytics/index.d.ts +0 -0
  102. package/pkg/test/@fixtures/app/@src/pages/dashboard/index.d.ts +0 -0
  103. package/pkg/test/@fixtures/app/@src/pages/dashboard/layout.d.ts +0 -0
  104. package/pkg/test/@fixtures/app/@src/pages/dashboard/settings/billing/index.d.ts +0 -0
  105. package/pkg/test/@fixtures/app/@src/pages/dashboard/settings/index.d.ts +0 -0
  106. package/pkg/test/@fixtures/app/@src/pages/dashboard/settings/layout.d.ts +0 -0
  107. package/pkg/test/@fixtures/app/@src/pages/dashboard/settings/notifications/index.d.ts +0 -0
  108. package/pkg/test/@fixtures/app/@src/pages/dashboard/settings/profile/index.d.ts +0 -0
  109. package/pkg/test/@fixtures/app/@src/pages/dashboard/settings/security/index.d.ts +0 -0
  110. package/pkg/test/@fixtures/app/@src/pages/dashboard/settings/security/layout.d.ts +0 -0
  111. package/pkg/test/@fixtures/app/@src/pages/docs/[...path]/index.d.ts +0 -0
  112. package/pkg/test/@fixtures/app/@src/pages/docs/index.d.ts +0 -0
  113. package/pkg/test/@fixtures/app/@src/pages/docs/layout.d.ts +0 -0
  114. package/pkg/test/@fixtures/app/@src/pages/files/[...filePath]/index.d.ts +0 -0
  115. package/pkg/test/@fixtures/app/@src/pages/files/[...filePath]/layout.d.ts +0 -0
  116. package/pkg/test/@fixtures/app/@src/pages/legal/layout.d.ts +0 -0
  117. package/pkg/test/@fixtures/app/@src/pages/legal/privacy/index.d.ts +0 -0
  118. package/pkg/test/@fixtures/app/@src/pages/legal/terms/index.d.ts +0 -0
  119. package/pkg/test/@fixtures/app/@src/pages/news/[category]/articles/[...articlePath]/index.d.ts +0 -0
  120. package/pkg/test/@fixtures/app/@src/pages/news/[category]/layout.d.ts +0 -0
  121. package/pkg/test/@fixtures/app/@src/pages/portal/[clientId]/layout.d.ts +0 -0
  122. package/pkg/test/@fixtures/app/@src/pages/portal/[clientId]/reports/[reportType]/data/[dataView]/index.d.ts +0 -0
  123. package/pkg/test/@fixtures/app/@src/pages/portal/[clientId]/reports/[reportType]/data/[dataView]/layout.d.ts +0 -0
  124. package/pkg/test/@fixtures/app/@src/pages/portal/[clientId]/reports/[reportType]/layout.d.ts +0 -0
  125. package/pkg/test/@fixtures/app/@src/pages/portal/[clientId]/reports/layout.d.ts +0 -0
  126. package/pkg/test/@fixtures/app/@src/pages/portal/layout.d.ts +0 -0
  127. package/pkg/test/@fixtures/app/@src/pages/products/[id]/index.d.ts +0 -0
  128. package/pkg/test/@fixtures/app/@src/pages/products/index.d.ts +0 -0
  129. package/pkg/test/@fixtures/app/@src/pages/profile/[username]/layout.d.ts +0 -0
  130. package/pkg/test/@fixtures/app/@src/pages/profile/[username]/posts/[postId]/comments/[...thread]/index.d.ts +0 -0
  131. package/pkg/test/@fixtures/app/@src/pages/profile/[username]/posts/[postId]/layout.d.ts +0 -0
  132. package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/files/[...path]/index.d.ts +0 -0
  133. package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/files/index.d.ts +0 -0
  134. package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/files/layout.d.ts +0 -0
  135. package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/index.d.ts +0 -0
  136. package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/layout.d.ts +0 -0
  137. package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/tasks/[taskId]/comments/[commentId]/index.d.ts +0 -0
  138. package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/tasks/[taskId]/comments/index.d.ts +0 -0
  139. package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/tasks/[taskId]/comments/layout.d.ts +0 -0
  140. package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/tasks/[taskId]/index.d.ts +0 -0
  141. package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/tasks/[taskId]/layout.d.ts +0 -0
  142. package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/tasks/index.d.ts +0 -0
  143. package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/tasks/layout.d.ts +0 -0
  144. package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/team/[userId]/index.d.ts +0 -0
  145. package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/team/index.d.ts +0 -0
  146. package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/team/layout.d.ts +0 -0
  147. package/pkg/test/@fixtures/app/@src/pages/projects/index.d.ts +0 -0
  148. package/pkg/test/@fixtures/app/@src/pages/projects/layout.d.ts +0 -0
  149. package/pkg/test/@fixtures/app/@src/pages/properties/[[city]]/filters/[...filters]/index.d.ts +0 -0
  150. package/pkg/test/@fixtures/app/@src/pages/properties/filters/index.d.ts +0 -0
  151. package/pkg/test/@fixtures/app/@src/pages/properties/layout.d.ts +0 -0
  152. package/pkg/test/@fixtures/app/@src/pages/search/[[query]]/[[page]]/index.d.ts +0 -0
  153. package/pkg/test/@fixtures/app/@src/pages/search/[[query]]/layout.d.ts +0 -0
  154. package/pkg/test/@fixtures/app/@src/pages/search/index.d.ts +0 -0
  155. package/pkg/test/@fixtures/app/@src/pages/shop/[category]/[productId]/index.d.ts +0 -0
  156. package/pkg/test/@fixtures/app/@src/pages/shop/[category]/[productId]/layout.d.ts +0 -0
  157. package/pkg/test/@fixtures/app/@src/pages/shop/cart/index.d.ts +0 -0
  158. package/pkg/test/@fixtures/app/@src/pages/shop/checkout/confirm/index.d.ts +0 -0
  159. package/pkg/test/@fixtures/app/@src/pages/shop/checkout/layout.d.ts +0 -0
  160. package/pkg/test/@fixtures/app/@src/pages/shop/checkout/payment/index.d.ts +0 -0
  161. package/pkg/test/@fixtures/app/@src/pages/shop/checkout/shipping/index.d.ts +0 -0
  162. package/pkg/test/@fixtures/app/@src/pages/shop/checkout/shipping/layout.d.ts +0 -0
  163. package/pkg/test/@fixtures/app/@src/pages/shop/index.d.ts +0 -0
  164. package/pkg/test/@fixtures/app/@src/pages/shop/layout.d.ts +0 -0
  165. package/pkg/test/@fixtures/app/@src/pages/shop/orders/[orderId]/index.d.ts +0 -0
  166. package/pkg/test/@fixtures/app/@src/pages/shop/orders/index.d.ts +0 -0
  167. package/pkg/test/@fixtures/app/@src/pages/shop/orders/layout.d.ts +0 -0
  168. package/pkg/test/@fixtures/app/@src/pages/shop/product/[id]/index.d.ts +0 -0
  169. package/pkg/test/@fixtures/app/@src/pages/shop/product/[id]/layout.d.ts +0 -0
  170. package/pkg/test/@fixtures/app/@src/pages/shop/product/[id]/reviews/index.d.ts +0 -0
  171. package/pkg/test/@fixtures/app/@src/pages/shop/products/[[category]]/index.d.ts +0 -0
  172. package/pkg/test/@fixtures/app/@src/pages/shop/products/index.d.ts +0 -0
  173. package/pkg/test/@fixtures/app/@src/pages/shop/products/layout.d.ts +0 -0
  174. package/pkg/test/@fixtures/app/@src/pages/signup/index.d.ts +0 -0
  175. package/pkg/test/@fixtures/app/@src/pages/store/[category]/filters/[...filters]/index.d.ts +0 -0
  176. package/pkg/test/@fixtures/app/@src/pages/store/[category]/sort/[sortBy]/index.d.ts +0 -0
  177. package/pkg/test/@fixtures/app/@src/pages/store/[category]/sort/layout.d.ts +0 -0
  178. package/pkg/test/@fixtures/app/@src/pages/store/layout.d.ts +0 -0
  179. package/pkg/test/@fixtures/app/@src/pages/users/[username]/followers/index.d.ts +0 -0
  180. package/pkg/test/@fixtures/app/@src/pages/users/[username]/following/index.d.ts +0 -0
  181. package/pkg/test/@fixtures/app/@src/pages/users/[username]/index.d.ts +0 -0
  182. package/pkg/test/@fixtures/app/@src/pages/users/[username]/layout.d.ts +0 -0
  183. package/pkg/test/@fixtures/app/@src/pages/users/[username]/posts/[postId]/index.d.ts +0 -0
  184. package/pkg/test/@fixtures/app/@src/pages/users/[username]/posts/[postId]/layout.d.ts +0 -0
  185. package/pkg/test/@fixtures/app/@src/pages/users/[username]/posts/index.d.ts +0 -0
  186. package/pkg/test/@fixtures/app/@src/pages/users/[username]/posts/layout.d.ts +0 -0
  187. package/pkg/test/@fixtures/app/@src/pages/users/index.d.ts +0 -0
  188. package/pkg/test/@fixtures/app/@src/pages/users/layout.d.ts +0 -0
  189. package/pkg/test/@fixtures/app/@src/pages/workspace/[workspaceId]/analytics/[range]/index.d.ts +0 -0
  190. package/pkg/test/@fixtures/app/@src/pages/workspace/[workspaceId]/analytics/[range]/layout.d.ts +0 -0
  191. package/pkg/test/@fixtures/app/@src/pages/workspace/[workspaceId]/analytics/index.d.ts +0 -0
  192. package/pkg/test/@fixtures/app/@src/pages/workspace/[workspaceId]/analytics/layout.d.ts +0 -0
  193. package/pkg/test/@fixtures/app/@src/pages/workspace/[workspaceId]/team/[memberId]/permissions/[...permissionPath]/index.d.ts +0 -0
  194. package/pkg/test/@fixtures/app/@src/pages/workspace/[workspaceId]/team/layout.d.ts +0 -0
  195. package/pkg/test/@fixtures/app/lib/@src/{api}/articles/[...path]/index.ts/types.d.ts +0 -3
  196. package/pkg/test/@fixtures/app/lib/@src/{api}/articles/[...path]/types.d.ts +0 -3
  197. package/pkg/test/@fixtures/app/lib/@src/{api}/books/[category]/[[author]]/index.ts/types.d.ts +0 -4
  198. package/pkg/test/@fixtures/app/lib/@src/{api}/books/[category]/[[author]]/types.d.ts +0 -4
  199. package/pkg/test/@fixtures/app/lib/@src/{api}/books/[category]/index.ts/types.d.ts +0 -3
  200. package/pkg/test/@fixtures/app/lib/@src/{api}/books/[category]/types.d.ts +0 -3
  201. package/pkg/test/@fixtures/app/lib/@src/{api}/books/index.ts/types.d.ts +0 -1
  202. package/pkg/test/@fixtures/app/lib/@src/{api}/books/types.d.ts +0 -1
  203. package/pkg/test/@fixtures/app/lib/@src/{api}/files/[[folder]]/[[id]].json/index.ts/types.d.ts +0 -4
  204. package/pkg/test/@fixtures/app/lib/@src/{api}/files/[[folder]]/[[id]].json/types.d.ts +0 -4
  205. package/pkg/test/@fixtures/app/lib/@src/{api}/files/[[folder]]/index.ts/types.d.ts +0 -3
  206. package/pkg/test/@fixtures/app/lib/@src/{api}/files/[[folder]]/types.d.ts +0 -3
  207. package/pkg/test/@fixtures/app/lib/@src/{api}/index/index.ts/types.d.ts +0 -1
  208. package/pkg/test/@fixtures/app/lib/@src/{api}/index/types.d.ts +0 -1
  209. package/pkg/test/@fixtures/app/lib/@src/{api}/pages/[...path].html/index.ts/types.d.ts +0 -3
  210. package/pkg/test/@fixtures/app/lib/@src/{api}/pages/[...path].html/types.d.ts +0 -3
  211. package/pkg/test/@fixtures/app/lib/@src/{api}/users/[id].json/index.ts/types.d.ts +0 -3
  212. package/pkg/test/@fixtures/app/lib/@src/{api}/users/[id].json/types.d.ts +0 -3
  213. package/pkg/test/@fixtures/ast/extractTypeDeclarations/exports/with-referenced-files.d.ts +0 -1
  214. package/pkg/test/@fixtures/ast/extractTypeDeclarations/imports/with-referenced-files.d.ts +0 -1
  215. package/pkg/test/ast/extractParamsRefinements.test.d.ts +0 -1
  216. package/pkg/test/ast/extractRouteMethods.test.d.ts +0 -1
  217. package/pkg/test/ast/extractTypeDeclarations.test.d.ts +0 -1
  218. package/pkg/test/cli/create.test.d.ts +0 -1
  219. package/pkg/test/routes/base.d.ts +0 -4
  220. package/pkg/test/routes/nesting.test.d.ts +0 -1
  221. package/pkg/test/routes/resolver.test.d.ts +0 -1
  222. package/pkg/test/setup.d.ts +0 -1
  223. /package/pkg/{src/alias-plugin → alias-plugin}/index.d.ts +0 -0
  224. /package/pkg/{src/base-plugin → base-plugin}/spinner.d.ts +0 -0
  225. /package/pkg/{src/define-plugin → define-plugin}/index.d.ts +0 -0
@@ -1,38 +1,121 @@
1
1
  // src/base-plugin/worker.ts
2
2
  import { parentPort, workerData } from "node:worker_threads";
3
3
  import chokidar from "chokidar";
4
- import crc4 from "crc/crc32";
5
- import {
6
- pathResolver as pathResolver3
7
- } from "@kosmojs/devlib";
4
+ import crc6 from "crc/crc32";
8
5
 
9
- // src/base-plugin/routes.ts
10
- import {
11
- defaults as defaults2
12
- } from "@kosmojs/devlib";
6
+ // src/paths.ts
7
+ import { join } from "node:path";
13
8
 
14
- // src/base-plugin/routes/resolve.ts
15
- import { dirname as dirname2, join, resolve as resolve3 } from "node:path";
16
- import crc3 from "crc/crc32";
9
+ // src/defaults.ts
10
+ var defaults = {
11
+ appPrefix: "~",
12
+ srcPrefix: "@",
13
+ libPrefix: "_",
14
+ coreDir: "core",
15
+ srcDir: "src",
16
+ libDir: "lib",
17
+ configDir: "config",
18
+ apiDir: "api",
19
+ pagesDir: "pages",
20
+ entryDir: "entry",
21
+ fetchDir: "fetch"
22
+ };
23
+
24
+ // src/paths.ts
25
+ var pathResolver = ({
26
+ appRoot: appRoot2,
27
+ sourceFolder: sourceFolder2
28
+ }) => {
29
+ const createPath2 = (...a) => {
30
+ return appRoot2 ? join(appRoot2, ...a) : join(...a);
31
+ };
32
+ const createImport = {
33
+ coreApi(...a) {
34
+ return join(defaults.appPrefix, defaults.coreDir, defaults.apiDir, ...a);
35
+ },
36
+ src(...a) {
37
+ return join(defaults.srcPrefix, sourceFolder2, ...a);
38
+ },
39
+ config(...a) {
40
+ return this.src(defaults.configDir, ...a);
41
+ },
42
+ api(...a) {
43
+ return this.src(defaults.apiDir, ...a);
44
+ },
45
+ pages(...a) {
46
+ return this.src(defaults.pagesDir, ...a);
47
+ },
48
+ lib(...a) {
49
+ return join(defaults.libPrefix, sourceFolder2, ...a);
50
+ },
51
+ libApi(...a) {
52
+ return this.lib(defaults.apiDir, ...a);
53
+ },
54
+ libEntry(...a) {
55
+ return this.lib(defaults.entryDir, ...a);
56
+ }
57
+ };
58
+ return {
59
+ createPath: {
60
+ coreApi(...a) {
61
+ return createPath2(defaults.coreDir, defaults.apiDir, ...a);
62
+ },
63
+ src(...a) {
64
+ return createPath2(defaults.srcDir, sourceFolder2, ...a);
65
+ },
66
+ api(...a) {
67
+ return this.src(defaults.apiDir, ...a);
68
+ },
69
+ pages(...a) {
70
+ return this.src(defaults.pagesDir, ...a);
71
+ },
72
+ config(...a) {
73
+ return this.src(defaults.configDir, ...a);
74
+ },
75
+ entry(...a) {
76
+ return this.src(defaults.entryDir, ...a);
77
+ },
78
+ lib(...a) {
79
+ return createPath2(defaults.libDir, defaults.srcDir, sourceFolder2, ...a);
80
+ },
81
+ libApi(...a) {
82
+ return this.lib(defaults.apiDir, ...a);
83
+ },
84
+ libEntry(...a) {
85
+ return this.lib(defaults.entryDir, ...a);
86
+ },
87
+ libPages(...a) {
88
+ return this.lib(defaults.pagesDir, ...a);
89
+ }
90
+ },
91
+ createImport,
92
+ createImportHelper: (key, ...a) => {
93
+ return createImport[key](...a.slice(0, -1));
94
+ }
95
+ };
96
+ };
97
+
98
+ // src/routes-factory/resolve.ts
99
+ import { dirname as dirname3, join as join3, resolve as resolve3 } from "node:path";
100
+ import { styleText as styleText2 } from "node:util";
101
+ import crc5 from "crc/crc32";
102
+ import mimeTypes from "mime-types";
17
103
  import picomatch from "picomatch";
18
104
  import { glob } from "tinyglobby";
19
- import {
20
- defaults,
21
- pathResolver as pathResolver2,
22
- pathTokensFactory,
23
- render,
24
- renderToFile
25
- } from "@kosmojs/devlib";
26
105
 
27
- // src/base-plugin/ast.ts
106
+ // src/ast.ts
28
107
  import { resolve } from "node:path";
108
+ import { styleText } from "node:util";
29
109
  import crc from "crc/crc32";
30
110
  import { flattener } from "tfusion";
31
111
  import {
32
112
  Project,
33
113
  SyntaxKind
34
114
  } from "ts-morph";
35
- import { HTTPMethods } from "@kosmojs/api";
115
+ import {
116
+ HTTPMethods,
117
+ RequestValidationTargets
118
+ } from "@kosmojs/api";
36
119
  var createProject = (opts) => new Project(opts);
37
120
  var resolveRouteSignature = async (route, opts) => {
38
121
  const {
@@ -44,19 +127,12 @@ var resolveRouteSignature = async (route, opts) => {
44
127
  );
45
128
  const defaultExport = extractDefaultExport(sourceFile);
46
129
  const paramsRefinements = defaultExport ? extractParamsRefinements(defaultExport) : void 0;
47
- const methods = defaultExport ? extractRouteMethods(defaultExport, route) : [];
48
- const payloadTypes = methods.flatMap((e) => {
49
- return e.payloadType ? [e.payloadType] : [];
50
- });
51
- const responseTypes = methods.flatMap((e) => {
52
- return e.responseType ? [e.responseType] : [];
53
- });
130
+ const methods = defaultExport ? extractRouteMethods(route, defaultExport) : [];
54
131
  return {
55
132
  typeDeclarations,
56
133
  paramsRefinements,
57
134
  methods: methods.map((e) => e.method),
58
- payloadTypes,
59
- responseTypes,
135
+ validationDefinitions: methods.flatMap((e) => e.validationDefinitions),
60
136
  referencedFiles
61
137
  };
62
138
  };
@@ -71,22 +147,23 @@ var extractDefaultExport = (sourceFile) => {
71
147
  return defaultExport;
72
148
  };
73
149
  var extractParamsRefinements = (callExpression) => {
74
- const [firstGeneric] = extractGenerics(callExpression);
75
- if (!firstGeneric?.node.isKind(SyntaxKind.TupleType)) {
150
+ const [
151
+ _routeName,
152
+ // first generic - the route name
153
+ paramsGeneric
154
+ // second generic - params refinements
155
+ ] = extractGenerics(callExpression);
156
+ if (!paramsGeneric?.isKind(SyntaxKind.TupleType)) {
76
157
  return;
77
158
  }
78
- const tupleElements = firstGeneric.node.getElements();
79
- if (!tupleElements?.length) {
80
- return;
81
- }
82
- return tupleElements.map((node, index) => {
159
+ return paramsGeneric.getElements().map((node, index) => {
83
160
  return {
84
161
  index,
85
162
  text: node.getText()
86
163
  };
87
164
  });
88
165
  };
89
- var extractRouteMethods = (callExpression, route) => {
166
+ var extractRouteMethods = (route, callExpression) => {
90
167
  const funcDeclaration = callExpression.getFirstChildByKind(SyntaxKind.ArrowFunction) || callExpression.getFirstChildByKind(SyntaxKind.FunctionExpression);
91
168
  if (!funcDeclaration) {
92
169
  return [];
@@ -107,35 +184,173 @@ var extractRouteMethods = (callExpression, route) => {
107
184
  }
108
185
  }
109
186
  const methods = [];
110
- const skipValidationFilter = (e) => /@skip-validation/.test(e);
111
187
  for (const [callExpression2, method] of callExpressions) {
112
- const [payloadGeneric, responseGeneric] = extractGenerics(callExpression2);
113
- const payloadText = payloadGeneric?.node ? payloadGeneric.node.getChildren().length === 0 ? "{}" : payloadGeneric.node.getFullText() : void 0;
114
- const responseText = responseGeneric?.node.getText();
115
- const responseType = responseText ? {
116
- id: ["ResponseT", crc(route.importName + method)].join(""),
117
- method,
118
- skipValidation: responseGeneric?.comments ? responseGeneric.comments.some(skipValidationFilter) : false,
119
- text: ["never", "object"].includes(responseText) ? "{}" : responseText,
120
- resolvedType: void 0
121
- } : void 0;
122
- const payloadType = payloadText ? {
123
- id: ["PayloadT", crc(route.importName + method)].join(""),
124
- responseTypeId: responseType?.id,
125
- method,
126
- skipValidation: payloadGeneric?.comments ? payloadGeneric.comments.some(skipValidationFilter) : false,
127
- isOptional: payloadText ? payloadText === "{}" || route.optionalParams : true,
128
- text: payloadText,
129
- resolvedType: void 0
130
- } : void 0;
188
+ const [vDefs, vOpts] = extractGenerics(callExpression2);
131
189
  methods.push({
132
190
  method,
133
- payloadType,
134
- responseType
191
+ validationDefinitions: extractValidationDefinitions(
192
+ route,
193
+ method,
194
+ vDefs,
195
+ vOpts
196
+ )
135
197
  });
136
198
  }
137
199
  return methods;
138
200
  };
201
+ var parseRuntimeValidation = (typeNode) => {
202
+ if (typeNode.isKind(SyntaxKind.LiteralType)) {
203
+ const literal = typeNode.getFirstChild();
204
+ if (literal?.isKind(SyntaxKind.TrueKeyword)) {
205
+ return true;
206
+ } else if (literal?.isKind(SyntaxKind.FalseKeyword)) {
207
+ return false;
208
+ }
209
+ }
210
+ return void 0;
211
+ };
212
+ var extractResponseVariant = (typeNode) => {
213
+ if (!typeNode.isKind(SyntaxKind.TupleType)) {
214
+ return;
215
+ }
216
+ let status = 200;
217
+ let contentType;
218
+ let body;
219
+ const [statusNode, contentTypeNode, bodyNode] = typeNode.getElements();
220
+ if (statusNode?.isKind(SyntaxKind.LiteralType)) {
221
+ const literal = statusNode.getFirstChildByKind(SyntaxKind.NumericLiteral);
222
+ if (literal) {
223
+ status = Number(literal.getText());
224
+ }
225
+ }
226
+ if (contentTypeNode) {
227
+ contentType = extractStringLiteral(contentTypeNode);
228
+ }
229
+ if (bodyNode) {
230
+ body = bodyNode.getText();
231
+ if (["object"].includes(body)) {
232
+ body = "{}";
233
+ }
234
+ }
235
+ return { status, contentType, body };
236
+ };
237
+ var parseValidationOptions = (typeNode) => {
238
+ const opts = {};
239
+ if (!typeNode?.isKind(SyntaxKind.TypeLiteral)) {
240
+ return opts;
241
+ }
242
+ for (const prop of typeNode.getMembers()) {
243
+ if (!prop.isKind(SyntaxKind.PropertySignature)) {
244
+ continue;
245
+ }
246
+ const target = prop.getName();
247
+ const typeNode2 = prop.getTypeNodeOrThrow();
248
+ if (!typeNode2.isKind(SyntaxKind.TypeLiteral)) {
249
+ continue;
250
+ }
251
+ let contentType;
252
+ let runtimeValidation;
253
+ const customErrors = {};
254
+ for (const member of typeNode2.getMembers()) {
255
+ if (!member.isKind(SyntaxKind.PropertySignature)) {
256
+ continue;
257
+ }
258
+ const nameNode = member.getNameNode();
259
+ const valueNode = member.getTypeNodeOrThrow();
260
+ const name = nameNode.isKind(SyntaxKind.StringLiteral) ? nameNode.getLiteralText() : nameNode.getText();
261
+ if (name === "contentType") {
262
+ contentType = extractStringLiteral(valueNode);
263
+ } else if (name === "runtimeValidation") {
264
+ runtimeValidation = parseRuntimeValidation(valueNode);
265
+ } else if (name.startsWith("error")) {
266
+ const literal = extractStringLiteral(valueNode);
267
+ if (literal) {
268
+ customErrors[name] = literal;
269
+ }
270
+ }
271
+ }
272
+ opts[target] = {
273
+ contentType,
274
+ runtimeValidation,
275
+ customErrors
276
+ };
277
+ }
278
+ return opts;
279
+ };
280
+ var extractStringLiteral = (typeNode) => {
281
+ const literal = typeNode.isKind(SyntaxKind.LiteralType) ? typeNode.getFirstChildByKind(SyntaxKind.StringLiteral) : void 0;
282
+ return literal ? literal.getLiteralText() : void 0;
283
+ };
284
+ var extractValidationDefinitions = (route, method, defsNode, optsNode) => {
285
+ const definitions = [];
286
+ if (!defsNode?.isKind(SyntaxKind.TypeLiteral)) {
287
+ return definitions;
288
+ }
289
+ const optsMap = parseValidationOptions(optsNode);
290
+ const createId = (target, hash) => {
291
+ return [
292
+ target.replace(/^./, (c) => c.toUpperCase()),
293
+ "T",
294
+ method,
295
+ crc(route.id + hash)
296
+ ].join("");
297
+ };
298
+ for (const prop of defsNode.getMembers()) {
299
+ if (!prop.isKind(SyntaxKind.PropertySignature)) {
300
+ continue;
301
+ }
302
+ const target = prop.getName();
303
+ const typeNode = prop.getTypeNodeOrThrow();
304
+ if (target === "response") {
305
+ const variants = typeNode.isKind(SyntaxKind.UnionType) ? typeNode.getChildrenOfKind(SyntaxKind.TupleType) : [typeNode];
306
+ definitions.push({
307
+ ...optsMap[target],
308
+ method,
309
+ target,
310
+ variants: variants.flatMap((e, i) => {
311
+ const { status, contentType, body } = extractResponseVariant(e) || {};
312
+ if (!status) {
313
+ return [];
314
+ }
315
+ if (contentType && typeof contentType !== "string") {
316
+ console.warn(
317
+ styleText(
318
+ ["bold", "red"],
319
+ `\u2717 The second element of a response variant should specify the Response Content Type`
320
+ )
321
+ );
322
+ console.warn(
323
+ styleText(["blue"], ` Example: [200, "json", Schema]`)
324
+ );
325
+ console.warn(
326
+ ` Route: ${route.name}; Method: ${method}; Response Variant: #${i}`
327
+ );
328
+ console.warn();
329
+ }
330
+ return [
331
+ {
332
+ id: createId(target, JSON.stringify([status, contentType, body])),
333
+ status,
334
+ contentType,
335
+ body
336
+ }
337
+ ];
338
+ })
339
+ });
340
+ } else if (Object.keys(RequestValidationTargets).includes(target)) {
341
+ definitions.push({
342
+ ...optsMap[target],
343
+ method,
344
+ target,
345
+ schema: {
346
+ id: createId(target),
347
+ text: typeNode.getText()
348
+ }
349
+ });
350
+ }
351
+ }
352
+ return definitions;
353
+ };
139
354
  var extractTypeDeclarations = (sourceFile, opts) => {
140
355
  const declarations = [];
141
356
  const referencedFiles = opts?.withReferencedFiles ? [] : void 0;
@@ -240,12 +455,7 @@ var getReferencedFiles = (importIdentifier) => {
240
455
  });
241
456
  };
242
457
  var extractGenerics = (callExpression) => {
243
- return callExpression.getTypeArguments().map((node) => {
244
- return {
245
- node,
246
- comments: node.getLeadingCommentRanges().map((range) => range.getText().trim())
247
- };
248
- });
458
+ return callExpression.getTypeArguments();
249
459
  };
250
460
  var typeResolverFactory = ({ appRoot: appRoot2 }) => {
251
461
  const project = createProject({
@@ -279,12 +489,24 @@ var typeResolverFactory = ({ appRoot: appRoot2 }) => {
279
489
  };
280
490
  };
281
491
 
282
- // src/base-plugin/cache.ts
492
+ // src/cache.ts
283
493
  import { mkdir, readFile, writeFile } from "node:fs/promises";
284
494
  import { dirname, resolve as resolve2 } from "node:path";
285
495
  import crc2 from "crc/crc32";
286
496
  import self from "@kosmojs/dev/package.json" with { type: "json" };
287
- import { pathExists, pathResolver } from "@kosmojs/devlib";
497
+
498
+ // src/fs.ts
499
+ import { access, constants } from "node:fs/promises";
500
+ var pathExists = async (path) => {
501
+ try {
502
+ await access(path, constants.F_OK);
503
+ return true;
504
+ } catch {
505
+ return false;
506
+ }
507
+ };
508
+
509
+ // src/cache.ts
288
510
  var cacheFactory = (route, {
289
511
  appRoot: appRoot2,
290
512
  sourceFolder: sourceFolder2,
@@ -293,7 +515,7 @@ var cacheFactory = (route, {
293
515
  const cacheFile = pathResolver({
294
516
  appRoot: appRoot2,
295
517
  sourceFolder: sourceFolder2
296
- }).resolve("apiLibDir", dirname(route.file), "cache.json");
518
+ }).createPath.libApi(dirname(route.file), "cache.json");
297
519
  const getCache = async (opt) => {
298
520
  if (await pathExists(cacheFile)) {
299
521
  try {
@@ -368,13 +590,169 @@ var identicalHashSum = (a, b) => {
368
590
  return a === b;
369
591
  };
370
592
 
371
- // src/base-plugin/templates/resolved-types.hbs
593
+ // src/render.ts
594
+ import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
595
+ import { dirname as dirname2, join as join2 } from "node:path";
596
+ import crc3 from "crc/crc32";
597
+ import handlebars from "handlebars";
598
+ var render = (template, context, options) => {
599
+ const { noEscape = true, renderer = handlebars } = { ...options };
600
+ return renderer.compile(template, { noEscape })(context);
601
+ };
602
+ var renderToFile = async (file, template, context, options) => {
603
+ const content = render(template, context, options);
604
+ if (await pathExists(file)) {
605
+ const { overwrite = true } = { ...options };
606
+ if (overwrite === false) {
607
+ return;
608
+ }
609
+ const fileContent = await readFile2(file, "utf8");
610
+ if (typeof overwrite === "function" && !overwrite(fileContent)) {
611
+ return;
612
+ }
613
+ if (crc3(content) === crc3(fileContent)) {
614
+ return;
615
+ }
616
+ }
617
+ await mkdir2(dirname2(file), { recursive: true });
618
+ await writeFile2(file, content, "utf8");
619
+ };
620
+
621
+ // src/routes-factory/base.ts
622
+ import crc4 from "crc/crc32";
623
+ import { parse } from "path-to-regexp";
624
+ var pathTokensFactory = (path, {
625
+ transformStaticValue = normalizeStaticValue
626
+ } = {}) => {
627
+ const extractParts = (tokens2, createConst, insideGroup = false) => {
628
+ const parts = [];
629
+ for (const token of tokens2) {
630
+ switch (token.type) {
631
+ case "text":
632
+ if (token.value !== "/") {
633
+ parts.push({
634
+ type: "static",
635
+ value: transformStaticValue(token.value)
636
+ });
637
+ }
638
+ break;
639
+ case "param":
640
+ parts.push({
641
+ type: "param",
642
+ kind: insideGroup ? "optional" : "required",
643
+ name: token.name,
644
+ const: createConst(token.name)
645
+ });
646
+ break;
647
+ case "wildcard":
648
+ parts.push({
649
+ type: "param",
650
+ kind: "splat",
651
+ name: token.name,
652
+ const: createConst(token.name)
653
+ });
654
+ break;
655
+ case "group":
656
+ parts.push(...extractParts(token.tokens, createConst, true));
657
+ break;
658
+ }
659
+ }
660
+ return parts;
661
+ };
662
+ const patternTransforms = [
663
+ // Transform required params: [id] => :id
664
+ // Only pure \w param names,
665
+ // [some-id] used as is, not treated as param,
666
+ // use [some_id] instead.
667
+ (s) => s.replace(/\[(\w+)\]/g, ":$1"),
668
+ // Transform optional params: {id} => {:id}
669
+ // Only pure \w param names,
670
+ // anything else treated as a path-to-regexp pattern and used as is.
671
+ // {some-id} treated as an optional static segment.
672
+ // use {some_id} for simple param syntax
673
+ // or {:some-id} pattern where :some is the param name and -id is a static segment.
674
+ (s) => s.replace(/\{(\w+)\}/g, "{:$1}"),
675
+ // Transform splat params: {...param} => {*param}
676
+ (s) => s.replace(/\{\.\.\./g, "{*"),
677
+ // Insert leading slash inside optional/splat groups.
678
+ // {:name} => {/:name}
679
+ // {*name} => {/*name}
680
+ (s) => {
681
+ return s.startsWith("{") ? s.replace(/^\{/, "{/") : s;
682
+ }
683
+ ];
684
+ const detectBareParams = (s) => {
685
+ let depth = 0;
686
+ for (const [i, ch] of [...s].entries()) {
687
+ if (ch === "{") {
688
+ depth += 1;
689
+ } else if (ch === "}") {
690
+ depth -= 1;
691
+ } else if (ch === ":" && depth === 0) {
692
+ const match = s.slice(i + 1).match(/^\w+/);
693
+ return match?.[0] || ":";
694
+ }
695
+ }
696
+ return;
697
+ };
698
+ const tokens = path.replace(/^index\/?/, "").split("/").flatMap((orig) => {
699
+ if (!orig.length) {
700
+ return [];
701
+ }
702
+ const bareParam = detectBareParams(orig);
703
+ if (bareParam === ":") {
704
+ throw new Error(
705
+ `${path} contains colons outside braces, use : only within {}`
706
+ );
707
+ } else if (bareParam) {
708
+ throw new Error(
709
+ `${path} contains bare params, use [${bareParam}] instead of :${bareParam}`
710
+ );
711
+ }
712
+ const pattern = patternTransforms.reduce((src, fn) => fn(src), orig);
713
+ const { tokens: tokens2 } = parse(pattern);
714
+ const parts = extractParts(tokens2, (val) => {
715
+ return /\W/.test(val) || /^\d/.test(val) ? [val.replace(/^\d+|\W/g, "_"), crc4(orig)].join("_") : val;
716
+ });
717
+ const isStatic = parts.length === 1 ? parts[0].type === "static" : false;
718
+ const isParam = parts.length === 1 ? parts[0].type === "param" : false;
719
+ const kind = isStatic ? "static" : isParam ? "param" : "mixed";
720
+ return [
721
+ {
722
+ kind,
723
+ orig,
724
+ pattern,
725
+ parts
726
+ }
727
+ ];
728
+ });
729
+ return [
730
+ tokens,
731
+ tokens.map(({ pattern }, i) => {
732
+ const next = tokens[i + 1];
733
+ if (!next || next.pattern.includes("/")) {
734
+ return pattern;
735
+ }
736
+ const slashRequired = tokens.slice(i + 1).some((e) => {
737
+ return e.parts.some((e2) => {
738
+ return e2.type === "static" || e2.kind === "required";
739
+ });
740
+ });
741
+ return slashRequired ? `${pattern}/` : pattern;
742
+ }).join("")
743
+ ];
744
+ };
745
+ var normalizeStaticValue = (value) => {
746
+ return value.replace(/\+/g, "\\\\+");
747
+ };
748
+
749
+ // src/routes-factory/templates/resolved-types.hbs
372
750
  var resolved_types_default = "{{#each resolvedTypes}}\nexport type {{name}} = {{text}};\n{{/each}}\n";
373
751
 
374
- // src/base-plugin/templates/types.hbs
375
- var types_default = '{{#each typeDeclarations}}{{text}}\n{{/each}}\n\nexport type {{params.id}} = {\n {{#each paramsSchema}}\n "{{name}}"{{#unless isRequired}}?{{/unless}}:{{#if isRest}} Array<{{/if}}\n {{#if refinement}}{{refinement.text}}{{else}}string{{/if}}\n {{#if isRest}}>{{/if}}\n {{/each}}\n};\n\n{{#each payloadTypes}}\nexport type {{id}} = {{text}};\n{{/each}}\n\n{{#each responseTypes}}\nexport type {{id}} = {{text}};\n{{/each}}\n';
752
+ // src/routes-factory/templates/types.hbs
753
+ var types_default = '{{#each typeDeclarations}}{{text}}\n{{/each}}\n\nexport type {{params.id}} = {\n {{#each paramsSchema}}\n "{{name}}"{{#unless isRequired}}?{{/unless}}: {{#if refinement}}\n {{refinement.text}},\n {{else}}\n {{#if isSplat}}Array<string>{{else}}string{{/if}},\n {{/if}}\n {{/each}}\n};\n\n{{#each validationTypes}}export type {{id}} = {{text}};\n{{/each}}\n';
376
754
 
377
- // src/base-plugin/routes/resolve.ts
755
+ // src/routes-factory/resolve.ts
378
756
  var API_INDEX_BASENAME = "index";
379
757
  var API_INDEX_PATTERN = `${API_INDEX_BASENAME}.ts`;
380
758
  var API_USE_BASENAME = "use";
@@ -397,8 +775,9 @@ var scanRoutes = async ({
397
775
  appRoot: appRoot2,
398
776
  sourceFolder: sourceFolder2
399
777
  }) => {
778
+ const { createPath: createPath2 } = pathResolver({ appRoot: appRoot2, sourceFolder: sourceFolder2 });
400
779
  return glob(ROUTE_FILE_PATTERNS, {
401
- cwd: resolve3(appRoot2, sourceFolder2),
780
+ cwd: createPath2.src(),
402
781
  absolute: true,
403
782
  onlyFiles: true,
404
783
  followSymbolicLinks: false,
@@ -415,11 +794,11 @@ var isRouteFile = (file, {
415
794
  appRoot: appRoot2,
416
795
  sourceFolder: sourceFolder2
417
796
  }) => {
418
- const [_sourceFolder, folder, ...rest] = resolve3(appRoot2, file).replace(`${appRoot2}/`, "").split("/");
797
+ const [_sourceFolder, folder, ...rest] = resolve3(appRoot2, file).replace(`${appRoot2}/${defaults.srcDir}/`, "").split("/");
419
798
  if (!folder || _sourceFolder !== sourceFolder2 || rest.length < 2) {
420
- return;
799
+ return false;
421
800
  }
422
- return picomatch.isMatch(join(folder, ...rest), ROUTE_FILE_PATTERNS) ? [folder, rest.join("/")] : void 0;
801
+ return picomatch.isMatch(join3(folder, ...rest), ROUTE_FILE_PATTERNS) ? [folder, rest.join("/")] : false;
423
802
  };
424
803
  var isApiRoute = (file) => {
425
804
  return picomatch.matchBase(file, `**/${API_INDEX_PATTERN}`);
@@ -433,29 +812,27 @@ var isPageRoute = (file) => {
433
812
  var isPageLayout = (file) => {
434
813
  return picomatch.matchBase(file, `**/${PAGE_LAYOUT_PATTERN}`);
435
814
  };
436
- var createRouteEntry = (_file, {
815
+ var createRouteEntry = (fileFullpath, {
437
816
  appRoot: appRoot2,
438
817
  sourceFolder: sourceFolder2
439
818
  }) => {
440
- const resolvedPaths = isRouteFile(_file, { appRoot: appRoot2, sourceFolder: sourceFolder2 });
819
+ const resolvedPaths = isRouteFile(fileFullpath, { appRoot: appRoot2, sourceFolder: sourceFolder2 });
441
820
  if (!resolvedPaths) {
442
821
  return;
443
822
  }
444
823
  const [folder, file] = resolvedPaths;
445
- const fileFullpath = join(appRoot2, sourceFolder2, folder, file);
446
- const pathTokens = pathTokensFactory(dirname2(file));
447
- const name = pathTokens.map((e) => e.orig).join("/");
448
- const importFile = file;
449
- const importName = `${importFile.replace(/\W+/g, "_")}_${crc3(importFile)}`;
450
- return {
451
- name,
452
- folder,
453
- file,
454
- fileFullpath,
455
- pathTokens,
456
- importFile,
457
- importName
458
- };
824
+ const id = `${file.replace(/\W+/g, "_")}_${crc5(file)}`;
825
+ const name = dirname3(file);
826
+ try {
827
+ const [pathTokens, pathPattern] = pathTokensFactory(dirname3(file));
828
+ return { id, name, folder, file, fileFullpath, pathTokens, pathPattern };
829
+ } catch (error) {
830
+ console.error(
831
+ `\u2757${styleText2("red", "ERROR")}: Failed parsing path for "${styleText2("cyan", file)}"`
832
+ );
833
+ console.error(error);
834
+ return;
835
+ }
459
836
  };
460
837
  var pageLayoutResolverFactory = () => {
461
838
  return (entry) => {
@@ -471,27 +848,21 @@ var pageLayoutResolverFactory = () => {
471
848
  };
472
849
  var pageRouteResolverFactory = () => {
473
850
  return (entry) => {
474
- const {
475
- name,
476
- folder,
477
- file,
478
- fileFullpath,
479
- pathTokens,
480
- importFile,
481
- importName
482
- } = entry;
851
+ const { id, name, folder, file, fileFullpath, pathTokens, pathPattern } = entry;
483
852
  const handler = async () => {
484
853
  const entry2 = {
854
+ id,
485
855
  name,
486
856
  pathTokens,
857
+ pathPattern,
487
858
  params: {
488
- schema: pathTokens.flatMap((e) => e.param ? [e.param] : [])
859
+ schema: pathTokens.flatMap((e) => {
860
+ return e.parts.filter((p) => p.type === "param");
861
+ })
489
862
  },
490
863
  folder,
491
864
  file,
492
- fileFullpath,
493
- importFile,
494
- importName
865
+ fileFullpath
495
866
  };
496
867
  return {
497
868
  kind: "pageRoute",
@@ -518,38 +889,35 @@ var apiRouteResolverFactory = (pluginOptions) => {
518
889
  appRoot: appRoot2,
519
890
  sourceFolder: sourceFolder2,
520
891
  generators: generators2 = [],
521
- formatters: formatters2 = [],
522
892
  refineTypeName
523
893
  } = pluginOptions;
524
- let resolveTypes = false;
525
- for (const { options } of generators2) {
526
- if (options?.resolveTypes) {
527
- resolveTypes = true;
528
- }
529
- }
894
+ const resolveTypes = generators2.some((e) => e.options?.resolveTypes);
530
895
  const {
531
896
  //
532
897
  literalTypesResolver,
533
898
  getSourceFile,
534
899
  refreshSourceFile
535
900
  } = typeResolverFactory(pluginOptions);
536
- return (entry) => {
537
- const {
538
- name,
539
- file,
540
- folder,
541
- fileFullpath,
542
- pathTokens,
543
- importFile,
544
- importName
545
- } = entry;
901
+ return ({
902
+ id,
903
+ name,
904
+ file,
905
+ folder,
906
+ fileFullpath,
907
+ pathTokens,
908
+ pathPattern
909
+ }) => {
546
910
  const handler = async (updatedFile) => {
547
- const paramsSchema = pathTokens.flatMap((e) => {
548
- return e.param ? [e.param] : [];
549
- });
550
- const optionalParams = paramsSchema.length ? !paramsSchema.some((e) => e.isRequired) : true;
911
+ const paramsSchema = pathTokens.flatMap(
912
+ (e) => {
913
+ return e.parts.flatMap((p) => {
914
+ return p.type === "param" ? [p] : [];
915
+ });
916
+ }
917
+ );
918
+ const optionalParams = paramsSchema.length ? paramsSchema.filter((e) => e.kind === "required").length === 0 : true;
551
919
  const { getCache, persistCache } = cacheFactory(
552
- { file, fileFullpath, importName },
920
+ { id, file, fileFullpath },
553
921
  {
554
922
  appRoot: appRoot2,
555
923
  sourceFolder: sourceFolder2,
@@ -565,19 +933,23 @@ var apiRouteResolverFactory = (pluginOptions) => {
565
933
  typeDeclarations,
566
934
  paramsRefinements,
567
935
  methods,
568
- payloadTypes,
569
- responseTypes,
936
+ validationDefinitions: validationDefinitions2,
570
937
  referencedFiles = []
571
938
  } = await resolveRouteSignature(
572
- { importName, fileFullpath, optionalParams },
939
+ { id, name, fileFullpath, optionalParams },
573
940
  {
574
941
  withReferencedFiles: true,
575
942
  sourceFile: getSourceFile(fileFullpath),
576
943
  relpathResolver(path) {
577
- return join(sourceFolder2, defaults.apiDir, dirname2(file), path);
944
+ return join3(sourceFolder2, defaults.apiDir, dirname3(file), path);
578
945
  }
579
946
  }
580
947
  );
948
+ const validationTypes = validationDefinitions2.flatMap((def) => {
949
+ return def.target === "response" ? def.variants.flatMap(({ id: id2, body }) => {
950
+ return body ? [{ id: id2, text: body }] : [];
951
+ }) : [def.schema];
952
+ });
581
953
  const numericParams = paramsRefinements ? paramsRefinements.flatMap(({ text, index }) => {
582
954
  if (text === "number") {
583
955
  const param = paramsSchema.at(index);
@@ -585,13 +957,12 @@ var apiRouteResolverFactory = (pluginOptions) => {
585
957
  }
586
958
  return [];
587
959
  }) : [];
588
- const typesFile = pathResolver2({ appRoot: appRoot2, sourceFolder: sourceFolder2 }).resolve(
589
- "apiLibDir",
590
- dirname2(file),
591
- "types.ts"
592
- );
960
+ const typesFile = pathResolver({
961
+ appRoot: appRoot2,
962
+ sourceFolder: sourceFolder2
963
+ }).createPath.libApi(dirname3(file), "types.ts");
593
964
  const params = {
594
- id: ["ParamsT", crc3(name)].join(""),
965
+ id: ["ParamsT", crc5(name)].join(""),
595
966
  schema: paramsSchema,
596
967
  resolvedType: void 0
597
968
  };
@@ -600,25 +971,21 @@ var apiRouteResolverFactory = (pluginOptions) => {
600
971
  paramsSchema: paramsSchema.map((param, index) => {
601
972
  return {
602
973
  ...param,
974
+ isRequired: param.kind === "required",
975
+ isSplat: param.kind === "splat",
603
976
  refinement: paramsRefinements?.at(index)
604
977
  };
605
978
  }),
606
979
  typeDeclarations,
607
- payloadTypes,
608
- responseTypes
980
+ validationTypes
609
981
  });
610
982
  const resolvedTypes = resolveTypes ? literalTypesResolver(typesFileContent, {
611
- overrides: [...payloadTypes, ...responseTypes].reduce(
612
- (map, { id, skipValidation }) => {
613
- if (skipValidation) {
614
- map[id] = "never";
615
- }
616
- return map;
617
- },
618
- { [refineTypeName]: refineTypeName }
619
- ),
620
- withProperties: [params.id, ...payloadTypes.map((e) => e.id)],
621
- formatters: formatters2
983
+ stripComments: true,
984
+ overrides: { [refineTypeName]: refineTypeName },
985
+ withProperties: [
986
+ params.id,
987
+ ...validationTypes.flatMap(({ id: id2 }) => id2)
988
+ ]
622
989
  }) : void 0;
623
990
  await renderToFile(
624
991
  typesFile,
@@ -631,37 +998,103 @@ var apiRouteResolverFactory = (pluginOptions) => {
631
998
  methods,
632
999
  typeDeclarations,
633
1000
  numericParams,
634
- // text was needed at writing types.ts file, dropping from cache
635
- payloadTypes: payloadTypes.map(({ text, ...rest }) => {
636
- return {
637
- ...rest,
638
- resolvedType: resolvedTypes?.find((e) => e.name === rest.id)
639
- };
640
- }),
641
- responseTypes: responseTypes.map(({ text, ...rest }) => {
1001
+ referencedFiles,
1002
+ validationDefinitions: validationDefinitions2.map((def) => {
642
1003
  return {
643
- ...rest,
644
- resolvedType: resolvedTypes?.find((e) => e.name === rest.id)
1004
+ ...def,
1005
+ ...def.target === "response" ? {
1006
+ variants: def.variants.map((variant) => {
1007
+ return {
1008
+ ...variant,
1009
+ resolvedType: resolvedTypes?.find(
1010
+ (e) => e.name === variant.id
1011
+ )
1012
+ };
1013
+ })
1014
+ } : {
1015
+ schema: {
1016
+ ...def.schema,
1017
+ resolvedType: resolvedTypes?.find(
1018
+ (e) => e.name === def.schema.id
1019
+ )
1020
+ }
1021
+ }
645
1022
  };
646
- }),
647
- referencedFiles
1023
+ })
648
1024
  });
649
1025
  }
650
- const entry2 = {
1026
+ const validationDefinitions = cache.validationDefinitions.flatMap(
1027
+ (def) => {
1028
+ let augmentedDef = def;
1029
+ if (def.target === "response") {
1030
+ augmentedDef = {
1031
+ ...def,
1032
+ variants: def.variants.flatMap((variant, i) => {
1033
+ if (typeof variant.contentType !== "string") {
1034
+ return [variant];
1035
+ }
1036
+ if (variant.contentType.includes("/")) {
1037
+ return [variant];
1038
+ }
1039
+ const contentType = mimeTypes.lookup(variant.contentType);
1040
+ if (contentType === false) {
1041
+ console.warn(
1042
+ styleText2(
1043
+ ["bold", "red"],
1044
+ "\u2717 Failed resolving Response Content Type"
1045
+ )
1046
+ );
1047
+ console.warn(
1048
+ ` Invalid value provided for mime-types lookup - ${variant.contentType}`
1049
+ );
1050
+ console.warn(
1051
+ styleText2(
1052
+ ["cyan"],
1053
+ ` Response variant #${i} excluded from route schemas`
1054
+ )
1055
+ );
1056
+ console.warn(` Route: ${name}; Method: ${def.method}`);
1057
+ console.warn();
1058
+ return [];
1059
+ }
1060
+ return [{ ...variant, contentType }];
1061
+ })
1062
+ };
1063
+ } else if (def.contentType && !def.contentType.includes("/")) {
1064
+ const contentType = mimeTypes.lookup(def.contentType);
1065
+ if (contentType === false) {
1066
+ console.warn(
1067
+ styleText2(
1068
+ ["bold", "red"],
1069
+ "\u2717 Failed resolving Response Content Type"
1070
+ )
1071
+ );
1072
+ console.warn(
1073
+ ` Invalid value provided for mime-types lookup - ${def.contentType}`
1074
+ );
1075
+ console.warn(` Route: ${name}; Method: ${def.method}`);
1076
+ console.warn();
1077
+ } else {
1078
+ augmentedDef = { ...def, contentType };
1079
+ }
1080
+ }
1081
+ return augmentedDef ? [augmentedDef] : [];
1082
+ }
1083
+ );
1084
+ const entry = {
1085
+ id,
651
1086
  name,
652
1087
  pathTokens,
1088
+ pathPattern,
653
1089
  params: cache.params,
654
1090
  numericParams: cache.numericParams,
655
1091
  optionalParams,
656
- importName,
657
- importFile,
658
1092
  folder,
659
1093
  file,
660
1094
  fileFullpath,
661
1095
  methods: cache.methods,
662
1096
  typeDeclarations: cache.typeDeclarations,
663
- payloadTypes: cache.payloadTypes,
664
- responseTypes: cache.responseTypes,
1097
+ validationDefinitions,
665
1098
  referencedFiles: Object.keys(cache.referencedFiles).map(
666
1099
  // expand referenced files path,
667
1100
  // they are stored as relative in cache
@@ -670,20 +1103,15 @@ var apiRouteResolverFactory = (pluginOptions) => {
670
1103
  };
671
1104
  return {
672
1105
  kind: "apiRoute",
673
- entry: entry2
1106
+ entry
674
1107
  };
675
1108
  };
676
1109
  return { name, handler };
677
1110
  };
678
1111
  };
679
1112
 
680
- // src/base-plugin/routes/nesting.ts
681
- import {
682
- sortRoutes
683
- } from "@kosmojs/devlib";
684
-
685
- // src/base-plugin/routes.ts
686
- var routes_default = async (pluginOptions) => {
1113
+ // src/routes-factory/index.ts
1114
+ var routesFactory = async (pluginOptions) => {
687
1115
  const { appRoot: appRoot2, sourceFolder: sourceFolder2 } = pluginOptions;
688
1116
  const apiRouteResolver = apiRouteResolverFactory(pluginOptions);
689
1117
  const apiUseResolver = apiUseResolverFactory(pluginOptions);
@@ -696,13 +1124,13 @@ var routes_default = async (pluginOptions) => {
696
1124
  return entry ? [entry] : [];
697
1125
  });
698
1126
  for (const entry of entries) {
699
- if (entry.folder === defaults2.apiDir) {
1127
+ if (entry.folder === defaults.apiDir) {
700
1128
  if (isApiRoute(entry.file)) {
701
1129
  resolvers2.set(entry.fileFullpath, apiRouteResolver(entry));
702
1130
  } else if (isApiUse(entry.file)) {
703
1131
  resolvers2.set(entry.fileFullpath, apiUseResolver(entry));
704
1132
  }
705
- } else if (entry.folder === defaults2.pagesDir) {
1133
+ } else if (entry.folder === defaults.pagesDir) {
706
1134
  if (isPageRoute(entry.file)) {
707
1135
  resolvers2.set(entry.fileFullpath, pageRouteResolver(entry));
708
1136
  } else if (isPageLayout(entry.file)) {
@@ -720,32 +1148,21 @@ var routes_default = async (pluginOptions) => {
720
1148
  };
721
1149
 
722
1150
  // src/base-plugin/worker.ts
723
- var {
724
- //
725
- generatorModules,
726
- formatterModules,
727
- ...restOptions
728
- } = workerData;
1151
+ var { generatorModules, ...restOptions } = workerData;
729
1152
  var generators = [];
730
- var formatters = [];
731
1153
  for (const [path, opts] of generatorModules) {
732
1154
  generators.push(await import(path).then((m) => m.default(opts)));
733
1155
  }
734
- for (const [path, opts] of formatterModules) {
735
- formatters.push(await import(path).then((m) => m.default(opts).formatter));
736
- }
737
1156
  var resolvedOptions = {
738
1157
  ...restOptions,
739
- generators,
740
- formatters
1158
+ generators
741
1159
  };
742
1160
  var { appRoot, sourceFolder } = resolvedOptions;
743
1161
  var watchHandlers = [];
744
1162
  var resolvedEntries = /* @__PURE__ */ new Map();
745
- var { resolvers, resolversFactory } = await routes_default(resolvedOptions);
746
- var { resolve: resolve4 } = pathResolver3({ appRoot, sourceFolder });
1163
+ var { resolvers, resolversFactory } = await routesFactory(resolvedOptions);
747
1164
  var spinnerFactory = (startText) => {
748
- const id = [startText, Date.now().toString()].map(crc4).join(":");
1165
+ const id = [startText, Date.now().toString()].map(crc6).join(":");
749
1166
  const postMessage = (method, text) => {
750
1167
  const spinner = { id, startText, method, text };
751
1168
  parentPort?.postMessage({ spinner });
@@ -832,11 +1249,12 @@ var runWatchHandlers = async (event) => {
832
1249
  }
833
1250
  spinner.succeed();
834
1251
  };
1252
+ var { createPath } = pathResolver({ appRoot, sourceFolder });
835
1253
  var watcher = chokidar.watch(
836
1254
  [
837
1255
  // watching for changes in sourceFolder's apiDir and pagesDir
838
- resolve4("apiDir"),
839
- resolve4("pagesDir")
1256
+ createPath.api(),
1257
+ createPath.pages()
840
1258
  ],
841
1259
  {
842
1260
  ...resolvedOptions.watcher.options,
@@ -889,8 +1307,8 @@ watcher.on("all", async (event, file) => {
889
1307
  for (const { name, factory } of generators) {
890
1308
  spinner.append(name);
891
1309
  try {
892
- const { watchHandler } = await factory(resolvedOptions);
893
- watchHandlers.push({ name, handler: watchHandler });
1310
+ const { watch } = await factory(resolvedOptions);
1311
+ watchHandlers.push({ name, handler: watch });
894
1312
  } catch (error) {
895
1313
  spinner.failed(error);
896
1314
  spinner = spinnerFactory("Initializing Generators");