Skip to main content

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 - _id property type inference
  • _base.repo.ts - Mongoose document generic type inference

These don't affect runtime behavior.

Step 7: Test Critical Paths

  1. Authentication - Sign in, create API keys
  2. CRUD operations - Create, read, update entities
  3. Archive/restore - Test soft delete functionality
  4. Permissions - Verify role-based access control
  5. 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