@kosmojs/dev 0.0.20 → 0.0.22

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 (192) hide show
  1. package/LICENSE +21 -0
  2. package/package.json +11 -10
  3. package/pkg/{src/ast.d.ts → ast.d.ts} +11 -16
  4. package/pkg/{src/base-plugin → base-plugin}/api-handler.d.ts +1 -1
  5. package/pkg/{src/base-plugin → base-plugin}/worker.d.ts +1 -2
  6. package/pkg/base-plugin/worker.js +489 -221
  7. package/pkg/base-plugin/worker.js.map +4 -4
  8. package/pkg/{src/cache.d.ts → cache.d.ts} +1 -1
  9. package/pkg/index.js +640 -296
  10. package/pkg/index.js.map +4 -4
  11. package/pkg/{src/paths.d.ts → paths.d.ts} +2 -2
  12. package/pkg/{src/render.d.ts → render.d.ts} +4 -4
  13. package/pkg/routes-factory/base.d.ts +47 -0
  14. package/pkg/{src/routes-factory → routes-factory}/index.d.ts +1 -0
  15. package/pkg/stub-generator/index.js +1 -12
  16. package/pkg/stub-generator/index.js.map +2 -2
  17. package/pkg/{src/types.d.ts → types.d.ts} +55 -38
  18. package/pkg/src/routes-factory/base.d.ts +0 -17
  19. package/pkg/test/@fixtures/app/lib/@src/{api}/articles/[...path]/index.ts/types.d.ts +0 -3
  20. package/pkg/test/@fixtures/app/lib/@src/{api}/articles/[...path]/types.d.ts +0 -3
  21. package/pkg/test/@fixtures/app/lib/@src/{api}/books/[category]/[[author]]/index.ts/types.d.ts +0 -4
  22. package/pkg/test/@fixtures/app/lib/@src/{api}/books/[category]/[[author]]/types.d.ts +0 -4
  23. package/pkg/test/@fixtures/app/lib/@src/{api}/books/[category]/index.ts/types.d.ts +0 -3
  24. package/pkg/test/@fixtures/app/lib/@src/{api}/books/[category]/types.d.ts +0 -3
  25. package/pkg/test/@fixtures/app/lib/@src/{api}/books/index.ts/types.d.ts +0 -1
  26. package/pkg/test/@fixtures/app/lib/@src/{api}/books/types.d.ts +0 -1
  27. package/pkg/test/@fixtures/app/lib/@src/{api}/files/[[folder]]/[[id]].json/index.ts/types.d.ts +0 -4
  28. package/pkg/test/@fixtures/app/lib/@src/{api}/files/[[folder]]/[[id]].json/types.d.ts +0 -4
  29. package/pkg/test/@fixtures/app/lib/@src/{api}/files/[[folder]]/index.ts/types.d.ts +0 -3
  30. package/pkg/test/@fixtures/app/lib/@src/{api}/files/[[folder]]/types.d.ts +0 -3
  31. package/pkg/test/@fixtures/app/lib/@src/{api}/index/index.ts/types.d.ts +0 -1
  32. package/pkg/test/@fixtures/app/lib/@src/{api}/index/types.d.ts +0 -1
  33. package/pkg/test/@fixtures/app/lib/@src/{api}/pages/[...path].html/index.ts/types.d.ts +0 -3
  34. package/pkg/test/@fixtures/app/lib/@src/{api}/pages/[...path].html/types.d.ts +0 -3
  35. package/pkg/test/@fixtures/app/lib/@src/{api}/users/[id].json/index.ts/types.d.ts +0 -3
  36. package/pkg/test/@fixtures/app/lib/@src/{api}/users/[id].json/types.d.ts +0 -3
  37. package/pkg/test/@fixtures/app/src/test/api/articles/[...path]/index.d.ts +0 -0
  38. package/pkg/test/@fixtures/app/src/test/api/books/[category]/[[author]]/index.d.ts +0 -0
  39. package/pkg/test/@fixtures/app/src/test/api/books/[category]/index.d.ts +0 -0
  40. package/pkg/test/@fixtures/app/src/test/api/books/index.d.ts +0 -0
  41. package/pkg/test/@fixtures/app/src/test/api/files/[[folder]]/[[id]].json/index.d.ts +0 -0
  42. package/pkg/test/@fixtures/app/src/test/api/files/[[folder]]/index.d.ts +0 -0
  43. package/pkg/test/@fixtures/app/src/test/api/index/index.d.ts +0 -0
  44. package/pkg/test/@fixtures/app/src/test/api/pages/[...path].html/index.d.ts +0 -0
  45. package/pkg/test/@fixtures/app/src/test/api/users/[id].json/index.d.ts +0 -0
  46. package/pkg/test/@fixtures/app/src/test/pages/about/careers/[jobId]/index.d.ts +0 -0
  47. package/pkg/test/@fixtures/app/src/test/pages/about/careers/layout.d.ts +0 -0
  48. package/pkg/test/@fixtures/app/src/test/pages/about/index.d.ts +0 -0
  49. package/pkg/test/@fixtures/app/src/test/pages/about/layout.d.ts +0 -0
  50. package/pkg/test/@fixtures/app/src/test/pages/about/team/index.d.ts +0 -0
  51. package/pkg/test/@fixtures/app/src/test/pages/account/layout.d.ts +0 -0
  52. package/pkg/test/@fixtures/app/src/test/pages/account/profile/index.d.ts +0 -0
  53. package/pkg/test/@fixtures/app/src/test/pages/admin/[tenant]/index.d.ts +0 -0
  54. package/pkg/test/@fixtures/app/src/test/pages/admin/[tenant]/resources/[[type]]/[...path]/index.d.ts +0 -0
  55. package/pkg/test/@fixtures/app/src/test/pages/admin/[tenant]/resources/[[type]]/index.d.ts +0 -0
  56. package/pkg/test/@fixtures/app/src/test/pages/admin/[tenant]/resources/[[type]]/layout.d.ts +0 -0
  57. package/pkg/test/@fixtures/app/src/test/pages/admin/[tenant]/resources/index.d.ts +0 -0
  58. package/pkg/test/@fixtures/app/src/test/pages/admin/[tenant]/resources/layout.d.ts +0 -0
  59. package/pkg/test/@fixtures/app/src/test/pages/admin/[tenant]/settings/general/index.d.ts +0 -0
  60. package/pkg/test/@fixtures/app/src/test/pages/admin/[tenant]/settings/index.d.ts +0 -0
  61. package/pkg/test/@fixtures/app/src/test/pages/admin/[tenant]/settings/layout.d.ts +0 -0
  62. package/pkg/test/@fixtures/app/src/test/pages/admin/[tenant]/settings/permissions/index.d.ts +0 -0
  63. package/pkg/test/@fixtures/app/src/test/pages/admin/[tenant]/users/[userId]/index.d.ts +0 -0
  64. package/pkg/test/@fixtures/app/src/test/pages/admin/[tenant]/users/index.d.ts +0 -0
  65. package/pkg/test/@fixtures/app/src/test/pages/admin/[tenant]/users/layout.d.ts +0 -0
  66. package/pkg/test/@fixtures/app/src/test/pages/admin/index.d.ts +0 -0
  67. package/pkg/test/@fixtures/app/src/test/pages/admin/layout.d.ts +0 -0
  68. package/pkg/test/@fixtures/app/src/test/pages/blog/[[category]]/[[tag]]/index.d.ts +0 -0
  69. package/pkg/test/@fixtures/app/src/test/pages/blog/[[category]]/index.d.ts +0 -0
  70. package/pkg/test/@fixtures/app/src/test/pages/blog/index.d.ts +0 -0
  71. package/pkg/test/@fixtures/app/src/test/pages/blog/layout.d.ts +0 -0
  72. package/pkg/test/@fixtures/app/src/test/pages/blog/post/[slug]/index.d.ts +0 -0
  73. package/pkg/test/@fixtures/app/src/test/pages/blog/post/[slug]/layout.d.ts +0 -0
  74. package/pkg/test/@fixtures/app/src/test/pages/contact/index.d.ts +0 -0
  75. package/pkg/test/@fixtures/app/src/test/pages/contact/layout.d.ts +0 -0
  76. package/pkg/test/@fixtures/app/src/test/pages/courses/[courseId]/layout.d.ts +0 -0
  77. package/pkg/test/@fixtures/app/src/test/pages/courses/[courseId]/lessons/[[lessonId]]/assignments/[...assignmentPath]/index.d.ts +0 -0
  78. package/pkg/test/@fixtures/app/src/test/pages/dashboard/[view]/index.d.ts +0 -0
  79. package/pkg/test/@fixtures/app/src/test/pages/dashboard/analytics/index.d.ts +0 -0
  80. package/pkg/test/@fixtures/app/src/test/pages/dashboard/index.d.ts +0 -0
  81. package/pkg/test/@fixtures/app/src/test/pages/dashboard/layout.d.ts +0 -0
  82. package/pkg/test/@fixtures/app/src/test/pages/dashboard/settings/billing/index.d.ts +0 -0
  83. package/pkg/test/@fixtures/app/src/test/pages/dashboard/settings/index.d.ts +0 -0
  84. package/pkg/test/@fixtures/app/src/test/pages/dashboard/settings/layout.d.ts +0 -0
  85. package/pkg/test/@fixtures/app/src/test/pages/dashboard/settings/notifications/index.d.ts +0 -0
  86. package/pkg/test/@fixtures/app/src/test/pages/dashboard/settings/profile/index.d.ts +0 -0
  87. package/pkg/test/@fixtures/app/src/test/pages/dashboard/settings/security/index.d.ts +0 -0
  88. package/pkg/test/@fixtures/app/src/test/pages/dashboard/settings/security/layout.d.ts +0 -0
  89. package/pkg/test/@fixtures/app/src/test/pages/docs/[...path]/index.d.ts +0 -0
  90. package/pkg/test/@fixtures/app/src/test/pages/docs/index.d.ts +0 -0
  91. package/pkg/test/@fixtures/app/src/test/pages/docs/layout.d.ts +0 -0
  92. package/pkg/test/@fixtures/app/src/test/pages/files/[...filePath]/index.d.ts +0 -0
  93. package/pkg/test/@fixtures/app/src/test/pages/files/[...filePath]/layout.d.ts +0 -0
  94. package/pkg/test/@fixtures/app/src/test/pages/legal/layout.d.ts +0 -0
  95. package/pkg/test/@fixtures/app/src/test/pages/legal/privacy/index.d.ts +0 -0
  96. package/pkg/test/@fixtures/app/src/test/pages/legal/terms/index.d.ts +0 -0
  97. package/pkg/test/@fixtures/app/src/test/pages/news/[category]/articles/[...articlePath]/index.d.ts +0 -0
  98. package/pkg/test/@fixtures/app/src/test/pages/news/[category]/layout.d.ts +0 -0
  99. package/pkg/test/@fixtures/app/src/test/pages/portal/[clientId]/layout.d.ts +0 -0
  100. package/pkg/test/@fixtures/app/src/test/pages/portal/[clientId]/reports/[reportType]/data/[dataView]/index.d.ts +0 -0
  101. package/pkg/test/@fixtures/app/src/test/pages/portal/[clientId]/reports/[reportType]/data/[dataView]/layout.d.ts +0 -0
  102. package/pkg/test/@fixtures/app/src/test/pages/portal/[clientId]/reports/[reportType]/layout.d.ts +0 -0
  103. package/pkg/test/@fixtures/app/src/test/pages/portal/[clientId]/reports/layout.d.ts +0 -0
  104. package/pkg/test/@fixtures/app/src/test/pages/portal/layout.d.ts +0 -0
  105. package/pkg/test/@fixtures/app/src/test/pages/products/[id]/index.d.ts +0 -0
  106. package/pkg/test/@fixtures/app/src/test/pages/products/index.d.ts +0 -0
  107. package/pkg/test/@fixtures/app/src/test/pages/profile/[username]/layout.d.ts +0 -0
  108. package/pkg/test/@fixtures/app/src/test/pages/profile/[username]/posts/[postId]/comments/[...thread]/index.d.ts +0 -0
  109. package/pkg/test/@fixtures/app/src/test/pages/profile/[username]/posts/[postId]/layout.d.ts +0 -0
  110. package/pkg/test/@fixtures/app/src/test/pages/projects/[projectId]/files/[...path]/index.d.ts +0 -0
  111. package/pkg/test/@fixtures/app/src/test/pages/projects/[projectId]/files/index.d.ts +0 -0
  112. package/pkg/test/@fixtures/app/src/test/pages/projects/[projectId]/files/layout.d.ts +0 -0
  113. package/pkg/test/@fixtures/app/src/test/pages/projects/[projectId]/index.d.ts +0 -0
  114. package/pkg/test/@fixtures/app/src/test/pages/projects/[projectId]/layout.d.ts +0 -0
  115. package/pkg/test/@fixtures/app/src/test/pages/projects/[projectId]/tasks/[taskId]/comments/[commentId]/index.d.ts +0 -0
  116. package/pkg/test/@fixtures/app/src/test/pages/projects/[projectId]/tasks/[taskId]/comments/index.d.ts +0 -0
  117. package/pkg/test/@fixtures/app/src/test/pages/projects/[projectId]/tasks/[taskId]/comments/layout.d.ts +0 -0
  118. package/pkg/test/@fixtures/app/src/test/pages/projects/[projectId]/tasks/[taskId]/index.d.ts +0 -0
  119. package/pkg/test/@fixtures/app/src/test/pages/projects/[projectId]/tasks/[taskId]/layout.d.ts +0 -0
  120. package/pkg/test/@fixtures/app/src/test/pages/projects/[projectId]/tasks/index.d.ts +0 -0
  121. package/pkg/test/@fixtures/app/src/test/pages/projects/[projectId]/tasks/layout.d.ts +0 -0
  122. package/pkg/test/@fixtures/app/src/test/pages/projects/[projectId]/team/[userId]/index.d.ts +0 -0
  123. package/pkg/test/@fixtures/app/src/test/pages/projects/[projectId]/team/index.d.ts +0 -0
  124. package/pkg/test/@fixtures/app/src/test/pages/projects/[projectId]/team/layout.d.ts +0 -0
  125. package/pkg/test/@fixtures/app/src/test/pages/projects/index.d.ts +0 -0
  126. package/pkg/test/@fixtures/app/src/test/pages/projects/layout.d.ts +0 -0
  127. package/pkg/test/@fixtures/app/src/test/pages/properties/[[city]]/filters/[...filters]/index.d.ts +0 -0
  128. package/pkg/test/@fixtures/app/src/test/pages/properties/filters/index.d.ts +0 -0
  129. package/pkg/test/@fixtures/app/src/test/pages/properties/layout.d.ts +0 -0
  130. package/pkg/test/@fixtures/app/src/test/pages/search/[[query]]/[[page]]/index.d.ts +0 -0
  131. package/pkg/test/@fixtures/app/src/test/pages/search/[[query]]/layout.d.ts +0 -0
  132. package/pkg/test/@fixtures/app/src/test/pages/search/index.d.ts +0 -0
  133. package/pkg/test/@fixtures/app/src/test/pages/shop/[category]/[productId]/index.d.ts +0 -0
  134. package/pkg/test/@fixtures/app/src/test/pages/shop/[category]/[productId]/layout.d.ts +0 -0
  135. package/pkg/test/@fixtures/app/src/test/pages/shop/cart/index.d.ts +0 -0
  136. package/pkg/test/@fixtures/app/src/test/pages/shop/checkout/confirm/index.d.ts +0 -0
  137. package/pkg/test/@fixtures/app/src/test/pages/shop/checkout/layout.d.ts +0 -0
  138. package/pkg/test/@fixtures/app/src/test/pages/shop/checkout/payment/index.d.ts +0 -0
  139. package/pkg/test/@fixtures/app/src/test/pages/shop/checkout/shipping/index.d.ts +0 -0
  140. package/pkg/test/@fixtures/app/src/test/pages/shop/checkout/shipping/layout.d.ts +0 -0
  141. package/pkg/test/@fixtures/app/src/test/pages/shop/index.d.ts +0 -0
  142. package/pkg/test/@fixtures/app/src/test/pages/shop/layout.d.ts +0 -0
  143. package/pkg/test/@fixtures/app/src/test/pages/shop/orders/[orderId]/index.d.ts +0 -0
  144. package/pkg/test/@fixtures/app/src/test/pages/shop/orders/index.d.ts +0 -0
  145. package/pkg/test/@fixtures/app/src/test/pages/shop/orders/layout.d.ts +0 -0
  146. package/pkg/test/@fixtures/app/src/test/pages/shop/product/[id]/index.d.ts +0 -0
  147. package/pkg/test/@fixtures/app/src/test/pages/shop/product/[id]/layout.d.ts +0 -0
  148. package/pkg/test/@fixtures/app/src/test/pages/shop/product/[id]/reviews/index.d.ts +0 -0
  149. package/pkg/test/@fixtures/app/src/test/pages/shop/products/[[category]]/index.d.ts +0 -0
  150. package/pkg/test/@fixtures/app/src/test/pages/shop/products/index.d.ts +0 -0
  151. package/pkg/test/@fixtures/app/src/test/pages/shop/products/layout.d.ts +0 -0
  152. package/pkg/test/@fixtures/app/src/test/pages/signup/index.d.ts +0 -0
  153. package/pkg/test/@fixtures/app/src/test/pages/store/[category]/filters/[...filters]/index.d.ts +0 -0
  154. package/pkg/test/@fixtures/app/src/test/pages/store/[category]/sort/[sortBy]/index.d.ts +0 -0
  155. package/pkg/test/@fixtures/app/src/test/pages/store/[category]/sort/layout.d.ts +0 -0
  156. package/pkg/test/@fixtures/app/src/test/pages/store/layout.d.ts +0 -0
  157. package/pkg/test/@fixtures/app/src/test/pages/users/[username]/followers/index.d.ts +0 -0
  158. package/pkg/test/@fixtures/app/src/test/pages/users/[username]/following/index.d.ts +0 -0
  159. package/pkg/test/@fixtures/app/src/test/pages/users/[username]/index.d.ts +0 -0
  160. package/pkg/test/@fixtures/app/src/test/pages/users/[username]/layout.d.ts +0 -0
  161. package/pkg/test/@fixtures/app/src/test/pages/users/[username]/posts/[postId]/index.d.ts +0 -0
  162. package/pkg/test/@fixtures/app/src/test/pages/users/[username]/posts/[postId]/layout.d.ts +0 -0
  163. package/pkg/test/@fixtures/app/src/test/pages/users/[username]/posts/index.d.ts +0 -0
  164. package/pkg/test/@fixtures/app/src/test/pages/users/[username]/posts/layout.d.ts +0 -0
  165. package/pkg/test/@fixtures/app/src/test/pages/users/index.d.ts +0 -0
  166. package/pkg/test/@fixtures/app/src/test/pages/users/layout.d.ts +0 -0
  167. package/pkg/test/@fixtures/app/src/test/pages/workspace/[workspaceId]/analytics/[range]/index.d.ts +0 -0
  168. package/pkg/test/@fixtures/app/src/test/pages/workspace/[workspaceId]/analytics/[range]/layout.d.ts +0 -0
  169. package/pkg/test/@fixtures/app/src/test/pages/workspace/[workspaceId]/analytics/index.d.ts +0 -0
  170. package/pkg/test/@fixtures/app/src/test/pages/workspace/[workspaceId]/analytics/layout.d.ts +0 -0
  171. package/pkg/test/@fixtures/app/src/test/pages/workspace/[workspaceId]/team/[memberId]/permissions/[...permissionPath]/index.d.ts +0 -0
  172. package/pkg/test/@fixtures/app/src/test/pages/workspace/[workspaceId]/team/layout.d.ts +0 -0
  173. package/pkg/test/@fixtures/ast/extractTypeDeclarations/exports/with-referenced-files.d.ts +0 -1
  174. package/pkg/test/@fixtures/ast/extractTypeDeclarations/imports/with-referenced-files.d.ts +0 -1
  175. package/pkg/test/ast/extractParamsRefinements.test.d.ts +0 -1
  176. package/pkg/test/ast/extractRouteMethods.test.d.ts +0 -1
  177. package/pkg/test/ast/extractTypeDeclarations.test.d.ts +0 -1
  178. package/pkg/test/routes/index.d.ts +0 -4
  179. package/pkg/test/routes/nesting.test.d.ts +0 -1
  180. package/pkg/test/routes/resolver.test.d.ts +0 -1
  181. package/pkg/test/routes/routes.test.d.ts +0 -1
  182. /package/pkg/{src/alias-plugin → alias-plugin}/index.d.ts +0 -0
  183. /package/pkg/{src/base-plugin → base-plugin}/index.d.ts +0 -0
  184. /package/pkg/{src/base-plugin → base-plugin}/spinner.d.ts +0 -0
  185. /package/pkg/{src/defaults.d.ts → defaults.d.ts} +0 -0
  186. /package/pkg/{src/define-plugin → define-plugin}/index.d.ts +0 -0
  187. /package/pkg/{src/fs.d.ts → fs.d.ts} +0 -0
  188. /package/pkg/{src/index.d.ts → index.d.ts} +0 -0
  189. /package/pkg/{src/routes-factory → routes-factory}/nesting.d.ts +0 -0
  190. /package/pkg/{src/routes-factory → routes-factory}/resolve.d.ts +0 -0
  191. /package/pkg/{src/stub-generator → stub-generator}/index.d.ts +0 -0
  192. /package/pkg/{src/typebox.d.ts → typebox.d.ts} +0 -0
@@ -53,9 +53,6 @@ var pathResolver = ({
53
53
  },
54
54
  libEntry(...a) {
55
55
  return this.lib(defaults.entryDir, ...a);
56
- },
57
- fetch(...a) {
58
- return this.lib(defaults.fetchDir, ...a);
59
56
  }
60
57
  };
61
58
  return {
@@ -89,9 +86,6 @@ var pathResolver = ({
89
86
  },
90
87
  libPages(...a) {
91
88
  return this.lib(defaults.pagesDir, ...a);
92
- },
93
- fetch(...a) {
94
- return this.lib(defaults.fetchDir, ...a);
95
89
  }
96
90
  },
97
91
  createImport,
@@ -103,65 +97,25 @@ var pathResolver = ({
103
97
 
104
98
  // src/routes-factory/resolve.ts
105
99
  import { dirname as dirname3, join as join3, resolve as resolve3 } from "node:path";
100
+ import { styleText as styleText2 } from "node:util";
106
101
  import crc5 from "crc/crc32";
102
+ import mimeTypes from "mime-types";
107
103
  import picomatch from "picomatch";
108
104
  import { glob } from "tinyglobby";
109
105
 
110
- // src/render.ts
111
- import { mkdir, readFile, writeFile } from "node:fs/promises";
112
- import { dirname, join as join2 } from "node:path";
113
- import crc from "crc/crc32";
114
- import handlebars from "handlebars";
115
-
116
- // src/fs.ts
117
- import { access, constants } from "node:fs/promises";
118
- var pathExists = async (path) => {
119
- try {
120
- await access(path, constants.F_OK);
121
- return true;
122
- } catch {
123
- return false;
124
- }
125
- };
126
-
127
- // src/render.ts
128
- var render = (template, context, options) => {
129
- const { noEscape = true, renderer = handlebars } = { ...options };
130
- return renderer.compile(template, { noEscape })(context);
131
- };
132
- var renderAsFile = (file, template, context, options) => {
133
- const { formatters: formatters2, ...renderOpts } = { ...options };
134
- const content = render(template, context, renderOpts);
135
- return Array.isArray(formatters2) ? formatters2.reduce((c, f) => f(c, file), content) : content;
136
- };
137
- var renderToFile = async (file, template, context, options) => {
138
- const content = renderAsFile(file, template, context, options);
139
- if (await pathExists(file)) {
140
- const { overwrite = true } = { ...options };
141
- if (overwrite === false) {
142
- return;
143
- }
144
- const fileContent = await readFile(file, "utf8");
145
- if (typeof overwrite === "function" && !overwrite(fileContent)) {
146
- return;
147
- }
148
- if (crc(content) === crc(fileContent)) {
149
- return;
150
- }
151
- }
152
- await mkdir(dirname(file), { recursive: true });
153
- await writeFile(file, content, "utf8");
154
- };
155
-
156
106
  // src/ast.ts
157
107
  import { resolve } from "node:path";
158
- import crc2 from "crc/crc32";
108
+ import { styleText } from "node:util";
109
+ import crc from "crc/crc32";
159
110
  import { flattener } from "tfusion";
160
111
  import {
161
112
  Project,
162
113
  SyntaxKind
163
114
  } from "ts-morph";
164
- import { HTTPMethods } from "@kosmojs/api";
115
+ import {
116
+ HTTPMethods,
117
+ RequestValidationTargets
118
+ } from "@kosmojs/api";
165
119
  var createProject = (opts) => new Project(opts);
166
120
  var resolveRouteSignature = async (route, opts) => {
167
121
  const {
@@ -173,19 +127,12 @@ var resolveRouteSignature = async (route, opts) => {
173
127
  );
174
128
  const defaultExport = extractDefaultExport(sourceFile);
175
129
  const paramsRefinements = defaultExport ? extractParamsRefinements(defaultExport) : void 0;
176
- const methods = defaultExport ? extractRouteMethods(defaultExport, route) : [];
177
- const payloadTypes = methods.flatMap((e) => {
178
- return e.payloadType ? [e.payloadType] : [];
179
- });
180
- const responseTypes = methods.flatMap((e) => {
181
- return e.responseType ? [e.responseType] : [];
182
- });
130
+ const methods = defaultExport ? extractRouteMethods(route, defaultExport) : [];
183
131
  return {
184
132
  typeDeclarations,
185
133
  paramsRefinements,
186
134
  methods: methods.map((e) => e.method),
187
- payloadTypes,
188
- responseTypes,
135
+ validationDefinitions: methods.flatMap((e) => e.validationDefinitions),
189
136
  referencedFiles
190
137
  };
191
138
  };
@@ -200,22 +147,23 @@ var extractDefaultExport = (sourceFile) => {
200
147
  return defaultExport;
201
148
  };
202
149
  var extractParamsRefinements = (callExpression) => {
203
- const [firstGeneric] = extractGenerics(callExpression);
204
- if (!firstGeneric?.node.isKind(SyntaxKind.TupleType)) {
205
- return;
206
- }
207
- const tupleElements = firstGeneric.node.getElements();
208
- if (!tupleElements?.length) {
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)) {
209
157
  return;
210
158
  }
211
- return tupleElements.map((node, index) => {
159
+ return paramsGeneric.getElements().map((node, index) => {
212
160
  return {
213
161
  index,
214
162
  text: node.getText()
215
163
  };
216
164
  });
217
165
  };
218
- var extractRouteMethods = (callExpression, route) => {
166
+ var extractRouteMethods = (route, callExpression) => {
219
167
  const funcDeclaration = callExpression.getFirstChildByKind(SyntaxKind.ArrowFunction) || callExpression.getFirstChildByKind(SyntaxKind.FunctionExpression);
220
168
  if (!funcDeclaration) {
221
169
  return [];
@@ -236,35 +184,173 @@ var extractRouteMethods = (callExpression, route) => {
236
184
  }
237
185
  }
238
186
  const methods = [];
239
- const skipValidationFilter = (e) => /@skip-validation/.test(e);
240
187
  for (const [callExpression2, method] of callExpressions) {
241
- const [payloadGeneric, responseGeneric] = extractGenerics(callExpression2);
242
- const payloadText = payloadGeneric?.node ? payloadGeneric.node.getChildren().length === 0 ? "{}" : payloadGeneric.node.getFullText() : void 0;
243
- const responseText = responseGeneric?.node.getText();
244
- const responseType = responseText ? {
245
- id: ["ResponseT", crc2(route.id + method)].join(""),
246
- method,
247
- skipValidation: responseGeneric?.comments ? responseGeneric.comments.some(skipValidationFilter) : false,
248
- text: ["never", "object"].includes(responseText) ? "{}" : responseText,
249
- resolvedType: void 0
250
- } : void 0;
251
- const payloadType = payloadText ? {
252
- id: ["PayloadT", crc2(route.id + method)].join(""),
253
- responseTypeId: responseType?.id,
254
- method,
255
- skipValidation: payloadGeneric?.comments ? payloadGeneric.comments.some(skipValidationFilter) : false,
256
- isOptional: payloadText ? payloadText === "{}" || route.optionalParams : true,
257
- text: payloadText,
258
- resolvedType: void 0
259
- } : void 0;
188
+ const [vDefs, vOpts] = extractGenerics(callExpression2);
260
189
  methods.push({
261
190
  method,
262
- payloadType,
263
- responseType
191
+ validationDefinitions: extractValidationDefinitions(
192
+ route,
193
+ method,
194
+ vDefs,
195
+ vOpts
196
+ )
264
197
  });
265
198
  }
266
199
  return methods;
267
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
+ };
268
354
  var extractTypeDeclarations = (sourceFile, opts) => {
269
355
  const declarations = [];
270
356
  const referencedFiles = opts?.withReferencedFiles ? [] : void 0;
@@ -369,12 +455,7 @@ var getReferencedFiles = (importIdentifier) => {
369
455
  });
370
456
  };
371
457
  var extractGenerics = (callExpression) => {
372
- return callExpression.getTypeArguments().map((node) => {
373
- return {
374
- node,
375
- comments: node.getLeadingCommentRanges().map((range) => range.getText().trim())
376
- };
377
- });
458
+ return callExpression.getTypeArguments();
378
459
  };
379
460
  var typeResolverFactory = ({ appRoot: appRoot2 }) => {
380
461
  const project = createProject({
@@ -383,7 +464,7 @@ var typeResolverFactory = ({ appRoot: appRoot2 }) => {
383
464
  });
384
465
  const literalTypesResolver = (literalTypes, options) => {
385
466
  const sourceFile = project.createSourceFile(
386
- `${crc2(literalTypes)}-${Date.now()}.ts`,
467
+ `${crc(literalTypes)}-${Date.now()}.ts`,
387
468
  literalTypes,
388
469
  { overwrite: true }
389
470
  );
@@ -409,10 +490,23 @@ var typeResolverFactory = ({ appRoot: appRoot2 }) => {
409
490
  };
410
491
 
411
492
  // src/cache.ts
412
- import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
413
- import { dirname as dirname2, resolve as resolve2 } from "node:path";
414
- import crc3 from "crc/crc32";
493
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
494
+ import { dirname, resolve as resolve2 } from "node:path";
495
+ import crc2 from "crc/crc32";
415
496
  import self from "@kosmojs/dev/package.json" with { type: "json" };
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
416
510
  var cacheFactory = (route, {
417
511
  appRoot: appRoot2,
418
512
  sourceFolder: sourceFolder2,
@@ -421,11 +515,11 @@ var cacheFactory = (route, {
421
515
  const cacheFile = pathResolver({
422
516
  appRoot: appRoot2,
423
517
  sourceFolder: sourceFolder2
424
- }).createPath.libApi(dirname2(route.file), "cache.json");
518
+ }).createPath.libApi(dirname(route.file), "cache.json");
425
519
  const getCache = async (opt) => {
426
520
  if (await pathExists(cacheFile)) {
427
521
  try {
428
- const cache = JSON.parse(await readFile2(cacheFile, "utf8"));
522
+ const cache = JSON.parse(await readFile(cacheFile, "utf8"));
429
523
  return opt?.validate ? validateCache(cache) : cache;
430
524
  } catch (_e) {
431
525
  }
@@ -448,8 +542,8 @@ var cacheFactory = (route, {
448
542
  ] = await generateFileHash(file);
449
543
  }
450
544
  const cache = { ...rest, hash, referencedFiles };
451
- await mkdir2(dirname2(cacheFile), { recursive: true });
452
- await writeFile2(cacheFile, JSON.stringify(cache, null, 2), "utf8");
545
+ await mkdir(dirname(cacheFile), { recursive: true });
546
+ await writeFile(cacheFile, JSON.stringify(cache, null, 2), "utf8");
453
547
  return cache;
454
548
  };
455
549
  const validateCache = async (cache) => {
@@ -481,11 +575,11 @@ var cacheFactory = (route, {
481
575
  var generateFileHash = async (file, extraContext) => {
482
576
  let fileContent;
483
577
  try {
484
- fileContent = await readFile2(file, "utf8");
578
+ fileContent = await readFile(file, "utf8");
485
579
  } catch (_e) {
486
580
  return 0;
487
581
  }
488
- return fileContent ? crc3(
582
+ return fileContent ? crc2(
489
583
  JSON.stringify({
490
584
  ...extraContext,
491
585
  [self.cacheVersion]: fileContent
@@ -496,61 +590,167 @@ var identicalHashSum = (a, b) => {
496
590
  return a === b;
497
591
  };
498
592
 
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
+
499
621
  // src/routes-factory/base.ts
500
622
  import crc4 from "crc/crc32";
501
- var pathTokensFactory = (path) => {
502
- const requiredParamRegex = /^\[([^\]]+)\]$/;
503
- const optionalParamRegex = /^\[\[([^\]]+)\]\]$/;
504
- const restParamRegex = /^\[\.\.\.([^\]]+)\]$/;
505
- return path.split("/").map((orig, i) => {
506
- const [base, ext = ""] = orig.split(/(\.([\w\d-]+)$)/);
507
- const paramBase = (regex) => {
508
- const name = base.replace(regex, "$1") || base;
509
- return {
510
- name,
511
- const: /\W/.test(name) ? [name.replace(/\W/g, "_"), crc4(orig)].join("_") : name
512
- };
513
- };
514
- let param;
515
- if (base.startsWith("[")) {
516
- if (restParamRegex.test(base)) {
517
- param = {
518
- ...paramBase(restParamRegex),
519
- isRequired: false,
520
- isOptional: false,
521
- isRest: true
522
- };
523
- } else if (optionalParamRegex.test(base)) {
524
- param = {
525
- ...paramBase(optionalParamRegex),
526
- isRequired: false,
527
- isOptional: true,
528
- isRest: false
529
- };
530
- } else if (requiredParamRegex.test(base)) {
531
- param = {
532
- ...paramBase(requiredParamRegex),
533
- isRequired: true,
534
- isOptional: false,
535
- isRest: false
536
- };
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;
537
658
  }
538
659
  }
539
- return {
540
- orig,
541
- base,
542
- path: i === 0 ? orig.replace(/^index$/, "/") : orig,
543
- ext,
544
- ...param ? { param } : {}
545
- };
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
+ ];
546
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, "\\\\+");
547
747
  };
548
748
 
549
749
  // src/routes-factory/templates/resolved-types.hbs
550
750
  var resolved_types_default = "{{#each resolvedTypes}}\nexport type {{name}} = {{text}};\n{{/each}}\n";
551
751
 
552
752
  // src/routes-factory/templates/types.hbs
553
- 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';
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';
554
754
 
555
755
  // src/routes-factory/resolve.ts
556
756
  var API_INDEX_BASENAME = "index";
@@ -621,15 +821,18 @@ var createRouteEntry = (fileFullpath, {
621
821
  return;
622
822
  }
623
823
  const [folder, file] = resolvedPaths;
624
- const pathTokens = pathTokensFactory(dirname3(file));
625
- return {
626
- id: `${file.replace(/\W+/g, "_")}_${crc5(file)}`,
627
- name: pathTokens.map((e) => e.orig).join("/"),
628
- folder,
629
- file,
630
- fileFullpath,
631
- pathTokens
632
- };
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
+ }
633
836
  };
634
837
  var pageLayoutResolverFactory = () => {
635
838
  return (entry) => {
@@ -645,14 +848,17 @@ var pageLayoutResolverFactory = () => {
645
848
  };
646
849
  var pageRouteResolverFactory = () => {
647
850
  return (entry) => {
648
- const { id, name, folder, file, fileFullpath, pathTokens } = entry;
851
+ const { id, name, folder, file, fileFullpath, pathTokens, pathPattern } = entry;
649
852
  const handler = async () => {
650
853
  const entry2 = {
651
854
  id,
652
855
  name,
653
856
  pathTokens,
857
+ pathPattern,
654
858
  params: {
655
- schema: pathTokens.flatMap((e) => e.param ? [e.param] : [])
859
+ schema: pathTokens.flatMap((e) => {
860
+ return e.parts.filter((p) => p.type === "param");
861
+ })
656
862
  },
657
863
  folder,
658
864
  file,
@@ -683,28 +889,33 @@ var apiRouteResolverFactory = (pluginOptions) => {
683
889
  appRoot: appRoot2,
684
890
  sourceFolder: sourceFolder2,
685
891
  generators: generators2 = [],
686
- formatters: formatters2 = [],
687
892
  refineTypeName
688
893
  } = pluginOptions;
689
- let resolveTypes = false;
690
- for (const { options } of generators2) {
691
- if (options?.resolveTypes) {
692
- resolveTypes = true;
693
- }
694
- }
894
+ const resolveTypes = generators2.some((e) => e.options?.resolveTypes);
695
895
  const {
696
896
  //
697
897
  literalTypesResolver,
698
898
  getSourceFile,
699
899
  refreshSourceFile
700
900
  } = typeResolverFactory(pluginOptions);
701
- return (entry) => {
702
- const { id, name, file, folder, fileFullpath, pathTokens } = entry;
901
+ return ({
902
+ id,
903
+ name,
904
+ file,
905
+ folder,
906
+ fileFullpath,
907
+ pathTokens,
908
+ pathPattern
909
+ }) => {
703
910
  const handler = async (updatedFile) => {
704
- const paramsSchema = pathTokens.flatMap((e) => {
705
- return e.param ? [e.param] : [];
706
- });
707
- 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;
708
919
  const { getCache, persistCache } = cacheFactory(
709
920
  { id, file, fileFullpath },
710
921
  {
@@ -722,11 +933,10 @@ var apiRouteResolverFactory = (pluginOptions) => {
722
933
  typeDeclarations,
723
934
  paramsRefinements,
724
935
  methods,
725
- payloadTypes,
726
- responseTypes,
936
+ validationDefinitions: validationDefinitions2,
727
937
  referencedFiles = []
728
938
  } = await resolveRouteSignature(
729
- { id, fileFullpath, optionalParams },
939
+ { id, name, fileFullpath, optionalParams },
730
940
  {
731
941
  withReferencedFiles: true,
732
942
  sourceFile: getSourceFile(fileFullpath),
@@ -735,6 +945,11 @@ var apiRouteResolverFactory = (pluginOptions) => {
735
945
  }
736
946
  }
737
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
+ });
738
953
  const numericParams = paramsRefinements ? paramsRefinements.flatMap(({ text, index }) => {
739
954
  if (text === "number") {
740
955
  const param = paramsSchema.at(index);
@@ -756,25 +971,21 @@ var apiRouteResolverFactory = (pluginOptions) => {
756
971
  paramsSchema: paramsSchema.map((param, index) => {
757
972
  return {
758
973
  ...param,
974
+ isRequired: param.kind === "required",
975
+ isSplat: param.kind === "splat",
759
976
  refinement: paramsRefinements?.at(index)
760
977
  };
761
978
  }),
762
979
  typeDeclarations,
763
- payloadTypes,
764
- responseTypes
980
+ validationTypes
765
981
  });
766
982
  const resolvedTypes = resolveTypes ? literalTypesResolver(typesFileContent, {
767
- overrides: [...payloadTypes, ...responseTypes].reduce(
768
- (map, { id: id2, skipValidation }) => {
769
- if (skipValidation) {
770
- map[id2] = "never";
771
- }
772
- return map;
773
- },
774
- { [refineTypeName]: refineTypeName }
775
- ),
776
- withProperties: [params.id, ...payloadTypes.map((e) => e.id)],
777
- formatters: formatters2
983
+ stripComments: true,
984
+ overrides: { [refineTypeName]: refineTypeName },
985
+ withProperties: [
986
+ params.id,
987
+ ...validationTypes.flatMap(({ id: id2 }) => id2)
988
+ ]
778
989
  }) : void 0;
779
990
  await renderToFile(
780
991
  typesFile,
@@ -787,26 +998,94 @@ var apiRouteResolverFactory = (pluginOptions) => {
787
998
  methods,
788
999
  typeDeclarations,
789
1000
  numericParams,
790
- // text was needed at writing types.ts file, dropping from cache
791
- payloadTypes: payloadTypes.map(({ text, ...rest }) => {
792
- return {
793
- ...rest,
794
- resolvedType: resolvedTypes?.find((e) => e.name === rest.id)
795
- };
796
- }),
797
- responseTypes: responseTypes.map(({ text, ...rest }) => {
1001
+ referencedFiles,
1002
+ validationDefinitions: validationDefinitions2.map((def) => {
798
1003
  return {
799
- ...rest,
800
- 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
+ }
801
1022
  };
802
- }),
803
- referencedFiles
1023
+ })
804
1024
  });
805
1025
  }
806
- 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 = {
807
1085
  id,
808
1086
  name,
809
1087
  pathTokens,
1088
+ pathPattern,
810
1089
  params: cache.params,
811
1090
  numericParams: cache.numericParams,
812
1091
  optionalParams,
@@ -815,8 +1094,7 @@ var apiRouteResolverFactory = (pluginOptions) => {
815
1094
  fileFullpath,
816
1095
  methods: cache.methods,
817
1096
  typeDeclarations: cache.typeDeclarations,
818
- payloadTypes: cache.payloadTypes,
819
- responseTypes: cache.responseTypes,
1097
+ validationDefinitions,
820
1098
  referencedFiles: Object.keys(cache.referencedFiles).map(
821
1099
  // expand referenced files path,
822
1100
  // they are stored as relative in cache
@@ -825,7 +1103,7 @@ var apiRouteResolverFactory = (pluginOptions) => {
825
1103
  };
826
1104
  return {
827
1105
  kind: "apiRoute",
828
- entry: entry2
1106
+ entry
829
1107
  };
830
1108
  };
831
1109
  return { name, handler };
@@ -870,24 +1148,14 @@ var routesFactory = async (pluginOptions) => {
870
1148
  };
871
1149
 
872
1150
  // src/base-plugin/worker.ts
873
- var {
874
- //
875
- generatorModules,
876
- formatterModules,
877
- ...restOptions
878
- } = workerData;
1151
+ var { generatorModules, ...restOptions } = workerData;
879
1152
  var generators = [];
880
- var formatters = [];
881
1153
  for (const [path, opts] of generatorModules) {
882
1154
  generators.push(await import(path).then((m) => m.default(opts)));
883
1155
  }
884
- for (const [path, opts] of formatterModules) {
885
- formatters.push(await import(path).then((m) => m.default(opts).formatter));
886
- }
887
1156
  var resolvedOptions = {
888
1157
  ...restOptions,
889
- generators,
890
- formatters
1158
+ generators
891
1159
  };
892
1160
  var { appRoot, sourceFolder } = resolvedOptions;
893
1161
  var watchHandlers = [];