create-jwn-js 1.0.2 → 1.0.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.
- package/index.js +11 -0
- package/package.json +1 -1
- package/template-vite-vue3-ts/.gitignore +5 -0
- package/template-vite-vue3-ts/connect-template.json +36 -0
- package/template-vite-vue3-ts/cron.js +90 -0
- package/template-vite-vue3-ts/docs/index.md +27 -0
- package/template-vite-vue3-ts/index.html +18 -0
- package/template-vite-vue3-ts/jest.config.ts +38 -0
- package/template-vite-vue3-ts/package.json +57 -0
- package/template-vite-vue3-ts/postcss.config.js +28 -0
- package/template-vite-vue3-ts/src/backend/server/helpers/createConfigServer.ts +16 -0
- package/template-vite-vue3-ts/src/backend/server/helpers/createMariadb.ts +16 -0
- package/template-vite-vue3-ts/src/backend/server/helpers/createMemcached.ts +15 -0
- package/template-vite-vue3-ts/src/backend/server/helpers/readManifest.ts +16 -0
- package/template-vite-vue3-ts/src/backend/server/index.ts +51 -0
- package/template-vite-vue3-ts/src/backend/server/site-schema.ts +21 -0
- package/template-vite-vue3-ts/src/backend/server/web-routes/index.ts +9 -0
- package/template-vite-vue3-ts/src/backend/views/Index/IndexController.ts +16 -0
- package/template-vite-vue3-ts/src/frontend/App.vue +30 -0
- package/template-vite-vue3-ts/src/frontend/entry-client.ts +2 -0
- package/template-vite-vue3-ts/src/frontend/entry-server.ts +4 -0
- package/template-vite-vue3-ts/src/frontend/helpers/customerPrefetch.ts +46 -0
- package/template-vite-vue3-ts/src/frontend/main.ts +68 -0
- package/template-vite-vue3-ts/src/frontend/routes/index.ts +42 -0
- package/template-vite-vue3-ts/src/frontend/shims-plugins.d.ts +18 -0
- package/template-vite-vue3-ts/src/frontend/shims-vue.d.ts +5 -0
- package/template-vite-vue3-ts/src/frontend/shims-vuex.d.ts +10 -0
- package/template-vite-vue3-ts/src/frontend/store/fetch.ts +174 -0
- package/template-vite-vue3-ts/src/frontend/store/index.ts +131 -0
- package/template-vite-vue3-ts/src/frontend/store/types.d.ts +83 -0
- package/template-vite-vue3-ts/src/frontend/views/Error/Error.vue +62 -0
- package/template-vite-vue3-ts/src/frontend/views/Index/Index.vue +27 -0
- package/template-vite-vue3-ts/src/frontend/views/Index/__tests__/Index.spec.ts +31 -0
- package/template-vite-vue3-ts/src/frontend/vite-env.d.ts +1 -0
- package/template-vite-vue3-ts/src/helpers/langLink.ts +17 -0
- package/template-vite-vue3-ts/src/helpers/parseLang.ts +10 -0
- package/template-vite-vue3-ts/src/scripts/jest.global.setup.ts +23 -0
- package/template-vite-vue3-ts/src/scripts/jest.global.teardown.ts +10 -0
- package/template-vite-vue3-ts/src/scripts/jest.setup.ts +16 -0
- package/template-vite-vue3-ts/tsconfig.json +47 -0
- package/template-vite-vue3-ts/vite.config.ts +87 -0
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"server": {
|
|
3
|
+
"development": {
|
|
4
|
+
"mode": "development",
|
|
5
|
+
"vite": {
|
|
6
|
+
"port": 3000
|
|
7
|
+
},
|
|
8
|
+
"port": 3001,
|
|
9
|
+
"host": "localhost"
|
|
10
|
+
},
|
|
11
|
+
"production": {
|
|
12
|
+
"mode": "production",
|
|
13
|
+
"port": 3000,
|
|
14
|
+
"host": "127.0.0.1",
|
|
15
|
+
"url": "http://127.0.0.1"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"db": {
|
|
19
|
+
"home": {
|
|
20
|
+
"engine": "mysql",
|
|
21
|
+
"host": "localhost",
|
|
22
|
+
"user": "",
|
|
23
|
+
"password": "",
|
|
24
|
+
"database": "",
|
|
25
|
+
"connectTimeout": 10000,
|
|
26
|
+
"acquireTimeout": 10000,
|
|
27
|
+
"connectionLimit": 2,
|
|
28
|
+
"charset": "utf8",
|
|
29
|
+
"compress": true,
|
|
30
|
+
"port": 3306,
|
|
31
|
+
"multipleStatements": true,
|
|
32
|
+
"namedPlaceholders": true,
|
|
33
|
+
"dateStrings": true
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
const {appendFileSync} = require("fs");
|
|
2
|
+
const {performance} = require("perf_hooks");
|
|
3
|
+
const margv = require("margv");
|
|
4
|
+
const fetch = require("cross-fetch");
|
|
5
|
+
const chalk = require("chalk");
|
|
6
|
+
const fs = require("fs");
|
|
7
|
+
const path = require("path");
|
|
8
|
+
|
|
9
|
+
const logFile = "/var/www/tehnoskarb/logs/cron/skarb.works.log";
|
|
10
|
+
const two = (value) => ("0" + value).slice(-2);
|
|
11
|
+
const toMysqlDatetime = (date) => `${date.getFullYear()}-${two(date.getMonth()+1)}-${two(date.getDate())} ${two(date.getHours())}:${two(date.getMinutes())}:${two(date.getSeconds())}`;
|
|
12
|
+
|
|
13
|
+
(async() => {
|
|
14
|
+
const start = performance.now();
|
|
15
|
+
const args = margv();
|
|
16
|
+
|
|
17
|
+
if(args.help) {
|
|
18
|
+
console.log(`// $ cron.js -c=<controller> -s=<subaction> -p={} -m=<method> -h={} --development`);
|
|
19
|
+
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const connect = path.resolve(__dirname, './connect.json');
|
|
24
|
+
const config = JSON.parse(fs.readFileSync(connect, 'utf8'));
|
|
25
|
+
const host = args.development || args.d
|
|
26
|
+
? `http://${config.server.development.host}:${config.server.development.port}/web`
|
|
27
|
+
: `http://${config.server.production.host}:${config.server.production.port}/web`;
|
|
28
|
+
const controller = args.controller || args.c;
|
|
29
|
+
const subaction = args.subaction || args.s;
|
|
30
|
+
const params = args.params || args.p || {};
|
|
31
|
+
const method = args.method || args.m || "get";
|
|
32
|
+
const headers = args.headers || args.h || {};
|
|
33
|
+
const adminToken = config.cron["admin-token"];
|
|
34
|
+
const apiToken = config.cron["api-token"];
|
|
35
|
+
|
|
36
|
+
console.log(chalk.green(host));
|
|
37
|
+
|
|
38
|
+
if(!controller) {
|
|
39
|
+
console.log(chalk.red("required --controller=<controller>"));
|
|
40
|
+
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if(!subaction) {
|
|
45
|
+
console.log(chalk.red("required --subaction=<subaction>"));
|
|
46
|
+
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const url = new URL(host);
|
|
51
|
+
const options = {
|
|
52
|
+
compress: true,
|
|
53
|
+
method,
|
|
54
|
+
headers: {
|
|
55
|
+
"content-type": "application/json",
|
|
56
|
+
"cookie":`admin-token=${adminToken}`,
|
|
57
|
+
...headers
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if(method.toLowerCase() === "get") {
|
|
62
|
+
url.search = new URLSearchParams(Object.assign(params, {controller, subaction, token: apiToken})).toString();
|
|
63
|
+
} else {
|
|
64
|
+
options.body = JSON.stringify(Object.assign(params, {controller, subaction, token: apiToken}));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
console.log(chalk.green(`send params to ${controller} ${subaction}`));
|
|
68
|
+
const response = await fetch(url.toString(), options);
|
|
69
|
+
const text = decodeURIComponent(await response.text());
|
|
70
|
+
const time = Math.round(performance.now() - start)/1000;
|
|
71
|
+
const logParams = (JSON.stringify(Object.assign(params, {subaction}))
|
|
72
|
+
.substring(0, 512));
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
appendFileSync(
|
|
76
|
+
logFile,
|
|
77
|
+
`${toMysqlDatetime(new Date())}\t${time}\t${text}\t${host}\t${logParams}\n`
|
|
78
|
+
);
|
|
79
|
+
} catch(e) {
|
|
80
|
+
console.log(chalk.red( `No log file ${logFile}`));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if(response.ok) {
|
|
84
|
+
console.log(chalk.green("response ok."));
|
|
85
|
+
console.log(chalk.green(text));
|
|
86
|
+
} else {
|
|
87
|
+
console.log(chalk.red("Error during request!"));
|
|
88
|
+
console.log(chalk.red(text));
|
|
89
|
+
}
|
|
90
|
+
})();
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Template template-vite-vue3-ts
|
|
2
|
+
|
|
3
|
+
```typescript
|
|
4
|
+
yarn
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
### Develop
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
yarn dev
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Test
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
yarn test
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Docs
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
yarn docs:dev
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
yarn docs:build
|
|
27
|
+
```
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="msapplication-TileColor" content="#da532c">
|
|
6
|
+
<meta name="theme-color" content="#ffffff">
|
|
7
|
+
<meta name='viewport' content="width=device-width, initial-scale=1, minimum-scale=1.0, maximum-scale=1.0">
|
|
8
|
+
<style>
|
|
9
|
+
.iconing {
|
|
10
|
+
width: 20px;
|
|
11
|
+
}
|
|
12
|
+
</style>
|
|
13
|
+
</head>
|
|
14
|
+
<body>
|
|
15
|
+
<div id="app"></div>
|
|
16
|
+
<script type="module" src="/src/frontend/entry-client.ts"></script>
|
|
17
|
+
</body>
|
|
18
|
+
</html>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
moduleFileExtensions: [
|
|
3
|
+
"js",
|
|
4
|
+
"ts",
|
|
5
|
+
"json",
|
|
6
|
+
"vue",
|
|
7
|
+
"node"
|
|
8
|
+
],
|
|
9
|
+
transform: {
|
|
10
|
+
"^.+\\.ts$": "ts-jest",
|
|
11
|
+
"^.+\\.vue$": "@vue/vue3-jest"
|
|
12
|
+
},
|
|
13
|
+
moduleNameMapper: {
|
|
14
|
+
"@/(.*)$": "<rootDir>/src/$1"
|
|
15
|
+
},
|
|
16
|
+
setupFiles: ["./src/scripts/jest.setup.ts"],
|
|
17
|
+
globalSetup: "./src/scripts/jest.global.setup.ts",
|
|
18
|
+
globalTeardown: "./src/scripts/jest.global.teardown.ts",
|
|
19
|
+
testTimeout: 35000,
|
|
20
|
+
globals: {
|
|
21
|
+
'ts-jest': {
|
|
22
|
+
tsconfig: './tsconfig.json',
|
|
23
|
+
diagnostics: false
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
testEnvironment: "jsdom",
|
|
27
|
+
maxWorkers: 2,
|
|
28
|
+
testMatch: [ "**/__its__/**/*.[jt]s?(x)", "**/__tests__/**/*.[jt]s?(x)", "**/?(*.)+(spec|test).[jt]s?(x)" ],
|
|
29
|
+
testPathIgnorePatterns: ["<rootDir>/src/scripts",],
|
|
30
|
+
collectCoverageFrom: [
|
|
31
|
+
"**/src/**/*.{ts}",
|
|
32
|
+
"!**/src/**/*.d.ts",
|
|
33
|
+
"!**/src/**/index.ts",
|
|
34
|
+
"!**/src/scripts/**",
|
|
35
|
+
"!**/src/sql/**",
|
|
36
|
+
"!**/src/backend/server/web-routes/**",
|
|
37
|
+
]
|
|
38
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "template-vite-vue3-ts",
|
|
3
|
+
"private": true,
|
|
4
|
+
"author": "webigorkiev",
|
|
5
|
+
"license": "PRIVATE",
|
|
6
|
+
"version": "1.0.1",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "vite",
|
|
9
|
+
"build": "vite build",
|
|
10
|
+
"test": "jest src -c jest.config.ts --silent true",
|
|
11
|
+
"docs:dev": "vitepress dev docs",
|
|
12
|
+
"docs:build": "vitepress build docs",
|
|
13
|
+
"docs:serve": "vitepress serve docs"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@types/jest": "^27.0.3",
|
|
17
|
+
"@types/memjs": "^1.2.4",
|
|
18
|
+
"@types/node": "^17.0.4",
|
|
19
|
+
"@vue/compiler-sfc": "^3.2.26",
|
|
20
|
+
"@vue/test-utils": "^2.0.0-rc.18",
|
|
21
|
+
"@vue/vue3-jest": "^27.0.0-alpha.4",
|
|
22
|
+
"autoprefixer": "^10.4.1",
|
|
23
|
+
"jest": "^27.4.5",
|
|
24
|
+
"ts-jest": "^27.1.2",
|
|
25
|
+
"ts-node": "^10.4.0",
|
|
26
|
+
"typescript": "^4.4.4",
|
|
27
|
+
"vite": "^2.7.10",
|
|
28
|
+
"vite-svg-loader": "^3.1.1",
|
|
29
|
+
"vitepress": "^0.20.10"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@jwn-js/common": "^2.0.7",
|
|
33
|
+
"@jwn-js/plugins": "^1.0.13",
|
|
34
|
+
"@vue/server-renderer": "^3.2.26",
|
|
35
|
+
"@vuemod/prefetch": "^1.0.10",
|
|
36
|
+
"amitt": "^1.0.5",
|
|
37
|
+
"buildmsql": "^1.3.2",
|
|
38
|
+
"chalk": "4",
|
|
39
|
+
"cross-fetch": "^3.1.4",
|
|
40
|
+
"easy-ash": "^1.1.5",
|
|
41
|
+
"margv": "^1.1.2",
|
|
42
|
+
"memjs": "^1.3.0",
|
|
43
|
+
"postcss": "^8.3.5",
|
|
44
|
+
"postcss-custom-media": "^8.0.0",
|
|
45
|
+
"postcss-each": "^1.1.0",
|
|
46
|
+
"postcss-load-config": "^3.1.0",
|
|
47
|
+
"postcss-nested": "^5.0.5",
|
|
48
|
+
"postcss-nesting": "^8.0.1",
|
|
49
|
+
"postcss-plugin": "^1.0.0",
|
|
50
|
+
"postcss-scss": "^4.0.0",
|
|
51
|
+
"primevue": "^3.10.0",
|
|
52
|
+
"vue": "^3.2.26",
|
|
53
|
+
"vue-router": "^4.0.12",
|
|
54
|
+
"vuex": "^4.0.2",
|
|
55
|
+
"vuex-router-sync": "^6.0.0-rc.1"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module.exports = (ctx) => {
|
|
2
|
+
|
|
3
|
+
return {
|
|
4
|
+
parser: 'postcss-scss',
|
|
5
|
+
map: {
|
|
6
|
+
inline: true
|
|
7
|
+
},
|
|
8
|
+
plugins: {
|
|
9
|
+
'postcss-nested': {},
|
|
10
|
+
'postcss-custom-media': {
|
|
11
|
+
importFrom: [
|
|
12
|
+
{
|
|
13
|
+
customMedia: {
|
|
14
|
+
'--xxl': '(max-width: 1920px)',
|
|
15
|
+
'--xl': '(min-width: 1200px)',
|
|
16
|
+
'--lg': '(min-width: 992px)',
|
|
17
|
+
'--md': '(min-width: 768px)',
|
|
18
|
+
'--sm': '(min-width: 576px)',
|
|
19
|
+
'--mm': '(max-width: 375px)',
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
'postcss-each': {},
|
|
25
|
+
'autoprefixer': {}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import margv from "margv";
|
|
2
|
+
const args = margv();
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Config for server
|
|
6
|
+
* @param config
|
|
7
|
+
*/
|
|
8
|
+
export const createConfigServer = (config: Record<string, any>) => {
|
|
9
|
+
const configServer = process.env.NODE_ENV === "production" ? config.server.production : config.server.development;
|
|
10
|
+
configServer.port = +args.port + 1 || configServer.port;
|
|
11
|
+
configServer.host = args.host || configServer.host;
|
|
12
|
+
configServer.proxy = `http://${configServer.host}:${configServer.port}`;
|
|
13
|
+
configServer.vitePort = config.server.development.vite.port;
|
|
14
|
+
|
|
15
|
+
return configServer;
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {Query} from "buildmsql";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Create mariadb pool
|
|
5
|
+
* @param config
|
|
6
|
+
*/
|
|
7
|
+
export const createMariadb = (config: Record<string, any>) => {
|
|
8
|
+
if(config.db.home) {
|
|
9
|
+
const home = new Query({debug: process.env.NODE_ENV === "production" ? 0 : 1});
|
|
10
|
+
const homePool = home.createPool(config.db.home);
|
|
11
|
+
|
|
12
|
+
return {homePool, home};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return {};
|
|
16
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import memjs from "memjs";
|
|
2
|
+
import {Memcached} from "@jwn-js/common";
|
|
3
|
+
|
|
4
|
+
export const createMemcached = () => {
|
|
5
|
+
const memcachedClient = memjs.Client.create("127.0.0.1:11211", {
|
|
6
|
+
timeout: 1,
|
|
7
|
+
conntimeout: 1,
|
|
8
|
+
logger: {
|
|
9
|
+
log: () => {}
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
const memcached = new Memcached(memcachedClient);
|
|
13
|
+
|
|
14
|
+
return {memcachedClient, memcached};
|
|
15
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {helpers} from "@jwn-js/common";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Read ssr manifest
|
|
5
|
+
*/
|
|
6
|
+
export const readManifest = () => {
|
|
7
|
+
let manifest = {};
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
manifest = helpers.readConfigSync("./dist/client/ssr-manifest.json");
|
|
11
|
+
} catch(e: any) {
|
|
12
|
+
// console.log(e.message);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return manifest;
|
|
16
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {Server, helpers, Web, Ssr, OptionsWeb, OptionsSsr} from "@jwn-js/common";
|
|
2
|
+
import {createConfigServer} from "./helpers/createConfigServer";
|
|
3
|
+
import {schema} from "./site-schema";
|
|
4
|
+
import {webRoutes} from "./web-routes";
|
|
5
|
+
import {createMariadb} from "./helpers/createMariadb";
|
|
6
|
+
import {createMemcached} from "./helpers/createMemcached";
|
|
7
|
+
import {readManifest} from "@/backend/server/helpers/readManifest";
|
|
8
|
+
import entry from "@/frontend/main";
|
|
9
|
+
declare var process: any;
|
|
10
|
+
|
|
11
|
+
const {readConfigSync} = helpers;
|
|
12
|
+
process.server = process.server || {};
|
|
13
|
+
let memcachedClient, memcached, home;
|
|
14
|
+
const config = readConfigSync("./connect.json");
|
|
15
|
+
const configServer = createConfigServer(config);
|
|
16
|
+
|
|
17
|
+
if(process.env.NODE_ENV === "production") {
|
|
18
|
+
({home} = createMariadb(config));
|
|
19
|
+
({memcachedClient, memcached} = createMemcached());
|
|
20
|
+
}
|
|
21
|
+
const webOptions: OptionsWeb = {
|
|
22
|
+
routes: webRoutes,
|
|
23
|
+
config,
|
|
24
|
+
db: process.server.db || {
|
|
25
|
+
home
|
|
26
|
+
},
|
|
27
|
+
memcached: process.server.memcached || memcached,
|
|
28
|
+
schema
|
|
29
|
+
}
|
|
30
|
+
const ssrOptions:OptionsSsr = {
|
|
31
|
+
manifest: readManifest(),
|
|
32
|
+
memcached: process.server.memcached || memcached
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
process.server.app = new Server({
|
|
36
|
+
...configServer,
|
|
37
|
+
routes: [
|
|
38
|
+
{
|
|
39
|
+
method: "any",
|
|
40
|
+
pattern: "/web",
|
|
41
|
+
handler: (res, req) => new Web(res, req, webOptions).request()
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
method: "get",
|
|
45
|
+
pattern: "/*",
|
|
46
|
+
handler: (res, req) => new Ssr(res, req, ssrOptions, entry).request()
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
})
|
|
50
|
+
.app()
|
|
51
|
+
.listen();
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {Schema} from "@jwn-js/common";
|
|
2
|
+
|
|
3
|
+
export const schema: Schema = {
|
|
4
|
+
actions: [
|
|
5
|
+
{
|
|
6
|
+
name: "view"
|
|
7
|
+
}
|
|
8
|
+
],
|
|
9
|
+
controllers: [
|
|
10
|
+
{
|
|
11
|
+
id: 1,
|
|
12
|
+
name: "Index",
|
|
13
|
+
subactions: [
|
|
14
|
+
{
|
|
15
|
+
name: "index",
|
|
16
|
+
action: "view"
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {Controller} from "@jwn-js/common";
|
|
2
|
+
import {http} from "@jwn-js/common";
|
|
3
|
+
|
|
4
|
+
export default class IndexController extends Controller {
|
|
5
|
+
|
|
6
|
+
@http()
|
|
7
|
+
async index() {
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
page: {
|
|
11
|
+
title: "Index Page",
|
|
12
|
+
h1: "Index page h1"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="app">
|
|
3
|
+
<RouterView />
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script lang="ts">
|
|
8
|
+
import {defineComponent, computed} from "vue";
|
|
9
|
+
import {useStore} from "vuex";
|
|
10
|
+
import {useHead} from "@vueuse/head";
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @emits
|
|
15
|
+
* web-notification - open notification
|
|
16
|
+
* confirm - open confirm dialog
|
|
17
|
+
*/
|
|
18
|
+
export default defineComponent({
|
|
19
|
+
name: "App",
|
|
20
|
+
setup() {
|
|
21
|
+
const store = useStore();
|
|
22
|
+
useHead(computed(() => store.state.page));
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<style lang="postcss">
|
|
28
|
+
@import "~primevue/resources/themes/bootstrap4-light-blue/theme.css";
|
|
29
|
+
@import "~primevue/resources/primevue.min.css";
|
|
30
|
+
</style>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type {Store} from "vuex";
|
|
2
|
+
import {NavigationGuardFetchWithThis} from "@vuemod/prefetch";
|
|
3
|
+
import {RouteLocationNormalized} from "vue-router";
|
|
4
|
+
|
|
5
|
+
interface Options {
|
|
6
|
+
store: Store<any>,
|
|
7
|
+
isFetch: boolean,
|
|
8
|
+
}
|
|
9
|
+
declare type Callback = (
|
|
10
|
+
store: Store<any>,
|
|
11
|
+
body: Record<string, any>,
|
|
12
|
+
to:RouteLocationNormalized,
|
|
13
|
+
from:RouteLocationNormalized
|
|
14
|
+
) => Promise<void>
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Admin prefetch helper
|
|
18
|
+
* @param options
|
|
19
|
+
* @param fn
|
|
20
|
+
*/
|
|
21
|
+
export const customerPrefetch = (options: {
|
|
22
|
+
controller?: string,
|
|
23
|
+
subaction?: string,
|
|
24
|
+
memcache?: number,
|
|
25
|
+
}, fn?:Callback): NavigationGuardFetchWithThis<any> => {
|
|
26
|
+
|
|
27
|
+
return async ({store, isFetch}: Options, to, from) => {
|
|
28
|
+
if(isFetch) {
|
|
29
|
+
const {body} = await store.dispatch("fetch", [{
|
|
30
|
+
lang: store.state.toLang,
|
|
31
|
+
route: to.fullPath,
|
|
32
|
+
...(to.query || {}),
|
|
33
|
+
...(options || {})
|
|
34
|
+
}, {
|
|
35
|
+
...(store.state?.Customer?.jwt ? {mergeHeaders: {"authorization": `Bearer ${store.state.Customer.jwt}`}} : {})
|
|
36
|
+
}]);
|
|
37
|
+
store.commit("SET_PAGE", body.data?.page || {});
|
|
38
|
+
store.commit("MERGE_CONTEXT", {memcache: options.memcache});
|
|
39
|
+
|
|
40
|
+
if(fn) {
|
|
41
|
+
await fn(store, body, to, from);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import ssr, {Context} from "vite-ssr-vue";
|
|
2
|
+
import App from "./App.vue";
|
|
3
|
+
import createRouter from "./routes";
|
|
4
|
+
import createStore from "./store";
|
|
5
|
+
import {createHead} from "@vueuse/head";
|
|
6
|
+
import {createPrefetch} from "@vuemod/prefetch";
|
|
7
|
+
import {amitt} from "amitt";
|
|
8
|
+
import {sync} from "vuex-router-sync";
|
|
9
|
+
|
|
10
|
+
// Multilang
|
|
11
|
+
import Multilang from "@jwn-js/plugins/Multilang";
|
|
12
|
+
import {parseLang} from "@/helpers/parseLang";
|
|
13
|
+
|
|
14
|
+
// Primevue
|
|
15
|
+
import PrimeVue from 'primevue/config';
|
|
16
|
+
import ConfirmationService from 'primevue/confirmationservice';
|
|
17
|
+
|
|
18
|
+
const defaultLang = "ru";
|
|
19
|
+
|
|
20
|
+
export default ssr(App, {
|
|
21
|
+
created({app, context, req, res, isClient}) {
|
|
22
|
+
const emitter = amitt();
|
|
23
|
+
const head = createHead();
|
|
24
|
+
const router = createRouter({isClient});
|
|
25
|
+
const store = createStore({
|
|
26
|
+
redirect: async function(url: string, statusCode: number = 307) {
|
|
27
|
+
console.log("Redirecting: " + url);
|
|
28
|
+
if(isClient) {
|
|
29
|
+
await router.push(url);
|
|
30
|
+
} else {
|
|
31
|
+
res.redirect(url, statusCode);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
app.use(router);
|
|
36
|
+
app.use(store);
|
|
37
|
+
app.use(head);
|
|
38
|
+
app.use(Multilang, {
|
|
39
|
+
default: defaultLang,
|
|
40
|
+
getLang() {
|
|
41
|
+
|
|
42
|
+
return store.state.lang;
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
sync(store, router);
|
|
46
|
+
|
|
47
|
+
const prefetch = createPrefetch();
|
|
48
|
+
app.use(prefetch, router, store);
|
|
49
|
+
app.use(PrimeVue);
|
|
50
|
+
app.use(ConfirmationService);
|
|
51
|
+
app.config.globalProperties.$emitter = emitter;
|
|
52
|
+
|
|
53
|
+
if(!isClient) {
|
|
54
|
+
store.state.context = context as Context;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Routers hooks
|
|
58
|
+
router.beforeEach(async (to) => {
|
|
59
|
+
store.commit('SET_TO_LANG', parseLang(to.fullPath, defaultLang));
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
router.afterEach(async (to, from) => {
|
|
63
|
+
store.commit('SET_LANG', parseLang(to.fullPath, defaultLang));
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
return {head, router, store}
|
|
67
|
+
}
|
|
68
|
+
});
|