@kuckit/cli 1.0.4 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +1293 -695
- package/dist/bin.js.map +1 -0
- package/dist/index.d.ts +476 -1
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -2
- package/dist/{discover-module-B4oRIuSK.js → provider-DbqTBb6C.js} +66 -1
- package/dist/provider-DbqTBb6C.js.map +1 -0
- package/package.json +3 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-DbqTBb6C.js","names":["before","after","discovered: DiscoveredModule[]","writeFile","result: DiscoverResult"],"sources":["../src/commands/generate-module.ts","../src/commands/add-module.ts","../src/lib/sdk-loader.ts","../src/commands/discover-module.ts","../src/commands/infra/types.ts","../src/commands/infra/provider.ts"],"sourcesContent":["import { mkdir, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\n\ninterface GenerateModuleOptions {\n\torg: string\n\tdir: string\n}\n\nfunction toKebabCase(str: string): string {\n\treturn str\n\t\t.replace(/([a-z])([A-Z])/g, '$1-$2')\n\t\t.replace(/[\\s_]+/g, '-')\n\t\t.toLowerCase()\n}\n\nfunction toPascalCase(str: string): string {\n\treturn str\n\t\t.split(/[-_\\s]+/)\n\t\t.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n\t\t.join('')\n}\n\nfunction toCamelCase(str: string): string {\n\tconst pascal = toPascalCase(str)\n\treturn pascal.charAt(0).toLowerCase() + pascal.slice(1)\n}\n\nexport async function generateModule(name: string, options: GenerateModuleOptions): Promise<void> {\n\tconst kebabName = toKebabCase(name)\n\tconst pascalName = toPascalCase(name)\n\tconst camelName = toCamelCase(name)\n\tconst moduleDirName = `${kebabName}-module`\n\n\tconst packageName = options.org ? `@${options.org}/${moduleDirName}` : `@kuckit/${moduleDirName}`\n\tconst moduleId = options.org ? `${options.org}.${kebabName}` : `kuckit.${kebabName}`\n\n\tconst targetDir = join(process.cwd(), options.dir, moduleDirName)\n\n\tconsole.log(`Creating module: ${packageName}`)\n\tconsole.log(` Directory: ${targetDir}`)\n\n\t// Create directory structure (Clean Architecture)\n\tawait mkdir(join(targetDir, 'src', 'domain'), { recursive: true })\n\tawait mkdir(join(targetDir, 'src', 'ports'), { recursive: true })\n\tawait mkdir(join(targetDir, 'src', 'adapters'), { recursive: true })\n\tawait mkdir(join(targetDir, 'src', 'usecases'), { recursive: true })\n\tawait mkdir(join(targetDir, 'src', 'api'), { recursive: true })\n\tawait mkdir(join(targetDir, 'src', 'ui'), { recursive: true })\n\n\t// Generate package.json\n\tconst packageJson = {\n\t\tname: packageName,\n\t\tversion: '0.1.0',\n\t\tprivate: true,\n\t\tdescription: `${pascalName} module for Kuckit`,\n\t\ttype: 'module',\n\t\tmain: 'src/index.ts',\n\t\ttypes: 'src/index.ts',\n\t\texports: {\n\t\t\t'.': {\n\t\t\t\ttypes: './src/index.ts',\n\t\t\t\tdefault: './src/index.ts',\n\t\t\t},\n\t\t\t'./client': {\n\t\t\t\ttypes: './src/client-module.ts',\n\t\t\t\tdefault: './src/client-module.ts',\n\t\t\t},\n\t\t\t'./ui': {\n\t\t\t\ttypes: './src/ui/index.ts',\n\t\t\t\tdefault: './src/ui/index.ts',\n\t\t\t},\n\t\t},\n\t\tpeerDependencies: {\n\t\t\ttypescript: '^5',\n\t\t},\n\t\tdependencies: {\n\t\t\t'@kuckit/sdk': '^1.0.0',\n\t\t\t'@kuckit/sdk-react': '^1.0.0',\n\t\t\t'@kuckit/api': '^1.0.0',\n\t\t\t'@orpc/server': '^1.10.0',\n\t\t\t'@orpc/zod': '^1.10.0',\n\t\t\t'drizzle-orm': '^0.44.0',\n\t\t\tzod: '^3.23.0',\n\t\t\treact: '^19.0.0',\n\t\t\t'@tanstack/react-query': '^5.0.0',\n\t\t},\n\t}\n\n\tawait writeFile(join(targetDir, 'package.json'), JSON.stringify(packageJson, null, '\\t') + '\\n')\n\n\t// Generate tsconfig.json\n\tconst tsconfig = {\n\t\textends: '../../tsconfig.base.json',\n\t\tcompilerOptions: {\n\t\t\toutDir: 'dist',\n\t\t\trootDir: 'src',\n\t\t},\n\t\tinclude: ['src'],\n\t}\n\n\tawait writeFile(join(targetDir, 'tsconfig.json'), JSON.stringify(tsconfig, null, '\\t') + '\\n')\n\n\t// =====================\n\t// DOMAIN LAYER\n\t// =====================\n\n\tconst entityFile = `import { z } from 'zod'\n\n/**\n * ${pascalName} entity schema\n */\nexport const ${pascalName}Schema = z.object({\n\tid: z.string(),\n\tname: z.string().min(1, 'Name is required'),\n\tdescription: z.string().optional(),\n\tcreatedAt: z.date(),\n\tupdatedAt: z.date(),\n\tuserId: z.string(),\n})\n\nexport type ${pascalName} = z.infer<typeof ${pascalName}Schema>\n\n/**\n * Create ${camelName} input schema\n */\nexport const Create${pascalName}InputSchema = z.object({\n\tname: z.string().min(1, 'Name is required'),\n\tdescription: z.string().optional(),\n})\n\nexport type Create${pascalName}Input = z.infer<typeof Create${pascalName}InputSchema>\n\n/**\n * Update ${camelName} input schema\n */\nexport const Update${pascalName}InputSchema = z.object({\n\tid: z.string(),\n\tname: z.string().min(1, 'Name is required').optional(),\n\tdescription: z.string().optional(),\n})\n\nexport type Update${pascalName}Input = z.infer<typeof Update${pascalName}InputSchema>\n`\n\n\tawait writeFile(join(targetDir, 'src', 'domain', `${kebabName}.entity.ts`), entityFile)\n\n\t// =====================\n\t// PORTS LAYER\n\t// =====================\n\n\tconst repositoryPort = `import type { ${pascalName}, Create${pascalName}Input, Update${pascalName}Input } from '../domain/${kebabName}.entity'\n\n/**\n * ${pascalName} repository port interface\n * Defines the contract for ${camelName} persistence operations\n */\nexport interface ${pascalName}Repository {\n\tfindById(id: string): Promise<${pascalName} | null>\n\tfindByUserId(userId: string): Promise<${pascalName}[]>\n\tcreate(input: Create${pascalName}Input & { id: string; userId: string }): Promise<${pascalName}>\n\tupdate(input: Update${pascalName}Input): Promise<${pascalName} | null>\n\tdelete(id: string): Promise<boolean>\n}\n`\n\n\tawait writeFile(join(targetDir, 'src', 'ports', `${kebabName}.repository.ts`), repositoryPort)\n\n\t// =====================\n\t// ADAPTERS LAYER\n\t// =====================\n\n\tconst drizzleAdapter = `import { pgTable, text, timestamp } from 'drizzle-orm/pg-core'\nimport { eq } from 'drizzle-orm'\nimport type { ${pascalName}Repository } from '../ports/${kebabName}.repository'\nimport type { ${pascalName}, Create${pascalName}Input, Update${pascalName}Input } from '../domain/${kebabName}.entity'\n\n/**\n * ${pascalName}s table schema for Drizzle ORM\n */\nexport const ${camelName}sTable = pgTable('${kebabName}s', {\n\tid: text('id').primaryKey(),\n\tname: text('name').notNull(),\n\tdescription: text('description'),\n\tcreatedAt: timestamp('created_at').notNull().defaultNow(),\n\tupdatedAt: timestamp('updated_at').notNull().defaultNow(),\n\tuserId: text('user_id').notNull(),\n})\n\n/**\n * Create a Drizzle-based ${camelName} repository\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function make${pascalName}Repository(db: any): ${pascalName}Repository {\n\treturn {\n\t\tasync findById(id: string): Promise<${pascalName} | null> {\n\t\t\tconst results = await db.select().from(${camelName}sTable).where(eq(${camelName}sTable.id, id))\n\t\t\treturn results[0] ?? null\n\t\t},\n\n\t\tasync findByUserId(userId: string): Promise<${pascalName}[]> {\n\t\t\treturn db.select().from(${camelName}sTable).where(eq(${camelName}sTable.userId, userId))\n\t\t},\n\n\t\tasync create(input: Create${pascalName}Input & { id: string; userId: string }): Promise<${pascalName}> {\n\t\t\tconst now = new Date()\n\t\t\tconst ${camelName} = {\n\t\t\t\tid: input.id,\n\t\t\t\tname: input.name,\n\t\t\t\tdescription: input.description ?? null,\n\t\t\t\tcreatedAt: now,\n\t\t\t\tupdatedAt: now,\n\t\t\t\tuserId: input.userId,\n\t\t\t}\n\t\t\tawait db.insert(${camelName}sTable).values(${camelName})\n\t\t\treturn ${camelName} as ${pascalName}\n\t\t},\n\n\t\tasync update(input: Update${pascalName}Input): Promise<${pascalName} | null> {\n\t\t\tconst existing = await this.findById(input.id)\n\t\t\tif (!existing) return null\n\n\t\t\tconst updated = {\n\t\t\t\t...existing,\n\t\t\t\t...(input.name !== undefined && { name: input.name }),\n\t\t\t\t...(input.description !== undefined && { description: input.description }),\n\t\t\t\tupdatedAt: new Date(),\n\t\t\t}\n\t\t\tawait db.update(${camelName}sTable).set(updated).where(eq(${camelName}sTable.id, input.id))\n\t\t\treturn updated\n\t\t},\n\n\t\tasync delete(id: string): Promise<boolean> {\n\t\t\tconst result = await db.delete(${camelName}sTable).where(eq(${camelName}sTable.id, id))\n\t\t\treturn result.rowCount > 0\n\t\t},\n\t}\n}\n`\n\n\tawait writeFile(join(targetDir, 'src', 'adapters', `${kebabName}.drizzle.ts`), drizzleAdapter)\n\n\t// =====================\n\t// USE CASES LAYER\n\t// =====================\n\n\tconst listUseCase = `import type { ${pascalName}Repository } from '../ports/${kebabName}.repository'\nimport type { ${pascalName} } from '../domain/${kebabName}.entity'\n\ninterface List${pascalName}sDeps {\n\t${camelName}Repository: ${pascalName}Repository\n}\n\n/**\n * List ${camelName}s use case\n */\nexport function makeList${pascalName}s(deps: List${pascalName}sDeps) {\n\treturn async (userId: string): Promise<${pascalName}[]> => {\n\t\treturn deps.${camelName}Repository.findByUserId(userId)\n\t}\n}\n`\n\n\tawait writeFile(join(targetDir, 'src', 'usecases', `list-${kebabName}s.ts`), listUseCase)\n\n\tconst getUseCase = `import type { ${pascalName}Repository } from '../ports/${kebabName}.repository'\nimport type { ${pascalName} } from '../domain/${kebabName}.entity'\n\ninterface Get${pascalName}Deps {\n\t${camelName}Repository: ${pascalName}Repository\n}\n\n/**\n * Get ${camelName} use case\n */\nexport function makeGet${pascalName}(deps: Get${pascalName}Deps) {\n\treturn async (id: string): Promise<${pascalName} | null> => {\n\t\treturn deps.${camelName}Repository.findById(id)\n\t}\n}\n`\n\n\tawait writeFile(join(targetDir, 'src', 'usecases', `get-${kebabName}.ts`), getUseCase)\n\n\tconst createUseCase = `import type { ${pascalName}Repository } from '../ports/${kebabName}.repository'\nimport type { ${pascalName}, Create${pascalName}Input } from '../domain/${kebabName}.entity'\n\nexport interface Create${pascalName}UseCaseInput extends Create${pascalName}Input {\n\tuserId: string\n}\n\ninterface Create${pascalName}Deps {\n\t${camelName}Repository: ${pascalName}Repository\n}\n\n/**\n * Create ${camelName} use case\n */\nexport function makeCreate${pascalName}(deps: Create${pascalName}Deps) {\n\treturn async (input: Create${pascalName}UseCaseInput): Promise<${pascalName}> => {\n\t\tconst id = crypto.randomUUID()\n\t\treturn deps.${camelName}Repository.create({\n\t\t\tid,\n\t\t\tname: input.name,\n\t\t\tdescription: input.description,\n\t\t\tuserId: input.userId,\n\t\t})\n\t}\n}\n`\n\n\tawait writeFile(join(targetDir, 'src', 'usecases', `create-${kebabName}.ts`), createUseCase)\n\n\tconst deleteUseCase = `import type { ${pascalName}Repository } from '../ports/${kebabName}.repository'\n\ninterface Delete${pascalName}Deps {\n\t${camelName}Repository: ${pascalName}Repository\n}\n\n/**\n * Delete ${camelName} use case\n */\nexport function makeDelete${pascalName}(deps: Delete${pascalName}Deps) {\n\treturn async (id: string): Promise<boolean> => {\n\t\treturn deps.${camelName}Repository.delete(id)\n\t}\n}\n`\n\n\tawait writeFile(join(targetDir, 'src', 'usecases', `delete-${kebabName}.ts`), deleteUseCase)\n\n\t// =====================\n\t// API LAYER\n\t// =====================\n\n\tconst routerFile = `import { z } from 'zod'\nimport { protectedProcedure } from '@kuckit/api'\nimport { Create${pascalName}InputSchema } from '../domain/${kebabName}.entity'\nimport type { ${pascalName}Repository } from '../ports/${kebabName}.repository'\n\n/**\n * ${pascalName}s oRPC router\n * Provides CRUD operations for ${camelName}s\n */\nexport const ${camelName}sRouter = {\n\tlist: protectedProcedure.input(z.object({})).handler(async ({ context }) => {\n\t\tconst userId = context.session?.user?.id\n\t\tif (!userId) throw new Error('User not authenticated')\n\n\t\tconst ${camelName}s = await context.di.resolve<${pascalName}Repository>('${camelName}Repository').findByUserId(userId)\n\t\treturn ${camelName}s\n\t}),\n\n\tget: protectedProcedure\n\t\t.input(z.object({ id: z.string() }))\n\t\t.handler(async ({ input, context }) => {\n\t\t\tconst ${camelName} = await context.di.resolve<${pascalName}Repository>('${camelName}Repository').findById(input.id)\n\t\t\treturn ${camelName}\n\t\t}),\n\n\tcreate: protectedProcedure.input(Create${pascalName}InputSchema).handler(async ({ input, context }) => {\n\t\tconst userId = context.session?.user?.id\n\t\tif (!userId) throw new Error('User not authenticated')\n\n\t\tconst id = crypto.randomUUID()\n\t\tconst ${camelName} = await context.di.resolve<${pascalName}Repository>('${camelName}Repository').create({\n\t\t\tid,\n\t\t\tname: input.name,\n\t\t\tdescription: input.description,\n\t\t\tuserId,\n\t\t})\n\t\treturn ${camelName}\n\t}),\n\n\tdelete: protectedProcedure\n\t\t.input(z.object({ id: z.string() }))\n\t\t.handler(async ({ input, context }) => {\n\t\t\tconst success = await context.di.resolve<${pascalName}Repository>('${camelName}Repository').delete(input.id)\n\t\t\treturn { success }\n\t\t}),\n}\n`\n\n\tawait writeFile(join(targetDir, 'src', 'api', `${kebabName}s.router.ts`), routerFile)\n\n\t// =====================\n\t// UI LAYER\n\t// =====================\n\n\tconst pageComponent = `import { useState } from 'react'\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'\nimport { useRpc } from '@kuckit/sdk-react'\n\ninterface ${pascalName} {\n\tid: string\n\tname: string\n\tdescription?: string\n\tcreatedAt: Date\n\tupdatedAt: Date\n}\n\ninterface ${pascalName}sRpc {\n\t${camelName}s: {\n\t\tlist: (input: Record<string, never>) => Promise<${pascalName}[]>\n\t\tcreate: (input: { name: string; description?: string }) => Promise<${pascalName}>\n\t\tdelete: (input: { id: string }) => Promise<void>\n\t}\n}\n\n/**\n * ${pascalName}s page component\n * Demonstrates CRUD operations using the ${camelName}s module with useRpc and TanStack Query\n */\nexport function ${pascalName}sPage() {\n\tconst rpc = useRpc<${pascalName}sRpc>()\n\tconst queryClient = useQueryClient()\n\tconst [newName, setNewName] = useState('')\n\tconst [newDescription, setNewDescription] = useState('')\n\n\tconst {\n\t\tdata: ${camelName}s = [],\n\t\tisLoading,\n\t\terror,\n\t} = useQuery({\n\t\tqueryKey: ['${camelName}s'],\n\t\tqueryFn: () => rpc.${camelName}s.list({}),\n\t})\n\n\tconst createMutation = useMutation({\n\t\tmutationFn: (data: { name: string; description?: string }) => rpc.${camelName}s.create(data),\n\t\tonSuccess: () => queryClient.invalidateQueries({ queryKey: ['${camelName}s'] }),\n\t})\n\n\tconst deleteMutation = useMutation({\n\t\tmutationFn: (id: string) => rpc.${camelName}s.delete({ id }),\n\t\tonSuccess: () => queryClient.invalidateQueries({ queryKey: ['${camelName}s'] }),\n\t})\n\n\tconst create${pascalName} = async (e: React.FormEvent) => {\n\t\te.preventDefault()\n\t\tif (!newName.trim()) return\n\n\t\tcreateMutation.mutate(\n\t\t\t{ name: newName, description: newDescription || undefined },\n\t\t\t{\n\t\t\t\tonSuccess: () => {\n\t\t\t\t\tsetNewName('')\n\t\t\t\t\tsetNewDescription('')\n\t\t\t\t},\n\t\t\t}\n\t\t)\n\t}\n\n\tconst delete${pascalName} = (id: string) => {\n\t\tdeleteMutation.mutate(id)\n\t}\n\n\tif (isLoading) {\n\t\treturn <div style={{ padding: '2rem' }}>Loading ${camelName}s...</div>\n\t}\n\n\treturn (\n\t\t<div style={{ padding: '2rem', fontFamily: 'system-ui', maxWidth: '600px', margin: '0 auto' }}>\n\t\t\t<h1>${pascalName}s</h1>\n\n\t\t\t{(error || createMutation.error || deleteMutation.error) && (\n\t\t\t\t<div style={{ color: 'red', marginBottom: '1rem' }}>\n\t\t\t\t\t{error?.message || createMutation.error?.message || deleteMutation.error?.message}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t<form onSubmit={create${pascalName}} style={{ marginBottom: '2rem' }}>\n\t\t\t\t<div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem' }}>\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tplaceholder=\"Name\"\n\t\t\t\t\t\tvalue={newName}\n\t\t\t\t\t\tonChange={(e) => setNewName(e.target.value)}\n\t\t\t\t\t\trequired\n\t\t\t\t\t\tstyle={{ padding: '0.5rem', fontSize: '1rem' }}\n\t\t\t\t\t/>\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tplaceholder=\"Description (optional)\"\n\t\t\t\t\t\tvalue={newDescription}\n\t\t\t\t\t\tonChange={(e) => setNewDescription(e.target.value)}\n\t\t\t\t\t\tstyle={{ padding: '0.5rem', fontSize: '1rem' }}\n\t\t\t\t\t/>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\tdisabled={createMutation.isPending}\n\t\t\t\t\t\tstyle={{ padding: '0.5rem 1rem', cursor: 'pointer' }}\n\t\t\t\t\t>\n\t\t\t\t\t\t{createMutation.isPending ? 'Adding...' : 'Add ${pascalName}'}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</form>\n\n\t\t\t<ul style={{ listStyle: 'none', padding: 0 }}>\n\t\t\t\t{${camelName}s.map((${camelName}) => (\n\t\t\t\t\t<li\n\t\t\t\t\t\tkey={${camelName}.id}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tpadding: '1rem',\n\t\t\t\t\t\t\tborder: '1px solid #ccc',\n\t\t\t\t\t\t\tmarginBottom: '0.5rem',\n\t\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<strong>{${camelName}.name}</strong>\n\t\t\t\t\t\t\t{${camelName}.description && (\n\t\t\t\t\t\t\t\t<p style={{ margin: '0.5rem 0 0 0', color: '#666' }}>{${camelName}.description}</p>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tonClick={() => delete${pascalName}(${camelName}.id)}\n\t\t\t\t\t\t\tdisabled={deleteMutation.isPending}\n\t\t\t\t\t\t\tstyle={{ cursor: 'pointer', color: 'red', background: 'none', border: 'none' }}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tDelete\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</li>\n\t\t\t\t))}\n\t\t\t</ul>\n\n\t\t\t{${camelName}s.length === 0 && <p>No ${camelName}s yet. Create one above!</p>}\n\t\t</div>\n\t)\n}\n`\n\n\tawait writeFile(join(targetDir, 'src', 'ui', `${pascalName}sPage.tsx`), pageComponent)\n\n\tconst uiIndex = `export { ${pascalName}sPage } from './${pascalName}sPage'\n`\n\n\tawait writeFile(join(targetDir, 'src', 'ui', 'index.ts'), uiIndex)\n\n\t// =====================\n\t// SERVER MODULE\n\t// =====================\n\n\tconst serverModule = `import { defineKuckitModule, asFunction, type KuckitModuleContext } from '@kuckit/sdk'\nimport { ${camelName}sTable, make${pascalName}Repository } from './adapters/${kebabName}.drizzle'\nimport { ${camelName}sRouter } from './api/${kebabName}s.router'\n\nexport type ${pascalName}ModuleConfig = Record<string, never>\n\n/**\n * ${pascalName} module - Kuckit module demonstrating Clean Architecture pattern\n *\n * This module shows:\n * - Domain entity with Zod validation\n * - Repository port/adapter pattern\n * - Use cases for business logic\n * - oRPC router for API endpoints\n */\nexport const kuckitModule = defineKuckitModule<${pascalName}ModuleConfig>({\n\tid: '${moduleId}',\n\tdisplayName: '${pascalName}',\n\tdescription: '${pascalName} module for CRUD operations',\n\tversion: '0.1.0',\n\n\tasync register(ctx: KuckitModuleContext<${pascalName}ModuleConfig>) {\n\t\tconst { container } = ctx\n\n\t\t// Register schema for migrations\n\t\tctx.registerSchema('${camelName}s', ${camelName}sTable)\n\n\t\t// Register repository\n\t\tcontainer.register({\n\t\t\t${camelName}Repository: asFunction(({ db }) => make${pascalName}Repository(db)).scoped(),\n\t\t})\n\t},\n\n\tregisterApi(ctx) {\n\t\tctx.addApiRegistration({\n\t\t\ttype: 'rpc-router',\n\t\t\tname: '${camelName}s',\n\t\t\trouter: ${camelName}sRouter,\n\t\t})\n\t},\n\n\tasync onBootstrap(ctx: KuckitModuleContext<${pascalName}ModuleConfig>) {\n\t\tconst { container } = ctx\n\t\tconst logger = container.resolve('logger')\n\t\tlogger.info('${pascalName} module initialized')\n\t},\n\n\tasync onShutdown(ctx: KuckitModuleContext<${pascalName}ModuleConfig>) {\n\t\tconst { container } = ctx\n\t\tconst logger = container.resolve('logger')\n\t\tlogger.info('${pascalName} module shutting down')\n\t},\n})\n`\n\n\tawait writeFile(join(targetDir, 'src', 'module.ts'), serverModule)\n\n\t// =====================\n\t// CLIENT MODULE\n\t// =====================\n\n\tconst clientModule = `import { defineKuckitClientModule, type KuckitClientModuleContext } from '@kuckit/sdk-react'\nimport { ${pascalName}sPage } from './ui/${pascalName}sPage'\n\n/**\n * ${pascalName} client module\n * Registers routes and components for the web app\n */\nexport const kuckitClientModule = defineKuckitClientModule({\n\tid: '${moduleId}',\n\tdisplayName: '${pascalName}',\n\tversion: '0.1.0',\n\n\tregister(ctx: KuckitClientModuleContext) {\n\t\t// Register the ${camelName}s page component\n\t\tctx.registerComponent('${pascalName}sPage', ${pascalName}sPage)\n\n\t\t// Add route for ${camelName}s page\n\t\tctx.addRoute({\n\t\t\tid: '${kebabName}s',\n\t\t\tpath: '/${kebabName}s',\n\t\t\tcomponent: ${pascalName}sPage,\n\t\t\tmeta: {\n\t\t\t\ttitle: '${pascalName}s',\n\t\t\t\trequiresAuth: true,\n\t\t\t},\n\t\t})\n\n\t\t// Add navigation item\n\t\tctx.addNavItem({\n\t\t\tid: '${kebabName}s-nav',\n\t\t\tlabel: '${pascalName}s',\n\t\t\tpath: '/${kebabName}s',\n\t\t\ticon: 'list',\n\t\t\torder: 100,\n\t\t})\n\t},\n})\n\nexport { ${pascalName}sPage } from './ui/${pascalName}sPage'\n`\n\n\tawait writeFile(join(targetDir, 'src', 'client-module.ts'), clientModule)\n\n\t// =====================\n\t// INDEX FILE\n\t// =====================\n\n\tconst indexFile = `// Server module\nexport { kuckitModule } from './module'\n\n// Domain\nexport * from './domain/${kebabName}.entity'\n\n// Ports\nexport type { ${pascalName}Repository } from './ports/${kebabName}.repository'\n\n// Adapters\nexport { ${camelName}sTable, make${pascalName}Repository } from './adapters/${kebabName}.drizzle'\n\n// Use cases\nexport { makeList${pascalName}s } from './usecases/list-${kebabName}s'\nexport { makeGet${pascalName} } from './usecases/get-${kebabName}'\nexport { makeCreate${pascalName} } from './usecases/create-${kebabName}'\nexport { makeDelete${pascalName} } from './usecases/delete-${kebabName}'\n\n// API\nexport { ${camelName}sRouter } from './api/${kebabName}s.router'\n`\n\n\tawait writeFile(join(targetDir, 'src', 'index.ts'), indexFile)\n\n\tconsole.log(`\n✅ Module created successfully!\n\n📁 Structure:\n ${options.dir}/${moduleDirName}/\n ├── src/\n │ ├── domain/\n │ │ └── ${kebabName}.entity.ts # Zod schema for entity\n │ ├── ports/\n │ │ └── ${kebabName}.repository.ts # Repository interface\n │ ├── adapters/\n │ │ └── ${kebabName}.drizzle.ts # Drizzle implementation\n │ ├── usecases/\n │ │ ├── list-${kebabName}s.ts\n │ │ ├── get-${kebabName}.ts\n │ │ ├── create-${kebabName}.ts\n │ │ └── delete-${kebabName}.ts\n │ ├── api/\n │ │ └── ${kebabName}s.router.ts # oRPC router\n │ ├── ui/\n │ │ └── ${pascalName}sPage.tsx # React component\n │ ├── module.ts # Server module\n │ ├── client-module.ts # Client module\n │ └── index.ts\n ├── package.json\n └── tsconfig.json\n\n📝 Next steps:\n 1. Run 'bun install' from the root to link the new package\n 2. Add module to apps/server/src/config/modules.ts:\n import { kuckitModule as ${camelName}Module } from '${packageName}'\n export const modules = [..., ${camelName}Module]\n 3. Add client module to apps/web/src/modules.client.ts:\n import { kuckitClientModule as ${camelName}Client } from '${packageName}/client'\n export const clientModules = [..., { module: ${camelName}Client }]\n 4. Add schema path to packages/db/drizzle.config.ts:\n schema: [..., '../${moduleDirName}/src/adapters/${kebabName}.drizzle.ts']\n 5. Run 'bun run db:push' to create the table\n`)\n}\n","import { execSync } from 'node:child_process'\nimport { readFile, writeFile, access } from 'node:fs/promises'\nimport { accessSync, constants, existsSync } from 'node:fs'\nimport { join } from 'node:path'\n\ninterface AddModuleOptions {\n\tskipInstall: boolean\n}\n\ninterface KuckitMetadata {\n\tid: string\n\tserver?: string\n\tclient?: string\n}\n\ninterface PackageJson {\n\tname: string\n\tkuckit?: KuckitMetadata\n}\n\nconst CONFIG_FILES = ['kuckit.config.ts', 'kuckit.config.js', 'kuckit.config.mjs']\n\nasync function fileExists(path: string): Promise<boolean> {\n\ttry {\n\t\tawait access(path, constants.F_OK)\n\t\treturn true\n\t} catch {\n\t\treturn false\n\t}\n}\n\nfunction findConfigFile(cwd: string): string | null {\n\tfor (const file of CONFIG_FILES) {\n\t\tconst configPath = join(cwd, file)\n\t\tif (existsSync(configPath)) {\n\t\t\treturn configPath\n\t\t}\n\t}\n\treturn null\n}\n\nfunction detectPackageManager(cwd: string): 'bun' | 'npm' | 'yarn' | 'pnpm' {\n\tconst lockFiles: Record<string, 'bun' | 'npm' | 'yarn' | 'pnpm'> = {\n\t\t'bun.lock': 'bun',\n\t\t'bun.lockb': 'bun',\n\t\t'package-lock.json': 'npm',\n\t\t'yarn.lock': 'yarn',\n\t\t'pnpm-lock.yaml': 'pnpm',\n\t}\n\n\tfor (const [file, pm] of Object.entries(lockFiles)) {\n\t\ttry {\n\t\t\taccessSync(join(cwd, file), constants.F_OK)\n\t\t\treturn pm\n\t\t} catch {\n\t\t\t// continue\n\t\t}\n\t}\n\n\treturn 'npm'\n}\n\nasync function readPackageKuckitMetadata(\n\tpackageName: string,\n\tcwd: string\n): Promise<KuckitMetadata | null> {\n\t// After install, read from node_modules\n\tconst packageJsonPath = join(cwd, 'node_modules', packageName, 'package.json')\n\n\ttry {\n\t\tconst content = await readFile(packageJsonPath, 'utf-8')\n\t\tconst pkg: PackageJson = JSON.parse(content)\n\t\treturn pkg.kuckit ?? null\n\t} catch {\n\t\treturn null\n\t}\n}\n\nconst MODULES_MARKER_START = '// KUCKIT_MODULES_START'\nconst MODULES_MARKER_END = '// KUCKIT_MODULES_END'\nconst CLIENT_MODULES_MARKER_START = '// KUCKIT_CLIENT_MODULES_START'\nconst CLIENT_MODULES_MARKER_END = '// KUCKIT_CLIENT_MODULES_END'\n\n/**\n * Add module to unified kuckit.config.ts\n */\nasync function addToUnifiedConfig(packageName: string, configPath: string): Promise<boolean> {\n\tlet content = await readFile(configPath, 'utf-8')\n\n\t// Check if package is already in config\n\tif (content.includes(`'${packageName}'`) || content.includes(`\"${packageName}\"`)) {\n\t\tconsole.log(` Module ${packageName} is already in ${configPath}`)\n\t\treturn true\n\t}\n\n\t// Find the modules array and add the new entry\n\t// Pattern: modules: [ ... ]\n\tconst modulesArrayMatch = content.match(/modules:\\s*\\[/)\n\tif (!modulesArrayMatch) {\n\t\tconsole.warn(`Warning: Could not find 'modules' array in ${configPath}`)\n\t\tconsole.log(` Please manually add: { package: '${packageName}' }`)\n\t\treturn false\n\t}\n\n\t// Find the position right after 'modules: ['\n\tconst insertPos = modulesArrayMatch.index! + modulesArrayMatch[0].length\n\n\t// Add the new module entry\n\tconst newEntry = `\\n\\t\\t{ package: '${packageName}' },`\n\tcontent = content.slice(0, insertPos) + newEntry + content.slice(insertPos)\n\n\tawait writeFile(configPath, content)\n\tconsole.log(` Added to unified config: ${configPath}`)\n\treturn true\n}\n\nasync function addToServerModules(packageName: string, cwd: string): Promise<boolean> {\n\tconst modulesPath = join(cwd, 'apps', 'server', 'src', 'config', 'modules.ts')\n\n\tif (!(await fileExists(modulesPath))) {\n\t\tconsole.warn(`Warning: Server modules file not found at ${modulesPath}`)\n\t\treturn false\n\t}\n\n\tlet content = await readFile(modulesPath, 'utf-8')\n\n\t// Check if package is already added\n\tif (content.includes(`package: '${packageName}'`)) {\n\t\tconsole.log(` Module ${packageName} is already in server modules`)\n\t\treturn true\n\t}\n\n\t// If markers don't exist, add them\n\tif (!content.includes(MODULES_MARKER_START)) {\n\t\t// Find the return statement and insert before it\n\t\tconst returnMatch = content.match(/return modules\\s*$/)\n\t\tif (returnMatch) {\n\t\t\tconst insertPos = content.lastIndexOf('return modules')\n\t\t\tconst before = content.slice(0, insertPos)\n\t\t\tconst after = content.slice(insertPos)\n\n\t\t\tcontent =\n\t\t\t\tbefore +\n\t\t\t\t`\\n\\t\\t${MODULES_MARKER_START}\\n\\t\\t// Modules installed via 'kuckit add' will be added here\\n\\t\\t${MODULES_MARKER_END}\\n\\n\\t\\t` +\n\t\t\t\tafter\n\t\t}\n\t}\n\n\t// Insert the module before the end marker\n\tconst newEntry = `{ package: '${packageName}' },`\n\tconst markerEndPos = content.indexOf(MODULES_MARKER_END)\n\n\tif (markerEndPos === -1) {\n\t\tconsole.warn(`Warning: Could not find marker in ${modulesPath}`)\n\t\tconsole.log(` Please manually add: ${newEntry}`)\n\t\treturn false\n\t}\n\n\tconst before = content.slice(0, markerEndPos)\n\tconst after = content.slice(markerEndPos)\n\n\tcontent = before + `${newEntry}\\n\\t\\t` + after\n\n\tawait writeFile(modulesPath, content)\n\tconsole.log(` Added to server modules: ${modulesPath}`)\n\treturn true\n}\n\nasync function addToClientModules(\n\tpackageName: string,\n\tclientPath: string,\n\tcwd: string\n): Promise<boolean> {\n\t// Check if there's a client modules file in apps/web\n\tconst clientModulesPath = join(cwd, 'apps', 'web', 'src', 'modules.client.ts')\n\n\tif (!(await fileExists(clientModulesPath))) {\n\t\t// Create the file if it doesn't exist\n\t\tconst template = `import type { ClientModuleSpec } from '@kuckit/sdk-react'\n\n/**\n * Client module specifications\n *\n * Add your Kuckit client modules here. Modules can be:\n * - Direct references: { module: myModule }\n * - Package imports: { package: '@acme/billing-module/client' }\n *\n * The CLI command \\`kuckit add <package>\\` will automatically update this file.\n */\nexport const getClientModuleSpecs = (): ClientModuleSpec[] => [\n\t${CLIENT_MODULES_MARKER_START}\n\t${CLIENT_MODULES_MARKER_END}\n]\n`\n\t\tawait writeFile(clientModulesPath, template)\n\t\tconsole.log(` Created client modules file: ${clientModulesPath}`)\n\t}\n\n\tlet content = await readFile(clientModulesPath, 'utf-8')\n\n\t// Check if package is already added\n\tconst clientPackagePath = `${packageName}/${clientPath.replace('./', '')}`\n\tif (content.includes(`package: '${clientPackagePath}'`)) {\n\t\tconsole.log(` Client module is already registered`)\n\t\treturn true\n\t}\n\n\t// Insert the module before the end marker\n\tconst newEntry = `{ package: '${clientPackagePath}' },`\n\tconst markerEndPos = content.indexOf(CLIENT_MODULES_MARKER_END)\n\n\tif (markerEndPos === -1) {\n\t\tconsole.warn(`Warning: Could not find marker in ${clientModulesPath}`)\n\t\tconsole.log(` Please manually add: ${newEntry}`)\n\t\treturn false\n\t}\n\n\tconst before = content.slice(0, markerEndPos)\n\tconst after = content.slice(markerEndPos)\n\n\tcontent = before + `${newEntry}\\n\\t` + after\n\n\tawait writeFile(clientModulesPath, content)\n\tconsole.log(` Added to client modules: ${clientModulesPath}`)\n\treturn true\n}\n\nexport async function addModule(packageName: string, options: AddModuleOptions): Promise<void> {\n\tconst cwd = process.cwd()\n\n\tconsole.log(`Adding module: ${packageName}`)\n\n\t// Step 1: Install the package\n\tif (!options.skipInstall) {\n\t\tconst pm = detectPackageManager(cwd)\n\t\tconst installCmd = pm === 'npm' ? `${pm} install ${packageName}` : `${pm} add ${packageName}`\n\n\t\tconsole.log(` Installing with ${pm}...`)\n\t\ttry {\n\t\t\texecSync(installCmd, { cwd, stdio: 'inherit' })\n\t\t} catch {\n\t\t\tconsole.error(`Failed to install ${packageName}`)\n\t\t\tprocess.exit(1)\n\t\t}\n\t}\n\n\t// Step 2: Validate kuckit metadata\n\tconst metadata = await readPackageKuckitMetadata(packageName, cwd)\n\n\tif (!metadata) {\n\t\tconsole.error(`\\nError: ${packageName} is not a valid Kuckit module.`)\n\t\tconsole.error(`The package.json must contain a \"kuckit\" field with module metadata.`)\n\t\tconsole.error(`\\nExpected structure:`)\n\t\tconsole.error(`{\n \"kuckit\": {\n \"id\": \"acme.billing\",\n \"server\": \".\",\n \"client\": \"./client\"\n }\n}`)\n\t\tprocess.exit(1)\n\t}\n\n\tconsole.log(` Found Kuckit module: ${metadata.id}`)\n\n\t// Step 3: Check for unified config\n\tconst configPath = findConfigFile(cwd)\n\n\tif (configPath) {\n\t\t// Use unified config\n\t\tawait addToUnifiedConfig(packageName, configPath)\n\t} else {\n\t\t// Fall back to separate config files\n\t\tif (metadata.server) {\n\t\t\tawait addToServerModules(packageName, cwd)\n\t\t}\n\t\tif (metadata.client) {\n\t\t\tawait addToClientModules(packageName, metadata.client, cwd)\n\t\t}\n\t}\n\n\tconsole.log(`\nModule ${packageName} added successfully!\n\nRun 'bun run dev' to start the server with the new module.\n`)\n}\n","interface KuckitConfig {\n\tmodules: Array<{ package?: string; disabled?: boolean }>\n\t_configPath?: string\n}\n\ntype TryLoadKuckitConfig = (cwd: string) => Promise<KuckitConfig | null>\n\nexport async function loadTryLoadKuckitConfig(): Promise<TryLoadKuckitConfig> {\n\ttry {\n\t\tconst sdk = (await import('@kuckit/sdk')) as { tryLoadKuckitConfig?: TryLoadKuckitConfig }\n\t\tif (!sdk.tryLoadKuckitConfig) {\n\t\t\tthrow new Error('Invalid @kuckit/sdk version: tryLoadKuckitConfig not found.')\n\t\t}\n\t\treturn sdk.tryLoadKuckitConfig\n\t} catch {\n\t\tconsole.error('Error: This command requires @kuckit/sdk to be installed in your project.')\n\t\tconsole.error('Install it with one of:')\n\t\tconsole.error(' npm install -D @kuckit/sdk')\n\t\tconsole.error(' pnpm add -D @kuckit/sdk')\n\t\tconsole.error(' bun add -d @kuckit/sdk')\n\t\tprocess.exit(1)\n\t}\n}\n","import { readdir, readFile } from 'node:fs/promises'\nimport { existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { loadTryLoadKuckitConfig } from '../lib/sdk-loader.js'\n\nexport interface DiscoverOptions {\n\tjson: boolean\n\tinteractive: boolean\n}\n\ninterface KuckitMetadata {\n\tid: string\n\tserver?: string\n\tclient?: string\n}\n\ninterface DiscoveredModule {\n\tpackage: string\n\tid: string\n\tserver?: string\n\tclient?: string\n\tenabled: boolean\n\tlocal?: boolean\n}\n\ninterface DiscoverResult {\n\tdiscovered: DiscoveredModule[]\n\tenabled: number\n\tunconfigured: number\n}\n\nasync function readKuckitMetadataFromPath(packageJsonPath: string): Promise<KuckitMetadata | null> {\n\ttry {\n\t\tconst content = await readFile(packageJsonPath, 'utf-8')\n\t\tconst pkg = JSON.parse(content) as { kuckit?: KuckitMetadata }\n\t\treturn pkg.kuckit ?? null\n\t} catch {\n\t\treturn null\n\t}\n}\n\nasync function readPackageName(packageJsonPath: string): Promise<string | null> {\n\ttry {\n\t\tconst content = await readFile(packageJsonPath, 'utf-8')\n\t\tconst pkg = JSON.parse(content) as { name?: string }\n\t\treturn pkg.name ?? null\n\t} catch {\n\t\treturn null\n\t}\n}\n\nasync function scanWorkspacePackages(cwd: string): Promise<DiscoveredModule[]> {\n\tconst discovered: DiscoveredModule[] = []\n\tconst packagesDir = join(cwd, 'packages')\n\n\tif (!existsSync(packagesDir)) return discovered\n\n\ttry {\n\t\tconst entries = await readdir(packagesDir, { withFileTypes: true })\n\n\t\tfor (const entry of entries) {\n\t\t\tif (!entry.isDirectory()) continue\n\n\t\t\tconst packageJsonPath = join(packagesDir, entry.name, 'package.json')\n\t\t\tconst metadata = await readKuckitMetadataFromPath(packageJsonPath)\n\n\t\t\tif (metadata) {\n\t\t\t\tconst packageName = await readPackageName(packageJsonPath)\n\t\t\t\tif (packageName) {\n\t\t\t\t\tdiscovered.push({\n\t\t\t\t\t\tpackage: packageName,\n\t\t\t\t\t\tid: metadata.id,\n\t\t\t\t\t\tserver: metadata.server,\n\t\t\t\t\t\tclient: metadata.client,\n\t\t\t\t\t\tenabled: false,\n\t\t\t\t\t\tlocal: true,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// packages directory not accessible\n\t}\n\n\treturn discovered\n}\n\nasync function scanNodeModules(cwd: string): Promise<DiscoveredModule[]> {\n\tconst nodeModulesPath = join(cwd, 'node_modules')\n\tconst discovered: DiscoveredModule[] = []\n\n\ttry {\n\t\tconst entries = await readdir(nodeModulesPath, { withFileTypes: true })\n\n\t\tfor (const entry of entries) {\n\t\t\tif (!entry.isDirectory() && !entry.isSymbolicLink()) continue\n\t\t\tif (entry.name.startsWith('.')) continue\n\n\t\t\tif (entry.name.startsWith('@')) {\n\t\t\t\tconst scopePath = join(nodeModulesPath, entry.name)\n\t\t\t\ttry {\n\t\t\t\t\tconst scopedEntries = await readdir(scopePath, { withFileTypes: true })\n\t\t\t\t\tfor (const scopedEntry of scopedEntries) {\n\t\t\t\t\t\tif (!scopedEntry.isDirectory() && !scopedEntry.isSymbolicLink()) continue\n\t\t\t\t\t\tconst packageName = `${entry.name}/${scopedEntry.name}`\n\t\t\t\t\t\tconst packageJsonPath = join(nodeModulesPath, packageName, 'package.json')\n\t\t\t\t\t\tconst metadata = await readKuckitMetadataFromPath(packageJsonPath)\n\t\t\t\t\t\tif (metadata) {\n\t\t\t\t\t\t\tdiscovered.push({\n\t\t\t\t\t\t\t\tpackage: packageName,\n\t\t\t\t\t\t\t\tid: metadata.id,\n\t\t\t\t\t\t\t\tserver: metadata.server,\n\t\t\t\t\t\t\t\tclient: metadata.client,\n\t\t\t\t\t\t\t\tenabled: false,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Skip inaccessible scoped directories\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst packageJsonPath = join(nodeModulesPath, entry.name, 'package.json')\n\t\t\t\tconst metadata = await readKuckitMetadataFromPath(packageJsonPath)\n\t\t\t\tif (metadata) {\n\t\t\t\t\tdiscovered.push({\n\t\t\t\t\t\tpackage: entry.name,\n\t\t\t\t\t\tid: metadata.id,\n\t\t\t\t\t\tserver: metadata.server,\n\t\t\t\t\t\tclient: metadata.client,\n\t\t\t\t\t\tenabled: false,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// node_modules doesn't exist\n\t}\n\n\treturn discovered\n}\n\nasync function addModulesToConfig(packages: string[], configPath: string): Promise<void> {\n\tconst content = await readFile(configPath, 'utf-8')\n\tlet updated = content\n\n\tfor (const pkg of packages) {\n\t\tif (updated.includes(`'${pkg}'`) || updated.includes(`\"${pkg}\"`)) {\n\t\t\tcontinue\n\t\t}\n\n\t\tconst modulesArrayMatch = updated.match(/modules:\\s*\\[/)\n\t\tif (!modulesArrayMatch) continue\n\n\t\tconst insertPos = modulesArrayMatch.index! + modulesArrayMatch[0].length\n\t\tconst newEntry = `\\n\\t\\t{ package: '${pkg}' },`\n\t\tupdated = updated.slice(0, insertPos) + newEntry + updated.slice(insertPos)\n\t}\n\n\tif (updated !== content) {\n\t\tconst { writeFile } = await import('node:fs/promises')\n\t\tawait writeFile(configPath, updated)\n\t}\n}\n\nexport async function discoverModules(options: DiscoverOptions): Promise<void> {\n\tconst cwd = process.cwd()\n\n\tif (!options.json) {\n\t\tconsole.log('Scanning for Kuckit modules...\\n')\n\t}\n\n\t// Load current config\n\tconst tryLoadKuckitConfig = await loadTryLoadKuckitConfig()\n\tconst config = await tryLoadKuckitConfig(cwd)\n\tconst configuredPackages = new Set(config?.modules.map((m) => m.package) ?? [])\n\n\t// Scan both workspace packages and node_modules\n\tconst workspaceModules = await scanWorkspacePackages(cwd)\n\tconst nodeModules = await scanNodeModules(cwd)\n\n\t// Combine and dedupe (workspace takes precedence)\n\tconst seen = new Set<string>()\n\tconst discovered: DiscoveredModule[] = []\n\n\tfor (const mod of workspaceModules) {\n\t\tseen.add(mod.package)\n\t\tmod.enabled = configuredPackages.has(mod.package)\n\t\tdiscovered.push(mod)\n\t}\n\n\tfor (const mod of nodeModules) {\n\t\tif (!seen.has(mod.package)) {\n\t\t\tmod.enabled = configuredPackages.has(mod.package)\n\t\t\tdiscovered.push(mod)\n\t\t}\n\t}\n\n\t// Sort: enabled first, then alphabetically\n\tdiscovered.sort((a, b) => {\n\t\tif (a.enabled !== b.enabled) return a.enabled ? -1 : 1\n\t\treturn a.package.localeCompare(b.package)\n\t})\n\n\tconst result: DiscoverResult = {\n\t\tdiscovered,\n\t\tenabled: discovered.filter((m) => m.enabled).length,\n\t\tunconfigured: discovered.filter((m) => !m.enabled).length,\n\t}\n\n\tif (options.json) {\n\t\tconsole.log(JSON.stringify(result, null, 2))\n\t\treturn\n\t}\n\n\tif (discovered.length === 0) {\n\t\tconsole.log('No Kuckit modules found.')\n\t\tconsole.log('\\nInstall modules with: kuckit add <package>')\n\t\treturn\n\t}\n\n\tconsole.log(`Found ${discovered.length} Kuckit module${discovered.length === 1 ? '' : 's'}:`)\n\tfor (const mod of discovered) {\n\t\tconst status = mod.enabled ? '✓' : '○'\n\t\tconst label = mod.enabled ? '(enabled)' : '(not configured)'\n\t\tconst localLabel = mod.local ? ' [local]' : ''\n\t\tconsole.log(` ${status} ${mod.package}${localLabel} ${label}`)\n\t}\n\n\tconst unconfigured = discovered.filter((m) => !m.enabled)\n\tif (unconfigured.length === 0) {\n\t\tconsole.log('\\nAll discovered modules are already configured.')\n\t\treturn\n\t}\n\n\tif (!options.interactive) {\n\t\tconsole.log(\n\t\t\t`\\n${unconfigured.length} module${unconfigured.length === 1 ? '' : 's'} not configured.`\n\t\t)\n\t\tconsole.log('Run without --no-interactive to enable them.')\n\t\treturn\n\t}\n\n\tif (!config?._configPath) {\n\t\tconsole.log('\\nNo kuckit.config.ts found. Create one first with:')\n\t\tconsole.log(' npx create-kuckit-app --init')\n\t\treturn\n\t}\n\n\t// Interactive mode: prompt for module selection\n\ttry {\n\t\tconst { checkbox } = await import('@inquirer/prompts')\n\n\t\tconst selected = await checkbox({\n\t\t\tmessage: 'Enable modules:',\n\t\t\tchoices: unconfigured.map((m) => ({\n\t\t\t\tname: m.package,\n\t\t\t\tvalue: m.package,\n\t\t\t\tchecked: true,\n\t\t\t})),\n\t\t})\n\n\t\tif (selected.length === 0) {\n\t\t\tconsole.log('\\nNo modules selected.')\n\t\t\treturn\n\t\t}\n\n\t\tawait addModulesToConfig(selected, config._configPath)\n\t\tconsole.log(\n\t\t\t`\\nUpdated kuckit.config.ts with ${selected.length} new module${selected.length === 1 ? '' : 's'}.`\n\t\t)\n\t} catch (error) {\n\t\tif ((error as Error).name === 'ExitPromptError') {\n\t\t\tconsole.log('\\nCancelled.')\n\t\t\treturn\n\t\t}\n\t\tthrow error\n\t}\n}\n","/**\n * Infrastructure types for CLI\n *\n * These types define the config schema stored in .kuckit/infra.json.\n * They are designed to support multiple cloud providers while maintaining\n * backward compatibility with existing GCP-only configurations.\n */\n\nimport type { BaseInfraConfig } from './provider.js'\n\n// ============================================================================\n// Provider-Specific Configuration Types\n// ============================================================================\n\n/**\n * GCP-specific configuration fields\n */\nexport interface GcpProviderConfig {\n\t/** GCP Project ID */\n\tgcpProject: string\n}\n\n/**\n * AWS-specific configuration fields (future)\n */\nexport interface AwsProviderConfig {\n\t/** AWS Account ID */\n\tawsAccountId: string\n\t/** AWS Profile name */\n\tawsProfile?: string\n}\n\n/**\n * Azure-specific configuration fields (future)\n */\nexport interface AzureProviderConfig {\n\t/** Azure Subscription ID */\n\tsubscriptionId: string\n\t/** Azure Resource Group */\n\tresourceGroup: string\n}\n\n/**\n * Union of all provider configs\n */\nexport type ProviderConfig = GcpProviderConfig | AwsProviderConfig | AzureProviderConfig\n\n// ============================================================================\n// Deployment Outputs (Provider-Specific)\n// ============================================================================\n\n/**\n * Base deployment outputs common to all providers\n */\nexport interface BaseDeploymentOutputs {\n\t/** Container registry URL */\n\tregistryUrl: string\n\t/** Service URL after deployment */\n\tserviceUrl?: string\n}\n\n/**\n * GCP-specific deployment outputs\n */\nexport interface GcpDeploymentOutputs extends BaseDeploymentOutputs {\n\t/** Cloud SQL connection name for Cloud SQL Auth Proxy */\n\tdatabaseConnectionName: string\n\t/** Database name inside Cloud SQL instance */\n\tdatabaseName?: string\n\t/** Database user for Cloud SQL */\n\tdatabaseUser?: string\n\t/** Memorystore Redis private IP address */\n\tredisHost: string\n\t/** Secret Manager secret IDs */\n\tsecretIds: {\n\t\t/** Database password secret ID */\n\t\tdbPassword: string\n\t\t/** Redis AUTH string secret ID */\n\t\tredisAuth: string\n\t}\n\t/** Cloud Run Job name for database migrations */\n\tmigrationJobName?: string\n}\n\n/**\n * AWS-specific deployment outputs (future)\n */\nexport interface AwsDeploymentOutputs extends BaseDeploymentOutputs {\n\t/** RDS instance endpoint */\n\tdatabaseEndpoint?: string\n\t/** ElastiCache endpoint */\n\tredisEndpoint?: string\n\t/** ECS service ARN */\n\tecsServiceArn?: string\n}\n\n/**\n * Azure-specific deployment outputs (future)\n */\nexport interface AzureDeploymentOutputs extends BaseDeploymentOutputs {\n\t/** Azure SQL server name */\n\tsqlServerName?: string\n\t/** Azure Cache for Redis hostname */\n\tredisHostname?: string\n\t/** Container Apps URL */\n\tcontainerAppUrl?: string\n}\n\n/**\n * Union of all deployment output types\n */\nexport type DeploymentOutputs = GcpDeploymentOutputs | AwsDeploymentOutputs | AzureDeploymentOutputs\n\n// ============================================================================\n// Stored Infrastructure Configuration\n// ============================================================================\n\n/**\n * Supported cloud provider IDs\n */\nexport type SupportedProvider = 'gcp' | 'aws' | 'azure'\n\n/**\n * CLI config stored in .kuckit/infra.json\n *\n * This is an extended version of BaseInfraConfig with additional fields\n * specific to CLI storage and provider management.\n */\nexport interface StoredInfraConfig extends BaseInfraConfig {\n\t/**\n\t * Provider ID (e.g., 'gcp', 'aws', 'azure')\n\t * @override Narrows the base string type to supported providers\n\t */\n\tprovider: SupportedProvider\n\n\t/**\n\t * npm package name of the provider (e.g., '@kuckit/infra-gcp')\n\t * Used to load the provider dynamically at runtime.\n\t */\n\tproviderPackage: string\n\n\t/**\n\t * Environment (dev/staging/prod)\n\t * @override Narrows to common environments\n\t */\n\tenv: 'dev' | 'staging' | 'prod'\n\n\t/**\n\t * Provider-specific configuration.\n\t * Contains fields that vary by cloud provider.\n\t */\n\tproviderConfig: ProviderConfig\n\n\t/**\n\t * Optional local infrastructure directory.\n\t * Set when provider has been ejected for customization.\n\t * If not set, uses provider's bundled infra.\n\t */\n\tlocalInfraDir?: string\n\n\t/**\n\t * Deployment outputs from the last successful deployment.\n\t * Structure varies by provider.\n\t */\n\toutputs?: DeploymentOutputs\n}\n\n// ============================================================================\n// Legacy Type Support (Backward Compatibility)\n// ============================================================================\n\n/**\n * Legacy config format (pre-provider-module)\n * Used for migration and backward compatibility\n *\n * @deprecated Use StoredInfraConfig instead\n */\nexport interface LegacyInfraConfig {\n\tprovider: 'gcp'\n\tgcpProject: string\n\tregion: string\n\tprojectName: string\n\tstackName: string\n\tenv: 'dev' | 'prod'\n\toutputs?: GcpDeploymentOutputs\n\tcreatedAt: string\n\tupdatedAt: string\n}\n\n/**\n * Check if config is legacy format\n */\nexport function isLegacyConfig(\n\tconfig: StoredInfraConfig | LegacyInfraConfig\n): config is LegacyInfraConfig {\n\treturn 'gcpProject' in config && !('providerPackage' in config)\n}\n\n/**\n * Migrate legacy config to new format\n */\nexport function migrateLegacyConfig(legacy: LegacyInfraConfig): StoredInfraConfig {\n\treturn {\n\t\tprovider: 'gcp',\n\t\tproviderPackage: '@kuckit/infra-gcp',\n\t\tregion: legacy.region,\n\t\tprojectName: legacy.projectName,\n\t\tstackName: legacy.stackName,\n\t\tenv: legacy.env,\n\t\tproviderConfig: {\n\t\t\tgcpProject: legacy.gcpProject,\n\t\t},\n\t\toutputs: legacy.outputs,\n\t\tcreatedAt: legacy.createdAt,\n\t\tupdatedAt: legacy.updatedAt,\n\t}\n}\n\n// ============================================================================\n// Type Guards for Provider-Specific Configs\n// ============================================================================\n\n/**\n * Check if config is for GCP\n */\nexport function isGcpConfig(config: StoredInfraConfig): config is StoredInfraConfig & {\n\tprovider: 'gcp'\n\tproviderConfig: GcpProviderConfig\n\toutputs?: GcpDeploymentOutputs\n} {\n\treturn config.provider === 'gcp'\n}\n\n/**\n * Check if config is for AWS\n */\nexport function isAwsConfig(config: StoredInfraConfig): config is StoredInfraConfig & {\n\tprovider: 'aws'\n\tproviderConfig: AwsProviderConfig\n\toutputs?: AwsDeploymentOutputs\n} {\n\treturn config.provider === 'aws'\n}\n\n/**\n * Check if config is for Azure\n */\nexport function isAzureConfig(config: StoredInfraConfig): config is StoredInfraConfig & {\n\tprovider: 'azure'\n\tproviderConfig: AzureProviderConfig\n\toutputs?: AzureDeploymentOutputs\n} {\n\treturn config.provider === 'azure'\n}\n","/**\n * KuckitInfraProvider Interface\n *\n * This interface defines the contract that all cloud infrastructure providers must implement.\n * It enables multi-cloud support by abstracting provider-specific logic behind a common interface.\n *\n * Provider packages (e.g., @kuckit/infra-gcp, @kuckit/infra-aws) implement this interface\n * and are discovered/loaded by the CLI at runtime.\n *\n * @example\n * ```typescript\n * // In @kuckit/infra-gcp/src/provider.ts\n * import { defineInfraProvider } from '@kuckit/cli'\n *\n * export const provider = defineInfraProvider({\n * id: 'gcp',\n * label: 'Google Cloud Platform',\n * // ... implementation\n * })\n * ```\n */\n\n/**\n * Base configuration stored by CLI (provider-agnostic fields)\n */\nexport interface BaseInfraConfig {\n\t/** Provider ID (e.g., 'gcp', 'aws', 'azure') */\n\tprovider: string\n\t/** Environment (dev/staging/prod) */\n\tenv: string\n\t/** Deployment region */\n\tregion: string\n\t/** Project/app name for resource naming */\n\tprojectName: string\n\t/** Pulumi stack name */\n\tstackName: string\n\t/** ISO timestamp of config creation */\n\tcreatedAt: string\n\t/** ISO timestamp of last update */\n\tupdatedAt: string\n}\n\n/**\n * Result from an infrastructure operation (init/deploy/destroy)\n */\nexport interface InfraOperationResult<TOutputs = Record<string, unknown>> {\n\t/** Whether the operation succeeded */\n\tsuccess: boolean\n\t/** Human-readable message */\n\tmessage: string\n\t/** Deployment outputs (only on success) */\n\toutputs?: TOutputs\n\t/** Error details (only on failure) */\n\terror?: {\n\t\tcode: string\n\t\tmessage: string\n\t\tdetails?: string\n\t}\n}\n\n/**\n * Options passed to provider init\n */\nexport interface ProviderInitOptions {\n\t/** Environment to initialize */\n\tenv: string\n\t/** Target region */\n\tregion: string\n\t/** Project root directory */\n\tprojectRoot: string\n\t/** Skip confirmation prompts */\n\tyes?: boolean\n\t/** Provider-specific options */\n\tproviderOptions?: Record<string, unknown>\n}\n\n/**\n * Options passed to provider deploy\n */\nexport interface ProviderDeployOptions {\n\t/** Environment to deploy */\n\tenv: string\n\t/** Project root directory */\n\tprojectRoot: string\n\t/** Preview changes without applying */\n\tpreview?: boolean\n\t/** Skip Docker build (use existing image) */\n\tskipBuild?: boolean\n\t/** Use specific image URL */\n\timage?: string\n\t/** Skip confirmation prompts */\n\tyes?: boolean\n}\n\n/**\n * Options passed to provider destroy\n */\nexport interface ProviderDestroyOptions {\n\t/** Environment to destroy */\n\tenv: string\n\t/** Project root directory */\n\tprojectRoot: string\n\t/** Only destroy application layer, keep persistent resources */\n\tappOnly?: boolean\n\t/** Skip confirmation prompts */\n\tforce?: boolean\n}\n\n/**\n * Options passed to provider status check\n */\nexport interface ProviderStatusOptions {\n\t/** Environment to check */\n\tenv: string\n\t/** Project root directory */\n\tprojectRoot: string\n}\n\n/**\n * Status information returned by provider\n */\nexport interface ProviderStatus {\n\t/** Whether infrastructure is deployed */\n\tdeployed: boolean\n\t/** Current state (initializing/ready/deploying/error) */\n\tstate: 'initializing' | 'ready' | 'deploying' | 'error' | 'not_initialized'\n\t/** Service URL if deployed */\n\tserviceUrl?: string\n\t/** Last deployment timestamp */\n\tlastDeployment?: string\n\t/** Provider-specific status details */\n\tdetails?: Record<string, unknown>\n}\n\n/**\n * Options for ejecting provider to local packages\n */\nexport interface ProviderEjectOptions {\n\t/** Target directory for ejected code */\n\ttargetDir: string\n\t/** Project root directory */\n\tprojectRoot: string\n\t/** Skip confirmation prompts */\n\tforce?: boolean\n}\n\n/**\n * The main infrastructure provider interface.\n *\n * All provider packages must export a `provider` object implementing this interface.\n * The CLI discovers and loads providers dynamically based on installed packages.\n *\n * @typeParam TConfig - Provider-specific configuration extending BaseInfraConfig\n * @typeParam TOutputs - Provider-specific deployment outputs\n */\nexport interface KuckitInfraProvider<\n\tTConfig extends BaseInfraConfig = BaseInfraConfig,\n\tTOutputs extends Record<string, unknown> = Record<string, unknown>,\n> {\n\t/**\n\t * Unique provider identifier (e.g., 'gcp', 'aws', 'azure')\n\t * Used for config storage and provider resolution\n\t */\n\treadonly id: string\n\n\t/**\n\t * Human-readable provider name for display\n\t * (e.g., 'Google Cloud Platform', 'Amazon Web Services')\n\t */\n\treadonly label: string\n\n\t/**\n\t * Provider version (semver)\n\t */\n\treadonly version: string\n\n\t/**\n\t * Get the infrastructure directory path for this provider.\n\t * This is where Pulumi/Terraform/CDK code lives.\n\t *\n\t * @param projectRoot - The project root directory\n\t * @returns Absolute path to infrastructure directory\n\t */\n\tgetInfraDir(projectRoot: string): string\n\n\t/**\n\t * Check if provider prerequisites are met (CLI tools, auth, etc.)\n\t *\n\t * @returns Object with status and any missing prerequisites\n\t */\n\tcheckPrerequisites(): Promise<{\n\t\tok: boolean\n\t\tmissing: Array<{ name: string; installUrl: string }>\n\t}>\n\n\t/**\n\t * Initialize base infrastructure for the project.\n\t * Creates foundational resources (VPC, registry, database) without deploying the app.\n\t *\n\t * @param options - Initialization options\n\t * @returns Operation result with deployment outputs\n\t */\n\tinit(options: ProviderInitOptions): Promise<InfraOperationResult<TOutputs>>\n\n\t/**\n\t * Deploy the application to the infrastructure.\n\t * Builds container image (if needed) and deploys to compute platform.\n\t *\n\t * @param options - Deployment options\n\t * @param config - Current stored configuration\n\t * @returns Operation result with deployment outputs\n\t */\n\tdeploy(options: ProviderDeployOptions, config: TConfig): Promise<InfraOperationResult<TOutputs>>\n\n\t/**\n\t * Destroy infrastructure resources.\n\t *\n\t * @param options - Destroy options\n\t * @param config - Current stored configuration\n\t * @returns Operation result\n\t */\n\tdestroy(options: ProviderDestroyOptions, config: TConfig): Promise<InfraOperationResult>\n\n\t/**\n\t * Get current infrastructure status.\n\t *\n\t * @param options - Status options\n\t * @param config - Current stored configuration\n\t * @returns Current provider status\n\t */\n\tstatus(options: ProviderStatusOptions, config: TConfig): Promise<ProviderStatus>\n\n\t/**\n\t * Get provider-specific configuration prompts for init.\n\t * Returns questions to ask user during interactive init.\n\t *\n\t * @param defaults - Any existing config values to use as defaults\n\t * @returns Array of prompts for inquirer\n\t */\n\tgetInitPrompts(defaults?: Partial<TConfig>): Promise<\n\t\tArray<{\n\t\t\tname: string\n\t\t\tmessage: string\n\t\t\ttype: 'input' | 'select' | 'confirm'\n\t\t\tdefault?: string | boolean\n\t\t\tchoices?: Array<{ value: string; label: string }>\n\t\t\tvalidate?: (value: string) => boolean | string\n\t\t}>\n\t>\n\n\t/**\n\t * Build provider-specific config from user responses.\n\t *\n\t * @param responses - User responses from init prompts\n\t * @param baseConfig - Base config fields\n\t * @returns Complete provider config\n\t */\n\tbuildConfig(\n\t\tresponses: Record<string, unknown>,\n\t\tbaseConfig: Pick<BaseInfraConfig, 'env' | 'region' | 'projectName' | 'stackName'>\n\t): TConfig\n\n\t/**\n\t * Optional: Eject provider infrastructure code to local project.\n\t * Allows customization of infrastructure beyond provider defaults.\n\t *\n\t * @param options - Eject options\n\t * @returns Operation result\n\t */\n\teject?(options: ProviderEjectOptions): Promise<InfraOperationResult>\n\n\t/**\n\t * Optional: Generate Dockerfile for the project.\n\t * Providers can include optimized Dockerfile templates.\n\t *\n\t * @param projectRoot - Project root directory\n\t * @returns Dockerfile content or null if using existing\n\t */\n\tgenerateDockerfile?(projectRoot: string): Promise<string | null>\n\n\t/**\n\t * Optional: Validate that project structure is compatible with provider.\n\t *\n\t * @param projectRoot - Project root directory\n\t * @returns Validation result with any issues\n\t */\n\tvalidateProject?(projectRoot: string): Promise<{\n\t\tvalid: boolean\n\t\tissues: Array<{ severity: 'error' | 'warning'; message: string }>\n\t}>\n}\n\n/**\n * Helper to define a provider with type inference.\n *\n * @example\n * ```typescript\n * export const provider = defineInfraProvider({\n * id: 'gcp',\n * label: 'Google Cloud Platform',\n * version: '1.0.0',\n * getInfraDir: (root) => join(root, 'node_modules/@kuckit/infra-gcp/infra'),\n * // ... rest of implementation\n * })\n * ```\n */\nexport function defineInfraProvider<\n\tTConfig extends BaseInfraConfig = BaseInfraConfig,\n\tTOutputs extends Record<string, unknown> = Record<string, unknown>,\n>(provider: KuckitInfraProvider<TConfig, TOutputs>): KuckitInfraProvider<TConfig, TOutputs> {\n\treturn provider\n}\n\n/**\n * Type for the provider module export.\n * Provider packages should default export this shape.\n */\nexport interface KuckitInfraProviderModule<\n\tTConfig extends BaseInfraConfig = BaseInfraConfig,\n\tTOutputs extends Record<string, unknown> = Record<string, unknown>,\n> {\n\tprovider: KuckitInfraProvider<TConfig, TOutputs>\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kuckit/cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "CLI tools for Kuckit SDK module development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build": "tsdown",
|
|
42
|
+
"test": "bun test",
|
|
42
43
|
"prepublishOnly": "npm run build && node ../../scripts/resolve-workspace-protocols.cjs && node ../../scripts/check-no-workspace-protocol.cjs"
|
|
43
44
|
},
|
|
44
45
|
"dependencies": {
|
|
@@ -53,7 +54,7 @@
|
|
|
53
54
|
"tsdown": "catalog:"
|
|
54
55
|
},
|
|
55
56
|
"peerDependencies": {
|
|
56
|
-
"@kuckit/sdk": ">=
|
|
57
|
+
"@kuckit/sdk": ">=2.0.0"
|
|
57
58
|
},
|
|
58
59
|
"peerDependenciesMeta": {
|
|
59
60
|
"@kuckit/sdk": {
|