deepspace 0.4.2 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1442 -275
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +197 -425
- package/dist/index.js +621 -1665
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +207 -28
- package/dist/server.js +713 -26
- package/dist/server.js.map +1 -1
- package/dist/worker.d.ts +207 -28
- package/dist/worker.js +713 -26
- package/dist/worker.js.map +1 -1
- package/features/admin-page/src/AdminPage.tsx +1 -1
- package/features/canvas/src/CanvasListPage.tsx +1 -1
- package/features/canvas/src/components/CanvasView.tsx +1 -1
- package/features/docs/src/DocsEditorPage.tsx +1 -1
- package/features/docs/src/InviteDialog.tsx +130 -139
- package/features/file-attachments/src/AttachmentsPage.tsx +1 -4
- package/features/file-manager/src/FileManagerPage.tsx +2 -1
- package/features/items/src/ItemsPage.tsx +1 -1
- package/features/landing/src/LandingPage.tsx +1 -1
- package/features/landing/src/primitives.tsx +1 -1
- package/features/leaderboard/src/LeaderboardPage.tsx +1 -1
- package/features/leaderboard/src/leaderboard-constants.ts +1 -1
- package/features/search-bar/src/SearchOverlay.tsx +1 -1
- package/features/tasks/src/TasksPage.tsx +1 -1
- package/features/tasks/src/tasks-constants.ts +1 -1
- package/package.json +1 -18
- package/dist/testing.d.ts +0 -115
|
@@ -13,7 +13,7 @@ import { useUser } from 'deepspace'
|
|
|
13
13
|
import { useUsers } from 'deepspace'
|
|
14
14
|
import { useQuery } from 'deepspace'
|
|
15
15
|
import { useMutations } from 'deepspace'
|
|
16
|
-
import { Button, Badge, Avatar, AvatarFallback, useToast } from '
|
|
16
|
+
import { Button, Badge, Avatar, AvatarFallback, useToast } from '@/components/ui'
|
|
17
17
|
import { ROLES, ROLE_CONFIG, type Role } from 'deepspace'
|
|
18
18
|
|
|
19
19
|
// ============================================================================
|
|
@@ -12,7 +12,7 @@ import { useNavigate } from 'react-router-dom'
|
|
|
12
12
|
import { useUser } from 'deepspace'
|
|
13
13
|
import { useQuery } from 'deepspace'
|
|
14
14
|
import { useMutations } from 'deepspace'
|
|
15
|
-
import { Button, Modal, EmptyState } from '
|
|
15
|
+
import { Button, Modal, EmptyState } from '@/components/ui'
|
|
16
16
|
import { ROLES, type Role } from 'deepspace'
|
|
17
17
|
|
|
18
18
|
// ============================================================================
|
|
@@ -6,7 +6,7 @@ import { useState, useRef, useCallback, useEffect } from 'react'
|
|
|
6
6
|
import { useCanvas, type CanvasShapeClient } from 'deepspace'
|
|
7
7
|
import { CanvasToolbar, type CanvasTool } from './CanvasToolbar'
|
|
8
8
|
import { ShapeRenderer } from './ShapeRenderer'
|
|
9
|
-
import { Badge } from '
|
|
9
|
+
import { Badge } from '@/components/ui'
|
|
10
10
|
|
|
11
11
|
interface CanvasViewProps {
|
|
12
12
|
docId: string
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
type PresencePeerClient,
|
|
25
25
|
} from 'deepspace'
|
|
26
26
|
import { ArrowLeft, AlertTriangle, List as ListIcon, RefreshCw, Share2 } from 'lucide-react'
|
|
27
|
-
import { Badge } from '
|
|
27
|
+
import { Badge } from '@/components/ui'
|
|
28
28
|
import { type Editor, useEditorState } from '@tiptap/react'
|
|
29
29
|
import { useYjsRoomWithAwareness } from './use-yjs-room-with-awareness'
|
|
30
30
|
import { useDocEditor } from './editor/useDocEditor'
|
|
@@ -2,14 +2,7 @@ import { useMemo, useState } from 'react'
|
|
|
2
2
|
import type { RecordData } from 'deepspace'
|
|
3
3
|
import { useMutations, useQuery, useUser } from 'deepspace'
|
|
4
4
|
import { Mail, ShieldCheck, UserMinus, Users } from 'lucide-react'
|
|
5
|
-
import {
|
|
6
|
-
Dialog,
|
|
7
|
-
DialogContent,
|
|
8
|
-
DialogDescription,
|
|
9
|
-
DialogHeader,
|
|
10
|
-
DialogTitle,
|
|
11
|
-
useToast,
|
|
12
|
-
} from '../../components/ui'
|
|
5
|
+
import { Modal, useToast } from '@/components/ui'
|
|
13
6
|
|
|
14
7
|
export interface InviteDialogDocumentFields {
|
|
15
8
|
title: string
|
|
@@ -187,150 +180,148 @@ export function InviteDialog({ open, onOpenChange, doc, isOwner, onAclChange }:
|
|
|
187
180
|
'Owner'
|
|
188
181
|
|
|
189
182
|
return (
|
|
190
|
-
<
|
|
191
|
-
<
|
|
192
|
-
<
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
</DialogHeader>
|
|
183
|
+
<Modal open={open} onClose={() => onOpenChange(false)} size="lg" className="docs-feature-scope">
|
|
184
|
+
<Modal.Header onClose={() => onOpenChange(false)}>
|
|
185
|
+
<Modal.Title>Share document</Modal.Title>
|
|
186
|
+
<Modal.Description>
|
|
187
|
+
Invite DeepSpace users by the email address on their account.
|
|
188
|
+
</Modal.Description>
|
|
189
|
+
</Modal.Header>
|
|
198
190
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
style={{ borderColor: 'var(--docs-el-line)', color: 'var(--docs-el-text)' }}
|
|
222
|
-
/>
|
|
223
|
-
</div>
|
|
224
|
-
<select
|
|
225
|
-
value={role}
|
|
226
|
-
onChange={(e) => setRole(e.target.value as InviteRole)}
|
|
227
|
-
className="h-10 rounded-lg border bg-transparent px-3 text-sm font-medium outline-none focus-visible:ring-2 focus-visible:ring-ring/30"
|
|
191
|
+
<Modal.Body className="space-y-5">
|
|
192
|
+
<div className="rounded-xl border p-3" style={{ borderColor: 'var(--docs-el-line)' }}>
|
|
193
|
+
<label
|
|
194
|
+
className="mb-2 block text-xs font-semibold uppercase tracking-wide"
|
|
195
|
+
style={{ color: 'var(--docs-el-muted)' }}
|
|
196
|
+
>
|
|
197
|
+
Add people
|
|
198
|
+
</label>
|
|
199
|
+
<div className="flex flex-col gap-2 sm:flex-row">
|
|
200
|
+
<div className="relative min-w-0 flex-1">
|
|
201
|
+
<Mail
|
|
202
|
+
className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2"
|
|
203
|
+
style={{ color: 'var(--docs-el-muted)' }}
|
|
204
|
+
/>
|
|
205
|
+
<input
|
|
206
|
+
value={email}
|
|
207
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
208
|
+
onKeyDown={(e) => {
|
|
209
|
+
if (e.key === 'Enter') void addInvite()
|
|
210
|
+
}}
|
|
211
|
+
placeholder="person@gmail.com"
|
|
212
|
+
className="h-10 w-full rounded-lg border bg-transparent pl-9 pr-3 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring/30"
|
|
228
213
|
style={{ borderColor: 'var(--docs-el-line)', color: 'var(--docs-el-text)' }}
|
|
229
|
-
|
|
230
|
-
<option value="editor">Editor</option>
|
|
231
|
-
<option value="viewer">Viewer</option>
|
|
232
|
-
</select>
|
|
233
|
-
<button
|
|
234
|
-
type="button"
|
|
235
|
-
onClick={() => void addInvite()}
|
|
236
|
-
disabled={saving || !email.trim()}
|
|
237
|
-
className="h-10 rounded-lg px-4 text-sm font-semibold text-white transition-opacity hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50"
|
|
238
|
-
style={{ backgroundColor: 'var(--docs-el-accent)' }}
|
|
239
|
-
>
|
|
240
|
-
Add
|
|
241
|
-
</button>
|
|
214
|
+
/>
|
|
242
215
|
</div>
|
|
216
|
+
<select
|
|
217
|
+
value={role}
|
|
218
|
+
onChange={(e) => setRole(e.target.value as InviteRole)}
|
|
219
|
+
className="h-10 rounded-lg border bg-transparent px-3 text-sm font-medium outline-none focus-visible:ring-2 focus-visible:ring-ring/30"
|
|
220
|
+
style={{ borderColor: 'var(--docs-el-line)', color: 'var(--docs-el-text)' }}
|
|
221
|
+
>
|
|
222
|
+
<option value="editor">Editor</option>
|
|
223
|
+
<option value="viewer">Viewer</option>
|
|
224
|
+
</select>
|
|
225
|
+
<button
|
|
226
|
+
type="button"
|
|
227
|
+
onClick={() => void addInvite()}
|
|
228
|
+
disabled={saving || !email.trim()}
|
|
229
|
+
className="h-10 rounded-lg px-4 text-sm font-semibold text-white transition-opacity hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50"
|
|
230
|
+
style={{ backgroundColor: 'var(--docs-el-accent)' }}
|
|
231
|
+
>
|
|
232
|
+
Add
|
|
233
|
+
</button>
|
|
243
234
|
</div>
|
|
235
|
+
</div>
|
|
244
236
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
237
|
+
<div>
|
|
238
|
+
<div className="mb-3 flex items-center gap-2">
|
|
239
|
+
<Users className="h-4 w-4" style={{ color: 'var(--docs-el-muted)' }} />
|
|
240
|
+
<h3 className="text-sm font-semibold">People with access</h3>
|
|
241
|
+
</div>
|
|
250
242
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
</div>
|
|
243
|
+
<div className="space-y-2">
|
|
244
|
+
<div
|
|
245
|
+
className="flex items-center gap-3 rounded-xl border p-3"
|
|
246
|
+
style={{ borderColor: 'var(--docs-el-line)' }}
|
|
247
|
+
>
|
|
248
|
+
<div className="flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-black/5 text-xs font-bold dark:bg-white/10">
|
|
249
|
+
{initialsFor(ownerName)}
|
|
250
|
+
</div>
|
|
251
|
+
<div className="min-w-0 flex-1">
|
|
252
|
+
<div className="truncate text-sm font-medium">{ownerName}</div>
|
|
253
|
+
<div className="truncate text-xs" style={{ color: 'var(--docs-el-muted)' }}>
|
|
254
|
+
{ownerRecord?.data.email ?? user?.email ?? 'Owner'}
|
|
264
255
|
</div>
|
|
265
|
-
<span className="inline-flex items-center gap-1 rounded-full border px-2.5 py-1 text-xs font-medium">
|
|
266
|
-
<ShieldCheck className="h-3.5 w-3.5" />
|
|
267
|
-
Owner
|
|
268
|
-
</span>
|
|
269
256
|
</div>
|
|
257
|
+
<span className="inline-flex items-center gap-1 rounded-full border px-2.5 py-1 text-xs font-medium">
|
|
258
|
+
<ShieldCheck className="h-3.5 w-3.5" />
|
|
259
|
+
Owner
|
|
260
|
+
</span>
|
|
261
|
+
</div>
|
|
270
262
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
</div>
|
|
263
|
+
{collaboratorRecords.map((u) => {
|
|
264
|
+
const name = u.data.name?.trim() || u.data.email?.trim() || 'Collaborator'
|
|
265
|
+
const userRole: InviteRole = editors.includes(u.recordId) ? 'editor' : 'viewer'
|
|
266
|
+
return (
|
|
267
|
+
<div
|
|
268
|
+
key={u.recordId}
|
|
269
|
+
className="flex items-center gap-3 rounded-xl border p-3"
|
|
270
|
+
style={{ borderColor: 'var(--docs-el-line)' }}
|
|
271
|
+
>
|
|
272
|
+
{u.data.imageUrl ? (
|
|
273
|
+
<img
|
|
274
|
+
src={u.data.imageUrl}
|
|
275
|
+
alt=""
|
|
276
|
+
className="h-9 w-9 shrink-0 rounded-full object-cover"
|
|
277
|
+
/>
|
|
278
|
+
) : (
|
|
279
|
+
<div className="flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-black/5 text-xs font-bold dark:bg-white/10">
|
|
280
|
+
{initialsFor(name)}
|
|
281
|
+
</div>
|
|
282
|
+
)}
|
|
283
|
+
<div className="min-w-0 flex-1">
|
|
284
|
+
<div className="truncate text-sm font-medium">{name}</div>
|
|
285
|
+
<div className="truncate text-xs" style={{ color: 'var(--docs-el-muted)' }}>
|
|
286
|
+
{u.data.email ?? 'No email'}
|
|
296
287
|
</div>
|
|
297
|
-
<select
|
|
298
|
-
value={userRole}
|
|
299
|
-
onChange={(e) =>
|
|
300
|
-
void setCollaboratorRole(u.recordId, e.target.value as InviteRole)
|
|
301
|
-
}
|
|
302
|
-
disabled={saving}
|
|
303
|
-
className="h-8 rounded-lg border bg-transparent px-2 text-xs font-medium outline-none"
|
|
304
|
-
style={{ borderColor: 'var(--docs-el-line)', color: 'var(--docs-el-text)' }}
|
|
305
|
-
>
|
|
306
|
-
<option value="editor">Editor</option>
|
|
307
|
-
<option value="viewer">Viewer</option>
|
|
308
|
-
</select>
|
|
309
|
-
<button
|
|
310
|
-
type="button"
|
|
311
|
-
onClick={() => void removeCollaborator(u.recordId)}
|
|
312
|
-
disabled={saving}
|
|
313
|
-
className="rounded-lg p-1.5 text-red-600 transition-colors hover:bg-red-500/10 disabled:opacity-50"
|
|
314
|
-
title="Remove access"
|
|
315
|
-
>
|
|
316
|
-
<UserMinus className="h-4 w-4" />
|
|
317
|
-
</button>
|
|
318
288
|
</div>
|
|
319
|
-
|
|
320
|
-
|
|
289
|
+
<select
|
|
290
|
+
value={userRole}
|
|
291
|
+
onChange={(e) =>
|
|
292
|
+
void setCollaboratorRole(u.recordId, e.target.value as InviteRole)
|
|
293
|
+
}
|
|
294
|
+
disabled={saving}
|
|
295
|
+
className="h-8 rounded-lg border bg-transparent px-2 text-xs font-medium outline-none"
|
|
296
|
+
style={{ borderColor: 'var(--docs-el-line)', color: 'var(--docs-el-text)' }}
|
|
297
|
+
>
|
|
298
|
+
<option value="editor">Editor</option>
|
|
299
|
+
<option value="viewer">Viewer</option>
|
|
300
|
+
</select>
|
|
301
|
+
<button
|
|
302
|
+
type="button"
|
|
303
|
+
onClick={() => void removeCollaborator(u.recordId)}
|
|
304
|
+
disabled={saving}
|
|
305
|
+
className="rounded-lg p-1.5 text-red-600 transition-colors hover:bg-red-500/10 disabled:opacity-50"
|
|
306
|
+
title="Remove access"
|
|
307
|
+
>
|
|
308
|
+
<UserMinus className="h-4 w-4" />
|
|
309
|
+
</button>
|
|
310
|
+
</div>
|
|
311
|
+
)
|
|
312
|
+
})}
|
|
321
313
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
</div>
|
|
314
|
+
{collaboratorRecords.length === 0 ? (
|
|
315
|
+
<p
|
|
316
|
+
className="rounded-xl border p-3 text-sm"
|
|
317
|
+
style={{ color: 'var(--docs-el-muted)' }}
|
|
318
|
+
>
|
|
319
|
+
Only the owner can access this document.
|
|
320
|
+
</p>
|
|
321
|
+
) : null}
|
|
331
322
|
</div>
|
|
332
323
|
</div>
|
|
333
|
-
</
|
|
334
|
-
</
|
|
324
|
+
</Modal.Body>
|
|
325
|
+
</Modal>
|
|
335
326
|
)
|
|
336
327
|
}
|
|
@@ -16,14 +16,11 @@ import {
|
|
|
16
16
|
useQuery,
|
|
17
17
|
useMutations,
|
|
18
18
|
useR2Files,
|
|
19
|
-
Button,
|
|
20
|
-
Modal,
|
|
21
|
-
EmptyState,
|
|
22
|
-
Badge,
|
|
23
19
|
ROLES,
|
|
24
20
|
formatFileSize,
|
|
25
21
|
type Role,
|
|
26
22
|
} from 'deepspace'
|
|
23
|
+
import { Button, Modal, EmptyState, Badge } from '@/components/ui'
|
|
27
24
|
import { useMimeTypeDetection, type FileCategory } from '../hooks/useMimeTypeDetection'
|
|
28
25
|
import { useFilePreview } from '../hooks/useFilePreview'
|
|
29
26
|
import { MAX_FILE_SIZE } from '../constants/attachments-constants'
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { useState, useEffect, useCallback, useRef } from 'react'
|
|
12
|
-
import { useUser, useR2Files
|
|
12
|
+
import { useUser, useR2Files } from 'deepspace'
|
|
13
|
+
import { Button, EmptyState, Badge, Modal } from '@/components/ui'
|
|
13
14
|
import type { R2FileInfo } from 'deepspace'
|
|
14
15
|
|
|
15
16
|
// ============================================================================
|
|
@@ -12,7 +12,7 @@ import { useState, useMemo } from 'react'
|
|
|
12
12
|
import { useUser } from 'deepspace'
|
|
13
13
|
import { useQuery } from 'deepspace'
|
|
14
14
|
import { useMutations } from 'deepspace'
|
|
15
|
-
import { Button, Modal, EmptyState, Badge } from '
|
|
15
|
+
import { Button, Modal, EmptyState, Badge } from '@/components/ui'
|
|
16
16
|
import { ROLES, type Role } from 'deepspace'
|
|
17
17
|
import { ITEM_STATUS } from '../components/items/items-constants'
|
|
18
18
|
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
Github, Twitter, Linkedin, Mail, Sparkles, ChevronRight, Plus, Minus,
|
|
15
15
|
} from 'lucide-react'
|
|
16
16
|
import { useUser } from 'deepspace'
|
|
17
|
-
import { Button, cn } from '
|
|
17
|
+
import { Button, cn } from '@/components/ui'
|
|
18
18
|
import {
|
|
19
19
|
Typewriter,
|
|
20
20
|
ScrollReveal,
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { useEffect, useState, useRef, type ReactNode } from 'react'
|
|
9
9
|
import { motion, AnimatePresence, useInView } from 'framer-motion'
|
|
10
10
|
import { ImageIcon, ChevronDown } from 'lucide-react'
|
|
11
|
-
import { cn } from '
|
|
11
|
+
import { cn } from '@/components/ui'
|
|
12
12
|
|
|
13
13
|
// ============================================================================
|
|
14
14
|
// Smooth Typewriter
|
|
@@ -12,7 +12,7 @@ import { useState } from 'react'
|
|
|
12
12
|
import { useUser } from 'deepspace'
|
|
13
13
|
import { useQuery } from 'deepspace'
|
|
14
14
|
import { useMutations } from 'deepspace'
|
|
15
|
-
import { Button, Modal, EmptyState, Badge } from '
|
|
15
|
+
import { Button, Modal, EmptyState, Badge } from '@/components/ui'
|
|
16
16
|
import { ROLES, type Role } from 'deepspace'
|
|
17
17
|
import { LEADERBOARD_CATEGORY, CATEGORY_CONFIG, type LeaderboardCategory } from '../components/leaderboard/leaderboard-constants'
|
|
18
18
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useEffect, useMemo, useRef, useState, type ReactNode } from 'react'
|
|
2
|
-
import { Badge, Button, EmptyState, SearchInput, cn } from '
|
|
2
|
+
import { Badge, Button, EmptyState, SearchInput, cn } from '@/components/ui'
|
|
3
3
|
import { Loader2 } from 'lucide-react'
|
|
4
4
|
|
|
5
5
|
export interface SearchItem {
|
|
@@ -13,7 +13,7 @@ import { useUser } from 'deepspace'
|
|
|
13
13
|
import { useUsers } from 'deepspace'
|
|
14
14
|
import { useQuery } from 'deepspace'
|
|
15
15
|
import { useMutations } from 'deepspace'
|
|
16
|
-
import { Button, Modal, Badge, EmptyState, type BadgeProps } from '
|
|
16
|
+
import { Button, Modal, Badge, EmptyState, type BadgeProps } from '@/components/ui'
|
|
17
17
|
import { ROLES, type Role } from 'deepspace'
|
|
18
18
|
import { DIFFICULTY, DIFFICULTY_CONFIG, GRADE, GRADE_CONFIG, type Difficulty, type Grade, type BadgeVariant } from '../components/tasks/tasks-constants'
|
|
19
19
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deepspace",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.4",
|
|
4
4
|
"description": "DeepSpace SDK — build real-time collaborative apps on Cloudflare Workers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -56,7 +56,6 @@
|
|
|
56
56
|
"@ai-sdk/openai-compatible": "^1.0.0",
|
|
57
57
|
"@playwright/test": ">=1.40.0",
|
|
58
58
|
"ai": "^5.0.0",
|
|
59
|
-
"class-variance-authority": ">=0.7.0",
|
|
60
59
|
"clsx": ">=2.0.0",
|
|
61
60
|
"lucide-react": ">=0.400.0",
|
|
62
61
|
"react": "^18.0.0 || ^19.0.0",
|
|
@@ -85,9 +84,6 @@
|
|
|
85
84
|
"react-dom": {
|
|
86
85
|
"optional": true
|
|
87
86
|
},
|
|
88
|
-
"class-variance-authority": {
|
|
89
|
-
"optional": true
|
|
90
|
-
},
|
|
91
87
|
"clsx": {
|
|
92
88
|
"optional": true
|
|
93
89
|
},
|
|
@@ -104,24 +100,11 @@
|
|
|
104
100
|
"@ai-sdk/openai-compatible": "^1.0.0",
|
|
105
101
|
"@cloudflare/workers-types": "^4.20241205.0",
|
|
106
102
|
"@playwright/test": "^1.59.1",
|
|
107
|
-
"@radix-ui/react-avatar": "^1.1.11",
|
|
108
|
-
"@radix-ui/react-checkbox": "^1.3.3",
|
|
109
|
-
"@radix-ui/react-dialog": "^1.1.15",
|
|
110
|
-
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
111
|
-
"@radix-ui/react-label": "^2.1.8",
|
|
112
|
-
"@radix-ui/react-progress": "^1.1.8",
|
|
113
|
-
"@radix-ui/react-select": "^2.2.6",
|
|
114
|
-
"@radix-ui/react-separator": "^1.1.8",
|
|
115
|
-
"@radix-ui/react-slot": "^1.2.4",
|
|
116
|
-
"@radix-ui/react-switch": "^1.2.6",
|
|
117
|
-
"@radix-ui/react-tabs": "^1.1.13",
|
|
118
|
-
"@radix-ui/react-tooltip": "^1.2.8",
|
|
119
103
|
"@types/better-sqlite3": "^7.6.12",
|
|
120
104
|
"@types/cross-spawn": "^6.0.6",
|
|
121
105
|
"@types/react": "^19.0.0",
|
|
122
106
|
"@types/react-dom": "^19.0.0",
|
|
123
107
|
"better-sqlite3": "^12.0.0",
|
|
124
|
-
"class-variance-authority": "^0.7.1",
|
|
125
108
|
"clsx": "^2.1.1",
|
|
126
109
|
"framer-motion": "^12.38.0",
|
|
127
110
|
"lucide-react": "^1.7.0",
|
package/dist/testing.d.ts
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import * as _playwright_test from '@playwright/test';
|
|
2
|
-
import { BrowserContext, Page, Browser } from '@playwright/test';
|
|
3
|
-
export { expect } from '@playwright/test';
|
|
4
|
-
|
|
5
|
-
interface MultiplayerUser {
|
|
6
|
-
context: BrowserContext;
|
|
7
|
-
page: Page;
|
|
8
|
-
email: string;
|
|
9
|
-
name: string;
|
|
10
|
-
/** Test account user ID, if known from the accounts registry. */
|
|
11
|
-
userId?: string;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Fixture function signature. Pass either a count (`users(2)`) or an
|
|
15
|
-
* array of account names (`users(['Alice', 'Bob'])`). Returns one entry
|
|
16
|
-
* per requested user.
|
|
17
|
-
*/
|
|
18
|
-
type UsersFixture = (selector: number | string[], options?: {
|
|
19
|
-
label?: string;
|
|
20
|
-
}) => Promise<MultiplayerUser[]>;
|
|
21
|
-
interface MultiplayerFixtures {
|
|
22
|
-
users: UsersFixture;
|
|
23
|
-
}
|
|
24
|
-
declare const test: _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & MultiplayerFixtures, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions>;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Account-credential plumbing for the testing module.
|
|
28
|
-
*
|
|
29
|
-
* Reads test accounts from `~/.deepspace/test-accounts.json` (the same
|
|
30
|
-
* file `deepspace test-accounts create` writes). Each account has at
|
|
31
|
-
* minimum `{email, password}`; `name` and `label` are optional.
|
|
32
|
-
*
|
|
33
|
-
* Used by the multi-user Playwright fixture in `./fixtures.ts` and is
|
|
34
|
-
* also exported standalone in case suites want to do their own
|
|
35
|
-
* orchestration.
|
|
36
|
-
*/
|
|
37
|
-
interface TestAccount {
|
|
38
|
-
email: string;
|
|
39
|
-
password: string;
|
|
40
|
-
name?: string;
|
|
41
|
-
label?: string | null;
|
|
42
|
-
id?: string;
|
|
43
|
-
userId?: string;
|
|
44
|
-
createdAt?: number;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Load all test accounts the developer has created. Returns an empty
|
|
48
|
-
* array if the file doesn't exist yet.
|
|
49
|
-
*/
|
|
50
|
-
declare function loadAllTestAccounts(): TestAccount[];
|
|
51
|
-
/**
|
|
52
|
-
* Pick `count` test accounts from the local registry, optionally
|
|
53
|
-
* filtered by `label`. Order-stable: sorted by `createdAt` ascending so
|
|
54
|
-
* the first test account you created is always the first one returned.
|
|
55
|
-
*
|
|
56
|
-
* Throws with a helpful message if not enough accounts exist.
|
|
57
|
-
*/
|
|
58
|
-
declare function pickTestAccounts(count: number, options?: {
|
|
59
|
-
label?: string;
|
|
60
|
-
}): TestAccount[];
|
|
61
|
-
/**
|
|
62
|
-
* Find a single account by name. Used by `users(['Alice', 'Bob'])`.
|
|
63
|
-
* Throws if not found.
|
|
64
|
-
*/
|
|
65
|
-
declare function findTestAccountByName(name: string): TestAccount;
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Per-account `storageState` cache for Playwright.
|
|
69
|
-
*
|
|
70
|
-
* Better Auth applies a per-IP rate limit on `/api/auth/sign-in/email`
|
|
71
|
-
* (~5 sign-ins / 60s / endpoint). A multiplayer suite that spins up
|
|
72
|
-
* 5+ users per spec would hit the limit and start failing in non-obvious
|
|
73
|
-
* ways. This module signs each account in *once*, persists the
|
|
74
|
-
* resulting browser cookies + storage to disk, and reuses the file on
|
|
75
|
-
* subsequent runs.
|
|
76
|
-
*
|
|
77
|
-
* Cache layout:
|
|
78
|
-
* ~/.deepspace/playwright-states/<sha256(email)>.json
|
|
79
|
-
*
|
|
80
|
-
* Validity: a cached file is reused if Playwright successfully loads it
|
|
81
|
-
* AND the resulting context produces a non-anonymous session on the
|
|
82
|
-
* target app. If validation fails, we fall back to a fresh sign-in and
|
|
83
|
-
* overwrite the cache.
|
|
84
|
-
*/
|
|
85
|
-
|
|
86
|
-
interface EnsureStorageStateOptions {
|
|
87
|
-
/** Max age of a cached state file before we re-sign-in. Default 7 days. */
|
|
88
|
-
maxAgeMs?: number;
|
|
89
|
-
/** Force a fresh sign-in even if the cache is fresh. */
|
|
90
|
-
force?: boolean;
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Ensure a Playwright `storageState` file exists for `account` and
|
|
94
|
-
* return its path. Signs in once if the cache is missing, stale, or
|
|
95
|
-
* `force: true`.
|
|
96
|
-
*/
|
|
97
|
-
declare function ensureStorageState(browser: Browser, account: {
|
|
98
|
-
email: string;
|
|
99
|
-
password: string;
|
|
100
|
-
}, baseURL: string, options?: EnsureStorageStateOptions): Promise<string>;
|
|
101
|
-
/**
|
|
102
|
-
* Convenience: open a fresh `BrowserContext` for `account` using the
|
|
103
|
-
* cached storage state (signing in if needed). The caller is responsible
|
|
104
|
-
* for closing the context.
|
|
105
|
-
*/
|
|
106
|
-
declare function newSignedInContext(browser: Browser, account: {
|
|
107
|
-
email: string;
|
|
108
|
-
password: string;
|
|
109
|
-
}, baseURL: string, options?: EnsureStorageStateOptions): Promise<BrowserContext>;
|
|
110
|
-
/** Read a cached storageState file (mostly for debugging). */
|
|
111
|
-
declare function readCachedState(email: string): unknown | null;
|
|
112
|
-
/** Where the cache for `email` lives. Useful for diagnostics. */
|
|
113
|
-
declare function getStatePathForEmail(email: string): string;
|
|
114
|
-
|
|
115
|
-
export { type EnsureStorageStateOptions, type MultiplayerUser, type TestAccount, type UsersFixture, ensureStorageState, findTestAccountByName, getStatePathForEmail, loadAllTestAccounts, newSignedInContext, pickTestAccounts, readCachedState, test };
|