@luutuankiet/gsd-reader 0.2.0 → 0.2.1

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 (54) hide show
  1. package/cli.cjs +395 -161
  2. package/dist/assets/{_baseUniq-Bdn1nEwY.js → _baseUniq-CKUecoLH.js} +1 -1
  3. package/dist/assets/{arc-fh_JU-kD.js → arc-w-ELZCWB.js} +1 -1
  4. package/dist/assets/{architectureDiagram-VXUJARFQ-ta8hDWLU.js → architectureDiagram-VXUJARFQ-CsAEKCx4.js} +1 -1
  5. package/dist/assets/{blockDiagram-VD42YOAC-fp46vVEh.js → blockDiagram-VD42YOAC-DlNmI1pW.js} +1 -1
  6. package/dist/assets/{c4Diagram-YG6GDRKO-CIUWbITm.js → c4Diagram-YG6GDRKO-DvcMVUiY.js} +1 -1
  7. package/dist/assets/channel-DFc32Psl.js +1 -0
  8. package/dist/assets/{chunk-4BX2VUAB-CiUTh5Wr.js → chunk-4BX2VUAB-Bz7vqOLd.js} +1 -1
  9. package/dist/assets/{chunk-55IACEB6-C0yEKdQa.js → chunk-55IACEB6-B0201kny.js} +1 -1
  10. package/dist/assets/{chunk-B4BG7PRW-Dph3sajP.js → chunk-B4BG7PRW-DSzi2E_1.js} +1 -1
  11. package/dist/assets/{chunk-DI55MBZ5-aBYeKGnn.js → chunk-DI55MBZ5-CeXGxt7g.js} +1 -1
  12. package/dist/assets/{chunk-FMBD7UC4-CEhTzqEH.js → chunk-FMBD7UC4-rwYYBtp0.js} +1 -1
  13. package/dist/assets/{chunk-QN33PNHL-BHk7wgpN.js → chunk-QN33PNHL-COd7MIBT.js} +1 -1
  14. package/dist/assets/{chunk-QZHKN3VN-CXgpYl35.js → chunk-QZHKN3VN-pIlrfp_i.js} +1 -1
  15. package/dist/assets/{chunk-TZMSLE5B-xFTTLJ9z.js → chunk-TZMSLE5B-Dtk8serO.js} +1 -1
  16. package/dist/assets/classDiagram-2ON5EDUG-BM5cPi6U.js +1 -0
  17. package/dist/assets/classDiagram-v2-WZHVMYZB-BM5cPi6U.js +1 -0
  18. package/dist/assets/clone-Wtv-bIdw.js +1 -0
  19. package/dist/assets/{cose-bilkent-S5V4N54A-DgvLJE5H.js → cose-bilkent-S5V4N54A-ysEkzH2M.js} +1 -1
  20. package/dist/assets/{dagre-6UL2VRFP-D53BTNxD.js → dagre-6UL2VRFP-BGJ_Wa94.js} +1 -1
  21. package/dist/assets/{diagram-PSM6KHXK-DXqmMUqU.js → diagram-PSM6KHXK-BG-NfT7k.js} +1 -1
  22. package/dist/assets/{diagram-QEK2KX5R-CLeMobu4.js → diagram-QEK2KX5R-CyXy7GGx.js} +1 -1
  23. package/dist/assets/{diagram-S2PKOQOG-D66o9MAr.js → diagram-S2PKOQOG-DkK5GNTL.js} +1 -1
  24. package/dist/assets/{erDiagram-Q2GNP2WA-CpJD1kMO.js → erDiagram-Q2GNP2WA-DmEg4tz4.js} +1 -1
  25. package/dist/assets/{flowDiagram-NV44I4VS-CbFkeHvb.js → flowDiagram-NV44I4VS-C5yszFqH.js} +1 -1
  26. package/dist/assets/{ganttDiagram-JELNMOA3-3fTl17JM.js → ganttDiagram-JELNMOA3-BFZcd3fA.js} +1 -1
  27. package/dist/assets/{gitGraphDiagram-NY62KEGX-CIJK1HZz.js → gitGraphDiagram-NY62KEGX-DZeUMcua.js} +1 -1
  28. package/dist/assets/{graph-WCuwHVe9.js → graph-1QrSm3zk.js} +1 -1
  29. package/dist/assets/{index-4oweX4fz.js → index-DBtLk3Vc.js} +20 -20
  30. package/dist/assets/{infoDiagram-WHAUD3N6-CvZ908oi.js → infoDiagram-WHAUD3N6-BfLOQrdd.js} +1 -1
  31. package/dist/assets/{journeyDiagram-XKPGCS4Q-BSwShGBk.js → journeyDiagram-XKPGCS4Q-Cf0ZUYZC.js} +1 -1
  32. package/dist/assets/{kanban-definition-3W4ZIXB7-B0M4IroL.js → kanban-definition-3W4ZIXB7-CIZW3mII.js} +1 -1
  33. package/dist/assets/{layout-BCTNMp28.js → layout-BJyZTIXw.js} +1 -1
  34. package/dist/assets/{linear-Bd-Gzgwq.js → linear-DPVIMMcl.js} +1 -1
  35. package/dist/assets/{mermaid.core-CWefC7Oh.js → mermaid.core-DktP_MzF.js} +4 -4
  36. package/dist/assets/{min-CLuzHP9M.js → min-D6Nsl4H7.js} +1 -1
  37. package/dist/assets/{mindmap-definition-VGOIOE7T-Cs-LAQ4V.js → mindmap-definition-VGOIOE7T-CgWCtKEj.js} +1 -1
  38. package/dist/assets/{pieDiagram-ADFJNKIX-CfEaM9L4.js → pieDiagram-ADFJNKIX-3krEz2hr.js} +1 -1
  39. package/dist/assets/{quadrantDiagram-AYHSOK5B-C1eE_1Yq.js → quadrantDiagram-AYHSOK5B-DhLVO3Jv.js} +1 -1
  40. package/dist/assets/{requirementDiagram-UZGBJVZJ-Mu-sTVKg.js → requirementDiagram-UZGBJVZJ-DJxn06px.js} +1 -1
  41. package/dist/assets/{sankeyDiagram-TZEHDZUN-Ls72W3Pm.js → sankeyDiagram-TZEHDZUN-CI4yeTwo.js} +1 -1
  42. package/dist/assets/{sequenceDiagram-WL72ISMW-CV9T-ld3.js → sequenceDiagram-WL72ISMW-CHzNt658.js} +1 -1
  43. package/dist/assets/{stateDiagram-FKZM4ZOC-B_2WH-Ns.js → stateDiagram-FKZM4ZOC-NurdbYdk.js} +1 -1
  44. package/dist/assets/stateDiagram-v2-4FDKWEC3-C0BCPrmC.js +1 -0
  45. package/dist/assets/{timeline-definition-IT6M3QCI-CGg3mPtB.js → timeline-definition-IT6M3QCI-BKSIpumj.js} +1 -1
  46. package/dist/assets/{treemap-KMMF4GRG-D84Z6fq0.js → treemap-KMMF4GRG-D7DE6DUP.js} +1 -1
  47. package/dist/assets/{xychartDiagram-PRI3JC2R-EVzJiOor.js → xychartDiagram-PRI3JC2R-bNNzjDxT.js} +1 -1
  48. package/dist/index.html +1 -1
  49. package/package.json +2 -1
  50. package/dist/assets/channel-BSNpO1uu.js +0 -1
  51. package/dist/assets/classDiagram-2ON5EDUG-DUftwofz.js +0 -1
  52. package/dist/assets/classDiagram-v2-WZHVMYZB-DUftwofz.js +0 -1
  53. package/dist/assets/clone-fKP9fCWC.js +0 -1
  54. package/dist/assets/stateDiagram-v2-4FDKWEC3-Cvx1tTX1.js +0 -1
package/cli.cjs CHANGED
@@ -3,213 +3,447 @@
3
3
  /**
4
4
  * GSD-Lite Worklog Reader CLI
5
5
  *
6
- * A lightweight server for viewing WORK.md files with live reload.
7
- * Uses chokidar for native file watching and WebSocket for push updates.
8
- *
9
- * Usage:
10
- * npx @gsd-lite/reader [path-to-worklog] [--port=3000]
6
+ * Commands:
7
+ * serve [path] [--port=3000] Start live-reload server (default)
8
+ * dump [path] --remote=URL Build and upload to remote server
11
9
  *
12
10
  * Examples:
13
- * npx @gsd-lite/reader # Watch ./gsd-lite/WORK.md on :3000
14
- * npx @gsd-lite/reader ./my-project/WORK.md # Custom path
15
- * npx @gsd-lite/reader --port=3001 # Custom port
11
+ * npx @luutuankiet/gsd-reader # Serve ./gsd-lite/WORK.md on :3000
12
+ * npx @luutuankiet/gsd-reader serve ./project/WORK.md # Serve custom path
13
+ * npx @luutuankiet/gsd-reader dump --remote=https://gsd.kenluu.org --user=ken
16
14
  */
17
15
 
18
16
  const http = require('http');
17
+ const https = require('https');
19
18
  const fs = require('fs');
20
19
  const path = require('path');
21
20
  const { WebSocketServer } = require('ws');
22
21
  const chokidar = require('chokidar');
22
+ const { execSync } = require('child_process');
23
+ const zlib = require('zlib');
24
+ const tar = require('tar');
25
+ const readline = require('readline');
23
26
 
24
27
  // =============================================================================
25
- // Configuration
28
+ // Argument Parsing
26
29
  // =============================================================================
27
30
 
28
- // Parse command line arguments
29
31
  const args = process.argv.slice(2);
32
+ const command = args[0] && !args[0].startsWith('--') && !args[0].includes('/') && !args[0].endsWith('.md')
33
+ ? args[0]
34
+ : 'serve';
35
+
36
+ // Extract flags
37
+ function getFlag(name) {
38
+ const arg = args.find(a => a.startsWith(`--${name}=`));
39
+ return arg?.split('=')[1];
40
+ }
30
41
 
31
- // Find port from --port=XXXX argument
32
- const portArg = args.find(a => a.startsWith('--port='));
33
- const PORT = parseInt(portArg?.split('=')[1] || process.env.PORT || '3000', 10);
34
-
35
- // First non-flag argument is the worklog path
36
- const WORKLOG = args.find(a => !a.startsWith('--')) || './gsd-lite/WORK.md';
37
- const WORKLOG_PATH = path.resolve(WORKLOG);
38
-
39
- // Static assets directory (bundled with this package)
40
- const DIST = path.join(__dirname, 'dist');
41
-
42
- // MIME types for static file serving
43
- const MIME_TYPES = {
44
- '.html': 'text/html',
45
- '.js': 'application/javascript',
46
- '.css': 'text/css',
47
- '.json': 'application/json',
48
- '.png': 'image/png',
49
- '.jpg': 'image/jpeg',
50
- '.gif': 'image/gif',
51
- '.svg': 'image/svg+xml',
52
- '.ico': 'image/x-icon',
53
- '.woff': 'font/woff',
54
- '.woff2': 'font/woff2',
55
- '.ttf': 'font/ttf',
56
- };
42
+ function hasFlag(name) {
43
+ return args.includes(`--${name}`);
44
+ }
45
+
46
+ // Find non-flag arguments (excluding command)
47
+ const positionalArgs = args.filter(a => !a.startsWith('--') && a !== command);
57
48
 
58
49
  // =============================================================================
59
- // HTTP Server
50
+ // Command: dump
60
51
  // =============================================================================
61
52
 
62
- const server = http.createServer((req, res) => {
63
- const url = new URL(req.url, `http://${req.headers.host}`);
64
- const pathname = url.pathname;
65
-
66
- // API endpoint: serve WORK.md content
67
- if (pathname === '/_worklog') {
68
- try {
69
- const content = fs.readFileSync(WORKLOG_PATH, 'utf-8');
70
- res.setHeader('Content-Type', 'text/plain; charset=utf-8');
71
- res.setHeader('Cache-Control', 'no-cache');
72
- res.end(content);
73
- } catch (err) {
74
- res.statusCode = 404;
75
- res.setHeader('Content-Type', 'text/plain');
76
- res.end(`WORK.md not found: ${WORKLOG_PATH}\n\nError: ${err.message}`);
77
- }
78
- return;
53
+ async function commandDump() {
54
+ const worklogPath = positionalArgs[0] || './gsd-lite/WORK.md';
55
+ const remote = getFlag('remote');
56
+ const user = getFlag('user');
57
+
58
+ if (!remote) {
59
+ console.error('❌ --remote=URL is required');
60
+ console.error('\nUsage: npx @luutuankiet/gsd-reader dump [path] --remote=URL --user=USER');
61
+ console.error('\nExample:');
62
+ console.error(' npx @luutuankiet/gsd-reader dump --remote=https://gsd.kenluu.org --user=ken');
63
+ process.exit(1);
79
64
  }
80
65
 
81
- // Static file serving from dist/
82
- let filePath = pathname === '/' ? '/index.html' : pathname;
83
- const fullPath = path.join(DIST, filePath);
66
+ // Resolve paths
67
+ const resolvedWorklog = path.resolve(worklogPath);
68
+ const projectDir = path.dirname(resolvedWorklog);
69
+
70
+ // Derive project name from path (last 2 segments)
71
+ const pathParts = projectDir.split(path.sep).filter(Boolean);
72
+ const projectName = pathParts.slice(-2).join('/');
73
+
74
+ console.log('');
75
+ console.log('┌─────────────────────────────────────────────────────┐');
76
+ console.log('│ 📤 GSD-Lite Worklog Dump │');
77
+ console.log('├─────────────────────────────────────────────────────┤');
78
+ console.log(`│ Worklog: ${path.basename(resolvedWorklog).padEnd(40)}│`);
79
+ console.log(`│ Project: ${projectName.padEnd(40)}│`);
80
+ console.log(`│ Remote: ${remote.padEnd(40)}│`);
81
+ console.log('└─────────────────────────────────────────────────────┘');
82
+ console.log('');
84
83
 
85
- // Security: prevent directory traversal
86
- if (!fullPath.startsWith(DIST)) {
87
- res.statusCode = 403;
88
- res.end('Forbidden');
89
- return;
84
+ // Check if worklog exists
85
+ if (!fs.existsSync(resolvedWorklog)) {
86
+ console.error(`❌ WORK.md not found: ${resolvedWorklog}`);
87
+ process.exit(1);
90
88
  }
91
89
 
92
- // Check if file exists
93
- if (!fs.existsSync(fullPath)) {
94
- // SPA fallback: serve index.html for non-file routes
95
- const indexPath = path.join(DIST, 'index.html');
96
- if (fs.existsSync(indexPath)) {
97
- serveFile(indexPath, '.html', res);
98
- return;
99
- }
100
- res.statusCode = 404;
101
- res.end('Not found');
102
- return;
103
- }
90
+ // Step 1: Build the static site
91
+ console.log('[dump] Building static site...');
92
+ const distDir = path.join(__dirname, 'dist');
93
+
94
+ // Copy dist to temp directory and inject worklog content
95
+ const tempDir = fs.mkdtempSync(path.join(require('os').tmpdir(), 'gsd-dump-'));
96
+ const tempDist = path.join(tempDir, 'dist');
97
+
98
+ // Copy dist directory
99
+ fs.cpSync(distDir, tempDist, { recursive: true });
100
+
101
+ // Read worklog and inject into HTML
102
+ const worklogContent = fs.readFileSync(resolvedWorklog, 'utf-8');
103
+ const indexPath = path.join(tempDist, 'index.html');
104
+ let indexHtml = fs.readFileSync(indexPath, 'utf-8');
105
+
106
+ // Fix asset paths: Vite builds with absolute paths (/assets/...) but we need
107
+ // relative paths (./assets/...) when served from subdirectories
108
+ indexHtml = indexHtml.replace(/href="\//g, 'href="./');
109
+ indexHtml = indexHtml.replace(/src="\//g, 'src="./');
110
+
111
+ // Inject worklog content as a script tag (the app will read this instead of fetching)
112
+ const escapedContent = JSON.stringify(worklogContent);
113
+ const injectScript = `<script>window.__WORKLOG_CONTENT__ = ${escapedContent};</script>`;
114
+ indexHtml = indexHtml.replace('</head>', `${injectScript}\n</head>`);
115
+ fs.writeFileSync(indexPath, indexHtml);
116
+
117
+ console.log(`[dump] Static site prepared in ${tempDist}`);
118
+
119
+ // Step 2: Create tar.gz
120
+ console.log('[dump] Creating archive...');
121
+ const tarPath = path.join(tempDir, 'dist.tar.gz');
122
+
123
+ await tar.create(
124
+ {
125
+ gzip: true,
126
+ file: tarPath,
127
+ cwd: tempDist,
128
+ },
129
+ fs.readdirSync(tempDist)
130
+ );
131
+
132
+ const tarStats = fs.statSync(tarPath);
133
+ console.log(`[dump] Archive created: ${(tarStats.size / 1024).toFixed(1)} KB`);
104
134
 
105
- // Serve the file
106
- const ext = path.extname(fullPath).toLowerCase();
107
- serveFile(fullPath, ext, res);
108
- });
135
+ // Step 3: Get password
136
+ let password = getFlag('pass');
137
+ if (!password && user) {
138
+ password = await promptPassword(`Password for ${user}: `);
139
+ }
109
140
 
110
- function serveFile(filePath, ext, res) {
111
- const mimeType = MIME_TYPES[ext] || 'application/octet-stream';
141
+ // Step 4: Upload to remote
142
+ console.log(`[dump] Uploading to ${remote}/upload/${projectName}...`);
143
+
144
+ const tarData = fs.readFileSync(tarPath);
145
+ const uploadUrl = new URL(`/upload/${projectName}`, remote);
112
146
 
147
+ const uploadOptions = {
148
+ method: 'POST',
149
+ headers: {
150
+ 'Content-Type': 'application/gzip',
151
+ 'Content-Length': tarData.length,
152
+ },
153
+ };
154
+
155
+ // Add basic auth if credentials provided
156
+ if (user && password) {
157
+ const auth = Buffer.from(`${user}:${password}`).toString('base64');
158
+ uploadOptions.headers['Authorization'] = `Basic ${auth}`;
159
+ }
160
+
113
161
  try {
114
- const content = fs.readFileSync(filePath);
115
- res.setHeader('Content-Type', mimeType);
116
- res.setHeader('Cache-Control', 'public, max-age=3600');
117
- res.end(content);
162
+ const response = await httpRequest(uploadUrl, uploadOptions, tarData);
163
+ console.log(`[dump] ✅ Upload complete: ${response}`);
164
+ console.log(`[dump] View at: ${remote}/${projectName}/`);
118
165
  } catch (err) {
119
- res.statusCode = 500;
120
- res.end(`Error reading file: ${err.message}`);
166
+ console.error(`[dump] Upload failed: ${err.message}`);
167
+ process.exit(1);
168
+ } finally {
169
+ // Cleanup
170
+ fs.rmSync(tempDir, { recursive: true, force: true });
121
171
  }
122
172
  }
123
173
 
174
+ function promptPassword(prompt) {
175
+ return new Promise((resolve) => {
176
+ const rl = readline.createInterface({
177
+ input: process.stdin,
178
+ output: process.stdout,
179
+ });
180
+
181
+ // Hide input (works on most terminals)
182
+ process.stdout.write(prompt);
183
+
184
+ // For password masking, we need to handle raw mode
185
+ if (process.stdin.isTTY) {
186
+ process.stdin.setRawMode(true);
187
+ }
188
+
189
+ let password = '';
190
+
191
+ process.stdin.on('data', (char) => {
192
+ char = char.toString();
193
+
194
+ switch (char) {
195
+ case '\n':
196
+ case '\r':
197
+ case '\u0004': // Ctrl+D
198
+ if (process.stdin.isTTY) {
199
+ process.stdin.setRawMode(false);
200
+ }
201
+ process.stdout.write('\n');
202
+ rl.close();
203
+ resolve(password);
204
+ break;
205
+ case '\u0003': // Ctrl+C
206
+ process.exit(1);
207
+ break;
208
+ case '\u007F': // Backspace
209
+ password = password.slice(0, -1);
210
+ break;
211
+ default:
212
+ password += char;
213
+ break;
214
+ }
215
+ });
216
+ });
217
+ }
218
+
219
+ function httpRequest(url, options, data) {
220
+ return new Promise((resolve, reject) => {
221
+ const protocol = url.protocol === 'https:' ? https : http;
222
+
223
+ const req = protocol.request(url, options, (res) => {
224
+ let body = '';
225
+ res.on('data', (chunk) => body += chunk);
226
+ res.on('end', () => {
227
+ if (res.statusCode >= 200 && res.statusCode < 300) {
228
+ resolve(body.trim() || `HTTP ${res.statusCode}`);
229
+ } else if (res.statusCode === 401) {
230
+ reject(new Error('Authentication failed (401). Check username/password.'));
231
+ } else {
232
+ reject(new Error(`HTTP ${res.statusCode}: ${body}`));
233
+ }
234
+ });
235
+ });
236
+
237
+ req.on('error', reject);
238
+ req.write(data);
239
+ req.end();
240
+ });
241
+ }
242
+
124
243
  // =============================================================================
125
- // WebSocket Server (Live Reload)
244
+ // Command: serve (default)
126
245
  // =============================================================================
127
246
 
128
- const wss = new WebSocketServer({ server });
247
+ function commandServe() {
248
+ // Parse serve-specific arguments
249
+ const portArg = getFlag('port');
250
+ const PORT = parseInt(portArg || process.env.PORT || '3000', 10);
251
+ const WORKLOG = positionalArgs[0] || './gsd-lite/WORK.md';
252
+ const WORKLOG_PATH = path.resolve(WORKLOG);
129
253
 
130
- wss.on('connection', (ws) => {
131
- console.log('[gsd-reader] Client connected');
132
-
133
- ws.on('close', () => {
134
- console.log('[gsd-reader] Client disconnected');
254
+ // Static assets directory (bundled with this package)
255
+ const DIST = path.join(__dirname, 'dist');
256
+
257
+ // MIME types for static file serving
258
+ const MIME_TYPES = {
259
+ '.html': 'text/html',
260
+ '.js': 'application/javascript',
261
+ '.css': 'text/css',
262
+ '.json': 'application/json',
263
+ '.png': 'image/png',
264
+ '.jpg': 'image/jpeg',
265
+ '.gif': 'image/gif',
266
+ '.svg': 'image/svg+xml',
267
+ '.ico': 'image/x-icon',
268
+ '.woff': 'font/woff',
269
+ '.woff2': 'font/woff2',
270
+ '.ttf': 'font/ttf',
271
+ };
272
+
273
+ // HTTP Server
274
+ const server = http.createServer((req, res) => {
275
+ const url = new URL(req.url, `http://${req.headers.host}`);
276
+ const pathname = url.pathname;
277
+
278
+ // API endpoint: serve WORK.md content
279
+ if (pathname === '/_worklog') {
280
+ try {
281
+ const content = fs.readFileSync(WORKLOG_PATH, 'utf-8');
282
+ res.setHeader('Content-Type', 'text/plain; charset=utf-8');
283
+ res.setHeader('Cache-Control', 'no-cache');
284
+ res.end(content);
285
+ } catch (err) {
286
+ res.statusCode = 404;
287
+ res.setHeader('Content-Type', 'text/plain');
288
+ res.end(`WORK.md not found: ${WORKLOG_PATH}\n\nError: ${err.message}`);
289
+ }
290
+ return;
291
+ }
292
+
293
+ // Static file serving from dist/
294
+ let filePath = pathname === '/' ? '/index.html' : pathname;
295
+ const fullPath = path.join(DIST, filePath);
296
+
297
+ // Security: prevent directory traversal
298
+ if (!fullPath.startsWith(DIST)) {
299
+ res.statusCode = 403;
300
+ res.end('Forbidden');
301
+ return;
302
+ }
303
+
304
+ // Check if file exists
305
+ if (!fs.existsSync(fullPath)) {
306
+ // SPA fallback: serve index.html for non-file routes
307
+ const indexPath = path.join(DIST, 'index.html');
308
+ if (fs.existsSync(indexPath)) {
309
+ serveFile(indexPath, '.html', res, MIME_TYPES);
310
+ return;
311
+ }
312
+ res.statusCode = 404;
313
+ res.end('Not found');
314
+ return;
315
+ }
316
+
317
+ // Serve the file
318
+ const ext = path.extname(fullPath).toLowerCase();
319
+ serveFile(fullPath, ext, res, MIME_TYPES);
135
320
  });
136
- });
137
-
138
- function broadcastReload() {
139
- let clientCount = 0;
140
- wss.clients.forEach((client) => {
141
- if (client.readyState === 1) { // WebSocket.OPEN
142
- client.send('reload');
143
- clientCount++;
321
+
322
+ function serveFile(filePath, ext, res, mimeTypes) {
323
+ const mimeType = mimeTypes[ext] || 'application/octet-stream';
324
+
325
+ try {
326
+ const content = fs.readFileSync(filePath);
327
+ res.setHeader('Content-Type', mimeType);
328
+ res.setHeader('Cache-Control', 'public, max-age=3600');
329
+ res.end(content);
330
+ } catch (err) {
331
+ res.statusCode = 500;
332
+ res.end(`Error reading file: ${err.message}`);
144
333
  }
334
+ }
335
+
336
+ // WebSocket Server (Live Reload)
337
+ const wss = new WebSocketServer({ server });
338
+
339
+ wss.on('connection', (ws) => {
340
+ console.log('[gsd-reader] Client connected');
341
+
342
+ ws.on('close', () => {
343
+ console.log('[gsd-reader] Client disconnected');
344
+ });
145
345
  });
146
- if (clientCount > 0) {
147
- console.log(`[gsd-reader] Notified ${clientCount} client(s)`);
346
+
347
+ function broadcastReload() {
348
+ let clientCount = 0;
349
+ wss.clients.forEach((client) => {
350
+ if (client.readyState === 1) { // WebSocket.OPEN
351
+ client.send('reload');
352
+ clientCount++;
353
+ }
354
+ });
355
+ if (clientCount > 0) {
356
+ console.log(`[gsd-reader] Notified ${clientCount} client(s)`);
357
+ }
148
358
  }
149
- }
150
359
 
151
- // =============================================================================
152
- // File Watcher (Chokidar)
153
- // =============================================================================
360
+ // Check if worklog exists before starting
361
+ if (!fs.existsSync(WORKLOG_PATH)) {
362
+ console.error(`\n❌ WORK.md not found: ${WORKLOG_PATH}`);
363
+ console.error('\nUsage: npx @luutuankiet/gsd-reader [serve] [path] [--port=3000]');
364
+ console.error('\nExamples:');
365
+ console.error(' npx @luutuankiet/gsd-reader # Watch ./gsd-lite/WORK.md');
366
+ console.error(' npx @luutuankiet/gsd-reader ./my-project/WORK.md # Custom path');
367
+ process.exit(1);
368
+ }
154
369
 
155
- // Check if worklog exists before starting
156
- if (!fs.existsSync(WORKLOG_PATH)) {
157
- console.error(`\n❌ WORK.md not found: ${WORKLOG_PATH}`);
158
- console.error('\nUsage: npx @gsd-lite/reader [path-to-worklog] [--port=3000]');
159
- console.error('\nExamples:');
160
- console.error(' npx @gsd-lite/reader # Watch ./gsd-lite/WORK.md');
161
- console.error(' npx @gsd-lite/reader ./my-project/WORK.md # Custom path');
162
- process.exit(1);
163
- }
370
+ // Watch the worklog file
371
+ const watcher = chokidar.watch(WORKLOG_PATH, {
372
+ persistent: true,
373
+ ignoreInitial: true,
374
+ awaitWriteFinish: {
375
+ stabilityThreshold: 100,
376
+ pollInterval: 50,
377
+ },
378
+ });
379
+
380
+ watcher.on('change', (filepath) => {
381
+ console.log(`[gsd-reader] ${path.basename(filepath)} changed`);
382
+ broadcastReload();
383
+ });
384
+
385
+ watcher.on('error', (error) => {
386
+ console.error('[gsd-reader] Watcher error:', error.message);
387
+ });
388
+
389
+ // Startup
390
+ server.listen(PORT, () => {
391
+ console.log('');
392
+ console.log('┌─────────────────────────────────────────────────────┐');
393
+ console.log('│ 📖 GSD-Lite Worklog Reader │');
394
+ console.log('├─────────────────────────────────────────────────────┤');
395
+ console.log(`│ Server: http://localhost:${PORT.toString().padEnd(25)}│`);
396
+ console.log(`│ Watching: ${path.basename(WORKLOG_PATH).padEnd(40)}│`);
397
+ console.log('├─────────────────────────────────────────────────────┤');
398
+ console.log('│ Press Ctrl+C to stop │');
399
+ console.log('└─────────────────────────────────────────────────────┘');
400
+ console.log('');
401
+ console.log(`[gsd-reader] Full path: ${WORKLOG_PATH}`);
402
+ });
164
403
 
165
- // Watch the worklog file
166
- const watcher = chokidar.watch(WORKLOG_PATH, {
167
- persistent: true,
168
- ignoreInitial: true,
169
- awaitWriteFinish: {
170
- stabilityThreshold: 100,
171
- pollInterval: 50,
172
- },
173
- });
174
-
175
- watcher.on('change', (filepath) => {
176
- console.log(`[gsd-reader] ${path.basename(filepath)} changed`);
177
- broadcastReload();
178
- });
179
-
180
- watcher.on('error', (error) => {
181
- console.error('[gsd-reader] Watcher error:', error.message);
182
- });
404
+ // Graceful shutdown
405
+ process.on('SIGINT', () => {
406
+ console.log('\n[gsd-reader] Shutting down...');
407
+ watcher.close();
408
+ wss.close();
409
+ server.close(() => {
410
+ console.log('[gsd-reader] Goodbye!');
411
+ process.exit(0);
412
+ });
413
+ });
414
+
415
+ process.on('SIGTERM', () => {
416
+ process.emit('SIGINT');
417
+ });
418
+ }
183
419
 
184
420
  // =============================================================================
185
- // Startup
421
+ // Main
186
422
  // =============================================================================
187
423
 
188
- server.listen(PORT, () => {
189
- console.log('');
190
- console.log('┌─────────────────────────────────────────────────────┐');
191
- console.log('│ 📖 GSD-Lite Worklog Reader │');
192
- console.log('├─────────────────────────────────────────────────────┤');
193
- console.log(`│ Server: http://localhost:${PORT.toString().padEnd(25)}│`);
194
- console.log(`│ Watching: ${path.basename(WORKLOG_PATH).padEnd(40)}│`);
195
- console.log('├─────────────────────────────────────────────────────┤');
196
- console.log('│ Press Ctrl+C to stop │');
197
- console.log('└─────────────────────────────────────────────────────┘');
198
- console.log('');
199
- console.log(`[gsd-reader] Full path: ${WORKLOG_PATH}`);
200
- });
201
-
202
- // Graceful shutdown
203
- process.on('SIGINT', () => {
204
- console.log('\n[gsd-reader] Shutting down...');
205
- watcher.close();
206
- wss.close();
207
- server.close(() => {
208
- console.log('[gsd-reader] Goodbye!');
209
- process.exit(0);
424
+ if (command === 'dump') {
425
+ commandDump().catch((err) => {
426
+ console.error('❌ Unexpected error:', err.message);
427
+ process.exit(1);
210
428
  });
211
- });
429
+ } else if (command === 'serve' || command === 'help' || command === '--help' || command === '-h') {
430
+ if (command === 'help' || command === '--help' || command === '-h') {
431
+ console.log(`
432
+ 📖 GSD-Lite Worklog Reader
433
+
434
+ Commands:
435
+ serve [path] [--port=3000] Start live-reload server (default)
436
+ dump [path] --remote=URL Build and upload to remote server
212
437
 
213
- process.on('SIGTERM', () => {
214
- process.emit('SIGINT');
215
- });
438
+ Examples:
439
+ npx @luutuankiet/gsd-reader # Serve ./gsd-lite/WORK.md
440
+ npx @luutuankiet/gsd-reader serve ./project/WORK.md # Serve custom path
441
+ npx @luutuankiet/gsd-reader dump --remote=https://gsd.kenluu.org --user=ken
442
+ `);
443
+ process.exit(0);
444
+ }
445
+ commandServe();
446
+ } else {
447
+ // Assume it's a path, not a command
448
+ commandServe();
449
+ }
@@ -1 +1 @@
1
- import{aU as L,bq as ln,aE as A,aS as P,aD as z,br as gn,bs as dn,bt as hn,bu as W,bv as pn,bl as An,bw as m,aV as N,a_ as U,b1 as T,bx as _n,aY as on,by as wn,bo as On,aF as V,bm as vn,bz as I}from"./mermaid.core-CWefC7Oh.js";var Pn="[object Symbol]";function x(n){return typeof n=="symbol"||L(n)&&ln(n)==Pn}function yn(n,r){for(var e=-1,i=n==null?0:n.length,f=Array(i);++e<i;)f[e]=r(n[e],e,n);return f}var B=P?P.prototype:void 0,K=B?B.toString:void 0;function k(n){if(typeof n=="string")return n;if(A(n))return yn(n,k)+"";if(x(n))return K?K.call(n):"";var r=n+"";return r=="0"&&1/n==-1/0?"-0":r}function En(){}function bn(n,r){for(var e=-1,i=n==null?0:n.length;++e<i&&r(n[e],e,n)!==!1;);return n}function cn(n,r,e,i){for(var f=n.length,t=e+-1;++t<f;)if(r(n[t],t,n))return t;return-1}function Tn(n){return n!==n}function Rn(n,r,e){for(var i=e-1,f=n.length;++i<f;)if(n[i]===r)return i;return-1}function In(n,r,e){return r===r?Rn(n,r,e):cn(n,Tn,e)}function Sn(n,r){var e=n==null?0:n.length;return!!e&&In(n,r,0)>-1}function M(n){return z(n)?gn(n):dn(n)}var Ln=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,xn=/^\w*$/;function $(n,r){if(A(n))return!1;var e=typeof n;return e=="number"||e=="symbol"||e=="boolean"||n==null||x(n)?!0:xn.test(n)||!Ln.test(n)||r!=null&&n in Object(r)}var Mn=500;function $n(n){var r=hn(n,function(i){return e.size===Mn&&e.clear(),i}),e=r.cache;return r}var Cn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,Dn=/\\(\\)?/g,Fn=$n(function(n){var r=[];return n.charCodeAt(0)===46&&r.push(""),n.replace(Cn,function(e,i,f,t){r.push(f?t.replace(Dn,"$1"):i||e)}),r});function Gn(n){return n==null?"":k(n)}function j(n,r){return A(n)?n:$(n,r)?[n]:Fn(Gn(n))}function R(n){if(typeof n=="string"||x(n))return n;var r=n+"";return r=="0"&&1/n==-1/0?"-0":r}function nn(n,r){r=j(r,n);for(var e=0,i=r.length;n!=null&&e<i;)n=n[R(r[e++])];return e&&e==i?n:void 0}function mn(n,r,e){var i=n==null?void 0:nn(n,r);return i===void 0?e:i}function rn(n,r){for(var e=-1,i=r.length,f=n.length;++e<i;)n[f+e]=r[e];return n}var H=P?P.isConcatSpreadable:void 0;function Nn(n){return A(n)||W(n)||!!(H&&n&&n[H])}function Hr(n,r,e,i,f){var t=-1,s=n.length;for(e||(e=Nn),f||(f=[]);++t<s;){var u=n[t];e(u)?rn(f,u):i||(f[f.length]=u)}return f}function Un(n,r,e,i){var f=-1,t=n==null?0:n.length;for(i&&t&&(e=n[++f]);++f<t;)e=r(e,n[f],f,n);return e}function en(n,r){for(var e=-1,i=n==null?0:n.length,f=0,t=[];++e<i;){var s=n[e];r(s,e,n)&&(t[f++]=s)}return t}function Bn(){return[]}var Kn=Object.prototype,Hn=Kn.propertyIsEnumerable,q=Object.getOwnPropertySymbols,qn=q?function(n){return n==null?[]:(n=Object(n),en(q(n),function(r){return Hn.call(n,r)}))}:Bn;function Yn(n,r,e){var i=r(n);return A(n)?i:rn(i,e(n))}function Y(n){return Yn(n,M,qn)}var Zn="__lodash_hash_undefined__";function Xn(n){return this.__data__.set(n,Zn),this}function Jn(n){return this.__data__.has(n)}function y(n){var r=-1,e=n==null?0:n.length;for(this.__data__=new pn;++r<e;)this.add(n[r])}y.prototype.add=y.prototype.push=Xn;y.prototype.has=Jn;function Qn(n,r){for(var e=-1,i=n==null?0:n.length;++e<i;)if(r(n[e],e,n))return!0;return!1}function tn(n,r){return n.has(r)}var zn=1,Wn=2;function fn(n,r,e,i,f,t){var s=e&zn,u=n.length,a=r.length;if(u!=a&&!(s&&a>u))return!1;var h=t.get(n),g=t.get(r);if(h&&g)return h==r&&g==n;var l=-1,d=!0,o=e&Wn?new y:void 0;for(t.set(n,r),t.set(r,n);++l<u;){var p=n[l],_=r[l];if(i)var w=s?i(_,p,l,r,n,t):i(p,_,l,n,r,t);if(w!==void 0){if(w)continue;d=!1;break}if(o){if(!Qn(r,function(O,v){if(!tn(o,v)&&(p===O||f(p,O,e,i,t)))return o.push(v)})){d=!1;break}}else if(!(p===_||f(p,_,e,i,t))){d=!1;break}}return t.delete(n),t.delete(r),d}function Vn(n){var r=-1,e=Array(n.size);return n.forEach(function(i,f){e[++r]=[f,i]}),e}function C(n){var r=-1,e=Array(n.size);return n.forEach(function(i){e[++r]=i}),e}var kn=1,jn=2,nr="[object Boolean]",rr="[object Date]",er="[object Error]",ir="[object Map]",tr="[object Number]",fr="[object RegExp]",sr="[object Set]",ur="[object String]",ar="[object Symbol]",lr="[object ArrayBuffer]",gr="[object DataView]",Z=P?P.prototype:void 0,S=Z?Z.valueOf:void 0;function dr(n,r,e,i,f,t,s){switch(e){case gr:if(n.byteLength!=r.byteLength||n.byteOffset!=r.byteOffset)return!1;n=n.buffer,r=r.buffer;case lr:return!(n.byteLength!=r.byteLength||!t(new m(n),new m(r)));case nr:case rr:case tr:return An(+n,+r);case er:return n.name==r.name&&n.message==r.message;case fr:case ur:return n==r+"";case ir:var u=Vn;case sr:var a=i&kn;if(u||(u=C),n.size!=r.size&&!a)return!1;var h=s.get(n);if(h)return h==r;i|=jn,s.set(n,r);var g=fn(u(n),u(r),i,f,t,s);return s.delete(n),g;case ar:if(S)return S.call(n)==S.call(r)}return!1}var hr=1,pr=Object.prototype,Ar=pr.hasOwnProperty;function _r(n,r,e,i,f,t){var s=e&hr,u=Y(n),a=u.length,h=Y(r),g=h.length;if(a!=g&&!s)return!1;for(var l=a;l--;){var d=u[l];if(!(s?d in r:Ar.call(r,d)))return!1}var o=t.get(n),p=t.get(r);if(o&&p)return o==r&&p==n;var _=!0;t.set(n,r),t.set(r,n);for(var w=s;++l<a;){d=u[l];var O=n[d],v=r[d];if(i)var G=s?i(v,O,d,r,n,t):i(O,v,d,n,r,t);if(!(G===void 0?O===v||f(O,v,e,i,t):G)){_=!1;break}w||(w=d=="constructor")}if(_&&!w){var E=n.constructor,b=r.constructor;E!=b&&"constructor"in n&&"constructor"in r&&!(typeof E=="function"&&E instanceof E&&typeof b=="function"&&b instanceof b)&&(_=!1)}return t.delete(n),t.delete(r),_}var or=1,X="[object Arguments]",J="[object Array]",c="[object Object]",wr=Object.prototype,Q=wr.hasOwnProperty;function Or(n,r,e,i,f,t){var s=A(n),u=A(r),a=s?J:N(n),h=u?J:N(r);a=a==X?c:a,h=h==X?c:h;var g=a==c,l=h==c,d=a==h;if(d&&U(n)){if(!U(r))return!1;s=!0,g=!1}if(d&&!g)return t||(t=new T),s||_n(n)?fn(n,r,e,i,f,t):dr(n,r,a,e,i,f,t);if(!(e&or)){var o=g&&Q.call(n,"__wrapped__"),p=l&&Q.call(r,"__wrapped__");if(o||p){var _=o?n.value():n,w=p?r.value():r;return t||(t=new T),f(_,w,e,i,t)}}return d?(t||(t=new T),_r(n,r,e,i,f,t)):!1}function D(n,r,e,i,f){return n===r?!0:n==null||r==null||!L(n)&&!L(r)?n!==n&&r!==r:Or(n,r,e,i,D,f)}var vr=1,Pr=2;function yr(n,r,e,i){var f=e.length,t=f;if(n==null)return!t;for(n=Object(n);f--;){var s=e[f];if(s[2]?s[1]!==n[s[0]]:!(s[0]in n))return!1}for(;++f<t;){s=e[f];var u=s[0],a=n[u],h=s[1];if(s[2]){if(a===void 0&&!(u in n))return!1}else{var g=new T,l;if(!(l===void 0?D(h,a,vr|Pr,i,g):l))return!1}}return!0}function sn(n){return n===n&&!on(n)}function Er(n){for(var r=M(n),e=r.length;e--;){var i=r[e],f=n[i];r[e]=[i,f,sn(f)]}return r}function un(n,r){return function(e){return e==null?!1:e[n]===r&&(r!==void 0||n in Object(e))}}function br(n){var r=Er(n);return r.length==1&&r[0][2]?un(r[0][0],r[0][1]):function(e){return e===n||yr(e,n,r)}}function cr(n,r){return n!=null&&r in Object(n)}function Tr(n,r,e){r=j(r,n);for(var i=-1,f=r.length,t=!1;++i<f;){var s=R(r[i]);if(!(t=n!=null&&e(n,s)))break;n=n[s]}return t||++i!=f?t:(f=n==null?0:n.length,!!f&&wn(f)&&On(s,f)&&(A(n)||W(n)))}function Rr(n,r){return n!=null&&Tr(n,r,cr)}var Ir=1,Sr=2;function Lr(n,r){return $(n)&&sn(r)?un(R(n),r):function(e){var i=mn(e,n);return i===void 0&&i===r?Rr(e,n):D(r,i,Ir|Sr)}}function xr(n){return function(r){return r==null?void 0:r[n]}}function Mr(n){return function(r){return nn(r,n)}}function $r(n){return $(n)?xr(R(n)):Mr(n)}function an(n){return typeof n=="function"?n:n==null?V:typeof n=="object"?A(n)?Lr(n[0],n[1]):br(n):$r(n)}function Cr(n,r){return n&&vn(n,r,M)}function Dr(n,r){return function(e,i){if(e==null)return e;if(!z(e))return n(e,i);for(var f=e.length,t=-1,s=Object(e);++t<f&&i(s[t],t,s)!==!1;);return e}}var F=Dr(Cr);function Fr(n){return typeof n=="function"?n:V}function qr(n,r){var e=A(n)?bn:F;return e(n,Fr(r))}function Gr(n,r){var e=[];return F(n,function(i,f,t){r(i,f,t)&&e.push(i)}),e}function Yr(n,r){var e=A(n)?en:Gr;return e(n,an(r))}function mr(n,r,e,i,f){return f(n,function(t,s,u){e=i?(i=!1,t):r(e,t,s,u)}),e}function Zr(n,r,e){var i=A(n)?Un:mr,f=arguments.length<3;return i(n,an(r),e,f,F)}var Nr=1/0,Ur=I&&1/C(new I([,-0]))[1]==Nr?function(n){return new I(n)}:En,Br=200;function Xr(n,r,e){var i=-1,f=Sn,t=n.length,s=!0,u=[],a=u;if(t>=Br){var h=r?null:Ur(n);if(h)return C(h);s=!1,f=tn,a=new y}else a=r?[]:u;n:for(;++i<t;){var g=n[i],l=r?r(g):g;if(g=g!==0?g:0,s&&l===l){for(var d=a.length;d--;)if(a[d]===l)continue n;r&&a.push(l),u.push(g)}else f(a,l,e)||(a!==u&&a.push(l),u.push(g))}return u}export{F as a,Hr as b,an as c,yn as d,rn as e,Yn as f,qn as g,bn as h,x as i,Y as j,M as k,Xr as l,Yr as m,qr as n,cn as o,Fr as p,Cr as q,Zr as r,Bn as s,Tr as t,j as u,R as v,nn as w,Rr as x,Gn as y};
1
+ import{aU as L,bq as ln,aE as A,aS as P,aD as z,br as gn,bs as dn,bt as hn,bu as W,bv as pn,bl as An,bw as m,aV as N,a_ as U,b1 as T,bx as _n,aY as on,by as wn,bo as On,aF as V,bm as vn,bz as I}from"./mermaid.core-DktP_MzF.js";var Pn="[object Symbol]";function x(n){return typeof n=="symbol"||L(n)&&ln(n)==Pn}function yn(n,r){for(var e=-1,i=n==null?0:n.length,f=Array(i);++e<i;)f[e]=r(n[e],e,n);return f}var B=P?P.prototype:void 0,K=B?B.toString:void 0;function k(n){if(typeof n=="string")return n;if(A(n))return yn(n,k)+"";if(x(n))return K?K.call(n):"";var r=n+"";return r=="0"&&1/n==-1/0?"-0":r}function En(){}function bn(n,r){for(var e=-1,i=n==null?0:n.length;++e<i&&r(n[e],e,n)!==!1;);return n}function cn(n,r,e,i){for(var f=n.length,t=e+-1;++t<f;)if(r(n[t],t,n))return t;return-1}function Tn(n){return n!==n}function Rn(n,r,e){for(var i=e-1,f=n.length;++i<f;)if(n[i]===r)return i;return-1}function In(n,r,e){return r===r?Rn(n,r,e):cn(n,Tn,e)}function Sn(n,r){var e=n==null?0:n.length;return!!e&&In(n,r,0)>-1}function M(n){return z(n)?gn(n):dn(n)}var Ln=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,xn=/^\w*$/;function $(n,r){if(A(n))return!1;var e=typeof n;return e=="number"||e=="symbol"||e=="boolean"||n==null||x(n)?!0:xn.test(n)||!Ln.test(n)||r!=null&&n in Object(r)}var Mn=500;function $n(n){var r=hn(n,function(i){return e.size===Mn&&e.clear(),i}),e=r.cache;return r}var Cn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,Dn=/\\(\\)?/g,Fn=$n(function(n){var r=[];return n.charCodeAt(0)===46&&r.push(""),n.replace(Cn,function(e,i,f,t){r.push(f?t.replace(Dn,"$1"):i||e)}),r});function Gn(n){return n==null?"":k(n)}function j(n,r){return A(n)?n:$(n,r)?[n]:Fn(Gn(n))}function R(n){if(typeof n=="string"||x(n))return n;var r=n+"";return r=="0"&&1/n==-1/0?"-0":r}function nn(n,r){r=j(r,n);for(var e=0,i=r.length;n!=null&&e<i;)n=n[R(r[e++])];return e&&e==i?n:void 0}function mn(n,r,e){var i=n==null?void 0:nn(n,r);return i===void 0?e:i}function rn(n,r){for(var e=-1,i=r.length,f=n.length;++e<i;)n[f+e]=r[e];return n}var H=P?P.isConcatSpreadable:void 0;function Nn(n){return A(n)||W(n)||!!(H&&n&&n[H])}function Hr(n,r,e,i,f){var t=-1,s=n.length;for(e||(e=Nn),f||(f=[]);++t<s;){var u=n[t];e(u)?rn(f,u):i||(f[f.length]=u)}return f}function Un(n,r,e,i){var f=-1,t=n==null?0:n.length;for(i&&t&&(e=n[++f]);++f<t;)e=r(e,n[f],f,n);return e}function en(n,r){for(var e=-1,i=n==null?0:n.length,f=0,t=[];++e<i;){var s=n[e];r(s,e,n)&&(t[f++]=s)}return t}function Bn(){return[]}var Kn=Object.prototype,Hn=Kn.propertyIsEnumerable,q=Object.getOwnPropertySymbols,qn=q?function(n){return n==null?[]:(n=Object(n),en(q(n),function(r){return Hn.call(n,r)}))}:Bn;function Yn(n,r,e){var i=r(n);return A(n)?i:rn(i,e(n))}function Y(n){return Yn(n,M,qn)}var Zn="__lodash_hash_undefined__";function Xn(n){return this.__data__.set(n,Zn),this}function Jn(n){return this.__data__.has(n)}function y(n){var r=-1,e=n==null?0:n.length;for(this.__data__=new pn;++r<e;)this.add(n[r])}y.prototype.add=y.prototype.push=Xn;y.prototype.has=Jn;function Qn(n,r){for(var e=-1,i=n==null?0:n.length;++e<i;)if(r(n[e],e,n))return!0;return!1}function tn(n,r){return n.has(r)}var zn=1,Wn=2;function fn(n,r,e,i,f,t){var s=e&zn,u=n.length,a=r.length;if(u!=a&&!(s&&a>u))return!1;var h=t.get(n),g=t.get(r);if(h&&g)return h==r&&g==n;var l=-1,d=!0,o=e&Wn?new y:void 0;for(t.set(n,r),t.set(r,n);++l<u;){var p=n[l],_=r[l];if(i)var w=s?i(_,p,l,r,n,t):i(p,_,l,n,r,t);if(w!==void 0){if(w)continue;d=!1;break}if(o){if(!Qn(r,function(O,v){if(!tn(o,v)&&(p===O||f(p,O,e,i,t)))return o.push(v)})){d=!1;break}}else if(!(p===_||f(p,_,e,i,t))){d=!1;break}}return t.delete(n),t.delete(r),d}function Vn(n){var r=-1,e=Array(n.size);return n.forEach(function(i,f){e[++r]=[f,i]}),e}function C(n){var r=-1,e=Array(n.size);return n.forEach(function(i){e[++r]=i}),e}var kn=1,jn=2,nr="[object Boolean]",rr="[object Date]",er="[object Error]",ir="[object Map]",tr="[object Number]",fr="[object RegExp]",sr="[object Set]",ur="[object String]",ar="[object Symbol]",lr="[object ArrayBuffer]",gr="[object DataView]",Z=P?P.prototype:void 0,S=Z?Z.valueOf:void 0;function dr(n,r,e,i,f,t,s){switch(e){case gr:if(n.byteLength!=r.byteLength||n.byteOffset!=r.byteOffset)return!1;n=n.buffer,r=r.buffer;case lr:return!(n.byteLength!=r.byteLength||!t(new m(n),new m(r)));case nr:case rr:case tr:return An(+n,+r);case er:return n.name==r.name&&n.message==r.message;case fr:case ur:return n==r+"";case ir:var u=Vn;case sr:var a=i&kn;if(u||(u=C),n.size!=r.size&&!a)return!1;var h=s.get(n);if(h)return h==r;i|=jn,s.set(n,r);var g=fn(u(n),u(r),i,f,t,s);return s.delete(n),g;case ar:if(S)return S.call(n)==S.call(r)}return!1}var hr=1,pr=Object.prototype,Ar=pr.hasOwnProperty;function _r(n,r,e,i,f,t){var s=e&hr,u=Y(n),a=u.length,h=Y(r),g=h.length;if(a!=g&&!s)return!1;for(var l=a;l--;){var d=u[l];if(!(s?d in r:Ar.call(r,d)))return!1}var o=t.get(n),p=t.get(r);if(o&&p)return o==r&&p==n;var _=!0;t.set(n,r),t.set(r,n);for(var w=s;++l<a;){d=u[l];var O=n[d],v=r[d];if(i)var G=s?i(v,O,d,r,n,t):i(O,v,d,n,r,t);if(!(G===void 0?O===v||f(O,v,e,i,t):G)){_=!1;break}w||(w=d=="constructor")}if(_&&!w){var E=n.constructor,b=r.constructor;E!=b&&"constructor"in n&&"constructor"in r&&!(typeof E=="function"&&E instanceof E&&typeof b=="function"&&b instanceof b)&&(_=!1)}return t.delete(n),t.delete(r),_}var or=1,X="[object Arguments]",J="[object Array]",c="[object Object]",wr=Object.prototype,Q=wr.hasOwnProperty;function Or(n,r,e,i,f,t){var s=A(n),u=A(r),a=s?J:N(n),h=u?J:N(r);a=a==X?c:a,h=h==X?c:h;var g=a==c,l=h==c,d=a==h;if(d&&U(n)){if(!U(r))return!1;s=!0,g=!1}if(d&&!g)return t||(t=new T),s||_n(n)?fn(n,r,e,i,f,t):dr(n,r,a,e,i,f,t);if(!(e&or)){var o=g&&Q.call(n,"__wrapped__"),p=l&&Q.call(r,"__wrapped__");if(o||p){var _=o?n.value():n,w=p?r.value():r;return t||(t=new T),f(_,w,e,i,t)}}return d?(t||(t=new T),_r(n,r,e,i,f,t)):!1}function D(n,r,e,i,f){return n===r?!0:n==null||r==null||!L(n)&&!L(r)?n!==n&&r!==r:Or(n,r,e,i,D,f)}var vr=1,Pr=2;function yr(n,r,e,i){var f=e.length,t=f;if(n==null)return!t;for(n=Object(n);f--;){var s=e[f];if(s[2]?s[1]!==n[s[0]]:!(s[0]in n))return!1}for(;++f<t;){s=e[f];var u=s[0],a=n[u],h=s[1];if(s[2]){if(a===void 0&&!(u in n))return!1}else{var g=new T,l;if(!(l===void 0?D(h,a,vr|Pr,i,g):l))return!1}}return!0}function sn(n){return n===n&&!on(n)}function Er(n){for(var r=M(n),e=r.length;e--;){var i=r[e],f=n[i];r[e]=[i,f,sn(f)]}return r}function un(n,r){return function(e){return e==null?!1:e[n]===r&&(r!==void 0||n in Object(e))}}function br(n){var r=Er(n);return r.length==1&&r[0][2]?un(r[0][0],r[0][1]):function(e){return e===n||yr(e,n,r)}}function cr(n,r){return n!=null&&r in Object(n)}function Tr(n,r,e){r=j(r,n);for(var i=-1,f=r.length,t=!1;++i<f;){var s=R(r[i]);if(!(t=n!=null&&e(n,s)))break;n=n[s]}return t||++i!=f?t:(f=n==null?0:n.length,!!f&&wn(f)&&On(s,f)&&(A(n)||W(n)))}function Rr(n,r){return n!=null&&Tr(n,r,cr)}var Ir=1,Sr=2;function Lr(n,r){return $(n)&&sn(r)?un(R(n),r):function(e){var i=mn(e,n);return i===void 0&&i===r?Rr(e,n):D(r,i,Ir|Sr)}}function xr(n){return function(r){return r==null?void 0:r[n]}}function Mr(n){return function(r){return nn(r,n)}}function $r(n){return $(n)?xr(R(n)):Mr(n)}function an(n){return typeof n=="function"?n:n==null?V:typeof n=="object"?A(n)?Lr(n[0],n[1]):br(n):$r(n)}function Cr(n,r){return n&&vn(n,r,M)}function Dr(n,r){return function(e,i){if(e==null)return e;if(!z(e))return n(e,i);for(var f=e.length,t=-1,s=Object(e);++t<f&&i(s[t],t,s)!==!1;);return e}}var F=Dr(Cr);function Fr(n){return typeof n=="function"?n:V}function qr(n,r){var e=A(n)?bn:F;return e(n,Fr(r))}function Gr(n,r){var e=[];return F(n,function(i,f,t){r(i,f,t)&&e.push(i)}),e}function Yr(n,r){var e=A(n)?en:Gr;return e(n,an(r))}function mr(n,r,e,i,f){return f(n,function(t,s,u){e=i?(i=!1,t):r(e,t,s,u)}),e}function Zr(n,r,e){var i=A(n)?Un:mr,f=arguments.length<3;return i(n,an(r),e,f,F)}var Nr=1/0,Ur=I&&1/C(new I([,-0]))[1]==Nr?function(n){return new I(n)}:En,Br=200;function Xr(n,r,e){var i=-1,f=Sn,t=n.length,s=!0,u=[],a=u;if(t>=Br){var h=r?null:Ur(n);if(h)return C(h);s=!1,f=tn,a=new y}else a=r?[]:u;n:for(;++i<t;){var g=n[i],l=r?r(g):g;if(g=g!==0?g:0,s&&l===l){for(var d=a.length;d--;)if(a[d]===l)continue n;r&&a.push(l),u.push(g)}else f(a,l,e)||(a!==u&&a.push(l),u.push(g))}return u}export{F as a,Hr as b,an as c,yn as d,rn as e,Yn as f,qn as g,bn as h,x as i,Y as j,M as k,Xr as l,Yr as m,qr as n,cn as o,Fr as p,Cr as q,Zr as r,Bn as s,Tr as t,j as u,R as v,nn as w,Rr as x,Gn as y};