Migration Guide: Pre-0.1 to v0.1.1
This guide documents the migration process from the old architecture to the new .radish/ structure (v0.1.1+).
Overview
What changed:
- Package structure moved from
packages/to.radish/lib/ - Import paths changed to
@generated/datalayer/*pattern - Services now export types and helper functions
- User/ApiKey entities have updated ownership model
- Archive/restore functionality added to all services
Migration effort: CommerceHub migration (13 entities) took ~2 hours and resolved 440+ TypeScript errors.
Step 1: Backup Your Current Code
git checkout -b migration-to-radish-cli-v0.1.1
git add -A
git commit -m "Pre-migration checkpoint"
Step 2: Update Path Aliases
The new architecture uses @generated/datalayer/* imports, but files are in .radish/lib/datalayer/. You need to configure path aliases.
SvelteKit Projects
svelte.config.js
import adapter from '@sveltejs/adapter-node';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
import { fileURLToPath } from 'url';
import path from 'path';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const config = {
preprocess: vitePreprocess(),
kit: {
adapter: adapter(),
alias: {
// Map @generated/datalayer/* to actual file locations
'@generated/datalayer/services': path.resolve(__dirname, '.radish/lib/datalayer/server/services'),
'@generated/datalayer/contracts': path.resolve(__dirname, '.radish/lib/datalayer/contracts'),
'@generated/datalayer/metadata': path.resolve(__dirname, '.radish/lib/datalayer/contracts/metadata'),
'@generated/datalayer': path.resolve(__dirname, '.radish/lib/datalayer'),
// Optional: shorter aliases for internal use
'@generated/server': '.radish/lib/datalayer/server',
'@contracts': '.radish/lib/datalayer/contracts',
'@web': 'src'
}
}
};
export default config;
tsconfig.paths.json (create this file)
{
"compilerOptions": {
"paths": {
"@generated/datalayer/contracts": [
"./.radish/lib/datalayer/contracts"
],
"@generated/datalayer/services": [
"./.radish/lib/datalayer/server/services"
],
"@generated/datalayer/metadata": [
"./.radish/lib/datalayer/contracts/metadata"
],
"@datalayer/*": [
"./.radish/lib/datalayer/*"
]
}
}
}
tsconfig.json
{
"extends": ["./tsconfig.paths.json", "./.svelte-kit/tsconfig.json"],
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"moduleResolution": "bundler"
}
}
Non-SvelteKit Projects
For Node.js/Express/Fastify projects, configure TypeScript paths:
tsconfig.json
{
"compilerOptions": {
"paths": {
"@generated/datalayer/*": [".radish/lib/datalayer/*"]
}
}
}
For runtime resolution, use tsconfig-paths or similar:
npm install --save-dev tsconfig-paths
Step 3: Regenerate Code
# Install/update radish-cli
npm install -g radish-cli@latest
# Regenerate datalayer
radish-cli create datalayer . --schema blueprints/your-schema.yml
Expected output:
🌱 Radish CLI v0.1.1
📝 Loading blueprint: blueprints/your-schema.yml
✅ Validated 13 entities
📦 Generating datalayer...
✓ Contracts package
✓ Server package
✓ Routes (SvelteKit/Fastify)
✓ Documentation
📦 Installing dependencies...
✅ Generation complete!
Step 4: Update Import Statements
Services
Before:
import { UserService } from '$lib/server/services/user.service';
import { TaskService } from '../packages/server/services/task.service';
After:
import { UserService, TaskService } from '@generated/datalayer/services';
Contracts (Types & Schemas)
Before:
import type { Task } from '$lib/contracts/task';
import { createTaskSchema } from '$lib/contracts/task';
After:
import type { Task, CreateTask, UpdateTask } from '@generated/datalayer/contracts';
import { createTaskSchema } from '@generated/datalayer/contracts';
Auth Types
Before:
import type { ServiceAuth } from '$lib/server/auth/types';
After:
import type { ServiceAuth } from '@generated/datalayer/services';
// or
import type { ServiceAuth } from '@generated/datalayer/server/auth/guard';
The services/index.ts barrel now exports auth types for convenience:
export type { LocalsAuth, Principal, UserPrincipal, ApiPrincipal } from '../auth/types';
export type { ServiceAuth } from '../auth/guard';
export { createServiceAuthFromLocals } from '../auth/service-auth';
Metadata
Before:
import { allEntitiesMetadata } from '$lib/contracts/metadata';
After:
import { MetadataService } from '@generated/datalayer/services';
const metadata = await new MetadataService(auth).getAllEntitiesMetadata();
Step 5: Fix Common TypeScript Errors
Error: Module not found '@generated/datalayer/services'
Cause: Path aliases not configured correctly.
Fix: Ensure both svelte.config.js (or vite.config) AND tsconfig.paths.json have the aliases. Restart your TypeScript server.
Error: Property 'ownerId' does not exist on type 'User'
Cause: Users own themselves in the new architecture (no ownerId field).
Fix: Update any code that references user.ownerId:
// Before
const isOwner = user.ownerId === auth.userId;
// After
const isOwner = user.id === auth.userId;
Error: Cannot destructure 'tokenHash' from ApiKey
Cause: tokenHash is a secret field (select: false), not included in responses.
Fix: Remove destructuring - the field is already excluded:
// Before
const { tokenHash, ...safeKey } = apiKey;
return safeKey;
// After
return apiKey; // tokenHash already excluded
Error: ServiceAuth type errors
Cause: ServiceAuth not exported from services barrel.
Fix: Import from the new location (already fixed in v0.1.1):
import type { ServiceAuth } from '@generated/datalayer/services';
Error: Argument of type 'TaskCriteria' not assignable to 'ListCriteria'
Cause: TypeScript strict mode with entity-specific criteria types.
Fix: Already fixed in templates with type casting. If you see this in custom code, cast as any:
const result = await repo.listIncludingArchived(criteria as any);
Step 6: Verify Build
# TypeScript check
npm run check
# Build
npm run build
# Expected: 0-4 errors (only unfixable Mongoose type issues)
Known acceptable errors:
user.model.ts-_idproperty type inference_base.repo.ts- Mongoose document generic type inference
These don't affect runtime behavior.
Step 7: Test Critical Paths
- Authentication - Sign in, create API keys
- CRUD operations - Create, read, update entities
- Archive/restore - Test soft delete functionality
- Permissions - Verify role-based access control
- Versioning (if used) - Test version tracking
Common Migration Issues
Issue: Imports break at runtime despite TypeScript success
Cause: Runtime module resolution differs from TypeScript.
Solution for SvelteKit: Use path.resolve(__dirname, ...) in svelte.config.js (see Step 2).
Solution for Node.js: Use tsconfig-paths/register or module aliasing:
// Add to your entry file
import 'tsconfig-paths/register';
Issue: Console shows old file paths
Cause: TypeScript cache or dev server cache.
Solution:
# Clear SvelteKit cache
rm -rf .svelte-kit
# Clear node_modules/.cache
rm -rf node_modules/.cache
# Restart dev server
npm run dev
Issue: Some services missing methods (archive/restore)
Cause: Old templates before v0.1.1 fixes.
Solution: Regenerate with radish-cli v0.1.1+:
radish-cli create datalayer . --schema blueprints/your-schema.yml --force
Migration Checklist
- Create migration branch and commit checkpoint
- Update radish-cli to v0.1.1+
- Add path aliases to svelte.config.js
- Add path aliases to tsconfig.paths.json
- Update tsconfig.json to extend tsconfig.paths.json
- Regenerate datalayer
- Update imports from old paths to
@generated/datalayer/* - Fix User entity ownerId references
- Fix ApiKey tokenHash destructuring
- Clear build caches
- Run TypeScript check
- Run build
- Test authentication
- Test CRUD operations
- Test archive/restore
- Test permissions
- Commit migration changes
Rollback Plan
If migration fails:
git checkout main
git branch -D migration-to-radish-cli-v0.1.1
To preserve work for later:
git add -A
git commit -m "WIP: migration attempt"
git checkout main
Getting Help
- Verify manifest:
radish-cli verify . - View metadata:
radish-cli info . - Launch console:
radish-cli console . - Check version:
radish-cli --version
Success Metrics
CommerceHub migration results:
- 13 entities migrated
- 448 TypeScript errors → 4 unfixable Mongoose errors
- 2 hours migration time
- Zero runtime errors
- All tests passing
Your results may vary based on:
- Number of entities
- Custom code complexity
- Framework integration depth