@airoom/nextmin-node 0.1.0
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/LICENSE +49 -0
- package/README.md +178 -0
- package/dist/api/apiRouter.d.ts +65 -0
- package/dist/api/apiRouter.js +1548 -0
- package/dist/database/DatabaseAdapter.d.ts +14 -0
- package/dist/database/DatabaseAdapter.js +2 -0
- package/dist/database/InMemoryAdapter.d.ts +15 -0
- package/dist/database/InMemoryAdapter.js +71 -0
- package/dist/database/MongoAdapter.d.ts +52 -0
- package/dist/database/MongoAdapter.js +409 -0
- package/dist/files/FileStorageAdapter.d.ts +35 -0
- package/dist/files/FileStorageAdapter.js +2 -0
- package/dist/files/S3FileStorageAdapter.d.ts +30 -0
- package/dist/files/S3FileStorageAdapter.js +84 -0
- package/dist/files/filename.d.ts +5 -0
- package/dist/files/filename.js +40 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +87 -0
- package/dist/models/BaseModel.d.ts +44 -0
- package/dist/models/BaseModel.js +31 -0
- package/dist/policy/authorize.d.ts +25 -0
- package/dist/policy/authorize.js +305 -0
- package/dist/policy/conditions.d.ts +14 -0
- package/dist/policy/conditions.js +30 -0
- package/dist/policy/types.d.ts +53 -0
- package/dist/policy/types.js +2 -0
- package/dist/policy/utils.d.ts +9 -0
- package/dist/policy/utils.js +118 -0
- package/dist/schemas/Roles.json +64 -0
- package/dist/schemas/Settings.json +62 -0
- package/dist/schemas/Users.json +123 -0
- package/dist/services/SchemaService.d.ts +10 -0
- package/dist/services/SchemaService.js +46 -0
- package/dist/utils/DefaultDataInitializer.d.ts +21 -0
- package/dist/utils/DefaultDataInitializer.js +269 -0
- package/dist/utils/Logger.d.ts +12 -0
- package/dist/utils/Logger.js +79 -0
- package/dist/utils/SchemaLoader.d.ts +51 -0
- package/dist/utils/SchemaLoader.js +323 -0
- package/dist/utils/apiKey.d.ts +5 -0
- package/dist/utils/apiKey.js +14 -0
- package/dist/utils/fieldCodecs.d.ts +13 -0
- package/dist/utils/fieldCodecs.js +133 -0
- package/package.json +45 -0
- package/tsconfig.json +8 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
Nextmin Proprietary License v1.0
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 GSCodes
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
1. Definitions
|
|
7
|
+
“Software” means the package and all accompanying files under the package name(s) @airoom/nextmin-react and @airoom/nextmin-node, including any updates provided by Licensor.
|
|
8
|
+
“Licensor” means GSCodes.
|
|
9
|
+
“Licensee” means the person or entity that obtains the Software.
|
|
10
|
+
|
|
11
|
+
2. Grant of License
|
|
12
|
+
Subject to full compliance with this License, Licensor grants Licensee a limited, non-exclusive, non-transferable, non-sublicensable license to:
|
|
13
|
+
a) install and use the Software internally, solely for evaluating or running Licensee’s own applications; and
|
|
14
|
+
b) make a reasonable number of copies solely for internal backup and archival purposes.
|
|
15
|
+
|
|
16
|
+
3. Restrictions
|
|
17
|
+
Except as expressly permitted in Section 2, Licensee must NOT:
|
|
18
|
+
a) copy, publish, distribute, sell, rent, lease, lend, sublicense, or otherwise make the Software available to any third party;
|
|
19
|
+
b) modify, translate, adapt, create derivative works of, or merge the Software with other software;
|
|
20
|
+
c) reverse engineer, decompile, disassemble, or otherwise attempt to derive source code or underlying ideas, except to the extent such restrictions are expressly prohibited by applicable law;
|
|
21
|
+
d) remove, obscure, or alter any proprietary notices or markings; or
|
|
22
|
+
e) use the Software to train, fine-tune, or improve any artificial intelligence or machine learning model.
|
|
23
|
+
|
|
24
|
+
4. Ownership
|
|
25
|
+
The Software is licensed, not sold. Licensor retains all right, title, and interest in and to the Software, including all intellectual property rights and all copies.
|
|
26
|
+
|
|
27
|
+
5. Confidentiality
|
|
28
|
+
The Software and any non-public information provided by Licensor shall be treated as confidential and not disclosed to any third party without Licensor’s prior written consent, except as required by law.
|
|
29
|
+
|
|
30
|
+
6. Term and Termination
|
|
31
|
+
This License is effective until terminated. Licensor may terminate this License immediately upon notice if Licensee breaches any term. Upon termination, Licensee must cease all use and destroy all copies of the Software. Sections 3–10 survive termination.
|
|
32
|
+
|
|
33
|
+
7. Updates; No Support Obligation
|
|
34
|
+
Licensor may, but is not obligated to, provide updates, bug fixes, or support. Any updates are governed by this License unless accompanied by a different license.
|
|
35
|
+
|
|
36
|
+
8. No Warranty
|
|
37
|
+
THE SOFTWARE IS PROVIDED “AS IS” AND “AS AVAILABLE,” WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. USE IS AT LICENSEE’S SOLE RISK.
|
|
38
|
+
|
|
39
|
+
9. Limitation of Liability
|
|
40
|
+
TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL LICENSOR BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, EXEMPLARY, OR PUNITIVE DAMAGES, OR FOR ANY LOSS OF PROFITS, REVENUE, DATA, GOODWILL, OR BUSINESS INTERRUPTION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. LICENSOR’S TOTAL LIABILITY FOR ALL CLAIMS SHALL NOT EXCEED THE AMOUNT PAID BY LICENSEE FOR THE SOFTWARE (IF ANY) IN THE TWELVE (12) MONTHS PRECEDING THE CLAIM.
|
|
41
|
+
|
|
42
|
+
10. Governing Law; Venue
|
|
43
|
+
This License is governed by the laws of State of California, USA, without regard to its conflict of laws principles. The parties submit to the exclusive jurisdiction and venue of the courts located in San Francisco County, California, USA.
|
|
44
|
+
|
|
45
|
+
11. Commercial Licensing
|
|
46
|
+
For commercial use, redistribution, or other rights not expressly granted, contact: tareqaziz0065@gmail.com.
|
|
47
|
+
|
|
48
|
+
12. Entire Agreement
|
|
49
|
+
This License constitutes the entire agreement with respect to the Software and supersedes all prior or contemporaneous agreements or understandings on the subject matter.
|
package/README.md
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# @airoom/nextmin-node
|
|
2
|
+
|
|
3
|
+
Schema‑driven Node.js toolkit that turns a JSON schema into a secure, policy‑aware REST API with authentication, CRUD, relationship querying, and file uploads. Pair it with `@airoom/nextmin-react` to get a fully‑featured Admin Panel in minutes.
|
|
4
|
+
|
|
5
|
+
- “From JSON schema to REST API + Admin”
|
|
6
|
+
- 1 month → 1 hour
|
|
7
|
+
|
|
8
|
+
## Highlights
|
|
9
|
+
|
|
10
|
+
- Express router factory: mount a complete REST API in a few lines
|
|
11
|
+
- Auth built in: register, login, me, change‑password, forgot‑password
|
|
12
|
+
- CRUD per model with read masks, write restrictions, and role/owner policies
|
|
13
|
+
- Advanced list endpoint: filter, multi‑field search, date ranges, multi‑field sort, paginate
|
|
14
|
+
- Relationship endpoints: forward and reverse lookups without autopopulate
|
|
15
|
+
- Schemas hot‑reload during development; automatic model wiring
|
|
16
|
+
- File uploads via pluggable storage (e.g., S3/MinIO); delete by key
|
|
17
|
+
- Database adapters: MongoDB (with index sync) and in‑memory for tests
|
|
18
|
+
- Emits a trusted API key stored in your Settings model for client access
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# npm
|
|
24
|
+
npm install @airoom/nextmin-node
|
|
25
|
+
|
|
26
|
+
# yarn
|
|
27
|
+
yarn add @airoom/nextmin-node
|
|
28
|
+
|
|
29
|
+
# pnpm
|
|
30
|
+
pnpm add @airoom/nextmin-node
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Quick start (Express + Mongo + S3 optional)
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import dotenv from 'dotenv';
|
|
37
|
+
import express from 'express';
|
|
38
|
+
import http from 'http';
|
|
39
|
+
import {
|
|
40
|
+
createNextMinRouter,
|
|
41
|
+
MongoAdapter,
|
|
42
|
+
S3FileStorageAdapter,
|
|
43
|
+
} from '@airoom/nextmin-node';
|
|
44
|
+
import cors from 'cors';
|
|
45
|
+
|
|
46
|
+
dotenv.config();
|
|
47
|
+
|
|
48
|
+
async function start() {
|
|
49
|
+
const app = express();
|
|
50
|
+
const server = http.createServer(app); // pass this to the router for sockets
|
|
51
|
+
|
|
52
|
+
app.use(cors());
|
|
53
|
+
|
|
54
|
+
// 1) Database
|
|
55
|
+
const db = new MongoAdapter(process.env.MONGO_URL!, process.env.MONGO_DB!);
|
|
56
|
+
await db.connect();
|
|
57
|
+
|
|
58
|
+
// 2) Optional: file storage adapter (S3/MinIO)
|
|
59
|
+
const files = new S3FileStorageAdapter({
|
|
60
|
+
bucket: process.env.S3_BUCKET!,
|
|
61
|
+
region: process.env.S3_REGION!,
|
|
62
|
+
credentials:
|
|
63
|
+
process.env.S3_ACCESS_KEY_ID && process.env.S3_SECRET_ACCESS_KEY
|
|
64
|
+
? {
|
|
65
|
+
accessKeyId: process.env.S3_ACCESS_KEY_ID!,
|
|
66
|
+
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY!,
|
|
67
|
+
}
|
|
68
|
+
: undefined,
|
|
69
|
+
endpoint: process.env.S3_ENDPOINT || undefined,
|
|
70
|
+
forcePathStyle: /^(1|true|yes)$/i.test(process.env.S3_FORCE_PATH_STYLE || ''),
|
|
71
|
+
defaultACL: (process.env.S3_DEFAULT_ACL as any) || 'public-read',
|
|
72
|
+
publicBaseUrl: process.env.S3_PUBLIC_BASE_URL || undefined,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// 3) Mount NextMin REST router
|
|
76
|
+
const router = createNextMinRouter({ dbAdapter: db, server, fileStorageAdapter: files });
|
|
77
|
+
app.use('/rest', router);
|
|
78
|
+
|
|
79
|
+
// 4) Listen with the same server instance
|
|
80
|
+
const port = Number(process.env.PORT || 8081);
|
|
81
|
+
server.listen(port, () => console.log(`REST ready: http://localhost:${port}/rest`));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
start().catch((e) => {
|
|
85
|
+
console.error(e);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## REST endpoints (summary)
|
|
91
|
+
|
|
92
|
+
Base: `/rest`
|
|
93
|
+
|
|
94
|
+
- Schemas: `GET /_schemas` → public schema list (requires x-api-key)
|
|
95
|
+
- Auth (users):
|
|
96
|
+
- `POST /auth/users/register`
|
|
97
|
+
- `POST /auth/users/login`
|
|
98
|
+
- `GET /auth/users/me`
|
|
99
|
+
- `POST /auth/users/change-password`
|
|
100
|
+
- `POST /auth/users/forgot-password`
|
|
101
|
+
- Generic CRUD per model (model names are lowercase):
|
|
102
|
+
- `POST /:model`
|
|
103
|
+
- `GET /:model` (query: page, limit, q, searchKey(s), searchMode, dateFrom/to/key, sort, sortType)
|
|
104
|
+
- `GET /:model/:id`
|
|
105
|
+
- `PUT /:model/:id` (or PATCH depending on client)
|
|
106
|
+
- `DELETE /:model/:id`
|
|
107
|
+
- Relationship queries:
|
|
108
|
+
- Forward: `GET /find/:container/:refField/:id`
|
|
109
|
+
- Reverse: `GET /find/reverse/:target/:byField/:id`
|
|
110
|
+
- Files (when file storage adapter is configured):
|
|
111
|
+
- Upload: `POST /files` (multipart form, fields named `file`)
|
|
112
|
+
- Delete: `DELETE /files/:key(*)`
|
|
113
|
+
|
|
114
|
+
See full examples in documentation and the `examples/node` app inside this monorepo.
|
|
115
|
+
|
|
116
|
+
## Headers and auth
|
|
117
|
+
|
|
118
|
+
- All requests must include the API key header: `x-api-key: <YOUR_API_KEY>`
|
|
119
|
+
- Authenticated routes also require: `Authorization: Bearer <JWT>`
|
|
120
|
+
|
|
121
|
+
Where do I find my API key?
|
|
122
|
+
|
|
123
|
+
- On first run, the server initializes default data and stores a trusted `apiKey` in your Settings collection/table.
|
|
124
|
+
- Copy that value into your clients. You can also preseed it by setting `NEXTMIN_API_KEY` before the first boot.
|
|
125
|
+
|
|
126
|
+
## Configuration (env)
|
|
127
|
+
|
|
128
|
+
Application
|
|
129
|
+
|
|
130
|
+
- `APP_MODE`: development | production (affects dev features)
|
|
131
|
+
- `JWT_SECRET`: secret used to sign JWTs
|
|
132
|
+
|
|
133
|
+
Database
|
|
134
|
+
|
|
135
|
+
- `MONGO_URL`: e.g. mongodb://localhost:27017
|
|
136
|
+
- `MONGO_DB`: database name
|
|
137
|
+
|
|
138
|
+
File storage (optional)
|
|
139
|
+
|
|
140
|
+
- `S3_BUCKET`, `S3_REGION`
|
|
141
|
+
- `S3_ACCESS_KEY_ID`, `S3_SECRET_ACCESS_KEY`
|
|
142
|
+
- `S3_ENDPOINT` (for MinIO or custom)
|
|
143
|
+
- `S3_FORCE_PATH_STYLE` (true for MinIO)
|
|
144
|
+
- `S3_DEFAULT_ACL` (e.g., public-read)
|
|
145
|
+
- `S3_PUBLIC_BASE_URL` (CDN/base URL for public links)
|
|
146
|
+
|
|
147
|
+
Frontend integration
|
|
148
|
+
|
|
149
|
+
- `NEXT_PUBLIC_GOOGLE_MAPS_KEY` (used by address autocomplete within the Admin UI)
|
|
150
|
+
|
|
151
|
+
## Default super admin (after setup)
|
|
152
|
+
|
|
153
|
+
After the initial setup, you can sign in with the default super user and should immediately change the password:
|
|
154
|
+
|
|
155
|
+
- Email: super@example.com
|
|
156
|
+
- Username: superadmin
|
|
157
|
+
- Password: supersecurepassword
|
|
158
|
+
|
|
159
|
+
Change it right after the first login.
|
|
160
|
+
|
|
161
|
+
## TypeScript
|
|
162
|
+
|
|
163
|
+
Types are bundled. Example import:
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
import type { APIRouterOptions } from '@airoom/nextmin-node';
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Troubleshooting
|
|
170
|
+
|
|
171
|
+
- 401 Unauthorized: verify `x-api-key` matches `Settings.apiKey` and that JWT is present for protected routes.
|
|
172
|
+
- CORS issues: allow your frontend origin in development.
|
|
173
|
+
- Sorting/filters: unknown fields are ignored; ensure you pass existing attribute names.
|
|
174
|
+
- Relationship endpoints: confirm your schema uses proper `ref` fields.
|
|
175
|
+
|
|
176
|
+
## License
|
|
177
|
+
|
|
178
|
+
Licensed under the Nextmin Proprietary License. © 2025 GSCodes. For commercial licensing or extended rights, contact: tareqaziz0065@gmail.com.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import type { Server as HttpServer } from 'http';
|
|
3
|
+
import { DatabaseAdapter } from '../database/DatabaseAdapter';
|
|
4
|
+
import type { FileStorageAdapter } from '../files/FileStorageAdapter';
|
|
5
|
+
export interface APIRouterOptions {
|
|
6
|
+
dbAdapter: DatabaseAdapter;
|
|
7
|
+
server?: HttpServer;
|
|
8
|
+
fileStorageAdapter?: FileStorageAdapter;
|
|
9
|
+
}
|
|
10
|
+
export declare class APIRouter {
|
|
11
|
+
private router;
|
|
12
|
+
private models;
|
|
13
|
+
private dbAdapter;
|
|
14
|
+
private jwtSecret;
|
|
15
|
+
private trustedApiKey;
|
|
16
|
+
private schemaLoader;
|
|
17
|
+
private isDevelopment;
|
|
18
|
+
private findRoutesMounted;
|
|
19
|
+
private authRoutesInitialized;
|
|
20
|
+
private schemasRouteRegistered;
|
|
21
|
+
private registeredModels;
|
|
22
|
+
private liveSchemas;
|
|
23
|
+
private notFoundHandler?;
|
|
24
|
+
private fileStorage?;
|
|
25
|
+
constructor(options: APIRouterOptions);
|
|
26
|
+
getRouter(): express.Router;
|
|
27
|
+
private wireSchemaHotReload;
|
|
28
|
+
private syncAllIndexes;
|
|
29
|
+
private diffRemovedModels;
|
|
30
|
+
private setLiveSchemas;
|
|
31
|
+
private rebuildModels;
|
|
32
|
+
private mountSchemasEndpointOnce;
|
|
33
|
+
private mountRoutes;
|
|
34
|
+
private getSchema;
|
|
35
|
+
private getModel;
|
|
36
|
+
private setupRoutes;
|
|
37
|
+
private mountFindRoutes;
|
|
38
|
+
private fileAuthMiddleware;
|
|
39
|
+
/** Mount generic file endpoints under this router */
|
|
40
|
+
private setupFileRoutes;
|
|
41
|
+
/** uploads/YYYY/MM/DD */
|
|
42
|
+
private shortFolder;
|
|
43
|
+
/** small, URL-safe uid */
|
|
44
|
+
private shortUid;
|
|
45
|
+
private normalizeAttrType;
|
|
46
|
+
private optionalAuthMiddleware;
|
|
47
|
+
private pickAuthFor;
|
|
48
|
+
private getUserRoleFromReq;
|
|
49
|
+
private normalizeRoleName;
|
|
50
|
+
private setupAuthRoutes;
|
|
51
|
+
/**
|
|
52
|
+
* Validate required fields.
|
|
53
|
+
* - create: field must exist and be non-empty (not null/undefined/'').
|
|
54
|
+
* - update: only validate fields that are explicitly present in the payload;
|
|
55
|
+
* absence means "unchanged".
|
|
56
|
+
*/
|
|
57
|
+
private validateRequiredFields;
|
|
58
|
+
private handleWriteError;
|
|
59
|
+
private setupNotFoundMiddleware;
|
|
60
|
+
private ensureNotFoundLast;
|
|
61
|
+
private apiKeyMiddleware;
|
|
62
|
+
private validateRoleValue;
|
|
63
|
+
private authenticateMiddleware;
|
|
64
|
+
private checkUniqueFields;
|
|
65
|
+
}
|