@mostajs/setup 2.1.3 → 2.1.5
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/README.md +54 -1
- package/dist/lib/load-setup-json.d.ts +5 -0
- package/dist/lib/load-setup-json.js +11 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1123,6 +1123,59 @@ Puis recompilez : `cd packages/mosta-setup && npx tsc`
|
|
|
1123
1123
|
| [@mostajs/settings](https://www.npmjs.com/package/@mostajs/settings) | oui | non | Parametres cle-valeur |
|
|
1124
1124
|
| [@mostajs/face](https://www.npmjs.com/package/@mostajs/face) | **non** | **oui** | Reconnaissance faciale (independant) |
|
|
1125
1125
|
|
|
1126
|
+
## Catch-all Route Factory (createSetupRoutes)
|
|
1127
|
+
|
|
1128
|
+
Replace 6+ individual route files with a single `[...slug]` handler :
|
|
1129
|
+
|
|
1130
|
+
```typescript
|
|
1131
|
+
// src/app/api/setup/[...slug]/route.ts — 7 lines replaces 6 files
|
|
1132
|
+
import { createSetupRoutes } from '@mostajs/setup'
|
|
1133
|
+
import { appNeedsSetup, getSetupConfig } from '@/lib/setup-config'
|
|
1134
|
+
|
|
1135
|
+
export const { GET, POST, DELETE, PATCH } = createSetupRoutes({
|
|
1136
|
+
needsSetup: appNeedsSetup,
|
|
1137
|
+
getSetupConfig,
|
|
1138
|
+
})
|
|
1139
|
+
```
|
|
1140
|
+
|
|
1141
|
+
Handles all 11 setup endpoints : status, test-db, create-db, preflight, detect-modules, install-modules, setup-json, upload-jar, wire-module, reconfig, install.
|
|
1142
|
+
|
|
1143
|
+
## createAdmin (auto-generated)
|
|
1144
|
+
|
|
1145
|
+
`loadSetupJson()` automatically generates a `createAdmin` callback that :
|
|
1146
|
+
1. Gets the `user` repo via `repoFactory`
|
|
1147
|
+
2. Gets the `role` repo to resolve the `admin` role
|
|
1148
|
+
3. Creates the admin user with bcrypt-hashed password and admin role
|
|
1149
|
+
|
|
1150
|
+
No need to define `createAdmin` manually — it comes from `loadSetupJson()`.
|
|
1151
|
+
|
|
1152
|
+
## lookupFields (cross-entity references in seeds)
|
|
1153
|
+
|
|
1154
|
+
Resolve a field value from another collection before inserting seed data :
|
|
1155
|
+
|
|
1156
|
+
```json
|
|
1157
|
+
{
|
|
1158
|
+
"key": "demoClients",
|
|
1159
|
+
"collection": "client",
|
|
1160
|
+
"lookupFields": {
|
|
1161
|
+
"createdBy": { "collection": "user", "match": "status", "value": "active" }
|
|
1162
|
+
},
|
|
1163
|
+
"data": [
|
|
1164
|
+
{ "firstName": "Samir", "lastName": "Boudjema", "phone": "0550100001" }
|
|
1165
|
+
]
|
|
1166
|
+
}
|
|
1167
|
+
```
|
|
1168
|
+
|
|
1169
|
+
`lookupFields.createdBy` : find the first `user` where `status = "active"`, inject its `id` as `createdBy` in every data item.
|
|
1170
|
+
|
|
1171
|
+
Useful for seeds that reference entities created by earlier seeds (RBAC roles, admin user, etc.).
|
|
1172
|
+
|
|
1173
|
+
## Dynamic Seeds in SetupWizard
|
|
1174
|
+
|
|
1175
|
+
The wizard automatically loads available seeds from the `/api/setup/setup-json` endpoint and displays them as checkboxes. Seeds with `"default": true` in setup.json are pre-checked.
|
|
1176
|
+
|
|
1177
|
+
No need to hardcode seed checkboxes — add a seed to `setup.json` and it appears in the wizard automatically.
|
|
1178
|
+
|
|
1126
1179
|
## License
|
|
1127
1180
|
|
|
1128
|
-
MIT — (c) 2025 Dr Hamid MADANI <drmdh@msn.com>
|
|
1181
|
+
MIT — (c) 2025-2026 Dr Hamid MADANI <drmdh@msn.com>
|
|
@@ -35,6 +35,11 @@ export interface SetupJsonSeed {
|
|
|
35
35
|
hashField?: string;
|
|
36
36
|
roleField?: string;
|
|
37
37
|
defaults?: Record<string, unknown>;
|
|
38
|
+
lookupFields?: Record<string, {
|
|
39
|
+
collection: string;
|
|
40
|
+
match: string;
|
|
41
|
+
value: string;
|
|
42
|
+
}>;
|
|
38
43
|
data: Record<string, unknown>[];
|
|
39
44
|
}
|
|
40
45
|
export interface SetupJson {
|
|
@@ -134,8 +134,18 @@ function buildSeedDefinition(seedDef, repoFactory) {
|
|
|
134
134
|
run: async () => {
|
|
135
135
|
const getRepo = repoFactory ?? defaultRepoFactory;
|
|
136
136
|
const repo = await getRepo(seedDef.collection);
|
|
137
|
+
// Resolve lookupFields once (e.g. createdBy → user where email = admin@test.dz → userId)
|
|
138
|
+
const resolved = {};
|
|
139
|
+
if (seedDef.lookupFields) {
|
|
140
|
+
for (const [field, lookup] of Object.entries(seedDef.lookupFields)) {
|
|
141
|
+
const lookupRepo = await getRepo(lookup.collection);
|
|
142
|
+
const found = await lookupRepo.findOne({ [lookup.match]: lookup.value });
|
|
143
|
+
if (found)
|
|
144
|
+
resolved[field] = found.id;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
137
147
|
for (const rawItem of seedDef.data) {
|
|
138
|
-
const item = { ...(seedDef.defaults ?? {}), ...rawItem };
|
|
148
|
+
const item = { ...(seedDef.defaults ?? {}), ...resolved, ...rawItem };
|
|
139
149
|
// Hash field if configured (e.g. password)
|
|
140
150
|
if (seedDef.hashField && item[seedDef.hashField]) {
|
|
141
151
|
const bcryptModule = await import('bcryptjs');
|
package/package.json
CHANGED