@hybridly/vite 0.0.1-dev.3 → 0.1.0-alpha.0
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.cjs +381 -64
- package/dist/index.d.ts +59 -21
- package/dist/index.mjs +374 -64
- package/package.json +15 -8
package/dist/index.cjs
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
+
const config = require('@hybridly/config');
|
|
6
|
+
const laravel = require('laravel-vite-plugin');
|
|
5
7
|
const path = require('node:path');
|
|
6
8
|
const vite = require('vite');
|
|
7
9
|
const makeDebugger = require('debug');
|
|
@@ -9,47 +11,136 @@ const fs = require('node:fs');
|
|
|
9
11
|
const throttleDebounce = require('throttle-debounce');
|
|
10
12
|
const node_child_process = require('node:child_process');
|
|
11
13
|
const node_util = require('node:util');
|
|
14
|
+
const run = require('vite-plugin-run');
|
|
15
|
+
const autoimport = require('unplugin-auto-import/vite');
|
|
16
|
+
const vueComponents = require('unplugin-vue-components/vite');
|
|
17
|
+
const iconsResolver = require('unplugin-icons/resolver');
|
|
18
|
+
const icons = require('unplugin-icons/vite');
|
|
19
|
+
const loaders = require('unplugin-icons/loaders');
|
|
20
|
+
const vue = require('@vitejs/plugin-vue');
|
|
12
21
|
|
|
13
22
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e["default"] : e; }
|
|
14
23
|
|
|
24
|
+
const laravel__default = /*#__PURE__*/_interopDefaultLegacy(laravel);
|
|
15
25
|
const path__default = /*#__PURE__*/_interopDefaultLegacy(path);
|
|
16
26
|
const makeDebugger__default = /*#__PURE__*/_interopDefaultLegacy(makeDebugger);
|
|
17
27
|
const fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
|
|
28
|
+
const run__default = /*#__PURE__*/_interopDefaultLegacy(run);
|
|
29
|
+
const autoimport__default = /*#__PURE__*/_interopDefaultLegacy(autoimport);
|
|
30
|
+
const vueComponents__default = /*#__PURE__*/_interopDefaultLegacy(vueComponents);
|
|
31
|
+
const iconsResolver__default = /*#__PURE__*/_interopDefaultLegacy(iconsResolver);
|
|
32
|
+
const icons__default = /*#__PURE__*/_interopDefaultLegacy(icons);
|
|
33
|
+
const vue__default = /*#__PURE__*/_interopDefaultLegacy(vue);
|
|
18
34
|
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const
|
|
35
|
+
const ROUTING_PLUGIN_NAME = "vite:hybridly:routing";
|
|
36
|
+
const ROUTING_HMR_UPDATE_ROUTING = "hybridly:routing:update";
|
|
37
|
+
const ROUTING_HMR_QUERY_UPDATE_ROUTING = "hybridly:routing:pls-update";
|
|
38
|
+
const ROUTING_VIRTUAL_MODULE_ID = "virtual:hybridly/router";
|
|
39
|
+
const RESOLVED_ROUTING_VIRTUAL_MODULE_ID = `\0${ROUTING_VIRTUAL_MODULE_ID}`;
|
|
23
40
|
const LAYOUT_PLUGIN_NAME = "vite:hybridly:layout";
|
|
41
|
+
const CONFIG_PLUGIN_NAME = "vite:hybridly:config";
|
|
42
|
+
const CONFIG_VIRTUAL_MODULE_ID = "virtual:hybridly/config";
|
|
43
|
+
const RESOLVED_CONFIG_VIRTUAL_MODULE_ID = `\0${CONFIG_VIRTUAL_MODULE_ID}`;
|
|
44
|
+
|
|
45
|
+
const initialize = (options, config) => {
|
|
46
|
+
return {
|
|
47
|
+
name: CONFIG_PLUGIN_NAME,
|
|
48
|
+
enforce: "pre",
|
|
49
|
+
config() {
|
|
50
|
+
return {
|
|
51
|
+
resolve: {
|
|
52
|
+
alias: {
|
|
53
|
+
"@": path__default.join(process.cwd(), config.root),
|
|
54
|
+
"#": path__default.join(process.cwd(), ".hybridly"),
|
|
55
|
+
"~": path__default.join(process.cwd())
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
},
|
|
60
|
+
configureServer(server) {
|
|
61
|
+
const reloadServer = (file) => {
|
|
62
|
+
if (!file.endsWith("hybridly.config.ts")) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
server.config.logger.info("Hybridly configuration file was changed: forcing a server restart.", {
|
|
66
|
+
clear: server.config.clearScreen,
|
|
67
|
+
timestamp: true
|
|
68
|
+
});
|
|
69
|
+
server?.restart();
|
|
70
|
+
};
|
|
71
|
+
server.watcher.on("add", reloadServer);
|
|
72
|
+
server.watcher.on("change", reloadServer);
|
|
73
|
+
server.watcher.on("unlink", reloadServer);
|
|
74
|
+
},
|
|
75
|
+
resolveId(id) {
|
|
76
|
+
if (id === CONFIG_VIRTUAL_MODULE_ID) {
|
|
77
|
+
return RESOLVED_CONFIG_VIRTUAL_MODULE_ID;
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
async load(id) {
|
|
81
|
+
if (id === RESOLVED_CONFIG_VIRTUAL_MODULE_ID) {
|
|
82
|
+
return `
|
|
83
|
+
import { initializeHybridly as init } from 'hybridly/vue'
|
|
84
|
+
import '${ROUTING_VIRTUAL_MODULE_ID}'
|
|
85
|
+
|
|
86
|
+
export function initializeHybridly(config) {
|
|
87
|
+
return init({
|
|
88
|
+
...${JSON.stringify(config)},
|
|
89
|
+
components: import.meta.glob("${config.pagesGlob}", { eager: ${config.eager ?? true} }),
|
|
90
|
+
...config,
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
`;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
};
|
|
24
98
|
|
|
25
99
|
const debug = {
|
|
26
|
-
router: makeDebugger__default(
|
|
100
|
+
router: makeDebugger__default(ROUTING_PLUGIN_NAME),
|
|
27
101
|
layout: makeDebugger__default(LAYOUT_PLUGIN_NAME)
|
|
28
102
|
};
|
|
29
103
|
|
|
30
|
-
const TEMPLATE_LAYOUT_REGEX = /<template +layout(?: *= *['"](
|
|
104
|
+
const TEMPLATE_LAYOUT_REGEX = /<template +layout(?: *= *['"]((?:[\w\/\-_,:](?:,\ )?)+)['"] *)?>/;
|
|
31
105
|
const TYPESCRIPT_REGEX = /lang=['"]ts['"]/;
|
|
32
|
-
const layout = (options
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
|
|
106
|
+
const layout = (options, config$1) => {
|
|
107
|
+
const defaultLayoutName = options?.layout?.defaultLayoutName?.replace(".vue", "") ?? "default";
|
|
108
|
+
const layoutsDirectory = path__default.resolve(process.cwd(), config$1.root, config$1.layouts);
|
|
109
|
+
const templateRegExp = options?.layout?.templateRegExp ?? TEMPLATE_LAYOUT_REGEX;
|
|
110
|
+
const resolveLayoutPath = (layoutName) => {
|
|
111
|
+
const [domain, layout] = layoutName.includes(":") ? layoutName.split(":") : [void 0, layoutName];
|
|
112
|
+
const layoutPath = path__default.resolve(config.resolveLayoutsDirectory(config$1, domain), `${layout}.vue`);
|
|
113
|
+
return vite.normalizePath(layoutPath).replaceAll("\\", "/");
|
|
114
|
+
};
|
|
115
|
+
debug.layout("Resolved options:", {
|
|
116
|
+
defaultLayoutName,
|
|
117
|
+
layoutsDirectory
|
|
118
|
+
});
|
|
36
119
|
return {
|
|
37
120
|
name: LAYOUT_PLUGIN_NAME,
|
|
121
|
+
enforce: "pre",
|
|
38
122
|
transform: (code, id) => {
|
|
39
|
-
if (!
|
|
123
|
+
if (!templateRegExp.test(code)) {
|
|
40
124
|
return;
|
|
41
125
|
}
|
|
42
|
-
return code.replace(
|
|
126
|
+
return code.replace(templateRegExp, (_, layoutName) => {
|
|
43
127
|
const isTypeScript = TYPESCRIPT_REGEX.test(code);
|
|
44
|
-
const
|
|
45
|
-
|
|
128
|
+
const layouts = layoutName?.toString()?.replaceAll(" ", "").split(",") ?? [defaultLayoutName];
|
|
129
|
+
const importName = (i) => `__hybridly_layout_${i}`;
|
|
130
|
+
const exports = layouts.map((_2, i) => importName(i));
|
|
131
|
+
const imports = layouts.reduce((imports2, layoutName2, i) => `
|
|
132
|
+
${imports2}
|
|
133
|
+
import ${importName(i)} from '${resolveLayoutPath(layoutName2)}';
|
|
134
|
+
`, "").trim();
|
|
135
|
+
debug.layout(`Resolved layouts "${layouts.join(", ")}":`, {
|
|
46
136
|
sourceFile: id,
|
|
47
|
-
|
|
137
|
+
layouts,
|
|
138
|
+
imports
|
|
48
139
|
});
|
|
49
140
|
return `
|
|
50
141
|
<script${isTypeScript ? ' lang="ts"' : ""}>
|
|
51
|
-
|
|
52
|
-
export default { layout }
|
|
142
|
+
${imports}
|
|
143
|
+
export default { layout: [${exports.join(", ")}] }
|
|
53
144
|
<\/script>
|
|
54
145
|
<template>
|
|
55
146
|
`;
|
|
@@ -58,42 +149,45 @@ const layout = (options = {}) => {
|
|
|
58
149
|
};
|
|
59
150
|
};
|
|
60
151
|
|
|
61
|
-
function
|
|
152
|
+
function getRouterClientCode(routing) {
|
|
62
153
|
return `
|
|
63
154
|
if (typeof window !== 'undefined') {
|
|
64
155
|
window.hybridly = {
|
|
65
|
-
|
|
156
|
+
routing: ${JSON.stringify(routing)}
|
|
66
157
|
}
|
|
67
|
-
|
|
158
|
+
|
|
68
159
|
if (import.meta.hot) {
|
|
69
|
-
import.meta.hot.on('${
|
|
70
|
-
window.dispatchEvent(
|
|
71
|
-
new CustomEvent('hybridly:routes', { detail: routes })
|
|
72
|
-
)
|
|
160
|
+
import.meta.hot.on('${ROUTING_HMR_UPDATE_ROUTING}', (routing) => {
|
|
161
|
+
window.dispatchEvent(new CustomEvent('hybridly:routing', { detail: routing }))
|
|
73
162
|
})
|
|
163
|
+
|
|
164
|
+
import.meta.hot.send('${ROUTING_HMR_QUERY_UPDATE_ROUTING}')
|
|
74
165
|
}
|
|
75
166
|
}
|
|
76
167
|
`;
|
|
77
168
|
}
|
|
78
169
|
|
|
79
170
|
const shell = node_util.promisify(node_child_process.exec);
|
|
80
|
-
async function
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
171
|
+
async function fetchRoutingFromArtisan(options) {
|
|
172
|
+
try {
|
|
173
|
+
const php = options.php ?? "php";
|
|
174
|
+
const result = await shell(`${php} artisan hybridly:routes`);
|
|
175
|
+
const routing = JSON.parse(result.stdout);
|
|
176
|
+
write$1(options, routing);
|
|
177
|
+
return routing;
|
|
178
|
+
} catch {
|
|
179
|
+
}
|
|
86
180
|
}
|
|
87
181
|
|
|
88
|
-
const write = throttleDebounce.debounce(1e3, writeDefinitions, { atBegin: true });
|
|
89
|
-
async function writeDefinitions(options,
|
|
90
|
-
|
|
91
|
-
if (options.dts === false) {
|
|
182
|
+
const write$1 = throttleDebounce.debounce(1e3, writeDefinitions, { atBegin: true });
|
|
183
|
+
async function writeDefinitions(options, routing) {
|
|
184
|
+
routing ?? (routing = await fetchRoutingFromArtisan(options));
|
|
185
|
+
if (options.dts === false || !routing) {
|
|
92
186
|
return;
|
|
93
187
|
}
|
|
94
|
-
debug.router("Writing types for
|
|
95
|
-
const target = path__default.resolve(options.dts ?? "
|
|
96
|
-
const routes = Object.fromEntries(Object.entries(
|
|
188
|
+
debug.router("Writing types for routing:", routing);
|
|
189
|
+
const target = path__default.resolve(options.dts ?? ".hybridly/routes.d.ts");
|
|
190
|
+
const routes = Object.fromEntries(Object.entries(routing.routes).map(([key, route]) => {
|
|
97
191
|
const bindings = route.bindings ? Object.fromEntries(Object.entries(route.bindings).map(([key2]) => [key2, "__key_placeholder__"])) : void 0;
|
|
98
192
|
return [key, {
|
|
99
193
|
...route.uri ? { uri: route.uri } : {},
|
|
@@ -102,7 +196,8 @@ async function writeDefinitions(options, collection) {
|
|
|
102
196
|
...route.bindings ? { bindings } : {}
|
|
103
197
|
}];
|
|
104
198
|
}));
|
|
105
|
-
const definitions = generateDefinitions().replace("__URL__",
|
|
199
|
+
const definitions = generateDefinitions().replace("__URL__", routing?.url ?? "").replace("__ROUTES__", JSON.stringify(routes).replaceAll('"__key_placeholder__"', "any"));
|
|
200
|
+
fs__default.mkdirSync(path__default.dirname(target), { recursive: true });
|
|
106
201
|
fs__default.writeFileSync(target, definitions, { encoding: "utf-8" });
|
|
107
202
|
}
|
|
108
203
|
function generateDefinitions() {
|
|
@@ -111,7 +206,7 @@ function generateDefinitions() {
|
|
|
111
206
|
// Modifications will be discarded
|
|
112
207
|
// It is recommended to add it in your .gitignore
|
|
113
208
|
|
|
114
|
-
declare module 'hybridly
|
|
209
|
+
declare module 'hybridly' {
|
|
115
210
|
export interface GlobalRouteCollection {
|
|
116
211
|
url: '__URL__'
|
|
117
212
|
routes: __ROUTES__
|
|
@@ -121,46 +216,52 @@ declare module 'hybridly/vue' {
|
|
|
121
216
|
export {}`;
|
|
122
217
|
}
|
|
123
218
|
|
|
124
|
-
const router = (options
|
|
219
|
+
const router = (options, config) => {
|
|
125
220
|
const resolved = {
|
|
126
221
|
php: "php",
|
|
127
|
-
dts: "
|
|
222
|
+
dts: ".hybridly/routes.d.ts",
|
|
128
223
|
watch: [
|
|
129
224
|
/routes\/.*\.php/
|
|
130
225
|
],
|
|
131
226
|
...options
|
|
132
227
|
};
|
|
133
|
-
let
|
|
228
|
+
let routingBeforeUpdate;
|
|
229
|
+
async function sendRoutingUpdate(server, force = false) {
|
|
230
|
+
const routing = await fetchRoutingFromArtisan(resolved) ?? routingBeforeUpdate;
|
|
231
|
+
if (force || JSON.stringify(routing) !== JSON.stringify(routingBeforeUpdate)) {
|
|
232
|
+
debug.router("Updating routes via HMR:", routing);
|
|
233
|
+
server.ws.send({
|
|
234
|
+
type: "custom",
|
|
235
|
+
event: ROUTING_HMR_UPDATE_ROUTING,
|
|
236
|
+
data: routing
|
|
237
|
+
});
|
|
238
|
+
write$1(resolved);
|
|
239
|
+
routingBeforeUpdate = routing;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
134
242
|
return {
|
|
135
|
-
name:
|
|
243
|
+
name: ROUTING_PLUGIN_NAME,
|
|
136
244
|
configureServer(server) {
|
|
137
|
-
write(resolved);
|
|
245
|
+
write$1(resolved);
|
|
246
|
+
server.ws.on(ROUTING_HMR_QUERY_UPDATE_ROUTING, () => {
|
|
247
|
+
sendRoutingUpdate(server, true);
|
|
248
|
+
});
|
|
138
249
|
server.watcher.on("change", async (path) => {
|
|
139
250
|
if (!resolved.watch.some((regex) => regex.test(path))) {
|
|
140
251
|
return;
|
|
141
252
|
}
|
|
142
|
-
|
|
143
|
-
if (JSON.stringify(routes) !== JSON.stringify(previousRoutes)) {
|
|
144
|
-
debug.router("Updating routes via HMR:", routes);
|
|
145
|
-
server.ws.send({
|
|
146
|
-
type: "custom",
|
|
147
|
-
event: ROUTER_HMR_UPDATE_ROUTE,
|
|
148
|
-
data: routes
|
|
149
|
-
});
|
|
150
|
-
write(resolved);
|
|
151
|
-
previousRoutes = routes;
|
|
152
|
-
}
|
|
253
|
+
sendRoutingUpdate(server);
|
|
153
254
|
});
|
|
154
255
|
},
|
|
155
256
|
resolveId(id) {
|
|
156
|
-
if (id ===
|
|
157
|
-
return
|
|
257
|
+
if (id === ROUTING_VIRTUAL_MODULE_ID) {
|
|
258
|
+
return RESOLVED_ROUTING_VIRTUAL_MODULE_ID;
|
|
158
259
|
}
|
|
159
260
|
},
|
|
160
261
|
async load(id) {
|
|
161
|
-
if (id ===
|
|
162
|
-
const
|
|
163
|
-
return
|
|
262
|
+
if (id === RESOLVED_ROUTING_VIRTUAL_MODULE_ID) {
|
|
263
|
+
const routing = await fetchRoutingFromArtisan(resolved);
|
|
264
|
+
return getRouterClientCode(routing);
|
|
164
265
|
}
|
|
165
266
|
},
|
|
166
267
|
async handleHotUpdate(ctx) {
|
|
@@ -169,15 +270,231 @@ const router = (options = {}) => {
|
|
|
169
270
|
}
|
|
170
271
|
},
|
|
171
272
|
transform() {
|
|
172
|
-
write(resolved);
|
|
273
|
+
write$1(resolved);
|
|
173
274
|
}
|
|
174
275
|
};
|
|
175
276
|
};
|
|
176
277
|
|
|
177
|
-
function
|
|
278
|
+
function getRunOptions(options) {
|
|
279
|
+
if (options.run === false) {
|
|
280
|
+
return [];
|
|
281
|
+
}
|
|
282
|
+
return [
|
|
283
|
+
{
|
|
284
|
+
name: "Generate TypeScript types",
|
|
285
|
+
run: ["php", "artisan", "hybridly:types"],
|
|
286
|
+
pattern: [
|
|
287
|
+
"(app|src)/**/*Data.php",
|
|
288
|
+
"(app|src)/**/Enums/*.php",
|
|
289
|
+
"(app|src)/**/Middlewrare/HandleHybridRequests.php"
|
|
290
|
+
]
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
name: "Generate i18n",
|
|
294
|
+
run: ["php", "artisan", "hybridly:i18n"],
|
|
295
|
+
pattern: "lang/**/*.php"
|
|
296
|
+
},
|
|
297
|
+
...options.run ?? []
|
|
298
|
+
];
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function getLaravelOptions(options, config) {
|
|
302
|
+
return {
|
|
303
|
+
input: `${config.root}/application/main.ts`,
|
|
304
|
+
...options.laravel ?? {}
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function getAutoImportsOptions(options, config) {
|
|
309
|
+
if (options.autoImports === false) {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
return {
|
|
313
|
+
vueTemplate: true,
|
|
314
|
+
dts: ".hybridly/auto-imports.d.ts",
|
|
315
|
+
dirs: [
|
|
316
|
+
`${config.root}/utils`,
|
|
317
|
+
`${config.root}/composables`,
|
|
318
|
+
...options.autoImports?.dirs ?? []
|
|
319
|
+
],
|
|
320
|
+
imports: [
|
|
321
|
+
"vue",
|
|
322
|
+
"vue/macros",
|
|
323
|
+
"@vueuse/core",
|
|
324
|
+
"@vueuse/head",
|
|
325
|
+
{
|
|
326
|
+
"hybridly/vue": [
|
|
327
|
+
"useProperty",
|
|
328
|
+
"useTypedProperty",
|
|
329
|
+
"useProperties",
|
|
330
|
+
"useBackForward",
|
|
331
|
+
"useContext",
|
|
332
|
+
"useForm",
|
|
333
|
+
"useDialog",
|
|
334
|
+
"useHistoryState",
|
|
335
|
+
"usePaginator",
|
|
336
|
+
"defineLayout",
|
|
337
|
+
"defineLayoutProperties",
|
|
338
|
+
"registerHook"
|
|
339
|
+
],
|
|
340
|
+
"hybridly": [
|
|
341
|
+
"router",
|
|
342
|
+
"route",
|
|
343
|
+
"current",
|
|
344
|
+
"can"
|
|
345
|
+
]
|
|
346
|
+
}
|
|
347
|
+
],
|
|
348
|
+
...options.autoImports
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function getVueComponentsOptions(options, config) {
|
|
353
|
+
if (options.vueComponents === false) {
|
|
354
|
+
return {};
|
|
355
|
+
}
|
|
356
|
+
const linkName = options.vueComponents?.linkName ?? "RouterLink";
|
|
357
|
+
const hasIcons = options?.icons !== false;
|
|
358
|
+
const customCollections = Array.isArray(options.customIcons) ? options.customIcons : options.customIcons?.collections ?? [];
|
|
359
|
+
const customResolvers = options.customResolvers ? Array.isArray(options.customResolvers) ? options.customResolvers : [options.customResolvers] : [];
|
|
360
|
+
return {
|
|
361
|
+
globs: [
|
|
362
|
+
`${config.root}/components/**/*.vue`,
|
|
363
|
+
...config.domains ? [`${config.root}/${config.domains}/**/components/**/*.vue`] : []
|
|
364
|
+
],
|
|
365
|
+
dts: ".hybridly/components.d.ts",
|
|
366
|
+
resolvers: [
|
|
367
|
+
...hasIcons ? [iconsResolver__default({ customCollections })] : [],
|
|
368
|
+
{
|
|
369
|
+
type: "component",
|
|
370
|
+
resolve: (name) => {
|
|
371
|
+
if (name === linkName) {
|
|
372
|
+
return {
|
|
373
|
+
from: "hybridly/vue",
|
|
374
|
+
name: "RouterLink",
|
|
375
|
+
as: linkName
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
},
|
|
380
|
+
...customResolvers
|
|
381
|
+
]
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
function getIconsOptions(options, config) {
|
|
386
|
+
if (options.icons === false) {
|
|
387
|
+
return {};
|
|
388
|
+
}
|
|
389
|
+
const resolved = Array.isArray(options.customIcons) ? { icons: void 0, collections: options.customIcons } : options.customIcons;
|
|
390
|
+
const customIconDirectoryName = resolved?.icons ?? "icons";
|
|
391
|
+
const customCollections = Object.fromEntries(resolved?.collections?.map((collection) => [
|
|
392
|
+
collection,
|
|
393
|
+
loaders.FileSystemIconLoader(`./${config.root}/${customIconDirectoryName}/${collection}`)
|
|
394
|
+
]) ?? []);
|
|
395
|
+
return {
|
|
396
|
+
autoInstall: true,
|
|
397
|
+
customCollections,
|
|
398
|
+
...options.icons
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
function getVueOptions(options) {
|
|
403
|
+
if (options.vue === false) {
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
return {
|
|
407
|
+
template: {
|
|
408
|
+
transformAssetUrls: {
|
|
409
|
+
base: null,
|
|
410
|
+
includeAbsolute: false
|
|
411
|
+
}
|
|
412
|
+
},
|
|
413
|
+
...options.vue
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function generateTsConfig(options, config) {
|
|
418
|
+
const tsconfig = {
|
|
419
|
+
compilerOptions: {
|
|
420
|
+
target: "esnext",
|
|
421
|
+
module: "esnext",
|
|
422
|
+
moduleResolution: "node",
|
|
423
|
+
strict: true,
|
|
424
|
+
jsx: "preserve",
|
|
425
|
+
sourceMap: true,
|
|
426
|
+
resolveJsonModule: true,
|
|
427
|
+
esModuleInterop: true,
|
|
428
|
+
allowSyntheticDefaultImports: true,
|
|
429
|
+
lib: [
|
|
430
|
+
"esnext",
|
|
431
|
+
"dom"
|
|
432
|
+
],
|
|
433
|
+
types: [
|
|
434
|
+
"vite/client",
|
|
435
|
+
"hybridly/client",
|
|
436
|
+
...options.icons !== false ? ["unplugin-icons/types/vue"] : []
|
|
437
|
+
],
|
|
438
|
+
baseUrl: "..",
|
|
439
|
+
paths: {
|
|
440
|
+
"#/*": [
|
|
441
|
+
".hybridly/*"
|
|
442
|
+
],
|
|
443
|
+
"~/*": [
|
|
444
|
+
"./*"
|
|
445
|
+
],
|
|
446
|
+
"@/*": [
|
|
447
|
+
`./${config.root}/*`
|
|
448
|
+
]
|
|
449
|
+
}
|
|
450
|
+
},
|
|
451
|
+
include: [
|
|
452
|
+
`../${config.root}/**/*`,
|
|
453
|
+
"./*"
|
|
454
|
+
],
|
|
455
|
+
exclude: [
|
|
456
|
+
"../public/**/*",
|
|
457
|
+
"../node_modules",
|
|
458
|
+
"../vendor"
|
|
459
|
+
]
|
|
460
|
+
};
|
|
461
|
+
write(JSON.stringify(tsconfig, null, 2), "tsconfig.json");
|
|
462
|
+
}
|
|
463
|
+
function generateVueShims(options) {
|
|
464
|
+
if (options.shims === false) {
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
const shims = `declare module '*.vue' {
|
|
468
|
+
import type { DefineComponent } from 'vue'
|
|
469
|
+
const component: DefineComponent<{}, {}, any>
|
|
470
|
+
export default component
|
|
471
|
+
}`;
|
|
472
|
+
write(shims, "vue-shims.d.ts");
|
|
473
|
+
}
|
|
474
|
+
function write(data, filename) {
|
|
475
|
+
const hybridlyPath = path__default.resolve(process.cwd(), ".hybridly");
|
|
476
|
+
if (!fs__default.existsSync(hybridlyPath)) {
|
|
477
|
+
fs__default.mkdirSync(hybridlyPath);
|
|
478
|
+
}
|
|
479
|
+
fs__default.writeFileSync(path__default.resolve(hybridlyPath, filename), data, {
|
|
480
|
+
encoding: "utf-8"
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
async function plugin(options = {}) {
|
|
485
|
+
const config$1 = await config.loadHybridlyConfig();
|
|
486
|
+
generateTsConfig(options, config$1);
|
|
487
|
+
generateVueShims(options);
|
|
178
488
|
return [
|
|
179
|
-
options
|
|
180
|
-
options
|
|
489
|
+
initialize(options, config$1),
|
|
490
|
+
layout(options, config$1),
|
|
491
|
+
router(options),
|
|
492
|
+
options.laravel !== false && laravel__default(getLaravelOptions(options, config$1)),
|
|
493
|
+
options.run !== false && run__default(getRunOptions(options)),
|
|
494
|
+
options.vueComponents !== false && vueComponents__default(getVueComponentsOptions(options, config$1)),
|
|
495
|
+
options.autoImports !== false && autoimport__default(getAutoImportsOptions(options, config$1)),
|
|
496
|
+
options.icons !== false && icons__default(getIconsOptions(options, config$1)),
|
|
497
|
+
options.vue !== false && vue__default(getVueOptions(options))
|
|
181
498
|
];
|
|
182
499
|
}
|
|
183
500
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,63 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ResolvedHybridlyConfig, HybridlyConfig } from '@hybridly/config';
|
|
2
|
+
import { Plugin } from 'vite';
|
|
3
|
+
import autoimport from 'unplugin-auto-import/vite';
|
|
4
|
+
import icons from 'unplugin-icons/vite';
|
|
5
|
+
import laravel from 'laravel-vite-plugin';
|
|
6
|
+
import { Runner } from 'vite-plugin-run';
|
|
7
|
+
import vue from '@vitejs/plugin-vue';
|
|
8
|
+
import vueComponents from 'unplugin-vue-components/vite';
|
|
9
|
+
import { ComponentResolver } from 'unplugin-vue-components/types';
|
|
2
10
|
|
|
3
|
-
|
|
11
|
+
type AutoImportOptions = Parameters<typeof autoimport>[0];
|
|
12
|
+
|
|
13
|
+
type IconsOptions = Parameters<typeof icons>[0];
|
|
14
|
+
type CustomIconOptions = string[] | {
|
|
15
|
+
/** Name of the icons directory under the root directory. */
|
|
16
|
+
icons?: string;
|
|
17
|
+
/** Names of the custom icon collections that should be registered. */
|
|
18
|
+
collections?: string[];
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
type LaravelOptions = Exclude<Parameters<typeof laravel>[0], string | string[]>;
|
|
22
|
+
|
|
23
|
+
type VueOptions = Parameters<typeof vue>[0];
|
|
24
|
+
|
|
25
|
+
type VueComponentsOptions = Parameters<typeof vueComponents>[0] & {
|
|
26
|
+
/** Name of the Link component. */
|
|
27
|
+
linkName?: string;
|
|
28
|
+
};
|
|
29
|
+
type CustomResolvers = ComponentResolver | ComponentResolver[];
|
|
30
|
+
type CustomComponentsOptions = VueComponentsOptions;
|
|
31
|
+
|
|
32
|
+
interface ViteOptions {
|
|
4
33
|
/** Options for the layout plugin. */
|
|
5
|
-
layout?:
|
|
34
|
+
layout?: LayoutOptions;
|
|
6
35
|
/** Options for the router plugin. */
|
|
7
|
-
router?:
|
|
36
|
+
router?: RouterOptions;
|
|
37
|
+
/** Options for `@vitejs/plugin-vue`. */
|
|
38
|
+
vue?: false | VueOptions;
|
|
39
|
+
/** Options for `laravel-vite-plugin`. Set to `false` to disable. */
|
|
40
|
+
laravel?: false | Partial<LaravelOptions>;
|
|
41
|
+
/** Options for `vite-plugin-run`. Set to `false` to disable. */
|
|
42
|
+
run?: false | Runner[];
|
|
43
|
+
/** Options for `unplugin-auto-import`. Set to `false` to disable. */
|
|
44
|
+
autoImports?: false | AutoImportOptions;
|
|
45
|
+
/** Options for `unplugin-vue-components`. Set to `false` to disable. */
|
|
46
|
+
vueComponents?: false | CustomComponentsOptions;
|
|
47
|
+
/** Options for `unplugin-icons`. Set to `false` to disable. */
|
|
48
|
+
icons?: false | IconsOptions;
|
|
49
|
+
/** Options for custom icon collections. */
|
|
50
|
+
customIcons?: CustomIconOptions;
|
|
51
|
+
/** Custom vue component resolvers. */
|
|
52
|
+
customResolvers?: CustomResolvers;
|
|
53
|
+
/** Whether to write shims. */
|
|
54
|
+
shims?: boolean;
|
|
8
55
|
}
|
|
9
56
|
interface LayoutOptions {
|
|
10
|
-
/**
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
|
|
57
|
+
/** Custom RegExp for parsing the template string. */
|
|
58
|
+
templateRegExp?: RegExp;
|
|
59
|
+
/** Name of the layout used when no argument is provided to `layout`. */
|
|
60
|
+
defaultLayoutName?: string;
|
|
14
61
|
}
|
|
15
62
|
interface RouterOptions {
|
|
16
63
|
/** Path to the PHP executable. */
|
|
@@ -21,19 +68,10 @@ interface RouterOptions {
|
|
|
21
68
|
watch?: RegExp[];
|
|
22
69
|
}
|
|
23
70
|
|
|
24
|
-
|
|
25
|
-
* A basic Vite plugin that adds a <template layout="name"> syntax to Vite SFCs.
|
|
26
|
-
* It must be used before the Vue plugin.
|
|
27
|
-
*/
|
|
28
|
-
declare const _default$1: (options?: LayoutOptions) => Plugin;
|
|
71
|
+
declare const _default$1: (options: ViteOptions, config: ResolvedHybridlyConfig) => Plugin;
|
|
29
72
|
|
|
30
|
-
|
|
31
|
-
* A basic Vite plugin that adds a <template layout="name"> syntax to Vite SFCs.
|
|
32
|
-
* It must be used before the Vue plugin.
|
|
33
|
-
*/
|
|
34
|
-
declare const _default: (options?: RouterOptions) => Plugin;
|
|
73
|
+
declare const _default: (options: ViteOptions, config: HybridlyConfig) => Plugin;
|
|
35
74
|
|
|
36
|
-
|
|
37
|
-
declare function plugin(options?: Options): PluginOption[];
|
|
75
|
+
declare function plugin(options?: ViteOptions): Promise<any[]>;
|
|
38
76
|
|
|
39
|
-
export { Options, plugin as default, _default$1 as layout, _default as router };
|
|
77
|
+
export { ViteOptions as Options, plugin as default, _default$1 as layout, _default as router };
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { resolveLayoutsDirectory, loadHybridlyConfig } from '@hybridly/config';
|
|
2
|
+
import laravel from 'laravel-vite-plugin';
|
|
1
3
|
import path from 'node:path';
|
|
2
4
|
import { normalizePath } from 'vite';
|
|
3
5
|
import makeDebugger from 'debug';
|
|
@@ -5,41 +7,123 @@ import fs from 'node:fs';
|
|
|
5
7
|
import { debounce } from 'throttle-debounce';
|
|
6
8
|
import { exec } from 'node:child_process';
|
|
7
9
|
import { promisify } from 'node:util';
|
|
10
|
+
import run from 'vite-plugin-run';
|
|
11
|
+
import autoimport from 'unplugin-auto-import/vite';
|
|
12
|
+
import vueComponents from 'unplugin-vue-components/vite';
|
|
13
|
+
import iconsResolver from 'unplugin-icons/resolver';
|
|
14
|
+
import icons from 'unplugin-icons/vite';
|
|
15
|
+
import { FileSystemIconLoader } from 'unplugin-icons/loaders';
|
|
16
|
+
import vue from '@vitejs/plugin-vue';
|
|
8
17
|
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
18
|
+
const ROUTING_PLUGIN_NAME = "vite:hybridly:routing";
|
|
19
|
+
const ROUTING_HMR_UPDATE_ROUTING = "hybridly:routing:update";
|
|
20
|
+
const ROUTING_HMR_QUERY_UPDATE_ROUTING = "hybridly:routing:pls-update";
|
|
21
|
+
const ROUTING_VIRTUAL_MODULE_ID = "virtual:hybridly/router";
|
|
22
|
+
const RESOLVED_ROUTING_VIRTUAL_MODULE_ID = `\0${ROUTING_VIRTUAL_MODULE_ID}`;
|
|
13
23
|
const LAYOUT_PLUGIN_NAME = "vite:hybridly:layout";
|
|
24
|
+
const CONFIG_PLUGIN_NAME = "vite:hybridly:config";
|
|
25
|
+
const CONFIG_VIRTUAL_MODULE_ID = "virtual:hybridly/config";
|
|
26
|
+
const RESOLVED_CONFIG_VIRTUAL_MODULE_ID = `\0${CONFIG_VIRTUAL_MODULE_ID}`;
|
|
27
|
+
|
|
28
|
+
const initialize = (options, config) => {
|
|
29
|
+
return {
|
|
30
|
+
name: CONFIG_PLUGIN_NAME,
|
|
31
|
+
enforce: "pre",
|
|
32
|
+
config() {
|
|
33
|
+
return {
|
|
34
|
+
resolve: {
|
|
35
|
+
alias: {
|
|
36
|
+
"@": path.join(process.cwd(), config.root),
|
|
37
|
+
"#": path.join(process.cwd(), ".hybridly"),
|
|
38
|
+
"~": path.join(process.cwd())
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
configureServer(server) {
|
|
44
|
+
const reloadServer = (file) => {
|
|
45
|
+
if (!file.endsWith("hybridly.config.ts")) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
server.config.logger.info("Hybridly configuration file was changed: forcing a server restart.", {
|
|
49
|
+
clear: server.config.clearScreen,
|
|
50
|
+
timestamp: true
|
|
51
|
+
});
|
|
52
|
+
server?.restart();
|
|
53
|
+
};
|
|
54
|
+
server.watcher.on("add", reloadServer);
|
|
55
|
+
server.watcher.on("change", reloadServer);
|
|
56
|
+
server.watcher.on("unlink", reloadServer);
|
|
57
|
+
},
|
|
58
|
+
resolveId(id) {
|
|
59
|
+
if (id === CONFIG_VIRTUAL_MODULE_ID) {
|
|
60
|
+
return RESOLVED_CONFIG_VIRTUAL_MODULE_ID;
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
async load(id) {
|
|
64
|
+
if (id === RESOLVED_CONFIG_VIRTUAL_MODULE_ID) {
|
|
65
|
+
return `
|
|
66
|
+
import { initializeHybridly as init } from 'hybridly/vue'
|
|
67
|
+
import '${ROUTING_VIRTUAL_MODULE_ID}'
|
|
68
|
+
|
|
69
|
+
export function initializeHybridly(config) {
|
|
70
|
+
return init({
|
|
71
|
+
...${JSON.stringify(config)},
|
|
72
|
+
components: import.meta.glob("${config.pagesGlob}", { eager: ${config.eager ?? true} }),
|
|
73
|
+
...config,
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
`;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
};
|
|
14
81
|
|
|
15
82
|
const debug = {
|
|
16
|
-
router: makeDebugger(
|
|
83
|
+
router: makeDebugger(ROUTING_PLUGIN_NAME),
|
|
17
84
|
layout: makeDebugger(LAYOUT_PLUGIN_NAME)
|
|
18
85
|
};
|
|
19
86
|
|
|
20
|
-
const TEMPLATE_LAYOUT_REGEX = /<template +layout(?: *= *['"](
|
|
87
|
+
const TEMPLATE_LAYOUT_REGEX = /<template +layout(?: *= *['"]((?:[\w\/\-_,:](?:,\ )?)+)['"] *)?>/;
|
|
21
88
|
const TYPESCRIPT_REGEX = /lang=['"]ts['"]/;
|
|
22
|
-
const layout = (options
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
|
|
89
|
+
const layout = (options, config) => {
|
|
90
|
+
const defaultLayoutName = options?.layout?.defaultLayoutName?.replace(".vue", "") ?? "default";
|
|
91
|
+
const layoutsDirectory = path.resolve(process.cwd(), config.root, config.layouts);
|
|
92
|
+
const templateRegExp = options?.layout?.templateRegExp ?? TEMPLATE_LAYOUT_REGEX;
|
|
93
|
+
const resolveLayoutPath = (layoutName) => {
|
|
94
|
+
const [domain, layout] = layoutName.includes(":") ? layoutName.split(":") : [void 0, layoutName];
|
|
95
|
+
const layoutPath = path.resolve(resolveLayoutsDirectory(config, domain), `${layout}.vue`);
|
|
96
|
+
return normalizePath(layoutPath).replaceAll("\\", "/");
|
|
97
|
+
};
|
|
98
|
+
debug.layout("Resolved options:", {
|
|
99
|
+
defaultLayoutName,
|
|
100
|
+
layoutsDirectory
|
|
101
|
+
});
|
|
26
102
|
return {
|
|
27
103
|
name: LAYOUT_PLUGIN_NAME,
|
|
104
|
+
enforce: "pre",
|
|
28
105
|
transform: (code, id) => {
|
|
29
|
-
if (!
|
|
106
|
+
if (!templateRegExp.test(code)) {
|
|
30
107
|
return;
|
|
31
108
|
}
|
|
32
|
-
return code.replace(
|
|
109
|
+
return code.replace(templateRegExp, (_, layoutName) => {
|
|
33
110
|
const isTypeScript = TYPESCRIPT_REGEX.test(code);
|
|
34
|
-
const
|
|
35
|
-
|
|
111
|
+
const layouts = layoutName?.toString()?.replaceAll(" ", "").split(",") ?? [defaultLayoutName];
|
|
112
|
+
const importName = (i) => `__hybridly_layout_${i}`;
|
|
113
|
+
const exports = layouts.map((_2, i) => importName(i));
|
|
114
|
+
const imports = layouts.reduce((imports2, layoutName2, i) => `
|
|
115
|
+
${imports2}
|
|
116
|
+
import ${importName(i)} from '${resolveLayoutPath(layoutName2)}';
|
|
117
|
+
`, "").trim();
|
|
118
|
+
debug.layout(`Resolved layouts "${layouts.join(", ")}":`, {
|
|
36
119
|
sourceFile: id,
|
|
37
|
-
|
|
120
|
+
layouts,
|
|
121
|
+
imports
|
|
38
122
|
});
|
|
39
123
|
return `
|
|
40
124
|
<script${isTypeScript ? ' lang="ts"' : ""}>
|
|
41
|
-
|
|
42
|
-
export default { layout }
|
|
125
|
+
${imports}
|
|
126
|
+
export default { layout: [${exports.join(", ")}] }
|
|
43
127
|
<\/script>
|
|
44
128
|
<template>
|
|
45
129
|
`;
|
|
@@ -48,42 +132,45 @@ const layout = (options = {}) => {
|
|
|
48
132
|
};
|
|
49
133
|
};
|
|
50
134
|
|
|
51
|
-
function
|
|
135
|
+
function getRouterClientCode(routing) {
|
|
52
136
|
return `
|
|
53
137
|
if (typeof window !== 'undefined') {
|
|
54
138
|
window.hybridly = {
|
|
55
|
-
|
|
139
|
+
routing: ${JSON.stringify(routing)}
|
|
56
140
|
}
|
|
57
|
-
|
|
141
|
+
|
|
58
142
|
if (import.meta.hot) {
|
|
59
|
-
import.meta.hot.on('${
|
|
60
|
-
window.dispatchEvent(
|
|
61
|
-
new CustomEvent('hybridly:routes', { detail: routes })
|
|
62
|
-
)
|
|
143
|
+
import.meta.hot.on('${ROUTING_HMR_UPDATE_ROUTING}', (routing) => {
|
|
144
|
+
window.dispatchEvent(new CustomEvent('hybridly:routing', { detail: routing }))
|
|
63
145
|
})
|
|
146
|
+
|
|
147
|
+
import.meta.hot.send('${ROUTING_HMR_QUERY_UPDATE_ROUTING}')
|
|
64
148
|
}
|
|
65
149
|
}
|
|
66
150
|
`;
|
|
67
151
|
}
|
|
68
152
|
|
|
69
153
|
const shell = promisify(exec);
|
|
70
|
-
async function
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
154
|
+
async function fetchRoutingFromArtisan(options) {
|
|
155
|
+
try {
|
|
156
|
+
const php = options.php ?? "php";
|
|
157
|
+
const result = await shell(`${php} artisan hybridly:routes`);
|
|
158
|
+
const routing = JSON.parse(result.stdout);
|
|
159
|
+
write$1(options, routing);
|
|
160
|
+
return routing;
|
|
161
|
+
} catch {
|
|
162
|
+
}
|
|
76
163
|
}
|
|
77
164
|
|
|
78
|
-
const write = debounce(1e3, writeDefinitions, { atBegin: true });
|
|
79
|
-
async function writeDefinitions(options,
|
|
80
|
-
|
|
81
|
-
if (options.dts === false) {
|
|
165
|
+
const write$1 = debounce(1e3, writeDefinitions, { atBegin: true });
|
|
166
|
+
async function writeDefinitions(options, routing) {
|
|
167
|
+
routing ?? (routing = await fetchRoutingFromArtisan(options));
|
|
168
|
+
if (options.dts === false || !routing) {
|
|
82
169
|
return;
|
|
83
170
|
}
|
|
84
|
-
debug.router("Writing types for
|
|
85
|
-
const target = path.resolve(options.dts ?? "
|
|
86
|
-
const routes = Object.fromEntries(Object.entries(
|
|
171
|
+
debug.router("Writing types for routing:", routing);
|
|
172
|
+
const target = path.resolve(options.dts ?? ".hybridly/routes.d.ts");
|
|
173
|
+
const routes = Object.fromEntries(Object.entries(routing.routes).map(([key, route]) => {
|
|
87
174
|
const bindings = route.bindings ? Object.fromEntries(Object.entries(route.bindings).map(([key2]) => [key2, "__key_placeholder__"])) : void 0;
|
|
88
175
|
return [key, {
|
|
89
176
|
...route.uri ? { uri: route.uri } : {},
|
|
@@ -92,7 +179,8 @@ async function writeDefinitions(options, collection) {
|
|
|
92
179
|
...route.bindings ? { bindings } : {}
|
|
93
180
|
}];
|
|
94
181
|
}));
|
|
95
|
-
const definitions = generateDefinitions().replace("__URL__",
|
|
182
|
+
const definitions = generateDefinitions().replace("__URL__", routing?.url ?? "").replace("__ROUTES__", JSON.stringify(routes).replaceAll('"__key_placeholder__"', "any"));
|
|
183
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
96
184
|
fs.writeFileSync(target, definitions, { encoding: "utf-8" });
|
|
97
185
|
}
|
|
98
186
|
function generateDefinitions() {
|
|
@@ -101,7 +189,7 @@ function generateDefinitions() {
|
|
|
101
189
|
// Modifications will be discarded
|
|
102
190
|
// It is recommended to add it in your .gitignore
|
|
103
191
|
|
|
104
|
-
declare module 'hybridly
|
|
192
|
+
declare module 'hybridly' {
|
|
105
193
|
export interface GlobalRouteCollection {
|
|
106
194
|
url: '__URL__'
|
|
107
195
|
routes: __ROUTES__
|
|
@@ -111,46 +199,52 @@ declare module 'hybridly/vue' {
|
|
|
111
199
|
export {}`;
|
|
112
200
|
}
|
|
113
201
|
|
|
114
|
-
const router = (options
|
|
202
|
+
const router = (options, config) => {
|
|
115
203
|
const resolved = {
|
|
116
204
|
php: "php",
|
|
117
|
-
dts: "
|
|
205
|
+
dts: ".hybridly/routes.d.ts",
|
|
118
206
|
watch: [
|
|
119
207
|
/routes\/.*\.php/
|
|
120
208
|
],
|
|
121
209
|
...options
|
|
122
210
|
};
|
|
123
|
-
let
|
|
211
|
+
let routingBeforeUpdate;
|
|
212
|
+
async function sendRoutingUpdate(server, force = false) {
|
|
213
|
+
const routing = await fetchRoutingFromArtisan(resolved) ?? routingBeforeUpdate;
|
|
214
|
+
if (force || JSON.stringify(routing) !== JSON.stringify(routingBeforeUpdate)) {
|
|
215
|
+
debug.router("Updating routes via HMR:", routing);
|
|
216
|
+
server.ws.send({
|
|
217
|
+
type: "custom",
|
|
218
|
+
event: ROUTING_HMR_UPDATE_ROUTING,
|
|
219
|
+
data: routing
|
|
220
|
+
});
|
|
221
|
+
write$1(resolved);
|
|
222
|
+
routingBeforeUpdate = routing;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
124
225
|
return {
|
|
125
|
-
name:
|
|
226
|
+
name: ROUTING_PLUGIN_NAME,
|
|
126
227
|
configureServer(server) {
|
|
127
|
-
write(resolved);
|
|
228
|
+
write$1(resolved);
|
|
229
|
+
server.ws.on(ROUTING_HMR_QUERY_UPDATE_ROUTING, () => {
|
|
230
|
+
sendRoutingUpdate(server, true);
|
|
231
|
+
});
|
|
128
232
|
server.watcher.on("change", async (path) => {
|
|
129
233
|
if (!resolved.watch.some((regex) => regex.test(path))) {
|
|
130
234
|
return;
|
|
131
235
|
}
|
|
132
|
-
|
|
133
|
-
if (JSON.stringify(routes) !== JSON.stringify(previousRoutes)) {
|
|
134
|
-
debug.router("Updating routes via HMR:", routes);
|
|
135
|
-
server.ws.send({
|
|
136
|
-
type: "custom",
|
|
137
|
-
event: ROUTER_HMR_UPDATE_ROUTE,
|
|
138
|
-
data: routes
|
|
139
|
-
});
|
|
140
|
-
write(resolved);
|
|
141
|
-
previousRoutes = routes;
|
|
142
|
-
}
|
|
236
|
+
sendRoutingUpdate(server);
|
|
143
237
|
});
|
|
144
238
|
},
|
|
145
239
|
resolveId(id) {
|
|
146
|
-
if (id ===
|
|
147
|
-
return
|
|
240
|
+
if (id === ROUTING_VIRTUAL_MODULE_ID) {
|
|
241
|
+
return RESOLVED_ROUTING_VIRTUAL_MODULE_ID;
|
|
148
242
|
}
|
|
149
243
|
},
|
|
150
244
|
async load(id) {
|
|
151
|
-
if (id ===
|
|
152
|
-
const
|
|
153
|
-
return
|
|
245
|
+
if (id === RESOLVED_ROUTING_VIRTUAL_MODULE_ID) {
|
|
246
|
+
const routing = await fetchRoutingFromArtisan(resolved);
|
|
247
|
+
return getRouterClientCode(routing);
|
|
154
248
|
}
|
|
155
249
|
},
|
|
156
250
|
async handleHotUpdate(ctx) {
|
|
@@ -159,15 +253,231 @@ const router = (options = {}) => {
|
|
|
159
253
|
}
|
|
160
254
|
},
|
|
161
255
|
transform() {
|
|
162
|
-
write(resolved);
|
|
256
|
+
write$1(resolved);
|
|
163
257
|
}
|
|
164
258
|
};
|
|
165
259
|
};
|
|
166
260
|
|
|
167
|
-
function
|
|
261
|
+
function getRunOptions(options) {
|
|
262
|
+
if (options.run === false) {
|
|
263
|
+
return [];
|
|
264
|
+
}
|
|
265
|
+
return [
|
|
266
|
+
{
|
|
267
|
+
name: "Generate TypeScript types",
|
|
268
|
+
run: ["php", "artisan", "hybridly:types"],
|
|
269
|
+
pattern: [
|
|
270
|
+
"(app|src)/**/*Data.php",
|
|
271
|
+
"(app|src)/**/Enums/*.php",
|
|
272
|
+
"(app|src)/**/Middlewrare/HandleHybridRequests.php"
|
|
273
|
+
]
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
name: "Generate i18n",
|
|
277
|
+
run: ["php", "artisan", "hybridly:i18n"],
|
|
278
|
+
pattern: "lang/**/*.php"
|
|
279
|
+
},
|
|
280
|
+
...options.run ?? []
|
|
281
|
+
];
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function getLaravelOptions(options, config) {
|
|
285
|
+
return {
|
|
286
|
+
input: `${config.root}/application/main.ts`,
|
|
287
|
+
...options.laravel ?? {}
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function getAutoImportsOptions(options, config) {
|
|
292
|
+
if (options.autoImports === false) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
return {
|
|
296
|
+
vueTemplate: true,
|
|
297
|
+
dts: ".hybridly/auto-imports.d.ts",
|
|
298
|
+
dirs: [
|
|
299
|
+
`${config.root}/utils`,
|
|
300
|
+
`${config.root}/composables`,
|
|
301
|
+
...options.autoImports?.dirs ?? []
|
|
302
|
+
],
|
|
303
|
+
imports: [
|
|
304
|
+
"vue",
|
|
305
|
+
"vue/macros",
|
|
306
|
+
"@vueuse/core",
|
|
307
|
+
"@vueuse/head",
|
|
308
|
+
{
|
|
309
|
+
"hybridly/vue": [
|
|
310
|
+
"useProperty",
|
|
311
|
+
"useTypedProperty",
|
|
312
|
+
"useProperties",
|
|
313
|
+
"useBackForward",
|
|
314
|
+
"useContext",
|
|
315
|
+
"useForm",
|
|
316
|
+
"useDialog",
|
|
317
|
+
"useHistoryState",
|
|
318
|
+
"usePaginator",
|
|
319
|
+
"defineLayout",
|
|
320
|
+
"defineLayoutProperties",
|
|
321
|
+
"registerHook"
|
|
322
|
+
],
|
|
323
|
+
"hybridly": [
|
|
324
|
+
"router",
|
|
325
|
+
"route",
|
|
326
|
+
"current",
|
|
327
|
+
"can"
|
|
328
|
+
]
|
|
329
|
+
}
|
|
330
|
+
],
|
|
331
|
+
...options.autoImports
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function getVueComponentsOptions(options, config) {
|
|
336
|
+
if (options.vueComponents === false) {
|
|
337
|
+
return {};
|
|
338
|
+
}
|
|
339
|
+
const linkName = options.vueComponents?.linkName ?? "RouterLink";
|
|
340
|
+
const hasIcons = options?.icons !== false;
|
|
341
|
+
const customCollections = Array.isArray(options.customIcons) ? options.customIcons : options.customIcons?.collections ?? [];
|
|
342
|
+
const customResolvers = options.customResolvers ? Array.isArray(options.customResolvers) ? options.customResolvers : [options.customResolvers] : [];
|
|
343
|
+
return {
|
|
344
|
+
globs: [
|
|
345
|
+
`${config.root}/components/**/*.vue`,
|
|
346
|
+
...config.domains ? [`${config.root}/${config.domains}/**/components/**/*.vue`] : []
|
|
347
|
+
],
|
|
348
|
+
dts: ".hybridly/components.d.ts",
|
|
349
|
+
resolvers: [
|
|
350
|
+
...hasIcons ? [iconsResolver({ customCollections })] : [],
|
|
351
|
+
{
|
|
352
|
+
type: "component",
|
|
353
|
+
resolve: (name) => {
|
|
354
|
+
if (name === linkName) {
|
|
355
|
+
return {
|
|
356
|
+
from: "hybridly/vue",
|
|
357
|
+
name: "RouterLink",
|
|
358
|
+
as: linkName
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
},
|
|
363
|
+
...customResolvers
|
|
364
|
+
]
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function getIconsOptions(options, config) {
|
|
369
|
+
if (options.icons === false) {
|
|
370
|
+
return {};
|
|
371
|
+
}
|
|
372
|
+
const resolved = Array.isArray(options.customIcons) ? { icons: void 0, collections: options.customIcons } : options.customIcons;
|
|
373
|
+
const customIconDirectoryName = resolved?.icons ?? "icons";
|
|
374
|
+
const customCollections = Object.fromEntries(resolved?.collections?.map((collection) => [
|
|
375
|
+
collection,
|
|
376
|
+
FileSystemIconLoader(`./${config.root}/${customIconDirectoryName}/${collection}`)
|
|
377
|
+
]) ?? []);
|
|
378
|
+
return {
|
|
379
|
+
autoInstall: true,
|
|
380
|
+
customCollections,
|
|
381
|
+
...options.icons
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
function getVueOptions(options) {
|
|
386
|
+
if (options.vue === false) {
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
return {
|
|
390
|
+
template: {
|
|
391
|
+
transformAssetUrls: {
|
|
392
|
+
base: null,
|
|
393
|
+
includeAbsolute: false
|
|
394
|
+
}
|
|
395
|
+
},
|
|
396
|
+
...options.vue
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
function generateTsConfig(options, config) {
|
|
401
|
+
const tsconfig = {
|
|
402
|
+
compilerOptions: {
|
|
403
|
+
target: "esnext",
|
|
404
|
+
module: "esnext",
|
|
405
|
+
moduleResolution: "node",
|
|
406
|
+
strict: true,
|
|
407
|
+
jsx: "preserve",
|
|
408
|
+
sourceMap: true,
|
|
409
|
+
resolveJsonModule: true,
|
|
410
|
+
esModuleInterop: true,
|
|
411
|
+
allowSyntheticDefaultImports: true,
|
|
412
|
+
lib: [
|
|
413
|
+
"esnext",
|
|
414
|
+
"dom"
|
|
415
|
+
],
|
|
416
|
+
types: [
|
|
417
|
+
"vite/client",
|
|
418
|
+
"hybridly/client",
|
|
419
|
+
...options.icons !== false ? ["unplugin-icons/types/vue"] : []
|
|
420
|
+
],
|
|
421
|
+
baseUrl: "..",
|
|
422
|
+
paths: {
|
|
423
|
+
"#/*": [
|
|
424
|
+
".hybridly/*"
|
|
425
|
+
],
|
|
426
|
+
"~/*": [
|
|
427
|
+
"./*"
|
|
428
|
+
],
|
|
429
|
+
"@/*": [
|
|
430
|
+
`./${config.root}/*`
|
|
431
|
+
]
|
|
432
|
+
}
|
|
433
|
+
},
|
|
434
|
+
include: [
|
|
435
|
+
`../${config.root}/**/*`,
|
|
436
|
+
"./*"
|
|
437
|
+
],
|
|
438
|
+
exclude: [
|
|
439
|
+
"../public/**/*",
|
|
440
|
+
"../node_modules",
|
|
441
|
+
"../vendor"
|
|
442
|
+
]
|
|
443
|
+
};
|
|
444
|
+
write(JSON.stringify(tsconfig, null, 2), "tsconfig.json");
|
|
445
|
+
}
|
|
446
|
+
function generateVueShims(options) {
|
|
447
|
+
if (options.shims === false) {
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
const shims = `declare module '*.vue' {
|
|
451
|
+
import type { DefineComponent } from 'vue'
|
|
452
|
+
const component: DefineComponent<{}, {}, any>
|
|
453
|
+
export default component
|
|
454
|
+
}`;
|
|
455
|
+
write(shims, "vue-shims.d.ts");
|
|
456
|
+
}
|
|
457
|
+
function write(data, filename) {
|
|
458
|
+
const hybridlyPath = path.resolve(process.cwd(), ".hybridly");
|
|
459
|
+
if (!fs.existsSync(hybridlyPath)) {
|
|
460
|
+
fs.mkdirSync(hybridlyPath);
|
|
461
|
+
}
|
|
462
|
+
fs.writeFileSync(path.resolve(hybridlyPath, filename), data, {
|
|
463
|
+
encoding: "utf-8"
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
async function plugin(options = {}) {
|
|
468
|
+
const config = await loadHybridlyConfig();
|
|
469
|
+
generateTsConfig(options, config);
|
|
470
|
+
generateVueShims(options);
|
|
168
471
|
return [
|
|
169
|
-
options
|
|
170
|
-
options
|
|
472
|
+
initialize(options, config),
|
|
473
|
+
layout(options, config),
|
|
474
|
+
router(options),
|
|
475
|
+
options.laravel !== false && laravel(getLaravelOptions(options, config)),
|
|
476
|
+
options.run !== false && run(getRunOptions(options)),
|
|
477
|
+
options.vueComponents !== false && vueComponents(getVueComponentsOptions(options, config)),
|
|
478
|
+
options.autoImports !== false && autoimport(getAutoImportsOptions(options, config)),
|
|
479
|
+
options.icons !== false && icons(getIconsOptions(options, config)),
|
|
480
|
+
options.vue !== false && vue(getVueOptions(options))
|
|
171
481
|
];
|
|
172
482
|
}
|
|
173
483
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hybridly/vite",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
|
+
"description": "Vite plugin for Hybridly",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"hybridly",
|
|
7
7
|
"inertiajs",
|
|
@@ -36,16 +36,23 @@
|
|
|
36
36
|
"module": "dist/index.mjs",
|
|
37
37
|
"types": "dist/index.d.ts",
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"vue": "^3.2.
|
|
39
|
+
"vue": "^3.2.45"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@
|
|
43
|
-
"
|
|
42
|
+
"@iconify/json": "^2.2.24",
|
|
43
|
+
"@vitejs/plugin-vue": "^4.0.0",
|
|
44
|
+
"laravel-vite-plugin": "^0.7.4",
|
|
45
|
+
"throttle-debounce": "^5.0.0",
|
|
46
|
+
"unplugin-auto-import": "^0.14.3",
|
|
47
|
+
"unplugin-icons": "^0.15.3",
|
|
48
|
+
"unplugin-vue-components": "^0.24.0",
|
|
49
|
+
"vite-plugin-run": "^0.3.2",
|
|
50
|
+
"@hybridly/core": "0.1.0-alpha.0"
|
|
44
51
|
},
|
|
45
52
|
"devDependencies": {
|
|
46
|
-
"rollup": "^
|
|
47
|
-
"vite": "^
|
|
48
|
-
"vue": "^3.2.
|
|
53
|
+
"rollup": "^3.17.1",
|
|
54
|
+
"vite": "^4.1.2",
|
|
55
|
+
"vue": "^3.2.47"
|
|
49
56
|
},
|
|
50
57
|
"scripts": {
|
|
51
58
|
"build": "unbuild",
|