@appxdigital/appx-core
v0.1.120
Published
Appx Core is a library that provides a set of tools to help you build your application faster.
Downloads
688
Readme
AppX Core
AppX Core is a production-oriented backend foundation that accelerates the delivery of secure, data-access-controlled APIs with an integrated admin backoffice. It scaffolds a native NestJS application and extends it with opinionated building blocks for authentication, authorization (ABAC-first), CRUD acceleration, and administration through AdminJS.
Built and maintained by AppX (appx-digital.com).
Table of Contents
- Why AppX Core
- Key Features
- Architecture Overview
- Getting Started
- Core Concepts
- Permissions
- Generated CRUD Endpoints
- Examples
- Limitations
- FAQ
- Roadmap
- Support
- Security
- Contributing
- License
Why AppX Core
Modern applications often fail not because teams cannot build endpoints, but because they ship access control too late, build inconsistent admin tooling, and recreate the same authentication and backoffice plumbing across projects.
AppX Core puts security and data-access control first, while keeping development fast:
- Start from a native NestJS structure (no “framework lock-in”).
- Define data in Prisma once.
- Generate a robust baseline for CRUD and service structure.
- Enforce permissions where it matters: at the data layer (ABAC).
- Operate and administrate through a standard AdminJS backoffice.
Key Features
- NestJS-native scaffold (standard structure, editable modules)
- Prisma ORM integration with opinionated permissions enforcement
- ABAC-first permission filtering (attribute-based access control)
- AdminJS backoffice exposed at
/adminwith configurable access and models - Authentication out-of-the-box
- Cookie/session auth
- JWT auth (recommended)
- Fast CRUD acceleration
- Generated modules, controllers, and services per model
- Standard REST CRUD endpoints
- Developer-friendly extension points
- Add custom endpoints with
@Permission(...) - Use services for business logic, controllers as transport layer
- Add custom endpoints with
Architecture Overview
AppX Core is designed as a base layer on top of NestJS:
- Your application remains a NestJS project with conventional modules.
- AppX Core provides:
- base configuration and wiring
- authentication modules
- permissions system (ABAC)
- generation pipeline based on Prisma schema
- AdminJS integration
Getting Started
Prerequisites
- Node.js 20+
- A running database (MySQL or PostgreSQL tested/validated)
1) Install the CLI
npm install -g @appxdigital/appx-core-cli2) Create a New Project
appx-core create
cd <your-project>3) Configure Environment
Create a .env file at the project root:
## DataBase Configurations ##
DB_HOST=127.0.0.1
DB_PORT=3306
DB_USER=root
DB_PASSWORD=
DB_NAME=generic
DB_PROVIDER=mysql
DB_URL="${DB_PROVIDER}://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}"
## Project configurations ##
APP_PORT=3000
USE_TRANSACTION=true
## Sessions ##
SESSION_SECRET="change-me"
SESSION_COOKIE_NAME="session_nestjs-project"
SESSION_TTL=86400
## JWT ##
JWT_EXPIRES_IN=10d
JWT_REFRESH_EXPIRES_IN=1y
JWT_SECRET="change-me"
JWT_REFRESH_SECRET="change-me"4) Define Data Models
Edit:
prisma/schema.prisma
Add your application models. You can add fields and relations freely. Avoid removing or changing types of the default models shipped with AppX Core.
If you already have an existing database schema and want to import it:
npx prisma db pullImportant: db pull overrides schema.prisma. Ensure you preserve default AppX Core models/configuration and merge accordingly.
5) Generate Modules and CRUD
After you edit schema.prisma, run:
appx-core generateRun this every time you change the Prisma schema. This is the only required generation step (no need to run prisma generate separately).
6) Run Migrations
npx prisma migrate devYou will be asked for a migration name.
7) Run the App
npm run start:devWhat you get out of the box
- Admin backoffice at
/admin(after you include models insrc/config/admin.config.ts) - Auth endpoints with no prefix:
POST /auth/registerPOST /auth/loginPOST /auth/logoutGET /mePOST /login/jwt(recommended)POST /logout/jwt
Core Concepts
Project Structure
AppX Core generates a standard NestJS structure. You will typically see:
src/main.ts– app bootstrap and cross-cutting config (cookies, sessions, logs, CORS)src/app.module.ts– high-level module wiring
Most customization happens in:
src/config/permissions.config.ts– granular ABAC rulessrc/config/admin.config.ts– AdminJS configuration and model registrationprisma/schema.prisma– your data model source of truth
Admin Backoffice
- AdminJS is exposed at
/admin - Models must be included/configured in
admin.config.tsto appear in the UI.
Authentication
Cookie/session:
POST /auth/registerPOST /auth/loginPOST /auth/logoutGET /me
JWT (recommended):
POST /login/jwtPOST /logout/jwt
Authorization Model
AppX Core emphasizes enforcement at the data layer:
- Permissions are designed to be applied automatically during database operations (ABAC), not only at the route layer.
- Implement permissions using:
permissions.config.ts@Permission('actionName')on endpoints- ABAC conditions aligned with Prisma
wherefilters
Unauthenticated requests are treated as a “guest context” (not a role).
Permissions
Permissions Configuration Shape
Permissions live in src/config/permissions.config.ts:
export const PermissionsConfig = {
ModelName: {
ADMIN: {
findMany: 'ALL',
create: 'ALL',
updateMany: 'ALL',
deleteMany: 'ALL',
},
USER: {
findMany: { conditions: { id: PermissionPlaceholder.USER_ID } },
updateMany: { conditions: { id: PermissionPlaceholder.USER_ID } },
},
},
};Rules
'ALL'– unrestricted access{ conditions: { ... } }– ABAC filtering using Prisma-likewheresyntax
Example: allow deletion only if related refresh tokens are expired:
deleteMany: {
conditions: {
refreshTokens: {
every: { expiresAt: { lt: new Date() } },
},
},
},Action Aliases and Fallbacks
To avoid duplicated config, the permissions engine supports fallback behavior. In practice:
- Define
findManywhen possible, as it generally covers read scenarios. countmay fall back to read permissions when not explicitly defined.
Custom Controller Actions
Add custom endpoints and protect them with @Permission(...).
@Permission('exportAuditReport')
@Get('/audit/export')
exportAuditReport() {
return this.service.exportAuditReport();
}Temporarily Exposing Models
Some operations require privileged access (e.g., registration pre-checks). You can temporarily expose a model:
- Endpoint-level (decorator’s second argument), or
- Service-level scoped exposure
Endpoint-level example:
@Permission('checkEmailAvailability', ['user'])
@Get('/auth/email-available')
async isEmailAvailable(@Query('email') email: string) {
return this.service.isEmailAvailable(email);
}Service-level example:
await this.prisma.withExposedModels(['user'], async () => {
// privileged operations here
});Use this sparingly and intentionally. Prefer ABAC whenever feasible.
Generated CRUD Endpoints
For each generated model/controller (subject to permissions):
GET /[model_name]GET /[model_name]/:idPOST /[model_name]PUT /[model_name]/:idDELETE /[model_name]/:id
To show a model in the admin backoffice, register it in src/config/admin.config.ts.
Examples
Example 1: Admin-Only Operational Endpoint
Use case: expose a lightweight operational endpoint to verify that background jobs ran recently.
Controller:
@Permission('viewSystemHealth')
@Get('/ops/health')
getHealth() {
return this.service.getHealthSummary();
}Permissions (permissions.config.ts):
export const PermissionsConfig = {
System: {
ADMIN: {
viewSystemHealth: 'ALL',
},
USER: {
// Not defined => denied
},
},
};Service (example logic):
async getHealthSummary() {
return {
status: 'ok',
timestamp: new Date().toISOString(),
};
}Example 2: “My Profile” Endpoint (User Can Only See Self)
Use case: ensure users can only access their own record, even if they try other IDs.
Controller:
@Permission('readMyProfile')
@Get('/me/profile')
getMyProfile() {
return this.service.getMyProfile();
}Permissions:
export const PermissionsConfig = {
User: {
ADMIN: { readMyProfile: 'ALL' },
USER: { readMyProfile: { conditions: { id: PermissionPlaceholder.USER_ID } } },
},
};Service (Prisma query remains straightforward; ABAC filtering is applied by the core):
async getMyProfile() {
return this.prisma.model.user.findFirst({
where: { id: PermissionPlaceholder.USER_ID },
});
}Example 3: Registration Email Availability Check
Use case: a public endpoint checks if an email is already used. This must access user data safely, even without a logged-in user.
Controller:
@Permission('checkEmailAvailability', ['user'])
@Get('/auth/email-available')
async isEmailAvailable(@Query('email') email: string) {
return this.service.isEmailAvailable(email);
}Service:
async isEmailAvailable(email: string) {
let exists = false;
await this.prisma.withExposedModels(['user'], async () => {
const user = await this.prisma.model.user.findFirst({ where: { email } });
exists = !!user;
});
return { available: !exists };
}This pattern should be used sparingly and intentionally.
Limitations
Prisma method restrictions (permission safety)
Avoid these Prisma methods because they can bypass or complicate granular permission filtering:
findUnique→ usefindFirstdelete→ usedeleteManywith a single-item filterupdate→ useupdateManywith a single-item filter
Operational guidance:
- Prefer
findMany,findFirst,updateMany, anddeleteMany. - When you intend a single-record operation, use a restrictive
whereclause.
GraphQL status
GraphQL is part of the direction, but is not fully ready in the current release. REST CRUD + AdminJS are the primary integration surfaces for now.
FAQ
Are CRUD endpoints only for AdminJS?
No. They can be used for any API consumer. Permissions are enforced consistently.
Do I need to treat generated modules as read-only?
No. Generated NestJS modules are editable and intended to be extended.
Roadmap
Planned and under consideration:
- Production-ready GraphQL
- Object storage patterns (S3-friendly out-of-the-box support)
- Forgot-password flow
- Email templates + sending primitives
- Push notifications primitives
- WebSockets support
- Stronger testing baseline (unit tests scaffolding and patterns)
- “Agent-ready” development guidance (
agents.txt, conventions for coding agents) - Optional AI-assisted project scaffolding
Support
Email: [email protected]
Security
Report vulnerabilities privately to [email protected]. Do not open public issues for sensitive reports.
Contributing
- Fork the repository.
- Create a feature branch.
- Keep changes focused; add tests where applicable.
- Open a PR with clear motivation and impact.
License
MIT License. See LICENSE.
