diff --git a/logs.txt b/logs.txt new file mode 100644 index 0000000..9bad474 --- /dev/null +++ b/logs.txt @@ -0,0 +1,5177 @@ +$ bunx turbo run test 2>&1 | tee /tmp/test.log; echo ''; echo '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'; echo '📋 TEST SUMMARY'; echo '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'; grep -oP '\d+ pass' /tmp/test.log | awk '{sum+=$1} END {print "✅ Passed: " sum}'; grep -oP '\d+ fail' /tmp/test.log | awk '{sum+=$1} END {print "❌ Failed: " sum}'; grep -oP '\d+ skip' /tmp/test.log | awk '{sum+=$1} END {if (sum>0) print "⏭️ Skipped: " sum}'; grep -oP 'Ran \d+ tests?' /tmp/test.log | grep -oP '\d+' | awk '{sum+=$1} END {print "📝 Total Tests: " sum}'; echo '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━' +• turbo 2.8.12 +• Packages in scope: @betterbase/cli, @betterbase/client, @betterbase/core, @betterbase/server, @betterbase/shared, betterbase-base-template, betterbase-dashboard, my-betterbase-project +• Running test in 8 packages +• Remote caching disabled +@betterbase/shared:test: cache bypass, force executing 8b4400cf2a26c3d0 +@betterbase/cli:test: cache bypass, force executing 02d7851a51b02d74 +betterbase-base-template:test: cache bypass, force executing 37bf3c233de27165 +@betterbase/client:test: cache bypass, force executing c0475020c0412845 +@betterbase/shared:test: $ bun test +@betterbase/client:build: cache hit, replaying logs cfb18f063fc09548 +@betterbase/client:build: $ bun run src/build.ts +@betterbase/client:build: ✅ Build complete! +@betterbase/core:test: cache bypass, force executing 74db4d71cfe38fe5 +@betterbase/shared:test: bun test v1.3.13 (bf2e2cec) +betterbase-base-template:test: bun test v1.3.13 (bf2e2cec) +betterbase-base-template:test: $ bun test +@betterbase/cli:test: bun test v1.3.13 (bf2e2cec) +@betterbase/cli:test: $ bun test +@betterbase/client:test: $ bun test +@betterbase/client:test: bun test v1.3.13 (bf2e2cec) +@betterbase/shared:test: +@betterbase/shared:test: test/shared.test.ts: +@betterbase/core:test: $ bun test +@betterbase/core:build: cache hit, replaying logs d66d743fce791100 +@betterbase/core:build: $ bun build ./src/index.ts --outdir ./dist --target node +@betterbase/core:build: Bundled 439 modules in 1034ms +@betterbase/core:build: +@betterbase/core:build: index.js 2.0 MB (entry point) +@betterbase/core:build: +@betterbase/server:test: cache bypass, force executing f882ed10692d9b29 +betterbase-base-template:test: +betterbase-base-template:test: test/health.test.ts: +@betterbase/client:test: +@betterbase/client:test: test/query-builder.test.ts: +@betterbase/core:test: bun test v1.3.13 (bf2e2cec) +@betterbase/cli:test: +@betterbase/cli:test: test/route-scanner.test.ts: +@betterbase/server:test: $ bun test +@betterbase/server:test: bun test v1.3.13 (bf2e2cec) +@betterbase/shared:test: (pass) shared/errors > BetterBaseError > is a subclass of Error +@betterbase/shared:test: (pass) shared/errors > BetterBaseError > preserves message +@betterbase/shared:test: (pass) shared/errors > BetterBaseError > has code property +@betterbase/shared:test: (pass) shared/errors > BetterBaseError > has default statusCode +@betterbase/shared:test: (pass) shared/errors > BetterBaseError > accepts custom statusCode +@betterbase/shared:test: (pass) shared/errors > BetterBaseError > has correct name +@betterbase/shared:test: (pass) shared/errors > ValidationError > has correct code and statusCode +@betterbase/shared:test: (pass) shared/errors > ValidationError > is subclass of BetterBaseError +@betterbase/shared:test: (pass) shared/errors > NotFoundError > creates message with resource name +@betterbase/shared:test: (pass) shared/errors > UnauthorizedError > has correct defaults [6.00ms] +@betterbase/shared:test: (pass) shared/errors > UnauthorizedError > accepts custom message [1.00ms] +@betterbase/core:test: +@betterbase/core:test: test/rls-types.test.ts: +@betterbase/shared:test: (pass) shared/constants > exports version string +@betterbase/shared:test: (pass) shared/constants > exports default port +@betterbase/shared:test: (pass) shared/constants > exports default db path +@betterbase/shared:test: (pass) shared/constants > exports context file name +@betterbase/shared:test: (pass) shared/constants > exports config file name +@betterbase/shared:test: (pass) shared/constants > exports migrations dir +@betterbase/shared:test: (pass) shared/constants > exports functions dir +@betterbase/shared:test: (pass) shared/constants > exports policies dir +@betterbase/shared:test: (pass) shared/utils > serializeError > serializes error properties +@betterbase/shared:test: (pass) shared/utils > isValidProjectName > accepts valid lowercase names [9.00ms] +@betterbase/shared:test: (pass) shared/utils > isValidProjectName > rejects invalid names +@betterbase/shared:test: (pass) shared/utils > toCamelCase > converts snake_case to camelCase +@betterbase/shared:test: (pass) shared/utils > toCamelCase > handles empty string +@betterbase/shared:test: (pass) shared/utils > toSnakeCase > converts camelCase to snake_case [1.00ms] +@betterbase/shared:test: (pass) shared/utils > toSnakeCase > converts PascalCase to snake_case +@betterbase/shared:test: (pass) shared/utils > toSnakeCase > handles empty string +@betterbase/shared:test: (pass) shared/utils > safeJsonParse > parses valid JSON +@betterbase/shared:test: (pass) shared/utils > safeJsonParse > returns null for invalid JSON +@betterbase/shared:test: (pass) shared/utils > formatBytes > formats bytes correctly +@betterbase/shared:test: (pass) shared/utils > formatBytes > throws for negative bytes +@betterbase/shared:test: +@betterbase/shared:test: test/constants.test.ts: +@betterbase/core:test: (pass) RLS Types > definePolicy > should create a basic policy with table name +@betterbase/shared:test: (pass) constants > BETTERBASE_VERSION > should export the correct version string +@betterbase/shared:test: (pass) constants > BETTERBASE_VERSION > should be a non-empty string +@betterbase/shared:test: (pass) constants > DEFAULT_PORT > should export the correct default port +@betterbase/shared:test: (pass) constants > DEFAULT_PORT > should be a valid HTTP port number +@betterbase/shared:test: (pass) constants > DEFAULT_DB_PATH > should export the correct default database path +@betterbase/shared:test: (pass) constants > DEFAULT_DB_PATH > should be a non-empty string +@betterbase/shared:test: (pass) constants > CONTEXT_FILE_NAME > should export the correct context file name +@betterbase/shared:test: (pass) constants > CONTEXT_FILE_NAME > should be a valid file name with json extension +@betterbase/shared:test: (pass) constants > CONFIG_FILE_NAME > should export the correct config file name +@betterbase/shared:test: (pass) constants > CONFIG_FILE_NAME > should be a TypeScript file +@betterbase/shared:test: (pass) constants > MIGRATIONS_DIR > should export the correct migrations directory name +@betterbase/shared:test: (pass) constants > MIGRATIONS_DIR > should be a non-empty string +@betterbase/shared:test: (pass) constants > FUNCTIONS_DIR > should export the correct functions directory path +@betterbase/shared:test: (pass) constants > FUNCTIONS_DIR > should be a valid directory path +@betterbase/shared:test: (pass) constants > POLICIES_DIR > should export the correct policies directory path +@betterbase/shared:test: (pass) constants > POLICIES_DIR > should be a valid directory path +@betterbase/shared:test: +@betterbase/shared:test: test/errors.test.ts: +@betterbase/core:test: (pass) RLS Types > definePolicy > should create a policy with multiple operations +@betterbase/core:test: (pass) RLS Types > definePolicy > should create a policy with using clause +@betterbase/core:test: (pass) RLS Types > definePolicy > should create a policy with withCheck clause +@betterbase/core:test: (pass) RLS Types > definePolicy > should create a policy with all clauses +@betterbase/core:test: (pass) RLS Types > definePolicy > should handle empty config +@betterbase/core:test: (pass) RLS Types > isPolicyDefinition > should return true for valid policy definition [1.00ms] +@betterbase/core:test: (pass) RLS Types > isPolicyDefinition > should return true for policy with minimum required fields +@betterbase/core:test: (pass) RLS Types > isPolicyDefinition > should return false for null +@betterbase/core:test: (pass) RLS Types > isPolicyDefinition > should return false for undefined +@betterbase/core:test: (pass) RLS Types > isPolicyDefinition > should return false for primitive values +@betterbase/core:test: (pass) RLS Types > isPolicyDefinition > should return false for empty object +@betterbase/core:test: (pass) RLS Types > isPolicyDefinition > should return false for object without table +@betterbase/core:test: (pass) RLS Types > isPolicyDefinition > should return false for object with empty table string +@betterbase/core:test: (pass) RLS Types > isPolicyDefinition > should return false for object with non-string table +@betterbase/core:test: (pass) RLS Types > mergePolicies > should merge policies for the same table [2.00ms] +@betterbase/core:test: (pass) RLS Types > mergePolicies > should keep separate policies for different tables +@betterbase/core:test: (pass) RLS Types > mergePolicies > should handle three policies for same table [1.00ms] +@betterbase/core:test: (pass) RLS Types > mergePolicies > should handle empty array +@betterbase/core:test: (pass) RLS Types > mergePolicies > should handle single policy +@betterbase/core:test: (pass) RLS Types > mergePolicies > should handle using and withCheck merging +@betterbase/core:test: (pass) RLS Types > mergePolicies > should preserve later values when merging duplicate operations +@betterbase/core:test: +@betterbase/core:test: test/graphql-sdl-exporter.test.ts: +@betterbase/server:test: +@betterbase/server:test: test/inngest.test.ts: +@betterbase/server:test: (pass) Inngest client > Module exports > should export deliverWebhook function [1.00ms] +@betterbase/server:test: (pass) Inngest client > Module exports > should export evaluateNotificationRule function +@betterbase/server:test: (pass) Inngest client > Module exports > should export exportProjectUsers function +@betterbase/server:test: (pass) Inngest client > Module exports > should export pollNotificationRules function [1.00ms] +@betterbase/server:test: (pass) Inngest client > Module exports > should export allInngestFunctions array with 4 functions +@betterbase/server:test: (pass) Inngest client > Module exports > should have correct function IDs in allInngestFunctions +@betterbase/server:test: (pass) Inngest client > inngest.send event triggering > should send webhook deliver event via inngest.send +@betterbase/shared:test: (pass) errors > BetterBaseError > should create an error with message, code, and default status code +@betterbase/shared:test: (pass) errors > BetterBaseError > should create an error with custom status code +@betterbase/shared:test: (pass) errors > BetterBaseError > should be an instance of Error +@betterbase/shared:test: (pass) errors > BetterBaseError > should have stack trace +@betterbase/shared:test: (pass) errors > ValidationError > should create a validation error with correct defaults +@betterbase/shared:test: (pass) errors > ValidationError > should be an instance of BetterBaseError +@betterbase/shared:test: (pass) errors > ValidationError > should be an instance of Error +@betterbase/shared:test: (pass) errors > NotFoundError > should create a not found error with formatted message +@betterbase/shared:test: (pass) errors > NotFoundError > should create error for different resources +@betterbase/shared:test: (pass) errors > NotFoundError > should be an instance of BetterBaseError +@betterbase/shared:test: (pass) errors > NotFoundError > should be an instance of Error +@betterbase/shared:test: (pass) errors > UnauthorizedError > should create an unauthorized error with default message +@betterbase/shared:test: (pass) errors > UnauthorizedError > should create an unauthorized error with custom message +@betterbase/shared:test: (pass) errors > UnauthorizedError > should be an instance of BetterBaseError +@betterbase/shared:test: (pass) errors > UnauthorizedError > should be an instance of Error [1.00ms] +@betterbase/shared:test: +@betterbase/shared:test: test/types.test.ts: +@betterbase/server:test: (pass) Inngest client > inngest.send event triggering > should send notification evaluate event via inngest.send [1.00ms] +@betterbase/server:test: (pass) Inngest client > inngest.send event triggering > should send export users event via inngest.send +@betterbase/server:test: (pass) Inngest client > Database pool interactions > should get pool from db module [1.00ms] +@betterbase/server:test: (pass) Inngest client > Database pool interactions > should call pool.query for export job insert +@betterbase/server:test: (pass) Inngest client > Database pool interactions > should call pool.query for webhook secret lookup +@betterbase/server:test: (pass) Inngest client > Database pool interactions > should call pool.query for notification rules +@betterbase/server:test: (pass) Inngest client > Database pool interactions > should call pool.query for request logs metric +@betterbase/server:test: (pass) Inngest environment configuration > BASE_URL scenarios > should use cloud API when INNGEST_BASE_URL is undefined +@betterbase/server:test: (pass) Inngest environment configuration > BASE_URL scenarios > should use local dev server when INNGEST_BASE_URL is localhost:8288 +@betterbase/server:test: (pass) Inngest environment configuration > BASE_URL scenarios > should use self-hosted container when INNGEST_BASE_URL is inngest:8288 +@betterbase/server:test: (pass) Inngest environment configuration > Signing key > should have default signing key for development +@betterbase/server:test: (pass) Inngest environment configuration > Signing key > should use provided signing key in production +@betterbase/server:test: (pass) Inngest environment configuration > Event key > should have default event key for development +@betterbase/server:test: (pass) Inngest environment configuration > Event key > should use provided event key in production [1.00ms] +@betterbase/server:test: +@betterbase/server:test: test/instance.test.ts: +@betterbase/shared:test: (pass) types > SerializedError > should allow creating a serialized error object +@betterbase/shared:test: (pass) types > SerializedError > should allow optional properties [1.00ms] +@betterbase/shared:test: (pass) types > BetterBaseResponse > should allow creating a response with data +@betterbase/shared:test: (pass) types > BetterBaseResponse > should allow creating a response with error +@betterbase/shared:test: (pass) types > BetterBaseResponse > should allow creating a response with serialized error +@betterbase/shared:test: (pass) types > BetterBaseResponse > should allow adding count and pagination +@betterbase/shared:test: (pass) types > DBEvent > should allow creating an INSERT event +@betterbase/shared:test: (pass) types > DBEvent > should allow creating an UPDATE event with old_record +@betterbase/shared:test: (pass) types > DBEvent > should allow creating a DELETE event +@betterbase/shared:test: (pass) types > DBEventType > should allow INSERT as a valid DBEventType +@betterbase/shared:test: (pass) types > DBEventType > should allow UPDATE as a valid DBEventType +@betterbase/shared:test: (pass) types > DBEventType > should allow DELETE as a valid DBEventType +@betterbase/shared:test: (pass) types > ProviderType > should allow neon as a valid provider +@betterbase/shared:test: (pass) types > ProviderType > should allow turso as a valid provider [3.00ms] +@betterbase/shared:test: (pass) types > ProviderType > should allow planetscale as a valid provider +@betterbase/shared:test: (pass) types > ProviderType > should allow supabase as a valid provider +@betterbase/shared:test: (pass) types > ProviderType > should allow postgres as a valid provider +@betterbase/shared:test: (pass) types > ProviderType > should allow managed as a valid provider +@betterbase/shared:test: (pass) types > PaginationParams > should allow creating pagination params with limit only +@betterbase/shared:test: (pass) types > PaginationParams > should allow creating pagination params with offset only +@betterbase/shared:test: (pass) types > PaginationParams > should allow creating pagination params with both limit and offset +@betterbase/shared:test: (pass) types > PaginationParams > should allow empty pagination params +@betterbase/shared:test: +@betterbase/shared:test: test/utils.test.ts: +@betterbase/shared:test: (pass) utils > serializeError > should serialize an Error object +@betterbase/shared:test: (pass) utils > serializeError > should include all properties from error +@betterbase/shared:test: (pass) utils > serializeError > should handle custom error names +@betterbase/shared:test: (pass) utils > isValidProjectName > valid project names > should accept simple lowercase names +@betterbase/shared:test: (pass) utils > isValidProjectName > valid project names > should accept names with numbers +@betterbase/shared:test: (pass) utils > isValidProjectName > valid project names > should accept names with hyphens +@betterbase/shared:test: (pass) utils > isValidProjectName > valid project names > should accept names starting with letter and ending with number +@betterbase/shared:test: (pass) utils > isValidProjectName > valid project names > should accept single letter names +@betterbase/shared:test: (pass) utils > isValidProjectName > valid project names > should accept complex valid names +@betterbase/shared:test: (pass) utils > isValidProjectName > invalid project names > should reject empty strings +@betterbase/shared:test: (pass) utils > isValidProjectName > invalid project names > should reject names starting with numbers +@betterbase/shared:test: (pass) utils > isValidProjectName > invalid project names > should reject names starting with hyphen +@betterbase/shared:test: (pass) utils > isValidProjectName > invalid project names > should reject names ending with hyphen +@betterbase/shared:test: (pass) utils > isValidProjectName > invalid project names > should reject names with uppercase letters +@betterbase/shared:test: (pass) utils > isValidProjectName > invalid project names > should reject names with special characters +@betterbase/shared:test: (pass) utils > isValidProjectName > invalid project names > should reject whitespace-only strings +@betterbase/shared:test: (pass) utils > toCamelCase > should convert snake_case to camelCase +@betterbase/shared:test: (pass) utils > toCamelCase > should convert multiple underscores +@betterbase/shared:test: (pass) utils > toCamelCase > should handle single word +@betterbase/shared:test: (pass) utils > toCamelCase > should handle empty string +@betterbase/shared:test: (pass) utils > toCamelCase > should handle strings with no underscores +@betterbase/shared:test: (pass) utils > toCamelCase > should handle leading underscore +@betterbase/shared:test: (pass) utils > toSnakeCase > should convert camelCase to snake_case +@betterbase/shared:test: (pass) utils > toSnakeCase > should convert PascalCase to snake_case +@betterbase/shared:test: (pass) utils > toSnakeCase > should handle single word +@betterbase/shared:test: (pass) utils > toSnakeCase > should handle empty string +@betterbase/shared:test: (pass) utils > toSnakeCase > should handle consecutive uppercase letters +@betterbase/shared:test: (pass) utils > toSnakeCase > should handle numbers in string +@betterbase/shared:test: (pass) utils > toSnakeCase > should handle all uppercase +@betterbase/shared:test: (pass) utils > safeJsonParse > should parse valid JSON [1.00ms] +@betterbase/shared:test: (pass) utils > safeJsonParse > should parse JSON arrays +@betterbase/shared:test: (pass) utils > safeJsonParse > should return null for invalid JSON +@betterbase/shared:test: (pass) utils > safeJsonParse > should return null for empty string +@betterbase/shared:test: (pass) utils > safeJsonParse > should return null for partial JSON +@betterbase/shared:test: (pass) utils > safeJsonParse > should parse numbers +@betterbase/shared:test: (pass) utils > safeJsonParse > should parse booleans +@betterbase/shared:test: (pass) utils > safeJsonParse > should parse null +@betterbase/shared:test: (pass) utils > formatBytes > should format 0 bytes +@betterbase/shared:test: (pass) utils > formatBytes > should format bytes in binary units +@betterbase/shared:test: (pass) utils > formatBytes > should format with decimal places +@betterbase/shared:test: (pass) utils > formatBytes > should handle small values +@betterbase/shared:test: (pass) utils > formatBytes > should handle large values +@betterbase/shared:test: (pass) utils > formatBytes > should throw RangeError for negative bytes [1.00ms] +@betterbase/shared:test: (pass) utils > formatBytes > should throw with correct message +@betterbase/shared:test: +@betterbase/shared:test: 128 pass +@betterbase/shared:test: 0 fail +@betterbase/shared:test: 199 expect() calls +@betterbase/shared:test: Ran 128 tests across 5 files. [225.00ms] +@betterbase/server:test: (pass) instance routes > GET /admin/instance > should return settings as key-value object [2.00ms] +@betterbase/server:test: (pass) instance routes > GET /admin/instance > should return empty object when no settings exist +@betterbase/server:test: (pass) instance routes > GET /admin/instance/health > should return health status with database latency +@betterbase/server:test: (pass) instance routes > GET /admin/instance/health > should handle database connection error gracefully [2.00ms] +@betterbase/server:test: (pass) instance routes > PATCH /admin/instance > should update only provided keys [1.00ms] +@betterbase/server:test: (pass) instance routes > PATCH /admin/instance > should validate input with zod schema +@betterbase/server:test: +@betterbase/server:test: test/iac-routes.test.ts: +@betterbase/server:test: (pass) IaC Routes > GET /:projectId/iac/schema > should return schema with tables and columns [36.00ms] +@betterbase/server:test: (pass) IaC Routes > GET /:projectId/iac/schema > should handle empty schema [2.00ms] +@betterbase/server:test: (pass) IaC Routes > GET /:projectId/iac/functions > should return IaC functions [3.00ms] +@betterbase/server:test: (pass) IaC Routes > GET /:projectId/iac/functions > should handle empty functions [7.00ms] +@betterbase/server:test: (pass) IaC Routes > GET /:projectId/iac/jobs > should return scheduled jobs [3.00ms] +@betterbase/server:test: (pass) IaC Routes > GET /:projectId/iac/realtime > should return realtime stats [7.00ms] +@betterbase/server:test: (pass) IaC Routes > POST /:projectId/iac/query > should execute SELECT query [3.00ms] +@betterbase/server:test: (pass) IaC Routes > POST /:projectId/iac/query > should reject non-SELECT queries [3.00ms] +@betterbase/server:test: (pass) IaC Routes > POST /:projectId/iac/query > should reject empty SQL [1.00ms] +@betterbase/server:test: (pass) IaC Routes > POST /:projectId/iac/query > should handle query errors [3.00ms] +@betterbase/server:test: +@betterbase/server:test: test/api-keys.test.ts: +@betterbase/server:test: (pass) API Keys > key generation > should generate keys with bb_live_ prefix [1.00ms] +@betterbase/server:test: (pass) API Keys > key generation > should generate unique keys each time +@betterbase/server:test: (pass) API Keys > key generation > should generate key prefix of 8 characters +@betterbase/server:test: (pass) API Keys > key hashing > should produce SHA-256 hash +@betterbase/server:test: (pass) API Keys > key hashing > should produce consistent hash for same input [1.00ms] +@betterbase/server:test: (pass) API Keys > key hashing > should produce different hashes for different inputs +@betterbase/server:test: (pass) API Keys > API key routes > POST /admin/api-keys > should create API key and return plaintext once +@betterbase/server:test: (pass) API Keys > API key routes > POST /admin/api-keys > should allow empty scopes for full access +@betterbase/server:test: (pass) API Keys > API key routes > GET /admin/api-keys > should return keys without exposing key_hash +@betterbase/server:test: (pass) API Keys > API key routes > DELETE /admin/api-keys/:id > should only delete keys owned by the admin +@betterbase/server:test: (pass) API Keys > API key routes > DELETE /admin/api-keys/:id > should return 404 when key not found or not owned [1.00ms] +@betterbase/server:test: (pass) API Keys > API key authentication > should verify key hash matches +@betterbase/server:test: (pass) API Keys > API key authentication > should reject expired keys +@betterbase/server:test: (pass) API Keys > API key authentication > should update last_used_at on successful auth +@betterbase/server:test: +@betterbase/server:test: test/routes.test.ts: +@betterbase/server:test: (pass) routes logic tests > SMTP routes logic > should mask password when present +@betterbase/server:test: (pass) routes logic tests > SMTP routes logic > should handle missing password gracefully +@betterbase/server:test: (pass) routes logic tests > metrics enhanced logic > should support different period intervals +@betterbase/server:test: (pass) routes logic tests > metrics enhanced logic > should handle unknown period with default +@betterbase/server:test: (pass) routes logic tests > notification rules logic > should have valid metric enum values +@betterbase/server:test: (pass) routes logic tests > notification rules logic > should have valid channel enum values +@betterbase/server:test: (pass) routes logic tests > notification rules logic > should evaluate threshold breach correctly +@betterbase/server:test: (pass) routes logic tests > notification rules logic > should not breach when value is below threshold +@betterbase/server:test: (pass) routes logic tests > Inngest webhook delivery logic > should evaluate threshold breach correctly +@betterbase/server:test: (pass) routes logic tests > Inngest webhook delivery logic > should generate valid HMAC-SHA256 signature format [8.00ms] +@betterbase/server:test: (pass) routes logic tests > Inngest webhook delivery logic > should calculate retry attempt from failed attempt +@betterbase/server:test: (pass) routes logic tests > Inngest webhook delivery logic > should use webhook ID in concurrency key format [1.00ms] +@betterbase/server:test: (pass) routes logic tests > Inngest cron polling logic > should parse cron expression into 5 parts +@betterbase/server:test: (pass) routes logic tests > Inngest cron polling logic > should calculate error rate percentage +@betterbase/server:test: (pass) routes logic tests > Inngest cron polling logic > should handle zero total requests without division by zero +@betterbase/server:test: (pass) unit logic tests > schema name generation > should generate correct schema name +@betterbase/server:test: (pass) unit logic tests > key format validation > should accept valid env var keys +@betterbase/server:test: (pass) unit logic tests > key format validation > should reject invalid env var keys +@betterbase/server:test: (pass) unit logic tests > allowed auth config keys > should include provider configs +@betterbase/server:test: (pass) unit logic tests > allowed auth config keys > should reject unknown keys +@betterbase/server:test: +@betterbase/server:test: test/project-scoped.test.ts: +@betterbase/server:test: (pass) project-scoped routes > schemaName helper > should generate correct schema name from slug [1.00ms] +@betterbase/server:test: (pass) project-scoped routes > schemaName helper > should handle slug with hyphens +@betterbase/server:test: (pass) project-scoped routes > project middleware > should verify project exists before routing +@betterbase/server:test: (pass) project-scoped routes > project middleware > should return 404 when project not found +@betterbase/server:test: (pass) project-scoped routes > users route > should query users with filtering [1.00ms] +@betterbase/server:test: (pass) project-scoped routes > users route > should handle search filter +@betterbase/server:test: (pass) project-scoped routes > users route > should handle banned filter +@betterbase/server:test: (pass) project-scoped routes > ban/unban user > should structure the ban operation correctly +@betterbase/server:test: (pass) project-scoped routes > auth-config route > should have allowed keys whitelist +@betterbase/server:test: (pass) project-scoped routes > auth-config route > should validate key is in allowed list +@betterbase/server:test: (pass) project-scoped routes > env vars route > should mask secret values in response +@betterbase/server:test: (pass) project-scoped routes > env vars route > should validate key format (uppercase alphanumeric with underscores) +@betterbase/server:test: (pass) project-scoped routes > database introspection > should construct correct information_schema query +@betterbase/server:test: (pass) project-scoped routes > webhooks route > should construct webhook delivery stats query +@betterbase/server:test: (pass) project-scoped routes > functions route > should construct function invocations query [1.00ms] +@betterbase/server:test: (pass) project-scoped routes > functions route > should construct function stats query with aggregation +@betterbase/server:test: +@betterbase/server:test: test/audit.test.ts: +@betterbase/server:test: (pass) audit utility > getClientIp > should extract IP from x-forwarded-for header [1.00ms] +@betterbase/server:test: (pass) audit utility > getClientIp > should extract IP from x-real-ip header when x-forwarded-for is missing +@betterbase/server:test: (pass) audit utility > getClientIp > should return 'unknown' when no IP headers are present +@betterbase/server:test: (pass) audit utility > getClientIp > should handle empty x-forwarded-for +@betterbase/server:test: (pass) audit utility > writeAuditLog > should insert audit log entry [3.00ms] +@betterbase/server:test: (pass) audit utility > writeAuditLog > should handle minimal entry with only action [1.00ms] +@betterbase/server:test: (pass) audit utility > writeAuditLog > should include beforeData and afterData as JSON strings [3.00ms] +@betterbase/server:test: (pass) audit utility > writeAuditLog > should handle undefined optional fields +@betterbase/server:test: [audit] Failed to write log: 97 | +@betterbase/server:test: 98 | expect(mockPool.query).toHaveBeenCalled(); +@betterbase/server:test: 99 | }); +@betterbase/server:test: 100 | +@betterbase/server:test: 101 | it("should not throw on database error (fire and forget)", async () => { +@betterbase/server:test: 102 | mockPool.query.mockRejectedValueOnce(new Error("DB error")); +@betterbase/server:test: ^ +@betterbase/server:test: error: DB error +@betterbase/server:test: at (/workspaces/Betterbase/packages/server/test/audit.test.ts:102:45) +@betterbase/server:test: +@betterbase/server:test: (pass) audit utility > writeAuditLog > should not throw on database error (fire and forget) [23.00ms] +@betterbase/server:test: (pass) audit utility > AuditAction type > should accept valid audit actions [3.00ms] +@betterbase/server:test: +@betterbase/server:test: test/roles.test.ts: +@betterbase/server:test: (pass) RBAC schema > roles table > should have correct structure for system roles +@betterbase/server:test: (pass) RBAC schema > roles table > should include unique constraint on name +@betterbase/server:test: (pass) RBAC schema > permissions table > should have permissions for all domains +@betterbase/server:test: (pass) RBAC schema > permissions table > should have standard actions per domain +@betterbase/server:test: (pass) RBAC schema > role_permissions mapping > should assign all permissions to owner role [1.00ms] +@betterbase/server:test: (pass) RBAC schema > role_permissions mapping > should exclude settings_edit from admin role +@betterbase/server:test: (pass) RBAC schema > role_permissions mapping > should only include view permissions for viewer role +@betterbase/server:test: (pass) RBAC schema > admin_roles assignment > should support global (NULL) project scope +@betterbase/server:test: (pass) RBAC schema > admin_roles assignment > should support project-scoped assignments +@betterbase/server:test: (pass) RBAC schema > admin_roles assignment > should enforce unique constraint on admin_user_id + role_id + project_id +@betterbase/server:test: (pass) role routes > GET /admin/roles > should return roles with permissions array +@betterbase/server:test: (pass) role routes > POST /admin/roles/assignments > should create assignment with provided data +@betterbase/server:test: (pass) role routes > POST /admin/roles/assignments > should handle ON CONFLICT DO NOTHING +@betterbase/server:test: (pass) role routes > DELETE /admin/roles/assignments/:id > should return error when assignment not found +@betterbase/server:test: +@betterbase/server:test: 111 pass +@betterbase/server:test: 0 fail +@betterbase/server:test: 205 expect() calls +@betterbase/server:test: Ran 111 tests across 8 files. [361.00ms] +@betterbase/client:test: (pass) QueryBuilder — HTTP request construction > execute() makes a GET request [26.00ms] +@betterbase/client:test: (pass) QueryBuilder — HTTP request construction > execute() targets /api/ +@betterbase/client:test: (pass) QueryBuilder — HTTP request construction > .select() appends select param to URL [6.00ms] +@betterbase/client:test: (pass) QueryBuilder — HTTP request construction > .eq() appends filter to URL [7.00ms] +@betterbase/client:test: (pass) QueryBuilder — HTTP request construction > .limit() appends limit param to URL [2.00ms] +@betterbase/client:test: (pass) QueryBuilder — HTTP request construction > .offset() appends offset param to URL +@betterbase/client:test: (pass) QueryBuilder — HTTP request construction > .order() appends sort param to URL +@betterbase/client:test: (pass) QueryBuilder — HTTP request construction > .in() sends JSON-encoded array [3.00ms] +@betterbase/client:test: (pass) QueryBuilder — response handling > returns data array on success [3.00ms] +@betterbase/client:test: (pass) QueryBuilder — response handling > returns error: null on success [2.00ms] +@betterbase/client:test: (pass) QueryBuilder — response handling > returns error and null data on 500 [8.00ms] +@betterbase/client:test: (pass) QueryBuilder — response handling > returns error and null data when fetch throws [4.00ms] +@betterbase/client:test: (pass) QueryBuilder — response handling > is single-use — second execute() returns error [5.00ms] +@betterbase/client:test: (pass) QueryBuilder — chaining > methods are chainable and return the same builder instance [5.00ms] +@betterbase/client:test: (pass) QueryBuilder — chaining > .eq() with special characters produces a parseable URL [8.00ms] +@betterbase/client:test: (pass) QueryBuilder — insert / update / delete > insert() sends POST request +@betterbase/client:test: (pass) QueryBuilder — insert / update / delete > update() sends PATCH request [19.00ms] +@betterbase/client:test: (pass) QueryBuilder — insert / update / delete > delete() sends DELETE request [9.00ms] +@betterbase/client:test: (pass) QueryBuilder — insert / update / delete > single() sends GET to /api/
/ [1.00ms] +@betterbase/client:test: +@betterbase/client:test: test/client.test.ts: +@betterbase/client:test: (pass) @betterbase/client > creates client with config +@betterbase/client:test: (pass) @betterbase/client > from creates query builder +@betterbase/client:test: (pass) @betterbase/client > execute sends chained query with key header [5.00ms] +@betterbase/client:test: (pass) @betterbase/client > execute sends simple request +@betterbase/client:test: (pass) @betterbase/client > client has auth property with methods [3.00ms] +@betterbase/client:test: (pass) @betterbase/client > client has realtime property [2.00ms] +@betterbase/client:test: (pass) @betterbase/client > client has storage property +@betterbase/client:test: (pass) @betterbase/client > client requires url parameter [8.00ms] +@betterbase/client:test: +@betterbase/client:test: test/auth.test.ts: +@betterbase/client:test: (pass) AuthClient > constructor > creates AuthClient with default storage when no storage provided +@betterbase/client:test: (pass) AuthClient > constructor > creates AuthClient with custom storage +@betterbase/client:test: (pass) AuthClient > constructor > creates AuthClient with auth state change callback +@betterbase/client:test: (pass) AuthClient > signUp > returns success with user and session on successful signup [2.00ms] +@betterbase/client:test: (pass) AuthClient > signUp > stores session token in storage on successful signup [1.00ms] +@betterbase/client:test: (pass) AuthClient > signUp > calls auth state change callback on successful signup +@betterbase/client:test: (pass) AuthClient > signUp > returns AuthError when signup fails with error response +@betterbase/client:test: (pass) AuthClient > signUp > returns NetworkError when network request fails [1.00ms] +@betterbase/client:test: (pass) AuthClient > signIn > returns success with user and session on successful signin [2.00ms] +@betterbase/client:test: (pass) AuthClient > signIn > stores session token in storage on successful signin +@betterbase/client:test: (pass) AuthClient > signIn > returns AuthError when signin fails with invalid credentials +@betterbase/client:test: (pass) AuthClient > signIn > returns NetworkError when network request fails +@betterbase/client:test: (pass) AuthClient > signOut > returns success on successful signout +@betterbase/client:test: (pass) AuthClient > signOut > removes session token from storage on signout [1.00ms] +@betterbase/client:test: (pass) AuthClient > signOut > calls auth state change callback with null on signout +@betterbase/client:test: (pass) AuthClient > signOut > returns AuthError when signout fails +@betterbase/client:test: (pass) AuthClient > signOut > handles network error during signout gracefully +@betterbase/client:test: (pass) AuthClient > getSession > returns success with user and session when session exists [1.00ms] +@betterbase/client:test: (pass) AuthClient > getSession > returns null data without error when no session exists +@betterbase/client:test: (pass) AuthClient > getSession > returns AuthError when session retrieval fails +@betterbase/client:test: (pass) AuthClient > getSession > returns NetworkError when network request fails +@betterbase/client:test: (pass) AuthClient > getToken > returns token from storage when present [1.00ms] +@betterbase/client:test: (pass) AuthClient > getToken > returns null when no token in storage +@betterbase/client:test: (pass) AuthClient > setToken > stores token in storage when token is provided +@betterbase/client:test: (pass) AuthClient > setToken > calls auth state change callback when token is set +@betterbase/client:test: (pass) AuthClient > setToken > removes token from storage when null is provided +@betterbase/client:test: (pass) AuthClient > setToken > calls auth state change callback with null when token is cleared +@betterbase/client:test: +@betterbase/client:test: test/errors.test.ts: +@betterbase/client:test: (pass) errors > BetterBaseError > is a subclass of Error +@betterbase/client:test: (pass) errors > BetterBaseError > preserves message +@betterbase/client:test: (pass) errors > BetterBaseError > has name property [1.00ms] +@betterbase/client:test: (pass) errors > BetterBaseError > can be thrown and caught +@betterbase/client:test: (pass) errors > NetworkError > is a subclass of BetterBaseError +@betterbase/client:test: (pass) errors > NetworkError > has correct name +@betterbase/client:test: (pass) errors > AuthError > is a subclass of BetterBaseError +@betterbase/client:test: (pass) errors > AuthError > has correct name +@betterbase/client:test: (pass) errors > ValidationError > is a subclass of BetterBaseError +@betterbase/client:test: (pass) errors > ValidationError > has correct name +@betterbase/client:test: (pass) errors > ValidationError > error hierarchy is correct +@betterbase/client:test: +@betterbase/client:test: test/edge-cases.test.ts: +@betterbase/client:test: (pass) Client SDK — network failure handling > handles fetch throwing a network error — returns error, not throw [1.00ms] +@betterbase/client:test: (pass) Client SDK — network failure handling > error message reflects the original network error +@betterbase/client:test: (pass) Client SDK — network failure handling > handles server 500 without throwing +@betterbase/client:test: (pass) Client SDK — network failure handling > handles server returning non-JSON body without throwing [6.00ms] +@betterbase/client:test: (pass) Client SDK — network failure handling > handles 404 response without throwing +@betterbase/client:test: (pass) Client SDK — URL encoding > .eq() with special characters produces a parseable URL +@betterbase/client:test: (pass) Client SDK — URL encoding > .in() with special characters in values produces a parseable URL [1.00ms] +@betterbase/client:test: (pass) Client SDK — URL encoding > table name is correctly included in the request URL +@betterbase/client:test: (pass) Client SDK — single-use QueryBuilder > calling execute() twice on same builder returns error on second call +@betterbase/client:test: (pass) Client SDK — single-use QueryBuilder > each client.from() call creates a fresh independent builder [1.00ms] +@betterbase/client:test: (pass) Client SDK — boundary inputs > .limit(0) sends limit=0 in request [1.00ms] +@betterbase/client:test: (pass) Client SDK — boundary inputs > .offset(0) sends offset=0 in request [1.00ms] +@betterbase/client:test: +@betterbase/client:test: test/realtime.test.ts: +@betterbase/client:test: (pass) RealtimeClient — no WebSocket environment > can be constructed without throwing +@betterbase/client:test: (pass) RealtimeClient — no WebSocket environment > setToken() does not throw [1.00ms] +@betterbase/client:test: (pass) RealtimeClient — no WebSocket environment > from() returns an object with an on() method +@betterbase/client:test: (pass) RealtimeClient — no WebSocket environment > from().on() returns an object with a subscribe() method +@betterbase/client:test: (pass) RealtimeClient — no WebSocket environment > subscribe() returns an object with an unsubscribe() method [1.00ms] +@betterbase/client:test: (pass) RealtimeClient — no WebSocket environment > unsubscribe() does not throw +@betterbase/client:test: (pass) RealtimeClient — no WebSocket environment > disconnect() does not throw +@betterbase/client:test: (pass) RealtimeClient — no WebSocket environment > callback is NOT called when disabled (no WebSocket) +@betterbase/client:test: [BetterBase] WebSocket error: ErrorEvent { +@betterbase/client:test: type: "error", +@betterbase/client:test: message: "WebSocket connection to 'ws://localhost:3000/ws' failed: Failed to connect", +@betterbase/client:test: error: error: WebSocket connection to 'ws://localhost:3000/ws' failed: Failed to connect +@betterbase/client:test: , +@betterbase/client:test: } +@betterbase/client:test: [BetterBase] WebSocket error: ErrorEvent { +@betterbase/client:test: type: "error", +@betterbase/client:test: message: "WebSocket connection to 'ws://localhost:3000/ws' failed: Failed to connect", +@betterbase/client:test: error: error: WebSocket connection to 'ws://localhost:3000/ws' failed: Failed to connect +@betterbase/client:test: , +@betterbase/client:test: } +@betterbase/client:test: (pass) RealtimeClient — with mock WebSocket > subscribe() triggers a WebSocket connection [23.00ms] +@betterbase/client:test: (pass) RealtimeClient — with mock WebSocket > subscribe() sends a subscribe message after connection opens [24.00ms] +@betterbase/client:test: (pass) RealtimeClient — with mock WebSocket > INSERT callback fires when server sends matching event [22.00ms] +@betterbase/core:test: (pass) SDL Exporter > exportSDL > should export basic schema to SDL [39.00ms] +@betterbase/core:test: (pass) SDL Exporter > exportSDL > should include Query type in SDL [5.00ms] +@betterbase/core:test: (pass) SDL Exporter > exportSDL > should include Mutation type in SDL [10.00ms] +@betterbase/core:test: (pass) SDL Exporter > exportSDL > should include Object types in SDL [5.00ms] +@betterbase/client:test: (pass) RealtimeClient — with mock WebSocket > callback does NOT fire for a different table [30.00ms] +@betterbase/core:test: (pass) SDL Exporter > exportSDL > should include Input types in SDL [6.00ms] +@betterbase/core:test: (pass) SDL Exporter > exportSDL > should include scalar types in SDL [6.00ms] +@betterbase/core:test: (pass) SDL Exporter > exportSDL > should respect includeDescriptions option [1.00ms] +@betterbase/core:test: (pass) SDL Exporter > exportSDL > should respect useCommentSyntax option [4.00ms] +@betterbase/core:test: (pass) SDL Exporter > exportSDL > should respect sortTypes option [5.00ms] +@betterbase/core:test: (pass) SDL Exporter > exportSDL > should include header comment [1.00ms] +@betterbase/core:test: (pass) SDL Exporter > exportTypeSDL > should export specific Object type [4.00ms] +@betterbase/client:test: (pass) RealtimeClient — with mock WebSocket > wildcard event '*' receives all event types [23.00ms] +@betterbase/core:test: (pass) SDL Exporter > exportTypeSDL > should export specific Input type [3.00ms] +@betterbase/core:test: (pass) SDL Exporter > exportTypeSDL > should throw error for non-existent type [1.00ms] +@betterbase/core:test: (pass) SDL Exporter > exportTypeSDL > should respect includeDescriptions option [1.00ms] +@betterbase/core:test: (pass) SDL Exporter > exportTypeSDL > should export scalar types [2.00ms] +@betterbase/core:test: (pass) SDL Exporter > saveSDL > should be a function [1.00ms] +@betterbase/core:test: (pass) SDL Exporter > SDL output validation > should produce valid SDL syntax +@betterbase/core:test: (pass) SDL Exporter > SDL output validation > should properly format field arguments [2.00ms] +@betterbase/core:test: (pass) SDL Exporter > SDL output validation > should include non-null markers for required fields [2.00ms] +@betterbase/core:test: +@betterbase/core:test: test/logger-functions.test.ts: +@betterbase/client:test: (pass) RealtimeClient — with mock WebSocket > unsubscribe() sends unsubscribe message when last subscriber leaves [22.00ms] +@betterbase/client:test: (pass) RealtimeClient — with mock WebSocket > WebSocket URL uses ws:// protocol [22.00ms] +@betterbase/client:test: (pass) RealtimeClient — with mock WebSocket > token is appended to WebSocket URL when provided [23.00ms] +@betterbase/client:test: +@betterbase/client:test: test/iac.test.ts: +@betterbase/client:test: (pass) IaC Client Integration Tests > createBetterBaseClient > should create a client with valid config +@betterbase/client:test: (pass) IaC Client Integration Tests > createBetterBaseClient > should create client and allow close +@betterbase/client:test: (pass) IaC Client Integration Tests > useQuery hook > should return default state on mount +@betterbase/client:test: (pass) IaC Client Integration Tests > useMutation hook > should return mutation interface +@betterbase/client:test: (pass) IaC Client Integration Tests > useAction hook > should return action interface +@betterbase/client:test: (pass) IaC Client Integration Tests > BetterbaseProvider > should export Provider component +@betterbase/client:test: (pass) Type exports > should export UseQueryResult type [1.00ms] +@betterbase/client:test: (pass) Type exports > should export BetterBaseConfig type +@betterbase/client:test: +@betterbase/client:test: test/storage.test.ts: +@betterbase/client:test: (pass) Storage > constructor > creates Storage instance +@betterbase/client:test: (pass) Storage > from > returns StorageBucketClient for specified bucket +@betterbase/client:test: (pass) Storage > from > creates bucket client with different bucket names +@betterbase/client:test: (pass) StorageBucketClient > upload > uploads file successfully and returns path and url [3.00ms] +@betterbase/client:test: (pass) StorageBucketClient > upload > uploads with custom content type +@betterbase/client:test: (pass) StorageBucketClient > upload > uploads with metadata headers +@betterbase/client:test: (pass) StorageBucketClient > upload > returns error when upload fails with non-ok response [18.00ms] +@betterbase/client:test: (pass) StorageBucketClient > upload > returns NetworkError when network request fails [6.00ms] +@betterbase/client:test: (pass) StorageBucketClient > download > downloads file successfully and returns Blob [4.00ms] +@betterbase/client:test: (pass) StorageBucketClient > download > returns error when download fails with non-ok response [4.00ms] +@betterbase/client:test: (pass) StorageBucketClient > download > returns NetworkError when network request fails +@betterbase/client:test: (pass) StorageBucketClient > getPublicUrl > returns public URL successfully [4.00ms] +@betterbase/client:test: (pass) StorageBucketClient > getPublicUrl > returns error when getting public URL fails [1.00ms] +@betterbase/client:test: (pass) StorageBucketClient > getPublicUrl > returns NetworkError when network request fails +@betterbase/client:test: (pass) StorageBucketClient > createSignedUrl > creates signed URL without options [1.00ms] +@betterbase/client:test: (pass) StorageBucketClient > createSignedUrl > creates signed URL with expiresIn option +@betterbase/client:test: (pass) StorageBucketClient > createSignedUrl > returns error when creating signed URL fails +@betterbase/client:test: (pass) StorageBucketClient > createSignedUrl > returns NetworkError when network request fails [2.00ms] +@betterbase/client:test: (pass) StorageBucketClient > remove > removes single file successfully [2.00ms] +@betterbase/client:test: (pass) StorageBucketClient > remove > removes multiple files successfully +@betterbase/client:test: (pass) StorageBucketClient > remove > returns error when remove fails [2.00ms] +@betterbase/client:test: (pass) StorageBucketClient > remove > returns NetworkError when network request fails [1.00ms] +@betterbase/client:test: (pass) StorageBucketClient > list > lists files without prefix [1.00ms] +@betterbase/client:test: (pass) StorageBucketClient > list > lists files with prefix filter +@betterbase/client:test: (pass) StorageBucketClient > list > returns empty array when no files exist [1.00ms] +@betterbase/client:test: (pass) StorageBucketClient > list > returns error when list fails +@betterbase/client:test: (pass) StorageBucketClient > list > returns NetworkError when network request fails [1.00ms] +@betterbase/client:test: (pass) StorageBucketClient > path encoding > properly encodes special characters in file paths +@betterbase/client:test: +@betterbase/client:test: 129 pass +@betterbase/client:test: 0 fail +@betterbase/client:test: 220 expect() calls +@betterbase/client:test: Ran 129 tests across 8 files. [1105.00ms] +@betterbase/core:test: (pass) Logger Functions > createRequestLogger > should create a child logger with reqId +@betterbase/core:test: (pass) Logger Functions > createRequestLogger > should generate unique request IDs +@betterbase/core:test: (pass) Logger Functions > createRequestLogger > should allow logging with the request logger [12.00ms] +@betterbase/core:test: (pass) Logger Functions > logSlowQuery > should not log when query is fast +@betterbase/core:test: (pass) Logger Functions > logSlowQuery > should log warning when query exceeds threshold +@betterbase/core:test: (pass) Logger Functions > logSlowQuery > should use default threshold of 100ms +@betterbase/core:test: (pass) Logger Functions > logSlowQuery > should log warning with custom threshold +@betterbase/core:test: (pass) Logger Functions > logSlowQuery > should handle empty query string +@betterbase/core:test: (pass) Logger Functions > logSlowQuery > should handle very long query strings +@betterbase/core:test: (pass) Logger Functions > logError > should log error with message [7.00ms] +@betterbase/core:test: (pass) Logger Functions > logError > should log error with context [3.00ms] +@betterbase/core:test: (pass) Logger Functions > logError > should log error with empty context +@betterbase/core:test: (pass) Logger Functions > logError > should handle error without stack trace +@betterbase/core:test: (pass) Logger Functions > logError > should handle error with custom name [2.00ms] +@betterbase/core:test: (pass) Logger Functions > logError > should handle various context values +@betterbase/core:test: (pass) Logger Functions > logSuccess > should log success with operation name +@betterbase/core:test: (pass) Logger Functions > logSuccess > should log success with metadata +@betterbase/core:test: (pass) Logger Functions > logSuccess > should log success with empty metadata +@betterbase/core:test: (pass) Logger Functions > logSuccess > should handle zero duration +@betterbase/core:test: (pass) Logger Functions > logSuccess > should handle long operation names [9.00ms] +@betterbase/core:test: (pass) Logger Functions > logSuccess > should handle complex metadata [5.00ms] +@betterbase/core:test: +@betterbase/core:test: test/storage-s3-adapter.test.ts: +@betterbase/cli:test: (pass) RouteScanner > extracts hono routes with auth and schemas (GET + POST) [77.00ms] +@betterbase/cli:test: (pass) RouteScanner > extracts PATCH routes [19.00ms] +@betterbase/cli:test: (pass) RouteScanner > extracts DELETE routes [19.00ms] +@betterbase/cli:test: (pass) RouteScanner > extracts public routes with no auth [5.00ms] +@betterbase/cli:test: (pass) RouteScanner > handles malformed decorators / syntax errors in route definitions [8.00ms] +@betterbase/cli:test: (pass) RouteScanner > discovers routes in nested directory groups [4.00ms] +@betterbase/cli:test: (pass) RouteScanner > extracts routes with multiple middleware [9.00ms] +@betterbase/cli:test: (pass) RouteScanner > extracts routes with query parameter validation [16.00ms] +@betterbase/cli:test: (pass) RouteScanner > handles mixed protected and public routes in the same file [5.00ms] +@betterbase/cli:test: (pass) RouteScanner > handles empty route files with no handlers [1.00ms] +@betterbase/cli:test: (pass) RouteScanner > PATCH and DELETE routes with both auth and no-auth variants [9.00ms] +@betterbase/cli:test: (pass) RouteScanner > No-auth routes (routes without requireAuth or optionalAuth) [5.00ms] +@betterbase/cli:test: (pass) RouteScanner > Malformed decorators (missing parentheses, invalid syntax) [10.00ms] +@betterbase/cli:test: (pass) RouteScanner > Nested route groups (app.group('/api', ...) with nested routes) [5.00ms] +@betterbase/cli:test: (pass) RouteScanner > Mixed public/protected in same file (detailed) [5.00ms] +@betterbase/cli:test: (pass) RouteScanner > Routes with CORS and other middleware that might confuse scanner [2.00ms] +@betterbase/cli:test: +@betterbase/cli:test: test/graphql-type-map.test.ts: +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > Integer types > should map integer to Int +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > Integer types > should map int to Int +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > Integer types > should map smallint to Int +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > Integer types > should map bigint to Int +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > Integer types > should handle uppercase INTEGER +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > Float types > should map real to Float +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > Float types > should map double to Float +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > Float types > should map float to Float +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > Float types > should map numeric to Float +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > Float types > should map decimal to Float +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > Float types > should handle case insensitivity for float types +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > Boolean types > should map boolean to Boolean +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > Boolean types > should map bool to Boolean +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > Boolean types > should handle case insensitivity for boolean types +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > String types > should map text to String +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > String types > should map varchar to String +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > String types > should map char to String +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > String types > should handle case insensitivity for string types +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > UUID types > should map uuid to ID +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > UUID types > should handle case insensitivity for uuid +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > DateTime types > should map timestamp to DateTime +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > DateTime types > should map timestamptz to DateTime +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > DateTime types > should map datetime to DateTime +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > DateTime types > should map date to DateTime +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > DateTime types > should handle case insensitivity for datetime types +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > JSON types > should map json to JSON +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > JSON types > should map jsonb to JSON +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > JSON types > should handle case insensitivity for json types +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > Binary types > should map blob to String +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > Binary types > should map bytea to String +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > Binary types > should handle case insensitivity for binary types +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > Default fallback > should return String for unknown types +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > Default fallback > should return String for empty string +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > Default fallback > should return String for custom types +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > Edge cases > should handle types with numbers (fallback to String) +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > Edge cases > should handle types with underscores (fallback to String) +@betterbase/cli:test: (pass) CLI GraphQL Type Map - drizzleTypeToGraphQL > Edge cases > should handle types with spaces +@betterbase/cli:test: (pass) CLI GraphQL Type Map - Integration Tests > should correctly map a complete PostgreSQL table schema +@betterbase/cli:test: (pass) CLI GraphQL Type Map - Integration Tests > should correctly map a complete MySQL table schema +@betterbase/cli:test: (pass) CLI GraphQL Type Map - Integration Tests > should correctly map a complete SQLite table schema +@betterbase/cli:test: (pass) CLI GraphQL Type Map - Integration Tests > should correctly map a user profile table schema [1.00ms] +@betterbase/cli:test: (pass) CLI GraphQL Type Map - Integration Tests > should correctly map an e-commerce products table schema +@betterbase/cli:test: (pass) CLI GraphQL Type Map - typeMap completeness > should have mappings for all PostgreSQL types +@betterbase/cli:test: (pass) CLI GraphQL Type Map - typeMap completeness > should have mappings for all MySQL types [1.00ms] +@betterbase/cli:test: (pass) CLI GraphQL Type Map - typeMap completeness > should have mappings for all SQLite types +@betterbase/cli:test: (pass) CLI GraphQL Type Map - Source File Comparison > should match the typeMap in src/commands/graphql.ts exactly [4.00ms] +@betterbase/cli:test: +@betterbase/cli:test: test/init.test.ts: +@betterbase/cli:test: (pass) runInitCommand > creates project with project name [1.00ms] +@betterbase/cli:test: (pass) runInitCommand > InitCommandOptions type is correct +@betterbase/cli:test: +@betterbase/cli:test: test/iac-commands.test.ts: +@betterbase/core:test: [18:04:06.645] INFO: test message +@betterbase/core:test: reqId: "4jTY52sNkD" +@betterbase/core:test: [18:04:06.648] WARN: Slow query detected +@betterbase/core:test: query: "SELECT * FROM users WHERE id = 1" +@betterbase/core:test: duration_ms: 200 +@betterbase/core:test: threshold_ms: 100 +@betterbase/core:test: [18:04:06.648] WARN: Slow query detected +@betterbase/core:test: query: "SELECT * FROM users" +@betterbase/core:test: duration_ms: 500 +@betterbase/core:test: threshold_ms: 200 +@betterbase/core:test: [18:04:06.648] WARN: Slow query detected +@betterbase/core:test: query: "" +@betterbase/core:test: duration_ms: 200 +@betterbase/core:test: threshold_ms: 100 +@betterbase/core:test: [18:04:06.648] WARN: Slow query detected +@betterbase/core:test: query: "SELECT aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +@betterbase/core:test: duration_ms: 200 +@betterbase/core:test: threshold_ms: 100 +@betterbase/core:test: [18:04:06.648] ERROR: Test error +@betterbase/core:test: stack: "Error: Test error\n at (/workspaces/Betterbase/packages/core/test/logger-functions.test.ts:86:22)" +@betterbase/core:test: error_name: "Error" +@betterbase/core:test: [18:04:06.657] ERROR: Test error +@betterbase/core:test: stack: "Error: Test error\n at (/workspaces/Betterbase/packages/core/test/logger-functions.test.ts:92:22)" +@betterbase/core:test: error_name: "Error" +@betterbase/core:test: userId: "123" +@betterbase/core:test: operation: "test" +@betterbase/core:test: [18:04:06.658] ERROR: Test error +@betterbase/core:test: stack: "Error: Test error\n at (/workspaces/Betterbase/packages/core/test/logger-functions.test.ts:99:22)" +@betterbase/core:test: error_name: "Error" +@betterbase/core:test: [18:04:06.658] ERROR: Test error +@betterbase/core:test: error_name: "Error" +@betterbase/core:test: [18:04:06.659] ERROR: Test error +@betterbase/core:test: stack: "CustomError: Test error\n at (/workspaces/Betterbase/packages/core/test/logger-functions.test.ts:113:22)" +@betterbase/core:test: error_name: "CustomError" +@betterbase/core:test: [18:04:06.659] ERROR: Test error +@betterbase/core:test: stack: "Error: Test error\n at (/workspaces/Betterbase/packages/core/test/logger-functions.test.ts:120:22)" +@betterbase/core:test: error_name: "Error" +@betterbase/core:test: userId: "123" +@betterbase/core:test: count: 42 +@betterbase/core:test: active: true +@betterbase/core:test: data: { +@betterbase/core:test: "nested": "value" +@betterbase/core:test: } +@betterbase/core:test: [18:04:06.660] INFO: Operation completed: test_operation +@betterbase/core:test: operation: "test_operation" +@betterbase/core:test: duration_ms: 100 +@betterbase/core:test: [18:04:06.660] INFO: Operation completed: test_operation +@betterbase/core:test: operation: "test_operation" +@betterbase/core:test: duration_ms: 100 +@betterbase/core:test: records: 10 +@betterbase/core:test: userId: "123" +@betterbase/core:test: [18:04:06.660] INFO: Operation completed: test_operation +@betterbase/core:test: operation: "test_operation" +@betterbase/core:test: duration_ms: 100 +@betterbase/core:test: [18:04:06.660] INFO: Operation completed: test_operation +@betterbase/core:test: operation: "test_operation" +@betterbase/core:test: duration_ms: 0 +@betterbase/core:test: [18:04:06.668] INFO: Operation completed: very_long_operation_name_that_does_something +@betterbase/core:test: operation: "very_long_operation_name_that_does_something" +@betterbase/core:test: duration_ms: 500 +@betterbase/core:test: [18:04:06.674] INFO: Operation completed: test +@betterbase/core:test: operation: "test" +@betterbase/core:test: duration_ms: 100 +@betterbase/core:test: users: [ +@betterbase/core:test: "user1", +@betterbase/core:test: "user2" +@betterbase/core:test: ] +@betterbase/core:test: count: 2 +@betterbase/core:test: data: { +@betterbase/core:test: "key": "value" +@betterbase/core:test: } +@betterbase/cli:test: 68 | return files; +@betterbase/cli:test: 69 | } +@betterbase/cli:test: 70 | +@betterbase/cli:test: 71 | function analyzeQuery(filePath: string, betterbaseDir: string): QueryAnalysis { +@betterbase/cli:test: 72 | const content = readFileSync(filePath, "utf-8"); +@betterbase/cli:test: 73 | const path = relative(betterbaseDir, filePath); +@betterbase/cli:test: ^ +@betterbase/cli:test: ReferenceError: relative is not defined +@betterbase/cli:test: at analyzeQuery (/workspaces/Betterbase/packages/cli/src/commands/iac/analyze.ts:73:15) +@betterbase/cli:test: at runIacAnalyze (/workspaces/Betterbase/packages/cli/src/commands/iac/analyze.ts:30:20) +@betterbase/cli:test: at captureConsole (/workspaces/Betterbase/packages/cli/test/iac-commands.test.ts:36:9) +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/iac-commands.test.ts:66:24) +@betterbase/cli:test: (fail) runIacAnalyze > should analyze queries and return results [7.00ms] +@betterbase/cli:test: 68 | return files; +@betterbase/cli:test: 69 | } +@betterbase/cli:test: 70 | +@betterbase/cli:test: 71 | function analyzeQuery(filePath: string, betterbaseDir: string): QueryAnalysis { +@betterbase/cli:test: 72 | const content = readFileSync(filePath, "utf-8"); +@betterbase/cli:test: 73 | const path = relative(betterbaseDir, filePath); +@betterbase/cli:test: ^ +@betterbase/cli:test: ReferenceError: relative is not defined +@betterbase/cli:test: at analyzeQuery (/workspaces/Betterbase/packages/cli/src/commands/iac/analyze.ts:73:15) +@betterbase/cli:test: at runIacAnalyze (/workspaces/Betterbase/packages/cli/src/commands/iac/analyze.ts:30:20) +@betterbase/cli:test: at captureConsole (/workspaces/Betterbase/packages/cli/test/iac-commands.test.ts:36:9) +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/iac-commands.test.ts:90:24) +@betterbase/cli:test: (fail) runIacAnalyze > should detect N+1 query patterns [2.00ms] +@betterbase/cli:test: 68 | return files; +@betterbase/cli:test: 69 | } +@betterbase/cli:test: 70 | +@betterbase/cli:test: 71 | function analyzeQuery(filePath: string, betterbaseDir: string): QueryAnalysis { +@betterbase/cli:test: 72 | const content = readFileSync(filePath, "utf-8"); +@betterbase/cli:test: 73 | const path = relative(betterbaseDir, filePath); +@betterbase/cli:test: ^ +@betterbase/cli:test: ReferenceError: relative is not defined +@betterbase/cli:test: at analyzeQuery (/workspaces/Betterbase/packages/cli/src/commands/iac/analyze.ts:73:15) +@betterbase/cli:test: at runIacAnalyze (/workspaces/Betterbase/packages/cli/src/commands/iac/analyze.ts:30:20) +@betterbase/cli:test: at captureConsole (/workspaces/Betterbase/packages/cli/test/iac-commands.test.ts:36:9) +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/iac-commands.test.ts:107:24) +@betterbase/cli:test: (fail) runIacAnalyze > should detect missing index usage [3.00ms] +@betterbase/cli:test: 68 | return files; +@betterbase/cli:test: 69 | } +@betterbase/cli:test: 70 | +@betterbase/cli:test: 71 | function analyzeQuery(filePath: string, betterbaseDir: string): QueryAnalysis { +@betterbase/cli:test: 72 | const content = readFileSync(filePath, "utf-8"); +@betterbase/cli:test: 73 | const path = relative(betterbaseDir, filePath); +@betterbase/cli:test: ^ +@betterbase/cli:test: ReferenceError: relative is not defined +@betterbase/cli:test: at analyzeQuery (/workspaces/Betterbase/packages/cli/src/commands/iac/analyze.ts:73:15) +@betterbase/cli:test: at runIacAnalyze (/workspaces/Betterbase/packages/cli/src/commands/iac/analyze.ts:30:20) +@betterbase/cli:test: at captureConsole (/workspaces/Betterbase/packages/cli/test/iac-commands.test.ts:36:9) +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/iac-commands.test.ts:121:24) +@betterbase/cli:test: (fail) runIacAnalyze > should output results in json format [1.00ms] +@betterbase/cli:test: 68 | return files; +@betterbase/cli:test: 69 | } +@betterbase/cli:test: 70 | +@betterbase/cli:test: 71 | function analyzeQuery(filePath: string, betterbaseDir: string): QueryAnalysis { +@betterbase/cli:test: 72 | const content = readFileSync(filePath, "utf-8"); +@betterbase/cli:test: 73 | const path = relative(betterbaseDir, filePath); +@betterbase/cli:test: ^ +@betterbase/cli:test: ReferenceError: relative is not defined +@betterbase/cli:test: at analyzeQuery (/workspaces/Betterbase/packages/cli/src/commands/iac/analyze.ts:73:15) +@betterbase/cli:test: at runIacAnalyze (/workspaces/Betterbase/packages/cli/src/commands/iac/analyze.ts:30:20) +@betterbase/cli:test: at captureConsole (/workspaces/Betterbase/packages/cli/test/iac-commands.test.ts:36:9) +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/iac-commands.test.ts:160:24) +@betterbase/cli:test: (fail) runIacAnalyze > should calculate complexity correctly [1.00ms] +@betterbase/cli:test: 68 | return files; +@betterbase/cli:test: 69 | } +@betterbase/cli:test: 70 | +@betterbase/cli:test: 71 | function analyzeQuery(filePath: string, betterbaseDir: string): QueryAnalysis { +@betterbase/cli:test: 72 | const content = readFileSync(filePath, "utf-8"); +@betterbase/cli:test: 73 | const path = relative(betterbaseDir, filePath); +@betterbase/cli:test: ^ +@betterbase/cli:test: ReferenceError: relative is not defined +@betterbase/cli:test: at analyzeQuery (/workspaces/Betterbase/packages/cli/src/commands/iac/analyze.ts:73:15) +@betterbase/cli:test: at runIacAnalyze (/workspaces/Betterbase/packages/cli/src/commands/iac/analyze.ts:30:20) +@betterbase/cli:test: at captureConsole (/workspaces/Betterbase/packages/cli/test/iac-commands.test.ts:36:9) +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/iac-commands.test.ts:181:24) +@betterbase/cli:test: (fail) runIacAnalyze > should detect N+1 query patterns using for loops [2.00ms] +@betterbase/cli:test: 68 | return files; +@betterbase/cli:test: 69 | } +@betterbase/cli:test: 70 | +@betterbase/cli:test: 71 | function analyzeQuery(filePath: string, betterbaseDir: string): QueryAnalysis { +@betterbase/cli:test: 72 | const content = readFileSync(filePath, "utf-8"); +@betterbase/cli:test: 73 | const path = relative(betterbaseDir, filePath); +@betterbase/cli:test: ^ +@betterbase/cli:test: ReferenceError: relative is not defined +@betterbase/cli:test: at analyzeQuery (/workspaces/Betterbase/packages/cli/src/commands/iac/analyze.ts:73:15) +@betterbase/cli:test: at runIacAnalyze (/workspaces/Betterbase/packages/cli/src/commands/iac/analyze.ts:30:20) +@betterbase/cli:test: at captureConsole (/workspaces/Betterbase/packages/cli/test/iac-commands.test.ts:36:9) +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/iac-commands.test.ts:197:24) +@betterbase/cli:test: (fail) runIacAnalyze > should detect manual join patterns [2.00ms] +@betterbase/cli:test: 68 | return files; +@betterbase/cli:test: 69 | } +@betterbase/cli:test: 70 | +@betterbase/cli:test: 71 | function analyzeQuery(filePath: string, betterbaseDir: string): QueryAnalysis { +@betterbase/cli:test: 72 | const content = readFileSync(filePath, "utf-8"); +@betterbase/cli:test: 73 | const path = relative(betterbaseDir, filePath); +@betterbase/cli:test: ^ +@betterbase/cli:test: ReferenceError: relative is not defined +@betterbase/cli:test: at analyzeQuery (/workspaces/Betterbase/packages/cli/src/commands/iac/analyze.ts:73:15) +@betterbase/cli:test: at runIacAnalyze (/workspaces/Betterbase/packages/cli/src/commands/iac/analyze.ts:30:20) +@betterbase/cli:test: at captureConsole (/workspaces/Betterbase/packages/cli/test/iac-commands.test.ts:36:9) +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/iac-commands.test.ts:229:24) +@betterbase/cli:test: (fail) runIacAnalyze > should handle multiple query files [3.00ms] +@betterbase/cli:test: ◆ Analyzing queries... +@betterbase/cli:test: 233 | expect(results).toHaveLength(3); +@betterbase/cli:test: 234 | }); +@betterbase/cli:test: 235 | +@betterbase/cli:test: +@betterbase/cli:test: 📊 Query Analysis Results +@betterbase/cli:test: +@betterbase/cli:test: ════════════════════════════════════════════════════════════════════════════════ +@betterbase/cli:test: Path Complexity Issues +@betterbase/cli:test: ════════════════════════════════════════════════════════════════════════════════ +@betterbase/cli:test: ════════════════════════════════════════════════════════════════════════════════ +@betterbase/cli:test: 236 | it("should throw when queries directory is missing", async () => { +@betterbase/cli:test: +@betterbase/cli:test: 237 | rmSync(join(testProjectRoot, "betterbase", "queries"), { recursive: true, force: true }); +@betterbase/cli:test: Total: 0 | High: 0 | Medium: 0 | Low: 0 +@betterbase/cli:test: 238 | await expect(runIacAnalyze(testProjectRoot)).rejects.toThrow(); +@betterbase/cli:test: +@betterbase/cli:test: ^ +@betterbase/cli:test: error: +@betterbase/cli:test: +@betterbase/cli:test: Expected promise that rejects +@betterbase/cli:test: Received promise that resolved: Promise { } +@betterbase/cli:test: +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/iac-commands.test.ts:238:56) +@betterbase/cli:test: (fail) runIacAnalyze > should throw when queries directory is missing +@betterbase/cli:test: 68 | return files; +@betterbase/cli:test: 69 | } +@betterbase/cli:test: 70 | +@betterbase/cli:test: 71 | function analyzeQuery(filePath: string, betterbaseDir: string): QueryAnalysis { +@betterbase/cli:test: 72 | const content = readFileSync(filePath, "utf-8"); +@betterbase/cli:test: 73 | const path = relative(betterbaseDir, filePath); +@betterbase/cli:test: ^ +@betterbase/cli:test: ReferenceError: relative is not defined +@betterbase/cli:test: at analyzeQuery (/workspaces/Betterbase/packages/cli/src/commands/iac/analyze.ts:73:15) +@betterbase/cli:test: at runIacAnalyze (/workspaces/Betterbase/packages/cli/src/commands/iac/analyze.ts:30:20) +@betterbase/cli:test: at captureConsole (/workspaces/Betterbase/packages/cli/test/iac-commands.test.ts:36:9) +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/iac-commands.test.ts:256:24) +@betterbase/cli:test: (fail) runIacAnalyze > should support nested betterbase directory structure [3.00ms] +@betterbase/cli:test: (pass) runIacExport > should handle json format export [1.00ms] +@betterbase/cli:test: (pass) runIacExport > should handle sql format export +@betterbase/cli:test: (pass) runIacExport > should use default format when not specified [2.00ms] +@betterbase/cli:test: (pass) runIacExport > should handle output path correctly +@betterbase/cli:test: (pass) runIacExport > should handle table-specific export [1.00ms] +@betterbase/cli:test: (pass) runIacExport > should accept absolute output paths [1.00ms] +@betterbase/cli:test: (pass) runIacExport > should accept custom table names with special characters +@betterbase/cli:test: (pass) runIacExport > should log export initialization success [2.00ms] +@betterbase/cli:test: (pass) runIacExport > should handle nested output directories [1.00ms] +@betterbase/cli:test: (pass) runIacImport > should detect json input files +@betterbase/cli:test: (pass) runIacImport > should detect sql input files [3.00ms] +@betterbase/cli:test: (pass) runIacImport > should respect dry-run flag +@betterbase/cli:test: (pass) runIacImport > should default dry-run to false [1.00ms] +@betterbase/cli:test: (pass) runIacImport > should error on missing input file [1.00ms] +@betterbase/cli:test: (pass) runIacImport > should handle table-specific imports [2.00ms] +@betterbase/cli:test: (pass) runIacImport > should handle complex json data structures [2.00ms] +@betterbase/cli:test: (pass) runIacImport > should accept absolute input paths [1.00ms] +@betterbase/cli:test: (pass) runIacImport > should log import success after processing [1.00ms] +@betterbase/cli:test: Migrating Convex project from /tmp/convex-migration-test/convex... +@betterbase/cli:test: Output will be in /tmp/convex-migration-test/migrated +@betterbase/cli:test: ✅ Converted schema.ts +@betterbase/cli:test: +@betterbase/cli:test: ✅ Convex Migration Complete! +@betterbase/cli:test: +@betterbase/cli:test: Converted files are in: /tmp/convex-migration-test/migrated +@betterbase/cli:test: +@betterbase/cli:test: Key changes made: +@betterbase/cli:test: - Convex v.* validators -> BetterBase v.* +@betterbase/cli:test: - Convex query/mutation/action -> BetterBase query/mutation/action +@betterbase/cli:test: - ctx.db.query() syntax preserved +@betterbase/cli:test: - ctx.runQuery/ctx.runMutation -> ctx.runQuery/ctx.runMutation +@betterbase/cli:test: +@betterbase/cli:test: Manual steps required: +@betterbase/cli:test: 1. Review the generated schema and adjust types if needed +@betterbase/cli:test: 2. Install dependencies: bun add @betterbase/core @betterbase/client +@betterbase/cli:test: 3. Run bb iac sync to create database tables +@betterbase/cli:test: 4. Test your functions +@betterbase/cli:test: 5. Review compatibility report: /tmp/convex-migration-test/migrated/betterbase/convex-migration-report.json +@betterbase/cli:test: +@betterbase/cli:test: Compatibility summary: +@betterbase/cli:test: - Blockers: 0 +@betterbase/cli:test: - Warnings: 0 +@betterbase/cli:test: - Files requiring manual review: 0 +@betterbase/cli:test: +@betterbase/cli:test: See docs/iac/migration-from-convex.md for detailed guide. +@betterbase/cli:test: +@betterbase/cli:test: (pass) runMigrateFromConvex > should convert Convex schema to BetterBase schema [6.00ms] +@betterbase/cli:test: Migrating Convex project from /tmp/convex-migration-test/convex... +@betterbase/cli:test: Output will be in /tmp/convex-migration-test/migrated +@betterbase/cli:test: ✅ Converted 1 querys +@betterbase/cli:test: (pass) runMigrateFromConvex > should convert Convex queries to BetterBase queries [3.00ms] +@betterbase/cli:test: +@betterbase/cli:test: ✅ Convex Migration Complete! +@betterbase/cli:test: +@betterbase/cli:test: Converted files are in: /tmp/convex-migration-test/migrated +@betterbase/cli:test: +@betterbase/cli:test: Key changes made: +@betterbase/cli:test: - Convex v.* validators -> BetterBase v.* +@betterbase/cli:test: - Convex query/mutation/action -> BetterBase query/mutation/action +@betterbase/cli:test: - ctx.db.query() syntax preserved +@betterbase/cli:test: - ctx.runQuery/ctx.runMutation -> ctx.runQuery/ctx.runMutation +@betterbase/cli:test: +@betterbase/cli:test: Manual steps required: +@betterbase/cli:test: 1. Review the generated schema and adjust types if needed +@betterbase/cli:test: 2. Install dependencies: bun add @betterbase/core @betterbase/client +@betterbase/cli:test: 3. Run bb iac sync to create database tables +@betterbase/cli:test: 4. Test your functions +@betterbase/cli:test: 5. Review compatibility report: /tmp/convex-migration-test/migrated/betterbase/convex-migration-report.json +@betterbase/cli:test: +@betterbase/cli:test: Compatibility summary: +@betterbase/cli:test: - Blockers: 0 +@betterbase/cli:test: - Warnings: 0 +@betterbase/cli:test: - Files requiring manual review: 0 +@betterbase/cli:test: +@betterbase/cli:test: See docs/iac/migration-from-convex.md for detailed guide. +@betterbase/cli:test: +@betterbase/cli:test: Migrating Convex project from /tmp/convex-migration-test/convex... +@betterbase/cli:test: Output will be in /tmp/convex-migration-test/migrated +@betterbase/cli:test: ✅ Converted 1 mutations +@betterbase/cli:test: +@betterbase/cli:test: ✅ Convex Migration Complete! +@betterbase/cli:test: +@betterbase/cli:test: Converted files are in: /tmp/convex-migration-test/migrated +@betterbase/cli:test: +@betterbase/cli:test: Key changes made: +@betterbase/cli:test: - Convex v.* validators -> BetterBase v.* +@betterbase/cli:test: - Convex query/mutation/action -> BetterBase query/mutation/action +@betterbase/cli:test: - ctx.db.query() syntax preserved +@betterbase/cli:test: - ctx.runQuery/ctx.runMutation -> ctx.runQuery/ctx.runMutation +@betterbase/cli:test: +@betterbase/cli:test: Manual steps required: +@betterbase/cli:test: 1. Review the generated schema and adjust types if needed +@betterbase/cli:test: 2. Install dependencies: bun add @betterbase/core @betterbase/client +@betterbase/cli:test: 3. Run bb iac sync to create database tables +@betterbase/cli:test: 4. Test your functions +@betterbase/cli:test: 5. Review compatibility report: /tmp/convex-migration-test/migrated/betterbase/convex-migration-report.json +@betterbase/cli:test: +@betterbase/cli:test: Compatibility summary: +@betterbase/cli:test: - Blockers: 0 +@betterbase/cli:test: - Warnings: 0 +@betterbase/cli:test: - Files requiring manual review: 0 +@betterbase/cli:test: +@betterbase/cli:test: See docs/iac/migration-from-convex.md for detailed guide. +@betterbase/cli:test: +@betterbase/cli:test: (pass) runMigrateFromConvex > should convert Convex mutations to BetterBase mutations [5.00ms] +@betterbase/cli:test: Migrating Convex project from /tmp/convex-migration-test/convex... +@betterbase/cli:test: Output will be in /tmp/convex-migration-test/migrated +@betterbase/cli:test: ✅ Converted 1 actions +@betterbase/cli:test: +@betterbase/cli:test: ✅ Convex Migration Complete! +@betterbase/cli:test: +@betterbase/cli:test: Converted files are in: /tmp/convex-migration-test/migrated +@betterbase/cli:test: +@betterbase/cli:test: Key changes made: +@betterbase/cli:test: - Convex v.* validators -> BetterBase v.* +@betterbase/cli:test: - Convex query/mutation/action -> BetterBase query/mutation/action +@betterbase/cli:test: - ctx.db.query() syntax preserved +@betterbase/cli:test: - ctx.runQuery/ctx.runMutation -> ctx.runQuery/ctx.runMutation +@betterbase/cli:test: +@betterbase/cli:test: Manual steps required: +@betterbase/cli:test: 1. Review the generated schema and adjust types if needed +@betterbase/cli:test: 2. Install dependencies: bun add @betterbase/core @betterbase/client +@betterbase/cli:test: 3. Run bb iac sync to create database tables +@betterbase/cli:test: 4. Test your functions +@betterbase/cli:test: 5. Review compatibility report: /tmp/convex-migration-test/migrated/betterbase/convex-migration-report.json +@betterbase/cli:test: +@betterbase/cli:test: Compatibility summary: +@betterbase/cli:test: - Blockers: 0 +@betterbase/cli:test: - Warnings: 0 +@betterbase/cli:test: - Files requiring manual review: 0 +@betterbase/cli:test: +@betterbase/cli:test: See docs/iac/migration-from-convex.md for detailed guide. +@betterbase/cli:test: +@betterbase/cli:test: (pass) runMigrateFromConvex > should convert Convex actions to BetterBase actions [2.00ms] +@betterbase/cli:test: Migrating Convex project from /tmp/convex-migration-test/convex... +@betterbase/cli:test: Output will be in /tmp/convex-migration-test/migrated +@betterbase/cli:test: ✅ Converted schema.ts +@betterbase/cli:test: +@betterbase/cli:test: ✅ Convex Migration Complete! +@betterbase/cli:test: +@betterbase/cli:test: Converted files are in: /tmp/convex-migration-test/migrated +@betterbase/cli:test: +@betterbase/cli:test: Key changes made: +@betterbase/cli:test: - Convex v.* validators -> BetterBase v.* +@betterbase/cli:test: - Convex query/mutation/action -> BetterBase query/mutation/action +@betterbase/cli:test: - ctx.db.query() syntax preserved +@betterbase/cli:test: - ctx.runQuery/ctx.runMutation -> ctx.runQuery/ctx.runMutation +@betterbase/cli:test: +@betterbase/cli:test: Manual steps required: +@betterbase/cli:test: 1. Review the generated schema and adjust types if needed +@betterbase/cli:test: 2. Install dependencies: bun add @betterbase/core @betterbase/client +@betterbase/cli:test: 3. Run bb iac sync to create database tables +@betterbase/cli:test: 4. Test your functions +@betterbase/cli:test: 5. Review compatibility report: /tmp/convex-migration-test/migrated/betterbase/convex-migration-report.json +@betterbase/cli:test: +@betterbase/cli:test: Compatibility summary: +@betterbase/cli:test: - Blockers: 0 +@betterbase/cli:test: - Warnings: 0 +@betterbase/cli:test: - Files requiring manual review: 0 +@betterbase/cli:test: +@betterbase/cli:test: See docs/iac/migration-from-convex.md for detailed guide. +@betterbase/cli:test: +@betterbase/cli:test: (pass) runMigrateFromConvex > should create proper directory structure in output [4.00ms] +@betterbase/cli:test: Migrating Convex project from /tmp/convex-migration-test/convex... +@betterbase/cli:test: Output will be in /tmp/convex-migration-test/migrated +@betterbase/cli:test: ✅ Converted 1 querys +@betterbase/cli:test: +@betterbase/cli:test: ✅ Convex Migration Complete! +@betterbase/cli:test: +@betterbase/cli:test: Converted files are in: /tmp/convex-migration-test/migrated +@betterbase/cli:test: +@betterbase/cli:test: Key changes made: +@betterbase/cli:test: - Convex v.* validators -> BetterBase v.* +@betterbase/cli:test: - Convex query/mutation/action -> BetterBase query/mutation/action +@betterbase/cli:test: - ctx.db.query() syntax preserved +@betterbase/cli:test: - ctx.runQuery/ctx.runMutation -> ctx.runQuery/ctx.runMutation +@betterbase/cli:test: +@betterbase/cli:test: Manual steps required: +@betterbase/cli:test: 1. Review the generated schema and adjust types if needed +@betterbase/cli:test: 2. Install dependencies: bun add @betterbase/core @betterbase/client +@betterbase/cli:test: 3. Run bb iac sync to create database tables +@betterbase/cli:test: 4. Test your functions +@betterbase/cli:test: 5. Review compatibility report: /tmp/convex-migration-test/migrated/betterbase/convex-migration-report.json +@betterbase/cli:test: +@betterbase/cli:test: Compatibility summary: +@betterbase/cli:test: - Blockers: 0 +@betterbase/cli:test: - Warnings: 0 +@betterbase/cli:test: - Files requiring manual review: 0 +@betterbase/cli:test: +@betterbase/cli:test: See docs/iac/migration-from-convex.md for detailed guide. +@betterbase/cli:test: +@betterbase/cli:test: (pass) runMigrateFromConvex > should replace Convex imports with BetterBase imports in functions [2.00ms] +@betterbase/cli:test: Migrating Convex project from /tmp/convex-migration-test/convex... +@betterbase/cli:test: Output will be in /tmp/convex-migration-test/migrated +@betterbase/cli:test: ✅ Converted schema.ts +@betterbase/cli:test: +@betterbase/cli:test: ✅ Convex Migration Complete! +@betterbase/cli:test: +@betterbase/cli:test: Converted files are in: /tmp/convex-migration-test/migrated +@betterbase/cli:test: +@betterbase/cli:test: Key changes made: +@betterbase/cli:test: - Convex v.* validators -> BetterBase v.* +@betterbase/cli:test: - Convex query/mutation/action -> BetterBase query/mutation/action +@betterbase/cli:test: - ctx.db.query() syntax preserved +@betterbase/cli:test: - ctx.runQuery/ctx.runMutation -> ctx.runQuery/ctx.runMutation +@betterbase/cli:test: +@betterbase/cli:test: Manual steps required: +@betterbase/cli:test: 1. Review the generated schema and adjust types if needed +@betterbase/cli:test: 2. Install dependencies: bun add @betterbase/core @betterbase/client +@betterbase/cli:test: 3. Run bb iac sync to create database tables +@betterbase/cli:test: 4. Test your functions +@betterbase/cli:test: 5. Review compatibility report: /tmp/convex-migration-test/migrated/betterbase/convex-migration-report.json +@betterbase/cli:test: +@betterbase/cli:test: Compatibility summary: +@betterbase/cli:test: - Blockers: 0 +@betterbase/cli:test: - Warnings: 0 +@betterbase/cli:test: - Files requiring manual review: 0 +@betterbase/cli:test: +@betterbase/cli:test: See docs/iac/migration-from-convex.md for detailed guide. +@betterbase/cli:test: +@betterbase/cli:test: (pass) runMigrateFromConvex > should handle schema with no tables [2.00ms] +@betterbase/cli:test: Migrating Convex project from /tmp/convex-migration-test/convex... +@betterbase/cli:test: Output will be in /tmp/convex-migration-test/migrated +@betterbase/cli:test: ✅ Converted schema.ts +@betterbase/cli:test: +@betterbase/cli:test: ✅ Convex Migration Complete! +@betterbase/cli:test: +@betterbase/cli:test: Converted files are in: /tmp/convex-migration-test/migrated +@betterbase/cli:test: +@betterbase/cli:test: Key changes made: +@betterbase/cli:test: - Convex v.* validators -> BetterBase v.* +@betterbase/cli:test: - Convex query/mutation/action -> BetterBase query/mutation/action +@betterbase/cli:test: - ctx.db.query() syntax preserved +@betterbase/cli:test: - ctx.runQuery/ctx.runMutation -> ctx.runQuery/ctx.runMutation +@betterbase/cli:test: +@betterbase/cli:test: Manual steps required: +@betterbase/cli:test: 1. Review the generated schema and adjust types if needed +@betterbase/cli:test: 2. Install dependencies: bun add @betterbase/core @betterbase/client +@betterbase/cli:test: 3. Run bb iac sync to create database tables +@betterbase/cli:test: 4. Test your functions +@betterbase/cli:test: 5. Review compatibility report: /tmp/convex-migration-test/migrated/betterbase/convex-migration-report.json +@betterbase/cli:test: +@betterbase/cli:test: Compatibility summary: +@betterbase/cli:test: - Blockers: 0 +@betterbase/cli:test: - Warnings: 0 +@betterbase/cli:test: - Files requiring manual review: 0 +@betterbase/cli:test: +@betterbase/cli:test: See docs/iac/migration-from-convex.md for detailed guide. +@betterbase/cli:test: +@betterbase/cli:test: (pass) runMigrateFromConvex > should generate migration report JSON file [3.00ms] +@betterbase/cli:test: Migrating Convex project from /tmp/convex-migration-test/convex... +@betterbase/cli:test: Output will be in /tmp/convex-migration-test/migrated +@betterbase/cli:test: (pass) runMigrateFromConvex > should generate migration report markdown file [2.00ms] +@betterbase/cli:test: ✅ Converted schema.ts +@betterbase/cli:test: +@betterbase/cli:test: ✅ Convex Migration Complete! +@betterbase/cli:test: +@betterbase/cli:test: Converted files are in: /tmp/convex-migration-test/migrated +@betterbase/cli:test: +@betterbase/cli:test: Key changes made: +@betterbase/cli:test: - Convex v.* validators -> BetterBase v.* +@betterbase/cli:test: - Convex query/mutation/action -> BetterBase query/mutation/action +@betterbase/cli:test: - ctx.db.query() syntax preserved +@betterbase/cli:test: - ctx.runQuery/ctx.runMutation -> ctx.runQuery/ctx.runMutation +@betterbase/cli:test: +@betterbase/cli:test: Manual steps required: +@betterbase/cli:test: 1. Review the generated schema and adjust types if needed +@betterbase/cli:test: 2. Install dependencies: bun add @betterbase/core @betterbase/client +@betterbase/cli:test: 3. Run bb iac sync to create database tables +@betterbase/cli:test: 4. Test your functions +@betterbase/cli:test: 5. Review compatibility report: /tmp/convex-migration-test/migrated/betterbase/convex-migration-report.json +@betterbase/cli:test: +@betterbase/cli:test: Compatibility summary: +@betterbase/cli:test: - Blockers: 0 +@betterbase/cli:test: - Warnings: 0 +@betterbase/cli:test: - Files requiring manual review: 0 +@betterbase/cli:test: +@betterbase/cli:test: See docs/iac/migration-from-convex.md for detailed guide. +@betterbase/cli:test: +@betterbase/cli:test: Migrating Convex project from /tmp/convex-migration-test/convex... +@betterbase/cli:test: Output will be in /tmp/convex-migration-test/migrated +@betterbase/cli:test: ✅ Converted 1 querys +@betterbase/cli:test: +@betterbase/cli:test: ✅ Convex Migration Complete! +@betterbase/cli:test: +@betterbase/cli:test: Converted files are in: /tmp/convex-migration-test/migrated +@betterbase/cli:test: +@betterbase/cli:test: Key changes made: +@betterbase/cli:test: - Convex v.* validators -> BetterBase v.* +@betterbase/cli:test: - Convex query/mutation/action -> BetterBase query/mutation/action +@betterbase/cli:test: - ctx.db.query() syntax preserved +@betterbase/cli:test: - ctx.runQuery/ctx.runMutation -> ctx.runQuery/ctx.runMutation +@betterbase/cli:test: +@betterbase/cli:test: Manual steps required: +@betterbase/cli:test: 1. Review the generated schema and adjust types if needed +@betterbase/cli:test: 2. Install dependencies: bun add @betterbase/core @betterbase/client +@betterbase/cli:test: 3. Run bb iac sync to create database tables +@betterbase/cli:test: 4. Test your functions +@betterbase/cli:test: 5. Review compatibility report: /tmp/convex-migration-test/migrated/betterbase/convex-migration-report.json +@betterbase/cli:test: +@betterbase/cli:test: Compatibility summary: +@betterbase/cli:test: - Blockers: 1 +@betterbase/cli:test: - Warnings: 0 +@betterbase/cli:test: - Files requiring manual review: 1 +@betterbase/cli:test: +@betterbase/cli:test: See docs/iac/migration-from-convex.md for detailed guide. +@betterbase/cli:test: +@betterbase/cli:test: (pass) runMigrateFromConvex > should detect httpAction as blocker [1.00ms] +@betterbase/cli:test: Migrating Convex project from /tmp/convex-migration-test/convex... +@betterbase/cli:test: Output will be in /tmp/convex-migration-test/migrated +@betterbase/cli:test: ✅ Converted 1 querys +@betterbase/cli:test: +@betterbase/cli:test: ✅ Convex Migration Complete! +@betterbase/cli:test: +@betterbase/cli:test: Converted files are in: /tmp/convex-migration-test/migrated +@betterbase/cli:test: +@betterbase/cli:test: Key changes made: +@betterbase/cli:test: - Convex v.* validators -> BetterBase v.* +@betterbase/cli:test: - Convex query/mutation/action -> BetterBase query/mutation/action +@betterbase/cli:test: - ctx.db.query() syntax preserved +@betterbase/cli:test: - ctx.runQuery/ctx.runMutation -> ctx.runQuery/ctx.runMutation +@betterbase/cli:test: +@betterbase/cli:test: Manual steps required: +@betterbase/cli:test: 1. Review the generated schema and adjust types if needed +@betterbase/cli:test: 2. Install dependencies: bun add @betterbase/core @betterbase/client +@betterbase/cli:test: 3. Run bb iac sync to create database tables +@betterbase/cli:test: 4. Test your functions +@betterbase/cli:test: 5. Review compatibility report: /tmp/convex-migration-test/migrated/betterbase/convex-migration-report.json +@betterbase/cli:test: +@betterbase/cli:test: Compatibility summary: +@betterbase/cli:test: - Blockers: 1 +@betterbase/cli:test: - Warnings: 0 +@betterbase/cli:test: - Files requiring manual review: 1 +@betterbase/cli:test: +@betterbase/cli:test: See docs/iac/migration-from-convex.md for detailed guide. +@betterbase/cli:test: +@betterbase/cli:test: (pass) runMigrateFromConvex > should detect cronJobs as blocker [3.00ms] +@betterbase/cli:test: (pass) runMigrateFromConvex > should throw when input directory does not exist +@betterbase/cli:test: Migrating Convex project from /tmp/convex-migration-test/convex... +@betterbase/cli:test: Output will be in /tmp/convex-migration-test/migrated +@betterbase/cli:test: ✅ Converted schema.ts +@betterbase/cli:test: ✅ Converted 1 querys +@betterbase/cli:test: ✅ Converted 1 mutations +@betterbase/cli:test: (pass) runMigrateFromConvex > should count converted files accurately in report [2.00ms] +@betterbase/cli:test: ✅ Converted 1 actions +@betterbase/cli:test: +@betterbase/cli:test: ✅ Convex Migration Complete! +@betterbase/cli:test: +@betterbase/cli:test: Converted files are in: /tmp/convex-migration-test/migrated +@betterbase/cli:test: +@betterbase/cli:test: Key changes made: +@betterbase/cli:test: - Convex v.* validators -> BetterBase v.* +@betterbase/cli:test: - Convex query/mutation/action -> BetterBase query/mutation/action +@betterbase/cli:test: - ctx.db.query() syntax preserved +@betterbase/cli:test: - ctx.runQuery/ctx.runMutation -> ctx.runQuery/ctx.runMutation +@betterbase/cli:test: +@betterbase/cli:test: Manual steps required: +@betterbase/cli:test: 1. Review the generated schema and adjust types if needed +@betterbase/cli:test: 2. Install dependencies: bun add @betterbase/core @betterbase/client +@betterbase/cli:test: 3. Run bb iac sync to create database tables +@betterbase/cli:test: 4. Test your functions +@betterbase/cli:test: 5. Review compatibility report: /tmp/convex-migration-test/migrated/betterbase/convex-migration-report.json +@betterbase/cli:test: +@betterbase/cli:test: Compatibility summary: +@betterbase/cli:test: - Blockers: 0 +@betterbase/cli:test: - Warnings: 0 +@betterbase/cli:test: - Files requiring manual review: 0 +@betterbase/cli:test: +@betterbase/cli:test: See docs/iac/migration-from-convex.md for detailed guide. +@betterbase/cli:test: +@betterbase/cli:test: Migrating Convex project from /tmp/convex-migration-test/convex... +@betterbase/cli:test: (pass) runMigrateFromConvex > should convert v.string(), v.number(), v.boolean() validators [2.00ms] +@betterbase/cli:test: Output will be in /tmp/convex-migration-test/migrated +@betterbase/cli:test: (pass) Integration Tests > should set up test project structure +@betterbase/cli:test: ✅ Converted schema.ts +@betterbase/cli:test: +@betterbase/cli:test: (pass) Integration Tests > should create sample query file [1.00ms] +@betterbase/cli:test: ✅ Convex Migration Complete! +@betterbase/cli:test: +@betterbase/cli:test: Converted files are in: /tmp/convex-migration-test/migrated +@betterbase/cli:test: +@betterbase/cli:test: Key changes made: +@betterbase/cli:test: - Convex v.* validators -> BetterBase v.* +@betterbase/cli:test: - Convex query/mutation/action -> BetterBase query/mutation/action +@betterbase/cli:test: - ctx.db.query() syntax preserved +@betterbase/cli:test: - ctx.runQuery/ctx.runMutation -> ctx.runQuery/ctx.runMutation +@betterbase/cli:test: +@betterbase/cli:test: Manual steps required: +@betterbase/cli:test: 1. Review the generated schema and adjust types if needed +@betterbase/cli:test: 2. Install dependencies: bun add @betterbase/core @betterbase/client +@betterbase/cli:test: 3. Run bb iac sync to create database tables +@betterbase/cli:test: 4. Test your functions +@betterbase/cli:test: 5. Review compatibility report: /tmp/convex-migration-test/migrated/betterbase/convex-migration-report.json +@betterbase/cli:test: +@betterbase/cli:test: Compatibility summary: +@betterbase/cli:test: - Blockers: 0 +@betterbase/cli:test: - Warnings: 0 +@betterbase/cli:test: - Files requiring manual review: 0 +@betterbase/cli:test: +@betterbase/cli:test: See docs/iac/migration-from-convex.md for detailed guide. +@betterbase/cli:test: +@betterbase/cli:test: (pass) Integration Tests > should create sample mutation file [1.00ms] +@betterbase/cli:test: (pass) Integration Tests > should create sample schema file +@betterbase/cli:test: 68 | return files; +@betterbase/cli:test: 69 | } +@betterbase/cli:test: 70 | +@betterbase/cli:test: 71 | function analyzeQuery(filePath: string, betterbaseDir: string): QueryAnalysis { +@betterbase/cli:test: 72 | const content = readFileSync(filePath, "utf-8"); +@betterbase/cli:test: 73 | const path = relative(betterbaseDir, filePath); +@betterbase/cli:test: ^ +@betterbase/cli:test: ReferenceError: relative is not defined +@betterbase/cli:test: at analyzeQuery (/workspaces/Betterbase/packages/cli/src/commands/iac/analyze.ts:73:15) +@betterbase/cli:test: at runIacAnalyze (/workspaces/Betterbase/packages/cli/src/commands/iac/analyze.ts:30:20) +@betterbase/cli:test: at captureConsole (/workspaces/Betterbase/packages/cli/test/iac-commands.test.ts:36:9) +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/iac-commands.test.ts:818:31) +@betterbase/cli:test: (fail) Integration Tests > should run full analyze-export-import workflow [1.00ms] +@betterbase/cli:test: (pass) Integration Tests > should handle Convex migration with blocker issues [2.00ms] +@betterbase/cli:test: Migrating Convex project from /tmp/iac-integration-test/convex... +@betterbase/cli:test: Output will be in /tmp/iac-integration-test/migrated +@betterbase/cli:test: ✅ Converted schema.ts +@betterbase/cli:test: ✅ Converted 1 querys +@betterbase/cli:test: ✅ Converted 1 mutations +@betterbase/cli:test: ✅ Converted 1 actions +@betterbase/cli:test: +@betterbase/cli:test: ✅ Convex Migration Complete! +@betterbase/cli:test: +@betterbase/cli:test: Converted files are in: /tmp/iac-integration-test/migrated +@betterbase/cli:test: +@betterbase/cli:test: Key changes made: +@betterbase/cli:test: - Convex v.* validators -> BetterBase v.* +@betterbase/cli:test: - Convex query/mutation/action -> BetterBase query/mutation/action +@betterbase/cli:test: - ctx.db.query() syntax preserved +@betterbase/cli:test: - ctx.runQuery/ctx.runMutation -> ctx.runQuery/ctx.runMutation +@betterbase/cli:test: +@betterbase/cli:test: Manual steps required: +@betterbase/cli:test: 1. Review the generated schema and adjust types if needed +@betterbase/cli:test: 2. Install dependencies: bun add @betterbase/core @betterbase/client +@betterbase/cli:test: 3. Run bb iac sync to create database tables +@betterbase/cli:test: 4. Test your functions +@betterbase/cli:test: 5. Review compatibility report: /tmp/iac-integration-test/migrated/betterbase/convex-migration-report.json +@betterbase/cli:test: +@betterbase/cli:test: Compatibility summary: +@betterbase/cli:test: - Blockers: 0 +@betterbase/cli:test: - Warnings: 0 +@betterbase/cli:test: - Files requiring manual review: 0 +@betterbase/cli:test: +@betterbase/cli:test: See docs/iac/migration-from-convex.md for detailed guide. +@betterbase/cli:test: +@betterbase/cli:test: (pass) Integration Tests > should complete full Convex migration with all file types [2.00ms] +@betterbase/cli:test: Migrating Convex project from /tmp/iac-integration-test/convex... +@betterbase/cli:test: Output will be in /tmp/iac-integration-test/migrated +@betterbase/cli:test: ✅ Converted schema.ts +@betterbase/cli:test: (pass) Integration Tests > should convert edge cases: optional fields and arrays [2.00ms] +@betterbase/cli:test: +@betterbase/cli:test: ✅ Convex Migration Complete! +@betterbase/cli:test: +@betterbase/cli:test: Converted files are in: /tmp/iac-integration-test/migrated +@betterbase/cli:test: +@betterbase/cli:test: Key changes made: +@betterbase/cli:test: - Convex v.* validators -> BetterBase v.* +@betterbase/cli:test: - Convex query/mutation/action -> BetterBase query/mutation/action +@betterbase/cli:test: - ctx.db.query() syntax preserved +@betterbase/cli:test: - ctx.runQuery/ctx.runMutation -> ctx.runQuery/ctx.runMutation +@betterbase/cli:test: +@betterbase/cli:test: Manual steps required: +@betterbase/cli:test: 1. Review the generated schema and adjust types if needed +@betterbase/cli:test: 2. Install dependencies: bun add @betterbase/core @betterbase/client +@betterbase/cli:test: 3. Run bb iac sync to create database tables +@betterbase/cli:test: 4. Test your functions +@betterbase/cli:test: 5. Review compatibility report: /tmp/iac-integration-test/migrated/betterbase/convex-migration-report.json +@betterbase/cli:test: +@betterbase/cli:test: Compatibility summary: +@betterbase/cli:test: - Blockers: 0 +@betterbase/cli:test: - Warnings: 0 +@betterbase/cli:test: - Files requiring manual review: 0 +@betterbase/cli:test: +@betterbase/cli:test: See docs/iac/migration-from-convex.md for detailed guide. +@betterbase/cli:test: +@betterbase/cli:test: Migrating Convex project from /tmp/iac-integration-test/convex... +@betterbase/cli:test: Output will be in /tmp/iac-integration-test/migrated +@betterbase/cli:test: ✅ Converted 1 querys +@betterbase/cli:test: +@betterbase/cli:test: (pass) Integration Tests > should preserve function logic during conversion [3.00ms] +@betterbase/cli:test: ✅ Convex Migration Complete! +@betterbase/cli:test: +@betterbase/cli:test: Converted files are in: /tmp/iac-integration-test/migrated +@betterbase/cli:test: +@betterbase/cli:test: Key changes made: +@betterbase/cli:test: - Convex v.* validators -> BetterBase v.* +@betterbase/cli:test: - Convex query/mutation/action -> BetterBase query/mutation/action +@betterbase/cli:test: - ctx.db.query() syntax preserved +@betterbase/cli:test: - ctx.runQuery/ctx.runMutation -> ctx.runQuery/ctx.runMutation +@betterbase/cli:test: +@betterbase/cli:test: Manual steps required: +@betterbase/cli:test: 1. Review the generated schema and adjust types if needed +@betterbase/cli:test: 2. Install dependencies: bun add @betterbase/core @betterbase/client +@betterbase/cli:test: 3. Run bb iac sync to create database tables +@betterbase/cli:test: 4. Test your functions +@betterbase/cli:test: 5. Review compatibility report: /tmp/iac-integration-test/migrated/betterbase/convex-migration-report.json +@betterbase/cli:test: +@betterbase/cli:test: Compatibility summary: +@betterbase/cli:test: - Blockers: 0 +@betterbase/cli:test: - Warnings: 0 +@betterbase/cli:test: - Files requiring manual review: 0 +@betterbase/cli:test: +@betterbase/cli:test: See docs/iac/migration-from-convex.md for detailed guide. +@betterbase/cli:test: +@betterbase/cli:test: Migrating Convex project from /tmp/iac-integration-test/convex... +@betterbase/cli:test: Output will be in /tmp/iac-integration-test/migrated +@betterbase/cli:test: ✅ Converted 1 querys +@betterbase/cli:test: +@betterbase/cli:test: ✅ Convex Migration Complete! +@betterbase/cli:test: +@betterbase/cli:test: Converted files are in: /tmp/iac-integration-test/migrated +@betterbase/cli:test: +@betterbase/cli:test: Key changes made: +@betterbase/cli:test: - Convex v.* validators -> BetterBase v.* +@betterbase/cli:test: - Convex query/mutation/action -> BetterBase query/mutation/action +@betterbase/cli:test: - ctx.db.query() syntax preserved +@betterbase/cli:test: - ctx.runQuery/ctx.runMutation -> ctx.runQuery/ctx.runMutation +@betterbase/cli:test: +@betterbase/cli:test: Manual steps required: +@betterbase/cli:test: 1. Review the generated schema and adjust types if needed +@betterbase/cli:test: 2. Install dependencies: bun add @betterbase/core @betterbase/client +@betterbase/cli:test: 3. Run bb iac sync to create database tables +@betterbase/cli:test: 4. Test your functions +@betterbase/cli:test: 5. Review compatibility report: /tmp/iac-integration-test/migrated/betterbase/convex-migration-report.json +@betterbase/cli:test: +@betterbase/cli:test: Compatibility summary: +@betterbase/cli:test: - Blockers: 0 +@betterbase/cli:test: - Warnings: 0 +@betterbase/cli:test: - Files requiring manual review: 0 +@betterbase/cli:test: +@betterbase/cli:test: See docs/iac/migration-from-convex.md for detailed guide. +@betterbase/cli:test: +@betterbase/cli:test: (pass) Integration Tests > should not modify original Convex source files [1.00ms] +@betterbase/cli:test: +@betterbase/cli:test: test/dev.test.ts: +@betterbase/cli:test: (pass) runDevCommand > is a callable async function [2.00ms] +@betterbase/cli:test: +@betterbase/cli:test: bb dev — watching for changes +@betterbase/cli:test: +@betterbase/cli:test: Project root /tmp/bb-test-8fc7a025 +@betterbase/cli:test: Server URL http://localhost:3000 +@betterbase/cli:test: Dashboard http://localhost:3000/admin +@betterbase/cli:test: +@betterbase/cli:test: Press Ctrl+C to stop +@betterbase/cli:test: +@betterbase/cli:test: ◆ [dev] Shutting down... +@betterbase/cli:test: (pass) runDevCommand > returns a cleanup function [9.00ms] +@betterbase/cli:test: +@betterbase/cli:test: bb dev — watching for changes +@betterbase/cli:test: +@betterbase/cli:test: Project root /tmp/bb-test-f5283ed4 +@betterbase/cli:test: Server URL http://localhost:3000 +@betterbase/cli:test: Dashboard http://localhost:3000/admin +@betterbase/cli:test: +@betterbase/cli:test: Press Ctrl+C to stop +@betterbase/cli:test: +@betterbase/cli:test: ◆ [dev] Shutting down... +@betterbase/cli:test: +@betterbase/cli:test: (pass) runDevCommand > cleanup function resolves without error [3.00ms] +@betterbase/cli:test: bb dev — watching for changes +@betterbase/cli:test: +@betterbase/cli:test: Project root /tmp/bb-test-3e50af45 +@betterbase/cli:test: Server URL http://localhost:3000 +@betterbase/cli:test: Dashboard http://localhost:3000/admin +@betterbase/cli:test: +@betterbase/cli:test: Press Ctrl+C to stop +@betterbase/cli:test: +@betterbase/cli:test: ◆ [dev] Shutting down... +@betterbase/cli:test: (pass) runDevCommand > starts ProcessManager when invoked [1.00ms] +@betterbase/cli:test: +@betterbase/cli:test: bb dev — watching for changes +@betterbase/cli:test: +@betterbase/cli:test: Project root /tmp/bb-test-17e3c3a5 +@betterbase/cli:test: Server URL http://localhost:3000 +@betterbase/cli:test: Dashboard http://localhost:3000/admin +@betterbase/cli:test: +@betterbase/cli:test: Press Ctrl+C to stop +@betterbase/cli:test: +@betterbase/cli:test: ◆ [dev] Shutting down... +@betterbase/cli:test: (pass) runDevCommand > starts DevWatcher when invoked [2.00ms] +@betterbase/cli:test: +@betterbase/cli:test: bb dev — watching for changes +@betterbase/cli:test: +@betterbase/cli:test: Project root /tmp/bb-test-e2d2f906 +@betterbase/cli:test: Server URL http://localhost:3000 +@betterbase/cli:test: Dashboard http://localhost:3000/admin +@betterbase/cli:test: +@betterbase/cli:test: Press Ctrl+C to stop +@betterbase/cli:test: +@betterbase/cli:test: ◆ [dev] Shutting down... +@betterbase/cli:test: +@betterbase/cli:test: bb dev — watching for changes +@betterbase/cli:test: +@betterbase/cli:test: Project root /tmp/bb-test-c4b13e4c +@betterbase/cli:test: Server URL http://localhost:3000 +@betterbase/cli:test: (pass) runDevCommand > skips IAC sync and generate when no betterbase/ directory [2.00ms] +@betterbase/cli:test: (pass) runDevCommand > calls IAC sync and generate when betterbase/ directory exists [2.00ms] +@betterbase/cli:test: Dashboard http://localhost:3000/admin +@betterbase/cli:test: +@betterbase/cli:test: Press Ctrl+C to stop +@betterbase/cli:test: +@betterbase/cli:test: ◆ IaC layer detected — betterbase/ will be watched for schema and function changes. +@betterbase/cli:test: ◆ [iac] Running initial sync... +@betterbase/cli:test: ◆ [dev] Shutting down... +@betterbase/cli:test: +@betterbase/cli:test: bb dev — watching for changes +@betterbase/cli:test: +@betterbase/cli:test: Project root /tmp/bb-test-945ad26e +@betterbase/cli:test: Server URL http://localhost:3000 +@betterbase/cli:test: Dashboard http://localhost:3000/admin +@betterbase/cli:test: +@betterbase/cli:test: Press Ctrl+C to stop +@betterbase/cli:test: +@betterbase/cli:test: ◆ IaC layer detected — betterbase/ will be watched for schema and function changes. +@betterbase/cli:test: ◆ [iac] Running initial sync... +@betterbase/cli:test: ⚠ [iac] Initial sync skipped: Schema parse error +@betterbase/cli:test: ◆ [dev] Shutting down... +@betterbase/cli:test: +@betterbase/cli:test: bb dev — watching for changes +@betterbase/cli:test: +@betterbase/cli:test: (pass) runDevCommand > does not crash when IAC sync throws an error [6.00ms] +@betterbase/cli:test: ⚠ [iac] Initial generate skipped: Generation failure +@betterbase/cli:test: Project root /tmp/bb-test-adfe1218 +@betterbase/cli:test: Server URL http://localhost:3000 +@betterbase/cli:test: Dashboard http://localhost:3000/admin +@betterbase/cli:test: +@betterbase/cli:test: Press Ctrl+C to stop +@betterbase/cli:test: +@betterbase/cli:test: ◆ IaC layer detected — betterbase/ will be watched for schema and function changes. +@betterbase/cli:test: ◆ [iac] Running initial sync... +@betterbase/cli:test: ◆ [dev] Shutting down... +@betterbase/cli:test: (pass) runDevCommand > does not crash when IAC generate throws an error [2.00ms] +@betterbase/cli:test: +@betterbase/cli:test: bb dev — watching for changes +@betterbase/cli:test: (pass) runDevCommand > enables query log when QUERY_LOG=true [3.00ms] +@betterbase/cli:test: +@betterbase/cli:test: Project root /tmp/bb-test-ce308734 +@betterbase/cli:test: Server URL http://localhost:3000 +@betterbase/cli:test: Dashboard http://localhost:3000/admin +@betterbase/cli:test: +@betterbase/cli:test: Press Ctrl+C to stop +@betterbase/cli:test: +@betterbase/cli:test: ◆ [dev] Shutting down... +@betterbase/cli:test: +@betterbase/cli:test: bb dev — watching for changes +@betterbase/cli:test: +@betterbase/cli:test: Project root /tmp/bb-test-d51dcfc9 +@betterbase/cli:test: Server URL http://localhost:3000 +@betterbase/cli:test: Dashboard http://localhost:3000/admin +@betterbase/cli:test: +@betterbase/cli:test: Press Ctrl+C to stop +@betterbase/cli:test: +@betterbase/cli:test: ◆ [dev] Shutting down... +@betterbase/cli:test: +@betterbase/cli:test: bb dev — watching for changes +@betterbase/cli:test: +@betterbase/cli:test: Project root /tmp/bb-test-51ee8544 +@betterbase/cli:test: (pass) runDevCommand > does not enable query log when QUERY_LOG is unset [1.00ms] +@betterbase/cli:test: Server URL http://localhost:3000 +@betterbase/cli:test: (pass) runDevCommand > cleanup stops ProcessManager and DevWatcher [2.00ms] +@betterbase/cli:test: Dashboard http://localhost:3000/admin +@betterbase/cli:test: (pass) runDevCommand > accepts projectRoot with a nonexistent path gracefully +@betterbase/cli:test: +@betterbase/cli:test: Press Ctrl+C to stop +@betterbase/cli:test: +@betterbase/cli:test: ◆ [dev] Shutting down... +@betterbase/cli:test: +@betterbase/cli:test: bb dev — watching for changes +@betterbase/cli:test: +@betterbase/cli:test: Project root /nonexistent/path/12345 +@betterbase/cli:test: Server URL http://localhost:3000 +@betterbase/cli:test: Dashboard http://localhost:3000/admin +@betterbase/cli:test: +@betterbase/cli:test: Press Ctrl+C to stop +@betterbase/cli:test: +@betterbase/cli:test: ◆ [dev] Shutting down... +@betterbase/cli:test: +@betterbase/cli:test: bb dev — watching for changes +@betterbase/cli:test: +@betterbase/cli:test: Project root /tmp/bb-test-e8efcbe1 +@betterbase/cli:test: Server URL http://localhost:3000 +@betterbase/cli:test: Dashboard http://localhost:3000/admin +@betterbase/cli:test: +@betterbase/cli:test: Press Ctrl+C to stop +@betterbase/cli:test: +@betterbase/cli:test: ◆ [dev] Shutting down... +@betterbase/cli:test: (pass) runDevCommand > generates context on startup [2.00ms] +@betterbase/cli:test: +@betterbase/cli:test: test/context-generator.test.ts: +@betterbase/cli:test: 34 | ); +@betterbase/cli:test: 35 | +@betterbase/cli:test: 36 | const generator = new ContextGenerator(); +@betterbase/cli:test: 37 | const context = await generator.generate(root); +@betterbase/cli:test: 38 | +@betterbase/cli:test: 39 | expect(context.tables.users).toBeDefined(); +@betterbase/cli:test: ^ +@betterbase/cli:test: TypeError: undefined is not an object (evaluating 'context.tables.users') +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/context-generator.test.ts:39:19) +@betterbase/cli:test: (fail) ContextGenerator > creates .betterbase-context.json from schema and routes [2.00ms] +@betterbase/cli:test: 65 | export const users = sqliteTable('users', { id: text('id').primaryKey() }); +@betterbase/cli:test: 66 | `, +@betterbase/cli:test: 67 | ); +@betterbase/cli:test: 68 | +@betterbase/cli:test: 69 | const context = await new ContextGenerator().generate(root); +@betterbase/cli:test: 70 | expect(context.routes).toEqual({}); +@betterbase/cli:test: ^ +@betterbase/cli:test: error: expect(received).toEqual(expected) +@betterbase/cli:test: +@betterbase/cli:test: Expected: {} +@betterbase/cli:test: Received: undefined +@betterbase/cli:test: +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/context-generator.test.ts:70:27) +@betterbase/cli:test: (fail) ContextGenerator > handles missing routes directory with empty routes [3.00ms] +@betterbase/cli:test: 83 | mkdirSync(path.join(root, "src/db"), { recursive: true }); +@betterbase/cli:test: 84 | mkdirSync(path.join(root, "src/routes"), { recursive: true }); +@betterbase/cli:test: 85 | writeFileSync(path.join(root, "src/db/schema.ts"), "export {};\n"); +@betterbase/cli:test: 86 | +@betterbase/cli:test: 87 | const context = await new ContextGenerator().generate(root); +@betterbase/cli:test: 88 | expect(context.tables).toEqual({}); +@betterbase/cli:test: ^ +@betterbase/cli:test: error: expect(received).toEqual(expected) +@betterbase/cli:test: +@betterbase/cli:test: Expected: {} +@betterbase/cli:test: Received: undefined +@betterbase/cli:test: +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/context-generator.test.ts:88:27) +@betterbase/cli:test: (fail) ContextGenerator > handles empty schema file with empty tables [8.00ms] +@betterbase/cli:test: 98 | try { +@betterbase/cli:test: 99 | mkdirSync(path.join(root, "src/routes"), { recursive: true }); +@betterbase/cli:test: 100 | writeFileSync(path.join(root, "src/routes/index.ts"), "export {};\n"); +@betterbase/cli:test: 101 | +@betterbase/cli:test: 102 | const context = await new ContextGenerator().generate(root); +@betterbase/cli:test: 103 | expect(context.tables).toEqual({}); +@betterbase/cli:test: ^ +@betterbase/cli:test: error: expect(received).toEqual(expected) +@betterbase/cli:test: +@betterbase/cli:test: Expected: {} +@betterbase/cli:test: Received: undefined +@betterbase/cli:test: +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/context-generator.test.ts:103:27) +@betterbase/cli:test: (fail) ContextGenerator > handles missing schema file with empty tables [3.00ms] +@betterbase/cli:test: +@betterbase/cli:test: test/output-snapshots.test.ts: +@betterbase/cli:test: (pass) output-snapshots: iac analyze > produces expected JSON output on empty project (snapshot) [7.00ms] +@betterbase/cli:test: +@betterbase/cli:test: test/provider-prompts.test.ts: +@betterbase/core:test: (pass) S3 Adapter > createS3Adapter - S3 Provider > should create S3 adapter with valid S3 config [44.00ms] +@betterbase/core:test: (pass) S3 Adapter > createS3Adapter - S3 Provider > should return StorageAdapter interface [2.00ms] +@betterbase/core:test: (pass) S3 Adapter > S3 Adapter - Get Public URL > should generate correct S3 public URL format [1.00ms] +@betterbase/core:test: (pass) S3 Adapter > S3 Adapter - Get Public URL > should handle different regions [1.00ms] +@betterbase/core:test: (pass) S3 Adapter > S3 Adapter - Get Public URL > should handle west regions [1.00ms] +@betterbase/core:test: (pass) S3 Adapter > S3 Adapter - Get Public URL > should handle nested paths +@betterbase/core:test: (pass) S3 Adapter > S3 Adapter - Get Public URL > should handle special characters in path [1.00ms] +@betterbase/core:test: (pass) S3 Adapter > R2 Provider > should create R2 adapter [1.00ms] +@betterbase/core:test: (pass) S3 Adapter > R2 Provider > should generate correct R2 public URL [1.00ms] +@betterbase/core:test: (pass) S3 Adapter > R2 Provider > should use custom endpoint if provided +@betterbase/core:test: (pass) S3 Adapter > Backblaze Provider > should create Backblaze adapter [1.00ms] +@betterbase/core:test: (pass) S3 Adapter > Backblaze Provider > should generate correct Backblaze public URL [2.00ms] +@betterbase/core:test: (pass) S3 Adapter > Backblaze Provider > should handle different Backblaze regions [1.00ms] +@betterbase/core:test: (pass) S3 Adapter > MinIO Provider > should create MinIO adapter with default settings [5.00ms] +@betterbase/core:test: (pass) S3 Adapter > MinIO Provider > should create MinIO adapter with custom port [3.00ms] +@betterbase/core:test: (pass) S3 Adapter > MinIO Provider > should generate correct MinIO public URL with SSL (default) +@betterbase/core:test: (pass) S3 Adapter > MinIO Provider > should generate correct MinIO public URL without SSL [5.00ms] +@betterbase/core:test: (pass) S3 Adapter > MinIO Provider > should use custom port without SSL [1.00ms] +@betterbase/core:test: (pass) S3 Adapter > MinIO Provider > should default to port 9000 without SSL +@betterbase/core:test: (pass) S3 Adapter > Adapter Interface Compliance > S3 adapter should have all required methods [1.00ms] +@betterbase/core:test: (pass) S3 Adapter > Adapter Interface Compliance > R2 adapter should have all required methods [8.00ms] +@betterbase/core:test: (pass) S3 Adapter > Config validation > should accept minimal S3 config +@betterbase/core:test: (pass) S3 Adapter > Config validation > should accept full R2 config with endpoint [1.00ms] +@betterbase/core:test: (pass) S3 Adapter > Config validation > should accept full Backblaze config with endpoint [4.00ms] +@betterbase/core:test: (pass) S3 Adapter > Config validation > should accept full MinIO config [3.00ms] +@betterbase/core:test: +@betterbase/core:test: test/webhook-functions.test.ts: +@betterbase/core:test: (pass) Webhook Functions > initializeWebhooks > should return null when no webhooks configured +@betterbase/core:test: (pass) Webhook Functions > initializeWebhooks > should return null when webhooks array is empty [1.00ms] +@betterbase/core:test: [webhooks] No webhooks configured +@betterbase/core:test: (pass) Webhook Functions > initializeWebhooks > should skip disabled webhooks +@betterbase/core:test: [webhooks] Skipping webhook test-webhook: URL and secret must be environment variable references +@betterbase/core:test: [webhooks] No webhooks configured +@betterbase/core:test: (pass) Webhook Functions > initializeWebhooks > should skip webhooks with invalid env var references +@betterbase/core:test: [webhooks] Skipping webhook test-webhook: MISSING_WEBHOOK_URL environment variable is not set +@betterbase/core:test: [webhooks] No webhooks initialized. Missing environment variables: MISSING_WEBHOOK_URL +@betterbase/core:test: (pass) Webhook Functions > initializeWebhooks > should skip webhooks with missing env vars +@betterbase/core:test: [webhooks] Active: 1 webhook(s) configured +@betterbase/core:test: [webhooks] Delivery logging: enabled (in-memory only) +@betterbase/core:test: (pass) Webhook Functions > initializeWebhooks > should initialize webhook with valid config and env vars [1.00ms] +@betterbase/core:test: [webhooks] Active: 2 webhook(s) configured +@betterbase/core:test: [webhooks] Delivery logging: enabled (in-memory only) +@betterbase/core:test: (pass) Webhook Functions > initializeWebhooks > should handle multiple webhooks +@betterbase/core:test: (pass) Webhook Functions > connectToRealtime > should connect dispatcher to realtime emitter +@betterbase/core:test: (pass) Webhook Functions > connectToRealtime > should handle db:change events [56.00ms] +@betterbase/core:test: (pass) Webhook Functions > connectToRealtime > should handle db:insert events [54.00ms] +@betterbase/core:test: (pass) Webhook Functions > connectToRealtime > should handle db:update events [52.00ms] +@betterbase/core:test: (pass) Webhook Functions > connectToRealtime > should handle db:delete events [54.00ms] +@betterbase/core:test: {"type":"webhook_realtime_integration_error","error":"Dispatch failed","timestamp":"2026-05-16T18:04:07.674Z"} +@betterbase/core:test: (pass) Webhook Functions > connectToRealtime > should handle dispatch errors gracefully [53.00ms] +@betterbase/core:test: +@betterbase/core:test: test/vector.test.ts: +@betterbase/core:test: (pass) vector/types > DEFAULT_EMBEDDING_CONFIGS has correct providers +@betterbase/core:test: (pass) vector/types > DEFAULT_EMBEDDING_CONFIGS.openai has correct defaults +@betterbase/core:test: (pass) vector/embeddings - validateEmbeddingDimensions > validates correct dimensions [1.00ms] +@betterbase/core:test: (pass) vector/embeddings - validateEmbeddingDimensions > throws on dimension mismatch [1.00ms] +@betterbase/core:test: (pass) vector/embeddings - normalizeVector > normalizes a vector to unit length +@betterbase/core:test: (pass) vector/embeddings - normalizeVector > handles zero vector +@betterbase/core:test: (pass) vector/embeddings - normalizeVector > preserves direction +@betterbase/core:test: (pass) vector/embeddings - computeCosineSimilarity > returns 1 for identical vectors [1.00ms] +@betterbase/core:test: (pass) vector/embeddings - computeCosineSimilarity > returns 0 for orthogonal vectors +@betterbase/core:test: (pass) vector/embeddings - computeCosineSimilarity > returns -1 for opposite vectors +@betterbase/core:test: (pass) vector/embeddings - computeCosineSimilarity > throws for different dimension vectors +@betterbase/core:test: (pass) vector/embeddings - createEmbeddingConfig > creates config with defaults [1.00ms] +@betterbase/core:test: (pass) vector/embeddings - createEmbeddingConfig > overrides defaults with provided values +@betterbase/core:test: (pass) vector/embeddings - createEmbeddingConfig > handles cohere provider +@betterbase/core:test: (pass) vector/search - VECTOR_OPERATORS > has correct cosine operator +@betterbase/core:test: (pass) vector/search - VECTOR_OPERATORS > has correct euclidean operator +@betterbase/core:test: (pass) vector/search - VECTOR_OPERATORS > has correct inner product operator +@betterbase/core:test: (pass) vector/search - validateEmbedding > validates valid embedding [1.00ms] +@betterbase/core:test: (pass) vector/search - validateEmbedding > throws for non-array +@betterbase/core:test: (pass) vector/search - validateEmbedding > throws for empty array +@betterbase/core:test: (pass) vector/search - validateEmbedding > throws for non-numeric values +@betterbase/core:test: (pass) vector/search - validateEmbedding > throws for NaN values +@betterbase/core:test: (pass) vector/search - validateEmbedding > throws for Infinity +@betterbase/core:test: (pass) vector/search - embeddingToSql > converts array to SQL vector literal +@betterbase/core:test: (pass) vector/search - embeddingToSql > handles empty-ish numbers +@betterbase/core:test: (pass) vector/search - buildVectorSearchQuery > builds basic query +@betterbase/core:test: (pass) vector/search - buildVectorSearchQuery > applies limit [1.00ms] +@betterbase/core:test: (pass) vector/search - buildVectorSearchQuery > applies filter +@betterbase/core:test: (pass) vector/search - buildVectorSearchQuery > uses correct operator for cosine +@betterbase/core:test: (pass) vector/search - buildVectorSearchQuery > uses correct operator for euclidean +@betterbase/core:test: (pass) vector/search - buildVectorSearchQuery > uses correct operator for inner_product +@betterbase/core:test: (pass) vector/search - createVectorIndex > creates HNSW index +@betterbase/core:test: (pass) vector/search - createVectorIndex > creates IVFFlat index +@betterbase/core:test: (pass) vector/search - createVectorIndex > uses correct ops for euclidean +@betterbase/core:test: (pass) vector/search - createVectorIndex > uses correct ops for inner_product +@betterbase/core:test: (pass) vector/search - createVectorIndex > respects custom connection count +@betterbase/core:test: (pass) vector - config integration > BetterBaseConfigSchema accepts vector config [54.00ms] +@betterbase/core:test: (pass) vector - config integration > BetterBaseConfigSchema accepts vector config with apiKey [3.00ms] +@betterbase/core:test: +@betterbase/core:test: test/vector-search.test.ts: +@betterbase/core:test: (pass) Vector Search > pgvector operator mappings > should have cosine distance operator +@betterbase/core:test: (pass) Vector Search > pgvector operator mappings > should have euclidean distance operator +@betterbase/core:test: (pass) Vector Search > pgvector operator mappings > should have inner product operator +@betterbase/core:test: (pass) Vector Search > pgvector operator mappings > should have correct operator mappings for all metrics +@betterbase/core:test: (pass) Vector Search > validateEmbedding > should accept valid embedding +@betterbase/core:test: (pass) Vector Search > validateEmbedding > should reject non-array embedding +@betterbase/core:test: (pass) Vector Search > validateEmbedding > should reject empty embedding +@betterbase/core:test: (pass) Vector Search > validateEmbedding > should reject embedding with NaN values +@betterbase/core:test: (pass) Vector Search > validateEmbedding > should reject embedding with non-number values +@betterbase/core:test: (pass) Vector Search > validateEmbedding > should handle high-dimensional embeddings [4.00ms] +@betterbase/core:test: (pass) Vector Search > vectorSearch > should return search results with default limit +@betterbase/core:test: (pass) Vector Search > vectorSearch > should respect custom limit +@betterbase/core:test: (pass) Vector Search > vectorSearch > should include score when requested +@betterbase/core:test: (pass) Vector Search > vectorSearch > should support different distance metrics [2.00ms] +@betterbase/core:test: (pass) Vector Search > vectorSearch > should handle threshold option +@betterbase/core:test: (pass) Vector Search > embedding generation > should generate embedding with default settings [4.00ms] +@betterbase/core:test: (pass) Vector Search > embedding generation > should generate embedding with custom dimensions [1.00ms] +@betterbase/core:test: (pass) Vector Search > embedding generation > should generate embedding with different providers [1.00ms] +@betterbase/core:test: (pass) Vector Search > embedding generation > should use custom model when specified +@betterbase/core:test: (pass) Vector Search > semantic search use cases > should perform semantic search on documents +@betterbase/core:test: (pass) Vector Search > semantic search use cases > should limit search results [3.00ms] +@betterbase/core:test: (pass) Vector Search > semantic search use cases > should handle empty document list [1.00ms] +@betterbase/core:test: +@betterbase/core:test: test/branching.test.ts: +@betterbase/core:test: (pass) branching/types - BranchStatus > BranchStatus enum values exist +@betterbase/core:test: (pass) branching/types - BranchStatus > BranchStatus enum can be used in comparisons [1.00ms] +@betterbase/core:test: (pass) branching/types - BranchConfig > BranchConfig has all required properties +@betterbase/core:test: (pass) branching/types - CreateBranchOptions > CreateBranchOptions has correct defaults +@betterbase/core:test: (pass) branching/types - CreateBranchOptions > CreateBranchOptions accepts all options +@betterbase/core:test: (pass) branching/types - PreviewEnvironment > PreviewEnvironment has correct structure +@betterbase/core:test: (pass) branching/types - BranchingConfig > BranchingConfig has correct defaults +@betterbase/core:test: (pass) branching/types - BranchOperationResult > BranchOperationResult success structure +@betterbase/core:test: (pass) branching/types - BranchOperationResult > BranchOperationResult failure structure +@betterbase/core:test: (pass) branching/types - BranchListResult > BranchListResult has correct structure +@betterbase/core:test: (pass) branching/database - DatabaseBranching > constructor > creates DatabaseBranching instance +@betterbase/core:test: (pass) branching/database - DatabaseBranching > isBranchingSupported > returns true for postgres provider +@betterbase/core:test: (pass) branching/database - DatabaseBranching > isBranchingSupported > returns true for neon provider +@betterbase/core:test: (pass) branching/database - DatabaseBranching > isBranchingSupported > returns true for supabase provider +@betterbase/core:test: (pass) branching/database - DatabaseBranching > isBranchingSupported > returns true for managed provider +@betterbase/core:test: (pass) branching/database - DatabaseBranching > isBranchingSupported > returns false for turso provider +@betterbase/core:test: (pass) branching/database - DatabaseBranching > isBranchingSupported > returns false for planetscale provider +@betterbase/core:test: (pass) branching/database - DatabaseBranching > cloneDatabase > throws error for unsupported provider [1.00ms] +@betterbase/core:test: (pass) branching/database - DatabaseBranching > connectPreviewDatabase > returns a postgres client [4.00ms] +@betterbase/core:test: (pass) branching/database - DatabaseBranching > getMainDatabase > returns a postgres client for main database +@betterbase/core:test: (pass) branching/database - DatabaseBranching > listPreviewDatabases > returns array of preview database names [1.00ms] +@betterbase/core:test: (pass) branching/database - DatabaseBranching > previewDatabaseExists > returns promise for checking database existence +@betterbase/core:test: (pass) branching/database - DatabaseBranching > teardownPreviewDatabase > returns promise for teardown operation +@betterbase/core:test: (pass) branching/database - buildBranchConfig > builds BranchConfig with correct properties +@betterbase/core:test: (pass) branching/storage - StorageBranching > constructor > creates StorageBranching instance +@betterbase/core:test: (pass) branching/storage - StorageBranching > createPreviewBucket > creates preview bucket with correct naming +@betterbase/core:test: (pass) branching/storage - StorageBranching > createPreviewBucket > returns PreviewStorage with publicUrl +@betterbase/core:test: (pass) branching/storage - StorageBranching > copyFilesToPreview > returns 0 when main bucket is empty [1.00ms] +@betterbase/core:test: (pass) branching/storage - StorageBranching > copyFilesToPreview > copies files from main bucket to preview bucket +@betterbase/core:test: (pass) branching/storage - StorageBranching > copyFilesToPreview > copies files with prefix filter [1.00ms] +@betterbase/core:test: (pass) branching/storage - StorageBranching > teardownPreviewStorage > handles empty bucket gracefully [2.00ms] +@betterbase/core:test: (pass) branching/storage - StorageBranching > teardownPreviewStorage > deletes files from preview bucket +@betterbase/core:test: (pass) branching/storage - StorageBranching > getPublicUrl > returns public URL for bucket and key +@betterbase/core:test: (pass) branching/storage - StorageBranching > getMainStorageAdapter > returns the main storage adapter +@betterbase/core:test: (pass) branching/storage - StorageBranching > getPreviewStorageAdapter > returns storage adapter for preview bucket +@betterbase/core:test: (pass) branching/storage - StorageBranching > listPreviewBuckets > returns empty array by default [1.00ms] +@betterbase/core:test: (pass) branching/storage - StorageBranching > previewBucketExists > returns true if bucket is accessible [2.00ms] +@betterbase/core:test: (pass) branching - BranchManager > constructor > creates BranchManager instance +@betterbase/core:test: (pass) branching - BranchManager > constructor > initializes with default config [1.00ms] +@betterbase/core:test: (pass) branching - BranchManager > setConfig and getConfig > updates configuration +@betterbase/core:test: (pass) branching - BranchManager > setConfig and getConfig > merges partial config +@betterbase/core:test: (pass) branching - BranchManager > setMainBranch and getMainBranch > sets and gets main branch name +@betterbase/core:test: (pass) branching - BranchManager > setMainBranch and getMainBranch > defaults to main +@betterbase/core:test: (pass) branching - BranchManager > createBranch > creates a new branch successfully [2.00ms] +@betterbase/core:test: (pass) branching - BranchManager > createBranch > creates branch with custom source branch +@betterbase/core:test: (pass) branching - BranchManager > createBranch > creates branch with custom sleep timeout +@betterbase/core:test: (pass) branching - BranchManager > createBranch > creates branch with custom metadata +@betterbase/core:test: (pass) branching - BranchManager > createBranch > fails when branching is disabled [2.00ms] +@betterbase/core:test: (pass) branching - BranchManager > createBranch > fails when max previews reached +@betterbase/core:test: (pass) branching - BranchManager > createBranch > generates preview URL +@betterbase/core:test: (pass) branching - BranchManager > getBranch > retrieves branch by ID +@betterbase/core:test: (pass) branching - BranchManager > getBranch > returns undefined for non-existent branch +@betterbase/core:test: (pass) branching - BranchManager > getBranch > updates lastAccessedAt when retrieving [12.00ms] +@betterbase/core:test: (pass) branching - BranchManager > getBranchByName > retrieves branch by name [8.00ms] +@betterbase/core:test: (pass) branching - BranchManager > getBranchByName > returns undefined for non-existent name [1.00ms] +@betterbase/core:test: (pass) branching - BranchManager > listBranches > lists all branches +@betterbase/core:test: (pass) branching - BranchManager > listBranches > filters by status [2.00ms] +@betterbase/core:test: (pass) branching - BranchManager > listBranches > applies pagination +@betterbase/core:test: (skip) branching - BranchManager > listBranches > sorts by creation date (newest first) +@betterbase/core:test: (pass) branching - BranchManager > deleteBranch > deletes a branch successfully [2.00ms] +@betterbase/core:test: (pass) branching - BranchManager > deleteBranch > returns error for non-existent branch +@betterbase/core:test: (pass) branching - BranchManager > sleepBranch > puts a branch to sleep +@betterbase/core:test: (pass) branching - BranchManager > sleepBranch > fails if branch is already sleeping [1.00ms] +@betterbase/core:test: (pass) branching - BranchManager > sleepBranch > fails if branch is deleted +@betterbase/core:test: (pass) branching - BranchManager > wakeBranch > wakes a sleeping branch [1.00ms] +@betterbase/core:test: (pass) branching - BranchManager > wakeBranch > fails if branch is already active [1.00ms] +@betterbase/core:test: (pass) branching - BranchManager > wakeBranch > fails if branch is deleted +@betterbase/core:test: (pass) branching - BranchManager > getPreviewEnvironment > returns full preview environment details +@betterbase/core:test: (pass) branching - BranchManager > getPreviewEnvironment > returns null for non-existent branch [1.00ms] +@betterbase/core:test: (pass) branching - Edge Cases > empty branch name > creates branch with empty name [1.00ms] +@betterbase/core:test: (pass) branching - Edge Cases > special characters in branch name > handles special characters in branch name +@betterbase/core:test: (pass) branching - Edge Cases > concurrent branch creation > handles multiple concurrent branch creations +@betterbase/core:test: (pass) branching - Edge Cases > config without storage > creates manager without storage config +@betterbase/core:test: (pass) branching - Edge Cases > config without database connection > creates manager without database connection [2.00ms] +@betterbase/core:test: (pass) branching - Integration > full branch lifecycle +@betterbase/core:test: (pass) branching - Integration > branch pagination edge cases [1.00ms] +@betterbase/core:test: (pass) branching - Integration > multiple branches with different statuses [1.00ms] +@betterbase/core:test: (pass) branching - Utility Functions > getAllBranches returns empty map initially +@betterbase/core:test: (pass) branching - Utility Functions > getAllBranches returns created branches [1.00ms] +@betterbase/core:test: (pass) branching - Utility Functions > clearAllBranches removes all branches +@betterbase/core:test: +@betterbase/core:test: test/iac-edge-cases.test.ts: +@betterbase/core:test: (pass) Edge Cases: Validators > v.id() with empty string table name +@betterbase/core:test: (pass) Edge Cases: Validators > v.id() with special characters in table name +@betterbase/core:test: (pass) Edge Cases: Validators > v.optional() with nested optional +@betterbase/core:test: (pass) Edge Cases: Validators > v.array() with complex element type [6.00ms] +@betterbase/core:test: (pass) Edge Cases: Validators > v.union() with many variants [3.00ms] +@betterbase/core:test: (pass) Edge Cases: Validators > v.object() with optional nested fields +@betterbase/core:test: (pass) Edge Cases: Validators > v.object() with deeply nested objects +@betterbase/core:test: (pass) Edge Cases: Validators > v.datetime() with various ISO formats [1.00ms] +@betterbase/core:test: (pass) Edge Cases: Validators > v.bytes() with valid base64 +@betterbase/core:test: (pass) Edge Cases: Validators > v.literal() with various primitive types [1.00ms] +@betterbase/core:test: (pass) Edge Cases: Schema Definition > defineTable with no user fields (system fields only) +@betterbase/core:test: (pass) Edge Cases: Schema Definition > defineTable with all field types +@betterbase/core:test: (pass) Edge Cases: Schema Definition > defineSchema with empty tables +@betterbase/core:test: (pass) Edge Cases: Schema Definition > defineSchema with many tables [1.00ms] +@betterbase/core:test: (pass) Edge Cases: Schema Definition > table with multiple indexes on same fields +@betterbase/core:test: (pass) Edge Cases: Schema Definition > table with index on system field +@betterbase/core:test: (pass) Edge Cases: Schema Serialization > serializeSchema with empty schema +@betterbase/core:test: (pass) Edge Cases: Schema Serialization > serializeSchema with deeply nested object +@betterbase/core:test: (pass) Edge Cases: Schema Serialization > serializeSchema with array of objects [1.00ms] +@betterbase/core:test: (pass) Edge Cases: Schema Serialization > serializeSchema with union type [1.00ms] +@betterbase/core:test: (pass) Edge Cases: Schema Serialization > serializeSchema preserves index metadata [1.00ms] +@betterbase/core:test: (pass) Edge Cases: Schema Diff > diffSchemas with multiple table changes [5.00ms] +@betterbase/core:test: (pass) Edge Cases: Schema Diff > diffSchemas with optional to required change [4.00ms] +@betterbase/core:test: (pass) Edge Cases: Schema Diff > diffSchemas with required to optional change [1.00ms] +@betterbase/core:test: (pass) Edge Cases: Schema Diff > diffSchemas with index changes only +@betterbase/core:test: (pass) Edge Cases: Schema Diff > diffSchemas with no changes returns empty [1.00ms] +@betterbase/core:test: (pass) Edge Cases: Schema Diff > formatDiff with empty diff +@betterbase/core:test: (pass) Edge Cases: Function Registration > query with empty args +@betterbase/core:test: (pass) Edge Cases: Function Registration > query with complex nested args [1.00ms] +@betterbase/core:test: (pass) Edge Cases: Function Registration > mutation returns null +@betterbase/core:test: (pass) Edge Cases: Function Registration > action with side effects only [1.00ms] +@betterbase/core:test: (pass) Edge Cases: Code Generation > generateDrizzleSchema with no tables +@betterbase/core:test: (pass) Edge Cases: Code Generation > generateDrizzleSchema with all SQL types [1.00ms] +@betterbase/core:test: (pass) Edge Cases: Code Generation > generateDrizzleSchema preserves indexes in output +@betterbase/core:test: (pass) Edge Cases: Code Generation > generateMigration with DROP_INDEX [1.00ms] +@betterbase/core:test: (pass) Edge Cases: Code Generation > generateMigration with DROP_TABLE +@betterbase/core:test: (pass) Edge Cases: Code Generation > generateMigration filename handles special characters [1.00ms] +@betterbase/core:test: (pass) Edge Cases: Code Generation > generateMigration pads sequence correctly [1.00ms] +@betterbase/core:test: (pass) Edge Cases: Code Generation > generateApiTypes with empty functions +@betterbase/core:test: (pass) Edge Cases: Code Generation > generateApiTypes with deeply nested path +@betterbase/core:test: (pass) Edge Cases: Round-trip Serialization > serialize -> deserialize -> diff produces no changes [1.00ms] +@betterbase/core:test: (pass) Edge Cases: Round-trip Serialization > generated code is parseable for empty schema +@betterbase/core:test: (pass) Edge Cases: Null Handling > v.null() accepts null only +@betterbase/core:test: (pass) Edge Cases: Null Handling > optional field can be null +@betterbase/core:test: (pass) Edge Cases: Type Inference > Infer works with v.string() +@betterbase/core:test: (pass) Edge Cases: Type Inference > Infer works with v.number() +@betterbase/core:test: (pass) Edge Cases: Type Inference > Infer works with v.object() +@betterbase/core:test: (pass) Edge Cases: Type Inference > Infer works with v.array() +@betterbase/core:test: +@betterbase/core:test: test/rls-generator.test.ts: +@betterbase/core:test: (pass) RLS Generator > policyToSQL > should generate SQL for SELECT policy +@betterbase/core:test: (pass) RLS Generator > policyToSQL > should generate SQL for INSERT policy +@betterbase/core:test: (pass) RLS Generator > policyToSQL > should generate SQL for UPDATE policy +@betterbase/core:test: (pass) RLS Generator > policyToSQL > should generate SQL for DELETE policy +@betterbase/core:test: (pass) RLS Generator > policyToSQL > should generate SQL for multiple operations [1.00ms] +@betterbase/core:test: (pass) RLS Generator > policyToSQL > should use USING clause for SELECT +@betterbase/core:test: (pass) RLS Generator > policyToSQL > should use WITH CHECK clause for INSERT +@betterbase/core:test: (pass) RLS Generator > policyToSQL > should prioritize using clause over operation-specific for SELECT/DELETE/UPDATE +@betterbase/core:test: (pass) RLS Generator > policyToSQL > should prioritize withCheck clause over operation-specific for INSERT/UPDATE [1.00ms] +@betterbase/core:test: (pass) RLS Generator > policyToSQL > should handle true policy (allow all) +@betterbase/core:test: (pass) RLS Generator > policyToSQL > should handle false policy (deny all) +@betterbase/core:test: (pass) RLS Generator > policyToSQL > should include operations when using or withCheck is defined +@betterbase/core:test: (pass) RLS Generator > policyToSQL > should enable RLS first +@betterbase/core:test: (pass) RLS Generator > dropPolicySQL > should generate DROP statements for all operations +@betterbase/core:test: (pass) RLS Generator > dropPolicySQL > should disable RLS last +@betterbase/core:test: (pass) RLS Generator > dropPolicyByName > should generate DROP statement for specific operation +@betterbase/core:test: (pass) RLS Generator > dropPolicyByName > should work for all operation types +@betterbase/core:test: (pass) RLS Generator > disableRLS > should generate ALTER TABLE DISABLE RLS statement +@betterbase/core:test: (pass) RLS Generator > hasPolicyConditions > should return true when select is defined +@betterbase/core:test: (pass) RLS Generator > hasPolicyConditions > should return true when insert is defined +@betterbase/core:test: (pass) RLS Generator > hasPolicyConditions > should return true when update is defined +@betterbase/core:test: (pass) RLS Generator > hasPolicyConditions > should return true when delete is defined +@betterbase/core:test: (pass) RLS Generator > hasPolicyConditions > should return true when using is defined +@betterbase/core:test: (pass) RLS Generator > hasPolicyConditions > should return true when withCheck is defined +@betterbase/core:test: (pass) RLS Generator > hasPolicyConditions > should return false when no conditions defined +@betterbase/core:test: (pass) RLS Generator > policiesToSQL > should generate SQL for multiple policies +@betterbase/core:test: (pass) RLS Generator > policiesToSQL > should handle empty array +@betterbase/core:test: (pass) RLS Generator > dropPoliciesSQL > should generate DROP SQL for multiple policies +@betterbase/core:test: (pass) RLS Generator > dropPoliciesSQL > should handle empty array +@betterbase/core:test: +@betterbase/core:test: test/rls.test.ts: +@betterbase/core:test: (pass) rls/types > definePolicy > creates a policy definition with select [1.00ms] +@betterbase/core:test: (pass) rls/types > definePolicy > creates a policy definition with multiple operations +@betterbase/core:test: (pass) rls/types > definePolicy > creates a policy with using clause +@betterbase/core:test: (pass) rls/types > definePolicy > creates a policy with withCheck clause [1.00ms] +@betterbase/core:test: (pass) rls/types > isPolicyDefinition > returns true for valid policy +@betterbase/core:test: (pass) rls/types > isPolicyDefinition > returns false for null +@betterbase/core:test: (pass) rls/types > isPolicyDefinition > returns false for undefined +@betterbase/core:test: (pass) rls/types > isPolicyDefinition > returns false for empty object [1.00ms] +@betterbase/core:test: (pass) rls/types > isPolicyDefinition > returns false for object without table +@betterbase/core:test: (pass) rls/types > isPolicyDefinition > returns false for object with empty table +@betterbase/core:test: (pass) rls/types > mergePolicies > merges policies for the same table +@betterbase/core:test: (pass) rls/types > mergePolicies > keeps separate policies for different tables [1.00ms] +@betterbase/core:test: (pass) rls/types > mergePolicies > prefers new values when merging +@betterbase/core:test: (pass) rls/generator > policyToSQL > generates SQL for select policy +@betterbase/cli:test: (pass) Provider prompts > promptForProvider > is a function that can be imported +@betterbase/cli:test: (pass) Provider prompts > generateEnvContent > generates env content for neon provider [1.00ms] +@betterbase/cli:test: (pass) Provider prompts > generateEnvContent > generates env content for turso provider +@betterbase/cli:test: (pass) Provider prompts > generateEnvContent > generates env content for planetscale provider +@betterbase/cli:test: (pass) Provider prompts > generateEnvContent > generates env content for supabase provider +@betterbase/cli:test: (pass) Provider prompts > generateEnvContent > generates env content for postgres provider +@betterbase/cli:test: (pass) Provider prompts > generateEnvContent > handles empty env vars +@betterbase/cli:test: (pass) Provider prompts > generateEnvExampleContent > generates env example for neon provider +@betterbase/cli:test: (pass) Provider prompts > generateEnvExampleContent > generates env example for turso provider +@betterbase/cli:test: (pass) Provider prompts > generateEnvExampleContent > generates env example for all provider types +@betterbase/cli:test: (pass) Provider prompts > promptForStorage > is a function that can be imported +@betterbase/cli:test: (pass) Provider prompts > ProviderPromptResult interface > defines providerType and envVars properties +@betterbase/cli:test: +@betterbase/cli:test: test/error-messages.test.ts: +@betterbase/core:test: (pass) rls/generator > policyToSQL > generates SQL for multiple operations +@betterbase/core:test: (pass) rls/generator > policyToSQL > generates USING clause for select/update/delete [1.00ms] +@betterbase/core:test: (pass) rls/generator > policyToSQL > generates WITH CHECK clause for insert/update +@betterbase/core:test: (pass) rls/generator > policyToSQL > handles insert with operation-specific condition +@betterbase/core:test: (pass) rls/generator > dropPolicySQL > generates DROP statements for all operations [1.00ms] +@betterbase/core:test: (pass) rls/generator > dropPolicyByName > generates DROP POLICY statement +@betterbase/core:test: (pass) rls/generator > disableRLS > generates ALTER TABLE statement +@betterbase/core:test: (pass) rls/generator > hasPolicyConditions > returns true when select is defined +@betterbase/core:test: (pass) rls/generator > hasPolicyConditions > returns true when using is defined [1.00ms] +@betterbase/core:test: (pass) rls/generator > hasPolicyConditions > returns true when withCheck is defined +@betterbase/core:test: (pass) rls/generator > hasPolicyConditions > returns false when no conditions are defined +@betterbase/core:test: (pass) rls/generator > policiesToSQL > generates SQL for multiple policies +@betterbase/core:test: (pass) rls/generator > dropPoliciesSQL > generates DROP SQL for multiple policies +@betterbase/core:test: (pass) rls/auth-bridge > generateAuthFunction > generates auth.uid() function SQL +@betterbase/core:test: (pass) rls/auth-bridge > generateAuthFunctionWithSetting > generates auth.uid() with custom setting [2.00ms] +@betterbase/core:test: (pass) rls/auth-bridge > generateAuthFunctionWithSetting > throws for invalid setting name +@betterbase/core:test: (pass) rls/auth-bridge > generateAuthFunctionWithSetting > allows valid setting names +@betterbase/core:test: (pass) rls/auth-bridge > dropAuthFunction > generates DROP FUNCTION statement +@betterbase/core:test: (pass) rls/auth-bridge > setCurrentUserId > generates SET statement with user ID [1.00ms] +@betterbase/core:test: (pass) rls/auth-bridge > setCurrentUserId > escapes single quotes in user ID +@betterbase/core:test: (pass) rls/auth-bridge > clearCurrentUserId > generates CLEAR statement +@betterbase/core:test: (pass) rls/auth-bridge > generateIsAuthenticatedCheck > generates auth.authenticated() function [1.00ms] +@betterbase/core:test: (pass) rls/auth-bridge > dropIsAuthenticatedCheck > generates DROP FUNCTION statement +@betterbase/core:test: (pass) rls/auth-bridge > generateAllAuthFunctions > returns array of all auth functions +@betterbase/core:test: (pass) rls/auth-bridge > dropAllAuthFunctions > returns array of all DROP statements +@betterbase/core:test: (pass) rls/scanner > scanPolicies > returns empty result for empty directory [4.00ms] +@betterbase/core:test: (pass) rls/scanner > scanPolicies > scans and loads policies from policy files [1.00ms] +@betterbase/cli:test: (pass) Error message quality > Migrate error messages > migrate error includes backup path and restore command [1.00ms] +@betterbase/cli:test: (pass) Error message quality > Migrate error messages > includes helpful restore instructions in error messages +@betterbase/core:test: (pass) rls/scanner > listPolicyFiles > returns empty array for directory without policy files [2.00ms] +@betterbase/core:test: (pass) rls/scanner > listPolicyFiles > finds policy files in policies directory [1.00ms] +@betterbase/core:test: (pass) rls/scanner > getPolicyFileInfo > returns empty array for non-existent file [1.00ms] +@betterbase/core:test: +@betterbase/core:test: test/rls-evaluator.test.ts: +@betterbase/core:test: (pass) RLS Evaluator > evaluatePolicy > true policy > should allow all when policy is 'true' +@betterbase/core:test: (pass) RLS Evaluator > evaluatePolicy > true policy > should allow all when policy is 'true' with null userId +@betterbase/core:test: (pass) RLS Evaluator > evaluatePolicy > false policy > should deny all when policy is 'false' +@betterbase/core:test: (pass) RLS Evaluator > evaluatePolicy > false policy > should deny all when policy is 'false' with null userId [1.00ms] +@betterbase/core:test: (pass) RLS Evaluator > evaluatePolicy > auth.uid() = column > should allow when userId matches column value +@betterbase/core:test: (pass) RLS Evaluator > evaluatePolicy > auth.uid() = column > should deny when userId does not match column value +@betterbase/core:test: (pass) RLS Evaluator > evaluatePolicy > auth.uid() = column > should deny when userId is null +@betterbase/core:test: (pass) RLS Evaluator > evaluatePolicy > auth.uid() = column > should handle string comparison +@betterbase/core:test: (pass) RLS Evaluator > evaluatePolicy > auth.uid() = column > should handle column value as number +@betterbase/core:test: (pass) RLS Evaluator > evaluatePolicy > auth.uid() = column > should handle missing column in record +@betterbase/core:test: (pass) RLS Evaluator > evaluatePolicy > auth.role() = 'value' > should deny role check (not implemented) +@betterbase/core:test: [RLS] Unknown policy expression: unknown_expression +@betterbase/core:test: (pass) RLS Evaluator > evaluatePolicy > unknown policy format > should deny unknown policy format +@betterbase/core:test: [RLS] Unknown policy expression: +@betterbase/core:test: (pass) RLS Evaluator > evaluatePolicy > unknown policy format > should deny empty string policy +@betterbase/core:test: (pass) RLS Evaluator > evaluatePolicy > different operations > should evaluate for insert operation +@betterbase/core:test: (pass) RLS Evaluator > evaluatePolicy > different operations > should evaluate for update operation +@betterbase/core:test: (pass) RLS Evaluator > evaluatePolicy > different operations > should evaluate for delete operation [1.00ms] +@betterbase/core:test: (pass) RLS Evaluator > applyRLSSelect > should return all rows when no policies defined +@betterbase/core:test: (pass) RLS Evaluator > applyRLSSelect > should filter rows based on SELECT policy +@betterbase/core:test: (pass) RLS Evaluator > applyRLSSelect > should deny anonymous when no SELECT policy defined +@betterbase/core:test: (pass) RLS Evaluator > applyRLSSelect > should allow authenticated when no SELECT policy defined +@betterbase/core:test: (pass) RLS Evaluator > applyRLSSelect > should apply USING clause for SELECT +@betterbase/core:test: (pass) RLS Evaluator > applyRLSSelect > should allow all when SELECT policy is 'true' +@betterbase/core:test: (pass) RLS Evaluator > applyRLSSelect > should filter correctly for multiple policies on different tables [1.00ms] +@betterbase/core:test: (pass) RLS Evaluator > applyRLSInsert > should throw when no policy and no user +@betterbase/core:test: (pass) RLS Evaluator > applyRLSInsert > should allow when authenticated and no policy +@betterbase/core:test: (pass) RLS Evaluator > applyRLSInsert > should throw when policy denies +@betterbase/core:test: (pass) RLS Evaluator > applyRLSInsert > should allow when policy allows +@betterbase/core:test: (pass) RLS Evaluator > applyRLSInsert > should evaluate auth.uid() check +@betterbase/core:test: (pass) RLS Evaluator > applyRLSUpdate > should throw when no policy and no user +@betterbase/core:test: (pass) RLS Evaluator > applyRLSUpdate > should allow when authenticated and no policy +@betterbase/core:test: (pass) RLS Evaluator > applyRLSUpdate > should throw when policy denies +@betterbase/core:test: (pass) RLS Evaluator > applyRLSUpdate > should allow when policy allows +@betterbase/core:test: (pass) RLS Evaluator > applyRLSUpdate > should evaluate using clause for update +@betterbase/core:test: (pass) RLS Evaluator > applyRLSDelete > should throw when no policy and no user [1.00ms] +@betterbase/core:test: (pass) RLS Evaluator > applyRLSDelete > should allow when authenticated and no policy +@betterbase/core:test: (pass) RLS Evaluator > applyRLSDelete > should throw when policy denies +@betterbase/core:test: (pass) RLS Evaluator > applyRLSDelete > should allow when policy allows +@betterbase/core:test: (pass) RLS Evaluator > applyRLSDelete > should evaluate auth.uid() check for delete +@betterbase/core:test: (pass) RLS Evaluator > createRLSMiddleware > middleware.select > should filter rows based on policy +@betterbase/core:test: (pass) RLS Evaluator > createRLSMiddleware > middleware.insert > should allow insert when policy passes [1.00ms] +@betterbase/core:test: (pass) RLS Evaluator > createRLSMiddleware > middleware.insert > should allow insert when policy is true +@betterbase/core:test: (pass) RLS Evaluator > createRLSMiddleware > middleware.update > should allow update when user owns record +@betterbase/core:test: (pass) RLS Evaluator > createRLSMiddleware > middleware.update > should throw when user does not own record +@betterbase/core:test: (pass) RLS Evaluator > createRLSMiddleware > middleware.delete > should allow delete when user owns record +@betterbase/core:test: (pass) RLS Evaluator > createRLSMiddleware > middleware.delete > should throw when user does not own record [1.00ms] +@betterbase/core:test: (pass) RLS Evaluator > createRLSMiddleware > middleware with null user > should deny select when user is null +@betterbase/core:test: (pass) RLS Evaluator > createRLSMiddleware > middleware with null user > should throw on insert when user is null +@betterbase/core:test: (pass) RLS Evaluator > createRLSMiddleware > middleware with null user > should throw on update when user is null +@betterbase/core:test: (pass) RLS Evaluator > createRLSMiddleware > middleware with null user > should throw on delete when user is null [1.00ms] +@betterbase/core:test: +@betterbase/core:test: test/graphql-resolvers.test.ts: +betterbase-base-template:test: <-- GET /health +@betterbase/cli:test: (pass) Error message quality > Generate CRUD error messages > generate crud error lists available tables when table not found [35.00ms] +@betterbase/cli:test: (pass) Error message quality > Generate CRUD error messages > provides clear error when schema file is missing +@betterbase/cli:test: (pass) Error message quality > Error message formatting > includes error details in migrate failure [1.00ms] +@betterbase/cli:test: (pass) Error message quality > Error message formatting > includes connection error details +@betterbase/cli:test: +@betterbase/cli:test: test/logger.test.ts: +betterbase-base-template:test: --> GET /health 200 13ms +betterbase-base-template:test: (pass) health endpoint > GET /health returns 200 with healthy status [79.00ms] +betterbase-base-template:test: +betterbase-base-template:test: test/crud.test.ts: +betterbase-base-template:test: <-- GET /api/users +@betterbase/cli:test: (pass) Logger utility > info method > logs informational messages to console.log [6.00ms] +@betterbase/cli:test: (pass) Logger utility > info method > handles empty string message +@betterbase/cli:test: (pass) Logger utility > info method > handles special characters in message +@betterbase/cli:test: 73 | logger.info("info test"); +@betterbase/cli:test: 74 | expect(spyLog).toHaveBeenCalledTimes(1); +@betterbase/cli:test: 75 | const raw = spyLog.mock.calls[0][0] as string; +@betterbase/cli:test: 76 | const stripped = stripAnsi(raw); +@betterbase/cli:test: 77 | expect(stripped).toContain(`${logger.sym.info} info test`); +@betterbase/cli:test: 78 | expect(raw).not.toBe(stripped); // ANSI codes present +@betterbase/cli:test: ^ +@betterbase/cli:test: error: expect(received).not.toBe(expected) +@betterbase/cli:test: +@betterbase/cli:test: Expected: not "◆ info test" +@betterbase/cli:test: +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/logger.test.ts:78:20) +@betterbase/cli:test: (fail) Logger utility > info method > calls console.log with info symbol prefix +@betterbase/cli:test: (pass) Logger utility > warn method > logs warning messages to console.warn +@betterbase/cli:test: (pass) Logger utility > warn method > handles empty string message +@betterbase/cli:test: 99 | logger.warn("warn test"); +@betterbase/cli:test: 100 | expect(spyWarn).toHaveBeenCalledTimes(1); +@betterbase/cli:test: 101 | const raw = spyWarn.mock.calls[0][0] as string; +@betterbase/cli:test: 102 | const stripped = stripAnsi(raw); +@betterbase/cli:test: 103 | expect(stripped).toContain(`${logger.sym.warn} warn test`); +@betterbase/cli:test: 104 | expect(raw).not.toBe(stripped); +@betterbase/cli:test: ^ +@betterbase/cli:test: error: expect(received).not.toBe(expected) +@betterbase/cli:test: +@betterbase/cli:test: Expected: not "⚠ warn test" +@betterbase/cli:test: +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/logger.test.ts:104:20) +@betterbase/cli:test: (fail) Logger utility > warn method > calls console.warn with warning symbol prefix [4.00ms] +@betterbase/cli:test: (pass) Logger utility > error method > logs error messages to console.error +@betterbase/cli:test: (pass) Logger utility > error method > handles empty string message +@betterbase/cli:test: (pass) Logger utility > error method > handles error objects as messages +@betterbase/cli:test: (pass) Logger utility > error method > prints hint on second line when hint is provided +@betterbase/cli:test: (pass) Logger utility > error method > does not print hint line when no hint is provided +@betterbase/cli:test: 145 | logger.error("error test"); +@betterbase/cli:test: 146 | expect(spyError).toHaveBeenCalledTimes(1); +@betterbase/cli:test: 147 | const raw = spyError.mock.calls[0][0] as string; +@betterbase/cli:test: 148 | const stripped = stripAnsi(raw); +@betterbase/cli:test: 149 | expect(stripped).toContain(`${logger.sym.error} error test`); +@betterbase/cli:test: 150 | expect(raw).not.toBe(stripped); +@betterbase/cli:test: ^ +@betterbase/cli:test: error: expect(received).not.toBe(expected) +@betterbase/cli:test: +@betterbase/cli:test: Expected: not "✗ error test" +@betterbase/cli:test: +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/logger.test.ts:150:20) +@betterbase/cli:test: (fail) Logger utility > error method > calls console.error with error symbol prefix and colored message +betterbase-base-template:test: --> GET /api/users 200 94ms +betterbase-base-template:test: (pass) users CRUD endpoint > GET /api/users > returns empty users array when no users exist [104.00ms] +betterbase-base-template:test: <-- GET /api/users?limit=10&offset=5 +@betterbase/cli:test: 152 | +@betterbase/cli:test: 153 | it("error shows hint when provided, with dim styling", () => { +@betterbase/cli:test: 154 | logger.error("Oops", "Run with --debug"); +@betterbase/cli:test: 155 | expect(spyError).toHaveBeenCalledTimes(2); +@betterbase/cli:test: 156 | const hintRaw = spyError.mock.calls[1][0] as string; +@betterbase/cli:test: 157 | expect(hintRaw).toContain("\x1b[2m"); // dim ANSI +@betterbase/cli:test: ^ +@betterbase/cli:test: error: expect(received).toContain(expected) +@betterbase/cli:test: +@betterbase/cli:test: Expected to contain: "\u001B[2m" +@betterbase/cli:test: Received: " Run with --debug" +@betterbase/cli:test: +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/logger.test.ts:157:20) +@betterbase/cli:test: (fail) Logger utility > error method > error shows hint when provided, with dim styling [12.00ms] +@betterbase/cli:test: (pass) Logger utility > success method > logs success messages to console.log [1.00ms] +@betterbase/cli:test: (pass) Logger utility > success method > handles empty string message +@betterbase/cli:test: 179 | logger.success("success test"); +@betterbase/cli:test: 180 | expect(spyLog).toHaveBeenCalledTimes(1); +@betterbase/cli:test: 181 | const raw = spyLog.mock.calls[0][0] as string; +@betterbase/cli:test: 182 | const stripped = stripAnsi(raw); +@betterbase/cli:test: 183 | expect(stripped).toContain(`${logger.sym.success} success test`); +@betterbase/cli:test: 184 | expect(raw).not.toBe(stripped); +@betterbase/cli:test: ^ +@betterbase/cli:test: error: expect(received).not.toBe(expected) +@betterbase/cli:test: +@betterbase/cli:test: Expected: not "✓ success test" +@betterbase/cli:test: +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/logger.test.ts:184:20) +@betterbase/cli:test: (fail) Logger utility > success method > calls console.log with success symbol prefix [1.00ms] +@betterbase/cli:test: (pass) Logger utility > dim method > logs dimmed message to console.log [1.00ms] +@betterbase/cli:test: (pass) Logger utility > dim method > handles empty string +@betterbase/cli:test: (pass) Logger utility > step method > logs step with badge to console.log [5.00ms] +@betterbase/cli:test: (pass) Logger utility > section method > prints blank line, bold title, and dim separator +@betterbase/cli:test: (pass) Logger utility > section method > truncates separator at 60 chars for long titles +betterbase-base-template:test: --> GET /api/users?limit=10&offset=5 200 16ms +@betterbase/cli:test: (pass) Logger utility > section method > handles empty title +@betterbase/cli:test: (pass) Logger utility > section method > outputs title and separator line correctly [1.00ms] +@betterbase/cli:test: 255 | expect(spyLog).toHaveBeenCalledTimes(1); +@betterbase/cli:test: 256 | const raw = spyLog.mock.calls[0][0] as string; +@betterbase/cli:test: 257 | const stripped = stripAnsi(raw); +@betterbase/cli:test: 258 | const expected = ` ${"Name".padEnd(22)} my-project`; +@betterbase/cli:test: 259 | expect(stripped).toBe(expected); +@betterbase/cli:test: 260 | expect(raw).not.toBe(stripped); // value is colored +@betterbase/cli:test: ^ +@betterbase/cli:test: error: expect(received).not.toBe(expected) +@betterbase/cli:test: +@betterbase/cli:test: Expected: not " Name my-project" +@betterbase/cli:test: +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/logger.test.ts:260:20) +@betterbase/cli:test: (fail) Logger utility > keyValue method > prints indented key-value pair with padded key and cyan value +@betterbase/cli:test: (pass) Logger utility > keyValue method > obscures secret values with dots +@betterbase/cli:test: (pass) Logger utility > keyValue method > pads key to exactly 22 characters +@betterbase/cli:test: 278 | }); +@betterbase/cli:test: 279 | +@betterbase/cli:test: 280 | it("value is colored cyan", () => { +@betterbase/cli:test: 281 | logger.keyValue("Env", "production"); +@betterbase/cli:test: 282 | const raw = spyLog.mock.calls[0][0] as string; +@betterbase/cli:test: 283 | expect(raw).toContain("\x1b[36m"); // cyan open +@betterbase/cli:test: ^ +@betterbase/cli:test: error: expect(received).toContain(expected) +@betterbase/cli:test: +@betterbase/cli:test: Expected to contain: "\u001B[36m" +@betterbase/cli:test: Received: " Env production" +@betterbase/cli:test: +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/logger.test.ts:283:16) +@betterbase/cli:test: (fail) Logger utility > keyValue method > value is colored cyan +@betterbase/cli:test: (pass) Logger utility > tree method > prints tree items with branch characters +@betterbase/cli:test: (pass) Logger utility > tree method > uses treeLast for single item +@betterbase/cli:test: (pass) Logger utility > tree method > handles empty array +betterbase-base-template:test: (pass) users CRUD endpoint > GET /api/users > accepts limit and offset query parameters [21.00ms] +betterbase-base-template:test: <-- GET /api/users?limit=-1 +@betterbase/cli:test: (pass) Logger utility > tree method > outputs tree lines with proper indentation and symbols [5.00ms] +betterbase-base-template:test: --> GET /api/users?limit=-1 400 4ms +betterbase-base-template:test: (pass) users CRUD endpoint > GET /api/users > returns 400 for invalid limit [10.00ms] +betterbase-base-template:test: <-- GET /api/users?limit=abc +betterbase-base-template:test: --> GET /api/users?limit=abc 400 0ms +@betterbase/cli:test: (pass) Logger utility > blank method > prints a single newline [11.00ms] +betterbase-base-template:test: (pass) users CRUD endpoint > GET /api/users > returns 400 for non-numeric limit [7.00ms] +betterbase-base-template:test: <-- POST /api/users +betterbase-base-template:test: --> POST /api/users 200 18ms +betterbase-base-template:test: (pass) users CRUD endpoint > POST /api/users > validates payload but does not persist (stub behavior) [19.00ms] +betterbase-base-template:test: <-- POST /api/users +betterbase-base-template:test: --> POST /api/users 400 0ms +betterbase-base-template:test: (pass) users CRUD endpoint > POST /api/users > returns 400 for missing email [1.00ms] +betterbase-base-template:test: <-- POST /api/users +betterbase-base-template:test: --> POST /api/users 400 3ms +betterbase-base-template:test: (pass) users CRUD endpoint > POST /api/users > returns 400 for invalid email [5.00ms] +betterbase-base-template:test: <-- POST /api/users +betterbase-base-template:test: --> POST /api/users 400 0ms +betterbase-base-template:test: (pass) users CRUD endpoint > POST /api/users > returns 400 for malformed JSON [4.00ms] +betterbase-base-template:test: +betterbase-base-template:test: 9 pass +betterbase-base-template:test: 0 fail +betterbase-base-template:test: 21 expect() calls +betterbase-base-template:test: Ran 9 tests across 2 files. [3.00s] +@betterbase/cli:test: (pass) Logger utility > blank method > calls console.log with empty string [89.00ms] +@betterbase/cli:test: (pass) Logger utility > box method > prints a box with title and key-value lines [4.00ms] +@betterbase/cli:test: (pass) Logger utility > box method > handles empty lines array +@betterbase/cli:test: (pass) Logger utility > box method > outputs multi-line box with borders +@betterbase/cli:test: (pass) Logger utility > banner method > prints app name, version, and tagline [4.00ms] +@betterbase/cli:test: (pass) Logger utility > done method > prints elapsed time with success symbol [4.00ms] +@betterbase/cli:test: (pass) Logger utility > done method > prints custom message when provided +@betterbase/cli:test: (pass) Logger utility > done method > prepends newline before output +@betterbase/cli:test: (pass) Logger utility > badge method > returns colored badge string for green +@betterbase/cli:test: (pass) Logger utility > badge method > returns colored badge string for red +@betterbase/cli:test: (pass) Logger utility > badge method > returns colored badge string for yellow +@betterbase/cli:test: (pass) Logger utility > badge method > returns colored badge string for blue +@betterbase/cli:test: (pass) Logger utility > badge method > returns colored badge string for dim +@betterbase/cli:test: 469 | }); +@betterbase/cli:test: 470 | +@betterbase/cli:test: 471 | it("contains ANSI color codes (not plain text)", () => { +@betterbase/cli:test: 472 | const result = logger.badge("PASS", "green"); +@betterbase/cli:test: 473 | expect(stripAnsi(result)).toBe(" PASS "); +@betterbase/cli:test: 474 | expect(result.length).toBeGreaterThan(" PASS ".length); +@betterbase/cli:test: ^ +@betterbase/cli:test: error: expect(received).toBeGreaterThan(expected) +@betterbase/cli:test: +@betterbase/cli:test: Expected: > 6 +@betterbase/cli:test: Received: 6 +@betterbase/cli:test: +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/logger.test.ts:474:26) +@betterbase/cli:test: (fail) Logger utility > badge method > contains ANSI color codes (not plain text) +@betterbase/cli:test: (pass) Logger utility > badge method > returns correct colored badge for each color +@betterbase/cli:test: (pass) Logger utility > sym constants > has success symbol [8.00ms] +@betterbase/cli:test: (pass) Logger utility > sym constants > has error symbol +@betterbase/cli:test: (pass) Logger utility > sym constants > has warn symbol +@betterbase/cli:test: (pass) Logger utility > sym constants > has info symbol +@betterbase/cli:test: (pass) Logger utility > sym constants > has arrow symbol [1.00ms] +@betterbase/cli:test: (pass) Logger utility > sym constants > has bullet symbol [3.00ms] +@betterbase/cli:test: (pass) Logger utility > sym constants > has tree symbol +@betterbase/cli:test: (pass) Logger utility > sym constants > has treeLast symbol +@betterbase/cli:test: (pass) Logger utility > sym constants > has dot symbol +@betterbase/cli:test: (pass) Logger utility > sym constants > all sym values are non-empty strings [1.00ms] +@betterbase/cli:test: (pass) Logger utility > sym constants > sym has correct emoji values when UNICODE is true [1.00ms] +@betterbase/cli:test: (pass) Logger utility > sym constants > sym has ASCII fallbacks when UNICODE is false +@betterbase/cli:test: (pass) Logger utility > logging with different message types > handles string messages +@betterbase/cli:test: (pass) Logger utility > logging with different message types > handles multiline messages +@betterbase/cli:test: (pass) Logger utility > logging with different message types > handles messages with quotes +@betterbase/cli:test: (pass) Logger utility > logging with different message types > handles unicode characters +@betterbase/cli:test: +@betterbase/cli:test: test/prompts.test.ts: +@betterbase/cli:test: (pass) Prompt utilities > text prompt > validates message is required [3.00ms] +@betterbase/cli:test: (pass) Prompt utilities > text prompt > accepts valid text prompt options [62.00ms] +@betterbase/cli:test: (pass) Prompt utilities > text prompt > accepts initial value option [6.00ms] +@betterbase/cli:test: (pass) Prompt utilities > confirm prompt > validates message is required [1.00ms] +@betterbase/cli:test: (pass) Prompt utilities > confirm prompt > accepts valid confirm prompt options [6.00ms] +@betterbase/cli:test: (pass) Prompt utilities > confirm prompt > accepts initial option for backward compatibility [4.00ms] +@betterbase/cli:test: (pass) Prompt utilities > select prompt > validates message is required [3.00ms] +@betterbase/cli:test: (pass) Prompt utilities > select prompt > validates options are required [1.00ms] +@betterbase/cli:test: ? Enter your name:? Enter your name: (John)? Continue? (Y/n)? Continue? (y/N)? Select one: (Use arrow keys) +@betterbase/cli:test: (pass) Prompt utilities > select prompt > validates option has value and label [16.00ms] +@betterbase/cli:test: ❯ Neon[?25l? Select provider: (Use arrow keys) +@betterbase/cli:test: ❯ Neon +@betterbase/cli:test: (pass) Prompt utilities > select prompt > accepts default option [7.00ms] +@betterbase/cli:test: Turso[?25l? Select provider: (Use arrow keys) +@betterbase/cli:test: Neon +@betterbase/cli:test: MaxListenersExceededWarning: Possible EventTarget memory leak detected. 21 keypress listeners added to [ReadStream]. MaxListeners is undefined. Use events.setMaxListeners() to increase limit +@betterbase/cli:test: emitter: ReadStream { +@betterbase/cli:test: fd: 0, +@betterbase/cli:test: [Symbol(kFs)]: [Object ...], +@betterbase/cli:test: start: undefined, +@betterbase/cli:test: end: Infinity, +@betterbase/cli:test: pos: undefined, +@betterbase/cli:test: bytesRead: 0, +@betterbase/cli:test: [Symbol(kReadStreamFastPath)]: false, +@betterbase/cli:test: _events: [Object ...], +@betterbase/cli:test: _readableState: [Object ...], +@betterbase/cli:test: _maxListeners: undefined, +@betterbase/cli:test: [Symbol(kCapture)]: false, +@betterbase/cli:test: _eventsCount: NaN, +@betterbase/cli:test: on: [Function], +@betterbase/cli:test: addListener: [Function], +@betterbase/cli:test: ref: [Function], +@betterbase/cli:test: unref: [Function], +@betterbase/cli:test: pause: [Function], +@betterbase/cli:test: resume: [Function], +@betterbase/cli:test: _read: [Function: triggerRead], +@betterbase/cli:test: [Symbol(keypress-decoder)]: [StringDecoder ...], +@betterbase/cli:test: [Symbol(escape-decoder)]: {}, +@betterbase/cli:test: autoClose: [Getter/Setter], +@betterbase/cli:test: open: [Function: open], +@betterbase/cli:test: _construct: [Function: streamConstruct], +@betterbase/cli:test: _destroy: [Function], +@betterbase/cli:test: close: [Function], +@betterbase/cli:test: pending: [Getter], +@betterbase/cli:test: pipe: [Function], +@betterbase/cli:test: destroy: [Function: destroy], +@betterbase/cli:test: _undestroy: [Function: undestroy], +@betterbase/cli:test: push: [Function], +@betterbase/cli:test: unshift: [Function], +@betterbase/cli:test: isPaused: [Function], +@betterbase/cli:test: setEncoding: [Function], +@betterbase/cli:test: read: [Function], +@betterbase/cli:test: unpipe: [Function], +@betterbase/cli:test: removeListener: [Function], +@betterbase/cli:test: off: [Function], +@betterbase/cli:test: removeAllListeners: [Function], +@betterbase/cli:test: wrap: [Function], +@betterbase/cli:test: iterator: [Function], +@betterbase/cli:test: readable: [Getter/Setter], +@betterbase/cli:test: readableDidRead: [Getter], +@betterbase/cli:test: readableAborted: [Getter], +@betterbase/cli:test: readableHighWaterMark: [Getter], +@betterbase/cli:test: readableBuffer: [Getter], +@betterbase/cli:test: readableFlowing: [Getter/Setter], +@betterbase/cli:test: readableLength: [Getter], +@betterbase/cli:test: readableObjectMode: [Getter], +@betterbase/cli:test: readableEncoding: [Getter], +@betterbase/cli:test: errored: [Getter], +@betterbase/cli:test: closed: [Getter], +@betterbase/cli:test: destroyed: [Getter/Setter], +@betterbase/cli:test: readableEnded: [Getter], +@betterbase/cli:test: drop: [Function], +@betterbase/cli:test: filter: [Function], +@betterbase/cli:test: flatMap: [Function], +@betterbase/cli:test: map: [Function], +@betterbase/cli:test: take: [Function], +@betterbase/cli:test: compose: [Function], +@betterbase/cli:test: every: [Function], +@betterbase/cli:test: forEach: [Function], +@betterbase/cli:test: reduce: [Function], +@betterbase/cli:test: toArray: [Function], +@betterbase/cli:test: some: [Function], +@betterbase/cli:test: find: [Function], +@betterbase/cli:test: [Symbol(nodejs.rejection)]: [Function], +@betterbase/cli:test: [Symbol(Symbol.asyncDispose)]: [Function], +@betterbase/cli:test: [Symbol(Symbol.asyncIterator)]: [Function], +@betterbase/cli:test: eventNames: [Function: eventNames], +@betterbase/cli:test: setMaxListeners: [Function: setMaxListeners], +@betterbase/cli:test: getMaxListeners: [Function: getMaxListeners], +@betterbase/cli:test: emit: [Function: emit], +@betterbase/cli:test: prependListener: [Function: prependListener], +@betterbase/cli:test: once: [Function: once], +@betterbase/cli:test: prependOnceListener: [Function: prependOnceListener], +@betterbase/cli:test: listeners: [Function: listeners], +@betterbase/cli:test: rawListeners: [Function: rawListeners], +@betterbase/cli:test: listenerCount: [Function: listenerCount], +@betterbase/cli:test: }, +@betterbase/cli:test: type: "keypress", +@betterbase/cli:test: count: 21, +@betterbase/cli:test: +@betterbase/cli:test: at overflowWarning (node:events:185:19) +@betterbase/cli:test: at addListener (node:events:158:22) +@betterbase/cli:test: at (internal:streams/readable:519:38) +@betterbase/cli:test: at (/workspaces/Betterbase/node_modules/@inquirer/core/dist/esm/lib/use-keypress.mjs:14:18) +@betterbase/cli:test: at (/workspaces/Betterbase/node_modules/@inquirer/core/dist/esm/lib/hook-engine.mjs:84:29) +@betterbase/cli:test: at (/workspaces/Betterbase/node_modules/@inquirer/core/dist/esm/lib/hook-engine.mjs:95:17) +@betterbase/cli:test: at forEach (1:11) +@betterbase/cli:test: at (/workspaces/Betterbase/node_modules/@inquirer/core/dist/esm/lib/hook-engine.mjs:94:31) +@betterbase/cli:test: at wrapped (/workspaces/Betterbase/node_modules/@inquirer/core/dist/esm/lib/hook-engine.mjs:50:29) +@betterbase/cli:test: at runInAsyncScope (node:async_hooks:137:23) +@betterbase/cli:test: +@betterbase/cli:test: (pass) Prompt utilities > select prompt > accepts initial option for backward compatibility [15.00ms] +@betterbase/cli:test: (pass) Prompt utilities > select prompt > validates default matches an option value +@betterbase/cli:test: +@betterbase/cli:test: test/scanner.test.ts: +@betterbase/core:test: (pass) GraphQL Resolvers > generateResolvers > should generate resolvers for single table +@betterbase/cli:test: (pass) SchemaScanner > extracts tables, columns, relations, and indexes from drizzle schema [9.00ms] +@betterbase/core:test: (pass) GraphQL Resolvers > generateResolvers > should generate resolvers for multiple tables [1.00ms] +@betterbase/core:test: (pass) GraphQL Resolvers > generateResolvers > should generate subscriptions when enabled +@betterbase/core:test: (pass) GraphQL Resolvers > generateResolvers > should accept empty config +@betterbase/core:test: (pass) GraphQL Resolvers > createGraphQLContext > should create context function +@betterbase/core:test: (pass) GraphQL Resolvers > requireAuth > should wrap a resolver with auth check +@betterbase/core:test: (pass) GraphQL Resolvers > requireAuth > wrapped resolver should throw when user missing [2.00ms] +@betterbase/core:test: (pass) GraphQL Resolvers > requireAuth > wrapped resolver should call original when user present +@betterbase/core:test: (pass) GraphQL Resolvers > resolver hooks configuration > should accept beforeCreate hook +@betterbase/core:test: (pass) GraphQL Resolvers > resolver hooks configuration > should accept afterCreate hook [1.00ms] +@betterbase/core:test: (pass) GraphQL Resolvers > resolver hooks configuration > should accept onError handler +@betterbase/core:test: (pass) GraphQL Resolvers > resolver types > should have correct Resolvers structure +@betterbase/core:test: (pass) GraphQL Resolvers > resolver types > GraphQLResolver type should accept function +@betterbase/core:test: (pass) GraphQL Resolvers > resolver types > GraphQLContext should accept db and user +@betterbase/core:test: +@betterbase/core:test: test/realtime-channel-manager.test.ts: +@betterbase/cli:test: (pass) SchemaScanner > handles empty tables (zero columns) [4.00ms] +@betterbase/cli:test: (pass) SchemaScanner > handles tables with no relations [3.00ms] +@betterbase/cli:test: (pass) SchemaScanner > handles circular foreign key dependencies [2.00ms] +@betterbase/core:test: (pass) Realtime Channel Manager > ChannelManager > should create channel manager [2.00ms] +@betterbase/core:test: (pass) Realtime Channel Manager > ChannelManager > should subscribe to channels +@betterbase/core:test: (pass) Realtime Channel Manager > ChannelManager > should unsubscribe from channels +@betterbase/core:test: (pass) Realtime Channel Manager > ChannelManager > should broadcast to channels +@betterbase/core:test: (pass) Realtime Channel Manager > ChannelManager > should handle presence +@betterbase/core:test: (pass) Realtime Channel Manager > ChannelManager > should handle transient messages +@betterbase/core:test: (pass) Realtime Channel Manager > ChannelManager > should handle state synchronization +@betterbase/core:test: (pass) Realtime Channel Manager > ChannelManager > should clean up disconnected clients +@betterbase/core:test: (pass) Realtime Channel Manager > createChannelManager > should create channel manager instance [1.00ms] +@betterbase/core:test: (pass) Realtime Channel Manager > createChannelManager > should configure options +@betterbase/core:test: (pass) Realtime Channel Manager > createChannelManager > should setup event handlers +@betterbase/cli:test: (pass) SchemaScanner > handles array columns [2.00ms] +@betterbase/core:test: (pass) Channel Manager Stubs > should have placeholder for subscription +@betterbase/core:test: (pass) Channel Manager Stubs > should have placeholder for broadcast [1.00ms] +@betterbase/core:test: (pass) Channel Manager Stubs > should have placeholder for presence +@betterbase/core:test: (pass) Channel Manager Stubs > should have placeholder for cleanup +@betterbase/core:test: +@betterbase/core:test: test/rls-scanner.test.ts: +@betterbase/cli:test: (pass) SchemaScanner > handles enum columns [3.00ms] +@betterbase/cli:test: (pass) SchemaScanner > handles large complex schema with 5 interconnected tables [6.00ms] +@betterbase/cli:test: +@betterbase/cli:test: test/migrate.test.ts: +@betterbase/core:test: (pass) RLS Scanner > scanPolicies > should return empty result when no policy directory exists [7.00ms] +@betterbase/core:test: Dynamic import failed for /tmp/rls-scanner-test-1778954648761/src/db/policies/users.policy.ts, using regex fallback +@betterbase/core:test: (pass) RLS Scanner > scanPolicies > should scan src/db/policies directory [4.00ms] +@betterbase/core:test: Dynamic import failed for /tmp/rls-scanner-test-1778954648766/db/policies/posts.policy.ts, using regex fallback +@betterbase/core:test: (pass) RLS Scanner > scanPolicies > should scan db/policies directory [1.00ms] +@betterbase/core:test: Dynamic import failed for /tmp/rls-scanner-test-1778954648767/policies/comments.policy.ts, using regex fallback +@betterbase/core:test: (pass) RLS Scanner > scanPolicies > should scan policies directory [2.00ms] +@betterbase/core:test: Dynamic import failed for /tmp/rls-scanner-test-1778954648768/src/db/policies/comments.policy.ts, using regex fallback +@betterbase/core:test: Dynamic import failed for /tmp/rls-scanner-test-1778954648768/src/db/policies/posts.policy.ts, using regex fallback +@betterbase/core:test: Dynamic import failed for /tmp/rls-scanner-test-1778954648768/src/db/policies/users.policy.ts, using regex fallback +@betterbase/core:test: (pass) RLS Scanner > scanPolicies > should load multiple policy files [2.00ms] +@betterbase/core:test: (pass) RLS Scanner > scanPolicies > should handle errors when policy file is invalid [1.00ms] +@betterbase/core:test: (pass) RLS Scanner > scanPolicies > should return empty when policy directory is empty [2.00ms] +@betterbase/core:test: Dynamic import failed for /tmp/rls-scanner-test-1778954648773/src/db/policies/users.policy.ts, using regex fallback +@betterbase/core:test: (pass) RLS Scanner > scanPoliciesStrict > should return policies when scan succeeds [3.00ms] +@betterbase/core:test: (pass) RLS Scanner > scanPoliciesStrict > should throw when scan has errors [2.00ms] +@betterbase/core:test: (pass) RLS Scanner > listPolicyFiles > should return empty array when no policy directory exists [3.00ms] +@betterbase/core:test: (pass) RLS Scanner > listPolicyFiles > should return list of policy file paths [1.00ms] +@betterbase/core:test: (pass) RLS Scanner > listPolicyFiles > should return empty when policy directory is empty [1.00ms] +@betterbase/core:test: (pass) RLS Scanner > listPolicyFiles > should not include non-policy files [1.00ms] +@betterbase/core:test: (pass) RLS Scanner > getPolicyFileInfo > should return policy file info +@betterbase/core:test: (pass) RLS Scanner > getPolicyFileInfo > should return empty array when no policies [1.00ms] +@betterbase/core:test: Dynamic import failed for /tmp/rls-scanner-test-1778954648786/src/db/policies/users.policy.ts, using regex fallback +@betterbase/core:test: (pass) RLS Scanner > policy file parsing > should parse policy with select condition [3.00ms] +@betterbase/core:test: Dynamic import failed for /tmp/rls-scanner-test-1778954648788/src/db/policies/posts.policy.ts, using regex fallback +@betterbase/core:test: (pass) RLS Scanner > policy file parsing > should parse policy with multiple conditions [3.00ms] +@betterbase/core:test: Dynamic import failed for /tmp/rls-scanner-test-1778954648791/src/db/policies/documents.policy.ts, using regex fallback +@betterbase/core:test: (pass) RLS Scanner > policy file parsing > should parse policy with using clause [7.00ms] +@betterbase/core:test: Dynamic import failed for /tmp/rls-scanner-test-1778954648798/src/db/policies/comments.policy.ts, using regex fallback +@betterbase/core:test: (pass) RLS Scanner > policy file parsing > should parse policy with withCheck clause [2.00ms] +@betterbase/core:test: (pass) RLS Scanner > PolicyScanError > should create error with message [1.00ms] +@betterbase/core:test: (pass) RLS Scanner > PolicyScanError > should create error with cause [1.00ms] +@betterbase/core:test: +@betterbase/core:test: test/image-transformer.test.ts: +@betterbase/core:test: (pass) ImageTransformer > generateCacheKey > should generate consistent cache key for same options [2.00ms] +@betterbase/core:test: (pass) ImageTransformer > generateCacheKey > should generate different cache key for different options +@betterbase/core:test: (pass) ImageTransformer > generateCacheKey > should generate different cache key for different paths +@betterbase/core:test: (pass) ImageTransformer > generateCacheKey > should handle empty options +@betterbase/core:test: (pass) ImageTransformer > buildCachePath > should build cache path for simple filename +@betterbase/core:test: (pass) ImageTransformer > buildCachePath > should build cache path for nested directory +@betterbase/core:test: (pass) ImageTransformer > buildCachePath > should handle filename without extension +@betterbase/core:test: (pass) ImageTransformer > buildCachePath > should use provided format in filename +@betterbase/core:test: (pass) ImageTransformer > parseTransformOptions > should parse valid width and height +@betterbase/core:test: (pass) ImageTransformer > parseTransformOptions > should parse valid format +@betterbase/core:test: (pass) ImageTransformer > parseTransformOptions > should parse valid quality +@betterbase/core:test: (pass) ImageTransformer > parseTransformOptions > should parse valid fit +@betterbase/core:test: (pass) ImageTransformer > parseTransformOptions > should return null for invalid width (too small) +@betterbase/core:test: (pass) ImageTransformer > parseTransformOptions > should return null for invalid width (too large) +@betterbase/core:test: (pass) ImageTransformer > parseTransformOptions > should return null for invalid width (negative) +@betterbase/core:test: (pass) ImageTransformer > parseTransformOptions > should return null for invalid height (too small) +@betterbase/core:test: (pass) ImageTransformer > parseTransformOptions > should return null for invalid height (too large) +@betterbase/core:test: (pass) ImageTransformer > parseTransformOptions > should return null for invalid format +@betterbase/core:test: (pass) ImageTransformer > parseTransformOptions > should return null for invalid quality (too low) +@betterbase/core:test: (pass) ImageTransformer > parseTransformOptions > should return null for invalid quality (too high) +@betterbase/core:test: (pass) ImageTransformer > parseTransformOptions > should return null for invalid fit +@betterbase/core:test: (pass) ImageTransformer > parseTransformOptions > should return null for empty query params +@betterbase/core:test: (pass) ImageTransformer > parseTransformOptions > should return null for non-numeric width +@betterbase/core:test: (pass) ImageTransformer > parseTransformOptions > should parse multiple valid options +@betterbase/core:test: (pass) ImageTransformer > parseTransformOptions > should accept jpg as format [1.00ms] +@betterbase/core:test: (pass) ImageTransformer > parseTransformOptions > should handle case-insensitive format +@betterbase/core:test: (pass) ImageTransformer > parseTransformOptions > should handle case-insensitive fit +@betterbase/core:test: (pass) ImageTransformer > isImage > should return true for JPEG +@betterbase/core:test: (pass) ImageTransformer > isImage > should return true for PNG +@betterbase/core:test: (pass) ImageTransformer > isImage > should return true for WebP +@betterbase/core:test: (pass) ImageTransformer > isImage > should return true for GIF +@betterbase/core:test: (pass) ImageTransformer > isImage > should return true for TIFF +@betterbase/core:test: (pass) ImageTransformer > isImage > should return true for AVIF +@betterbase/core:test: (pass) ImageTransformer > isImage > should return true for HEIF +@betterbase/core:test: (pass) ImageTransformer > isImage > should return false for PDF +@betterbase/core:test: (pass) ImageTransformer > isImage > should return false for SVG +@betterbase/core:test: (pass) ImageTransformer > isImage > should return false for unknown type +@betterbase/core:test: (pass) ImageTransformer > isImage > should return false for empty string +@betterbase/core:test: (pass) ImageTransformer > getContentType > should return image/webp for webp format +@betterbase/core:test: (pass) ImageTransformer > getContentType > should return image/jpeg for jpeg format +@betterbase/core:test: (pass) ImageTransformer > getContentType > should return image/jpeg for jpg format +@betterbase/core:test: (pass) ImageTransformer > getContentType > should return image/png for png format +@betterbase/core:test: (pass) ImageTransformer > getContentType > should return image/avif for avif format +@betterbase/core:test: (pass) ImageTransformer > getContentType > should return image/webp for unknown format [1.00ms] +@betterbase/core:test: (pass) ImageTransformer > Edge cases > should handle path with no directory +@betterbase/core:test: (pass) ImageTransformer > Edge cases > should handle path with multiple dots +@betterbase/core:test: (pass) ImageTransformer > Edge cases > should handle parseTransformOptions with undefined values +@betterbase/core:test: (pass) ImageTransformer > Edge cases > should handle cache key with hash containing special characters +@betterbase/core:test: +@betterbase/core:test: test/config.test.ts: +@betterbase/core:test: (pass) config/schema > ProviderTypeSchema > accepts valid provider types +@betterbase/core:test: (pass) config/schema > ProviderTypeSchema > rejects invalid provider types [1.00ms] +@betterbase/core:test: (pass) config/schema > BetterBaseConfigSchema > validates a complete valid config [1.00ms] +@betterbase/core:test: (pass) config/schema > BetterBaseConfigSchema > validates config with optional storage +@betterbase/core:test: (pass) config/schema > BetterBaseConfigSchema > validates config with webhooks [1.00ms] +@betterbase/core:test: (pass) config/schema > BetterBaseConfigSchema > rejects config without project name [1.00ms] +@betterbase/core:test: (pass) config/schema > BetterBaseConfigSchema > rejects config with invalid mode +@betterbase/core:test: (pass) config/schema > BetterBaseConfigSchema > rejects config without connectionString for non-managed providers +@betterbase/core:test: (pass) config/schema > BetterBaseConfigSchema > validates turso provider with url and authToken +@betterbase/core:test: (pass) config/schema > BetterBaseConfigSchema > rejects turso provider without url +@betterbase/core:test: (pass) config/schema > BetterBaseConfigSchema > validates managed provider without connectionString +@betterbase/core:test: (pass) config/schema > defineConfig > returns validated config [1.00ms] +@betterbase/core:test: (pass) config/schema > validateConfig > returns true for valid config [1.00ms] +@betterbase/core:test: (pass) config/schema > validateConfig > returns false for invalid config +@betterbase/core:test: (pass) config/schema > parseConfig > returns success result for valid config +@betterbase/core:test: (pass) config/schema > parseConfig > returns error result for invalid config +@betterbase/core:test: (pass) config/schema > assertConfig > does not throw for valid config +@betterbase/core:test: (pass) config/schema > assertConfig > throws for invalid config +@betterbase/core:test: +@betterbase/core:test: test/storage-types.test.ts: +@betterbase/core:test: (pass) Storage Types > StorageProvider > should allow 's3' as valid provider +@betterbase/core:test: (pass) Storage Types > StorageProvider > should allow 'r2' as valid provider [1.00ms] +@betterbase/core:test: (pass) Storage Types > StorageProvider > should allow 'backblaze' as valid provider +@betterbase/core:test: (pass) Storage Types > StorageProvider > should allow 'minio' as valid provider +@betterbase/core:test: (pass) Storage Types > StorageProvider > should allow 'managed' as valid provider +@betterbase/core:test: (pass) Storage Types > UploadOptions > should allow optional contentType +@betterbase/core:test: (pass) Storage Types > UploadOptions > should allow optional metadata +@betterbase/core:test: (pass) Storage Types > UploadOptions > should allow optional isPublic flag +@betterbase/core:test: (pass) Storage Types > UploadOptions > should allow empty options +@betterbase/core:test: (pass) Storage Types > SignedUrlOptions > should allow optional expiresIn +@betterbase/core:test: (pass) Storage Types > SignedUrlOptions > should allow empty options +@betterbase/core:test: (pass) Storage Types > UploadResult > should have required key and size properties +@betterbase/core:test: (pass) Storage Types > UploadResult > should allow optional contentType and etag +@betterbase/core:test: (pass) Storage Types > StorageObject > should have required properties +@betterbase/core:test: (pass) Storage Types > StorageObject > should allow optional contentType +@betterbase/core:test: (pass) Storage Types > AllowedMimeTypes > should allow only allow list +@betterbase/core:test: (pass) Storage Types > AllowedMimeTypes > should allow deny list +@betterbase/core:test: (pass) Storage Types > AllowedMimeTypes > should allow allowListOnly flag +@betterbase/core:test: (pass) Storage Types > BucketConfig > should allow maxFileSize +@betterbase/core:test: (pass) Storage Types > BucketConfig > should allow allowedMimeTypes +@betterbase/core:test: (pass) Storage Types > BucketConfig > should allow allowedExtensions +@betterbase/core:test: (pass) Storage Types > BucketConfig > should allow empty config +@betterbase/core:test: (pass) Storage Types > defineStoragePolicy > should create storage policy with bucket, operation, and expression +@betterbase/core:test: (pass) Storage Types > defineStoragePolicy > should create policy with wildcard operation +@betterbase/core:test: (pass) Storage Types > defineStoragePolicy > should create policy with different operations +@betterbase/core:test: (pass) Storage Types > StorageConfig types > should validate S3Config +@betterbase/core:test: (pass) Storage Types > StorageConfig types > should validate R2Config +@betterbase/core:test: (pass) Storage Types > StorageConfig types > should validate R2Config with custom endpoint +@betterbase/core:test: (pass) Storage Types > StorageConfig types > should validate BackblazeConfig +@betterbase/core:test: (pass) Storage Types > StorageConfig types > should validate BackblazeConfig with custom endpoint +@betterbase/core:test: (pass) Storage Types > StorageConfig types > should validate MinioConfig [1.00ms] +@betterbase/core:test: (pass) Storage Types > StorageConfig types > should validate MinioConfig with full options +@betterbase/core:test: (pass) Storage Types > StorageConfig types > should validate ManagedConfig +@betterbase/core:test: (pass) Storage Types > StorageConfig types > should validate StorageConfig union type +@betterbase/core:test: +@betterbase/core:test: test/graphql-schema-generator.test.ts: +@betterbase/core:test: (pass) GraphQL Schema Generator > generateGraphQLSchema > should generate a valid GraphQL schema +@betterbase/core:test: (pass) GraphQL Schema Generator > generateGraphQLSchema > should generate Query type [1.00ms] +@betterbase/core:test: (pass) GraphQL Schema Generator > generateGraphQLSchema > should generate Mutation type +@betterbase/core:test: (pass) GraphQL Schema Generator > generateGraphQLSchema > should generate Subscription type by default +@betterbase/core:test: (pass) GraphQL Schema Generator > generateGraphQLSchema > should handle multiple tables [1.00ms] +@betterbase/core:test: (pass) GraphQL Schema Generator > generateGraphQLSchema > should handle empty tables object +@betterbase/core:test: (pass) GraphQL Schema Generator > GraphQL scalar types > should have GraphQLJSON scalar +@betterbase/core:test: (pass) GraphQL Schema Generator > GraphQL scalar types > should have GraphQLDateTime scalar +@betterbase/core:test: (pass) GraphQL Schema Generator > GraphQL scalar types > should serialize Date to ISO string +@betterbase/core:test: (pass) GraphQL Schema Generator > GraphQL scalar types > should serialize string to string +@betterbase/core:test: (pass) GraphQL Schema Generator > GraphQL scalar types > should parse string to Date +@betterbase/core:test: (pass) GraphQL Schema Generator > GraphQL scalar types > should serialize JSON value +@betterbase/core:test: (pass) GraphQL Schema Generator > GraphQL scalar types > should parse JSON value [3.00ms] +@betterbase/core:test: (pass) GraphQL Schema Generator > GraphQLGenerationConfig > should accept empty config object +@betterbase/core:test: (pass) GraphQL Schema Generator > GraphQLGenerationConfig > should accept custom typePrefix [2.00ms] +@betterbase/core:test: (pass) GraphQL Schema Generator > schema structure > should have proper query fields +@betterbase/core:test: (pass) GraphQL Schema Generator > schema structure > should have mutation fields when enabled +@betterbase/core:test: (pass) GraphQL Schema Generator > schema structure > should have subscription fields when enabled +@betterbase/core:test: +@betterbase/core:test: test/providers.test.ts: +@betterbase/cli:test: (pass) splitStatements > splits two statements separated by semicolons +@betterbase/cli:test: (pass) splitStatements > trims whitespace from each statement +@betterbase/cli:test: (pass) splitStatements > ignores empty statements from consecutive semicolons +@betterbase/cli:test: (pass) splitStatements > returns empty array for empty input [2.00ms] +@betterbase/cli:test: (pass) splitStatements > returns single item for input with no semicolons +@betterbase/cli:test: (pass) splitStatements > handles strings with semicolons inside quotes +@betterbase/cli:test: (pass) splitStatements > handles double-quoted strings with semicolons +@betterbase/cli:test: (pass) splitStatements > handles backtick-quoted strings with semicolons +@betterbase/cli:test: (pass) analyzeMigration > returns empty changes for empty array +@betterbase/cli:test: (pass) analyzeMigration > detects CREATE TABLE as non-destructive +@betterbase/cli:test: (pass) analyzeMigration > detects ADD COLUMN as non-destructive [1.00ms] +@betterbase/cli:test: (pass) analyzeMigration > detects DROP TABLE as destructive +@betterbase/cli:test: (pass) analyzeMigration > detects DROP COLUMN as destructive +@betterbase/cli:test: (pass) analyzeMigration > handles multiple statements with mixed destructiveness +@betterbase/cli:test: (pass) analyzeMigration > case-insensitive detection of DROP TABLE [1.00ms] +@betterbase/cli:test: (pass) analyzeMigration > handles IF NOT EXISTS for CREATE TABLE +@betterbase/cli:test: (pass) analyzeMigration > handles IF EXISTS for DROP TABLE +@betterbase/cli:test: +@betterbase/cli:test: test/migrate-from-convex.test.ts: +@betterbase/cli:test: ❯ Turso[?25lMigrating Convex project from /tmp/bb-convex-input-b1DJOA... +@betterbase/cli:test: Output will be in /tmp/bb-convex-output-LoLvY3 +@betterbase/cli:test: ✅ Converted schema.ts +@betterbase/cli:test: +@betterbase/cli:test: ✅ Convex Migration Complete! +@betterbase/cli:test: +@betterbase/cli:test: Converted files are in: /tmp/bb-convex-output-LoLvY3 +@betterbase/cli:test: +@betterbase/cli:test: Key changes made: +@betterbase/cli:test: - Convex v.* validators -> BetterBase v.* +@betterbase/cli:test: - Convex query/mutation/action -> BetterBase query/mutation/action +@betterbase/cli:test: - ctx.db.query() syntax preserved +@betterbase/cli:test: - ctx.runQuery/ctx.runMutation -> ctx.runQuery/ctx.runMutation +@betterbase/cli:test: +@betterbase/cli:test: Manual steps required: +@betterbase/cli:test: 1. Review the generated schema and adjust types if needed +@betterbase/cli:test: 2. Install dependencies: bun add @betterbase/core @betterbase/client +@betterbase/cli:test: 3. Run bb iac sync to create database tables +@betterbase/cli:test: 4. Test your functions +@betterbase/cli:test: 5. Review compatibility report: /tmp/bb-convex-output-LoLvY3/betterbase/convex-migration-report.json +@betterbase/cli:test: +@betterbase/cli:test: Compatibility summary: +@betterbase/cli:test: - Blockers: 0 +@betterbase/cli:test: - Warnings: 0 +@betterbase/cli:test: - Files requiring manual review: 0 +@betterbase/cli:test: +@betterbase/cli:test: See docs/iac/migration-from-convex.md for detailed guide. +@betterbase/cli:test: +@betterbase/cli:test: (pass) runMigrateFromConvex compatibility report > creates report files even when query/mutation/action directories are missing [1.00ms] +@betterbase/cli:test: Migrating Convex project from /tmp/bb-convex-input-dY5OAj... +@betterbase/cli:test: Output will be in /tmp/bb-convex-output-zs86jb +@betterbase/cli:test: ✅ Converted 1 actions +@betterbase/cli:test: +@betterbase/cli:test: ✅ Convex Migration Complete! +@betterbase/cli:test: +@betterbase/cli:test: Converted files are in: /tmp/bb-convex-output-zs86jb +@betterbase/cli:test: +@betterbase/cli:test: Key changes made: +@betterbase/cli:test: - Convex v.* validators -> BetterBase v.* +@betterbase/cli:test: - Convex query/mutation/action -> BetterBase query/mutation/action +@betterbase/cli:test: - ctx.db.query() syntax preserved +@betterbase/cli:test: - ctx.runQuery/ctx.runMutation -> ctx.runQuery/ctx.runMutation +@betterbase/cli:test: +@betterbase/cli:test: Manual steps required: +@betterbase/cli:test: 1. Review the generated schema and adjust types if needed +@betterbase/cli:test: 2. Install dependencies: bun add @betterbase/core @betterbase/client +@betterbase/cli:test: 3. Run bb iac sync to create database tables +@betterbase/cli:test: 4. Test your functions +@betterbase/cli:test: 5. Review compatibility report: /tmp/bb-convex-output-zs86jb/betterbase/convex-migration-report.json +@betterbase/cli:test: +@betterbase/cli:test: Compatibility summary: +@betterbase/cli:test: - Blockers: 1 +@betterbase/cli:test: - Warnings: 1 +@betterbase/cli:test: - Files requiring manual review: 1 +@betterbase/cli:test: +@betterbase/cli:test: See docs/iac/migration-from-convex.md for detailed guide. +@betterbase/cli:test: +@betterbase/cli:test: (pass) runMigrateFromConvex compatibility report > detects compatibility blockers and warnings in converted functions [2.00ms] +@betterbase/cli:test: +@betterbase/cli:test: test/edge-cases.test.ts: +@betterbase/cli:test: (pass) SchemaScanner — malformed and edge inputs > does not throw on completely empty file [2.00ms] +@betterbase/cli:test: (pass) SchemaScanner — malformed and edge inputs > returns empty object for empty file [4.00ms] +@betterbase/cli:test: (pass) SchemaScanner — malformed and edge inputs > returns empty object for schema with only import statements [4.00ms] +@betterbase/cli:test: (pass) SchemaScanner — malformed and edge inputs > returns empty object for schema with only comments [2.00ms] +@betterbase/cli:test: (pass) SchemaScanner — malformed and edge inputs > does not throw on schema with syntax errors [2.00ms] +@betterbase/cli:test: (pass) SchemaScanner — malformed and edge inputs > handles very long column names without throwing [1.00ms] +@betterbase/cli:test: (pass) SchemaScanner — malformed and edge inputs > throws when file does not exist [1.00ms] +@betterbase/cli:test: (pass) RouteScanner — malformed and edge inputs > does not throw on empty file [1.00ms] +@betterbase/cli:test: (pass) RouteScanner — malformed and edge inputs > scan() result is defined for empty file [1.00ms] +@betterbase/cli:test: (pass) RouteScanner — malformed and edge inputs > does not throw on file with no route registrations [1.00ms] +@betterbase/cli:test: (pass) RouteScanner — malformed and edge inputs > does not throw on malformed TypeScript [2.00ms] +@betterbase/cli:test: (pass) RouteScanner — malformed and edge inputs > does not throw on deeply nested code [3.00ms] +@betterbase/cli:test: (pass) ContextGenerator — boundary conditions > does not throw on project with no schema and no routes [1.00ms] +@betterbase/cli:test: (pass) ContextGenerator — boundary conditions > generate() returns an object +@betterbase/cli:test: (pass) ContextGenerator — boundary conditions > output is always JSON-serializable [5.00ms] +@betterbase/cli:test: (pass) ContextGenerator — boundary conditions > handles empty schema file without throwing [1.00ms] +@betterbase/cli:test: (pass) ContextGenerator — boundary conditions > handles schema with real tables [2.00ms] +@betterbase/cli:test: +@betterbase/cli:test: test/generate-crud.test.ts: +@betterbase/cli:test: ◆ Generating CRUD for posts... +@betterbase/cli:test: +@betterbase/cli:test: Generating CRUD for "posts" +@betterbase/cli:test: ───────────────────────────── +@betterbase/cli:test: ├─ src/routes/posts.ts +@betterbase/cli:test: └─ Updated src/routes/index.ts +@betterbase/cli:test: +@betterbase/cli:test: - Scanning schema... +@betterbase/cli:test: ✓ Found table posts +@betterbase/cli:test: +@betterbase/cli:test: +@betterbase/cli:test: - Writing route file... +@betterbase/cli:test: ✓ Created src/routes/posts.ts +@betterbase/cli:test: - Updating router index... +@betterbase/cli:test: ✓ Router updated +@betterbase/cli:test: Generated endpoints +@betterbase/cli:test: ───────────────────── +@betterbase/cli:test: GET /api/posts List all (paginated) +@betterbase/cli:test: GET /api/posts/:id Get single +@betterbase/cli:test: POST /api/posts Create +@betterbase/cli:test: PATCH /api/posts/:id Update +@betterbase/cli:test: DELETE /api/posts/:id Delete +@betterbase/cli:test: ◆ Regenerating GraphQL schema... +@betterbase/cli:test: ◆ Generating GraphQL schema... +@betterbase/cli:test: ✓ GraphQL SDL written to src/lib/graphql/schema.graphql +@betterbase/cli:test: ✓ GraphQL server setup written to src/routes/graphql.ts +@betterbase/cli:test: ✓ GraphQL API generated at /api/graphql +@betterbase/cli:test: ◆ Run "bb graphql playground" to open the GraphQL Playground +@betterbase/cli:test: (pass) runGenerateCrudCommand > creates src/routes/posts.ts for posts table [20.00ms] +@betterbase/cli:test: ◆ Generating CRUD for posts... +@betterbase/cli:test: +@betterbase/cli:test: Generating CRUD for "posts" +@betterbase/cli:test: ───────────────────────────── +@betterbase/cli:test: ├─ src/routes/posts.ts +@betterbase/cli:test: └─ Updated src/routes/index.ts +@betterbase/cli:test: +@betterbase/cli:test: - Scanning schema... +@betterbase/cli:test: ✓ Found table posts +@betterbase/cli:test: - Writing route file... +@betterbase/cli:test: ✓ Created src/routes/posts.ts +@betterbase/cli:test: - Updating router index... +@betterbase/cli:test: ✓ Router updated +@betterbase/cli:test: +@betterbase/cli:test: +@betterbase/cli:test: Generated endpoints +@betterbase/cli:test: ───────────────────── +@betterbase/cli:test: GET /api/posts List all (paginated) +@betterbase/cli:test: GET /api/posts/:id Get single +@betterbase/cli:test: POST /api/posts Create +@betterbase/cli:test: PATCH /api/posts/:id Update +@betterbase/cli:test: DELETE /api/posts/:id Delete +@betterbase/cli:test: ◆ Regenerating GraphQL schema... +@betterbase/cli:test: ◆ Generating GraphQL schema... +@betterbase/cli:test: ✓ GraphQL SDL written to src/lib/graphql/schema.graphql +@betterbase/cli:test: ✓ GraphQL server setup written to src/routes/graphql.ts +@betterbase/cli:test: ✓ GraphQL API generated at /api/graphql +@betterbase/cli:test: ◆ Run "bb graphql playground" to open the GraphQL Playground +@betterbase/cli:test: (pass) runGenerateCrudCommand > generated route exports postsRoute [14.00ms] +@betterbase/cli:test: ◆ Generating CRUD for posts... +@betterbase/cli:test: +@betterbase/cli:test: Generating CRUD for "posts" +@betterbase/cli:test: ───────────────────────────── +@betterbase/cli:test: ├─ src/routes/posts.ts +@betterbase/cli:test: └─ Updated src/routes/index.ts +@betterbase/cli:test: +@betterbase/cli:test: - Scanning schema... +@betterbase/cli:test: +@betterbase/cli:test: +@betterbase/cli:test: Generated endpoints +@betterbase/cli:test: ───────────────────── +@betterbase/cli:test: GET /api/posts List all (paginated) +@betterbase/cli:test: ✓ Found table posts +@betterbase/cli:test: - Writing route file... +@betterbase/cli:test: GET /api/posts/:id Get single +@betterbase/cli:test: POST /api/posts Create +@betterbase/cli:test: ✓ Created src/routes/posts.ts +@betterbase/cli:test: PATCH /api/posts/:id Update +@betterbase/cli:test: - Updating router index... +@betterbase/cli:test: DELETE /api/posts/:id Delete +@betterbase/cli:test: ✓ Router updated +@betterbase/cli:test: (pass) runGenerateCrudCommand > generated route contains GET / handler [11.00ms] +@betterbase/cli:test: ◆ Regenerating GraphQL schema... +@betterbase/cli:test: ◆ Generating GraphQL schema... +@betterbase/cli:test: ✓ GraphQL SDL written to src/lib/graphql/schema.graphql +@betterbase/cli:test: ✓ GraphQL server setup written to src/routes/graphql.ts +@betterbase/cli:test: ✓ GraphQL API generated at /api/graphql +@betterbase/cli:test: ◆ Run "bb graphql playground" to open the GraphQL Playground +@betterbase/cli:test: ◆ Generating CRUD for posts... +@betterbase/cli:test: +@betterbase/cli:test: - Scanning schema... +@betterbase/cli:test: Generating CRUD for "posts" +@betterbase/cli:test: ───────────────────────────── +@betterbase/cli:test: ├─ src/routes/posts.ts +@betterbase/cli:test: └─ Updated src/routes/index.ts +@betterbase/cli:test: +@betterbase/cli:test: ✓ Found table posts +@betterbase/cli:test: - Writing route file... +@betterbase/cli:test: +@betterbase/cli:test: ✓ Created src/routes/posts.ts +@betterbase/cli:test: +@betterbase/cli:test: Generated endpoints +@betterbase/cli:test: ───────────────────── +@betterbase/cli:test: GET /api/posts List all (paginated) +@betterbase/cli:test: GET /api/posts/:id Get single +@betterbase/cli:test: - Updating router index... +@betterbase/cli:test: POST /api/posts Create +@betterbase/cli:test: PATCH /api/posts/:id Update +@betterbase/cli:test: ✓ Router updated +@betterbase/cli:test: DELETE /api/posts/:id Delete +@betterbase/cli:test: ◆ Regenerating GraphQL schema... +@betterbase/cli:test: ◆ Generating GraphQL schema... +@betterbase/cli:test: ✓ GraphQL SDL written to src/lib/graphql/schema.graphql +@betterbase/cli:test: ✓ GraphQL server setup written to src/routes/graphql.ts +@betterbase/cli:test: ✓ GraphQL API generated at /api/graphql +@betterbase/cli:test: ◆ Run "bb graphql playground" to open the GraphQL Playground +@betterbase/cli:test: (pass) runGenerateCrudCommand > generated route contains GET /:id handler [6.00ms] +@betterbase/cli:test: ◆ Generating CRUD for posts... +@betterbase/cli:test: +@betterbase/cli:test: Generating CRUD for "posts" +@betterbase/cli:test: ───────────────────────────── +@betterbase/cli:test: ├─ src/routes/posts.ts +@betterbase/cli:test: └─ Updated src/routes/index.ts +@betterbase/cli:test: +@betterbase/cli:test: - Scanning schema... +@betterbase/cli:test: ✓ Found table posts +@betterbase/cli:test: +@betterbase/cli:test: +@betterbase/cli:test: Generated endpoints +@betterbase/cli:test: ───────────────────── +@betterbase/cli:test: GET /api/posts List all (paginated) +@betterbase/cli:test: GET /api/posts/:id Get single +@betterbase/cli:test: POST /api/posts Create +@betterbase/cli:test: - Writing route file... +@betterbase/cli:test: PATCH /api/posts/:id Update +@betterbase/cli:test: DELETE /api/posts/:id Delete +@betterbase/cli:test: ◆ Regenerating GraphQL schema... +@betterbase/cli:test: ◆ Generating GraphQL schema... +@betterbase/cli:test: ✓ Created src/routes/posts.ts +@betterbase/cli:test: - Updating router index... +@betterbase/cli:test: ✓ Router updated +@betterbase/cli:test: ✓ GraphQL SDL written to src/lib/graphql/schema.graphql +@betterbase/cli:test: ✓ GraphQL server setup written to src/routes/graphql.ts +@betterbase/cli:test: ✓ GraphQL API generated at /api/graphql +@betterbase/cli:test: ◆ Run "bb graphql playground" to open the GraphQL Playground +@betterbase/cli:test: (pass) runGenerateCrudCommand > generated route contains POST handler [16.00ms] +@betterbase/cli:test: ◆ Generating CRUD for posts... +@betterbase/cli:test: +@betterbase/cli:test: Generating CRUD for "posts" +@betterbase/cli:test: ───────────────────────────── +@betterbase/cli:test: ├─ src/routes/posts.ts +@betterbase/cli:test: └─ Updated src/routes/index.ts +@betterbase/cli:test: +@betterbase/cli:test: - Scanning schema... +@betterbase/core:test: [18:04:08.067] INFO: Preview storage bucket 'empty-bucket' has been cleaned up +@betterbase/core:test: bucket: "empty-bucket" +@betterbase/cli:test: ✓ Found table posts +@betterbase/cli:test: - Writing route file... +@betterbase/cli:test: ✓ Created src/routes/posts.ts +@betterbase/cli:test: - Updating router index... +@betterbase/cli:test: ✓ Router updated +@betterbase/cli:test: +@betterbase/cli:test: +@betterbase/cli:test: Generated endpoints +@betterbase/cli:test: ───────────────────── +@betterbase/cli:test: GET /api/posts List all (paginated) +@betterbase/cli:test: GET /api/posts/:id Get single +@betterbase/cli:test: POST /api/posts Create +@betterbase/cli:test: PATCH /api/posts/:id Update +@betterbase/cli:test: DELETE /api/posts/:id Delete +@betterbase/cli:test: ◆ Regenerating GraphQL schema... +@betterbase/cli:test: ◆ Generating GraphQL schema... +@betterbase/cli:test: ✓ GraphQL SDL written to src/lib/graphql/schema.graphql +@betterbase/cli:test: ✓ GraphQL server setup written to src/routes/graphql.ts +@betterbase/cli:test: ✓ GraphQL API generated at /api/graphql +@betterbase/cli:test: ◆ Run "bb graphql playground" to open the GraphQL Playground +@betterbase/cli:test: (pass) runGenerateCrudCommand > generated route contains PATCH handler [16.00ms] +@betterbase/core:test: [18:04:08.068] INFO: Preview storage bucket 'preview-bucket' has been cleaned up +@betterbase/core:test: bucket: "preview-bucket" +@betterbase/core:test: [18:04:08.111] WARN: Failed to initialize storage branching +@betterbase/core:test: err: { +@betterbase/core:test: "type": "Error", +@betterbase/core:test: "message": "Managed storage provider is coming soon. Please use s3, r2, backblaze, or minio.", +@betterbase/core:test: "stack": +@betterbase/core:test: Error: Managed storage provider is coming soon. Please use s3, r2, backblaze, or minio. +@betterbase/core:test: at resolveStorageAdapter (/workspaces/Betterbase/packages/core/src/storage/index.ts:103:13) +@betterbase/core:test: at new BranchManager (/workspaces/Betterbase/packages/core/src/branching/index.ts:69:28) +@betterbase/core:test: at createBranchManager (/workspaces/Betterbase/packages/core/src/branching/index.ts:455:13) +@betterbase/core:test: at (/workspaces/Betterbase/packages/core/test/branching.test.ts:1018:20) +@betterbase/core:test: } +@betterbase/core:test: [18:04:08.840] WARN: Invalid width parameter +@betterbase/core:test: value: "0" +@betterbase/core:test: validRange: "1-4000" +@betterbase/core:test: [18:04:08.840] WARN: Invalid width parameter +@betterbase/core:test: value: "5000" +@betterbase/core:test: validRange: "1-4000" +@betterbase/core:test: [18:04:08.840] WARN: Invalid width parameter +@betterbase/core:test: value: "-100" +@betterbase/core:test: validRange: "1-4000" +@betterbase/core:test: [18:04:08.841] WARN: Invalid height parameter +@betterbase/core:test: value: "0" +@betterbase/core:test: validRange: "1-4000" +@betterbase/core:test: [18:04:08.841] WARN: Invalid height parameter +@betterbase/core:test: value: "5000" +@betterbase/core:test: validRange: "1-4000" +@betterbase/core:test: [18:04:08.841] WARN: Invalid format parameter +@betterbase/core:test: value: "invalid" +@betterbase/core:test: validFormats: [ +@betterbase/core:test: "webp", +@betterbase/core:test: "jpeg", +@betterbase/core:test: "png", +@betterbase/core:test: "avif" +@betterbase/core:test: ] +@betterbase/core:test: [18:04:08.842] WARN: Invalid quality parameter +@betterbase/core:test: value: "0" +@betterbase/core:test: validRange: "1-100" +@betterbase/core:test: [18:04:08.843] WARN: Invalid quality parameter +@betterbase/core:test: value: "101" +@betterbase/core:test: validRange: "1-100" +@betterbase/core:test: [18:04:08.843] WARN: Invalid fit parameter +@betterbase/core:test: value: "invalid" +@betterbase/core:test: validFits: [ +@betterbase/core:test: "cover", +@betterbase/core:test: "contain", +@betterbase/core:test: "fill", +@betterbase/core:test: "inside", +@betterbase/core:test: "outside" +@betterbase/core:test: ] +@betterbase/core:test: [18:04:08.843] WARN: Invalid width parameter +@betterbase/core:test: value: "abc" +@betterbase/core:test: validRange: "1-4000" +@betterbase/cli:test: ◆ Generating CRUD for posts... +@betterbase/cli:test: +@betterbase/cli:test: Generating CRUD for "posts" +@betterbase/cli:test: ───────────────────────────── +@betterbase/cli:test: ├─ src/routes/posts.ts +@betterbase/cli:test: └─ Updated src/routes/index.ts +@betterbase/cli:test: +@betterbase/cli:test: - Scanning schema... +@betterbase/cli:test: ✓ Found table posts +@betterbase/cli:test: - Writing route file... +@betterbase/cli:test: ✓ Created src/routes/posts.ts +@betterbase/cli:test: +@betterbase/cli:test: +@betterbase/cli:test: - Updating router index... +@betterbase/cli:test: Generated endpoints +@betterbase/cli:test: ───────────────────── +@betterbase/cli:test: GET /api/posts List all (paginated) +@betterbase/cli:test: GET /api/posts/:id Get single +@betterbase/cli:test: POST /api/posts Create +@betterbase/cli:test: PATCH /api/posts/:id Update +@betterbase/cli:test: ✓ Router updated +@betterbase/cli:test: DELETE /api/posts/:id Delete +@betterbase/cli:test: ◆ Regenerating GraphQL schema... +@betterbase/cli:test: ◆ Generating GraphQL schema... +@betterbase/cli:test: ✓ GraphQL SDL written to src/lib/graphql/schema.graphql +@betterbase/cli:test: ✓ GraphQL server setup written to src/routes/graphql.ts +@betterbase/cli:test: ✓ GraphQL API generated at /api/graphql +@betterbase/cli:test: ◆ Run "bb graphql playground" to open the GraphQL Playground +@betterbase/cli:test: (pass) runGenerateCrudCommand > generated route contains DELETE handler [14.00ms] +@betterbase/cli:test: ◆ Generating CRUD for posts... +@betterbase/cli:test: +@betterbase/cli:test: Generating CRUD for "posts" +@betterbase/cli:test: ───────────────────────────── +@betterbase/cli:test: ├─ src/routes/posts.ts +@betterbase/cli:test: └─ Updated src/routes/index.ts +@betterbase/cli:test: +@betterbase/cli:test: - Scanning schema... +@betterbase/cli:test: ✓ Found table posts +@betterbase/cli:test: - Writing route file... +@betterbase/cli:test: ✓ Created src/routes/posts.ts +@betterbase/cli:test: - Updating router index... +@betterbase/cli:test: ✓ Router updated +@betterbase/cli:test: +@betterbase/cli:test: +@betterbase/cli:test: Generated endpoints +@betterbase/cli:test: ───────────────────── +@betterbase/cli:test: GET /api/posts List all (paginated) +@betterbase/cli:test: GET /api/posts/:id Get single +@betterbase/cli:test: POST /api/posts Create +@betterbase/cli:test: PATCH /api/posts/:id Update +@betterbase/cli:test: DELETE /api/posts/:id Delete +@betterbase/cli:test: ◆ Regenerating GraphQL schema... +@betterbase/cli:test: ◆ Generating GraphQL schema... +@betterbase/cli:test: ✓ GraphQL SDL written to src/lib/graphql/schema.graphql +@betterbase/cli:test: ✓ GraphQL server setup written to src/routes/graphql.ts +@betterbase/cli:test: ✓ GraphQL API generated at /api/graphql +@betterbase/cli:test: ◆ Run "bb graphql playground" to open the GraphQL Playground +@betterbase/cli:test: (pass) runGenerateCrudCommand > generated route imports Zod and uses zValidator [12.00ms] +@betterbase/cli:test: ◆ Generating CRUD for posts... +@betterbase/cli:test: +@betterbase/cli:test: Generating CRUD for "posts" +@betterbase/cli:test: ───────────────────────────── +@betterbase/cli:test: ├─ src/routes/posts.ts +@betterbase/cli:test: └─ Updated src/routes/index.ts +@betterbase/cli:test: +@betterbase/cli:test: - Scanning schema... +@betterbase/cli:test: ✓ Found table posts +@betterbase/cli:test: - Writing route file... +@betterbase/core:test: (pass) providers/types > ProviderConfigSchema > validates a valid Neon provider config [1.00ms] +@betterbase/cli:test: ✓ Created src/routes/posts.ts +@betterbase/core:test: (pass) providers/types > ProviderConfigSchema > validates a valid Turso provider config +@betterbase/cli:test: - Updating router index... +@betterbase/cli:test: +@betterbase/cli:test: +@betterbase/cli:test: Generated endpoints +@betterbase/cli:test: ✓ Router updated +@betterbase/cli:test: ───────────────────── +@betterbase/cli:test: GET /api/posts List all (paginated) +@betterbase/cli:test: GET /api/posts/:id Get single +@betterbase/cli:test: POST /api/posts Create +@betterbase/cli:test: PATCH /api/posts/:id Update +@betterbase/cli:test: DELETE /api/posts/:id Delete +@betterbase/cli:test: ◆ Regenerating GraphQL schema... +@betterbase/cli:test: ◆ Generating GraphQL schema... +@betterbase/cli:test: ✓ GraphQL SDL written to src/lib/graphql/schema.graphql +@betterbase/cli:test: ✓ GraphQL server setup written to src/routes/graphql.ts +@betterbase/cli:test: ✓ GraphQL API generated at /api/graphql +@betterbase/cli:test: ◆ Run "bb graphql playground" to open the GraphQL Playground +@betterbase/core:test: (pass) providers/types > ProviderConfigSchema > validates a valid PlanetScale provider config [1.00ms] +@betterbase/core:test: (pass) providers/types > ProviderConfigSchema > validates a valid Supabase provider config +@betterbase/core:test: (pass) providers/types > ProviderConfigSchema > validates a valid Postgres provider config +@betterbase/core:test: (pass) providers/types > ProviderConfigSchema > validates a managed provider config (no required fields) +@betterbase/core:test: (pass) providers/types > ProviderConfigSchema > rejects invalid provider type +@betterbase/core:test: (pass) providers/types > ProviderConfigSchema > rejects Neon config without connectionString +@betterbase/core:test: (pass) providers/types > ProviderConfigSchema > rejects Turso config without url +@betterbase/core:test: (pass) providers/types > ProviderConfigSchema > rejects Turso config without authToken [1.00ms] +@betterbase/core:test: (pass) providers/types > NeonProviderConfigSchema > validates valid Neon config +@betterbase/core:test: (pass) providers/types > NeonProviderConfigSchema > rejects wrong type +@betterbase/core:test: (pass) providers/types > TursoProviderConfigSchema > validates valid Turso config +@betterbase/core:test: (pass) providers/types > PlanetScaleProviderConfigSchema > validates valid PlanetScale config +@betterbase/core:test: (pass) providers/types > SupabaseProviderConfigSchema > validates valid Supabase config +@betterbase/core:test: (pass) providers/types > PostgresProviderConfigSchema > validates valid Postgres config +@betterbase/core:test: (pass) providers/types > ManagedProviderConfigSchema > validates managed config with just type +@betterbase/core:test: (pass) providers/types > isValidProviderConfig > returns true for valid config [2.00ms] +@betterbase/core:test: (pass) providers/types > isValidProviderConfig > returns false for invalid config [1.00ms] +@betterbase/core:test: (pass) providers/types > parseProviderConfig > parses valid config +@betterbase/core:test: (pass) providers/types > parseProviderConfig > throws on invalid config [1.00ms] +@betterbase/core:test: (pass) providers/types > safeParseProviderConfig > returns success for valid config +@betterbase/core:test: (pass) providers/types > safeParseProviderConfig > returns error for invalid config +@betterbase/core:test: (pass) providers/index > getSupportedProviders > returns all supported providers except managed +@betterbase/core:test: (pass) providers/index > providerSupportsRLS > returns true for PostgreSQL-based providers +@betterbase/core:test: (pass) providers/index > providerSupportsRLS > returns false for SQLite and MySQL providers +@betterbase/core:test: (pass) providers/index > providerSupportsRLS > returns true for managed provider +@betterbase/core:test: (pass) providers/index > getProviderDialect > returns postgres for PostgreSQL-based providers +@betterbase/core:test: (pass) providers/index > getProviderDialect > returns mysql for PlanetScale +@betterbase/core:test: (pass) providers/index > getProviderDialect > returns sqlite for Turso +@betterbase/core:test: (pass) providers/index > getProviderDialect > throws for managed provider +@betterbase/cli:test: (pass) runGenerateCrudCommand > generated route includes pagination schema [16.00ms] +@betterbase/core:test: (pass) providers/index > resolveProvider > resolves Neon provider config [2.00ms] +@betterbase/core:test: (pass) providers/index > resolveProvider > resolves Postgres provider config [1.00ms] +@betterbase/core:test: (pass) providers/index > resolveProvider > resolves Supabase provider config +@betterbase/cli:test: ◆ Generating CRUD for posts... +@betterbase/core:test: (pass) providers/index > resolveProvider > resolves Turso provider config +@betterbase/cli:test: +@betterbase/core:test: (pass) providers/index > resolveProvider > resolves PlanetScale provider config [1.00ms] +@betterbase/cli:test: Generating CRUD for "posts" +@betterbase/core:test: (pass) providers/index > resolveProvider > throws for managed provider +@betterbase/cli:test: ───────────────────────────── +@betterbase/cli:test: ├─ src/routes/posts.ts +@betterbase/cli:test: └─ Updated src/routes/index.ts +@betterbase/cli:test: +@betterbase/core:test: (pass) providers/index > resolveProviderByType > resolves Neon by type string +@betterbase/core:test: (pass) providers/index > resolveProviderByType > resolves Postgres by type string +@betterbase/core:test: (pass) providers/index > resolveProviderByType > resolves Supabase by type string +@betterbase/core:test: (pass) providers/index > resolveProviderByType > resolves Turso by type string +@betterbase/core:test: (pass) providers/index > resolveProviderByType > resolves PlanetScale by type string +@betterbase/core:test: (pass) providers/index > resolveProviderByType > throws for managed provider +@betterbase/core:test: (pass) providers/index > ManagedProviderNotSupportedError > has correct message +@betterbase/core:test: (pass) NeonProviderAdapter > constructor > creates adapter with correct type and dialect +@betterbase/core:test: (pass) NeonProviderAdapter > connect > validates config type +@betterbase/cli:test: - Scanning schema... +@betterbase/core:test: (pass) NeonProviderAdapter > connect > creates connection on valid config [1.00ms] +@betterbase/core:test: (pass) NeonProviderAdapter > supportsRLS > returns true +@betterbase/core:test: (pass) NeonProviderAdapter > supportsGraphQL > returns true +@betterbase/core:test: (pass) NeonProviderAdapter > getMigrationsDriver > throws if not connected first +@betterbase/cli:test: ✓ Found table posts +@betterbase/cli:test: - Writing route file... +@betterbase/cli:test: ✓ Created src/routes/posts.ts +@betterbase/cli:test: - Updating router index... +@betterbase/core:test: (pass) NeonProviderAdapter > getMigrationsDriver > returns driver after connection [1.00ms] +@betterbase/cli:test: ✓ Router updated +@betterbase/cli:test: +@betterbase/cli:test: +@betterbase/cli:test: Generated endpoints +@betterbase/cli:test: ───────────────────── +@betterbase/cli:test: GET /api/posts List all (paginated) +@betterbase/cli:test: GET /api/posts/:id Get single +@betterbase/cli:test: POST /api/posts Create +@betterbase/cli:test: PATCH /api/posts/:id Update +@betterbase/cli:test: DELETE /api/posts/:id Delete +@betterbase/cli:test: ◆ Regenerating GraphQL schema... +@betterbase/cli:test: ◆ Generating GraphQL schema... +@betterbase/cli:test: ✓ GraphQL SDL written to src/lib/graphql/schema.graphql +@betterbase/cli:test: ✓ GraphQL server setup written to src/routes/graphql.ts +@betterbase/cli:test: ✓ GraphQL API generated at /api/graphql +@betterbase/cli:test: ◆ Run "bb graphql playground" to open the GraphQL Playground +@betterbase/core:test: (pass) PostgresProviderAdapter > constructor > creates adapter with correct type and dialect +@betterbase/core:test: (pass) PostgresProviderAdapter > connect > validates config type +@betterbase/core:test: (pass) PostgresProviderAdapter > supportsRLS > returns true +@betterbase/core:test: (pass) SupabaseProviderAdapter > constructor > creates adapter with correct type and dialect +@betterbase/core:test: (pass) SupabaseProviderAdapter > connect > validates config type [1.00ms] +@betterbase/core:test: (pass) SupabaseProviderAdapter > supportsRLS > returns true +@betterbase/cli:test: (pass) runGenerateCrudCommand > generated route broadcasts realtime events [8.00ms] +@betterbase/core:test: (pass) TursoProviderAdapter > constructor > creates adapter with correct type and dialect +@betterbase/core:test: (pass) TursoProviderAdapter > connect > validates config type [1.00ms] +@betterbase/core:test: (pass) TursoProviderAdapter > connect > validates url is provided +@betterbase/cli:test: ◆ Generating CRUD for posts... +@betterbase/cli:test: +@betterbase/cli:test: Generating CRUD for "posts" +@betterbase/cli:test: ───────────────────────────── +@betterbase/cli:test: ├─ src/routes/posts.ts +@betterbase/cli:test: └─ Updated src/routes/index.ts +@betterbase/cli:test: +@betterbase/cli:test: - Scanning schema... +@betterbase/cli:test: +@betterbase/cli:test: +@betterbase/cli:test: Generated endpoints +@betterbase/cli:test: ───────────────────── +@betterbase/cli:test: GET /api/posts List all (paginated) +@betterbase/cli:test: GET /api/posts/:id Get single +@betterbase/cli:test: POST /api/posts Create +@betterbase/cli:test: PATCH /api/posts/:id Update +@betterbase/cli:test: DELETE /api/posts/:id Delete +@betterbase/cli:test: ◆ Regenerating GraphQL schema... +@betterbase/cli:test: ◆ Generating GraphQL schema... +@betterbase/cli:test: ✓ GraphQL SDL written to src/lib/graphql/schema.graphql +@betterbase/cli:test: ✓ GraphQL server setup written to src/routes/graphql.ts +@betterbase/cli:test: ✓ Found table posts +@betterbase/cli:test: - Writing route file... +@betterbase/cli:test: ✓ GraphQL API generated at /api/graphql +@betterbase/cli:test: ◆ Run "bb graphql playground" to open the GraphQL Playground +@betterbase/cli:test: ✓ Created src/routes/posts.ts +@betterbase/cli:test: - Updating router index... +@betterbase/cli:test: ✓ Router updated +@betterbase/core:test: (pass) TursoProviderAdapter > connect > validates authToken is provided [1.00ms] +@betterbase/core:test: (pass) TursoProviderAdapter > supportsRLS > returns false for SQLite +@betterbase/core:test: (pass) TursoProviderAdapter > supportsGraphQL > returns false for SQLite +@betterbase/core:test: (pass) PlanetScaleProviderAdapter > constructor > creates adapter with correct type and dialect +@betterbase/core:test: (pass) PlanetScaleProviderAdapter > connect > validates config type +@betterbase/core:test: (pass) PlanetScaleProviderAdapter > supportsRLS > returns false for MySQL +@betterbase/core:test: +@betterbase/core:test: test/chain-code-maps.test.ts: +@betterbase/cli:test: (pass) runGenerateCrudCommand > updates src/routes/index.ts to register the new route [7.00ms] +@betterbase/cli:test: ◆ Generating CRUD for nonexistent_table_xyz... +@betterbase/cli:test: +@betterbase/cli:test: Generating CRUD for "nonexistent_table_xyz" +@betterbase/cli:test: ───────────────────────────────────────────── +@betterbase/cli:test: ├─ src/routes/nonexistent_table_xyz.ts +@betterbase/cli:test: └─ Updated src/routes/index.ts +@betterbase/cli:test: +@betterbase/cli:test: - Scanning schema... +@betterbase/cli:test: ✓ Found table nonexistent_table_xyz +@betterbase/cli:test: (pass) runGenerateCrudCommand > throws for a table that does not exist in the schema [4.00ms] +@betterbase/cli:test: (pass) runGenerateCrudCommand > throws when schema file does not exist [1.00ms] +@betterbase/cli:test: +@betterbase/cli:test: test/auth-command.test.ts: +@betterbase/core:test: (pass) Chain Code Maps - columnMap > getColumnTypeName > should map varchar constructor to varchar type [1.00ms] +@betterbase/core:test: (pass) Chain Code Maps - columnMap > getColumnTypeName > should map text constructor to text type [1.00ms] +@betterbase/core:test: (pass) Chain Code Maps - columnMap > getColumnTypeName > should map integer constructor to integer type +@betterbase/core:test: (pass) Chain Code Maps - columnMap > getColumnTypeName > should map boolean constructor to boolean type +@betterbase/core:test: (pass) Chain Code Maps - columnMap > getColumnTypeName > should map timestamp constructor to timestamp type +@betterbase/core:test: (pass) Chain Code Maps - columnMap > getColumnTypeName > should map uuid constructor to uuid type +@betterbase/core:test: (pass) Chain Code Maps - columnMap > getColumnTypeName > should map json constructor to json type +@betterbase/core:test: (pass) Chain Code Maps - columnMap > getColumnTypeName > should map jsonb constructor to jsonb type (falls to json) +@betterbase/core:test: (pass) Chain Code Maps - columnMap > getColumnTypeName > should map real constructor to real type +@betterbase/core:test: (pass) Chain Code Maps - columnMap > getColumnTypeName > should map double constructor to double type +@betterbase/core:test: (pass) Chain Code Maps - columnMap > getColumnTypeName > should map numeric constructor to numeric type +@betterbase/core:test: (pass) Chain Code Maps - columnMap > getColumnTypeName > should return text as default for unknown constructor +@betterbase/core:test: (pass) Chain Code Maps - columnMap > getColumnTypeName > should handle case-insensitive constructor names +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > integer types > should map integer to Int +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > integer types > should map serial to Int (falls through to text, then to String) +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > integer types > should map smallint to Int (falls through) +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > integer types > should map bigint to Int (falls through) +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > string types > should map varchar to String +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > string types > should map text to String [1.00ms] +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > string types > should map char to String +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > boolean types > should map boolean to Boolean +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > boolean types > should map bool to Boolean (falls through) +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > uuid types > should map uuid to ID +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > timestamp/date types > should map timestamp to DateTime +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > timestamp/date types > should map date to DateTime (falls through) +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > json types > should map json to JSON +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > json types > should map jsonb to JSON +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > numeric types > should map real to String +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > numeric types > should map double to String +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > numeric types > should map numeric to String +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > numeric types > should map decimal to String +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > mode-based type mapping > should map timestamp mode to DateTime +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > mode-based type mapping > should map json mode to JSON +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > mode-based type mapping > should map jsonb mode to JSON +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > mode-based type mapping > should map boolean mode to Boolean +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > default types > should default to String for unknown types +@betterbase/core:test: (pass) Chain Code Maps - getGraphQLType > default types > should default to String when constructor name is empty +@betterbase/core:test: (pass) Chain Code Maps - Integration > should correctly map a complete user table schema +@betterbase/core:test: (pass) Chain Code Maps - Integration > should correctly map a complete post table schema +@betterbase/core:test: (pass) Chain Code Maps - Integration > should handle all PostgreSQL column types +@betterbase/core:test: (pass) Chain Code Maps - Integration > should handle all SQLite column types +@betterbase/core:test: (pass) Chain Code Maps - Integration > should handle all MySQL column types [1.00ms] +@betterbase/core:test: +@betterbase/core:test: test/middleware-functions.test.ts: +@betterbase/core:test: (pass) Middleware Functions > requestLogger > should be a function +@betterbase/core:test: (pass) Middleware Functions > requestLogger > should log incoming requests +@betterbase/core:test: (pass) Middleware Functions > requestLogger > should log response status +@betterbase/core:test: (pass) Middleware Functions > requestLogger > should log request duration +@betterbase/core:test: (pass) Middleware Functions > requestLogger > should include request metadata +@betterbase/core:test: (pass) Middleware Functions > requestLogger > should handle errors gracefully +@betterbase/core:test: (pass) Request Logger Stubs > should have placeholder for logging +@betterbase/core:test: (pass) Request Logger Stubs > should have placeholder for duration +@betterbase/core:test: (pass) Request Logger Stubs > should have placeholder for metadata +@betterbase/core:test: +@betterbase/core:test: test/functions-runtime.test.ts: +@betterbase/core:test: (pass) Functions Runtime > LocalFunctionsRuntime > should initialize functions runtime +@betterbase/core:test: (pass) Functions Runtime > LocalFunctionsRuntime > should load function definitions +@betterbase/core:test: (pass) Functions Runtime > LocalFunctionsRuntime > should execute function code +@betterbase/core:test: (pass) Functions Runtime > LocalFunctionsRuntime > should handle function errors +@betterbase/core:test: (pass) Functions Runtime > LocalFunctionsRuntime > should manage function lifecycle +@betterbase/core:test: (pass) Functions Runtime > LocalFunctionsRuntime > should handle timeouts +@betterbase/core:test: (pass) Functions Runtime > LocalFunctionsRuntime > should handle memory limits +@betterbase/core:test: (pass) Functions Runtime > createFunctionsMiddleware > should create middleware for functions +@betterbase/core:test: (pass) Functions Runtime > createFunctionsMiddleware > should route requests to functions +@betterbase/core:test: (pass) Functions Runtime > createFunctionsMiddleware > should handle function responses +@betterbase/core:test: (pass) Functions Runtime > initializeFunctionsRuntime > should initialize the runtime +@betterbase/core:test: (pass) Functions Runtime > initializeFunctionsRuntime > should load all functions +@betterbase/core:test: (pass) Functions Runtime > initializeFunctionsRuntime > should setup execution environment +@betterbase/core:test: (pass) Functions Runtime Stubs > should have placeholder for initialization [2.00ms] +@betterbase/core:test: (pass) Functions Runtime Stubs > should have placeholder for execution +@betterbase/core:test: (pass) Functions Runtime Stubs > should have placeholder for lifecycle +@betterbase/core:test: +@betterbase/core:test: test/storage-policy-engine.test.ts: +@betterbase/cli:test: ◆ 🔐 Setting up BetterAuth... +@betterbase/cli:test: ◆ 📦 Installing better-auth... +@betterbase/core:test: (pass) Storage Policy Engine > defineStoragePolicy > should create policy with bucket, operation, and expression +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - true expression > should allow upload when policy is 'true' with authenticated user +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - true expression > should allow upload when policy is 'true' with anonymous user +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - true expression > should allow download when policy is 'true' +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - true expression > should allow different bucket operations +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - false expression > should deny upload when policy is 'false' +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - false expression > should deny download when policy is 'false' +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - false expression > should deny with anonymous user when policy is 'false' +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - path.startsWith expression > should allow when path starts with prefix [1.00ms] +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - path.startsWith expression > should allow for nested paths starting with prefix +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - path.startsWith expression > should deny when path does not start with prefix +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - path.startsWith expression > should work for download operations +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - path.startsWith expression > should deny download for non-prefix paths +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - auth.uid() = path.split() expression > should allow when userId matches first path segment +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - auth.uid() = path.split() expression > should deny when userId does not match first path segment +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - auth.uid() = path.split() expression > should deny when userId is null (anonymous) +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - auth.uid() = path.split() expression > should work with longer paths +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - auth.uid() = path.split with delimiter > should allow when userId matches second path segment +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - auth.uid() = path.split with delimiter > should deny when userId does not match second segment [1.00ms] +@betterbase/core:test: [Storage Policy] No policy found for unknown-bucket/upload, denying by default +@betterbase/core:test: [Storage Policy] No policy found for avatars/delete, denying by default +@betterbase/core:test: [Storage Policy] No policy found for files/list, denying by default +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - auth.uid() = path.split with delimiter > should deny when userId is null +@betterbase/core:test: [Storage Policy] No policy found for files/list, denying by default +@betterbase/core:test: [Storage Policy] No policy found for files/delete, denying by default +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - wildcard operation > should allow upload with wildcard policy +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - wildcard operation > should allow download with wildcard policy +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - wildcard operation > should allow list with wildcard policy +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - wildcard operation > should allow delete with wildcard policy +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - wildcard operation > should allow with anonymous user +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - no matching policies > should deny when no policy matches the bucket +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - no matching policies > should deny when no policy matches the operation +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - no matching policies > should deny when bucket and operation don't match +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - multiple policies > should allow if any policy matches (public path) +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - multiple policies > should allow if any policy matches (user path) +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - multiple policies > should deny if no policy matches +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - list operation > should allow list operation with 'true' policy +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - list operation > should allow list with path prefix +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - list operation > should deny list without matching policy +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - delete operation > should allow delete operation with 'true' policy +@betterbase/core:test: (pass) Storage Policy Engine > checkStorageAccess - delete operation > should deny delete without matching policy +@betterbase/core:test: (pass) Storage Policy Engine > getPolicyDenialMessage > should return message for upload operation +@betterbase/core:test: (pass) Storage Policy Engine > getPolicyDenialMessage > should return message for download operation +@betterbase/core:test: (pass) Storage Policy Engine > getPolicyDenialMessage > should return message for list operation +@betterbase/core:test: (pass) Storage Policy Engine > getPolicyDenialMessage > should return message for delete operation +@betterbase/core:test: (pass) Storage Policy Engine > Edge cases > should handle empty path +@betterbase/core:test: (pass) Storage Policy Engine > Edge cases > should handle paths with special characters [1.00ms] +@betterbase/core:test: (pass) Storage Policy Engine > Edge cases > should handle very long paths +@betterbase/core:test: (pass) Storage Policy Engine > Edge cases > should handle bucket names with special characters +@betterbase/core:test: +@betterbase/core:test: test/auto-rest-functions.test.ts: +@betterbase/cli:test: bun add v1.3.13 (bf2e2cec) +@betterbase/core:test: (pass) Auto-REST Functions > QUERY_OPERATORS > should define equals operator +@betterbase/core:test: (pass) Auto-REST Functions > QUERY_OPERATORS > should define not equals operator +@betterbase/core:test: (pass) Auto-REST Functions > QUERY_OPERATORS > should define greater than operator +@betterbase/core:test: (pass) Auto-REST Functions > QUERY_OPERATORS > should define less than operator +@betterbase/core:test: (pass) Auto-REST Functions > QUERY_OPERATORS > should define like operator +@betterbase/core:test: (pass) Auto-REST Functions > QUERY_OPERATORS > should define in operator +@betterbase/core:test: (pass) Auto-REST Functions > mountAutoRest > should mount auto-rest routes +@betterbase/core:test: (pass) Auto-REST Functions > mountAutoRest > should register CRUD endpoints +@betterbase/core:test: (pass) Auto-REST Functions > mountAutoRest > should handle table definitions +@betterbase/core:test: (pass) Auto-REST Functions > mountAutoRest > should apply RLS policies +@betterbase/core:test: (pass) Auto-REST Functions > mountAutoRest > should handle query parameters +@betterbase/core:test: (pass) Auto-REST Functions > mountAutoRest > should handle pagination +@betterbase/core:test: (pass) Auto-REST Functions > mountAutoRest > should handle sorting +@betterbase/core:test: (pass) Auto-REST Functions > mountAutoRest > should handle filtering +@betterbase/core:test: (pass) Auto-REST Stubs > should have placeholder for operators +@betterbase/core:test: (pass) Auto-REST Stubs > should have placeholder for CRUD +@betterbase/core:test: (pass) Auto-REST Stubs > should have placeholder for pagination [1.00ms] +@betterbase/core:test: +@betterbase/core:test: test/iac.test.ts: +@betterbase/cli:test: Resolving dependencies +@betterbase/core:test: (pass) IAC Validators (v.*) > v.string() returns ZodString +@betterbase/core:test: (pass) IAC Validators (v.*) > v.number() returns ZodNumber +@betterbase/core:test: (pass) IAC Validators (v.*) > v.boolean() returns ZodBoolean [1.00ms] +@betterbase/core:test: (pass) IAC Validators (v.*) > v.null() returns ZodNull +@betterbase/core:test: (pass) IAC Validators (v.*) > v.int64() returns ZodBigInt +@betterbase/core:test: (pass) IAC Validators (v.*) > v.any() returns ZodAny [1.00ms] +@betterbase/core:test: (pass) IAC Validators (v.*) > v.optional() wraps a validator +@betterbase/core:test: (pass) IAC Validators (v.*) > v.array() creates array schema +@betterbase/core:test: (pass) IAC Validators (v.*) > v.object() creates object schema +@betterbase/core:test: (pass) IAC Validators (v.*) > v.union() creates union schema [1.00ms] +@betterbase/core:test: (pass) IAC Validators (v.*) > v.literal() creates literal schema +@betterbase/core:test: (pass) IAC Validators (v.*) > v.id() creates branded ID type +@betterbase/core:test: (pass) IAC Validators (v.*) > v.datetime() creates datetime schema +@betterbase/core:test: (pass) IAC Validators (v.*) > v.bytes() creates base64 schema [1.00ms] +@betterbase/core:test: (pass) IAC Validators (v.*) > Infer type helper works +@betterbase/core:test: (pass) IAC Schema (defineTable) > defineTable creates table with system fields +@betterbase/core:test: (pass) IAC Schema (defineTable) > defineTable adds index +@betterbase/core:test: (pass) IAC Schema (defineTable) > defineTable adds uniqueIndex +@betterbase/core:test: (pass) IAC Schema (defineTable) > defineTable adds searchIndex +@betterbase/core:test: (pass) IAC Schema (defineTable) > defineTable is chainable [1.00ms] +@betterbase/core:test: (pass) IAC Schema (defineSchema) > defineSchema creates schema definition +@betterbase/core:test: (pass) IAC Schema (defineSchema) > InferSchema produces document types +@betterbase/core:test: (pass) IAC Schema (defineSchema) > Doc type extracts specific table +@betterbase/core:test: (pass) IAC Schema (defineSchema) > TableNames extracts table names [1.00ms] +@betterbase/core:test: (pass) Schema Serializer > serializeSchema produces JSON-serializable output +@betterbase/core:test: (pass) Schema Serializer > serializeSchema marks system fields +@betterbase/core:test: (pass) Schema Serializer > serializeSchema handles v.id() as id:type +@betterbase/core:test: (pass) Schema Serializer > serializeSchema handles v.optional() [1.00ms] +@betterbase/core:test: (pass) Schema Diff Engine > diffSchemas from null produces ADD_TABLE for each table +@betterbase/core:test: (pass) Schema Diff Engine > diffSchemas identical schemas produces empty diff +@betterbase/core:test: (pass) Schema Diff Engine > diffSchemas detects ADD_COLUMN [1.00ms] +@betterbase/core:test: (pass) Schema Diff Engine > diffSchemas detects DROP_COLUMN as destructive +@betterbase/core:test: (pass) Schema Diff Engine > diffSchemas detects ALTER_COLUMN as potentially destructive +@betterbase/core:test: (pass) Schema Diff Engine > diffSchemas detects ADD_INDEX [1.00ms] +@betterbase/core:test: (pass) Schema Diff Engine > formatDiff produces human-readable output +@betterbase/core:test: (pass) Function Primitives (query, mutation, action) > query creates query registration +@betterbase/core:test: (pass) Function Primitives (query, mutation, action) > mutation creates mutation registration +@betterbase/core:test: (pass) Function Primitives (query, mutation, action) > action creates action registration +@betterbase/core:test: (pass) Function Primitives (query, mutation, action) > query validates args [1.00ms] +@betterbase/core:test: (pass) Function Primitives (query, mutation, action) > query rejects invalid args +@betterbase/core:test: (pass) DatabaseReader > DatabaseReader has get and query methods +@betterbase/core:test: (pass) DatabaseWriter > DatabaseWriter extends DatabaseReader +@betterbase/core:test: (pass) Function Registry > setFunctionRegistry and getFunctionRegistry +@betterbase/core:test: (pass) Function Registry > lookupFunction finds registered function +@betterbase/core:test: (pass) Function Registry > lookupFunction returns null for unknown path +@betterbase/core:test: (pass) Cron Jobs > cron registers a job +@betterbase/core:test: (pass) Drizzle Schema Generator > generateDrizzleSchema produces valid code [1.00ms] +@betterbase/core:test: (pass) Drizzle Schema Generator > generateDrizzleSchema supports postgres dialect +@betterbase/core:test: (pass) Migration Generator > generateMigration produces valid SQL +@betterbase/core:test: (pass) Migration Generator > generateMigration handles ADD_COLUMN +@betterbase/core:test: (pass) API Type Generator > generateApiTypes produces declaration file [1.00ms] +@betterbase/core:test: (pass) API Type Generator > generateApiTypes groups by kind and file +@betterbase/core:test: +@betterbase/core:test: test/storage.test.ts: +@betterbase/core:test: (pass) Storage Module > createStorage > should return null for null config +@betterbase/core:test: (pass) Storage Module > createStorage > should return null for undefined config [1.00ms] +@betterbase/core:test: (pass) Storage Module > createStorage > should return StorageFactory for valid S3 config [3.00ms] +@betterbase/core:test: (pass) Storage Module > createStorage > should return StorageFactory for valid R2 config [1.00ms] +@betterbase/core:test: (pass) Storage Module > createStorage > should return StorageFactory for valid Backblaze config [1.00ms] +@betterbase/core:test: (pass) Storage Module > createStorage > should return StorageFactory for valid MinIO config +@betterbase/core:test: (pass) Storage Module > createStorage > should throw error for managed provider +@betterbase/core:test: (pass) Storage Module > StorageFactory.from() > should return BucketClient with from() method [1.00ms] +@betterbase/core:test: (pass) Storage Module > StorageFactory.from() > should return BucketClient with all required methods +@betterbase/core:test: (pass) Storage Module > resolveStorageAdapter > should resolve S3 adapter for s3 provider [1.00ms] +@betterbase/core:test: (pass) Storage Module > resolveStorageAdapter > should resolve adapter for R2 provider +@betterbase/core:test: (pass) Storage Module > resolveStorageAdapter > should throw error for managed provider +@betterbase/core:test: (pass) Storage Module > Storage class > should create Storage instance with adapter [1.00ms] +@betterbase/core:test: (pass) Storage Module > Storage class > should return BucketClient from from() [1.00ms] +@betterbase/core:test: (pass) Storage Module > BucketClient operations > BucketClient should have upload method [2.00ms] +@betterbase/core:test: (pass) Storage Module > BucketClient operations > BucketClient should have download method +@betterbase/core:test: (pass) Storage Module > BucketClient operations > BucketClient should have remove method [1.00ms] +@betterbase/core:test: (pass) Storage Module > BucketClient operations > BucketClient should have getPublicUrl method +@betterbase/core:test: (pass) Storage Module > BucketClient operations > BucketClient should have createSignedUrl method [1.00ms] +@betterbase/core:test: (pass) Storage Module > BucketClient operations > BucketClient should have list method +@betterbase/core:test: (pass) Storage Module > Type exports > should export StorageConfig type [1.00ms] +@betterbase/core:test: (pass) Storage Module > Type exports > should export StorageFactory interface +@betterbase/core:test: (pass) Storage Module > Type exports > should export BucketClient interface +@betterbase/core:test: (pass) Storage Module > Multiple buckets > should create multiple bucket clients from same storage +@betterbase/core:test: (pass) Storage Module > Edge cases > should handle empty bucket name [1.00ms] +@betterbase/core:test: (pass) Storage Module > Edge cases > should handle bucket name with special characters +@betterbase/core:test: +@betterbase/core:test: test/graphql-server.test.ts: +@betterbase/core:test: (pass) GraphQL Server > createGraphQLServer > should create server with required config [9.00ms] +@betterbase/core:test: (pass) GraphQL Server > createGraphQLServer > should create server with custom path [3.00ms] +@betterbase/core:test: (pass) GraphQL Server > createGraphQLServer > should create server with auth disabled [1.00ms] +@betterbase/core:test: (pass) GraphQL Server > createGraphQLServer > should create server with playground disabled [2.00ms] +@betterbase/core:test: (pass) GraphQL Server > createGraphQLServer > should create server with custom getUser function [2.00ms] +@betterbase/core:test: (pass) GraphQL Server > createGraphQLServer > should create server with yoga options [1.00ms] +@betterbase/core:test: (pass) GraphQL Server > startGraphQLServer > should be a function [1.00ms] +@betterbase/core:test: (pass) GraphQL Server > GraphQLConfig type > should accept minimal config +@betterbase/core:test: (pass) GraphQL Server > GraphQLConfig type > should accept all optional config [1.00ms] +@betterbase/core:test: (pass) GraphQL Server > server structure > should return app with route method [2.00ms] +@betterbase/core:test: (pass) GraphQL Server > server structure > should return yoga server instance [1.00ms] +@betterbase/core:test: (pass) GraphQL Server > server structure > should return HTTP server [1.00ms] +@betterbase/core:test: (pass) GraphQL Server > default configuration > should use default path when not provided [1.00ms] +@betterbase/core:test: +@betterbase/core:test: test/migration.test.ts: +@betterbase/core:test: (pass) migration/index > runMigration > warns when provider does not support RLS [1.00ms] +@betterbase/core:test: (pass) migration/index > runMigration > logs info when no policies found +@betterbase/core:test: (pass) migration/index > runMigration > applies policies when RLS is supported [1.00ms] +@betterbase/core:test: (pass) migration/index > runMigration > warns about policy loading errors +@betterbase/core:test: (pass) migration/index > isRLSSupported > returns true for provider that supports RLS +@betterbase/core:test: (pass) migration/index > isRLSSupported > returns false for provider that does not support RLS +@betterbase/core:test: (pass) migration/rls-migrator > applyAuthFunction > executes auth function SQL [1.00ms] +@betterbase/core:test: (pass) migration/rls-migrator > applyAuthFunction > throws when database does not support raw queries +@betterbase/core:test: (pass) migration/rls-migrator > applyPolicies > does nothing for empty policies array +@betterbase/core:test: (pass) migration/rls-migrator > applyPolicies > generates and executes SQL for policies +@betterbase/core:test: (pass) migration/rls-migrator > applyRLSMigration > applies auth function then policies +@betterbase/core:test: (pass) migration/rls-migrator > dropPolicies > does nothing for empty policies array +@betterbase/core:test: (pass) migration/rls-migrator > dropPolicies > generates and executes DROP SQL for policies +@betterbase/core:test: (pass) migration/rls-migrator > dropTableRLS > drops all policies for a table +@betterbase/core:test: (pass) migration/rls-migrator > getAppliedPolicies > queries pg_policies for applied policies +@betterbase/core:test: (pass) migration/rls-migrator > getAppliedPolicies > throws when database does not support raw queries +@betterbase/core:test: +@betterbase/core:test: test/rls-auth-bridge.test.ts: +@betterbase/core:test: (pass) RLS Auth Bridge > generateAuthFunction > should generate auth.uid() function +@betterbase/core:test: (pass) RLS Auth Bridge > generateAuthFunction > should be valid SQL [2.00ms] +@betterbase/core:test: (pass) RLS Auth Bridge > generateAuthFunctionWithSetting > should use custom setting name +@betterbase/core:test: (pass) RLS Auth Bridge > generateAuthFunctionWithSetting > should throw for invalid setting name with semicolon +@betterbase/core:test: (pass) RLS Auth Bridge > generateAuthFunctionWithSetting > should throw for invalid setting name with quotes [1.00ms] +@betterbase/core:test: (pass) RLS Auth Bridge > generateAuthFunctionWithSetting > should throw for invalid setting name with special chars +@betterbase/core:test: (pass) RLS Auth Bridge > generateAuthFunctionWithSetting > should allow valid setting names with dots and underscores +@betterbase/core:test: (pass) RLS Auth Bridge > generateAuthFunctionWithSetting > should allow alphanumeric setting names +@betterbase/core:test: (pass) RLS Auth Bridge > dropAuthFunction > should generate DROP FUNCTION statement +@betterbase/core:test: (pass) RLS Auth Bridge > setCurrentUserId > should generate SET statement with user ID +@betterbase/core:test: (pass) RLS Auth Bridge > setCurrentUserId > should escape single quotes in user ID +@betterbase/core:test: (pass) RLS Auth Bridge > setCurrentUserId > should handle UUID format +@betterbase/core:test: (pass) RLS Auth Bridge > setCurrentUserId > should handle numeric user ID as string +@betterbase/core:test: (pass) RLS Auth Bridge > clearCurrentUserId > should generate SET statement to clear user ID +@betterbase/core:test: (pass) RLS Auth Bridge > generateIsAuthenticatedCheck > should generate auth.authenticated() function +@betterbase/core:test: (pass) RLS Auth Bridge > dropIsAuthenticatedCheck > should generate DROP FUNCTION statement +@betterbase/core:test: (pass) RLS Auth Bridge > generateAllAuthFunctions > should return array of auth functions +@betterbase/core:test: (pass) RLS Auth Bridge > generateAllAuthFunctions > should include auth.uid() function +@betterbase/core:test: (pass) RLS Auth Bridge > generateAllAuthFunctions > should include auth.authenticated() function +@betterbase/core:test: (pass) RLS Auth Bridge > dropAllAuthFunctions > should return array of DROP statements +@betterbase/core:test: (pass) RLS Auth Bridge > dropAllAuthFunctions > should include drop for auth.authenticated() +@betterbase/core:test: (pass) RLS Auth Bridge > dropAllAuthFunctions > should include drop for auth.uid() +@betterbase/core:test: (pass) RLS Auth Bridge > SQL generation integration > auth functions should be valid PostgreSQL +@betterbase/core:test: (pass) RLS Auth Bridge > SQL generation integration > generated functions should have proper language specification +@betterbase/core:test: (pass) RLS Auth Bridge > SQL generation integration > SET statements should use LOCAL for session scope +@betterbase/core:test: +@betterbase/core:test: test/graphql.test.ts: +@betterbase/core:test: (pass) graphql/schema-generator > generateGraphQLSchema > generates schema with empty tables object +@betterbase/core:test: (pass) graphql/schema-generator > generateGraphQLSchema > generates schema with single table [2.00ms] +@betterbase/core:test: (pass) graphql/schema-generator > generateGraphQLSchema > generates query type with get and list operations +@betterbase/core:test: (pass) graphql/schema-generator > generateGraphQLSchema > generates mutation type when enabled +@betterbase/core:test: (pass) graphql/schema-generator > generateGraphQLSchema > does not generate mutation type when disabled [1.00ms] +@betterbase/core:test: (pass) graphql/schema-generator > generateGraphQLSchema > generates subscription type when enabled +@betterbase/core:test: (pass) graphql/schema-generator > generateGraphQLSchema > does not generate subscription type when disabled +@betterbase/core:test: (pass) graphql/schema-generator > generateGraphQLSchema > applies type prefix when configured [1.00ms] +@betterbase/core:test: (pass) graphql/sdl-exporter > exportSDL > exports empty schema with Query type +@betterbase/core:test: (pass) graphql/sdl-exporter > exportSDL > exports custom scalars +@betterbase/core:test: (pass) graphql/sdl-exporter > exportSDL > exports mutations when present [1.00ms] +@betterbase/core:test: (pass) graphql/sdl-exporter > exportSDL > exports subscriptions when present +@betterbase/core:test: (pass) graphql/sdl-exporter > exportSDL > respects includeDescriptions option [1.00ms] +@betterbase/core:test: (pass) graphql/sdl-exporter > exportSDL > respects sortTypes option [1.00ms] +@betterbase/core:test: (pass) graphql/sdl-exporter > exportTypeSDL > exports a specific object type +@betterbase/core:test: (pass) graphql/sdl-exporter > exportTypeSDL > throws for non-existent type [1.00ms] +@betterbase/core:test: (pass) graphql/resolvers > generateResolvers > generates resolvers for empty tables +@betterbase/core:test: (pass) graphql/resolvers > generateResolvers > generates query resolvers +@betterbase/core:test: (pass) graphql/resolvers > generateResolvers > respects mutations config +@betterbase/core:test: (pass) graphql/resolvers > generateResolvers > respects subscriptions config +@betterbase/core:test: +@betterbase/core:test: test/webhooks.test.ts: +@betterbase/core:test: (pass) webhooks/signer > signPayload > signs a string payload [2.00ms] +@betterbase/core:test: (pass) webhooks/signer > signPayload > signs an object payload +@betterbase/core:test: (pass) webhooks/signer > signPayload > same input produces same signature +@betterbase/core:test: (pass) webhooks/signer > signPayload > different secrets produce different signatures +@betterbase/core:test: (pass) webhooks/signer > signPayload > different payloads produce different signatures +@betterbase/core:test: (pass) webhooks/signer > verifySignature > returns true for valid signature [1.00ms] +@betterbase/core:test: (pass) webhooks/signer > verifySignature > returns false for invalid signature +@betterbase/core:test: (pass) webhooks/signer > verifySignature > returns false for wrong secret +@betterbase/core:test: (pass) webhooks/signer > verifySignature > returns false for tampered payload +@betterbase/core:test: (pass) webhooks/signer > verifySignature > handles object payloads +@betterbase/core:test: (pass) webhooks/signer > verifySignature > returns false for mismatched signature length +@betterbase/core:test: +@betterbase/core:test: 1 tests skipped: +@betterbase/core:test: (skip) branching - BranchManager > listBranches > sorts by creation date (newest first) +@betterbase/core:test: +@betterbase/core:test: 934 pass +@betterbase/core:test: 1 skip +@betterbase/core:test: 0 fail +@betterbase/core:test: 1506 expect() calls +@betterbase/core:test: Ran 935 tests across 32 files. [3.80s] +@betterbase/cli:test: Resolved, downloaded and extracted [14] +@betterbase/cli:test: Saved lockfile +@betterbase/cli:test: +@betterbase/cli:test: installed better-auth@1.6.11 +@betterbase/cli:test: +@betterbase/cli:test: 22 packages installed [1.68s] +@betterbase/cli:test: ◆ 📝 Creating auth schema... +@betterbase/cli:test: ◆ Updated src/db/index.ts to export auth-schema +@betterbase/cli:test: ◆ 🔑 Creating auth instance... +@betterbase/cli:test: ◆ 📋 Creating auth types... +@betterbase/cli:test: ◆ 🛡️ Creating auth middleware... +@betterbase/cli:test: ◆ Updated src/index.ts with BetterAuth handler mount +@betterbase/cli:test: ◆ 🗄️ Running database migrations... +@betterbase/cli:test: ◆ Executing drizzle-kit push... +@betterbase/cli:test: No config path provided, using default 'drizzle.config.json' +@betterbase/cli:test: /tmp/bb-auth-2NsDK2/drizzle.config.json file does not exist +@betterbase/cli:test: ⚠ Could not run drizzle-kit push automatically: Command failed: bunx drizzle-kit push. Please run it manually. +@betterbase/cli:test: ✓ ✅ BetterAuth setup complete! +@betterbase/cli:test: ◆ Next steps: +@betterbase/cli:test: ◆ 1. Set AUTH_SECRET in .env (already added to .env.example) +@betterbase/cli:test: ◆ 2. Run: bunx drizzle-kit push (if not already run) +@betterbase/cli:test: ◆ 3. Use requireAuth middleware on protected routes: +@betterbase/cli:test: ◆ import { requireAuth } from './middleware/auth' +@betterbase/cli:test: ◆ app.use('*', requireAuth) +@betterbase/cli:test: (pass) runAuthSetupCommand > creates src/auth/index.ts +@betterbase/cli:test: (pass) runAuthSetupCommand > creates src/auth/types.ts +@betterbase/cli:test: (pass) runAuthSetupCommand > creates src/db/auth-schema.ts +@betterbase/cli:test: (pass) runAuthSetupCommand > creates src/middleware/auth.ts [1.00ms] +@betterbase/cli:test: (pass) runAuthSetupCommand > middleware contains requireAuth export +@betterbase/cli:test: (pass) runAuthSetupCommand > middleware contains optionalAuth export [2.00ms] +@betterbase/cli:test: (pass) runAuthSetupCommand > auth-schema.ts contains user and session tables for sqlite +@betterbase/cli:test: ◆ 🔐 Setting up BetterAuth... +@betterbase/cli:test: ◆ 📦 Installing better-auth... +@betterbase/cli:test: bun add v1.3.13 (bf2e2cec) +@betterbase/cli:test: Resolving dependencies +@betterbase/cli:test: Resolved, downloaded and extracted [0] +@betterbase/cli:test: Saved lockfile +@betterbase/cli:test: +@betterbase/cli:test: installed better-auth@1.6.11 +@betterbase/cli:test: +@betterbase/cli:test: 22 packages installed [104.00ms] +@betterbase/cli:test: ◆ 📝 Creating auth schema... +@betterbase/cli:test: ◆ Updated src/db/index.ts to export auth-schema +@betterbase/cli:test: ◆ 🔑 Creating auth instance... +@betterbase/cli:test: ◆ 📋 Creating auth types... +@betterbase/cli:test: ◆ 🛡️ Creating auth middleware... +@betterbase/cli:test: ◆ Updated src/index.ts with BetterAuth handler mount +@betterbase/cli:test: ◆ 🗄️ Running database migrations... +@betterbase/cli:test: ◆ Executing drizzle-kit push... +@betterbase/cli:test: No config path provided, using default 'drizzle.config.json' +@betterbase/cli:test: /tmp/bb-auth-pg-FpQYlX/drizzle.config.json file does not exist +@betterbase/cli:test: ⚠ Could not run drizzle-kit push automatically: Command failed: bunx drizzle-kit push. Please run it manually. +@betterbase/cli:test: ✓ ✅ BetterAuth setup complete! +@betterbase/cli:test: ◆ Next steps: +@betterbase/cli:test: ◆ 1. Set AUTH_SECRET in .env (already added to .env.example) +@betterbase/cli:test: ◆ 2. Run: bunx drizzle-kit push (if not already run) +@betterbase/cli:test: ◆ 3. Use requireAuth middleware on protected routes: +@betterbase/cli:test: ◆ import { requireAuth } from './middleware/auth' +@betterbase/cli:test: ◆ app.use('*', requireAuth) +@betterbase/cli:test: (pass) runAuthSetupCommand > auth-schema.ts uses pgTable for pg provider [365.00ms] +@betterbase/cli:test: (pass) runAuthSetupCommand > auth/index.ts references the correct provider and betterAuth [1.00ms] +@betterbase/cli:test: (pass) runAuthSetupCommand > adds AUTH_SECRET to .env.example +@betterbase/cli:test: (pass) runAuthSetupCommand > mounts auth handler in src/index.ts [1.00ms] +@betterbase/cli:test: ◆ ✅ Auth is already set up! +@betterbase/cli:test: ◆ ✅ Auth is already set up! +@betterbase/cli:test: (pass) runAuthSetupCommand > is idempotent — running twice does not duplicate auth handler mount +@betterbase/cli:test: +@betterbase/cli:test: test/migrate-utils.test.ts: +@betterbase/cli:test: (pass) Migrate Utils > calculateChecksum > should calculate SHA256 checksum of SQL content +@betterbase/cli:test: (pass) Migrate Utils > calculateChecksum > should produce same checksum for same content +@betterbase/cli:test: (pass) Migrate Utils > calculateChecksum > should produce different checksum for different content +@betterbase/cli:test: (pass) Migrate Utils > calculateChecksum > should trim whitespace before calculating checksum +@betterbase/cli:test: (pass) Migrate Utils > calculateChecksum > should handle empty SQL +@betterbase/cli:test: (pass) Migrate Utils > calculateChecksum > should handle multiline SQL +@betterbase/cli:test: (pass) Migrate Utils > parseMigrationFilename > should parse valid up migration filename +@betterbase/cli:test: (pass) Migrate Utils > parseMigrationFilename > should parse valid down migration filename +@betterbase/cli:test: (pass) Migrate Utils > parseMigrationFilename > should parse migration with complex name +@betterbase/cli:test: (pass) Migrate Utils > parseMigrationFilename > should return null for invalid filename format +@betterbase/cli:test: (pass) Migrate Utils > parseMigrationFilename > should return null for filename without direction +@betterbase/cli:test: (pass) Migrate Utils > parseMigrationFilename > should return null for filename without id +@betterbase/cli:test: (pass) Migrate Utils > parseMigrationFilename > should return null for filename with invalid direction +@betterbase/cli:test: (pass) Migrate Utils > parseMigrationFilename > should handle multiple underscores in name +@betterbase/cli:test: (pass) Migrate Utils > parseMigrationFilename > should handle large migration numbers +@betterbase/cli:test: (pass) Migrate Utils > getDatabaseType > should return postgresql for postgres:// URL +@betterbase/cli:test: (pass) Migrate Utils > getDatabaseType > should return postgresql for postgresql:// URL +@betterbase/cli:test: (pass) Migrate Utils > getDatabaseType > should return postgresql for DB_URL with postgres +@betterbase/cli:test: (pass) Migrate Utils > getDatabaseType > should return sqlite for file paths +@betterbase/cli:test: (pass) Migrate Utils > getDatabaseType > should return sqlite for local database URLs +@betterbase/cli:test: (pass) Migrate Utils > getMigrationsTableSql > should return PostgreSQL migrations table SQL +@betterbase/cli:test: (pass) Migrate Utils > getMigrationsTableSql > should return SQLite migrations table SQL +@betterbase/cli:test: (pass) Migrate Utils > getMigrationsTableSql > should create table with all required columns +@betterbase/cli:test: (pass) Migrate Utils > Integration - loadMigrationFiles > should verify calculateChecksum produces valid output +@betterbase/cli:test: +@betterbase/cli:test: test/smoke.test.ts: +@betterbase/cli:test: (pass) cli > has expected program name [14.00ms] +@betterbase/cli:test: (pass) cli > supports init positional argument [2.00ms] +@betterbase/cli:test: (pass) cli > registers generate crud command [1.00ms] +@betterbase/cli:test: (pass) cli > registers auth setup command [2.00ms] +@betterbase/cli:test: (pass) cli > registers dev command +@betterbase/cli:test: (pass) cli > registers migrate commands [1.00ms] +@betterbase/cli:test: +@betterbase/cli:test: test/unit/api-client.test.ts: +@betterbase/cli:test: +@betterbase/cli:test: # Unhandled error between tests +@betterbase/cli:test: ------------------------------- +@betterbase/cli:test: 26 | process.env.BB_CREDENTIALS_DIR = originalBBCredentialsDir; +@betterbase/cli:test: 27 | } +@betterbase/cli:test: 28 | } +@betterbase/cli:test: 29 | +@betterbase/cli:test: 30 | describe("api-client", () => { +@betterbase/cli:test: 31 | beforeEach(() => { +@betterbase/cli:test: ^ +@betterbase/cli:test: ReferenceError: beforeEach is not defined +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/unit/api-client.test.ts:31:3) +@betterbase/cli:test: ------------------------------- +@betterbase/cli:test: +@betterbase/cli:test: +@betterbase/cli:test: test/unit/credentials.test.ts: +@betterbase/cli:test: (pass) credentials > saveCredentials > saves credentials to ~/.betterbase/credentials.json +@betterbase/cli:test: (pass) credentials > saveCredentials > creates the directory if it does not exist +@betterbase/cli:test: (pass) credentials > saveCredentials > overwrites existing credentials +@betterbase/cli:test: (pass) credentials > loadCredentials > returns null when no credentials file exists [2.00ms] +@betterbase/cli:test: (pass) credentials > loadCredentials > loads and validates valid credentials [18.00ms] +@betterbase/cli:test: (pass) credentials > loadCredentials > returns null for corrupt JSON file +@betterbase/cli:test: (pass) credentials > loadCredentials > returns null for missing required fields (Zod validation) [1.00ms] +@betterbase/cli:test: (pass) credentials > loadCredentials > returns null for invalid email format [1.00ms] +@betterbase/cli:test: (pass) credentials > loadCredentials > returns null for invalid URL format [1.00ms] +@betterbase/cli:test: (pass) credentials > clearCredentials > clears the credentials file by writing empty object +@betterbase/cli:test: (pass) credentials > clearCredentials > does not throw when no credentials file exists +@betterbase/cli:test: (pass) credentials > getServerUrl > returns the server URL from saved credentials [2.00ms] +@betterbase/cli:test: (pass) credentials > getServerUrl > falls back to default URL when no credentials exist +@betterbase/cli:test: (pass) credentials > getServerUrl > removes trailing slash from URL +@betterbase/cli:test: +@betterbase/cli:test: test/unit/config.test.ts: +@betterbase/cli:test: (pass) config > findConfigFile > discovers betterbase.config.ts +@betterbase/cli:test: (pass) config > findConfigFile > discovers betterbase.config.js when .ts not present [2.00ms] +@betterbase/cli:test: (pass) config > findConfigFile > discovers betterbase.config.mts when .ts and .js not present [1.00ms] +@betterbase/cli:test: (pass) config > findConfigFile > prefers .ts variant over .js and .mts [1.00ms] +@betterbase/cli:test: (pass) config > findConfigFile > returns null when no config file exists [1.00ms] +@betterbase/cli:test: +@betterbase/cli:test: test/unit/spinner.test.ts: +@betterbase/cli:test: (pass) spinner > createSpinner > creates an Ora instance +@betterbase/cli:test: - Testing spinner +@betterbase/cli:test: ✓ Done +@betterbase/cli:test: (pass) spinner > withSpinner > calls task and returns result on success [2.00ms] +@betterbase/cli:test: - Testing spinner failure +@betterbase/cli:test: ✗ Failed: task failed +@betterbase/cli:test: (pass) spinner > withSpinner > re-throws error after catching task failure [1.00ms] +@betterbase/cli:test: +@betterbase/cli:test: test/unit/auth-providers.test.ts: +@betterbase/cli:test: (pass) auth-providers > PROVIDER_TEMPLATES > has entries for all 7 providers [2.00ms] +@betterbase/cli:test: (pass) auth-providers > PROVIDER_TEMPLATES > each provider has required fields [1.00ms] +@betterbase/cli:test: (pass) auth-providers > PROVIDER_TEMPLATES > each provider config references correct env vars +@betterbase/cli:test: (pass) auth-providers > PROVIDER_TEMPLATES > each template has correct callback URL pattern +@betterbase/cli:test: (pass) auth-providers > getProviderTemplate > returns template for valid provider name +@betterbase/cli:test: (pass) auth-providers > getProviderTemplate > is case-insensitive +@betterbase/cli:test: (pass) auth-providers > getProviderTemplate > returns null for unknown provider +@betterbase/cli:test: (pass) auth-providers > getAvailableProviders > returns 7 provider names +@betterbase/cli:test: (pass) auth-providers > getAvailableProviders > includes all expected providers +@betterbase/cli:test: +@betterbase/cli:test: test/e2e/binary-smoke.test.ts: +@betterbase/cli:test: (pass) binary smoke tests > can build the CLI [1211.00ms] +@betterbase/cli:test: (pass) binary smoke tests > bb --version exits with 0 and stdout contains version [690.00ms] +@betterbase/cli:test: (pass) binary smoke tests > bb --help exits with 0 and stdout contains subcommand list [641.00ms] +@betterbase/cli:test: (pass) binary smoke tests > bb init --help exits 0 and contains usage [658.00ms] +@betterbase/cli:test: (pass) binary smoke tests > bb unknown-command exits non-zero [631.00ms] +@betterbase/cli:test: +@betterbase/cli:test: test/integration/webhook-commands.test.ts: +@betterbase/cli:test: (pass) runWebhookListCommand > lists all configured webhooks from the config [6.00ms] +@betterbase/cli:test: (pass) runWebhookListCommand > shows message when no webhooks are configured [2.00ms] +@betterbase/cli:test: (pass) runWebhookListCommand > shows disabled webhooks with correct status label [1.00ms] +@betterbase/cli:test: (pass) runWebhookListCommand > shows event types comma separated [3.00ms] +@betterbase/cli:test: (pass) runWebhookListCommand > returns early when config is missing [1.00ms] +@betterbase/cli:test: (pass) runWebhookTestCommand > errors when webhook ID is not found in config [2.00ms] +@betterbase/cli:test: (pass) runWebhookTestCommand > errors when URL environment variable is not set [1.00ms] +@betterbase/cli:test: (pass) runWebhookTestCommand > errors when secret environment variable is not set [1.00ms] +@betterbase/cli:test: (pass) runWebhookTestCommand > config validation rejects URLs and secrets not using env var references [1.00ms] +@betterbase/cli:test: (pass) runWebhookTestCommand > sends a test payload when all env vars are set [1.00ms] +@betterbase/cli:test: (pass) runWebhookTestCommand > reports failure when test webhook returns success: false [1.00ms] +@betterbase/cli:test: (pass) runWebhookLogsCommand > displays delivery logs from the local database [18.00ms] +@betterbase/cli:test: (pass) runWebhookLogsCommand > shows message when no delivery logs exist [4.00ms] +@betterbase/cli:test: (pass) runWebhookLogsCommand > shows error when the database file does not exist [1.00ms] +@betterbase/cli:test: (pass) runWebhookLogsCommand > errors when webhook ID is not found [1.00ms] +@betterbase/cli:test: (pass) runWebhookLogsCommand > respects the limit option when querying logs [8.00ms] +@betterbase/cli:test: (pass) runWebhookCommand routing > routes 'list' to list command and shows webhooks [2.00ms] +@betterbase/cli:test: (pass) runWebhookCommand routing > routes 'test' to test command [1.00ms] +@betterbase/cli:test: (pass) runWebhookCommand routing > routes 'logs' to logs command [1.00ms] +@betterbase/cli:test: (pass) runWebhookCommand routing > shows help when no subcommand is provided +@betterbase/cli:test: (pass) runWebhookCommand routing > shows usage error when 'test' has no webhook ID [1.00ms] +@betterbase/cli:test: (pass) runWebhookCommand routing > shows usage error when 'logs' has no webhook ID +@betterbase/cli:test: (pass) generateWebhookId > generateWebhookId creates ID with correct format +@betterbase/cli:test: (pass) generateWebhookId > IDs are unique across calls [14.00ms] +@betterbase/cli:test: (pass) runWebhookCreateCommand helpers > returns early when config file does not exist [2.00ms] +@betterbase/cli:test: +@betterbase/cli:test: test/integration/rls-test-command.test.ts: +@betterbase/cli:test: (pass) RLS Test Command > RLSTestCase type > has correct shape with all required fields +@betterbase/cli:test: (pass) RLS Test Command > RLSTestCase type > supports optional expectedRowCount field on blocked tests +@betterbase/cli:test: (pass) RLS Test Command > RLSTestResult type > has correct shape with all fields +@betterbase/cli:test: (pass) RLS Test Command > RLSTestResult type > includes optional error field for failure results +@betterbase/cli:test: ◆ Testing RLS policies for table: users +@betterbase/cli:test: ◆ Creating test schema: test_L8QYKFOX +@betterbase/cli:test: ◆ Copying table structure... +@betterbase/cli:test: ⚠ No policies directory found, creating default test policies +@betterbase/cli:test: ◆ Applying 4 policy(ies)... +@betterbase/cli:test: ◆ Inserting test data... +@betterbase/cli:test: ◆ +@betterbase/cli:test: Running 8 test(s)... +@betterbase/cli:test: +@betterbase/cli:test: ✓ ✅ User can read own records (SELECT) +@betterbase/cli:test: ✗ ❌ User cannot read others' records (SELECT) +@betterbase/cli:test: ✓ ✅ User can insert records with own user_id +@betterbase/cli:test: ✓ ✅ User can update own records +@betterbase/cli:test: ✓ ✅ User can delete own records +@betterbase/cli:test: ✗ ❌ User cannot insert records with other user's user_id +@betterbase/cli:test: ✗ ❌ User cannot update others' records +@betterbase/cli:test: ✗ ❌ User cannot delete others' records +@betterbase/cli:test: +@betterbase/cli:test: 📊 Results +@betterbase/cli:test: +@betterbase/cli:test: { +@betterbase/cli:test: ✗ RLS tests: 4 passed, 4 failed +@betterbase/cli:test: "table": "users", +@betterbase/cli:test: "schema": "test_L8QYKFOX", +@betterbase/cli:test: "total": 8, +@betterbase/cli:test: "passed": 4, +@betterbase/cli:test: "failed": 4, +@betterbase/cli:test: "results": [ +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can read own records (SELECT)", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot read others' records (SELECT)", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can insert records with own user_id", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot insert records with other user's user_id", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can update own records", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot update others' records", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can delete own records", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot delete others' records", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: } +@betterbase/cli:test: ] +@betterbase/cli:test: } +@betterbase/cli:test: ◆ Cleaning up test schema... +@betterbase/cli:test: ✓ Test schema cleaned up +@betterbase/cli:test: (pass) RLS Test Command > getDatabaseUrl > returns DATABASE_URL when set in env [5.00ms] +@betterbase/cli:test: ◆ Testing RLS policies for table: users +@betterbase/cli:test: (pass) RLS Test Command > getDatabaseUrl > throws when DATABASE_URL is not set +@betterbase/cli:test: ◆ Testing RLS policies for table: users +@betterbase/cli:test: ◆ Creating test schema: test_NoDz2hjh +@betterbase/cli:test: ◆ Copying table structure... +@betterbase/cli:test: ⚠ No policies directory found, creating default test policies +@betterbase/cli:test: ◆ Applying 4 policy(ies)... +@betterbase/cli:test: ◆ Inserting test data... +@betterbase/cli:test: ◆ +@betterbase/cli:test: Running 8 test(s)... +@betterbase/cli:test: +@betterbase/cli:test: ✓ ✅ User can read own records (SELECT) +@betterbase/cli:test: ✗ ❌ User cannot read others' records (SELECT) +@betterbase/cli:test: ✓ ✅ User can insert records with own user_id +@betterbase/cli:test: ✗ ❌ User cannot insert records with other user's user_id +@betterbase/cli:test: ✓ ✅ User can update own records +@betterbase/cli:test: ✗ ❌ User cannot update others' records +@betterbase/cli:test: ✓ ✅ User can delete own records +@betterbase/cli:test: ✗ ❌ User cannot delete others' records +@betterbase/cli:test: +@betterbase/cli:test: 📊 Results +@betterbase/cli:test: +@betterbase/cli:test: { +@betterbase/cli:test: "table": "users", +@betterbase/cli:test: "schema": "test_NoDz2hjh", +@betterbase/cli:test: "total": 8, +@betterbase/cli:test: "passed": 4, +@betterbase/cli:test: "failed": 4, +@betterbase/cli:test: "results": [ +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can read own records (SELECT)", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot read others' records (SELECT)", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can insert records with own user_id", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot insert records with other user's user_id", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can update own records", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot update others' records", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can delete own records", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot delete others' records", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: } +@betterbase/cli:test: ] +@betterbase/cli:test: } +@betterbase/cli:test: ◆ Cleaning up test schema... +@betterbase/cli:test: ✓ Test schema cleaned up +@betterbase/cli:test: ✗ RLS tests: 4 passed, 4 failed +@betterbase/cli:test: (pass) RLS Test Command > loadTablePolicies > returns defaults when no policies directory exists [2.00ms] +@betterbase/cli:test: ◆ Testing RLS policies for table: users +@betterbase/cli:test: ◆ Creating test schema: test_5K4OmEYr +@betterbase/cli:test: ◆ Copying table structure... +@betterbase/cli:test: ◆ Applying 2 policy(ies)... +@betterbase/cli:test: ◆ Inserting test data... +@betterbase/cli:test: ◆ +@betterbase/cli:test: Running 8 test(s)... +@betterbase/cli:test: +@betterbase/cli:test: ✗ ❌ User cannot read others' records (SELECT) +@betterbase/cli:test: ✗ ❌ User cannot insert records with other user's user_id +@betterbase/cli:test: ✓ ✅ User can read own records (SELECT) +@betterbase/cli:test: ✓ ✅ User can insert records with own user_id +@betterbase/cli:test: ✗ ❌ User cannot update others' records +@betterbase/cli:test: ✓ ✅ User can update own records +@betterbase/cli:test: ✓ ✅ User can delete own records +@betterbase/cli:test: ✗ ❌ User cannot delete others' records +@betterbase/cli:test: +@betterbase/cli:test: 📊 Results +@betterbase/cli:test: +@betterbase/cli:test: { +@betterbase/cli:test: "table": "users", +@betterbase/cli:test: "schema": "test_5K4OmEYr", +@betterbase/cli:test: ✗ RLS tests: 4 passed, 4 failed +@betterbase/cli:test: "total": 8, +@betterbase/cli:test: "passed": 4, +@betterbase/cli:test: "failed": 4, +@betterbase/cli:test: "results": [ +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can read own records (SELECT)", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot read others' records (SELECT)", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can insert records with own user_id", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot insert records with other user's user_id", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can update own records", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot update others' records", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can delete own records", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot delete others' records", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: } +@betterbase/cli:test: ] +@betterbase/cli:test: } +@betterbase/cli:test: ◆ Cleaning up test schema... +@betterbase/cli:test: ✓ Test schema cleaned up +@betterbase/cli:test: (pass) RLS Test Command > loadTablePolicies > reads policy files correctly and extracts operations [1.00ms] +@betterbase/cli:test: ◆ Testing RLS policies for table: users +@betterbase/cli:test: ◆ Creating test schema: test_Iu5YLGUe +@betterbase/cli:test: ◆ Copying table structure... +@betterbase/cli:test: ⚠ No policies found for users, using default test policies +@betterbase/cli:test: ◆ Applying 4 policy(ies)... +@betterbase/cli:test: ◆ Inserting test data... +@betterbase/cli:test: ◆ +@betterbase/cli:test: Running 8 test(s)... +@betterbase/cli:test: +@betterbase/cli:test: ✓ ✅ User can read own records (SELECT) +@betterbase/cli:test: ✗ ❌ User cannot read others' records (SELECT) +@betterbase/cli:test: ✓ ✅ User can insert records with own user_id +@betterbase/cli:test: ✓ ✅ User can update own records +@betterbase/cli:test: ✗ ❌ User cannot insert records with other user's user_id +@betterbase/cli:test: ✗ ❌ User cannot update others' records +@betterbase/cli:test: ✗ ❌ User cannot delete others' records +@betterbase/cli:test: ✓ ✅ User can delete own records +@betterbase/cli:test: ✗ RLS tests: 4 passed, 4 failed +@betterbase/cli:test: +@betterbase/cli:test: 📊 Results +@betterbase/cli:test: +@betterbase/cli:test: { +@betterbase/cli:test: "table": "users", +@betterbase/cli:test: "schema": "test_Iu5YLGUe", +@betterbase/cli:test: "total": 8, +@betterbase/cli:test: "passed": 4, +@betterbase/cli:test: "failed": 4, +@betterbase/cli:test: "results": [ +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can read own records (SELECT)", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot read others' records (SELECT)", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can insert records with own user_id", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot insert records with other user's user_id", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can update own records", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot update others' records", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can delete own records", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot delete others' records", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: } +@betterbase/cli:test: ] +@betterbase/cli:test: } +@betterbase/cli:test: ◆ Cleaning up test schema... +@betterbase/cli:test: ✓ Test schema cleaned up +@betterbase/cli:test: (pass) RLS Test Command > loadTablePolicies > returns defaults when no matching .policy.ts files found for table [2.00ms] +@betterbase/cli:test: ◆ Testing RLS policies for table: users +@betterbase/cli:test: ◆ Creating test schema: test_shWk97XQ +@betterbase/cli:test: ◆ Copying table structure... +@betterbase/cli:test: ◆ Applying 1 policy(ies)... +@betterbase/cli:test: ◆ Inserting test data... +@betterbase/cli:test: ◆ +@betterbase/cli:test: Running 8 test(s)... +@betterbase/cli:test: +@betterbase/cli:test: ✓ ✅ User can read own records (SELECT) +@betterbase/cli:test: ✗ ❌ User cannot read others' records (SELECT) +@betterbase/cli:test: ✓ ✅ User can insert records with own user_id +@betterbase/cli:test: ✓ ✅ User can update own records +@betterbase/cli:test: ✓ ✅ User can delete own records +@betterbase/cli:test: ✗ ❌ User cannot insert records with other user's user_id +@betterbase/cli:test: ✗ ❌ User cannot update others' records +@betterbase/cli:test: ✗ ❌ User cannot delete others' records +@betterbase/cli:test: +@betterbase/cli:test: 📊 Results +@betterbase/cli:test: +@betterbase/cli:test: { +@betterbase/cli:test: "table": "users", +@betterbase/cli:test: "schema": "test_shWk97XQ", +@betterbase/cli:test: "total": 8, +@betterbase/cli:test: "passed": 4, +@betterbase/cli:test: "failed": 4, +@betterbase/cli:test: "results": [ +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can read own records (SELECT)", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot read others' records (SELECT)", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can insert records with own user_id", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot insert records with other user's user_id", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can update own records", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot update others' records", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can delete own records", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot delete others' records", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: } +@betterbase/cli:test: ] +@betterbase/cli:test: } +@betterbase/cli:test: ◆ Cleaning up test schema... +@betterbase/cli:test: ✗ RLS tests: 4 passed, 4 failed +@betterbase/cli:test: ✓ Test schema cleaned up +@betterbase/cli:test: (pass) RLS Test Command > generatePolicySQL > generates CREATE POLICY for select only [2.00ms] +@betterbase/cli:test: ◆ Testing RLS policies for table: users +@betterbase/cli:test: ◆ Creating test schema: test_jT4OsqCj +@betterbase/cli:test: ◆ Copying table structure... +@betterbase/cli:test: ◆ Applying 1 policy(ies)... +@betterbase/cli:test: ◆ Inserting test data... +@betterbase/cli:test: ◆ +@betterbase/cli:test: Running 8 test(s)... +@betterbase/cli:test: +@betterbase/cli:test: ✓ ✅ User can read own records (SELECT) +@betterbase/cli:test: ✗ ❌ User cannot read others' records (SELECT) +@betterbase/cli:test: ✓ ✅ User can insert records with own user_id +@betterbase/cli:test: ✗ ❌ User cannot insert records with other user's user_id +@betterbase/cli:test: ✓ ✅ User can update own records +@betterbase/cli:test: ✗ ❌ User cannot update others' records +@betterbase/cli:test: ✓ ✅ User can delete own records +@betterbase/cli:test: ✗ ❌ User cannot delete others' records +@betterbase/cli:test: +@betterbase/cli:test: 📊 Results +@betterbase/cli:test: +@betterbase/cli:test: { +@betterbase/cli:test: "table": "users", +@betterbase/cli:test: ✗ RLS tests: 4 passed, 4 failed +@betterbase/cli:test: "schema": "test_jT4OsqCj", +@betterbase/cli:test: "total": 8, +@betterbase/cli:test: "passed": 4, +@betterbase/cli:test: "failed": 4, +@betterbase/cli:test: "results": [ +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can read own records (SELECT)", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot read others' records (SELECT)", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can insert records with own user_id", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot insert records with other user's user_id", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can update own records", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot update others' records", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can delete own records", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot delete others' records", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: } +@betterbase/cli:test: ] +@betterbase/cli:test: } +@betterbase/cli:test: ◆ Cleaning up test schema... +@betterbase/cli:test: ✓ Test schema cleaned up +@betterbase/cli:test: 411 | +@betterbase/cli:test: 412 | const policyStmts = capturedSqlCalls.filter((s) => +@betterbase/cli:test: 413 | s.toUpperCase().includes("CREATE POLICY"), +@betterbase/cli:test: 414 | ); +@betterbase/cli:test: 415 | +@betterbase/cli:test: 416 | expect(policyStmts.length).toBe(2); +@betterbase/cli:test: ^ +@betterbase/cli:test: error: expect(received).toBe(expected) +@betterbase/cli:test: +@betterbase/cli:test: Expected: 2 +@betterbase/cli:test: Received: 1 +@betterbase/cli:test: +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/integration/rls-test-command.test.ts:416:36) +@betterbase/cli:test: (fail) RLS Test Command > generatePolicySQL > generates CREATE POLICY for select + insert [2.00ms] +@betterbase/cli:test: ◆ Testing RLS policies for table: users +@betterbase/cli:test: ◆ Creating test schema: test_ByrjVUFU +@betterbase/cli:test: ◆ Copying table structure... +@betterbase/cli:test: ◆ Applying 1 policy(ies)... +@betterbase/cli:test: ◆ Inserting test data... +@betterbase/cli:test: ◆ +@betterbase/cli:test: Running 8 test(s)... +@betterbase/cli:test: +@betterbase/cli:test: ✓ ✅ User can read own records (SELECT) +@betterbase/cli:test: ✗ ❌ User cannot read others' records (SELECT) +@betterbase/cli:test: ✗ ❌ User cannot insert records with other user's user_id +@betterbase/cli:test: ✓ ✅ User can insert records with own user_id +@betterbase/cli:test: ✓ ✅ User can update own records +@betterbase/cli:test: ✗ ❌ User cannot update others' records +@betterbase/cli:test: ✓ ✅ User can delete own records +@betterbase/cli:test: +@betterbase/cli:test: 📊 Results +@betterbase/cli:test: ✗ ❌ User cannot delete others' records +@betterbase/cli:test: +@betterbase/cli:test: ✗ RLS tests: 4 passed, 4 failed +@betterbase/cli:test: { +@betterbase/cli:test: "table": "users", +@betterbase/cli:test: "schema": "test_ByrjVUFU", +@betterbase/cli:test: "total": 8, +@betterbase/cli:test: (pass) RLS Test Command > generatePolicySQL > generates CREATE POLICY for all operations [1.00ms] +@betterbase/cli:test: "passed": 4, +@betterbase/cli:test: "failed": 4, +@betterbase/cli:test: "results": [ +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can read own records (SELECT)", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot read others' records (SELECT)", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can insert records with own user_id", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot insert records with other user's user_id", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can update own records", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot update others' records", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can delete own records", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot delete others' records", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: } +@betterbase/cli:test: ] +@betterbase/cli:test: } +@betterbase/cli:test: ◆ Cleaning up test schema... +@betterbase/cli:test: ✓ Test schema cleaned up +@betterbase/cli:test: ◆ Testing RLS policies for table: users +@betterbase/cli:test: ◆ Creating test schema: test_hpu2O2Vz +@betterbase/cli:test: ◆ Copying table structure... +@betterbase/cli:test: ◆ Applying 1 policy(ies)... +@betterbase/cli:test: ◆ Inserting test data... +@betterbase/cli:test: ◆ +@betterbase/cli:test: Running 8 test(s)... +@betterbase/cli:test: +@betterbase/cli:test: ✗ ❌ User cannot read others' records (SELECT) +@betterbase/cli:test: ✓ ✅ User can read own records (SELECT) +@betterbase/cli:test: ✓ ✅ User can insert records with own user_id +@betterbase/cli:test: ✗ ❌ User cannot insert records with other user's user_id +@betterbase/cli:test: ✓ ✅ User can update own records +@betterbase/cli:test: ✗ ❌ User cannot update others' records +@betterbase/cli:test: ✓ ✅ User can delete own records +@betterbase/cli:test: ✗ ❌ User cannot delete others' records +@betterbase/cli:test: +@betterbase/cli:test: 📊 Results +@betterbase/cli:test: +@betterbase/cli:test: { +@betterbase/cli:test: "table": "users", +@betterbase/cli:test: "schema": "test_hpu2O2Vz", +@betterbase/cli:test: "total": 8, +@betterbase/cli:test: "passed": 4, +@betterbase/cli:test: "failed": 4, +@betterbase/cli:test: "results": [ +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can read own records (SELECT)", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot read others' records (SELECT)", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can insert records with own user_id", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot insert records with other user's user_id", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can update own records", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot update others' records", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User can delete own records", +@betterbase/cli:test: "passed": true, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "allowed", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: }, +@betterbase/cli:test: { +@betterbase/cli:test: "test": "User cannot delete others' records", +@betterbase/cli:test: "passed": false, +@betterbase/cli:test: "actual": "allowed", +@betterbase/cli:test: "expected": "blocked", +@betterbase/cli:test: "rowCount": 1 +@betterbase/cli:test: } +@betterbase/cli:test: ] +@betterbase/cli:test: } +@betterbase/cli:test: ◆ Cleaning up test schema... +@betterbase/cli:test: ✓ Test schema cleaned up +@betterbase/cli:test: ✗ RLS tests: 4 passed, 4 failed +@betterbase/cli:test: (pass) RLS Test Command > generatePolicySQL > returns empty string when policy file has no operations [2.00ms] +@betterbase/cli:test: ◆ Testing RLS policies for table: users +@betterbase/cli:test: (pass) RLS Test Command > runRLSTestCommand database type validation > rejects non-PostgreSQL database type +@betterbase/cli:test: ◆ Testing RLS policies for table: users +@betterbase/cli:test: (pass) RLS Test Command > runRLSTestCommand database type validation > throws when DATABASE_URL is missing [1.00ms] +@betterbase/cli:test: +@betterbase/cli:test: test/integration/init.test.ts: +@betterbase/cli:test: (pass) projectNameSchema > accepts valid names (alphanumeric, hyphens, underscores) +@betterbase/cli:test: (pass) projectNameSchema > rejects empty strings +@betterbase/cli:test: (pass) projectNameSchema > rejects names with special characters (spaces, @, !, etc.) +@betterbase/cli:test: (pass) projectNameSchema > trims whitespace before validation +@betterbase/cli:test: (pass) initOptionsSchema > accepts empty object [1.00ms] +@betterbase/cli:test: (pass) initOptionsSchema > accepts object with valid projectName +@betterbase/cli:test: (pass) initOptionsSchema > accepts object with iac flag +@betterbase/cli:test: (pass) initOptionsSchema > accepts object with both projectName and iac +@betterbase/cli:test: (pass) initOptionsSchema > rejects object with invalid projectName +@betterbase/cli:test: (pass) providerTypeSchema > accepts all valid provider types +@betterbase/cli:test: (pass) providerTypeSchema > rejects invalid provider types +@betterbase/cli:test: (pass) getDatabaseLabel > returns correct label for neon +@betterbase/cli:test: (pass) getDatabaseLabel > returns correct label for turso [1.00ms] +@betterbase/cli:test: (pass) getDatabaseLabel > returns correct label for planetscale +@betterbase/cli:test: (pass) getDatabaseLabel > returns correct label for supabase +@betterbase/cli:test: (pass) getDatabaseLabel > returns correct label for postgres +@betterbase/cli:test: (pass) getDatabaseLabel > returns correct label for managed +@betterbase/cli:test: (pass) getDatabaseLabel > every known provider has a distinct label +@betterbase/cli:test: (pass) getAuthDialect > returns sqlite for turso +@betterbase/cli:test: (pass) getAuthDialect > returns mysql for planetscale +@betterbase/cli:test: (pass) getAuthDialect > returns pg for neon +@betterbase/cli:test: (pass) getAuthDialect > returns pg for postgres +@betterbase/cli:test: (pass) getAuthDialect > returns pg for supabase +@betterbase/cli:test: (pass) getAuthDialect > returns pg for managed +@betterbase/cli:test: (pass) InitCommandOptions > allows empty object +@betterbase/cli:test: (pass) InitCommandOptions > allows projectName string +@betterbase/cli:test: (pass) InitCommandOptions > allows iac boolean flag +@betterbase/cli:test: (pass) InitCommandOptions > validation rejects invalid projectName via initOptionsSchema +@betterbase/cli:test: (pass) InitCommandOptions > validation passes with valid combined options +@betterbase/cli:test: +@betterbase/cli:test: Create a new Betterbase project +@betterbase/cli:test: +@betterbase/cli:test: ◆ Creating BetterBase IaC project: bb-test-1b7c2062 +@betterbase/cli:test: ✓ IaC template copied to /tmp/tmp-integration-parent-b7c38e2c/bb-test-1b7c2062 +@betterbase/cli:test: +@betterbase/cli:test: ✦ bb-test-1b7c2062 initialized +@betterbase/cli:test: +@betterbase/cli:test: +@betterbase/cli:test: Created +@betterbase/cli:test: ───────── +@betterbase/cli:test: ├─ betterbase.config.ts +@betterbase/cli:test: ├─ betterbase/schema.ts +@betterbase/cli:test: ├─ src/index.ts +@betterbase/cli:test: ├─ betterbase/queries/todos.ts +@betterbase/cli:test: ├─ betterbase/mutations/todos.ts +@betterbase/cli:test: └─ ... and more +@betterbase/cli:test: +@betterbase/cli:test: Next steps +@betterbase/cli:test: ──────────── +@betterbase/cli:test: 1. cd bb-test-1b7c2062 +@betterbase/cli:test: 2. bun install +@betterbase/cli:test: 3. bb dev +@betterbase/cli:test: +@betterbase/cli:test: 328 | expect(existsSync(join(projectPath, "src", "modules", ".gitkeep"))).toBe(true); +@betterbase/cli:test: 329 | +@betterbase/cli:test: 330 | // Spot-check contents +@betterbase/cli:test: 331 | const pkg = JSON.parse(readFileSync(join(projectPath, "package.json"), "utf-8")); +@betterbase/cli:test: 332 | expect(pkg.name).toBe(projectName); +@betterbase/cli:test: 333 | expect(pkg.scripts.dev).toContain("bun"); +@betterbase/cli:test: ^ +@betterbase/cli:test: error: expect(received).toContain(expected) +@betterbase/cli:test: +@betterbase/cli:test: Expected to contain: "bun" +@betterbase/cli:test: Received: "bb dev" +@betterbase/cli:test: +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/integration/init.test.ts:333:28) +@betterbase/cli:test: (fail) runInitCommand (IaC integration) > copies full IaC template into new project directory [6.00ms] +@betterbase/cli:test: +@betterbase/cli:test: test/integration/rls-commands.test.ts: +@betterbase/cli:test: (pass) runRlsCreate > creates a .policy.ts file with correct template [1.00ms] +@betterbase/cli:test: (pass) runRlsCreate > sanitizes table name (special chars → underscores) [1.00ms] +@betterbase/cli:test: (pass) runRlsCreate > sanitizes table name with spaces +@betterbase/cli:test: (pass) runRlsCreate > warns on duplicate policy [1.00ms] +@betterbase/cli:test: (pass) runRlsCreate > throws on missing table name (empty string) +@betterbase/cli:test: (pass) runRlsCreate > throws on missing table name (undefined) +@betterbase/cli:test: (pass) runRlsList > lists multiple policies [1.00ms] +@betterbase/cli:test: (pass) runRlsList > displays correct count +@betterbase/cli:test: (pass) runRlsList > handles empty/no policies directory [1.00ms] +@betterbase/cli:test: (pass) runRlsList > handles existing but empty policies directory +@betterbase/cli:test: (pass) runRlsList > ignores non-policy files in the directory [1.00ms] +@betterbase/cli:test: (pass) runRlsDisable > shows delete instructions when policy exists +@betterbase/cli:test: (pass) runRlsDisable > handles missing policy (no policy file found) [1.00ms] +@betterbase/cli:test: (pass) runRlsDisable > throws on missing table name (empty string) +@betterbase/cli:test: (pass) runRlsDisable > throws on missing table name (undefined) +@betterbase/cli:test: (pass) runRlsCommand > routes 'create' to runRlsCreate [1.00ms] +@betterbase/cli:test: (pass) runRlsCommand > routes 'list' to runRlsList +@betterbase/cli:test: (pass) runRlsCommand > routes 'disable' to runRlsDisable [1.00ms] +@betterbase/cli:test: (pass) runRlsCommand > shows help when no subcommand given (empty array) +@betterbase/cli:test: (pass) runRlsCommand > shows help for unknown subcommand [1.00ms] +@betterbase/cli:test: (pass) runRlsCommand > shows help for undefined subcommand +@betterbase/cli:test: +@betterbase/cli:test: test/integration/dev.test.ts: +@betterbase/cli:test: +@betterbase/cli:test: bb dev — watching for changes +@betterbase/cli:test: +@betterbase/cli:test: Project root /tmp/bb-test-d8a31b50 +@betterbase/cli:test: Server URL http://localhost:3000 +@betterbase/cli:test: Dashboard http://localhost:3000/admin +@betterbase/cli:test: +@betterbase/cli:test: Press Ctrl+C to stop +@betterbase/cli:test: +@betterbase/cli:test: ◆ [dev] Shutting down... +@betterbase/cli:test: (pass) runDevCommand > creates cleanup function [1.00ms] +@betterbase/cli:test: +@betterbase/cli:test: (pass) runDevCommand > detects betterbase/ directory [1.00ms] +@betterbase/cli:test: bb dev — watching for changes +@betterbase/cli:test: +@betterbase/cli:test: Project root /tmp/bb-test-69c0b9f5 +@betterbase/cli:test: (pass) runDevCommand > handles missing betterbase/ gracefully [1.00ms] +@betterbase/cli:test: Server URL http://localhost:3000 +@betterbase/cli:test: Dashboard http://localhost:3000/admin +@betterbase/cli:test: +@betterbase/cli:test: Press Ctrl+C to stop +@betterbase/cli:test: +@betterbase/cli:test: ◆ IaC layer detected — betterbase/ will be watched for schema and function changes. +@betterbase/cli:test: ◆ [iac] Running initial sync... +@betterbase/cli:test: ◆ [dev] Shutting down... +@betterbase/cli:test: +@betterbase/cli:test: bb dev — watching for changes +@betterbase/cli:test: +@betterbase/cli:test: Project root /tmp/bb-test-8b1f968b +@betterbase/cli:test: Server URL http://localhost:3000 +@betterbase/cli:test: Dashboard http://localhost:3000/admin +@betterbase/cli:test: +@betterbase/cli:test: Press Ctrl+C to stop +@betterbase/cli:test: +@betterbase/cli:test: ◆ [dev] Shutting down... +@betterbase/cli:test: +@betterbase/cli:test: bb dev — watching for changes +@betterbase/cli:test: +@betterbase/cli:test: Project root /tmp/bb-test-2eee5299 +@betterbase/cli:test: Server URL http://localhost:3000 +@betterbase/cli:test: Dashboard http://localhost:3000/admin +@betterbase/cli:test: +@betterbase/cli:test: Press Ctrl+C to stop +@betterbase/cli:test: +@betterbase/cli:test: ◆ [dev] Shutting down... +@betterbase/cli:test: (pass) runDevCommand > QUERY_LOG=true enables query log [1.00ms] +@betterbase/cli:test: +@betterbase/cli:test: bb dev — watching for changes +@betterbase/cli:test: +@betterbase/cli:test: Project root /tmp/bb-test-0be37b3b +@betterbase/cli:test: (pass) runDevCommand > QUERY_LOG=false disables query log +@betterbase/cli:test: Server URL http://localhost:3000 +@betterbase/cli:test: Dashboard http://localhost:3000/admin +@betterbase/cli:test: +@betterbase/cli:test: Press Ctrl+C to stop +@betterbase/cli:test: +@betterbase/cli:test: ◆ [dev] Shutting down... +@betterbase/cli:test: +@betterbase/cli:test: bb dev — watching for changes +@betterbase/cli:test: +@betterbase/cli:test: Project root /nonexistent/path/12345 +@betterbase/cli:test: Server URL http://localhost:3000 +@betterbase/cli:test: Dashboard http://localhost:3000/admin +@betterbase/cli:test: +@betterbase/cli:test: Press Ctrl+C to stop +@betterbase/cli:test: +@betterbase/cli:test: ◆ [dev] Shutting down... +@betterbase/cli:test: (pass) runDevCommand > validates project root exists [1.00ms] +@betterbase/cli:test: +@betterbase/cli:test: bb dev — watching for changes +@betterbase/cli:test: +@betterbase/cli:test: Project root /tmp/bb-test-06c1b079 +@betterbase/cli:test: Server URL http://localhost:3000 +@betterbase/cli:test: Dashboard http://localhost:3000/admin +@betterbase/cli:test: +@betterbase/cli:test: Press Ctrl+C to stop +@betterbase/cli:test: +@betterbase/cli:test: ◆ [dev] Shutting down... +@betterbase/cli:test: (pass) runDevCommand > cleanup function can be called without error +@betterbase/cli:test: +@betterbase/cli:test: bb dev — watching for changes +@betterbase/cli:test: +@betterbase/cli:test: Project root /tmp/bb-test-026da1cd +@betterbase/cli:test: Server URL http://localhost:3000 +@betterbase/cli:test: Dashboard http://localhost:3000/admin +@betterbase/cli:test: +@betterbase/cli:test: Press Ctrl+C to stop +@betterbase/cli:test: +@betterbase/cli:test: ✗ Context generation failed: Cannot find module: @betterbase/core +@betterbase/cli:test: ◆ [dev] Shutting down... +@betterbase/cli:test: (pass) runDevCommand > handles missing schema gracefully [1.00ms] +@betterbase/cli:test: +@betterbase/cli:test: test/integration/cross-product-workflow.test.ts: +@betterbase/cli:test: - Generating migration files... +@betterbase/cli:test: ✓ Migration files generated +@betterbase/cli:test: +@betterbase/cli:test: Migration Preview +@betterbase/cli:test: ─────────────────── +@betterbase/cli:test: No schema changes detected. +@betterbase/cli:test: ◆ drizzle/ files are for preview; running push will apply changes. +@betterbase/cli:test: - Applying migration changes... +@betterbase/cli:test: ✓ Applied migration changes +@betterbase/cli:test: 106 | throw new Error( +@betterbase/cli:test: 107 | `Migration conflict detected during push. Please resolve and retry.\n${push.stderr}`, +@betterbase/cli:test: 108 | ); +@betterbase/cli:test: 109 | } +@betterbase/cli:test: 110 | +@betterbase/cli:test: 111 | throw new Error(`Migration push failed.\n${push.stderr || push.stdout}`); +@betterbase/cli:test: ^ +@betterbase/cli:test: error: Migration push failed. +@betterbase/cli:test: No config path provided, using default 'drizzle.config.ts' +@betterbase/cli:test: Reading config file '/tmp/bb-test-256727ff/drizzle.config.ts' +@betterbase/cli:test: Error Please provide required params: +@betterbase/cli:test: [x] url: undefined +@betterbase/cli:test: +@betterbase/cli:test: at runMigrateCommand (/workspaces/Betterbase/packages/cli/src/commands/migrate.ts:111:13) +@betterbase/cli:test: at async (/workspaces/Betterbase/packages/cli/test/integration/cross-product-workflow.test.ts:75:10) +@betterbase/cli:test: (fail) Cross-Product Integration Pipeline (real implementations) > migrate generates migrations and GraphQL schema, then context builds on them [721.00ms] +@betterbase/cli:test: +@betterbase/cli:test: test/integration/branch-commands.test.ts: +@betterbase/cli:test: (pass) runBranchCreateCommand > throws when branch name is not provided [1.00ms] +@betterbase/cli:test: ◆ Creating preview environment: my-feature +@betterbase/cli:test: (pass) runBranchCreateCommand > throws when config file cannot be loaded +@betterbase/cli:test: ◆ Creating preview environment: my-feature +@betterbase/cli:test: +@betterbase/cli:test: Preview environment created +@betterbase/cli:test: ───────────────────────────── +@betterbase/cli:test: Name my-feature +@betterbase/cli:test: Preview URL https://my-feature.preview.betterbase.io +@betterbase/cli:test: Status active +@betterbase/cli:test: ◆ Database: Cloned from main +@betterbase/cli:test: Storage my-feature-bucket +@betterbase/cli:test: (pass) runBranchCreateCommand > creates a branch successfully with a valid name and config [1.00ms] +@betterbase/cli:test: ◆ Creating preview environment: my-feature +@betterbase/cli:test: (pass) runBranchCreateCommand > throws when branch creation fails (success: false) +@betterbase/cli:test: (pass) runBranchListCommand > throws when config file cannot be loaded [1.00ms] +@betterbase/cli:test: +@betterbase/cli:test: Preview Environments (2) +@betterbase/cli:test: ────────────────────────── +@betterbase/cli:test: feature-a (active) +@betterbase/cli:test: URL: https://feature-a.preview.betterbase.io +@betterbase/cli:test: Created: 2026-01-15 +@betterbase/cli:test: Last: 2026-04-20 +@betterbase/cli:test: +@betterbase/cli:test: feature-b (sleeping) +@betterbase/cli:test: URL: https://feature-b.preview.betterbase.io +@betterbase/cli:test: Created: 2026-02-10 +@betterbase/cli:test: Last: 2026-03-01 +@betterbase/cli:test: +@betterbase/cli:test: (pass) runBranchListCommand > lists branches when config is valid and branches exist +@betterbase/cli:test: ◆ No preview environments found. +@betterbase/cli:test: ◆ Run 'bb branch create ' to create one. +@betterbase/cli:test: (pass) runBranchListCommand > shows empty state message when no branches exist +@betterbase/cli:test: (pass) runBranchDeleteCommand > throws when branch name is not provided [1.00ms] +@betterbase/cli:test: ◆ Deleting preview environment: my-feature +@betterbase/cli:test: (pass) runBranchDeleteCommand > throws when config file cannot be loaded +@betterbase/cli:test: ◆ Deleting preview environment: nonexistent-branch +@betterbase/cli:test: (pass) runBranchDeleteCommand > throws when branch name is not found +@betterbase/cli:test: ◆ Deleting preview environment: stale-feature +@betterbase/cli:test: ✓ Preview environment 'stale-feature' deleted. +@betterbase/cli:test: (pass) runBranchDeleteCommand > deletes an existing branch successfully [1.00ms] +@betterbase/cli:test: ◆ Deleting preview environment: stale-feature +@betterbase/cli:test: (pass) runBranchDeleteCommand > throws when delete operation fails +@betterbase/cli:test: (pass) runBranchSleepCommand > throws when branch name is not provided +@betterbase/cli:test: ◆ Putting preview environment to sleep: my-feature +@betterbase/cli:test: (pass) runBranchSleepCommand > throws when config file cannot be loaded [1.00ms] +@betterbase/cli:test: ◆ Putting preview environment to sleep: nonexistent +@betterbase/cli:test: (pass) runBranchSleepCommand > throws when branch name is not found +@betterbase/cli:test: ◆ Putting preview environment to sleep: idle-feature +@betterbase/cli:test: ✓ Preview environment 'idle-feature' is now sleeping. +@betterbase/cli:test: ◆ Wake it up later with 'bb branch wake ' +@betterbase/cli:test: (pass) runBranchSleepCommand > puts a branch to sleep successfully +@betterbase/cli:test: ◆ Putting preview environment to sleep: idle-feature +@betterbase/cli:test: (pass) runBranchSleepCommand > throws when sleep operation fails [1.00ms] +@betterbase/cli:test: (pass) runBranchWakeCommand > throws when branch name is not provided +@betterbase/cli:test: ◆ Waking preview environment: my-feature +@betterbase/cli:test: (pass) runBranchWakeCommand > throws when config file cannot be loaded +@betterbase/cli:test: ◆ Waking preview environment: nonexistent +@betterbase/cli:test: (pass) runBranchWakeCommand > throws when branch name is not found +@betterbase/cli:test: ◆ Waking preview environment: dormant-feature +@betterbase/cli:test: ✓ Preview environment 'dormant-feature' is now active! +@betterbase/cli:test: Preview URL https://dormant-feature.preview.betterbase.io +@betterbase/cli:test: (pass) runBranchWakeCommand > wakes a sleeping branch successfully [1.00ms] +@betterbase/cli:test: ◆ Waking preview environment: dormant-feature +@betterbase/cli:test: (pass) runBranchWakeCommand > throws when wake operation fails +@betterbase/cli:test: ◆ Creating preview environment: my-branch +@betterbase/cli:test: +@betterbase/cli:test: Preview environment created +@betterbase/cli:test: ───────────────────────────── +@betterbase/cli:test: Name my-branch +@betterbase/cli:test: Preview URL https://test-branch.preview.betterbase.io +@betterbase/cli:test: Status active +@betterbase/cli:test: ◆ Database: Cloned from main +@betterbase/cli:test: Storage test-branch-bucket +@betterbase/cli:test: (pass) runBranchCommand routing > "create" subcommand > dispatches to runBranchCreateCommand [1.00ms] +@betterbase/cli:test: ✗ Branch name is required. Usage: bb branch create +@betterbase/cli:test: (pass) runBranchCommand routing > "create" subcommand > re-throws errors from create (e.g. missing name) +@betterbase/cli:test: +@betterbase/cli:test: Preview Environments (1) +@betterbase/cli:test: ────────────────────────── +@betterbase/cli:test: test-branch (active) +@betterbase/cli:test: URL: https://test-branch.preview.betterbase.io +@betterbase/cli:test: Created: 2026-05-16 +@betterbase/cli:test: Last: 2026-05-16 +@betterbase/cli:test: +@betterbase/cli:test: (pass) runBranchCommand routing > "list" and "ls" subcommands > dispatches "list" to runBranchListCommand [1.00ms] +@betterbase/cli:test: +@betterbase/cli:test: Preview Environments (1) +@betterbase/cli:test: ────────────────────────── +@betterbase/cli:test: test-branch (active) +@betterbase/cli:test: URL: https://test-branch.preview.betterbase.io +@betterbase/cli:test: Created: 2026-05-16 +@betterbase/cli:test: Last: 2026-05-16 +@betterbase/cli:test: +@betterbase/cli:test: (pass) runBranchCommand routing > "list" and "ls" subcommands > dispatches "ls" alias to runBranchListCommand +@betterbase/cli:test: ✗ Could not load configuration from betterbase.config.ts. Make sure you're in a BetterBase project directory. +@betterbase/cli:test: (pass) runBranchCommand routing > "list" and "ls" subcommands > re-throws errors from list (e.g. missing config) +@betterbase/cli:test: ◆ Deleting preview environment: to-delete +@betterbase/cli:test: ✓ Preview environment 'to-delete' deleted. +@betterbase/cli:test: (pass) runBranchCommand routing > "delete", "remove", and "rm" subcommands > dispatches "delete" to runBranchDeleteCommand +@betterbase/cli:test: ◆ Deleting preview environment: to-remove +@betterbase/cli:test: ✓ Preview environment 'to-remove' deleted. +@betterbase/cli:test: (pass) runBranchCommand routing > "delete", "remove", and "rm" subcommands > dispatches "remove" alias to runBranchDeleteCommand [1.00ms] +@betterbase/cli:test: ◆ Deleting preview environment: to-rm +@betterbase/cli:test: ✓ Preview environment 'to-rm' deleted. +@betterbase/cli:test: (pass) runBranchCommand routing > "delete", "remove", and "rm" subcommands > dispatches "rm" alias to runBranchDeleteCommand +@betterbase/cli:test: ✗ Branch name is required. Usage: bb branch delete +@betterbase/cli:test: (pass) runBranchCommand routing > "delete", "remove", and "rm" subcommands > re-throws errors from delete (e.g. missing name) +@betterbase/cli:test: ◆ Putting preview environment to sleep: nap-time +@betterbase/cli:test: ✓ Preview environment 'nap-time' is now sleeping. +@betterbase/cli:test: ◆ Wake it up later with 'bb branch wake ' +@betterbase/cli:test: (pass) runBranchCommand routing > "sleep" subcommand > dispatches to runBranchSleepCommand +@betterbase/cli:test: ✗ Branch name is required. Usage: bb branch sleep +@betterbase/cli:test: (pass) runBranchCommand routing > "sleep" subcommand > re-throws errors from sleep (e.g. missing name) [1.00ms] +@betterbase/cli:test: ◆ Waking preview environment: rise-shine +@betterbase/cli:test: ✓ Preview environment 'rise-shine' is now active! +@betterbase/cli:test: Preview URL https://rise-shine.preview.betterbase.io +@betterbase/cli:test: (pass) runBranchCommand routing > "wake" subcommand > dispatches to runBranchWakeCommand +@betterbase/cli:test: ✗ Branch name is required. Usage: bb branch wake +@betterbase/cli:test: (pass) runBranchCommand routing > "wake" subcommand > re-throws errors from wake (e.g. missing name) +@betterbase/cli:test: ◆ Usage: bb branch [options] +@betterbase/cli:test: +@betterbase/cli:test: ◆ Commands: +@betterbase/cli:test: ◆ create Create a new preview environment +@betterbase/cli:test: ◆ list List all preview environments +@betterbase/cli:test: ◆ delete Delete a preview environment +@betterbase/cli:test: ◆ sleep Put a preview environment to sleep +@betterbase/cli:test: ◆ wake Wake a sleeping preview environment +@betterbase/cli:test: +@betterbase/cli:test: ◆ Examples: +@betterbase/cli:test: ◆ bb branch create my-feature +@betterbase/cli:test: ◆ bb branch list +@betterbase/cli:test: ◆ bb branch delete my-feature +@betterbase/cli:test: (pass) runBranchCommand routing > no subcommand > shows help without throwing [1.00ms] +@betterbase/cli:test: ◆ Usage: bb branch [options] +@betterbase/cli:test: +@betterbase/cli:test: ◆ Commands: +@betterbase/cli:test: ◆ create Create a new preview environment +@betterbase/cli:test: ◆ list List all preview environments +@betterbase/cli:test: ◆ delete Delete a preview environment +@betterbase/cli:test: ◆ sleep Put a preview environment to sleep +@betterbase/cli:test: ◆ wake Wake a sleeping preview environment +@betterbase/cli:test: +@betterbase/cli:test: ◆ Examples: +@betterbase/cli:test: ◆ bb branch create my-feature +@betterbase/cli:test: ◆ bb branch list +@betterbase/cli:test: ◆ bb branch delete my-feature +@betterbase/cli:test: (pass) runBranchCommand routing > no subcommand > shows help when args are undefined +@betterbase/cli:test: ✗ Unknown branch command: foobar +@betterbase/cli:test: (pass) runBranchCommand routing > unknown subcommand > throws for unrecognized subcommand +@betterbase/cli:test: ✗ Unknown branch command: xyzzy +@betterbase/cli:test: (pass) runBranchCommand routing > unknown subcommand > throws for any random string [1.00ms] +@betterbase/cli:test: +@betterbase/cli:test: test/integration/function-commands.test.ts: +@betterbase/cli:test: (pass) runFunctionCommand create > creates a function directory with index.ts and config.ts [2.00ms] +@betterbase/cli:test: (pass) runFunctionCommand create > creates a function with hyphens and underscores in name +@betterbase/cli:test: (pass) runFunctionCommand create > rejects names with special characters [1.00ms] +@betterbase/cli:test: (pass) runFunctionCommand create > rejects names with spaces +@betterbase/cli:test: (pass) runFunctionCommand create > rejects names with dots (e.g. path traversal) +@betterbase/cli:test: (pass) runFunctionCommand create > rejects missing function name +@betterbase/cli:test: Function created: src/functions/duplicate-func/ +@betterbase/cli:test: Run with: bb function dev duplicate-func +@betterbase/cli:test: (pass) runFunctionCommand create > rejects duplicate function name [1.00ms] +@betterbase/cli:test: Function created: src/functions/api-handler/ +@betterbase/cli:test: Run with: bb function dev api-handler +@betterbase/cli:test: (pass) runFunctionCommand create > index.ts template contains POST handler [1.00ms] +@betterbase/cli:test: (pass) runFunctionCommand list > lists functions with proper table format +@betterbase/cli:test: (pass) runFunctionCommand list > shows 'not built' status for unbuilt functions [1.00ms] +@betterbase/cli:test: (pass) runFunctionCommand list > shows message when no functions exist +@betterbase/cli:test: (pass) runFunctionCommand list > calls isFunctionBuilt for each function +@betterbase/cli:test: (pass) runFunctionCommand list > handles mixed built/not-built status across functions [1.00ms] +@betterbase/cli:test: (pass) runFunctionCommand build > builds a function successfully +@betterbase/cli:test: (pass) runFunctionCommand build > reports errors when build fails [1.00ms] +@betterbase/cli:test: (pass) runFunctionCommand build > rejects missing function name [1.00ms] +@betterbase/cli:test: (pass) runFunctionCommand build > handles bundle with multiple errors +@betterbase/cli:test: (pass) runFunctionCommand deploy > rejects missing function name [1.00ms] +@betterbase/cli:test: (pass) runFunctionCommand deploy > errors when function directory does not exist +@betterbase/cli:test: - Bundling function... +@betterbase/cli:test: ✓ Bundled dist/cf-func.js +@betterbase/cli:test: - Deploying to edge... +@betterbase/cli:test: ✓ Deployed cf-func +@betterbase/cli:test: (pass) runFunctionCommand deploy > deploys to cloudflare-workers successfully [2.00ms] +@betterbase/cli:test: - Bundling function... +@betterbase/cli:test: ✓ Bundled dist/vc-func.js +@betterbase/cli:test: - Deploying to edge... +@betterbase/cli:test: ✓ Deployed vc-func +@betterbase/cli:test: (pass) runFunctionCommand deploy > deploys to vercel-edge successfully [1.00ms] +@betterbase/cli:test: - Bundling function... +@betterbase/cli:test: ✓ Bundled dist/broken-deploy.js +@betterbase/cli:test: (pass) runFunctionCommand deploy > reports build failure during deploy +@betterbase/cli:test: - Bundling function... +@betterbase/cli:test: ✓ Bundled dist/fail-deploy.js +@betterbase/cli:test: - Deploying to edge... +@betterbase/cli:test: (pass) runFunctionCommand deploy > handles deployment failure after successful build [1.00ms] +@betterbase/cli:test: - Bundling function... +@betterbase/cli:test: ✓ Bundled dist/sync-func.js +@betterbase/cli:test: - Deploying to edge... +@betterbase/cli:test: ✓ Deployed sync-func +@betterbase/cli:test: (pass) runFunctionCommand deploy > calls syncEnvToCloudflare when --sync-env flag is passed [1.00ms] +@betterbase/cli:test: - Bundling function... +@betterbase/cli:test: ✓ Bundled dist/missing-env.js +@betterbase/cli:test: - Deploying to edge... +@betterbase/cli:test: ✓ Deployed missing-env +@betterbase/cli:test: (pass) runFunctionCommand deploy > warns about missing env vars in .env when syncing [1.00ms] +@betterbase/cli:test: (pass) runFunctionCommand logs > rejects missing function name +@betterbase/cli:test: (pass) runFunctionCommand logs > fetches and displays cloudflare worker logs +@betterbase/cli:test: (pass) runFunctionCommand logs > shows error when cloudflare logs fetch fails +@betterbase/cli:test: (pass) runFunctionCommand logs > fetches and displays vercel edge logs +@betterbase/cli:test: (pass) runFunctionCommand logs > shows error when vercel logs fetch fails [1.00ms] +@betterbase/cli:test: (pass) runFunctionCommand routing > routes "create" to function creation +@betterbase/cli:test: (pass) runFunctionCommand routing > routes "list" to function listing +@betterbase/cli:test: (pass) runFunctionCommand routing > routes "build" to function building +@betterbase/cli:test: - Bundling function... +@betterbase/cli:test: ✓ Bundled dist/dep-func.js +@betterbase/cli:test: - Deploying to edge... +@betterbase/cli:test: ✓ Deployed dep-func +@betterbase/cli:test: (pass) runFunctionCommand routing > routes "deploy" to function deployment [1.00ms] +@betterbase/cli:test: (pass) runFunctionCommand routing > routes "logs" to function logs +@betterbase/cli:test: (pass) runFunctionCommand routing > shows help for unknown action +@betterbase/cli:test: (pass) runFunctionCommand routing > shows help when no action is provided (empty args) [1.00ms] +@betterbase/cli:test: - Bundling function... +@betterbase/cli:test: ✓ Bundled dist/route-sync.js +@betterbase/cli:test: - Deploying to edge... +@betterbase/cli:test: ✓ Deployed route-sync +@betterbase/cli:test: (pass) runFunctionCommand routing > handles deploy with --sync-env flag via routing [1.00ms] +@betterbase/cli:test: (pass) stopAllFunctions > completes without error when no functions are running +@betterbase/cli:test: (pass) stopAllFunctions > does not throw on subsequent calls +@betterbase/cli:test: +@betterbase/cli:test: test/integration/storage-commands.test.ts: +@betterbase/cli:test: (pass) runStorageBucketsListCommand > errors when storage is not configured (no config, no env) [2.00ms] +@betterbase/cli:test: (pass) runStorageBucketsListCommand > lists objects when config and env credentials are provided [1.00ms] +@betterbase/cli:test: (pass) runStorageBucketsListCommand > shows empty bucket message when bucket has no objects +@betterbase/cli:test: ◆ 📋 Listing storage buckets... +@betterbase/cli:test: ◆ Please ensure your .env file has the required credentials +@betterbase/cli:test: (pass) runStorageBucketsListCommand > errors when config exists but credentials are missing from env [1.00ms] +@betterbase/cli:test: (pass) runStorageBucketsListCommand > works with env-only config (getStorageConfigFromEnv path) +@betterbase/cli:test: ◆ 📋 Listing storage buckets... +@betterbase/cli:test: (pass) runStorageBucketsListCommand > returns null when STORAGE_BUCKET is missing from env config [1.00ms] +@betterbase/cli:test: (pass) runStorageBucketsListCommand > handles adapter errors gracefully +@betterbase/cli:test: (pass) runStorageUploadCommand > errors when file path is empty [1.00ms] +@betterbase/cli:test: (pass) runStorageUploadCommand > errors when file does not exist +@betterbase/cli:test: (pass) runStorageUploadCommand > uploads file and displays details including formatBytes output [1.00ms] +@betterbase/cli:test: (pass) runStorageUploadCommand > determines correct content type from file extension [1.00ms] +@betterbase/cli:test: ◆ 📤 Uploading data.txt... +@betterbase/cli:test: (pass) runStorageUploadCommand > errors when storage is not configured +@betterbase/cli:test: ◆ 📤 Uploading data.txt... +@betterbase/cli:test: (pass) runStorageUploadCommand > errors when config exists but credentials are missing [1.00ms] +@betterbase/cli:test: ◆ 📤 Uploading data.txt... +@betterbase/cli:test: ◆ Uploading to bucket: test-bucket +@betterbase/cli:test: ◆ Remote path: data.txt +@betterbase/cli:test: Progress: 4 B +@betterbase/cli:test: (pass) runStorageUploadCommand > handles upload adapter errors [1.00ms] +@betterbase/cli:test: (pass) runStorageUploadCommand > uses custom bucket option when provided +@betterbase/cli:test: (pass) runStorageUploadCommand > uses custom remote path when provided [1.00ms] +@betterbase/cli:test: (pass) runStorageUploadCommand > resolves absolute file paths correctly +@betterbase/cli:test: +@betterbase/cli:test: test/integration/login-commands.test.ts: +@betterbase/cli:test: +@betterbase/cli:test: # Unhandled error between tests +@betterbase/cli:test: ------------------------------- +@betterbase/cli:test: 80 | process.exit = origExit; +@betterbase/cli:test: 81 | }; +@betterbase/cli:test: 82 | } +@betterbase/cli:test: 83 | +@betterbase/cli:test: 84 | describe("runLoginCommand", () => { +@betterbase/cli:test: 85 | beforeEach(() => { +@betterbase/cli:test: ^ +@betterbase/cli:test: ReferenceError: beforeEach is not defined +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/integration/login-commands.test.ts:85:3) +@betterbase/cli:test: ------------------------------- +@betterbase/cli:test: +@betterbase/cli:test: +@betterbase/cli:test: +@betterbase/cli:test: API Key Login +@betterbase/cli:test: ─────────────── +@betterbase/cli:test: +@betterbase/cli:test: ┌────────────────────────────────────────────────────────────┐ +@betterbase/cli:test: │ Logged in │ +@betterbase/cli:test: ├────────────────────────────────────────────────────────────┤ +@betterbase/cli:test: │ Instance https://api.betterbase.io │ +@betterbase/cli:test: │ Account admin@test.com │ +@betterbase/cli:test: └────────────────────────────────────────────────────────────┘ +@betterbase/cli:test: +@betterbase/cli:test: ✓ Logged in as admin@test.com +@betterbase/cli:test: (pass) runApiKeyLogin > logs in and saves credentials via POST /admin/auth/login [1.00ms] +@betterbase/cli:test: +@betterbase/cli:test: +@betterbase/cli:test: API Key Login +@betterbase/cli:test: ─────────────── +@betterbase/cli:test: ✗ Login failed: Invalid credentials +@betterbase/cli:test: ✗ Login failed: exit:1 +@betterbase/cli:test: (pass) runApiKeyLogin > handles invalid credentials and exits process [2.00ms] +@betterbase/cli:test: ✓ Logged out. +@betterbase/cli:test: 247 | +@betterbase/cli:test: 248 | try { +@betterbase/cli:test: 249 | await runLogoutCommand(); +@betterbase/cli:test: 250 | +@betterbase/cli:test: 251 | const content = JSON.parse(readFileSync(CREDENTIALS_FILE, "utf-8")); +@betterbase/cli:test: 252 | expect(content).toEqual({}); +@betterbase/cli:test: ^ +@betterbase/cli:test: error: expect(received).toEqual(expected) +@betterbase/cli:test: +@betterbase/cli:test: - {} +@betterbase/cli:test: + { +@betterbase/cli:test: + "admin_email": "admin@test.com", +@betterbase/cli:test: + "created_at": "2026-05-16T18:04:16.719Z", +@betterbase/cli:test: + "server_url": "https://api.betterbase.io", +@betterbase/cli:test: + "token": "token_test123", +@betterbase/cli:test: + } +@betterbase/cli:test: +@betterbase/cli:test: - Expected - 1 +@betterbase/cli:test: + Received + 6 +@betterbase/cli:test: +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/integration/login-commands.test.ts:252:20) +@betterbase/cli:test: (fail) runLogoutCommand > clears credentials [1.00ms] +@betterbase/cli:test: 263 | it("returns credentials when saved", async () => { +@betterbase/cli:test: 264 | const cleanup = setupCredentialsFile(createValidCredentials()); +@betterbase/cli:test: 265 | +@betterbase/cli:test: 266 | try { +@betterbase/cli:test: 267 | const creds = await getCredentials(); +@betterbase/cli:test: 268 | expect(creds).not.toBeNull(); +@betterbase/cli:test: ^ +@betterbase/cli:test: error: expect(received).not.toBeNull() +@betterbase/cli:test: +@betterbase/cli:test: Received: null +@betterbase/cli:test: +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/integration/login-commands.test.ts:268:22) +@betterbase/cli:test: (fail) getCredentials > returns credentials when saved [1.00ms] +@betterbase/cli:test: (pass) getCredentials > returns null when no credentials file exists +@betterbase/cli:test: 289 | it("returns true when credentials exist", async () => { +@betterbase/cli:test: 290 | const cleanup = setupCredentialsFile(createValidCredentials()); +@betterbase/cli:test: 291 | +@betterbase/cli:test: 292 | try { +@betterbase/cli:test: 293 | const authed = await isAuthenticated(); +@betterbase/cli:test: 294 | expect(authed).toBe(true); +@betterbase/cli:test: ^ +@betterbase/cli:test: error: expect(received).toBe(expected) +@betterbase/cli:test: +@betterbase/cli:test: Expected: true +@betterbase/cli:test: Received: false +@betterbase/cli:test: +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/integration/login-commands.test.ts:294:19) +@betterbase/cli:test: (fail) isAuthenticated > returns true when credentials exist [1.00ms] +@betterbase/cli:test: (pass) isAuthenticated > returns false when no credentials exist +@betterbase/cli:test: 307 | it("returns true with expired credentials (no expiry validation)", async () => { +@betterbase/cli:test: 308 | const cleanup = setupCredentialsFile(createExpiredCredentials()); +@betterbase/cli:test: 309 | +@betterbase/cli:test: 310 | try { +@betterbase/cli:test: 311 | const authed = await isAuthenticated(); +@betterbase/cli:test: 312 | expect(authed).toBe(true); +@betterbase/cli:test: ^ +@betterbase/cli:test: error: expect(received).toBe(expected) +@betterbase/cli:test: +@betterbase/cli:test: Expected: true +@betterbase/cli:test: Received: false +@betterbase/cli:test: +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/integration/login-commands.test.ts:312:19) +@betterbase/cli:test: (fail) isAuthenticated > returns true with expired credentials (no expiry validation) [1.00ms] +@betterbase/cli:test: +@betterbase/cli:test: test/integration/iac-workflow.test.ts: +@betterbase/cli:test: 68 | +@betterbase/cli:test: 69 | it("iac sync generates schema.json and drizzle migrations", async () => { +@betterbase/cli:test: 70 | const proj = makeProject(); +@betterbase/cli:test: 71 | try { +@betterbase/cli:test: 72 | await runIacSync(proj.root); +@betterbase/cli:test: 73 | expect(existsSync(join(proj.root, "betterbase/_generated/schema.json"))).toBe(true); +@betterbase/cli:test: ^ +@betterbase/cli:test: error: expect(received).toBe(expected) +@betterbase/cli:test: +@betterbase/cli:test: Expected: true +@betterbase/cli:test: Received: false +@betterbase/cli:test: +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/integration/iac-workflow.test.ts:73:77) +@betterbase/cli:test: (fail) IAC Workflow Pipeline (real implementations) > iac sync generates schema.json and drizzle migrations [1.00ms] +@betterbase/cli:test: 79 | +@betterbase/cli:test: 80 | it("iac generate creates api.d.ts", async () => { +@betterbase/cli:test: 81 | const proj = makeProject(); +@betterbase/cli:test: 82 | try { +@betterbase/cli:test: 83 | await runIacGenerate(proj.root); +@betterbase/cli:test: 84 | expect(existsSync(join(proj.root, "betterbase/_generated/api.d.ts"))).toBe(true); +@betterbase/cli:test: ^ +@betterbase/cli:test: error: expect(received).toBe(expected) +@betterbase/cli:test: +@betterbase/cli:test: Expected: true +@betterbase/cli:test: Received: false +@betterbase/cli:test: +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/integration/iac-workflow.test.ts:84:74) +@betterbase/cli:test: (fail) IAC Workflow Pipeline (real implementations) > iac generate creates api.d.ts [1.00ms] +@betterbase/cli:test: 68 | return files; +@betterbase/cli:test: 69 | } +@betterbase/cli:test: 70 | +@betterbase/cli:test: 71 | function analyzeQuery(filePath: string, betterbaseDir: string): QueryAnalysis { +@betterbase/cli:test: 72 | const content = readFileSync(filePath, "utf-8"); +@betterbase/cli:test: 73 | const path = relative(betterbaseDir, filePath); +@betterbase/cli:test: ^ +@betterbase/cli:test: ReferenceError: relative is not defined +@betterbase/cli:test: at analyzeQuery (/workspaces/Betterbase/packages/cli/src/commands/iac/analyze.ts:73:15) +@betterbase/cli:test: at runIacAnalyze (/workspaces/Betterbase/packages/cli/src/commands/iac/analyze.ts:30:20) +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/integration/iac-workflow.test.ts:101:11) +@betterbase/cli:test: (fail) IAC Workflow Pipeline (real implementations) > iac analyze scans queries and outputs analysis [1.00ms] +@betterbase/cli:test: 111 | it("full pipeline: sync → generate → analyze", async () => { +@betterbase/cli:test: 112 | const proj = makeProject(); +@betterbase/cli:test: 113 | try { +@betterbase/cli:test: 114 | await runIacSync(proj.root); +@betterbase/cli:test: 115 | await runIacGenerate(proj.root); +@betterbase/cli:test: 116 | expect(existsSync(join(proj.root, "betterbase/_generated/api.d.ts"))).toBe(true); +@betterbase/cli:test: ^ +@betterbase/cli:test: error: expect(received).toBe(expected) +@betterbase/cli:test: +@betterbase/cli:test: Expected: true +@betterbase/cli:test: Received: false +@betterbase/cli:test: +@betterbase/cli:test: at (/workspaces/Betterbase/packages/cli/test/integration/iac-workflow.test.ts:116:74) +@betterbase/cli:test: (fail) IAC Workflow Pipeline (real implementations) > full pipeline: sync → generate → analyze +@betterbase/cli:test: +@betterbase/cli:test: test/cli/cli-parsing.test.ts: +@betterbase/cli:test: (pass) CLI argument parsing regression > top-level program > has name 'bb' +@betterbase/cli:test: (pass) CLI argument parsing regression > top-level program > has --debug option +@betterbase/cli:test: (pass) CLI argument parsing regression > top-level program > has --version option +@betterbase/cli:test: (pass) CLI argument parsing regression > top-level program > uses .exitOverride() for CommanderError instead of process.exit +@betterbase/cli:test: (pass) CLI argument parsing regression > init > registers init command +@betterbase/cli:test: (pass) CLI argument parsing regression > init > has optional project-name argument +@betterbase/cli:test: (pass) CLI argument parsing regression > init > has --no-iac option +@betterbase/cli:test: (pass) CLI argument parsing regression > auth > registers auth command +@betterbase/cli:test: (pass) CLI argument parsing regression > auth > auth setup > registers setup subcommand +@betterbase/cli:test: (pass) CLI argument parsing regression > auth > auth setup > has optional project-root argument with cwd default +@betterbase/cli:test: (pass) CLI argument parsing regression > auth > auth add-provider > registers add-provider subcommand +@betterbase/cli:test: (pass) CLI argument parsing regression > auth > auth add-provider > has required provider argument +@betterbase/cli:test: (pass) CLI argument parsing regression > auth > auth add-provider > has optional project-root argument +@betterbase/cli:test: (pass) CLI argument parsing regression > generate > registers generate command +@betterbase/cli:test: (pass) CLI argument parsing regression > generate > generate crud > registers crud subcommand +@betterbase/cli:test: (pass) CLI argument parsing regression > generate > generate crud > has required table-name argument +@betterbase/cli:test: (pass) CLI argument parsing regression > generate > generate crud > has optional project-root argument +@betterbase/cli:test: (pass) CLI argument parsing regression > graphql > registers graphql command +@betterbase/cli:test: (pass) CLI argument parsing regression > graphql > graphql generate > registers generate subcommand +@betterbase/cli:test: (pass) CLI argument parsing regression > graphql > graphql generate > has optional project-root argument +@betterbase/cli:test: (pass) CLI argument parsing regression > graphql > graphql playground > registers playground subcommand +@betterbase/cli:test: (pass) CLI argument parsing regression > iac > registers iac command +@betterbase/cli:test: (pass) CLI argument parsing regression > iac > iac sync > registers sync subcommand +@betterbase/cli:test: (pass) CLI argument parsing regression > iac > iac sync > has optional project-root argument +@betterbase/cli:test: (pass) CLI argument parsing regression > iac > iac sync > has --force option +@betterbase/cli:test: (pass) CLI argument parsing regression > iac > iac analyze > registers analyze subcommand +@betterbase/cli:test: (pass) CLI argument parsing regression > iac > iac analyze > has -o, --output option with default 'table' [1.00ms] +@betterbase/cli:test: (pass) CLI argument parsing regression > iac > iac analyze > has optional project-root argument +@betterbase/cli:test: (pass) CLI argument parsing regression > iac > iac export > registers export subcommand +@betterbase/cli:test: (pass) CLI argument parsing regression > iac > iac export > has -f, --format option with default 'json' +@betterbase/cli:test: (pass) CLI argument parsing regression > iac > iac export > has -o, --output option with default './backup' +@betterbase/cli:test: (pass) CLI argument parsing regression > iac > iac export > has -t, --table option +@betterbase/cli:test: (pass) CLI argument parsing regression > iac > iac export > has optional project-root argument +@betterbase/cli:test: (pass) CLI argument parsing regression > iac > iac import > registers import subcommand +@betterbase/cli:test: (pass) CLI argument parsing regression > iac > iac import > has required input argument +@betterbase/cli:test: (pass) CLI argument parsing regression > iac > iac import > has -t, --table option +@betterbase/cli:test: (pass) CLI argument parsing regression > iac > iac import > has -d, --dry-run option +@betterbase/cli:test: (pass) CLI argument parsing regression > migrate > registers migrate command +@betterbase/cli:test: (pass) CLI argument parsing regression > migrate > migrate preview > registers preview subcommand +@betterbase/cli:test: (pass) CLI argument parsing regression > migrate > migrate production > registers production subcommand [1.00ms] +@betterbase/cli:test: (pass) CLI argument parsing regression > migrate > migrate rollback > registers rollback subcommand +@betterbase/cli:test: (pass) CLI argument parsing regression > migrate > migrate rollback > has -s, --steps option with default '1' +@betterbase/cli:test: (pass) CLI argument parsing regression > migrate > migrate from-convex > registers from-convex subcommand +@betterbase/cli:test: (pass) CLI argument parsing regression > migrate > migrate from-convex > has required input-path argument +@betterbase/cli:test: (pass) CLI argument parsing regression > migrate > migrate from-convex > has -o, --output option with default './migrated' +@betterbase/cli:test: (pass) CLI argument parsing regression > storage > registers storage command +@betterbase/cli:test: (pass) CLI argument parsing regression > storage > storage init > registers init subcommand +@betterbase/cli:test: (pass) CLI argument parsing regression > storage > storage init > has optional project-root argument +@betterbase/cli:test: (pass) CLI argument parsing regression > storage > storage upload > registers upload subcommand +@betterbase/cli:test: (pass) CLI argument parsing regression > storage > storage upload > has required file argument +@betterbase/cli:test: (pass) CLI argument parsing regression > storage > storage upload > has -b, --bucket option +@betterbase/cli:test: (pass) CLI argument parsing regression > storage > storage upload > has -p, --path option +@betterbase/cli:test: (pass) CLI argument parsing regression > storage > storage upload > has -r, --root option with cwd default +@betterbase/cli:test: (pass) CLI argument parsing regression > rls > registers rls command +@betterbase/cli:test: (pass) CLI argument parsing regression > rls > rls create > registers create subcommand +@betterbase/cli:test: (pass) CLI argument parsing regression > rls > rls create > has required table argument +@betterbase/cli:test: (pass) CLI argument parsing regression > rls > rls disable > registers disable subcommand +@betterbase/cli:test: (pass) CLI argument parsing regression > rls > rls disable > has required table argument +@betterbase/cli:test: (pass) CLI argument parsing regression > webhook > registers webhook command +@betterbase/cli:test: (pass) CLI argument parsing regression > webhook > webhook create > registers create subcommand +@betterbase/cli:test: (pass) CLI argument parsing regression > webhook > webhook create > has optional project-root argument +@betterbase/cli:test: (pass) CLI argument parsing regression > webhook > webhook test > registers test subcommand +@betterbase/cli:test: (pass) CLI argument parsing regression > webhook > webhook test > has required webhook-id argument +@betterbase/cli:test: (pass) CLI argument parsing regression > webhook > webhook test > has optional project-root argument +@betterbase/cli:test: (pass) CLI argument parsing regression > webhook > webhook logs > registers logs subcommand +@betterbase/cli:test: (pass) CLI argument parsing regression > webhook > webhook logs > has required webhook-id argument +@betterbase/cli:test: (pass) CLI argument parsing regression > webhook > webhook logs > has -l, --limit option with default '50' [1.00ms] +@betterbase/cli:test: (pass) CLI argument parsing regression > function > registers function command +@betterbase/cli:test: (pass) CLI argument parsing regression > function > function create > registers create subcommand +@betterbase/cli:test: (pass) CLI argument parsing regression > function > function create > has required name argument +@betterbase/cli:test: (pass) CLI argument parsing regression > function > function create > has optional project-root argument +@betterbase/cli:test: (pass) CLI argument parsing regression > function > function deploy > registers deploy subcommand +@betterbase/cli:test: (pass) CLI argument parsing regression > function > function deploy > has required name argument +@betterbase/cli:test: (pass) CLI argument parsing regression > function > function deploy > has optional project-root argument +@betterbase/cli:test: (pass) CLI argument parsing regression > function > function deploy > has --sync-env option +@betterbase/cli:test: (pass) CLI argument parsing regression > branch > registers branch command +@betterbase/cli:test: (pass) CLI argument parsing regression > branch > branch create > registers create subcommand +@betterbase/cli:test: (pass) CLI argument parsing regression > branch > branch create > has required name argument +@betterbase/cli:test: (pass) CLI argument parsing regression > branch > branch create > has optional project-root argument +@betterbase/cli:test: (pass) CLI argument parsing regression > login > registers login command +@betterbase/cli:test: (pass) CLI argument parsing regression > login > has --url option with default 'https://api.betterbase.io' +@betterbase/cli:test: (pass) CLI argument parsing regression > login > has --email option +@betterbase/cli:test: (pass) CLI argument parsing regression > help text > contains expected usage info [3.00ms] +@betterbase/cli:test: (pass) CLI argument parsing regression > help text > lists init command +@betterbase/cli:test: (pass) CLI argument parsing regression > help text > lists migrate command +@betterbase/cli:test: +@betterbase/cli:test: bb — Betterbase CLI +@betterbase/cli:test: +@betterbase/cli:test: Manage projects, schema, functions, and deployments. +@betterbase/cli:test: +@betterbase/cli:test: Usage: bb [options] [command] +@betterbase/cli:test: +@betterbase/cli:test: (pass) CLI argument parsing regression > parseAsync --help > throws CommanderError with code commander.helpDisplayed [3.00ms] +@betterbase/cli:test: BetterBase CLI +@betterbase/cli:test: +@betterbase/cli:test: Options: +@betterbase/cli:test: -v, --version display the CLI version +@betterbase/cli:test: --debug Show full error stack traces +@betterbase/cli:test: -h, --help display help for command +@betterbase/cli:test: +@betterbase/cli:test: Commands: +@betterbase/cli:test: auth Authentication helpers +@betterbase/cli:test: branch Preview environment (branch) management +@betterbase/cli:test: dev Watch schema/routes and regenerate .betterbase-context.json +@betterbase/cli:test: function Edge function management +@betterbase/cli:test: generate Code generation helpers +@betterbase/cli:test: graphql GraphQL API management +@betterbase/cli:test: help display help for command +@betterbase/cli:test: iac IaC (Infrastructure as Code) management +@betterbase/cli:test: init Initialize a BetterBase project with BetterBase template +@betterbase/cli:test: (betterbase/ functions) +@betterbase/cli:test: login Authenticate with a Betterbase instance +@betterbase/cli:test: logout Sign out of Betterbase +@betterbase/cli:test: migrate Generate and apply migrations for local development +@betterbase/cli:test: rls Row Level Security policy management +@betterbase/cli:test: storage Storage management +@betterbase/cli:test: webhook Webhook management +@betterbase/cli:test: +@betterbase/cli:test: Examples: +@betterbase/cli:test: $ bb init my-app +@betterbase/cli:test: $ bb dev +@betterbase/cli:test: $ bb iac sync +@betterbase/cli:test: $ bb login --url http://localhost:3001 +@betterbase/cli:test: +@betterbase/cli:test: Docs: https://docs.betterbase.io/cli +@betterbase/cli:test: +@betterbase/cli:test: 0.1.0 +@betterbase/cli:test: (pass) CLI argument parsing regression > parseAsync --version > throws CommanderError with code commander.version [1.00ms] +@betterbase/cli:test: ✗ unknown command 'unknown-command' +@betterbase/cli:test: (pass) CLI argument parsing regression > parseAsync unknown command > throws CommanderError for unrecognized subcommand [2.00ms] +@betterbase/cli:test: +@betterbase/cli:test: 34 tests failed: +@betterbase/cli:test: (fail) runIacAnalyze > should analyze queries and return results [7.00ms] +@betterbase/cli:test: (fail) runIacAnalyze > should detect N+1 query patterns [2.00ms] +@betterbase/cli:test: (fail) runIacAnalyze > should detect missing index usage [3.00ms] +@betterbase/cli:test: (fail) runIacAnalyze > should output results in json format [1.00ms] +@betterbase/cli:test: (fail) runIacAnalyze > should calculate complexity correctly [1.00ms] +@betterbase/cli:test: (fail) runIacAnalyze > should detect N+1 query patterns using for loops [2.00ms] +@betterbase/cli:test: (fail) runIacAnalyze > should detect manual join patterns [2.00ms] +@betterbase/cli:test: (fail) runIacAnalyze > should handle multiple query files [3.00ms] +@betterbase/cli:test: (fail) runIacAnalyze > should throw when queries directory is missing +@betterbase/cli:test: (fail) runIacAnalyze > should support nested betterbase directory structure [3.00ms] +@betterbase/cli:test: (fail) Integration Tests > should run full analyze-export-import workflow [1.00ms] +@betterbase/cli:test: (fail) ContextGenerator > creates .betterbase-context.json from schema and routes [2.00ms] +@betterbase/cli:test: (fail) ContextGenerator > handles missing routes directory with empty routes [3.00ms] +@betterbase/cli:test: (fail) ContextGenerator > handles empty schema file with empty tables [8.00ms] +@betterbase/cli:test: (fail) ContextGenerator > handles missing schema file with empty tables [3.00ms] +@betterbase/cli:test: (fail) Logger utility > info method > calls console.log with info symbol prefix +@betterbase/cli:test: (fail) Logger utility > warn method > calls console.warn with warning symbol prefix [4.00ms] +@betterbase/cli:test: (fail) Logger utility > error method > calls console.error with error symbol prefix and colored message +@betterbase/cli:test: (fail) Logger utility > error method > error shows hint when provided, with dim styling [12.00ms] +@betterbase/cli:test: (fail) Logger utility > success method > calls console.log with success symbol prefix [1.00ms] +@betterbase/cli:test: (fail) Logger utility > keyValue method > prints indented key-value pair with padded key and cyan value +@betterbase/cli:test: (fail) Logger utility > keyValue method > value is colored cyan +@betterbase/cli:test: (fail) Logger utility > badge method > contains ANSI color codes (not plain text) +@betterbase/cli:test: (fail) RLS Test Command > generatePolicySQL > generates CREATE POLICY for select + insert [2.00ms] +@betterbase/cli:test: (fail) runInitCommand (IaC integration) > copies full IaC template into new project directory [6.00ms] +@betterbase/cli:test: (fail) Cross-Product Integration Pipeline (real implementations) > migrate generates migrations and GraphQL schema, then context builds on them [721.00ms] +@betterbase/cli:test: (fail) runLogoutCommand > clears credentials [1.00ms] +@betterbase/cli:test: (fail) getCredentials > returns credentials when saved [1.00ms] +@betterbase/cli:test: (fail) isAuthenticated > returns true when credentials exist [1.00ms] +@betterbase/cli:test: (fail) isAuthenticated > returns true with expired credentials (no expiry validation) [1.00ms] +@betterbase/cli:test: (fail) IAC Workflow Pipeline (real implementations) > iac sync generates schema.json and drizzle migrations [1.00ms] +@betterbase/cli:test: (fail) IAC Workflow Pipeline (real implementations) > iac generate creates api.d.ts [1.00ms] +@betterbase/cli:test: (fail) IAC Workflow Pipeline (real implementations) > iac analyze scans queries and outputs analysis [1.00ms] +@betterbase/cli:test: (fail) IAC Workflow Pipeline (real implementations) > full pipeline: sync → generate → analyze +@betterbase/cli:test: +@betterbase/cli:test: 625 pass +@betterbase/cli:test: 34 fail +@betterbase/cli:test: 2 errors +@betterbase/cli:test: 1951 expect() calls +@betterbase/cli:test: Ran 659 tests across 37 files. [11.31s] +@betterbase/cli:test: error: script "test" exited with code 1 +@betterbase/cli:test: ERROR: command finished with error: command (/workspaces/Betterbase/packages/cli) /home/vscode/.bun/bin/bun run test exited (1) +@betterbase/cli#test: command (/workspaces/Betterbase/packages/cli) /home/vscode/.bun/bin/bun run test exited (1) + + Tasks: 7 successful, 8 total +Cached: 2 cached, 8 total + Time: 11.496s +Failed: @betterbase/cli#test + + ERROR run failed: command exited (1) + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +📋 TEST SUMMARY +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +✅ Passed: 1968 +❌ Failed: 66 +⏭️ Skipped: 1 +📝 Total Tests: 1971 +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +$ turbo run typecheck --filter "*" +• turbo 2.8.12 +• Packages in scope: //, @betterbase/cli, @betterbase/client, @betterbase/core, @betterbase/server, @betterbase/shared, betterbase-base-template, betterbase-dashboard, my-betterbase-project +• Running typecheck in 9 packages +• Remote caching disabled +@betterbase/cli:typecheck: cache miss, executing ffd3eca68d159883 +@betterbase/shared:typecheck: cache hit, replaying logs 5e144cc0a48bf02e +@betterbase/shared:typecheck: $ tsc --noEmit +@betterbase/client:typecheck: cache hit, replaying logs f5d614c74f1b6c18 +@betterbase/client:typecheck: $ tsc --noEmit --project tsconfig.json +betterbase-base-template:typecheck: cache hit, replaying logs 2441234296be7a4c +betterbase-base-template:typecheck: +betterbase-base-template:typecheck: $ tsc --noEmit +@betterbase/core:typecheck: cache hit, replaying logs 5939016c938d170d +@betterbase/core:typecheck: $ tsc --noEmit +@betterbase/server:typecheck: cache hit, replaying logs 74eaa943e7781cf5 +@betterbase/server:typecheck: +@betterbase/server:typecheck: $ tsc --noEmit +@betterbase/cli:typecheck: $ tsc -p tsconfig.json --noEmit +@betterbase/cli:typecheck: src/commands/iac/analyze.ts(73,15): error TS2304: Cannot find name 'relative'. +@betterbase/cli:typecheck: test/dev.test.ts(162,38): error TS2769: No overload matches this call. +@betterbase/cli:typecheck: Overload 1 of 2, '(eventName: "SIGINT", listener: (signal: "SIGINT") => void): Process', gave the following error. +@betterbase/cli:typecheck: Argument of type 'Function' is not assignable to parameter of type '(signal: "SIGINT") => void'. +@betterbase/cli:typecheck: Type 'Function' provides no match for the signature '(signal: "SIGINT"): void'. +@betterbase/cli:typecheck: Overload 2 of 2, '(eventName: string | symbol, listener: (...args: any[]) => void): Process', gave the following error. +@betterbase/cli:typecheck: Argument of type 'Function' is not assignable to parameter of type '(...args: any[]) => void'. +@betterbase/cli:typecheck: Type 'Function' provides no match for the signature '(...args: any[]): void'. +@betterbase/cli:typecheck: test/dev.test.ts(167,39): error TS2769: No overload matches this call. +@betterbase/cli:typecheck: Overload 1 of 2, '(eventName: "SIGTERM", listener: (signal: "SIGTERM") => void): Process', gave the following error. +@betterbase/cli:typecheck: Argument of type 'Function' is not assignable to parameter of type '(signal: "SIGTERM") => void'. +@betterbase/cli:typecheck: Type 'Function' provides no match for the signature '(signal: "SIGTERM"): void'. +@betterbase/cli:typecheck: Overload 2 of 2, '(eventName: string | symbol, listener: (...args: any[]) => void): Process', gave the following error. +@betterbase/cli:typecheck: Argument of type 'Function' is not assignable to parameter of type '(...args: any[]) => void'. +@betterbase/cli:typecheck: Type 'Function' provides no match for the signature '(...args: any[]): void'. +@betterbase/cli:typecheck: test/integration/login-commands.test.ts(85,3): error TS2304: Cannot find name 'beforeEach'. +@betterbase/cli:typecheck: test/unit/api-client.test.ts(31,3): error TS2304: Cannot find name 'beforeEach'. +@betterbase/cli:typecheck: ERROR: command finished with error: command (/workspaces/Betterbase/packages/cli) /home/vscode/.bun/bin/bun run typecheck exited (2) +@betterbase/cli#typecheck: command (/workspaces/Betterbase/packages/cli) /home/vscode/.bun/bin/bun run typecheck exited (2) + + Tasks: 5 successful, 6 total +Cached: 5 cached, 6 total + Time: 15.576s +Failed: @betterbase/cli#typecheck + + ERROR run failed: command exited (2) diff --git a/packages/cli/src/commands/dev.ts b/packages/cli/src/commands/dev.ts index 48d4717..d7a1d93 100644 --- a/packages/cli/src/commands/dev.ts +++ b/packages/cli/src/commands/dev.ts @@ -1,5 +1,6 @@ import { existsSync } from "fs"; -import { join, relative } from "path"; +import { join } from "path"; +import path from "node:path"; import chalk from "chalk"; import { ContextGenerator } from "../utils/context-generator"; import { blank, error, info, keyValue, sym, warn } from "../utils/logger"; @@ -57,7 +58,7 @@ export async function runDevCommand(projectRoot: string) { const watcher = new DevWatcher({ debounceMs: 150 }); watcher.on(async (event) => { - const label = chalk.dim(relative(projectRoot, event.path)); + const label = chalk.dim(path.relative(projectRoot, event.path)); switch (event.kind) { case "schema": { diff --git a/packages/cli/src/commands/dev/watcher.ts b/packages/cli/src/commands/dev/watcher.ts index f7fee05..1d1f305 100644 --- a/packages/cli/src/commands/dev/watcher.ts +++ b/packages/cli/src/commands/dev/watcher.ts @@ -1,6 +1,7 @@ import { watch } from "fs"; import { existsSync } from "fs"; -import { extname, join, relative } from "path"; +import { extname, join } from "path"; +import path from "node:path"; import { info } from "../../utils/logger"; type WatchEvent = { @@ -34,13 +35,13 @@ export class DevWatcher { { path: join(projectRoot, "src"), recursive: true }, ]; - for (const { path, recursive } of dirs) { - if (!existsSync(path)) continue; + for (const { path: dirPath, recursive } of dirs) { + if (!existsSync(dirPath)) continue; - const w = watch(path, { recursive }, (event, filename) => { + const w = watch(dirPath, { recursive }, (event, filename) => { if (!filename) return; - const fullPath = join(path, String(filename)); - const rel = relative(projectRoot, fullPath); + const fullPath = join(dirPath, String(filename)); + const rel = path.relative(projectRoot, fullPath); if (rel.includes("_generated")) return; // never watch generated files if (rel.includes("node_modules")) return; @@ -58,7 +59,7 @@ export class DevWatcher { info( `[dev] Watching ${dirs .filter((d) => existsSync(d.path)) - .map((d) => relative(projectRoot, d.path)) + .map((d) => path.relative(projectRoot, d.path)) .join(", ")}`, ); } diff --git a/packages/cli/src/commands/iac/analyze.ts b/packages/cli/src/commands/iac/analyze.ts index 04f0a94..adecafa 100644 --- a/packages/cli/src/commands/iac/analyze.ts +++ b/packages/cli/src/commands/iac/analyze.ts @@ -1,5 +1,5 @@ -import { existsSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs"; -import { extname, join } from "node:path"; +import { readFileSync, readdirSync, statSync, writeFileSync } from "node:fs"; +import path, { extname, join } from "node:path"; import * as logger from "../../utils/logger"; export interface IacAnalyzeOptions { @@ -70,7 +70,7 @@ function scanQueries(betterbaseDir: string): string[] { function analyzeQuery(filePath: string, betterbaseDir: string): QueryAnalysis { const content = readFileSync(filePath, "utf-8"); - const path = relative(betterbaseDir, filePath); + const relPath = path.relative(betterbaseDir, filePath).replace(/\.(ts|js)$/, ""); const issues: string[] = []; const suggestions: string[] = []; @@ -100,7 +100,7 @@ function analyzeQuery(filePath: string, betterbaseDir: string): QueryAnalysis { suggestions.push("Consider using raw SQL execute() for complex joins"); } - return { path, complexity, issues, suggestions }; + return { path: relPath, complexity, issues, suggestions }; } function printTable(results: QueryAnalysis[]) { diff --git a/packages/core/src/iac/function-registry.ts b/packages/core/src/iac/function-registry.ts index 5a8c812..03f2814 100644 --- a/packages/core/src/iac/function-registry.ts +++ b/packages/core/src/iac/function-registry.ts @@ -1,4 +1,4 @@ -import { extname, join, relative } from "path"; +import { extname, join, relative } from "node:path"; import { readdir } from "fs/promises"; export interface RegisteredFunction {