@vitnode/core 1.2.0-canary.60 → 1.2.0-canary.61
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/dist/scripts/get-config.js +15 -0
- package/dist/scripts/plugin.js +188 -0
- package/dist/scripts/prepare-database.js +177 -0
- package/dist/scripts/prepare-plugins-files.js +134 -0
- package/dist/scripts/run-interactive-shell-command.js +21 -0
- package/dist/scripts/scripts.js +39 -13
- package/dist/scripts/shared/file-utils.js +203 -0
- package/dist/src/api/adapters/sso/discord.js +1 -77
- package/dist/src/api/adapters/sso/facebook.js +1 -76
- package/dist/src/api/adapters/sso/google.js +1 -87
- package/dist/src/api/config.js +1 -67
- package/dist/src/api/lib/check-plugin-id.js +1 -43
- package/dist/src/api/lib/cron.js +1 -22
- package/dist/src/api/lib/logger-middleware.js +1 -35
- package/dist/src/api/lib/module.js +1 -22
- package/dist/src/api/lib/plugin.js +1 -22
- package/dist/src/api/lib/route.js +1 -27
- package/dist/src/api/lib/with-pagination.js +1 -83
- package/dist/src/api/middlewares/captcha.middleware.js +1 -63
- package/dist/src/api/middlewares/cron-auth.middleware.js +1 -19
- package/dist/src/api/middlewares/global.middleware.js +1 -93
- package/dist/src/api/middlewares/rate-limiter.middleware.js +1 -32
- package/dist/src/api/models/device.js +1 -61
- package/dist/src/api/models/email.js +1 -76
- package/dist/src/api/models/password.js +1 -36
- package/dist/src/api/models/session-admin.js +1 -106
- package/dist/src/api/models/session.js +1 -85
- package/dist/src/api/models/sso.js +1 -120
- package/dist/src/api/models/user/get-user-by-id.js +1 -19
- package/dist/src/api/models/user/sign-in-with-passwords.js +1 -22
- package/dist/src/api/models/user/sign-up.js +1 -73
- package/dist/src/api/models/user.js +1 -8
- package/dist/src/api/modules/admin/admin.module.js +1 -19
- package/dist/src/api/modules/admin/advanced/advanced.admin.module.js +1 -11
- package/dist/src/api/modules/admin/advanced/cron/cron.admin.module.js +1 -12
- package/dist/src/api/modules/admin/advanced/cron/routes/get.route.js +1 -66
- package/dist/src/api/modules/admin/advanced/cron/routes/run.route.js +1 -95
- package/dist/src/api/modules/admin/debug/debug.admin.module.js +1 -10
- package/dist/src/api/modules/admin/debug/routes/logs.route.js +1 -94
- package/dist/src/api/modules/admin/routes/session.route.js +1 -47
- package/dist/src/api/modules/admin/users/routes/list.route.js +1 -79
- package/dist/src/api/modules/admin/users/routes/users.route.js +1 -84
- package/dist/src/api/modules/admin/users/users.admin.module.js +1 -10
- package/dist/src/api/modules/cron/cron/clean.cron.js +1 -24
- package/dist/src/api/modules/cron/cron.module.js +1 -14
- package/dist/src/api/modules/cron/helpers/process-cron-jobs.d.ts.map +1 -1
- package/dist/src/api/modules/cron/helpers/process-cron-jobs.js +1 -76
- package/dist/src/api/modules/cron/routes/cron.route.js +1 -101
- package/dist/src/api/modules/middleware/middleware.module.js +1 -10
- package/dist/src/api/modules/middleware/route.js +1 -49
- package/dist/src/api/modules/users/avatar-color.js +1 -43
- package/dist/src/api/modules/users/routes/change-password.route.js +1 -58
- package/dist/src/api/modules/users/routes/reset-passowrd.route.js +1 -91
- package/dist/src/api/modules/users/routes/session.route.js +1 -46
- package/dist/src/api/modules/users/routes/sign-in.route.js +1 -71
- package/dist/src/api/modules/users/routes/sign-out.route.js +1 -43
- package/dist/src/api/modules/users/routes/sign-up.route.js +1 -77
- package/dist/src/api/modules/users/routes/test.route.js +1 -33
- package/dist/src/api/modules/users/sso/routes/callback.route.js +1 -52
- package/dist/src/api/modules/users/sso/routes/create-url.route.js +1 -36
- package/dist/src/api/modules/users/sso/sso.module.js +1 -12
- package/dist/src/api/modules/users/users.module.js +1 -26
- package/dist/src/api/plugin.js +1 -15
- package/dist/src/app/login/page.js +1 -16
- package/dist/src/app/login/reset-password/page.js +1 -18
- package/dist/src/app/login/sso/[providerId]/page.js +1 -10
- package/dist/src/app/register/page.js +1 -16
- package/dist/src/app_admin/core/advanced/cron/page.js +1 -42
- package/dist/src/app_admin/core/debug/page.js +1 -45
- package/dist/src/app_admin/core/page.js +1 -5
- package/dist/src/app_admin/core/test/page.js +1 -5
- package/dist/src/app_admin/core/users/page.js +1 -38
- package/dist/src/components/avatar.js +1 -14
- package/dist/src/components/confirm-action/confirm-action-alert-dialog.js +1 -42
- package/dist/src/components/confirm-action/content.js +1 -31
- package/dist/src/components/date-format.js +1 -41
- package/dist/src/components/form/auto-form.js +1 -103
- package/dist/src/components/form/common/desc.js +1 -9
- package/dist/src/components/form/common/label.js +1 -18
- package/dist/src/components/form/fields/checkbox.js +1 -37
- package/dist/src/components/form/fields/combobox-async.js +1 -123
- package/dist/src/components/form/fields/combobox.js +1 -87
- package/dist/src/components/form/fields/input.js +1 -39
- package/dist/src/components/form/fields/radio-group.js +1 -50
- package/dist/src/components/form/fields/select.js +1 -58
- package/dist/src/components/form/fields/switch.js +1 -36
- package/dist/src/components/form/fields/textarea.js +1 -36
- package/dist/src/components/i18n-provider.js +1 -43
- package/dist/src/components/logo-vitnode.js +1 -119
- package/dist/src/components/switchers/langs/language-switcher.js +1 -47
- package/dist/src/components/switchers/themes/theme-switcher.js +1 -28
- package/dist/src/components/table/content.js +1 -81
- package/dist/src/components/table/data-table.js +1 -68
- package/dist/src/components/table/order-table-head.js +1 -50
- package/dist/src/components/table/pagination.js +1 -122
- package/dist/src/components/tiptap/extension.js +1 -33
- package/dist/src/components/tiptap/toolbar/actions/alignment-action.js +1 -91
- package/dist/src/components/tiptap/toolbar/actions/bold-action.js +1 -39
- package/dist/src/components/tiptap/toolbar/actions/headings-action.js +1 -93
- package/dist/src/components/tiptap/toolbar/actions/italic-action.js +1 -38
- package/dist/src/components/tiptap/toolbar/actions/list-action.js +1 -61
- package/dist/src/components/tiptap/toolbar/actions/text-format-more/text-format-more.js +1 -59
- package/dist/src/components/tiptap/toolbar/actions/underline-action.js +1 -38
- package/dist/src/components/tiptap/toolbar/actions/undo-redo-actions.js +1 -63
- package/dist/src/components/tiptap/toolbar/actions/utils/tooltip-shortcut.js +1 -11
- package/dist/src/components/tiptap/toolbar/tiptap-toolbar.js +1 -55
- package/dist/src/components/tiptap/toolbar/use-toolbar-editor.js +1 -5
- package/dist/src/components/ui/accordion.js +1 -46
- package/dist/src/components/ui/alert-dialog.js +1 -123
- package/dist/src/components/ui/alert.js +1 -39
- package/dist/src/components/ui/badge.js +1 -28
- package/dist/src/components/ui/button-client.js +1 -57
- package/dist/src/components/ui/button.js +1 -32
- package/dist/src/components/ui/card.js +1 -52
- package/dist/src/components/ui/checkbox.js +1 -20
- package/dist/src/components/ui/collapsible.js +1 -22
- package/dist/src/components/ui/command.js +1 -98
- package/dist/src/components/ui/context-menu.js +1 -140
- package/dist/src/components/ui/dialog.js +1 -189
- package/dist/src/components/ui/drawer.js +1 -83
- package/dist/src/components/ui/dropdown-menu.js +1 -141
- package/dist/src/components/ui/editor-content.js +1 -10
- package/dist/src/components/ui/editor.js +1 -35
- package/dist/src/components/ui/form.js +1 -148
- package/dist/src/components/ui/header-content.js +1 -30
- package/dist/src/components/ui/hover-card.js +1 -29
- package/dist/src/components/ui/input-otp.js +1 -48
- package/dist/src/components/ui/input.js +1 -11
- package/dist/src/components/ui/label.js +1 -12
- package/dist/src/components/ui/loader.js +1 -16
- package/dist/src/components/ui/menubar.js +1 -151
- package/dist/src/components/ui/navigation-menu.js +1 -82
- package/dist/src/components/ui/popover.js +1 -35
- package/dist/src/components/ui/progress.js +1 -19
- package/dist/src/components/ui/radio-group.js +1 -27
- package/dist/src/components/ui/scroll-area.js +1 -33
- package/dist/src/components/ui/select.js +1 -113
- package/dist/src/components/ui/separator.js +1 -14
- package/dist/src/components/ui/sheet.js +1 -92
- package/dist/src/components/ui/sidebar.js +1 -433
- package/dist/src/components/ui/skeleton.js +1 -10
- package/dist/src/components/ui/slider.js +1 -50
- package/dist/src/components/ui/sonner.js +1 -26
- package/dist/src/components/ui/switch.js +1 -16
- package/dist/src/components/ui/table.js +1 -63
- package/dist/src/components/ui/tabs.js +1 -33
- package/dist/src/components/ui/textarea.js +1 -10
- package/dist/src/components/ui/toggle-group.js +1 -45
- package/dist/src/components/ui/toggle.js +1 -34
- package/dist/src/components/ui/tooltip.js +1 -57
- package/dist/src/config.js +1 -4
- package/dist/src/database/admins.js +1 -74
- package/dist/src/database/cron.js +1 -22
- package/dist/src/database/languages.js +1 -52
- package/dist/src/database/logs.js +1 -34
- package/dist/src/database/moderators.js +1 -37
- package/dist/src/database/roles.js +1 -13
- package/dist/src/database/sessions.js +1 -60
- package/dist/src/database/users.js +1 -145
- package/dist/src/drizzle.config.js +1 -67
- package/dist/src/emails/default-template.js +1 -99
- package/dist/src/emails/reset-password.js +1 -132
- package/dist/src/emails/ui/button.js +1 -36
- package/dist/src/emails/ui/card.js +1 -39
- package/dist/src/hooks/use-before-unload.js +1 -30
- package/dist/src/hooks/use-captcha.js +1 -122
- package/dist/src/hooks/use-mobile.js +1 -16
- package/dist/src/lib/api/get-middleware-api.js +1 -13
- package/dist/src/lib/api/get-next-cron-run-date.js +1 -14
- package/dist/src/lib/api/get-next-cron-run-date.test.js +1 -55
- package/dist/src/lib/api/get-session-admin-api.js +1 -19
- package/dist/src/lib/api/get-session-api.js +1 -14
- package/dist/src/lib/api/should-cron-job-run.js +1 -16
- package/dist/src/lib/api/should-cron-job-run.test.js +1 -213
- package/dist/src/lib/api/validate-cron-schedule.d.ts +2 -0
- package/dist/src/lib/api/validate-cron-schedule.d.ts.map +1 -0
- package/dist/src/lib/api/validate-cron-schedule.js +1 -0
- package/dist/src/lib/api/validate-cron-schedule.test.d.ts +2 -0
- package/dist/src/lib/api/validate-cron-schedule.test.d.ts.map +1 -0
- package/dist/src/lib/api/validate-cron-schedule.test.js +1 -0
- package/dist/src/lib/colors.js +1 -140
- package/dist/src/lib/colors.test.js +1 -173
- package/dist/src/lib/config.js +1 -14
- package/dist/src/lib/ctrl-or-command-character.js +1 -5
- package/dist/src/lib/fetcher/cookie-from-string-to-object.js +1 -12
- package/dist/src/lib/fetcher/cookie-from-string-to-object.test.js +1 -78
- package/dist/src/lib/fetcher/core.js +3 -48
- package/dist/src/lib/fetcher/helpers-server.js +1 -18
- package/dist/src/lib/fetcher/helpers.js +1 -16
- package/dist/src/lib/fetcher/helpers.test.js +1 -37
- package/dist/src/lib/fetcher/types.js +1 -1
- package/dist/src/lib/fetcher-client.js +1 -17
- package/dist/src/lib/fetcher.js +1 -33
- package/dist/src/lib/helpers/auto-form.js +1 -98
- package/dist/src/lib/helpers/auto-form.test.js +1 -336
- package/dist/src/lib/navigation.js +1 -11
- package/dist/src/lib/plugin.js +1 -3
- package/dist/src/lib/special-characters.js +1 -4
- package/dist/src/lib/special-characters.test.js +1 -56
- package/dist/src/lib/utils.js +1 -5
- package/dist/src/locales/en.json +308 -0
- package/dist/src/tests/setup.js +1 -6
- package/dist/src/views/admin/layouts/admin-layout.js +1 -73
- package/dist/src/views/admin/layouts/sidebar/nav/item.js +1 -98
- package/dist/src/views/admin/layouts/sidebar/nav/nav.js +1 -60
- package/dist/src/views/admin/layouts/sidebar/sidebar.js +1 -28
- package/dist/src/views/admin/layouts/sidebar/sign-out.js +1 -14
- package/dist/src/views/admin/layouts/user-bar/client.js +1 -69
- package/dist/src/views/admin/layouts/user-bar/user-bar.js +1 -32
- package/dist/src/views/admin/sign-in/sign-in-admin-view.js +1 -27
- package/dist/src/views/admin/views/core/advanced/cron/cron-table-view.js +1 -97
- package/dist/src/views/admin/views/core/advanced/cron/run-action/mutation-api.js +1 -23
- package/dist/src/views/admin/views/core/advanced/cron/run-action/run-action.js +1 -38
- package/dist/src/views/admin/views/core/dashboard/dashboard-admin-view.js +1 -44
- package/dist/src/views/admin/views/core/debug/actions/clear-cache/clear-cache.js +1 -35
- package/dist/src/views/admin/views/core/debug/actions/clear-cache/mutation-api.js +1 -5
- package/dist/src/views/admin/views/core/debug/system-logs/actions/more/content.js +1 -281
- package/dist/src/views/admin/views/core/debug/system-logs/actions/more/more.js +1 -67
- package/dist/src/views/admin/views/core/debug/system-logs/badges/badge-status.js +1 -14
- package/dist/src/views/admin/views/core/debug/system-logs/badges/badge-type-log.js +1 -30
- package/dist/src/views/admin/views/core/debug/system-logs/system-logs-view.js +1 -96
- package/dist/src/views/admin/views/core/test.js +1 -161
- package/dist/src/views/admin/views/core/users/users-admin-view.js +1 -89
- package/dist/src/views/auth/password-reset/change-password-form/form.js +1 -48
- package/dist/src/views/auth/password-reset/change-password-form/mutation-api.js +1 -22
- package/dist/src/views/auth/password-reset/change-password-form/use-form.js +1 -36
- package/dist/src/views/auth/password-reset/form/form.js +1 -104
- package/dist/src/views/auth/password-reset/form/mutation-api.js +1 -21
- package/dist/src/views/auth/password-reset/form/use-form.js +1 -33
- package/dist/src/views/auth/password-reset/password-reset-view.js +1 -37
- package/dist/src/views/auth/sign-in/form/form.js +1 -64
- package/dist/src/views/auth/sign-in/form/mutation-api.js +1 -33
- package/dist/src/views/auth/sign-in/form/use-form.js +1 -38
- package/dist/src/views/auth/sign-in/sign-in-view.js +1 -61
- package/dist/src/views/auth/sign-up/components/password-input.js +1 -96
- package/dist/src/views/auth/sign-up/email-confirmation-view.js +1 -55
- package/dist/src/views/auth/sign-up/form/form.js +1 -89
- package/dist/src/views/auth/sign-up/form/mutation-api.js +1 -30
- package/dist/src/views/auth/sign-up/form/use-form.js +1 -70
- package/dist/src/views/auth/sign-up/sign-up-view.js +1 -65
- package/dist/src/views/auth/sign-up/wrapper.js +1 -22
- package/dist/src/views/auth/sso/buttons/client.js +1 -22
- package/dist/src/views/auth/sso/buttons/mutation-api.js +1 -24
- package/dist/src/views/auth/sso/buttons/sso-buttons.js +1 -56
- package/dist/src/views/auth/sso/callback/callback-sso-view.js +1 -32
- package/dist/src/views/auth/sso/callback/client/client.js +1 -68
- package/dist/src/views/auth/sso/callback/client/mutation-api.js +1 -32
- package/dist/src/views/error/back-button.js +1 -14
- package/dist/src/views/error/error-view.js +1 -58
- package/dist/src/views/error/global-error-view.js +1 -50
- package/dist/src/views/layouts/provider.js +1 -44
- package/dist/src/views/layouts/root-layout.js +1 -25
- package/dist/src/views/layouts/theme/header/header.js +1 -38
- package/dist/src/views/layouts/theme/header/user/auth/auth.js +1 -33
- package/dist/src/views/layouts/theme/header/user/auth/client.js +1 -47
- package/dist/src/views/layouts/theme/header/user/auth/log-out-mutation-api.js +1 -27
- package/dist/src/views/layouts/theme/header/user/user.js +1 -32
- package/dist/src/views/layouts/theme/layout.js +1 -16
- package/dist/src/vitnode.config.js +1 -42
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/tsup.config.js +18 -0
- package/dist/vitest.config.d.ts.map +1 -1
- package/dist/vitest.config.js +49 -0
- package/eslint.config.mjs +2 -0
- package/package.json +6 -10
- package/dist/src/api/adapters/cron/node-cron.adapter.d.ts +0 -3
- package/dist/src/api/adapters/cron/node-cron.adapter.d.ts.map +0 -1
- package/dist/src/api/adapters/cron/node-cron.adapter.js +0 -11
- package/dist/src/api/adapters/email/nodemailer.d.ts +0 -10
- package/dist/src/api/adapters/email/nodemailer.d.ts.map +0 -1
- package/dist/src/api/adapters/email/nodemailer.js +0 -30
- package/dist/src/api/adapters/email/resend.d.ts +0 -6
- package/dist/src/api/adapters/email/resend.d.ts.map +0 -1
- package/dist/src/api/adapters/email/resend.js +0 -21
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
3
|
+
export const getConfig = async ({ type = "config", }) => {
|
|
4
|
+
const configPath = join(process.cwd(), "src", `vitnode.${type}.ts`);
|
|
5
|
+
try {
|
|
6
|
+
const configUrl = pathToFileURL(configPath).href;
|
|
7
|
+
const loaded = await import(configUrl);
|
|
8
|
+
const config = type === "config" ? loaded.vitNodeConfig : loaded.vitNodeApiConfig;
|
|
9
|
+
return config;
|
|
10
|
+
}
|
|
11
|
+
catch (error) {
|
|
12
|
+
console.error("Failed to load config:", error);
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import chokidar from "chokidar";
|
|
2
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, unlinkSync, } from "node:fs";
|
|
3
|
+
import { basename, join, relative } from "node:path";
|
|
4
|
+
import { buildInitialRouteMap, copyFile, findLocaleRoot, findRepoRoot, getAllFiles, isDirectoryEmpty, routeKey, } from "./shared/file-utils";
|
|
5
|
+
const detectAppType = (appPath) => {
|
|
6
|
+
const hasWebConfig = existsSync(join(appPath, "src", "vitnode.config.ts"));
|
|
7
|
+
const hasApiConfig = existsSync(join(appPath, "src", "vitnode.api.config.ts"));
|
|
8
|
+
if (hasApiConfig && !hasWebConfig)
|
|
9
|
+
return "api";
|
|
10
|
+
if (hasWebConfig)
|
|
11
|
+
return "web";
|
|
12
|
+
return null;
|
|
13
|
+
};
|
|
14
|
+
const collectSources = (pluginDir, repoRoot, pluginName, pluginPathName) => {
|
|
15
|
+
const sources = [];
|
|
16
|
+
const appsDir = join(repoRoot, "apps");
|
|
17
|
+
const isMonorepo = existsSync(appsDir);
|
|
18
|
+
if (isMonorepo) {
|
|
19
|
+
const appDirs = existsSync(appsDir)
|
|
20
|
+
? readdirSync(appsDir, { withFileTypes: true })
|
|
21
|
+
.filter(dirent => dirent.isDirectory())
|
|
22
|
+
.map(dirent => dirent.name)
|
|
23
|
+
: [];
|
|
24
|
+
for (const appName of appDirs) {
|
|
25
|
+
const appPath = join(repoRoot, "apps", appName);
|
|
26
|
+
const appType = detectAppType(appPath);
|
|
27
|
+
if (appType === "web") {
|
|
28
|
+
sources.push({
|
|
29
|
+
sourceDir: join(pluginDir, "src", "app_admin"),
|
|
30
|
+
destinationDir: join(appPath, "src", "app", "[locale]", "admin", "(auth)", join("(plugins)", `(${pluginPathName})`)),
|
|
31
|
+
}, {
|
|
32
|
+
sourceDir: join(pluginDir, "src", "app"),
|
|
33
|
+
destinationDir: join(appPath, "src", "app", "[locale]", "(main)", join("(plugins)", `(${pluginPathName})`)),
|
|
34
|
+
}, {
|
|
35
|
+
sourceDir: join(pluginDir, "src", "locales"),
|
|
36
|
+
destinationDir: join(appPath, "src", "locales", pluginName),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
else if (appType === "api") {
|
|
40
|
+
sources.push({
|
|
41
|
+
sourceDir: join(pluginDir, "src", "locales"),
|
|
42
|
+
destinationDir: join(appPath, "src", "locales", pluginName),
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
const cwd = process.cwd();
|
|
49
|
+
const projectType = detectAppType(cwd);
|
|
50
|
+
if (projectType === "web") {
|
|
51
|
+
sources.push({
|
|
52
|
+
sourceDir: join(pluginDir, "src", "app_admin"),
|
|
53
|
+
destinationDir: join(cwd, "src", "app", "[locale]", "admin", "(auth)", join("(plugins)", `(${pluginPathName})`)),
|
|
54
|
+
}, {
|
|
55
|
+
sourceDir: join(pluginDir, "src", "app"),
|
|
56
|
+
destinationDir: join(cwd, "src", "app", "[locale]", "(main)", join("(plugins)", `(${pluginPathName})`)),
|
|
57
|
+
}, {
|
|
58
|
+
sourceDir: join(pluginDir, "src", "locales"),
|
|
59
|
+
destinationDir: join(cwd, "src", "locales", pluginName),
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
else if (projectType === "api") {
|
|
63
|
+
sources.push({
|
|
64
|
+
sourceDir: join(pluginDir, "src", "locales"),
|
|
65
|
+
destinationDir: join(cwd, "src", "locales", pluginName),
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return sources;
|
|
70
|
+
};
|
|
71
|
+
const ensureDestinationDirs = (sources) => {
|
|
72
|
+
for (const { sourceDir, destinationDir } of sources) {
|
|
73
|
+
if (existsSync(sourceDir) &&
|
|
74
|
+
!isDirectoryEmpty(sourceDir) &&
|
|
75
|
+
!existsSync(destinationDir)) {
|
|
76
|
+
mkdirSync(destinationDir, { recursive: true });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
const createFileOps = (pluginName, routeMap, localeRoot, repoRoot) => {
|
|
81
|
+
const copyFileWrapper = (srcPath, destPath) => {
|
|
82
|
+
copyFile(srcPath, destPath, pluginName, routeMap, localeRoot, repoRoot);
|
|
83
|
+
};
|
|
84
|
+
const removeFile = (filePath) => {
|
|
85
|
+
try {
|
|
86
|
+
if (existsSync(filePath)) {
|
|
87
|
+
unlinkSync(filePath);
|
|
88
|
+
console.log(`\x1b[33mRemoved:\x1b[0m ${filePath}`);
|
|
89
|
+
if (/^page\.(tsx|ts|jsx|js)$/i.test(basename(filePath))) {
|
|
90
|
+
const key = routeKey(filePath, localeRoot);
|
|
91
|
+
if (routeMap.get(key) === filePath) {
|
|
92
|
+
routeMap.delete(key);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
console.error(`\x1b[31mError removing file:\x1b[0m ${filePath}`, error);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
return { copyFileWrapper, removeFile };
|
|
102
|
+
};
|
|
103
|
+
const cleanupDeletedFiles = (sourceDir, destinationDir, removeFileFn) => {
|
|
104
|
+
if (!existsSync(destinationDir))
|
|
105
|
+
return;
|
|
106
|
+
const isLocaleDir = destinationDir.includes(join("src", "locales"));
|
|
107
|
+
if (isLocaleDir)
|
|
108
|
+
return;
|
|
109
|
+
const destFiles = getAllFiles(destinationDir);
|
|
110
|
+
for (const destFile of destFiles) {
|
|
111
|
+
const relativePath = relative(destinationDir, destFile);
|
|
112
|
+
const sourceFile = join(sourceDir, relativePath);
|
|
113
|
+
if (!existsSync(sourceFile)) {
|
|
114
|
+
removeFileFn(destFile);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
const makeGetDestinationPaths = (sources) => {
|
|
119
|
+
return (srcPath) => {
|
|
120
|
+
const candidates = sources.filter(({ sourceDir }) => {
|
|
121
|
+
const normalizedSrcPath = srcPath.replace(/\\/g, "/");
|
|
122
|
+
const normalizedSourceDir = sourceDir.replace(/\\/g, "/");
|
|
123
|
+
return (normalizedSrcPath === normalizedSourceDir ||
|
|
124
|
+
normalizedSrcPath.startsWith(`${normalizedSourceDir}/`));
|
|
125
|
+
});
|
|
126
|
+
if (candidates.length === 0) {
|
|
127
|
+
throw new Error(`No matching source directory for: ${srcPath}`);
|
|
128
|
+
}
|
|
129
|
+
return candidates.map(sourceConfig => {
|
|
130
|
+
const relativePath = relative(sourceConfig.sourceDir, srcPath);
|
|
131
|
+
return join(sourceConfig.destinationDir, relativePath);
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
};
|
|
135
|
+
const setupWatcher = (sourceDirs, getDestinationPaths, copyFileWrapper, removeFile) => {
|
|
136
|
+
const watcher = chokidar.watch(sourceDirs, {
|
|
137
|
+
ignoreInitial: false,
|
|
138
|
+
persistent: true,
|
|
139
|
+
});
|
|
140
|
+
watcher
|
|
141
|
+
.on("add", filePath => {
|
|
142
|
+
const destPaths = getDestinationPaths(filePath);
|
|
143
|
+
destPaths.forEach(destPath => copyFileWrapper(filePath, destPath));
|
|
144
|
+
})
|
|
145
|
+
.on("change", filePath => {
|
|
146
|
+
const destPaths = getDestinationPaths(filePath);
|
|
147
|
+
destPaths.forEach(destPath => copyFileWrapper(filePath, destPath));
|
|
148
|
+
})
|
|
149
|
+
.on("unlink", filePath => {
|
|
150
|
+
const destPaths = getDestinationPaths(filePath);
|
|
151
|
+
destPaths.forEach(destPath => removeFile(destPath));
|
|
152
|
+
})
|
|
153
|
+
.on("error", error => {
|
|
154
|
+
console.error("\x1b[31mWatcher error:\x1b[0m", error);
|
|
155
|
+
});
|
|
156
|
+
return watcher;
|
|
157
|
+
};
|
|
158
|
+
export const processPlugin = ({ initMessage }) => {
|
|
159
|
+
const pluginDir = process.cwd();
|
|
160
|
+
const repoRoot = findRepoRoot(pluginDir);
|
|
161
|
+
const localeRoot = findLocaleRoot(repoRoot);
|
|
162
|
+
const routeMap = buildInitialRouteMap(localeRoot);
|
|
163
|
+
let pluginName = basename(pluginDir);
|
|
164
|
+
try {
|
|
165
|
+
const packageJsonPath = join(pluginDir, "package.json");
|
|
166
|
+
if (existsSync(packageJsonPath)) {
|
|
167
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
168
|
+
pluginName = packageJson.name ?? "";
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
console.error("\x1b[31mError reading package.json:\x1b[0m", error);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
const pluginPathName = pluginName.replace(/\//g, "-").replace(/@/g, "");
|
|
176
|
+
const sources = collectSources(pluginDir, repoRoot, pluginName, pluginPathName);
|
|
177
|
+
ensureDestinationDirs(sources);
|
|
178
|
+
const { copyFileWrapper, removeFile } = createFileOps(pluginName, routeMap, localeRoot, repoRoot);
|
|
179
|
+
for (const { sourceDir, destinationDir } of sources) {
|
|
180
|
+
cleanupDeletedFiles(sourceDir, destinationDir, removeFile);
|
|
181
|
+
}
|
|
182
|
+
console.log(`${initMessage} \x1b[34mWatching for changes in plugins...\x1b[0m`);
|
|
183
|
+
const sourceDirs = sources
|
|
184
|
+
.map(s => s.sourceDir)
|
|
185
|
+
.filter(dir => existsSync(dir));
|
|
186
|
+
const getDestinationPaths = makeGetDestinationPaths(sources);
|
|
187
|
+
setupWatcher(sourceDirs, getDestinationPaths, copyFileWrapper, removeFile);
|
|
188
|
+
};
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { count } from "drizzle-orm";
|
|
2
|
+
import { core_admin_permissions } from "../src/database/admins.js";
|
|
3
|
+
import { core_languages, core_languages_words } from "../src/database/languages.js";
|
|
4
|
+
import { core_moderators_permissions } from "../src/database/moderators.js";
|
|
5
|
+
import { core_roles } from "../src/database/roles.js";
|
|
6
|
+
import { getConfig } from "./get-config.js";
|
|
7
|
+
import { preparePluginsFiles } from "./prepare-plugins-files.js";
|
|
8
|
+
import { runInteractiveShellCommand } from "./run-interactive-shell-command.js";
|
|
9
|
+
export const generateDatabaseMigrations = async () => {
|
|
10
|
+
try {
|
|
11
|
+
await runInteractiveShellCommand("npm", ["run", "drizzle-kit", "up"]);
|
|
12
|
+
await runInteractiveShellCommand("npm", ["run", "drizzle-kit", "generate"]);
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
15
|
+
console.error("\x1b[31m%s\x1b[0m", err);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
export const runMigrations = async () => {
|
|
20
|
+
try {
|
|
21
|
+
await runInteractiveShellCommand("npm", ["run", "drizzle-kit", "migrate"]);
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
console.error("\x1b[31m%s\x1b[0m", err);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
export const initialDataForDatabase = async () => {
|
|
29
|
+
const config = await getConfig({ type: "api.config" });
|
|
30
|
+
const dbClient = config.dbProvider;
|
|
31
|
+
const [roleCount] = await dbClient
|
|
32
|
+
.select({
|
|
33
|
+
count: count(),
|
|
34
|
+
})
|
|
35
|
+
.from(core_roles)
|
|
36
|
+
.limit(1);
|
|
37
|
+
const [languageCount] = await dbClient
|
|
38
|
+
.select({
|
|
39
|
+
count: count(),
|
|
40
|
+
})
|
|
41
|
+
.from(core_languages);
|
|
42
|
+
if (languageCount.count === 0) {
|
|
43
|
+
await dbClient.insert(core_languages).values([
|
|
44
|
+
{
|
|
45
|
+
code: "en",
|
|
46
|
+
name: "English (USA)",
|
|
47
|
+
default: true,
|
|
48
|
+
protected: true,
|
|
49
|
+
timezone: "America/New_York",
|
|
50
|
+
},
|
|
51
|
+
]);
|
|
52
|
+
}
|
|
53
|
+
if (roleCount.count === 0) {
|
|
54
|
+
const roles = await dbClient
|
|
55
|
+
.insert(core_roles)
|
|
56
|
+
.values([
|
|
57
|
+
{
|
|
58
|
+
protected: true,
|
|
59
|
+
guest: true,
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
protected: true,
|
|
63
|
+
default: true,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
protected: true,
|
|
67
|
+
color: "hsl(122, 80%, 45%)",
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
protected: true,
|
|
71
|
+
root: true,
|
|
72
|
+
color: "hsl(0, 100%, 50%)",
|
|
73
|
+
},
|
|
74
|
+
])
|
|
75
|
+
.returning({ id: core_roles.id });
|
|
76
|
+
await dbClient.insert(core_languages_words).values([
|
|
77
|
+
{
|
|
78
|
+
languageCode: "en",
|
|
79
|
+
pluginCode: "core",
|
|
80
|
+
itemId: roles[0].id,
|
|
81
|
+
value: "Guest",
|
|
82
|
+
tableName: "core_roles",
|
|
83
|
+
variable: "name",
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
languageCode: "en",
|
|
87
|
+
pluginCode: "core",
|
|
88
|
+
itemId: roles[1].id,
|
|
89
|
+
value: "Member",
|
|
90
|
+
tableName: "core_roles",
|
|
91
|
+
variable: "name",
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
languageCode: "en",
|
|
95
|
+
pluginCode: "core",
|
|
96
|
+
itemId: roles[2].id,
|
|
97
|
+
value: "Moderator",
|
|
98
|
+
tableName: "core_roles",
|
|
99
|
+
variable: "name",
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
languageCode: "en",
|
|
103
|
+
pluginCode: "core",
|
|
104
|
+
itemId: roles[3].id,
|
|
105
|
+
value: "Administrator",
|
|
106
|
+
tableName: "core_roles",
|
|
107
|
+
variable: "name",
|
|
108
|
+
},
|
|
109
|
+
]);
|
|
110
|
+
await dbClient.insert(core_moderators_permissions).values([
|
|
111
|
+
{
|
|
112
|
+
roleId: roles[2].id,
|
|
113
|
+
protected: true,
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
roleId: roles[3].id,
|
|
117
|
+
protected: true,
|
|
118
|
+
},
|
|
119
|
+
]);
|
|
120
|
+
await dbClient.insert(core_admin_permissions).values({
|
|
121
|
+
roleId: roles[3].id,
|
|
122
|
+
protected: true,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
export const prepareDatabase = async ({ initMessage, flag, }) => {
|
|
127
|
+
const steps = [];
|
|
128
|
+
if (flag === "--web") {
|
|
129
|
+
steps.push({
|
|
130
|
+
label: "Prepare plugins files...",
|
|
131
|
+
action: async () => await preparePluginsFiles(flag),
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
else if (flag === "--api") {
|
|
135
|
+
steps.push({
|
|
136
|
+
label: "Prepare plugins files...",
|
|
137
|
+
action: async () => await preparePluginsFiles(flag),
|
|
138
|
+
}, {
|
|
139
|
+
label: "Generate migrations...",
|
|
140
|
+
action: generateDatabaseMigrations,
|
|
141
|
+
}, {
|
|
142
|
+
label: "Run migrations...",
|
|
143
|
+
action: runMigrations,
|
|
144
|
+
}, {
|
|
145
|
+
label: "Insert initial data...",
|
|
146
|
+
action: initialDataForDatabase,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
steps.push({
|
|
151
|
+
label: "Prepare plugins files...",
|
|
152
|
+
action: async () => await preparePluginsFiles(flag),
|
|
153
|
+
}, {
|
|
154
|
+
label: "Generate migrations...",
|
|
155
|
+
action: generateDatabaseMigrations,
|
|
156
|
+
}, {
|
|
157
|
+
label: "Run migrations...",
|
|
158
|
+
action: runMigrations,
|
|
159
|
+
}, {
|
|
160
|
+
label: "Insert initial data...",
|
|
161
|
+
action: initialDataForDatabase,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
for (let i = 0; i < steps.length; i++) {
|
|
165
|
+
const step = steps[i];
|
|
166
|
+
const stepNum = `[${i + 1}/${steps.length}]`;
|
|
167
|
+
if (step.label === "Insert initial data...") {
|
|
168
|
+
console.log(`\n${initMessage} ${stepNum} ${step.label}`);
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
console.log(`${initMessage} ${stepNum} ${step.label}`);
|
|
172
|
+
}
|
|
173
|
+
await step.action();
|
|
174
|
+
}
|
|
175
|
+
console.log(`${initMessage} \x1b[32mInitial setup completed.\x1b[0m`);
|
|
176
|
+
process.exit(0);
|
|
177
|
+
};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { join, relative } from "node:path";
|
|
4
|
+
import { getConfig } from "./get-config";
|
|
5
|
+
import { buildInitialRouteMap, copyDirectoryRecursive, findLocaleRoot, findRepoRoot, isDirectoryEmpty, } from "./shared/file-utils";
|
|
6
|
+
export const preparePluginsFiles = async (flag) => {
|
|
7
|
+
const cwd = process.cwd();
|
|
8
|
+
const hasWebConfig = existsSync(join(cwd, "src", "vitnode.config.ts"));
|
|
9
|
+
const hasApiConfig = existsSync(join(cwd, "src", "vitnode.api.config.ts"));
|
|
10
|
+
let config;
|
|
11
|
+
if (flag === "--api" && hasApiConfig) {
|
|
12
|
+
config = await getConfig({ type: "api.config" });
|
|
13
|
+
}
|
|
14
|
+
else if (flag === "--web" && hasWebConfig) {
|
|
15
|
+
config = await getConfig({});
|
|
16
|
+
}
|
|
17
|
+
else if (hasApiConfig && !hasWebConfig) {
|
|
18
|
+
config = await getConfig({ type: "api.config" });
|
|
19
|
+
}
|
|
20
|
+
else if (hasWebConfig) {
|
|
21
|
+
config = await getConfig({});
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
config = { plugins: [] };
|
|
25
|
+
}
|
|
26
|
+
const plugins = [
|
|
27
|
+
...config.plugins.map(plugin => plugin.pluginId),
|
|
28
|
+
"@vitnode/core",
|
|
29
|
+
];
|
|
30
|
+
const repoRoot = findRepoRoot(process.cwd());
|
|
31
|
+
const localeRoot = findLocaleRoot(repoRoot);
|
|
32
|
+
const routeMap = buildInitialRouteMap(localeRoot);
|
|
33
|
+
const baseDir = process.cwd();
|
|
34
|
+
const findPluginPath = (pluginName) => {
|
|
35
|
+
const cwd = process.cwd();
|
|
36
|
+
const cwdPluginPath = join(cwd, "node_modules", pluginName);
|
|
37
|
+
if (existsSync(cwdPluginPath)) {
|
|
38
|
+
return cwdPluginPath;
|
|
39
|
+
}
|
|
40
|
+
if (repoRoot && repoRoot !== cwd) {
|
|
41
|
+
const rootPluginPath = join(repoRoot, "node_modules", pluginName);
|
|
42
|
+
if (existsSync(rootPluginPath)) {
|
|
43
|
+
return rootPluginPath;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
};
|
|
48
|
+
await Promise.all(plugins.map(async (pluginName) => {
|
|
49
|
+
const pluginPath = findPluginPath(pluginName);
|
|
50
|
+
if (!pluginPath) {
|
|
51
|
+
console.error(`\x1b[31mPlugin not found:\x1b[0m ${pluginName} in node_modules`);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
let packageName = "";
|
|
55
|
+
try {
|
|
56
|
+
const packageJsonPath = join(pluginPath, "package.json");
|
|
57
|
+
if (existsSync(packageJsonPath)) {
|
|
58
|
+
const packageJson = JSON.parse(await readFile(packageJsonPath, "utf-8"));
|
|
59
|
+
packageName = packageJson.name ?? "";
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
console.error(`\x1b[31mError reading package.json for ${pluginName}:\x1b[0m`, error);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const pluginPathName = pluginName.replace(/\//g, "-").replace(/@/g, "");
|
|
67
|
+
const detectAppType = (appPath) => {
|
|
68
|
+
const hasWebConfig = existsSync(join(appPath, "src", "vitnode.config.ts"));
|
|
69
|
+
const hasApiConfig = existsSync(join(appPath, "src", "vitnode.api.config.ts"));
|
|
70
|
+
if (hasApiConfig && !hasWebConfig)
|
|
71
|
+
return "api";
|
|
72
|
+
if (hasWebConfig)
|
|
73
|
+
return "web";
|
|
74
|
+
return null;
|
|
75
|
+
};
|
|
76
|
+
const appsDir = join(repoRoot, "apps");
|
|
77
|
+
const isMonorepo = existsSync(appsDir);
|
|
78
|
+
const sources = [];
|
|
79
|
+
if (isMonorepo) {
|
|
80
|
+
const appDirs = existsSync(appsDir)
|
|
81
|
+
? readdirSync(appsDir, { withFileTypes: true })
|
|
82
|
+
.filter(dirent => dirent.isDirectory())
|
|
83
|
+
.map(dirent => dirent.name)
|
|
84
|
+
: [];
|
|
85
|
+
for (const appName of appDirs) {
|
|
86
|
+
const appPath = join(repoRoot, "apps", appName);
|
|
87
|
+
const appType = detectAppType(appPath);
|
|
88
|
+
if (appType === "web") {
|
|
89
|
+
const mainDest = join(appPath, "src", "app", "[locale]", "(main)", join("(plugins)", `(${pluginPathName})`));
|
|
90
|
+
const adminDest = join(appPath, "src", "app", "[locale]", "admin", "(auth)", join("(plugins)", `(${pluginPathName})`));
|
|
91
|
+
const langDest = join(appPath, "src", "locales", pluginName);
|
|
92
|
+
sources.push({
|
|
93
|
+
sourceDir: join(pluginPath, "src", "app_admin"),
|
|
94
|
+
destinationDir: adminDest,
|
|
95
|
+
}, {
|
|
96
|
+
sourceDir: join(pluginPath, "src", "app"),
|
|
97
|
+
destinationDir: mainDest,
|
|
98
|
+
}, {
|
|
99
|
+
sourceDir: join(pluginPath, "src", "locales"),
|
|
100
|
+
destinationDir: langDest,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
else if (appType === "api") {
|
|
104
|
+
const apiLangDest = join(appPath, "src", "locales", pluginName);
|
|
105
|
+
sources.push({
|
|
106
|
+
sourceDir: join(pluginPath, "src", "locales"),
|
|
107
|
+
destinationDir: apiLangDest,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
const mainDest = join(baseDir, "src", "app", "[locale]", "(main)", join("(plugins)", `(${pluginPathName})`));
|
|
114
|
+
const adminDest = join(baseDir, "src", "app", "[locale]", "admin", "(auth)", join("(plugins)", `(${pluginPathName})`));
|
|
115
|
+
const langDest = join(baseDir, "src", "locales", pluginName);
|
|
116
|
+
sources.push({
|
|
117
|
+
sourceDir: join(pluginPath, "src", "app_admin"),
|
|
118
|
+
destinationDir: adminDest,
|
|
119
|
+
}, {
|
|
120
|
+
sourceDir: join(pluginPath, "src", "app"),
|
|
121
|
+
destinationDir: mainDest,
|
|
122
|
+
}, {
|
|
123
|
+
sourceDir: join(pluginPath, "src", "locales"),
|
|
124
|
+
destinationDir: langDest,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
for (const { sourceDir, destinationDir } of sources) {
|
|
128
|
+
if (existsSync(sourceDir) && !isDirectoryEmpty(sourceDir)) {
|
|
129
|
+
console.log(`\x1b[36mCopying ${pluginName}:\x1b[0m ${relative(repoRoot, sourceDir)} → ${relative(repoRoot, destinationDir)}`);
|
|
130
|
+
copyDirectoryRecursive(sourceDir, destinationDir, packageName, routeMap, localeRoot, repoRoot, false);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}));
|
|
134
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
export const runInteractiveShellCommand = async (cmd, args = []) => {
|
|
3
|
+
return await new Promise((resolve, reject) => {
|
|
4
|
+
const child = spawn(cmd, args, {
|
|
5
|
+
stdio: "inherit",
|
|
6
|
+
shell: true,
|
|
7
|
+
env: process.env,
|
|
8
|
+
});
|
|
9
|
+
child.on("error", error => {
|
|
10
|
+
reject(error);
|
|
11
|
+
});
|
|
12
|
+
child.on("close", code => {
|
|
13
|
+
if (code !== 0) {
|
|
14
|
+
reject(new Error(`Command failed with exit code ${code}`));
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
resolve(true);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
};
|