@motiadev/workbench 0.14.0-beta.165-285707 → 0.15.0-beta.165
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/index.d.ts +189 -10
- package/dist/index.html +1 -1
- package/dist/index.js +1065 -7
- package/dist/middleware.d.ts +66 -8
- package/dist/middleware.js +694 -86
- package/dist/motia-plugin/__tests__/generator.test.ts +129 -0
- package/dist/motia-plugin/__tests__/resolver.test.ts +82 -0
- package/dist/motia-plugin/__tests__/validator.test.ts +71 -0
- package/dist/motia-plugin/{generator.js → generator.ts} +37 -35
- package/dist/motia-plugin/hmr.ts +123 -0
- package/dist/motia-plugin/index.ts +183 -0
- package/dist/motia-plugin/{resolver.d.ts → resolver.ts} +38 -5
- package/dist/motia-plugin/types.ts +198 -0
- package/dist/motia-plugin/{utils.d.ts → utils.ts} +17 -4
- package/dist/motia-plugin/validator.ts +197 -0
- package/dist/src/App.tsx +41 -0
- package/dist/src/components/NotFoundPage.tsx +11 -0
- package/dist/src/components/bottom-panel.tsx +39 -0
- package/dist/src/components/flow/base-edge.tsx +61 -0
- package/dist/src/components/flow/flow-loader.tsx +3 -0
- package/dist/src/components/flow/flow-page.tsx +75 -0
- package/dist/src/components/flow/flow-tab-menu-item.tsx +52 -0
- package/dist/src/components/flow/flow-view.tsx +66 -0
- package/dist/src/components/flow/hooks/use-get-flow-state.tsx +171 -0
- package/dist/src/components/flow/hooks/use-save-workflow-config.ts +25 -0
- package/dist/src/components/flow/node-organizer.tsx +103 -0
- package/dist/src/components/flow/nodes/api-flow-node.tsx +6 -0
- package/dist/src/components/flow/nodes/cron-flow-node.tsx +6 -0
- package/dist/src/components/flow/nodes/event-flow-node.tsx +6 -0
- package/dist/src/components/flow/nodes/noop-flow-node.tsx +6 -0
- package/dist/src/components/header/deploy-button.tsx +110 -0
- package/dist/src/components/header/header.tsx +39 -0
- package/dist/src/components/root-motia.tsx +10 -0
- package/dist/src/components/top-panel.tsx +40 -0
- package/dist/src/components/tutorial/engine/tutorial-engine.ts +26 -0
- package/dist/src/components/tutorial/engine/tutorial-types.ts +26 -0
- package/dist/src/components/tutorial/engine/workbench-xpath.ts +53 -0
- package/dist/src/components/tutorial/hooks/tutorial-utils.ts +26 -0
- package/dist/src/components/tutorial/hooks/use-tutorial-engine.ts +213 -0
- package/dist/src/components/tutorial/hooks/use-tutorial.ts +14 -0
- package/dist/src/components/tutorial/tutorial-button.tsx +46 -0
- package/dist/src/components/tutorial/tutorial-step.tsx +82 -0
- package/dist/src/components/tutorial/tutorial.tsx +59 -0
- package/dist/src/components/ui/json-editor.tsx +68 -0
- package/dist/src/components/ui/table.tsx +75 -0
- package/dist/src/components/ui/theme-toggle.tsx +54 -0
- package/dist/src/components/ui/tooltip.tsx +26 -0
- package/dist/src/hooks/use-debounced.ts +22 -0
- package/dist/src/hooks/use-fetch-flows.ts +33 -0
- package/dist/src/hooks/use-mobile.ts +19 -0
- package/dist/src/hooks/use-update-handle-positions.ts +42 -0
- package/dist/src/index.css +5 -5
- package/dist/src/lib/__tests__/utils.test.ts +110 -0
- package/dist/src/lib/motia-analytics.ts +140 -0
- package/dist/src/lib/plugins.tsx +132 -0
- package/dist/src/lib/utils.ts +37 -0
- package/dist/src/main.tsx +30 -0
- package/dist/src/project-view-mode.tsx +32 -0
- package/dist/src/publicComponents/api-node.tsx +26 -0
- package/dist/src/publicComponents/base-node/base-handle.tsx +50 -0
- package/dist/src/publicComponents/base-node/base-node.tsx +114 -0
- package/dist/src/publicComponents/base-node/code-display.tsx +119 -0
- package/dist/src/publicComponents/base-node/emits.tsx +17 -0
- package/dist/src/publicComponents/base-node/feature-card.tsx +32 -0
- package/dist/src/publicComponents/base-node/language-indicator.tsx +131 -0
- package/dist/src/publicComponents/base-node/node-header.tsx +49 -0
- package/dist/src/publicComponents/base-node/node-sidebar.tsx +41 -0
- package/dist/src/publicComponents/base-node/subscribe.tsx +13 -0
- package/dist/src/publicComponents/cron-node.tsx +24 -0
- package/dist/src/publicComponents/event-node.tsx +20 -0
- package/dist/src/publicComponents/node-props.tsx +15 -0
- package/dist/src/publicComponents/noop-node.tsx +19 -0
- package/dist/src/setupTests.ts +1 -0
- package/dist/src/stores/use-app-tabs-store.ts +49 -0
- package/dist/src/stores/use-flow-store.ts +31 -0
- package/dist/src/stores/use-global-store.ts +24 -0
- package/dist/src/stores/use-motia-config-store.ts +36 -0
- package/dist/src/stores/use-tabs-store.ts +34 -0
- package/dist/src/system-view-mode.tsx +28 -0
- package/dist/src/types/endpoint.ts +12 -0
- package/dist/src/types/file.ts +7 -0
- package/dist/src/types/flow.ts +103 -0
- package/eslint.config.cjs +22 -0
- package/jest.config.cjs +68 -0
- package/package.json +53 -51
- package/dist/motia-plugin/__tests__/generator.test.d.ts +0 -1
- package/dist/motia-plugin/__tests__/generator.test.js +0 -97
- package/dist/motia-plugin/__tests__/resolver.test.d.ts +0 -1
- package/dist/motia-plugin/__tests__/resolver.test.js +0 -64
- package/dist/motia-plugin/__tests__/validator.test.d.ts +0 -1
- package/dist/motia-plugin/__tests__/validator.test.js +0 -59
- package/dist/motia-plugin/generator.d.ts +0 -78
- package/dist/motia-plugin/hmr.d.ts +0 -22
- package/dist/motia-plugin/hmr.js +0 -100
- package/dist/motia-plugin/index.d.ts +0 -3
- package/dist/motia-plugin/index.js +0 -153
- package/dist/motia-plugin/resolver.js +0 -92
- package/dist/motia-plugin/types.d.ts +0 -169
- package/dist/motia-plugin/types.js +0 -36
- package/dist/motia-plugin/utils.js +0 -75
- package/dist/motia-plugin/validator.d.ts +0 -19
- package/dist/motia-plugin/validator.js +0 -163
- package/dist/src/App.d.ts +0 -2
- package/dist/src/App.js +0 -35
- package/dist/src/components/NotFoundPage.d.ts +0 -1
- package/dist/src/components/NotFoundPage.js +0 -3
- package/dist/src/components/bottom-panel.d.ts +0 -1
- package/dist/src/components/bottom-panel.js +0 -15
- package/dist/src/components/flow/base-edge.d.ts +0 -3
- package/dist/src/components/flow/base-edge.js +0 -39
- package/dist/src/components/flow/flow-loader.d.ts +0 -1
- package/dist/src/components/flow/flow-loader.js +0 -4
- package/dist/src/components/flow/flow-page.d.ts +0 -1
- package/dist/src/components/flow/flow-page.js +0 -25
- package/dist/src/components/flow/flow-tab-menu-item.d.ts +0 -1
- package/dist/src/components/flow/flow-tab-menu-item.js +0 -18
- package/dist/src/components/flow/flow-view.d.ts +0 -12
- package/dist/src/components/flow/flow-view.js +0 -22
- package/dist/src/components/flow/hooks/use-get-flow-state.d.ts +0 -10
- package/dist/src/components/flow/hooks/use-get-flow-state.js +0 -133
- package/dist/src/components/flow/hooks/use-save-workflow-config.d.ts +0 -2
- package/dist/src/components/flow/hooks/use-save-workflow-config.js +0 -22
- package/dist/src/components/flow/node-organizer.d.ts +0 -10
- package/dist/src/components/flow/node-organizer.js +0 -82
- package/dist/src/components/flow/nodes/api-flow-node.d.ts +0 -2
- package/dist/src/components/flow/nodes/api-flow-node.js +0 -5
- package/dist/src/components/flow/nodes/cron-flow-node.d.ts +0 -2
- package/dist/src/components/flow/nodes/cron-flow-node.js +0 -5
- package/dist/src/components/flow/nodes/event-flow-node.d.ts +0 -2
- package/dist/src/components/flow/nodes/event-flow-node.js +0 -5
- package/dist/src/components/flow/nodes/noop-flow-node.d.ts +0 -2
- package/dist/src/components/flow/nodes/noop-flow-node.js +0 -5
- package/dist/src/components/header/deploy-button.d.ts +0 -1
- package/dist/src/components/header/deploy-button.js +0 -28
- package/dist/src/components/header/header.d.ts +0 -2
- package/dist/src/components/header/header.js +0 -23
- package/dist/src/components/root-motia.d.ts +0 -2
- package/dist/src/components/root-motia.js +0 -7
- package/dist/src/components/top-panel.d.ts +0 -1
- package/dist/src/components/top-panel.js +0 -15
- package/dist/src/components/tutorial/engine/tutorial-engine.d.ts +0 -12
- package/dist/src/components/tutorial/engine/tutorial-engine.js +0 -36
- package/dist/src/components/tutorial/engine/tutorial-types.d.ts +0 -22
- package/dist/src/components/tutorial/engine/tutorial-types.js +0 -1
- package/dist/src/components/tutorial/engine/workbench-xpath.d.ts +0 -45
- package/dist/src/components/tutorial/engine/workbench-xpath.js +0 -45
- package/dist/src/components/tutorial/hooks/tutorial-utils.d.ts +0 -1
- package/dist/src/components/tutorial/hooks/tutorial-utils.js +0 -17
- package/dist/src/components/tutorial/hooks/use-tutorial-engine.d.ts +0 -15
- package/dist/src/components/tutorial/hooks/use-tutorial-engine.js +0 -183
- package/dist/src/components/tutorial/hooks/use-tutorial.d.ts +0 -5
- package/dist/src/components/tutorial/hooks/use-tutorial.js +0 -10
- package/dist/src/components/tutorial/tutorial-button.d.ts +0 -2
- package/dist/src/components/tutorial/tutorial-button.js +0 -21
- package/dist/src/components/tutorial/tutorial-step.d.ts +0 -14
- package/dist/src/components/tutorial/tutorial-step.js +0 -19
- package/dist/src/components/tutorial/tutorial.d.ts +0 -2
- package/dist/src/components/tutorial/tutorial.js +0 -32
- package/dist/src/components/ui/json-editor.d.ts +0 -12
- package/dist/src/components/ui/json-editor.js +0 -35
- package/dist/src/components/ui/table.d.ts +0 -10
- package/dist/src/components/ui/table.js +0 -20
- package/dist/src/components/ui/theme-toggle.d.ts +0 -2
- package/dist/src/components/ui/theme-toggle.js +0 -19
- package/dist/src/components/ui/tooltip.d.ts +0 -6
- package/dist/src/components/ui/tooltip.js +0 -3
- package/dist/src/hooks/use-debounced.d.ts +0 -1
- package/dist/src/hooks/use-debounced.js +0 -18
- package/dist/src/hooks/use-fetch-flows.d.ts +0 -1
- package/dist/src/hooks/use-fetch-flows.js +0 -26
- package/dist/src/hooks/use-mobile.d.ts +0 -1
- package/dist/src/hooks/use-mobile.js +0 -15
- package/dist/src/hooks/use-update-handle-positions.d.ts +0 -10
- package/dist/src/hooks/use-update-handle-positions.js +0 -35
- package/dist/src/lib/__tests__/utils.test.d.ts +0 -1
- package/dist/src/lib/__tests__/utils.test.js +0 -94
- package/dist/src/lib/motia-analytics.d.ts +0 -38
- package/dist/src/lib/motia-analytics.js +0 -132
- package/dist/src/lib/plugins.d.ts +0 -2
- package/dist/src/lib/plugins.js +0 -105
- package/dist/src/lib/utils.d.ts +0 -7
- package/dist/src/lib/utils.js +0 -34
- package/dist/src/main.d.ts +0 -2
- package/dist/src/main.js +0 -17
- package/dist/src/project-view-mode.d.ts +0 -1
- package/dist/src/project-view-mode.js +0 -20
- package/dist/src/publicComponents/api-node.d.ts +0 -5
- package/dist/src/publicComponents/api-node.js +0 -5
- package/dist/src/publicComponents/base-node/base-handle.d.ts +0 -9
- package/dist/src/publicComponents/base-node/base-handle.js +0 -8
- package/dist/src/publicComponents/base-node/base-node.d.ts +0 -15
- package/dist/src/publicComponents/base-node/base-node.js +0 -30
- package/dist/src/publicComponents/base-node/code-display.d.ts +0 -9
- package/dist/src/publicComponents/base-node/code-display.js +0 -64
- package/dist/src/publicComponents/base-node/emits.d.ts +0 -5
- package/dist/src/publicComponents/base-node/emits.js +0 -5
- package/dist/src/publicComponents/base-node/feature-card.d.ts +0 -10
- package/dist/src/publicComponents/base-node/feature-card.js +0 -5
- package/dist/src/publicComponents/base-node/language-indicator.d.ts +0 -10
- package/dist/src/publicComponents/base-node/language-indicator.js +0 -29
- package/dist/src/publicComponents/base-node/node-header.d.ts +0 -13
- package/dist/src/publicComponents/base-node/node-header.js +0 -30
- package/dist/src/publicComponents/base-node/node-sidebar.d.ts +0 -14
- package/dist/src/publicComponents/base-node/node-sidebar.js +0 -9
- package/dist/src/publicComponents/base-node/subscribe.d.ts +0 -4
- package/dist/src/publicComponents/base-node/subscribe.js +0 -4
- package/dist/src/publicComponents/cron-node.d.ts +0 -4
- package/dist/src/publicComponents/cron-node.js +0 -6
- package/dist/src/publicComponents/event-node.d.ts +0 -4
- package/dist/src/publicComponents/event-node.js +0 -5
- package/dist/src/publicComponents/node-props.d.ts +0 -21
- package/dist/src/publicComponents/node-props.js +0 -1
- package/dist/src/publicComponents/noop-node.d.ts +0 -4
- package/dist/src/publicComponents/noop-node.js +0 -5
- package/dist/src/setupTests.d.ts +0 -1
- package/dist/src/setupTests.js +0 -1
- package/dist/src/stores/use-app-tabs-store.d.ts +0 -16
- package/dist/src/stores/use-app-tabs-store.js +0 -31
- package/dist/src/stores/use-flow-store.d.ts +0 -21
- package/dist/src/stores/use-flow-store.js +0 -16
- package/dist/src/stores/use-global-store.d.ts +0 -18
- package/dist/src/stores/use-global-store.js +0 -12
- package/dist/src/stores/use-motia-config-store.d.ts +0 -12
- package/dist/src/stores/use-motia-config-store.js +0 -24
- package/dist/src/stores/use-tabs-store.d.ts +0 -19
- package/dist/src/stores/use-tabs-store.js +0 -22
- package/dist/src/system-view-mode.d.ts +0 -1
- package/dist/src/system-view-mode.js +0 -10
- package/dist/src/types/endpoint.d.ts +0 -14
- package/dist/src/types/endpoint.js +0 -1
- package/dist/src/types/file.d.ts +0 -7
- package/dist/src/types/file.js +0 -1
- package/dist/src/types/flow.d.ts +0 -115
- package/dist/src/types/flow.js +0 -1
- package/dist/tsconfig.app.tsbuildinfo +0 -1
- package/dist/tsconfig.node.tsbuildinfo +0 -1
package/dist/middleware.js
CHANGED
|
@@ -1,98 +1,706 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { Printer } from "@motiadev/core";
|
|
2
|
+
import react from "@vitejs/plugin-react";
|
|
3
|
+
import fs, { existsSync } from "fs";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
import { createServer } from "vite";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
|
|
9
|
+
//#region motia-plugin/utils.ts
|
|
10
|
+
/**
|
|
11
|
+
* Normalizes a file path by replacing backslashes with forward slashes.
|
|
12
|
+
* This is useful for consistent path comparisons across different operating systems.
|
|
13
|
+
*
|
|
14
|
+
* @param filePath - The file path to normalize
|
|
15
|
+
* @returns The normalized file path with forward slashes
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* normalizePath('C:\\Users\\file.ts') // Returns: 'C:/Users/file.ts'
|
|
20
|
+
* normalizePath('/Users/file.ts') // Returns: '/Users/file.ts'
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
function normalizePath(filePath) {
|
|
24
|
+
return filePath.replace(/\\/g, "/");
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Checks if a package name represents a local plugin (starts with ~/).
|
|
28
|
+
*
|
|
29
|
+
* @param packageName - The package name to check
|
|
30
|
+
* @returns True if the package is a local plugin
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* isLocalPlugin('~/plugins/my-plugin') // Returns: true
|
|
35
|
+
* isLocalPlugin('@my-org/my-plugin') // Returns: false
|
|
36
|
+
* isLocalPlugin('my-plugin') // Returns: false
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
function isLocalPlugin(packageName) {
|
|
40
|
+
return packageName.startsWith("~/");
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Resolves a local plugin path to an absolute path.
|
|
44
|
+
* Strips the ~/ prefix and joins with the current working directory.
|
|
45
|
+
*
|
|
46
|
+
* @param packageName - The local plugin package name (must start with ~/)
|
|
47
|
+
* @returns The absolute path to the local plugin
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* // If cwd is /Users/project
|
|
52
|
+
* resolveLocalPath('~/plugins/my-plugin')
|
|
53
|
+
* // Returns: '/Users/project/plugins/my-plugin'
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
function resolveLocalPath(packageName) {
|
|
57
|
+
return path.join(process.cwd(), packageName.replace("~/", ""));
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Resolves an npm package path to the node_modules directory.
|
|
61
|
+
*
|
|
62
|
+
* @param packageName - The npm package name
|
|
63
|
+
* @returns The absolute path to the package in node_modules
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```ts
|
|
67
|
+
* // If cwd is /Users/project
|
|
68
|
+
* resolveNpmPath('@my-org/my-plugin')
|
|
69
|
+
* // Returns: '/Users/project/node_modules/@my-org/my-plugin'
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
function resolveNpmPath(packageName) {
|
|
73
|
+
return path.join(process.cwd(), "node_modules", packageName);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
//#endregion
|
|
77
|
+
//#region motia-plugin/resolver.ts
|
|
78
|
+
/**
|
|
79
|
+
* Resolves a plugin package to its absolute path and creates an alias.
|
|
80
|
+
*
|
|
81
|
+
* @param plugin - The plugin configuration to resolve
|
|
82
|
+
* @returns Resolved package information including path and alias
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* // Local plugin
|
|
87
|
+
* resolvePluginPackage({ packageName: '~/plugins/my-plugin' })
|
|
88
|
+
* // Returns: {
|
|
89
|
+
* // packageName: '~/plugins/my-plugin',
|
|
90
|
+
* // resolvedPath: '/Users/project/plugins/my-plugin',
|
|
91
|
+
* // isLocal: true,
|
|
92
|
+
* // alias: '~/plugins/my-plugin'
|
|
93
|
+
* // }
|
|
94
|
+
*
|
|
95
|
+
* // NPM package
|
|
96
|
+
* resolvePluginPackage({ packageName: '@org/plugin' })
|
|
97
|
+
* // Returns: {
|
|
98
|
+
* // packageName: '@org/plugin',
|
|
99
|
+
* // resolvedPath: '/Users/project/node_modules/@org/plugin',
|
|
100
|
+
* // isLocal: false,
|
|
101
|
+
* // alias: '@org/plugin'
|
|
102
|
+
* // }
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
function resolvePluginPackage(plugin) {
|
|
106
|
+
const { packageName } = plugin;
|
|
107
|
+
const local = isLocalPlugin(packageName);
|
|
108
|
+
return {
|
|
109
|
+
packageName,
|
|
110
|
+
resolvedPath: normalizePath(local ? resolveLocalPath(packageName) : resolveNpmPath(packageName)),
|
|
111
|
+
isLocal: local,
|
|
112
|
+
alias: packageName
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Resolves all plugin packages and creates a Vite alias configuration.
|
|
117
|
+
*
|
|
118
|
+
* @param plugins - Array of plugin configurations
|
|
119
|
+
* @returns Vite alias configuration object
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```ts
|
|
123
|
+
* const plugins = [
|
|
124
|
+
* { packageName: '~/plugins/local' },
|
|
125
|
+
* { packageName: '@org/npm-plugin' }
|
|
126
|
+
* ]
|
|
127
|
+
* const aliases = createAliasConfig(plugins)
|
|
128
|
+
* // Returns: {
|
|
129
|
+
* // '~/plugins/local': '/Users/project/plugins/local',
|
|
130
|
+
* // '@org/npm-plugin': '/Users/project/node_modules/@org/npm-plugin'
|
|
131
|
+
* // }
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
function createAliasConfig(plugins) {
|
|
135
|
+
const uniquePackages = Array.from(new Set(plugins.map((p) => p.packageName)));
|
|
136
|
+
const aliases = {};
|
|
137
|
+
for (const packageName of uniquePackages) aliases[packageName] = resolvePluginPackage({ packageName }).resolvedPath;
|
|
138
|
+
return aliases;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Gets the unique set of package names from plugins.
|
|
142
|
+
*
|
|
143
|
+
* @param plugins - Array of plugin configurations
|
|
144
|
+
* @returns Array of unique package names
|
|
145
|
+
*/
|
|
146
|
+
function getUniquePackageNames(plugins) {
|
|
147
|
+
return Array.from(new Set(plugins.map((p) => p.packageName)));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
//#endregion
|
|
151
|
+
//#region motia-plugin/generator.ts
|
|
152
|
+
/**
|
|
153
|
+
* Generates import statements for all unique plugin packages.
|
|
154
|
+
*
|
|
155
|
+
* @param packages - Array of unique package names
|
|
156
|
+
* @returns JavaScript code string with import statements
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```ts
|
|
160
|
+
* generateImports(['@org/plugin-1', '~/plugins/local'])
|
|
161
|
+
* // Returns:
|
|
162
|
+
* // import * as plugin_0 from '@org/plugin-1'
|
|
163
|
+
* // import * as plugin_1 from '~/plugins/local'
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
function generateImports(packages) {
|
|
167
|
+
return packages.map((packageName, index) => `import * as plugin_${index} from '${packageName}'`).join("\n");
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Generates the package map that links package names to their imported modules.
|
|
171
|
+
*
|
|
172
|
+
* @param packages - Array of unique package names
|
|
173
|
+
* @returns JavaScript code string defining the package map
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```ts
|
|
177
|
+
* generatePackageMap(['@org/plugin-1', '~/plugins/local'])
|
|
178
|
+
* // Returns: const packageMap = {'@org/plugin-1': plugin_0,'~/plugins/local': plugin_1}
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
function generatePackageMap(packages) {
|
|
182
|
+
return `const packageMap = {${packages.map((packageName, index) => `'${packageName}': plugin_${index}`).join(",")}}`;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Generates the plugin transformation logic that processes plugin configurations.
|
|
186
|
+
*
|
|
187
|
+
* @param plugins - Array of plugin configurations
|
|
188
|
+
* @returns JavaScript code string with plugin processing logic
|
|
189
|
+
*/
|
|
190
|
+
function generatePluginLogic(plugins) {
|
|
191
|
+
return `
|
|
192
|
+
const motiaPlugins = ${JSON.stringify(plugins)}
|
|
193
|
+
|
|
194
|
+
export const plugins = motiaPlugins.map((plugin) => {
|
|
195
|
+
const component = packageMap[plugin.packageName]
|
|
196
|
+
const config = component.config || {}
|
|
197
|
+
const componentName = config.componentName || plugin.componentName
|
|
198
|
+
|
|
199
|
+
return {
|
|
200
|
+
label: plugin.label || config.label || 'Plugin label',
|
|
201
|
+
labelIcon: plugin.labelIcon || config.labelIcon || 'toy-brick',
|
|
202
|
+
position: plugin.position || config.position || 'top',
|
|
203
|
+
props: plugin.props || config.props || {},
|
|
204
|
+
component: componentName ? component[componentName] : component.default,
|
|
205
|
+
}
|
|
206
|
+
})
|
|
207
|
+
`;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Generates the complete virtual module code for all plugins.
|
|
211
|
+
* This is the main code generation function that combines all parts.
|
|
212
|
+
*
|
|
213
|
+
* @param plugins - Array of plugin configurations
|
|
214
|
+
* @returns Complete JavaScript code string for the virtual module
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* ```ts
|
|
218
|
+
* const plugins = [
|
|
219
|
+
* { packageName: '@test/plugin', label: 'Test' }
|
|
220
|
+
* ]
|
|
221
|
+
* const code = generatePluginCode(plugins)
|
|
222
|
+
* // Returns complete module code with imports, map, and logic
|
|
223
|
+
* ```
|
|
224
|
+
*/
|
|
225
|
+
function generatePluginCode(plugins) {
|
|
226
|
+
if (!plugins || plugins.length === 0) return "export const plugins = []";
|
|
227
|
+
const packages = getUniquePackageNames(plugins);
|
|
228
|
+
return `${generateImports(packages)}
|
|
229
|
+
${generatePackageMap(packages)}
|
|
230
|
+
${generatePluginLogic(plugins)}`;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Generates CSS imports for plugins that specify cssImports.
|
|
234
|
+
*
|
|
235
|
+
* @param plugins - Array of plugin configurations
|
|
236
|
+
* @returns CSS import statements as a string
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* ```ts
|
|
240
|
+
* const plugins = [
|
|
241
|
+
* { packageName: '@test/plugin', cssImports: ['styles.css', 'theme.css'] }
|
|
242
|
+
* ]
|
|
243
|
+
* generateCssImports(plugins)
|
|
244
|
+
* // Returns:
|
|
245
|
+
* // @import 'styles.css';
|
|
246
|
+
* // @import 'theme.css';
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
function generateCssImports(plugins) {
|
|
250
|
+
return plugins.flatMap((plugin) => plugin.cssImports || []).filter((cssImport) => cssImport && cssImport.trim() !== "").map((cssImport) => `@import '${cssImport}';`).join("\n");
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Checks if the generated code is valid (non-empty and has content).
|
|
254
|
+
*
|
|
255
|
+
* @param code - The generated code to check
|
|
256
|
+
* @returns True if code is valid
|
|
257
|
+
*/
|
|
258
|
+
function isValidCode(code) {
|
|
259
|
+
return typeof code === "string" && code.trim().length > 0;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
//#endregion
|
|
263
|
+
//#region motia-plugin/types.ts
|
|
264
|
+
/**
|
|
265
|
+
* Type guard to check if position is valid.
|
|
266
|
+
*/
|
|
267
|
+
function isValidPosition(position) {
|
|
268
|
+
return position === "top" || position === "bottom";
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Constants used throughout the plugin system.
|
|
272
|
+
*/
|
|
273
|
+
const CONSTANTS = {
|
|
274
|
+
VIRTUAL_MODULE_ID: "virtual:motia-plugins",
|
|
275
|
+
RESOLVED_VIRTUAL_MODULE_ID: "\0virtual:motia-plugins",
|
|
276
|
+
LOG_PREFIX: "[motia-plugins]",
|
|
277
|
+
DEFAULTS: {
|
|
278
|
+
POSITION: "top",
|
|
279
|
+
LABEL: "Plugin label",
|
|
280
|
+
ICON: "toy-brick",
|
|
281
|
+
PROPS: {}
|
|
282
|
+
}
|
|
4
283
|
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
284
|
+
|
|
285
|
+
//#endregion
|
|
286
|
+
//#region motia-plugin/hmr.ts
|
|
287
|
+
const WATCHED_EXTENSIONS = [
|
|
288
|
+
".ts",
|
|
289
|
+
".tsx",
|
|
290
|
+
".js",
|
|
291
|
+
".jsx",
|
|
292
|
+
".css",
|
|
293
|
+
".scss",
|
|
294
|
+
".less"
|
|
295
|
+
];
|
|
296
|
+
function isConfigFile(file) {
|
|
297
|
+
const normalizedFile = normalizePath(file);
|
|
298
|
+
return normalizedFile.endsWith("motia.config.ts") || normalizedFile.endsWith("motia.config.js");
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Checks if a file change should trigger HMR for plugins.
|
|
302
|
+
*
|
|
303
|
+
* @param file - The file path that changed
|
|
304
|
+
* @param plugins - Current plugin configurations
|
|
305
|
+
* @returns True if the change affects plugins
|
|
306
|
+
*/
|
|
307
|
+
function shouldInvalidatePlugins(file, plugins) {
|
|
308
|
+
const normalizedFile = normalizePath(file);
|
|
309
|
+
const absoluteFile = path.isAbsolute(normalizedFile) ? normalizedFile : path.resolve(process.cwd(), normalizedFile);
|
|
310
|
+
if (isConfigFile(file)) return true;
|
|
311
|
+
if (!WATCHED_EXTENSIONS.some((ext) => absoluteFile.endsWith(ext))) return false;
|
|
312
|
+
for (const plugin of plugins) if (isLocalPlugin(plugin.packageName)) {
|
|
313
|
+
const resolved = resolvePluginPackage(plugin);
|
|
314
|
+
const pluginAbsolutePath = path.isAbsolute(resolved.resolvedPath) ? resolved.resolvedPath : path.resolve(process.cwd(), resolved.resolvedPath);
|
|
315
|
+
const normalizedPluginPath = pluginAbsolutePath.endsWith(path.sep) ? pluginAbsolutePath : `${pluginAbsolutePath}${path.sep}`;
|
|
316
|
+
if (absoluteFile.startsWith(normalizedPluginPath) || absoluteFile === pluginAbsolutePath) return true;
|
|
317
|
+
}
|
|
318
|
+
return false;
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Handles hot updates for the plugin system.
|
|
322
|
+
* This function is called by Vite's handleHotUpdate hook.
|
|
323
|
+
*
|
|
324
|
+
* @param ctx - Vite's HMR context
|
|
325
|
+
* @param plugins - Current plugin configurations
|
|
326
|
+
* @param printer - Printer instance for logging
|
|
327
|
+
* @returns Array of modules to update, or undefined to continue with default behavior
|
|
328
|
+
*/
|
|
329
|
+
function handlePluginHotUpdate(ctx, plugins, printer$2) {
|
|
330
|
+
const { file, server, timestamp } = ctx;
|
|
331
|
+
printer$2.printPluginLog(`HMR: File changed: ${normalizePath(file)}`);
|
|
332
|
+
if (isConfigFile(file)) {
|
|
333
|
+
printer$2.printPluginLog("HMR: Config file changed, triggering full page reload");
|
|
334
|
+
printer$2.printPluginWarn("Configuration changes require a server restart for full effect. Please restart the dev server to apply all changes.");
|
|
335
|
+
server.ws.send({
|
|
336
|
+
type: "full-reload",
|
|
337
|
+
path: "*"
|
|
338
|
+
});
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
if (!shouldInvalidatePlugins(file, plugins)) {
|
|
342
|
+
printer$2.printPluginLog("HMR: Change outside plugin scope, delegating to Vite default handling");
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
printer$2.printPluginLog("HMR: Plugin change detected, invalidating virtual module");
|
|
346
|
+
const virtualModule = server.moduleGraph.getModuleById(CONSTANTS.RESOLVED_VIRTUAL_MODULE_ID);
|
|
347
|
+
if (!virtualModule) {
|
|
348
|
+
printer$2.printPluginWarn("HMR: Virtual module not found, triggering full reload as fallback");
|
|
349
|
+
server.ws.send({
|
|
350
|
+
type: "full-reload",
|
|
351
|
+
path: "*"
|
|
352
|
+
});
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
server.moduleGraph.invalidateModule(virtualModule, /* @__PURE__ */ new Set(), timestamp);
|
|
356
|
+
printer$2.printPluginLog("HMR: Virtual module invalidated");
|
|
357
|
+
const modulesToUpdateSet = new Set([virtualModule]);
|
|
358
|
+
const processedModules = new Set([virtualModule]);
|
|
359
|
+
for (const importer of virtualModule.importers) if (!processedModules.has(importer)) {
|
|
360
|
+
processedModules.add(importer);
|
|
361
|
+
modulesToUpdateSet.add(importer);
|
|
362
|
+
server.moduleGraph.invalidateModule(importer, /* @__PURE__ */ new Set(), timestamp);
|
|
363
|
+
}
|
|
364
|
+
const modulesToUpdate = Array.from(modulesToUpdateSet);
|
|
365
|
+
printer$2.printPluginLog(`HMR: Updated ${modulesToUpdate.length} module(s)`);
|
|
366
|
+
return modulesToUpdate;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
//#endregion
|
|
370
|
+
//#region motia-plugin/validator.ts
|
|
371
|
+
/**
|
|
372
|
+
* Zod schema for WorkbenchPlugin configuration.
|
|
373
|
+
* Provides runtime type validation with detailed error messages.
|
|
374
|
+
*/
|
|
375
|
+
const WorkbenchPluginSchema = z.object({
|
|
376
|
+
packageName: z.string().min(1, "packageName is required and cannot be empty").refine((name) => name.startsWith("~/") || name.startsWith("@") || /^[a-z0-9-_]+$/i.test(name), { message: "packageName must be a valid npm package name or local path (starting with ~/)" }),
|
|
377
|
+
componentName: z.string().optional(),
|
|
378
|
+
position: z.enum(["top", "bottom"]).optional().refine((pos) => pos === void 0 || isValidPosition(pos), { message: "position must be either \"top\" or \"bottom\"" }),
|
|
379
|
+
label: z.string().optional(),
|
|
380
|
+
labelIcon: z.string().optional(),
|
|
381
|
+
cssImports: z.array(z.string()).optional(),
|
|
382
|
+
props: z.record(z.any(), z.any()).optional()
|
|
383
|
+
});
|
|
384
|
+
/**
|
|
385
|
+
* Validates a single plugin configuration.
|
|
386
|
+
*
|
|
387
|
+
* @param plugin - The plugin configuration to validate
|
|
388
|
+
* @param index - The index of the plugin in the array (for error messages)
|
|
389
|
+
* @returns A validation result with errors, warnings, and normalized plugin
|
|
390
|
+
*/
|
|
391
|
+
function validatePluginConfig(plugin, index) {
|
|
392
|
+
const errors = [];
|
|
393
|
+
const warnings = [];
|
|
394
|
+
if (typeof plugin !== "object" || plugin === null) return {
|
|
395
|
+
valid: false,
|
|
396
|
+
errors: [`Plugin at index ${index}: expected object, got ${typeof plugin}`],
|
|
397
|
+
warnings: []
|
|
398
|
+
};
|
|
399
|
+
try {
|
|
400
|
+
const result = WorkbenchPluginSchema.safeParse(plugin);
|
|
401
|
+
if (!result.success) {
|
|
402
|
+
result.error.issues.forEach((err) => {
|
|
403
|
+
const path$1 = err.path.join(".");
|
|
404
|
+
errors.push(`Plugin at index ${index}, field "${path$1}": ${err.message}`);
|
|
405
|
+
});
|
|
406
|
+
return {
|
|
407
|
+
valid: false,
|
|
408
|
+
errors,
|
|
409
|
+
warnings
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
const validatedPlugin = result.data;
|
|
413
|
+
if (isLocalPlugin(validatedPlugin.packageName)) {
|
|
414
|
+
const resolvedPath = resolveLocalPath(validatedPlugin.packageName);
|
|
415
|
+
if (!existsSync(resolvedPath)) warnings.push(`Plugin at index ${index}: local path "${validatedPlugin.packageName}" does not exist at "${resolvedPath}". Make sure the path is correct relative to the project root.`);
|
|
416
|
+
}
|
|
417
|
+
if (!validatedPlugin.label) warnings.push(`Plugin at index ${index}: "label" not specified, will use default "${CONSTANTS.DEFAULTS.LABEL}"`);
|
|
418
|
+
if (!validatedPlugin.labelIcon) warnings.push(`Plugin at index ${index}: "labelIcon" not specified, will use default "${CONSTANTS.DEFAULTS.ICON}"`);
|
|
419
|
+
if (!validatedPlugin.position) warnings.push(`Plugin at index ${index}: "position" not specified, will use default "${CONSTANTS.DEFAULTS.POSITION}"`);
|
|
420
|
+
if (validatedPlugin.props && Object.keys(validatedPlugin.props).length === 0) warnings.push(`Plugin at index ${index}: "props" is an empty object`);
|
|
421
|
+
if (validatedPlugin.cssImports) {
|
|
422
|
+
if (validatedPlugin.cssImports.length === 0) warnings.push(`Plugin at index ${index}: "cssImports" is an empty array`);
|
|
423
|
+
validatedPlugin.cssImports.forEach((cssImport, cssIndex) => {
|
|
424
|
+
if (!cssImport || cssImport.trim() === "") warnings.push(`Plugin at index ${index}: cssImport at index ${cssIndex} is empty or whitespace`);
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
return {
|
|
428
|
+
valid: true,
|
|
429
|
+
errors: [],
|
|
430
|
+
warnings,
|
|
431
|
+
plugin: validatedPlugin
|
|
432
|
+
};
|
|
433
|
+
} catch (error) {
|
|
434
|
+
return {
|
|
435
|
+
valid: false,
|
|
436
|
+
errors: [`Plugin at index ${index}: unexpected validation error: ${error}`],
|
|
437
|
+
warnings: []
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Validates an array of plugin configurations.
|
|
443
|
+
*
|
|
444
|
+
* @param plugins - Array of plugin configurations to validate
|
|
445
|
+
* @param options - Validation options
|
|
446
|
+
* @returns Combined validation result for all plugins
|
|
447
|
+
*/
|
|
448
|
+
function validatePlugins(plugins, options = {}) {
|
|
449
|
+
const allErrors = [];
|
|
450
|
+
const allWarnings = [];
|
|
451
|
+
const validatedPlugins = [];
|
|
452
|
+
if (!Array.isArray(plugins)) return {
|
|
453
|
+
valid: false,
|
|
454
|
+
errors: [`Expected plugins to be an array, got ${typeof plugins}`],
|
|
455
|
+
warnings: []
|
|
456
|
+
};
|
|
457
|
+
if (plugins.length === 0) {
|
|
458
|
+
console.warn("[motia-plugins] No plugins provided to validate");
|
|
459
|
+
return {
|
|
460
|
+
valid: true,
|
|
461
|
+
errors: [],
|
|
462
|
+
warnings: ["No plugins configured"]
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
for (let i = 0; i < plugins.length; i++) {
|
|
466
|
+
const result = validatePluginConfig(plugins[i], i);
|
|
467
|
+
allErrors.push(...result.errors);
|
|
468
|
+
allWarnings.push(...result.warnings);
|
|
469
|
+
if (result.valid && result.plugin) validatedPlugins.push(result.plugin);
|
|
470
|
+
if (options.failFast && result.errors.length > 0) break;
|
|
471
|
+
}
|
|
472
|
+
const packageNames = validatedPlugins.map((p) => p.packageName);
|
|
473
|
+
const duplicates = packageNames.filter((name, index) => packageNames.indexOf(name) !== index);
|
|
474
|
+
if (duplicates.length > 0) [...new Set(duplicates)].forEach((dup) => {
|
|
475
|
+
allWarnings.push(`Duplicate package name found: "${dup}". This may cause conflicts.`);
|
|
476
|
+
});
|
|
477
|
+
const valid = allErrors.length === 0;
|
|
478
|
+
if (valid) {
|
|
479
|
+
console.log(`[motia-plugins] ✓ Validated ${validatedPlugins.length} plugin(s) successfully`);
|
|
480
|
+
if (allWarnings.length > 0) console.warn(`[motia-plugins] Found ${allWarnings.length} warning(s)`);
|
|
481
|
+
} else console.error(`[motia-plugins] ✗ Validation failed with ${allErrors.length} error(s)`);
|
|
482
|
+
return {
|
|
483
|
+
valid,
|
|
484
|
+
errors: allErrors,
|
|
485
|
+
warnings: allWarnings
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
//#endregion
|
|
490
|
+
//#region motia-plugin/index.ts
|
|
491
|
+
/**
|
|
492
|
+
* Vite plugin for loading and managing Motia workbench plugins.
|
|
493
|
+
*
|
|
494
|
+
* Features:
|
|
495
|
+
* - Hot Module Replacement (HMR) support
|
|
496
|
+
* - Runtime validation with detailed error messages
|
|
497
|
+
* - Verbose logging for debugging
|
|
498
|
+
* - CSS injection for plugin styles
|
|
499
|
+
*
|
|
500
|
+
* @param plugins - Array of plugin configurations
|
|
501
|
+
* @param options - Optional loader configuration
|
|
502
|
+
* @returns Vite plugin instance
|
|
503
|
+
*
|
|
504
|
+
* @example
|
|
505
|
+
* ```ts
|
|
506
|
+
* export default defineConfig({
|
|
507
|
+
* plugins: [
|
|
508
|
+
* motiaPluginsPlugin([
|
|
509
|
+
* { packageName: '@my-org/plugin', label: 'My Plugin' }
|
|
510
|
+
* ])
|
|
511
|
+
* ]
|
|
512
|
+
* })
|
|
513
|
+
* ```
|
|
514
|
+
*/
|
|
515
|
+
const printer$1 = new Printer(process.cwd());
|
|
516
|
+
function motiaPluginsPlugin(plugins) {
|
|
517
|
+
let devServer = null;
|
|
518
|
+
try {
|
|
519
|
+
const validationResult = validatePlugins(plugins, { failFast: false });
|
|
520
|
+
if (!validationResult.valid) {
|
|
521
|
+
printer$1.printPluginError("Plugin configuration validation failed:");
|
|
522
|
+
for (const err of validationResult.errors) printer$1.printPluginError(` ${err}`);
|
|
523
|
+
throw new Error("Invalid plugin configuration. See errors above.");
|
|
524
|
+
}
|
|
525
|
+
if (validationResult.warnings.length > 0) for (const warning of validationResult.warnings) printer$1.printPluginWarn(warning);
|
|
526
|
+
} catch (error) {
|
|
527
|
+
printer$1.printPluginError(`Failed to validate plugins: ${error}`);
|
|
528
|
+
throw error;
|
|
529
|
+
}
|
|
530
|
+
const alias = createAliasConfig(plugins);
|
|
531
|
+
printer$1.printPluginLog(`Initialized with ${plugins.length} plugin(s)`);
|
|
532
|
+
return {
|
|
533
|
+
name: "vite-plugin-motia-plugins",
|
|
534
|
+
enforce: "pre",
|
|
535
|
+
buildStart() {
|
|
536
|
+
printer$1.printPluginLog("Build started");
|
|
537
|
+
},
|
|
538
|
+
config: () => ({ resolve: { alias } }),
|
|
539
|
+
configureServer(server) {
|
|
540
|
+
devServer = server;
|
|
541
|
+
printer$1.printPluginLog("Dev server configured, HMR enabled");
|
|
542
|
+
const configPaths = [path.join(process.cwd(), "motia.config.ts"), path.join(process.cwd(), "motia.config.js")];
|
|
543
|
+
for (const configPath of configPaths) server.watcher.add(configPath);
|
|
544
|
+
printer$1.printPluginLog("Watching for config file changes");
|
|
545
|
+
const localPlugins = plugins.filter((p) => isLocalPlugin(p.packageName));
|
|
546
|
+
if (localPlugins.length > 0) {
|
|
547
|
+
printer$1.printPluginLog(`Watching ${localPlugins.length} local plugin(s)`);
|
|
548
|
+
for (const plugin of localPlugins) {
|
|
549
|
+
const watchPath = resolvePluginPackage(plugin).resolvedPath;
|
|
550
|
+
server.watcher.add(watchPath);
|
|
551
|
+
printer$1.printPluginLog(`Watching: ${watchPath}`);
|
|
552
|
+
}
|
|
553
|
+
server.watcher.on("change", (file) => {
|
|
554
|
+
const normalizedFile = normalizePath(file);
|
|
555
|
+
printer$1.printPluginLog(`File watcher detected change: ${normalizedFile}`);
|
|
556
|
+
});
|
|
557
|
+
server.watcher.on("add", (file) => {
|
|
558
|
+
const normalizedFile = normalizePath(file);
|
|
559
|
+
printer$1.printPluginLog(`File watcher detected new file: ${normalizedFile}`);
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
},
|
|
563
|
+
resolveId(id) {
|
|
564
|
+
if (id === CONSTANTS.VIRTUAL_MODULE_ID) return CONSTANTS.RESOLVED_VIRTUAL_MODULE_ID;
|
|
565
|
+
},
|
|
566
|
+
load(id) {
|
|
567
|
+
if (id !== CONSTANTS.RESOLVED_VIRTUAL_MODULE_ID) return null;
|
|
568
|
+
printer$1.printPluginLog("Loading plugins virtual module");
|
|
569
|
+
printer$1.printPluginLog("Generating plugin code...");
|
|
570
|
+
const code = generatePluginCode(plugins);
|
|
571
|
+
if (!isValidCode(code)) {
|
|
572
|
+
printer$1.printPluginError("Generated code is invalid or empty");
|
|
573
|
+
return "export const plugins = []";
|
|
574
|
+
}
|
|
575
|
+
printer$1.printPluginLog("Plugin code generated successfully");
|
|
576
|
+
return code;
|
|
577
|
+
},
|
|
578
|
+
async transform(code, id) {
|
|
579
|
+
if (!normalizePath(id).endsWith("src/index.css")) return null;
|
|
580
|
+
printer$1.printPluginLog("Injecting plugin CSS imports");
|
|
581
|
+
const cssImports = generateCssImports(plugins);
|
|
582
|
+
if (!cssImports) return null;
|
|
583
|
+
return {
|
|
584
|
+
code: `${cssImports}\n${code}`,
|
|
585
|
+
map: null
|
|
586
|
+
};
|
|
587
|
+
},
|
|
588
|
+
handleHotUpdate(ctx) {
|
|
589
|
+
if (!devServer) {
|
|
590
|
+
printer$1.printPluginWarn("HMR: Dev server not available");
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
const modulesToUpdate = handlePluginHotUpdate(ctx, plugins, printer$1);
|
|
594
|
+
if (modulesToUpdate && modulesToUpdate.length > 0) {
|
|
595
|
+
const merged = Array.from(new Set([...ctx.modules || [], ...modulesToUpdate]));
|
|
596
|
+
printer$1.printPluginLog(`HMR: Successfully updated ${merged.length} module(s)`);
|
|
597
|
+
return merged;
|
|
598
|
+
}
|
|
599
|
+
},
|
|
600
|
+
buildEnd() {
|
|
601
|
+
printer$1.printPluginLog("Build ended");
|
|
602
|
+
}
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
//#endregion
|
|
607
|
+
//#region middleware.ts
|
|
12
608
|
const workbenchBasePlugin = (workbenchBase) => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
609
|
+
return {
|
|
610
|
+
name: "html-transform",
|
|
611
|
+
transformIndexHtml: (html) => {
|
|
612
|
+
return html.replace("</head>", `<script>const workbenchBase = ${JSON.stringify(workbenchBase)};<\/script></head>`);
|
|
613
|
+
}
|
|
614
|
+
};
|
|
19
615
|
};
|
|
20
616
|
const processCwdPlugin = () => {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
};
|
|
617
|
+
return {
|
|
618
|
+
name: "html-transform",
|
|
619
|
+
transformIndexHtml: (html) => {
|
|
620
|
+
const cwd = process.cwd().replace(/\\/g, "/");
|
|
621
|
+
return html.replace("</head>", `<script>const processCwd = "${cwd}";<\/script></head>`);
|
|
622
|
+
}
|
|
623
|
+
};
|
|
29
624
|
};
|
|
30
625
|
const reoPlugin = () => {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return html;
|
|
37
|
-
}
|
|
38
|
-
// inject before </head>
|
|
39
|
-
return html.replace('</head>', `
|
|
626
|
+
return {
|
|
627
|
+
name: "html-transform",
|
|
628
|
+
transformIndexHtml(html) {
|
|
629
|
+
if (!(process.env.MOTIA_ANALYTICS_DISABLED !== "true")) return html;
|
|
630
|
+
return html.replace("</head>", `
|
|
40
631
|
<script type="text/javascript">
|
|
41
632
|
!function(){var e,t,n;e="d8f0ce9cae8ae64",t=function(){Reo.init({clientID:"d8f0ce9cae8ae64", source: "internal"})},(n=document.createElement("script")).src="https://static.reo.dev/"+e+"/reo.js",n.defer=!0,n.onload=t,document.head.appendChild(n)}();
|
|
42
|
-
|
|
633
|
+
<\/script>
|
|
43
634
|
</head>`);
|
|
44
|
-
|
|
45
|
-
|
|
635
|
+
}
|
|
636
|
+
};
|
|
637
|
+
};
|
|
638
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
639
|
+
const warmupMotiaPlugins = async (viteServer) => {
|
|
640
|
+
try {
|
|
641
|
+
if ((await viteServer.transformRequest(CONSTANTS.VIRTUAL_MODULE_ID))?.code) printer.printPluginLog("Plugin system warmed up eagerly");
|
|
642
|
+
else printer.printPluginWarn("Plugin warm-up returned empty result");
|
|
643
|
+
} catch (error) {
|
|
644
|
+
printer.printPluginWarn(`Failed to warm up plugin system, continuing lazily: ${error}`);
|
|
645
|
+
}
|
|
46
646
|
};
|
|
647
|
+
const printer = new Printer(process.cwd());
|
|
47
648
|
const applyMiddleware = async ({ app, port, workbenchBase, plugins }) => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
649
|
+
const vite = await createServer({
|
|
650
|
+
appType: "spa",
|
|
651
|
+
root: __dirname,
|
|
652
|
+
base: workbenchBase,
|
|
653
|
+
server: {
|
|
654
|
+
middlewareMode: true,
|
|
655
|
+
allowedHosts: true,
|
|
656
|
+
host: true,
|
|
657
|
+
hmr: { port: 21678 + port },
|
|
658
|
+
fs: { allow: [
|
|
659
|
+
__dirname,
|
|
660
|
+
path.join(process.cwd(), "./steps"),
|
|
661
|
+
path.join(process.cwd(), "./src"),
|
|
662
|
+
path.join(process.cwd(), "./tutorial"),
|
|
663
|
+
path.join(process.cwd(), "./node_modules"),
|
|
664
|
+
path.join(__dirname, "./node_modules")
|
|
665
|
+
] }
|
|
666
|
+
},
|
|
667
|
+
resolve: { alias: {
|
|
668
|
+
"@": path.resolve(__dirname, "./src"),
|
|
669
|
+
"@/assets": path.resolve(__dirname, "./src/assets"),
|
|
670
|
+
"lucide-react/dynamic": "lucide-react/dynamic.mjs",
|
|
671
|
+
"lucide-react": "lucide-react/dist/cjs/lucide-react.js"
|
|
672
|
+
} },
|
|
673
|
+
plugins: [
|
|
674
|
+
react({ babel: { plugins: ["babel-plugin-react-compiler"] } }),
|
|
675
|
+
processCwdPlugin(),
|
|
676
|
+
reoPlugin(),
|
|
677
|
+
motiaPluginsPlugin(plugins),
|
|
678
|
+
workbenchBasePlugin(workbenchBase)
|
|
679
|
+
],
|
|
680
|
+
assetsInclude: [
|
|
681
|
+
"**/*.png",
|
|
682
|
+
"**/*.jpg",
|
|
683
|
+
"**/*.jpeg",
|
|
684
|
+
"**/*.gif",
|
|
685
|
+
"**/*.svg",
|
|
686
|
+
"**/*.ico",
|
|
687
|
+
"**/*.webp",
|
|
688
|
+
"**/*.avif"
|
|
689
|
+
]
|
|
690
|
+
});
|
|
691
|
+
await warmupMotiaPlugins(vite);
|
|
692
|
+
app.use(workbenchBase, vite.middlewares);
|
|
693
|
+
app.use(`${workbenchBase}/*`, async (req, res, next) => {
|
|
694
|
+
const url = req.originalUrl;
|
|
695
|
+
try {
|
|
696
|
+
const index = fs.readFileSync(path.resolve(__dirname, "index.html"), "utf-8");
|
|
697
|
+
const html = await vite.transformIndexHtml(url, index);
|
|
698
|
+
res.status(200).set({ "Content-Type": "text/html" }).end(html);
|
|
699
|
+
} catch (e) {
|
|
700
|
+
next(e);
|
|
701
|
+
}
|
|
702
|
+
});
|
|
97
703
|
};
|
|
98
|
-
|
|
704
|
+
|
|
705
|
+
//#endregion
|
|
706
|
+
export { applyMiddleware };
|