import { SmartObjectConfig } from '@happyvertical/smrt-core'; import { CommandRequirements, DiscoveryConformanceArtifact } from '../app-contract.js'; import { TerminalAuthServiceOptions } from '../services/TerminalAuthService.js'; import { SessionLocals } from './types.js'; type ApiHttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'; export type CommandKind = 'crud' | 'custom'; export type CommandScope = 'item' | 'collection'; export interface CommandDefinition { /** Method name in source casing — source of truth for HTTP routing. */ methodName: string; /** Kebab-case identifier used by the CLI argv parser. */ commandName: string; kind: CommandKind; scope: CommandScope; httpMethod: ApiHttpMethod; /** URL path segments after `/[/]/`. May be empty. */ pathSegments: string[]; description?: string; /** JSONSchema describing the command's argv-flag surface. */ parameters?: Record; /** Retry and optimistic-concurrency fields declared by the action schema. */ requirements?: CommandRequirements; } export interface CliResource { /** Kebab-case identifier; the first positional argument after the CLI name. */ slug: string; className: string; qualifiedName?: string; packageName?: string; label: string; /** Collection segment, no leading slash, no `/api` prefix. */ apiPath: string; commands: CommandDefinition[]; } export interface ResolvedSession { user: SessionLocals['user']; membership?: SessionLocals['membership']; permissions: string[]; tenantId: string | null; sessionId: string | null; } export interface CommandPolicyContext { resource: Omit; command: CommandDefinition; session: ResolvedSession; /** * Stable identifiers for policy authors that need more than the * caller-facing `resource` view (e.g. package-scoped role checks). */ classMeta: { name: string; qualifiedName?: string; packageName?: string; decoratorConfig: SmartObjectConfig; }; } export interface ResourceListResponseBody { user: { authenticated: boolean; id?: string; }; warnings: string[]; resources: CliResource[]; /** Versioned deterministic artifact for consumers that integrity-pin discovery. */ artifact?: DiscoveryConformanceArtifact; } export interface CreateResourceListHandlerOptions extends TerminalAuthServiceOptions { /** * Ensures `ObjectRegistry` is populated before the handler walks it. * * v0.1 escape hatch: the consumer app must trigger its `@smrt()` side * effects (typically by importing the generated `smrt-register.ts`). * Without this, a fresh request handler process may see an empty * registry and return zero resources. */ ensureRegistry: () => void | Promise; /** * Resolve the caller's session. Defaults to `event.locals` (set by * `createSessionHandler` in `hooks.server.ts`) with a `Bearer ` * fallback for terminal-auth CLI clients. * * If a bearer token is present but doesn't resolve to a live session, * the handler responds 401 — NOT silent anonymous, so a stale CLI token * gets a clear signal to re-authenticate. */ resolveSession?: (event: SveltekitEvent) => Promise; /** * Per-command permission filter. Default: deny everything when the * caller is anonymous; allow everything when authenticated. * * Note: this is _capability filtering_, not row-level authorization. * Per-route handlers remain authoritative for `can user X update record Y`. */ commandPolicy?: (ctx: CommandPolicyContext) => boolean | Promise; /** * Override the slug derivation. Default: kebab-case of `collection` * (which is already plural+lowercase from the manifest generator). */ resourceSlug?: (meta: { className: string; collection: string; qualifiedName?: string; packageName?: string; }) => string; /** * Match the vite plugin's `svelteKit.kebabRoutes` setting. When `true`, * custom method URL segments are kebab-cased on the wire (the CLI sends * `/discover-from-url`); when `false`, source-cased (`/discoverFromUrl`). * Defaults to `false` to match the vite plugin default. */ kebabRoutes?: boolean; } type SveltekitEvent = { cookies: { get: (name: string) => string | undefined; }; locals?: Record; request: Request; url: URL; }; export declare function createResourceListHandler(options: CreateResourceListHandlerOptions): (event: SveltekitEvent) => Promise; /** * Thrown by the default `resolveSession` when a bearer token is present in * the request but doesn't resolve to a live session. The handler catches * this and responds 401. Exported so custom `resolveSession` implementations * can opt in to the same semantics. */ export declare class InvalidBearerError extends Error { constructor(message?: string); } export {}; //# sourceMappingURL=resource-list-handler.d.ts.map