Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b239d0b79a | |||
| 671655411b | |||
| 393979bfb2 | |||
| 6e93195cde | |||
| c5685f61f8 | |||
|
|
f6094cff4b |
116
.gitea/workflows/docv-front-runtime-release.yml
Normal file
116
.gitea/workflows/docv-front-runtime-release.yml
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
name: docv-front-runtime-release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- "release/**"
|
||||||
|
paths:
|
||||||
|
- "**/src/lib/docv-sdk/**"
|
||||||
|
- "**/package.json"
|
||||||
|
- "**/package-lock.json"
|
||||||
|
- ".gitea/workflows/docv-front-runtime-release.yml"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
verify-docv-front-runtime-release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
environment: docv-integration
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
origin:
|
||||||
|
- label: test
|
||||||
|
value: https://test.enso.4nkweb.com
|
||||||
|
- label: pprod
|
||||||
|
value: https://pprod.enso.4nkweb.com
|
||||||
|
- label: prod
|
||||||
|
value: https://prod.enso.4nkweb.com
|
||||||
|
env:
|
||||||
|
DOCV_IT_API_BASE: ${{ secrets.DOCV_IT_API_BASE }}
|
||||||
|
DOCV_IT_TOKEN: ${{ secrets.DOCV_IT_TOKEN }}
|
||||||
|
DOCV_IT_FILE_UID: ${{ secrets.DOCV_IT_FILE_UID }}
|
||||||
|
DOCV_IT_FOLDER_UID: ${{ secrets.DOCV_IT_FOLDER_UID }}
|
||||||
|
DOCV_IT_API_VERSION: ${{ secrets.DOCV_IT_API_VERSION }}
|
||||||
|
DOCV_IT_ORIGIN: ${{ matrix.origin.value }}
|
||||||
|
DOCV_IT_REQUIRED: "1"
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: "20"
|
||||||
|
|
||||||
|
- name: Validate integration environment matrix
|
||||||
|
run: |
|
||||||
|
test -n "${DOCV_IT_API_BASE}"
|
||||||
|
test -n "${DOCV_IT_TOKEN}"
|
||||||
|
test -n "${DOCV_IT_FILE_UID}"
|
||||||
|
test -n "${DOCV_IT_FOLDER_UID}"
|
||||||
|
test -n "${DOCV_IT_API_VERSION}"
|
||||||
|
test -n "${DOCV_IT_ORIGIN}"
|
||||||
|
|
||||||
|
- name: Run mandatory DocV runtime integration checks on all fronts
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
mapfile -t docv_surfaces < <(node <<'NODE'
|
||||||
|
const { execSync } = require('node:child_process');
|
||||||
|
const { readFileSync, existsSync } = require('node:fs');
|
||||||
|
const { dirname } = require('node:path');
|
||||||
|
|
||||||
|
const files = execSync('git ls-files "**/package.json"').toString('utf8').trim().split('\n').filter(Boolean);
|
||||||
|
const surfaceSet = new Set();
|
||||||
|
|
||||||
|
for (const packageFile of files) {
|
||||||
|
if (packageFile.includes('/node_modules/')) continue;
|
||||||
|
let raw = '';
|
||||||
|
try {
|
||||||
|
raw = readFileSync(packageFile, 'utf8');
|
||||||
|
} catch {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let pkg = null;
|
||||||
|
try {
|
||||||
|
pkg = JSON.parse(raw);
|
||||||
|
} catch {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const scripts = pkg && typeof pkg.scripts === 'object' ? pkg.scripts : {};
|
||||||
|
const hasRuntimeScripts = Boolean(
|
||||||
|
scripts['test:docv:integration'] &&
|
||||||
|
scripts['ci:docv-it-env'] &&
|
||||||
|
scripts['ci:docv-it-api-version']
|
||||||
|
);
|
||||||
|
if (!hasRuntimeScripts) continue;
|
||||||
|
|
||||||
|
const root = dirname(packageFile);
|
||||||
|
const hasDocvSdkIntegrationFile = existsSync(`${root}/src/lib/docv-sdk/api.integration.test.ts`);
|
||||||
|
const deps = Object.assign({}, pkg.dependencies || {}, pkg.devDependencies || {}, pkg.peerDependencies || {});
|
||||||
|
const hasDocvSdkDependency = Object.prototype.hasOwnProperty.call(deps, '@4nk/docv-sdk');
|
||||||
|
|
||||||
|
if (hasDocvSdkIntegrationFile || hasDocvSdkDependency) {
|
||||||
|
surfaceSet.add(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const surfaces = Array.from(surfaceSet).sort();
|
||||||
|
for (const surface of surfaces) {
|
||||||
|
process.stdout.write(`${surface}\n`);
|
||||||
|
}
|
||||||
|
NODE
|
||||||
|
)
|
||||||
|
if [[ "${#docv_surfaces[@]}" -eq 0 ]]; then
|
||||||
|
echo "[docv-front-runtime-release] no docv runtime integration surface found" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
for surface in "${docv_surfaces[@]}"; do
|
||||||
|
if [[ ! -f "${surface}/package.json" ]]; then
|
||||||
|
echo "[docv-front-runtime-release] missing package.json in ${surface}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
npm --prefix "${surface}" ci
|
||||||
|
npm --prefix "${surface}" run ci:docv-it-env
|
||||||
|
npm --prefix "${surface}" run ci:docv-it-api-version
|
||||||
|
DOCV_IT_REQUIRED=1 npm --prefix "${surface}" run test:docv:integration
|
||||||
|
done
|
||||||
16
.gitea/workflows/no-tracked-dotenv.yml
Normal file
16
.gitea/workflows/no-tracked-dotenv.yml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
name: no-tracked-dotenv
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
verify-no-tracked-dotenv:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Ensure no tracked dotenv files
|
||||||
|
run: bash scripts/check-no-tracked-dotenv-files.sh
|
||||||
@ -41,6 +41,7 @@ export default function DashboardLayout({ children }: { children: React.ReactNod
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const pathname = usePathname()
|
const pathname = usePathname()
|
||||||
const iframeUrl = process.env.NEXT_PUBLIC_4NK_IFRAME_URL || "https://dev3.4nkweb.com"
|
const iframeUrl = process.env.NEXT_PUBLIC_4NK_IFRAME_URL || "https://dev3.4nkweb.com"
|
||||||
|
const isMockAuthEnabled = process.env.NODE_ENV !== "production"
|
||||||
|
|
||||||
const navigation = [
|
const navigation = [
|
||||||
{ name: "Tableau de bord", href: "/dashboard", icon: LayoutDashboard },
|
{ name: "Tableau de bord", href: "/dashboard", icon: LayoutDashboard },
|
||||||
@ -57,15 +58,17 @@ export default function DashboardLayout({ children }: { children: React.ReactNod
|
|||||||
try {
|
try {
|
||||||
const userStore = UserStore.getInstance()
|
const userStore = UserStore.getInstance()
|
||||||
const accessToken = userStore.getAccessToken()
|
const accessToken = userStore.getAccessToken()
|
||||||
|
const refreshToken = userStore.getRefreshToken()
|
||||||
const messageBus = MessageBus.getInstance(iframeUrl)
|
const messageBus = MessageBus.getInstance(iframeUrl)
|
||||||
|
|
||||||
if (accessToken) {
|
if (accessToken) {
|
||||||
// Vérifier si on est en mode mock
|
const isMockSession =
|
||||||
// const mockMode = messageBus.isInMockMode()
|
accessToken === "mock_access_token" &&
|
||||||
// setIsMockMode(mockMode)
|
refreshToken === "mock_refresh_token"
|
||||||
|
|
||||||
if (true) {
|
if (isMockAuthEnabled && isMockSession) {
|
||||||
console.log("🎭 Dashboard en mode mock")
|
console.log("🎭 Dashboard en mode mock")
|
||||||
|
setIsMockMode(true)
|
||||||
setIsAuthenticated(true)
|
setIsAuthenticated(true)
|
||||||
setUserInfo({
|
setUserInfo({
|
||||||
id: "mock_user_001",
|
id: "mock_user_001",
|
||||||
@ -74,22 +77,25 @@ export default function DashboardLayout({ children }: { children: React.ReactNod
|
|||||||
role: "Administrateur",
|
role: "Administrateur",
|
||||||
company: "Entreprise Démo (ID: 1234)",
|
company: "Entreprise Démo (ID: 1234)",
|
||||||
})
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsMockMode(false)
|
||||||
|
|
||||||
|
// Vérifier la validité du token en mode production
|
||||||
|
const isValid = await messageBus.validateToken()
|
||||||
|
if (isValid) {
|
||||||
|
setIsAuthenticated(true)
|
||||||
|
const pairingId = userStore.getUserPairingId()
|
||||||
|
setUserInfo({
|
||||||
|
id: pairingId?.slice(0, 8) + "...",
|
||||||
|
name: "Utilisateur 4NK",
|
||||||
|
email: "user@4nk.io",
|
||||||
|
role: "Utilisateur",
|
||||||
|
company: "Organisation 4NK",
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
// Vérifier la validité du token en mode production
|
setIsAuthModalOpen(true)
|
||||||
const isValid = await messageBus.validateToken()
|
|
||||||
if (isValid) {
|
|
||||||
setIsAuthenticated(true)
|
|
||||||
const pairingId = userStore.getUserPairingId()
|
|
||||||
setUserInfo({
|
|
||||||
id: pairingId?.slice(0, 8) + "...",
|
|
||||||
name: "Utilisateur 4NK",
|
|
||||||
email: "user@4nk.io",
|
|
||||||
role: "Utilisateur",
|
|
||||||
company: "Organisation 4NK",
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
setIsAuthModalOpen(true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setIsAuthModalOpen(true)
|
setIsAuthModalOpen(true)
|
||||||
|
|||||||
@ -28,6 +28,14 @@
|
|||||||
--chart-3: oklch(0.398 0.07 227.392);
|
--chart-3: oklch(0.398 0.07 227.392);
|
||||||
--chart-4: oklch(0.828 0.189 84.429);
|
--chart-4: oklch(0.828 0.189 84.429);
|
||||||
--chart-5: oklch(0.769 0.188 70.08);
|
--chart-5: oklch(0.769 0.188 70.08);
|
||||||
|
--color-chart-series-1: var(--chart-1);
|
||||||
|
--color-chart-series-2: var(--chart-2);
|
||||||
|
--color-chart-series-3: var(--chart-3);
|
||||||
|
--color-chart-series-4: var(--chart-4);
|
||||||
|
--color-chart-series-5: var(--chart-5);
|
||||||
|
--color-chart-series-6: var(--chart-1);
|
||||||
|
--color-chart-series-7: var(--chart-2);
|
||||||
|
--color-chart-series-8: var(--chart-3);
|
||||||
--radius: 0.625rem;
|
--radius: 0.625rem;
|
||||||
--sidebar: oklch(0.985 0 0);
|
--sidebar: oklch(0.985 0 0);
|
||||||
--sidebar-foreground: oklch(0.145 0 0);
|
--sidebar-foreground: oklch(0.145 0 0);
|
||||||
@ -64,6 +72,14 @@
|
|||||||
--chart-3: oklch(0.769 0.188 70.08);
|
--chart-3: oklch(0.769 0.188 70.08);
|
||||||
--chart-4: oklch(0.627 0.265 303.9);
|
--chart-4: oklch(0.627 0.265 303.9);
|
||||||
--chart-5: oklch(0.645 0.246 16.439);
|
--chart-5: oklch(0.645 0.246 16.439);
|
||||||
|
--color-chart-series-1: var(--chart-1);
|
||||||
|
--color-chart-series-2: var(--chart-2);
|
||||||
|
--color-chart-series-3: var(--chart-3);
|
||||||
|
--color-chart-series-4: var(--chart-4);
|
||||||
|
--color-chart-series-5: var(--chart-5);
|
||||||
|
--color-chart-series-6: var(--chart-1);
|
||||||
|
--color-chart-series-7: var(--chart-2);
|
||||||
|
--color-chart-series-8: var(--chart-3);
|
||||||
--sidebar: oklch(0.205 0 0);
|
--sidebar: oklch(0.205 0 0);
|
||||||
--sidebar-foreground: oklch(0.985 0 0);
|
--sidebar-foreground: oklch(0.985 0 0);
|
||||||
--sidebar-primary: oklch(0.488 0.243 264.376);
|
--sidebar-primary: oklch(0.488 0.243 264.376);
|
||||||
|
|||||||
@ -26,6 +26,7 @@ export default function LoginPage() {
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const iframeUrl = process.env.NEXT_PUBLIC_4NK_IFRAME_URL || "https://dev3.4nkweb.com"
|
const iframeUrl = process.env.NEXT_PUBLIC_4NK_IFRAME_URL || "https://dev3.4nkweb.com"
|
||||||
|
const isMockAuthEnabled = process.env.NODE_ENV !== "production"
|
||||||
|
|
||||||
// Vérifier l'état de connexion au chargement
|
// Vérifier l'état de connexion au chargement
|
||||||
useState(() => {
|
useState(() => {
|
||||||
@ -34,6 +35,13 @@ export default function LoginPage() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const handleLogin = () => {
|
const handleLogin = () => {
|
||||||
|
if (isMockAuthEnabled) {
|
||||||
|
const userStore = UserStore.getInstance()
|
||||||
|
userStore.connect("mock_access_token", "mock_refresh_token")
|
||||||
|
router.push("/dashboard")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
setIsAuthModalOpen(true)
|
setIsAuthModalOpen(true)
|
||||||
setError(null)
|
setError(null)
|
||||||
}
|
}
|
||||||
|
|||||||
14
package-lock.json
generated
14
package-lock.json
generated
@ -3732,7 +3732,6 @@
|
|||||||
"integrity": "sha512-EhBeSYX0Y6ye8pNebpKrwFJq7BoQ8J5SO6NlvNwwHjSj6adXJViPQrKlsyPw7hLBLvckEMO1yxeGdR82YBBlDg==",
|
"integrity": "sha512-EhBeSYX0Y6ye8pNebpKrwFJq7BoQ8J5SO6NlvNwwHjSj6adXJViPQrKlsyPw7hLBLvckEMO1yxeGdR82YBBlDg==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
}
|
}
|
||||||
@ -3743,7 +3742,6 @@
|
|||||||
"integrity": "sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw==",
|
"integrity": "sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "^19.0.0"
|
"@types/react": "^19.0.0"
|
||||||
}
|
}
|
||||||
@ -3823,7 +3821,6 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"caniuse-lite": "^1.0.30001733",
|
"caniuse-lite": "^1.0.30001733",
|
||||||
"electron-to-chromium": "^1.5.199",
|
"electron-to-chromium": "^1.5.199",
|
||||||
@ -4151,8 +4148,7 @@
|
|||||||
"version": "8.5.1",
|
"version": "8.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.5.1.tgz",
|
||||||
"integrity": "sha512-JUb5+FOHobSiWQ2EJNaueCNT/cQU9L6XWBbWmorWPQT9bkbk+fhsuLr8wWrzXKagO3oWszBO7MSx+GfaRk4E6A==",
|
"integrity": "sha512-JUb5+FOHobSiWQ2EJNaueCNT/cQU9L6XWBbWmorWPQT9bkbk+fhsuLr8wWrzXKagO3oWszBO7MSx+GfaRk4E6A==",
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/embla-carousel-react": {
|
"node_modules/embla-carousel-react": {
|
||||||
"version": "8.5.1",
|
"version": "8.5.1",
|
||||||
@ -4632,7 +4628,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/next/-/next-15.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/next/-/next-15.2.4.tgz",
|
||||||
"integrity": "sha512-VwL+LAaPSxEkd3lU2xWbgEOtrM8oedmyhBqaVNmgKB+GvZlCy9rgaEc+y2on0wv+l0oSFqLtYD6dcC1eAedUaQ==",
|
"integrity": "sha512-VwL+LAaPSxEkd3lU2xWbgEOtrM8oedmyhBqaVNmgKB+GvZlCy9rgaEc+y2on0wv+l0oSFqLtYD6dcC1eAedUaQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@next/env": "15.2.4",
|
"@next/env": "15.2.4",
|
||||||
"@swc/counter": "0.1.3",
|
"@swc/counter": "0.1.3",
|
||||||
@ -4778,7 +4773,6 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nanoid": "^3.3.11",
|
"nanoid": "^3.3.11",
|
||||||
"picocolors": "^1.1.1",
|
"picocolors": "^1.1.1",
|
||||||
@ -4816,7 +4810,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz",
|
||||||
"integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==",
|
"integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@ -4847,7 +4840,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz",
|
||||||
"integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==",
|
"integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"scheduler": "^0.26.0"
|
"scheduler": "^0.26.0"
|
||||||
},
|
},
|
||||||
@ -4860,7 +4852,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.62.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.62.0.tgz",
|
||||||
"integrity": "sha512-7KWFejc98xqG/F4bAxpL41NB3o1nnvQO1RWZT3TqRZYL8RryQETGfEdVnJN2fy1crCiBLLjkRBVK05j24FxJGA==",
|
"integrity": "sha512-7KWFejc98xqG/F4bAxpL41NB3o1nnvQO1RWZT3TqRZYL8RryQETGfEdVnJN2fy1crCiBLLjkRBVK05j24FxJGA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0"
|
"node": ">=18.0.0"
|
||||||
},
|
},
|
||||||
@ -5153,8 +5144,7 @@
|
|||||||
"version": "4.1.11",
|
"version": "4.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz",
|
||||||
"integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==",
|
"integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==",
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/tailwindcss-animate": {
|
"node_modules/tailwindcss-animate": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.7",
|
||||||
|
|||||||
@ -3,9 +3,10 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"check:theme-tokens": "node scripts/check-global-theme-tokens.mjs",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"lint": "next lint",
|
"lint": "npm run check:theme-tokens && next lint",
|
||||||
"start": "next start"
|
"start": "next start"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
77
scripts/check-global-theme-tokens.mjs
Normal file
77
scripts/check-global-theme-tokens.mjs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import { readFile } from "node:fs/promises";
|
||||||
|
import path from "node:path";
|
||||||
|
import process from "node:process";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = path.dirname(__filename);
|
||||||
|
const projectRoot = path.resolve(__dirname, "..");
|
||||||
|
const cssFiles = ["app/globals.css", "styles/globals.css"];
|
||||||
|
|
||||||
|
const hardcodedColorPattern = /#[\da-fA-F]{3,8}\b|rgba?\(|hsla?\(/;
|
||||||
|
const varFallbackPattern = /var\([^),]+,\s*[^)]+\)/;
|
||||||
|
|
||||||
|
function removeInlineComment(line) {
|
||||||
|
const start = line.indexOf("/*");
|
||||||
|
if (start < 0) {
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
return line.slice(0, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function checkCssFile(relativePath) {
|
||||||
|
const absolutePath = path.join(projectRoot, relativePath);
|
||||||
|
const file = await readFile(absolutePath, "utf8");
|
||||||
|
const lines = file.split(/\r?\n/);
|
||||||
|
const issues = [];
|
||||||
|
|
||||||
|
for (let index = 0; index < lines.length; index += 1) {
|
||||||
|
const lineNumber = index + 1;
|
||||||
|
const line = removeInlineComment(lines[index]).trim();
|
||||||
|
if (!line || line.startsWith("@")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!line.includes(":")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const [property, ...valueParts] = line.split(":");
|
||||||
|
const propertyName = property.trim();
|
||||||
|
const value = valueParts.join(":").trim();
|
||||||
|
if (!propertyName || propertyName.startsWith("--")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (varFallbackPattern.test(value)) {
|
||||||
|
issues.push(`${relativePath}:${lineNumber} forbidden CSS fallback: ${value}`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (hardcodedColorPattern.test(value)) {
|
||||||
|
issues.push(`${relativePath}:${lineNumber} hardcoded color literal/function: ${value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return issues;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const issues = [];
|
||||||
|
for (const cssFile of cssFiles) {
|
||||||
|
issues.push(...(await checkCssFile(cssFile)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (issues.length > 0) {
|
||||||
|
console.error("[check-global-theme-tokens] failed:");
|
||||||
|
for (const issue of issues) {
|
||||||
|
console.error(`- ${issue}`);
|
||||||
|
}
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("[check-global-theme-tokens] OK");
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch((error) => {
|
||||||
|
console.error(`[check-global-theme-tokens] ${String(error)}`);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
49
scripts/check-no-tracked-dotenv-files.sh
Executable file
49
scripts/check-no-tracked-dotenv-files.sh
Executable file
@ -0,0 +1,49 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
TARGET_REPO="${1:-$(pwd)}"
|
||||||
|
ALLOWED_PREFIX="${2:-.secrets/}"
|
||||||
|
TAG="${3:-[check-no-tracked-dotenv]}"
|
||||||
|
ALLOWLIST_FILE="${4:-}"
|
||||||
|
|
||||||
|
if [[ ! -d "${TARGET_REPO}/.git" ]]; then
|
||||||
|
echo "${TAG} ERR not a git repository: ${TARGET_REPO}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
tracked_dotenv="$(
|
||||||
|
git -C "$TARGET_REPO" ls-files | awk -v allowed="$ALLOWED_PREFIX" '
|
||||||
|
/(^|\/)(\.env($|\.|\/)|[^\/]+\.env($|\/))/ {
|
||||||
|
if ($0 !~ ("^" allowed)) print
|
||||||
|
}
|
||||||
|
'
|
||||||
|
)"
|
||||||
|
|
||||||
|
if [[ -n "$ALLOWLIST_FILE" && -f "$ALLOWLIST_FILE" ]]; then
|
||||||
|
filtered_dotenv=""
|
||||||
|
while IFS= read -r dotenv_path; do
|
||||||
|
[[ -z "$dotenv_path" ]] && continue
|
||||||
|
allowed_match=0
|
||||||
|
while IFS= read -r allowed_path; do
|
||||||
|
allowed_trimmed="$(printf '%s' "$allowed_path" | awk '{$1=$1;print}')"
|
||||||
|
[[ -z "$allowed_trimmed" ]] && continue
|
||||||
|
[[ "$allowed_trimmed" == \#* ]] && continue
|
||||||
|
if [[ "$dotenv_path" == "$allowed_trimmed" ]]; then
|
||||||
|
allowed_match=1
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done < "$ALLOWLIST_FILE"
|
||||||
|
if [[ "$allowed_match" -eq 0 ]]; then
|
||||||
|
filtered_dotenv+="${dotenv_path}"$'\n'
|
||||||
|
fi
|
||||||
|
done <<< "$tracked_dotenv"
|
||||||
|
tracked_dotenv="${filtered_dotenv%$'\n'}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$tracked_dotenv" ]]; then
|
||||||
|
echo "${TAG} ERR tracked .env files are forbidden outside ${ALLOWED_PREFIX}" >&2
|
||||||
|
printf '%s\n' "$tracked_dotenv" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "${TAG} OK"
|
||||||
@ -28,6 +28,14 @@
|
|||||||
--chart-3: oklch(0.398 0.07 227.392);
|
--chart-3: oklch(0.398 0.07 227.392);
|
||||||
--chart-4: oklch(0.828 0.189 84.429);
|
--chart-4: oklch(0.828 0.189 84.429);
|
||||||
--chart-5: oklch(0.769 0.188 70.08);
|
--chart-5: oklch(0.769 0.188 70.08);
|
||||||
|
--color-chart-series-1: var(--chart-1);
|
||||||
|
--color-chart-series-2: var(--chart-2);
|
||||||
|
--color-chart-series-3: var(--chart-3);
|
||||||
|
--color-chart-series-4: var(--chart-4);
|
||||||
|
--color-chart-series-5: var(--chart-5);
|
||||||
|
--color-chart-series-6: var(--chart-1);
|
||||||
|
--color-chart-series-7: var(--chart-2);
|
||||||
|
--color-chart-series-8: var(--chart-3);
|
||||||
--radius: 0.625rem;
|
--radius: 0.625rem;
|
||||||
--sidebar: oklch(0.985 0 0);
|
--sidebar: oklch(0.985 0 0);
|
||||||
--sidebar-foreground: oklch(0.145 0 0);
|
--sidebar-foreground: oklch(0.145 0 0);
|
||||||
@ -64,6 +72,14 @@
|
|||||||
--chart-3: oklch(0.769 0.188 70.08);
|
--chart-3: oklch(0.769 0.188 70.08);
|
||||||
--chart-4: oklch(0.627 0.265 303.9);
|
--chart-4: oklch(0.627 0.265 303.9);
|
||||||
--chart-5: oklch(0.645 0.246 16.439);
|
--chart-5: oklch(0.645 0.246 16.439);
|
||||||
|
--color-chart-series-1: var(--chart-1);
|
||||||
|
--color-chart-series-2: var(--chart-2);
|
||||||
|
--color-chart-series-3: var(--chart-3);
|
||||||
|
--color-chart-series-4: var(--chart-4);
|
||||||
|
--color-chart-series-5: var(--chart-5);
|
||||||
|
--color-chart-series-6: var(--chart-1);
|
||||||
|
--color-chart-series-7: var(--chart-2);
|
||||||
|
--color-chart-series-8: var(--chart-3);
|
||||||
--sidebar: oklch(0.205 0 0);
|
--sidebar: oklch(0.205 0 0);
|
||||||
--sidebar-foreground: oklch(0.985 0 0);
|
--sidebar-foreground: oklch(0.985 0 0);
|
||||||
--sidebar-primary: oklch(0.488 0.243 264.376);
|
--sidebar-primary: oklch(0.488 0.243 264.376);
|
||||||
|
|||||||
@ -19,7 +19,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["./*"]
|
"@/*": ["./*"],
|
||||||
|
"@frontend-runtime/*": ["../apps/agent-studio-web/public/shared/frontend-runtime/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||||
|
|||||||
@ -9,6 +9,7 @@ export default defineConfig({
|
|||||||
'@': path.resolve(__dirname, './src'),
|
'@': path.resolve(__dirname, './src'),
|
||||||
'@/components': path.resolve(__dirname, './components'),
|
'@/components': path.resolve(__dirname, './components'),
|
||||||
'@/lib': path.resolve(__dirname, './lib'),
|
'@/lib': path.resolve(__dirname, './lib'),
|
||||||
|
'@frontend-runtime': path.resolve(__dirname, '../apps/agent-studio-web/public/shared/frontend-runtime'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user