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:
+20
-5
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user