@shahadpichen/docpush 1.0.4 → 1.0.6

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.
@@ -1 +1 @@
1
- {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/add.ts"],"names":[],"mappings":"AAmCA;;GAEG;AACH,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA6HpE"}
1
+ {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/add.ts"],"names":[],"mappings":"AAmCA;;GAEG;AACH,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAyGpE"}
@@ -17,11 +17,11 @@ const COMPONENTS = {
17
17
  card: { files: ['card.tsx'], dependencies: ['utils'] },
18
18
  'scroll-area': { files: ['scroll-area.tsx'], dependencies: ['utils'] },
19
19
  // Feature components
20
- 'docs-sidebar': { files: ['docs-sidebar.tsx'], dependencies: ['utils', 'scroll-area'] },
20
+ 'docs-sidebar': { files: ['docs-sidebar.tsx'], dependencies: ['utils', 'button', 'scroll-area'] },
21
21
  'markdown-viewer': { files: ['markdown-viewer.tsx'], dependencies: ['utils'] },
22
22
  'markdown-editor': {
23
23
  files: ['markdown-editor.tsx'],
24
- dependencies: ['utils', 'button', 'textarea'],
24
+ dependencies: ['utils', 'button', 'textarea', 'markdown-viewer'],
25
25
  },
26
26
  'comments-panel': {
27
27
  files: ['comments-panel.tsx'],
@@ -73,7 +73,6 @@ async function addCommand(components) {
73
73
  // Load config to get custom paths (if docs.config.js exists)
74
74
  let uiDir = './src/components/ui';
75
75
  let libDir = './src/lib';
76
- let aliasPrefix = '@';
77
76
  try {
78
77
  const configPath = node_path_1.default.resolve('./docs.config.js');
79
78
  if (await fs_extra_1.default.pathExists(configPath)) {
@@ -85,59 +84,43 @@ async function addCommand(components) {
85
84
  if (config.components?.libPath) {
86
85
  libDir = config.components.libPath;
87
86
  }
88
- if (config.components?.aliasPrefix) {
89
- aliasPrefix = config.components.aliasPrefix;
90
- }
91
87
  }
92
88
  }
93
- catch (e) {
89
+ catch {
94
90
  // Config doesn't exist or has errors, use defaults
95
91
  }
96
92
  console.log(chalk_1.default.gray(`šŸ“ UI components: ${uiDir}`));
97
93
  console.log(chalk_1.default.gray(`šŸ“ Utilities: ${libDir}\n`));
98
94
  await fs_extra_1.default.ensureDir(uiDir);
99
95
  await fs_extra_1.default.ensureDir(libDir);
100
- // Find package location
96
+ // Find package location for templates
101
97
  const packageDir = node_path_1.default.dirname(require.resolve('@shahadpichen/docpush/package.json'));
102
- const reactSrcDir = node_path_1.default.join(packageDir, 'dist', 'react');
98
+ const templatesDir = node_path_1.default.join(packageDir, 'templates', 'components');
103
99
  // Copy components
104
100
  for (const compName of toInstall) {
105
101
  const comp = COMPONENTS[compName];
106
102
  for (const file of comp.files) {
107
- let srcPath;
108
103
  let destPath;
109
104
  if (compName === 'utils') {
110
105
  // Utils go to src/lib
111
- srcPath = node_path_1.default.join(reactSrcDir, 'lib', file.replace('.ts', '.js'));
112
106
  destPath = node_path_1.default.join(libDir, file);
113
- // Write TypeScript source instead of compiled
114
- const tsContent = `import { clsx, type ClassValue } from 'clsx';
115
- import { twMerge } from 'tailwind-merge';
116
-
117
- export function cn(...inputs: ClassValue[]) {
118
- return twMerge(clsx(inputs));
119
- }
120
- `;
121
- await fs_extra_1.default.writeFile(destPath, tsContent);
122
- console.log(chalk_1.default.green('āœ“'), `Created ${destPath}`);
107
+ const content = getUtilsTemplate();
108
+ await fs_extra_1.default.writeFile(destPath, content);
123
109
  }
124
110
  else {
125
- // Determine source path based on component type
126
- const isUiComponent = [
127
- 'button',
128
- 'input',
129
- 'textarea',
130
- 'badge',
131
- 'card',
132
- 'scroll-area',
133
- ].includes(compName);
134
- const srcSubdir = isUiComponent ? 'components/ui' : 'components';
135
- // Get component template from package
136
- const template = getComponentTemplate(compName);
111
+ // Try to read from templates directory first
112
+ const templatePath = node_path_1.default.join(templatesDir, file);
137
113
  destPath = node_path_1.default.join(uiDir, file);
138
- await fs_extra_1.default.writeFile(destPath, template);
139
- console.log(chalk_1.default.green('āœ“'), `Created ${destPath}`);
114
+ if (await fs_extra_1.default.pathExists(templatePath)) {
115
+ await fs_extra_1.default.copy(templatePath, destPath);
116
+ }
117
+ else {
118
+ // Fallback to inline template
119
+ const template = getComponentTemplate(compName);
120
+ await fs_extra_1.default.writeFile(destPath, template);
121
+ }
140
122
  }
123
+ console.log(chalk_1.default.green('āœ“'), `Created ${destPath}`);
141
124
  }
142
125
  }
143
126
  console.log(chalk_1.default.blue('\n✨ Components added successfully!'));
@@ -149,18 +132,30 @@ export function cn(...inputs: ClassValue[]) {
149
132
  console.log(' npm install clsx tailwind-merge class-variance-authority');
150
133
  console.log(' npm install @radix-ui/react-scroll-area @radix-ui/react-slot');
151
134
  }
135
+ function getUtilsTemplate() {
136
+ return `import { clsx, type ClassValue } from 'clsx';
137
+ import { twMerge } from 'tailwind-merge';
138
+
139
+ export function cn(...inputs: ClassValue[]) {
140
+ return twMerge(clsx(inputs));
141
+ }
142
+ `;
143
+ }
152
144
  /**
153
- * Get component TypeScript template
145
+ * Get component TypeScript template (inline fallback)
154
146
  */
155
147
  function getComponentTemplate(name) {
148
+ // Basic templates - users can customize after copying
156
149
  const templates = {
157
- button: `import * as React from 'react';
150
+ button: `'use client';
151
+
152
+ import * as React from 'react';
158
153
  import { Slot } from '@radix-ui/react-slot';
159
154
  import { cva, type VariantProps } from 'class-variance-authority';
160
155
  import { cn } from '@/lib/utils';
161
156
 
162
157
  const buttonVariants = cva(
163
- 'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
158
+ 'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50',
164
159
  {
165
160
  variants: {
166
161
  variant: {
@@ -178,16 +173,11 @@ const buttonVariants = cva(
178
173
  icon: 'h-10 w-10',
179
174
  },
180
175
  },
181
- defaultVariants: {
182
- variant: 'default',
183
- size: 'default',
184
- },
176
+ defaultVariants: { variant: 'default', size: 'default' },
185
177
  }
186
178
  );
187
179
 
188
- export interface ButtonProps
189
- extends React.ButtonHTMLAttributes<HTMLButtonElement>,
190
- VariantProps<typeof buttonVariants> {
180
+ export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
191
181
  asChild?: boolean;
192
182
  }
193
183
 
@@ -201,7 +191,9 @@ Button.displayName = 'Button';
201
191
 
202
192
  export { Button, buttonVariants };
203
193
  `,
204
- input: `import * as React from 'react';
194
+ input: `'use client';
195
+
196
+ import * as React from 'react';
205
197
  import { cn } from '@/lib/utils';
206
198
 
207
199
  export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {}
@@ -211,7 +203,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(({ className, type,
211
203
  <input
212
204
  type={type}
213
205
  className={cn(
214
- 'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
206
+ 'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50',
215
207
  className
216
208
  )}
217
209
  ref={ref}
@@ -223,7 +215,9 @@ Input.displayName = 'Input';
223
215
 
224
216
  export { Input };
225
217
  `,
226
- textarea: `import * as React from 'react';
218
+ textarea: `'use client';
219
+
220
+ import * as React from 'react';
227
221
  import { cn } from '@/lib/utils';
228
222
 
229
223
  export interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
@@ -232,7 +226,7 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(({ classNa
232
226
  return (
233
227
  <textarea
234
228
  className={cn(
235
- 'flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
229
+ 'flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50',
236
230
  className
237
231
  )}
238
232
  ref={ref}
@@ -244,28 +238,26 @@ Textarea.displayName = 'Textarea';
244
238
 
245
239
  export { Textarea };
246
240
  `,
247
- badge: `import * as React from 'react';
241
+ badge: `'use client';
242
+
243
+ import * as React from 'react';
248
244
  import { cva, type VariantProps } from 'class-variance-authority';
249
245
  import { cn } from '@/lib/utils';
250
246
 
251
247
  const badgeVariants = cva(
252
- 'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
248
+ 'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors',
253
249
  {
254
250
  variants: {
255
251
  variant: {
256
- default: 'border-transparent bg-primary text-primary-foreground hover:bg-primary/80',
257
- secondary: 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
258
- destructive: 'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',
252
+ default: 'border-transparent bg-primary text-primary-foreground',
253
+ secondary: 'border-transparent bg-secondary text-secondary-foreground',
254
+ destructive: 'border-transparent bg-destructive text-destructive-foreground',
259
255
  outline: 'text-foreground',
260
- draft: 'border-transparent bg-yellow-100 text-yellow-800',
261
- pending: 'border-transparent bg-blue-100 text-blue-800',
262
- approved: 'border-transparent bg-green-100 text-green-800',
263
- rejected: 'border-transparent bg-red-100 text-red-800',
256
+ warning: 'border-transparent bg-yellow-100 text-yellow-800',
257
+ success: 'border-transparent bg-green-100 text-green-800',
264
258
  },
265
259
  },
266
- defaultVariants: {
267
- variant: 'default',
268
- },
260
+ defaultVariants: { variant: 'default' },
269
261
  }
270
262
  );
271
263
 
@@ -277,7 +269,9 @@ function Badge({ className, variant, ...props }: BadgeProps) {
277
269
 
278
270
  export { Badge, badgeVariants };
279
271
  `,
280
- card: `import * as React from 'react';
272
+ card: `'use client';
273
+
274
+ import * as React from 'react';
281
275
  import { cn } from '@/lib/utils';
282
276
 
283
277
  const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
@@ -288,9 +282,7 @@ const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElemen
288
282
  Card.displayName = 'Card';
289
283
 
290
284
  const CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
291
- ({ className, ...props }, ref) => (
292
- <div ref={ref} className={cn('flex flex-col space-y-1.5 p-6', className)} {...props} />
293
- )
285
+ ({ className, ...props }, ref) => <div ref={ref} className={cn('flex flex-col space-y-1.5 p-6', className)} {...props} />
294
286
  );
295
287
  CardHeader.displayName = 'CardHeader';
296
288
 
@@ -301,26 +293,12 @@ const CardTitle = React.forwardRef<HTMLHeadingElement, React.HTMLAttributes<HTML
301
293
  );
302
294
  CardTitle.displayName = 'CardTitle';
303
295
 
304
- const CardDescription = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(
305
- ({ className, ...props }, ref) => (
306
- <p ref={ref} className={cn('text-sm text-muted-foreground', className)} {...props} />
307
- )
308
- );
309
- CardDescription.displayName = 'CardDescription';
310
-
311
296
  const CardContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
312
297
  ({ className, ...props }, ref) => <div ref={ref} className={cn('p-6 pt-0', className)} {...props} />
313
298
  );
314
299
  CardContent.displayName = 'CardContent';
315
300
 
316
- const CardFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
317
- ({ className, ...props }, ref) => (
318
- <div ref={ref} className={cn('flex items-center p-6 pt-0', className)} {...props} />
319
- )
320
- );
321
- CardFooter.displayName = 'CardFooter';
322
-
323
- export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };
301
+ export { Card, CardHeader, CardTitle, CardContent };
324
302
  `,
325
303
  'scroll-area': `'use client';
326
304
 
@@ -333,38 +311,237 @@ const ScrollArea = React.forwardRef<
333
311
  React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
334
312
  >(({ className, children, ...props }, ref) => (
335
313
  <ScrollAreaPrimitive.Root ref={ref} className={cn('relative overflow-hidden', className)} {...props}>
336
- <ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
337
- {children}
338
- </ScrollAreaPrimitive.Viewport>
339
- <ScrollBar />
314
+ <ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">{children}</ScrollAreaPrimitive.Viewport>
315
+ <ScrollAreaPrimitive.ScrollAreaScrollbar
316
+ orientation="vertical"
317
+ className="flex touch-none select-none transition-colors h-full w-2.5 border-l border-l-transparent p-[1px]"
318
+ >
319
+ <ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
320
+ </ScrollAreaPrimitive.ScrollAreaScrollbar>
340
321
  <ScrollAreaPrimitive.Corner />
341
322
  </ScrollAreaPrimitive.Root>
342
323
  ));
343
- ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
344
-
345
- const ScrollBar = React.forwardRef<
346
- React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
347
- React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
348
- >(({ className, orientation = 'vertical', ...props }, ref) => (
349
- <ScrollAreaPrimitive.ScrollAreaScrollbar
350
- ref={ref}
351
- orientation={orientation}
352
- className={cn(
353
- 'flex touch-none select-none transition-colors',
354
- orientation === 'vertical' && 'h-full w-2.5 border-l border-l-transparent p-[1px]',
355
- orientation === 'horizontal' && 'h-2.5 flex-col border-t border-t-transparent p-[1px]',
356
- className
357
- )}
358
- {...props}
359
- >
360
- <ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
361
- </ScrollAreaPrimitive.ScrollAreaScrollbar>
362
- ));
363
- ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
324
+ ScrollArea.displayName = 'ScrollArea';
325
+
326
+ export { ScrollArea };
327
+ `,
328
+ 'docs-sidebar': `'use client';
329
+
330
+ import * as React from 'react';
331
+ import { cn } from '@/lib/utils';
332
+ import { Button } from '@/components/ui/button';
333
+ import { ScrollArea } from '@/components/ui/scroll-area';
334
+
335
+ interface DocTreeItem { path: string; type: 'file' | 'dir'; }
336
+ interface DocsSidebarProps { tree: DocTreeItem[]; activePath?: string; onSelect?: (path: string) => void; className?: string; }
337
+
338
+ export function DocsSidebar({ tree, activePath, onSelect, className }: DocsSidebarProps) {
339
+ return (
340
+ <ScrollArea className={cn('h-full w-64 border-r', className)}>
341
+ <div className="space-y-1 py-4 px-3">
342
+ {tree.filter(item => item.type === 'file').map((item) => {
343
+ const isActive = item.path === activePath;
344
+ const fileName = item.path.split('/').pop()?.replace('.md', '') || item.path;
345
+ return (
346
+ <Button
347
+ key={item.path}
348
+ variant={isActive ? 'secondary' : 'ghost'}
349
+ size="sm"
350
+ className={cn('w-full justify-start', isActive && 'bg-muted font-medium')}
351
+ onClick={() => onSelect?.(item.path)}
352
+ >
353
+ {fileName}
354
+ </Button>
355
+ );
356
+ })}
357
+ </div>
358
+ </ScrollArea>
359
+ );
360
+ }
361
+ `,
362
+ 'markdown-viewer': `'use client';
364
363
 
365
- export { ScrollArea, ScrollBar };
364
+ import * as React from 'react';
365
+ import { cn } from '@/lib/utils';
366
+
367
+ interface MarkdownViewerProps { content: string; className?: string; }
368
+
369
+ export function MarkdownViewer({ content, className }: MarkdownViewerProps) {
370
+ const html = React.useMemo(() => {
371
+ return content
372
+ .replace(/^### (.*$)/gim, '<h3 class="text-lg font-semibold mt-6 mb-2">$1</h3>')
373
+ .replace(/^## (.*$)/gim, '<h2 class="text-xl font-semibold mt-8 mb-3">$1</h2>')
374
+ .replace(/^# (.*$)/gim, '<h1 class="text-2xl font-bold mt-10 mb-4">$1</h1>')
375
+ .replace(/\\*\\*(.*?)\\*\\*/gim, '<strong>$1</strong>')
376
+ .replace(/\\*(.*?)\\*/gim, '<em>$1</em>')
377
+ .replace(/^- (.*$)/gim, '<li class="ml-4">$1</li>')
378
+ .replace(/\\n\\n/gim, '</p><p class="my-4">')
379
+ .replace(/\\n/gim, '<br>');
380
+ }, [content]);
381
+
382
+ return <article className={cn('prose max-w-none p-6', className)} dangerouslySetInnerHTML={{ __html: '<p>' + html + '</p>' }} />;
383
+ }
384
+ `,
385
+ 'markdown-editor': `'use client';
386
+
387
+ import * as React from 'react';
388
+ import { cn } from '@/lib/utils';
389
+ import { MarkdownViewer } from '@/components/ui/markdown-viewer';
390
+ import { Button } from '@/components/ui/button';
391
+ import { Textarea } from '@/components/ui/textarea';
392
+
393
+ interface MarkdownEditorProps { initialContent?: string; onSave?: (content: string) => void; className?: string; }
394
+
395
+ export function MarkdownEditor({ initialContent = '', onSave, className }: MarkdownEditorProps) {
396
+ const [content, setContent] = React.useState(initialContent);
397
+ const [showPreview, setShowPreview] = React.useState(false);
398
+
399
+ return (
400
+ <div className={cn('flex flex-col', className)}>
401
+ <div className="flex items-center gap-2 border-b p-2">
402
+ <Button variant={showPreview ? 'ghost' : 'secondary'} size="sm" onClick={() => setShowPreview(false)}>Edit</Button>
403
+ <Button variant={showPreview ? 'secondary' : 'ghost'} size="sm" onClick={() => setShowPreview(true)}>Preview</Button>
404
+ {onSave && <Button size="sm" className="ml-auto" onClick={() => onSave(content)}>Save</Button>}
405
+ </div>
406
+ <div className="flex-1 overflow-auto">
407
+ {showPreview ? <MarkdownViewer content={content} /> : (
408
+ <Textarea value={content} onChange={(e) => setContent(e.target.value)} className="min-h-[400px] resize-none border-0 font-mono" placeholder="Write markdown..." />
409
+ )}
410
+ </div>
411
+ </div>
412
+ );
413
+ }
414
+ `,
415
+ 'comments-panel': `'use client';
416
+
417
+ import * as React from 'react';
418
+ import { cn } from '@/lib/utils';
419
+ import { Button } from '@/components/ui/button';
420
+ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
421
+ import { ScrollArea } from '@/components/ui/scroll-area';
422
+ import { Textarea } from '@/components/ui/textarea';
423
+
424
+ interface Comment { id: string; userName: string | null; content: string; createdAt: number; }
425
+ interface CommentsPanelProps { comments: Comment[]; onAddComment?: (content: string) => void; className?: string; }
426
+
427
+ export function CommentsPanel({ comments, onAddComment, className }: CommentsPanelProps) {
428
+ const [newComment, setNewComment] = React.useState('');
429
+
430
+ const handleSubmit = (e: React.FormEvent) => {
431
+ e.preventDefault();
432
+ if (newComment.trim() && onAddComment) { onAddComment(newComment); setNewComment(''); }
433
+ };
434
+
435
+ return (
436
+ <Card className={cn('flex flex-col', className)}>
437
+ <CardHeader className="border-b py-3"><CardTitle className="text-base">Comments ({comments.length})</CardTitle></CardHeader>
438
+ <ScrollArea className="flex-1">
439
+ <CardContent className="space-y-4 p-4">
440
+ {comments.length === 0 ? <p className="text-center text-muted-foreground py-8">No comments yet</p> : (
441
+ comments.map((c) => (
442
+ <div key={c.id} className="rounded-lg border p-3">
443
+ <div className="flex justify-between text-xs text-muted-foreground">
444
+ <span className="font-medium">{c.userName || 'Anonymous'}</span>
445
+ <span>{new Date(c.createdAt * 1000).toLocaleDateString()}</span>
446
+ </div>
447
+ <p className="mt-2 text-sm">{c.content}</p>
448
+ </div>
449
+ ))
450
+ )}
451
+ </CardContent>
452
+ </ScrollArea>
453
+ {onAddComment && (
454
+ <form onSubmit={handleSubmit} className="border-t p-4">
455
+ <Textarea value={newComment} onChange={(e) => setNewComment(e.target.value)} placeholder="Add a comment..." className="mb-2" />
456
+ <Button type="submit" size="sm" disabled={!newComment.trim()}>Send</Button>
457
+ </form>
458
+ )}
459
+ </Card>
460
+ );
461
+ }
462
+ `,
463
+ 'drafts-list': `'use client';
464
+
465
+ import * as React from 'react';
466
+ import { cn } from '@/lib/utils';
467
+ import { Badge } from '@/components/ui/badge';
468
+ import { Button } from '@/components/ui/button';
469
+ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
470
+
471
+ interface Draft { id: string; docPath: string; title: string; status: 'pending' | 'approved' | 'rejected'; createdAt: number; }
472
+ interface DraftsListProps { drafts: Draft[]; onSelect?: (draft: Draft) => void; onApprove?: (id: string) => void; onReject?: (id: string) => void; showActions?: boolean; className?: string; }
473
+
474
+ const statusVariants = { pending: 'warning', approved: 'success', rejected: 'destructive' } as const;
475
+
476
+ export function DraftsList({ drafts, onSelect, onApprove, onReject, showActions = false, className }: DraftsListProps) {
477
+ return (
478
+ <Card className={cn('', className)}>
479
+ <CardHeader><CardTitle>Drafts</CardTitle></CardHeader>
480
+ <CardContent>
481
+ {drafts.length === 0 ? <p className="text-center text-muted-foreground py-8">No drafts found</p> : (
482
+ <div className="space-y-2">
483
+ {drafts.map((draft) => (
484
+ <div key={draft.id} className={cn('flex items-center justify-between rounded-lg border p-3', onSelect && 'cursor-pointer hover:bg-muted/50')} onClick={() => onSelect?.(draft)}>
485
+ <div><p className="font-medium">{draft.title}</p><p className="text-xs text-muted-foreground">{draft.docPath}</p></div>
486
+ <div className="flex items-center gap-2">
487
+ <Badge variant={statusVariants[draft.status]}>{draft.status}</Badge>
488
+ {showActions && draft.status === 'pending' && (
489
+ <>
490
+ <Button size="icon" variant="ghost" className="h-8 w-8 text-green-600" onClick={(e) => { e.stopPropagation(); onApprove?.(draft.id); }}>āœ“</Button>
491
+ <Button size="icon" variant="ghost" className="h-8 w-8 text-red-600" onClick={(e) => { e.stopPropagation(); onReject?.(draft.id); }}>āœ•</Button>
492
+ </>
493
+ )}
494
+ </div>
495
+ </div>
496
+ ))}
497
+ </div>
498
+ )}
499
+ </CardContent>
500
+ </Card>
501
+ );
502
+ }
503
+ `,
504
+ 'search-bar': `'use client';
505
+
506
+ import * as React from 'react';
507
+ import { cn } from '@/lib/utils';
508
+ import { Input } from '@/components/ui/input';
509
+
510
+ interface SearchResult { path: string; title: string; excerpt: string; }
511
+ interface SearchBarProps { onSearch?: (query: string) => Promise<SearchResult[]>; onSelect?: (path: string) => void; placeholder?: string; className?: string; }
512
+
513
+ export function SearchBar({ onSearch, onSelect, placeholder = 'Search docs...', className }: SearchBarProps) {
514
+ const [query, setQuery] = React.useState('');
515
+ const [results, setResults] = React.useState<SearchResult[]>([]);
516
+ const [loading, setLoading] = React.useState(false);
517
+
518
+ const handleSearch = async (value: string) => {
519
+ setQuery(value);
520
+ if (value.length < 2 || !onSearch) { setResults([]); return; }
521
+ setLoading(true);
522
+ try { const res = await onSearch(value); setResults(res); } catch { setResults([]); } finally { setLoading(false); }
523
+ };
524
+
525
+ return (
526
+ <div className={cn('relative', className)}>
527
+ <Input value={query} onChange={(e) => handleSearch(e.target.value)} placeholder={placeholder} />
528
+ {results.length > 0 && (
529
+ <div className="absolute top-full left-0 right-0 z-50 mt-1 rounded-md border bg-popover shadow-lg max-h-[300px] overflow-auto">
530
+ {results.map((r) => (
531
+ <button key={r.path} type="button" onClick={() => { onSelect?.(r.path); setQuery(''); setResults([]); }} className="flex w-full flex-col p-3 text-left hover:bg-muted border-b last:border-0">
532
+ <span className="font-medium">{r.title}</span>
533
+ <span className="text-xs text-muted-foreground">{r.excerpt}</span>
534
+ </button>
535
+ ))}
536
+ </div>
537
+ )}
538
+ {loading && <div className="absolute top-full left-0 right-0 mt-1 p-4 text-center text-sm text-muted-foreground border rounded-md bg-popover">Searching...</div>}
539
+ </div>
540
+ );
541
+ }
366
542
  `,
367
543
  };
368
- return templates[name] || `// Component template not found: ${name}`;
544
+ return (templates[name] ||
545
+ `// Component template not found: ${name}\n// Please install from: npx @shahadpichen/docpush add ${name}`);
369
546
  }
370
547
  //# sourceMappingURL=add.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"add.js","sourceRoot":"","sources":["../../../src/cli/commands/add.ts"],"names":[],"mappings":";;;;;AAsCA,gCA6HC;AAnKD,0DAA6B;AAC7B,kDAA0B;AAC1B,wDAA0B;AAE1B,kEAAkE;AAClE,MAAM,UAAU,GAAiE;IAC/E,gBAAgB;IAChB,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,YAAY,CAAC,EAAE,YAAY,EAAE,CAAC,OAAO,CAAC,EAAE;IAC1D,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,WAAW,CAAC,EAAE,YAAY,EAAE,CAAC,OAAO,CAAC,EAAE;IACxD,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,cAAc,CAAC,EAAE,YAAY,EAAE,CAAC,OAAO,CAAC,EAAE;IAC9D,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,WAAW,CAAC,EAAE,YAAY,EAAE,CAAC,OAAO,CAAC,EAAE;IACxD,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,UAAU,CAAC,EAAE,YAAY,EAAE,CAAC,OAAO,CAAC,EAAE;IACtD,aAAa,EAAE,EAAE,KAAK,EAAE,CAAC,iBAAiB,CAAC,EAAE,YAAY,EAAE,CAAC,OAAO,CAAC,EAAE;IAEtE,qBAAqB;IACrB,cAAc,EAAE,EAAE,KAAK,EAAE,CAAC,kBAAkB,CAAC,EAAE,YAAY,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC,EAAE;IACvF,iBAAiB,EAAE,EAAE,KAAK,EAAE,CAAC,qBAAqB,CAAC,EAAE,YAAY,EAAE,CAAC,OAAO,CAAC,EAAE;IAC9E,iBAAiB,EAAE;QACjB,KAAK,EAAE,CAAC,qBAAqB,CAAC;QAC9B,YAAY,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC;KAC9C;IACD,gBAAgB,EAAE;QAChB,KAAK,EAAE,CAAC,oBAAoB,CAAC;QAC7B,YAAY,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,CAAC;KACrE;IACD,aAAa,EAAE,EAAE,KAAK,EAAE,CAAC,iBAAiB,CAAC,EAAE,YAAY,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE;IACjG,YAAY,EAAE,EAAE,KAAK,EAAE,CAAC,gBAAgB,CAAC,EAAE,YAAY,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE;IAE7E,YAAY;IACZ,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,UAAU,CAAC,EAAE;CAC/B,CAAC;AAEF,2BAA2B;AAC3B,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC;AAE5E;;GAEG;AACI,KAAK,UAAU,UAAU,CAAC,UAAoB;IACnD,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC,CAAC;IAE7D,gDAAgD;IAChD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IAEpC,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;YACnB,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAClD,CAAC;aAAM,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAED,mBAAmB;IACnB,SAAS,OAAO,CAAC,QAAgB;QAC/B,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,IAAI,EAAE,YAAY,EAAE,CAAC;YACvB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;gBACpC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBACxB,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;oBACnB,OAAO,CAAC,GAAG,CAAC,CAAC;gBACf,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAErC,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CAAC,gCAAgC,CAAC,CAAC,CAAC;QAC5D,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAChE,OAAO;IACT,CAAC;IAED,6DAA6D;IAC7D,IAAI,KAAK,GAAG,qBAAqB,CAAC;IAClC,IAAI,MAAM,GAAG,WAAW,CAAC;IACzB,IAAI,WAAW,GAAG,GAAG,CAAC;IAEtB,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,mBAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;QACpD,IAAI,MAAM,kBAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YACpC,+DAA+D;YAC/D,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,UAAU,IAAI,CAAC,CAAC;YAChD,IAAI,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;gBAC9B,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC;YACnC,CAAC;YACD,IAAI,MAAM,CAAC,UAAU,EAAE,OAAO,EAAE,CAAC;gBAC/B,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC;YACrC,CAAC;YACD,IAAI,MAAM,CAAC,UAAU,EAAE,WAAW,EAAE,CAAC;gBACnC,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC;YAC9C,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,mDAAmD;IACrD,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,qBAAqB,KAAK,EAAE,CAAC,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,iBAAiB,MAAM,IAAI,CAAC,CAAC,CAAC;IAErD,MAAM,kBAAE,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC1B,MAAM,kBAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAE3B,wBAAwB;IACxB,MAAM,UAAU,GAAG,mBAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,oCAAoC,CAAC,CAAC,CAAC;IACvF,MAAM,WAAW,GAAG,mBAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAE3D,kBAAkB;IAClB,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;QAElC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,IAAI,OAAe,CAAC;YACpB,IAAI,QAAgB,CAAC;YAErB,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;gBACzB,sBAAsB;gBACtB,OAAO,GAAG,mBAAI,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;gBACpE,QAAQ,GAAG,mBAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBAEnC,8CAA8C;gBAC9C,MAAM,SAAS,GAAG;;;;;;CAMzB,CAAC;gBACM,MAAM,kBAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;gBACxC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,WAAW,QAAQ,EAAE,CAAC,CAAC;YACvD,CAAC;iBAAM,CAAC;gBACN,gDAAgD;gBAChD,MAAM,aAAa,GAAG;oBACpB,QAAQ;oBACR,OAAO;oBACP,UAAU;oBACV,OAAO;oBACP,MAAM;oBACN,aAAa;iBACd,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;gBACrB,MAAM,SAAS,GAAG,aAAa,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,YAAY,CAAC;gBAEjE,sCAAsC;gBACtC,MAAM,QAAQ,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;gBAChD,QAAQ,GAAG,mBAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;gBAElC,MAAM,kBAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;gBACvC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,WAAW,QAAQ,EAAE,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC,CAAC;IAC9D,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC,CAAC;IAC9E,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC,CAAC;IAE/D,kCAAkC;IAClC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,4DAA4D,CAAC,CAAC;IAC1E,OAAO,CAAC,GAAG,CAAC,gEAAgE,CAAC,CAAC;AAChF,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAAC,IAAY;IACxC,MAAM,SAAS,GAA2B;QACxC,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8CX;QAEG,KAAK,EAAE;;;;;;;;;;;;;;;;;;;;;CAqBV;QAEG,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;CAoBb;QAEG,KAAK,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgCV;QAEG,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4CT;QAEG,aAAa,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyClB;KACE,CAAC;IAEF,OAAO,SAAS,CAAC,IAAI,CAAC,IAAI,oCAAoC,IAAI,EAAE,CAAC;AACvE,CAAC"}
1
+ {"version":3,"file":"add.js","sourceRoot":"","sources":["../../../src/cli/commands/add.ts"],"names":[],"mappings":"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"}
@@ -11,11 +11,12 @@ export declare function useDrafts(status?: string): {
11
11
  drafts: Draft[];
12
12
  loading: boolean;
13
13
  error: string | null;
14
+ isSubmitting: boolean;
14
15
  createDraft: (data: {
15
16
  docPath: string;
16
17
  title: string;
17
18
  content?: string;
18
- }) => Promise<Draft>;
19
+ }) => Promise<Draft | null>;
19
20
  updateDraft: (id: string, content: string, message?: string) => Promise<void>;
20
21
  approveDraft: (id: string) => Promise<void>;
21
22
  rejectDraft: (id: string, reason?: string) => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"use-drafts.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/use-drafts.ts"],"names":[],"mappings":"AAKA,UAAU,KAAK;IACb,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM;;;;wBAuBN;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE;sBAStD,MAAM,WAAW,MAAM,YAAY,MAAM;uBAQxC,MAAM;sBAKP,MAAM,WAAW,MAAM;;EAkBvD"}
1
+ {"version":3,"file":"use-drafts.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/use-drafts.ts"],"names":[],"mappings":"AAKA,UAAU,KAAK;IACb,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM;;;;;wBAwBN;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE;sBAoBtD,MAAM,WAAW,MAAM,YAAY,MAAM;uBAQxC,MAAM;sBAKP,MAAM,WAAW,MAAM;;EAmBvD"}
@@ -42,6 +42,7 @@ function useDrafts(status) {
42
42
  const [drafts, setDrafts] = React.useState([]);
43
43
  const [loading, setLoading] = React.useState(true);
44
44
  const [error, setError] = React.useState(null);
45
+ const [isSubmitting, setIsSubmitting] = React.useState(false);
45
46
  const fetchDrafts = React.useCallback(async () => {
46
47
  setLoading(true);
47
48
  try {
@@ -60,12 +61,23 @@ function useDrafts(status) {
60
61
  fetchDrafts();
61
62
  }, [fetchDrafts]);
62
63
  const createDraft = async (data) => {
63
- const res = await fetcher('/api/drafts', {
64
- method: 'POST',
65
- body: JSON.stringify(data),
66
- });
67
- await fetchDrafts();
68
- return res.draft;
64
+ // Prevent duplicate submissions
65
+ if (isSubmitting) {
66
+ console.warn('Draft submission already in progress');
67
+ return null;
68
+ }
69
+ setIsSubmitting(true);
70
+ try {
71
+ const res = await fetcher('/api/drafts', {
72
+ method: 'POST',
73
+ body: JSON.stringify(data),
74
+ });
75
+ await fetchDrafts();
76
+ return res.draft;
77
+ }
78
+ finally {
79
+ setIsSubmitting(false);
80
+ }
69
81
  };
70
82
  const updateDraft = async (id, content, message) => {
71
83
  await fetcher(`/api/drafts/${id}`, {
@@ -89,6 +101,7 @@ function useDrafts(status) {
89
101
  drafts,
90
102
  loading,
91
103
  error,
104
+ isSubmitting,
92
105
  createDraft,
93
106
  updateDraft,
94
107
  approveDraft,
@@ -1 +1 @@
1
- {"version":3,"file":"use-drafts.js","sourceRoot":"","sources":["../../../src/react/hooks/use-drafts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use-drafts.js","sourceRoot":"","sources":["../../../src/react/hooks/use-drafts.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shahadpichen/docpush",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },