fg-devkit 1.5.2 → 1.6.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/configs/dependency-policy.vue-workspace.json +6 -6
- package/package.json +9 -1
- package/scaffold/vue/.browserslistrc +3 -0
- package/scaffold/vue/.editorconfig +5 -0
- package/scaffold/vue/Dockerfile +18 -0
- package/scaffold/vue/Dockerfile.local +16 -0
- package/scaffold/vue/Jenkinsfile +130 -0
- package/scaffold/vue/LICENSE +19 -0
- package/scaffold/vue/env-adjustment.sh +19 -0
- package/scaffold/vue/index.html +16 -0
- package/scaffold/vue/nginx/default.conf +23 -0
- package/scaffold/vue/nginx/gzip.conf +10 -0
- package/scaffold/vue/nginx/security.conf +6 -0
- package/scaffold/vue/package.json +44 -0
- package/scaffold/vue/poeditor/.poeditor.json +8 -0
- package/scaffold/vue/public/config.json +8 -0
- package/scaffold/vue/src/App.vue +10 -0
- package/scaffold/vue/src/api/client.ts +114 -0
- package/scaffold/vue/src/api/runtimeConfig.ts +10 -0
- package/scaffold/vue/src/assets/.gitkeep +0 -0
- package/scaffold/vue/src/components/.gitkeep +0 -0
- package/scaffold/vue/src/composables/.gitkeep +0 -0
- package/scaffold/vue/src/config/env.ts +45 -0
- package/scaffold/vue/src/i18n.ts +11 -0
- package/scaffold/vue/src/lang/sv.json +1 -0
- package/scaffold/vue/src/main.ts +29 -0
- package/scaffold/vue/src/queries/.gitkeep +0 -0
- package/scaffold/vue/src/router/index.ts +22 -0
- package/scaffold/vue/src/style.css +7 -0
- package/scaffold/vue/src/types/.gitkeep +0 -0
- package/scaffold/vue/src/views/HomeView.vue +10 -0
- package/scaffold/vue/src/vite-env.d.ts +1 -0
- package/scaffold/vue/start-container.sh +15 -0
- package/scaffold/vue/tailwind.config.js +21 -0
- package/scaffold/vue/vite.config.ts +41 -0
- package/scripts/fg-devkit.mjs +28 -3
- package/scripts/fleet-bump-fg-devkit.mjs +135 -0
- package/scripts/poeditor-common.mjs +118 -0
- package/scripts/poeditor-download.mjs +101 -0
- package/scripts/poeditor-upload.mjs +58 -0
- package/scripts/policy-upgrade.mjs +3 -0
- package/scripts/refresh-dependency-policy-from-repos.mjs +7 -0
- package/scripts/scaffold-vue.mjs +183 -0
- package/scripts/sync-scaffold-vue-deps.mjs +68 -0
- package/tsconfig.json +13 -0
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"content-disposition-header": "0.6.0",
|
|
24
24
|
"date-fns": "4.1.0",
|
|
25
25
|
"element-plus": "2.9.7",
|
|
26
|
-
"fds-vue-core": "6.2.
|
|
26
|
+
"fds-vue-core": "6.2.6",
|
|
27
27
|
"imask": "7.6.1",
|
|
28
28
|
"leaflet": "1.8.0",
|
|
29
29
|
"lexical": "0.30.0",
|
|
@@ -56,14 +56,14 @@
|
|
|
56
56
|
"@storybook/addon-vitest": "10.2.12",
|
|
57
57
|
"@storybook/vue3": "10.2.12",
|
|
58
58
|
"@storybook/vue3-vite": "10.2.12",
|
|
59
|
-
"@tanstack/vue-query-devtools": "6.1.
|
|
59
|
+
"@tanstack/vue-query-devtools": "6.1.20",
|
|
60
60
|
"@tsconfig/node22": "22.0.5",
|
|
61
61
|
"@types/lodash-es": "4.17.12",
|
|
62
62
|
"@types/node": "22.16.5",
|
|
63
63
|
"@vitest/browser": "3.2.4",
|
|
64
|
-
"@vue/compiler-dom": "3.5.
|
|
64
|
+
"@vue/compiler-dom": "3.5.33",
|
|
65
65
|
"@vue/eslint-config-standard": "8.0.1",
|
|
66
|
-
"@vue/server-renderer": "3.5.
|
|
66
|
+
"@vue/server-renderer": "3.5.33",
|
|
67
67
|
"@vue/test-utils": "2.4.6",
|
|
68
68
|
"@vuepic/vue-datepicker": "6.0.3",
|
|
69
69
|
"arg": "5.0.2",
|
|
@@ -86,12 +86,12 @@
|
|
|
86
86
|
"managedAnywhere": {
|
|
87
87
|
"@tailwindcss/vite": "4.2.4",
|
|
88
88
|
"@vitejs/plugin-vue": "6.0.6",
|
|
89
|
-
"axios": "1.15.
|
|
89
|
+
"axios": "1.15.2",
|
|
90
90
|
"dotenv": "16.4.5",
|
|
91
91
|
"qrcode.vue": "3.8.1",
|
|
92
92
|
"tailwindcss": "4.2.4",
|
|
93
93
|
"vite": "7.3.2",
|
|
94
|
-
"vue": "3.5.
|
|
94
|
+
"vue": "3.5.33"
|
|
95
95
|
},
|
|
96
96
|
"overrides": {
|
|
97
97
|
"lodash@<=4.17.23": ">=4.18.0",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fg-devkit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Shared configs, scripts, and DX tooling for Vue / TypeScript frontend repos",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -32,11 +32,17 @@
|
|
|
32
32
|
"./scripts/policy-vulns.mjs": "./scripts/policy-vulns.mjs",
|
|
33
33
|
"./scripts/repo-vulns.mjs": "./scripts/repo-vulns.mjs",
|
|
34
34
|
"./scripts/fleet-vulns.mjs": "./scripts/fleet-vulns.mjs",
|
|
35
|
+
"./scripts/fleet-bump-fg-devkit.mjs": "./scripts/fleet-bump-fg-devkit.mjs",
|
|
35
36
|
"./scripts/policy-upgrade.mjs": "./scripts/policy-upgrade.mjs",
|
|
36
37
|
"./scripts/check-dependency-policy.mjs": "./scripts/check-dependency-policy.mjs",
|
|
37
38
|
"./scripts/sync-dependency-policy.mjs": "./scripts/sync-dependency-policy.mjs",
|
|
38
39
|
"./scripts/resolve-dependency-policy-path.mjs": "./scripts/resolve-dependency-policy-path.mjs",
|
|
39
40
|
"./scripts/refresh-dependency-policy-from-repos.mjs": "./scripts/refresh-dependency-policy-from-repos.mjs",
|
|
41
|
+
"./scripts/sync-scaffold-vue-deps.mjs": "./scripts/sync-scaffold-vue-deps.mjs",
|
|
42
|
+
"./scripts/poeditor-common.mjs": "./scripts/poeditor-common.mjs",
|
|
43
|
+
"./scripts/poeditor-download.mjs": "./scripts/poeditor-download.mjs",
|
|
44
|
+
"./scripts/poeditor-upload.mjs": "./scripts/poeditor-upload.mjs",
|
|
45
|
+
"./scripts/scaffold-vue.mjs": "./scripts/scaffold-vue.mjs",
|
|
40
46
|
"./scripts/fg-devkit.mjs": "./scripts/fg-devkit.mjs",
|
|
41
47
|
"./scripts/release.sh": "./scripts/release.sh",
|
|
42
48
|
"./scripts/cz/cz-adapter.cjs": "./scripts/cz/cz-adapter.cjs",
|
|
@@ -45,7 +51,9 @@
|
|
|
45
51
|
},
|
|
46
52
|
"files": [
|
|
47
53
|
"configs",
|
|
54
|
+
"scaffold",
|
|
48
55
|
"scripts",
|
|
56
|
+
"tsconfig.json",
|
|
49
57
|
".cursor/rules/core-coding-standards.mdc"
|
|
50
58
|
],
|
|
51
59
|
"engines": {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
FROM nginx
|
|
2
|
+
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
|
|
3
|
+
ENV CONFIG_FILE_PATH=/usr/share/nginx/html/config.json
|
|
4
|
+
RUN apt-get update && apt-get install -y vim curl
|
|
5
|
+
COPY nginx/*.conf /etc/nginx/conf.d/
|
|
6
|
+
COPY dist /usr/share/nginx/html
|
|
7
|
+
COPY start-container.sh /usr/local/bin/start-container
|
|
8
|
+
RUN chmod +x /usr/local/bin/start-container
|
|
9
|
+
COPY build_date.txt build_hash.txt version.txt ./
|
|
10
|
+
|
|
11
|
+
COPY env-adjustment.sh /env-adjustment.sh
|
|
12
|
+
RUN cat /env-adjustment.sh > /tempentrypoint.sh
|
|
13
|
+
RUN tail -n+2 /usr/local/bin/start-container >> /tempentrypoint.sh
|
|
14
|
+
RUN cat /tempentrypoint.sh > /usr/local/bin/start-container
|
|
15
|
+
RUN rm -f /tempentrypoint.sh
|
|
16
|
+
|
|
17
|
+
ENTRYPOINT ["start-container"]
|
|
18
|
+
CMD ["nginx"]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
FROM node:22-bookworm AS build
|
|
2
|
+
WORKDIR /src
|
|
3
|
+
COPY . /src
|
|
4
|
+
RUN corepack enable && corepack prepare pnpm@10.17.1 --activate
|
|
5
|
+
RUN pnpm install
|
|
6
|
+
RUN pnpm build
|
|
7
|
+
|
|
8
|
+
FROM nginx
|
|
9
|
+
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
|
|
10
|
+
ENV CONFIG_FILE_PATH=/usr/share/nginx/html/config.json
|
|
11
|
+
COPY --from=build /src/dist /usr/share/nginx/html
|
|
12
|
+
COPY nginx/*.conf /etc/nginx/conf.d/
|
|
13
|
+
COPY start-container.sh /usr/local/bin/start-container
|
|
14
|
+
RUN chmod +x /usr/local/bin/start-container
|
|
15
|
+
ENTRYPOINT ["start-container"]
|
|
16
|
+
CMD ["nginx"]
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
@Library('PLACEHOLDER_JENKINS_SHARED_LIBRARY')_
|
|
2
|
+
|
|
3
|
+
pipeline {
|
|
4
|
+
environment {
|
|
5
|
+
registry="PLACEHOLDER_DOCKER_REGISTRY_IMAGE"
|
|
6
|
+
registryCredential='PLACEHOLDER_DOCKER_REGISTRY_CREDENTIAL_ID'
|
|
7
|
+
POEDITOR_API_KEY = credentials('PLACEHOLDER_POEDITOR_CREDENTIAL_ID')
|
|
8
|
+
devBranch='PLACEHOLDER_PRIMARY_DEV_BRANCH'
|
|
9
|
+
NPM_CONFIG_STORE_DIR='/home/jenkins/.cache/pnpm-store'
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
agent any
|
|
13
|
+
options {
|
|
14
|
+
ansiColor('xterm')
|
|
15
|
+
}
|
|
16
|
+
stages {
|
|
17
|
+
stage('Run tests') {
|
|
18
|
+
agent {
|
|
19
|
+
docker {
|
|
20
|
+
image "PLACEHOLDER_JENKINS_NODE_IMAGE"
|
|
21
|
+
args "-v /home/jenkins/.cache:/home/jenkins/.cache:rw,z -v /home/jenkins/tools:/home/jenkins/tools:rw,z"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
stages {
|
|
25
|
+
stage('Dependency Check: OWASP Scan') {
|
|
26
|
+
when {
|
|
27
|
+
not {
|
|
28
|
+
expression {
|
|
29
|
+
env.BRANCH_NAME?.contains('dependabot')
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
steps {
|
|
34
|
+
owaspDependencyCheck()
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
stage('Install dependencies') {
|
|
38
|
+
steps {
|
|
39
|
+
sh '''
|
|
40
|
+
pnpm store path
|
|
41
|
+
pnpm install --frozen-lockfile --prefer-offline
|
|
42
|
+
'''
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
stage('Lint ESLint') {
|
|
46
|
+
steps {
|
|
47
|
+
sh '''pnpm run lint-check'''
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
stage('Lint TypeScript') {
|
|
51
|
+
steps {
|
|
52
|
+
sh '''pnpm run lint:ts'''
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
stage('Build and publish application') {
|
|
58
|
+
when {
|
|
59
|
+
anyOf {
|
|
60
|
+
branch 'master'
|
|
61
|
+
branch devBranch
|
|
62
|
+
buildingTag()
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
stages {
|
|
66
|
+
stage('Build dist') {
|
|
67
|
+
agent {
|
|
68
|
+
docker {
|
|
69
|
+
image "PLACEHOLDER_JENKINS_NODE_IMAGE"
|
|
70
|
+
args "-v /home/jenkins/.cache:/home/jenkins/.cache:rw,z"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
steps {
|
|
74
|
+
sh '''
|
|
75
|
+
pnpm store path
|
|
76
|
+
pnpm install --frozen-lockfile --prefer-offline
|
|
77
|
+
'''
|
|
78
|
+
sh 'sed -i "s/POEDITOR_DUMMY_API_KEY/${POEDITOR_API_KEY}/" ./public/config.json'
|
|
79
|
+
sh 'pnpm run poeditor:download'
|
|
80
|
+
sh 'pnpm run build'
|
|
81
|
+
stash includes: 'dist/**/*', name: 'distfiles'
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
stage('Build and push Docker image') {
|
|
85
|
+
agent {
|
|
86
|
+
node {
|
|
87
|
+
label 'PLACEHOLDER_JENKINS_DOCKER_BUILD_LABEL'
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
steps {
|
|
91
|
+
checkout scm
|
|
92
|
+
unstash 'distfiles'
|
|
93
|
+
script {
|
|
94
|
+
def tag = sh(returnStdout: true, script: "git tag --contains | head -1 | sed 's/^v//'").trim()
|
|
95
|
+
def build_hash = sh(returnStdout: true, script: "git log --pretty=format:'%h' -n 1").trim()
|
|
96
|
+
writeFile file: 'build_hash.txt', text: build_hash
|
|
97
|
+
def build_date = sh(returnStdout: true, script: "git log --pretty=format:'%cI' -n 1").trim()
|
|
98
|
+
writeFile file: 'build_date.txt', text: build_date
|
|
99
|
+
def version = tag
|
|
100
|
+
if (env.BRANCH_NAME == 'master') {
|
|
101
|
+
tag = 'latest'
|
|
102
|
+
version = build_hash + '-' + build_date
|
|
103
|
+
|
|
104
|
+
if (devBranch == 'master') {
|
|
105
|
+
writeFile file: 'version.txt', text: version
|
|
106
|
+
def image = docker.build(registry + ':' + tag)
|
|
107
|
+
image.push()
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (env.BRANCH_NAME == devBranch) {
|
|
112
|
+
tag = 'dev'
|
|
113
|
+
version = build_hash + '-' + build_date
|
|
114
|
+
}
|
|
115
|
+
writeFile file: 'version.txt', text: version
|
|
116
|
+
def image = docker.build(registry + ':' + tag)
|
|
117
|
+
image.push()
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
post {
|
|
125
|
+
always {
|
|
126
|
+
slackBuildStatus(currentBuild.currentResult)
|
|
127
|
+
deleteDir()
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
PROPRIETARY LICENSE
|
|
2
|
+
|
|
3
|
+
Copyright (c) PLACEHOLDER_COPYRIGHT_YEAR PLACEHOLDER_COPYRIGHT_HOLDER
|
|
4
|
+
|
|
5
|
+
All rights reserved.
|
|
6
|
+
|
|
7
|
+
This software and associated documentation files (the "Software") are the
|
|
8
|
+
proprietary and confidential property of PLACEHOLDER_COPYRIGHT_HOLDER.
|
|
9
|
+
|
|
10
|
+
The Software is protected by copyright laws and international copyright
|
|
11
|
+
treaties, as well as other intellectual property laws and treaties.
|
|
12
|
+
|
|
13
|
+
Unauthorized copying, modification, distribution, or use of this Software,
|
|
14
|
+
via any medium, is strictly prohibited and may result in severe civil and
|
|
15
|
+
criminal penalties.
|
|
16
|
+
|
|
17
|
+
The Software is provided "AS IS", without warranty of any kind, express or
|
|
18
|
+
implied, including but not limited to the warranties of merchantability,
|
|
19
|
+
fitness for a particular purpose and noninfringement.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
touch ~/newvars.env
|
|
3
|
+
env | while IFS= read -r line; do
|
|
4
|
+
value=${line#*=}
|
|
5
|
+
name=${line%%=*}
|
|
6
|
+
nameupper=${name^^}
|
|
7
|
+
if [[ "$nameupper" == *_FILE ]]
|
|
8
|
+
then
|
|
9
|
+
if [ -n "$value" ] && [ -f "$value" ]
|
|
10
|
+
then
|
|
11
|
+
file_value=`cat ${value}`
|
|
12
|
+
varname=${nameupper::-5}
|
|
13
|
+
echo "export ${varname}='${file_value}'" >> ~/newvars.env
|
|
14
|
+
echo "export VITE_${varname}='${file_value}'" >> ~/newvars.env
|
|
15
|
+
fi
|
|
16
|
+
fi
|
|
17
|
+
done
|
|
18
|
+
. ~/newvars.env
|
|
19
|
+
rm ~/newvars.env
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="sv">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
6
|
+
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
7
|
+
<title>PLACEHOLDER_APP_NAME</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body class="font-main text-base font-normal tracking-wide text-gray-900 bg-blue-100 leading-lg antialiased">
|
|
10
|
+
<noscript>
|
|
11
|
+
<strong>This application requires JavaScript.</strong>
|
|
12
|
+
</noscript>
|
|
13
|
+
<div id="app"></div>
|
|
14
|
+
<script type="module" src="/src/main.ts"></script>
|
|
15
|
+
</body>
|
|
16
|
+
</html>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
server {
|
|
2
|
+
listen 80;
|
|
3
|
+
server_name localhost;
|
|
4
|
+
large_client_header_buffers 4 32k;
|
|
5
|
+
index index.html;
|
|
6
|
+
root /usr/share/nginx/html;
|
|
7
|
+
|
|
8
|
+
location / {
|
|
9
|
+
index index.html;
|
|
10
|
+
try_files $uri $uri/ /index.html;
|
|
11
|
+
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
|
|
12
|
+
add_header Pragma "no-cache" always;
|
|
13
|
+
add_header Expires "0" always;
|
|
14
|
+
|
|
15
|
+
etag off;
|
|
16
|
+
if_modified_since off;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
error_page 500 502 503 504 /50x.html;
|
|
20
|
+
location = /50x.html {
|
|
21
|
+
root /usr/share/nginx/html;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
gzip on;
|
|
2
|
+
gzip_disable "msie6";
|
|
3
|
+
|
|
4
|
+
gzip_vary on;
|
|
5
|
+
gzip_proxied any;
|
|
6
|
+
gzip_comp_level 6;
|
|
7
|
+
gzip_buffers 16 8k;
|
|
8
|
+
gzip_http_version 1.1;
|
|
9
|
+
gzip_min_length 256;
|
|
10
|
+
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon application/font-woff application/font-woff2;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
add_header Server "-";
|
|
2
|
+
add_header Strict-Transport-Security "max-age=31536000" always;
|
|
3
|
+
add_header X-Content-Type-Options "nosniff" always;
|
|
4
|
+
add_header X-Frame-Options SAMEORIGIN;
|
|
5
|
+
add_header Referrer-Policy "no-referrer-when-downgrade";
|
|
6
|
+
add_header X-XSS-Protection "1; mode=block" always;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"type": "module",
|
|
3
|
+
"name": "PLACEHOLDER_APP_SLUG",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"private": true,
|
|
6
|
+
"scripts": {
|
|
7
|
+
"serve": "vite",
|
|
8
|
+
"build": "vite build",
|
|
9
|
+
"preview": "vite preview",
|
|
10
|
+
"lint:ts": "pnpm exec fgd typecheck",
|
|
11
|
+
"lint": "pnpm exec fgd lint --fix .",
|
|
12
|
+
"lint-check": "pnpm exec fgd lint .",
|
|
13
|
+
"lint:all": "pnpm lint && pnpm lint:ts",
|
|
14
|
+
"poeditor:download": "pnpm exec fg-devkit poeditor-download --format json",
|
|
15
|
+
"poeditor:upload": "pnpm exec fg-devkit poeditor-upload --language sv --file ./src/lang/sv.json"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@tailwindcss/postcss": "4.2.4",
|
|
19
|
+
"@tailwindcss/vite": "4.2.4",
|
|
20
|
+
"@tanstack/vue-query": "5.99.2",
|
|
21
|
+
"axios": "1.15.2",
|
|
22
|
+
"content-disposition-header": "0.6.0",
|
|
23
|
+
"date-fns": "4.1.0",
|
|
24
|
+
"dotenv": "16.4.5",
|
|
25
|
+
"fds-vue-core": "6.2.6",
|
|
26
|
+
"pinia": "3.0.4",
|
|
27
|
+
"qrcode.vue": "3.8.1",
|
|
28
|
+
"vue": "3.5.33",
|
|
29
|
+
"vue-i18n": "11.3.2",
|
|
30
|
+
"vue-router": "4.6.3"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@intlify/unplugin-vue-i18n": "11.0.7",
|
|
34
|
+
"@tanstack/vue-query-devtools": "6.1.20",
|
|
35
|
+
"@types/node": "22.16.5",
|
|
36
|
+
"@vitejs/plugin-vue": "6.0.6",
|
|
37
|
+
"fg-devkit": "1.5.3",
|
|
38
|
+
"start-server-and-test": "2.1.3",
|
|
39
|
+
"tailwindcss": "4.2.4",
|
|
40
|
+
"tsx": "4.21.0",
|
|
41
|
+
"vite": "7.3.2"
|
|
42
|
+
},
|
|
43
|
+
"packageManager": "pnpm@10.17.1"
|
|
44
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { QueryClient } from '@tanstack/vue-query'
|
|
2
|
+
import axios, { type AxiosError, type AxiosRequestConfig, type AxiosResponse } from 'axios'
|
|
3
|
+
import { getApiBaseUrl } from './runtimeConfig'
|
|
4
|
+
|
|
5
|
+
export const api = axios.create({
|
|
6
|
+
timeout: Infinity,
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
api.interceptors.request.use((config) => {
|
|
10
|
+
const baseURL = getApiBaseUrl()
|
|
11
|
+
|
|
12
|
+
if (!baseURL) {
|
|
13
|
+
return Promise.reject(new Error('baseURL missing - request blocked'))
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
config.baseURL = baseURL
|
|
17
|
+
config.headers = config.headers || {}
|
|
18
|
+
|
|
19
|
+
return config
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
type EnhancedAxiosError = AxiosError & { data?: unknown }
|
|
23
|
+
|
|
24
|
+
const handleError = (error: unknown): never => {
|
|
25
|
+
const axiosError = error as AxiosError
|
|
26
|
+
if (axiosError.response?.data) {
|
|
27
|
+
;(axiosError as EnhancedAxiosError).data = axiosError.response.data
|
|
28
|
+
}
|
|
29
|
+
return Promise.reject(axiosError) as never
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const useApi = () => {
|
|
33
|
+
const get = async <T>(url: string, config?: AxiosRequestConfig): Promise<T> => {
|
|
34
|
+
try {
|
|
35
|
+
const { data } = await api.get<T>(url, config)
|
|
36
|
+
return data
|
|
37
|
+
} catch (error) {
|
|
38
|
+
return handleError(error)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const post = async <T>(url: string, body?: unknown, config?: AxiosRequestConfig): Promise<T> => {
|
|
43
|
+
try {
|
|
44
|
+
const { data } = await api.post<T>(url, body, config)
|
|
45
|
+
return data
|
|
46
|
+
} catch (error) {
|
|
47
|
+
return handleError(error)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const postWithResponse = async <T>(
|
|
52
|
+
url: string,
|
|
53
|
+
body?: unknown,
|
|
54
|
+
config?: AxiosRequestConfig,
|
|
55
|
+
): Promise<AxiosResponse<T>> => {
|
|
56
|
+
try {
|
|
57
|
+
return await api.post<T>(url, body, config)
|
|
58
|
+
} catch (error) {
|
|
59
|
+
return handleError(error)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const put = async <T>(url: string, body?: unknown, config?: AxiosRequestConfig): Promise<T> => {
|
|
64
|
+
try {
|
|
65
|
+
const { data } = await api.put<T>(url, body, config)
|
|
66
|
+
return data
|
|
67
|
+
} catch (error) {
|
|
68
|
+
return handleError(error)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const patch = async <T>(url: string, body?: unknown, config?: AxiosRequestConfig): Promise<T> => {
|
|
73
|
+
try {
|
|
74
|
+
const { data } = await api.patch<T>(url, body, config)
|
|
75
|
+
return data
|
|
76
|
+
} catch (error) {
|
|
77
|
+
return handleError(error)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const del = async <T>(url: string, config?: AxiosRequestConfig): Promise<T> => {
|
|
82
|
+
try {
|
|
83
|
+
const { data } = await api.delete<T>(url, config)
|
|
84
|
+
return data
|
|
85
|
+
} catch (error) {
|
|
86
|
+
return handleError(error)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return { get, post, postWithResponse, put, patch, del }
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const NO_RETRY_STATUSES = [400, 401, 403, 404, 406, 409, 422, 498, 500]
|
|
94
|
+
const MAX_RETRIES = 3
|
|
95
|
+
|
|
96
|
+
const retryFunction = (failureCount: number, error: unknown): boolean => {
|
|
97
|
+
if (failureCount >= MAX_RETRIES) return false
|
|
98
|
+
|
|
99
|
+
const axiosError = error as AxiosError
|
|
100
|
+
const status = axiosError?.response?.status
|
|
101
|
+
|
|
102
|
+
return status ? !NO_RETRY_STATUSES.includes(status) : true
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export const queryClient = new QueryClient({
|
|
106
|
+
defaultOptions: {
|
|
107
|
+
queries: {
|
|
108
|
+
retry: retryFunction,
|
|
109
|
+
},
|
|
110
|
+
mutations: {
|
|
111
|
+
retry: retryFunction,
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
})
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
type EnvironmentConstants = {
|
|
2
|
+
environment: 'localhost' | 'development' | 'preprod' | 'production'
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
const local: EnvironmentConstants = {
|
|
6
|
+
environment: 'localhost',
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const development: EnvironmentConstants = {
|
|
10
|
+
environment: 'development',
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const preprod: EnvironmentConstants = {
|
|
14
|
+
environment: 'preprod',
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const production: EnvironmentConstants = {
|
|
18
|
+
environment: 'production',
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Map hostnames to deployment environments. Replace placeholders with your own hosts.
|
|
23
|
+
*/
|
|
24
|
+
const getEnvironment = (): EnvironmentConstants => {
|
|
25
|
+
const { hostname, host } = window.location
|
|
26
|
+
|
|
27
|
+
if (hostname === 'localhost') {
|
|
28
|
+
return local
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
switch (host) {
|
|
32
|
+
case 'PLACEHOLDER_ENV_DEV_HOST':
|
|
33
|
+
return development
|
|
34
|
+
case 'PLACEHOLDER_ENV_PREPROD_HOST':
|
|
35
|
+
return preprod
|
|
36
|
+
case 'PLACEHOLDER_ENV_PROD_HOST':
|
|
37
|
+
return production
|
|
38
|
+
default:
|
|
39
|
+
return local
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const env = getEnvironment()
|
|
44
|
+
|
|
45
|
+
export default env
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { VueQueryPlugin } from '@tanstack/vue-query'
|
|
2
|
+
import FDSVueCore from 'fds-vue-core'
|
|
3
|
+
import { createPinia } from 'pinia'
|
|
4
|
+
import { createApp } from 'vue'
|
|
5
|
+
import { queryClient } from './api/client'
|
|
6
|
+
import { setApiBaseUrlFromConfig } from './api/runtimeConfig'
|
|
7
|
+
import App from './App.vue'
|
|
8
|
+
import i18n from './i18n'
|
|
9
|
+
import router from './router'
|
|
10
|
+
import './style.css'
|
|
11
|
+
|
|
12
|
+
const app = createApp(App)
|
|
13
|
+
const pinia = createPinia()
|
|
14
|
+
|
|
15
|
+
async function bootstrap() {
|
|
16
|
+
const response = await fetch(`${import.meta.env.BASE_URL}config.json`)
|
|
17
|
+
const config = (await response.json()) as Record<string, unknown>
|
|
18
|
+
setApiBaseUrlFromConfig(config)
|
|
19
|
+
|
|
20
|
+
app
|
|
21
|
+
.use(pinia)
|
|
22
|
+
.use(router)
|
|
23
|
+
.use(i18n)
|
|
24
|
+
.use(VueQueryPlugin, { queryClient })
|
|
25
|
+
.use(FDSVueCore)
|
|
26
|
+
app.mount('#app')
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
void bootstrap()
|
|
File without changes
|