chore: bump version to 1.3.6 and remove unused dependencies
- Remove `react-email`, `react-grid-layout` from dependencies - Remove `tailwindcss`, `@tailwindcss/cli`, `@tailwindcss/postcss`, `autoprefixer`, `postcss`, and `typescript` from devDependencies - Update package-lock.json to reflect dependency removals - Bump package version from 1.3.5 to 1.3.6
This commit is contained in:
Generated
+76
-2162
File diff suppressed because it is too large
Load Diff
+2
-10
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@zen/core",
|
"name": "@zen/core",
|
||||||
"version": "1.3.5",
|
"version": "1.3.6",
|
||||||
"description": "Un CMS construit sur l'essentiel, rien de plus, rien de moins.",
|
"description": "Un CMS construit sur l'essentiel, rien de plus, rien de moins.",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -32,21 +32,13 @@
|
|||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"node-cron": "^3.0.3",
|
"node-cron": "^3.0.3",
|
||||||
"pg": "^8.11.3",
|
"pg": "^8.11.3",
|
||||||
"react-email": "^4.3.0",
|
|
||||||
"react-grid-layout": "^1.5.2",
|
|
||||||
"resend": "^3.2.0",
|
"resend": "^3.2.0",
|
||||||
"stripe": "^14.0.0"
|
"stripe": "^14.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/cli": "^4.2.1",
|
|
||||||
"@tailwindcss/postcss": "^4",
|
|
||||||
"autoprefixer": "^10.4.0",
|
|
||||||
"postcss": "^8.4.0",
|
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"tailwindcss": "^4",
|
"tsup": "^8.0.0"
|
||||||
"tsup": "^8.0.0",
|
|
||||||
"typescript": "^5.0.0"
|
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"next": ">=14.0.0",
|
"next": ">=14.0.0",
|
||||||
|
|||||||
@@ -1,362 +0,0 @@
|
|||||||
/**
|
|
||||||
* Dynamic API Router
|
|
||||||
* Routes incoming requests to appropriate handlers
|
|
||||||
* Supports both core routes and dynamically discovered module routes
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { validateSession } from '../../features/auth/lib/session.js';
|
|
||||||
import { cookies } from 'next/headers';
|
|
||||||
import { getSessionCookieName } from '../../shared/lib/appConfig.js';
|
|
||||||
import { checkRateLimit, getIpFromRequest, formatRetryAfter } from '../../features/auth/lib/rateLimit.js';
|
|
||||||
|
|
||||||
// Core handlers
|
|
||||||
import { handleHealth } from './handlers/health.js';
|
|
||||||
import { handleVersion } from './handlers/version.js';
|
|
||||||
import {
|
|
||||||
handleGetCurrentUser,
|
|
||||||
handleGetUserById,
|
|
||||||
handleListUsers,
|
|
||||||
handleUpdateProfile,
|
|
||||||
handleUpdateUserById,
|
|
||||||
handleUploadProfilePicture,
|
|
||||||
handleDeleteProfilePicture
|
|
||||||
} from './handlers/users.js';
|
|
||||||
import { handleGetFile } from './handlers/storage.js';
|
|
||||||
import updatesHandler from './handlers/updates.js';
|
|
||||||
|
|
||||||
// Get cookie name from environment or use default
|
|
||||||
const COOKIE_NAME = getSessionCookieName();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CSRF origin check — mirrors the implementation in router.js.
|
|
||||||
* Applied here so the dynamic router cannot be used as a bypass vector.
|
|
||||||
* @param {Request} request
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
function passesCsrfCheck(request) {
|
|
||||||
const safeMethods = new Set(['GET', 'HEAD', 'OPTIONS']);
|
|
||||||
if (safeMethods.has(request.method)) return true;
|
|
||||||
|
|
||||||
const appUrl = process.env.ZEN_APP_URL;
|
|
||||||
if (!appUrl) {
|
|
||||||
console.error('[ZEN CSRF] ZEN_APP_URL is not set — CSRF origin check is ENFORCED DENY. Configure this variable immediately.');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let expectedOrigin;
|
|
||||||
try {
|
|
||||||
expectedOrigin = new URL(appUrl).origin;
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const origin = request.headers.get('origin');
|
|
||||||
if (origin) return origin === expectedOrigin;
|
|
||||||
|
|
||||||
const referer = request.headers.get('referer');
|
|
||||||
if (referer) {
|
|
||||||
try { return new URL(referer).origin === expectedOrigin; } catch { return false; }
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if user is authenticated
|
|
||||||
* @param {Request} request - The request object
|
|
||||||
* @returns {Promise<Object>} Session object if authenticated
|
|
||||||
* @throws {Error} If not authenticated
|
|
||||||
*/
|
|
||||||
async function requireAuth(request) {
|
|
||||||
const cookieStore = await cookies();
|
|
||||||
const sessionToken = cookieStore.get(COOKIE_NAME)?.value;
|
|
||||||
|
|
||||||
if (!sessionToken) {
|
|
||||||
throw new Error('Unauthorized');
|
|
||||||
}
|
|
||||||
|
|
||||||
const session = await validateSession(sessionToken);
|
|
||||||
|
|
||||||
if (!session || !session.user) {
|
|
||||||
throw new Error('Unauthorized');
|
|
||||||
}
|
|
||||||
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if user is authenticated and is admin
|
|
||||||
* @param {Request} request - The request object
|
|
||||||
* @returns {Promise<Object>} Session object if authenticated and admin
|
|
||||||
* @throws {Error} If not authenticated or not admin
|
|
||||||
*/
|
|
||||||
async function requireAdmin(request) {
|
|
||||||
const session = await requireAuth(request);
|
|
||||||
|
|
||||||
if (session.user.role !== 'admin') {
|
|
||||||
throw new Error('Admin access required');
|
|
||||||
}
|
|
||||||
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Route an API request to the appropriate handler
|
|
||||||
* @param {Request} request - The incoming request
|
|
||||||
* @param {string[]} path - The path segments after /zen/api/
|
|
||||||
* @returns {Promise<Object>} - The response data
|
|
||||||
*/
|
|
||||||
export async function routeRequest(request, path) {
|
|
||||||
const method = request.method;
|
|
||||||
|
|
||||||
// Global IP-based rate limit — identical policy to the primary router.
|
|
||||||
// Health and version are exempt; all other endpoints are throttled.
|
|
||||||
const isExempt = (path[0] === 'health' || path[0] === 'version') && method === 'GET';
|
|
||||||
if (!isExempt) {
|
|
||||||
const ip = getIpFromRequest(request);
|
|
||||||
const rl = checkRateLimit(ip, 'api');
|
|
||||||
if (!rl.allowed) {
|
|
||||||
return {
|
|
||||||
error: 'Too Many Requests',
|
|
||||||
message: `Trop de requêtes. Réessayez dans ${formatRetryAfter(rl.retryAfterMs)}.`
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CSRF origin validation for state-mutating requests.
|
|
||||||
if (!passesCsrfCheck(request)) {
|
|
||||||
return { error: 'Forbidden', message: 'CSRF validation failed' };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try core routes first
|
|
||||||
const coreResult = await routeCoreRequest(request, path, method);
|
|
||||||
if (coreResult !== null) {
|
|
||||||
return coreResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try module routes
|
|
||||||
const moduleResult = await routeModuleRequest(request, path, method);
|
|
||||||
if (moduleResult !== null) {
|
|
||||||
return moduleResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
// No matching route — generic message prevents route structure enumeration.
|
|
||||||
return {
|
|
||||||
error: 'Not Found',
|
|
||||||
message: 'The requested resource does not exist'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Route core (non-module) requests
|
|
||||||
* @param {Request} request - The incoming request
|
|
||||||
* @param {string[]} path - The path segments
|
|
||||||
* @param {string} method - HTTP method
|
|
||||||
* @returns {Promise<Object|null>} Response or null if no match
|
|
||||||
*/
|
|
||||||
async function routeCoreRequest(request, path, method) {
|
|
||||||
// Health check endpoint
|
|
||||||
if (path[0] === 'health' && method === 'GET') {
|
|
||||||
return await handleHealth();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Version endpoint — authentication required; see handlers/version.js
|
|
||||||
if (path[0] === 'version' && method === 'GET') {
|
|
||||||
return await handleVersion(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Updates endpoint
|
|
||||||
if (path[0] === 'updates' && method === 'GET') {
|
|
||||||
return await updatesHandler(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Storage endpoint - serve files securely
|
|
||||||
if (path[0] === 'storage' && method === 'GET') {
|
|
||||||
const fileKey = path.slice(1).join('/');
|
|
||||||
if (!fileKey) {
|
|
||||||
return {
|
|
||||||
error: 'Bad Request',
|
|
||||||
message: 'File path is required'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return await handleGetFile(request, fileKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
// User endpoints
|
|
||||||
if (path[0] === 'users') {
|
|
||||||
// GET /zen/api/users - List all users (admin only)
|
|
||||||
if (path.length === 1 && method === 'GET') {
|
|
||||||
return await handleListUsers(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GET /zen/api/users/me - Get current user
|
|
||||||
if (path[1] === 'me' && method === 'GET') {
|
|
||||||
return await handleGetCurrentUser(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
// PUT /zen/api/users/profile - Update current user profile
|
|
||||||
if (path[1] === 'profile' && method === 'PUT') {
|
|
||||||
return await handleUpdateProfile(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
// POST /zen/api/users/profile/picture - Upload profile picture
|
|
||||||
if (path[1] === 'profile' && path[2] === 'picture' && method === 'POST') {
|
|
||||||
return await handleUploadProfilePicture(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
// DELETE /zen/api/users/profile/picture - Delete profile picture
|
|
||||||
if (path[1] === 'profile' && path[2] === 'picture' && method === 'DELETE') {
|
|
||||||
return await handleDeleteProfilePicture(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GET /zen/api/users/:id - Get user by ID (admin only)
|
|
||||||
if (path[1] && path[1] !== 'me' && path[1] !== 'profile' && method === 'GET') {
|
|
||||||
return await handleGetUserById(request, path[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// PUT /zen/api/users/:id - Update user by ID (admin only)
|
|
||||||
if (path[1] && path[1] !== 'me' && path[1] !== 'profile' && method === 'PUT') {
|
|
||||||
return await handleUpdateUserById(request, path[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Route module requests
|
|
||||||
* @param {Request} request - The incoming request
|
|
||||||
* @param {string[]} path - The path segments
|
|
||||||
* @param {string} method - HTTP method
|
|
||||||
* @returns {Promise<Object|null>} Response or null if no match
|
|
||||||
*/
|
|
||||||
async function routeModuleRequest(request, path, method) {
|
|
||||||
try {
|
|
||||||
// Import module registry
|
|
||||||
const { getAllApiRoutes } = await import('../modules/registry.js');
|
|
||||||
const routes = getAllApiRoutes();
|
|
||||||
|
|
||||||
// Convert path array to path string
|
|
||||||
const pathString = '/' + path.join('/');
|
|
||||||
|
|
||||||
// Find matching route
|
|
||||||
for (const route of routes) {
|
|
||||||
if (matchRoute(route.path, pathString) && route.method === method) {
|
|
||||||
// Check authentication
|
|
||||||
try {
|
|
||||||
if (route.auth === 'admin') {
|
|
||||||
await requireAdmin(request);
|
|
||||||
} else if (route.auth === 'user' || route.auth === 'auth') {
|
|
||||||
await requireAuth(request);
|
|
||||||
}
|
|
||||||
// 'public' or undefined means no auth required
|
|
||||||
|
|
||||||
// Call the handler
|
|
||||||
if (typeof route.handler === 'function') {
|
|
||||||
// Extract path parameters
|
|
||||||
const params = extractPathParams(route.path, pathString);
|
|
||||||
return await route.handler(request, params);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
// Only known auth-error strings are safe to surface; all other
|
|
||||||
// exceptions are logged server-side and returned as a generic message.
|
|
||||||
const SAFE_AUTH_MESSAGES = new Set(['Unauthorized', 'Admin access required']);
|
|
||||||
if (!SAFE_AUTH_MESSAGES.has(err.message)) {
|
|
||||||
console.error('[ZEN] Module route handler error:', err);
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
error: SAFE_AUTH_MESSAGES.has(err.message) ? err.message : 'Internal Server Error'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('[Dynamic Router] Error routing module request:', error);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Match a route pattern against a path
|
|
||||||
* Supports path parameters like :id
|
|
||||||
* @param {string} pattern - Route pattern (e.g., '/admin/invoices/:id')
|
|
||||||
* @param {string} path - Actual path (e.g., '/admin/invoices/123')
|
|
||||||
* @returns {boolean} True if matches
|
|
||||||
*/
|
|
||||||
function matchRoute(pattern, path) {
|
|
||||||
const patternParts = pattern.split('/').filter(Boolean);
|
|
||||||
const pathParts = path.split('/').filter(Boolean);
|
|
||||||
|
|
||||||
if (patternParts.length !== pathParts.length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < patternParts.length; i++) {
|
|
||||||
const patternPart = patternParts[i];
|
|
||||||
const pathPart = pathParts[i];
|
|
||||||
|
|
||||||
// Skip parameter parts (they match anything)
|
|
||||||
if (patternPart.startsWith(':')) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (patternPart !== pathPart) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract path parameters from a path
|
|
||||||
* @param {string} pattern - Route pattern (e.g., '/admin/invoices/:id')
|
|
||||||
* @param {string} path - Actual path (e.g., '/admin/invoices/123')
|
|
||||||
* @returns {Object} Path parameters
|
|
||||||
*/
|
|
||||||
function extractPathParams(pattern, path) {
|
|
||||||
const params = {};
|
|
||||||
const patternParts = pattern.split('/').filter(Boolean);
|
|
||||||
const pathParts = path.split('/').filter(Boolean);
|
|
||||||
|
|
||||||
for (let i = 0; i < patternParts.length; i++) {
|
|
||||||
const patternPart = patternParts[i];
|
|
||||||
|
|
||||||
if (patternPart.startsWith(':')) {
|
|
||||||
const paramName = patternPart.slice(1);
|
|
||||||
params[paramName] = pathParts[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return params;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the HTTP status code based on the response
|
|
||||||
* @param {Object} response - The response object
|
|
||||||
* @returns {number} - HTTP status code
|
|
||||||
*/
|
|
||||||
export function getStatusCode(response) {
|
|
||||||
if (response.error) {
|
|
||||||
switch (response.error) {
|
|
||||||
case 'Unauthorized':
|
|
||||||
return 401;
|
|
||||||
case 'Forbidden':
|
|
||||||
case 'Admin access required':
|
|
||||||
return 403;
|
|
||||||
case 'Not Found':
|
|
||||||
return 404;
|
|
||||||
case 'Bad Request':
|
|
||||||
return 400;
|
|
||||||
default:
|
|
||||||
return 500;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 200;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Export auth helpers for use in module handlers
|
|
||||||
export { requireAuth, requireAdmin };
|
|
||||||
@@ -1,9 +1,3 @@
|
|||||||
export const Invoice03Icon = (props) => (
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width={24} height={24} color={"currentColor"} fill={"none"} {...props}>
|
|
||||||
<path fillRule="evenodd" clipRule="evenodd" d="M10 22.75C9.7007 22.75 9.44762 22.6611 9.2239 22.5507C9.02352 22.4518 8.80135 22.3117 8.56674 22.1637L8.5667 22.1636L6.62905 20.9417C6.37416 20.7809 6.22825 20.6899 6.11404 20.6327C6.0083 20.5747 5.93256 20.6033 5.9079 20.6249C5.7948 20.678 5.64376 20.7696 5.37095 20.9417L4.86225 21.2911C4.65149 21.4359 4.39744 21.6033 4.12709 21.7447C3.655 21.9917 2.81435 22.3299 2.05584 21.8414C1.54247 21.5107 1.38152 20.9658 1.3149 20.487C1.24992 20.0198 1.24996 19.4095 1.25 18.7008L1.25 7.99976C1.24998 6.61906 1.24997 5.50754 1.36641 4.63362C1.48716 3.72735 1.74526 2.96484 2.34597 2.35869C2.94761 1.75161 3.70602 1.48992 4.60737 1.36764C5.47476 1.24997 6.57745 1.24998 7.94463 1.25H7.94464H7.94466H7.94471H10H20.016C20.4911 1.25 20.8802 1.4793 21.1687 1.7609C21.4541 2.03946 21.6847 2.40829 21.8722 2.81006C22.2486 3.61642 22.5188 4.70246 22.6626 5.91555L22.6684 5.96436V5.96438V5.9644V5.96442V5.96444C22.7158 6.36378 22.7614 6.74778 22.7473 7.07225C22.7309 7.4502 22.6325 7.83058 22.3326 8.16518C22.0239 8.50953 21.6366 8.64316 21.2576 8.69983C20.921 8.75013 20.5084 8.75007 20.0646 8.75001L20.016 8.75H18.75L18.75 18.7008V18.7009C18.75 19.4096 18.7501 20.0198 18.6851 20.487C18.6185 20.9658 18.4575 21.5107 17.9441 21.8414C17.1856 22.3299 16.345 21.9917 15.8729 21.7447C15.6025 21.6033 15.3485 21.4359 15.1377 21.2911L14.629 20.9417C14.3562 20.7696 14.2052 20.678 14.0921 20.6249C14.0674 20.6033 13.9917 20.5747 13.8859 20.6327C13.7717 20.6899 13.6258 20.7809 13.3709 20.9417L11.4333 22.1636C11.1987 22.3116 10.9765 22.4518 10.7761 22.5507C10.5524 22.6611 10.2993 22.75 10 22.75ZM19.8186 2.93803C19.9219 2.80796 19.9892 2.76622 20.0165 2.75367C20.0343 2.76222 20.069 2.78358 20.121 2.83431C20.2313 2.94204 20.3694 3.13683 20.513 3.44447C20.7989 4.05692 21.0404 4.97278 21.173 6.09207C21.2283 6.55875 21.2569 6.81923 21.2487 7.00716C21.2426 7.14751 21.2183 7.16254 21.2153 7.16437C21.2118 7.16832 21.2095 7.17082 21.1969 7.17658C21.1776 7.18544 21.1317 7.20197 21.0358 7.21631C20.8236 7.24804 20.5254 7.25 20.016 7.25H18.7663C18.7682 7.20712 18.7702 7.16442 18.7724 7.12189C18.836 5.88595 19.0311 4.80062 19.3014 3.99624C19.3119 3.96507 19.3224 3.93447 19.333 3.90445C19.4918 3.45423 19.6624 3.13461 19.8186 2.93803ZM6 5.25C5.58579 5.25 5.25 5.58579 5.25 6C5.25 6.41421 5.58579 6.75 6 6.75H14C14.4142 6.75 14.75 6.41421 14.75 6C14.75 5.58579 14.4142 5.25 14 5.25H6ZM8.75 10C8.75 10.4142 8.41422 10.75 8 10.75H6C5.58579 10.75 5.25 10.4142 5.25 10C5.25 9.58579 5.58579 9.25 6 9.25H8C8.41422 9.25 8.75 9.58579 8.75 10ZM13.25 10C13.25 9.58579 12.9142 9.25 12.5 9.25C12.0858 9.25 11.75 9.58579 11.75 10V10.2449C10.916 10.517 10.25 11.2324 10.25 12.1875C10.25 13.4175 11.3546 14.25 12.5 14.25C13.0114 14.25 13.25 14.5928 13.25 14.8125C13.25 15.0322 13.0114 15.375 12.5 15.375C12.1136 15.375 11.8582 15.1608 11.7808 14.9691C11.6256 14.585 11.1885 14.3995 10.8045 14.5546C10.4204 14.7097 10.2348 15.1468 10.3899 15.5309C10.6304 16.1261 11.1404 16.5603 11.75 16.7573V17C11.75 17.4142 12.0858 17.75 12.5 17.75C12.9142 17.75 13.25 17.4142 13.25 17V16.7551C14.084 16.483 14.75 15.7676 14.75 14.8125C14.75 13.5825 13.6454 12.75 12.5 12.75C11.9886 12.75 11.75 12.4072 11.75 12.1875C11.75 11.9678 11.9886 11.625 12.5 11.625C12.8864 11.625 13.1418 11.8392 13.2192 12.0309C13.3744 12.415 13.8115 12.6005 14.1956 12.4454C14.5796 12.2903 14.7652 11.8532 14.6101 11.4691C14.3696 10.8739 13.8596 10.4397 13.25 10.2427V10Z" fill="currentColor"></path>
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
export const ChevronDownIcon = (props) => (
|
export const ChevronDownIcon = (props) => (
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width={16} height={16} color={"currentColor"} fill={"none"} {...props}>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width={16} height={16} color={"currentColor"} fill={"none"} {...props}>
|
||||||
@@ -342,12 +336,6 @@ export const CancelCircleIcon = (props) => (
|
|||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|
||||||
export const Invoice04Icon = (props) => (
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width={24} height={24} color={"currentColor"} fill={"none"} {...props}>
|
|
||||||
<path fillRule="evenodd" clipRule="evenodd" d="M10.9917 21.8163C9.99781 23.0612 7.97828 23.0612 6.98434 21.8163L6.43326 21.1261C6.3636 21.0389 6.23198 20.9736 6.06421 20.9816C5.89617 20.9896 5.78156 21.066 5.72902 21.1494C5.30689 21.8191 4.58616 22.06 3.95942 22.0124C3.35027 21.9661 2.6841 21.6344 2.37482 20.9755C2.18146 20.6744 2.25512 19.9988 2.31612 19.6987L4.24708 10.5615C4.47973 9.46055 4.66851 8.56723 4.90773 7.86925C5.15714 7.14153 5.48722 6.54343 6.05242 6.08663C6.61716 5.63021 7.2714 5.43226 8.03598 5.33927C8.77022 5.24997 9.68609 5.24998 10.8162 5.25H10.8163H10.8163H13.1837H13.1837H13.1838C14.3139 5.24998 15.2298 5.24997 15.964 5.33927C16.7286 5.43226 17.3828 5.63021 17.9476 6.08663C18.5128 6.54343 18.8429 7.14153 19.0923 7.86925C19.3315 8.5672 19.5203 9.46049 19.7529 10.5614L19.7529 10.5615L19.7529 10.5615L21.6839 19.6987C21.7449 19.9988 21.8185 20.6744 21.6252 20.9755C21.3159 21.6344 20.6497 21.9661 20.0406 22.0124C19.4138 22.06 18.6931 21.8191 18.271 21.1494C18.2184 21.066 18.1038 20.9896 17.9358 20.9816C17.768 20.9736 17.6364 21.0389 17.5667 21.1261L17.0157 21.8163C16.0217 23.0612 14.0022 23.0612 13.0083 21.8163C12.7897 21.5426 12.3515 21.2972 12 21.2972C11.6485 21.2972 11.2103 21.5426 10.9917 21.8163ZM12.75 10C12.75 9.58579 12.4142 9.25 12 9.25H9C8.58579 9.25 8.25 9.58579 8.25 10C8.25 10.4142 8.58579 10.75 9 10.75H12C12.4142 10.75 12.75 10.4142 12.75 10ZM14 13.25C14.4142 13.25 14.75 13.5858 14.75 14C14.75 14.4142 14.4142 14.75 14 14.75H8C7.58579 14.75 7.25 14.4142 7.25 14C7.25 13.5858 7.58579 13.25 8 13.25H14Z" fill="currentColor" />
|
|
||||||
<path fillRule="evenodd" clipRule="evenodd" d="M6.07495 1.25C6.09695 1.25 6.11902 1.25001 6.14117 1.25001L17.9252 1.25C18.7891 1.24995 19.5372 1.24991 20.1371 1.33111C20.7842 1.41873 21.4008 1.61673 21.8969 2.11636C22.3881 2.61093 22.5779 3.21692 22.6626 3.8511C22.7422 4.44779 22.7422 5.19468 22.7422 6.06963L22.7422 6.13062C22.7422 6.36995 22.7443 6.59989 22.7464 6.81886C22.7517 7.38963 22.7563 7.88588 22.7203 8.2796C22.6644 8.89092 22.5004 9.45974 22.0039 9.95966C21.6296 10.3366 21.011 10.348 20.6221 9.98514C20.2333 9.62228 20.2215 9.02255 20.5958 8.64561C20.6714 8.56951 20.7398 8.4794 20.7734 8.11226C20.8005 7.81569 20.7972 7.46151 20.7924 6.95031C20.7901 6.71393 20.7876 6.44398 20.7876 6.13062C20.7876 5.17774 20.7857 4.55487 20.7242 4.0943C20.6658 3.65741 20.5697 3.51185 20.4888 3.43041C20.4129 3.35402 20.2832 3.26402 19.8667 3.20764C19.4182 3.14691 18.8083 3.14474 17.8589 3.14474L6.14117 3.14474C5.19187 3.14474 4.58196 3.14691 4.13342 3.20764C3.71692 3.26402 3.58717 3.35402 3.51132 3.43041C3.43044 3.51185 3.33428 3.6574 3.27594 4.0943C3.21445 4.55487 3.21253 5.17774 3.21253 6.13062C3.21253 6.44562 3.20993 6.71673 3.20767 6.95398C3.2028 7.46333 3.19942 7.81653 3.22639 8.11257C3.25986 8.47981 3.32825 8.5697 3.40363 8.64561C3.77795 9.02255 3.76618 9.62228 3.37734 9.98514C2.9885 10.348 2.36983 10.3366 1.9955 9.95966C1.49887 9.45955 1.33511 8.89051 1.27941 8.27929C1.24362 7.88646 1.24831 7.39125 1.2537 6.82187C1.25578 6.60197 1.25796 6.37102 1.25796 6.13062C1.25796 6.11022 1.25796 6.08988 1.25796 6.06962C1.25792 5.19467 1.25788 4.44779 1.33755 3.8511C1.42222 3.21692 1.61206 2.61093 2.10319 2.11636C2.59935 1.61673 3.21592 1.41873 3.86306 1.33111C4.46288 1.24991 5.21101 1.24995 6.07495 1.25Z" fill="currentColor" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
|
|
||||||
export const Link02Icon = (props) => (
|
export const Link02Icon = (props) => (
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width={24} height={24} color={"currentColor"} fill={"none"} {...props}>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width={24} height={24} color={"currentColor"} fill={"none"} {...props}>
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ export default defineConfig([
|
|||||||
'src/core/api/nx-route.js',
|
'src/core/api/nx-route.js',
|
||||||
'src/core/database/index.js',
|
'src/core/database/index.js',
|
||||||
'src/cli/database.js',
|
'src/cli/database.js',
|
||||||
'src/cli/setup.js',
|
|
||||||
'src/core/email/index.js',
|
'src/core/email/index.js',
|
||||||
'src/core/email/templates/index.js',
|
'src/core/email/templates/index.js',
|
||||||
'src/core/storage/index.js',
|
'src/core/storage/index.js',
|
||||||
@@ -33,9 +32,6 @@ export default defineConfig([
|
|||||||
'src/modules/*/actions.js',
|
'src/modules/*/actions.js',
|
||||||
'src/modules/*/api.js',
|
'src/modules/*/api.js',
|
||||||
'src/modules/*/crud.js',
|
'src/modules/*/crud.js',
|
||||||
'src/modules/**/statsActions.js',
|
|
||||||
'src/modules/invoice/dashboard/index.js',
|
|
||||||
'src/modules/nuage/dashboard/index.js',
|
|
||||||
'src/shared/lib/metadata/index.js',
|
'src/shared/lib/metadata/index.js',
|
||||||
],
|
],
|
||||||
format: ['esm'],
|
format: ['esm'],
|
||||||
|
|||||||
Reference in New Issue
Block a user