@notis_ai/cli 0.2.13 → 0.2.15
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/README.md +125 -21
- package/dist/agent-hooks/notis-agent-hook.mjs +19750 -0
- package/{skills → dist/base-skills}/notis-apps/SKILL.md +93 -58
- package/{skills → dist/base-skills}/notis-cli/SKILL.md +9 -9
- package/dist/base-skills/notis-query/SKILL.md +705 -0
- package/dist/skill-sync/index.js +1528 -0
- package/dist/skill-sync/index.js.map +7 -0
- package/package.json +5 -2
- package/skills/notis-apps/cli.md +44 -18
- package/skills/notis-cli/AGENT_INSTRUCTIONS.md +39 -0
- package/skills/notis-onboarding/BRIEF.md +16 -0
- package/src/agent-hook-entry.js +5 -0
- package/src/cli.js +23 -14
- package/src/command-specs/agents.js +392 -0
- package/src/command-specs/apps.js +1090 -418
- package/src/command-specs/auth.js +63 -10
- package/src/command-specs/handover.js +374 -0
- package/src/command-specs/index.js +9 -0
- package/src/command-specs/onboarding.js +69 -5
- package/src/command-specs/skills.js +56 -0
- package/src/command-specs/tools.js +6 -0
- package/src/runtime/agent-memory-state.js +126 -0
- package/src/runtime/agent-setup.js +383 -0
- package/src/runtime/app-dev-consumers.js +154 -0
- package/src/runtime/app-dev-host-lock.js +80 -0
- package/src/runtime/app-dev-roots.js +284 -0
- package/src/runtime/app-dev-server.js +229 -30
- package/src/runtime/app-dev-sessions.js +105 -145
- package/src/runtime/app-platform.js +1499 -161
- package/src/runtime/app-registry-scaffolds.js +367 -0
- package/src/runtime/base-skills.d.ts +20 -0
- package/src/runtime/base-skills.js +167 -0
- package/src/runtime/delegated-context.js +68 -0
- package/src/runtime/git.js +233 -0
- package/src/runtime/login-listener.js +15 -0
- package/src/runtime/oauth.js +1506 -141
- package/src/runtime/output.js +7 -0
- package/src/runtime/ports.js +16 -0
- package/src/runtime/profiles.js +0 -5
- package/src/runtime/skill-sync/cloud-client.ts +96 -0
- package/src/runtime/skill-sync/index.ts +644 -0
- package/src/runtime/skill-sync/local-scanner.ts +1046 -0
- package/src/runtime/skill-sync/symlink-manager.ts +383 -0
- package/src/runtime/skill-sync/sync-plan.ts +22 -0
- package/src/runtime/skill-sync/types.ts +103 -0
- package/src/runtime/skill-sync/write-cloud-skill.ts +50 -0
- package/src/runtime/store-screenshot.js +6 -1
- package/src/runtime/sync-skills.d.ts +37 -0
- package/src/runtime/sync-skills.js +215 -0
- package/src/runtime/transport.js +19 -2
- package/template/.harness/index.html.tmpl +116 -47
- package/template/app/layout.tsx +5 -1
- package/template/notis.config.ts +1 -0
- package/template/packages/sdk/package.json +2 -1
- package/template/packages/sdk/src/components/DocumentEditor.tsx +13 -3
- package/template/packages/sdk/src/components/MarkdownEditor.tsx +121 -0
- package/template/packages/sdk/src/components/MultiSelectActionBar.tsx +37 -119
- package/template/packages/sdk/src/components/MultiSelectCheckbox.tsx +5 -1
- package/template/packages/sdk/src/components/MultiSelectDragOverlay.tsx +1 -1
- package/template/packages/sdk/src/components/NotisSelectionBoundary.tsx +55 -0
- package/template/packages/sdk/src/components/ShortcutHints.tsx +56 -0
- package/template/packages/sdk/src/config.ts +71 -0
- package/template/packages/sdk/src/documents.ts +28 -1
- package/template/packages/sdk/src/hooks/useActiveResource.ts +19 -0
- package/template/packages/sdk/src/hooks/useCloudComputer.ts +97 -0
- package/template/packages/sdk/src/hooks/useCollectionInteractions.ts +709 -0
- package/template/packages/sdk/src/hooks/useDatabaseSubscription.ts +76 -0
- package/template/packages/sdk/src/hooks/useHandover.ts +78 -0
- package/template/packages/sdk/src/hooks/useMultiSelect.ts +44 -482
- package/template/packages/sdk/src/hooks/useTool.ts +5 -4
- package/template/packages/sdk/src/index.ts +64 -2
- package/template/packages/sdk/src/interactions/actions.ts +46 -0
- package/template/packages/sdk/src/interactions/shortcuts.tsx +628 -0
- package/template/packages/sdk/src/interactions.ts +41 -0
- package/template/packages/sdk/src/provider.tsx +2 -1
- package/template/packages/sdk/src/runtime.ts +219 -3
- package/dist/scaffolds/notis-database/CHANGELOG.md +0 -5
- package/dist/scaffolds/notis-database/app/globals.css +0 -44
- package/dist/scaffolds/notis-database/app/layout.tsx +0 -6
- package/dist/scaffolds/notis-database/app/page.tsx +0 -1088
- package/dist/scaffolds/notis-database/components/ui/badge.tsx +0 -28
- package/dist/scaffolds/notis-database/components/ui/button.tsx +0 -53
- package/dist/scaffolds/notis-database/components/ui/card.tsx +0 -56
- package/dist/scaffolds/notis-database/components/ui/table.tsx +0 -120
- package/dist/scaffolds/notis-database/components.json +0 -20
- package/dist/scaffolds/notis-database/index.html +0 -12
- package/dist/scaffolds/notis-database/lib/types.ts +0 -132
- package/dist/scaffolds/notis-database/lib/utils.ts +0 -6
- package/dist/scaffolds/notis-database/metadata/screenshot-1.png +0 -0
- package/dist/scaffolds/notis-database/metadata/screenshot-2.png +0 -0
- package/dist/scaffolds/notis-database/metadata/screenshot-3.png +0 -0
- package/dist/scaffolds/notis-database/metadata/screenshot-4.png +0 -0
- package/dist/scaffolds/notis-database/metadata/screenshot-5.png +0 -0
- package/dist/scaffolds/notis-database/metadata/screenshot-fixtures.json +0 -1839
- package/dist/scaffolds/notis-database/notis.config.ts +0 -73
- package/dist/scaffolds/notis-database/package-lock.json +0 -3935
- package/dist/scaffolds/notis-database/package.json +0 -32
- package/dist/scaffolds/notis-database/packages/sdk/package.json +0 -36
- package/dist/scaffolds/notis-database/packages/sdk/src/components/DocumentEditor.tsx +0 -93
- package/dist/scaffolds/notis-database/packages/sdk/src/components/Markdown.tsx +0 -60
- package/dist/scaffolds/notis-database/packages/sdk/src/components/MultiSelectActionBar.tsx +0 -278
- package/dist/scaffolds/notis-database/packages/sdk/src/components/MultiSelectCheckbox.tsx +0 -91
- package/dist/scaffolds/notis-database/packages/sdk/src/components/MultiSelectDragOverlay.tsx +0 -39
- package/dist/scaffolds/notis-database/packages/sdk/src/config.ts +0 -196
- package/dist/scaffolds/notis-database/packages/sdk/src/documents.ts +0 -229
- package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useBackend.ts +0 -41
- package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useDatabaseSchema.ts +0 -85
- package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useDocument.ts +0 -78
- package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useDocuments.ts +0 -121
- package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useMultiSelect.ts +0 -539
- package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useNotis.ts +0 -34
- package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useNotisNavigation.ts +0 -49
- package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useTool.ts +0 -64
- package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useTools.ts +0 -56
- package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useTopBarSearch.ts +0 -73
- package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useUpsertDocument.ts +0 -95
- package/dist/scaffolds/notis-database/packages/sdk/src/index.ts +0 -83
- package/dist/scaffolds/notis-database/packages/sdk/src/provider.tsx +0 -43
- package/dist/scaffolds/notis-database/packages/sdk/src/runtime.ts +0 -220
- package/dist/scaffolds/notis-database/packages/sdk/src/styles.css +0 -186
- package/dist/scaffolds/notis-database/packages/sdk/src/ui.ts +0 -15
- package/dist/scaffolds/notis-database/packages/sdk/src/vite.ts +0 -56
- package/dist/scaffolds/notis-database/packages/sdk/tsconfig.json +0 -15
- package/dist/scaffolds/notis-database/postcss.config.mjs +0 -8
- package/dist/scaffolds/notis-database/src/dev-main.tsx +0 -23
- package/dist/scaffolds/notis-database/src/mock-runtime.ts +0 -561
- package/dist/scaffolds/notis-database/tailwind.config.ts +0 -59
- package/dist/scaffolds/notis-database/tsconfig.json +0 -23
- package/dist/scaffolds/notis-database/vite.config.ts +0 -22
- package/dist/scaffolds/notis-journal/CHANGELOG.md +0 -29
- package/dist/scaffolds/notis-journal/app/globals.css +0 -37
- package/dist/scaffolds/notis-journal/app/insights/page.tsx +0 -513
- package/dist/scaffolds/notis-journal/app/journal-core.tsx +0 -362
- package/dist/scaffolds/notis-journal/app/journal-ui.tsx +0 -337
- package/dist/scaffolds/notis-journal/app/layout.tsx +0 -6
- package/dist/scaffolds/notis-journal/app/page.tsx +0 -486
- package/dist/scaffolds/notis-journal/components/ui/badge.tsx +0 -28
- package/dist/scaffolds/notis-journal/components/ui/button.tsx +0 -53
- package/dist/scaffolds/notis-journal/components/ui/card.tsx +0 -56
- package/dist/scaffolds/notis-journal/components.json +0 -20
- package/dist/scaffolds/notis-journal/index.html +0 -12
- package/dist/scaffolds/notis-journal/lib/utils.ts +0 -6
- package/dist/scaffolds/notis-journal/metadata/screenshot-1.png +0 -0
- package/dist/scaffolds/notis-journal/metadata/screenshot-2.png +0 -0
- package/dist/scaffolds/notis-journal/metadata/screenshot-3.png +0 -0
- package/dist/scaffolds/notis-journal/metadata/screenshot-4.png +0 -0
- package/dist/scaffolds/notis-journal/metadata/screenshot-5.png +0 -0
- package/dist/scaffolds/notis-journal/metadata/screenshot-6.png +0 -0
- package/dist/scaffolds/notis-journal/metadata/screenshot-fixtures.json +0 -132
- package/dist/scaffolds/notis-journal/notis.config.ts +0 -93
- package/dist/scaffolds/notis-journal/package-lock.json +0 -4615
- package/dist/scaffolds/notis-journal/package.json +0 -34
- package/dist/scaffolds/notis-journal/packages/sdk/package.json +0 -36
- package/dist/scaffolds/notis-journal/packages/sdk/src/components/DocumentEditor.tsx +0 -93
- package/dist/scaffolds/notis-journal/packages/sdk/src/components/Markdown.tsx +0 -60
- package/dist/scaffolds/notis-journal/packages/sdk/src/components/MultiSelectActionBar.tsx +0 -278
- package/dist/scaffolds/notis-journal/packages/sdk/src/components/MultiSelectCheckbox.tsx +0 -91
- package/dist/scaffolds/notis-journal/packages/sdk/src/components/MultiSelectDragOverlay.tsx +0 -39
- package/dist/scaffolds/notis-journal/packages/sdk/src/config.ts +0 -196
- package/dist/scaffolds/notis-journal/packages/sdk/src/documents.ts +0 -229
- package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useBackend.ts +0 -41
- package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useDatabaseSchema.ts +0 -85
- package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useDocument.ts +0 -78
- package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useDocuments.ts +0 -121
- package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useMultiSelect.ts +0 -539
- package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useNotis.ts +0 -34
- package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useNotisNavigation.ts +0 -49
- package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useTool.ts +0 -64
- package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useTools.ts +0 -56
- package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useTopBarSearch.ts +0 -73
- package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useUpsertDocument.ts +0 -95
- package/dist/scaffolds/notis-journal/packages/sdk/src/index.ts +0 -83
- package/dist/scaffolds/notis-journal/packages/sdk/src/provider.tsx +0 -43
- package/dist/scaffolds/notis-journal/packages/sdk/src/runtime.ts +0 -220
- package/dist/scaffolds/notis-journal/packages/sdk/src/styles.css +0 -186
- package/dist/scaffolds/notis-journal/packages/sdk/src/ui.ts +0 -15
- package/dist/scaffolds/notis-journal/packages/sdk/src/vite.ts +0 -56
- package/dist/scaffolds/notis-journal/packages/sdk/tsconfig.json +0 -15
- package/dist/scaffolds/notis-journal/postcss.config.mjs +0 -8
- package/dist/scaffolds/notis-journal/skills/journal-onboarding/SKILL.md +0 -120
- package/dist/scaffolds/notis-journal/src/dev-main.tsx +0 -58
- package/dist/scaffolds/notis-journal/src/mock-runtime.ts +0 -197
- package/dist/scaffolds/notis-journal/tailwind.config.ts +0 -58
- package/dist/scaffolds/notis-journal/tsconfig.json +0 -23
- package/dist/scaffolds/notis-journal/vite.config.ts +0 -10
- package/dist/scaffolds/notis-notes/CHANGELOG.md +0 -5
- package/dist/scaffolds/notis-notes/app/globals.css +0 -3
- package/dist/scaffolds/notis-notes/app/layout.tsx +0 -6
- package/dist/scaffolds/notis-notes/app/page.tsx +0 -1943
- package/dist/scaffolds/notis-notes/app/phosphor-icons.ts +0 -596
- package/dist/scaffolds/notis-notes/components/ui/badge.tsx +0 -28
- package/dist/scaffolds/notis-notes/components/ui/button.tsx +0 -53
- package/dist/scaffolds/notis-notes/components/ui/card.tsx +0 -56
- package/dist/scaffolds/notis-notes/components.json +0 -20
- package/dist/scaffolds/notis-notes/lib/utils.ts +0 -6
- package/dist/scaffolds/notis-notes/lib/visible-properties.ts +0 -144
- package/dist/scaffolds/notis-notes/metadata/screenshot-1.png +0 -0
- package/dist/scaffolds/notis-notes/metadata/screenshot-2.png +0 -0
- package/dist/scaffolds/notis-notes/metadata/screenshot-3.png +0 -0
- package/dist/scaffolds/notis-notes/metadata/screenshot-4.png +0 -0
- package/dist/scaffolds/notis-notes/metadata/screenshot-5.png +0 -0
- package/dist/scaffolds/notis-notes/metadata/screenshot-fixtures.json +0 -752
- package/dist/scaffolds/notis-notes/notis.config.ts +0 -80
- package/dist/scaffolds/notis-notes/package-lock.json +0 -4636
- package/dist/scaffolds/notis-notes/package.json +0 -35
- package/dist/scaffolds/notis-notes/packages/sdk/package.json +0 -36
- package/dist/scaffolds/notis-notes/packages/sdk/src/components/DocumentEditor.tsx +0 -93
- package/dist/scaffolds/notis-notes/packages/sdk/src/components/Markdown.tsx +0 -60
- package/dist/scaffolds/notis-notes/packages/sdk/src/components/MultiSelectActionBar.tsx +0 -278
- package/dist/scaffolds/notis-notes/packages/sdk/src/components/MultiSelectCheckbox.tsx +0 -91
- package/dist/scaffolds/notis-notes/packages/sdk/src/components/MultiSelectDragOverlay.tsx +0 -39
- package/dist/scaffolds/notis-notes/packages/sdk/src/config.ts +0 -196
- package/dist/scaffolds/notis-notes/packages/sdk/src/documents.ts +0 -229
- package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useBackend.ts +0 -41
- package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useDatabaseSchema.ts +0 -85
- package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useDocument.ts +0 -78
- package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useDocuments.ts +0 -121
- package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useMultiSelect.ts +0 -539
- package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useNotis.ts +0 -34
- package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useNotisNavigation.ts +0 -49
- package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useTool.ts +0 -64
- package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useTools.ts +0 -56
- package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useTopBarSearch.ts +0 -73
- package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useUpsertDocument.ts +0 -95
- package/dist/scaffolds/notis-notes/packages/sdk/src/index.ts +0 -83
- package/dist/scaffolds/notis-notes/packages/sdk/src/provider.tsx +0 -43
- package/dist/scaffolds/notis-notes/packages/sdk/src/runtime.ts +0 -220
- package/dist/scaffolds/notis-notes/packages/sdk/src/styles.css +0 -186
- package/dist/scaffolds/notis-notes/packages/sdk/src/ui.ts +0 -15
- package/dist/scaffolds/notis-notes/packages/sdk/src/vite.ts +0 -56
- package/dist/scaffolds/notis-notes/packages/sdk/tsconfig.json +0 -15
- package/dist/scaffolds/notis-notes/postcss.config.mjs +0 -8
- package/dist/scaffolds/notis-notes/tailwind.config.ts +0 -58
- package/dist/scaffolds/notis-notes/tsconfig.json +0 -23
- package/dist/scaffolds/notis-notes/vite.config.ts +0 -10
- package/dist/scaffolds/notis-random/CHANGELOG.md +0 -15
- package/dist/scaffolds/notis-random/README.md +0 -33
- package/dist/scaffolds/notis-random/app/globals.css +0 -11
- package/dist/scaffolds/notis-random/app/history/page.tsx +0 -67
- package/dist/scaffolds/notis-random/app/layout.tsx +0 -7
- package/dist/scaffolds/notis-random/app/page.tsx +0 -289
- package/dist/scaffolds/notis-random/components/ui/button.tsx +0 -50
- package/dist/scaffolds/notis-random/components/ui/card.tsx +0 -16
- package/dist/scaffolds/notis-random/components/ui/input.tsx +0 -23
- package/dist/scaffolds/notis-random/components.json +0 -20
- package/dist/scaffolds/notis-random/index.html +0 -12
- package/dist/scaffolds/notis-random/lib/notis-tools.ts +0 -128
- package/dist/scaffolds/notis-random/lib/rng.ts +0 -202
- package/dist/scaffolds/notis-random/lib/roll-record.ts +0 -189
- package/dist/scaffolds/notis-random/lib/utils.ts +0 -25
- package/dist/scaffolds/notis-random/metadata/screenshot-1.png +0 -0
- package/dist/scaffolds/notis-random/metadata/screenshot-2.png +0 -0
- package/dist/scaffolds/notis-random/metadata/screenshot-3.png +0 -0
- package/dist/scaffolds/notis-random/metadata/screenshot-4.png +0 -0
- package/dist/scaffolds/notis-random/metadata/screenshot-5.png +0 -0
- package/dist/scaffolds/notis-random/metadata/screenshot-fixtures.json +0 -753
- package/dist/scaffolds/notis-random/notis.config.ts +0 -86
- package/dist/scaffolds/notis-random/package-lock.json +0 -4513
- package/dist/scaffolds/notis-random/package.json +0 -36
- package/dist/scaffolds/notis-random/packages/sdk/package.json +0 -36
- package/dist/scaffolds/notis-random/packages/sdk/src/components/DocumentEditor.tsx +0 -93
- package/dist/scaffolds/notis-random/packages/sdk/src/components/Markdown.tsx +0 -60
- package/dist/scaffolds/notis-random/packages/sdk/src/components/MultiSelectActionBar.tsx +0 -278
- package/dist/scaffolds/notis-random/packages/sdk/src/components/MultiSelectCheckbox.tsx +0 -91
- package/dist/scaffolds/notis-random/packages/sdk/src/components/MultiSelectDragOverlay.tsx +0 -39
- package/dist/scaffolds/notis-random/packages/sdk/src/config.ts +0 -196
- package/dist/scaffolds/notis-random/packages/sdk/src/documents.ts +0 -229
- package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useBackend.ts +0 -41
- package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useDatabaseSchema.ts +0 -85
- package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useDocument.ts +0 -78
- package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useDocuments.ts +0 -121
- package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useMultiSelect.ts +0 -539
- package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useNotis.ts +0 -34
- package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useNotisNavigation.ts +0 -49
- package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useTool.ts +0 -64
- package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useTools.ts +0 -56
- package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useTopBarSearch.ts +0 -73
- package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useUpsertDocument.ts +0 -95
- package/dist/scaffolds/notis-random/packages/sdk/src/index.ts +0 -83
- package/dist/scaffolds/notis-random/packages/sdk/src/provider.tsx +0 -43
- package/dist/scaffolds/notis-random/packages/sdk/src/runtime.ts +0 -220
- package/dist/scaffolds/notis-random/packages/sdk/src/styles.css +0 -186
- package/dist/scaffolds/notis-random/packages/sdk/src/ui.ts +0 -15
- package/dist/scaffolds/notis-random/packages/sdk/src/vite.ts +0 -56
- package/dist/scaffolds/notis-random/packages/sdk/tsconfig.json +0 -15
- package/dist/scaffolds/notis-random/postcss.config.mjs +0 -6
- package/dist/scaffolds/notis-random/src/dev-main.tsx +0 -70
- package/dist/scaffolds/notis-random/src/mock-runtime.ts +0 -129
- package/dist/scaffolds/notis-random/tailwind.config.ts +0 -50
- package/dist/scaffolds/notis-random/tsconfig.json +0 -23
- package/dist/scaffolds/notis-random/vite.config.ts +0 -11
- package/dist/scaffolds.json +0 -49
- package/template/metadata/screenshot-1.png +0 -0
- package/template/metadata/screenshot-2.png +0 -0
- package/template/metadata/screenshot-3.png +0 -0
|
@@ -1,289 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { useCallback, useMemo, useState } from 'react';
|
|
4
|
-
import { useNotis, useNotisNavigation } from '@notis/sdk';
|
|
5
|
-
import { DiceFiveIcon as Dices, SparkleIcon as Sparkles, ClockCounterClockwiseIcon as History, ArrowRightIcon as ArrowRight, HashIcon as Hash, PercentIcon as Percent, InfinityIcon, ArrowClockwiseIcon as RefreshCw, WarningCircleIcon as WarningCircle } from '@phosphor-icons/react';
|
|
6
|
-
import { Button } from '@/components/ui/button';
|
|
7
|
-
import { Card } from '@/components/ui/card';
|
|
8
|
-
import { Input } from '@/components/ui/input';
|
|
9
|
-
import { cn, formatNumber, relativeTime } from '@/lib/utils';
|
|
10
|
-
import { DICE_SIDES, DEFAULT_DICE_SIDES, type DiceSides, type Mode, type Roll, checkBounds, parseBoundDraft, roll } from '@/lib/rng';
|
|
11
|
-
import { normalizeRollRecord, sortRollRecordsDesc } from '@/lib/roll-record';
|
|
12
|
-
import { usePersistRoll, useRollDocuments } from '@/lib/notis-tools';
|
|
13
|
-
|
|
14
|
-
const MODES: Array<{ id: Mode; label: string; icon: typeof Hash; hint: string }> = [
|
|
15
|
-
{ id: 'integer', label: 'Integer', icon: Hash, hint: 'Whole numbers only' },
|
|
16
|
-
{ id: 'decimal', label: 'Decimal', icon: Percent, hint: 'Continuous range' },
|
|
17
|
-
{ id: 'dice', label: 'Dice', icon: Dices, hint: 'Standard polyhedral dice' },
|
|
18
|
-
];
|
|
19
|
-
|
|
20
|
-
export default function HomePage() {
|
|
21
|
-
const { app, ready } = useNotis();
|
|
22
|
-
const nav = useNotisNavigation();
|
|
23
|
-
const { documents, loading, refetch } = useRollDocuments(5);
|
|
24
|
-
const { persist: persistRoll } = usePersistRoll();
|
|
25
|
-
|
|
26
|
-
const [mode, setMode] = useState<Mode>('integer');
|
|
27
|
-
const [minDraft, setMinDraft] = useState('1');
|
|
28
|
-
const [maxDraft, setMaxDraft] = useState('100');
|
|
29
|
-
const [sides, setSides] = useState<DiceSides>(DEFAULT_DICE_SIDES);
|
|
30
|
-
const [current, setCurrent] = useState<Roll | null>(null);
|
|
31
|
-
const [rolling, setRolling] = useState(false);
|
|
32
|
-
const [saveError, setSaveError] = useState<string | null>(null);
|
|
33
|
-
|
|
34
|
-
const recent = useMemo(
|
|
35
|
-
() => documents
|
|
36
|
-
.map(normalizeRollRecord)
|
|
37
|
-
.sort(sortRollRecordsDesc)
|
|
38
|
-
.slice(0, 5),
|
|
39
|
-
[documents],
|
|
40
|
-
);
|
|
41
|
-
|
|
42
|
-
// Dice mode draws from 1..sides; the manual range inputs drive the other modes.
|
|
43
|
-
const bounds = useMemo(
|
|
44
|
-
() => (
|
|
45
|
-
mode === 'dice'
|
|
46
|
-
? { min: 1, max: sides }
|
|
47
|
-
: {
|
|
48
|
-
min: parseBoundDraft(minDraft),
|
|
49
|
-
max: parseBoundDraft(maxDraft),
|
|
50
|
-
}
|
|
51
|
-
),
|
|
52
|
-
[mode, sides, minDraft, maxDraft],
|
|
53
|
-
);
|
|
54
|
-
const check = useMemo(
|
|
55
|
-
() => checkBounds(bounds.min, bounds.max, mode),
|
|
56
|
-
[bounds.min, bounds.max, mode],
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
const generate = useCallback(async () => {
|
|
60
|
-
if (rolling || !check.ok) return;
|
|
61
|
-
setRolling(true);
|
|
62
|
-
setSaveError(null);
|
|
63
|
-
try {
|
|
64
|
-
// roll() throws on unusable bounds, and persist() can fail on the network.
|
|
65
|
-
// Both have to leave `rolling` false or the button would stay stuck.
|
|
66
|
-
const next = roll(bounds.min, bounds.max, mode);
|
|
67
|
-
setCurrent(next);
|
|
68
|
-
await persistRoll(next);
|
|
69
|
-
refetch();
|
|
70
|
-
} catch (err) {
|
|
71
|
-
setSaveError(err instanceof Error ? err.message : 'Could not save this roll.');
|
|
72
|
-
} finally {
|
|
73
|
-
setRolling(false);
|
|
74
|
-
}
|
|
75
|
-
}, [rolling, check.ok, bounds.min, bounds.max, mode, persistRoll, refetch]);
|
|
76
|
-
|
|
77
|
-
return (
|
|
78
|
-
<main data-store-screenshot="generator" className="notis-random-shell space-y-6">
|
|
79
|
-
<header className="flex items-start justify-between gap-6">
|
|
80
|
-
<div className="space-y-1.5">
|
|
81
|
-
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
|
82
|
-
<Sparkles className="h-3.5 w-3.5" />
|
|
83
|
-
<span>{ready ? app?.name : 'Loading…'}</span>
|
|
84
|
-
</div>
|
|
85
|
-
<h1 className="text-2xl font-semibold tracking-tight text-foreground">Generator</h1>
|
|
86
|
-
<p className="text-sm text-muted-foreground max-w-md">
|
|
87
|
-
Pick a mode, set the range, and press generate. Every roll is saved to the History view.
|
|
88
|
-
</p>
|
|
89
|
-
</div>
|
|
90
|
-
<Button
|
|
91
|
-
type="button"
|
|
92
|
-
variant="outline"
|
|
93
|
-
size="sm"
|
|
94
|
-
onClick={() => refetch()}
|
|
95
|
-
className="gap-2 border-border text-muted-foreground hover:text-foreground"
|
|
96
|
-
>
|
|
97
|
-
<RefreshCw className={cn('h-3.5 w-3.5', loading && 'animate-spin')} />
|
|
98
|
-
Refresh
|
|
99
|
-
</Button>
|
|
100
|
-
</header>
|
|
101
|
-
|
|
102
|
-
{/* The dial and the controls sit side by side so the whole generator —
|
|
103
|
-
result, mode, range, and recent rolls — stays above the fold. */}
|
|
104
|
-
<section className="grid gap-6 lg:grid-cols-[1.05fr_1fr]">
|
|
105
|
-
<Card className="flex flex-col items-center justify-center gap-5 rounded-2xl p-6">
|
|
106
|
-
<div
|
|
107
|
-
className={cn(
|
|
108
|
-
'flex items-center justify-center rounded-full border border-border bg-background',
|
|
109
|
-
'h-40 w-40 transition-transform',
|
|
110
|
-
rolling && 'animate-pulse',
|
|
111
|
-
)}
|
|
112
|
-
>
|
|
113
|
-
{current ? (
|
|
114
|
-
<span className="font-mono text-5xl font-semibold tabular-nums text-foreground">
|
|
115
|
-
{formatNumber(current.value)}
|
|
116
|
-
</span>
|
|
117
|
-
) : (
|
|
118
|
-
<InfinityIcon className="h-10 w-10 text-muted-foreground" strokeWidth={1.2} />
|
|
119
|
-
)}
|
|
120
|
-
</div>
|
|
121
|
-
<Button
|
|
122
|
-
type="button"
|
|
123
|
-
size="lg"
|
|
124
|
-
data-action="generate"
|
|
125
|
-
onClick={generate}
|
|
126
|
-
disabled={rolling || !check.ok}
|
|
127
|
-
className="gap-2 rounded-full px-6"
|
|
128
|
-
>
|
|
129
|
-
<Dices className="h-4 w-4" />
|
|
130
|
-
{rolling ? 'Rolling…' : current ? 'Roll again' : 'Generate'}
|
|
131
|
-
</Button>
|
|
132
|
-
{check.issue ? (
|
|
133
|
-
<p className="flex items-center gap-1.5 text-xs text-destructive">
|
|
134
|
-
<WarningCircle className="h-3.5 w-3.5 shrink-0" />
|
|
135
|
-
{check.issue.message}
|
|
136
|
-
</p>
|
|
137
|
-
) : current ? (
|
|
138
|
-
<p className="text-xs text-muted-foreground">
|
|
139
|
-
<span className="font-mono">[{formatNumber(current.min)}, {formatNumber(current.max)}]</span>
|
|
140
|
-
{' · '}{current.mode}
|
|
141
|
-
</p>
|
|
142
|
-
) : null}
|
|
143
|
-
{saveError && (
|
|
144
|
-
<p className="flex items-center gap-1.5 text-xs text-destructive">
|
|
145
|
-
<WarningCircle className="h-3.5 w-3.5 shrink-0" />
|
|
146
|
-
{saveError}
|
|
147
|
-
</p>
|
|
148
|
-
)}
|
|
149
|
-
</Card>
|
|
150
|
-
|
|
151
|
-
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-1">
|
|
152
|
-
<Card className="p-5">
|
|
153
|
-
<h2 className="mb-3 text-sm font-medium text-foreground">Mode</h2>
|
|
154
|
-
<div className="grid gap-2">
|
|
155
|
-
{MODES.map(({ id, label, icon: Icon, hint }) => (
|
|
156
|
-
<Button
|
|
157
|
-
key={id}
|
|
158
|
-
type="button"
|
|
159
|
-
variant="outline"
|
|
160
|
-
data-mode={id}
|
|
161
|
-
onClick={() => setMode(id)}
|
|
162
|
-
className={cn(
|
|
163
|
-
'h-auto w-full justify-start gap-3 px-3 py-2.5 text-left whitespace-normal',
|
|
164
|
-
mode === id
|
|
165
|
-
? 'border-foreground bg-accent text-accent-foreground'
|
|
166
|
-
: 'border-border hover:bg-accent/50',
|
|
167
|
-
)}
|
|
168
|
-
>
|
|
169
|
-
<Icon className="h-4 w-4 shrink-0" strokeWidth={1.5} />
|
|
170
|
-
<div className="flex-1 min-w-0">
|
|
171
|
-
<div className="text-sm font-medium">{label}</div>
|
|
172
|
-
<div className="text-xs text-muted-foreground">{hint}</div>
|
|
173
|
-
</div>
|
|
174
|
-
</Button>
|
|
175
|
-
))}
|
|
176
|
-
</div>
|
|
177
|
-
</Card>
|
|
178
|
-
|
|
179
|
-
<Card className="space-y-4 p-5">
|
|
180
|
-
<h2 className="text-sm font-medium text-foreground">
|
|
181
|
-
{mode === 'dice' ? 'Die' : 'Range'}
|
|
182
|
-
</h2>
|
|
183
|
-
{mode === 'dice' ? (
|
|
184
|
-
<>
|
|
185
|
-
<div className="flex flex-wrap gap-2">
|
|
186
|
-
{DICE_SIDES.map((n) => (
|
|
187
|
-
<Button
|
|
188
|
-
key={n}
|
|
189
|
-
type="button"
|
|
190
|
-
variant="outline"
|
|
191
|
-
data-die={n}
|
|
192
|
-
onClick={() => setSides(n)}
|
|
193
|
-
className={cn(
|
|
194
|
-
'h-10 min-w-[3.25rem] px-3 font-mono',
|
|
195
|
-
sides === n
|
|
196
|
-
? 'border-foreground bg-accent text-accent-foreground'
|
|
197
|
-
: 'border-border hover:bg-accent/50',
|
|
198
|
-
)}
|
|
199
|
-
>
|
|
200
|
-
d{n}
|
|
201
|
-
</Button>
|
|
202
|
-
))}
|
|
203
|
-
</div>
|
|
204
|
-
<p className="text-xs text-muted-foreground">
|
|
205
|
-
Rolls a whole number from 1 to {sides}, each equally likely.
|
|
206
|
-
</p>
|
|
207
|
-
</>
|
|
208
|
-
) : (
|
|
209
|
-
<>
|
|
210
|
-
<div className="grid grid-cols-2 gap-3">
|
|
211
|
-
<RangeInput label="Minimum" name="min" value={minDraft} onChange={setMinDraft} />
|
|
212
|
-
<RangeInput label="Maximum" name="max" value={maxDraft} onChange={setMaxDraft} />
|
|
213
|
-
</div>
|
|
214
|
-
<p className="text-xs text-muted-foreground">
|
|
215
|
-
{mode === 'decimal'
|
|
216
|
-
? 'Decimal draws include the minimum but never reach the maximum.'
|
|
217
|
-
: 'Integer draws include both ends of the range.'}
|
|
218
|
-
</p>
|
|
219
|
-
</>
|
|
220
|
-
)}
|
|
221
|
-
</Card>
|
|
222
|
-
</div>
|
|
223
|
-
</section>
|
|
224
|
-
|
|
225
|
-
<Card className="p-5">
|
|
226
|
-
<header className="mb-4 flex items-center justify-between gap-3">
|
|
227
|
-
<h2 className="flex items-center gap-2 text-sm font-medium text-foreground">
|
|
228
|
-
<History className="h-4 w-4 text-muted-foreground" strokeWidth={1.5} />
|
|
229
|
-
Recent rolls
|
|
230
|
-
</h2>
|
|
231
|
-
<Button
|
|
232
|
-
type="button"
|
|
233
|
-
variant="ghost"
|
|
234
|
-
size="sm"
|
|
235
|
-
onClick={() => nav.toRoute('/history')}
|
|
236
|
-
className="h-auto gap-1 px-2 py-1 text-xs text-muted-foreground hover:text-foreground"
|
|
237
|
-
>
|
|
238
|
-
View all <ArrowRight className="h-3 w-3" />
|
|
239
|
-
</Button>
|
|
240
|
-
</header>
|
|
241
|
-
{loading && recent.length === 0 ? (
|
|
242
|
-
<p className="text-sm text-muted-foreground">Loading…</p>
|
|
243
|
-
) : recent.length === 0 ? (
|
|
244
|
-
<div className="rounded-md border border-dashed border-border px-4 py-8 text-center text-sm text-muted-foreground">
|
|
245
|
-
Nothing rolled yet. Press Generate to see history here.
|
|
246
|
-
</div>
|
|
247
|
-
) : (
|
|
248
|
-
<ul className="divide-y divide-border">
|
|
249
|
-
{recent.map((r) => (
|
|
250
|
-
<li key={r.id} className="flex items-center justify-between py-2.5">
|
|
251
|
-
<div className="flex items-center gap-3">
|
|
252
|
-
<span className="font-mono text-lg tabular-nums text-foreground">{formatNumber(r.value)}</span>
|
|
253
|
-
<span className="text-xs text-muted-foreground">{r.mode}</span>
|
|
254
|
-
</div>
|
|
255
|
-
<span className="text-xs text-muted-foreground">{relativeTime(r.at)}</span>
|
|
256
|
-
</li>
|
|
257
|
-
))}
|
|
258
|
-
</ul>
|
|
259
|
-
)}
|
|
260
|
-
</Card>
|
|
261
|
-
</main>
|
|
262
|
-
);
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
function RangeInput({
|
|
266
|
-
label,
|
|
267
|
-
name,
|
|
268
|
-
value,
|
|
269
|
-
onChange,
|
|
270
|
-
}: {
|
|
271
|
-
label: string;
|
|
272
|
-
name: string;
|
|
273
|
-
value: string;
|
|
274
|
-
onChange: (v: string) => void;
|
|
275
|
-
}) {
|
|
276
|
-
return (
|
|
277
|
-
<label className="block space-y-1.5">
|
|
278
|
-
<span className="text-xs font-medium text-muted-foreground">{label}</span>
|
|
279
|
-
<Input
|
|
280
|
-
type="text"
|
|
281
|
-
inputMode="decimal"
|
|
282
|
-
data-bound={name}
|
|
283
|
-
value={value}
|
|
284
|
-
onChange={(e) => onChange(e.target.value)}
|
|
285
|
-
className="border-border font-mono"
|
|
286
|
-
/>
|
|
287
|
-
</label>
|
|
288
|
-
);
|
|
289
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { Slot } from '@radix-ui/react-slot';
|
|
3
|
-
import { cva, type VariantProps } from 'class-variance-authority';
|
|
4
|
-
|
|
5
|
-
import { cn } from '@/lib/utils';
|
|
6
|
-
|
|
7
|
-
const buttonVariants = cva(
|
|
8
|
-
'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',
|
|
9
|
-
{
|
|
10
|
-
variants: {
|
|
11
|
-
variant: {
|
|
12
|
-
default: 'bg-foreground text-background hover:bg-foreground/90',
|
|
13
|
-
outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
|
|
14
|
-
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
|
15
|
-
},
|
|
16
|
-
size: {
|
|
17
|
-
default: 'h-10 px-4 py-2',
|
|
18
|
-
sm: 'h-9 rounded-md px-3',
|
|
19
|
-
lg: 'h-11 rounded-md px-8',
|
|
20
|
-
icon: 'h-10 w-10',
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
defaultVariants: {
|
|
24
|
-
variant: 'default',
|
|
25
|
-
size: 'default',
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
export interface ButtonProps
|
|
31
|
-
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
32
|
-
VariantProps<typeof buttonVariants> {
|
|
33
|
-
asChild?: boolean;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
37
|
-
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
38
|
-
const Comp = asChild ? Slot : 'button';
|
|
39
|
-
return (
|
|
40
|
-
<Comp
|
|
41
|
-
className={cn(buttonVariants({ variant, size, className }))}
|
|
42
|
-
ref={ref}
|
|
43
|
-
{...props}
|
|
44
|
-
/>
|
|
45
|
-
);
|
|
46
|
-
},
|
|
47
|
-
);
|
|
48
|
-
Button.displayName = 'Button';
|
|
49
|
-
|
|
50
|
-
export { Button, buttonVariants };
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
|
|
3
|
-
import { cn } from '@/lib/utils';
|
|
4
|
-
|
|
5
|
-
const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
6
|
-
({ className, ...props }, ref) => (
|
|
7
|
-
<div
|
|
8
|
-
ref={ref}
|
|
9
|
-
className={cn('rounded-xl border border-border bg-card text-card-foreground', className)}
|
|
10
|
-
{...props}
|
|
11
|
-
/>
|
|
12
|
-
),
|
|
13
|
-
);
|
|
14
|
-
Card.displayName = 'Card';
|
|
15
|
-
|
|
16
|
-
export { Card };
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
|
|
3
|
-
import { cn } from '@/lib/utils';
|
|
4
|
-
|
|
5
|
-
const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(
|
|
6
|
-
({ className, type, ...props }, ref) => (
|
|
7
|
-
<input
|
|
8
|
-
type={type}
|
|
9
|
-
className={cn(
|
|
10
|
-
'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground ring-offset-background',
|
|
11
|
-
'file:border-0 file:bg-transparent file:text-sm file:font-medium',
|
|
12
|
-
'placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
|
|
13
|
-
'disabled:cursor-not-allowed disabled:opacity-50',
|
|
14
|
-
className,
|
|
15
|
-
)}
|
|
16
|
-
ref={ref}
|
|
17
|
-
{...props}
|
|
18
|
-
/>
|
|
19
|
-
),
|
|
20
|
-
);
|
|
21
|
-
Input.displayName = 'Input';
|
|
22
|
-
|
|
23
|
-
export { Input };
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ui.shadcn.com/schema.json",
|
|
3
|
-
"style": "new-york",
|
|
4
|
-
"rsc": false,
|
|
5
|
-
"tsx": true,
|
|
6
|
-
"tailwind": {
|
|
7
|
-
"config": "tailwind.config.ts",
|
|
8
|
-
"css": "app/globals.css",
|
|
9
|
-
"baseColor": "zinc",
|
|
10
|
-
"cssVariables": true,
|
|
11
|
-
"prefix": ""
|
|
12
|
-
},
|
|
13
|
-
"aliases": {
|
|
14
|
-
"components": "@/components",
|
|
15
|
-
"utils": "@/lib/utils",
|
|
16
|
-
"ui": "@/components/ui",
|
|
17
|
-
"lib": "@/lib",
|
|
18
|
-
"hooks": "@/hooks"
|
|
19
|
-
}
|
|
20
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>Random Number Generator (dev preview)</title>
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
9
|
-
<div id="root"></div>
|
|
10
|
-
<script type="module" src="/src/dev-main.tsx"></script>
|
|
11
|
-
</body>
|
|
12
|
-
</html>
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { useCallback, useEffect, useState } from 'react';
|
|
4
|
-
import { useTool } from '@notis/sdk';
|
|
5
|
-
import type { RollDocument } from '@/lib/roll-record';
|
|
6
|
-
import type { Roll } from '@/lib/rng';
|
|
7
|
-
import { formatNumber } from '@/lib/utils';
|
|
8
|
-
|
|
9
|
-
type QueryRollsArgs = {
|
|
10
|
-
database_slug: 'rolls';
|
|
11
|
-
query?: {
|
|
12
|
-
page_size?: number;
|
|
13
|
-
};
|
|
14
|
-
offset?: number;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
type QueryRollsResult = {
|
|
18
|
-
documents?: RollDocument[];
|
|
19
|
-
has_more?: boolean;
|
|
20
|
-
next_offset?: number | null;
|
|
21
|
-
message?: string;
|
|
22
|
-
error?: string;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
type UpsertRollArgs = {
|
|
26
|
-
title: string;
|
|
27
|
-
Value: number;
|
|
28
|
-
Mode: Roll['mode'];
|
|
29
|
-
Min: number;
|
|
30
|
-
Max: number;
|
|
31
|
-
'Rolled At': string;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
type UpsertRollResult = {
|
|
35
|
-
status?: string;
|
|
36
|
-
document?: RollDocument;
|
|
37
|
-
message?: string;
|
|
38
|
-
error?: string;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export function useRollDocuments(pageSize = 20, fetchAll = false) {
|
|
42
|
-
const queryRolls = useTool<QueryRollsArgs, QueryRollsResult>('LOCAL_NOTIS_DATABASE_QUERY');
|
|
43
|
-
const [documents, setDocuments] = useState<RollDocument[]>([]);
|
|
44
|
-
const [error, setError] = useState<Error | null>(null);
|
|
45
|
-
const [fetchKey, setFetchKey] = useState(0);
|
|
46
|
-
|
|
47
|
-
const refetch = useCallback(() => {
|
|
48
|
-
setFetchKey((key) => key + 1);
|
|
49
|
-
}, []);
|
|
50
|
-
|
|
51
|
-
useEffect(() => {
|
|
52
|
-
let cancelled = false;
|
|
53
|
-
setError(null);
|
|
54
|
-
|
|
55
|
-
const fetchRolls = async (): Promise<RollDocument[]> => {
|
|
56
|
-
const allDocuments: RollDocument[] = [];
|
|
57
|
-
let offset = 0;
|
|
58
|
-
while (true) {
|
|
59
|
-
const result = await queryRolls.call({
|
|
60
|
-
database_slug: 'rolls',
|
|
61
|
-
query: { page_size: pageSize },
|
|
62
|
-
...(offset > 0 ? { offset } : {}),
|
|
63
|
-
});
|
|
64
|
-
const message = result.error ?? result.message;
|
|
65
|
-
if (message && !result.documents) {
|
|
66
|
-
throw new Error(message);
|
|
67
|
-
}
|
|
68
|
-
allDocuments.push(...(result.documents ?? []));
|
|
69
|
-
if (!fetchAll || !result.has_more) return allDocuments;
|
|
70
|
-
if (typeof result.next_offset !== 'number' || result.next_offset <= offset) {
|
|
71
|
-
throw new Error('Roll history returned an invalid pagination offset.');
|
|
72
|
-
}
|
|
73
|
-
offset = result.next_offset;
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
fetchRolls()
|
|
78
|
-
.then((result) => {
|
|
79
|
-
if (cancelled) return;
|
|
80
|
-
setDocuments(result);
|
|
81
|
-
})
|
|
82
|
-
.catch((err) => {
|
|
83
|
-
if (cancelled) return;
|
|
84
|
-
setError(err instanceof Error ? err : new Error(String(err)));
|
|
85
|
-
setDocuments([]);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
return () => {
|
|
89
|
-
cancelled = true;
|
|
90
|
-
};
|
|
91
|
-
}, [fetchAll, fetchKey, pageSize, queryRolls.call]);
|
|
92
|
-
|
|
93
|
-
return {
|
|
94
|
-
documents,
|
|
95
|
-
loading: queryRolls.loading,
|
|
96
|
-
error: queryRolls.error ?? error,
|
|
97
|
-
refetch,
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export function usePersistRoll() {
|
|
102
|
-
const upsertRoll = useTool<UpsertRollArgs, UpsertRollResult>('LOCAL_NOTIS_DATABASE_UPSERT_ROLLS');
|
|
103
|
-
|
|
104
|
-
const persist = useCallback(
|
|
105
|
-
async (roll: Roll) => {
|
|
106
|
-
const result = await upsertRoll.call({
|
|
107
|
-
title: formatNumber(roll.value),
|
|
108
|
-
Value: roll.value,
|
|
109
|
-
Mode: roll.mode,
|
|
110
|
-
Min: roll.min,
|
|
111
|
-
Max: roll.max,
|
|
112
|
-
'Rolled At': roll.at,
|
|
113
|
-
});
|
|
114
|
-
const message = result.error ?? result.message;
|
|
115
|
-
if (message && result.status === 'error') {
|
|
116
|
-
throw new Error(message);
|
|
117
|
-
}
|
|
118
|
-
return result.document ?? null;
|
|
119
|
-
},
|
|
120
|
-
[upsertRoll.call],
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
return {
|
|
124
|
-
persist,
|
|
125
|
-
loading: upsertRoll.loading,
|
|
126
|
-
error: upsertRoll.error,
|
|
127
|
-
};
|
|
128
|
-
}
|