Package Management
Lockness provides a powerful package management system that automatically configures and integrates additional features into your application. Packages are registered in deno.json and loaded dynamically at runtime.
Overview
The package system allows you to add functionality to your Lockness application with zero configuration. Packages automatically register their CLI commands, services, and configurations when listed in your deno.json.
🎯 Key Benefits
- Zero configuration - just install and use
- Automatic CLI command registration
- Install scripts for automated setup
- Declarative package configuration
- Clean uninstallation
Configuration
Packages are declared in the lockness section of your deno.json:
{
"lockness": {
"packages": [
"drizzle",
"openapi",
"cache",
"socialite"
]
}
}When your application starts, Lockness automatically:
- Loads each package from the list
- Registers their CLI commands
- Makes their services available via DI
Installing Packages
Option 1: Automated Installation (Recommended)
Use the package:install command for fully automated setup:
deno task cli package:install openapiThis command will:
- Add the package to
deno.json - Run the package's install script (if available)
- Create necessary files and configurations
- Display next steps and documentation links
✅ Example: Installing OpenAPI
$ deno task cli package:install openapi
🌊 Installing @lockness/openapi...
✓ Added openapi to lockness.packages
✓ Created app/controller/docs_controller.ts
⚠️ Routes need to be regenerated:
Run: deno task routes:generate
✅ @lockness/openapi installed successfully!
📖 Next steps:
1. Start your dev server: deno task dev
2. Visit: http://localhost:8888/docs
3. Document your routes with @ApiDoc decoratorOption 2: Manual Configuration
Add the package manually and configure it yourself:
deno task cli package:add openapiThis only adds the package to your configuration. You'll need to follow the package's documentation for manual setup.
Option 3: Direct Script Execution
Run a package's install script directly from JSR:
deno run -A jsr:@lockness/openapi/installRemoving Packages
Remove a package from your configuration:
deno task cli package:remove openapi⚠️ Note
This only removes the package from deno.json. You'll need to manually delete any generated files (controllers, configs, etc.) if desired.
Available Commands
| Command | Description |
|---|---|
package:install <name> | Install and configure a package with automated setup |
package:add <name> | Add package to configuration only (no setup) |
package:remove <name> | Remove package from configuration |
Official Packages
@lockness/drizzle
Drizzle ORM integration with migrations, seeders, and CLI commands
package:install drizzle@lockness/openapi
OpenAPI/Swagger documentation with automatic spec generation
package:install openapi@lockness/cache
Multi-driver caching system (Memory, Deno KV, Redis)
package:install cache@lockness/socialite
OAuth2 authentication (Google, GitHub, Discord)
package:install socialiteHow It Works
When you start your application, the cli.ts file loads packages automatically:
import { Cli, loadPackageCommands, registerCoreCommands } from '@lockness/cli'
const cli = new Cli()
// Register core commands
registerCoreCommands(cli)
// Load commands from packages in deno.json
await loadPackageCommands(cli)
// Discover user commands
await cli.discoverCommands('./app/command')The loadPackageCommands() function:
- Reads the
lockness.packagesarray fromdeno.json - Dynamically imports each package
- Looks for a
register*Commandsfunction - Calls the function to register CLI commands
💡 Convention
Packages export a function named register[Name]Commands or register[Name]Command from their main entry point. This function receives the Cli instance and registers the package's commands.
Creating Your Own Package
You can create custom Lockness packages that integrate seamlessly with the package management system.
1. Export Register Function
// my-package/index.ts
import type { Cli } from '@lockness/cli'
export function registerMyPackageCommands(cli: Cli) {
cli.register('my:command', async () => {
console.log('Hello from my package!')
}, 'My custom command')
}
export { myPackageFunction } from './lib.ts'2. Create Install Script (Optional)
// my-package/install.ts
import { addPackage } from '@lockness/cli'
async function main() {
console.log('🌊 Installing my-package...\n')
// Add to deno.json
await addPackage('my-package')
// Create config file
await Deno.writeTextFile(
'./config/my-package.ts',
'export const config = { enabled: true }'
)
console.log('✅ Installation complete!')
}
if (import.meta.main) {
await main()
}3. Update Package Configuration
// deno.json
{
"name": "@myorg/my-package",
"exports": {
".": "./index.ts",
"./install": "./install.ts"
}
}4. Development Standards
To maintain consistency and ensure compatibility across the Lockness ecosystem, all packages should follow these standards:
- Standard Entry Point:Always use
mod.tsas the main entry point for your package. - Test Organization:Place all test files in a dedicated
tests/directory and use the*.test.tsnaming convention. - Workspace Imports:Use named workspace imports (e.g.,
@lockness/core) for cross-package dependencies instead of relative paths. - JSR Ready:Configure the
publishfield in yourdeno.jsonto include only source files and exclude tests.
See INSTALL_SCRIPTS.md for complete documentation on creating install scripts.