@hardimpactdev/craft-ui 0.0.5 → 0.0.6
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/src/vite/craftPlugin.d.ts +4 -0
- package/dist/src/vite/defineCraftConfig.d.ts +15 -20
- package/dist/vite/craftPlugin.js +105 -0
- package/dist/vite/defineCraftConfig.js +157 -106
- package/dist/vite/ts/craftPlugin.ts +106 -0
- package/dist/vite/ts/defineCraftConfig.ts +207 -129
- package/package.json +11 -4
|
@@ -1,26 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
interface CraftConfigOptions {
|
|
1
|
+
interface viteConfigOptions {
|
|
3
2
|
laravel?: {
|
|
4
|
-
input
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
detectTls?: string | boolean;
|
|
12
|
-
valetTls?: string | boolean;
|
|
13
|
-
transformOnServe?: (code: string, url: string) => string;
|
|
3
|
+
input?: string[];
|
|
4
|
+
refresh?: boolean;
|
|
5
|
+
};
|
|
6
|
+
plugins?: any[];
|
|
7
|
+
aliases?: any[];
|
|
8
|
+
ui?: {
|
|
9
|
+
localPath?: string;
|
|
14
10
|
};
|
|
15
11
|
}
|
|
16
|
-
export declare function defineCraftConfig(options?:
|
|
17
|
-
|
|
18
|
-
* Craft Vite plugin that provides virtual module for app initialization
|
|
19
|
-
*/
|
|
20
|
-
export declare function craft(): {
|
|
12
|
+
export declare function defineCraftConfig(options?: viteConfigOptions): import('vite').UserConfigFnObject;
|
|
13
|
+
export declare function pluginConfig(options: viteConfigOptions): ({
|
|
21
14
|
name: string;
|
|
22
|
-
enforce:
|
|
23
|
-
|
|
24
|
-
|
|
15
|
+
enforce: string;
|
|
16
|
+
}[] | import('vite').PluginOption)[];
|
|
17
|
+
export declare function aliasConfig(aliases?: any[], ui?: any): {
|
|
18
|
+
dedupe: string[];
|
|
19
|
+
alias: any[];
|
|
25
20
|
};
|
|
26
21
|
export {};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
function craft() {
|
|
2
|
+
const plugins = [];
|
|
3
|
+
plugins.push({
|
|
4
|
+
name: "craft",
|
|
5
|
+
enforce: "pre",
|
|
6
|
+
config() {
|
|
7
|
+
return {
|
|
8
|
+
optimizeDeps: {
|
|
9
|
+
exclude: [
|
|
10
|
+
"@hardimpactdev/craft-ui",
|
|
11
|
+
"@tailwindcss/vite",
|
|
12
|
+
"laravel-vue-i18n/vite"
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
},
|
|
17
|
+
resolveId(id) {
|
|
18
|
+
if (id === "virtual:craft") {
|
|
19
|
+
return id;
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
load(id) {
|
|
23
|
+
if (id === "virtual:craft") {
|
|
24
|
+
return `
|
|
25
|
+
import { createInertiaApp } from "@inertiajs/vue3";
|
|
26
|
+
import { resolvePageComponent } from "laravel-vite-plugin/inertia-helpers";
|
|
27
|
+
import { createApp, h } from "vue";
|
|
28
|
+
import { i18n } from "@hardimpactdev/craft-ui";
|
|
29
|
+
import { TooltipProvider } from "reka-ui";
|
|
30
|
+
|
|
31
|
+
const appName = import.meta.env.VITE_APP_NAME || "Laravel";
|
|
32
|
+
|
|
33
|
+
export function initializeCraft(options) {
|
|
34
|
+
const { enhanceVue, layouts } = options || {};
|
|
35
|
+
|
|
36
|
+
return createInertiaApp({
|
|
37
|
+
title: (title) => \`\${title} - \${appName}\`,
|
|
38
|
+
resolve: (name) => {
|
|
39
|
+
const pages = import.meta.glob('/resources/js/pages/**/*.vue', {
|
|
40
|
+
eager: true,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const page = pages[\`/resources/js/pages/\${name}.vue\`];
|
|
44
|
+
|
|
45
|
+
let defaultLayout = undefined;
|
|
46
|
+
|
|
47
|
+
if (layouts) {
|
|
48
|
+
Object.entries(layouts).forEach(([key, value]) => {
|
|
49
|
+
if(name.startsWith(key)) {
|
|
50
|
+
defaultLayout = value;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if(!defaultLayout && layouts.default) {
|
|
54
|
+
defaultLayout = layouts.default;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if(!page) {
|
|
60
|
+
const errorMessage = \`Page not found: \${name}.vue\`;
|
|
61
|
+
|
|
62
|
+
console.error(\`[Inertia] \${errorMessage}\`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
page.default.layout = defaultLayout;
|
|
66
|
+
return page;
|
|
67
|
+
},
|
|
68
|
+
setup({ el, App, props, plugin }) {
|
|
69
|
+
// Get the language files and transform the paths
|
|
70
|
+
const langGlob = import.meta.glob("/lang/*.json", { eager: true });
|
|
71
|
+
|
|
72
|
+
// Transform absolute paths to relative paths expected by i18n
|
|
73
|
+
const transformedLangs = {};
|
|
74
|
+
Object.entries(langGlob).forEach(([absolutePath, module]) => {
|
|
75
|
+
// Convert "/lang/en.json" to "../../lang/en.json"
|
|
76
|
+
const relativePath = absolutePath.replace('/lang/', '../../lang/');
|
|
77
|
+
transformedLangs[relativePath] = module;
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
let app = createApp({ render: () => h(TooltipProvider, null, () => h(App, props)) })
|
|
81
|
+
.use(plugin)
|
|
82
|
+
.use(i18n, {
|
|
83
|
+
langs: transformedLangs,
|
|
84
|
+
changeLanguageRoute: '/change-language',
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
if (enhanceVue) {
|
|
88
|
+
app = enhanceVue(app);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
app.mount(el);
|
|
92
|
+
},
|
|
93
|
+
progress: {
|
|
94
|
+
includeCSS: false,
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
}`;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
return plugins;
|
|
102
|
+
}
|
|
103
|
+
export {
|
|
104
|
+
craft
|
|
105
|
+
};
|
|
@@ -1,115 +1,166 @@
|
|
|
1
|
+
import { defineConfig, loadEnv } from "vite";
|
|
2
|
+
import vue from "@vitejs/plugin-vue";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import laravel from "laravel-vite-plugin";
|
|
5
|
+
import { run } from "vite-plugin-run";
|
|
6
|
+
import { craft } from "./craftPlugin.js";
|
|
7
|
+
import tailwindcss from "@tailwindcss/vite";
|
|
8
|
+
import i18n from "laravel-vue-i18n/vite";
|
|
9
|
+
import vueDevTools from "vite-plugin-vue-devtools";
|
|
1
10
|
function defineCraftConfig(options = {}) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
11
|
+
return defineConfig(({ mode }) => {
|
|
12
|
+
const serverConfig = getServerConfig(mode);
|
|
13
|
+
return {
|
|
14
|
+
plugins: [
|
|
15
|
+
...pluginConfig(options),
|
|
16
|
+
...options.plugins || [],
|
|
17
|
+
// Plugin to enforce allowedHosts after laravel-vite-plugin
|
|
18
|
+
// This bypasses Vite's DNS rebinding protection which conflicts with reverse proxy setups
|
|
19
|
+
{
|
|
20
|
+
name: "craft-allowed-hosts",
|
|
21
|
+
enforce: "post",
|
|
22
|
+
config() {
|
|
23
|
+
return {
|
|
24
|
+
server: {
|
|
25
|
+
allowedHosts: true
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
resolve: {
|
|
32
|
+
...aliasConfig(options.aliases, options.ui)
|
|
33
|
+
},
|
|
34
|
+
server: serverConfig
|
|
35
|
+
};
|
|
36
|
+
});
|
|
22
37
|
}
|
|
23
|
-
function
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
38
|
+
function getServerConfig(mode) {
|
|
39
|
+
const env = loadEnv(mode, process.cwd());
|
|
40
|
+
const appUrl = env.VITE_APP_URL;
|
|
41
|
+
if (!appUrl) {
|
|
42
|
+
return { host: "0.0.0.0" };
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const url = new URL(appUrl);
|
|
46
|
+
const isHttps = url.protocol === "https:";
|
|
47
|
+
return {
|
|
48
|
+
host: "0.0.0.0",
|
|
49
|
+
origin: appUrl,
|
|
50
|
+
allowedHosts: true,
|
|
51
|
+
hmr: {
|
|
52
|
+
host: url.hostname,
|
|
53
|
+
protocol: isHttps ? "wss" : "ws",
|
|
54
|
+
clientPort: isHttps ? 443 : parseInt(url.port) || 80
|
|
30
55
|
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
let defaultLayout = undefined;
|
|
56
|
-
|
|
57
|
-
if (layouts) {
|
|
58
|
-
Object.entries(layouts).forEach(([key, value]) => {
|
|
59
|
-
if(name.startsWith(key)) {
|
|
60
|
-
defaultLayout = value;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if(!defaultLayout && layouts.default) {
|
|
64
|
-
defaultLayout = layouts.default;
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if(!page) {
|
|
70
|
-
const errorMessage = \`Page not found: \${name}.vue\`;
|
|
71
|
-
|
|
72
|
-
console.error(\`[Inertia] \${errorMessage}\`);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
page.default.layout = defaultLayout;
|
|
76
|
-
return page;
|
|
77
|
-
},
|
|
78
|
-
setup({ el, App, props, plugin }) {
|
|
79
|
-
// Get the language files and transform the paths
|
|
80
|
-
const langGlob = import.meta.glob("/lang/*.json", { eager: true });
|
|
81
|
-
|
|
82
|
-
// Transform absolute paths to relative paths expected by i18n
|
|
83
|
-
const transformedLangs = {};
|
|
84
|
-
Object.entries(langGlob).forEach(([absolutePath, module]) => {
|
|
85
|
-
// Convert "/lang/en.json" to "../../lang/en.json"
|
|
86
|
-
const relativePath = absolutePath.replace('/lang/', '../../lang/');
|
|
87
|
-
transformedLangs[relativePath] = module;
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
let app = createApp({ render: () => h(TooltipProvider, null, () => h(App, props)) })
|
|
91
|
-
.use(plugin)
|
|
92
|
-
.use(i18n, {
|
|
93
|
-
langs: transformedLangs,
|
|
94
|
-
changeLanguageRoute: '/change-language',
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
if (enhanceVue) {
|
|
98
|
-
app = enhanceVue(app);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
app.mount(el);
|
|
102
|
-
},
|
|
103
|
-
progress: {
|
|
104
|
-
includeCSS: false,
|
|
105
|
-
},
|
|
106
|
-
});
|
|
107
|
-
}`;
|
|
56
|
+
};
|
|
57
|
+
} catch {
|
|
58
|
+
return { host: "0.0.0.0" };
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function pluginConfig(options) {
|
|
62
|
+
return [
|
|
63
|
+
craft(),
|
|
64
|
+
laravel({
|
|
65
|
+
input: options.laravel?.input || ["resources/js/app.ts"],
|
|
66
|
+
refresh: options.laravel?.refresh || true
|
|
67
|
+
}),
|
|
68
|
+
tailwindcss(),
|
|
69
|
+
i18n(),
|
|
70
|
+
vue({
|
|
71
|
+
template: {
|
|
72
|
+
transformAssetUrls: {
|
|
73
|
+
base: null,
|
|
74
|
+
includeAbsolute: false
|
|
75
|
+
},
|
|
76
|
+
compilerOptions: {
|
|
77
|
+
isCustomElement: (tag) => tag === "trix-editor"
|
|
78
|
+
}
|
|
108
79
|
}
|
|
80
|
+
}),
|
|
81
|
+
runConfiguration(),
|
|
82
|
+
vueDevTools({
|
|
83
|
+
appendTo: "virtual:craft",
|
|
84
|
+
launchEditor: import.meta.env?.VITE_EDITOR || "cursor"
|
|
85
|
+
})
|
|
86
|
+
].filter(Boolean);
|
|
87
|
+
}
|
|
88
|
+
function runConfiguration() {
|
|
89
|
+
if (false) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
return run([
|
|
93
|
+
{
|
|
94
|
+
name: "waymaker",
|
|
95
|
+
run: ["php", "artisan", "waymaker:generate"],
|
|
96
|
+
pattern: ["app/**/Http/**/*.php"]
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: "wayfinder",
|
|
100
|
+
run: ["php", "artisan", "wayfinder:generate"],
|
|
101
|
+
pattern: ["routes/*.php", "app/**/Http/**/*.php"]
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: "typescript",
|
|
105
|
+
run: ["php", "artisan", "typescript:transform"],
|
|
106
|
+
pattern: ["app/{Data,Enums}/**/*.php"]
|
|
109
107
|
}
|
|
108
|
+
]);
|
|
109
|
+
}
|
|
110
|
+
function aliasConfig(aliases = [], ui = {}) {
|
|
111
|
+
if (!process.argv.includes("build") && ui.localPath) {
|
|
112
|
+
const absoluteLibraryPath = path.resolve(process.cwd(), ui.localPath);
|
|
113
|
+
const localAliases = [
|
|
114
|
+
// The following alias will make the @ alias work correctly depending on the importer path.
|
|
115
|
+
{
|
|
116
|
+
regex: /^@\//,
|
|
117
|
+
replacement: "@/",
|
|
118
|
+
libraryPath: absoluteLibraryPath,
|
|
119
|
+
aliasLocalBasePath: "./resources/js",
|
|
120
|
+
aliasExternalBasePath: path.join(ui.localPath, "src")
|
|
121
|
+
},
|
|
122
|
+
// The following alias config will change all package references like import { Dialog } from '@hardimpactdev/craft-ui';
|
|
123
|
+
// to the library's index.ts file instead.
|
|
124
|
+
{
|
|
125
|
+
regex: /^@hardimpactdev\/craft-ui/,
|
|
126
|
+
replacement: path.join(ui.localPath, "index.ts")
|
|
127
|
+
}
|
|
128
|
+
];
|
|
129
|
+
aliases.push(...aliasLocalPackage(localAliases));
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
dedupe: ["@inertiajs/vue3", "@tailwindcss/vite"],
|
|
133
|
+
alias: aliases
|
|
110
134
|
};
|
|
111
135
|
}
|
|
136
|
+
function aliasLocalPackage(aliases) {
|
|
137
|
+
return aliases.map((alias) => {
|
|
138
|
+
if (!alias.libraryPath && !alias.aliasLocalBasePath && !alias.aliasExternalBasePath) {
|
|
139
|
+
return {
|
|
140
|
+
find: alias.regex,
|
|
141
|
+
replacement: path.resolve(process.cwd(), alias.replacement)
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
find: alias.regex,
|
|
146
|
+
replacement: alias.replacement,
|
|
147
|
+
async customResolver(source, importer) {
|
|
148
|
+
let resolvedPath = "";
|
|
149
|
+
resolvedPath = path.resolve(
|
|
150
|
+
// get the directory name of the importer
|
|
151
|
+
process.cwd(),
|
|
152
|
+
// if the importer string includes the folder name, use the external path, otherwise use the local path
|
|
153
|
+
importer?.includes(alias.libraryPath) ? alias.aliasExternalBasePath : alias.aliasLocalBasePath,
|
|
154
|
+
// remove the alias replacement from the source path
|
|
155
|
+
source.replace(alias.replacement, "")
|
|
156
|
+
);
|
|
157
|
+
return (await this.resolve(resolvedPath))?.id;
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
});
|
|
161
|
+
}
|
|
112
162
|
export {
|
|
113
|
-
|
|
114
|
-
defineCraftConfig
|
|
163
|
+
aliasConfig,
|
|
164
|
+
defineCraftConfig,
|
|
165
|
+
pluginConfig
|
|
115
166
|
};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
export function craft() {
|
|
2
|
+
const plugins = [];
|
|
3
|
+
|
|
4
|
+
// Core plugin
|
|
5
|
+
plugins.push({
|
|
6
|
+
name: 'craft',
|
|
7
|
+
enforce: 'pre',
|
|
8
|
+
config() {
|
|
9
|
+
return {
|
|
10
|
+
optimizeDeps: {
|
|
11
|
+
exclude: [
|
|
12
|
+
'@hardimpactdev/craft-ui',
|
|
13
|
+
'@tailwindcss/vite',
|
|
14
|
+
'laravel-vue-i18n/vite'
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
resolveId(id: string) {
|
|
21
|
+
if (id === 'virtual:craft') {
|
|
22
|
+
return id;
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
load(id: string) {
|
|
26
|
+
if (id === 'virtual:craft') {
|
|
27
|
+
return `
|
|
28
|
+
import { createInertiaApp } from "@inertiajs/vue3";
|
|
29
|
+
import { resolvePageComponent } from "laravel-vite-plugin/inertia-helpers";
|
|
30
|
+
import { createApp, h } from "vue";
|
|
31
|
+
import { i18n } from "@hardimpactdev/craft-ui";
|
|
32
|
+
import { TooltipProvider } from "reka-ui";
|
|
33
|
+
|
|
34
|
+
const appName = import.meta.env.VITE_APP_NAME || "Laravel";
|
|
35
|
+
|
|
36
|
+
export function initializeCraft(options) {
|
|
37
|
+
const { enhanceVue, layouts } = options || {};
|
|
38
|
+
|
|
39
|
+
return createInertiaApp({
|
|
40
|
+
title: (title) => \`\${title} - \${appName}\`,
|
|
41
|
+
resolve: (name) => {
|
|
42
|
+
const pages = import.meta.glob('/resources/js/pages/**/*.vue', {
|
|
43
|
+
eager: true,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const page = pages[\`/resources/js/pages/\${name}.vue\`];
|
|
47
|
+
|
|
48
|
+
let defaultLayout = undefined;
|
|
49
|
+
|
|
50
|
+
if (layouts) {
|
|
51
|
+
Object.entries(layouts).forEach(([key, value]) => {
|
|
52
|
+
if(name.startsWith(key)) {
|
|
53
|
+
defaultLayout = value;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if(!defaultLayout && layouts.default) {
|
|
57
|
+
defaultLayout = layouts.default;
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if(!page) {
|
|
63
|
+
const errorMessage = \`Page not found: \${name}.vue\`;
|
|
64
|
+
|
|
65
|
+
console.error(\`[Inertia] \${errorMessage}\`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
page.default.layout = defaultLayout;
|
|
69
|
+
return page;
|
|
70
|
+
},
|
|
71
|
+
setup({ el, App, props, plugin }) {
|
|
72
|
+
// Get the language files and transform the paths
|
|
73
|
+
const langGlob = import.meta.glob("/lang/*.json", { eager: true });
|
|
74
|
+
|
|
75
|
+
// Transform absolute paths to relative paths expected by i18n
|
|
76
|
+
const transformedLangs = {};
|
|
77
|
+
Object.entries(langGlob).forEach(([absolutePath, module]) => {
|
|
78
|
+
// Convert "/lang/en.json" to "../../lang/en.json"
|
|
79
|
+
const relativePath = absolutePath.replace('/lang/', '../../lang/');
|
|
80
|
+
transformedLangs[relativePath] = module;
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
let app = createApp({ render: () => h(TooltipProvider, null, () => h(App, props)) })
|
|
84
|
+
.use(plugin)
|
|
85
|
+
.use(i18n, {
|
|
86
|
+
langs: transformedLangs,
|
|
87
|
+
changeLanguageRoute: '/change-language',
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
if (enhanceVue) {
|
|
91
|
+
app = enhanceVue(app);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
app.mount(el);
|
|
95
|
+
},
|
|
96
|
+
progress: {
|
|
97
|
+
includeCSS: false,
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
}`;
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
return plugins;
|
|
106
|
+
}
|
|
@@ -1,135 +1,213 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
import { defineConfig, loadEnv } from 'vite';
|
|
2
|
+
import vue from '@vitejs/plugin-vue';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import laravel from 'laravel-vite-plugin';
|
|
5
|
+
import { run } from 'vite-plugin-run';
|
|
6
|
+
import { craft } from './craftPlugin.js';
|
|
7
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
8
|
+
import i18n from 'laravel-vue-i18n/vite';
|
|
9
|
+
import vueDevTools from 'vite-plugin-vue-devtools';
|
|
10
|
+
|
|
11
|
+
interface viteConfigOptions {
|
|
12
|
+
laravel?: {
|
|
13
|
+
input?: string[];
|
|
14
|
+
refresh?: boolean;
|
|
15
|
+
};
|
|
16
|
+
plugins?: any[];
|
|
17
|
+
aliases?: any[];
|
|
18
|
+
ui?: {
|
|
19
|
+
localPath?: string;
|
|
20
|
+
};
|
|
16
21
|
}
|
|
17
22
|
|
|
18
|
-
export function defineCraftConfig(options:
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
23
|
+
export function defineCraftConfig(options: viteConfigOptions = {}) {
|
|
24
|
+
return defineConfig(({ mode }) => {
|
|
25
|
+
const serverConfig = getServerConfig(mode);
|
|
26
|
+
return {
|
|
27
|
+
plugins: [
|
|
28
|
+
...pluginConfig(options),
|
|
29
|
+
...(options.plugins || []),
|
|
30
|
+
// Plugin to enforce allowedHosts after laravel-vite-plugin
|
|
31
|
+
// This bypasses Vite's DNS rebinding protection which conflicts with reverse proxy setups
|
|
32
|
+
{
|
|
33
|
+
name: 'craft-allowed-hosts',
|
|
34
|
+
enforce: 'post' as const,
|
|
35
|
+
config() {
|
|
36
|
+
return {
|
|
37
|
+
server: {
|
|
38
|
+
allowedHosts: true as const,
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
resolve: {
|
|
45
|
+
...aliasConfig(options.aliases, options.ui),
|
|
46
|
+
},
|
|
47
|
+
server: serverConfig,
|
|
48
|
+
};
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function getServerConfig(mode: string) {
|
|
53
|
+
// Only load VITE_* prefixed env vars (Vite's default secure behavior)
|
|
54
|
+
const env = loadEnv(mode, process.cwd());
|
|
55
|
+
const appUrl = env.VITE_APP_URL;
|
|
56
|
+
|
|
57
|
+
if (!appUrl) {
|
|
58
|
+
return { host: '0.0.0.0' };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
const url = new URL(appUrl);
|
|
63
|
+
const isHttps = url.protocol === 'https:';
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
host: '0.0.0.0',
|
|
67
|
+
origin: appUrl,
|
|
68
|
+
allowedHosts: true as const,
|
|
69
|
+
hmr: {
|
|
70
|
+
host: url.hostname,
|
|
71
|
+
protocol: isHttps ? 'wss' : 'ws',
|
|
72
|
+
clientPort: isHttps ? 443 : (parseInt(url.port) || 80),
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
} catch {
|
|
76
|
+
return { host: '0.0.0.0' };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function pluginConfig(options: viteConfigOptions) {
|
|
81
|
+
return [
|
|
82
|
+
craft(),
|
|
83
|
+
laravel({
|
|
84
|
+
input: options.laravel?.input || ['resources/js/app.ts'],
|
|
85
|
+
refresh: options.laravel?.refresh || true,
|
|
86
|
+
}),
|
|
87
|
+
tailwindcss(),
|
|
88
|
+
i18n(),
|
|
89
|
+
vue({
|
|
90
|
+
template: {
|
|
91
|
+
transformAssetUrls: {
|
|
92
|
+
base: null,
|
|
93
|
+
includeAbsolute: false,
|
|
94
|
+
},
|
|
95
|
+
compilerOptions: {
|
|
96
|
+
isCustomElement: (tag) => tag === 'trix-editor',
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
}),
|
|
100
|
+
runConfiguration(),
|
|
101
|
+
vueDevTools({
|
|
102
|
+
appendTo: 'virtual:craft',
|
|
103
|
+
launchEditor: import.meta.env?.VITE_EDITOR || 'cursor',
|
|
104
|
+
}),
|
|
105
|
+
].filter(Boolean);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function runConfiguration() {
|
|
109
|
+
if (process.env.NODE_ENV !== 'development') {
|
|
110
|
+
return null;
|
|
38
111
|
}
|
|
39
|
-
|
|
112
|
+
|
|
113
|
+
return run([
|
|
114
|
+
{
|
|
115
|
+
name: 'waymaker',
|
|
116
|
+
run: ['php', 'artisan', 'waymaker:generate'],
|
|
117
|
+
pattern: ['app/**/Http/**/*.php'],
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: 'wayfinder',
|
|
121
|
+
run: ['php', 'artisan', 'wayfinder:generate'],
|
|
122
|
+
pattern: ['routes/*.php', 'app/**/Http/**/*.php'],
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: 'typescript',
|
|
126
|
+
run: ['php', 'artisan', 'typescript:transform'],
|
|
127
|
+
pattern: ['app/{Data,Enums}/**/*.php'],
|
|
128
|
+
},
|
|
129
|
+
]);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
interface LocalAlias {
|
|
133
|
+
regex: RegExp;
|
|
134
|
+
replacement: string;
|
|
135
|
+
libraryPath?: string;
|
|
136
|
+
aliasLocalBasePath?: string;
|
|
137
|
+
aliasExternalBasePath?: string;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function aliasConfig(aliases: any[] = [], ui: any = {}) {
|
|
141
|
+
if (!process.argv.includes('build') && ui.localPath) {
|
|
142
|
+
|
|
143
|
+
const absoluteLibraryPath = path.resolve(process.cwd(), ui.localPath);
|
|
144
|
+
|
|
145
|
+
const localAliases = [
|
|
146
|
+
// The following alias will make the @ alias work correctly depending on the importer path.
|
|
147
|
+
{
|
|
148
|
+
regex: /^@\//,
|
|
149
|
+
replacement: "@/",
|
|
150
|
+
libraryPath: absoluteLibraryPath,
|
|
151
|
+
aliasLocalBasePath: "./resources/js",
|
|
152
|
+
aliasExternalBasePath: path.join(ui.localPath, "src"),
|
|
153
|
+
},
|
|
154
|
+
// The following alias config will change all package references like import { Dialog } from '@hardimpactdev/craft-ui';
|
|
155
|
+
// to the library's index.ts file instead.
|
|
156
|
+
{
|
|
157
|
+
regex: /^@hardimpactdev\/craft-ui/,
|
|
158
|
+
replacement: path.join(ui.localPath, "index.ts"),
|
|
159
|
+
},
|
|
160
|
+
];
|
|
161
|
+
|
|
162
|
+
aliases.push(...aliasLocalPackage(localAliases as LocalAlias[]));
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
dedupe: ['@inertiajs/vue3', '@tailwindcss/vite'],
|
|
167
|
+
alias: aliases,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
interface CustomResolverContext {
|
|
172
|
+
resolve: (id: string, importer?: string) => Promise<{ id: string } | null>;
|
|
40
173
|
}
|
|
41
174
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if (layouts) {
|
|
82
|
-
Object.entries(layouts).forEach(([key, value]) => {
|
|
83
|
-
if(name.startsWith(key)) {
|
|
84
|
-
defaultLayout = value;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if(!defaultLayout && layouts.default) {
|
|
88
|
-
defaultLayout = layouts.default;
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if(!page) {
|
|
94
|
-
const errorMessage = \`Page not found: \${name}.vue\`;
|
|
95
|
-
|
|
96
|
-
console.error(\`[Inertia] \${errorMessage}\`);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
page.default.layout = defaultLayout;
|
|
100
|
-
return page;
|
|
101
|
-
},
|
|
102
|
-
setup({ el, App, props, plugin }) {
|
|
103
|
-
// Get the language files and transform the paths
|
|
104
|
-
const langGlob = import.meta.glob("/lang/*.json", { eager: true });
|
|
105
|
-
|
|
106
|
-
// Transform absolute paths to relative paths expected by i18n
|
|
107
|
-
const transformedLangs = {};
|
|
108
|
-
Object.entries(langGlob).forEach(([absolutePath, module]) => {
|
|
109
|
-
// Convert "/lang/en.json" to "../../lang/en.json"
|
|
110
|
-
const relativePath = absolutePath.replace('/lang/', '../../lang/');
|
|
111
|
-
transformedLangs[relativePath] = module;
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
let app = createApp({ render: () => h(TooltipProvider, null, () => h(App, props)) })
|
|
115
|
-
.use(plugin)
|
|
116
|
-
.use(i18n, {
|
|
117
|
-
langs: transformedLangs,
|
|
118
|
-
changeLanguageRoute: '/change-language',
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
if (enhanceVue) {
|
|
122
|
-
app = enhanceVue(app);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
app.mount(el);
|
|
126
|
-
},
|
|
127
|
-
progress: {
|
|
128
|
-
includeCSS: false,
|
|
129
|
-
},
|
|
130
|
-
});
|
|
131
|
-
}`;
|
|
132
|
-
}
|
|
133
|
-
},
|
|
134
|
-
}
|
|
175
|
+
function aliasLocalPackage(aliases: Array<LocalAlias>) {
|
|
176
|
+
|
|
177
|
+
return aliases.map((alias) => {
|
|
178
|
+
|
|
179
|
+
// if the alias has no external path, folder name, or local path, use the replacement as the path
|
|
180
|
+
// For example library references like import { Dialog } from '@hardimpactdev/craft-ui'; will be resolved to the library's index.ts file instead.
|
|
181
|
+
// This will make HMR work correctly. Allowing to update the library and see the changes in the target project without hard page reloads.
|
|
182
|
+
if (!alias.libraryPath && !alias.aliasLocalBasePath && !alias.aliasExternalBasePath) {
|
|
183
|
+
return {
|
|
184
|
+
find: alias.regex,
|
|
185
|
+
replacement: path.resolve(process.cwd(), alias.replacement),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// When using an alias both in a library and the target project, we need to resolve the alias correctly based on the importer path.
|
|
190
|
+
// This allows for example to use the @ alias both in the library and the target project.
|
|
191
|
+
return {
|
|
192
|
+
find: alias.regex,
|
|
193
|
+
replacement: alias.replacement,
|
|
194
|
+
async customResolver(this: CustomResolverContext, source: any, importer: any) {
|
|
195
|
+
let resolvedPath = '';
|
|
196
|
+
|
|
197
|
+
resolvedPath = path.resolve(
|
|
198
|
+
// get the directory name of the importer
|
|
199
|
+
process.cwd(),
|
|
200
|
+
|
|
201
|
+
// if the importer string includes the folder name, use the external path, otherwise use the local path
|
|
202
|
+
importer?.includes(alias.libraryPath) ? alias.aliasExternalBasePath! : alias.aliasLocalBasePath!,
|
|
203
|
+
|
|
204
|
+
// remove the alias replacement from the source path
|
|
205
|
+
source.replace(alias.replacement, ''),
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
// use Vite's (in fact, rollup's) resolution function
|
|
209
|
+
return (await this.resolve(resolvedPath))?.id;
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
});
|
|
135
213
|
}
|
package/package.json
CHANGED
|
@@ -46,12 +46,17 @@
|
|
|
46
46
|
"import": "./dist/craft-ui.css",
|
|
47
47
|
"default": "./dist/craft-ui.css"
|
|
48
48
|
},
|
|
49
|
+
"./dist/craft-ui.css": {
|
|
50
|
+
"style": "./dist/craft-ui.css",
|
|
51
|
+
"import": "./dist/craft-ui.css",
|
|
52
|
+
"default": "./dist/craft-ui.css"
|
|
53
|
+
},
|
|
49
54
|
"./vite": {
|
|
50
55
|
"import": "./dist/vite/defineCraftConfig.js",
|
|
51
56
|
"types": "./dist/src/vite/defineCraftConfig.d.ts"
|
|
52
57
|
}
|
|
53
58
|
},
|
|
54
|
-
"version": "0.0.
|
|
59
|
+
"version": "0.0.6",
|
|
55
60
|
"type": "module",
|
|
56
61
|
"scripts": {
|
|
57
62
|
"dev": "vite",
|
|
@@ -71,6 +76,7 @@
|
|
|
71
76
|
"@inertiajs/core": "^2.3.6",
|
|
72
77
|
"@inertiajs/vue3": "^2.0.0",
|
|
73
78
|
"@tailwindcss/vite": "^4.0.0",
|
|
79
|
+
"@vitejs/plugin-vue": "^6.0.3",
|
|
74
80
|
"@tanstack/vue-table": "^8.21.3",
|
|
75
81
|
"@types/node": "^25.0.3",
|
|
76
82
|
"@unovis/ts": "^1.6.2",
|
|
@@ -91,6 +97,7 @@
|
|
|
91
97
|
"tw-animate-css": "^1.4.0",
|
|
92
98
|
"vaul-vue": "^0.4.1",
|
|
93
99
|
"vee-validate": "^4.15.1",
|
|
100
|
+
"vite-plugin-run": "^0.6.1",
|
|
94
101
|
"vite-plugin-vue-devtools": "^8.0.5",
|
|
95
102
|
"vue": "^3.5.0",
|
|
96
103
|
"vue-chartjs": "^5.3.3",
|
|
@@ -104,7 +111,6 @@
|
|
|
104
111
|
"@storybook/addon-themes": "^10.1.11",
|
|
105
112
|
"@storybook/addon-vitest": "10.1.11",
|
|
106
113
|
"@storybook/vue3-vite": "^10.1.11",
|
|
107
|
-
"@vitejs/plugin-vue": "^6.0.3",
|
|
108
114
|
"@vitest/browser": "^4.0.16",
|
|
109
115
|
"@vitest/browser-playwright": "^4.0.16",
|
|
110
116
|
"@vitest/coverage-v8": "^4.0.16",
|
|
@@ -116,7 +122,6 @@
|
|
|
116
122
|
"typescript": "~5.9.3",
|
|
117
123
|
"vite": "^7.3.0",
|
|
118
124
|
"vite-plugin-dts": "^4.5.4",
|
|
119
|
-
"vite-plugin-run": "^0.6.1",
|
|
120
125
|
"vitest": "^4.0.16",
|
|
121
126
|
"vue-draggable-plus": "^0.6.0",
|
|
122
127
|
"vue-router": "^4.6.4",
|
|
@@ -125,9 +130,11 @@
|
|
|
125
130
|
"peerDependencies": {
|
|
126
131
|
"@inertiajs/vue3": "^2.0.0",
|
|
127
132
|
"@tailwindcss/vite": "^4.0.0",
|
|
133
|
+
"@vitejs/plugin-vue": "^6.0.0",
|
|
128
134
|
"laravel-vite-plugin": "^2.0.1",
|
|
129
135
|
"laravel-vue-i18n": "^2.8.0",
|
|
130
|
-
"vite-plugin-run": "^0.6.
|
|
136
|
+
"vite-plugin-run": "^0.6.0",
|
|
137
|
+
"vite-plugin-vue-devtools": "^8.0.0",
|
|
131
138
|
"vue": "^3.5.0"
|
|
132
139
|
}
|
|
133
140
|
}
|