mjpic 1.0.0

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.
Files changed (58) hide show
  1. package/.trae/documents/mjpic-prd.md +111 -0
  2. package/.trae/documents/mjpic-technical-architecture.md +234 -0
  3. package/README.md +57 -0
  4. package/api/app.ts +60 -0
  5. package/api/cli.ts +61 -0
  6. package/api/index.ts +19 -0
  7. package/api/routes/auth.ts +33 -0
  8. package/api/routes/image.ts +27 -0
  9. package/api/server.ts +45 -0
  10. package/dist/cli/app.js +43 -0
  11. package/dist/cli/cli.js +49 -0
  12. package/dist/cli/index.js +13 -0
  13. package/dist/cli/routes/auth.js +28 -0
  14. package/dist/cli/routes/image.js +21 -0
  15. package/dist/cli/server.js +38 -0
  16. package/dist/client/assets/index-BUIYLOn-.js +197 -0
  17. package/dist/client/assets/index-BoiS81Ei.css +1 -0
  18. package/dist/client/favicon.svg +4 -0
  19. package/dist/client/index.html +354 -0
  20. package/eslint.config.js +28 -0
  21. package/index.html +24 -0
  22. package/nodemon.json +10 -0
  23. package/package.json +68 -0
  24. package/postcss.config.js +10 -0
  25. package/public/favicon.svg +4 -0
  26. package/src/App.tsx +13 -0
  27. package/src/assets/react.svg +1 -0
  28. package/src/components/Empty.tsx +8 -0
  29. package/src/components/dialogs/AspectRatioDialog.tsx +218 -0
  30. package/src/components/dialogs/SaveDialog.tsx +150 -0
  31. package/src/components/layout/CanvasArea.tsx +874 -0
  32. package/src/components/layout/Header.tsx +156 -0
  33. package/src/components/layout/RightPanel.tsx +886 -0
  34. package/src/components/layout/Sidebar.tsx +36 -0
  35. package/src/components/layout/StatusBar.tsx +44 -0
  36. package/src/hooks/useDebounce.ts +17 -0
  37. package/src/hooks/useTheme.ts +29 -0
  38. package/src/i18n/index.ts +26 -0
  39. package/src/i18n/locales/en.json +56 -0
  40. package/src/i18n/locales/zh.json +59 -0
  41. package/src/index.css +14 -0
  42. package/src/lib/utils.ts +73 -0
  43. package/src/main.tsx +11 -0
  44. package/src/pages/Home.tsx +72 -0
  45. package/src/store/useImageStore.ts +316 -0
  46. package/src/store/usePresetStore.ts +65 -0
  47. package/src/store/useUIStore.ts +17 -0
  48. package/src/vite-env.d.ts +1 -0
  49. package/tailwind.config.js +13 -0
  50. package/tmp/guangxi.jpg +0 -0
  51. package/tsconfig.json +40 -0
  52. package/tsconfig.server.json +15 -0
  53. package/vercel.json +12 -0
  54. package/vite.config.ts +50 -0
  55. package//345/217/202/350/200/203/345/233/276/347/211/207//346/210/252/345/261/2172026-02-18 16.47.45_/345/233/276/347/211/207/345/260/272/345/257/270/350/260/203/350/212/202_/351/242/204/350/256/276/345/260/272/345/257/270.jpg +0 -0
  56. package//345/217/202/350/200/203/345/233/276/347/211/207//346/210/252/345/261/2172026-02-18 16.47.51_/345/233/276/347/211/207/345/260/272/345/257/270/350/260/203/350/212/202_/346/211/213/345/267/245/350/276/223/345/205/245/345/260/272/345/257/270.jpg +0 -0
  57. package//345/217/202/350/200/203/345/233/276/347/211/207//346/210/252/345/261/2172026-02-18 16.54.56_/345/233/276/347/211/207/345/260/272/345/257/270/350/260/203/350/212/202_/346/267/273/345/212/240/345/270/270/347/224/250/345/260/272/345/257/270.jpg +0 -0
  58. package//345/217/202/350/200/203/345/233/276/347/211/207//346/210/252/345/261/2172026-02-18 16.55.11_/345/233/276/347/211/207/345/260/272/345/257/270/350/260/203/350/212/202_/345/210/240/351/231/244/345/270/270/347/224/250/345/260/272/345/257/270.jpg +0 -0
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import express from 'express';
4
+ import path from 'path';
5
+ import { fileURLToPath } from 'url';
6
+ import open from 'open';
7
+ import app from './app.js';
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = path.dirname(__filename);
10
+ const program = new Command();
11
+ program
12
+ .name('mjpic')
13
+ .description('Agile Image Processing Tool')
14
+ .version('1.0.0')
15
+ .option('-p, --port <number>', 'server port', '3000')
16
+ .option('--host <string>', 'server host', 'localhost')
17
+ .argument('[file]', 'image file to open')
18
+ .action(async (file, options) => {
19
+ const port = parseInt(options.port, 10);
20
+ const host = options.host;
21
+ if (file) {
22
+ const absPath = path.resolve(file);
23
+ console.log(`Opening file: ${absPath}`);
24
+ app.get('/api/current-image', (req, res) => {
25
+ res.json({ path: absPath });
26
+ });
27
+ app.get('/api/image-content', (req, res) => {
28
+ res.sendFile(absPath);
29
+ });
30
+ }
31
+ // Serve static files
32
+ // In production (dist), client is in ../client
33
+ const clientPath = path.join(__dirname, '../client');
34
+ app.use(express.static(clientPath));
35
+ // API 404 handler - Ensure API requests don't fall through to index.html
36
+ app.use('/api/*', (req, res) => {
37
+ res.status(404).json({ success: false, error: 'API not found' });
38
+ });
39
+ // SPA fallback
40
+ app.get('*', (req, res) => {
41
+ res.sendFile(path.join(clientPath, 'index.html'));
42
+ });
43
+ app.listen(port, host, () => {
44
+ const url = `http://${host}:${port}`;
45
+ console.log(`mjpic is running at ${url}`);
46
+ open(url);
47
+ });
48
+ });
49
+ program.parse();
@@ -0,0 +1,13 @@
1
+ import app from './app.js';
2
+ /**
3
+ * 404 handler
4
+ */
5
+ app.use((req, res) => {
6
+ res.status(404).json({
7
+ success: false,
8
+ error: 'API not found',
9
+ });
10
+ });
11
+ export default function handler(req, res) {
12
+ return app(req, res);
13
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * This is a user authentication API route demo.
3
+ * Handle user registration, login, token management, etc.
4
+ */
5
+ import { Router } from 'express';
6
+ const router = Router();
7
+ /**
8
+ * User Login
9
+ * POST /api/auth/register
10
+ */
11
+ router.post('/register', async (req, res) => {
12
+ // TODO: Implement register logic
13
+ });
14
+ /**
15
+ * User Login
16
+ * POST /api/auth/login
17
+ */
18
+ router.post('/login', async (req, res) => {
19
+ // TODO: Implement login logic
20
+ });
21
+ /**
22
+ * User Logout
23
+ * POST /api/auth/logout
24
+ */
25
+ router.post('/logout', async (req, res) => {
26
+ // TODO: Implement logout logic
27
+ });
28
+ export default router;
@@ -0,0 +1,21 @@
1
+ import { Router } from 'express';
2
+ import fs from 'fs/promises';
3
+ const router = Router();
4
+ router.post('/save', async (req, res) => {
5
+ try {
6
+ const { filePath, data } = req.body;
7
+ if (!filePath || !data) {
8
+ return res.status(400).json({ success: false, error: 'Missing filePath or data' });
9
+ }
10
+ // data is data:image/png;base64,....
11
+ const base64Data = data.replace(/^data:image\/\w+;base64,/, "");
12
+ const buffer = Buffer.from(base64Data, 'base64');
13
+ await fs.writeFile(filePath, buffer);
14
+ res.json({ success: true });
15
+ }
16
+ catch (error) {
17
+ console.error('Save error:', error);
18
+ res.status(500).json({ success: false, error: 'Failed to save file' });
19
+ }
20
+ });
21
+ export default router;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * local server entry file, for local development
3
+ */
4
+ import app from './app.js';
5
+ /**
6
+ * 404 handler
7
+ */
8
+ app.use((req, res) => {
9
+ res.status(404).json({
10
+ success: false,
11
+ error: 'API not found',
12
+ });
13
+ });
14
+ /**
15
+ * start server with port
16
+ */
17
+ const PORT = process.env.PORT || 3002;
18
+ const server = app.listen(PORT, () => {
19
+ console.log(`Server ready on port ${PORT}`);
20
+ });
21
+ /**
22
+ * close server
23
+ */
24
+ process.on('SIGTERM', () => {
25
+ console.log('SIGTERM signal received');
26
+ server.close(() => {
27
+ console.log('Server closed');
28
+ process.exit(0);
29
+ });
30
+ });
31
+ process.on('SIGINT', () => {
32
+ console.log('SIGINT signal received');
33
+ server.close(() => {
34
+ console.log('Server closed');
35
+ process.exit(0);
36
+ });
37
+ });
38
+ export default app;