feat: Enhance provider components with detailed documentation and comments

- Added comprehensive comments and JSDoc-style documentation to NotificationProvider, ThemeProvider, UserProvider, and WebsiteThemeProvider for better clarity and maintainability.
- Improved type definitions in index.ts for better code understanding and usage.
- Introduced Docker support with Dockerfiles for various services including AI server, signaling server, and browser-use service.
- Created a docker-compose.yml file to orchestrate multiple services including PostgreSQL, AI, scraper, and frontend.
- Added a startup guide (startup.txt) for setting up the CRM environment on Ubuntu with Docker.
- Included a .dockerignore file to exclude unnecessary files from Docker builds.
This commit is contained in:
Ace
2026-07-13 13:05:30 +02:00
parent dba4c84cd5
commit d35c806d5b
167 changed files with 3474 additions and 102 deletions
+20 -5
View File
@@ -15,12 +15,14 @@ import { platform } from "node:os"
import { resolve, dirname } from "node:path"
import { fileURLToPath } from "node:url"
// Shell command separator differs per platform (Windows uses &, POSIX uses ;)
const SEP = platform() === "win32" ? "&" : ";"
const SELF = dirname(fileURLToPath(import.meta.url))
const ROOT = resolve(SELF, "..")
// ── Helpers ────────────────────────────────────────────────────────
/** Try known Python command names until one succeeds, then exit if none found. */
function detectPython() {
const candidates = platform() === "win32" ? ["python", "python3"] : ["python3", "python"]
for (const cmd of candidates) {
@@ -33,6 +35,7 @@ function detectPython() {
process.exit(1)
}
/** Detect pip; fall back to `python -m pip` if no standalone pip binary exists. */
function detectPip(python) {
const candidates = platform() === "win32" ? ["pip", "pip3"] : ["pip3", "pip"]
for (const cmd of candidates) {
@@ -44,6 +47,7 @@ function detectPip(python) {
return `${python} -m pip`
}
/** Run a shell command with label output. Exits on failure unless opts.optional is set. */
function run(cmd, label, opts = {}) {
console.log(`\n── ${label} ──`)
try {
@@ -60,11 +64,15 @@ function run(cmd, label, opts = {}) {
}
// ── Self-Healing Module Registry ───────────────────────────────────
// Maps internal import paths (like @/data/stickers) to template files.
// Supports custom templates in .setup-templates/ that override built-ins.
// Fallback patterns catch whole directories (e.g. @/hooks/* → hook-generic.ts).
function loadRegistry() {
const registryPath = resolve(ROOT, ".setup-templates", "registry.json")
const templatesDir = resolve(ROOT, ".setup-templates", "templates")
// Hard-coded templates for commonly imported modules
const builtInTemplates = {
"data/stickers": { template: "stickers.ts" },
"data/constants": { template: "constants.ts" },
@@ -75,6 +83,7 @@ function loadRegistry() {
"hooks/use-local-storage": { template: "hooks/use-local-storage.ts" },
}
// Catch-all fallbacks for entire directory prefixes
const builtInFallbacks = {
"@/data/*": "data-generic.ts",
"@/lib/*": "lib-generic.ts",
@@ -87,6 +96,7 @@ function loadRegistry() {
let templates = { ...builtInTemplates }
let fallbacks = { ...builtInFallbacks }
// Merge custom templates from .setup-templates/registry.json (if it exists)
try {
if (existsSync(registryPath)) {
const custom = JSON.parse(readFileSync(registryPath, "utf-8"))
@@ -97,6 +107,7 @@ function loadRegistry() {
const templateCache = {}
/** Read a template file, checking the custom templates dir first, then hooks subdirectory. */
function getTemplate(templateName) {
if (templateCache[templateName]) return templateCache[templateName]
const candidatePaths = [
@@ -113,6 +124,7 @@ function loadRegistry() {
return ""
}
/** Convert a glob pattern (e.g. @/hooks/*) to a regex and test against the internal path. */
function matchFallback(internalPath) {
for (const [pattern, templateFile] of Object.entries(fallbacks)) {
const regexStr = "^" + pattern
@@ -125,6 +137,7 @@ function loadRegistry() {
return null
}
/** Generate (or regenerate) a single module file from its template. */
function generateModule(internalPath) {
let templateFile = templates[internalPath]?.template
if (!templateFile) templateFile = matchFallback(internalPath)
@@ -143,6 +156,7 @@ function loadRegistry() {
return { generateModule }
}
/** Parse `tsc --noEmit` or `npm run build` output for missing-module errors, returning unique import paths. */
function parseMissingModules(buildOutput) {
const results = []
const seen = new Set()
@@ -177,21 +191,22 @@ function parseMissingModules(buildOutput) {
// ── Main ───────────────────────────────────────────────────────────
// Detect Python and pip executables before running any steps
const PY = detectPython()
const PIP = detectPip(PY)
console.log("=== CoastIT CRM Setup ===\n")
// 1. Node dependencies
// Step 1 — Install all Node.js dependencies (includes next, react, etc.)
run("npm install", "Installing Node.js dependencies")
// 2. Python dependencies
// Step 2 — Install Python deps for the browser-use service (Playwright-based scraper)
run(`cd browser-use-service ${SEP} ${PIP} install -r requirements.txt`, "Installing Python dependencies")
// 3. Playwright browsers
// Step 3 — Download Playwright browser binaries for scraper automation
run(`${PY} -m playwright install firefox chromium`, "Installing Playwright browsers")
// 4. .env file
// Step 4 — Bootstrap .env.local from the example template (won't overwrite existing)
if (!existsSync(resolve(ROOT, ".env.local"))) {
console.log("\n── Creating .env.local ──")
copyFileSync(resolve(ROOT, ".env.example"), resolve(ROOT, ".env.local"))
@@ -200,7 +215,7 @@ if (!existsSync(resolve(ROOT, ".env.local"))) {
console.log("\n── .env.local already exists, skipping ──")
}
// 5. Final summary
// Step 5 — Print post-setup instructions
console.log("\n── Final Steps ──")
console.log(" 1. Make sure PostgreSQL is running with database 'crm'")
console.log(" 2. Pull the Ollama model: ollama pull dolphin-llama3:8b")