create-jwn-js 1.2.1 → 1.2.3

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.
Files changed (27) hide show
  1. package/package.json +1 -1
  2. package/template-vite-node-mts/src/scripts/test.setup.mts +2 -2
  3. package/template-vite-node-mts/vite.config.mts +1 -1
  4. package/template-vite-vue3-mts/src/scripts/test.setup.mts +9 -6
  5. package/template-vite-vue3-mts/src/scripts/vitest.global.setup.mts +3 -3
  6. package/template-vite-vue3-mts/{vite.config.ts → vite.config.mts} +1 -1
  7. package/template-vite-vue3-pinia-mts/dist/client/.vite/manifest.json +38 -0
  8. package/template-vite-vue3-pinia-mts/dist/client/.vite/ssr-manifest.json +1169 -69
  9. package/template-vite-vue3-pinia-mts/dist/client/assets/index-B40M1W6I.css +1 -0
  10. package/template-vite-vue3-pinia-mts/dist/client/assets/index-CIJvTamH.js +249 -0
  11. package/template-vite-vue3-pinia-mts/dist/client/assets/primeicons-C6QP2o4f.woff2 +0 -0
  12. package/template-vite-vue3-pinia-mts/dist/client/assets/primeicons-DMOk5skT.eot +0 -0
  13. package/template-vite-vue3-pinia-mts/dist/client/assets/primeicons-Dr5RGzOO.svg +345 -0
  14. package/template-vite-vue3-pinia-mts/dist/client/assets/primeicons-MpK4pl85.ttf +0 -0
  15. package/template-vite-vue3-pinia-mts/dist/client/assets/primeicons-WjwUDZjB.woff +0 -0
  16. package/template-vite-vue3-pinia-mts/dist/client/robots.txt +2 -0
  17. package/template-vite-vue3-pinia-mts/dist/server/entry-server.mjs +287 -378
  18. package/template-vite-vue3-pinia-mts/dist/server/package.json +2 -1
  19. package/template-vite-vue3-pinia-mts/dist/server/robots.txt +2 -0
  20. package/template-vite-vue3-pinia-mts/package.json +4 -4
  21. package/template-vite-vue3-pinia-mts/src/frontend/entry-options.mts +3 -3
  22. package/template-vite-vue3-pinia-mts/src/helpers/parseLang.mts +2 -2
  23. package/template-vite-vue3-pinia-mts/src/scripts/vitest.global.setup.mts +1 -1
  24. package/template-vite-vue3-pinia-mts/{vite.config.ts → vite.config.mts} +1 -1
  25. package/template-vite-vue3-pinia-mts/yarn.lock +260 -323
  26. package/template-vite-vue3-pinia-mts/dist/client/assets/index-B8XEaJMM.css +0 -1
  27. package/template-vite-vue3-pinia-mts/dist/client/assets/index-DJNddzdM.js +0 -224
@@ -3,20 +3,20 @@ import { renderToString } from "@vue/server-renderer";
3
3
  import { renderHeadToString, createHead, useHead } from "@vueuse/head";
4
4
  import { parse } from "node-html-parser";
5
5
  import { createRouter as createRouter$1, createWebHistory, createMemoryHistory } from "vue-router";
6
- import { mapMutations, mapState, createStore as createStore$1, useStore } from "vuex";
7
- import { ssrRenderAttrs, ssrInterpolate, ssrRenderComponent } from "vue/server-renderer";
8
- import { isBrowser } from "easy-ash";
9
- import fetch from "cross-fetch";
6
+ import { defineStore, storeToRefs, createPinia } from "pinia";
7
+ import { isBrowser, omit } from "easy-ash";
10
8
  import { ApiError } from "@jwn-js/common/ApiError.mjs";
9
+ import { ssrRenderAttrs, ssrInterpolate, ssrRenderComponent } from "vue/server-renderer";
11
10
  import { createPrefetch } from "@vuemod/prefetch";
12
11
  import { amitt } from "amitt";
13
12
  import Multilang from "@jwn-js/plugins/Multilang/index.js";
14
13
  import PrimeVue from "primevue/config";
14
+ import Aura from "@primevue/themes/aura";
15
15
  import ConfirmationService from "primevue/confirmationservice";
16
- import { Memcached, helpers, Server, Web, Ssr } from "@jwn-js/common";
16
+ import ToastService from "primevue/toastservice";
17
+ import { helpers, Server, Web, Ssr } from "@jwn-js/common";
17
18
  import margv from "margv";
18
19
  import { Query } from "buildmsql";
19
- import memjs from "memjs";
20
20
  import JSON5 from "json5";
21
21
  import path from "node:path";
22
22
  import fs from "node:fs";
@@ -52,8 +52,7 @@ const createUrl = (url) => {
52
52
  return new URL(url);
53
53
  };
54
54
  const fileType = (file) => {
55
- var _a;
56
- const ext = ((_a = file.split(".").pop()) == null ? void 0 : _a.toLowerCase()) || "";
55
+ const ext = file.split(".").pop()?.toLowerCase() || "";
57
56
  if (ext === "js") {
58
57
  return "script";
59
58
  } else if (ext === "css") {
@@ -65,11 +64,11 @@ const fileType = (file) => {
65
64
  }
66
65
  return "";
67
66
  };
68
- const findDependencies = (modules, manifest, shouldPreload, shouldPrefetch) => {
67
+ const findDependencies = (modules, ssrManifest, shouldPreload, shouldPrefetch) => {
69
68
  const preload = /* @__PURE__ */ new Set();
70
69
  const prefetch = /* @__PURE__ */ new Set();
71
70
  for (const id of modules || []) {
72
- for (const file of manifest[id] || []) {
71
+ for (const file of ssrManifest[id] || []) {
73
72
  const asType = fileType(file);
74
73
  if (!shouldPreload && asType !== "script" && asType !== "style") {
75
74
  continue;
@@ -80,8 +79,8 @@ const findDependencies = (modules, manifest, shouldPreload, shouldPrefetch) => {
80
79
  preload.add(file);
81
80
  }
82
81
  }
83
- for (const id of Object.keys(manifest)) {
84
- for (const file of manifest[id]) {
82
+ for (const id of Object.keys(ssrManifest)) {
83
+ for (const file of ssrManifest[id]) {
85
84
  if (!preload.has(file)) {
86
85
  const asType = fileType(file);
87
86
  if (!shouldPrefetch) {
@@ -97,22 +96,21 @@ const findDependencies = (modules, manifest, shouldPreload, shouldPrefetch) => {
97
96
  return { preload: [...preload], prefetch: [...prefetch] };
98
97
  };
99
98
  const renderPreloadLinks = (files) => {
100
- var _a;
101
- const link = [];
99
+ const links = [];
102
100
  for (const file of files || []) {
103
101
  const asType = fileType(file);
104
- const ext = ((_a = file.split(".").pop()) == null ? void 0 : _a.toLowerCase()) || "";
102
+ const ext = file.split(".").pop()?.toLowerCase() || "";
105
103
  if (asType === "script") {
106
- link.push(`<link rel="modulepreload" crossorigin href="${file}">`);
104
+ links.push(`<link rel="modulepreload" crossorigin href="${file}">`);
107
105
  } else if (asType === "style") {
108
- link.push(`<link rel="stylesheet" href="${file}">`);
106
+ links.push(`<link rel="stylesheet" href="${file}">`);
109
107
  } else if (asType === "font") {
110
- link.push(`<link rel="stylesheet" href="${file}" type="font/${ext}" crossorigin>`);
108
+ links.push(`<link rel="stylesheet" href="${file}" type="font/${ext}" crossorigin>`);
111
109
  } else {
112
- link.push(`<link rel="stylesheet" href="${file}">`);
110
+ links.push(`<link rel="stylesheet" href="${file}">`);
113
111
  }
114
112
  }
115
- return link;
113
+ return links;
116
114
  };
117
115
  const renderPrefetchLinks = (files) => {
118
116
  const link = [];
@@ -121,6 +119,30 @@ const renderPrefetchLinks = (files) => {
121
119
  }
122
120
  return link;
123
121
  };
122
+ const findIndexHtmlDependencies = (manifest) => {
123
+ const output = [];
124
+ const indexHtmlDependencies = manifest["index.html"] || {};
125
+ indexHtmlDependencies.file && output.push(indexHtmlDependencies.file);
126
+ indexHtmlDependencies.css && indexHtmlDependencies.css.length && output.push(...indexHtmlDependencies.css);
127
+ output.forEach((file, index) => {
128
+ if (!/^\//.test(file)) {
129
+ output[index] = `/${file}`;
130
+ }
131
+ });
132
+ return output;
133
+ };
134
+ const renderPreloadLinksIndexHtml = (files) => {
135
+ const links = [];
136
+ for (const file of files || []) {
137
+ const asType = fileType(file);
138
+ if (asType === "script") {
139
+ links.push(`<link rel="modulepreload" crossorigin href="${file}">`);
140
+ } else if (asType === "style") {
141
+ links.push(`<link rel="preload" href="${file}" as="style">`);
142
+ }
143
+ }
144
+ return links;
145
+ };
124
146
  const teleportsInject = (body, teleports = {}) => {
125
147
  const teleportsKeys = Object.keys(teleports);
126
148
  if (teleportsKeys.length) {
@@ -140,7 +162,7 @@ const teleportsInject = (body, teleports = {}) => {
140
162
  return body;
141
163
  };
142
164
  const createViteSsrVue = (App2, options2 = {}) => {
143
- return async (url, { manifest, ...extra } = {}) => {
165
+ return async (url, { manifest, ssrManifest, ...extra } = {}) => {
144
166
  const app = createSSRApp(App2, options2.rootProps);
145
167
  const serializer = options2.serializer || serialize;
146
168
  const ssrContext = {
@@ -149,7 +171,8 @@ const createViteSsrVue = (App2, options2 = {}) => {
149
171
  initialState: {},
150
172
  ...extra
151
173
  };
152
- const { head, router, store, inserts, context } = options2.created && await options2.created({
174
+ ssrManifest = ssrManifest || manifest;
175
+ const { head, router, store, inserts, context, pinia } = options2.created && await options2.created({
153
176
  app,
154
177
  ...ssrContext
155
178
  }) || {};
@@ -161,20 +184,29 @@ const createViteSsrVue = (App2, options2 = {}) => {
161
184
  app,
162
185
  router,
163
186
  store,
187
+ pinia,
164
188
  ...ssrContext
165
189
  });
166
190
  if (store) {
167
191
  ssrContext.initialState.state = store.state;
168
192
  }
169
- const body = (inserts == null ? void 0 : inserts.body) || await renderToString(app, Object.assign(ssrContext, context || {}));
170
- let headTags = (inserts == null ? void 0 : inserts.headTags) || "", htmlAttrs = (inserts == null ? void 0 : inserts.htmlAttrs) || "", bodyAttrs = (inserts == null ? void 0 : inserts.bodyAttrs) || "", dependencies = (inserts == null ? void 0 : inserts.dependencies) || [];
193
+ if (pinia) {
194
+ ssrContext.initialState.pinia = pinia.state.value;
195
+ }
196
+ const body = inserts?.body || await renderToString(app, Object.assign(ssrContext, context || {}));
197
+ let headTags = inserts?.headTags || "", htmlAttrs = inserts?.htmlAttrs || "", bodyAttrs = inserts?.bodyAttrs || "", dependencies = inserts?.dependencies || [];
171
198
  if (head) {
172
199
  ({ headTags, htmlAttrs, bodyAttrs } = await renderHeadToString(head));
173
200
  }
174
- if (manifest) {
201
+ if (options2.preloadIndexHtml && manifest) {
202
+ const preloadIndexHtmlFiles = findIndexHtmlDependencies(manifest);
203
+ const links = renderPreloadLinksIndexHtml(preloadIndexHtmlFiles);
204
+ headTags += links.length ? "\n" + links.join("\n") : "";
205
+ }
206
+ if (ssrManifest) {
175
207
  const { preload, prefetch } = findDependencies(
176
208
  ssrContext.modules,
177
- manifest,
209
+ ssrManifest,
178
210
  options2.shouldPreload,
179
211
  options2.shouldPrefetch
180
212
  );
@@ -192,10 +224,11 @@ const createViteSsrVue = (App2, options2 = {}) => {
192
224
  app,
193
225
  router,
194
226
  store,
227
+ pinia,
195
228
  ...ssrContext
196
229
  });
197
230
  const initialState = await serializer(ssrContext.initialState || {});
198
- const teleports = (ssrContext == null ? void 0 : ssrContext.teleports) || {};
231
+ const teleports = ssrContext?.teleports || {};
199
232
  return {
200
233
  html: teleportsInject(`<!DOCTYPE html>
201
234
  <html${htmlAttrs}>
@@ -210,8 +243,8 @@ const createViteSsrVue = (App2, options2 = {}) => {
210
243
  }
211
244
 
212
245
  /*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4Lmh0bWwlM0ZodG1sLXByb3h5JmlubGluZS1jc3MmaW5kZXg9MC5jc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtZQUNZO2dCQUNJLFdBQVc7WUFDZiIsImZpbGUiOiJpbmRleC5odG1sP2h0bWwtcHJveHkmaW5saW5lLWNzcyZpbmRleD0wLmNzcyIsInNvdXJjZXNDb250ZW50IjpbIlxuICAgICAgICAgICAgLmljb25pbmcge1xuICAgICAgICAgICAgICAgIHdpZHRoOiAyMHB4O1xuICAgICAgICAgICAgfVxuICAgICAgICAiXX0= */</style>
213
- <script type="module" crossorigin src="/assets/index-DJNddzdM.js"><\/script>
214
- <link rel="stylesheet" crossorigin href="/assets/index-B8XEaJMM.css">
246
+ <script type="module" crossorigin src="/assets/index-CIJvTamH.js"><\/script>
247
+ <link rel="stylesheet" crossorigin href="/assets/index-B40M1W6I.css">
215
248
  ${headTags}
216
249
  </head>
217
250
  <body${bodyAttrs}>
@@ -229,23 +262,155 @@ const createViteSsrVue = (App2, options2 = {}) => {
229
262
  };
230
263
  };
231
264
  };
232
- const _export_sfc = (sfc, props) => {
233
- const target = sfc.__vccOpts || sfc;
234
- for (const [key, val] of props) {
235
- target[key] = val;
236
- }
237
- return target;
265
+ const langLink = (url, lang = "ru", defaultLang2 = "ru") => {
266
+ url = (url || "").replace(/\/(ru|ua|en)(\/|$)/, "/");
267
+ const result = (lang === defaultLang2 ? "" : "/" + lang) + url;
268
+ return result === "/" ? result : result.replace(/\/$/, "");
238
269
  };
270
+ const useBaseStore = defineStore("baseStore", {
271
+ state: () => {
272
+ return {
273
+ context: {},
274
+ // Ssr context
275
+ page: {
276
+ h1: "",
277
+ title: "",
278
+ htmlAttrs: {}
279
+ },
280
+ way: [],
281
+ // breadcrumbs
282
+ microdata: "",
283
+ // Микроразметка
284
+ toLang: "ua",
285
+ // Before route - set to new value
286
+ lang: "ua",
287
+ // After route set to new value
288
+ loading: false
289
+ // is data loading
290
+ };
291
+ },
292
+ getters: {
293
+ getBaseUrl() {
294
+ return `${this.context.protocol}://${this.context.hostname}`;
295
+ }
296
+ },
297
+ actions: {
298
+ mergeContext(context) {
299
+ Object.assign(this.context, context);
300
+ },
301
+ addToastNotify(params) {
302
+ this.$emitter.emit("web-notification", params);
303
+ },
304
+ langLink(path2) {
305
+ return langLink(path2, this.lang);
306
+ },
307
+ async fetch(input, init = {}, opts = {}) {
308
+ const url = new URL(`${this.getBaseUrl}${input}`);
309
+ const token = init?.token || "";
310
+ const search = url.searchParams;
311
+ search.set("lang", search.get("lang") || this.lang);
312
+ const ssrHeaders = this.context.headers || {};
313
+ if (isBrowser()) {
314
+ [
315
+ "host",
316
+ "connection",
317
+ "user-agent",
318
+ "referer",
319
+ "accept-encoding",
320
+ "cookie",
321
+ "sec-ch-ua",
322
+ "sec-ch-ua-mobile",
323
+ "sec-fetch-site",
324
+ "sec-fetch-mode",
325
+ "sec-fetch-dest",
326
+ "sec-fetch-user",
327
+ "sec-ch-ua-platform"
328
+ ].map((key) => delete ssrHeaders[key]);
329
+ } else {
330
+ ssrHeaders["x-forwarded-for"] = this.context.ip;
331
+ }
332
+ init.headers = init.headers || {};
333
+ init.headers = Object.assign(
334
+ {},
335
+ ssrHeaders,
336
+ init?.body instanceof FormData ? {} : { "content-type": "application/json" },
337
+ token ? { "authorization": "Bearer " + token } : {},
338
+ init.headers
339
+ );
340
+ init.method = init.method || "GET";
341
+ if (["get", "head"].includes(init.method.toLowerCase())) {
342
+ url.search = new URLSearchParams(init?.data || url.search || {}).toString();
343
+ } else {
344
+ init.body = init?.body || JSON.stringify(init?.data || {});
345
+ }
346
+ try {
347
+ this.loading = true;
348
+ const response = await fetch(url, init);
349
+ if (!response.ok) {
350
+ const headers = {};
351
+ response.headers.forEach((value, key) => headers[key] = value);
352
+ const text = await response.text();
353
+ let json = {};
354
+ try {
355
+ json = JSON.parse(text);
356
+ } catch (e) {
357
+ }
358
+ throw new ApiError({
359
+ code: json.code || 0,
360
+ statusCode: response.status,
361
+ message: "Web api request error",
362
+ headers,
363
+ data: { json, text }
364
+ });
365
+ }
366
+ return response;
367
+ } catch (e) {
368
+ if (e instanceof TypeError) {
369
+ if (isBrowser()) {
370
+ this.addToastNotify({
371
+ severity: "error",
372
+ detail: "Check your internet connection. No contact)"
373
+ });
374
+ }
375
+ }
376
+ if (e instanceof ApiError) {
377
+ const statusCode = e.getStatusCode();
378
+ const error = e.getData()?.json?.error || e.getData().text || e.getMessage();
379
+ if (init.method.toLowerCase() === "get") {
380
+ if (statusCode === 410) {
381
+ const location = e.getHeaders().location;
382
+ if (location) {
383
+ await this.$redirect(location);
384
+ }
385
+ }
386
+ }
387
+ if (statusCode >= 400 && !opts.suppressError && statusCode !== 410) {
388
+ isBrowser() ? this.addToastNotify({ severity: "error", summary: "Request error", detail: error }) : this.$redirect(langLink(`/${statusCode}?error=${encodeURIComponent(error)}`, this.lang));
389
+ }
390
+ }
391
+ throw e;
392
+ } finally {
393
+ this.loading = false;
394
+ }
395
+ }
396
+ }
397
+ });
239
398
  const _sfc_main$2 = defineComponent({
240
399
  name: "Error",
241
400
  async prefetch({ store, isClient }, to, from) {
242
- store.commit("SET_PAGE", {
401
+ const baseStore = useBaseStore(store);
402
+ baseStore.page = {
243
403
  title: "Error page. Something went wrong",
244
404
  htmlAttrs: {
245
405
  lang: "en"
246
- }
247
- });
248
- store.commit("MERGE_CONTEXT", { statusCode: 404 });
406
+ },
407
+ h1: ""
408
+ };
409
+ baseStore.mergeContext({ statusCode: 404 });
410
+ },
411
+ setup() {
412
+ const baseStore = useBaseStore();
413
+ return { baseStore };
249
414
  },
250
415
  props: {
251
416
  code: {
@@ -254,14 +419,19 @@ const _sfc_main$2 = defineComponent({
254
419
  }
255
420
  },
256
421
  created() {
257
- this.mergeContext({ statusCode: this.code });
422
+ this.baseStore.mergeContext({ statusCode: parseInt(this.code) });
258
423
  },
259
- methods: {
260
- ...mapMutations({
261
- mergeContext: "MERGE_CONTEXT"
262
- })
424
+ mounted() {
425
+ console.log("Component mounted.");
263
426
  }
264
427
  });
428
+ const _export_sfc = (sfc, props) => {
429
+ const target = sfc.__vccOpts || sfc;
430
+ for (const [key, val] of props) {
431
+ target[key] = val;
432
+ }
433
+ return target;
434
+ };
265
435
  function _sfc_ssrRender$2(_ctx, _push, _parent, _attrs, $props, $setup, $data, $options) {
266
436
  const _component_RouterLink = resolveComponent("RouterLink");
267
437
  _push(`<div${ssrRenderAttrs(mergeProps({ class: "error-page" }, _attrs))}><div class="code">${ssrInterpolate(_ctx.code)}</div><div class="content">Oops. Something went wrong</div>`);
@@ -290,30 +460,37 @@ _sfc_main$2.setup = (props, ctx) => {
290
460
  (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("src/frontend/views/Error/Error.vue");
291
461
  return _sfc_setup$2 ? _sfc_setup$2(props, ctx) : void 0;
292
462
  };
293
- const Error$1 = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["ssrRender", _sfc_ssrRender$2], ["__file", "/Volumes/MacMiniAPFS/projects/packages/vite-node-template/template-vite-vue3-mts/src/frontend/views/Error/Error.vue"]]);
294
- const customerPrefetch = (options2, fn) => {
463
+ const Error$1 = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["ssrRender", _sfc_ssrRender$2], ["__file", "/Volumes/MacMiniAPFS/projects/packages/vite-node-template/template-vite-vue3-pinia-mts/src/frontend/views/Error/Error.vue"]]);
464
+ const customerPrefetchPinia = (options2, fn) => {
295
465
  return async ({ store, isFetch }, to, from) => {
296
- var _a, _b, _c;
297
466
  if (isFetch) {
298
- const { body } = await store.dispatch("fetch", [{
299
- lang: store.state.toLang,
300
- route: to.fullPath,
301
- ...to.query || {},
302
- ...options2 || {}
303
- }, {
304
- ...((_b = (_a = store.state) == null ? void 0 : _a.Customer) == null ? void 0 : _b.jwt) ? { mergeHeaders: { "authorization": `Bearer ${store.state.Customer.jwt}` } } : {}
305
- }]);
306
- store.commit("SET_PAGE", ((_c = body.data) == null ? void 0 : _c.page) || {});
307
- store.commit("MERGE_CONTEXT", { memcache: options2.memcache });
467
+ const baseStore = useBaseStore(store);
468
+ const res = await baseStore.fetch("/web", {
469
+ data: {
470
+ lang: baseStore.toLang,
471
+ route: to.fullPath,
472
+ ...to.query || {},
473
+ ...options2 || {}
474
+ }
475
+ });
476
+ const body = await res.json();
477
+ const page = body.data?.page;
478
+ baseStore.page = page ? omit(page, ["way"]) : {};
479
+ baseStore.way = page?.way || [];
480
+ baseStore.microdata = body.data?.microdata || "";
481
+ baseStore.mergeContext({ memcache: options2.memcache || null });
308
482
  }
309
483
  };
310
484
  };
311
485
  const _sfc_main$1 = defineComponent({
312
486
  name: "Index",
313
- components: {},
314
- prefetch: customerPrefetch({ controller: "Index" }),
315
- computed: {
316
- ...mapState(["page", "context"])
487
+ prefetch: customerPrefetchPinia({ controller: "Index" }),
488
+ setup() {
489
+ const baseStore = useBaseStore();
490
+ const { page } = storeToRefs(baseStore);
491
+ return {
492
+ page
493
+ };
317
494
  }
318
495
  });
319
496
  function _sfc_ssrRender$1(_ctx, _push, _parent, _attrs, $props, $setup, $data, $options) {
@@ -325,7 +502,7 @@ _sfc_main$1.setup = (props, ctx) => {
325
502
  (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("src/frontend/views/Index/Index.vue");
326
503
  return _sfc_setup$1 ? _sfc_setup$1(props, ctx) : void 0;
327
504
  };
328
- const Index = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["ssrRender", _sfc_ssrRender$1], ["__file", "/Volumes/MacMiniAPFS/projects/packages/vite-node-template/template-vite-vue3-mts/src/frontend/views/Index/Index.vue"]]);
505
+ const Index = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["ssrRender", _sfc_ssrRender$1], ["__file", "/Volumes/MacMiniAPFS/projects/packages/vite-node-template/template-vite-vue3-pinia-mts/src/frontend/views/Index/Index.vue"]]);
329
506
  const createRouter = (opt) => createRouter$1({
330
507
  history: opt.isClient ? createWebHistory() : createMemoryHistory(),
331
508
  routes: [
@@ -347,284 +524,15 @@ const createRouter = (opt) => createRouter$1({
347
524
  }
348
525
  ],
349
526
  async scrollBehavior(to, from, savedPosition) {
350
- var _a;
351
- if ((_a = to.query) == null ? void 0 : _a.el) {
527
+ if (to.query?.el) {
352
528
  const el = to.query.el;
353
- return {
354
- el
355
- };
529
+ return { el };
356
530
  }
357
531
  if (to.meta.scrollToTop) {
358
532
  return { left: 0, top: 0 };
359
533
  }
360
534
  }
361
535
  });
362
- const langLink = (url, lang = "ru", defaultLang2 = "ru") => {
363
- url = (url || "").replace(/\/(ru|ua|en)(\/|$)/, "/");
364
- const result = (lang === defaultLang2 ? "" : "/" + lang) + url;
365
- return result === "/" ? result : result.replace(/\/$/, "");
366
- };
367
- const fetchAction = async ({ state, commit, getters, dispatch }, [
368
- params = {},
369
- options2
370
- ]) => {
371
- var _a, _b, _c;
372
- const headers = {};
373
- try {
374
- const isFormData = typeof FormData !== "undefined" && params instanceof FormData;
375
- const ssrHeaders = state.context.headers || {};
376
- if (isFormData) {
377
- if (!params.has("lang")) {
378
- params.append("lang", state.lang);
379
- }
380
- } else {
381
- if (!params.lang) {
382
- params.lang = state.lang;
383
- }
384
- }
385
- if (isBrowser()) {
386
- [
387
- "host",
388
- "connection",
389
- "user-agent",
390
- "referer",
391
- "accept-encoding",
392
- "cookie",
393
- "sec-ch-ua",
394
- "sec-ch-ua-mobile",
395
- "sec-fetch-site",
396
- "sec-fetch-mode",
397
- "sec-fetch-dest",
398
- "sec-fetch-user",
399
- "sec-ch-ua-platform"
400
- ].map((key) => delete ssrHeaders[key]);
401
- } else {
402
- ssrHeaders["x-forwarded-for"] = state.context.ip;
403
- }
404
- const defaultOptions = {
405
- url: `${getters.getBaseUrl}/web`,
406
- method: "get",
407
- preloader: true,
408
- error: true,
409
- compress: true,
410
- headers: {
411
- // Proxy ssr headers to request
412
- ...ssrHeaders,
413
- ...isFormData ? {} : { "content-type": "application/json" }
414
- }
415
- };
416
- options2 = Object.assign(
417
- {},
418
- defaultOptions,
419
- options2 || {}
420
- );
421
- if (options2 == null ? void 0 : options2.preloader) {
422
- commit("SET_LOADING", true);
423
- }
424
- if (options2.mergeHeaders) {
425
- options2.headers = Object.assign(options2.headers || {}, options2.mergeHeaders);
426
- delete options2.mergeHeaders;
427
- }
428
- const url = new URL(options2.url);
429
- if (!["get", "head"].includes((_a = options2 == null ? void 0 : options2.method) == null ? void 0 : _a.toLowerCase())) {
430
- if (isFormData) {
431
- options2.body = params;
432
- } else {
433
- options2.body = JSON.stringify(params);
434
- }
435
- } else {
436
- url.search = new URLSearchParams(params).toString();
437
- }
438
- const response = await fetch(url.toString(), options2);
439
- response.headers.forEach((value, key) => headers[key] = value);
440
- const json = await response.json();
441
- if (!response.ok) {
442
- throw new ApiError({
443
- code: json.code || 0,
444
- statusCode: response.status,
445
- message: "Api request error",
446
- headers,
447
- data: json
448
- });
449
- }
450
- return { body: json, response };
451
- } catch (e) {
452
- if (e instanceof TypeError) {
453
- if (isBrowser()) {
454
- commit("SET_NOTIFICATION", {
455
- type: "danger",
456
- text: "Check your internet connection. No contact)"
457
- });
458
- }
459
- }
460
- if (e instanceof ApiError) {
461
- const statusCode = e.getStatusCode();
462
- if (statusCode === 400 && (options2 == null ? void 0 : options2.error)) {
463
- commit("SET_NOTIFICATION", { type: "danger", text: e.getData()["error"] });
464
- }
465
- if (statusCode === 404 && (options2 == null ? void 0 : options2.error)) {
466
- if (isBrowser()) {
467
- commit("SET_NOTIFICATION", {
468
- type: "danger",
469
- text: "Something went wrong. We are working hard to fix this)"
470
- });
471
- } else {
472
- await dispatch("redirect", {
473
- url: "/404",
474
- code: 307
475
- });
476
- }
477
- }
478
- if (((_b = options2 == null ? void 0 : options2.method) == null ? void 0 : _b.toLowerCase()) === "get") {
479
- if (statusCode === 410) {
480
- const location = (_c = e.getHeaders()) == null ? void 0 : _c.location;
481
- if (location) {
482
- await dispatch("redirect", { url: location, code: 307 });
483
- }
484
- }
485
- }
486
- }
487
- throw e;
488
- } finally {
489
- if (options2 == null ? void 0 : options2.preloader) {
490
- commit("SET_LOADING", false);
491
- }
492
- }
493
- };
494
- const createStore = (opt) => createStore$1({
495
- state: () => {
496
- return {
497
- context: {},
498
- page: {},
499
- way: [],
500
- toLang: "ru",
501
- lang: "ru",
502
- loading: false
503
- };
504
- },
505
- mutations: {
506
- MERGE_CONTEXT(state, context) {
507
- Object.assign(state.context, context);
508
- },
509
- MERGE_CONTEXT_HEADERS(state, headers) {
510
- state.context.responseHeaders = Object.assign(state.context.responseHeaders || {}, headers);
511
- },
512
- SET_PAGE(state, page) {
513
- state.page = page || {};
514
- },
515
- SET_WAY(state, way) {
516
- state.way = way || [];
517
- },
518
- SET_LANG(state, lang) {
519
- state.lang = lang;
520
- },
521
- SET_TO_LANG(state, lang) {
522
- state.toLang = lang;
523
- },
524
- SET_LOADING(state, loading) {
525
- state.loading = loading;
526
- }
527
- },
528
- getters: {
529
- getToLang(state) {
530
- return state.toLang;
531
- },
532
- getLang(state) {
533
- return state.lang;
534
- },
535
- urlFromLang: (state) => (url = "/", lang = state.toLang) => langLink(url, lang),
536
- /**
537
- * Get absolute url for requests
538
- * @param state
539
- */
540
- getBaseUrl(state) {
541
- return `${state.context.protocol}://${state.context.hostname}`;
542
- }
543
- },
544
- actions: {
545
- /**
546
- * Base fetch data action
547
- * @param state
548
- * @param payload
549
- * @returns
550
- */
551
- async fetch(state, payload) {
552
- return fetchAction(state, payload);
553
- },
554
- /**
555
- * Redirect
556
- * @param context
557
- * @param url auto transform to multilang
558
- * @param query query params
559
- * @param code status code for server, when on the client is discarded
560
- */
561
- async redirect({ state, getters }, { url, code, query }) {
562
- if (query) {
563
- url = url + new URLSearchParams(query).toString();
564
- }
565
- await opt.redirect(langLink(url, state.toLang), code || 307);
566
- }
567
- }
568
- });
569
- /*!
570
- /**
571
- * vuex-router-sync v6.0.0-rc.1
572
- * (c) 2021 Evan You
573
- * @license MIT
574
- */
575
- function sync(store, router, options2) {
576
- const moduleName = {}.moduleName || "route";
577
- store.registerModule(moduleName, {
578
- namespaced: true,
579
- state: cloneRoute(router.currentRoute.value),
580
- mutations: {
581
- ROUTE_CHANGED(_state, transition) {
582
- store.state[moduleName] = cloneRoute(transition.to, transition.from);
583
- }
584
- }
585
- });
586
- let isTimeTraveling = false;
587
- let currentPath;
588
- const storeUnwatch = store.watch((state) => state[moduleName], (route) => {
589
- const { fullPath } = route;
590
- if (fullPath === currentPath) {
591
- return;
592
- }
593
- if (currentPath != null) {
594
- isTimeTraveling = true;
595
- router.push(route);
596
- }
597
- currentPath = fullPath;
598
- }, { flush: "sync" });
599
- const afterEachUnHook = router.afterEach((to, from) => {
600
- if (isTimeTraveling) {
601
- isTimeTraveling = false;
602
- return;
603
- }
604
- currentPath = to.fullPath;
605
- store.commit(moduleName + "/ROUTE_CHANGED", { to, from });
606
- });
607
- return function unsync() {
608
- afterEachUnHook();
609
- storeUnwatch();
610
- store.unregisterModule(moduleName);
611
- };
612
- }
613
- function cloneRoute(to, from) {
614
- const clone = {
615
- name: to.name,
616
- path: to.path,
617
- hash: to.hash,
618
- query: to.query,
619
- params: to.params,
620
- fullPath: to.fullPath,
621
- meta: to.meta
622
- };
623
- if (from) {
624
- clone.from = cloneRoute(from);
625
- }
626
- return Object.freeze(clone);
627
- }
628
536
  const parseLang = (url, defaultLang2 = "ru") => {
629
537
  const result = url.match(/^\/(ru|ua|en)\/?/i);
630
538
  return result && result.length > 0 ? result[1] : defaultLang2;
@@ -635,48 +543,64 @@ const options = {
635
543
  const emitter = amitt();
636
544
  const head = createHead();
637
545
  const router = createRouter({ isClient });
638
- const store = createStore({
639
- redirect: async function(url, statusCode = 307) {
640
- console.log("Redirecting: " + url);
641
- if (isClient) {
642
- await router.push(url);
643
- } else {
644
- res.redirect(url, statusCode);
645
- }
646
- }
546
+ const pinia = createPinia();
547
+ const redirect = async function(url, statusCode = 307) {
548
+ console.log("Redirecting: " + url);
549
+ isClient ? await router.push(url) : res.redirect(url, statusCode);
550
+ };
551
+ pinia.use(function() {
552
+ return {
553
+ "$redirect": redirect,
554
+ "$emitter": emitter
555
+ };
647
556
  });
648
557
  app.use(router);
649
- app.use(store);
558
+ app.use(pinia);
650
559
  app.use(head);
651
560
  app.use(Multilang, {
652
561
  default: defaultLang,
653
- getLang() {
654
- return store.state.lang;
655
- }
562
+ getLang: () => useBaseStore(pinia).lang
656
563
  });
657
- sync(store, router);
658
564
  const prefetch = createPrefetch();
659
- app.use(prefetch, router, store);
660
- app.use(PrimeVue.default || PrimeVue);
661
- app.use(ConfirmationService.default || ConfirmationService);
565
+ app.use(prefetch, router, pinia);
566
+ app.use(PrimeVue, {
567
+ theme: {
568
+ preset: Aura,
569
+ options: {
570
+ darkModeSelector: false
571
+ }
572
+ }
573
+ });
574
+ app.use(ConfirmationService);
575
+ app.use(ToastService);
662
576
  app.config.globalProperties.$emitter = emitter;
663
- if (!isClient) {
664
- store.state.context = context;
665
- }
577
+ app.config.globalProperties.$emitter = emitter;
578
+ app.config.globalProperties.$redirect = redirect;
579
+ !isClient && (useBaseStore(pinia).context = context);
666
580
  router.beforeEach(async (to) => {
667
- store.commit("SET_TO_LANG", parseLang(to.fullPath, defaultLang));
581
+ useBaseStore(pinia).toLang = parseLang(to.fullPath, defaultLang);
668
582
  });
669
583
  router.afterEach(async (to, from) => {
670
- store.commit("SET_LANG", parseLang(to.fullPath, defaultLang));
584
+ useBaseStore(pinia).lang = parseLang(to.fullPath, defaultLang);
671
585
  });
672
- return { head, router, store };
586
+ return { head, router, pinia };
587
+ },
588
+ // В случае кеширования нельзя кешировать весь контекст
589
+ rendered({ isClient, pinia }) {
590
+ if (!isClient) {
591
+ const baseStore = useBaseStore(pinia);
592
+ baseStore.context.cookies = {};
593
+ baseStore.context.headers = {};
594
+ baseStore.context.ip = "";
595
+ baseStore.context.memcache = null;
596
+ }
673
597
  }
674
598
  };
675
599
  const _sfc_main = defineComponent({
676
600
  name: "App",
677
601
  setup() {
678
- const store = useStore();
679
- useHead(computed(() => store.state.page));
602
+ const baseStore = useBaseStore();
603
+ useHead(computed(() => baseStore.page));
680
604
  }
681
605
  });
682
606
  function _sfc_ssrRender(_ctx, _push, _parent, _attrs, $props, $setup, $data, $options) {
@@ -691,7 +615,7 @@ _sfc_main.setup = (props, ctx) => {
691
615
  (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("src/frontend/App.vue");
692
616
  return _sfc_setup ? _sfc_setup(props, ctx) : void 0;
693
617
  };
694
- const App = /* @__PURE__ */ _export_sfc(_sfc_main, [["ssrRender", _sfc_ssrRender], ["__file", "/Volumes/MacMiniAPFS/projects/packages/vite-node-template/template-vite-vue3-mts/src/frontend/App.vue"]]);
618
+ const App = /* @__PURE__ */ _export_sfc(_sfc_main, [["ssrRender", _sfc_ssrRender], ["__file", "/Volumes/MacMiniAPFS/projects/packages/vite-node-template/template-vite-vue3-pinia-mts/src/frontend/App.vue"]]);
695
619
  const args = margv();
696
620
  const createConfigServer = (config2, nodeEnv) => {
697
621
  const env = process.env.NODE_ENV || "development";
@@ -731,26 +655,13 @@ const webRoutes = [
731
655
  }
732
656
  ];
733
657
  const createMariadb = (config2) => {
734
- var _a;
735
- if ((_a = config2.db) == null ? void 0 : _a.home) {
658
+ if (config2.db?.home) {
736
659
  const home2 = new Query({ debug: process.env.NODE_ENV === "production" ? 0 : 1 });
737
660
  const homePool = home2.createPool(config2.db.home);
738
661
  return { homePool, home: home2 };
739
662
  }
740
663
  return {};
741
664
  };
742
- const createMemcached = () => {
743
- const memcachedClient2 = memjs.Client.create("127.0.0.1:11211", {
744
- timeout: 1,
745
- conntimeout: 1,
746
- logger: {
747
- log: () => {
748
- }
749
- }
750
- });
751
- const memcached2 = new Memcached(memcachedClient2);
752
- return { memcachedClient: memcachedClient2, memcached: memcached2 };
753
- };
754
665
  const readManifest = () => {
755
666
  let manifest = {};
756
667
  try {
@@ -766,13 +677,13 @@ const readJson5ConfigsSync = (configs, input = {}) => {
766
677
  }
767
678
  return input;
768
679
  };
680
+ const { readConfigSync } = helpers;
769
681
  process.server = process.server || {};
770
- let memcachedClient, memcached, home;
682
+ let home;
771
683
  const config = readJson5ConfigsSync(["./connect.json5", "./common.json5"]);
772
684
  const configServer = createConfigServer(config);
773
685
  if (process.env.NODE_ENV === "production") {
774
686
  ({ home } = createMariadb(config));
775
- ({ memcachedClient, memcached } = createMemcached());
776
687
  }
777
688
  const webOptions = {
778
689
  routes: webRoutes,
@@ -780,12 +691,10 @@ const webOptions = {
780
691
  db: process.server.db || {
781
692
  home
782
693
  },
783
- memcached: process.server.memcached || memcached,
784
694
  schema
785
695
  };
786
696
  const ssrOptions = {
787
- manifest: readManifest(),
788
- memcached: process.server.memcached || memcached
697
+ manifest: readManifest()
789
698
  };
790
699
  process.server.app = new Server({
791
700
  ...configServer,