Sonamu projects are written in TypeScript, with API and Web each having independent tsconfig.json files. They use configurations optimized for their respective environments.
Project Structure
API and Web are independent TypeScript projects. Their configurations are separate.
API Server Configuration
Base tsconfig.json
{
"compilerOptions" : {
/* Basic Options */
"target" : "esnext" ,
"module" : "esnext" ,
"outDir" : "dist" ,
"sourceMap" : true ,
"lib" : [ "esnext" , "dom" ],
/* Strict Type-Checking Options */
"strict" : true ,
"noImplicitAny" : true ,
"strictNullChecks" : true ,
"strictFunctionTypes" : true ,
"strictBindCallApply" : true ,
"strictPropertyInitialization" : true ,
"noImplicitThis" : true ,
"alwaysStrict" : true ,
/* Additional Checks */
"noUnusedLocals" : true ,
"noUnusedParameters" : true ,
"noImplicitReturns" : true ,
"noFallthroughCasesInSwitch" : true ,
"useUnknownInCatchVariables" : true ,
/* Module Resolution Options */
"moduleResolution" : "bundler" ,
"esModuleInterop" : true ,
/* Experimental Options */
"experimentalDecorators" : true ,
"emitDecoratorMetadata" : true ,
/* Advanced Options */
"forceConsistentCasingInFileNames" : true ,
"noErrorTruncation" : true ,
"resolveJsonModule" : true ,
"skipLibCheck" : true ,
"noUncheckedIndexedAccess" : true
},
"include" : [ "src/**/*.ts" , "src/**/*.json" ],
"exclude" : [
"node_modules" ,
"dist/*" ,
"public" ,
// "src/**/*.test.ts", // Test files also type-checked, so commented out
"**/__mocks__/**" ,
"vite.config.ts"
]
}
Key Options Explained
Module Settings
Decorators
Strict Mode
Additional Checks
{
"target" : "esnext" , // Use latest ECMAScript syntax
"module" : "esnext" , // Output ES modules
"moduleResolution" : "bundler" // Compatible with Vite/esbuild
}
moduleResolution: “bundler”
Uses bundler mode instead of Node.js’s node mode
Matches how Vite and esbuild resolve modules
Supports package.json’s exports field
Using moduleResolution: "node" may conflict with Vite.
{
"experimentalDecorators" : true ,
"emitDecoratorMetadata" : true
}
Required in Sonamu API
Use @api decorator for API methods
Use @transactional decorator for transactions
Use @upload decorator for file uploads
Usage Example: import { BaseModelClass , api , transactional } from "sonamu" ;
class UserModelClass extends BaseModelClass <
UserSubsetKey ,
UserSubsetMapping ,
UserSubsetQueries
> {
@ api ({ httpMethod: "GET" })
async findById ( subset : UserSubsetKey , id : number ) {
const rdb = this . getPuri ( "r" );
return rdb . table ( "users" ). where ( "id" , id ). first ();
}
@ api ({ httpMethod: "POST" })
@ transactional ()
async save ( data : UserSaveParams ) {
const wdb = this . getDB ( "w" );
return this . upsert ( wdb , data );
}
}
export const UserModel = new UserModelClass ();
Entities are defined in entity.json files and do not use TypeScript decorators. See Defining Entities for details. {
"strict" : true ,
"noImplicitAny" : true ,
"strictNullChecks" : true ,
"strictFunctionTypes" : true ,
"strictBindCallApply" : true ,
"strictPropertyInitialization" : true ,
"noImplicitThis" : true ,
"alwaysStrict" : true
}
Sonamu enables all strict options .
Maximize type safety
Prevent runtime errors in advance
Improve code quality
See Type Checking for details. {
"noUnusedLocals" : true ,
"noUnusedParameters" : true ,
"noImplicitReturns" : true ,
"noFallthroughCasesInSwitch" : true ,
"useUnknownInCatchVariables" : true ,
"noUncheckedIndexedAccess" : true
}
Code Quality Improvement Options:
noUnusedLocals: Warn about unused variables
noUnusedParameters: Warn about unused parameters
noImplicitReturns: Require return in all paths
noUncheckedIndexedAccess: Check for undefined when accessing arrays/objects
Extended Configuration Files
Sonamu API uses additional tsconfig files for code generation.
tsconfig.schemas.json - Schema Generation
api/tsconfig.schemas.json
{
"extends" : "./tsconfig.json" ,
"include" : [ "src/sonamu.generated.ts" ],
"exclude" : [ "src/**/*.types.ts" ]
}
Purpose:
Generate sonamu.generated.ts file
Generate Entity schema types
Convert DB schema → TypeScript types
When Used: # Automatically used by Sonamu
pnpm sonamu entity:load
tsconfig.types.json - Type Generation
{
"extends" : "./tsconfig.json" ,
"include" : [ "src/**/*.types.ts" ],
"references" : [{ "path" : "./tsconfig.schemas.json" }]
}
Purpose:
Generate API response types
Define Request/Response types
Share types with frontend
When Used: # Sync types to Web
pnpm sonamu sync:types
Web (React) Configuration
{
"compilerOptions" : {
"target" : "ESNext" ,
"useDefineForClassFields" : true ,
"lib" : [ "DOM" , "DOM.Iterable" , "ESNext" ],
"allowJs" : false ,
"skipLibCheck" : true ,
"esModuleInterop" : false ,
"allowSyntheticDefaultImports" : true ,
"strict" : true ,
"forceConsistentCasingInFileNames" : true ,
"module" : "ESNext" ,
"moduleResolution" : "Bundler" ,
"resolveJsonModule" : true ,
"isolatedModules" : true ,
"noEmit" : true ,
"jsx" : "react-jsx" ,
"baseUrl" : "." ,
"paths" : {
"@/*" : [ "./src/*" ]
}
},
"include" : [ "src" , "src/routeTree.gen.ts" ],
"references" : [{ "path" : "./tsconfig.node.json" }]
}
Differences from API
Option API Web Reason moduleResolutionbundlerBundlerVite uses bundler mode jsx- react-jsxReact 17+ JSX Transform noEmitfalsetrueVite handles build isolatedModules- trueRequired by Vite’s esbuild paths- @/*Absolute path imports
API uses moduleResolution: "bundler" (lowercase), Web uses moduleResolution: "Bundler" (uppercase). Both make Vite resolve modules in bundler mode.
Path Mapping
{
"paths" : {
"@/*" : [ "./src/*" ]
}
}
You can import with absolute paths:
// ❌ Relative path
import { Button } from "../../../components/Button" ;
// ✅ Absolute path
import { Button } from "@/components/Button" ;
See Path Mapping for details.
Running Type Checks
cd api
# Type check only
pnpm tsc --noEmit
# Watch mode
pnpm tsc --noEmit --watch
cd web
# Type check only
pnpm tsc --noEmit
# Watch mode
pnpm tsc --noEmit --watch
# From project root
pnpm -r tsc --noEmit
# Check API and Web simultaneously
During development, --watch mode is recommended for real-time type checking.
Common Troubleshooting
Symptoms: Cannot find module 'sonamu' or its corresponding type declarations.
Cause:
node_modules not installed
Incorrect import path
Solution: # Reinstall dependencies
pnpm install
# Check type definitions
ls node_modules/sonamu/dist/ * .d.ts
Symptoms: Experimental support for decorators is a feature that is subject to change
Cause:
experimentalDecorators is disabled
Solution: {
"compilerOptions" : {
"experimentalDecorators" : true ,
"emitDecoratorMetadata" : true
}
}
Symptoms: Cannot use JSX unless the '--jsx' flag is provided.
Cause:
jsx option not configured
Solution: {
"compilerOptions" : {
"jsx" : "react-jsx"
}
}
Required for React 17+
Symptoms: Cannot find module '@/components/Button'
Cause:
paths configuration missing
baseUrl configuration needed
Solution: {
"compilerOptions" : {
"baseUrl" : "." ,
"paths" : {
"@/*" : [ "./src/*" ]
}
}
}
Vite configuration also needed: import path from "path" ;
export default {
resolve: {
alias: {
"@" : path . resolve ( __dirname , "./src" ),
},
} ,
} ;
Customization
Additional Library Types
{
"compilerOptions" : {
"lib" : [ "esnext" , "dom" , "dom.iterable" , "webworker" ]
}
}
Stricter Checks
{
"compilerOptions" : {
"noPropertyAccessFromIndexSignature" : true ,
"exactOptionalPropertyTypes" : true ,
"noUncheckedIndexedAccess" : true
}
}
These options may cause compatibility issues with existing code.
include/exclude Patterns
{
"include" : [
"src/**/*.ts" ,
"src/**/*.tsx" ,
"src/**/*.json"
],
"exclude" : [
"node_modules" ,
"dist" ,
"**/*.test.ts" ,
"**/*.spec.ts" ,
"**/__mocks__/**"
]
}
Next Steps