diff --git a/.gitignore b/.gitignore
index 78a64ad..4a546d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,8 +14,20 @@ backend/node_modules
# Build outputs
dist
dist-ssr
+dev-dist
*.local
+# Vite
+.vite
+vite.config.*.timestamp-*
+
+# Build artifacts in backend/public
+backend/public/assets/
+backend/public/workbox-*.js
+backend/public/registerSW.js
+backend/public/sw.js
+backend/public/index.html
+
# Environment variables
.env
.env.local
@@ -26,6 +38,7 @@ backend/.env
backend/database/*.db
backend/database/*.db-shm
backend/database/*.db-wal
+backend/database/*.db-journal
# Uploads
backend/public/uploads/*
@@ -35,7 +48,6 @@ backend/public/uploads/*
.vscode/*
!.vscode/extensions.json
.idea
-.DS_Store
*.suo
*.ntvs*
*.njsproj
@@ -47,4 +59,25 @@ public/sw.js.map
# OS
Thumbs.db
+.DS_Store
+*.swp
+*.swo
+*~
+
+# TypeScript
+*.tsbuildinfo
+.tsbuildinfo
+
+# Coverage
+coverage
+*.lcov
+.nyc_output
+
+# Testing
+.jest
+
+# Misc
+.cache
+.parcel-cache
+.turbo
diff --git a/backend/public/index.html b/backend/public/index.html
index fd7cee9..cb9ad94 100644
--- a/backend/public/index.html
+++ b/backend/public/index.html
@@ -1,69 +1,69 @@
-
-
-
-
-
- NoteJS - Система заметок
-
-
-
-
-
+
+
+
+
+
+ NoteJS - Система заметок
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/backend/public/manifest.json b/backend/public/manifest.json
index ac17bce..ad0f651 100644
--- a/backend/public/manifest.json
+++ b/backend/public/manifest.json
@@ -9,27 +9,10 @@
"orientation": "portrait-primary",
"scope": "/",
"lang": "ru",
- "id": "/",
"categories": ["productivity", "utilities"],
"prefer_related_applications": false,
"display_override": ["window-controls-overlay", "standalone"],
"dir": "ltr",
- "shortcuts": [
- {
- "name": "Новая заметка",
- "short_name": "Новая",
- "description": "Создать новую заметку",
- "url": "/notes?new=true",
- "icons": [{ "src": "/icons/icon-192x192.png", "sizes": "192x192" }]
- },
- {
- "name": "Мой профиль",
- "short_name": "Профиль",
- "description": "Открыть профиль",
- "url": "/profile",
- "icons": [{ "src": "/icons/icon-192x192.png", "sizes": "192x192" }]
- }
- ],
"screenshots": [
{
"src": "/icons/icon-512x512.png",
diff --git a/backend/public/sw.js b/backend/public/sw.js
index 0f41c4a..d2cb491 100644
--- a/backend/public/sw.js
+++ b/backend/public/sw.js
@@ -1 +1 @@
-if(!self.define){let e,i={};const n=(n,c)=>(n=new URL(n+".js",c).href,i[n]||new Promise(i=>{if("document"in self){const e=document.createElement("script");e.src=n,e.onload=i,document.head.appendChild(e)}else e=n,importScripts(n),i()}).then(()=>{let e=i[n];if(!e)throw new Error(`Module ${n} didn’t register its module`);return e}));self.define=(c,o)=>{const s=e||("document"in self?document.currentScript.src:"")||location.href;if(i[s])return;let r={};const d=e=>n(e,s),a={module:{uri:s},exports:r,require:d};i[s]=Promise.all(c.map(e=>a[e]||d(e))).then(e=>(o(...e),r))}}define(["./workbox-57555046"],function(e){"use strict";self.addEventListener("message",e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()}),e.precacheAndRoute([{url:"assets/index-CRKRzJj1.js",revision:null},{url:"assets/index-QEK5TGz3.css",revision:null},{url:"assets/workbox-window.prod.es5-B9K5rw8f.js",revision:null},{url:"icon.svg",revision:"537ae73d8f9e90e6a01816aa6d527d16"},{url:"icons/icon-128x128.png",revision:"fa71db17e345406d5f7d847f88c65ac4"},{url:"icons/icon-144x144.png",revision:"e790ff42758ea1a2a46eb84201630757"},{url:"icons/icon-152x152.png",revision:"88f2400f6617a32cc9cd62c70fb49a05"},{url:"icons/icon-16x16.png",revision:"101c13808e9fd0956f247bc446a8ac1e"},{url:"icons/icon-192x192.png",revision:"7d86d2d2ada99d7cee015dff0fdcb497"},{url:"icons/icon-32x32.png",revision:"22ee5d42535bc339ab0e19cb496378a5"},{url:"icons/icon-384x384.png",revision:"c601fa602952a903389e5e8f8a699617"},{url:"icons/icon-48x48.png",revision:"cfdd3bebd931375f2e0277d638ec8781"},{url:"icons/icon-512x512.png",revision:"8731edef999b9e7deba310d72a739925"},{url:"icons/icon-72x72.png",revision:"6b3cb1b2537ec91921698260a9c2f47c"},{url:"icons/icon-96x96.png",revision:"7efd757a81217207d981de88ef199d86"},{url:"index.html",revision:"52c85beb0841c0c7c8ddf774370cff39"},{url:"logo.svg",revision:"11616ede8898b4c24203e331b3ec6dc3"},{url:"icons/icon-72x72.png",revision:"6b3cb1b2537ec91921698260a9c2f47c"},{url:"icons/icon-96x96.png",revision:"7efd757a81217207d981de88ef199d86"},{url:"icons/icon-128x128.png",revision:"fa71db17e345406d5f7d847f88c65ac4"},{url:"icons/icon-144x144.png",revision:"e790ff42758ea1a2a46eb84201630757"},{url:"icons/icon-152x152.png",revision:"88f2400f6617a32cc9cd62c70fb49a05"},{url:"icons/icon-192x192.png",revision:"7d86d2d2ada99d7cee015dff0fdcb497"},{url:"icons/icon-384x384.png",revision:"c601fa602952a903389e5e8f8a699617"},{url:"icons/icon-512x512.png",revision:"8731edef999b9e7deba310d72a739925"},{url:"manifest.webmanifest",revision:"1c071cadebd7a1b0dc1eeb0270e73fb8"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("index.html"))),e.registerRoute(/^https:\/\/api\./i,new e.NetworkFirst({cacheName:"api-cache",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:50,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:png|jpg|jpeg|svg|gif|webp)$/i,new e.CacheFirst({cacheName:"image-cache",plugins:[new e.ExpirationPlugin({maxEntries:100,maxAgeSeconds:2592e3})]}),"GET")});
+if(!self.define){let e,n={};const i=(i,c)=>(i=new URL(i+".js",c).href,n[i]||new Promise(n=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=n,document.head.appendChild(e)}else e=i,importScripts(i),n()}).then(()=>{let e=n[i];if(!e)throw new Error(`Module ${i} didn’t register its module`);return e}));self.define=(c,o)=>{const s=e||("document"in self?document.currentScript.src:"")||location.href;if(n[s])return;let a={};const r=e=>i(e,s),d={module:{uri:s},exports:a,require:r};n[s]=Promise.all(c.map(e=>d[e]||r(e))).then(e=>(o(...e),a))}}define(["./workbox-e20531c6"],function(e){"use strict";self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"assets/index-Czo9BXMw.js",revision:null},{url:"assets/index-d4V1QKN4.css",revision:null},{url:"icon.svg",revision:"0ec61aab261526d4c491e887a6f3374e"},{url:"icons/icon-128x128.png",revision:"fa71db17e345406d5f7d847f88c65ac4"},{url:"icons/icon-144x144.png",revision:"e790ff42758ea1a2a46eb84201630757"},{url:"icons/icon-152x152.png",revision:"88f2400f6617a32cc9cd62c70fb49a05"},{url:"icons/icon-16x16.png",revision:"101c13808e9fd0956f247bc446a8ac1e"},{url:"icons/icon-192x192.png",revision:"7d86d2d2ada99d7cee015dff0fdcb497"},{url:"icons/icon-32x32.png",revision:"22ee5d42535bc339ab0e19cb496378a5"},{url:"icons/icon-384x384.png",revision:"c601fa602952a903389e5e8f8a699617"},{url:"icons/icon-48x48.png",revision:"cfdd3bebd931375f2e0277d638ec8781"},{url:"icons/icon-512x512.png",revision:"8731edef999b9e7deba310d72a739925"},{url:"icons/icon-72x72.png",revision:"6b3cb1b2537ec91921698260a9c2f47c"},{url:"icons/icon-96x96.png",revision:"7efd757a81217207d981de88ef199d86"},{url:"index.html",revision:"b8f278b7bd4e55f30369e5de187d6eaa"},{url:"logo.svg",revision:"5962d0d24d9cd26cd8aaff9cb6f54a5a"},{url:"registerSW.js",revision:"1872c500de691dce40960bb85481de07"},{url:"icon.svg",revision:"0ec61aab261526d4c491e887a6f3374e"},{url:"icons/icon-192x192.png",revision:"7d86d2d2ada99d7cee015dff0fdcb497"},{url:"icons/icon-512x512.png",revision:"8731edef999b9e7deba310d72a739925"},{url:"icons/icon-72x72.png",revision:"6b3cb1b2537ec91921698260a9c2f47c"},{url:"icons/icon-96x96.png",revision:"7efd757a81217207d981de88ef199d86"},{url:"icons/icon-128x128.png",revision:"fa71db17e345406d5f7d847f88c65ac4"},{url:"icons/icon-144x144.png",revision:"e790ff42758ea1a2a46eb84201630757"},{url:"icons/icon-152x152.png",revision:"88f2400f6617a32cc9cd62c70fb49a05"},{url:"icons/icon-384x384.png",revision:"c601fa602952a903389e5e8f8a699617"},{url:"manifest.webmanifest",revision:"1c071cadebd7a1b0dc1eeb0270e73fb8"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("index.html"))),e.registerRoute(/^https:\/\/api\./,new e.NetworkFirst({cacheName:"api-cache",plugins:[new e.ExpirationPlugin({maxEntries:50,maxAgeSeconds:3600})]}),"GET"),e.registerRoute(/\/api\//,new e.NetworkFirst({cacheName:"api-cache-local",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:100,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\/uploads\//,new e.CacheFirst({cacheName:"uploads-cache",plugins:[new e.ExpirationPlugin({maxEntries:200,maxAgeSeconds:2592e3})]}),"GET"),e.registerRoute(/\.(?:png|jpg|jpeg|svg|gif|webp)$/,new e.CacheFirst({cacheName:"images-cache",plugins:[new e.ExpirationPlugin({maxEntries:100,maxAgeSeconds:2592e3})]}),"GET")});
diff --git a/backend/server.js b/backend/server.js
index b93897a..e2a9fce 100644
--- a/backend/server.js
+++ b/backend/server.js
@@ -203,6 +203,43 @@ app.get("/sw.js", (req, res) => {
res.sendFile(path.join(__dirname, "public", "sw.js"));
});
+// Service worker для dev режима
+const devDistPath = path.join(__dirname, "..", "dev-dist");
+app.get("/dev-sw.js", (req, res) => {
+ res.setHeader("Content-Type", "application/javascript");
+ res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
+ const swPath = path.join(devDistPath, "sw.js");
+ if (fs.existsSync(swPath)) {
+ res.sendFile(swPath);
+ } else {
+ res.status(404).send("Service worker not found");
+ }
+});
+
+// RegisterSW для dev режима
+app.get("/registerSW.js", (req, res) => {
+ res.setHeader("Content-Type", "application/javascript");
+ res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
+ const registerSWPath = path.join(devDistPath, "registerSW.js");
+ if (fs.existsSync(registerSWPath)) {
+ res.sendFile(registerSWPath);
+ } else {
+ res.status(404).send("registerSW.js not found");
+ }
+});
+
+// Workbox файлы для dev режима
+app.get("/workbox-:hash.js", (req, res) => {
+ res.setHeader("Content-Type", "application/javascript");
+ res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
+ const workboxPath = path.join(devDistPath, `workbox-${req.params.hash}.js`);
+ if (fs.existsSync(workboxPath)) {
+ res.sendFile(workboxPath);
+ } else {
+ res.status(404).send("Workbox file not found");
+ }
+});
+
app.get("/browserconfig.xml", (req, res) => {
res.setHeader("Content-Type", "application/xml");
res.setHeader("Cache-Control", "public, max-age=86400"); // 24 часа
@@ -793,19 +830,19 @@ app.get("/notes", requireAuth, (req, res) => {
db.get(sql, [req.session.userId], (err, user) => {
if (err) {
console.error("Ошибка получения цвета пользователя:", err.message);
- return res.sendFile(path.join(__dirname, "public", "notes.html"));
+ return res.sendFile(path.join(__dirname, "public", "index.html"));
}
const accentColor = user?.accent_color || "#007bff";
// Читаем HTML файл
fs.readFile(
- path.join(__dirname, "public", "notes.html"),
+ path.join(__dirname, "public", "index.html"),
"utf8",
(err, html) => {
if (err) {
- console.error("Ошибка чтения файла notes.html:", err.message);
- return res.sendFile(path.join(__dirname, "public", "notes.html"));
+ console.error("Ошибка чтения файла index.html:", err.message);
+ return res.sendFile(path.join(__dirname, "public", "index.html"));
}
// Вставляем inline CSS с правильным цветом в самое начало head для предотвращения FOUC
@@ -1559,19 +1596,19 @@ app.get("/profile", requireAuth, (req, res) => {
db.get(sql, [req.session.userId], (err, user) => {
if (err) {
console.error("Ошибка получения цвета пользователя:", err.message);
- return res.sendFile(path.join(__dirname, "public", "profile.html"));
+ return res.sendFile(path.join(__dirname, "public", "index.html"));
}
const accentColor = user?.accent_color || "#007bff";
// Читаем HTML файл
fs.readFile(
- path.join(__dirname, "public", "profile.html"),
+ path.join(__dirname, "public", "index.html"),
"utf8",
(err, html) => {
if (err) {
- console.error("Ошибка чтения файла profile.html:", err.message);
- return res.sendFile(path.join(__dirname, "public", "profile.html"));
+ console.error("Ошибка чтения файла index.html:", err.message);
+ return res.sendFile(path.join(__dirname, "public", "index.html"));
}
// Вставляем inline CSS с правильным цветом в самое начало head для предотвращения FOUC
@@ -2243,19 +2280,19 @@ app.get("/settings", requireAuth, (req, res) => {
db.get(sql, [req.session.userId], (err, user) => {
if (err) {
console.error("Ошибка получения цвета пользователя:", err.message);
- return res.sendFile(path.join(__dirname, "public", "settings.html"));
+ return res.sendFile(path.join(__dirname, "public", "index.html"));
}
const accentColor = user?.accent_color || "#007bff";
// Читаем HTML файл
fs.readFile(
- path.join(__dirname, "public", "settings.html"),
+ path.join(__dirname, "public", "index.html"),
"utf8",
(err, html) => {
if (err) {
- console.error("Ошибка чтения файла settings.html:", err.message);
- return res.sendFile(path.join(__dirname, "public", "settings.html"));
+ console.error("Ошибка чтения файла index.html:", err.message);
+ return res.sendFile(path.join(__dirname, "public", "index.html"));
}
// Вставляем inline CSS с правильным цветом
diff --git a/dev-dist/sw.js b/dev-dist/sw.js
index 04d17d9..66cc4be 100644
--- a/dev-dist/sw.js
+++ b/dev-dist/sw.js
@@ -82,7 +82,7 @@ define(['./workbox-9dc17825'], (function (workbox) { 'use strict';
"revision": "3ca0b8505b4bec776b69afdba2768812"
}, {
"url": "index.html",
- "revision": "0.fijdulj6fg"
+ "revision": "0.q31tuubm2tg"
}], {});
workbox.cleanupOutdatedCaches();
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
diff --git a/vite.config.ts b/vite.config.ts
index d7e1ff5..ba6dd44 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -143,7 +143,8 @@ export default defineConfig({
registerType: "prompt",
devOptions: {
enabled: true,
- type: "module",
+ type: "classic",
+ navigateFallback: "index.html",
},
}),
],