@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.
- package/LICENSE +21 -0
- package/package.json +13 -45
- package/pkg/{src/base-plugin/ast.d.ts → ast.d.ts} +11 -16
- package/pkg/{src/base-plugin → base-plugin}/api-handler.d.ts +2 -2
- package/pkg/{src/base-plugin → base-plugin}/index.d.ts +1 -1
- package/pkg/{src/base-plugin → base-plugin}/worker.d.ts +2 -3
- package/pkg/base-plugin/worker.js +614 -196
- package/pkg/base-plugin/worker.js.map +4 -4
- package/pkg/{src/base-plugin/cache.d.ts → cache.d.ts} +3 -3
- package/pkg/defaults.d.ts +13 -0
- package/pkg/fs.d.ts +1 -0
- package/pkg/index.d.ts +9 -0
- package/pkg/index.js +991 -313
- package/pkg/index.js.map +4 -4
- package/pkg/paths.d.ts +13 -0
- package/pkg/render.d.ts +28 -0
- package/pkg/routes-factory/base.d.ts +47 -0
- package/pkg/routes-factory/index.d.ts +9 -0
- package/pkg/routes-factory/nesting.d.ts +3 -0
- package/pkg/{src/base-plugin/routes → routes-factory}/resolve.d.ts +3 -3
- package/pkg/{src/stub-generator → stub-generator}/index.d.ts +1 -1
- package/pkg/stub-generator/index.js +155 -24
- package/pkg/stub-generator/index.js.map +4 -4
- package/pkg/typebox.d.ts +2 -0
- package/pkg/types.d.ts +305 -0
- package/pkg/base-plugin/routes.js +0 -819
- package/pkg/base-plugin/routes.js.map +0 -7
- package/pkg/cli/cli.js +0 -583
- package/pkg/cli/cli.js.map +0 -7
- package/pkg/cli/index.js +0 -422
- package/pkg/cli/index.js.map +0 -7
- package/pkg/cli/templates/.env +0 -1
- package/pkg/cli/templates/@src/api/app.hbs +0 -32
- package/pkg/cli/templates/@src/api/router.hbs +0 -11
- package/pkg/cli/templates/@src/api/server.hbs +0 -4
- package/pkg/cli/templates/@src/api/use.hbs +0 -6
- package/pkg/cli/templates/@src/config/index.hbs +0 -2
- package/pkg/cli/templates/@src/index.html +0 -4
- package/pkg/cli/templates/@src/vite.config.hbs +0 -29
- package/pkg/cli/templates/core/api/app.ts +0 -6
- package/pkg/cli/templates/core/api/env.d.ts +0 -4
- package/pkg/cli/templates/core/api/errors.ts +0 -18
- package/pkg/cli/templates/core/api/router.ts +0 -6
- package/pkg/cli/templates/core/api/server.ts +0 -63
- package/pkg/cli/templates/core/api/use.ts +0 -25
- package/pkg/cli/templates/vite.base.hbs +0 -44
- package/pkg/src/base-plugin/routes/nesting.d.ts +0 -5
- package/pkg/src/base-plugin/routes.d.ts +0 -9
- package/pkg/src/cli/base.d.ts +0 -30
- package/pkg/src/cli/cli.d.ts +0 -2
- package/pkg/src/cli/factory.d.ts +0 -12
- package/pkg/src/cli/index.d.ts +0 -2
- package/pkg/src/cli/templates/core/api/app.d.ts +0 -3
- package/pkg/src/cli/templates/core/api/errors.d.ts +0 -1
- package/pkg/src/cli/templates/core/api/router.d.ts +0 -3
- package/pkg/src/cli/templates/core/api/server.d.ts +0 -3
- package/pkg/src/cli/templates/core/api/use.d.ts +0 -2
- package/pkg/src/index.d.ts +0 -6
- package/pkg/test/@fixtures/app/@src/api/articles/[...path]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/api/books/[category]/[[author]]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/api/books/[category]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/api/books/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/api/files/[[folder]]/[[id]].json/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/api/files/[[folder]]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/api/index/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/api/pages/[...path].html/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/api/users/[id].json/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/about/careers/[jobId]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/about/careers/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/about/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/about/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/about/team/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/account/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/account/profile/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/resources/[[type]]/[...path]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/resources/[[type]]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/resources/[[type]]/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/resources/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/resources/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/settings/general/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/settings/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/settings/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/settings/permissions/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/users/[userId]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/users/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/admin/[tenant]/users/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/admin/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/admin/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/blog/[[category]]/[[tag]]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/blog/[[category]]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/blog/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/blog/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/blog/post/[slug]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/blog/post/[slug]/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/contact/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/contact/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/courses/[courseId]/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/courses/[courseId]/lessons/[[lessonId]]/assignments/[...assignmentPath]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/dashboard/[view]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/dashboard/analytics/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/dashboard/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/dashboard/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/dashboard/settings/billing/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/dashboard/settings/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/dashboard/settings/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/dashboard/settings/notifications/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/dashboard/settings/profile/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/dashboard/settings/security/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/dashboard/settings/security/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/docs/[...path]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/docs/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/docs/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/files/[...filePath]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/files/[...filePath]/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/legal/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/legal/privacy/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/legal/terms/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/news/[category]/articles/[...articlePath]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/news/[category]/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/portal/[clientId]/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/portal/[clientId]/reports/[reportType]/data/[dataView]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/portal/[clientId]/reports/[reportType]/data/[dataView]/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/portal/[clientId]/reports/[reportType]/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/portal/[clientId]/reports/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/portal/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/products/[id]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/products/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/profile/[username]/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/profile/[username]/posts/[postId]/comments/[...thread]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/profile/[username]/posts/[postId]/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/files/[...path]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/files/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/files/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/tasks/[taskId]/comments/[commentId]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/tasks/[taskId]/comments/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/tasks/[taskId]/comments/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/tasks/[taskId]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/tasks/[taskId]/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/tasks/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/tasks/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/team/[userId]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/team/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/projects/[projectId]/team/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/projects/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/projects/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/properties/[[city]]/filters/[...filters]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/properties/filters/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/properties/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/search/[[query]]/[[page]]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/search/[[query]]/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/search/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/shop/[category]/[productId]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/shop/[category]/[productId]/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/shop/cart/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/shop/checkout/confirm/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/shop/checkout/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/shop/checkout/payment/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/shop/checkout/shipping/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/shop/checkout/shipping/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/shop/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/shop/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/shop/orders/[orderId]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/shop/orders/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/shop/orders/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/shop/product/[id]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/shop/product/[id]/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/shop/product/[id]/reviews/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/shop/products/[[category]]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/shop/products/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/shop/products/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/signup/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/store/[category]/filters/[...filters]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/store/[category]/sort/[sortBy]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/store/[category]/sort/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/store/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/users/[username]/followers/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/users/[username]/following/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/users/[username]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/users/[username]/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/users/[username]/posts/[postId]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/users/[username]/posts/[postId]/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/users/[username]/posts/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/users/[username]/posts/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/users/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/users/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/workspace/[workspaceId]/analytics/[range]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/workspace/[workspaceId]/analytics/[range]/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/workspace/[workspaceId]/analytics/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/workspace/[workspaceId]/analytics/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/workspace/[workspaceId]/team/[memberId]/permissions/[...permissionPath]/index.d.ts +0 -0
- package/pkg/test/@fixtures/app/@src/pages/workspace/[workspaceId]/team/layout.d.ts +0 -0
- package/pkg/test/@fixtures/app/lib/@src/{api}/articles/[...path]/index.ts/types.d.ts +0 -3
- package/pkg/test/@fixtures/app/lib/@src/{api}/articles/[...path]/types.d.ts +0 -3
- package/pkg/test/@fixtures/app/lib/@src/{api}/books/[category]/[[author]]/index.ts/types.d.ts +0 -4
- package/pkg/test/@fixtures/app/lib/@src/{api}/books/[category]/[[author]]/types.d.ts +0 -4
- package/pkg/test/@fixtures/app/lib/@src/{api}/books/[category]/index.ts/types.d.ts +0 -3
- package/pkg/test/@fixtures/app/lib/@src/{api}/books/[category]/types.d.ts +0 -3
- package/pkg/test/@fixtures/app/lib/@src/{api}/books/index.ts/types.d.ts +0 -1
- package/pkg/test/@fixtures/app/lib/@src/{api}/books/types.d.ts +0 -1
- package/pkg/test/@fixtures/app/lib/@src/{api}/files/[[folder]]/[[id]].json/index.ts/types.d.ts +0 -4
- package/pkg/test/@fixtures/app/lib/@src/{api}/files/[[folder]]/[[id]].json/types.d.ts +0 -4
- package/pkg/test/@fixtures/app/lib/@src/{api}/files/[[folder]]/index.ts/types.d.ts +0 -3
- package/pkg/test/@fixtures/app/lib/@src/{api}/files/[[folder]]/types.d.ts +0 -3
- package/pkg/test/@fixtures/app/lib/@src/{api}/index/index.ts/types.d.ts +0 -1
- package/pkg/test/@fixtures/app/lib/@src/{api}/index/types.d.ts +0 -1
- package/pkg/test/@fixtures/app/lib/@src/{api}/pages/[...path].html/index.ts/types.d.ts +0 -3
- package/pkg/test/@fixtures/app/lib/@src/{api}/pages/[...path].html/types.d.ts +0 -3
- package/pkg/test/@fixtures/app/lib/@src/{api}/users/[id].json/index.ts/types.d.ts +0 -3
- package/pkg/test/@fixtures/app/lib/@src/{api}/users/[id].json/types.d.ts +0 -3
- package/pkg/test/@fixtures/ast/extractTypeDeclarations/exports/with-referenced-files.d.ts +0 -1
- package/pkg/test/@fixtures/ast/extractTypeDeclarations/imports/with-referenced-files.d.ts +0 -1
- package/pkg/test/ast/extractParamsRefinements.test.d.ts +0 -1
- package/pkg/test/ast/extractRouteMethods.test.d.ts +0 -1
- package/pkg/test/ast/extractTypeDeclarations.test.d.ts +0 -1
- package/pkg/test/cli/create.test.d.ts +0 -1
- package/pkg/test/routes/base.d.ts +0 -4
- package/pkg/test/routes/nesting.test.d.ts +0 -1
- package/pkg/test/routes/resolver.test.d.ts +0 -1
- package/pkg/test/setup.d.ts +0 -1
- /package/pkg/{src/alias-plugin → alias-plugin}/index.d.ts +0 -0
- /package/pkg/{src/base-plugin → base-plugin}/spinner.d.ts +0 -0
- /package/pkg/{src/define-plugin → define-plugin}/index.d.ts +0 -0
package/pkg/index.js
CHANGED
|
@@ -1,33 +1,135 @@
|
|
|
1
|
-
// src/index.ts
|
|
2
|
-
import { default as default2 } from "@kosmojs/api-generator";
|
|
3
|
-
import { default as default3 } from "@kosmojs/fetch-generator";
|
|
4
|
-
|
|
5
1
|
// src/alias-plugin/index.ts
|
|
6
2
|
import { glob } from "tinyglobby";
|
|
3
|
+
|
|
4
|
+
// src/paths.ts
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
|
|
7
|
+
// src/defaults.ts
|
|
8
|
+
var defaults = {
|
|
9
|
+
appPrefix: "~",
|
|
10
|
+
srcPrefix: "@",
|
|
11
|
+
libPrefix: "_",
|
|
12
|
+
coreDir: "core",
|
|
13
|
+
srcDir: "src",
|
|
14
|
+
libDir: "lib",
|
|
15
|
+
configDir: "config",
|
|
16
|
+
apiDir: "api",
|
|
17
|
+
pagesDir: "pages",
|
|
18
|
+
entryDir: "entry",
|
|
19
|
+
fetchDir: "fetch"
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// src/paths.ts
|
|
23
|
+
var createTsconfigPaths = (prefix) => {
|
|
24
|
+
return {
|
|
25
|
+
[`${defaults.appPrefix}/*`]: [`${prefix}/*`],
|
|
26
|
+
[`${defaults.srcPrefix}/*`]: [`${prefix}/${defaults.srcDir}/*`],
|
|
27
|
+
[`${defaults.libPrefix}/*`]: [
|
|
28
|
+
`${prefix}/${defaults.libDir}/${defaults.srcDir}/*`
|
|
29
|
+
]
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
var pathResolver = ({
|
|
33
|
+
appRoot,
|
|
34
|
+
sourceFolder
|
|
35
|
+
}) => {
|
|
36
|
+
const createPath = (...a) => {
|
|
37
|
+
return appRoot ? join(appRoot, ...a) : join(...a);
|
|
38
|
+
};
|
|
39
|
+
const createImport = {
|
|
40
|
+
coreApi(...a) {
|
|
41
|
+
return join(defaults.appPrefix, defaults.coreDir, defaults.apiDir, ...a);
|
|
42
|
+
},
|
|
43
|
+
src(...a) {
|
|
44
|
+
return join(defaults.srcPrefix, sourceFolder, ...a);
|
|
45
|
+
},
|
|
46
|
+
config(...a) {
|
|
47
|
+
return this.src(defaults.configDir, ...a);
|
|
48
|
+
},
|
|
49
|
+
api(...a) {
|
|
50
|
+
return this.src(defaults.apiDir, ...a);
|
|
51
|
+
},
|
|
52
|
+
pages(...a) {
|
|
53
|
+
return this.src(defaults.pagesDir, ...a);
|
|
54
|
+
},
|
|
55
|
+
lib(...a) {
|
|
56
|
+
return join(defaults.libPrefix, sourceFolder, ...a);
|
|
57
|
+
},
|
|
58
|
+
libApi(...a) {
|
|
59
|
+
return this.lib(defaults.apiDir, ...a);
|
|
60
|
+
},
|
|
61
|
+
libEntry(...a) {
|
|
62
|
+
return this.lib(defaults.entryDir, ...a);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
return {
|
|
66
|
+
createPath: {
|
|
67
|
+
coreApi(...a) {
|
|
68
|
+
return createPath(defaults.coreDir, defaults.apiDir, ...a);
|
|
69
|
+
},
|
|
70
|
+
src(...a) {
|
|
71
|
+
return createPath(defaults.srcDir, sourceFolder, ...a);
|
|
72
|
+
},
|
|
73
|
+
api(...a) {
|
|
74
|
+
return this.src(defaults.apiDir, ...a);
|
|
75
|
+
},
|
|
76
|
+
pages(...a) {
|
|
77
|
+
return this.src(defaults.pagesDir, ...a);
|
|
78
|
+
},
|
|
79
|
+
config(...a) {
|
|
80
|
+
return this.src(defaults.configDir, ...a);
|
|
81
|
+
},
|
|
82
|
+
entry(...a) {
|
|
83
|
+
return this.src(defaults.entryDir, ...a);
|
|
84
|
+
},
|
|
85
|
+
lib(...a) {
|
|
86
|
+
return createPath(defaults.libDir, defaults.srcDir, sourceFolder, ...a);
|
|
87
|
+
},
|
|
88
|
+
libApi(...a) {
|
|
89
|
+
return this.lib(defaults.apiDir, ...a);
|
|
90
|
+
},
|
|
91
|
+
libEntry(...a) {
|
|
92
|
+
return this.lib(defaults.entryDir, ...a);
|
|
93
|
+
},
|
|
94
|
+
libPages(...a) {
|
|
95
|
+
return this.lib(defaults.pagesDir, ...a);
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
createImport,
|
|
99
|
+
createImportHelper: (key, ...a) => {
|
|
100
|
+
return createImport[key](...a.slice(0, -1));
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// src/alias-plugin/index.ts
|
|
7
106
|
var alias_plugin_default = (appRoot, opt) => {
|
|
8
107
|
return {
|
|
9
108
|
name: "@kosmojs:aliasPlugin",
|
|
10
109
|
async config() {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
110
|
+
const paths = await import(`${appRoot}/tsconfig.json`, { with: { type: "json" } }).then((e) => {
|
|
111
|
+
return {
|
|
112
|
+
...e.default.compilerOptions?.paths,
|
|
113
|
+
...createTsconfigPaths(".")
|
|
114
|
+
};
|
|
115
|
+
});
|
|
14
116
|
const aliasmap = [];
|
|
15
|
-
const pathEntries = Object.entries(
|
|
117
|
+
const pathEntries = Object.entries(paths);
|
|
16
118
|
for (const [aliasPattern, pathPatterns] of pathEntries) {
|
|
17
119
|
const alias = aliasPattern.replace("/*", "");
|
|
18
|
-
const
|
|
19
|
-
if (
|
|
120
|
+
const paths2 = pathPatterns.map((e) => e.replace("/*", "")).sort((a, b) => a.split(/\/+/).length - b.split(/\/+/).length);
|
|
121
|
+
if (paths2.length === 1) {
|
|
20
122
|
aliasmap.push({
|
|
21
123
|
find: new RegExp(`^${alias}/`),
|
|
22
|
-
replacement: `${appRoot}/${
|
|
124
|
+
replacement: `${appRoot}/${paths2[0]}/`
|
|
23
125
|
});
|
|
24
|
-
} else if (
|
|
126
|
+
} else if (paths2.length > 1) {
|
|
25
127
|
aliasmap.push({
|
|
26
128
|
find: new RegExp(`^${alias}/`),
|
|
27
129
|
replacement: "",
|
|
28
130
|
async customResolver(_src) {
|
|
29
131
|
const src = _src.replace(/(\$|\^|\+|\(|\)|\[|\])/g, "\\$1");
|
|
30
|
-
const patterns =
|
|
132
|
+
const patterns = paths2.flatMap((path) => [
|
|
31
133
|
// Case 1: Extension is explicitly provided
|
|
32
134
|
// e.g. import styles from "@admin/{solid}/styles.module.css"
|
|
33
135
|
`${path}/${src}*`,
|
|
@@ -67,111 +169,33 @@ var alias_plugin_default = (appRoot, opt) => {
|
|
|
67
169
|
};
|
|
68
170
|
|
|
69
171
|
// src/base-plugin/index.ts
|
|
70
|
-
import {
|
|
71
|
-
import {
|
|
172
|
+
import { writeFile as writeFile3 } from "node:fs/promises";
|
|
173
|
+
import { basename as basename2, join as join5, resolve as resolve5 } from "node:path";
|
|
174
|
+
import { styleText as styleText4 } from "node:util";
|
|
72
175
|
import { Worker } from "node:worker_threads";
|
|
73
|
-
import apiGenerator from "@kosmojs/api-generator";
|
|
74
176
|
import stubGenerator from "@kosmojs/dev/stub-generator";
|
|
75
|
-
import fetchGenerator from "@kosmojs/fetch-generator";
|
|
76
177
|
|
|
77
|
-
// src/
|
|
78
|
-
import { join, resolve } from "node:path";
|
|
79
|
-
import { styleText } from "node:util";
|
|
80
|
-
import
|
|
81
|
-
import
|
|
82
|
-
var api_handler_default = async (options) => {
|
|
83
|
-
const { appRoot, sourceFolder, baseurl, apiurl } = options;
|
|
84
|
-
const apiDir = join(sourceFolder, defaults.apiDir);
|
|
85
|
-
const outDir = join(options.outDir, defaults.apiDir);
|
|
86
|
-
const esbuildOptions = await import(resolve(appRoot, "esbuild.json"), { with: { type: "json" } }).then((e) => e.default);
|
|
87
|
-
let app;
|
|
88
|
-
let devMiddlewareFactory;
|
|
89
|
-
let teardownHandler;
|
|
90
|
-
const watcher = async () => {
|
|
91
|
-
const rebuildPlugin = {
|
|
92
|
-
name: "rebuild",
|
|
93
|
-
setup(build) {
|
|
94
|
-
build.onEnd(async () => {
|
|
95
|
-
if (app) {
|
|
96
|
-
await teardownHandler?.(app);
|
|
97
|
-
}
|
|
98
|
-
try {
|
|
99
|
-
const exports = await import(`${outDir}/app.js?${Date.now()}`);
|
|
100
|
-
devMiddlewareFactory = exports.devMiddlewareFactory;
|
|
101
|
-
teardownHandler = exports.teardownHandler;
|
|
102
|
-
app = await exports.default();
|
|
103
|
-
console.debug(`${styleText("green", "\u279C")} Api handler ready`);
|
|
104
|
-
} catch (error) {
|
|
105
|
-
console.error(`${styleText("red", "\u2717")} Api handler error`);
|
|
106
|
-
console.error(error);
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
const ctx = await context({
|
|
112
|
-
...esbuildOptions,
|
|
113
|
-
logLevel: "error",
|
|
114
|
-
bundle: true,
|
|
115
|
-
entryPoints: [join(apiDir, "app.ts")],
|
|
116
|
-
plugins: [rebuildPlugin],
|
|
117
|
-
outdir: outDir
|
|
118
|
-
});
|
|
119
|
-
return {
|
|
120
|
-
async start() {
|
|
121
|
-
await ctx.watch({
|
|
122
|
-
// waits this many milliseconds before rebuilding after a change is detected
|
|
123
|
-
delay: options.watcher.delay
|
|
124
|
-
});
|
|
125
|
-
},
|
|
126
|
-
async stop() {
|
|
127
|
-
await ctx.dispose();
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
};
|
|
131
|
-
const devMiddleware = async (req, res, viteHandler) => {
|
|
132
|
-
const next = () => {
|
|
133
|
-
return viteHandler();
|
|
134
|
-
};
|
|
135
|
-
if (devMiddlewareFactory) {
|
|
136
|
-
const handler = devMiddlewareFactory(app);
|
|
137
|
-
await handler(req, res, next);
|
|
138
|
-
} else {
|
|
139
|
-
!req?.url || !new RegExp(`^${join(baseurl, apiurl)}($|/)`).test(req.url) ? next() : await app?.callback()(req, res);
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
return {
|
|
143
|
-
watcher,
|
|
144
|
-
devMiddleware
|
|
145
|
-
};
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
// src/base-plugin/routes.ts
|
|
149
|
-
import {
|
|
150
|
-
defaults as defaults3
|
|
151
|
-
} from "@kosmojs/devlib";
|
|
152
|
-
|
|
153
|
-
// src/base-plugin/routes/resolve.ts
|
|
154
|
-
import { dirname as dirname2, join as join2, resolve as resolve4 } from "node:path";
|
|
155
|
-
import crc3 from "crc/crc32";
|
|
178
|
+
// src/routes-factory/resolve.ts
|
|
179
|
+
import { dirname as dirname3, join as join3, resolve as resolve3 } from "node:path";
|
|
180
|
+
import { styleText as styleText2 } from "node:util";
|
|
181
|
+
import crc5 from "crc/crc32";
|
|
182
|
+
import mimeTypes from "mime-types";
|
|
156
183
|
import picomatch from "picomatch";
|
|
157
184
|
import { glob as glob2 } from "tinyglobby";
|
|
158
|
-
import {
|
|
159
|
-
defaults as defaults2,
|
|
160
|
-
pathResolver as pathResolver2,
|
|
161
|
-
pathTokensFactory,
|
|
162
|
-
render,
|
|
163
|
-
renderToFile
|
|
164
|
-
} from "@kosmojs/devlib";
|
|
165
185
|
|
|
166
|
-
// src/
|
|
167
|
-
import { resolve
|
|
186
|
+
// src/ast.ts
|
|
187
|
+
import { resolve } from "node:path";
|
|
188
|
+
import { styleText } from "node:util";
|
|
168
189
|
import crc from "crc/crc32";
|
|
169
190
|
import { flattener } from "tfusion";
|
|
170
191
|
import {
|
|
171
192
|
Project,
|
|
172
193
|
SyntaxKind
|
|
173
194
|
} from "ts-morph";
|
|
174
|
-
import {
|
|
195
|
+
import {
|
|
196
|
+
HTTPMethods,
|
|
197
|
+
RequestValidationTargets
|
|
198
|
+
} from "@kosmojs/api";
|
|
175
199
|
var createProject = (opts) => new Project(opts);
|
|
176
200
|
var resolveRouteSignature = async (route, opts) => {
|
|
177
201
|
const {
|
|
@@ -183,19 +207,12 @@ var resolveRouteSignature = async (route, opts) => {
|
|
|
183
207
|
);
|
|
184
208
|
const defaultExport = extractDefaultExport(sourceFile);
|
|
185
209
|
const paramsRefinements = defaultExport ? extractParamsRefinements(defaultExport) : void 0;
|
|
186
|
-
const methods = defaultExport ? extractRouteMethods(
|
|
187
|
-
const payloadTypes = methods.flatMap((e) => {
|
|
188
|
-
return e.payloadType ? [e.payloadType] : [];
|
|
189
|
-
});
|
|
190
|
-
const responseTypes = methods.flatMap((e) => {
|
|
191
|
-
return e.responseType ? [e.responseType] : [];
|
|
192
|
-
});
|
|
210
|
+
const methods = defaultExport ? extractRouteMethods(route, defaultExport) : [];
|
|
193
211
|
return {
|
|
194
212
|
typeDeclarations,
|
|
195
213
|
paramsRefinements,
|
|
196
214
|
methods: methods.map((e) => e.method),
|
|
197
|
-
|
|
198
|
-
responseTypes,
|
|
215
|
+
validationDefinitions: methods.flatMap((e) => e.validationDefinitions),
|
|
199
216
|
referencedFiles
|
|
200
217
|
};
|
|
201
218
|
};
|
|
@@ -210,22 +227,23 @@ var extractDefaultExport = (sourceFile) => {
|
|
|
210
227
|
return defaultExport;
|
|
211
228
|
};
|
|
212
229
|
var extractParamsRefinements = (callExpression) => {
|
|
213
|
-
const [
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
230
|
+
const [
|
|
231
|
+
_routeName,
|
|
232
|
+
// first generic - the route name
|
|
233
|
+
paramsGeneric
|
|
234
|
+
// second generic - params refinements
|
|
235
|
+
] = extractGenerics(callExpression);
|
|
236
|
+
if (!paramsGeneric?.isKind(SyntaxKind.TupleType)) {
|
|
219
237
|
return;
|
|
220
238
|
}
|
|
221
|
-
return
|
|
239
|
+
return paramsGeneric.getElements().map((node, index) => {
|
|
222
240
|
return {
|
|
223
241
|
index,
|
|
224
242
|
text: node.getText()
|
|
225
243
|
};
|
|
226
244
|
});
|
|
227
245
|
};
|
|
228
|
-
var extractRouteMethods = (
|
|
246
|
+
var extractRouteMethods = (route, callExpression) => {
|
|
229
247
|
const funcDeclaration = callExpression.getFirstChildByKind(SyntaxKind.ArrowFunction) || callExpression.getFirstChildByKind(SyntaxKind.FunctionExpression);
|
|
230
248
|
if (!funcDeclaration) {
|
|
231
249
|
return [];
|
|
@@ -246,35 +264,173 @@ var extractRouteMethods = (callExpression, route) => {
|
|
|
246
264
|
}
|
|
247
265
|
}
|
|
248
266
|
const methods = [];
|
|
249
|
-
const skipValidationFilter = (e) => /@skip-validation/.test(e);
|
|
250
267
|
for (const [callExpression2, method] of callExpressions) {
|
|
251
|
-
const [
|
|
252
|
-
const payloadText = payloadGeneric?.node ? payloadGeneric.node.getChildren().length === 0 ? "{}" : payloadGeneric.node.getFullText() : void 0;
|
|
253
|
-
const responseText = responseGeneric?.node.getText();
|
|
254
|
-
const responseType = responseText ? {
|
|
255
|
-
id: ["ResponseT", crc(route.importName + method)].join(""),
|
|
256
|
-
method,
|
|
257
|
-
skipValidation: responseGeneric?.comments ? responseGeneric.comments.some(skipValidationFilter) : false,
|
|
258
|
-
text: ["never", "object"].includes(responseText) ? "{}" : responseText,
|
|
259
|
-
resolvedType: void 0
|
|
260
|
-
} : void 0;
|
|
261
|
-
const payloadType = payloadText ? {
|
|
262
|
-
id: ["PayloadT", crc(route.importName + method)].join(""),
|
|
263
|
-
responseTypeId: responseType?.id,
|
|
264
|
-
method,
|
|
265
|
-
skipValidation: payloadGeneric?.comments ? payloadGeneric.comments.some(skipValidationFilter) : false,
|
|
266
|
-
isOptional: payloadText ? payloadText === "{}" || route.optionalParams : true,
|
|
267
|
-
text: payloadText,
|
|
268
|
-
resolvedType: void 0
|
|
269
|
-
} : void 0;
|
|
268
|
+
const [vDefs, vOpts] = extractGenerics(callExpression2);
|
|
270
269
|
methods.push({
|
|
271
270
|
method,
|
|
272
|
-
|
|
273
|
-
|
|
271
|
+
validationDefinitions: extractValidationDefinitions(
|
|
272
|
+
route,
|
|
273
|
+
method,
|
|
274
|
+
vDefs,
|
|
275
|
+
vOpts
|
|
276
|
+
)
|
|
274
277
|
});
|
|
275
278
|
}
|
|
276
279
|
return methods;
|
|
277
280
|
};
|
|
281
|
+
var parseRuntimeValidation = (typeNode) => {
|
|
282
|
+
if (typeNode.isKind(SyntaxKind.LiteralType)) {
|
|
283
|
+
const literal = typeNode.getFirstChild();
|
|
284
|
+
if (literal?.isKind(SyntaxKind.TrueKeyword)) {
|
|
285
|
+
return true;
|
|
286
|
+
} else if (literal?.isKind(SyntaxKind.FalseKeyword)) {
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return void 0;
|
|
291
|
+
};
|
|
292
|
+
var extractResponseVariant = (typeNode) => {
|
|
293
|
+
if (!typeNode.isKind(SyntaxKind.TupleType)) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
let status = 200;
|
|
297
|
+
let contentType;
|
|
298
|
+
let body;
|
|
299
|
+
const [statusNode, contentTypeNode, bodyNode] = typeNode.getElements();
|
|
300
|
+
if (statusNode?.isKind(SyntaxKind.LiteralType)) {
|
|
301
|
+
const literal = statusNode.getFirstChildByKind(SyntaxKind.NumericLiteral);
|
|
302
|
+
if (literal) {
|
|
303
|
+
status = Number(literal.getText());
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
if (contentTypeNode) {
|
|
307
|
+
contentType = extractStringLiteral(contentTypeNode);
|
|
308
|
+
}
|
|
309
|
+
if (bodyNode) {
|
|
310
|
+
body = bodyNode.getText();
|
|
311
|
+
if (["object"].includes(body)) {
|
|
312
|
+
body = "{}";
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
return { status, contentType, body };
|
|
316
|
+
};
|
|
317
|
+
var parseValidationOptions = (typeNode) => {
|
|
318
|
+
const opts = {};
|
|
319
|
+
if (!typeNode?.isKind(SyntaxKind.TypeLiteral)) {
|
|
320
|
+
return opts;
|
|
321
|
+
}
|
|
322
|
+
for (const prop of typeNode.getMembers()) {
|
|
323
|
+
if (!prop.isKind(SyntaxKind.PropertySignature)) {
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
const target = prop.getName();
|
|
327
|
+
const typeNode2 = prop.getTypeNodeOrThrow();
|
|
328
|
+
if (!typeNode2.isKind(SyntaxKind.TypeLiteral)) {
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
let contentType;
|
|
332
|
+
let runtimeValidation;
|
|
333
|
+
const customErrors = {};
|
|
334
|
+
for (const member of typeNode2.getMembers()) {
|
|
335
|
+
if (!member.isKind(SyntaxKind.PropertySignature)) {
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
const nameNode = member.getNameNode();
|
|
339
|
+
const valueNode = member.getTypeNodeOrThrow();
|
|
340
|
+
const name = nameNode.isKind(SyntaxKind.StringLiteral) ? nameNode.getLiteralText() : nameNode.getText();
|
|
341
|
+
if (name === "contentType") {
|
|
342
|
+
contentType = extractStringLiteral(valueNode);
|
|
343
|
+
} else if (name === "runtimeValidation") {
|
|
344
|
+
runtimeValidation = parseRuntimeValidation(valueNode);
|
|
345
|
+
} else if (name.startsWith("error")) {
|
|
346
|
+
const literal = extractStringLiteral(valueNode);
|
|
347
|
+
if (literal) {
|
|
348
|
+
customErrors[name] = literal;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
opts[target] = {
|
|
353
|
+
contentType,
|
|
354
|
+
runtimeValidation,
|
|
355
|
+
customErrors
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
return opts;
|
|
359
|
+
};
|
|
360
|
+
var extractStringLiteral = (typeNode) => {
|
|
361
|
+
const literal = typeNode.isKind(SyntaxKind.LiteralType) ? typeNode.getFirstChildByKind(SyntaxKind.StringLiteral) : void 0;
|
|
362
|
+
return literal ? literal.getLiteralText() : void 0;
|
|
363
|
+
};
|
|
364
|
+
var extractValidationDefinitions = (route, method, defsNode, optsNode) => {
|
|
365
|
+
const definitions = [];
|
|
366
|
+
if (!defsNode?.isKind(SyntaxKind.TypeLiteral)) {
|
|
367
|
+
return definitions;
|
|
368
|
+
}
|
|
369
|
+
const optsMap = parseValidationOptions(optsNode);
|
|
370
|
+
const createId = (target, hash) => {
|
|
371
|
+
return [
|
|
372
|
+
target.replace(/^./, (c) => c.toUpperCase()),
|
|
373
|
+
"T",
|
|
374
|
+
method,
|
|
375
|
+
crc(route.id + hash)
|
|
376
|
+
].join("");
|
|
377
|
+
};
|
|
378
|
+
for (const prop of defsNode.getMembers()) {
|
|
379
|
+
if (!prop.isKind(SyntaxKind.PropertySignature)) {
|
|
380
|
+
continue;
|
|
381
|
+
}
|
|
382
|
+
const target = prop.getName();
|
|
383
|
+
const typeNode = prop.getTypeNodeOrThrow();
|
|
384
|
+
if (target === "response") {
|
|
385
|
+
const variants = typeNode.isKind(SyntaxKind.UnionType) ? typeNode.getChildrenOfKind(SyntaxKind.TupleType) : [typeNode];
|
|
386
|
+
definitions.push({
|
|
387
|
+
...optsMap[target],
|
|
388
|
+
method,
|
|
389
|
+
target,
|
|
390
|
+
variants: variants.flatMap((e, i) => {
|
|
391
|
+
const { status, contentType, body } = extractResponseVariant(e) || {};
|
|
392
|
+
if (!status) {
|
|
393
|
+
return [];
|
|
394
|
+
}
|
|
395
|
+
if (contentType && typeof contentType !== "string") {
|
|
396
|
+
console.warn(
|
|
397
|
+
styleText(
|
|
398
|
+
["bold", "red"],
|
|
399
|
+
`\u2717 The second element of a response variant should specify the Response Content Type`
|
|
400
|
+
)
|
|
401
|
+
);
|
|
402
|
+
console.warn(
|
|
403
|
+
styleText(["blue"], ` Example: [200, "json", Schema]`)
|
|
404
|
+
);
|
|
405
|
+
console.warn(
|
|
406
|
+
` Route: ${route.name}; Method: ${method}; Response Variant: #${i}`
|
|
407
|
+
);
|
|
408
|
+
console.warn();
|
|
409
|
+
}
|
|
410
|
+
return [
|
|
411
|
+
{
|
|
412
|
+
id: createId(target, JSON.stringify([status, contentType, body])),
|
|
413
|
+
status,
|
|
414
|
+
contentType,
|
|
415
|
+
body
|
|
416
|
+
}
|
|
417
|
+
];
|
|
418
|
+
})
|
|
419
|
+
});
|
|
420
|
+
} else if (Object.keys(RequestValidationTargets).includes(target)) {
|
|
421
|
+
definitions.push({
|
|
422
|
+
...optsMap[target],
|
|
423
|
+
method,
|
|
424
|
+
target,
|
|
425
|
+
schema: {
|
|
426
|
+
id: createId(target),
|
|
427
|
+
text: typeNode.getText()
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
return definitions;
|
|
433
|
+
};
|
|
278
434
|
var extractTypeDeclarations = (sourceFile, opts) => {
|
|
279
435
|
const declarations = [];
|
|
280
436
|
const referencedFiles = opts?.withReferencedFiles ? [] : void 0;
|
|
@@ -379,16 +535,11 @@ var getReferencedFiles = (importIdentifier) => {
|
|
|
379
535
|
});
|
|
380
536
|
};
|
|
381
537
|
var extractGenerics = (callExpression) => {
|
|
382
|
-
return callExpression.getTypeArguments()
|
|
383
|
-
return {
|
|
384
|
-
node,
|
|
385
|
-
comments: node.getLeadingCommentRanges().map((range) => range.getText().trim())
|
|
386
|
-
};
|
|
387
|
-
});
|
|
538
|
+
return callExpression.getTypeArguments();
|
|
388
539
|
};
|
|
389
540
|
var typeResolverFactory = ({ appRoot }) => {
|
|
390
541
|
const project = createProject({
|
|
391
|
-
tsConfigFilePath:
|
|
542
|
+
tsConfigFilePath: resolve(appRoot, "tsconfig.json"),
|
|
392
543
|
skipAddingFilesFromTsConfig: true
|
|
393
544
|
});
|
|
394
545
|
const literalTypesResolver = (literalTypes, options) => {
|
|
@@ -418,12 +569,24 @@ var typeResolverFactory = ({ appRoot }) => {
|
|
|
418
569
|
};
|
|
419
570
|
};
|
|
420
571
|
|
|
421
|
-
// src/
|
|
572
|
+
// src/cache.ts
|
|
422
573
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
423
|
-
import { dirname, resolve as
|
|
574
|
+
import { dirname, resolve as resolve2 } from "node:path";
|
|
424
575
|
import crc2 from "crc/crc32";
|
|
425
576
|
import self from "@kosmojs/dev/package.json" with { type: "json" };
|
|
426
|
-
|
|
577
|
+
|
|
578
|
+
// src/fs.ts
|
|
579
|
+
import { access, constants } from "node:fs/promises";
|
|
580
|
+
var pathExists = async (path) => {
|
|
581
|
+
try {
|
|
582
|
+
await access(path, constants.F_OK);
|
|
583
|
+
return true;
|
|
584
|
+
} catch {
|
|
585
|
+
return false;
|
|
586
|
+
}
|
|
587
|
+
};
|
|
588
|
+
|
|
589
|
+
// src/cache.ts
|
|
427
590
|
var cacheFactory = (route, {
|
|
428
591
|
appRoot,
|
|
429
592
|
sourceFolder,
|
|
@@ -432,7 +595,7 @@ var cacheFactory = (route, {
|
|
|
432
595
|
const cacheFile = pathResolver({
|
|
433
596
|
appRoot,
|
|
434
597
|
sourceFolder
|
|
435
|
-
}).
|
|
598
|
+
}).createPath.libApi(dirname(route.file), "cache.json");
|
|
436
599
|
const getCache = async (opt) => {
|
|
437
600
|
if (await pathExists(cacheFile)) {
|
|
438
601
|
try {
|
|
@@ -477,7 +640,7 @@ var cacheFactory = (route, {
|
|
|
477
640
|
return;
|
|
478
641
|
}
|
|
479
642
|
for (const [file, hash2] of Object.entries(cache.referencedFiles)) {
|
|
480
|
-
if (!identicalHashSum(hash2, await generateFileHash(
|
|
643
|
+
if (!identicalHashSum(hash2, await generateFileHash(resolve2(appRoot, file)))) {
|
|
481
644
|
return;
|
|
482
645
|
}
|
|
483
646
|
}
|
|
@@ -507,13 +670,232 @@ var identicalHashSum = (a, b) => {
|
|
|
507
670
|
return a === b;
|
|
508
671
|
};
|
|
509
672
|
|
|
510
|
-
// src/
|
|
673
|
+
// src/render.ts
|
|
674
|
+
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
|
|
675
|
+
import { dirname as dirname2, join as join2 } from "node:path";
|
|
676
|
+
import crc3 from "crc/crc32";
|
|
677
|
+
import handlebars from "handlebars";
|
|
678
|
+
var render = (template, context2, options) => {
|
|
679
|
+
const { noEscape = true, renderer = handlebars } = { ...options };
|
|
680
|
+
return renderer.compile(template, { noEscape })(context2);
|
|
681
|
+
};
|
|
682
|
+
var renderToFile = async (file, template, context2, options) => {
|
|
683
|
+
const content = render(template, context2, options);
|
|
684
|
+
if (await pathExists(file)) {
|
|
685
|
+
const { overwrite = true } = { ...options };
|
|
686
|
+
if (overwrite === false) {
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
const fileContent = await readFile2(file, "utf8");
|
|
690
|
+
if (typeof overwrite === "function" && !overwrite(fileContent)) {
|
|
691
|
+
return;
|
|
692
|
+
}
|
|
693
|
+
if (crc3(content) === crc3(fileContent)) {
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
await mkdir2(dirname2(file), { recursive: true });
|
|
698
|
+
await writeFile2(file, content, "utf8");
|
|
699
|
+
};
|
|
700
|
+
var renderFactory = (options) => {
|
|
701
|
+
const renderer = handlebars.create();
|
|
702
|
+
renderer.registerPartial({ ...options?.partials });
|
|
703
|
+
renderer.registerHelper({ ...options?.helpers });
|
|
704
|
+
return {
|
|
705
|
+
render(template, context2, selfOoptions) {
|
|
706
|
+
return render(template, context2, {
|
|
707
|
+
renderer,
|
|
708
|
+
...options,
|
|
709
|
+
...selfOoptions
|
|
710
|
+
});
|
|
711
|
+
},
|
|
712
|
+
async renderToFile(file, template, context2, selfOoptions) {
|
|
713
|
+
return renderToFile(
|
|
714
|
+
options?.outdir ? join2(options.outdir, file) : file,
|
|
715
|
+
template,
|
|
716
|
+
context2,
|
|
717
|
+
{ renderer, ...options, ...selfOoptions }
|
|
718
|
+
);
|
|
719
|
+
}
|
|
720
|
+
};
|
|
721
|
+
};
|
|
722
|
+
var renderHelpers = {
|
|
723
|
+
createParamsLiteral: (params) => {
|
|
724
|
+
return params.schema.map((p) => {
|
|
725
|
+
return p.kind === "splat" ? `${p.const}?: Array<string | number>` : p.kind === "optional" ? `${p.const}?: string | number` : `${p.const}: string | number`;
|
|
726
|
+
}).join(", ");
|
|
727
|
+
}
|
|
728
|
+
};
|
|
729
|
+
|
|
730
|
+
// src/routes-factory/base.ts
|
|
731
|
+
import crc4 from "crc/crc32";
|
|
732
|
+
import { parse } from "path-to-regexp";
|
|
733
|
+
var pathTokensFactory = (path, {
|
|
734
|
+
transformStaticValue = normalizeStaticValue
|
|
735
|
+
} = {}) => {
|
|
736
|
+
const extractParts = (tokens2, createConst, insideGroup = false) => {
|
|
737
|
+
const parts = [];
|
|
738
|
+
for (const token of tokens2) {
|
|
739
|
+
switch (token.type) {
|
|
740
|
+
case "text":
|
|
741
|
+
if (token.value !== "/") {
|
|
742
|
+
parts.push({
|
|
743
|
+
type: "static",
|
|
744
|
+
value: transformStaticValue(token.value)
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
break;
|
|
748
|
+
case "param":
|
|
749
|
+
parts.push({
|
|
750
|
+
type: "param",
|
|
751
|
+
kind: insideGroup ? "optional" : "required",
|
|
752
|
+
name: token.name,
|
|
753
|
+
const: createConst(token.name)
|
|
754
|
+
});
|
|
755
|
+
break;
|
|
756
|
+
case "wildcard":
|
|
757
|
+
parts.push({
|
|
758
|
+
type: "param",
|
|
759
|
+
kind: "splat",
|
|
760
|
+
name: token.name,
|
|
761
|
+
const: createConst(token.name)
|
|
762
|
+
});
|
|
763
|
+
break;
|
|
764
|
+
case "group":
|
|
765
|
+
parts.push(...extractParts(token.tokens, createConst, true));
|
|
766
|
+
break;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
return parts;
|
|
770
|
+
};
|
|
771
|
+
const patternTransforms = [
|
|
772
|
+
// Transform required params: [id] => :id
|
|
773
|
+
// Only pure \w param names,
|
|
774
|
+
// [some-id] used as is, not treated as param,
|
|
775
|
+
// use [some_id] instead.
|
|
776
|
+
(s) => s.replace(/\[(\w+)\]/g, ":$1"),
|
|
777
|
+
// Transform optional params: {id} => {:id}
|
|
778
|
+
// Only pure \w param names,
|
|
779
|
+
// anything else treated as a path-to-regexp pattern and used as is.
|
|
780
|
+
// {some-id} treated as an optional static segment.
|
|
781
|
+
// use {some_id} for simple param syntax
|
|
782
|
+
// or {:some-id} pattern where :some is the param name and -id is a static segment.
|
|
783
|
+
(s) => s.replace(/\{(\w+)\}/g, "{:$1}"),
|
|
784
|
+
// Transform splat params: {...param} => {*param}
|
|
785
|
+
(s) => s.replace(/\{\.\.\./g, "{*"),
|
|
786
|
+
// Insert leading slash inside optional/splat groups.
|
|
787
|
+
// {:name} => {/:name}
|
|
788
|
+
// {*name} => {/*name}
|
|
789
|
+
(s) => {
|
|
790
|
+
return s.startsWith("{") ? s.replace(/^\{/, "{/") : s;
|
|
791
|
+
}
|
|
792
|
+
];
|
|
793
|
+
const detectBareParams = (s) => {
|
|
794
|
+
let depth = 0;
|
|
795
|
+
for (const [i, ch] of [...s].entries()) {
|
|
796
|
+
if (ch === "{") {
|
|
797
|
+
depth += 1;
|
|
798
|
+
} else if (ch === "}") {
|
|
799
|
+
depth -= 1;
|
|
800
|
+
} else if (ch === ":" && depth === 0) {
|
|
801
|
+
const match = s.slice(i + 1).match(/^\w+/);
|
|
802
|
+
return match?.[0] || ":";
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
return;
|
|
806
|
+
};
|
|
807
|
+
const tokens = path.replace(/^index\/?/, "").split("/").flatMap((orig) => {
|
|
808
|
+
if (!orig.length) {
|
|
809
|
+
return [];
|
|
810
|
+
}
|
|
811
|
+
const bareParam = detectBareParams(orig);
|
|
812
|
+
if (bareParam === ":") {
|
|
813
|
+
throw new Error(
|
|
814
|
+
`${path} contains colons outside braces, use : only within {}`
|
|
815
|
+
);
|
|
816
|
+
} else if (bareParam) {
|
|
817
|
+
throw new Error(
|
|
818
|
+
`${path} contains bare params, use [${bareParam}] instead of :${bareParam}`
|
|
819
|
+
);
|
|
820
|
+
}
|
|
821
|
+
const pattern = patternTransforms.reduce((src, fn) => fn(src), orig);
|
|
822
|
+
const { tokens: tokens2 } = parse(pattern);
|
|
823
|
+
const parts = extractParts(tokens2, (val) => {
|
|
824
|
+
return /\W/.test(val) || /^\d/.test(val) ? [val.replace(/^\d+|\W/g, "_"), crc4(orig)].join("_") : val;
|
|
825
|
+
});
|
|
826
|
+
const isStatic = parts.length === 1 ? parts[0].type === "static" : false;
|
|
827
|
+
const isParam = parts.length === 1 ? parts[0].type === "param" : false;
|
|
828
|
+
const kind = isStatic ? "static" : isParam ? "param" : "mixed";
|
|
829
|
+
return [
|
|
830
|
+
{
|
|
831
|
+
kind,
|
|
832
|
+
orig,
|
|
833
|
+
pattern,
|
|
834
|
+
parts
|
|
835
|
+
}
|
|
836
|
+
];
|
|
837
|
+
});
|
|
838
|
+
return [
|
|
839
|
+
tokens,
|
|
840
|
+
tokens.map(({ pattern }, i) => {
|
|
841
|
+
const next = tokens[i + 1];
|
|
842
|
+
if (!next || next.pattern.includes("/")) {
|
|
843
|
+
return pattern;
|
|
844
|
+
}
|
|
845
|
+
const slashRequired = tokens.slice(i + 1).some((e) => {
|
|
846
|
+
return e.parts.some((e2) => {
|
|
847
|
+
return e2.type === "static" || e2.kind === "required";
|
|
848
|
+
});
|
|
849
|
+
});
|
|
850
|
+
return slashRequired ? `${pattern}/` : pattern;
|
|
851
|
+
}).join("")
|
|
852
|
+
];
|
|
853
|
+
};
|
|
854
|
+
var normalizeStaticValue = (value) => {
|
|
855
|
+
return value.replace(/\+/g, "\\\\+");
|
|
856
|
+
};
|
|
857
|
+
var sortRoutes = (a, b) => {
|
|
858
|
+
const aSpecificity = routeSpecificity(a.pathTokens);
|
|
859
|
+
const bSpecificity = routeSpecificity(b.pathTokens);
|
|
860
|
+
if (aSpecificity !== bSpecificity) {
|
|
861
|
+
return bSpecificity - aSpecificity;
|
|
862
|
+
}
|
|
863
|
+
if (a.pathTokens.length !== b.pathTokens.length) {
|
|
864
|
+
return a.pathTokens.length - b.pathTokens.length;
|
|
865
|
+
}
|
|
866
|
+
return a.name.localeCompare(b.name);
|
|
867
|
+
};
|
|
868
|
+
var paramWeight = (part) => {
|
|
869
|
+
return {
|
|
870
|
+
required: 2,
|
|
871
|
+
optional: 1,
|
|
872
|
+
splat: 0
|
|
873
|
+
}[part.kind];
|
|
874
|
+
};
|
|
875
|
+
var mixedSegmentWeight = (parts) => {
|
|
876
|
+
const hasSplat = parts.some((p) => {
|
|
877
|
+
return p.type === "param" ? p.kind === "splat" : false;
|
|
878
|
+
});
|
|
879
|
+
return hasSplat ? 0.5 : 3;
|
|
880
|
+
};
|
|
881
|
+
var segmentWeight = (token) => {
|
|
882
|
+
return {
|
|
883
|
+
static: 4,
|
|
884
|
+
mixed: mixedSegmentWeight(token.parts),
|
|
885
|
+
param: paramWeight(token.parts[0])
|
|
886
|
+
}[token.kind];
|
|
887
|
+
};
|
|
888
|
+
var routeSpecificity = (pathTokens) => {
|
|
889
|
+
return pathTokens.reduce((sum, token) => sum + segmentWeight(token), 0);
|
|
890
|
+
};
|
|
891
|
+
|
|
892
|
+
// src/routes-factory/templates/resolved-types.hbs
|
|
511
893
|
var resolved_types_default = "{{#each resolvedTypes}}\nexport type {{name}} = {{text}};\n{{/each}}\n";
|
|
512
894
|
|
|
513
|
-
// src/
|
|
514
|
-
var types_default = '{{#each typeDeclarations}}{{text}}\n{{/each}}\n\nexport type {{params.id}} = {\n {{#each paramsSchema}}\n "{{name}}"{{#unless isRequired}}?{{/unless}}:{{#if
|
|
895
|
+
// src/routes-factory/templates/types.hbs
|
|
896
|
+
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';
|
|
515
897
|
|
|
516
|
-
// src/
|
|
898
|
+
// src/routes-factory/resolve.ts
|
|
517
899
|
var API_INDEX_BASENAME = "index";
|
|
518
900
|
var API_INDEX_PATTERN = `${API_INDEX_BASENAME}.ts`;
|
|
519
901
|
var API_USE_BASENAME = "use";
|
|
@@ -524,29 +906,30 @@ var PAGE_LAYOUT_BASENAME = "layout";
|
|
|
524
906
|
var PAGE_LAYOUT_PATTERN = `${PAGE_LAYOUT_BASENAME}.{tsx,vue}`;
|
|
525
907
|
var ROUTE_FILE_PATTERNS = [
|
|
526
908
|
// match index files in api dir
|
|
527
|
-
`${
|
|
909
|
+
`${defaults.apiDir}/**/${API_INDEX_PATTERN}`,
|
|
528
910
|
// match use files in api dir
|
|
529
|
-
`${
|
|
911
|
+
`${defaults.apiDir}/**/${API_USE_PATTERN}`,
|
|
530
912
|
// match index files in pages dir
|
|
531
|
-
`${
|
|
913
|
+
`${defaults.pagesDir}/**/${PAGE_INDEX_PATTERN}`,
|
|
532
914
|
// match layout files in pages dir
|
|
533
|
-
`${
|
|
915
|
+
`${defaults.pagesDir}/**/${PAGE_LAYOUT_PATTERN}`
|
|
534
916
|
];
|
|
535
917
|
var scanRoutes = async ({
|
|
536
918
|
appRoot,
|
|
537
919
|
sourceFolder
|
|
538
920
|
}) => {
|
|
921
|
+
const { createPath } = pathResolver({ appRoot, sourceFolder });
|
|
539
922
|
return glob2(ROUTE_FILE_PATTERNS, {
|
|
540
|
-
cwd:
|
|
923
|
+
cwd: createPath.src(),
|
|
541
924
|
absolute: true,
|
|
542
925
|
onlyFiles: true,
|
|
543
926
|
followSymbolicLinks: false,
|
|
544
927
|
ignore: [
|
|
545
928
|
// ignore top-level matches, routes resides in folders, even index route
|
|
546
|
-
`${
|
|
547
|
-
`${
|
|
548
|
-
`${
|
|
549
|
-
`${
|
|
929
|
+
`${defaults.apiDir}/${API_INDEX_PATTERN}`,
|
|
930
|
+
`${defaults.apiDir}/${API_USE_PATTERN}`,
|
|
931
|
+
`${defaults.pagesDir}/${PAGE_INDEX_PATTERN}`,
|
|
932
|
+
`${defaults.pagesDir}/${PAGE_LAYOUT_PATTERN}`
|
|
550
933
|
]
|
|
551
934
|
});
|
|
552
935
|
};
|
|
@@ -554,11 +937,11 @@ var isRouteFile = (file, {
|
|
|
554
937
|
appRoot,
|
|
555
938
|
sourceFolder
|
|
556
939
|
}) => {
|
|
557
|
-
const [_sourceFolder, folder, ...rest] =
|
|
940
|
+
const [_sourceFolder, folder, ...rest] = resolve3(appRoot, file).replace(`${appRoot}/${defaults.srcDir}/`, "").split("/");
|
|
558
941
|
if (!folder || _sourceFolder !== sourceFolder || rest.length < 2) {
|
|
559
|
-
return;
|
|
942
|
+
return false;
|
|
560
943
|
}
|
|
561
|
-
return picomatch.isMatch(
|
|
944
|
+
return picomatch.isMatch(join3(folder, ...rest), ROUTE_FILE_PATTERNS) ? [folder, rest.join("/")] : false;
|
|
562
945
|
};
|
|
563
946
|
var isApiRoute = (file) => {
|
|
564
947
|
return picomatch.matchBase(file, `**/${API_INDEX_PATTERN}`);
|
|
@@ -572,29 +955,27 @@ var isPageRoute = (file) => {
|
|
|
572
955
|
var isPageLayout = (file) => {
|
|
573
956
|
return picomatch.matchBase(file, `**/${PAGE_LAYOUT_PATTERN}`);
|
|
574
957
|
};
|
|
575
|
-
var createRouteEntry = (
|
|
958
|
+
var createRouteEntry = (fileFullpath, {
|
|
576
959
|
appRoot,
|
|
577
960
|
sourceFolder
|
|
578
961
|
}) => {
|
|
579
|
-
const resolvedPaths = isRouteFile(
|
|
962
|
+
const resolvedPaths = isRouteFile(fileFullpath, { appRoot, sourceFolder });
|
|
580
963
|
if (!resolvedPaths) {
|
|
581
964
|
return;
|
|
582
965
|
}
|
|
583
966
|
const [folder, file] = resolvedPaths;
|
|
584
|
-
const
|
|
585
|
-
const
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
importName
|
|
597
|
-
};
|
|
967
|
+
const id = `${file.replace(/\W+/g, "_")}_${crc5(file)}`;
|
|
968
|
+
const name = dirname3(file);
|
|
969
|
+
try {
|
|
970
|
+
const [pathTokens, pathPattern] = pathTokensFactory(dirname3(file));
|
|
971
|
+
return { id, name, folder, file, fileFullpath, pathTokens, pathPattern };
|
|
972
|
+
} catch (error) {
|
|
973
|
+
console.error(
|
|
974
|
+
`\u2757${styleText2("red", "ERROR")}: Failed parsing path for "${styleText2("cyan", file)}"`
|
|
975
|
+
);
|
|
976
|
+
console.error(error);
|
|
977
|
+
return;
|
|
978
|
+
}
|
|
598
979
|
};
|
|
599
980
|
var pageLayoutResolverFactory = () => {
|
|
600
981
|
return (entry) => {
|
|
@@ -610,27 +991,21 @@ var pageLayoutResolverFactory = () => {
|
|
|
610
991
|
};
|
|
611
992
|
var pageRouteResolverFactory = () => {
|
|
612
993
|
return (entry) => {
|
|
613
|
-
const {
|
|
614
|
-
name,
|
|
615
|
-
folder,
|
|
616
|
-
file,
|
|
617
|
-
fileFullpath,
|
|
618
|
-
pathTokens,
|
|
619
|
-
importFile,
|
|
620
|
-
importName
|
|
621
|
-
} = entry;
|
|
994
|
+
const { id, name, folder, file, fileFullpath, pathTokens, pathPattern } = entry;
|
|
622
995
|
const handler = async () => {
|
|
623
996
|
const entry2 = {
|
|
997
|
+
id,
|
|
624
998
|
name,
|
|
625
999
|
pathTokens,
|
|
1000
|
+
pathPattern,
|
|
626
1001
|
params: {
|
|
627
|
-
schema: pathTokens.flatMap((e) =>
|
|
1002
|
+
schema: pathTokens.flatMap((e) => {
|
|
1003
|
+
return e.parts.filter((p) => p.type === "param");
|
|
1004
|
+
})
|
|
628
1005
|
},
|
|
629
1006
|
folder,
|
|
630
1007
|
file,
|
|
631
|
-
fileFullpath
|
|
632
|
-
importFile,
|
|
633
|
-
importName
|
|
1008
|
+
fileFullpath
|
|
634
1009
|
};
|
|
635
1010
|
return {
|
|
636
1011
|
kind: "pageRoute",
|
|
@@ -657,38 +1032,35 @@ var apiRouteResolverFactory = (pluginOptions) => {
|
|
|
657
1032
|
appRoot,
|
|
658
1033
|
sourceFolder,
|
|
659
1034
|
generators = [],
|
|
660
|
-
formatters = [],
|
|
661
1035
|
refineTypeName
|
|
662
1036
|
} = pluginOptions;
|
|
663
|
-
|
|
664
|
-
for (const { options } of generators) {
|
|
665
|
-
if (options?.resolveTypes) {
|
|
666
|
-
resolveTypes = true;
|
|
667
|
-
}
|
|
668
|
-
}
|
|
1037
|
+
const resolveTypes = generators.some((e) => e.options?.resolveTypes);
|
|
669
1038
|
const {
|
|
670
1039
|
//
|
|
671
1040
|
literalTypesResolver,
|
|
672
1041
|
getSourceFile,
|
|
673
1042
|
refreshSourceFile
|
|
674
1043
|
} = typeResolverFactory(pluginOptions);
|
|
675
|
-
return (
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
} = entry;
|
|
1044
|
+
return ({
|
|
1045
|
+
id,
|
|
1046
|
+
name,
|
|
1047
|
+
file,
|
|
1048
|
+
folder,
|
|
1049
|
+
fileFullpath,
|
|
1050
|
+
pathTokens,
|
|
1051
|
+
pathPattern
|
|
1052
|
+
}) => {
|
|
685
1053
|
const handler = async (updatedFile) => {
|
|
686
|
-
const paramsSchema = pathTokens.flatMap(
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
1054
|
+
const paramsSchema = pathTokens.flatMap(
|
|
1055
|
+
(e) => {
|
|
1056
|
+
return e.parts.flatMap((p) => {
|
|
1057
|
+
return p.type === "param" ? [p] : [];
|
|
1058
|
+
});
|
|
1059
|
+
}
|
|
1060
|
+
);
|
|
1061
|
+
const optionalParams = paramsSchema.length ? paramsSchema.filter((e) => e.kind === "required").length === 0 : true;
|
|
690
1062
|
const { getCache, persistCache } = cacheFactory(
|
|
691
|
-
{ file, fileFullpath
|
|
1063
|
+
{ id, file, fileFullpath },
|
|
692
1064
|
{
|
|
693
1065
|
appRoot,
|
|
694
1066
|
sourceFolder,
|
|
@@ -704,19 +1076,23 @@ var apiRouteResolverFactory = (pluginOptions) => {
|
|
|
704
1076
|
typeDeclarations,
|
|
705
1077
|
paramsRefinements,
|
|
706
1078
|
methods,
|
|
707
|
-
|
|
708
|
-
responseTypes,
|
|
1079
|
+
validationDefinitions: validationDefinitions2,
|
|
709
1080
|
referencedFiles = []
|
|
710
1081
|
} = await resolveRouteSignature(
|
|
711
|
-
{
|
|
1082
|
+
{ id, name, fileFullpath, optionalParams },
|
|
712
1083
|
{
|
|
713
1084
|
withReferencedFiles: true,
|
|
714
1085
|
sourceFile: getSourceFile(fileFullpath),
|
|
715
1086
|
relpathResolver(path) {
|
|
716
|
-
return
|
|
1087
|
+
return join3(sourceFolder, defaults.apiDir, dirname3(file), path);
|
|
717
1088
|
}
|
|
718
1089
|
}
|
|
719
1090
|
);
|
|
1091
|
+
const validationTypes = validationDefinitions2.flatMap((def) => {
|
|
1092
|
+
return def.target === "response" ? def.variants.flatMap(({ id: id2, body }) => {
|
|
1093
|
+
return body ? [{ id: id2, text: body }] : [];
|
|
1094
|
+
}) : [def.schema];
|
|
1095
|
+
});
|
|
720
1096
|
const numericParams = paramsRefinements ? paramsRefinements.flatMap(({ text, index }) => {
|
|
721
1097
|
if (text === "number") {
|
|
722
1098
|
const param = paramsSchema.at(index);
|
|
@@ -724,13 +1100,12 @@ var apiRouteResolverFactory = (pluginOptions) => {
|
|
|
724
1100
|
}
|
|
725
1101
|
return [];
|
|
726
1102
|
}) : [];
|
|
727
|
-
const typesFile =
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
);
|
|
1103
|
+
const typesFile = pathResolver({
|
|
1104
|
+
appRoot,
|
|
1105
|
+
sourceFolder
|
|
1106
|
+
}).createPath.libApi(dirname3(file), "types.ts");
|
|
732
1107
|
const params = {
|
|
733
|
-
id: ["ParamsT",
|
|
1108
|
+
id: ["ParamsT", crc5(name)].join(""),
|
|
734
1109
|
schema: paramsSchema,
|
|
735
1110
|
resolvedType: void 0
|
|
736
1111
|
};
|
|
@@ -739,25 +1114,21 @@ var apiRouteResolverFactory = (pluginOptions) => {
|
|
|
739
1114
|
paramsSchema: paramsSchema.map((param, index) => {
|
|
740
1115
|
return {
|
|
741
1116
|
...param,
|
|
1117
|
+
isRequired: param.kind === "required",
|
|
1118
|
+
isSplat: param.kind === "splat",
|
|
742
1119
|
refinement: paramsRefinements?.at(index)
|
|
743
1120
|
};
|
|
744
1121
|
}),
|
|
745
1122
|
typeDeclarations,
|
|
746
|
-
|
|
747
|
-
responseTypes
|
|
1123
|
+
validationTypes
|
|
748
1124
|
});
|
|
749
1125
|
const resolvedTypes = resolveTypes ? literalTypesResolver(typesFileContent, {
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
},
|
|
757
|
-
{ [refineTypeName]: refineTypeName }
|
|
758
|
-
),
|
|
759
|
-
withProperties: [params.id, ...payloadTypes.map((e) => e.id)],
|
|
760
|
-
formatters
|
|
1126
|
+
stripComments: true,
|
|
1127
|
+
overrides: { [refineTypeName]: refineTypeName },
|
|
1128
|
+
withProperties: [
|
|
1129
|
+
params.id,
|
|
1130
|
+
...validationTypes.flatMap(({ id: id2 }) => id2)
|
|
1131
|
+
]
|
|
761
1132
|
}) : void 0;
|
|
762
1133
|
await renderToFile(
|
|
763
1134
|
typesFile,
|
|
@@ -770,59 +1141,205 @@ var apiRouteResolverFactory = (pluginOptions) => {
|
|
|
770
1141
|
methods,
|
|
771
1142
|
typeDeclarations,
|
|
772
1143
|
numericParams,
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
return {
|
|
776
|
-
...rest,
|
|
777
|
-
resolvedType: resolvedTypes?.find((e) => e.name === rest.id)
|
|
778
|
-
};
|
|
779
|
-
}),
|
|
780
|
-
responseTypes: responseTypes.map(({ text, ...rest }) => {
|
|
1144
|
+
referencedFiles,
|
|
1145
|
+
validationDefinitions: validationDefinitions2.map((def) => {
|
|
781
1146
|
return {
|
|
782
|
-
...
|
|
783
|
-
|
|
1147
|
+
...def,
|
|
1148
|
+
...def.target === "response" ? {
|
|
1149
|
+
variants: def.variants.map((variant) => {
|
|
1150
|
+
return {
|
|
1151
|
+
...variant,
|
|
1152
|
+
resolvedType: resolvedTypes?.find(
|
|
1153
|
+
(e) => e.name === variant.id
|
|
1154
|
+
)
|
|
1155
|
+
};
|
|
1156
|
+
})
|
|
1157
|
+
} : {
|
|
1158
|
+
schema: {
|
|
1159
|
+
...def.schema,
|
|
1160
|
+
resolvedType: resolvedTypes?.find(
|
|
1161
|
+
(e) => e.name === def.schema.id
|
|
1162
|
+
)
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
784
1165
|
};
|
|
785
|
-
})
|
|
786
|
-
referencedFiles
|
|
1166
|
+
})
|
|
787
1167
|
});
|
|
788
1168
|
}
|
|
789
|
-
const
|
|
1169
|
+
const validationDefinitions = cache.validationDefinitions.flatMap(
|
|
1170
|
+
(def) => {
|
|
1171
|
+
let augmentedDef = def;
|
|
1172
|
+
if (def.target === "response") {
|
|
1173
|
+
augmentedDef = {
|
|
1174
|
+
...def,
|
|
1175
|
+
variants: def.variants.flatMap((variant, i) => {
|
|
1176
|
+
if (typeof variant.contentType !== "string") {
|
|
1177
|
+
return [variant];
|
|
1178
|
+
}
|
|
1179
|
+
if (variant.contentType.includes("/")) {
|
|
1180
|
+
return [variant];
|
|
1181
|
+
}
|
|
1182
|
+
const contentType = mimeTypes.lookup(variant.contentType);
|
|
1183
|
+
if (contentType === false) {
|
|
1184
|
+
console.warn(
|
|
1185
|
+
styleText2(
|
|
1186
|
+
["bold", "red"],
|
|
1187
|
+
"\u2717 Failed resolving Response Content Type"
|
|
1188
|
+
)
|
|
1189
|
+
);
|
|
1190
|
+
console.warn(
|
|
1191
|
+
` Invalid value provided for mime-types lookup - ${variant.contentType}`
|
|
1192
|
+
);
|
|
1193
|
+
console.warn(
|
|
1194
|
+
styleText2(
|
|
1195
|
+
["cyan"],
|
|
1196
|
+
` Response variant #${i} excluded from route schemas`
|
|
1197
|
+
)
|
|
1198
|
+
);
|
|
1199
|
+
console.warn(` Route: ${name}; Method: ${def.method}`);
|
|
1200
|
+
console.warn();
|
|
1201
|
+
return [];
|
|
1202
|
+
}
|
|
1203
|
+
return [{ ...variant, contentType }];
|
|
1204
|
+
})
|
|
1205
|
+
};
|
|
1206
|
+
} else if (def.contentType && !def.contentType.includes("/")) {
|
|
1207
|
+
const contentType = mimeTypes.lookup(def.contentType);
|
|
1208
|
+
if (contentType === false) {
|
|
1209
|
+
console.warn(
|
|
1210
|
+
styleText2(
|
|
1211
|
+
["bold", "red"],
|
|
1212
|
+
"\u2717 Failed resolving Response Content Type"
|
|
1213
|
+
)
|
|
1214
|
+
);
|
|
1215
|
+
console.warn(
|
|
1216
|
+
` Invalid value provided for mime-types lookup - ${def.contentType}`
|
|
1217
|
+
);
|
|
1218
|
+
console.warn(` Route: ${name}; Method: ${def.method}`);
|
|
1219
|
+
console.warn();
|
|
1220
|
+
} else {
|
|
1221
|
+
augmentedDef = { ...def, contentType };
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
return augmentedDef ? [augmentedDef] : [];
|
|
1225
|
+
}
|
|
1226
|
+
);
|
|
1227
|
+
const entry = {
|
|
1228
|
+
id,
|
|
790
1229
|
name,
|
|
791
1230
|
pathTokens,
|
|
1231
|
+
pathPattern,
|
|
792
1232
|
params: cache.params,
|
|
793
1233
|
numericParams: cache.numericParams,
|
|
794
1234
|
optionalParams,
|
|
795
|
-
importName,
|
|
796
|
-
importFile,
|
|
797
1235
|
folder,
|
|
798
1236
|
file,
|
|
799
1237
|
fileFullpath,
|
|
800
1238
|
methods: cache.methods,
|
|
801
1239
|
typeDeclarations: cache.typeDeclarations,
|
|
802
|
-
|
|
803
|
-
responseTypes: cache.responseTypes,
|
|
1240
|
+
validationDefinitions,
|
|
804
1241
|
referencedFiles: Object.keys(cache.referencedFiles).map(
|
|
805
1242
|
// expand referenced files path,
|
|
806
1243
|
// they are stored as relative in cache
|
|
807
|
-
(e) =>
|
|
1244
|
+
(e) => resolve3(appRoot, e)
|
|
808
1245
|
)
|
|
809
1246
|
};
|
|
810
1247
|
return {
|
|
811
1248
|
kind: "apiRoute",
|
|
812
|
-
entry
|
|
1249
|
+
entry
|
|
813
1250
|
};
|
|
814
1251
|
};
|
|
815
1252
|
return { name, handler };
|
|
816
1253
|
};
|
|
817
1254
|
};
|
|
818
1255
|
|
|
819
|
-
// src/
|
|
820
|
-
import {
|
|
821
|
-
|
|
822
|
-
|
|
1256
|
+
// src/routes-factory/nesting.ts
|
|
1257
|
+
import { basename } from "node:path";
|
|
1258
|
+
var nestedRoutesFactory = (routeEntries) => {
|
|
1259
|
+
const entryStack = structuredClone(routeEntries).sort(sortRoutes);
|
|
1260
|
+
const transformEntries = (entries, parent) => {
|
|
1261
|
+
return [...new Set(entries.map((e) => e.name))].flatMap((name) => {
|
|
1262
|
+
const nameEntries = entryStack.flatMap(({ fileFullpath, ...entry }) => {
|
|
1263
|
+
return entry.name === name ? [entry] : [];
|
|
1264
|
+
});
|
|
1265
|
+
const index = nameEntries.find(
|
|
1266
|
+
(e) => basename(e.file).startsWith(PAGE_INDEX_BASENAME)
|
|
1267
|
+
);
|
|
1268
|
+
const layout = nameEntries.find(
|
|
1269
|
+
(e) => basename(e.file).startsWith(PAGE_LAYOUT_BASENAME)
|
|
1270
|
+
);
|
|
1271
|
+
if (index || layout) {
|
|
1272
|
+
return [
|
|
1273
|
+
{
|
|
1274
|
+
index: index ? {
|
|
1275
|
+
...index,
|
|
1276
|
+
pathTokens: index.pathTokens.slice(
|
|
1277
|
+
parent?.pathTokens.length || 0
|
|
1278
|
+
)
|
|
1279
|
+
} : void 0,
|
|
1280
|
+
layout: layout ? {
|
|
1281
|
+
...layout,
|
|
1282
|
+
pathTokens: layout.pathTokens.slice(
|
|
1283
|
+
parent?.pathTokens.length || 0
|
|
1284
|
+
)
|
|
1285
|
+
} : void 0,
|
|
1286
|
+
parent: parent?.name,
|
|
1287
|
+
children: transformEntries(
|
|
1288
|
+
findDescendantEntries(index || layout),
|
|
1289
|
+
index || layout
|
|
1290
|
+
)
|
|
1291
|
+
}
|
|
1292
|
+
];
|
|
1293
|
+
}
|
|
1294
|
+
return [];
|
|
1295
|
+
});
|
|
1296
|
+
};
|
|
1297
|
+
const findDescendantEntries = ({
|
|
1298
|
+
name,
|
|
1299
|
+
pathTokens
|
|
1300
|
+
}) => {
|
|
1301
|
+
const potentialChildren = entryStack.filter((entry) => {
|
|
1302
|
+
if (entry.pathTokens.length <= pathTokens.length) {
|
|
1303
|
+
return false;
|
|
1304
|
+
}
|
|
1305
|
+
if (!entry.name.startsWith(`${name}/`)) {
|
|
1306
|
+
return false;
|
|
1307
|
+
}
|
|
1308
|
+
return true;
|
|
1309
|
+
});
|
|
1310
|
+
return potentialChildren.filter((child) => {
|
|
1311
|
+
const hasIntermediateRoute = potentialChildren.some((intermediate) => {
|
|
1312
|
+
if (intermediate === child) {
|
|
1313
|
+
return false;
|
|
1314
|
+
}
|
|
1315
|
+
if (intermediate.pathTokens.length <= pathTokens.length) {
|
|
1316
|
+
return false;
|
|
1317
|
+
}
|
|
1318
|
+
if (intermediate.pathTokens.length >= child.pathTokens.length) {
|
|
1319
|
+
return false;
|
|
1320
|
+
}
|
|
1321
|
+
return child.name.startsWith(`${intermediate.name}/`);
|
|
1322
|
+
});
|
|
1323
|
+
return !hasIntermediateRoute;
|
|
1324
|
+
});
|
|
1325
|
+
};
|
|
1326
|
+
const rootEntries = entryStack.filter((entry) => {
|
|
1327
|
+
const hasParent = entryStack.some((potential) => {
|
|
1328
|
+
if (potential === entry) {
|
|
1329
|
+
return false;
|
|
1330
|
+
}
|
|
1331
|
+
if (potential.pathTokens.length >= entry.pathTokens.length) {
|
|
1332
|
+
return false;
|
|
1333
|
+
}
|
|
1334
|
+
return entry.name.startsWith(`${potential.name}/`);
|
|
1335
|
+
});
|
|
1336
|
+
return !hasParent;
|
|
1337
|
+
});
|
|
1338
|
+
return transformEntries(rootEntries);
|
|
1339
|
+
};
|
|
823
1340
|
|
|
824
|
-
// src/
|
|
825
|
-
var
|
|
1341
|
+
// src/routes-factory/index.ts
|
|
1342
|
+
var routesFactory = async (pluginOptions) => {
|
|
826
1343
|
const { appRoot, sourceFolder } = pluginOptions;
|
|
827
1344
|
const apiRouteResolver = apiRouteResolverFactory(pluginOptions);
|
|
828
1345
|
const apiUseResolver = apiUseResolverFactory(pluginOptions);
|
|
@@ -835,13 +1352,13 @@ var routes_default = async (pluginOptions) => {
|
|
|
835
1352
|
return entry ? [entry] : [];
|
|
836
1353
|
});
|
|
837
1354
|
for (const entry of entries) {
|
|
838
|
-
if (entry.folder ===
|
|
1355
|
+
if (entry.folder === defaults.apiDir) {
|
|
839
1356
|
if (isApiRoute(entry.file)) {
|
|
840
1357
|
resolvers.set(entry.fileFullpath, apiRouteResolver(entry));
|
|
841
1358
|
} else if (isApiUse(entry.file)) {
|
|
842
1359
|
resolvers.set(entry.fileFullpath, apiUseResolver(entry));
|
|
843
1360
|
}
|
|
844
|
-
} else if (entry.folder ===
|
|
1361
|
+
} else if (entry.folder === defaults.pagesDir) {
|
|
845
1362
|
if (isPageRoute(entry.file)) {
|
|
846
1363
|
resolvers.set(entry.fileFullpath, pageRouteResolver(entry));
|
|
847
1364
|
} else if (isPageLayout(entry.file)) {
|
|
@@ -858,10 +1375,85 @@ var routes_default = async (pluginOptions) => {
|
|
|
858
1375
|
};
|
|
859
1376
|
};
|
|
860
1377
|
|
|
1378
|
+
// src/base-plugin/api-handler.ts
|
|
1379
|
+
import { join as join4, resolve as resolve4 } from "node:path";
|
|
1380
|
+
import { styleText as styleText3 } from "node:util";
|
|
1381
|
+
import { context } from "esbuild";
|
|
1382
|
+
var api_handler_default = async (options) => {
|
|
1383
|
+
const { appRoot, sourceFolder, baseurl, apiurl } = options;
|
|
1384
|
+
const { createPath } = pathResolver({ appRoot, sourceFolder });
|
|
1385
|
+
const outDir = join4(options.outDir, defaults.apiDir);
|
|
1386
|
+
const esbuildOptions = await import(resolve4(appRoot, "esbuild.json"), { with: { type: "json" } }).then((e) => e.default);
|
|
1387
|
+
let devSetup;
|
|
1388
|
+
const watcher = async () => {
|
|
1389
|
+
const rebuildPlugin = {
|
|
1390
|
+
name: "rebuild",
|
|
1391
|
+
setup(build) {
|
|
1392
|
+
build.onEnd(async () => {
|
|
1393
|
+
if (devSetup) {
|
|
1394
|
+
await devSetup.teardownHandler?.();
|
|
1395
|
+
}
|
|
1396
|
+
try {
|
|
1397
|
+
await import(`${outDir}/dev.js?${Date.now()}`).then((e) => {
|
|
1398
|
+
devSetup = e.default;
|
|
1399
|
+
});
|
|
1400
|
+
console.debug(`${styleText3("green", "\u279C")} Api handler ready`);
|
|
1401
|
+
} catch (error) {
|
|
1402
|
+
console.error(`${styleText3("red", "\u2717")} Api handler error`);
|
|
1403
|
+
console.error(error);
|
|
1404
|
+
}
|
|
1405
|
+
});
|
|
1406
|
+
}
|
|
1407
|
+
};
|
|
1408
|
+
const ctx = await context({
|
|
1409
|
+
...esbuildOptions,
|
|
1410
|
+
define: {
|
|
1411
|
+
...esbuildOptions.define,
|
|
1412
|
+
PRODUCTION_BUILD: "false"
|
|
1413
|
+
},
|
|
1414
|
+
logLevel: "error",
|
|
1415
|
+
bundle: true,
|
|
1416
|
+
entryPoints: [createPath.api("dev.ts")],
|
|
1417
|
+
plugins: [rebuildPlugin],
|
|
1418
|
+
outdir: outDir
|
|
1419
|
+
});
|
|
1420
|
+
return {
|
|
1421
|
+
async start() {
|
|
1422
|
+
await ctx.watch({
|
|
1423
|
+
// waits this many milliseconds before rebuilding after a change is detected
|
|
1424
|
+
delay: options.watcher.delay
|
|
1425
|
+
});
|
|
1426
|
+
},
|
|
1427
|
+
async stop() {
|
|
1428
|
+
await ctx.dispose();
|
|
1429
|
+
}
|
|
1430
|
+
};
|
|
1431
|
+
};
|
|
1432
|
+
const devMiddleware = async (req, res, next) => {
|
|
1433
|
+
const {
|
|
1434
|
+
requestMatcher = () => {
|
|
1435
|
+
return new RegExp(`^${join4(baseurl, apiurl)}($|/)`).test(
|
|
1436
|
+
req.url
|
|
1437
|
+
);
|
|
1438
|
+
},
|
|
1439
|
+
requestHandler
|
|
1440
|
+
} = { ...devSetup };
|
|
1441
|
+
if (!requestMatcher(req)) {
|
|
1442
|
+
return next();
|
|
1443
|
+
}
|
|
1444
|
+
const handler = requestHandler?.();
|
|
1445
|
+
return handler ? handler(req, res) : next();
|
|
1446
|
+
};
|
|
1447
|
+
return {
|
|
1448
|
+
watcher,
|
|
1449
|
+
devMiddleware
|
|
1450
|
+
};
|
|
1451
|
+
};
|
|
1452
|
+
|
|
861
1453
|
// src/base-plugin/spinner.ts
|
|
862
|
-
import
|
|
1454
|
+
import { Spinner } from "@topcli/spinner";
|
|
863
1455
|
var spinnerFactory = (startText) => {
|
|
864
|
-
const spinner =
|
|
1456
|
+
const spinner = new Spinner().start(startText);
|
|
865
1457
|
let _text = startText;
|
|
866
1458
|
return {
|
|
867
1459
|
text(text) {
|
|
@@ -883,7 +1475,7 @@ var spinnerFactory = (startText) => {
|
|
|
883
1475
|
if (text) {
|
|
884
1476
|
this.text([_text, text].join("\n"));
|
|
885
1477
|
}
|
|
886
|
-
spinner.
|
|
1478
|
+
spinner.failed();
|
|
887
1479
|
}
|
|
888
1480
|
};
|
|
889
1481
|
};
|
|
@@ -894,19 +1486,13 @@ var base_plugin_default = (apiurl, pluginOptions) => {
|
|
|
894
1486
|
const outDirSuffix = "client";
|
|
895
1487
|
const store = {};
|
|
896
1488
|
const createWorker = () => {
|
|
897
|
-
const {
|
|
898
|
-
generators = [],
|
|
899
|
-
formatters = [],
|
|
900
|
-
...restOptions
|
|
901
|
-
} = store.resolvedOptions;
|
|
1489
|
+
const { generators = [], ...restOptions } = store.resolvedOptions;
|
|
902
1490
|
const generatorModules = generators.map(
|
|
903
1491
|
(e) => [e.moduleImport, e.moduleConfig]
|
|
904
1492
|
);
|
|
905
|
-
const formatterModules = pluginOptions?.formatters ? pluginOptions.formatters.map((e) => [e.moduleImport, e.moduleConfig]) : [];
|
|
906
1493
|
const workerData = {
|
|
907
1494
|
...restOptions,
|
|
908
|
-
generatorModules
|
|
909
|
-
formatterModules
|
|
1495
|
+
generatorModules
|
|
910
1496
|
};
|
|
911
1497
|
return new Worker(resolve5(import.meta.dirname, "base-plugin/worker.js"), {
|
|
912
1498
|
workerData,
|
|
@@ -945,10 +1531,10 @@ var base_plugin_default = (apiurl, pluginOptions) => {
|
|
|
945
1531
|
const { error } = msg;
|
|
946
1532
|
if (error.stack) {
|
|
947
1533
|
const [message, ...stack] = error.stack.split("\n");
|
|
948
|
-
console.error(
|
|
1534
|
+
console.error(styleText4("red", message));
|
|
949
1535
|
console.error(stack.join("\n"));
|
|
950
1536
|
} else if (error?.message) {
|
|
951
|
-
console.error(`${
|
|
1537
|
+
console.error(`${styleText4("red", error?.name)}: ${error.message}`);
|
|
952
1538
|
} else {
|
|
953
1539
|
console.error(error);
|
|
954
1540
|
}
|
|
@@ -974,15 +1560,15 @@ var base_plugin_default = (apiurl, pluginOptions) => {
|
|
|
974
1560
|
}
|
|
975
1561
|
return {
|
|
976
1562
|
build: {
|
|
977
|
-
outDir:
|
|
1563
|
+
outDir: join5(config.build.outDir, outDirSuffix),
|
|
978
1564
|
manifest: true
|
|
979
1565
|
}
|
|
980
1566
|
};
|
|
981
1567
|
},
|
|
982
1568
|
async configResolved(_config) {
|
|
983
1569
|
store.config = _config;
|
|
984
|
-
const appRoot = resolve5(store.config.root, "
|
|
985
|
-
const sourceFolder =
|
|
1570
|
+
const appRoot = resolve5(store.config.root, "../..");
|
|
1571
|
+
const sourceFolder = basename2(store.config.root);
|
|
986
1572
|
const outDir = resolve5(appRoot, resolve5(store.config.build.outDir, ".."));
|
|
987
1573
|
const { stabilityThreshold = 1e3 } = typeof store.config.server.watch?.awaitWriteFinish === "object" ? store.config.server.watch.awaitWriteFinish : {};
|
|
988
1574
|
const watcher = {
|
|
@@ -990,14 +1576,12 @@ var base_plugin_default = (apiurl, pluginOptions) => {
|
|
|
990
1576
|
...store.config.server.watch ? { options: store.config.server.watch } : {}
|
|
991
1577
|
};
|
|
992
1578
|
{
|
|
993
|
-
const {
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
const
|
|
999
|
-
const _fetchGenerator = generators.find((e) => e.kind === "fetch");
|
|
1000
|
-
const _ssrGenerator = generators.find((e) => e.kind === "ssr");
|
|
1579
|
+
const { generators = [], refineTypeName = "TRefine" } = {
|
|
1580
|
+
...pluginOptions
|
|
1581
|
+
};
|
|
1582
|
+
const apiGenerator = generators.find((e) => e.slot === "api");
|
|
1583
|
+
const fetchGenerator = generators.find((e) => e.slot === "fetch");
|
|
1584
|
+
const ssrGenerator = generators.find((e) => e.slot === "ssr");
|
|
1001
1585
|
store.resolvedOptions = {
|
|
1002
1586
|
...pluginOptions,
|
|
1003
1587
|
command: store.config.command,
|
|
@@ -1006,17 +1590,16 @@ var base_plugin_default = (apiurl, pluginOptions) => {
|
|
|
1006
1590
|
// 1. stub generator should run first
|
|
1007
1591
|
stubGenerator(),
|
|
1008
1592
|
// 2. then api generator
|
|
1009
|
-
|
|
1010
|
-
// 3. then fetch generator
|
|
1011
|
-
|
|
1593
|
+
...apiGenerator ? [apiGenerator] : [],
|
|
1594
|
+
// 3. then fetch generator, only if api generator also enabled
|
|
1595
|
+
...fetchGenerator && apiGenerator ? [fetchGenerator] : [],
|
|
1012
1596
|
// 4. user generators in the order they were added
|
|
1013
1597
|
...generators.filter((e) => {
|
|
1014
|
-
return e.
|
|
1598
|
+
return e.slot ? !["api", "fetch", "ssr"].includes(e.slot) : true;
|
|
1015
1599
|
}),
|
|
1016
1600
|
// 5. ssr generator should run last
|
|
1017
|
-
...
|
|
1601
|
+
...ssrGenerator ? [ssrGenerator] : []
|
|
1018
1602
|
],
|
|
1019
|
-
formatters: formatters.map((e) => e.formatter),
|
|
1020
1603
|
refineTypeName,
|
|
1021
1604
|
baseurl: store.config.base,
|
|
1022
1605
|
apiurl,
|
|
@@ -1025,8 +1608,54 @@ var base_plugin_default = (apiurl, pluginOptions) => {
|
|
|
1025
1608
|
outDir
|
|
1026
1609
|
};
|
|
1027
1610
|
}
|
|
1611
|
+
const packageJsonFile = resolve5(appRoot, "package.json");
|
|
1612
|
+
const packageJson = await import(packageJsonFile, {
|
|
1613
|
+
with: { type: "json" }
|
|
1614
|
+
}).then((e) => e.default);
|
|
1615
|
+
const newDependencies = [];
|
|
1616
|
+
for (const generator of store.resolvedOptions.generators) {
|
|
1617
|
+
for (const key of ["dependencies", "devDependencies"]) {
|
|
1618
|
+
for (const [pkg, ver] of Object.entries(generator[key] || {})) {
|
|
1619
|
+
if (!packageJson[key]?.[pkg]) {
|
|
1620
|
+
newDependencies.push([key, pkg, ver]);
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1625
|
+
if (newDependencies.length) {
|
|
1626
|
+
console.warn();
|
|
1627
|
+
console.warn(
|
|
1628
|
+
[
|
|
1629
|
+
"\u{1F4A1} ",
|
|
1630
|
+
styleText4(["bold", "italic", "red"], "New dependencies added: "),
|
|
1631
|
+
styleText4("dim", newDependencies.map(([, pkg]) => pkg).join(", "))
|
|
1632
|
+
].join("")
|
|
1633
|
+
);
|
|
1634
|
+
console.warn(
|
|
1635
|
+
"\u{1F4E6}",
|
|
1636
|
+
[
|
|
1637
|
+
styleText4(
|
|
1638
|
+
["bold", "blueBright"],
|
|
1639
|
+
store.config.command === "build" ? "Install them and run a new build: " : "Install them and restart dev server: "
|
|
1640
|
+
),
|
|
1641
|
+
styleText4(
|
|
1642
|
+
"dim",
|
|
1643
|
+
["npm", "pnpm", "yarn"].map((e) => `\`${e} install\``).join(" / ")
|
|
1644
|
+
)
|
|
1645
|
+
].join("")
|
|
1646
|
+
);
|
|
1647
|
+
console.warn();
|
|
1648
|
+
for (const [key, pkg, ver] of newDependencies) {
|
|
1649
|
+
packageJson[key] = { ...packageJson[key], [pkg]: ver };
|
|
1650
|
+
}
|
|
1651
|
+
await writeFile3(
|
|
1652
|
+
packageJsonFile,
|
|
1653
|
+
JSON.stringify(packageJson, null, 2),
|
|
1654
|
+
"utf8"
|
|
1655
|
+
);
|
|
1656
|
+
}
|
|
1028
1657
|
if (store.config.command === "build") {
|
|
1029
|
-
const { resolvers } = await
|
|
1658
|
+
const { resolvers } = await routesFactory(store.resolvedOptions);
|
|
1030
1659
|
const resolvedEntries = [];
|
|
1031
1660
|
{
|
|
1032
1661
|
const spinner = spinnerFactory("Resolving Routes");
|
|
@@ -1042,8 +1671,8 @@ var base_plugin_default = (apiurl, pluginOptions) => {
|
|
|
1042
1671
|
const spinner = spinnerFactory("Running Generators");
|
|
1043
1672
|
for (const { name, factory } of store.resolvedOptions.generators) {
|
|
1044
1673
|
spinner.append(name);
|
|
1045
|
-
const {
|
|
1046
|
-
await
|
|
1674
|
+
const { build } = await factory(store.resolvedOptions);
|
|
1675
|
+
await build(resolvedEntries);
|
|
1047
1676
|
}
|
|
1048
1677
|
spinner.succeed();
|
|
1049
1678
|
}
|
|
@@ -1053,6 +1682,10 @@ var base_plugin_default = (apiurl, pluginOptions) => {
|
|
|
1053
1682
|
if (store.config.command !== "serve") {
|
|
1054
1683
|
return;
|
|
1055
1684
|
}
|
|
1685
|
+
if (!store.resolvedOptions.generators.find((e) => e.slot === "api")) {
|
|
1686
|
+
const stopWorker2 = workerHandler(() => stopWorker2());
|
|
1687
|
+
return;
|
|
1688
|
+
}
|
|
1056
1689
|
const apiHandler = await api_handler_default(store.resolvedOptions);
|
|
1057
1690
|
const apiWatcher = await apiHandler.watcher();
|
|
1058
1691
|
const stopWorker = workerHandler(
|
|
@@ -1070,9 +1703,8 @@ var base_plugin_default = (apiurl, pluginOptions) => {
|
|
|
1070
1703
|
};
|
|
1071
1704
|
|
|
1072
1705
|
// src/define-plugin/index.ts
|
|
1073
|
-
import { readFile as
|
|
1706
|
+
import { readFile as readFile3 } from "node:fs/promises";
|
|
1074
1707
|
import { parse as dotenv } from "dotenv";
|
|
1075
|
-
import { pathExists as pathExists2 } from "@kosmojs/devlib";
|
|
1076
1708
|
var define_plugin_default = (entries) => {
|
|
1077
1709
|
return {
|
|
1078
1710
|
name: "@kosmojs:definePlugin",
|
|
@@ -1080,8 +1712,8 @@ var define_plugin_default = (entries) => {
|
|
|
1080
1712
|
const define = {};
|
|
1081
1713
|
for (const { keys, file, defineOn = "process.env", use } of entries) {
|
|
1082
1714
|
define[defineOn] = {};
|
|
1083
|
-
const fileExists = file ? await
|
|
1084
|
-
const env = fileExists ? dotenv(await
|
|
1715
|
+
const fileExists = file ? await pathExists(file) : false;
|
|
1716
|
+
const env = fileExists ? dotenv(await readFile3(file, "utf8")) : process.env;
|
|
1085
1717
|
for (const [key, val] of Object.entries(env)) {
|
|
1086
1718
|
if (keys.includes(key)) {
|
|
1087
1719
|
define[`${defineOn}.${key}`] = JSON.stringify(val);
|
|
@@ -1093,11 +1725,57 @@ var define_plugin_default = (entries) => {
|
|
|
1093
1725
|
}
|
|
1094
1726
|
};
|
|
1095
1727
|
};
|
|
1728
|
+
|
|
1729
|
+
// src/typebox.ts
|
|
1730
|
+
var typeboxLiteralText = (text, options) => {
|
|
1731
|
+
return [
|
|
1732
|
+
// Escape backticks for safe use in template literals
|
|
1733
|
+
[/(?<!\\)`/g, "\\`"],
|
|
1734
|
+
// Escape $ for safe use in template literals
|
|
1735
|
+
[/(?<!\\)\$\{/g, "\\${"],
|
|
1736
|
+
/**
|
|
1737
|
+
* TypeBox's built-in `Options` type is not configurable.
|
|
1738
|
+
* To allow a custom type name, exposing `refineTypeName` option,
|
|
1739
|
+
* defaulted to TRefine, then renaming it to `Options`.
|
|
1740
|
+
* */
|
|
1741
|
+
[new RegExp(`\\b${options.refineTypeName}\\s*<`, "g"), "Options<"]
|
|
1742
|
+
].reduce((text2, [a, b]) => text2.replace(a, b), text);
|
|
1743
|
+
};
|
|
1096
1744
|
export {
|
|
1745
|
+
API_INDEX_BASENAME,
|
|
1746
|
+
API_INDEX_PATTERN,
|
|
1747
|
+
API_USE_BASENAME,
|
|
1748
|
+
API_USE_PATTERN,
|
|
1749
|
+
PAGE_INDEX_BASENAME,
|
|
1750
|
+
PAGE_INDEX_PATTERN,
|
|
1751
|
+
PAGE_LAYOUT_BASENAME,
|
|
1752
|
+
PAGE_LAYOUT_PATTERN,
|
|
1097
1753
|
alias_plugin_default as aliasPlugin,
|
|
1098
|
-
|
|
1754
|
+
apiRouteResolverFactory,
|
|
1755
|
+
apiUseResolverFactory,
|
|
1756
|
+
createRouteEntry,
|
|
1757
|
+
createTsconfigPaths,
|
|
1099
1758
|
base_plugin_default as default,
|
|
1759
|
+
defaults,
|
|
1100
1760
|
define_plugin_default as definePlugin,
|
|
1101
|
-
|
|
1761
|
+
isApiRoute,
|
|
1762
|
+
isApiUse,
|
|
1763
|
+
isPageLayout,
|
|
1764
|
+
isPageRoute,
|
|
1765
|
+
isRouteFile,
|
|
1766
|
+
nestedRoutesFactory,
|
|
1767
|
+
normalizeStaticValue,
|
|
1768
|
+
pageLayoutResolverFactory,
|
|
1769
|
+
pageRouteResolverFactory,
|
|
1770
|
+
pathResolver,
|
|
1771
|
+
pathTokensFactory,
|
|
1772
|
+
render,
|
|
1773
|
+
renderFactory,
|
|
1774
|
+
renderHelpers,
|
|
1775
|
+
renderToFile,
|
|
1776
|
+
routesFactory,
|
|
1777
|
+
scanRoutes,
|
|
1778
|
+
sortRoutes,
|
|
1779
|
+
typeboxLiteralText
|
|
1102
1780
|
};
|
|
1103
1781
|
//# sourceMappingURL=index.js.map
|