monorepotime 1.1.12 → 1.1.14
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/dist/index.js
CHANGED
|
@@ -55247,7 +55247,7 @@ __export(index_exports, {
|
|
|
55247
55247
|
io: () => io2
|
|
55248
55248
|
});
|
|
55249
55249
|
module.exports = __toCommonJS(index_exports);
|
|
55250
|
-
var
|
|
55250
|
+
var import_express25 = __toESM(require_express2());
|
|
55251
55251
|
var import_cors = __toESM(require_lib3());
|
|
55252
55252
|
var import_path19 = __toESM(require("path"));
|
|
55253
55253
|
|
|
@@ -56729,12 +56729,33 @@ var EXCLUDE_PATTERNS = {
|
|
|
56729
56729
|
"**/turbo.json": true,
|
|
56730
56730
|
"**/nodemon.json": true,
|
|
56731
56731
|
"**/temp.md": true,
|
|
56732
|
-
"
|
|
56733
|
-
"
|
|
56734
|
-
"
|
|
56735
|
-
"
|
|
56736
|
-
"
|
|
56737
|
-
"
|
|
56732
|
+
"**/postcss.config.js": true,
|
|
56733
|
+
"**/configs": true,
|
|
56734
|
+
"**/tailwind.config.js": true,
|
|
56735
|
+
"**/tsconfig.app.json": true,
|
|
56736
|
+
"**/tsconfig.json": true,
|
|
56737
|
+
"**/tsconfig.node.json": true,
|
|
56738
|
+
"**/tsconfig.spec.json": true,
|
|
56739
|
+
"**/eslint.json": true,
|
|
56740
|
+
"**/eslint.config.js": true,
|
|
56741
|
+
"**/eslint.config.mjs": true,
|
|
56742
|
+
"**/prettier.config.js": true,
|
|
56743
|
+
"**/prettier.config.mjs": true,
|
|
56744
|
+
"**/prettier.config.cjs": true,
|
|
56745
|
+
"**/vite.config.ts": true,
|
|
56746
|
+
"**/vite.config.js": true,
|
|
56747
|
+
"**/tsup.config.ts": true,
|
|
56748
|
+
"**/rollup.config.ts": true,
|
|
56749
|
+
"**/rollup.config.js": true,
|
|
56750
|
+
"**/webpack.config.js": true,
|
|
56751
|
+
"**/babel.config.js": true,
|
|
56752
|
+
"**/jest.config.js": true,
|
|
56753
|
+
"**/jest.config.ts": true,
|
|
56754
|
+
"**/next.config.js": true,
|
|
56755
|
+
"**/next.config.mjs": true,
|
|
56756
|
+
"**/postcss.config.cjs": true,
|
|
56757
|
+
"**/postcss.config.mjs": true,
|
|
56758
|
+
"**/tailwind.config.ts": true,
|
|
56738
56759
|
"_temp": true,
|
|
56739
56760
|
".gitignore": true,
|
|
56740
56761
|
".vscode": true,
|
|
@@ -57624,7 +57645,7 @@ router17.post("/stop-all", async (req, res) => {
|
|
|
57624
57645
|
var apidocker_default = router17;
|
|
57625
57646
|
|
|
57626
57647
|
// src/routes/availabletemplates.ts
|
|
57627
|
-
var
|
|
57648
|
+
var import_express22 = __toESM(require_express2());
|
|
57628
57649
|
|
|
57629
57650
|
// ../../packages/template/databases/mysql.ts
|
|
57630
57651
|
var MySQL = {
|
|
@@ -57666,6 +57687,11 @@ const EDITOR_URL = 'http://localhost/phpmyadmin'; // Change this to your preferr
|
|
|
57666
57687
|
cmd: "npm",
|
|
57667
57688
|
args: ["pkg", "set", "scripts.stop=echo 'Note: MySQL is running as a system service. Please stop it manually.'"]
|
|
57668
57689
|
},
|
|
57690
|
+
{
|
|
57691
|
+
action: "command",
|
|
57692
|
+
cmd: "npm",
|
|
57693
|
+
args: ["pkg", "set", "description=MySQL (Local)"]
|
|
57694
|
+
},
|
|
57669
57695
|
{
|
|
57670
57696
|
action: "command",
|
|
57671
57697
|
cmd: "npm",
|
|
@@ -57861,7 +57887,12 @@ process.on('SIGTERM', cleanup);`
|
|
|
57861
57887
|
{
|
|
57862
57888
|
action: "command",
|
|
57863
57889
|
cmd: "npm",
|
|
57864
|
-
args: ["pkg", "set", "
|
|
57890
|
+
args: ["pkg", "set", "description=PostgreSQL (Docker)"]
|
|
57891
|
+
},
|
|
57892
|
+
{
|
|
57893
|
+
action: "command",
|
|
57894
|
+
cmd: "npm",
|
|
57895
|
+
args: ["pkg", "set", "fontawesomeIcon=fas fa-database text-blue-500"]
|
|
57865
57896
|
}
|
|
57866
57897
|
]
|
|
57867
57898
|
};
|
|
@@ -57895,7 +57926,12 @@ var Supabase = {
|
|
|
57895
57926
|
{
|
|
57896
57927
|
action: "command",
|
|
57897
57928
|
cmd: "npm",
|
|
57898
|
-
args: ["pkg", "set", "
|
|
57929
|
+
args: ["pkg", "set", "description=Supabase (Docker)"]
|
|
57930
|
+
},
|
|
57931
|
+
{
|
|
57932
|
+
action: "command",
|
|
57933
|
+
cmd: "npm",
|
|
57934
|
+
args: ["pkg", "set", "fontawesomeIcon=fas fa-bolt text-green-500"]
|
|
57899
57935
|
}
|
|
57900
57936
|
]
|
|
57901
57937
|
};
|
|
@@ -58050,7 +58086,12 @@ process.on('SIGTERM', cleanup);`
|
|
|
58050
58086
|
{
|
|
58051
58087
|
action: "command",
|
|
58052
58088
|
cmd: "npm",
|
|
58053
|
-
args: ["pkg", "set", "
|
|
58089
|
+
args: ["pkg", "set", "description=Redis (Docker)"]
|
|
58090
|
+
},
|
|
58091
|
+
{
|
|
58092
|
+
action: "command",
|
|
58093
|
+
cmd: "npm",
|
|
58094
|
+
args: ["pkg", "set", "fontawesomeIcon=fas fa-server text-red-500"]
|
|
58054
58095
|
}
|
|
58055
58096
|
]
|
|
58056
58097
|
};
|
|
@@ -58205,6 +58246,11 @@ process.on('SIGTERM', cleanup);`
|
|
|
58205
58246
|
cmd: "npm",
|
|
58206
58247
|
args: ["pkg", "set", `scripts.stop=node -e 'const fs=require("fs"); try{const p=JSON.parse(fs.readFileSync(".runtime.json")).port; fetch("http://localhost:"+p+"/stop").catch(e=>{})}catch(e){}'`]
|
|
58207
58248
|
},
|
|
58249
|
+
{
|
|
58250
|
+
action: "command",
|
|
58251
|
+
cmd: "npm",
|
|
58252
|
+
args: ["pkg", "set", "description=MongoDB (Docker)"]
|
|
58253
|
+
},
|
|
58208
58254
|
{
|
|
58209
58255
|
action: "command",
|
|
58210
58256
|
cmd: "npm",
|
|
@@ -58362,6 +58408,11 @@ process.on('SIGTERM', cleanup);`
|
|
|
58362
58408
|
cmd: "npm",
|
|
58363
58409
|
args: ["pkg", "set", "fontawesomeIcon=fab fa-meetup text-green-500"]
|
|
58364
58410
|
},
|
|
58411
|
+
{
|
|
58412
|
+
action: "command",
|
|
58413
|
+
cmd: "npm",
|
|
58414
|
+
args: ["pkg", "set", "description=Meilisearch (Docker)"]
|
|
58415
|
+
},
|
|
58365
58416
|
{
|
|
58366
58417
|
action: "command",
|
|
58367
58418
|
cmd: "npm",
|
|
@@ -58537,6 +58588,11 @@ process.on('SIGTERM', cleanup);`
|
|
|
58537
58588
|
cmd: "npm",
|
|
58538
58589
|
args: ["pkg", "set", "fontawesomeIcon=fab fa-amazon text-blue-500"]
|
|
58539
58590
|
},
|
|
58591
|
+
{
|
|
58592
|
+
action: "command",
|
|
58593
|
+
cmd: "npm",
|
|
58594
|
+
args: ["pkg", "set", "description=MinIO (Docker)"]
|
|
58595
|
+
},
|
|
58540
58596
|
{
|
|
58541
58597
|
action: "command",
|
|
58542
58598
|
cmd: "npm",
|
|
@@ -58557,1552 +58613,315 @@ var templates = [
|
|
|
58557
58613
|
];
|
|
58558
58614
|
var database_default = templates;
|
|
58559
58615
|
|
|
58560
|
-
// ../../packages/template/demo/
|
|
58561
|
-
var
|
|
58562
|
-
|
|
58563
|
-
|
|
58564
|
-
|
|
58565
|
-
|
|
58566
|
-
|
|
58567
|
-
|
|
58568
|
-
|
|
58569
|
-
|
|
58570
|
-
|
|
58571
|
-
|
|
58572
|
-
|
|
58573
|
-
|
|
58574
|
-
|
|
58575
|
-
|
|
58576
|
-
|
|
58577
|
-
|
|
58578
|
-
|
|
58579
|
-
|
|
58580
|
-
|
|
58581
|
-
|
|
58582
|
-
|
|
58583
|
-
|
|
58584
|
-
|
|
58585
|
-
|
|
58586
|
-
|
|
58587
|
-
|
|
58588
|
-
|
|
58589
|
-
<
|
|
58590
|
-
|
|
58591
|
-
|
|
58592
|
-
|
|
58593
|
-
|
|
58594
|
-
|
|
58595
|
-
|
|
58596
|
-
|
|
58597
|
-
|
|
58598
|
-
|
|
58599
|
-
|
|
58600
|
-
|
|
58601
|
-
|
|
58602
|
-
|
|
58603
|
-
|
|
58604
|
-
|
|
58605
|
-
|
|
58606
|
-
|
|
58607
|
-
|
|
58608
|
-
|
|
58609
|
-
|
|
58610
|
-
|
|
58611
|
-
|
|
58612
|
-
|
|
58613
|
-
|
|
58614
|
-
|
|
58615
|
-
|
|
58616
|
-
|
|
58617
|
-
|
|
58618
|
-
|
|
58619
|
-
|
|
58620
|
-
|
|
58621
|
-
|
|
58622
|
-
|
|
58623
|
-
|
|
58624
|
-
|
|
58625
|
-
|
|
58626
|
-
|
|
58627
|
-
|
|
58628
|
-
|
|
58629
|
-
|
|
58630
|
-
|
|
58631
|
-
<div class="product-card">
|
|
58632
|
-
<div class="product-image">\u{1F353}</div>
|
|
58633
|
-
<div class="product-info">
|
|
58634
|
-
<h3>Fresh Strawberries</h3>
|
|
58635
|
-
<p>Hand-picked at peak ripeness for maximum flavor</p>
|
|
58636
|
-
<span class="product-price">$7.49/lb</span>
|
|
58637
|
-
</div>
|
|
58638
|
-
</div>
|
|
58639
|
-
<div class="product-card">
|
|
58640
|
-
<div class="product-image">\u{1F34C}</div>
|
|
58641
|
-
<div class="product-info">
|
|
58642
|
-
<h3>Organic Bananas</h3>
|
|
58643
|
-
<p>Naturally ripened, perfect for smoothies</p>
|
|
58644
|
-
<span class="product-price">$2.99/lb</span>
|
|
58645
|
-
</div>
|
|
58646
|
-
</div>
|
|
58647
|
-
</div>
|
|
58648
|
-
</section>
|
|
58649
|
-
|
|
58650
|
-
<!-- Chat Widget -->
|
|
58651
|
-
<div class="chat-widget">
|
|
58652
|
-
<div class="chat-window" id="chatWindow">
|
|
58653
|
-
<div class="chat-header">
|
|
58654
|
-
<div class="chat-header-avatar">\u{1F34A}</div>
|
|
58655
|
-
<div class="chat-header-info">
|
|
58656
|
-
<h4>FreshFruit Support</h4>
|
|
58657
|
-
<span>We typically reply instantly</span>
|
|
58658
|
-
</div>
|
|
58659
|
-
</div>
|
|
58660
|
-
<div class="chat-messages" id="chatMessages">
|
|
58661
|
-
<div class="message bot">
|
|
58662
|
-
Hi! \u{1F44B} Welcome to FreshFruit! How can I help you today? I can answer questions about our products, delivery, or anything else!
|
|
58663
|
-
</div>
|
|
58664
|
-
</div>
|
|
58665
|
-
<div class="chat-input-container">
|
|
58666
|
-
<input type="text" class="chat-input" id="chatInput" placeholder="Type your message..." autocomplete="off">
|
|
58667
|
-
<button class="chat-send" id="chatSend">
|
|
58668
|
-
<svg viewBox="0 0 24 24"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/></svg>
|
|
58669
|
-
</button>
|
|
58670
|
-
</div>
|
|
58671
|
-
</div>
|
|
58672
|
-
<button class="chat-toggle" id="chatToggle">
|
|
58673
|
-
<svg viewBox="0 0 24 24"><path d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H6l-2 2V4h16v12z"/></svg>
|
|
58674
|
-
</button>
|
|
58675
|
-
</div>
|
|
58676
|
-
|
|
58677
|
-
<script>
|
|
58678
|
-
// Chat Widget Functionality
|
|
58679
|
-
const chatToggle = document.getElementById('chatToggle');
|
|
58680
|
-
const chatWindow = document.getElementById('chatWindow');
|
|
58681
|
-
const chatInput = document.getElementById('chatInput');
|
|
58682
|
-
const chatSend = document.getElementById('chatSend');
|
|
58683
|
-
const chatMessages = document.getElementById('chatMessages');
|
|
58684
|
-
|
|
58685
|
-
// Toggle chat window
|
|
58686
|
-
chatToggle.addEventListener('click', () => {
|
|
58687
|
-
chatWindow.classList.toggle('open');
|
|
58688
|
-
if (chatWindow.classList.contains('open')) {
|
|
58689
|
-
chatInput.focus();
|
|
58690
|
-
}
|
|
58691
|
-
});
|
|
58692
|
-
|
|
58693
|
-
// Send message function
|
|
58694
|
-
async function sendMessage() {
|
|
58695
|
-
const message = chatInput.value.trim();
|
|
58696
|
-
if (!message) return;
|
|
58697
|
-
|
|
58698
|
-
// Add user message
|
|
58699
|
-
addMessage(message, 'user');
|
|
58700
|
-
chatInput.value = '';
|
|
58701
|
-
|
|
58702
|
-
// Show typing indicator
|
|
58703
|
-
const typingEl = showTyping();
|
|
58704
|
-
|
|
58705
|
-
try {
|
|
58706
|
-
const response = await fetch('/api/chat', {
|
|
58707
|
-
method: 'POST',
|
|
58708
|
-
headers: { 'Content-Type': 'application/json' },
|
|
58709
|
-
body: JSON.stringify({ message })
|
|
58710
|
-
});
|
|
58711
|
-
|
|
58712
|
-
const data = await response.json();
|
|
58713
|
-
typingEl.remove();
|
|
58714
|
-
|
|
58715
|
-
if (data.reply) {
|
|
58716
|
-
addMessage(data.reply, 'bot');
|
|
58717
|
-
} else {
|
|
58718
|
-
addMessage('Sorry, I encountered an error. Please try again.', 'bot');
|
|
58719
|
-
}
|
|
58720
|
-
} catch (error) {
|
|
58721
|
-
typingEl.remove();
|
|
58722
|
-
addMessage('Sorry, I\\'m having trouble connecting. Please try again later.', 'bot');
|
|
58723
|
-
}
|
|
58724
|
-
}
|
|
58616
|
+
// ../../packages/template/demo/monochat.ts
|
|
58617
|
+
var MonoChat = {
|
|
58618
|
+
name: "Chat To MonoChat",
|
|
58619
|
+
description: "React Frontend, needs custom backend",
|
|
58620
|
+
notes: "Vite React + TailwindCSS + TypeScript",
|
|
58621
|
+
templating: [
|
|
58622
|
+
{
|
|
58623
|
+
action: "command",
|
|
58624
|
+
cmd: "rm -rf ./* ./.[!.]*",
|
|
58625
|
+
args: []
|
|
58626
|
+
},
|
|
58627
|
+
{
|
|
58628
|
+
action: "file",
|
|
58629
|
+
file: ".gitignore",
|
|
58630
|
+
filecontent: "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
|
|
58631
|
+
},
|
|
58632
|
+
{
|
|
58633
|
+
action: "file",
|
|
58634
|
+
file: "README.md",
|
|
58635
|
+
filecontent: "# React + TypeScript + Vite\n\nThis template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.\n\nCurrently, two official plugins are available:\n\n- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh\n- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh\n\n## React Compiler\n\nThe React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).\n\n## Expanding the ESLint configuration\n\nIf you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:\n\n```js\nexport default defineConfig([\n globalIgnores(['dist']),\n {\n files: ['**/*.{ts,tsx}'],\n extends: [\n // Other configs...\n\n // Remove tseslint.configs.recommended and replace with this\n tseslint.configs.recommendedTypeChecked,\n // Alternatively, use this for stricter rules\n tseslint.configs.strictTypeChecked,\n // Optionally, add this for stylistic rules\n tseslint.configs.stylisticTypeChecked,\n\n // Other configs...\n ],\n languageOptions: {\n parserOptions: {\n project: ['./tsconfig.node.json', './tsconfig.app.json'],\n tsconfigRootDir: import.meta.dirname,\n },\n // other options...\n },\n },\n])\n```\n\nYou can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:\n\n```js\n// eslint.config.js\nimport reactX from 'eslint-plugin-react-x'\nimport reactDom from 'eslint-plugin-react-dom'\n\nexport default defineConfig([\n globalIgnores(['dist']),\n {\n files: ['**/*.{ts,tsx}'],\n extends: [\n // Other configs...\n // Enable lint rules for React\n reactX.configs['recommended-typescript'],\n // Enable lint rules for React DOM\n reactDom.configs.recommended,\n ],\n languageOptions: {\n parserOptions: {\n project: ['./tsconfig.node.json', './tsconfig.app.json'],\n tsconfigRootDir: import.meta.dirname,\n },\n // other options...\n },\n },\n])\n```\n"
|
|
58636
|
+
},
|
|
58637
|
+
{
|
|
58638
|
+
action: "file",
|
|
58639
|
+
file: "eslint.config.js",
|
|
58640
|
+
filecontent: "import js from '@eslint/js'\nimport globals from 'globals'\nimport reactHooks from 'eslint-plugin-react-hooks'\nimport reactRefresh from 'eslint-plugin-react-refresh'\nimport tseslint from 'typescript-eslint'\nimport { defineConfig, globalIgnores } from 'eslint/config'\n\nexport default defineConfig([\n globalIgnores(['dist']),\n {\n files: ['**/*.{ts,tsx}'],\n extends: [\n js.configs.recommended,\n tseslint.configs.recommended,\n reactHooks.configs.flat.recommended,\n reactRefresh.configs.vite,\n ],\n languageOptions: {\n ecmaVersion: 2020,\n globals: globals.browser,\n },\n },\n])\n"
|
|
58641
|
+
},
|
|
58642
|
+
{
|
|
58643
|
+
action: "file",
|
|
58644
|
+
file: "index.html",
|
|
58645
|
+
filecontent: '<!doctype html>\n<html lang="en">\n <head>\n <meta charset="UTF-8" />\n <link rel="icon" type="image/svg+xml" href="/logo.svg" />\n <meta name="viewport" content="width=device-width, initial-scale=1.0" />\n <title>MonoChat</title>\n </head>\n <body>\n <div id="root"></div>\n <script type="module" src="/src/main.tsx"></script>\n </body>\n</html>\n'
|
|
58646
|
+
},
|
|
58647
|
+
{
|
|
58648
|
+
action: "file",
|
|
58649
|
+
file: "netlify.toml",
|
|
58650
|
+
filecontent: '[build]\n command = "npm run build"\n publish = "dist"\n\n[[redirects]]\n from = "/*"\n to = "/index.html"\n status = 200'
|
|
58651
|
+
},
|
|
58652
|
+
{
|
|
58653
|
+
action: "file",
|
|
58654
|
+
file: "package.json",
|
|
58655
|
+
filecontent: '{\n "name": "z-chat",\n "private": true,\n "version": "0.0.0",\n "type": "module",\n "scripts": {\n "dev": "vite",\n "build": "tsc -b && vite build",\n "lint": "eslint .",\n "preview": "vite preview",\n "stop": ""\n },\n "dependencies": {\n "react": "^19.2.0",\n "react-dom": "^19.2.0",\n "zustand": "^4.5.7"\n },\n "devDependencies": {\n "@eslint/js": "^9.39.1",\n "@tailwindcss/postcss": "^4.0.0",\n "@types/node": "^24.10.1",\n "@types/react": "^19.2.5",\n "@types/react-dom": "^19.2.3",\n "@vitejs/plugin-react": "^5.1.1",\n "autoprefixer": "^10.4.20",\n "eslint": "^9.39.1",\n "eslint-plugin-react-hooks": "^7.0.1",\n "eslint-plugin-react-refresh": "^0.4.24",\n "globals": "^16.5.0",\n "jiti": "^2.4.2",\n "postcss": "^8.5.1",\n "tailwindcss": "^4.0.0",\n "typescript": "~5.9.3",\n "typescript-eslint": "^8.46.4",\n "vite": "^7.2.4"\n },\n "description": "Vite React TS",\n "fontawesomeIcon": "fab fa-react text-blue-500"\n}\n'
|
|
58656
|
+
},
|
|
58657
|
+
{
|
|
58658
|
+
action: "file",
|
|
58659
|
+
file: "postcss.config.js",
|
|
58660
|
+
filecontent: 'export default {\n plugins: {\n "@tailwindcss/postcss": {},\n autoprefixer: {},\n },\n}'
|
|
58661
|
+
},
|
|
58662
|
+
{
|
|
58663
|
+
action: "file",
|
|
58664
|
+
file: "public/logo.svg",
|
|
58665
|
+
filecontent: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">\n <defs>\n <linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">\n <stop offset="0%" style="stop-color:#6366f1;stop-opacity:1" />\n <stop offset="100%" style="stop-color:#a855f7;stop-opacity:1" />\n </linearGradient>\n </defs>\n <rect width="512" height="512" rx="128" fill="url(#grad)" />\n <path d="M375.3 325.7c22.1-24.9 36.7-56.3 36.7-91.7c0-79.5-72.7-144-162-144S88 154.5 88 234s72.7 144 162 144c20.3 0 39.7-3.4 57.6-9.6L368 400l-45.7-31.3c18.5-12.7 34.6-28 47-45.7v2.7z" fill="white" />\n <circle cx="178" cy="234" r="20" fill="#6366f1"/>\n <circle cx="250" cy="234" r="20" fill="#6366f1"/>\n <circle cx="322" cy="234" r="20" fill="#6366f1"/>\n</svg>\n'
|
|
58666
|
+
},
|
|
58667
|
+
{
|
|
58668
|
+
action: "file",
|
|
58669
|
+
file: "render.yaml",
|
|
58670
|
+
filecontent: "services:\n - type: web\n name: vite-react-app\n env: static\n buildCommand: npm install && npm run build\n staticPublishPath: ./dist"
|
|
58671
|
+
},
|
|
58672
|
+
{
|
|
58673
|
+
action: "file",
|
|
58674
|
+
file: "src/App.tsx",
|
|
58675
|
+
filecontent: "import Background from './components/Background';\nimport ChatContainer from './components/ChatContainer';\nimport Header from './components/Header';\n\nexport default function App() {\n return (\n <div className={`\n h-[100vh]\n w-[100vw]\n overflow-hidden\n bg-zinc-900 \n `}>\n <div className='w-full h-full'>\n <Background />\n <Header />\n <ChatContainer />\n </div>\n </div>\n );\n}"
|
|
58676
|
+
},
|
|
58677
|
+
{
|
|
58678
|
+
action: "file",
|
|
58679
|
+
file: "src/_FetchToWho.ts",
|
|
58680
|
+
filecontent: 'import type { ChatItem } from "./app/chat";\n\n//@ts-ignore\nexport default async function FetchToWho( chats: ChatItem[]) {\n // const lastChat = chats[chats.length - 1];\n // if (!lastChat) return;\n // const response = await fetch("https://api.openai.com/v1/chat/completions", {\n // method: "POST",\n // headers: {\n // "Content-Type": "application/json",\n // "Authorization": `Bearer ${process.env.OPENAI_API_KEY}`\n // },\n // body: JSON.stringify({\n // model: "gpt-3.5-turbo",\n // messages: [\n // { role: "system", content: "You are a helpful assistant." },\n // { role: "user", content: lastChat.message }\n // ]\n // })\n // });\n // const data = await response.json();\n // return data.choices[0].message.content;\n\n const lorem = "Please edit the FetchToWho function. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quod. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quod. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quod. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quod. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quod.";\n return lorem;\n}\n'
|
|
58681
|
+
},
|
|
58682
|
+
{
|
|
58683
|
+
action: "file",
|
|
58684
|
+
file: "src/app/chat.ts",
|
|
58685
|
+
filecontent: `import { create } from 'zustand';
|
|
58686
|
+
import { createSelectors } from './zustandSelector';
|
|
58725
58687
|
|
|
58726
|
-
|
|
58727
|
-
|
|
58728
|
-
|
|
58729
|
-
|
|
58730
|
-
|
|
58731
|
-
|
|
58732
|
-
chatMessages.scrollTop = chatMessages.scrollHeight;
|
|
58733
|
-
}
|
|
58688
|
+
export interface ChatItem {
|
|
58689
|
+
id: number;
|
|
58690
|
+
who: "user" | "system";
|
|
58691
|
+
timestamp: number;
|
|
58692
|
+
message: string;
|
|
58693
|
+
}
|
|
58734
58694
|
|
|
58735
|
-
|
|
58736
|
-
|
|
58737
|
-
|
|
58738
|
-
|
|
58739
|
-
|
|
58740
|
-
|
|
58741
|
-
chatMessages.scrollTop = chatMessages.scrollHeight;
|
|
58742
|
-
return typingEl;
|
|
58743
|
-
}
|
|
58695
|
+
interface chatContext {
|
|
58696
|
+
chats: Array<ChatItem>;
|
|
58697
|
+
textinput: string;
|
|
58698
|
+
addChat: (chat: ChatItem) => void;
|
|
58699
|
+
setTextinput: (textinput: string) => void;
|
|
58700
|
+
}
|
|
58744
58701
|
|
|
58745
|
-
|
|
58746
|
-
|
|
58747
|
-
|
|
58748
|
-
|
|
58749
|
-
|
|
58750
|
-
|
|
58751
|
-
|
|
58752
|
-
|
|
58753
|
-
|
|
58702
|
+
const chatstate = create<chatContext>()((set) => ({
|
|
58703
|
+
chats: [],
|
|
58704
|
+
textinput: "",
|
|
58705
|
+
addChat: (chat: ChatItem) => set((state) => ({
|
|
58706
|
+
chats: [...state.chats, chat]
|
|
58707
|
+
})),
|
|
58708
|
+
setTextinput: (textinput: string) => set(() => ({
|
|
58709
|
+
textinput: textinput
|
|
58710
|
+
}))
|
|
58754
58711
|
|
|
58755
|
-
|
|
58756
|
-
var adminHTML = `<!DOCTYPE html>
|
|
58757
|
-
<html lang="en">
|
|
58758
|
-
<head>
|
|
58759
|
-
<meta charset="UTF-8">
|
|
58760
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
58761
|
-
<title>Admin Panel - AI Chat Configuration</title>
|
|
58762
|
-
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
58763
|
-
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
58764
|
-
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
|
58765
|
-
<link rel="stylesheet" href="/styles.css">
|
|
58766
|
-
</head>
|
|
58767
|
-
<body>
|
|
58768
|
-
<header class="header">
|
|
58769
|
-
<div class="header-content">
|
|
58770
|
-
<div class="logo">\u{1F34A} FreshFruit Admin</div>
|
|
58771
|
-
<nav>
|
|
58772
|
-
<ul class="nav-links">
|
|
58773
|
-
<li><a href="/">View Store</a></li>
|
|
58774
|
-
</ul>
|
|
58775
|
-
</nav>
|
|
58776
|
-
</div>
|
|
58777
|
-
</header>
|
|
58712
|
+
}));
|
|
58778
58713
|
|
|
58779
|
-
|
|
58780
|
-
|
|
58781
|
-
<h1>AI Chat Configuration</h1>
|
|
58782
|
-
<p>Configure your AI provider and embed FAQ knowledge for customer support</p>
|
|
58783
|
-
</div>
|
|
58714
|
+
const useChatState = createSelectors(chatstate);
|
|
58715
|
+
export default useChatState;
|
|
58784
58716
|
|
|
58785
|
-
|
|
58786
|
-
|
|
58787
|
-
|
|
58788
|
-
|
|
58789
|
-
|
|
58790
|
-
|
|
58791
|
-
|
|
58792
|
-
|
|
58793
|
-
|
|
58794
|
-
|
|
58795
|
-
|
|
58796
|
-
|
|
58797
|
-
|
|
58798
|
-
|
|
58799
|
-
|
|
58800
|
-
|
|
58801
|
-
|
|
58802
|
-
|
|
58803
|
-
|
|
58804
|
-
|
|
58805
|
-
|
|
58806
|
-
|
|
58807
|
-
|
|
58717
|
+
`
|
|
58718
|
+
},
|
|
58719
|
+
{
|
|
58720
|
+
action: "file",
|
|
58721
|
+
file: "src/app/zustandSelector.ts",
|
|
58722
|
+
filecontent: "//from: https://docs.pmnd.rs/zustand/guides/auto-generating-selectors\nimport type { StoreApi, UseBoundStore } from 'zustand'\n\ntype WithSelectors<S> = S extends { getState: () => infer T }\n ? S & { use: { [K in keyof T]: () => T[K] } }\n : never\n\nexport const createSelectors = <S extends UseBoundStore<StoreApi<object>>>(\n _store: S\n) => {\n let store = _store as WithSelectors<typeof _store>\n store.use = {}\n for (let k of Object.keys(store.getState())) {\n ;(store.use as any)[k] = () => store((s) => s[k as keyof typeof s])\n }\n\n return store\n}\n"
|
|
58723
|
+
},
|
|
58724
|
+
{
|
|
58725
|
+
action: "file",
|
|
58726
|
+
file: "src/components/Background.tsx",
|
|
58727
|
+
filecontent: 'export default function Background() {\n return (\n <>\n <div className="absolute -top-[25%] -left-[10%] w-[80%] h-[80%] bg-blue-800/10 rounded-full blur-[128px]"></div>\n <div className="absolute bottom-[0%] right-[0%] w-[80%] h-[40%] bg-purple-800/10 rounded-full blur-[128px]"></div>\n </>\n )\n}'
|
|
58728
|
+
},
|
|
58729
|
+
{
|
|
58730
|
+
action: "file",
|
|
58731
|
+
file: "src/components/ChatContainer.tsx",
|
|
58732
|
+
filecontent: `import useChatState from '../app/chat';
|
|
58733
|
+
import TextInput from './TextInput';
|
|
58734
|
+
import ChatContents from './ChatContents';
|
|
58735
|
+
|
|
58736
|
+
export default function ChatContainer() {
|
|
58737
|
+
const chats = useChatState.use.chats();
|
|
58738
|
+
|
|
58739
|
+
return (
|
|
58740
|
+
<div className="flex flex-col h-[calc(100vh-6rem)] w-full max-w-[900px] mx-auto relative font-sans">
|
|
58741
|
+
{chats.length > 0 ? (
|
|
58742
|
+
<>
|
|
58743
|
+
<ChatContents />
|
|
58744
|
+
<TextInput />
|
|
58745
|
+
</>
|
|
58746
|
+
) : (
|
|
58747
|
+
<div className="flex flex-col items-center justify-center h-full w-full p-4">
|
|
58748
|
+
<div className="flex gap-4 items-center justify-center">
|
|
58749
|
+
<div className="w-10 h-10 mb-8">
|
|
58750
|
+
<img src="/logo.svg" alt="MonoChat Logo" className="w-full h-full object-contain" />
|
|
58751
|
+
</div>
|
|
58752
|
+
<h2 className="text-xl font-bold text-white mb-8">How can I help you today?</h2>
|
|
58753
|
+
</div>
|
|
58754
|
+
<TextInput />
|
|
58808
58755
|
</div>
|
|
58809
|
-
|
|
58810
|
-
</form>
|
|
58756
|
+
)}
|
|
58811
58757
|
</div>
|
|
58758
|
+
);
|
|
58759
|
+
}
|
|
58812
58760
|
|
|
58813
|
-
|
|
58814
|
-
|
|
58815
|
-
|
|
58816
|
-
|
|
58817
|
-
|
|
58818
|
-
</
|
|
58819
|
-
|
|
58820
|
-
|
|
58821
|
-
|
|
58822
|
-
|
|
58823
|
-
|
|
58824
|
-
|
|
58825
|
-
|
|
58826
|
-
|
|
58827
|
-
|
|
58828
|
-
|
|
58829
|
-
|
|
58761
|
+
`
|
|
58762
|
+
},
|
|
58763
|
+
{
|
|
58764
|
+
action: "file",
|
|
58765
|
+
file: "src/components/ChatContents.tsx",
|
|
58766
|
+
filecontent: "import { useEffect, useRef } from \"react\";\nimport useChatState from \"../app/chat\";\n\nexport default function ChatContents() {\n const chats = useChatState.use.chats();\n const messagesEndRef = useRef<HTMLDivElement>(null);\n\n const scrollToBottom = () => {\n messagesEndRef.current?.scrollIntoView({ behavior: \"smooth\" });\n };\n\n useEffect(() => {\n scrollToBottom();\n }, [chats]);\n\n return (\n <div className=\"flex-1 overflow-y-auto w-full px-4 scrollbar-hide\">\n {chats.map((chat) => (\n <div\n key={chat.id}\n className={`group flex w-full ${chat.who === 'user' ? 'justify-end' : 'justify-start'}`}\n >\n <div className={`flex max-w-[85%] md:max-w-[80%] gap-4 ${chat.who === 'user' ? 'flex-row-reverse' : 'flex-row'}`}>\n <div className={`flex flex-col ${chat.who === 'user' ? 'items-end' : 'items-start'}`}>\n <div className={`flex items-center gap-2 mb-1.5 opacity-90 ${chat.who === 'user' ? 'flex-row-reverse' : 'flex-row'}`}>\n <span className=\"text-[10px] text-zinc-500\">\n {new Date(chat.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}\n </span>\n </div>\n <div\n className={`relative px-5 py-3 rounded-2xl text-md leading-relaxed transition-transform duration-200 ${chat.who === 'user'\n ? 'bg-zinc-800/80 text-white rounded-tr-sm border border-zinc-700/50 shadow-lg backdrop-blur-sm'\n : ' text-zinc-100'\n }`}\n >\n {chat.message}\n </div>\n </div>\n </div>\n </div>\n ))}\n <div ref={messagesEndRef} className=\"h-4\" />\n </div>\n )\n}"
|
|
58767
|
+
},
|
|
58768
|
+
{
|
|
58769
|
+
action: "file",
|
|
58770
|
+
file: "src/components/Header.tsx",
|
|
58771
|
+
filecontent: '\nexport default function Header() {\n return (\n <div className="w-full h-12">\n <div className="container px-4 max-w-7xl mx-auto h-full flex items-center gap-3">\n <img src="/logo.svg" alt="MonoChat Logo" className="w-8 h-8" />\n <h1 className="font-bold text-lg tracking-wide text-white">\n MonoChat\n </h1>\n </div>\n </div>\n )\n}'
|
|
58772
|
+
},
|
|
58773
|
+
{
|
|
58774
|
+
action: "file",
|
|
58775
|
+
file: "src/components/SendIcon.tsx",
|
|
58776
|
+
filecontent: '\nexport default function SendIcon({ className }: { className?: string }) {\n return (\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className={className}>\n <path d="M3.478 2.404a.75.75 0 0 0-.926.941l2.432 7.905H13.5a.75.75 0 0 1 0 1.5H4.984l-2.432 7.905a.75.75 0 0 0 .926.94 60.519 60.519 0 0 0 18.445-8.986.75.75 0 0 0 0-1.218A60.517 60.517 0 0 0 3.478 2.404Z" />\n </svg>\n )\n}'
|
|
58777
|
+
},
|
|
58778
|
+
{
|
|
58779
|
+
action: "file",
|
|
58780
|
+
file: "src/components/TextInput.tsx",
|
|
58781
|
+
filecontent: `import FetchToWho from "../_FetchToWho";
|
|
58782
|
+
import useChatState from "../app/chat";
|
|
58783
|
+
import SendIcon from "./SendIcon";
|
|
58784
|
+
|
|
58785
|
+
export default function TextInput() {
|
|
58786
|
+
const chats = useChatState.use.chats();
|
|
58787
|
+
const textinput = useChatState.use.textinput();
|
|
58788
|
+
const setTextinput = useChatState.use.setTextinput();
|
|
58789
|
+
const addChat = useChatState.use.addChat();
|
|
58790
|
+
|
|
58791
|
+
const handleSend = async () => {
|
|
58792
|
+
if (!textinput.trim()) return;
|
|
58793
|
+
addChat({
|
|
58794
|
+
id: Date.now(),
|
|
58795
|
+
who: "user",
|
|
58796
|
+
timestamp: Date.now(),
|
|
58797
|
+
message: textinput
|
|
58798
|
+
});
|
|
58799
|
+
setTextinput("");
|
|
58800
|
+
|
|
58801
|
+
const userChat = chats.filter((chat) => chat.who === "user");
|
|
58802
|
+
const response = await FetchToWho(userChat);
|
|
58803
|
+
addChat({
|
|
58804
|
+
id: Date.now(),
|
|
58805
|
+
who: "system",
|
|
58806
|
+
timestamp: Date.now(),
|
|
58807
|
+
message: response
|
|
58808
|
+
});
|
|
58809
|
+
};
|
|
58830
58810
|
|
|
58831
|
-
|
|
58832
|
-
|
|
58833
|
-
|
|
58834
|
-
|
|
58835
|
-
|
|
58836
|
-
|
|
58837
|
-
|
|
58838
|
-
|
|
58839
|
-
|
|
58840
|
-
|
|
58841
|
-
<div
|
|
58842
|
-
<
|
|
58843
|
-
|
|
58844
|
-
|
|
58845
|
-
|
|
58846
|
-
|
|
58847
|
-
|
|
58811
|
+
const handleKeyDown = (e: React.KeyboardEvent) => {
|
|
58812
|
+
if (e.key === 'Enter' && !e.shiftKey) {
|
|
58813
|
+
e.preventDefault();
|
|
58814
|
+
handleSend();
|
|
58815
|
+
}
|
|
58816
|
+
};
|
|
58817
|
+
|
|
58818
|
+
return (
|
|
58819
|
+
<div className="p-4 w-full">
|
|
58820
|
+
<div className="w-full max-w-3xl mx-auto">
|
|
58821
|
+
<div className="relative flex items-end gap-2 bg-zinc-900/80 hover:bg-zinc-900/90 focus-within:bg-black/90 transition-all duration-300 border border-white/10 rounded-[24px] p-2 pr-2 shadow-xl backdrop-blur-xl ring-1 ring-white/5 focus-within:ring-indigo-500/30">
|
|
58822
|
+
<textarea
|
|
58823
|
+
value={textinput}
|
|
58824
|
+
onChange={(e) => setTextinput(e.target.value)}
|
|
58825
|
+
onKeyDown={handleKeyDown}
|
|
58826
|
+
placeholder="Message MonoChat..."
|
|
58827
|
+
className="w-full pl-4 py-3 bg-transparent active:bg-transparent border-none outline-none focus:outline-none text-zinc-100 placeholder:text-zinc-500 focus:ring-0 resize-none max-h-48 min-h-[44px] scrollbar-hide text-md leading-6"
|
|
58828
|
+
rows={1}
|
|
58829
|
+
style={{ height: 'auto', minHeight: '44px' }}
|
|
58830
|
+
onInput={(e) => {
|
|
58831
|
+
const target = e.target as HTMLTextAreaElement;
|
|
58832
|
+
target.style.height = 'auto';
|
|
58833
|
+
target.style.height = \`\${Math.min(target.scrollHeight, 192)}px\`;
|
|
58834
|
+
}}
|
|
58835
|
+
/>
|
|
58836
|
+
<button
|
|
58837
|
+
onClick={handleSend}
|
|
58838
|
+
disabled={!textinput.trim()}
|
|
58839
|
+
className={\`p-2 rounded-full mb-1 transition-all duration-200 flex-shrink-0 \${textinput.trim()
|
|
58840
|
+
? 'bg-indigo-600 text-white shadow-lg shadow-indigo-500/20 hover:bg-indigo-500'
|
|
58841
|
+
: 'bg-zinc-800 text-zinc-600 cursor-not-allowed'
|
|
58842
|
+
}\`}
|
|
58843
|
+
>
|
|
58844
|
+
<SendIcon className="w-5 h-5" />
|
|
58845
|
+
</button>
|
|
58848
58846
|
</div>
|
|
58849
58847
|
</div>
|
|
58850
58848
|
</div>
|
|
58849
|
+
)
|
|
58850
|
+
}
|
|
58851
|
+
`
|
|
58852
|
+
},
|
|
58853
|
+
{
|
|
58854
|
+
action: "file",
|
|
58855
|
+
file: "src/index.css",
|
|
58856
|
+
filecontent: '@import "tailwindcss";'
|
|
58857
|
+
},
|
|
58858
|
+
{
|
|
58859
|
+
action: "file",
|
|
58860
|
+
file: "src/main.tsx",
|
|
58861
|
+
filecontent: "import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport App from './App'\nimport './index.css'\n\nReactDOM.createRoot(document.getElementById('root')!).render(\n <React.StrictMode>\n <App />\n </React.StrictMode>,\n)"
|
|
58862
|
+
},
|
|
58863
|
+
{
|
|
58864
|
+
action: "file",
|
|
58865
|
+
file: "tailwind.config.js",
|
|
58866
|
+
filecontent: `/** @type {import('tailwindcss').Config} */
|
|
58867
|
+
export default {
|
|
58868
|
+
content: [
|
|
58869
|
+
"./index.html",
|
|
58870
|
+
"./src/**/*.{js,ts,jsx,tsx}",
|
|
58871
|
+
],
|
|
58872
|
+
theme: {
|
|
58873
|
+
extend: {},
|
|
58874
|
+
},
|
|
58875
|
+
plugins: [],
|
|
58876
|
+
};`
|
|
58877
|
+
},
|
|
58878
|
+
{
|
|
58879
|
+
action: "file",
|
|
58880
|
+
file: "tsconfig.app.json",
|
|
58881
|
+
filecontent: '{\n "compilerOptions": {\n "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",\n "target": "ES2022",\n "useDefineForClassFields": true,\n "lib": ["ES2022", "DOM", "DOM.Iterable"],\n "module": "ESNext",\n "types": ["vite/client"],\n "skipLibCheck": true,\n\n /* Bundler mode */\n "moduleResolution": "bundler",\n "allowImportingTsExtensions": true,\n "verbatimModuleSyntax": true,\n "moduleDetection": "force",\n "noEmit": true,\n "jsx": "react-jsx",\n\n /* Linting */\n "strict": true,\n "noUnusedLocals": true,\n "noUnusedParameters": true,\n "erasableSyntaxOnly": true,\n "noFallthroughCasesInSwitch": true,\n "noUncheckedSideEffectImports": true\n },\n "include": ["src"]\n}\n'
|
|
58882
|
+
},
|
|
58883
|
+
{
|
|
58884
|
+
action: "file",
|
|
58885
|
+
file: "tsconfig.json",
|
|
58886
|
+
filecontent: '{\n "files": [],\n "references": [\n { "path": "./tsconfig.app.json" },\n { "path": "./tsconfig.node.json" }\n ]\n}\n'
|
|
58887
|
+
},
|
|
58888
|
+
{
|
|
58889
|
+
action: "file",
|
|
58890
|
+
file: "tsconfig.node.json",
|
|
58891
|
+
filecontent: '{\n "compilerOptions": {\n "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",\n "target": "ES2023",\n "lib": ["ES2023"],\n "module": "ESNext",\n "types": ["node"],\n "skipLibCheck": true,\n\n /* Bundler mode */\n "moduleResolution": "bundler",\n "allowImportingTsExtensions": true,\n "verbatimModuleSyntax": true,\n "moduleDetection": "force",\n "noEmit": true,\n\n /* Linting */\n "strict": true,\n "noUnusedLocals": true,\n "noUnusedParameters": true,\n "erasableSyntaxOnly": true,\n "noFallthroughCasesInSwitch": true,\n "noUncheckedSideEffectImports": true\n },\n "include": ["vite.config.ts"]\n}\n'
|
|
58892
|
+
},
|
|
58893
|
+
{
|
|
58894
|
+
action: "file",
|
|
58895
|
+
file: "vercel.json",
|
|
58896
|
+
filecontent: '{\n "rewrites": [\n {\n "source": "/(.*)",\n "destination": "/index.html"\n }\n ]\n}'
|
|
58897
|
+
},
|
|
58898
|
+
{
|
|
58899
|
+
action: "file",
|
|
58900
|
+
file: "vite.config.ts",
|
|
58901
|
+
filecontent: "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\n\n// https://vite.dev/config/\nexport default defineConfig({\n plugins: [react()],\n})\n"
|
|
58902
|
+
},
|
|
58903
|
+
{
|
|
58904
|
+
action: "command",
|
|
58905
|
+
cmd: "npm",
|
|
58906
|
+
args: ["install"]
|
|
58907
|
+
},
|
|
58908
|
+
{
|
|
58909
|
+
action: "command",
|
|
58910
|
+
cmd: "npm",
|
|
58911
|
+
args: ["pkg", "set", "name=$(basename $PWD)"]
|
|
58912
|
+
}
|
|
58913
|
+
]
|
|
58914
|
+
};
|
|
58915
|
+
var monochat_default = MonoChat;
|
|
58851
58916
|
|
|
58852
|
-
|
|
58853
|
-
|
|
58854
|
-
|
|
58855
|
-
|
|
58856
|
-
|
|
58857
|
-
</p>
|
|
58858
|
-
<button class="btn btn-secondary" id="clearBtn">Clear All Embeddings</button>
|
|
58859
|
-
</div>
|
|
58860
|
-
</div>
|
|
58861
|
-
|
|
58862
|
-
<div class="toast" id="toast"></div>
|
|
58863
|
-
|
|
58864
|
-
<script>
|
|
58865
|
-
// Toast notification
|
|
58866
|
-
function showToast(message, duration = 3000) {
|
|
58867
|
-
const toast = document.getElementById('toast');
|
|
58868
|
-
toast.textContent = message;
|
|
58869
|
-
toast.classList.add('show');
|
|
58870
|
-
setTimeout(() => toast.classList.remove('show'), duration);
|
|
58871
|
-
}
|
|
58872
|
-
|
|
58873
|
-
// Load configuration on page load
|
|
58874
|
-
async function loadConfig() {
|
|
58875
|
-
try {
|
|
58876
|
-
const response = await fetch('/api/config');
|
|
58877
|
-
const data = await response.json();
|
|
58878
|
-
|
|
58879
|
-
if (data.config) {
|
|
58880
|
-
document.getElementById('apiKey').value = data.config.apiKey || '';
|
|
58881
|
-
document.getElementById('providerUrl').value = data.config.providerUrl || 'https://api.openai.com/v1/chat/completions';
|
|
58882
|
-
document.getElementById('embeddingsUrl').value = data.config.embeddingsUrl || 'https://api.openai.com/v1/embeddings';
|
|
58883
|
-
document.getElementById('model').value = data.config.model || 'gpt-3.5-turbo';
|
|
58884
|
-
document.getElementById('embeddingsModel').value = data.config.embeddingsModel || 'text-embedding-3-small';
|
|
58885
|
-
}
|
|
58886
|
-
|
|
58887
|
-
document.getElementById('embeddingCount').textContent = data.embeddingCount || 0;
|
|
58888
|
-
document.getElementById('lastUpdated').textContent = data.lastUpdated || 'Never';
|
|
58889
|
-
document.getElementById('configStatus').textContent = data.config?.apiKey ? '\u2705' : '\u274C';
|
|
58890
|
-
} catch (error) {
|
|
58891
|
-
console.error('Failed to load config:', error);
|
|
58892
|
-
}
|
|
58893
|
-
}
|
|
58894
|
-
|
|
58895
|
-
// Save configuration
|
|
58896
|
-
document.getElementById('configForm').addEventListener('submit', async (e) => {
|
|
58897
|
-
e.preventDefault();
|
|
58898
|
-
|
|
58899
|
-
const config = {
|
|
58900
|
-
apiKey: document.getElementById('apiKey').value,
|
|
58901
|
-
providerUrl: document.getElementById('providerUrl').value,
|
|
58902
|
-
embeddingsUrl: document.getElementById('embeddingsUrl').value,
|
|
58903
|
-
model: document.getElementById('model').value,
|
|
58904
|
-
embeddingsModel: document.getElementById('embeddingsModel').value
|
|
58905
|
-
};
|
|
58906
|
-
|
|
58907
|
-
try {
|
|
58908
|
-
const response = await fetch('/api/config', {
|
|
58909
|
-
method: 'POST',
|
|
58910
|
-
headers: { 'Content-Type': 'application/json' },
|
|
58911
|
-
body: JSON.stringify(config)
|
|
58912
|
-
});
|
|
58913
|
-
|
|
58914
|
-
if (response.ok) {
|
|
58915
|
-
showToast('\u2705 Configuration saved successfully!');
|
|
58916
|
-
document.getElementById('configStatus').textContent = config.apiKey ? '\u2705' : '\u274C';
|
|
58917
|
-
} else {
|
|
58918
|
-
showToast('\u274C Failed to save configuration');
|
|
58919
|
-
}
|
|
58920
|
-
} catch (error) {
|
|
58921
|
-
showToast('\u274C Error saving configuration');
|
|
58922
|
-
}
|
|
58923
|
-
});
|
|
58924
|
-
|
|
58925
|
-
// Embed knowledge
|
|
58926
|
-
document.getElementById('embedForm').addEventListener('submit', async (e) => {
|
|
58927
|
-
e.preventDefault();
|
|
58928
|
-
|
|
58929
|
-
const content = document.getElementById('faqContent').value.trim();
|
|
58930
|
-
if (!content) {
|
|
58931
|
-
showToast('\u26A0\uFE0F Please enter some content to embed');
|
|
58932
|
-
return;
|
|
58933
|
-
}
|
|
58934
|
-
|
|
58935
|
-
const embedBtn = document.getElementById('embedBtn');
|
|
58936
|
-
embedBtn.disabled = true;
|
|
58937
|
-
embedBtn.textContent = '\u23F3 Embedding...';
|
|
58938
|
-
|
|
58939
|
-
try {
|
|
58940
|
-
const response = await fetch('/api/embed', {
|
|
58941
|
-
method: 'POST',
|
|
58942
|
-
headers: { 'Content-Type': 'application/json' },
|
|
58943
|
-
body: JSON.stringify({ content })
|
|
58944
|
-
});
|
|
58945
|
-
|
|
58946
|
-
const data = await response.json();
|
|
58947
|
-
|
|
58948
|
-
if (response.ok) {
|
|
58949
|
-
showToast('\u2705 ' + (data.message || 'Content embedded successfully!'));
|
|
58950
|
-
document.getElementById('embeddingCount').textContent = data.count || 0;
|
|
58951
|
-
document.getElementById('lastUpdated').textContent = new Date().toLocaleString();
|
|
58952
|
-
document.getElementById('faqContent').value = '';
|
|
58953
|
-
} else {
|
|
58954
|
-
showToast('\u274C ' + (data.error || 'Failed to embed content'));
|
|
58955
|
-
}
|
|
58956
|
-
} catch (error) {
|
|
58957
|
-
showToast('\u274C Error embedding content');
|
|
58958
|
-
} finally {
|
|
58959
|
-
embedBtn.disabled = false;
|
|
58960
|
-
embedBtn.textContent = '\u{1F52E} Embed Knowledge';
|
|
58961
|
-
}
|
|
58962
|
-
});
|
|
58963
|
-
|
|
58964
|
-
// Clear embeddings
|
|
58965
|
-
document.getElementById('clearBtn').addEventListener('click', async () => {
|
|
58966
|
-
if (!confirm('Are you sure you want to clear all embeddings?')) return;
|
|
58967
|
-
|
|
58968
|
-
try {
|
|
58969
|
-
const response = await fetch('/api/embed', {
|
|
58970
|
-
method: 'DELETE'
|
|
58971
|
-
});
|
|
58972
|
-
|
|
58973
|
-
if (response.ok) {
|
|
58974
|
-
showToast('\u2705 All embeddings cleared');
|
|
58975
|
-
document.getElementById('embeddingCount').textContent = '0';
|
|
58976
|
-
} else {
|
|
58977
|
-
showToast('\u274C Failed to clear embeddings');
|
|
58978
|
-
}
|
|
58979
|
-
} catch (error) {
|
|
58980
|
-
showToast('\u274C Error clearing embeddings');
|
|
58981
|
-
}
|
|
58982
|
-
});
|
|
58983
|
-
|
|
58984
|
-
// Load config on page load
|
|
58985
|
-
loadConfig();
|
|
58986
|
-
</script>
|
|
58987
|
-
</body>
|
|
58988
|
-
</html>
|
|
58989
|
-
`;
|
|
58990
|
-
|
|
58991
|
-
// ../../packages/template/demo/aichat/files/stylesTs.ts
|
|
58992
|
-
var stylesCSS = `/* === CSS Variables === */
|
|
58993
|
-
:root {
|
|
58994
|
-
--primary: #22c55e;
|
|
58995
|
-
--primary-dark: #16a34a;
|
|
58996
|
-
--secondary: #f97316;
|
|
58997
|
-
--bg-dark: #0f172a;
|
|
58998
|
-
--bg-card: rgba(255, 255, 255, 0.05);
|
|
58999
|
-
--text-light: #f8fafc;
|
|
59000
|
-
--text-muted: #94a3b8;
|
|
59001
|
-
--border-color: rgba(255, 255, 255, 0.1);
|
|
59002
|
-
--shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
|
|
59003
|
-
--glass: rgba(255, 255, 255, 0.1);
|
|
59004
|
-
}
|
|
59005
|
-
|
|
59006
|
-
* {
|
|
59007
|
-
margin: 0;
|
|
59008
|
-
padding: 0;
|
|
59009
|
-
box-sizing: border-box;
|
|
59010
|
-
}
|
|
59011
|
-
|
|
59012
|
-
body {
|
|
59013
|
-
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
|
59014
|
-
background: linear-gradient(135deg, #0f172a 0%, #1e293b 50%, #0f172a 100%);
|
|
59015
|
-
color: var(--text-light);
|
|
59016
|
-
min-height: 100vh;
|
|
59017
|
-
line-height: 1.6;
|
|
59018
|
-
}
|
|
59019
|
-
|
|
59020
|
-
/* === Header === */
|
|
59021
|
-
.header {
|
|
59022
|
-
background: var(--glass);
|
|
59023
|
-
backdrop-filter: blur(10px);
|
|
59024
|
-
border-bottom: 1px solid var(--border-color);
|
|
59025
|
-
padding: 1rem 2rem;
|
|
59026
|
-
position: fixed;
|
|
59027
|
-
top: 0;
|
|
59028
|
-
left: 0;
|
|
59029
|
-
right: 0;
|
|
59030
|
-
z-index: 100;
|
|
59031
|
-
}
|
|
59032
|
-
|
|
59033
|
-
.header-content {
|
|
59034
|
-
max-width: 1200px;
|
|
59035
|
-
margin: 0 auto;
|
|
59036
|
-
display: flex;
|
|
59037
|
-
justify-content: space-between;
|
|
59038
|
-
align-items: center;
|
|
59039
|
-
}
|
|
59040
|
-
|
|
59041
|
-
.logo {
|
|
59042
|
-
font-size: 1.5rem;
|
|
59043
|
-
font-weight: 700;
|
|
59044
|
-
background: linear-gradient(135deg, var(--primary), var(--secondary));
|
|
59045
|
-
-webkit-background-clip: text;
|
|
59046
|
-
-webkit-text-fill-color: transparent;
|
|
59047
|
-
background-clip: text;
|
|
59048
|
-
}
|
|
59049
|
-
|
|
59050
|
-
.nav-links {
|
|
59051
|
-
display: flex;
|
|
59052
|
-
gap: 2rem;
|
|
59053
|
-
list-style: none;
|
|
59054
|
-
}
|
|
59055
|
-
|
|
59056
|
-
.nav-links a {
|
|
59057
|
-
color: var(--text-muted);
|
|
59058
|
-
text-decoration: none;
|
|
59059
|
-
transition: color 0.3s;
|
|
59060
|
-
}
|
|
59061
|
-
|
|
59062
|
-
.nav-links a:hover {
|
|
59063
|
-
color: var(--primary);
|
|
59064
|
-
}
|
|
59065
|
-
|
|
59066
|
-
/* === Hero Section === */
|
|
59067
|
-
.hero {
|
|
59068
|
-
padding: 8rem 2rem 4rem;
|
|
59069
|
-
text-align: center;
|
|
59070
|
-
max-width: 900px;
|
|
59071
|
-
margin: 0 auto;
|
|
59072
|
-
}
|
|
59073
|
-
|
|
59074
|
-
.hero h1 {
|
|
59075
|
-
font-size: 3.5rem;
|
|
59076
|
-
font-weight: 800;
|
|
59077
|
-
margin-bottom: 1rem;
|
|
59078
|
-
background: linear-gradient(135deg, #fff, var(--primary));
|
|
59079
|
-
-webkit-background-clip: text;
|
|
59080
|
-
-webkit-text-fill-color: transparent;
|
|
59081
|
-
background-clip: text;
|
|
59082
|
-
}
|
|
59083
|
-
|
|
59084
|
-
.hero p {
|
|
59085
|
-
font-size: 1.25rem;
|
|
59086
|
-
color: var(--text-muted);
|
|
59087
|
-
margin-bottom: 2rem;
|
|
59088
|
-
}
|
|
59089
|
-
|
|
59090
|
-
.cta-button {
|
|
59091
|
-
background: linear-gradient(135deg, var(--primary), var(--primary-dark));
|
|
59092
|
-
color: white;
|
|
59093
|
-
padding: 1rem 2.5rem;
|
|
59094
|
-
border: none;
|
|
59095
|
-
border-radius: 50px;
|
|
59096
|
-
font-size: 1.1rem;
|
|
59097
|
-
font-weight: 600;
|
|
59098
|
-
cursor: pointer;
|
|
59099
|
-
transition: transform 0.3s, box-shadow 0.3s;
|
|
59100
|
-
}
|
|
59101
|
-
|
|
59102
|
-
.cta-button:hover {
|
|
59103
|
-
transform: translateY(-2px);
|
|
59104
|
-
box-shadow: 0 10px 30px rgba(34, 197, 94, 0.3);
|
|
59105
|
-
}
|
|
59106
|
-
|
|
59107
|
-
/* === Products Grid === */
|
|
59108
|
-
.products {
|
|
59109
|
-
max-width: 1200px;
|
|
59110
|
-
margin: 0 auto;
|
|
59111
|
-
padding: 4rem 2rem;
|
|
59112
|
-
}
|
|
59113
|
-
|
|
59114
|
-
.products h2 {
|
|
59115
|
-
text-align: center;
|
|
59116
|
-
font-size: 2.5rem;
|
|
59117
|
-
margin-bottom: 3rem;
|
|
59118
|
-
}
|
|
59119
|
-
|
|
59120
|
-
.products-grid {
|
|
59121
|
-
display: grid;
|
|
59122
|
-
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
59123
|
-
gap: 2rem;
|
|
59124
|
-
}
|
|
59125
|
-
|
|
59126
|
-
.product-card {
|
|
59127
|
-
background: var(--bg-card);
|
|
59128
|
-
border: 1px solid var(--border-color);
|
|
59129
|
-
border-radius: 20px;
|
|
59130
|
-
overflow: hidden;
|
|
59131
|
-
transition: transform 0.3s, box-shadow 0.3s;
|
|
59132
|
-
}
|
|
59133
|
-
|
|
59134
|
-
.product-card:hover {
|
|
59135
|
-
transform: translateY(-5px);
|
|
59136
|
-
box-shadow: var(--shadow);
|
|
59137
|
-
}
|
|
59138
|
-
|
|
59139
|
-
.product-image {
|
|
59140
|
-
width: 100%;
|
|
59141
|
-
height: 200px;
|
|
59142
|
-
object-fit: cover;
|
|
59143
|
-
background: linear-gradient(135deg, var(--primary), var(--secondary));
|
|
59144
|
-
display: flex;
|
|
59145
|
-
align-items: center;
|
|
59146
|
-
justify-content: center;
|
|
59147
|
-
font-size: 4rem;
|
|
59148
|
-
}
|
|
59149
|
-
|
|
59150
|
-
.product-info {
|
|
59151
|
-
padding: 1.5rem;
|
|
59152
|
-
}
|
|
59153
|
-
|
|
59154
|
-
.product-info h3 {
|
|
59155
|
-
font-size: 1.25rem;
|
|
59156
|
-
margin-bottom: 0.5rem;
|
|
59157
|
-
}
|
|
59158
|
-
|
|
59159
|
-
.product-info p {
|
|
59160
|
-
color: var(--text-muted);
|
|
59161
|
-
font-size: 0.9rem;
|
|
59162
|
-
margin-bottom: 1rem;
|
|
59163
|
-
}
|
|
59164
|
-
|
|
59165
|
-
.product-price {
|
|
59166
|
-
font-size: 1.5rem;
|
|
59167
|
-
font-weight: 700;
|
|
59168
|
-
color: var(--primary);
|
|
59169
|
-
}
|
|
59170
|
-
|
|
59171
|
-
/* === Chatbox Widget === */
|
|
59172
|
-
.chat-widget {
|
|
59173
|
-
position: fixed;
|
|
59174
|
-
bottom: 20px;
|
|
59175
|
-
right: 20px;
|
|
59176
|
-
z-index: 1000;
|
|
59177
|
-
}
|
|
59178
|
-
|
|
59179
|
-
.chat-toggle {
|
|
59180
|
-
width: 60px;
|
|
59181
|
-
height: 60px;
|
|
59182
|
-
border-radius: 50%;
|
|
59183
|
-
background: linear-gradient(135deg, var(--primary), var(--secondary));
|
|
59184
|
-
border: none;
|
|
59185
|
-
cursor: pointer;
|
|
59186
|
-
display: flex;
|
|
59187
|
-
align-items: center;
|
|
59188
|
-
justify-content: center;
|
|
59189
|
-
box-shadow: 0 5px 30px rgba(34, 197, 94, 0.4);
|
|
59190
|
-
transition: transform 0.3s;
|
|
59191
|
-
}
|
|
59192
|
-
|
|
59193
|
-
.chat-toggle:hover {
|
|
59194
|
-
transform: scale(1.1);
|
|
59195
|
-
}
|
|
59196
|
-
|
|
59197
|
-
.chat-toggle svg {
|
|
59198
|
-
width: 28px;
|
|
59199
|
-
height: 28px;
|
|
59200
|
-
fill: white;
|
|
59201
|
-
}
|
|
59202
|
-
|
|
59203
|
-
.chat-window {
|
|
59204
|
-
position: absolute;
|
|
59205
|
-
bottom: 80px;
|
|
59206
|
-
right: 0;
|
|
59207
|
-
width: 380px;
|
|
59208
|
-
height: 500px;
|
|
59209
|
-
background: var(--bg-dark);
|
|
59210
|
-
border: 1px solid var(--border-color);
|
|
59211
|
-
border-radius: 20px;
|
|
59212
|
-
box-shadow: var(--shadow);
|
|
59213
|
-
display: none;
|
|
59214
|
-
flex-direction: column;
|
|
59215
|
-
overflow: hidden;
|
|
59216
|
-
animation: slideUp 0.3s ease;
|
|
59217
|
-
}
|
|
59218
|
-
|
|
59219
|
-
.chat-window.open {
|
|
59220
|
-
display: flex;
|
|
59221
|
-
}
|
|
59222
|
-
|
|
59223
|
-
@keyframes slideUp {
|
|
59224
|
-
from {
|
|
59225
|
-
opacity: 0;
|
|
59226
|
-
transform: translateY(20px);
|
|
59227
|
-
}
|
|
59228
|
-
to {
|
|
59229
|
-
opacity: 1;
|
|
59230
|
-
transform: translateY(0);
|
|
59231
|
-
}
|
|
59232
|
-
}
|
|
59233
|
-
|
|
59234
|
-
.chat-header {
|
|
59235
|
-
background: linear-gradient(135deg, var(--primary), var(--primary-dark));
|
|
59236
|
-
padding: 1rem 1.5rem;
|
|
59237
|
-
display: flex;
|
|
59238
|
-
align-items: center;
|
|
59239
|
-
gap: 0.75rem;
|
|
59240
|
-
}
|
|
59241
|
-
|
|
59242
|
-
.chat-header-avatar {
|
|
59243
|
-
width: 40px;
|
|
59244
|
-
height: 40px;
|
|
59245
|
-
border-radius: 50%;
|
|
59246
|
-
background: rgba(255, 255, 255, 0.2);
|
|
59247
|
-
display: flex;
|
|
59248
|
-
align-items: center;
|
|
59249
|
-
justify-content: center;
|
|
59250
|
-
font-size: 1.25rem;
|
|
59251
|
-
}
|
|
59252
|
-
|
|
59253
|
-
.chat-header-info h4 {
|
|
59254
|
-
font-size: 1rem;
|
|
59255
|
-
font-weight: 600;
|
|
59256
|
-
}
|
|
59257
|
-
|
|
59258
|
-
.chat-header-info span {
|
|
59259
|
-
font-size: 0.75rem;
|
|
59260
|
-
opacity: 0.8;
|
|
59261
|
-
}
|
|
59262
|
-
|
|
59263
|
-
.chat-messages {
|
|
59264
|
-
flex: 1;
|
|
59265
|
-
overflow-y: auto;
|
|
59266
|
-
padding: 1rem;
|
|
59267
|
-
display: flex;
|
|
59268
|
-
flex-direction: column;
|
|
59269
|
-
gap: 0.75rem;
|
|
59270
|
-
}
|
|
59271
|
-
|
|
59272
|
-
.message {
|
|
59273
|
-
max-width: 80%;
|
|
59274
|
-
padding: 0.75rem 1rem;
|
|
59275
|
-
border-radius: 18px;
|
|
59276
|
-
font-size: 0.9rem;
|
|
59277
|
-
line-height: 1.4;
|
|
59278
|
-
}
|
|
59279
|
-
|
|
59280
|
-
.message.bot {
|
|
59281
|
-
background: var(--glass);
|
|
59282
|
-
border: 1px solid var(--border-color);
|
|
59283
|
-
align-self: flex-start;
|
|
59284
|
-
border-bottom-left-radius: 4px;
|
|
59285
|
-
}
|
|
59286
|
-
|
|
59287
|
-
.message.user {
|
|
59288
|
-
background: linear-gradient(135deg, var(--primary), var(--primary-dark));
|
|
59289
|
-
align-self: flex-end;
|
|
59290
|
-
border-bottom-right-radius: 4px;
|
|
59291
|
-
}
|
|
59292
|
-
|
|
59293
|
-
.typing-indicator {
|
|
59294
|
-
display: flex;
|
|
59295
|
-
gap: 4px;
|
|
59296
|
-
padding: 0.75rem 1rem;
|
|
59297
|
-
background: var(--glass);
|
|
59298
|
-
border: 1px solid var(--border-color);
|
|
59299
|
-
border-radius: 18px;
|
|
59300
|
-
align-self: flex-start;
|
|
59301
|
-
border-bottom-left-radius: 4px;
|
|
59302
|
-
}
|
|
59303
|
-
|
|
59304
|
-
.typing-indicator span {
|
|
59305
|
-
width: 8px;
|
|
59306
|
-
height: 8px;
|
|
59307
|
-
background: var(--text-muted);
|
|
59308
|
-
border-radius: 50%;
|
|
59309
|
-
animation: bounce 1.4s infinite ease-in-out;
|
|
59310
|
-
}
|
|
59311
|
-
|
|
59312
|
-
.typing-indicator span:nth-child(1) { animation-delay: -0.32s; }
|
|
59313
|
-
.typing-indicator span:nth-child(2) { animation-delay: -0.16s; }
|
|
59314
|
-
|
|
59315
|
-
@keyframes bounce {
|
|
59316
|
-
0%, 80%, 100% { transform: scale(0); }
|
|
59317
|
-
40% { transform: scale(1); }
|
|
59318
|
-
}
|
|
59319
|
-
|
|
59320
|
-
.chat-input-container {
|
|
59321
|
-
padding: 1rem;
|
|
59322
|
-
border-top: 1px solid var(--border-color);
|
|
59323
|
-
display: flex;
|
|
59324
|
-
gap: 0.5rem;
|
|
59325
|
-
}
|
|
59326
|
-
|
|
59327
|
-
.chat-input {
|
|
59328
|
-
flex: 1;
|
|
59329
|
-
background: var(--glass);
|
|
59330
|
-
border: 1px solid var(--border-color);
|
|
59331
|
-
border-radius: 25px;
|
|
59332
|
-
padding: 0.75rem 1rem;
|
|
59333
|
-
color: var(--text-light);
|
|
59334
|
-
font-size: 0.9rem;
|
|
59335
|
-
outline: none;
|
|
59336
|
-
}
|
|
59337
|
-
|
|
59338
|
-
.chat-input::placeholder {
|
|
59339
|
-
color: var(--text-muted);
|
|
59340
|
-
}
|
|
59341
|
-
|
|
59342
|
-
.chat-send {
|
|
59343
|
-
width: 44px;
|
|
59344
|
-
height: 44px;
|
|
59345
|
-
border-radius: 50%;
|
|
59346
|
-
background: linear-gradient(135deg, var(--primary), var(--primary-dark));
|
|
59347
|
-
border: none;
|
|
59348
|
-
cursor: pointer;
|
|
59349
|
-
display: flex;
|
|
59350
|
-
align-items: center;
|
|
59351
|
-
justify-content: center;
|
|
59352
|
-
transition: transform 0.2s;
|
|
59353
|
-
}
|
|
59354
|
-
|
|
59355
|
-
.chat-send:hover {
|
|
59356
|
-
transform: scale(1.05);
|
|
59357
|
-
}
|
|
59358
|
-
|
|
59359
|
-
.chat-send svg {
|
|
59360
|
-
width: 20px;
|
|
59361
|
-
height: 20px;
|
|
59362
|
-
fill: white;
|
|
59363
|
-
}
|
|
59364
|
-
|
|
59365
|
-
/* === Admin Panel Styles === */
|
|
59366
|
-
.admin-container {
|
|
59367
|
-
max-width: 900px;
|
|
59368
|
-
margin: 0 auto;
|
|
59369
|
-
padding: 6rem 2rem 4rem;
|
|
59370
|
-
}
|
|
59371
|
-
|
|
59372
|
-
.admin-header {
|
|
59373
|
-
text-align: center;
|
|
59374
|
-
margin-bottom: 3rem;
|
|
59375
|
-
}
|
|
59376
|
-
|
|
59377
|
-
.admin-header h1 {
|
|
59378
|
-
font-size: 2.5rem;
|
|
59379
|
-
margin-bottom: 0.5rem;
|
|
59380
|
-
}
|
|
59381
|
-
|
|
59382
|
-
.admin-header p {
|
|
59383
|
-
color: var(--text-muted);
|
|
59384
|
-
}
|
|
59385
|
-
|
|
59386
|
-
.admin-card {
|
|
59387
|
-
background: var(--bg-card);
|
|
59388
|
-
border: 1px solid var(--border-color);
|
|
59389
|
-
border-radius: 20px;
|
|
59390
|
-
padding: 2rem;
|
|
59391
|
-
margin-bottom: 2rem;
|
|
59392
|
-
}
|
|
59393
|
-
|
|
59394
|
-
.admin-card h2 {
|
|
59395
|
-
font-size: 1.25rem;
|
|
59396
|
-
margin-bottom: 1.5rem;
|
|
59397
|
-
display: flex;
|
|
59398
|
-
align-items: center;
|
|
59399
|
-
gap: 0.5rem;
|
|
59400
|
-
}
|
|
59401
|
-
|
|
59402
|
-
.form-group {
|
|
59403
|
-
margin-bottom: 1.5rem;
|
|
59404
|
-
}
|
|
59405
|
-
|
|
59406
|
-
.form-group label {
|
|
59407
|
-
display: block;
|
|
59408
|
-
font-size: 0.9rem;
|
|
59409
|
-
color: var(--text-muted);
|
|
59410
|
-
margin-bottom: 0.5rem;
|
|
59411
|
-
}
|
|
59412
|
-
|
|
59413
|
-
.form-input {
|
|
59414
|
-
width: 100%;
|
|
59415
|
-
background: var(--glass);
|
|
59416
|
-
border: 1px solid var(--border-color);
|
|
59417
|
-
border-radius: 10px;
|
|
59418
|
-
padding: 0.875rem 1rem;
|
|
59419
|
-
color: var(--text-light);
|
|
59420
|
-
font-size: 0.95rem;
|
|
59421
|
-
outline: none;
|
|
59422
|
-
transition: border-color 0.3s;
|
|
59423
|
-
}
|
|
59424
|
-
|
|
59425
|
-
.form-input:focus {
|
|
59426
|
-
border-color: var(--primary);
|
|
59427
|
-
}
|
|
59428
|
-
|
|
59429
|
-
.form-input::placeholder {
|
|
59430
|
-
color: var(--text-muted);
|
|
59431
|
-
}
|
|
59432
|
-
|
|
59433
|
-
textarea.form-input {
|
|
59434
|
-
min-height: 200px;
|
|
59435
|
-
resize: vertical;
|
|
59436
|
-
font-family: inherit;
|
|
59437
|
-
}
|
|
59438
|
-
|
|
59439
|
-
.btn {
|
|
59440
|
-
background: linear-gradient(135deg, var(--primary), var(--primary-dark));
|
|
59441
|
-
color: white;
|
|
59442
|
-
padding: 0.875rem 2rem;
|
|
59443
|
-
border: none;
|
|
59444
|
-
border-radius: 10px;
|
|
59445
|
-
font-size: 1rem;
|
|
59446
|
-
font-weight: 600;
|
|
59447
|
-
cursor: pointer;
|
|
59448
|
-
transition: transform 0.2s, box-shadow 0.2s;
|
|
59449
|
-
display: inline-flex;
|
|
59450
|
-
align-items: center;
|
|
59451
|
-
gap: 0.5rem;
|
|
59452
|
-
}
|
|
59453
|
-
|
|
59454
|
-
.btn:hover {
|
|
59455
|
-
transform: translateY(-2px);
|
|
59456
|
-
box-shadow: 0 10px 30px rgba(34, 197, 94, 0.3);
|
|
59457
|
-
}
|
|
59458
|
-
|
|
59459
|
-
.btn:disabled {
|
|
59460
|
-
opacity: 0.6;
|
|
59461
|
-
cursor: not-allowed;
|
|
59462
|
-
transform: none;
|
|
59463
|
-
}
|
|
59464
|
-
|
|
59465
|
-
.btn-secondary {
|
|
59466
|
-
background: var(--glass);
|
|
59467
|
-
border: 1px solid var(--border-color);
|
|
59468
|
-
}
|
|
59469
|
-
|
|
59470
|
-
.status-bar {
|
|
59471
|
-
background: var(--glass);
|
|
59472
|
-
border: 1px solid var(--border-color);
|
|
59473
|
-
border-radius: 10px;
|
|
59474
|
-
padding: 1rem 1.5rem;
|
|
59475
|
-
display: flex;
|
|
59476
|
-
justify-content: space-between;
|
|
59477
|
-
align-items: center;
|
|
59478
|
-
margin-top: 1.5rem;
|
|
59479
|
-
}
|
|
59480
|
-
|
|
59481
|
-
.status-item {
|
|
59482
|
-
text-align: center;
|
|
59483
|
-
}
|
|
59484
|
-
|
|
59485
|
-
.status-item .value {
|
|
59486
|
-
font-size: 1.5rem;
|
|
59487
|
-
font-weight: 700;
|
|
59488
|
-
color: var(--primary);
|
|
59489
|
-
}
|
|
59490
|
-
|
|
59491
|
-
.status-item .label {
|
|
59492
|
-
font-size: 0.8rem;
|
|
59493
|
-
color: var(--text-muted);
|
|
59494
|
-
}
|
|
59495
|
-
|
|
59496
|
-
.toast {
|
|
59497
|
-
position: fixed;
|
|
59498
|
-
bottom: 20px;
|
|
59499
|
-
left: 50%;
|
|
59500
|
-
transform: translateX(-50%);
|
|
59501
|
-
background: var(--primary);
|
|
59502
|
-
color: white;
|
|
59503
|
-
padding: 1rem 2rem;
|
|
59504
|
-
border-radius: 10px;
|
|
59505
|
-
box-shadow: var(--shadow);
|
|
59506
|
-
opacity: 0;
|
|
59507
|
-
transition: opacity 0.3s;
|
|
59508
|
-
z-index: 2000;
|
|
59509
|
-
}
|
|
59510
|
-
|
|
59511
|
-
.toast.show {
|
|
59512
|
-
opacity: 1;
|
|
59513
|
-
}
|
|
59514
|
-
|
|
59515
|
-
/* === Responsive === */
|
|
59516
|
-
@media (max-width: 768px) {
|
|
59517
|
-
.hero h1 {
|
|
59518
|
-
font-size: 2.5rem;
|
|
59519
|
-
}
|
|
59520
|
-
|
|
59521
|
-
.chat-window {
|
|
59522
|
-
width: calc(100vw - 40px);
|
|
59523
|
-
height: 60vh;
|
|
59524
|
-
}
|
|
59525
|
-
|
|
59526
|
-
.nav-links {
|
|
59527
|
-
display: none;
|
|
59528
|
-
}
|
|
59529
|
-
}
|
|
59530
|
-
`;
|
|
59531
|
-
|
|
59532
|
-
// ../../packages/template/demo/aichat/files/serverTs.ts
|
|
59533
|
-
var serverTs = `import express, { Request, Response } from 'express';
|
|
59534
|
-
import path from 'path';
|
|
59535
|
-
import chatRouter from './routes/chat';
|
|
59536
|
-
import embedRouter from './routes/embed';
|
|
59537
|
-
import configRouter from './routes/config';
|
|
59538
|
-
import { loadEmbeddings } from './vectorStore';
|
|
59539
|
-
import { loadConfig } from './aiClient';
|
|
59540
|
-
|
|
59541
|
-
const app = express();
|
|
59542
|
-
const port = 3500;
|
|
59543
|
-
|
|
59544
|
-
// Middleware
|
|
59545
|
-
app.use(express.static(path.join(__dirname, '../public')));
|
|
59546
|
-
app.use(express.json());
|
|
59547
|
-
|
|
59548
|
-
// Load persisted data
|
|
59549
|
-
loadEmbeddings();
|
|
59550
|
-
loadConfig();
|
|
59551
|
-
|
|
59552
|
-
// API Routes
|
|
59553
|
-
app.use('/api/chat', chatRouter);
|
|
59554
|
-
app.use('/api/embed', embedRouter);
|
|
59555
|
-
app.use('/api/config', configRouter);
|
|
59556
|
-
|
|
59557
|
-
// Serve main page
|
|
59558
|
-
app.get('/', (req: Request, res: Response) => {
|
|
59559
|
-
res.sendFile(path.join(__dirname, '../public/index.html'));
|
|
59560
|
-
});
|
|
59561
|
-
|
|
59562
|
-
// Start server
|
|
59563
|
-
app.listen(port, () => {
|
|
59564
|
-
console.log('');
|
|
59565
|
-
console.log('\u{1F34A} ====================================');
|
|
59566
|
-
console.log(' FreshFruit AI Chat Demo');
|
|
59567
|
-
console.log('====================================');
|
|
59568
|
-
console.log('');
|
|
59569
|
-
console.log('\u{1F4CD} Store: http://localhost:' + port);
|
|
59570
|
-
console.log('\u{1F527} Admin Panel: http://localhost:' + port + '/admin.html');
|
|
59571
|
-
console.log('');
|
|
59572
|
-
console.log('\u{1F4DD} Quick Start:');
|
|
59573
|
-
console.log(' 1. Open the Admin Panel');
|
|
59574
|
-
console.log(' 2. Configure your OpenAI API key');
|
|
59575
|
-
console.log(' 3. Add FAQ content and click "Embed"');
|
|
59576
|
-
console.log(' 4. Open the Store and chat with the AI!');
|
|
59577
|
-
console.log('');
|
|
59578
|
-
});
|
|
59579
|
-
`;
|
|
59580
|
-
var tsconfigJson = `{
|
|
59581
|
-
"compilerOptions": {
|
|
59582
|
-
"target": "es2016",
|
|
59583
|
-
"module": "commonjs",
|
|
59584
|
-
"outDir": "./dist",
|
|
59585
|
-
"esModuleInterop": true,
|
|
59586
|
-
"forceConsistentCasingInFileNames": true,
|
|
59587
|
-
"strict": true,
|
|
59588
|
-
"skipLibCheck": true
|
|
59589
|
-
}
|
|
59590
|
-
}`;
|
|
59591
|
-
var tsupConfig = `import { defineConfig } from 'tsup';
|
|
59592
|
-
|
|
59593
|
-
export default defineConfig({
|
|
59594
|
-
entry: ['src/index.ts'],
|
|
59595
|
-
splitting: false,
|
|
59596
|
-
sourcemap: true,
|
|
59597
|
-
clean: true,
|
|
59598
|
-
format: ['cjs'],
|
|
59599
|
-
});`;
|
|
59600
|
-
|
|
59601
|
-
// ../../packages/template/demo/aichat/files/vectorStoreTs.ts
|
|
59602
|
-
var vectorStoreTs = `import fs from 'fs';
|
|
59603
|
-
import path from 'path';
|
|
59604
|
-
|
|
59605
|
-
const EMBEDDINGS_FILE = path.join(__dirname, '../embeddings.json');
|
|
59606
|
-
|
|
59607
|
-
interface EmbeddingEntry {
|
|
59608
|
-
id: string;
|
|
59609
|
-
text: string;
|
|
59610
|
-
embedding: number[];
|
|
59611
|
-
timestamp: number;
|
|
59612
|
-
}
|
|
59613
|
-
|
|
59614
|
-
// In-memory vector database
|
|
59615
|
-
let vectorStore: EmbeddingEntry[] = [];
|
|
59616
|
-
|
|
59617
|
-
// Load embeddings from file on startup
|
|
59618
|
-
export function loadEmbeddings(): void {
|
|
59619
|
-
try {
|
|
59620
|
-
if (fs.existsSync(EMBEDDINGS_FILE)) {
|
|
59621
|
-
const data = fs.readFileSync(EMBEDDINGS_FILE, 'utf-8');
|
|
59622
|
-
vectorStore = JSON.parse(data);
|
|
59623
|
-
console.log('\u{1F4DA} Loaded ' + vectorStore.length + ' embeddings from file');
|
|
59624
|
-
}
|
|
59625
|
-
} catch (error) {
|
|
59626
|
-
console.error('Failed to load embeddings:', error);
|
|
59627
|
-
vectorStore = [];
|
|
59628
|
-
}
|
|
59629
|
-
}
|
|
59630
|
-
|
|
59631
|
-
// Save embeddings to file
|
|
59632
|
-
export function saveEmbeddings(): void {
|
|
59633
|
-
try {
|
|
59634
|
-
fs.writeFileSync(EMBEDDINGS_FILE, JSON.stringify(vectorStore, null, 2));
|
|
59635
|
-
} catch (error) {
|
|
59636
|
-
console.error('Failed to save embeddings:', error);
|
|
59637
|
-
}
|
|
59638
|
-
}
|
|
59639
|
-
|
|
59640
|
-
// Add embedding to store
|
|
59641
|
-
export function addEmbedding(text: string, embedding: number[]): void {
|
|
59642
|
-
const entry: EmbeddingEntry = {
|
|
59643
|
-
id: Date.now().toString(36) + Math.random().toString(36).substr(2),
|
|
59644
|
-
text,
|
|
59645
|
-
embedding,
|
|
59646
|
-
timestamp: Date.now()
|
|
59647
|
-
};
|
|
59648
|
-
vectorStore.push(entry);
|
|
59649
|
-
saveEmbeddings();
|
|
59650
|
-
}
|
|
59651
|
-
|
|
59652
|
-
// Clear all embeddings
|
|
59653
|
-
export function clearEmbeddings(): void {
|
|
59654
|
-
vectorStore = [];
|
|
59655
|
-
saveEmbeddings();
|
|
59656
|
-
}
|
|
59657
|
-
|
|
59658
|
-
// Get embedding count
|
|
59659
|
-
export function getEmbeddingCount(): number {
|
|
59660
|
-
return vectorStore.length;
|
|
59661
|
-
}
|
|
59662
|
-
|
|
59663
|
-
// Cosine similarity between two vectors
|
|
59664
|
-
function cosineSimilarity(a: number[], b: number[]): number {
|
|
59665
|
-
if (a.length !== b.length) return 0;
|
|
59666
|
-
|
|
59667
|
-
let dotProduct = 0;
|
|
59668
|
-
let normA = 0;
|
|
59669
|
-
let normB = 0;
|
|
59670
|
-
|
|
59671
|
-
for (let i = 0; i < a.length; i++) {
|
|
59672
|
-
dotProduct += a[i] * b[i];
|
|
59673
|
-
normA += a[i] * a[i];
|
|
59674
|
-
normB += b[i] * b[i];
|
|
59675
|
-
}
|
|
59676
|
-
|
|
59677
|
-
if (normA === 0 || normB === 0) return 0;
|
|
59678
|
-
return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
|
|
59679
|
-
}
|
|
59680
|
-
|
|
59681
|
-
// Search for similar embeddings
|
|
59682
|
-
export function searchSimilar(queryEmbedding: number[], topK: number = 3): { text: string; score: number }[] {
|
|
59683
|
-
const results = vectorStore
|
|
59684
|
-
.map(entry => ({
|
|
59685
|
-
text: entry.text,
|
|
59686
|
-
score: cosineSimilarity(queryEmbedding, entry.embedding)
|
|
59687
|
-
}))
|
|
59688
|
-
.sort((a, b) => b.score - a.score)
|
|
59689
|
-
.slice(0, topK);
|
|
59690
|
-
|
|
59691
|
-
return results;
|
|
59692
|
-
}
|
|
59693
|
-
|
|
59694
|
-
// Get last update time
|
|
59695
|
-
export function getLastUpdated(): string | null {
|
|
59696
|
-
if (vectorStore.length === 0) return null;
|
|
59697
|
-
const latest = Math.max(...vectorStore.map(e => e.timestamp));
|
|
59698
|
-
return new Date(latest).toLocaleString();
|
|
59699
|
-
}
|
|
59700
|
-
`;
|
|
59701
|
-
|
|
59702
|
-
// ../../packages/template/demo/aichat/files/aiClientTs.ts
|
|
59703
|
-
var aiClientTs = `import fs from 'fs';
|
|
59704
|
-
import path from 'path';
|
|
59705
|
-
|
|
59706
|
-
const CONFIG_FILE = path.join(__dirname, '../config.json');
|
|
59707
|
-
|
|
59708
|
-
export interface AIConfig {
|
|
59709
|
-
apiKey: string;
|
|
59710
|
-
providerUrl: string;
|
|
59711
|
-
embeddingsUrl: string;
|
|
59712
|
-
model: string;
|
|
59713
|
-
embeddingsModel: string;
|
|
59714
|
-
}
|
|
59715
|
-
|
|
59716
|
-
// Default configuration
|
|
59717
|
-
const defaultConfig: AIConfig = {
|
|
59718
|
-
apiKey: '',
|
|
59719
|
-
providerUrl: 'https://api.openai.com/v1/chat/completions',
|
|
59720
|
-
embeddingsUrl: 'https://api.openai.com/v1/embeddings',
|
|
59721
|
-
model: 'gpt-3.5-turbo',
|
|
59722
|
-
embeddingsModel: 'text-embedding-3-small'
|
|
59723
|
-
};
|
|
59724
|
-
|
|
59725
|
-
let currentConfig: AIConfig = { ...defaultConfig };
|
|
59726
|
-
|
|
59727
|
-
// Load configuration from file
|
|
59728
|
-
export function loadConfig(): void {
|
|
59729
|
-
try {
|
|
59730
|
-
if (fs.existsSync(CONFIG_FILE)) {
|
|
59731
|
-
const data = fs.readFileSync(CONFIG_FILE, 'utf-8');
|
|
59732
|
-
currentConfig = { ...defaultConfig, ...JSON.parse(data) };
|
|
59733
|
-
console.log('\u{1F511} Loaded AI configuration');
|
|
59734
|
-
}
|
|
59735
|
-
} catch (error) {
|
|
59736
|
-
console.error('Failed to load config:', error);
|
|
59737
|
-
currentConfig = { ...defaultConfig };
|
|
59738
|
-
}
|
|
59739
|
-
}
|
|
59740
|
-
|
|
59741
|
-
// Save configuration to file
|
|
59742
|
-
export function saveConfig(config: AIConfig): void {
|
|
59743
|
-
currentConfig = { ...config };
|
|
59744
|
-
try {
|
|
59745
|
-
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
59746
|
-
} catch (error) {
|
|
59747
|
-
console.error('Failed to save config:', error);
|
|
59748
|
-
}
|
|
59749
|
-
}
|
|
59750
|
-
|
|
59751
|
-
// Get current configuration
|
|
59752
|
-
export function getConfig(): AIConfig {
|
|
59753
|
-
return currentConfig;
|
|
59754
|
-
}
|
|
59755
|
-
|
|
59756
|
-
// Call embeddings API
|
|
59757
|
-
export async function callEmbeddingsAPI(text: string): Promise<number[]> {
|
|
59758
|
-
const config = getConfig();
|
|
59759
|
-
|
|
59760
|
-
if (!config.apiKey) {
|
|
59761
|
-
throw new Error('API key not configured');
|
|
59762
|
-
}
|
|
59763
|
-
|
|
59764
|
-
const response = await fetch(config.embeddingsUrl, {
|
|
59765
|
-
method: 'POST',
|
|
59766
|
-
headers: {
|
|
59767
|
-
'Content-Type': 'application/json',
|
|
59768
|
-
'Authorization': 'Bearer ' + config.apiKey
|
|
59769
|
-
},
|
|
59770
|
-
body: JSON.stringify({
|
|
59771
|
-
model: config.embeddingsModel,
|
|
59772
|
-
input: text
|
|
59773
|
-
})
|
|
59774
|
-
});
|
|
59775
|
-
|
|
59776
|
-
if (!response.ok) {
|
|
59777
|
-
const error = await response.text();
|
|
59778
|
-
throw new Error('Embeddings API error: ' + error);
|
|
59779
|
-
}
|
|
59780
|
-
|
|
59781
|
-
const data = await response.json();
|
|
59782
|
-
return data.data[0].embedding;
|
|
59783
|
-
}
|
|
59784
|
-
|
|
59785
|
-
// Call chat completions API
|
|
59786
|
-
export async function callChatAPI(systemPrompt: string, userMessage: string): Promise<string> {
|
|
59787
|
-
const config = getConfig();
|
|
59788
|
-
|
|
59789
|
-
if (!config.apiKey) {
|
|
59790
|
-
throw new Error('API key not configured');
|
|
59791
|
-
}
|
|
59792
|
-
|
|
59793
|
-
const response = await fetch(config.providerUrl, {
|
|
59794
|
-
method: 'POST',
|
|
59795
|
-
headers: {
|
|
59796
|
-
'Content-Type': 'application/json',
|
|
59797
|
-
'Authorization': 'Bearer ' + config.apiKey
|
|
59798
|
-
},
|
|
59799
|
-
body: JSON.stringify({
|
|
59800
|
-
model: config.model,
|
|
59801
|
-
messages: [
|
|
59802
|
-
{ role: 'system', content: systemPrompt },
|
|
59803
|
-
{ role: 'user', content: userMessage }
|
|
59804
|
-
],
|
|
59805
|
-
max_tokens: 500,
|
|
59806
|
-
temperature: 0.7
|
|
59807
|
-
})
|
|
59808
|
-
});
|
|
59809
|
-
|
|
59810
|
-
if (!response.ok) {
|
|
59811
|
-
const error = await response.text();
|
|
59812
|
-
throw new Error('Chat API error: ' + error);
|
|
59813
|
-
}
|
|
59814
|
-
|
|
59815
|
-
const data = await response.json();
|
|
59816
|
-
return data.choices[0].message.content;
|
|
59817
|
-
}
|
|
59818
|
-
`;
|
|
59819
|
-
|
|
59820
|
-
// ../../packages/template/demo/aichat/files/routesTs.ts
|
|
59821
|
-
var chatRouteTs = `import { Router, Request, Response } from 'express';
|
|
59822
|
-
import { searchSimilar } from '../vectorStore';
|
|
59823
|
-
import { getConfig, callEmbeddingsAPI, callChatAPI } from '../aiClient';
|
|
59824
|
-
|
|
59825
|
-
const router = Router();
|
|
59826
|
-
|
|
59827
|
-
router.post('/', async (req: Request, res: Response) => {
|
|
59828
|
-
try {
|
|
59829
|
-
const { message } = req.body;
|
|
59830
|
-
|
|
59831
|
-
if (!message) {
|
|
59832
|
-
return res.status(400).json({ error: 'Message is required' });
|
|
59833
|
-
}
|
|
59834
|
-
|
|
59835
|
-
const config = getConfig();
|
|
59836
|
-
if (!config.apiKey) {
|
|
59837
|
-
return res.json({
|
|
59838
|
-
reply: "I'm not configured yet. Please ask the admin to set up the AI provider in the admin panel."
|
|
59839
|
-
});
|
|
59840
|
-
}
|
|
59841
|
-
|
|
59842
|
-
// Get embedding for the user's message
|
|
59843
|
-
const queryEmbedding = await callEmbeddingsAPI(message);
|
|
59844
|
-
|
|
59845
|
-
// Search for similar content in our knowledge base
|
|
59846
|
-
const similarDocs = searchSimilar(queryEmbedding, 3);
|
|
59847
|
-
|
|
59848
|
-
// Build context from similar documents
|
|
59849
|
-
let context = '';
|
|
59850
|
-
if (similarDocs.length > 0 && similarDocs[0].score > 0.3) {
|
|
59851
|
-
context = 'Relevant information from our knowledge base:\\n' +
|
|
59852
|
-
similarDocs
|
|
59853
|
-
.filter(doc => doc.score > 0.3)
|
|
59854
|
-
.map(doc => doc.text)
|
|
59855
|
-
.join('\\n\\n');
|
|
59856
|
-
}
|
|
59857
|
-
|
|
59858
|
-
// Create the chat prompt
|
|
59859
|
-
const systemPrompt = "You are a helpful customer support assistant for FreshFruit, " +
|
|
59860
|
-
"a premium organic fruit delivery service. Be friendly, helpful, and concise. " +
|
|
59861
|
-
"If you have relevant information from the knowledge base, use it to answer. " +
|
|
59862
|
-
"If you don't know something, say so politely and suggest contacting human support.\\n\\n" +
|
|
59863
|
-
(context ? 'Knowledge Base Context:\\n' + context : 'No specific knowledge base context available for this query.');
|
|
59864
|
-
|
|
59865
|
-
// Call the chat API
|
|
59866
|
-
const reply = await callChatAPI(systemPrompt, message);
|
|
59867
|
-
|
|
59868
|
-
res.json({ reply });
|
|
59869
|
-
} catch (error) {
|
|
59870
|
-
console.error('Chat error:', error);
|
|
59871
|
-
res.status(500).json({ error: 'Failed to process message' });
|
|
59872
|
-
}
|
|
59873
|
-
});
|
|
59874
|
-
|
|
59875
|
-
export default router;
|
|
59876
|
-
`;
|
|
59877
|
-
var embedRouteTs = `import { Router, Request, Response } from 'express';
|
|
59878
|
-
import { addEmbedding, clearEmbeddings, getEmbeddingCount } from '../vectorStore';
|
|
59879
|
-
import { getConfig, callEmbeddingsAPI } from '../aiClient';
|
|
59880
|
-
|
|
59881
|
-
const router = Router();
|
|
59882
|
-
|
|
59883
|
-
// Embed new content
|
|
59884
|
-
router.post('/', async (req: Request, res: Response) => {
|
|
59885
|
-
try {
|
|
59886
|
-
const { content } = req.body;
|
|
59887
|
-
|
|
59888
|
-
if (!content) {
|
|
59889
|
-
return res.status(400).json({ error: 'Content is required' });
|
|
59890
|
-
}
|
|
59891
|
-
|
|
59892
|
-
const config = getConfig();
|
|
59893
|
-
if (!config.apiKey) {
|
|
59894
|
-
return res.status(400).json({ error: 'API key not configured. Please configure in admin panel.' });
|
|
59895
|
-
}
|
|
59896
|
-
|
|
59897
|
-
// Split content into chunks (by double newline or paragraph)
|
|
59898
|
-
const chunks = content
|
|
59899
|
-
.split(/\\n\\n+/)
|
|
59900
|
-
.map((chunk: string) => chunk.trim())
|
|
59901
|
-
.filter((chunk: string) => chunk.length > 10);
|
|
59902
|
-
|
|
59903
|
-
if (chunks.length === 0) {
|
|
59904
|
-
return res.status(400).json({ error: 'No valid content chunks found' });
|
|
59905
|
-
}
|
|
59906
|
-
|
|
59907
|
-
// Embed each chunk
|
|
59908
|
-
let embedded = 0;
|
|
59909
|
-
for (const chunk of chunks) {
|
|
59910
|
-
try {
|
|
59911
|
-
const embedding = await callEmbeddingsAPI(chunk);
|
|
59912
|
-
addEmbedding(chunk, embedding);
|
|
59913
|
-
embedded++;
|
|
59914
|
-
} catch (error) {
|
|
59915
|
-
console.error('Failed to embed chunk:', error);
|
|
59916
|
-
}
|
|
59917
|
-
}
|
|
59918
|
-
|
|
59919
|
-
res.json({
|
|
59920
|
-
message: 'Successfully embedded ' + embedded + ' chunks',
|
|
59921
|
-
count: getEmbeddingCount()
|
|
59922
|
-
});
|
|
59923
|
-
} catch (error) {
|
|
59924
|
-
console.error('Embed error:', error);
|
|
59925
|
-
res.status(500).json({ error: 'Failed to embed content' });
|
|
59926
|
-
}
|
|
59927
|
-
});
|
|
59928
|
-
|
|
59929
|
-
// Clear all embeddings
|
|
59930
|
-
router.delete('/', (req: Request, res: Response) => {
|
|
59931
|
-
clearEmbeddings();
|
|
59932
|
-
res.json({ message: 'All embeddings cleared', count: 0 });
|
|
59933
|
-
});
|
|
59934
|
-
|
|
59935
|
-
export default router;
|
|
59936
|
-
`;
|
|
59937
|
-
var configRouteTs = `import { Router, Request, Response } from 'express';
|
|
59938
|
-
import { getConfig, saveConfig, AIConfig } from '../aiClient';
|
|
59939
|
-
import { getEmbeddingCount, getLastUpdated } from '../vectorStore';
|
|
59940
|
-
|
|
59941
|
-
const router = Router();
|
|
59942
|
-
|
|
59943
|
-
// Get current config
|
|
59944
|
-
router.get('/', (req: Request, res: Response) => {
|
|
59945
|
-
const config = getConfig();
|
|
59946
|
-
// Mask the API key for security
|
|
59947
|
-
const maskedConfig = {
|
|
59948
|
-
...config,
|
|
59949
|
-
apiKey: config.apiKey ? '\u2022\u2022\u2022\u2022\u2022\u2022' + config.apiKey.slice(-4) : ''
|
|
59950
|
-
};
|
|
59951
|
-
|
|
59952
|
-
res.json({
|
|
59953
|
-
config: maskedConfig,
|
|
59954
|
-
embeddingCount: getEmbeddingCount(),
|
|
59955
|
-
lastUpdated: getLastUpdated()
|
|
59956
|
-
});
|
|
59957
|
-
});
|
|
59958
|
-
|
|
59959
|
-
// Update config
|
|
59960
|
-
router.post('/', (req: Request, res: Response) => {
|
|
59961
|
-
try {
|
|
59962
|
-
const { apiKey, providerUrl, embeddingsUrl, model, embeddingsModel } = req.body;
|
|
59963
|
-
|
|
59964
|
-
const newConfig: AIConfig = {
|
|
59965
|
-
apiKey: apiKey || '',
|
|
59966
|
-
providerUrl: providerUrl || 'https://api.openai.com/v1/chat/completions',
|
|
59967
|
-
embeddingsUrl: embeddingsUrl || 'https://api.openai.com/v1/embeddings',
|
|
59968
|
-
model: model || 'gpt-3.5-turbo',
|
|
59969
|
-
embeddingsModel: embeddingsModel || 'text-embedding-3-small'
|
|
59970
|
-
};
|
|
59971
|
-
|
|
59972
|
-
saveConfig(newConfig);
|
|
59973
|
-
res.json({ message: 'Configuration saved' });
|
|
59974
|
-
} catch (error) {
|
|
59975
|
-
console.error('Config save error:', error);
|
|
59976
|
-
res.status(500).json({ error: 'Failed to save configuration' });
|
|
59977
|
-
}
|
|
59978
|
-
});
|
|
59979
|
-
|
|
59980
|
-
export default router;
|
|
59981
|
-
`;
|
|
59982
|
-
|
|
59983
|
-
// ../../packages/template/demo/aichat/index.ts
|
|
59984
|
-
var AIChat = {
|
|
59985
|
-
name: "AI Chat",
|
|
59986
|
-
description: "Fullstack AI Customer Support Chat - Chat with your FAQ/Knowledge Base",
|
|
59987
|
-
notes: "Requires Node.js, NPM, and an OpenAI-compatible API key",
|
|
59988
|
-
templating: [
|
|
59989
|
-
// Install dependencies
|
|
59990
|
-
{
|
|
59991
|
-
action: "command",
|
|
59992
|
-
cmd: "npm",
|
|
59993
|
-
args: ["init", "-y"]
|
|
59994
|
-
},
|
|
59995
|
-
{
|
|
59996
|
-
action: "command",
|
|
59997
|
-
cmd: "npm",
|
|
59998
|
-
args: ["install", "express"]
|
|
59999
|
-
},
|
|
60000
|
-
{
|
|
60001
|
-
action: "command",
|
|
60002
|
-
cmd: "npm",
|
|
60003
|
-
args: ["install", "-D", "nodemon", "typescript", "ts-node", "@types/node", "@types/express", "tsup"]
|
|
60004
|
-
},
|
|
60005
|
-
// Public files
|
|
60006
|
-
{
|
|
60007
|
-
action: "file",
|
|
60008
|
-
file: "public/index.html",
|
|
60009
|
-
filecontent: indexHTML
|
|
60010
|
-
},
|
|
60011
|
-
{
|
|
60012
|
-
action: "file",
|
|
60013
|
-
file: "public/admin.html",
|
|
60014
|
-
filecontent: adminHTML
|
|
60015
|
-
},
|
|
60016
|
-
{
|
|
60017
|
-
action: "file",
|
|
60018
|
-
file: "public/styles.css",
|
|
60019
|
-
filecontent: stylesCSS
|
|
60020
|
-
},
|
|
60021
|
-
// Source files
|
|
60022
|
-
{
|
|
60023
|
-
action: "file",
|
|
60024
|
-
file: "src/index.ts",
|
|
60025
|
-
filecontent: serverTs
|
|
60026
|
-
},
|
|
60027
|
-
{
|
|
60028
|
-
action: "file",
|
|
60029
|
-
file: "src/vectorStore.ts",
|
|
60030
|
-
filecontent: vectorStoreTs
|
|
60031
|
-
},
|
|
60032
|
-
{
|
|
60033
|
-
action: "file",
|
|
60034
|
-
file: "src/aiClient.ts",
|
|
60035
|
-
filecontent: aiClientTs
|
|
60036
|
-
},
|
|
60037
|
-
{
|
|
60038
|
-
action: "file",
|
|
60039
|
-
file: "src/routes/chat.ts",
|
|
60040
|
-
filecontent: chatRouteTs
|
|
60041
|
-
},
|
|
60042
|
-
{
|
|
60043
|
-
action: "file",
|
|
60044
|
-
file: "src/routes/embed.ts",
|
|
60045
|
-
filecontent: embedRouteTs
|
|
60046
|
-
},
|
|
60047
|
-
{
|
|
60048
|
-
action: "file",
|
|
60049
|
-
file: "src/routes/config.ts",
|
|
60050
|
-
filecontent: configRouteTs
|
|
60051
|
-
},
|
|
60052
|
-
// Config files
|
|
60053
|
-
{
|
|
60054
|
-
action: "file",
|
|
60055
|
-
file: "tsconfig.json",
|
|
60056
|
-
filecontent: tsconfigJson
|
|
60057
|
-
},
|
|
60058
|
-
{
|
|
60059
|
-
action: "file",
|
|
60060
|
-
file: "tsup.config.ts",
|
|
60061
|
-
filecontent: tsupConfig
|
|
60062
|
-
},
|
|
60063
|
-
// NPM scripts
|
|
60064
|
-
{
|
|
60065
|
-
action: "command",
|
|
60066
|
-
cmd: "npm",
|
|
60067
|
-
args: ["pkg", "set", "scripts.dev=nodemon --watch 'src/**/*.ts' --exec 'ts-node' src/index.ts"]
|
|
60068
|
-
},
|
|
60069
|
-
{
|
|
60070
|
-
action: "command",
|
|
60071
|
-
cmd: "npm",
|
|
60072
|
-
args: ["pkg", "set", "scripts.build=tsup"]
|
|
60073
|
-
},
|
|
60074
|
-
{
|
|
60075
|
-
action: "command",
|
|
60076
|
-
cmd: "npm",
|
|
60077
|
-
args: ["pkg", "set", "scripts.start=node dist/index.js"]
|
|
60078
|
-
},
|
|
60079
|
-
{
|
|
60080
|
-
action: "command",
|
|
60081
|
-
cmd: "npm",
|
|
60082
|
-
args: ["pkg", "set", "scripts.stop=npx -y kill-port 3500"]
|
|
60083
|
-
},
|
|
60084
|
-
{
|
|
60085
|
-
action: "command",
|
|
60086
|
-
cmd: "npm",
|
|
60087
|
-
args: ["pkg", "set", "fontawesomeIcon=fa-solid fa-comments"]
|
|
60088
|
-
},
|
|
60089
|
-
{
|
|
60090
|
-
action: "command",
|
|
60091
|
-
cmd: "npm",
|
|
60092
|
-
args: ["pkg", "set", "name=$(basename $PWD)"]
|
|
60093
|
-
}
|
|
60094
|
-
]
|
|
60095
|
-
};
|
|
60096
|
-
|
|
60097
|
-
// ../../packages/template/demo.ts
|
|
60098
|
-
var templates2 = [
|
|
60099
|
-
AIChat
|
|
60100
|
-
];
|
|
60101
|
-
var demo_default = templates2;
|
|
60102
|
-
|
|
60103
|
-
// ../../packages/template/projects/_viteapp.ts
|
|
60104
|
-
var file = `import { useState } from 'react'
|
|
58917
|
+
// ../../packages/template/demo.ts
|
|
58918
|
+
var templates2 = [
|
|
58919
|
+
monochat_default
|
|
58920
|
+
];
|
|
58921
|
+
var demo_default = templates2;
|
|
60105
58922
|
|
|
58923
|
+
// ../../packages/template/projects/files/_viteapp.ts
|
|
58924
|
+
var file = `
|
|
60106
58925
|
function App() {
|
|
60107
58926
|
return (
|
|
60108
58927
|
<div className="min-h-screen bg-slate-950 text-white font-sans selection:bg-indigo-500 selection:text-white">
|
|
@@ -60227,7 +59046,7 @@ var ViteReact = {
|
|
|
60227
59046
|
{
|
|
60228
59047
|
action: "command",
|
|
60229
59048
|
cmd: "npm",
|
|
60230
|
-
args: ["install", "-D", "tailwindcss", "@tailwindcss/postcss", "autoprefixer"]
|
|
59049
|
+
args: ["install", "-D", "tailwindcss", "@tailwindcss/postcss", "postcss", "autoprefixer"]
|
|
60231
59050
|
},
|
|
60232
59051
|
{
|
|
60233
59052
|
action: "file",
|
|
@@ -60235,19 +59054,9 @@ var ViteReact = {
|
|
|
60235
59054
|
filecontent: 'export default {\n plugins: {\n "@tailwindcss/postcss": {},\n autoprefixer: {},\n },\n}'
|
|
60236
59055
|
},
|
|
60237
59056
|
{
|
|
60238
|
-
action: "
|
|
60239
|
-
|
|
60240
|
-
|
|
60241
|
-
export default {
|
|
60242
|
-
content: [
|
|
60243
|
-
"./index.html",
|
|
60244
|
-
"./src/**/*.{js,ts,jsx,tsx}",
|
|
60245
|
-
],
|
|
60246
|
-
theme: {
|
|
60247
|
-
extend: {},
|
|
60248
|
-
},
|
|
60249
|
-
plugins: [],
|
|
60250
|
-
};`
|
|
59057
|
+
action: "command",
|
|
59058
|
+
cmd: "rm",
|
|
59059
|
+
args: ["src/App.css"]
|
|
60251
59060
|
},
|
|
60252
59061
|
{
|
|
60253
59062
|
action: "file",
|
|
@@ -60268,11 +59077,6 @@ ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
|
60268
59077
|
</React.StrictMode>,
|
|
60269
59078
|
)`
|
|
60270
59079
|
},
|
|
60271
|
-
{
|
|
60272
|
-
action: "command",
|
|
60273
|
-
cmd: "rm",
|
|
60274
|
-
args: ["src/App.css"]
|
|
60275
|
-
},
|
|
60276
59080
|
{
|
|
60277
59081
|
action: "file",
|
|
60278
59082
|
file: "src/App.tsx",
|
|
@@ -60325,12 +59129,17 @@ ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
|
60325
59129
|
{
|
|
60326
59130
|
action: "command",
|
|
60327
59131
|
cmd: "npm",
|
|
60328
|
-
args: ["pkg", "set", "
|
|
59132
|
+
args: ["pkg", "set", "description=Vite React TS"]
|
|
59133
|
+
},
|
|
59134
|
+
{
|
|
59135
|
+
action: "command",
|
|
59136
|
+
cmd: "npm",
|
|
59137
|
+
args: ["pkg", "set", "fontawesomeIcon=fab fa-react text-blue-500"]
|
|
60329
59138
|
}
|
|
60330
59139
|
]
|
|
60331
59140
|
};
|
|
60332
59141
|
|
|
60333
|
-
// ../../packages/template/projects/_nextapp.ts
|
|
59142
|
+
// ../../packages/template/projects/files/_nextapp.ts
|
|
60334
59143
|
var app = `export default function Home() {
|
|
60335
59144
|
return (
|
|
60336
59145
|
<div className="min-h-screen bg-slate-950 text-white font-sans selection:bg-indigo-500 selection:text-white">
|
|
@@ -60561,6 +59370,11 @@ export default function RootLayout({
|
|
|
60561
59370
|
file: "Procfile",
|
|
60562
59371
|
filecontent: "web: npm start"
|
|
60563
59372
|
},
|
|
59373
|
+
{
|
|
59374
|
+
action: "command",
|
|
59375
|
+
cmd: "npm",
|
|
59376
|
+
args: ["pkg", "set", "description=Next.js TS"]
|
|
59377
|
+
},
|
|
60564
59378
|
{
|
|
60565
59379
|
action: "command",
|
|
60566
59380
|
cmd: "npm",
|
|
@@ -60569,7 +59383,7 @@ export default function RootLayout({
|
|
|
60569
59383
|
]
|
|
60570
59384
|
};
|
|
60571
59385
|
|
|
60572
|
-
// ../../packages/template/projects/
|
|
59386
|
+
// ../../packages/template/projects/files/_express.ts
|
|
60573
59387
|
var expressFile = `import express, { Request, Response } from "express";
|
|
60574
59388
|
import path from "path";
|
|
60575
59389
|
import cors from "cors";
|
|
@@ -60676,6 +59490,13 @@ var htmlFile = `<!DOCTYPE html>
|
|
|
60676
59490
|
</body>
|
|
60677
59491
|
</html>
|
|
60678
59492
|
`;
|
|
59493
|
+
var express_default = {
|
|
59494
|
+
expressFile,
|
|
59495
|
+
helloRouterFile,
|
|
59496
|
+
htmlFile
|
|
59497
|
+
};
|
|
59498
|
+
|
|
59499
|
+
// ../../packages/template/projects/express.ts
|
|
60679
59500
|
var ExpressTS = {
|
|
60680
59501
|
name: "Express.js TS",
|
|
60681
59502
|
description: "Express.js TS template",
|
|
@@ -60686,6 +59507,11 @@ var ExpressTS = {
|
|
|
60686
59507
|
cmd: "npm",
|
|
60687
59508
|
args: ["init", "-y"]
|
|
60688
59509
|
},
|
|
59510
|
+
{
|
|
59511
|
+
action: "command",
|
|
59512
|
+
cmd: "node",
|
|
59513
|
+
args: ["-e", "const fs=require('fs');const p=JSON.parse(fs.readFileSync('package.json'));if(p.name==='express'){p.name='express-app';fs.writeFileSync('package.json',JSON.stringify(p,null,2))}"]
|
|
59514
|
+
},
|
|
60689
59515
|
{
|
|
60690
59516
|
action: "command",
|
|
60691
59517
|
cmd: "npm",
|
|
@@ -60704,17 +59530,17 @@ var ExpressTS = {
|
|
|
60704
59530
|
{
|
|
60705
59531
|
action: "file",
|
|
60706
59532
|
file: "public/index.html",
|
|
60707
|
-
filecontent: htmlFile
|
|
59533
|
+
filecontent: express_default.htmlFile
|
|
60708
59534
|
},
|
|
60709
59535
|
{
|
|
60710
59536
|
action: "file",
|
|
60711
59537
|
file: "src/routes/hello.ts",
|
|
60712
|
-
filecontent: helloRouterFile
|
|
59538
|
+
filecontent: express_default.helloRouterFile
|
|
60713
59539
|
},
|
|
60714
59540
|
{
|
|
60715
59541
|
action: "file",
|
|
60716
59542
|
file: "src/index.ts",
|
|
60717
|
-
filecontent: expressFile
|
|
59543
|
+
filecontent: express_default.expressFile
|
|
60718
59544
|
},
|
|
60719
59545
|
{
|
|
60720
59546
|
action: "file",
|
|
@@ -60789,6 +59615,11 @@ var ExpressTS = {
|
|
|
60789
59615
|
file: "Procfile",
|
|
60790
59616
|
filecontent: "web: npm start"
|
|
60791
59617
|
},
|
|
59618
|
+
{
|
|
59619
|
+
action: "command",
|
|
59620
|
+
cmd: "npm",
|
|
59621
|
+
args: ["pkg", "set", "description=Express.js TS"]
|
|
59622
|
+
},
|
|
60792
59623
|
{
|
|
60793
59624
|
action: "command",
|
|
60794
59625
|
cmd: "npm",
|
|
@@ -60797,7 +59628,7 @@ var ExpressTS = {
|
|
|
60797
59628
|
]
|
|
60798
59629
|
};
|
|
60799
59630
|
|
|
60800
|
-
// ../../packages/template/projects/
|
|
59631
|
+
// ../../packages/template/projects/files/_serverless.ts
|
|
60801
59632
|
var htmlFile2 = `<!DOCTYPE html>
|
|
60802
59633
|
<html lang="en">
|
|
60803
59634
|
<head>
|
|
@@ -60974,17 +59805,29 @@ functions:
|
|
|
60974
59805
|
events:
|
|
60975
59806
|
- httpApi: '*'
|
|
60976
59807
|
`;
|
|
59808
|
+
var serverless_default = {
|
|
59809
|
+
htmlFile: htmlFile2,
|
|
59810
|
+
appFile,
|
|
59811
|
+
localFile,
|
|
59812
|
+
vercelApiFile,
|
|
59813
|
+
netlifyFunctionFile,
|
|
59814
|
+
helloRouterFile: helloRouterFile2,
|
|
59815
|
+
lambdaFile,
|
|
59816
|
+
dockerFile,
|
|
59817
|
+
serverlessYmlFile
|
|
59818
|
+
};
|
|
59819
|
+
|
|
59820
|
+
// ../../packages/template/projects/serverless-express.ts
|
|
60977
59821
|
var ServerlessExpressTS = {
|
|
60978
|
-
name: "
|
|
60979
|
-
description: "Express
|
|
60980
|
-
notes: "
|
|
59822
|
+
name: "Serverless Express TS",
|
|
59823
|
+
description: "Serverless Express TS template optimized for Serverless (Netlify, Vercel, AWS) & Containers (Docker, Render, Fly.io)",
|
|
59824
|
+
notes: "Node.js and NPM must be installed.",
|
|
60981
59825
|
templating: [
|
|
60982
59826
|
{
|
|
60983
59827
|
action: "command",
|
|
60984
59828
|
cmd: "npm",
|
|
60985
59829
|
args: ["init", "-y"]
|
|
60986
59830
|
},
|
|
60987
|
-
// Dependencies
|
|
60988
59831
|
{
|
|
60989
59832
|
action: "command",
|
|
60990
59833
|
cmd: "npm",
|
|
@@ -60999,44 +59842,44 @@ var ServerlessExpressTS = {
|
|
|
60999
59842
|
{
|
|
61000
59843
|
action: "file",
|
|
61001
59844
|
file: "public/index.html",
|
|
61002
|
-
filecontent:
|
|
59845
|
+
filecontent: serverless_default.htmlFile
|
|
61003
59846
|
},
|
|
61004
59847
|
{
|
|
61005
59848
|
action: "file",
|
|
61006
59849
|
file: "src/app.ts",
|
|
61007
|
-
filecontent: appFile
|
|
59850
|
+
filecontent: serverless_default.appFile
|
|
61008
59851
|
},
|
|
61009
59852
|
{
|
|
61010
59853
|
action: "file",
|
|
61011
59854
|
file: "src/local.ts",
|
|
61012
|
-
filecontent: localFile
|
|
59855
|
+
filecontent: serverless_default.localFile
|
|
61013
59856
|
},
|
|
61014
59857
|
{
|
|
61015
59858
|
action: "file",
|
|
61016
59859
|
file: "src/routes/hello.ts",
|
|
61017
|
-
filecontent:
|
|
59860
|
+
filecontent: serverless_default.helloRouterFile
|
|
61018
59861
|
},
|
|
61019
59862
|
// Serverless Entry Points
|
|
61020
59863
|
{
|
|
61021
59864
|
action: "file",
|
|
61022
59865
|
file: "api/index.ts",
|
|
61023
|
-
filecontent: vercelApiFile
|
|
59866
|
+
filecontent: serverless_default.vercelApiFile
|
|
61024
59867
|
},
|
|
61025
59868
|
{
|
|
61026
59869
|
action: "file",
|
|
61027
59870
|
file: "netlify/functions/api.ts",
|
|
61028
|
-
filecontent: netlifyFunctionFile
|
|
59871
|
+
filecontent: serverless_default.netlifyFunctionFile
|
|
61029
59872
|
},
|
|
61030
59873
|
{
|
|
61031
59874
|
action: "file",
|
|
61032
59875
|
file: "src/lambda.ts",
|
|
61033
|
-
filecontent: lambdaFile
|
|
59876
|
+
filecontent: serverless_default.lambdaFile
|
|
61034
59877
|
},
|
|
61035
59878
|
// Container Configs
|
|
61036
59879
|
{
|
|
61037
59880
|
action: "file",
|
|
61038
59881
|
file: "Dockerfile",
|
|
61039
|
-
filecontent: dockerFile
|
|
59882
|
+
filecontent: serverless_default.dockerFile
|
|
61040
59883
|
},
|
|
61041
59884
|
{
|
|
61042
59885
|
action: "file",
|
|
@@ -61046,7 +59889,7 @@ var ServerlessExpressTS = {
|
|
|
61046
59889
|
{
|
|
61047
59890
|
action: "file",
|
|
61048
59891
|
file: "serverless.yml",
|
|
61049
|
-
filecontent: serverlessYmlFile
|
|
59892
|
+
filecontent: serverless_default.serverlessYmlFile
|
|
61050
59893
|
},
|
|
61051
59894
|
// Config Files
|
|
61052
59895
|
{
|
|
@@ -61124,6 +59967,11 @@ var ServerlessExpressTS = {
|
|
|
61124
59967
|
cmd: "npm",
|
|
61125
59968
|
args: ["pkg", "set", "scripts.stop=npx -y kill-port 3500"]
|
|
61126
59969
|
},
|
|
59970
|
+
{
|
|
59971
|
+
action: "command",
|
|
59972
|
+
cmd: "npm",
|
|
59973
|
+
args: ["pkg", "set", "description=Serverless Express TS"]
|
|
59974
|
+
},
|
|
61127
59975
|
{
|
|
61128
59976
|
action: "command",
|
|
61129
59977
|
cmd: "npm",
|
|
@@ -61132,6 +59980,82 @@ var ServerlessExpressTS = {
|
|
|
61132
59980
|
]
|
|
61133
59981
|
};
|
|
61134
59982
|
|
|
59983
|
+
// ../../packages/template/projects/files/_php.ts
|
|
59984
|
+
var phpContent = `<?php
|
|
59985
|
+
$file = 'visits.txt';
|
|
59986
|
+
if (!file_exists($file)) {
|
|
59987
|
+
file_put_contents($file, 0);
|
|
59988
|
+
}
|
|
59989
|
+
$count = (int)file_get_contents($file);
|
|
59990
|
+
$count++;
|
|
59991
|
+
file_put_contents($file, $count);
|
|
59992
|
+
?>
|
|
59993
|
+
<!DOCTYPE html>
|
|
59994
|
+
<html lang="en">
|
|
59995
|
+
<head>
|
|
59996
|
+
<meta charset="UTF-8">
|
|
59997
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
59998
|
+
<title>Welcome to Monorepo Time</title>
|
|
59999
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
60000
|
+
<style>
|
|
60001
|
+
@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600&display=swap');
|
|
60002
|
+
body { font-family: 'Outfit', sans-serif; }
|
|
60003
|
+
</style>
|
|
60004
|
+
</head>
|
|
60005
|
+
<body class="bg-gray-900 text-white min-h-screen flex items-center justify-center relative overflow-hidden">
|
|
60006
|
+
<!-- Background Elements -->
|
|
60007
|
+
<div class="absolute top-0 left-0 w-full h-full overflow-hidden z-0">
|
|
60008
|
+
<div class="absolute top-[-10%] right-[-10%] w-96 h-96 bg-purple-600 rounded-full mix-blend-multiply filter blur-3xl opacity-20 animate-blob"></div>
|
|
60009
|
+
<div class="absolute bottom-[-10%] left-[-10%] w-96 h-96 bg-blue-600 rounded-full mix-blend-multiply filter blur-3xl opacity-20 animate-blob animation-delay-2000"></div>
|
|
60010
|
+
</div>
|
|
60011
|
+
|
|
60012
|
+
<div class="z-10 text-center p-8 bg-white/10 backdrop-blur-lg rounded-2xl border border-white/20 shadow-2xl max-w-lg w-full transform hover:scale-105 transition-transform duration-300">
|
|
60013
|
+
<div class="mb-6">
|
|
60014
|
+
<span class="text-4xl">\u{1F680}</span>
|
|
60015
|
+
</div>
|
|
60016
|
+
<h1 class="text-4xl font-bold mb-2 bg-clip-text text-transparent bg-gradient-to-r from-blue-400 to-purple-400">
|
|
60017
|
+
Monorepo Time
|
|
60018
|
+
</h1>
|
|
60019
|
+
<p class="text-gray-300 text-lg mb-6">
|
|
60020
|
+
Your PHP application is up and running.
|
|
60021
|
+
</p>
|
|
60022
|
+
|
|
60023
|
+
<div class="bg-black/30 rounded-xl p-4 mb-6">
|
|
60024
|
+
<p class="text-sm text-gray-400 uppercase tracking-widest mb-1">Total Visits</p>
|
|
60025
|
+
<p class="text-3xl font-mono font-bold text-green-400">
|
|
60026
|
+
<?php echo number_format($count); ?>
|
|
60027
|
+
</p>
|
|
60028
|
+
</div>
|
|
60029
|
+
|
|
60030
|
+
<div class="flex justify-center gap-4">
|
|
60031
|
+
<a href="#" class="px-6 py-2 bg-blue-600 hover:bg-blue-700 rounded-full font-medium transition-colors duration-200">
|
|
60032
|
+
Documentation
|
|
60033
|
+
</a>
|
|
60034
|
+
<a href="#" class="px-6 py-2 bg-transparent border border-white/30 hover:bg-white/10 rounded-full font-medium transition-colors duration-200">
|
|
60035
|
+
Learn More
|
|
60036
|
+
</a>
|
|
60037
|
+
</div>
|
|
60038
|
+
</div>
|
|
60039
|
+
|
|
60040
|
+
<!-- Animation Keyframes -->
|
|
60041
|
+
<style>
|
|
60042
|
+
@keyframes blob {
|
|
60043
|
+
0% { transform: translate(0px, 0px) scale(1); }
|
|
60044
|
+
33% { transform: translate(30px, -50px) scale(1.1); }
|
|
60045
|
+
66% { transform: translate(-20px, 20px) scale(0.9); }
|
|
60046
|
+
100% { transform: translate(0px, 0px) scale(1); }
|
|
60047
|
+
}
|
|
60048
|
+
.animate-blob {
|
|
60049
|
+
animation: blob 7s infinite;
|
|
60050
|
+
}
|
|
60051
|
+
.animation-delay-2000 {
|
|
60052
|
+
animation-delay: 2s;
|
|
60053
|
+
}
|
|
60054
|
+
</style>
|
|
60055
|
+
</body>
|
|
60056
|
+
</html>
|
|
60057
|
+
`;
|
|
60058
|
+
|
|
61135
60059
|
// ../../packages/template/projects/php.ts
|
|
61136
60060
|
var PHP = {
|
|
61137
60061
|
name: "PHP",
|
|
@@ -61141,27 +60065,27 @@ var PHP = {
|
|
|
61141
60065
|
{
|
|
61142
60066
|
action: "file",
|
|
61143
60067
|
file: "index.php",
|
|
61144
|
-
filecontent:
|
|
60068
|
+
filecontent: phpContent
|
|
61145
60069
|
},
|
|
61146
60070
|
{
|
|
61147
60071
|
action: "command",
|
|
61148
60072
|
cmd: "npm",
|
|
61149
|
-
args: ["pkg", "set", "scripts.
|
|
60073
|
+
args: ["pkg", "set", "scripts.start=php -S localhost:3000"]
|
|
61150
60074
|
},
|
|
61151
60075
|
{
|
|
61152
60076
|
action: "command",
|
|
61153
60077
|
cmd: "npm",
|
|
61154
|
-
args: ["pkg", "set", "scripts.
|
|
60078
|
+
args: ["pkg", "set", "scripts.stop=npx kill-port 3000"]
|
|
61155
60079
|
},
|
|
61156
60080
|
{
|
|
61157
60081
|
action: "command",
|
|
61158
60082
|
cmd: "npm",
|
|
61159
|
-
args: ["pkg", "set", "
|
|
60083
|
+
args: ["pkg", "set", "description=PHP"]
|
|
61160
60084
|
},
|
|
61161
60085
|
{
|
|
61162
60086
|
action: "command",
|
|
61163
60087
|
cmd: "npm",
|
|
61164
|
-
args: ["pkg", "set", "fontawesomeIcon=fab fa-php text-indigo-
|
|
60088
|
+
args: ["pkg", "set", "fontawesomeIcon=fab fa-php text-indigo-500"]
|
|
61165
60089
|
}
|
|
61166
60090
|
]
|
|
61167
60091
|
};
|
|
@@ -61202,6 +60126,11 @@ var Laravel = {
|
|
|
61202
60126
|
cmd: "npm",
|
|
61203
60127
|
args: ["pkg", "set", "scripts.stop=npx -y kill-port 8000"]
|
|
61204
60128
|
},
|
|
60129
|
+
{
|
|
60130
|
+
action: "command",
|
|
60131
|
+
cmd: "npm",
|
|
60132
|
+
args: ["pkg", "set", "description=Laravel"]
|
|
60133
|
+
},
|
|
61205
60134
|
{
|
|
61206
60135
|
action: "command",
|
|
61207
60136
|
cmd: "npm",
|
|
@@ -61210,31 +60139,171 @@ var Laravel = {
|
|
|
61210
60139
|
]
|
|
61211
60140
|
};
|
|
61212
60141
|
|
|
61213
|
-
// ../../packages/template/projects/
|
|
61214
|
-
var
|
|
61215
|
-
|
|
61216
|
-
|
|
60142
|
+
// ../../packages/template/projects/files/_python.ts
|
|
60143
|
+
var mainPy = `import http.server
|
|
60144
|
+
import socketserver
|
|
60145
|
+
import os
|
|
60146
|
+
import sys
|
|
60147
|
+
|
|
60148
|
+
# Define port, default to 3000 or use environment variable
|
|
60149
|
+
PORT = int(os.environ.get('PORT', 3000))
|
|
60150
|
+
|
|
60151
|
+
class MyHandler(http.server.SimpleHTTPRequestHandler):
|
|
60152
|
+
def do_GET(self):
|
|
60153
|
+
# Route: / -> Load index.html
|
|
60154
|
+
if self.path == '/':
|
|
60155
|
+
self.path = 'index.html'
|
|
60156
|
+
return http.server.SimpleHTTPRequestHandler.do_GET(self)
|
|
60157
|
+
|
|
60158
|
+
# Route: /test -> Return "Hello World"
|
|
60159
|
+
elif self.path == '/test':
|
|
60160
|
+
self.send_response(200)
|
|
60161
|
+
self.send_header('Content-type', 'text/plain')
|
|
60162
|
+
self.end_headers()
|
|
60163
|
+
self.wfile.write(b"Hello World")
|
|
60164
|
+
return
|
|
60165
|
+
|
|
60166
|
+
# Default: Serve static files
|
|
60167
|
+
return http.server.SimpleHTTPRequestHandler.do_GET(self)
|
|
60168
|
+
|
|
60169
|
+
# Ensure index.html exists (though template should create it)
|
|
60170
|
+
if not os.path.exists('index.html'):
|
|
60171
|
+
with open('index.html', 'w') as f:
|
|
60172
|
+
f.write("<h1>Error: index.html not found</h1>")
|
|
60173
|
+
|
|
60174
|
+
print(f"Python server is running at http://localhost:{PORT}")
|
|
60175
|
+
print("Press Ctrl+C to stop.")
|
|
60176
|
+
|
|
60177
|
+
try:
|
|
60178
|
+
# Allow address reuse to prevent "Address already in use" errors on restart
|
|
60179
|
+
socketserver.TCPServer.allow_reuse_address = True
|
|
60180
|
+
with socketserver.TCPServer(("", PORT), MyHandler) as httpd:
|
|
60181
|
+
httpd.serve_forever()
|
|
60182
|
+
except KeyboardInterrupt:
|
|
60183
|
+
print("^C received, shutting down server")
|
|
60184
|
+
sys.exit(0)
|
|
60185
|
+
`;
|
|
60186
|
+
var indexHtml = `<!DOCTYPE html>
|
|
60187
|
+
<html lang="en">
|
|
60188
|
+
<head>
|
|
60189
|
+
<meta charset="UTF-8">
|
|
60190
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
60191
|
+
<title>Monorepo Time - Python Backend</title>
|
|
60192
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
60193
|
+
<style>
|
|
60194
|
+
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&display=swap');
|
|
60195
|
+
body { font-family: 'JetBrains Mono', monospace; }
|
|
60196
|
+
.glass {
|
|
60197
|
+
background: rgba(255, 255, 255, 0.05);
|
|
60198
|
+
backdrop-filter: blur(10px);
|
|
60199
|
+
-webkit-backdrop-filter: blur(10px);
|
|
60200
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
60201
|
+
}
|
|
60202
|
+
</style>
|
|
60203
|
+
</head>
|
|
60204
|
+
<body class="bg-[#0f172a] text-gray-200 min-h-screen flex items-center justify-center relative overflow-hidden">
|
|
60205
|
+
<!-- Background Decor -->
|
|
60206
|
+
<div class="absolute top-0 left-0 w-full h-full overflow-hidden z-0 pointer-events-none">
|
|
60207
|
+
<div class="absolute top-1/4 left-1/4 w-96 h-96 bg-blue-500/20 rounded-full blur-[100px]"></div>
|
|
60208
|
+
<div class="absolute bottom-1/4 right-1/4 w-96 h-96 bg-yellow-500/10 rounded-full blur-[100px]"></div>
|
|
60209
|
+
</div>
|
|
60210
|
+
|
|
60211
|
+
<!-- Main Content -->
|
|
60212
|
+
<div class="z-10 w-full max-w-2xl px-4">
|
|
60213
|
+
<div class="glass rounded-2xl p-8 md:p-12 shadow-2xl border border-white/5 transform transition-all hover:scale-[1.01]">
|
|
60214
|
+
<div class="flex items-center justify-between mb-8">
|
|
60215
|
+
<div class="flex items-center space-x-3">
|
|
60216
|
+
<span class="text-4xl">\u{1F40D}</span>
|
|
60217
|
+
<h1 class="text-3xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-blue-400 to-yellow-300">
|
|
60218
|
+
Python Backend
|
|
60219
|
+
</h1>
|
|
60220
|
+
</div>
|
|
60221
|
+
<div class="flex items-center space-x-2">
|
|
60222
|
+
<div class="w-3 h-3 bg-green-500 rounded-full animate-pulse"></div>
|
|
60223
|
+
<span class="text-xs font-mono text-green-400 uppercase tracking-widest">Online</span>
|
|
60224
|
+
</div>
|
|
60225
|
+
</div>
|
|
60226
|
+
|
|
60227
|
+
<div class="space-y-6">
|
|
60228
|
+
<p class="text-xl text-gray-300 leading-relaxed font-light">
|
|
60229
|
+
Python server is running.
|
|
60230
|
+
</p>
|
|
60231
|
+
|
|
60232
|
+
<div class="p-4 rounded-lg bg-black/30 border border-white/10 font-mono text-sm text-gray-400">
|
|
60233
|
+
<p>$ python main.py</p>
|
|
60234
|
+
<p class="text-green-400">>> Server started at http://localhost:3000</p>
|
|
60235
|
+
</div>
|
|
60236
|
+
|
|
60237
|
+
<div class="pt-4 flex flex-col sm:flex-row gap-4">
|
|
60238
|
+
<a href="/test" class="group relative px-8 py-3 bg-blue-600 hover:bg-blue-500 rounded-lg font-bold text-white transition-all shadow-[0_0_20px_rgba(37,99,235,0.3)] hover:shadow-[0_0_30px_rgba(37,99,235,0.5)] overflow-hidden">
|
|
60239
|
+
<span class="relative z-10 flex items-center justify-center gap-2">
|
|
60240
|
+
Test Endpoint
|
|
60241
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 transition-transform group-hover:translate-x-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
60242
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7l5 5m0 0l-5 5m5-5H6" />
|
|
60243
|
+
</svg>
|
|
60244
|
+
</span>
|
|
60245
|
+
</a>
|
|
60246
|
+
|
|
60247
|
+
<a href="https://docs.python.org/3/library/http.server.html" target="_blank" class="px-8 py-3 bg-transparent border border-white/20 hover:bg-white/5 rounded-lg font-bold text-gray-300 transition-colors text-center">
|
|
60248
|
+
Docs
|
|
60249
|
+
</a>
|
|
60250
|
+
</div>
|
|
60251
|
+
</div>
|
|
60252
|
+
</div>
|
|
60253
|
+
|
|
60254
|
+
<div class="mt-8 text-center text-sm text-gray-500">
|
|
60255
|
+
<p>Powered by Python Standard Library & Tailwind CSS</p>
|
|
60256
|
+
</div>
|
|
60257
|
+
</div>
|
|
60258
|
+
</body>
|
|
60259
|
+
</html>
|
|
61217
60260
|
`;
|
|
60261
|
+
var python_default = {
|
|
60262
|
+
mainPy,
|
|
60263
|
+
indexHtml
|
|
60264
|
+
};
|
|
60265
|
+
|
|
60266
|
+
// ../../packages/template/projects/python.ts
|
|
61218
60267
|
var PythonConsole = {
|
|
61219
|
-
name: "Python
|
|
61220
|
-
description: "Simple Python
|
|
60268
|
+
name: "Python Backend",
|
|
60269
|
+
description: "Simple Python Backend Application",
|
|
61221
60270
|
notes: "Python 3 must be installed in your system.",
|
|
61222
60271
|
templating: [
|
|
61223
60272
|
{
|
|
61224
60273
|
action: "file",
|
|
61225
60274
|
file: "main.py",
|
|
61226
|
-
filecontent:
|
|
60275
|
+
filecontent: python_default.mainPy
|
|
60276
|
+
},
|
|
60277
|
+
{
|
|
60278
|
+
action: "file",
|
|
60279
|
+
file: "index.html",
|
|
60280
|
+
filecontent: python_default.indexHtml
|
|
60281
|
+
},
|
|
60282
|
+
{
|
|
60283
|
+
action: "command",
|
|
60284
|
+
cmd: "npm",
|
|
60285
|
+
args: ["install", "-D", "nodemon"]
|
|
61227
60286
|
},
|
|
61228
60287
|
{
|
|
61229
60288
|
action: "command",
|
|
61230
60289
|
cmd: "npm",
|
|
61231
|
-
args: ["pkg", "set", "scripts.dev=python3 main.py"]
|
|
60290
|
+
args: ["pkg", "set", "scripts.dev=nodemon --watch . --ext py --exec python3 main.py"]
|
|
61232
60291
|
},
|
|
61233
60292
|
{
|
|
61234
60293
|
action: "command",
|
|
61235
60294
|
cmd: "npm",
|
|
61236
60295
|
args: ["pkg", "set", "scripts.start=python3 main.py"]
|
|
61237
60296
|
},
|
|
60297
|
+
{
|
|
60298
|
+
action: "command",
|
|
60299
|
+
cmd: "npm",
|
|
60300
|
+
args: ["pkg", "set", "description=Python Backend"]
|
|
60301
|
+
},
|
|
60302
|
+
{
|
|
60303
|
+
action: "command",
|
|
60304
|
+
cmd: "npm",
|
|
60305
|
+
args: ["pkg", "set", "scripts.stop=npx kill-port 3000"]
|
|
60306
|
+
},
|
|
61238
60307
|
{
|
|
61239
60308
|
action: "command",
|
|
61240
60309
|
cmd: "npm",
|
|
@@ -61278,7 +60347,12 @@ var DotNetConsole = {
|
|
|
61278
60347
|
{
|
|
61279
60348
|
action: "command",
|
|
61280
60349
|
cmd: "npm",
|
|
61281
|
-
args: ["pkg", "set", "
|
|
60350
|
+
args: ["pkg", "set", "description=.NET Console"]
|
|
60351
|
+
},
|
|
60352
|
+
{
|
|
60353
|
+
action: "command",
|
|
60354
|
+
cmd: "npm",
|
|
60355
|
+
args: ["pkg", "set", "fontawesomeIcon=fab fa-windows text-blue-500"]
|
|
61282
60356
|
}
|
|
61283
60357
|
]
|
|
61284
60358
|
};
|
|
@@ -61327,6 +60401,11 @@ var N8NLocal = {
|
|
|
61327
60401
|
cmd: "npm",
|
|
61328
60402
|
args: ["pkg", "set", "fontawesomeIcon=fas fa-project-diagram text-red-500"]
|
|
61329
60403
|
},
|
|
60404
|
+
{
|
|
60405
|
+
action: "command",
|
|
60406
|
+
cmd: "npm",
|
|
60407
|
+
args: ["pkg", "set", "description=N8N (Local)"]
|
|
60408
|
+
},
|
|
61330
60409
|
{
|
|
61331
60410
|
action: "command",
|
|
61332
60411
|
cmd: "npm",
|
|
@@ -61568,7 +60647,7 @@ networks:
|
|
|
61568
60647
|
driver: bridge`;
|
|
61569
60648
|
|
|
61570
60649
|
// ../../packages/template/services_list/aws/indexHtml.ts
|
|
61571
|
-
var
|
|
60650
|
+
var indexHtml2 = `<!DOCTYPE html>
|
|
61572
60651
|
<html lang="en" class="dark">
|
|
61573
60652
|
<head>
|
|
61574
60653
|
<meta charset="UTF-8">
|
|
@@ -61904,7 +60983,7 @@ spawn('docker', ['compose', 'down'], { stdio: 'inherit' });`;
|
|
|
61904
60983
|
|
|
61905
60984
|
// ../../packages/template/services_list/aws.ts
|
|
61906
60985
|
var AWSTemplate = {
|
|
61907
|
-
name: "
|
|
60986
|
+
name: "Localstack (Experimental)",
|
|
61908
60987
|
description: "AWS LocalStack Environment with Manager",
|
|
61909
60988
|
notes: "Requires Docker, Node.js, and AWS CLI installed.",
|
|
61910
60989
|
templating: [
|
|
@@ -61931,7 +61010,7 @@ var AWSTemplate = {
|
|
|
61931
61010
|
{
|
|
61932
61011
|
action: "file",
|
|
61933
61012
|
file: "index.html",
|
|
61934
|
-
filecontent:
|
|
61013
|
+
filecontent: indexHtml2
|
|
61935
61014
|
},
|
|
61936
61015
|
{
|
|
61937
61016
|
action: "command",
|
|
@@ -61961,7 +61040,12 @@ var AWSTemplate = {
|
|
|
61961
61040
|
{
|
|
61962
61041
|
action: "command",
|
|
61963
61042
|
cmd: "npm",
|
|
61964
|
-
args: ["pkg", "set", "fontawesomeIcon=fab fa-aws text-orange-
|
|
61043
|
+
args: ["pkg", "set", "fontawesomeIcon=fab fa-aws text-orange-500"]
|
|
61044
|
+
},
|
|
61045
|
+
{
|
|
61046
|
+
action: "command",
|
|
61047
|
+
cmd: "npm",
|
|
61048
|
+
args: ["pkg", "set", "description=AWS LocalStack Environment with Manager"]
|
|
61965
61049
|
},
|
|
61966
61050
|
{
|
|
61967
61051
|
action: "command",
|
|
@@ -62142,7 +61226,7 @@ const stripe = new Stripe('sk_test_mock_123', {
|
|
|
62142
61226
|
})();
|
|
62143
61227
|
`;
|
|
62144
61228
|
var StripeTemplate = {
|
|
62145
|
-
name: "Stripe Mock",
|
|
61229
|
+
name: "Stripe Mock (Experimental)",
|
|
62146
61230
|
description: "Stripe API Mock Server",
|
|
62147
61231
|
notes: "Runs the official stripe-mock image. Requires Docker.",
|
|
62148
61232
|
templating: [
|
|
@@ -62191,6 +61275,11 @@ var StripeTemplate = {
|
|
|
62191
61275
|
cmd: "npm",
|
|
62192
61276
|
args: ["pkg", "set", "fontawesomeIcon=fas fa-credit-card text-green-500"]
|
|
62193
61277
|
},
|
|
61278
|
+
{
|
|
61279
|
+
action: "command",
|
|
61280
|
+
cmd: "npm",
|
|
61281
|
+
args: ["pkg", "set", "description=Stripe Mock"]
|
|
61282
|
+
},
|
|
62194
61283
|
{
|
|
62195
61284
|
action: "command",
|
|
62196
61285
|
cmd: "npm",
|
|
@@ -62217,7 +61306,7 @@ var MonorepoTemplates = {
|
|
|
62217
61306
|
var template_default = MonorepoTemplates;
|
|
62218
61307
|
|
|
62219
61308
|
// src/routes/availabletemplates.ts
|
|
62220
|
-
var router18 =
|
|
61309
|
+
var router18 = import_express22.default.Router();
|
|
62221
61310
|
router18.get("/", (req, res) => {
|
|
62222
61311
|
try {
|
|
62223
61312
|
const stripTemplating = (templates5) => {
|
|
@@ -62238,7 +61327,7 @@ router18.get("/", (req, res) => {
|
|
|
62238
61327
|
var availabletemplates_default = router18;
|
|
62239
61328
|
|
|
62240
61329
|
// src/routes/setworkspace/index.ts
|
|
62241
|
-
var
|
|
61330
|
+
var import_express23 = __toESM(require_express2());
|
|
62242
61331
|
|
|
62243
61332
|
// src/routes/setworkspace/template.ts
|
|
62244
61333
|
var import_path17 = __toESM(require("path"));
|
|
@@ -62261,6 +61350,33 @@ async function writeFile(filePath, content) {
|
|
|
62261
61350
|
await import_fs3.promises.writeFile(filePath, content, { encoding: "utf8" });
|
|
62262
61351
|
}
|
|
62263
61352
|
var isWindows = process.platform === "win32";
|
|
61353
|
+
async function findMonorepoRoot4(startDir) {
|
|
61354
|
+
let currentDir = startDir;
|
|
61355
|
+
while (true) {
|
|
61356
|
+
const markers = ["pnpm-workspace.yaml", "turbo.json", "lerna.json", ".git"];
|
|
61357
|
+
for (const marker of markers) {
|
|
61358
|
+
try {
|
|
61359
|
+
await import_fs3.promises.stat(import_path15.default.join(currentDir, marker));
|
|
61360
|
+
return currentDir;
|
|
61361
|
+
} catch {
|
|
61362
|
+
}
|
|
61363
|
+
}
|
|
61364
|
+
try {
|
|
61365
|
+
const pkgPath = import_path15.default.join(currentDir, "package.json");
|
|
61366
|
+
const content = await import_fs3.promises.readFile(pkgPath, "utf8");
|
|
61367
|
+
const pkg = JSON.parse(content);
|
|
61368
|
+
if (pkg.workspaces) {
|
|
61369
|
+
return currentDir;
|
|
61370
|
+
}
|
|
61371
|
+
} catch {
|
|
61372
|
+
}
|
|
61373
|
+
const parentDir = import_path15.default.dirname(currentDir);
|
|
61374
|
+
if (parentDir === currentDir) {
|
|
61375
|
+
return startDir;
|
|
61376
|
+
}
|
|
61377
|
+
currentDir = parentDir;
|
|
61378
|
+
}
|
|
61379
|
+
}
|
|
62264
61380
|
|
|
62265
61381
|
// src/routes/setworkspace/command.ts
|
|
62266
61382
|
var import_path16 = __toESM(require("path"));
|
|
@@ -62358,11 +61474,17 @@ async function executeTemplate(template, workspacePath, onProgress) {
|
|
|
62358
61474
|
await ensureDirectory(workspacePath);
|
|
62359
61475
|
const progress = onProgress || ((msg) => console.log(`[Template] ${msg}`));
|
|
62360
61476
|
for (const step of template.templating) {
|
|
62361
|
-
if (step.action === "command" && step.cmd) {
|
|
61477
|
+
if ((step.action === "command" || step.action === "root-command") && step.cmd) {
|
|
62362
61478
|
const cmd = step.cmd;
|
|
62363
61479
|
let args2 = step.args || [];
|
|
61480
|
+
let cwd = workspacePath;
|
|
61481
|
+
if (step.action === "root-command") {
|
|
61482
|
+
cwd = await findMonorepoRoot4(workspacePath);
|
|
61483
|
+
}
|
|
61484
|
+
let relativePath = import_path17.default.relative(cwd, workspacePath);
|
|
61485
|
+
if (relativePath === "") relativePath = ".";
|
|
62364
61486
|
const rawFullCmd = args2.length > 0 ? `${cmd} ${args2.join(" ")}` : cmd;
|
|
62365
|
-
const processedCmd = preprocessCommand(rawFullCmd,
|
|
61487
|
+
const processedCmd = preprocessCommand(rawFullCmd, cwd);
|
|
62366
61488
|
let finalCmd = cmd;
|
|
62367
61489
|
let finalArgs = args2;
|
|
62368
61490
|
let useShell = false;
|
|
@@ -62370,13 +61492,16 @@ async function executeTemplate(template, workspacePath, onProgress) {
|
|
|
62370
61492
|
finalCmd = processedCmd;
|
|
62371
61493
|
finalArgs = [];
|
|
62372
61494
|
useShell = true;
|
|
61495
|
+
finalCmd = finalCmd.replace(/\{\{RELATIVE_PATH\}\}/g, relativePath);
|
|
62373
61496
|
} else {
|
|
62374
|
-
const dirName = import_path17.default.basename(
|
|
62375
|
-
finalArgs = finalArgs.map(
|
|
61497
|
+
const dirName = import_path17.default.basename(cwd);
|
|
61498
|
+
finalArgs = finalArgs.map(
|
|
61499
|
+
(arg) => arg.replace(/\$\(basename \$PWD\)/g, dirName).replace(/\{\{RELATIVE_PATH\}\}/g, relativePath)
|
|
61500
|
+
);
|
|
62376
61501
|
}
|
|
62377
|
-
progress(`Running: ${finalCmd} ${finalArgs.join(" ")}`);
|
|
61502
|
+
progress(`Running in ${step.action === "root-command" ? "Root" : "Workspace"}: ${finalCmd} ${finalArgs.join(" ")}`);
|
|
62378
61503
|
try {
|
|
62379
|
-
const result = await runCommand2(finalCmd, finalArgs,
|
|
61504
|
+
const result = await runCommand2(finalCmd, finalArgs, cwd, useShell, (data) => {
|
|
62380
61505
|
const trimmed = data.trim();
|
|
62381
61506
|
if (trimmed) progress(trimmed);
|
|
62382
61507
|
});
|
|
@@ -62396,7 +61521,7 @@ ${cmdErr.message}`);
|
|
|
62396
61521
|
}
|
|
62397
61522
|
|
|
62398
61523
|
// src/routes/setworkspace/index.ts
|
|
62399
|
-
var router19 =
|
|
61524
|
+
var router19 = import_express23.default.Router();
|
|
62400
61525
|
router19.post("/", async (req, res) => {
|
|
62401
61526
|
try {
|
|
62402
61527
|
const { workspace, templatename } = req.body;
|
|
@@ -62451,12 +61576,12 @@ function setWorkspaceTemplateSocket(io3) {
|
|
|
62451
61576
|
}
|
|
62452
61577
|
|
|
62453
61578
|
// src/routes/stopTerminalWorkspace.ts
|
|
62454
|
-
var
|
|
61579
|
+
var import_express24 = __toESM(require_express2());
|
|
62455
61580
|
var import_fs_extra13 = __toESM(require_lib4());
|
|
62456
61581
|
var import_path18 = __toESM(require("path"));
|
|
62457
61582
|
init_execa();
|
|
62458
61583
|
var import_tree_kill = __toESM(require_tree_kill());
|
|
62459
|
-
var router20 = (0,
|
|
61584
|
+
var router20 = (0, import_express24.Router)();
|
|
62460
61585
|
async function killProcessTree(pid, signal = "SIGKILL") {
|
|
62461
61586
|
return new Promise((resolve, reject) => {
|
|
62462
61587
|
(0, import_tree_kill.default)(pid, signal, (err) => {
|
|
@@ -62631,14 +61756,14 @@ if (command === "init") {
|
|
|
62631
61756
|
process.exit(1);
|
|
62632
61757
|
});
|
|
62633
61758
|
}
|
|
62634
|
-
var app2 = (0,
|
|
61759
|
+
var app2 = (0, import_express25.default)();
|
|
62635
61760
|
var port2 = config_default.apiPort;
|
|
62636
61761
|
app2.use((0, import_cors.default)({
|
|
62637
61762
|
origin: true,
|
|
62638
61763
|
credentials: true
|
|
62639
61764
|
}));
|
|
62640
|
-
app2.use(
|
|
62641
|
-
app2.use(
|
|
61765
|
+
app2.use(import_express25.default.static("public"));
|
|
61766
|
+
app2.use(import_express25.default.json());
|
|
62642
61767
|
app2.use("/", tester_default);
|
|
62643
61768
|
app2.use("/" + api_default.scanWorkspace, scanworkspace_default);
|
|
62644
61769
|
app2.use("/" + api_default.stopProcess, stopcmd_default);
|
|
@@ -62662,7 +61787,7 @@ app2.use("/" + api_default.docker, apidocker_default);
|
|
|
62662
61787
|
app2.use("/" + api_default.availabletemplates, availabletemplates_default);
|
|
62663
61788
|
app2.use("/" + api_default.setWorkspaceTemplate, setworkspace_default);
|
|
62664
61789
|
var frontendPath = import_path19.default.join(__dirname, "../public");
|
|
62665
|
-
app2.use(
|
|
61790
|
+
app2.use(import_express25.default.static(frontendPath));
|
|
62666
61791
|
app2.get("*", (req, res) => {
|
|
62667
61792
|
res.sendFile(import_path19.default.join(frontendPath, "index.html"));
|
|
62668
61793
|
});
|