@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 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 ROUTER_PLUGIN_NAME = "vite:hybridly:router";
20
- const ROUTER_HMR_UPDATE_ROUTE = "hybridly:routes:update";
21
- const ROUTER_VIRTUAL_MODULE_ID = "virtual:hybridly/router";
22
- const RESOLVED_ROUTER_VIRTUAL_MODULE_ID = `\0${ROUTER_VIRTUAL_MODULE_ID}`;
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(ROUTER_PLUGIN_NAME),
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(?: *= *['"](?:(?:(\w+):)?(\w+))['"] *)?>/;
104
+ const TEMPLATE_LAYOUT_REGEX = /<template +layout(?: *= *['"]((?:[\w\/\-_,:](?:,\ )?)+)['"] *)?>/;
31
105
  const TYPESCRIPT_REGEX = /lang=['"]ts['"]/;
32
- const layout = (options = {}) => {
33
- const base = options?.directory ? options?.directory : path__default.resolve(process.cwd(), "resources", "views", "layouts");
34
- const layoutPath = options?.resolve ? options.resolve : (layoutName) => vite.normalizePath(path__default.resolve(base, `${layoutName ?? "default"}.vue`)).replaceAll("\\", "/");
35
- debug.layout("Registered layout path:", base);
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 (!TEMPLATE_LAYOUT_REGEX.test(code)) {
123
+ if (!templateRegExp.test(code)) {
40
124
  return;
41
125
  }
42
- return code.replace(TEMPLATE_LAYOUT_REGEX, (_, __, layoutName) => {
126
+ return code.replace(templateRegExp, (_, layoutName) => {
43
127
  const isTypeScript = TYPESCRIPT_REGEX.test(code);
44
- const importPath = layoutPath(layoutName);
45
- debug.layout(`Resolved layout "${layoutName}":`, {
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
- importPath
137
+ layouts,
138
+ imports
48
139
  });
49
140
  return `
50
141
  <script${isTypeScript ? ' lang="ts"' : ""}>
51
- import layout from '${importPath}'
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 getClientCode(routes) {
152
+ function getRouterClientCode(routing) {
62
153
  return `
63
154
  if (typeof window !== 'undefined') {
64
155
  window.hybridly = {
65
- routes: ${JSON.stringify(routes)}
156
+ routing: ${JSON.stringify(routing)}
66
157
  }
67
-
158
+
68
159
  if (import.meta.hot) {
69
- import.meta.hot.on('${ROUTER_HMR_UPDATE_ROUTE}', (routes) => {
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 fetchRoutesFromArtisan(options) {
81
- const php = options.php ?? "php";
82
- const result = await shell(`${php} artisan hybridly:routes`);
83
- const routes = JSON.parse(result.stdout);
84
- write(options, routes);
85
- return routes;
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, collection) {
90
- collection ?? (collection = await fetchRoutesFromArtisan(options));
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 route collection:", collection);
95
- const target = path__default.resolve(options.dts ?? "resources/types/routes.d.ts");
96
- const routes = Object.fromEntries(Object.entries(collection.routes).map(([key, route]) => {
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__", collection?.url ?? "").replace("__ROUTES__", JSON.stringify(routes).replaceAll('"__key_placeholder__"', "any"));
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/vue' {
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: "resources/types/routes.d.ts",
222
+ dts: ".hybridly/routes.d.ts",
128
223
  watch: [
129
224
  /routes\/.*\.php/
130
225
  ],
131
226
  ...options
132
227
  };
133
- let previousRoutes;
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: ROUTER_PLUGIN_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
- const routes = await fetchRoutesFromArtisan(resolved);
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 === ROUTER_VIRTUAL_MODULE_ID) {
157
- return RESOLVED_ROUTER_VIRTUAL_MODULE_ID;
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 === RESOLVED_ROUTER_VIRTUAL_MODULE_ID) {
162
- const routes = await fetchRoutesFromArtisan(resolved);
163
- return getClientCode(routes);
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 plugin(options = {}) {
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.layout !== false && layout(options.layout),
180
- options.router !== false && router(options.router)
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 { Plugin, PluginOption } from 'vite';
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
- interface Options {
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?: false | LayoutOptions;
34
+ layout?: LayoutOptions;
6
35
  /** Options for the router plugin. */
7
- router?: false | RouterOptions;
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
- /** The directory in which layouts are stored. */
11
- directory?: string;
12
- /** Function that resolves the layout path given its name. */
13
- resolve?: (layout: string) => string;
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
- /** Registers `unplugin-vue-define-options`. */
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 ROUTER_PLUGIN_NAME = "vite:hybridly:router";
10
- const ROUTER_HMR_UPDATE_ROUTE = "hybridly:routes:update";
11
- const ROUTER_VIRTUAL_MODULE_ID = "virtual:hybridly/router";
12
- const RESOLVED_ROUTER_VIRTUAL_MODULE_ID = `\0${ROUTER_VIRTUAL_MODULE_ID}`;
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(ROUTER_PLUGIN_NAME),
83
+ router: makeDebugger(ROUTING_PLUGIN_NAME),
17
84
  layout: makeDebugger(LAYOUT_PLUGIN_NAME)
18
85
  };
19
86
 
20
- const TEMPLATE_LAYOUT_REGEX = /<template +layout(?: *= *['"](?:(?:(\w+):)?(\w+))['"] *)?>/;
87
+ const TEMPLATE_LAYOUT_REGEX = /<template +layout(?: *= *['"]((?:[\w\/\-_,:](?:,\ )?)+)['"] *)?>/;
21
88
  const TYPESCRIPT_REGEX = /lang=['"]ts['"]/;
22
- const layout = (options = {}) => {
23
- const base = options?.directory ? options?.directory : path.resolve(process.cwd(), "resources", "views", "layouts");
24
- const layoutPath = options?.resolve ? options.resolve : (layoutName) => normalizePath(path.resolve(base, `${layoutName ?? "default"}.vue`)).replaceAll("\\", "/");
25
- debug.layout("Registered layout path:", base);
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 (!TEMPLATE_LAYOUT_REGEX.test(code)) {
106
+ if (!templateRegExp.test(code)) {
30
107
  return;
31
108
  }
32
- return code.replace(TEMPLATE_LAYOUT_REGEX, (_, __, layoutName) => {
109
+ return code.replace(templateRegExp, (_, layoutName) => {
33
110
  const isTypeScript = TYPESCRIPT_REGEX.test(code);
34
- const importPath = layoutPath(layoutName);
35
- debug.layout(`Resolved layout "${layoutName}":`, {
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
- importPath
120
+ layouts,
121
+ imports
38
122
  });
39
123
  return `
40
124
  <script${isTypeScript ? ' lang="ts"' : ""}>
41
- import layout from '${importPath}'
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 getClientCode(routes) {
135
+ function getRouterClientCode(routing) {
52
136
  return `
53
137
  if (typeof window !== 'undefined') {
54
138
  window.hybridly = {
55
- routes: ${JSON.stringify(routes)}
139
+ routing: ${JSON.stringify(routing)}
56
140
  }
57
-
141
+
58
142
  if (import.meta.hot) {
59
- import.meta.hot.on('${ROUTER_HMR_UPDATE_ROUTE}', (routes) => {
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 fetchRoutesFromArtisan(options) {
71
- const php = options.php ?? "php";
72
- const result = await shell(`${php} artisan hybridly:routes`);
73
- const routes = JSON.parse(result.stdout);
74
- write(options, routes);
75
- return routes;
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, collection) {
80
- collection ?? (collection = await fetchRoutesFromArtisan(options));
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 route collection:", collection);
85
- const target = path.resolve(options.dts ?? "resources/types/routes.d.ts");
86
- const routes = Object.fromEntries(Object.entries(collection.routes).map(([key, route]) => {
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__", collection?.url ?? "").replace("__ROUTES__", JSON.stringify(routes).replaceAll('"__key_placeholder__"', "any"));
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/vue' {
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: "resources/types/routes.d.ts",
205
+ dts: ".hybridly/routes.d.ts",
118
206
  watch: [
119
207
  /routes\/.*\.php/
120
208
  ],
121
209
  ...options
122
210
  };
123
- let previousRoutes;
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: ROUTER_PLUGIN_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
- const routes = await fetchRoutesFromArtisan(resolved);
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 === ROUTER_VIRTUAL_MODULE_ID) {
147
- return RESOLVED_ROUTER_VIRTUAL_MODULE_ID;
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 === RESOLVED_ROUTER_VIRTUAL_MODULE_ID) {
152
- const routes = await fetchRoutesFromArtisan(resolved);
153
- return getClientCode(routes);
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 plugin(options = {}) {
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.layout !== false && layout(options.layout),
170
- options.router !== false && router(options.router)
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.1-dev.3",
4
- "description": "A solution to develop server-driven, client-rendered applications",
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.33"
39
+ "vue": "^3.2.45"
40
40
  },
41
41
  "dependencies": {
42
- "@hybridly/core": "0.0.1-dev.3",
43
- "throttle-debounce": "^5.0.0"
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": "^2.79.1",
47
- "vite": "^3.1.7",
48
- "vue": "^3.2.40"
53
+ "rollup": "^3.17.1",
54
+ "vite": "^4.1.2",
55
+ "vue": "^3.2.47"
49
56
  },
50
57
  "scripts": {
51
58
  "build": "unbuild",