deepspace 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +22 -8
  3. package/dist/cli.js +10306 -5256
  4. package/dist/cli.js.map +1 -1
  5. package/dist/feature-installer.js +638 -0
  6. package/dist/feature-installer.js.map +1 -0
  7. package/dist/index.d.ts +107 -117
  8. package/dist/index.js +610 -779
  9. package/dist/index.js.map +1 -1
  10. package/dist/server.d.ts +403 -167
  11. package/dist/server.js +498 -367
  12. package/dist/server.js.map +1 -1
  13. package/dist/testing.d.ts +115 -0
  14. package/dist/testing.js +3 -3
  15. package/dist/testing.js.map +1 -1
  16. package/dist/worker.d.ts +397 -160
  17. package/dist/worker.js +506 -367
  18. package/dist/worker.js.map +1 -1
  19. package/features/ai-chat/feature.json +2 -0
  20. package/features/ai-chat/src/AiChatPage.tsx +2 -3
  21. package/features/ai-chat/src/ChatPanel.messages.tsx +344 -0
  22. package/features/ai-chat/src/ChatPanel.stream.ts +397 -0
  23. package/features/ai-chat/src/ChatPanel.tsx +158 -862
  24. package/features/ai-chat/src/__tests__/ChatPanel.stream.test.ts +163 -0
  25. package/features/canvas/src/CanvasListPage.tsx +1 -1
  26. package/features/docs/feature.json +4 -8
  27. package/features/docs/src/DocsEditorPage.tsx +33 -326
  28. package/features/docs/src/DocsListPage.tsx +33 -29
  29. package/features/docs/src/InviteDialog.tsx +11 -40
  30. package/features/docs/src/__tests__/docs-presence-access.test.ts +71 -0
  31. package/features/docs/src/docs-library-types.ts +28 -3
  32. package/features/docs/src/docs-ui.css +1 -4
  33. package/features/docs/src/use-docs-presence-access.ts +330 -0
  34. package/features/file-attachments/feature.json +2 -2
  35. package/features/file-attachments/src/AttachmentPreview.tsx +428 -0
  36. package/features/file-attachments/src/AttachmentsPage.tsx +100 -462
  37. package/features/file-attachments/src/useFilePreview.ts +54 -68
  38. package/features/file-manager/src/FileManagerPage.tsx +1 -1
  39. package/features/integration-test/src/integration.spec.ts +1 -1
  40. package/features/items/feature.json +1 -5
  41. package/features/items/src/ItemsPage.tsx +207 -135
  42. package/features/landing/feature.json +3 -0
  43. package/features/landing/src/LandingPage.tsx +4 -18
  44. package/features/leaderboard/feature.json +1 -5
  45. package/features/leaderboard/src/LeaderboardPage.tsx +333 -198
  46. package/features/messaging/feature.json +0 -4
  47. package/features/messaging/src/ChatMultiPage.tsx +1 -3
  48. package/features/messaging/src/ChatPage.tsx +1 -3
  49. package/features/messaging/src/components/chat/MessageActionSheet.tsx +40 -16
  50. package/features/search-bar/feature.json +8 -3
  51. package/features/search-bar/src/SearchOverlay.tsx +108 -252
  52. package/features/search-bar/src/__tests__/search-model.test.ts +40 -0
  53. package/features/search-bar/src/search-model.ts +223 -0
  54. package/features/tasks/src/TasksPage.tsx +3 -3
  55. package/features/topbar/src/Topbar.tsx +0 -17
  56. package/package.json +1 -2
  57. package/features/docs/src/docs-favorites.ts +0 -18
  58. package/features/docs/src/use-yjs-room-with-awareness.ts +0 -289
  59. package/features/file-attachments/src/attachments-constants.ts +0 -9
  60. package/features/items/src/items-constants.ts +0 -10
  61. package/features/leaderboard/src/leaderboard-constants.ts +0 -21
  62. package/features/messaging/src/components/chat/ReactionPicker.tsx +0 -2
  63. package/scripts/add-feature.cjs +0 -807
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/commands/feature-installer.ts","../src/cli/lib/package-manager.ts"],"sourcesContent":["/**\n * The feature catalog and installer.\n *\n * This is a separate build entry because `add` loads the copy shipped by the\n * target app's installed `deepspace` package. That keeps feature files,\n * manifest interpretation, and mutations on the app-pinned SDK version while\n * leaving the public command/output contract in add.ts.\n */\n\nimport {\n closeSync,\n copyFileSync,\n existsSync,\n fstatSync,\n mkdirSync,\n mkdtempSync,\n openSync,\n readFileSync,\n readSync,\n readdirSync,\n rmSync,\n writeFileSync,\n} from 'node:fs'\nimport { spawnSync } from 'node:child_process'\nimport { tmpdir } from 'node:os'\nimport { dirname, isAbsolute, join, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { detectPackageManager } from '../lib/package-manager'\n\nconst NAV_MARKER = '// ── Features add nav items below this line ──'\n\ninterface FeatureFile {\n src: string\n dest: string\n overwrite?: boolean\n}\n\ninterface FeatureSchema {\n exportName: string\n importPath: string\n spreadOperator?: boolean\n}\n\ninterface FeatureAction {\n exportName: string\n registerAs: string\n importPath: string\n}\n\nexport interface FeatureConfig {\n id: string\n name: string\n category?: string\n description?: string\n details?: string\n internal?: boolean\n files: FeatureFile[]\n route?: { path?: string; protected?: boolean }\n schema?: FeatureSchema\n actions?: FeatureAction[]\n css?: string[]\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n instructions?: string[]\n patterns?: string[]\n agentNotes?: string[]\n example?: string\n [key: string]: unknown\n}\n\nexport interface FeatureCatalogEntry {\n id: string\n name: string\n category: string | null\n description: string | null\n}\n\ntype DependencySection = 'dependencies' | 'devDependencies'\n\ninterface DependencyAddition {\n name: string\n section: DependencySection\n version: unknown\n}\n\ntype IntegrationArea = 'schema' | 'actions' | 'css' | 'nav'\n\ninterface UnresolvedIntegration {\n area: IntegrationArea\n reason: string\n steps: string[]\n}\n\ninterface InstallData extends Record<string, unknown> {\n feature: string\n dir: string\n installed: boolean\n observedChanges: {\n files: { created: string[]; preexisting: string[]; missing: string[] }\n dependencies: {\n added: DependencyAddition[]\n missingDeclarations: string[]\n installRequested: boolean\n diagnosticTail?: string\n }\n }\n unresolvedIntegrations: UnresolvedIntegration[]\n manifestGuidance: {\n instructions: string[]\n patterns: string[]\n agentNotes: string[]\n }\n}\n\ninterface InstallerAction {\n cwd: string\n argv: string[]\n}\n\nexport type FeatureInstallOutcome =\n | { ok: true; data: InstallData; action?: InstallerAction }\n | {\n ok: false\n code: 'unknown_feature'\n error: string\n data: {\n requestedFeature: string\n suggestedFeature: string | null\n availableFeatures: FeatureCatalogEntry[]\n }\n }\n | {\n ok: false\n code: 'dependency_install_failed' | 'manual_integration_required'\n error: string\n data: InstallData\n }\n\nexport type FeatureInstallerOutput = (line: string, stream?: 'stdout' | 'stderr') => void\n\nexport interface FeatureInstallOptions {\n feature: string\n targetDir: string\n installDependencies: boolean\n emit?: FeatureInstallerOutput\n}\n\n/** Find the package containing this source file or emitted build entry. */\nexport function featurePackageRoot(moduleUrl: string = import.meta.url): string {\n let dir = dirname(fileURLToPath(moduleUrl))\n for (;;) {\n const packagePath = join(dir, 'package.json')\n if (existsSync(packagePath)) {\n try {\n const pkg = JSON.parse(readFileSync(packagePath, 'utf-8')) as { name?: unknown }\n if (pkg.name === 'deepspace') return dir\n } catch {\n // Keep walking: a nearer unrelated package.json is not this package.\n }\n }\n const parent = dirname(dir)\n if (parent === dir) throw new Error('Could not locate the deepspace package root')\n dir = parent\n }\n}\n\nexport function hasFeatureCatalog(packageRoot: string = featurePackageRoot()): boolean {\n return existsSync(join(packageRoot, 'features'))\n}\n\nexport function readFeatureConfig(\n id: string,\n packageRoot: string = featurePackageRoot(),\n): FeatureConfig | null {\n const configPath = join(packageRoot, 'features', id, 'feature.json')\n if (!existsSync(configPath)) return null\n try {\n const config = JSON.parse(readFileSync(configPath, 'utf-8')) as Partial<FeatureConfig>\n if (\n typeof config.id !== 'string' ||\n typeof config.name !== 'string' ||\n !Array.isArray(config.files)\n ) {\n return null\n }\n return config as FeatureConfig\n } catch {\n return null\n }\n}\n\nexport function listFeatureConfigs(packageRoot: string = featurePackageRoot()): FeatureConfig[] {\n const featuresDir = join(packageRoot, 'features')\n if (!existsSync(featuresDir)) return []\n return readdirSync(featuresDir, { withFileTypes: true })\n .filter((entry) => entry.isDirectory())\n .map((entry) => readFeatureConfig(entry.name, packageRoot))\n .filter((config): config is FeatureConfig => config !== null && !config.internal)\n .sort((a, b) => a.id.localeCompare(b.id))\n}\n\nexport function featureCatalog(packageRoot: string = featurePackageRoot()): FeatureCatalogEntry[] {\n return listFeatureConfigs(packageRoot).map((config) => ({\n id: config.id,\n name: config.name,\n category: config.category ?? null,\n description: config.description ?? null,\n }))\n}\n\nfunction editDistance(a: string, b: string): number {\n const row = Array.from({ length: b.length + 1 }, (_, index) => index)\n for (let i = 1; i <= a.length; i++) {\n let previous = row[0]\n row[0] = i\n for (let j = 1; j <= b.length; j++) {\n const current = row[j]\n row[j] = Math.min(row[j] + 1, row[j - 1] + 1, previous + (a[i - 1] === b[j - 1] ? 0 : 1))\n previous = current\n }\n }\n return row[b.length]\n}\n\nexport function suggestFeature(\n featureId: string,\n packageRoot: string = featurePackageRoot(),\n): string | null {\n let closest: string | null = null\n let closestDistance = Number.POSITIVE_INFINITY\n for (const feature of listFeatureConfigs(packageRoot)) {\n const distance = editDistance(featureId, feature.id)\n if (distance < closestDistance) {\n closest = feature.id\n closestDistance = distance\n }\n }\n const threshold = Math.max(2, Math.floor(featureId.length / 3))\n return closest !== null && closestDistance <= threshold ? closest : null\n}\n\nfunction resolveTargetDir(raw: string): string {\n return isAbsolute(raw) ? raw : resolve(raw)\n}\n\nexport function resolveFeatureDestPath(fileDest: string, route: FeatureConfig['route']): string {\n const pages = 'src/pages/'\n const appPages = 'src/pages/(app)/'\n if (!fileDest.startsWith(pages) || fileDest.startsWith(appPages)) return fileDest\n const rest = fileDest.slice(pages.length)\n return route?.protected === false ? `${appPages}${rest}` : `${appPages}(protected)/${rest}`\n}\n\nfunction copyFile(src: string, dest: string): void {\n mkdirSync(dirname(dest), { recursive: true })\n copyFileSync(src, dest)\n}\n\nfunction copyFileWithImportShift(src: string, dest: string, levels: number): void {\n mkdirSync(dirname(dest), { recursive: true })\n const prefix = '../'.repeat(levels)\n const shifted = readFileSync(src, 'utf-8').replace(\n /(from\\s+|import\\s+|import\\()(['\"])(\\.\\.\\/)/g,\n `$1$2${prefix}$3`,\n )\n writeFileSync(dest, shifted)\n}\n\nfunction installFiles(\n packageRoot: string,\n config: FeatureConfig,\n targetDir: string,\n emit: FeatureInstallerOutput,\n): {\n copied: number\n skipped: number\n files: { created: string[]; preexisting: string[]; missing: string[] }\n} {\n let copied = 0\n let skipped = 0\n const created: string[] = []\n const preexisting: string[] = []\n const missing: string[] = []\n\n for (const file of config.files) {\n const srcPath = join(packageRoot, 'features', config.id, file.src)\n const resolvedDest = resolveFeatureDestPath(file.dest, config.route)\n const destPath = join(targetDir, resolvedDest)\n const existed = existsSync(destPath)\n if (existed) preexisting.push(resolvedDest)\n\n if (!existsSync(srcPath)) {\n emit(` Warning: source not found: ${file.src}`, 'stderr')\n if (!existed) missing.push(resolvedDest)\n continue\n }\n\n if (existed && !file.overwrite) {\n emit(` Exists (skipped): ${resolvedDest}`)\n skipped++\n continue\n }\n\n const wasRedirected = resolvedDest !== file.dest\n const shiftLevels = resolvedDest.split('/').length - file.dest.split('/').length\n if (wasRedirected) copyFileWithImportShift(srcPath, destPath, shiftLevels)\n else copyFile(srcPath, destPath)\n emit(` ${existed ? 'Overwrote' : 'Copied'}: ${resolvedDest}`)\n if (!existed) created.push(resolvedDest)\n copied++\n }\n\n return { copied, skipped, files: { created, preexisting, missing } }\n}\n\nfunction unresolvedSchema(\n schema: FeatureSchema,\n reason: string,\n emit: FeatureInstallerOutput,\n): UnresolvedIntegration {\n const entry = schema.spreadOperator ? `...${schema.exportName}` : schema.exportName\n emit('')\n emit(' Add manually to src/schemas.ts:')\n emit(` import { ${schema.exportName} } from '${schema.importPath}'`)\n emit(` // then add ${entry} to the schemas array`)\n return {\n area: 'schema',\n reason,\n steps: [\n `Add import { ${schema.exportName} } from '${schema.importPath}' to src/schemas.ts.`,\n `Add ${entry} to the exported schemas array.`,\n ],\n }\n}\n\nfunction integrateSchema(\n config: FeatureConfig,\n targetDir: string,\n emit: FeatureInstallerOutput,\n): UnresolvedIntegration[] {\n if (!config.schema) return []\n const schemasPath = join(targetDir, 'src', 'schemas.ts')\n if (!existsSync(schemasPath)) {\n return [unresolvedSchema(config.schema, 'src/schemas.ts was not found.', emit)]\n }\n\n let content = readFileSync(schemasPath, 'utf-8')\n const { exportName, importPath, spreadOperator } = config.schema\n const importPattern = new RegExp(`^import\\\\s+\\\\{[^}]*\\\\b${exportName}\\\\b`, 'm')\n if (importPattern.test(content)) {\n emit(` Schema already present: ${exportName}`)\n return []\n }\n if (\n !content.includes('export const schemas') ||\n !/export const schemas:\\s*CollectionSchema\\[\\]\\s*=\\s*\\[/.test(content)\n ) {\n const reason = 'src/schemas.ts has an unexpected structure.'\n emit(` Could not auto-integrate schema (${reason})`)\n return [unresolvedSchema(config.schema, reason, emit)]\n }\n\n const importLine = `import { ${exportName} } from '${importPath}'`\n const withImport = content.replace(\n /export const schemas/,\n `${importLine}\\n\\nexport const schemas`,\n )\n const schemaEntry = spreadOperator ? `...${exportName}` : exportName\n const withEntry = withImport.replace(\n /export const schemas:\\s*CollectionSchema\\[\\]\\s*=\\s*\\[/,\n `export const schemas: CollectionSchema[] = [\\n ${schemaEntry},`,\n )\n if (withImport === content || withEntry === withImport) {\n const reason = 'src/schemas.ts could not be updated safely.'\n emit(` Could not auto-integrate schema (${reason})`)\n return [unresolvedSchema(config.schema, reason, emit)]\n }\n content = withEntry\n writeFileSync(schemasPath, content)\n emit(` Schema integrated: ${exportName} -> schemas.ts`)\n return []\n}\n\nfunction unresolvedActions(\n actions: FeatureAction[],\n reason: string,\n emit: FeatureInstallerOutput,\n): UnresolvedIntegration {\n emit('')\n emit(' Add manually to src/actions/index.ts:')\n for (const action of actions) {\n emit(` import { ${action.exportName} } from '${action.importPath}'`)\n emit(` // then add '${action.registerAs}': ${action.exportName} to the actions object`)\n }\n return {\n area: 'actions',\n reason,\n steps: actions.flatMap((action) => [\n `Add import { ${action.exportName} } from '${action.importPath}' to src/actions/index.ts.`,\n `Register '${action.registerAs}': ${action.exportName} in the exported actions object.`,\n ]),\n }\n}\n\nfunction integrateActions(\n config: FeatureConfig,\n targetDir: string,\n emit: FeatureInstallerOutput,\n): UnresolvedIntegration[] {\n if (!config.actions?.length) return []\n const actionsPath = join(targetDir, 'src', 'actions', 'index.ts')\n if (!existsSync(actionsPath)) {\n return [unresolvedActions(config.actions, 'src/actions/index.ts was not found.', emit)]\n }\n\n let content = readFileSync(actionsPath, 'utf-8')\n const registryPattern =\n /export const actions:\\s*Record<string,\\s*ActionHandler(?:<[^>]*>)?>\\s*=\\s*\\{/\n if (!registryPattern.test(content)) {\n const reason = 'src/actions/index.ts has an unexpected structure.'\n emit(` Could not auto-integrate actions (${reason})`)\n return [unresolvedActions(config.actions, reason, emit)]\n }\n\n let integrated = 0\n const unresolved: UnresolvedIntegration[] = []\n for (const action of config.actions) {\n const importPattern = new RegExp(`^import\\\\s+\\\\{[^}]*\\\\b${action.exportName}\\\\b`, 'm')\n if (importPattern.test(content)) {\n emit(` Action already present: ${action.registerAs}`)\n continue\n }\n const importLine = `import { ${action.exportName} } from '${action.importPath}'`\n const withImport = content.replace(\n /export const actions:/,\n `${importLine}\\n\\nexport const actions:`,\n )\n const registryEntry = ` '${action.registerAs}': ${action.exportName},`\n const withEntry = withImport.replace(registryPattern, (match) => `${match}\\n${registryEntry}`)\n if (withImport === content || withEntry === withImport) {\n emit(` Could not integrate action: ${action.registerAs}`)\n unresolved.push(\n unresolvedActions(\n [action],\n `Action '${action.registerAs}' could not be registered safely.`,\n emit,\n ),\n )\n continue\n }\n content = withEntry\n integrated++\n emit(` Action integrated: ${action.registerAs} (${action.exportName})`)\n }\n if (integrated > 0) writeFileSync(actionsPath, content)\n return unresolved\n}\n\nfunction integrateCss(\n packageRoot: string,\n config: FeatureConfig,\n targetDir: string,\n emit: FeatureInstallerOutput,\n): UnresolvedIntegration[] {\n if (!config.css?.length) return []\n const stylesPath = join(targetDir, 'src', 'styles.css')\n if (!existsSync(stylesPath)) {\n emit(' Warning: Cannot integrate CSS — src/styles.css not found')\n return [\n {\n area: 'css',\n reason: 'src/styles.css was not found.',\n steps: config.css.map(\n (cssFile) =>\n `Append node_modules/deepspace/features/${config.id}/${cssFile} to src/styles.css.`,\n ),\n },\n ]\n }\n\n let styles = readFileSync(stylesPath, 'utf-8')\n let integrated = 0\n const unresolved: UnresolvedIntegration[] = []\n for (const cssFile of config.css) {\n const srcPath = join(packageRoot, 'features', config.id, cssFile)\n if (!existsSync(srcPath)) {\n emit(` Warning: CSS source not found: ${cssFile}`, 'stderr')\n unresolved.push({\n area: 'css',\n reason: `Feature CSS source '${cssFile}' was not found in the installed package.`,\n steps: ['Reinstall the current deepspace package, then retry this feature installation.'],\n })\n continue\n }\n const css = readFileSync(srcPath, 'utf-8')\n const fingerprint = css.match(/\\.([\\w-]+)\\s*\\{|@keyframes\\s+([\\w-]+)/)\n const marker = fingerprint?.[1] ?? fingerprint?.[2]\n if (marker && styles.includes(marker)) {\n emit(` CSS already present: ${cssFile} (found .${marker})`)\n continue\n }\n styles += `\\n${css}`\n integrated++\n emit(` CSS integrated: ${cssFile} -> styles.css`)\n }\n if (integrated > 0) writeFileSync(stylesPath, styles)\n return unresolved\n}\n\nfunction unresolvedRoute(\n route: NonNullable<FeatureConfig['route']>,\n config: FeatureConfig,\n reason: string,\n emit: FeatureInstallerOutput,\n): UnresolvedIntegration {\n emit('')\n emit(' Add manually to src/nav.ts:')\n emit(` { path: '${route.path}', label: '${config.name}' },`)\n return {\n area: 'nav',\n reason,\n steps: [`Add { path: '${route.path}', label: '${config.name}' } to the exported nav array.`],\n }\n}\n\nfunction integrateRoute(\n config: FeatureConfig,\n targetDir: string,\n emit: FeatureInstallerOutput,\n): UnresolvedIntegration[] {\n if (!config.route) return []\n const navPath = join(targetDir, 'src', 'nav.ts')\n if (!existsSync(navPath)) {\n return [unresolvedRoute(config.route, config, 'src/nav.ts was not found.', emit)]\n }\n let content = readFileSync(navPath, 'utf-8')\n const routePath = config.route.path\n if (content.includes(`'${routePath}'`)) {\n emit(` Nav already present: ${routePath}`)\n return []\n }\n if (!content.includes(NAV_MARKER)) {\n emit(' Could not auto-wire nav (marker not found in nav.ts)')\n return [\n unresolvedRoute(\n config.route,\n config,\n 'The feature insertion marker was not found in src/nav.ts.',\n emit,\n ),\n ]\n }\n const roles = config.route.protected === false ? '' : \", roles: ['member' as Role]\"\n const entry = ` { path: '${routePath}', label: '${config.name}'${roles} },`\n content = content.replace(NAV_MARKER, `${NAV_MARKER}\\n${entry}`)\n writeFileSync(navPath, content)\n emit(` Nav wired: ${routePath} (${config.name})`)\n emit(' Route: automatic (file-based routing via src/pages/)')\n return []\n}\n\nconst INSTALL_DIAGNOSTIC_BYTES = 16 * 1024\n\ninterface PackageInstallRun {\n error?: Error\n status: number | null\n diagnosticTail?: string\n}\n\nfunction readDiagnosticTail(outputFd: number): string | undefined {\n const size = fstatSync(outputFd).size\n if (size === 0) return undefined\n const length = Math.min(size, INSTALL_DIAGNOSTIC_BYTES)\n const buffer = Buffer.alloc(length)\n readSync(outputFd, buffer, 0, length, size - length)\n const tail = buffer.toString('utf-8').trim()\n if (!tail) return undefined\n return size > length ? `[last ${length} bytes]\\n${tail}` : tail\n}\n\nfunction runPackageInstall(\n packageManager: string,\n targetDir: string,\n outputVisible: boolean,\n): PackageInstallRun {\n const options = {\n cwd: targetDir,\n shell: process.platform === 'win32',\n }\n if (outputVisible) {\n const child = spawnSync(packageManager, ['install'], { ...options, stdio: 'inherit' })\n return { error: child.error, status: child.status }\n }\n\n // Keep stdout reserved for the command's one-line JSON envelope. Both child\n // streams share a temporary file, then only a fixed-size tail enters memory.\n const captureDir = mkdtempSync(join(tmpdir(), 'deepspace-add-install-'))\n let outputFd: number | undefined\n try {\n outputFd = openSync(join(captureDir, 'output.log'), 'w+')\n const child = spawnSync(packageManager, ['install'], {\n ...options,\n stdio: ['ignore', outputFd, outputFd],\n })\n return {\n error: child.error,\n status: child.status,\n diagnosticTail: readDiagnosticTail(outputFd),\n }\n } finally {\n if (outputFd !== undefined) closeSync(outputFd)\n rmSync(captureDir, { recursive: true, force: true })\n }\n}\n\nfunction integrateDependencies(\n config: FeatureConfig,\n targetDir: string,\n runInstall: boolean,\n outputVisible: boolean,\n emit: FeatureInstallerOutput,\n): {\n added: DependencyAddition[]\n installRan: boolean\n installError?: string\n diagnosticTail?: string\n packageManager: string\n} {\n const packageManager = detectPackageManager(targetDir)\n const declarations: Array<{\n section: DependencySection\n values: Record<string, string> | undefined\n }> = [\n { section: 'dependencies', values: config.dependencies },\n { section: 'devDependencies', values: config.devDependencies },\n ]\n if (declarations.every(({ values }) => !values || Object.keys(values).length === 0)) {\n return { added: [], installRan: false, packageManager }\n }\n\n const packagePath = join(targetDir, 'package.json')\n if (!existsSync(packagePath)) {\n emit(' Could not patch package.json (file not found)')\n return { added: [], installRan: false, packageManager }\n }\n\n let pkg: Record<string, unknown> & {\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n }\n try {\n pkg = JSON.parse(readFileSync(packagePath, 'utf-8')) as typeof pkg\n } catch (error) {\n emit(\n ` Could not patch package.json (parse error: ${error instanceof Error ? error.message : String(error)})`,\n )\n return { added: [], installRan: false, packageManager }\n }\n\n const added: DependencyAddition[] = []\n const skipped: string[] = []\n for (const { section, values } of declarations) {\n if (!values) continue\n pkg[section] ??= {}\n for (const [name, version] of Object.entries(values)) {\n if (pkg.dependencies?.[name] || pkg.devDependencies?.[name]) {\n if (!added.some((dependency) => dependency.name === name)) skipped.push(name)\n continue\n }\n pkg[section]![name] = version\n added.push({ name, section, version })\n }\n }\n\n if (added.length === 0) {\n emit(' Dependencies already present')\n } else {\n writeFileSync(packagePath, `${JSON.stringify(pkg, null, 2)}\\n`, 'utf-8')\n emit(` Added to package.json: ${added.map(({ name }) => name).join(', ')}`)\n if (skipped.length) emit(` Already present (kept your version): ${skipped.join(', ')}`)\n }\n\n if (!runInstall) return { added, installRan: false, packageManager }\n emit('')\n emit(` Installing dependencies with ${packageManager}...`)\n const child = runPackageInstall(packageManager, targetDir, outputVisible)\n if (child.error) {\n const error = child.error as NodeJS.ErrnoException\n const reason = error.code === 'ENOENT' ? `${packageManager} not found on PATH` : error.message\n return {\n added,\n installRan: false,\n installError: `Could not launch ${packageManager} (${reason}).`,\n diagnosticTail: child.diagnosticTail,\n packageManager,\n }\n }\n if (child.status !== 0) {\n const diagnostic = child.diagnosticTail ? `\\nDiagnostic tail:\\n${child.diagnosticTail}` : ''\n return {\n added,\n installRan: false,\n installError: `${packageManager} install did not complete (exit ${child.status ?? 'unknown'}).${diagnostic}`,\n diagnosticTail: child.diagnosticTail,\n packageManager,\n }\n }\n return { added, installRan: true, packageManager }\n}\n\nfunction dependencySnapshot(targetDir: string): {\n dependencies: Record<string, unknown>\n devDependencies: Record<string, unknown>\n} {\n try {\n const pkg = JSON.parse(readFileSync(join(targetDir, 'package.json'), 'utf-8')) as {\n dependencies?: Record<string, unknown>\n devDependencies?: Record<string, unknown>\n }\n return {\n dependencies: pkg.dependencies ?? {},\n devDependencies: pkg.devDependencies ?? {},\n }\n } catch {\n return { dependencies: {}, devDependencies: {} }\n }\n}\n\nfunction installedNavFeatures(packageRoot: string, targetDir: string): string[] {\n return listFeatureConfigs(packageRoot)\n .filter((feature) => feature.category === 'nav' && feature.files.length > 0)\n .filter((feature) => {\n const signature = resolveFeatureDestPath(feature.files[0].dest, feature.route)\n return existsSync(join(targetDir, signature))\n })\n .map((feature) => feature.id)\n}\n\nfunction warnNavConflicts(\n packageRoot: string,\n config: FeatureConfig,\n targetDir: string,\n emit: FeatureInstallerOutput,\n): void {\n if (config.category !== 'nav') return\n const present = installedNavFeatures(packageRoot, targetDir)\n if (present.length <= 1) return\n emit('')\n emit(`⚠ Multiple navigation features present (${present.join(', ')}).`)\n emit(' sidebar, topbar, and tree are mutually exclusive — keep one and remove the')\n emit(' others to avoid competing navigation in your layout.')\n}\n\nexport function installFeature(options: FeatureInstallOptions): FeatureInstallOutcome {\n const packageRoot = featurePackageRoot()\n const targetDir = resolveTargetDir(options.targetDir)\n const config = readFeatureConfig(options.feature, packageRoot)\n if (!config) {\n const suggestion = suggestFeature(options.feature, packageRoot)\n return {\n ok: false,\n code: 'unknown_feature',\n error: [\n `Unknown feature: ${options.feature}`,\n ...(suggestion ? [`Did you mean \"${suggestion}\"?`] : []),\n ].join('\\n'),\n data: {\n requestedFeature: options.feature,\n suggestedFeature: suggestion,\n availableFeatures: featureCatalog(packageRoot),\n },\n }\n }\n\n const emit: FeatureInstallerOutput = options.emit ?? (() => undefined)\n emit('')\n emit(`Installing: ${config.name}`)\n emit(` ${config.description ?? ''}`)\n emit(` Target: ${targetDir}`)\n\n const installedFiles = installFiles(packageRoot, config, targetDir, emit)\n emit('')\n emit(\n `Copied ${installedFiles.copied} file(s)${\n installedFiles.skipped > 0 ? `, skipped ${installedFiles.skipped} existing` : ''\n }`,\n )\n\n const unresolvedIntegrations = [\n ...integrateSchema(config, targetDir, emit),\n ...integrateActions(config, targetDir, emit),\n ...integrateCss(packageRoot, config, targetDir, emit),\n ...integrateRoute(config, targetDir, emit),\n ]\n const dependencyResult = integrateDependencies(\n config,\n targetDir,\n options.installDependencies,\n options.emit !== undefined,\n emit,\n )\n\n if (config.instructions?.length) {\n emit('')\n emit('--- Manual wiring needed ---')\n emit('')\n config.instructions.forEach((instruction, index) => {\n emit(`${index + 1}. ${instruction}`)\n emit('')\n })\n }\n if (config.patterns?.length) {\n emit('--- Key patterns ---')\n emit('')\n config.patterns.forEach((pattern) => emit(`- ${pattern}`))\n emit('')\n }\n warnNavConflicts(packageRoot, config, targetDir, emit)\n\n const dependenciesAfter = dependencySnapshot(targetDir)\n const declaredDependencies = [\n ...Object.keys(config.dependencies ?? {}),\n ...Object.keys(config.devDependencies ?? {}),\n ]\n const missingDeclarations = declaredDependencies.filter(\n (name) =>\n !(name in dependenciesAfter.dependencies) && !(name in dependenciesAfter.devDependencies),\n )\n const installed =\n installedFiles.files.missing.length === 0 &&\n missingDeclarations.length === 0 &&\n unresolvedIntegrations.length === 0 &&\n dependencyResult.installError === undefined\n const dependencyInstallRequired =\n installed &&\n dependencyResult.added.length > 0 &&\n !options.installDependencies &&\n !dependencyResult.installRan\n\n const data: InstallData = {\n feature: config.id,\n dir: targetDir,\n installed,\n observedChanges: {\n files: installedFiles.files,\n dependencies: {\n added: dependencyResult.added,\n missingDeclarations,\n installRequested: options.installDependencies,\n ...(dependencyResult.diagnosticTail\n ? { diagnosticTail: dependencyResult.diagnosticTail }\n : {}),\n },\n },\n unresolvedIntegrations,\n manifestGuidance: {\n instructions: config.instructions ?? [],\n patterns: config.patterns ?? [],\n agentNotes: config.agentNotes ?? [],\n },\n }\n if (dependencyResult.installError) {\n return {\n ok: false,\n code: 'dependency_install_failed',\n error: dependencyResult.installError,\n data,\n }\n }\n if (unresolvedIntegrations.length > 0) {\n const count = unresolvedIntegrations.length\n return {\n ok: false,\n code: 'manual_integration_required',\n error: `${count} app integration${count === 1 ? '' : 's'} require manual completion. Follow the unresolved integration steps, then run your checks.`,\n data,\n }\n }\n\n return {\n ok: true,\n data,\n ...(dependencyInstallRequired\n ? {\n action: {\n cwd: targetDir,\n argv: [dependencyResult.packageManager, 'install'],\n },\n }\n : {}),\n }\n}\n","import { existsSync, readFileSync } from 'node:fs'\nimport { join } from 'node:path'\n\nexport type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun'\n\n/** Resolve the repository's package manager from its explicit packageManager\n * field first, then its lockfile. npm is the conservative fallback. */\nexport function detectPackageManager(appDir: string): PackageManager {\n try {\n const pkg = JSON.parse(readFileSync(join(appDir, 'package.json'), 'utf-8')) as {\n packageManager?: unknown\n }\n const name = typeof pkg.packageManager === 'string' ? pkg.packageManager.split('@')[0] : ''\n if (name === 'npm' || name === 'pnpm' || name === 'yarn' || name === 'bun') return name\n } catch {\n // Missing/malformed package.json falls through to lockfile detection.\n }\n if (existsSync(join(appDir, 'pnpm-lock.yaml'))) return 'pnpm'\n if (existsSync(join(appDir, 'yarn.lock'))) return 'yarn'\n if (existsSync(join(appDir, 'bun.lock')) || existsSync(join(appDir, 'bun.lockb'))) return 'bun'\n return 'npm'\n}\n\nexport function installCommand(appDir: string): string {\n return `${detectPackageManager(appDir)} install`\n}\n"],"mappings":"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","names":["existsSync","readFileSync","join","join","existsSync","readFileSync"]}
package/dist/index.d.ts CHANGED
@@ -17,43 +17,91 @@ import * as node_modules_better_auth_dist_plugins_access_types_mjs from 'node_mo
17
17
  *
18
18
  * Types used by both client-side SDK and server-side workers.
19
19
  */
20
- type PermissionRule = boolean | 'own' | 'unclaimed-or-own' | 'collaborator' | 'team' | 'access' | 'published' | 'shared';
21
- interface SchemaPermissions {
22
- read: PermissionRule;
23
- create: PermissionRule;
24
- update: PermissionRule;
25
- delete: PermissionRule;
20
+ type ColumnInterpretation = {
21
+ kind: 'plain';
22
+ } | {
23
+ kind: 'currency';
24
+ symbol: string;
25
+ decimals: number;
26
+ } | {
27
+ kind: 'date';
28
+ format?: string;
29
+ } | {
30
+ kind: 'datetime';
31
+ format?: string;
32
+ } | {
33
+ kind: 'boolean';
34
+ trueLabel?: string;
35
+ falseLabel?: string;
36
+ } | {
37
+ kind: 'percent';
38
+ decimals?: number;
39
+ } | {
40
+ kind: 'select';
41
+ options: string[];
42
+ } | {
43
+ kind: 'multiselect';
44
+ options: string[];
45
+ } | {
46
+ kind: 'url';
47
+ } | {
48
+ kind: 'email';
49
+ } | {
50
+ kind: 'json';
51
+ } | {
52
+ kind: 'reference';
53
+ targetTable: string;
54
+ displayColumn: string;
55
+ };
56
+ interface ColumnDefinition {
57
+ /** Stable ID override (survives renames). Falls back to `col_{name}`. */
58
+ id?: string;
59
+ name: string;
60
+ storage: 'number' | 'text';
61
+ interpretation: ColumnInterpretation | string;
62
+ expression?: string;
63
+ userBound?: boolean;
64
+ immutable?: boolean;
65
+ required?: boolean;
66
+ default?: unknown;
67
+ timestampTrigger?: {
68
+ field: string;
69
+ value?: unknown;
70
+ };
71
+ }
72
+ type PermissionLevel = boolean | 'own' | 'unclaimed-or-own' | 'collaborator' | 'team' | 'access' | 'published' | 'shared';
73
+ interface RolePermissions {
74
+ read: PermissionLevel;
75
+ /** Create has no existing record to evaluate, so it is an explicit grant. */
76
+ create: boolean;
77
+ update: PermissionLevel;
78
+ delete: PermissionLevel;
79
+ /** If set, only these columns can be updated by this role. */
26
80
  writableFields?: string[];
27
81
  }
28
82
  interface CollectionSchema {
29
83
  name: string;
30
- columns: Array<{
31
- name: string;
32
- storage: string;
33
- interpretation: string | Record<string, unknown>;
34
- id?: string;
35
- expression?: string;
36
- userBound?: boolean;
37
- immutable?: boolean;
38
- required?: boolean;
39
- default?: unknown;
40
- timestampTrigger?: {
41
- field: string;
42
- value?: unknown;
43
- };
44
- }>;
84
+ /** Every collection is stored in typed SQL columns. */
85
+ columns: ColumnDefinition[];
86
+ /** Composite uniqueness constraint (for example `['userId', 'taskId']`). */
45
87
  uniqueOn?: string[];
46
- permissions: Record<string, SchemaPermissions>;
88
+ /** Ownership column; defaults to the row creator. */
47
89
  ownerField?: string;
90
+ /** Column containing a JSON array of collaborator user ids. */
48
91
  collaboratorsField?: string;
92
+ /** Column containing the team id used by team permission rules. */
49
93
  teamField?: string;
94
+ /** A string is public when equal to `public`; an object supplies an exact value. */
50
95
  visibilityField?: string | {
51
96
  field: string;
52
97
  value: unknown;
53
98
  };
99
+ /** Permissions per role; `*` is the catch-all role. */
100
+ permissions: Record<string, RolePermissions>;
101
+ /** Default role assigned on the `users` collection. */
54
102
  defaultRole?: string;
55
103
  }
56
- interface Query$1 {
104
+ interface Query {
57
105
  collection: string;
58
106
  where?: Record<string, unknown>;
59
107
  orderBy?: string;
@@ -62,7 +110,7 @@ interface Query$1 {
62
110
  }
63
111
  interface Subscription {
64
112
  id: string;
65
- query: Query$1;
113
+ query: Query;
66
114
  }
67
115
  /** Key for Yjs doc: collection:recordId:fieldName */
68
116
  type YjsDocKey = string;
@@ -162,7 +210,7 @@ interface ConvReadCursorData {
162
210
  * 3. Server-side process.env.DEEPSPACE_ENV
163
211
  * 4. Hostname detection (fallback)
164
212
  */
165
- type Environment = 'dev' | 'prod';
213
+ type Environment = 'dev' | 'staging' | 'prod';
166
214
  interface EnvironmentConfig {
167
215
  name: Environment;
168
216
  /** Platform API worker URL */
@@ -331,6 +379,8 @@ declare class Awareness {
331
379
  * Remove awareness states for disconnected clients
332
380
  */
333
381
  removeStates(clientIds: number[]): void;
382
+ /** Release all state and listeners owned by this awareness instance. */
383
+ destroy(): void;
334
384
  }
335
385
  /**
336
386
  * Encode a full awareness message
@@ -1270,8 +1320,6 @@ interface ConnectionAttachment extends UserAttachment {
1270
1320
  subscriptions: Subscription[];
1271
1321
  /** Yjs docs this connection is editing */
1272
1322
  yjsSubscriptions: YjsSubscription[];
1273
- /** Yjs client ID for awareness */
1274
- yjsClientId?: number;
1275
1323
  /** Client-side Yjs awareness clientId (extracted from first awareness message) */
1276
1324
  awarenessClientId?: number;
1277
1325
  }
@@ -2569,13 +2617,6 @@ declare function GuestBanner({ message, storageKey, onSignIn, }: GuestBannerProp
2569
2617
  * Type definitions for the RecordRoom storage system.
2570
2618
  */
2571
2619
 
2572
- interface Query {
2573
- collection: string;
2574
- where?: Record<string, unknown>;
2575
- orderBy?: string;
2576
- orderDir?: 'asc' | 'desc';
2577
- limit?: number;
2578
- }
2579
2620
  interface RecordData<T = unknown> {
2580
2621
  recordId: string;
2581
2622
  data: T;
@@ -2642,22 +2683,17 @@ interface RoomUser {
2642
2683
  lastSeenAt: string;
2643
2684
  }
2644
2685
  type RoomConnectionState = 'connecting' | 'connected' | 'disconnected';
2645
- /**
2646
- * Function to fetch user profile from API.
2647
- * Uses Better Auth token from the auth module.
2648
- */
2649
- type FetchUserProfile = () => Promise<UserProfile | null>;
2686
+ /** A server-rejected optimistic write. */
2687
+ interface WriteError {
2688
+ /** RBAC denial or data validation/other rejection. */
2689
+ kind: 'permission' | 'validation';
2690
+ /** Short human-readable summary, safe to show end users. */
2691
+ title: string;
2692
+ /** Longer human-readable explanation; may be empty. */
2693
+ detail: string;
2694
+ }
2650
2695
  interface RecordProviderProps {
2651
- /** Room ID for backward compat. Omit for multi-scope mode (use RecordScope instead). */
2652
- roomId?: string;
2653
- schemas?: CollectionSchema[];
2654
- wsUrl?: string;
2655
- children: React.ReactNode;
2656
- /**
2657
- * Custom function to fetch user profile.
2658
- * If not provided, uses Better Auth session.
2659
- */
2660
- fetchUser?: FetchUserProfile;
2696
+ children: ReactNode;
2661
2697
  /**
2662
2698
  * If true, allow anonymous users to connect as read-only viewers.
2663
2699
  * Non-signed-in users skip the sign-in screen and connect
@@ -2667,6 +2703,11 @@ interface RecordProviderProps {
2667
2703
  allowAnonymous?: boolean;
2668
2704
  /** Auth token provider for WS connections. */
2669
2705
  getAuthToken?: () => Promise<string | null>;
2706
+ /**
2707
+ * Receives server-rejected optimistic writes. Wire this to app UI so users
2708
+ * see denied or invalid changes. Defaults to a deduplicated console error.
2709
+ */
2710
+ onWriteError?: (error: WriteError) => void;
2670
2711
  }
2671
2712
 
2672
2713
  /**
@@ -2740,11 +2781,8 @@ declare class RecordStore {
2740
2781
  /**
2741
2782
  * RecordProvider Context
2742
2783
  *
2743
- * Provides WebSocket connection and state management for RecordRoom.
2744
- *
2745
- * Multi-scope mode: RecordProvider can be used without roomId
2746
- * to provide only auth context + ScopeRegistry. RecordScope components
2747
- * handle individual WebSocket connections.
2784
+ * Provides shared authentication state and scope registration for RecordRoom.
2785
+ * RecordScope components own individual WebSocket connections.
2748
2786
  */
2749
2787
 
2750
2788
  interface RecordContextValue {
@@ -2781,36 +2819,11 @@ interface RecordContextValue {
2781
2819
  }
2782
2820
  declare function useRecordContext(): RecordContextValue;
2783
2821
  /**
2784
- * A server-rejected write, delivered to `RecordProvider`'s `onWriteError`.
2785
- * One structured object rather than positional strings so future rejection
2786
- * kinds (rate-limit, quota, dropped-while-offline) and correlation fields
2787
- * (collection, recordId, the raw server string) can be added without
2788
- * breaking the callback signature.
2789
- */
2790
- interface WriteError {
2791
- /** 'permission' — an RBAC denial; 'validation' — missing/immutable/invalid field or any other rejection. */
2792
- kind: 'permission' | 'validation';
2793
- /** Short human-readable summary, safe to show end users. */
2794
- title: string;
2795
- /** Longer human-readable explanation; may be empty. */
2796
- detail: string;
2797
- }
2798
- /**
2799
- * RecordProvider - Main entry point for storage.
2800
- *
2801
- * Two modes:
2802
- * 1. **Single-scope (backward compat):** Pass `roomId` + `schemas`. Opens one WS connection.
2803
- * 2. **Multi-scope:** Omit `roomId`. Only provides auth + ScopeRegistry.
2804
- * Use `<RecordScope>` components for individual WS connections.
2822
+ * RecordProvider supplies shared authentication and scope registration.
2823
+ * Use `<RecordScope>` for every RecordRoom connection.
2805
2824
  *
2806
2825
  * @example
2807
2826
  * ```tsx
2808
- * // Single-scope (backward compat)
2809
- * <RecordProvider roomId="my-app" schemas={schemas}>
2810
- * <App />
2811
- * </RecordProvider>
2812
- *
2813
- * // Multi-scope
2814
2827
  * <RecordProvider>
2815
2828
  * <RecordScope roomId="app:slack-clone" schemas={appSchemas}>
2816
2829
  * <RecordScope roomId={`conv:${channelId}`} schemas={convSchemas}>
@@ -2820,27 +2833,7 @@ interface WriteError {
2820
2833
  * </RecordProvider>
2821
2834
  * ```
2822
2835
  */
2823
- declare function RecordProvider({ roomId, schemas, wsUrl, children, allowAnonymous, getAuthToken: getAuthTokenProp, onWriteError, }: {
2824
- roomId?: string;
2825
- /**
2826
- * Accepted for API compatibility with `RecordScope` and documented usage,
2827
- * but the single-scope backward-compat provider does no local-first
2828
- * registration, so it's ignored. Pass schemas to `RecordScope` instead.
2829
- */
2830
- schemas?: CollectionSchema[];
2831
- wsUrl?: string;
2832
- children: ReactNode;
2833
- allowAnonymous?: boolean;
2834
- getAuthToken?: () => Promise<string | null>;
2835
- /**
2836
- * Called when the server rejects a write. Optimistic mutations
2837
- * (`create`/`put`/`remove`) resolve before the server answers, so this
2838
- * callback is the only place a denied or invalid write surfaces — wire it
2839
- * to your toast/alert system and branch on `error.kind`. Defaults to a
2840
- * deduped console.error so rejections are never fully silent.
2841
- */
2842
- onWriteError?: (error: WriteError) => void;
2843
- }): React__default.ReactElement;
2836
+ declare function RecordProvider({ children, allowAnonymous, getAuthToken: getAuthTokenProp, onWriteError, }: RecordProviderProps): React__default.ReactElement;
2844
2837
 
2845
2838
  interface SharedScopeConfig {
2846
2839
  roomId: string;
@@ -2850,8 +2843,6 @@ interface RecordScopeProps {
2850
2843
  roomId: string;
2851
2844
  schemas: CollectionSchema[];
2852
2845
  children?: ReactNode;
2853
- /** App ID passed to the server for schema resolution. */
2854
- appId: string;
2855
2846
  /** Additional scopes to connect (headless — no children, just register collections). */
2856
2847
  sharedScopes?: SharedScopeConfig[];
2857
2848
  /** WebSocket base URL override. Derived from window.location if omitted. */
@@ -2861,7 +2852,7 @@ interface RecordScopeProps {
2861
2852
  /** Don't register collections in ScopeRegistry (prevents name collisions). */
2862
2853
  isolated?: boolean;
2863
2854
  }
2864
- declare function RecordScope({ roomId, schemas, children, appId, sharedScopes, wsUrl, wsPathPrefix, isolated, }: RecordScopeProps): react_jsx_runtime.JSX.Element;
2855
+ declare function RecordScope({ roomId, schemas, children, sharedScopes, wsUrl, wsPathPrefix, isolated, }: RecordScopeProps): react_jsx_runtime.JSX.Element;
2865
2856
 
2866
2857
  interface ScopeEntry {
2867
2858
  store: RecordStore;
@@ -2927,7 +2918,7 @@ declare function useUser(): {
2927
2918
  *
2928
2919
  * Subscribe to a query with real-time updates.
2929
2920
  * Resolves the correct scope via ScopeRegistry (multi-scope)
2930
- * or falls back to useRecordContext() (single-scope backward compat).
2921
+ * or uses the nearest RecordScope context during registry transitions.
2931
2922
  */
2932
2923
 
2933
2924
  /**
@@ -2959,7 +2950,7 @@ declare function useQuery<T = unknown>(collection: string, options?: {
2959
2950
  *
2960
2951
  * Get mutation functions for a collection.
2961
2952
  * Resolves the correct scope via ScopeRegistry (multi-scope)
2962
- * or falls back to useRecordContext() (single-scope backward compat).
2953
+ * or uses the nearest RecordScope context during registry transitions.
2963
2954
  */
2964
2955
  /**
2965
2956
  * Get mutation functions for a collection.
@@ -3156,6 +3147,8 @@ interface UseYjsRoomResult {
3156
3147
  synced: boolean;
3157
3148
  /** Whether user has write access */
3158
3149
  canWrite: boolean;
3150
+ /** Whether the server has resolved this connection's write permission */
3151
+ writeAuthResolved: boolean;
3159
3152
  }
3160
3153
  /**
3161
3154
  * Connect to a YjsRoom DO for collaborative editing.
@@ -4378,8 +4371,6 @@ interface UseAuthStatusOptions {
4378
4371
  interface UseAuthProfileReadyOptions extends UseAuthStatusOptions {
4379
4372
  requireUser?: boolean;
4380
4373
  }
4381
- /** @deprecated Use `UseAuthProfileReadyOptions` instead. */
4382
- type UseAuthReadyOptions = UseAuthProfileReadyOptions;
4383
4374
  declare function useAuthStatus(options?: UseAuthStatusOptions): {
4384
4375
  status: LoadState;
4385
4376
  isReady: boolean;
@@ -4399,8 +4390,6 @@ declare function useAuthProfileReady(options?: UseAuthProfileReadyOptions): {
4399
4390
  userId: string | null;
4400
4391
  sessionId: string | null;
4401
4392
  };
4402
- /** @deprecated Use `useAuthStatus` for auth-only UI or `useAuthProfileReady` for profile-backed UI. */
4403
- declare const useAuthReady: typeof useAuthProfileReady;
4404
4393
  type AsyncResourceStatus = 'idle' | 'loading' | 'ready' | 'error';
4405
4394
  type PagedResourceStatus = AsyncResourceStatus;
4406
4395
  interface AsyncResourceState<T> {
@@ -4486,9 +4475,10 @@ interface PlanPrice {
4486
4475
  currency?: string;
4487
4476
  }
4488
4477
  /**
4489
- * Plan shape returned by `/api/subscriptions/me` and consumed directly by
4490
- * `<PricingTable plans={sub.plans}>`. Fields beyond slug/rank are optional so
4491
- * a free tier (no prices, no trial) doesn't need to fabricate them.
4478
+ * Plan shape returned by `/api/subscriptions/me` and consumed by
4479
+ * `<PricingTable plans={sub.plans} onSelect={...}>`. Fields beyond slug/rank
4480
+ * are optional so a free tier (no prices, no trial) doesn't need to fabricate
4481
+ * them.
4492
4482
  */
4493
4483
  interface PlanInfo {
4494
4484
  slug: string;
@@ -4547,7 +4537,7 @@ interface UseSubscriptionReturn {
4547
4537
  * subscription is currently entitled. Same entitlement gate as `hasTier`.
4548
4538
  */
4549
4539
  isAtLeast: (slug: string) => boolean;
4550
- /** Plan catalog from /me — pass into `<PricingTable plans={...}>` directly. */
4540
+ /** Plan catalog from /me; PricingTable also requires an onSelect callback. */
4551
4541
  plans: PlanInfo[];
4552
4542
  subscribe: (planSlug: string, opts?: SubscribeOpts) => Promise<SubscribeResult>;
4553
4543
  openPortal: (returnUrl?: string) => Promise<{
@@ -4699,7 +4689,7 @@ interface ClientErrorReport {
4699
4689
  * rebuilds each event field-by-field from a raw Cloudflare row — see the
4700
4690
  * security invariant there). The consumers are the CLI tail
4701
4691
  * (`cli/commands/logs.ts`), the dashboard Logs panel
4702
- * (`apps/dashboard/src/lib/types.ts`), and the e2e whitelist assertion
4692
+ * (`apps/dashboard/src/lib/apps.ts`), and the e2e whitelist assertion
4703
4693
  * (`tests/e2e/tests/logs.spec.ts`). This module used to be hand-mirrored in
4704
4694
  * all four places; `source` was added to three of them and missed in the
4705
4695
  * e2e whitelist, so it now lives here once and they import it.
@@ -4764,4 +4754,4 @@ interface AppLogsResponse {
4764
4754
  declare const APP_LOG_EVENT_KEYS: readonly ["id", "timestamp", "level", "eventType", "message", "source", "outcome", "request", "exception"];
4765
4755
  type AppLogEventKey = (typeof APP_LOG_EVENT_KEYS)[number];
4766
4756
 
4767
- export { APP_LOG_EVENT_KEYS, ASYNC_RESOURCE_DEFAULTS, type AdHocChargeOpts, type AiStreamAction, type AiStreamChunk, type AppLogEvent, type AppLogEventKey, type AppLogsResponse, type AsyncResourceDefaults, type AsyncResourceState, type AsyncResourceStatus, AuthGate, type AuthGateProps, AuthOverlay, Awareness, type AwarenessState, type AwarenessStates, type BaseMessage, type CanvasShapeClient, type Channel, type ChannelInvitation, type ChannelMember, type ChargeOnceOpts, type ChargeOnceResult, type ClientErrorKind, type ClientErrorReport, type ClientErrorReporterOptions, type ClientMessage, type CollectionSchema, type ConnectionAttachment, type ConnectionStatus, type ContentSegment, type ConversationObject, type CronHistoryEntry, type CronTaskState, DEEPSPACE_THEME_PROPERTIES, DEFAULT_USER_COLORS, DeepSpaceAuthProvider, type DeepSpaceThemeConfig, DeepSpaceThemeProvider, type DeepSpaceThemeProviderProps, type DeriveLoadStateInput, ENV, type Environment, type FetchUserProfile, type FileAttachment, type GamePlayer, type GroupedReaction, GuestBanner, type HandlerContext, type InboxEntry, type IntegrationResponse, type JobStatusView, type JobView, LOG_LEVELS, type LinkPreviewData, type LoadState, type LoadStateAuthInput, type LoadStateStatusInput, type LogLevel, MSG, MSG_AWARENESS, MSG_SYNC, MSG_SYNC_STEP1, MSG_SYNC_STEP2, MSG_SYNC_UPDATE, MSG_YJS_AWARENESS, MSG_YJS_SYNC, type MemberRecord, type Message, type MessageHandlers, type MessageRecord, type MsgType, type PagedResourceFetchArgs, type PagedResourcePage, type PagedResourceState, type PagedResourceStatus, type PlanInfo, PlatformContext, type PlatformContextValue, PlatformProvider, type PlatformWSOptions, type PlatformWSResult, type PresencePeerClient, PricingTable, type PricingTablePlan, type PricingTablePrice, type ProductChargeOpts, type ProtocolMessage, type Purchase, type Query, type R2FileInfo, type R2Scope, type R2UploadResult, ROLES, ROLE_ADMIN, ROLE_ANONYMOUS, ROLE_CONFIG, ROLE_DEFAULT, type Reaction, type ReactionRecord, type ReadCursorRecord, type ReadReceipt, type RecordData, RecordProvider, type RecordProviderProps, RecordScope, type RequestOptions, type Role, type RoomUser, type ScopeEntry, ScopeRegistryProvider, type ServerMessage, SignedIn, SignedOut, type SubscribeOpts, type SubscribeResult, type SubscriptionState, type SubscriptionStatus, type SyncResult, type UseAsyncResourceOptions, type UseAuthProfileReadyOptions, type UseAuthReadyOptions, type UseAuthStatusOptions, type UseCanvasResult, type UseCheckoutOpts, type UseCronMonitorResult, type UseGameRoomResult, type UseJobsResult, type UsePagedResourceOptions, type UsePresenceRoomResult, type UseR2FilesReturn, type UseVoiceAgentOptions, type UseVoiceAgentResult, type UseYjsFieldResult, type UseYjsRoomResult, type UseYjsTextResult, type User, type UserCredits, type UserInfo, type UserKarma, type UserProfile, type ViewportClient, type VoiceStatus, type VoiceTranscriptEntry, type WriteError, applyDeepSpaceTheme, applyUIThemeTokens, authClient, canAutoLoadPagedResource, clampPagedResourceItems, clearAuthToken, clearDeepSpaceTheme, clientBuild, createDecoder, createEncoder, decodeAiStreamChunk, deriveLoadState, detectEnvironment, dispatch, encode, encodeAwarenessMessage, encodeSyncStep1, encodeSyncStep2, encodeUpdate, formatFileSize, formatFullTimestamp, formatMessageTime, getApiUrl, getAuthToken, getAuthUrl, getConversationDisplayName, getConversationParticipantIds, getEnvironmentConfig, getMessageType, getPagedResourceCooldownMs, getPlatformWorkerUrl, getThreadCounts, getUserColor, groupReactionsForMessage, handleAwarenessMessage, handleSyncMessage, hasContent, installClientErrorReporter, integration, isAsyncResourceSlow, isDMConversation, isDarkColor, isImageFile, isLocalDev, isProduction, parseMessageMetadata, parseSseLine, readThemeFromDOM, readVarUint, readVarUint8Array, reportClientError, resetEnvironmentCache, serverBuild, shouldGroupMessages, signIn, signOut, toConnectionStatus, toUint8Array, useAsyncResource, useAuth, useAuthProfileReady, useAuthReady, useAuthStatus, useAuthUser, useCanvas, useChannelMembers, useChannels, useCheckout, useCommunities, useConversation, useConversations, useCronMonitor, useDisplayName, useGameRoom, useInbox, useIsDarkTheme, useJobs, useMessages, useMutations, usePagedResource, usePlatform, usePlatformWS, usePosts, usePresence, usePresenceRoom, useQuery, useR2Files, useReactions, useReadReceipts, useRecordContext, useSession, useSubscription, useUser, useUserLookup, useUsers, useVoiceAgent, useYjsField, useYjsRoom, useYjsText, writeVarUint, writeVarUint8Array };
4757
+ export { APP_LOG_EVENT_KEYS, ASYNC_RESOURCE_DEFAULTS, type AdHocChargeOpts, type AiStreamAction, type AiStreamChunk, type AppLogEvent, type AppLogEventKey, type AppLogsResponse, type AsyncResourceDefaults, type AsyncResourceState, type AsyncResourceStatus, AuthGate, type AuthGateProps, AuthOverlay, Awareness, type AwarenessState, type AwarenessStates, type BaseMessage, type CanvasShapeClient, type Channel, type ChannelInvitation, type ChannelMember, type ChargeOnceOpts, type ChargeOnceResult, type ClientErrorKind, type ClientErrorReport, type ClientErrorReporterOptions, type ClientMessage, type CollectionSchema, type ConnectionAttachment, type ConnectionStatus, type ContentSegment, type ConversationObject, type CronHistoryEntry, type CronTaskState, DEEPSPACE_THEME_PROPERTIES, DEFAULT_USER_COLORS, DeepSpaceAuthProvider, type DeepSpaceThemeConfig, DeepSpaceThemeProvider, type DeepSpaceThemeProviderProps, type DeriveLoadStateInput, ENV, type Environment, type FileAttachment, type GamePlayer, type GroupedReaction, GuestBanner, type HandlerContext, type InboxEntry, type IntegrationResponse, type JobStatusView, type JobView, LOG_LEVELS, type LinkPreviewData, type LoadState, type LoadStateAuthInput, type LoadStateStatusInput, type LogLevel, MSG, MSG_AWARENESS, MSG_SYNC, MSG_SYNC_STEP1, MSG_SYNC_STEP2, MSG_SYNC_UPDATE, MSG_YJS_AWARENESS, MSG_YJS_SYNC, type MemberRecord, type Message, type MessageHandlers, type MessageRecord, type MsgType, type PagedResourceFetchArgs, type PagedResourcePage, type PagedResourceState, type PagedResourceStatus, type PlanInfo, PlatformContext, type PlatformContextValue, PlatformProvider, type PlatformWSOptions, type PlatformWSResult, type PresencePeerClient, PricingTable, type PricingTablePlan, type PricingTablePrice, type ProductChargeOpts, type ProtocolMessage, type Purchase, type Query, type R2FileInfo, type R2Scope, type R2UploadResult, ROLES, ROLE_ADMIN, ROLE_ANONYMOUS, ROLE_CONFIG, ROLE_DEFAULT, type Reaction, type ReactionRecord, type ReadCursorRecord, type ReadReceipt, type RecordData, RecordProvider, type RecordProviderProps, RecordScope, type RequestOptions, type Role, type RoomUser, type ScopeEntry, ScopeRegistryProvider, type ServerMessage, SignedIn, SignedOut, type SubscribeOpts, type SubscribeResult, type SubscriptionState, type SubscriptionStatus, type SyncResult, type UseAsyncResourceOptions, type UseAuthProfileReadyOptions, type UseAuthStatusOptions, type UseCanvasResult, type UseCheckoutOpts, type UseCronMonitorResult, type UseGameRoomResult, type UseJobsResult, type UsePagedResourceOptions, type UsePresenceRoomResult, type UseR2FilesReturn, type UseVoiceAgentOptions, type UseVoiceAgentResult, type UseYjsFieldResult, type UseYjsRoomResult, type UseYjsTextResult, type User, type UserCredits, type UserInfo, type UserKarma, type UserProfile, type ViewportClient, type VoiceStatus, type VoiceTranscriptEntry, type WriteError, applyDeepSpaceTheme, applyUIThemeTokens, authClient, canAutoLoadPagedResource, clampPagedResourceItems, clearAuthToken, clearDeepSpaceTheme, clientBuild, createDecoder, createEncoder, decodeAiStreamChunk, deriveLoadState, detectEnvironment, dispatch, encode, encodeAwarenessMessage, encodeSyncStep1, encodeSyncStep2, encodeUpdate, formatFileSize, formatFullTimestamp, formatMessageTime, getApiUrl, getAuthToken, getAuthUrl, getConversationDisplayName, getConversationParticipantIds, getEnvironmentConfig, getMessageType, getPagedResourceCooldownMs, getPlatformWorkerUrl, getThreadCounts, getUserColor, groupReactionsForMessage, handleAwarenessMessage, handleSyncMessage, hasContent, installClientErrorReporter, integration, isAsyncResourceSlow, isDMConversation, isDarkColor, isImageFile, isLocalDev, isProduction, parseMessageMetadata, parseSseLine, readThemeFromDOM, readVarUint, readVarUint8Array, reportClientError, resetEnvironmentCache, serverBuild, shouldGroupMessages, signIn, signOut, toConnectionStatus, toUint8Array, useAsyncResource, useAuth, useAuthProfileReady, useAuthStatus, useAuthUser, useCanvas, useChannelMembers, useChannels, useCheckout, useCommunities, useConversation, useConversations, useCronMonitor, useDisplayName, useGameRoom, useInbox, useIsDarkTheme, useJobs, useMessages, useMutations, usePagedResource, usePlatform, usePlatformWS, usePosts, usePresence, usePresenceRoom, useQuery, useR2Files, useReactions, useReadReceipts, useRecordContext, useSession, useSubscription, useUser, useUserLookup, useUsers, useVoiceAgent, useYjsField, useYjsRoom, useYjsText, writeVarUint, writeVarUint8Array };